[hamradio-commits] [xastir] 01/05: Imported Upstream version 2.0.4
Iain Learmonth
irl-guest at moszumanska.debian.org
Sat Nov 15 18:59:04 UTC 2014
This is an automated email from the git hooks/post-receive script.
irl-guest pushed a commit to branch master
in repository xastir.
commit aca251bbd821be1161955f5a46f6c4ae529d48eb
Author: Iain R. Learmonth <irl at fsfe.org>
Date: Sat Nov 15 18:41:49 2014 +0000
Imported Upstream version 2.0.4
---
ABOUT-NLS | 226 +
AUTHORS | 59 +
CC_OpenStreetMap_logo.png | Bin 0 -> 5299 bytes
CC_OpenStreetMap_txt.png | Bin 0 -> 1950 bytes
COPYING | 340 +
COPYING.LIB.LESSTIF | 481 +
CanadaTopo250k.geo | 2 +
CanadaTopo50k.geo | 2 +
ChangeLog | 30054 ++++++++++++++++++++++
DEBUG_LEVELS | 123 +
Davis/.cvsignore | 15 +
Davis/AUTHORS | 24 +
Davis/COPYING | 340 +
Davis/CVS/Entries | 11 +
Davis/CVS/Entries.Log | 1 +
Davis/CVS/Repository | 1 +
Davis/CVS/Root | 1 +
Davis/ChangeLog | 3 +
Davis/INSTALL | 232 +
Davis/Makefile.am | 43 +
Davis/NEWS | 3 +
Davis/README | 211 +
Davis/bootstrap.sh | 10 +
Davis/configure.ac | 67 +
Davis/src/.cvsignore | 4 +
Davis/src/CVS/Entries | 5 +
Davis/src/CVS/Repository | 1 +
Davis/src/CVS/Root | 1 +
Davis/src/Makefile.am | 14 +
Davis/src/db2APRS.c | 1132 +
Davis/src/defs.h | 14 +
FAQ | 1270 +
INSTALL | 1623 ++
LICENSE | 1775 ++
LaCrosse/.cvsignore | 16 +
LaCrosse/AUTHORS | 26 +
LaCrosse/COPYING | 340 +
LaCrosse/CVS/Entries | 12 +
LaCrosse/CVS/Entries.Log | 2 +
LaCrosse/CVS/Repository | 1 +
LaCrosse/CVS/Root | 1 +
LaCrosse/ChangeLog | 3 +
LaCrosse/INSTALL | 232 +
LaCrosse/Makefile.am | 43 +
LaCrosse/NEWS | 3 +
LaCrosse/README | 202 +
LaCrosse/autom4te.cache/CVS/Entries | 1 +
LaCrosse/autom4te.cache/CVS/Repository | 1 +
LaCrosse/autom4te.cache/CVS/Root | 1 +
LaCrosse/bootstrap.sh | 10 +
LaCrosse/configure.ac | 68 +
LaCrosse/src/.cvsignore | 4 +
LaCrosse/src/CVS/Entries | 5 +
LaCrosse/src/CVS/Repository | 1 +
LaCrosse/src/CVS/Root | 1 +
LaCrosse/src/Makefile.am | 15 +
LaCrosse/src/defs.h | 15 +
LaCrosse/src/open2300db2APRS.c | 912 +
LaCrosse/weatherdump.sql | 32 +
Makefile.am | 153 +
Makefile.in | 1129 +
NEWS | 39 +
OSM_template | 52 +
README | 629 +
README.CVS | 414 +
README.CYGWIN | 857 +
README.Contributing | 327 +
README.Getting-Started | 902 +
README.MAPS | 1518 ++
README.OSM_maps | 216 +
README.win32 | 1357 +
TXRadar.geo | 23 +
UPGRADE | 95 +
USRadar.geo | 37 +
WMSRadar.geo | 17 +
acinclude.m4 | 1106 +
aclocal.m4 | 964 +
bootstrap.sh | 69 +
callpass.1 | 29 +
callpass/Makefile.am | 13 +
callpass/Makefile.in | 501 +
callpass/callpass.c | 81 +
config.guess | 1511 ++
config.h.in | 661 +
config.sub | 1705 ++
config/24kgrid.dbfawk | 42 +
config/Makefile.am | 130 +
config/Makefile.in | 534 +
config/OSM_Cloudmade_administrative.dbfawk | 59 +
config/OSM_Cloudmade_highway.dbfawk | 106 +
config/OSM_Cloudmade_natural.dbfawk | 58 +
config/OSM_Cloudmade_poi.dbfawk | 62 +
config/OSM_Cloudmade_water_and_coastline.dbfawk | 59 +
config/arealm.dbfawk | 53 +
config/areawater.dbfawk | 52 +
config/cousub.dbfawk | 52 +
config/cousub00.dbfawk | 51 +
config/edge.dbfawk | 87 +
config/featnames.dbfawk | 87 +
config/gfe_coastal_waters.dbfawk | 42 +
config/gfe_coastal_waters_warnings.dbfawk | 42 +
config/gfe_fire_weather.dbfawk | 42 +
config/gfe_metro_areas.dbfawk | 42 +
config/gfe_public_weather.dbfawk | 42 +
config/gps_wpt.dbfawk | 20 +
config/language-Dutch.sys | 1372 +
config/language-ElmerFudd.sys | 1143 +
config/language-English.sys | 1352 +
config/language-French.sys | 1366 +
config/language-German.sys | 1363 +
config/language-Italian.sys | 1354 +
config/language-MuppetsChef.sys | 1143 +
config/language-OldeEnglish.sys | 1143 +
config/language-PigLatin.sys | 1143 +
config/language-PirateEnglish.sys | 1143 +
config/language-Portuguese.sys | 1353 +
config/language-Spanish.sys | 1345 +
config/nwsc_ddmmyy.dbfawk | 55 +
config/nwsc_ddmmyy_09.dbfawk | 59 +
config/nwsc_ddmmyy_09b.dbfawk | 59 +
config/nwsc_ddmmyy_10.dbfawk | 59 +
config/nwsc_ddmmyy_10a.dbfawk | 59 +
config/nwshzddmmyy.dbfawk | 42 +
config/nwsmzddmmyy.dbfawk | 41 +
config/nwsmzddmmyy_09.dbfawk | 41 +
config/nwsmzddmmyy_11.dbfawk | 41 +
config/nwsmzoddmmyy.dbfawk | 41 +
config/nwsozddap12.dbfawk | 42 +
config/nwsozddmmyy.dbfawk | 42 +
config/nwsozddmmyy_09.dbfawk | 42 +
config/nwsw_ddjn12.dbfawk | 41 +
config/nwsw_ddmmyy.dbfawk | 41 +
config/nwsw_ddmmyy_09.dbfawk | 41 +
config/nwsw_ddmmyy_10.dbfawk | 41 +
config/nwsz1ddmmyy.dbfawk | 42 +
config/nwsz_ddmmyy.dbfawk | 42 +
config/nwsz_ddmmyy_09.dbfawk | 42 +
config/nwsz_ddmmyy_10.dbfawk | 42 +
config/nwsz_ddmmyy_10b.dbfawk | 42 +
config/nwsz_ddmmyy_10c.dbfawk | 42 +
config/nwsz_ddmmyy_11.dbfawk | 43 +
config/nwszoddmmyy.dbfawk | 42 +
config/pointlm.dbfawk | 63 +
config/predefined_EVENT.sys | 109 +
config/predefined_SAR.sys | 135 +
config/stored_track.dbfawk | 15 +
config/tabblock.dbfawk | 53 +
config/tgr2shp.dbfawk | 263 +
config/tgr2shppoly.dbfawk | 262 +
config/tgr2shppoly_2006.dbfawk | 265 +
config/tgrcty.dbfawk | 48 +
config/tgrkgl.dbfawk | 66 +
config/tgrlk.dbfawk | 247 +
config/tgrlpt.dbfawk | 106 +
config/tgrlpy.dbfawk | 48 +
config/tgrplc00.dbfawk | 38 +
config/tgrwat.dbfawk | 49 +
config/tl_2009_aiannh.dbfawk | 52 +
config/tl_2009_aits.dbfawk | 52 +
config/tl_2009_arealm.dbfawk | 104 +
config/tl_2009_areawater.dbfawk | 74 +
config/tl_2009_county.dbfawk | 55 +
config/tl_2009_cousub.dbfawk | 55 +
config/tl_2009_edges.dbfawk | 100 +
config/tl_2009_mil.dbfawk | 47 +
config/tl_2009_nn_county.dbfawk | 56 +
config/tl_2009_pointlm.dbfawk | 135 +
config/tl_2009_zcta5.dbfawk | 47 +
config/tnc-startup.aea | 47 +
config/tnc-startup.d700 | 69 +
config/tnc-startup.d72_d710 | 47 +
config/tnc-startup.kam | 43 +
config/tnc-startup.kpc2 | 30 +
config/tnc-startup.kpc3 | 76 +
config/tnc-startup.null | 0
config/tnc-startup.paccomm | 50 +
config/tnc-startup.pico | 86 +
config/tnc-startup.sys | 56 +
config/tnc-startup.thd7 | 79 +
config/tnc-startup.tnc2 | 48 +
config/tnc-startup.tnc2-ui | 19 +
config/tnc-stop.d700 | 48 +
config/tnc-stop.d72_d710 | 39 +
config/tnc-stop.sys | 9 +
config/tnc-stop.thd7 | 39 +
config/tnc-stop.tnc2-ui | 12 +
config/xastir.rgb | 92 +
configure | 14320 +++++++++++
configure.ac | 1003 +
depcomp | 630 +
help/Makefile.am | 22 +
help/Makefile.in | 430 +
help/help-Dutch.dat | 3099 +++
help/help-English.dat | 3099 +++
help/help-French.dat | 593 +
help/help-German.dat | 1957 ++
help/help-Italian.dat | 1047 +
help/help-Portuguese.dat | 3099 +++
help/help-Spanish.dat | 1681 ++
install-sh | 520 +
m4/Makefile.am | 5 +
m4/Makefile.in | 364 +
m4/xmhtml.m4 | 215 +
missing | 376 +
mkinstalldirs | 162 +
placeholder | 5 +
scripts/Coordinate.pm | 2465 ++
scripts/Makefile.am | 52 +
scripts/Makefile.in | 467 +
scripts/Xastir_tigerpoly.py | 562 +
scripts/coord-convert.pl | 280 +
scripts/geopdf2gtiff.pl | 231 +
scripts/get-BOMdata | 95 +
scripts/get-NWSdata | 91 +
scripts/get-fcc-rac.pl | 141 +
scripts/get-gnis | 75 +
scripts/get-maptools.sh | 370 +
scripts/get-pop | 81 +
scripts/get_shapelib.sh | 189 +
scripts/gpx2shape | 218 +
scripts/icontable.pl | 158 +
scripts/inf2geo.pl | 249 +
scripts/kiss-off.pl | 40 +
scripts/langElmerFudd.pl | 94 +
scripts/langMuppetsChef.pl | 145 +
scripts/langOldeEnglish.pl | 129 +
scripts/langPigLatin.pl | 85 +
scripts/langPirateEnglish.pl | 545 +
scripts/mapblast2geo.pl | 200 +
scripts/mapfgd.pl | 258 +
scripts/object2shp.pl | 147 +
scripts/overlay.pl | 248 +
scripts/ozi2geo.pl | 211 +
scripts/permutations.pl | 391 +
scripts/pos2shp.pl | 162 +
scripts/ridge_radar.pl | 62 +
scripts/slideshow.pl | 90 +
scripts/split_gnis.bash | 61 +
scripts/split_gnis.pl | 35 +
scripts/test_coord.pl | 151 +
scripts/toporama250k.pl | 276 +
scripts/toporama50k.pl | 195 +
scripts/track-get.pl | 163 +
scripts/update_langfile.pl | 117 +
scripts/values | 2 +
scripts/values.in | 2 +
scripts/values.pl | 8 +
scripts/values.pl.in | 8 +
scripts/waypoint-get.pl | 165 +
scripts/xastir-fixcfg.sh | 34 +
scripts/xastir-migrate.sh | 60 +
src/Makefile.am | 103 +
src/Makefile.in | 837 +
src/alert.c | 2275 ++
src/alert.h | 98 +
src/awk.c | 1111 +
src/awk.h | 127 +
src/bulletin_gui.c | 804 +
src/bulletin_gui.h | 38 +
src/color.c | 304 +
src/color.h | 53 +
src/compiledate.c | 1 +
src/database.h | 669 +
src/datum.c | 818 +
src/datum.h | 112 +
src/db.c | 19490 ++++++++++++++
src/db_gis.c | 2675 ++
src/db_gis.h | 176 +
src/dbfawk.c | 498 +
src/dbfawk.h | 65 +
src/draw_symbols.c | 3547 +++
src/draw_symbols.h | 77 +
src/fcc_data.c | 503 +
src/fcc_data.h | 90 +
src/festival.c | 476 +
src/festival.h | 102 +
src/fetch_remote.c | 267 +
src/fetch_remote.h | 40 +
src/geo-find.c | 529 +
src/geo.h | 49 +
src/geocoder_gui.c | 572 +
src/gps.c | 874 +
src/gps.h | 44 +
src/hashtable.c | 277 +
src/hashtable.h | 194 +
src/hashtable_itr.c | 212 +
src/hashtable_itr.h | 123 +
src/hashtable_private.h | 80 +
src/hostname.c | 347 +
src/hostname.h | 33 +
src/icon.xbm | 20 +
src/igate.c | 1443 ++
src/igate.h | 41 +
src/interface.c | 10181 ++++++++
src/interface.h | 276 +
src/interface_gui.c | 9146 +++++++
src/io-common.c | 70 +
src/io-mmap.c | 218 +
src/io.h | 54 +
src/lang.c | 255 +
src/lang.h | 39 +
src/leak_detection.h | 101 +
src/list_gui.c | 2489 ++
src/list_gui.h | 50 +
src/locate_gui.c | 1220 +
src/location.c | 104 +
src/location_gui.c | 592 +
src/main.c | 28028 ++++++++++++++++++++
src/main.h | 463 +
src/map_OSM.c | 1655 ++
src/map_OSM.h | 60 +
src/map_WMS.c | 1042 +
src/map_cache.c | 1059 +
src/map_cache.h | 79 +
src/map_dos.c | 1364 +
src/map_gdal.c | 5087 ++++
src/map_geo.c | 2550 ++
src/map_gnis.c | 1405 +
src/map_pdb.c | 585 +
src/map_pop.c | 1405 +
src/map_shp.c | 4182 +++
src/map_tif.c | 2824 ++
src/map_tiger.c | 969 +
src/maps.c | 9061 +++++++
src/maps.h | 230 +
src/messages.c | 1480 ++
src/messages.h | 123 +
src/messages_gui.c | 2673 ++
src/objects.c | 11106 ++++++++
src/objects.h | 160 +
src/popup.h | 47 +
src/popup_gui.c | 382 +
src/rac_data.c | 386 +
src/rac_data.h | 63 +
src/rotated.c | 1618 ++
src/rotated.h | 89 +
src/rpl_malloc.c | 59 +
src/rpl_malloc.h | 37 +
src/rtree/Makefile.am | 13 +
src/rtree/Makefile.in | 476 +
src/rtree/card.c | 52 +
src/rtree/card.h | 49 +
src/rtree/index.c | 367 +
src/rtree/index.h | 130 +
src/rtree/node.c | 285 +
src/rtree/rect.c | 393 +
src/rtree/split_l.c | 408 +
src/rtree/split_l.h | 54 +
src/shapelib/ChangeLog | 204 +
src/shapelib/LICENSE.LGPL | 483 +
src/shapelib/Makefile.am | 42 +
src/shapelib/Makefile.in | 724 +
src/shapelib/README | 35 +
src/shapelib/README.tree | 172 +
src/shapelib/contrib/Makefile.am | 51 +
src/shapelib/contrib/Makefile.in | 627 +
src/shapelib/contrib/Makefile_orig | 59 +
src/shapelib/contrib/ShapeFileII.pas | 254 +
src/shapelib/contrib/dbfcat.c | 209 +
src/shapelib/contrib/dbfinfo.c | 135 +
src/shapelib/contrib/makefile.vc | 29 +
src/shapelib/contrib/my_nan.h | 56 +
src/shapelib/contrib/shpcat.c | 99 +
src/shapelib/contrib/shpcentrd.c | 190 +
src/shapelib/contrib/shpdata.c | 164 +
src/shapelib/contrib/shpdxf.c | 328 +
src/shapelib/contrib/shpfix.c | 111 +
src/shapelib/contrib/shpgeo.c | 1642 ++
src/shapelib/contrib/shpgeo.h | 177 +
src/shapelib/contrib/shpinfo.c | 147 +
src/shapelib/contrib/shpproj.c | 297 +
src/shapelib/contrib/shpwkb.c | 160 +
src/shapelib/dbf_api.html | 408 +
src/shapelib/dbfadd.c | 151 +
src/shapelib/dbfcreate.c | 150 +
src/shapelib/dbfdump.c | 305 +
src/shapelib/dbfopen.c | 1526 ++
src/shapelib/libtool | 4149 +++
src/shapelib/makefile.vc | 55 +
src/shapelib/makeshape.sh | 21 +
src/shapelib/mkinstalldirs | 38 +
src/shapelib/shapefil.h | 507 +
src/shapelib/shapelib.def | 42 +
src/shapelib/shapelib.html | 334 +
src/shapelib/shp_api.html | 376 +
src/shapelib/shpadd.c | 197 +
src/shapelib/shpcreate.c | 138 +
src/shapelib/shpdump.c | 234 +
src/shapelib/shpopen.c | 1892 ++
src/shapelib/shprewind.c | 140 +
src/shapelib/shptest.c | 333 +
src/shapelib/shptree.c | 705 +
src/shapelib/shptreedump.c | 430 +
src/shapelib/shputils.c | 1124 +
src/shapelib/stream1.out | 1465 ++
src/shapelib/stream1.sh | 28 +
src/shapelib/stream2.out | 530 +
src/shapelib/stream2.sh | 11 +
src/shapelib/stream3.out | 37 +
src/shp_hash.c | 390 +
src/shp_hash.h | 39 +
src/snprintf.c | 747 +
src/snprintf.h | 59 +
src/sound.c | 124 +
src/symbols.h | 33 +
src/testdbfawk.c | 282 +
src/tile_mgmnt.c | 355 +
src/tile_mgmnt.h | 63 +
src/track_gui.c | 1007 +
src/track_gui.h | 42 +
src/util.c | 5738 +++++
src/util.h | 179 +
src/view_message_gui.c | 732 +
src/wx.c | 3770 +++
src/wx.h | 79 +
src/wx_gui.c | 2116 ++
src/x_spider.c | 1725 ++
src/x_spider.h | 48 +
src/xa_config.c | 2489 ++
src/xa_config.h | 35 +
src/xastir.h | 270 +
src/xastir_udp_client.c | 212 +
symbols/13pct.xbm | 5 +
symbols/25pct.xbm | 5 +
symbols/2x2.xbm | 5 +
symbols/Makefile.am | 8 +
symbols/Makefile.in | 414 +
symbols/alert.xbm | 41 +
symbols/flood.xbm | 41 +
symbols/icon.png | Bin 0 -> 313 bytes
symbols/red_flag.xbm | 41 +
symbols/snow.xbm | 41 +
symbols/symbols.dat | 4758 ++++
symbols/torndo.xbm | 41 +
symbols/wind.xbm | 41 +
symbols/winter_storm.xbm | 41 +
symbols/winter_weather.xbm | 41 +
terraserver-reflectivity.geo | 2 +
terraserver-topo.geo | 2 +
terraserver-urban.geo | 2 +
terraserver.geo | 2 +
testdbfawk.1 | 48 +
worldhi.map | Bin 0 -> 274556 bytes
xastir-lsb.spec.in | 108 +
xastir-min.spec | 77 +
xastir-min.spec.in | 77 +
xastir.1 | 108 +
xastir.spec | 77 +
xastir.spec.in | 77 +
xastir_udp_client.1 | 43 +
450 files changed, 314202 insertions(+)
diff --git a/ABOUT-NLS b/ABOUT-NLS
new file mode 100644
index 0000000..28d38c7
--- /dev/null
+++ b/ABOUT-NLS
@@ -0,0 +1,226 @@
+Notes on the Free Translation Project
+*************************************
+
+ Free software is going international! The Free Translation Project
+is a way to get maintainers of free software, translators, and users all
+together, so that will gradually become able to speak many languages.
+A few packages already provide translations for their messages.
+
+ If you found this `ABOUT-NLS' file inside a distribution, you may
+assume that the distributed package does use GNU `gettext' internally,
+itself available at your nearest GNU archive site. But you do *not*
+need to install GNU `gettext' prior to configuring, installing or using
+this package with messages translated.
+
+ Installers will find here some useful hints. These notes also
+explain how users should proceed for getting the programs to use the
+available translations. They tell how people wanting to contribute and
+work at translations should contact the appropriate team.
+
+ When reporting bugs in the `intl/' directory or bugs which may be
+related to internationalization, you should tell about the version of
+`gettext' which is used. The information can be found in the
+`intl/VERSION' file, in internationalized packages.
+
+One advise in advance
+=====================
+
+ If you want to exploit the full power of internationalization, you
+should configure it using
+
+ ./configure --with-included-gettext
+
+to force usage of internationalizing routines provided within this
+package, despite the existence of internationalizing capabilities in the
+operating system where this package is being installed. So far, only
+the `gettext' implementation in the GNU C library version 2 provides as
+many features (such as locale alias or message inheritance) as the
+implementation here. It is also not possible to offer this additional
+functionality on top of a `catgets' implementation. Future versions of
+GNU `gettext' will very likely convey even more functionality. So it
+might be a good idea to change to GNU `gettext' as soon as possible.
+
+ So you need not provide this option if you are using GNU libc 2 or
+you have installed a recent copy of the GNU gettext package with the
+included `libintl'.
+
+INSTALL Matters
+===============
+
+ Some packages are "localizable" when properly installed; the
+programs they contain can be made to speak your own native language.
+Most such packages use GNU `gettext'. Other packages have their own
+ways to internationalization, predating GNU `gettext'.
+
+ By default, this package will be installed to allow translation of
+messages. It will automatically detect whether the system provides
+usable `catgets' (if using this is selected by the installer) or
+`gettext' functions. If neither is available, the GNU `gettext' own
+library will be used. This library is wholly contained within this
+package, usually in the `intl/' subdirectory, so prior installation of
+the GNU `gettext' package is *not* required. Installers may use
+special options at configuration time for changing the default
+behaviour. The commands:
+
+ ./configure --with-included-gettext
+ ./configure --with-catgets
+ ./configure --disable-nls
+
+will respectively bypass any pre-existing `catgets' or `gettext' to use
+the internationalizing routines provided within this package, enable
+the use of the `catgets' functions (if found on the locale system), or
+else, *totally* disable translation of messages.
+
+ When you already have GNU `gettext' installed on your system and run
+configure without an option for your new package, `configure' will
+probably detect the previously built and installed `libintl.a' file and
+will decide to use this. This might be not what is desirable. You
+should use the more recent version of the GNU `gettext' library. I.e.
+if the file `intl/VERSION' shows that the library which comes with this
+package is more recent, you should use
+
+ ./configure --with-included-gettext
+
+to prevent auto-detection.
+
+ By default the configuration process will not test for the `catgets'
+function and therefore they will not be used. The reasons are already
+given above: the emulation on top of `catgets' cannot provide all the
+extensions provided by the GNU `gettext' library. If you nevertheless
+want to use the `catgets' functions use
+
+ ./configure --with-catgets
+
+to enable the test for `catgets' (this causes no harm if `catgets' is
+not available on your system). If you really select this option we
+would like to hear about the reasons because we cannot think of any
+good one ourself.
+
+ Internationalized packages have usually many `po/LL.po' files, where
+LL gives an ISO 639 two-letter code identifying the language. Unless
+translations have been forbidden at `configure' time by using the
+`--disable-nls' switch, all available translations are installed
+together with the package. However, the environment variable `LINGUAS'
+may be set, prior to configuration, to limit the installed set.
+`LINGUAS' should then contain a space separated list of two-letter
+codes, stating which languages are allowed.
+
+Using This Package
+==================
+
+ As a user, if your language has been installed for this package, you
+only have to set the `LANG' environment variable to the appropriate
+ISO 639 `LL' two-letter code prior to using the programs in the
+package. For example, let's suppose that you speak German. At the
+shell prompt, merely execute `setenv LANG de' (in `csh'),
+`export LANG; LANG=de' (in `sh') or `export LANG=de' (in `bash'). This
+can be done from your `.login' or `.profile' file, once and for all.
+
+ An operating system might already offer message localization for
+many of its programs, while other programs have been installed locally
+with the full capabilities of GNU `gettext'. Just using `gettext'
+extended syntax for `LANG' would break proper localization of already
+available operating system programs. In this case, users should set
+both `LANGUAGE' and `LANG' variables in their environment, as programs
+using GNU `gettext' give preference to `LANGUAGE'. For example, some
+Swedish users would rather read translations in German than English for
+when Swedish is not available. This is easily accomplished by setting
+`LANGUAGE' to `sv:de' while leaving `LANG' to `sv'.
+
+Translating Teams
+=================
+
+ For the Free Translation Project to be a success, we need interested
+people who like their own language and write it well, and who are also
+able to synergize with other translators speaking the same language.
+Each translation team has its own mailing list, courtesy of Linux
+International. You may reach your translation team at the address
+`LL at li.org', replacing LL by the two-letter ISO 639 code for your
+language. Language codes are *not* the same as the country codes given
+in ISO 3166. The following translation teams exist, as of December
+1997:
+
+ Chinese `zh', Czech `cs', Danish `da', Dutch `nl', English `en',
+ Esperanto `eo', Finnish `fi', French `fr', German `de', Hungarian
+ `hu', Irish `ga', Italian `it', Indonesian `id', Japanese `ja',
+ Korean `ko', Latin `la', Norwegian `no', Persian `fa', Polish
+ `pl', Portuguese `pt', Russian `ru', Slovenian `sl', Spanish `es',
+ Swedish `sv', and Turkish `tr'.
+
+For example, you may reach the Chinese translation team by writing to
+`zh at li.org'.
+
+ If you'd like to volunteer to *work* at translating messages, you
+should become a member of the translating team for your own language.
+The subscribing address is *not* the same as the list itself, it has
+`-request' appended. For example, speakers of Swedish can send a
+message to `sv-request at li.org', having this message body:
+
+ subscribe
+
+ Keep in mind that team members are expected to participate
+*actively* in translations, or at solving translational difficulties,
+rather than merely lurking around. If your team does not exist yet and
+you want to start one, or if you are unsure about what to do or how to
+get started, please write to `translation at iro.umontreal.ca' to reach the
+coordinator for all translator teams.
+
+ The English team is special. It works at improving and uniformizing
+the terminology in use. Proven linguistic skill are praised more than
+programming skill, here.
+
+Available Packages
+==================
+
+ Languages are not equally supported in all packages. The following
+matrix shows the current state of internationalization, as of December
+1997. The matrix shows, in regard of each package, for which languages
+PO files have been submitted to translation coordination.
+
+ Ready PO files cs da de en es fi fr it ja ko nl no pl pt ru sl sv
+ .----------------------------------------------------.
+ bash | [] [] [] | 3
+ bison | [] [] [] | 3
+ clisp | [] [] [] [] | 4
+ cpio | [] [] [] [] [] [] | 6
+ diffutils | [] [] [] [] [] | 5
+ enscript | [] [] [] [] [] [] | 6
+ fileutils | [] [] [] [] [] [] [] [] [] [] | 10
+ findutils | [] [] [] [] [] [] [] [] [] | 9
+ flex | [] [] [] [] | 4
+ gcal | [] [] [] [] [] | 5
+ gettext | [] [] [] [] [] [] [] [] [] [] [] | 12
+ grep | [] [] [] [] [] [] [] [] [] [] | 10
+ hello | [] [] [] [] [] [] [] [] [] [] [] | 11
+ id-utils | [] [] [] | 3
+ indent | [] [] [] [] [] | 5
+ libc | [] [] [] [] [] [] [] | 7
+ m4 | [] [] [] [] [] [] | 6
+ make | [] [] [] [] [] [] | 6
+ music | [] [] | 2
+ ptx | [] [] [] [] [] [] [] [] | 8
+ recode | [] [] [] [] [] [] [] [] [] | 9
+ sh-utils | [] [] [] [] [] [] [] [] | 8
+ sharutils | [] [] [] [] [] [] | 6
+ tar | [] [] [] [] [] [] [] [] [] [] [] | 11
+ texinfo | [] [] [] | 3
+ textutils | [] [] [] [] [] [] [] [] [] | 9
+ wdiff | [] [] [] [] [] [] [] [] | 8
+ `----------------------------------------------------'
+ 17 languages cs da de en es fi fr it ja ko nl no pl pt ru sl sv
+ 27 packages 6 4 25 1 18 1 26 2 1 12 20 9 19 7 4 7 17 179
+
+ Some counters in the preceding matrix are higher than the number of
+visible blocks let us expect. This is because a few extra PO files are
+used for implementing regional variants of languages, or language
+dialects.
+
+ For a PO file in the matrix above to be effective, the package to
+which it applies should also have been internationalized and
+distributed as such by its maintainer. There might be an observable
+lag between the mere existence a PO file and its wide availability in a
+distribution.
+
+ If December 1997 seems to be old, you may fetch a more recent copy
+of this `ABOUT-NLS' file on most GNU archive sites.
+
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..ffa06c6
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,59 @@
+
+$Id: AUTHORS,v 1.25 2012/11/01 18:57:18 we7u Exp $
+
+ Developers and Contributors
+ _________________________________________________________________
+
+ Here we attempt to list most of the Xastir developers and contributors
+ who have devoted large amounts of time to making Xastir one of the best
+ APRS(tm) clients ever. Unfortunately we can't devote much time to
+ keeping this list current or adding new contributors.
+
+ Xastir was originally written by Frank Giannandrea, KC2GJS (was KC0DGE).
+
+ APRS(tm) is a Trademark of Bob Bruninga
+
+ Developers and Contributors (in alphabetical order):
+
+ DK7IN Rolf Bleher
+ HI8GN Jose R Marte A
+ IK0YUP Alessandro Frigeri
+ KA6HLD Jerry Dunmire
+ KA9KIM Mike Sims
+ KB3EGH Derrick Brashear
+ KB3EHW Reuven Gevaryahu (our resident docs guy!)
+ KC2ELS Jack Twilley
+ KD5AMB Mark Grennan
+ KD6VPE Jim Sevilla
+ KD6ZWR Chris Bell
+ KE4NFJ Gerald Stueve (K4INT)
+ KG4IJB Charles Byam (fearless leader)
+ KM5VY Tom Russo
+ N0VH Jim Chandler
+ N2YGK Alan Crosswell
+ N3NYN Michael G Petry
+ N7IPB Ken Koster
+ N7TAP Olivier Calle
+ N8YSZ Dan Brown
+ PE1DNN Henk de Groot
+ VE3UNW Richard Hagemyer
+ VE6LFM Lloyd Miller
+ WE7U Curt Mills (lackey)
+
+ SmartBeaconing(tm) was invented by Tony Arnerich (KD7TA) and Steve
+ Bragg (KA9MVA) for the HamHUD project. They offer the algorithm to
+ other authors as long as proper credit is given and the term
+ SmartBeaconing(tm) is used to describe it. So be it. Thanks Tony
+ and Steve!
+
+ Thanks go to all the people who have made individual contributions to
+ the Xastir project by sending bug-reports, patches, or who have
+ otherwise supported the project. There are too many to list.
+
+ If you think that you are missing from this list contact the Xastir
+ Development Team at <http://sourceforge.net/projects/xastir/> or at
+ <http://xastir.sourceforge.net>.
+ _________________________________________________________________
+
+ Copyright (C) 2000-2012 The Xastir Group
+
diff --git a/CC_OpenStreetMap_logo.png b/CC_OpenStreetMap_logo.png
new file mode 100644
index 0000000..dd49add
Binary files /dev/null and b/CC_OpenStreetMap_logo.png differ
diff --git a/CC_OpenStreetMap_txt.png b/CC_OpenStreetMap_txt.png
new file mode 100644
index 0000000..c953572
Binary files /dev/null and b/CC_OpenStreetMap_txt.png differ
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/COPYING.LIB.LESSTIF b/COPYING.LIB.LESSTIF
new file mode 100644
index 0000000..eb685a5
--- /dev/null
+++ b/COPYING.LIB.LESSTIF
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/CanadaTopo250k.geo b/CanadaTopo250k.geo
new file mode 100644
index 0000000..661ca67
--- /dev/null
+++ b/CanadaTopo250k.geo
@@ -0,0 +1,2 @@
+TOPORAMA-250k
+
diff --git a/CanadaTopo50k.geo b/CanadaTopo50k.geo
new file mode 100644
index 0000000..c503678
--- /dev/null
+++ b/CanadaTopo50k.geo
@@ -0,0 +1,2 @@
+TOPORAMA-50k
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..243cdf5
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,30054 @@
+2012-11-01 11:57 we7u
+
+ * .cvsignore, AUTHORS, ChangeLog, DEBUG_LEVELS, FAQ, INSTALL,
+ LICENSE, Makefile.am, NEWS, README, README.CVS, README.CYGWIN,
+ README.Contributing, README.OSM_maps, README.win32,
+ REGRESSION_TESTS, UPGRADE, acinclude.m4, bootstrap.sh,
+ callpass.1, changes.txt, configure.ac, install-xastir,
+ testdbfawk.1, update-xastir, xastir.1, xastir_udp_client.1,
+ Davis/Makefile.am, Davis/README, Davis/bootstrap.sh,
+ Davis/configure.ac, Davis/src/Makefile.am, Davis/src/db2APRS.c,
+ Davis/src/defs.h, LaCrosse/Makefile.am, LaCrosse/README,
+ LaCrosse/bootstrap.sh, LaCrosse/configure.ac,
+ LaCrosse/src/Makefile.am, LaCrosse/src/defs.h,
+ LaCrosse/src/open2300db2APRS.c, callpass/Makefile.am,
+ callpass/callpass.c, config/24kgrid.dbfawk,
+ config/OSM_Cloudmade_administrative.dbfawk,
+ config/OSM_Cloudmade_highway.dbfawk,
+ config/OSM_Cloudmade_natural.dbfawk,
+ config/OSM_Cloudmade_poi.dbfawk,
+ config/OSM_Cloudmade_water_and_coastline.dbfawk,
+ config/arealm.dbfawk, config/areawater.dbfawk,
+ config/cousub.dbfawk, config/cousub00.dbfawk, config/edge.dbfawk,
+ config/featnames.dbfawk, config/gps_wpt.dbfawk,
+ config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, config/nwsc_ddmmyy.dbfawk,
+ config/nwsc_ddmmyy_09.dbfawk, config/nwsc_ddmmyy_09b.dbfawk,
+ config/nwsc_ddmmyy_10.dbfawk, config/nwsc_ddmmyy_10a.dbfawk,
+ config/nwshzddmmyy.dbfawk, config/nwsmzddmmyy.dbfawk,
+ config/nwsmzddmmyy_09.dbfawk, config/nwsmzddmmyy_11.dbfawk,
+ config/nwsmzoddmmyy.dbfawk, config/nwsozddap12.dbfawk,
+ config/nwsozddmmyy.dbfawk, config/nwsozddmmyy_09.dbfawk,
+ config/nwsw_ddjn12.dbfawk, config/nwsw_ddmmyy.dbfawk,
+ config/nwsw_ddmmyy_09.dbfawk, config/nwsw_ddmmyy_10.dbfawk,
+ config/nwsz1ddmmyy.dbfawk, config/nwsz_ddmmyy.dbfawk,
+ config/nwsz_ddmmyy_09.dbfawk, config/nwsz_ddmmyy_10.dbfawk,
+ config/nwsz_ddmmyy_10b.dbfawk, config/nwsz_ddmmyy_10c.dbfawk,
+ config/nwszoddmmyy.dbfawk, config/pointlm.dbfawk,
+ config/predefined_EVENT.sys, config/predefined_SAR.sys,
+ config/stored_track.dbfawk, config/tabblock.dbfawk,
+ config/tgr2shp.dbfawk, config/tgr2shppoly.dbfawk,
+ config/tgr2shppoly_2006.dbfawk, config/tgrcty.dbfawk,
+ config/tgrkgl.dbfawk, config/tgrlk.dbfawk, config/tgrlpt.dbfawk,
+ config/tgrlpy.dbfawk, config/tgrplc00.dbfawk,
+ config/tgrwat.dbfawk, config/tl_2009_nn_county.dbfawk,
+ config/tnc-startup.aea, config/tnc-startup.d700,
+ config/tnc-startup.d72_d710, config/tnc-startup.kam,
+ config/tnc-startup.kpc2, config/tnc-startup.kpc3,
+ config/tnc-startup.paccomm, config/tnc-startup.pico,
+ config/tnc-startup.sys, config/tnc-startup.thd7,
+ config/tnc-startup.tnc2, config/tnc-startup.tnc2-ui,
+ config/tnc-stop.d700, config/tnc-stop.d72_d710,
+ config/tnc-stop.sys, config/tnc-stop.thd7,
+ config/tnc-stop.tnc2-ui, help/Makefile.am, help/help-Dutch.dat,
+ help/help-English.dat, help/help-French.dat,
+ help/help-German.dat, help/help-Italian.dat,
+ help/help-Portuguese.dat, help/help-Spanish.dat, m4/Makefile.am,
+ scripts/BUILDRPMS, scripts/Coordinate.pm, scripts/LSB-BUILD,
+ scripts/LSB-BUILD-ALL, scripts/LSB-BUILD-CURL,
+ scripts/LSB-BUILD-DB, scripts/LSB-BUILD-GDAL,
+ scripts/LSB-BUILD-GRAPHICSMAGICK, scripts/LSB-BUILD-JASPER,
+ scripts/LSB-BUILD-JPEG, scripts/LSB-BUILD-LESSTIF,
+ scripts/LSB-BUILD-PCRE, scripts/LSB-BUILD-PNG,
+ scripts/LSB-BUILD-ZLIB, scripts/UIView2XastirLog.pl,
+ scripts/Xastir_tigerpoly.py, scripts/do_xastir_release_dev,
+ scripts/do_xastir_release_stable, scripts/example_objects.log,
+ scripts/geopdf2gtiff.pl, scripts/get-fcc-rac.pl,
+ scripts/get-gnis, scripts/get-maptools.sh, scripts/get-pop,
+ scripts/get_shapelib.sh, scripts/kiss-off.pl,
+ scripts/langElmerFudd.pl, scripts/langMuppetsChef.pl,
+ scripts/langOldeEnglish.pl, scripts/langPigLatin.pl,
+ scripts/langPirateEnglish.pl, scripts/object2shp.pl,
+ scripts/pos2shp.pl, scripts/slideshow.pl, scripts/test_coord.pl,
+ scripts/toporama250k.pl, scripts/toporama50k.pl,
+ scripts/track-get.pl, scripts/waypoint-get.pl,
+ scripts/xastir-fixcfg.sh, scripts/xastir-migrate.sh,
+ src/Makefile.am, src/alert.h, src/awk.h, src/bulletin_gui.h,
+ src/color.h, src/database.h, src/datum.h, src/db_gis.h,
+ src/dbfawk.h, src/draw_symbols.h, src/fcc_data.h, src/festival.h,
+ src/fetch_remote.h, src/geo.h, src/gps.h, src/hashtable.h,
+ src/hashtable_itr.h, src/hashtable_private.h, src/hostname.h,
+ src/igate.h, src/interface.h, src/io.h, src/lang.h,
+ src/leak_detection.h, src/list_gui.h, src/macspeech.c,
+ src/main.h, src/map_OSM.c, src/map_OSM.h, src/map_cache.h,
+ src/maps.h, src/messages.h, src/objects.h, src/popup.h,
+ src/rac_data.h, src/rotated.h, src/rpl_malloc.h, src/shp_hash.h,
+ src/snprintf.h, src/symbols.h, src/tile_mgmnt.h, src/track_gui.h,
+ src/util.h, src/wx.h, src/x_spider.h, src/xa_config.h,
+ src/xastir.h, src/rtree/Makefile.am, src/rtree/card.c,
+ src/rtree/card.h, src/rtree/gammavol.c, src/rtree/index.c,
+ src/rtree/index.h, src/rtree/node.c, src/rtree/rect.c,
+ src/rtree/sphvol.c, src/rtree/split_l.c, src/rtree/split_l.h,
+ src/rtree/split_q.c, src/rtree/split_q.h,
+ src/shapelib/Makefile.am, src/shapelib/contrib/Makefile.am,
+ symbols/Makefile.am, symbols/symbols.dat: Updating the Copyright
+ notices. Bumping revision to 2.0.2 in preparation for stable
+ release.
+
+2012-10-22 17:37 tvrusso
+
+ * src/interface.c: Tidy up a comment and remove some
+ now-commented-out code. At this point, everything that I had
+ hoped to be in the next stable release is in place.
+
+2012-10-22 16:59 we7u
+
+ * src/: interface.c, interface_gui.c, xa_config.c: The rest of the
+ code to implement "TNC Delay" for the serial tnc types of
+ interfaces. This is most useful with a KAM TNC. Note that one
+ can hand edit the value up to 9,999,999 us in the Xastir config
+ file, but pressing the togglebutton will enter 1,000,000 us by
+ default. Thanks for that idea Tom!
+
+2012-10-22 16:40 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface.h,
+ src/interface_gui.c, src/xa_config.c: Implementing the GUI and
+ save/restore portions of the "Add Delay" togglebutton for the
+ three types of Serial TNC interfaces. The back-end code which
+ actually uses the button value hasn't been coded yet.
+
+2012-10-11 11:25 we7u
+
+ * scripts/get-fcc-rac.pl: Fixing the RAC database fetch/install.
+
+2012-10-11 11:09 we7u
+
+ * scripts/get-NWSdata: Updating for the current set of NWS
+ filenames.
+
+2012-10-11 10:58 tvrusso
+
+ * symbols/: Makefile.am, icon.png: Add a PNG icon for Xastir,
+ converted from the icon.xbm file in the src directory.
+
+ I did this because I generally create a desktop shortcut to
+ Xastir on my laptop, and as of the most recent version of Gnome I
+ am unable to use an xbm to do so, but a PNG works.
+
+ This new icon is installed into ${prefix}/share/xastir/symbols
+ and may be used by the user to define a custom icon for a desktop
+ shortcut.
+
+ Remember, the Xastir project does not directly support
+ distro-specific (or desktop-specific) packages, but we do want to
+ make sure that those who generate such packages have the tools
+ and files they need to do so.
+
+2012-10-10 15:18 tvrusso
+
+ * help/: help-Dutch.dat, help-Portuguese.dat: The Dutch and
+ Portuguese help files were actually not in Dutch or Portuguese,
+ but English, and were woefully outdated.
+
+ Copied the current English helpfile into those two, so at least
+ the only thing that's wrong with them would be that they're not
+ in the language they're supposed to be.
+
+2012-10-10 15:16 tvrusso
+
+ * ChangeLog, help/help-English.dat: Regenerate ChangeLog from CVS
+ logs.
+
+ Add a "what's new in Xastir 2.0.1" section to the on-line help.
+
+ Looking over our non-English helpfiles, it is clear that it has
+ been a very long time since anyone has translated the help into
+ other languages. The German help file hasn't been updated since
+ Xastir 1.2, Spanish hasn't been updated since 1.1, and several
+ languages have help files, but they're still in English.
+
+2012-10-10 14:46 tvrusso
+
+ * scripts/cvs2cl.pl: Add cvs2cl script (from
+ http://www.red-bean.com/cvs2cl/cvs2cl.pl) to our tools. This
+ generates a ChangeLog from cvs commit logs.
+
+2012-10-07 10:41 tvrusso
+
+ * configure.ac: Move probe for proj to before probe for shapelib.
+ When using internal shapelib, the probe checks whether "use_proj"
+ is "yes", but until this commit, use_proj was unset until *AFTER*
+ the shapelib probe. This led to warnings from the shell about
+ unary "=" in a test (if test $use_proj = "yes")
+
+2012-10-05 13:19 we7u
+
+ * scripts/get-NWSdata: Updating a file or two, and changing the
+ order of FILE1 and FILE2 in the definitions to match the order
+ they are on the NWS web pages. We will need to check this file
+ again on/after Oct 11 as several of the filenames change then.
+
+2012-10-05 12:56 we7u
+
+ * scripts/get-fcc-rac.pl: Changing the RAC address to one that
+ currently works. The old site looks to have a brand spanking new
+ version of Drupal on it, so they may have messed up the rest of
+ the machine temporarily (or permanently).
+
+2012-09-26 21:15 tvrusso
+
+ * acinclude.m4, configure.ac: Remove some unnecessary macros from
+ the probes for Berkeley DB.
+
+ The code in acinclude.m4 to probe for Berkeley DB was copied from
+ another project, and included a macro that tried to guess how to
+ add a "runpath" to the build. On most systems this is either
+ -Rlibrarydirectory or -Wl,rpath,librarydirectory, but the macro
+ in our acinclude.m4 was in fact correctly identifying the way to
+ do it ONLY on Linux, and then discarding the information anyway.
+ Thus, this was a no-op on Linux, and was wrong elsewhere (but
+ also a no-op). The technique used to do the probe also broke
+ when the compiler was clang, but again, to no effect because the
+ result was discarded anyway.
+
+ SO since the result wasn't used, why probe it? I have removed
+ the macros and replaced the use of "XASTIR_ADD_LIBRARY_TO" with a
+ simple shell variable assignment.
+
+ While I was at it, I removed the deprecated two-argument call to
+ AM_INIT_AUTOMAKE. It has started causing newer versions of
+ automake to complain, and has been deprecated for some time.
+
+2012-09-23 09:19 tvrusso
+
+ * src/: db.c, fcc_data.c, igate.c, interface.c, location_gui.c,
+ main.c, map_OSM.c, map_WMS.c, map_cache.c, map_geo.c, map_shp.c,
+ map_tiger.c, maps.c, messages.c, messages_gui.c, objects.c,
+ rac_data.c, track_gui.c, util.c, xa_config.c, xa_config.h: Big
+ commit for a little, insidious threading problem.
+
+ xa_config.c provides a function called get_user_base_dir(char*)
+ that returns a pointer to a string that is the concatenation of
+ the base configuration directory for Xastir (usually ~/.xastir,
+ but selectable by the user with a command line option or
+ environment variable) and the argument.
+
+ This function was highly thread-unsafe --- it kept a local static
+ char array that it used to build the concatenated string, then
+ returned a pointer to the local array.
+
+ This function was used in multiple threads, meaning that one
+ thread could start scribbling into the static array while another
+ was writing into it. I first tried to fix this by adding a mutex
+ that locked the writes for all but one thread at a time, but that
+ wasn't even good enough, because after unlocking the write mutex
+ another thread could write into the buffer while the first thread
+ was reading the results just produced.
+
+ The result of this mess was a highly unpredictable tendency for
+ Xastir to start producing corrupted paths from this function.
+ This would show up most often on multi-core machines with
+ threading libraries that let threads run simultaneously on
+ different cores, but it could show up on single-core machines
+ with just the right scheduler. It is revealed most easily by
+ enabling multiple logging options (e.g. TNC logging, NET logging,
+ WX logging) and PNG snapshots all at once. In testing, I found
+ this sufficient to produce corrupted file paths in an hour or so.
+ I'm somewhat surprised that nobody has ever reported this issue,
+ because I've been seeing it for ages.
+
+ This commit replaces the original get_user_base_dir
+ implementation with one that requires the caller to provide its
+ own buffer, and completely removes the use of the static buffer.
+ More than 200 calls to get_user_base_dir had to be modified, but
+ some simplifcation was also possible --- I was able to replace a
+ few usages like this:
+
+ xastir_snprintf(dest_string, sizeof(dest_string), "%s",
+ get_user_base_dir("tmp"));
+
+ with: get_user_base_dir("tmp", dest_string,
+ sizeof(dest_string));
+
+ get_user_base_dir still returns the pointer to the destination
+ string, so it can still be used as an argument to log_data or
+ xastir_snprintf where necessary.
+
+ I also replaced several wasteful uses of the function. There
+ were places where get_user_base_dir was being called repeatedly
+ with the same argument many times in a single function. I
+ replaced this usage in many cases with a single call to store the
+ answer in a local buffer, and use that repeatedly.
+
+ Since implementing this change I have seen Xastir run without
+ producing a single corrupted path, even with TNC, NET, and WX
+ logging and PNG snapshots turned on.
+
+2012-09-21 18:32 tvrusso
+
+ * configure.ac, src/main.c: Ifdef out the hack added to main.c to
+ deal with the broken Xorg-server 1.7.5. This server version had
+ a bug that interfered with all motif programs, causing them to
+ grab the cursor and never release it when a context (pop-up) menu
+ was created. The bug was promptly fixed, but not before several
+ distros locked in version 1.7.5 as their supported version.
+
+ The workaround ungrabs the cursor, but has the annoying
+ side-effect of making the user hold down the button that brings
+ up the menu, rather than allowing a quick click to access it.
+
+ This commit puts the hack into an ifdef, and enables the user to
+ select the workaround by adding "--with-xorg_175_workaround" to
+ the configure line. The default behavior is now to NOT use the
+ workaround.
+
+ The workaround and configure.ac code to enable it should be
+ removed completely in one release cycle. Xorg-server 1.7.5 is
+ long gone, and keeping this code around is a nod to the fact that
+ some people do not upgrade for years. One more release cycle
+ should be enough to forget this mistake ever happened.
+
+2012-09-20 22:11 tvrusso
+
+ * src/map_OSM.c: Patch from Tom Hayward (KD7LXL):
+
+ This patch fixes an issue in the OSM tile download loop. If a
+ tile is 404, 403, or any other error that doesn't return a valid
+ image, imagemagick (or gm) puts the error info in &exception.
+ Subsequent iterations read &exception, note the error, and fail
+ to composite any further tiles. This patch adds
+ GetExceptionInfo() to the end of the loop, so subsequent
+ iterations do not start off with error info in the exception
+ struct.
+
+2012-09-19 07:56 tvrusso
+
+ * Davis/src/db2APRS.c, LaCrosse/src/open2300db2APRS.c: Make sure to
+ include <sys/stat.h> before using umask(), to avoid compiler
+ warning about implicit declaration.
+
+2012-09-14 13:57 tvrusso
+
+ * config/tnc-startup.kam, src/interface.c: Definitive fix for KAM
+ TNCs.
+
+ The KAM apparently does not go into converse mode if one sends
+ "K\r" and immediately sends the stuff you want to go into the
+ converse. It requires a tiny delay between the command to go
+ into converse mode and the data.
+
+ I have inserted a 50ms delay after sending the converse command,
+ which should be insignificant enough that nobody will need it to
+ be a configurable option.
+
+ This fix has been confirmed to end the problems with KAM TNCs,
+ and the 50ms delay was the smallest delay tested.
+
+ Also commented out two commands in tnc-startup.kam that do not
+ apparently exist in the KAM.
+
+2012-09-08 15:07 tvrusso
+
+ * Davis/src/db2APRS.c: Reverting my last change to the Davis
+ Meteo->APRS glue program. This is in response to testing by Dean
+ Groe, who is so far the only person on the xastir mailing list
+ who has fed back any information about the behavior of the code
+ after my last commit.
+
+ Turns out that Meteo does not appear to put "Total Rain" (rain
+ since station reset) into the database in the "raintotal" field,
+ it appears to put "rain since midnight" there, i.e. "total rain
+ for today." This is not what Xastir means, since it has a
+ separate spot for "today's rain."
+
+ Thus, it is pointless to be sending the extra data to Xastir,
+ because it is a duplicate of something else we already have.
+
+ I am changing only the Davis database glue program, and leaving
+ in place the LaCrosse changes --- LaCrosse stations *do* maintain
+ their own record of "total rain" and open2300 does put that data
+ into the database. It's just Meteo that doesn't.
+
+2012-08-31 16:39 tvrusso
+
+ * Davis/configure.ac, Davis/src/db2APRS.c,
+ LaCrosse/src/open2300db2APRS.c, src/wx.c: Fix for Davis and
+ LaCrosse weather stations.
+
+ Neither of the two "db2APRS" programs for these stations provided
+ "total rain" (rain since wx station reset), and thus Xastir would
+ show a blank in the Own Weather Data dialog box for this.
+
+ Further, LaCrosse weather stations don't report
+ rain-since-midnight, and by not having total rain available,
+ Xastir isn't able to compute the missing datum.
+
+ This commit does three things:
+
+ adds total rain to the string that db2APRS and open2300db2APRS
+ send
+ adds code to Xastir to parse the new bit of data
+ adds code to Xastir to compute rain-since-midnight if total
+ rain
+ is available AND rain-since-midnight is not sent from the
+ wx station.
+
+ WARNING: THE CODE FOR db2APRS has NOT been tested except to
+ assure that it compiles cleanly. I have no Davis weather station
+ to test it on.
+
+ The LaCrosse code runs correctly.
+
+2012-08-26 11:34 tvrusso
+
+ * INSTALL, README.Getting-Started: Update documentation to reflect
+ some changes in GPSMan and GPSManShp.
+
+2012-08-26 11:28 tvrusso
+
+ * src/main.c: Current versions of gpsman and gpsmanshp now require
+ "Shapefile" and "dim=2" instead of "Shapefile_2D"
+
+ For quite a long time the gpsman maintainer kept backward
+ compatibility, but it's gone now. This commit resolves issue
+ http://sourceforge.net/tracker/?func=detail&aid=1820056&group_id=45562&atid=443271
+ in the sourceforge bug tracker.
+
+2012-08-26 11:11 tvrusso
+
+ * acinclude.m4: Remove bashism from configure process, per
+ sourceforge bug
+
+ https://sourceforge.net/tracker/?func=detail&aid=3422711&group_id=45562&atid=443271
+
+2012-08-25 09:38 tvrusso
+
+ * src/: awk.c, bulletin_gui.c, color.c, datum.c, db_gis.c,
+ dbfawk.c, draw_symbols.c, fcc_data.c, festival.c, fetch_remote.c,
+ geo-client.c, geo-find.c, geocoder_gui.c, gps.c, hashtable.c,
+ hashtable_itr.c, hostname.c, igate.c, interface.c,
+ interface_gui.c, io-common.c, io-mmap.c, lang.c, list_gui.c,
+ locate_gui.c, location.c, location_gui.c, main.c, map_OSM.c,
+ map_WMS.c, map_cache.c, map_dos.c, map_gdal.c, map_geo.c,
+ map_gnis.c, map_pdb.c, map_pop.c, map_shp.c, map_tif.c,
+ map_tiger.c, messages.c, messages_gui.c, objects.c, popup_gui.c,
+ rac_data.c, rotated.c, rpl_malloc.c, shp_hash.c, snprintf.c,
+ sound.c, testdbfawk.c, tile_mgmnt.c, track_gui.c,
+ view_message_gui.c, wx.c, wx_gui.c, x_spider.c, xa_config.c,
+ xastir_udp_client.c: update neglected copyright dates.
+
+ Notably, update the one that shows up in the Help->About dialog.
+
+2012-08-22 18:05 tvrusso
+
+ * help/help-English.dat: Update help file to reflect recent change
+ to "Serial TNC with GPS on AUX port" interface type, documenting
+ the 'Send Control-E to get GPS data?' checkbox.
+
+ I can only update this in English. Translations requested for
+ our other supported languages.
+
+2012-08-22 17:41 tvrusso
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface.c,
+ src/interface_gui.c, src/main.c: Remove a horrid work-around of
+ some bad behavior of Xastir with Kenwood D7* radios with attached
+ GPS.
+
+ Back in 2006, several Xastir users noticed that when Xastir was
+ attached to a Kenwood D700 (and other Kenwood APRS radios) using
+ the "TNC with GPS on AUX port" interface type, every time Xastir
+ tried to transmit the TNC would reply with an "Eh?" error when
+ sent the MYCALL line that precedes a posit. We realized that
+ there must be some kind of junk in the TNC buffer that was
+ causing the MYCALL line to not be recognized. In some cases,
+ this had bad consequences, especially if no previous MYCALL had
+ succeeded --- the result would be that the TNC would transmit
+ using the default MYCALL, "NOCALL".
+
+ Since we couldn't for the life of us figure out what the junk in
+ the buffer was, we kludged: Before sending MYCALL, Xastir would
+ send a carriage return, letting the "eh?" error happen where it
+ had no consequence.
+
+ This was a horrid kludge, as it just swept the real problem under
+ the rug.
+
+ The real issue is that "Serial TNC with GPS on AUX port" was
+ written to support devices like the Kantronics KPC-3+, which
+ requires that Xastir send a Control-E to the TNC in order to poll
+ it for GPS data. This is how the KPC-3+ multiplexes the output
+ serial port --- normally it sends packet data to the serial port,
+ but immediately after receiving a Control-E from the connected
+ computer, it sends one NMEA string from the GPS instead.
+
+ The Kenwwood radios stream the GPS data and packet data together
+ all the time, and not only do not require a Control-E to switch
+ between them, they don't even read the Control-Es.
+
+ The "Eh?" errors from the Kenwood TNCs were it complaining that
+ MYCALL was preceded by all those Control-E characters that Xastir
+ had been sending since the last transmit.
+
+ This commit adds a configuration option to the Serial TNC with
+ GPS on AUX port set-up dialog so that one can turn this control-E
+ feature on and off as appropriate.
+
+ THIS HAS USER-VISIBLE IMPACT FOR ALL KENWOOD USERS:
+
+ If you are currently using Xastir with a Kenwood radio, after
+ doing this update you MUST open your interface property dialog
+ and de-select the 'Send Control-E to get GPS data?" check box.
+ If you do NOT take this step, you will begin seeing the old "Eh?"
+ problem on your TNC, and may well transmit your posit as NOCALL.
+
+ This may seem an annoyance, but really, this is the fix that we
+ should have put in place six years ago.
+
+2012-08-14 15:14 tvrusso
+
+ * src/db.c: Fix two instances of a logical AND being used where a
+ bit-wise AND was intended.
+
+ In this case, the test was supposed to be checking that a station
+ posit was not a third-party packet, but was improperly doing flag
+ && ST_3RD_PT instead of flag & ST_3RD_PT.
+
+ This impacts ONLY speech-enabled band opening alerts. It is
+ unlikely that anyone was even using these. I found this error
+ only because clang spits out warnings about it. The specific
+ warning is that one is attempting to do a logical AND with a
+ constant value (which is more likely an error than intentional).
+
+2012-08-13 10:22 tvrusso
+
+ * src/: database.h, wx.c: EXPERIMENTAL COMMIT FOR TESTING PURPOSES.
+
+ This commit modifies the weather station code so taht stations
+ which provide 1-hour, 24-hour, and since-midnight rain rates
+ (e.g. Davis through Meteo and db2APRS, LaCrosse, and Davis APRS
+ Data Logger) do not have those station- provided data overwritten
+ by Xastir when it tries to recalculate these quantities from
+ "total rain" (i.e. total rainfall since the weather station was
+ reset).
+
+ The Davis Meteo/LaCrosse code does not even provide "total
+ rainfall" information (though the database they access does in
+ fact have this information), and the APRS Data Logger does not
+ provide total rainfall. All three provide per-hour and 24-hour
+ rain data, and the Data Logger provides rain-since -midnight.
+
+ What this code does is add a flag to the WeatherRow structure
+ that is set to 1 by stations that provide total rain, and to zero
+ by stations that provide the rate data instead. In
+ "cycle_weather", the three rate strings are only overwritten if
+ the flag is 1, and are left as the station set them if the flag
+ is 0.
+
+ This should address issues of transmitted rain rates being
+ completely incorrect for Davis and LaCrosse stations.
+
+ Needs a lot more testing to assure that there is no impact on
+ other stations. This code should result in no change in Xastir's
+ behavior for any station other than Davis or LaCrosse.
+
+2012-08-08 19:19 tvrusso
+
+ * src/: main.c, xa_config.c: Patch by Tom Hayward.
+
+ This commit allows the "posit interval" slider to go all the way
+ to zero. If zero, Xastir will not emit timed beacons.
+
+ It also adds a SIGUSR2 signal handler. If Xastir receives a
+ SIGUSR2, it will beacon immediately.
+
+ This commit provides all the functionality requested by David
+ Ranch on the Xastir mailing list in this post:
+
+ http://lists.xastir.org/pipermail/xastir/2012-August/020936.html
+
+2012-07-27 12:58 tvrusso
+
+ * src/: interface.c, interface.h: Remove commented-out, hard-coded
+ choices of 'conv' and 'k' to put a TNC into "converse" mode. The
+ Interface Properties dialog now allows a user to specify this at
+ run time, and the presence of this commented-out code was
+ confusing some users into thinking they still might need to edit
+ source code to change it.
+
+2012-07-24 17:17 tvrusso
+
+ * LaCrosse/weatherdump.sql: Modify mysql database for LaCrosse to
+ support more digits of precision for wind direction and other
+ data that can exceed 99.9.
+
+ "decimal(3,1)" means 3 digits with one past the decimal, i.e.
+ +/-99.9. It was being used for fields that could take values
+ well outside this range.
+
+ I know that in at least one prior incarnation, this usage
+ accepted 3 digits to the left of the decimal, but now it doesn't.
+ My weather station has been misreporting wind direction ever
+ since I did a major overhaul that required re-loading the mysql
+ data from a dump.
+
+2012-07-10 14:02 we7u
+
+ * Makefile.am: Tweaking the URL for the cycle map for OSM (shows
+ contours).
+
+2012-07-05 11:53 tvrusso
+
+ * src/: igate.c, messages.c: Silence some warnings that showed up
+ when building with CLang instead of GCC.
+
+ One (in igate.c) is just a misuse of "debug_level && 1024"
+ instead of "debug_level & 1024), and the changes in messages.c
+ are all about use of things like: found =- 1;
+
+ which it warns as a potential mistake, since it is common to
+ intend this to be: found -= 1;
+
+ Making it found = -1;
+
+ clarifies the intent for the compiler and stops it from warning.
+
+2012-05-31 11:49 tvrusso
+
+ * src/wx.c: Fix incorrect test of sscanf return value. When I
+ changed the scanf to ignore the PXXX field, I forgot to decrease
+ the value.
+
+2012-05-31 11:41 tvrusso
+
+ * src/wx.c: Add a string to the APRS DataLogger debug output.
+
+2012-05-26 19:57 tvrusso
+
+ * src/wx.c: Fix what seems to be a serious error in the Davis APRS
+ DataLogger code.
+
+ When I first wrote this section I decoded pXXX into "wx_prec_24"
+ and PXXX into "wx_prec_00" since pXXX means "rain in last 24
+ hours" and PXXX means "rain since midnight." But Xastir actually
+ computes those things itself, and the DAVISMETEO code puts pXXX
+ into "wx_rain_total" instead.
+
+ AA9VI has been having Issues with his DataLogger, in that Xastir
+ is zeroing out the rainfall improperly. Turns out that's because
+ I'm never setting wx_rain_total, and Xastir needs that.
+
+ So I'm removing "rp-" and "rP-" from the debug output, no longer
+ saving PXXX into wx_prec_00 (it's discarded now), and am now
+ saving pXXX into wx_rain_total so that Xastir can handle it
+ properly.
+
+ This should fix Mike's problem.
+
+2012-05-15 08:29 tvrusso
+
+ * src/map_tif.c: Replace include of "projects.h" with "proj_api.h"
+ and remove use of what is now considered an internal structure
+ (struct PJ). Replace that usage with a pointer to such a
+ structure (projPJ, which is a typedef to a pointer to a PJ).
+
+ Proj.4 has removed "projects.h" from the installation of that
+ library, because much that's in it is considered private
+ implementation details that should not have been exposed. That
+ many packages use those internals directly is considered a
+ problem in those other packages, and a bug request in proj.4's
+ bug tracker to reinstate projects.h as an installed file was
+ closed with the status "wontfix". Codes that use the public API
+ of proj.4 are supposed to include "proj_api.h" and use the API
+ calls, not direct access to internal data structures or functions
+ that are not intended for use outside the library.
+
+2012-05-14 13:38 tvrusso
+
+ * config/Makefile.am, config/nwsozddap12.dbfawk,
+ config/nwsw_ddjn12.dbfawk, scripts/get-NWSdata, src/testdbfawk.c:
+ Update get-NWSdata to fetch the very latest NWS data. Some of
+ the files it was trying to get are non longer available.
+
+ Before committing, I assured that *ALL* files that get-NWSdata
+ downloads have corresponding matching dbfawk files. Two of the
+ files (oz and w) have had their dbf signatures change, so needed
+ new dbfawk files. Updated Makefiles to install these new files
+ (which I've named according to a new convention, instead of
+ _ddmmyy_year, I'm using mmyy that matches the dbf file to which
+ it corresponds).
+
+ Fix a spelling error in testdbfawk ("mathing" instead of
+ "matching").
+
+2012-05-10 18:55 tvrusso
+
+ * src/: db.c, maps.c: Comment out fprintfs to stderr that were
+ introduced by last commit. They are spewing info to stderr of an
+ exact sort that other types of weather alerts have commented out.
+
+2012-05-08 11:04 tvrusso
+
+ * src/wx.c: Fix debug output for Davis APRS DataLogger so that it
+ actually prints the decoded values for 24-hour and since-midnight
+ precipitation.
+
+2012-05-06 09:09 tvrusso
+
+ * configure.ac: make a single change of
+
+ if [ "$var" = "yes" ]
+
+ to if test "$var" = "yes"
+
+ because I found that a Fedora 15 install was complaining about
+ the former.
+
+2012-03-05 10:49 we7u
+
+ * symbols/: tornado.xbm, winter_wx.xbm, wntr_strm.xbm: Removing no
+ longer used weather alert files. We renamed them slightly to
+ match the alert_tag text in the NWS weather alerts.
+
+2012-03-05 10:47 we7u
+
+ * symbols/Makefile.am, symbols/torndo.xbm,
+ symbols/winter_storm.xbm, symbols/winter_weather.xbm,
+ src/map_shp.c, src/util.c, src/util.h: A rewrite of a patch
+ supplied by Arnaud, F4EIR, which simplifies how we do alert->tag
+ processing. We now grab the alert tag, change it to lower-case,
+ then find a matching file on the filesystem. If not found, we
+ grab one called "alert.xbm" as a default. This change will allow
+ adding more files over time for more types (or Country's) alerts.
+ Arnaud has plans to add support for France's weather alerts.
+
+2012-03-02 12:28 we7u
+
+ * README.Getting-Started, README.MAPS: Updating the copyright year
+ for these two files.
+
+2012-03-02 12:26 we7u
+
+ * config/Makefile.am, config/gfe_coastal_waters.dbfawk,
+ config/gfe_coastal_waters_warnings.dbfawk,
+ config/gfe_fire_weather.dbfawk, config/gfe_metro_areas.dbfawk,
+ config/gfe_public_weather.dbfawk, scripts/Makefile.am,
+ scripts/get-BOMdata, src/alert.c, src/db.c, src/maps.c,
+ src/util.c: Tweaks to allow using Australian Bureau of Metrology
+ weather alerts in Xastir. This allows lighting up zones in a
+ similar manner to the NWS weather alerts. Thanks to Geoff
+ Gatward, VK2XJG/VK8GG, for this work!
+
+2012-03-02 12:10 we7u
+
+ * config/nwsmzddmmyy_11.dbfawk, config/nwsz_ddmmyy_11.dbfawk,
+ scripts/get-NWSdata: Updates to the NWS fetch script and dbfawk
+ files by Geoff Gatward, VK2XJG/VK8GG. Thanks!
+
+2012-03-01 10:11 we7u
+
+ * FAQ: Adding 4.34 question/answer from the web-based FAQ, and 4.35
+ from a question answered by Tom Russo on the mailing list (added
+ with permission).
+
+2012-02-04 16:10 tvrusso
+
+ * README.Getting-Started, README.MAPS, scripts/Makefile.am: Change
+ scripts Makefile.am to remove misuse of "pkglib_SCRIPTS" as this
+ usage was one that was not intended to be correct, but was
+ silently accepted by older versions of automake. Now automake
+ enforces certain rules about what directory prefixes may be used
+ with what "primaries" (such as _SCRIPTS and _DATA), and "pkglib"
+ is forbidden as a prefix to "_SCRIPTS."
+
+ This change also changes where scripts are installed. They used
+ to get installed to /usr/local/lib/xastir, now they go to
+ /usr/local/share/xastir/scripts. Documentation has been updated
+ to fix references to the old directory.
+
+2011-10-20 19:08 tvrusso
+
+ * README.MAPS: Testing CVSROOT/loginfo change.
+
+2011-10-20 18:45 we7u
+
+ * src/: interface.c, interface.h, interface_gui.c, xa_config.c:
+ Added a new box in the TNC properties dialog for setting the
+ CONVERSE mode command. If blank it will get set to "k" which
+ most TNC's accept. Can be set to "conv" for TNC's like the KPC-2
+ on an individual port basis.
+
+2011-09-08 12:47 tvrusso
+
+ * config/: Makefile.am, nwsz_ddmmyy_11.dbfawk: Add a new dbfawk
+ file for the newest NWS Zone file, which once again has different
+ dbf signature than all previous versions.
+
+2011-09-05 13:24 tvrusso
+
+ * scripts/geopdf2gtiff.pl: Remove creation options for PACKBITS
+ compression, until I figure out why that's creating tiffs Xastir
+ can't read.
+
+2011-09-05 12:58 tvrusso
+
+ * scripts/geopdf2gtiff.pl: Add a "fix neatline" option for GeoPDFs
+ with bad neatlines, such as the most recent US Topo editions,
+ which have neatlines that include all the collar.
+
+ This hack works when the user specifies --fixneatline or -f, and
+ rounds the left, right, top, and bottom of the image down to the
+ nearest 7.5' quad boundary, and uses those values to construct
+ its own neatline prior to calling gdalwarp with the -cutline
+ -crop_to_cutline options.
+
+2011-09-05 10:54 tvrusso
+
+ * scripts/geopdf2gtiff.pl: Add compress=packbits to geotiff
+ creation options for minor disk space savings.
+
+2011-09-05 10:29 tvrusso
+
+ * scripts/: Makefile.am, geopdf2gtiff.pl: Added script to convert
+ GeoPDF files to usable GeoTIFF files.
+
+ This involves extracting the neatline from the GeoPDF, then doing
+ a gdalwarp to strip the collar and warp to EPSG:4326 coordinate
+ system (WGS84 equidistant cylindrical projection), and finally to
+ dither to 8 bit if there is more than one band present.
+
+ I have found that some GeoPDF files lie about their neatlines,
+ saying the neatline encloses the whole raster including the
+ collar. There is nothing to be done about this except to
+ hand-craft an FGD file for such GeoPDFs. With an FGD file,
+ Xastir will collar-strip itself. This seems only to be a problem
+ with some of the fancier new-style GeoPDF files, the "Digital
+ Maps, Beta."
+
+2011-07-06 00:45 we7u
+
+ * config/: Makefile.am, tnc-startup.d72_d710, tnc-stop.d72_d710:
+ New start/stop files for Kenwood D72 and D710, contributed by Kai
+ Günter, LA3QMA. Thanks!
+
+2011-05-31 08:37 gstueve
+
+ * config/Makefile.am, config/nwsc_ddmmyy_10a.dbfawk,
+ config/nwsmzddmmyy_11.dbfawk, config/nwsw_ddmmyy_10.dbfawk,
+ config/nwsz_ddmmyy_10c.dbfawk, scripts/get-NWSdata: Make sure we
+ have good mapping files for current NWS data files. Also get
+ current set of files from NWS.
+
+2011-03-26 20:07 jedunmire
+
+ * src/map_OSM.c: - fix for downloading tile '5 of 4' bug
+ - the bug and the fix are cosmetic and should not impact any
+ other
+ operations.
+
+2011-02-25 22:06 we7u
+
+ * config/: Makefile.am, nwsc_ddmmyy_10.dbfawk, nwshzddmmyy.dbfawk,
+ nwsz_ddmmyy_10b.dbfawk: Updating dbfawk files to match current
+ set of NWS Shapefiles.
+
+2011-02-25 15:06 we7u
+
+ * scripts/get-NWSdata: Updating to the most recent valid NWS files
+ for alerts. We'll need to update our dbfawk files to match
+ these.
+
+2011-01-23 17:29 we7u
+
+ * scripts/get-NWSdata: Updating to latest NWS Shapefiles.
+
+2011-01-03 17:30 we7u
+
+ * README: Added the OpenSuSE-11.3 repository to the notes plus a
+ command-line option to configure which picks up another needed
+ library location.
+
+2010-12-31 04:58 we7u
+
+ * help/help-English.dat: Revising the tactical callsign text a bit.
+
+2010-12-31 04:41 we7u
+
+ * FAQ: Changed the "Can I run multiple Xastir's at once" answer to
+ incorporate use of the new(er) "-c" command-line flag.
+
+2010-12-31 04:17 we7u
+
+ * help/help-English.dat: Added info about publishing tactical
+ callsigns across the air and later revoking those assignments via
+ APRS messaging.
+
+2010-12-20 15:43 jedunmire
+
+ * src/map_OSM.c: - Re-organized a few lines in map_OSM.c so
+ that it not produce an
+ error message when *Magick libraries are not used.
+
+2010-12-04 17:37 tvrusso
+
+ * configure.ac, src/shapelib/contrib/Makefile.am: Fix
+ configure/make so that it works properly when internal shapelib
+ is being built on a system without libproj.
+
+2010-11-08 17:48 tvrusso
+
+ * Makefile.am: Fix for bug reported by Jeremy Utley, in which using
+ DESTDIR at install time was depositing some CC_*.png files in a
+ directory that ignored DESTDIR.
+
+2010-10-25 20:25 we7u
+
+ * configure.ac: Bumping CVS up to v2.0.1 for further development.
+
+2010-10-25 20:02 we7u
+
+ * configure.ac, scripts/BUILDRPMS, scripts/LSB-BUILD,
+ scripts/do_xastir_release_dev, scripts/do_xastir_release_stable:
+ Setting up for the v2.0.0 stable release.
+
+2010-10-24 10:01 we7u
+
+ * config/language-French.sys: Updates by Arnaud, F4EIR. Thanks!
+
+2010-10-24 09:59 we7u
+
+ * config/language-German.sys: Updates by Rolf, DK7IN. Thanks!
+
+2010-10-05 07:14 chicoreus
+
+ * scripts/db_gis_mysql.sql: Fixing script to generate database and
+ tables for MySQL based persistence. Previous versions include
+ invalid syntax.
+
+ Changes herein largely follow patch by Dan Zubey N7NMD.
+
+ This script has now been tested both with grant statments
+ commented out and with grants included.
+
+2010-09-30 08:35 gstueve
+
+ * scripts/get-NWSdata: Update files for current boundaries.
+
+2010-09-28 20:55 jedunmire
+
+ * src/map_geo.c: - eliminate the warning about a missing
+ prototype for
+ DistroyImagePixels() but enabling prototypes for 'private'
+ functions
+ in GraphicsMagick.
+
+2010-09-23 19:24 jedunmire
+
+ * src/map_OSM.c: - changes to transparency code for OSM tiled
+ maps.
+ This fixes the problem with 16-bit *Magick quantums.
+
+2010-09-21 07:46 we7u
+
+ * src/list_gui.c: A patch by Jason Godfrey, N0RPM, which fixes the
+ segfault on list close problem. We were calling
+ XtDestroyWidget() on child widgets, but calling it on the parent
+ is sufficient. We just have to make sure there aren't any
+ references to those child widgets first.
+
+2010-09-08 11:13 jedunmire
+
+ * Makefile.am, src/Makefile.am, src/tile_mgmnt.c, src/tile_test.c:
+ - Removed obsolete tile experiment application (tile_test)
+ - Stopped using http 'newer than' requests for OSM tiles. The
+ 'newer
+ than' test was ignored by all observed OSM servers and
+ caused
+ corrupted downloads and long delays for the topOSM tiles.
+ - Changed the names of the TopOSM files so that they layer
+ automatically.
+
+2010-08-17 10:26 gstueve
+
+ * src/main.c: Add setlocale() back in place to calm Warnings about
+ charset mismatch.
+
+2010-08-14 16:21 we7u
+
+ * src/wx.c: Fixes for One-Wire-Daemon ARNE protocol mode to allow
+ the use of the current string output: 12 parameters instead of
+ 19. We allow use of either format now.
+
+2010-08-14 14:32 jedunmire
+
+ * Makefile.am, OSM_template, README.OSM_maps, src/map_OSM.c,
+ src/map_OSM.h, src/map_geo.c, src/tile_mgmnt.c, src/tile_mgmnt.h,
+ src/tile_test.c: - fix for '1 of 0' tile download message
+ - fixed a memory leak in map_OSM.c
+ - fixed installation of OSM CC icons
+ - added support for .jpg tiles
+ - implemented transparency for tiles. No more red blocks for
+ missing
+ tiles, tiles can be stacked, and lower levels show through
+ for
+ missing tiles.
+ - zoom level limits for OSM maps
+ - New map definitions for topOSM
+
+2010-08-13 14:53 we7u
+
+ * src/map_shp.c: A fix for segfaults caused by some Shapefile maps.
+ Kyle and Nathan Mills were my consultants for fixing this bug,
+ though the final bug-fix was mine.
+
+2010-08-10 02:11 we7u
+
+ * src/xa_config.c: Faster processing of the config file. We now
+ call fseek to reset to the beginning of the file only if we don't
+ find a particular option the first time through. We were calling
+ it before every search, plus were reading in another line in the
+ loop before we checked whether we had found the current option
+ (making us go one too far each time).
+
+2010-08-10 01:39 we7u
+
+ * .cvsignore, src/.cvsignore: Adding a few files to .cvsignore to
+ keep the cvs status clean.
+
+2010-08-10 01:22 we7u
+
+ * src/: alert.c, db.c, interface.c, interface.h, util.c, util.h,
+ x_spider.c, xa_config.c: More work to help assure that config
+ file reading/writing is consistent no matter the locale.
+ Replacing more dangerous string functions with safer functions.
+ Combined split_string_char and split_string into one function.
+ Added get_float() and store_float() function to simplify code.
+
+2010-08-10 01:07 we7u
+
+ * src/main.c: Adding more setlocale() calls before we read in the
+ config data.
+
+2010-08-04 04:12 we7u
+
+ * config/: OSM_Cloudmade_administrative.dbfawk, Makefile.am,
+ OSM_Cloudmade_highway.dbfawk, OSM_Cloudmade_natural.dbfawk,
+ OSM_Cloudmade_poi.dbfawk,
+ OSM_Cloudmade_water_and_coastline.dbfawk: Adding dbfawk files for
+ the Open Street Maps "Cloudmade" Shapefile extracts.
+
+2010-08-01 22:12 we7u
+
+ * configure.ac: Mark GeoTiff support as a "no" if we can't find the
+ geotiff include files.
+
+2010-08-01 21:06 we7u
+
+ * configure.ac: Removing the extra -I for finding libgeotiff. It
+ appears to be distribution-specific, depending on where they
+ decide to stuff the include files. libgeotiff itself when
+ installed from sources goes into /usr/include and Xastir finds it
+ readily.
+
+2010-08-01 15:25 we7u
+
+ * configure.ac: Updating path to libgeotiff include files.
+
+2010-07-30 20:12 jedunmire
+
+ * README.OSM_maps, src/fetch_remote.c, src/fetch_remote.h,
+ src/map_OSM.c, src/tile_mgmnt.c, src/tile_mgmnt.h,
+ src/tile_test.c: - cached OSM tiles are not checked for updates
+ after 7 days
+ - tile downloads will use http pipelining if supported by the
+ server
+ - new debug level, 8192 for verbose curl output
+
+2010-07-30 11:18 we7u
+
+ * Makefile.am: Fixing a minor hitch the install-exec-hook.
+
+2010-07-29 14:57 jedunmire
+
+ * src/map_OSM.c: - fixed compile error when map-cache is
+ disabled
+
+2010-07-27 09:48 we7u
+
+ * src/fetch_remote.c: Adding a prototype needed on some systems.
+
+2010-07-27 01:40 we7u
+
+ * CC_OpenStreetMap_logo.png, CC_OpenStreetMap_txt.png, ChangeLog,
+ Makefile.am, OSM_template, README.OSM_maps,
+ config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/Makefile.am, src/main.c,
+ src/map_OSM.c, src/map_OSM.h, src/map_WMS.c, src/fetch_remote.c,
+ src/fetch_remote.h, src/map_geo.c, src/map_tiger.c, src/maps.c,
+ src/tile_mgmnt.c, src/tile_mgmnt.h, src/tile_test.c,
+ src/track_gui.c, src/util.c, src/util.h: Open Street Maps tiling
+ patches by Jerry Dunmire, KA6HLD. Way to go Jerry!
+
+2010-07-21 04:52 we7u
+
+ * .cvsignore, src/shapelib/contrib/.cvsignore: Updating .cvsignore
+ files to current build configuration.
+
+2010-07-12 23:12 we7u
+
+ * src/shapelib/contrib/: my_nan.h, shpgeo.c: Attempting to fix the
+ "endian-ness" tests.
+
+2010-07-12 11:22 we7u
+
+ * src/shapelib/contrib/my_nan.h: Fixing up BYTE_ORDER so that
+ internal Shapelib compiles on more machines.
+
+2010-07-11 16:39 we7u
+
+ * src/: main.c, objects.h: Getting rid of the final two compiler
+ warnings, again by switch to the use of intptr_t instead of int.
+ Other systems may have more warnings, but this OpenSuSE-11.2
+ 64-bit system compiles Xastir cleanly now.
+
+2010-07-11 16:31 we7u
+
+ * src/: draw_symbols.c, interface.c, map_shp.c, messages_gui.c,
+ objects.c, shp_hash.c, testdbfawk.c: Getting rid of more compiler
+ warnings, mostly by casting to/from intptr_t.
+
+2010-07-11 14:41 we7u
+
+ * src/rtree/: index.c, index.h, rect.c: Fixed some long-standing
+ compiler warnings in the rtree code. Seems to still work
+ properly.
+
+2010-07-11 13:30 we7u
+
+ * src/shapelib/: dbfdump.c, shputils.c, contrib/dbfcat.c,
+ contrib/shpdxf.c, contrib/shpgeo.c, contrib/shpproj.c: More minor
+ tweaks to get rid of compiler warnings. Of particular note are
+ some TODO entries added to a couple of files for two enumerated
+ values that weren't being handled in "switch" statements. There
+ still isn't any code for those case statements, but the compiler
+ warnings are gone.
+
+2010-07-11 01:01 we7u
+
+ * src/shapelib/shputils.c: Adding some braces for some "if"
+ statements so that the enclosed else clause won't be ambiguous.
+
+2010-07-11 00:57 we7u
+
+ * src/shapelib/: shpdump.c, shptreedump.c, contrib/shpdxf.c: Fixing
+ a few more compiler warnings.
+
+2010-07-11 00:51 we7u
+
+ * src/shapelib/: shptreedump.c, shputils.c, contrib/shpcentrd.c,
+ contrib/shpdata.c, contrib/shpdxf.c, contrib/shpfix.c,
+ contrib/shpinfo.c, contrib/shpproj.c, contrib/shpwkb.c: Fixing
+ more compiler warnings. There are a few left yet.
+
+2010-07-11 00:24 we7u
+
+ * src/shapelib/: dbfdump.c, shprewind.c, shputils.c,
+ contrib/dbfcat.c, contrib/dbfinfo.c, contrib/shpcentrd.c,
+ contrib/shpdata.c, contrib/shpdxf.c, contrib/shpgeo.c,
+ contrib/shpinfo.c, contrib/shpproj.c, contrib/shpwkb.c: Fixing
+ multiple minor warnings with Shapelib. Still plenty left.
+
+2010-07-10 23:31 we7u
+
+ * src/shapelib/: Makefile.am, contrib/Makefile.am: Changing the
+ shapelib and shapelib/contrib Makefile.am files so that the
+ binaries don't get installed during "make install"
+
+2010-07-10 23:22 we7u
+
+ * src/shapelib/: Makefile.am, shputils.c, contrib/Makefile.am:
+ Setting up the rest of shapelib and shapelib/contrib so that
+ everything compiles. Had to add an include to shputils.c and add
+ a "1" parameter to exit() in one spot.
+
+2010-07-10 22:52 we7u
+
+ * src/shapelib/: Makefile.am, contrib/Makefile.am: Now building
+ libshape.a in both the shapelib and the shapelib/contrib
+ directories so that we can build executables in both places
+ successfully.
+
+2010-07-10 22:39 we7u
+
+ * src/shapelib/: Makefile.am, contrib/Makefile.am: Adding more
+ binaries into the build. The ones in "contrib" still depend on
+ "libshape.a" in the "shapelib" dir and we still need to figure
+ out how to build that library first.
+
+2010-07-10 13:53 tvrusso
+
+ * src/shapelib/: Makefile.am, contrib/Makefile.am: Modifications to
+ internal shapelib support so that dbfinfo (from the contrib
+ directory) builds when internal shapelib builds. Until now, none
+ of the "contrib" programs were built.
+
+2010-07-06 23:16 we7u
+
+ * src/main.c: Patch by Jerry Dunmire to prevent use of F4 key (Open
+ Street Map optimum zoom) when Disable Fast Zoom is activated on
+ the Map menu.
+
+2010-07-03 15:09 we7u
+
+ * scripts/: coord-convert.pl, inf2geo.pl, mapfgd.pl, overlay.pl,
+ ozi2geo.pl, permutations.pl, ridge_radar.pl: Removing the
+ Copyright noticed from scripts that were released to the public
+ domain. They are mutually exclusive.
+
+2010-07-02 00:17 we7u
+
+ * config/tl_2009_aiannh.dbfawk: I screwed up the credit on that
+ last commit. Those dbfawk files come to us courtesy of Peter
+ Gamache, KC0TFB. Sorry about that!
+
+2010-07-02 00:12 we7u
+
+ * config/: Makefile.am, tl_2009_aiannh.dbfawk, tl_2009_aits.dbfawk,
+ tl_2009_arealm.dbfawk, tl_2009_areawater.dbfawk,
+ tl_2009_county.dbfawk, tl_2009_cousub.dbfawk,
+ tl_2009_edges.dbfawk, tl_2009_mil.dbfawk,
+ tl_2009_nn_county.dbfawk, tl_2009_pointlm.dbfawk,
+ tl_2009_zcta5.dbfawk: Contributions by Kevin Paetzold, K1KWP.
+ Thanks!
+
+2010-07-02 00:08 we7u
+
+ * scripts/: Makefile.am, ridge_radar.pl: Adding ridge_radar.pl,
+ which computes a .geo file for a particular NWS abbreviation.
+ Contribution by Jeremy McDermond (NH6Z). Thanks!
+
+2010-06-30 16:31 we7u
+
+ * src/map_OSM.c: Adding the ImageMagick ifdef's back in. Patch by
+ Jerry Dunmire.
+
+2010-06-29 23:41 we7u
+
+ * src/: main.c, map_geo.c: F4 key multiple maps fix by Jerry
+ Dunmire.
+
+2010-06-29 23:25 we7u
+
+ * src/: interface.c, main.c, wx.c, wx.h: A fix for Radio
+ Shack/Huger/Oregon Scientific weather stations connected via the
+ WX200d daemon. This fix may also help direct-connected weather
+ stations of the above type, but since I don't have any to test
+ with, it's unknown until someone tries.
+
+2010-06-29 10:01 we7u
+
+ * Makefile.am, tigermap.geo: First step at removing tigermap.geo:
+ Making it invisible to the user.
+
+2010-06-28 14:25 we7u
+
+ * OSM_cloudmade_1.geo, OSM_cloudmade_2.geo, OSM_cloudmade_5.geo,
+ OSM_cloudmade_998.geo, OSM_cloudmade_999.geo, OSM_cycle.geo,
+ OSM_mapnik.geo, OSM_osmarender.geo, OSM_skiing.geo: Removing .geo
+ files that are now created from a template.
+
+2010-06-28 13:49 we7u
+
+ * OSM_template: Need to commit a new file after Jerry's latest
+ patch for things to work for everyone else!
+
+2010-06-28 12:17 we7u
+
+ * OSM_cloudmade_1.osm, OSM_cloudmade_2.osm, OSM_cloudmade_5.osm,
+ OSM_cloudmade_998.osm, OSM_cloudmade_999.osm, OSM_cycle.osm,
+ OSM_mapnik.osm, OSM_osmarender.osm, OSM_skiing.osm: A bit of
+ cleanup: Getting rid of the no-longer-used *.osm files.
+
+2010-06-28 12:14 we7u
+
+ * Makefile.am, OSM_cloudmade_1.geo, OSM_cloudmade_2.geo,
+ OSM_cloudmade_5.geo, OSM_cloudmade_998.geo,
+ OSM_cloudmade_999.geo, OSM_cycle.geo, OSM_mapnik.geo,
+ OSM_osmarender.geo, OSM_skiing.geo, src/main.c, src/map_OSM.c,
+ src/map_OSM.h, src/map_geo.c, src/maps.c: Mods by Jerry Dunmmire
+ WRT OSM. His notes: Summary of changes: - scaling corrected
+ - requested OSM map size limited to 2000x2000 and +/-89 deg
+ latitude - no 'binned' zoom levels - new function key (F4) to
+ 'optimize' zoom level for OSM - .osm maps eliminated - OSM
+ map files (.geo) built from a single template
+
+ Details: scaling corrected: This required a major rewrite
+ of the map_OSM.c code since the map_tiger.c code that it was
+ based on did not support Mercator projection.
+
+ Note that due to size limitations from the server and the
+ use of Mercator scaling when the OSM bitmap images are
+ rendered,
+ some OSM maps will not fill the display window. This is
+ particularly common when using a large display window.
+ Selecting
+ an optimized OSM zoom level (F4) will generally, but not
+ always,
+ result in bit map image that fills the window.
+
+ map size limitations:
+ The OSM map server that is used by this code limits the
+ returned
+ bitmap image to 2000 pixels in either direction. Also, as a
+ side
+ effect of the Mercator projection, latitude values must be
+ limited to -90 < lat < 90.
+
+ no binned zoom levels:
+ Attempts to constrain the linear Xastir scaling to the binned
+ OSM levels has been unsuccessful. The final straw was a
+ problem
+ with float to integer transitions that would result in
+ looping
+ and oscillation between levels.
+
+ new function key to optimize OSM zoom levels:
+ Since bitmap images do not scale well, they will always look
+ best when the Xastir scale is closest to the OSM scale. A
+ function key (F4) has been defined that will adjust the
+ Xastir
+ scale to the nearest OSM level and redraw the screen. Note
+ that
+ even if the scale is not changed, the F4 key will redraw the
+ screen- this is intentional on my part.
+
+ The F4 key works only if an OSM map is selected.
+
+ If the F4 key is already defined for some other use on your
+ system you can specify an alternative key by modifying the
+ map
+ files (OSM*.geo). The specified value must be an X11 KeySym
+ value. Setting the value to 0 will disable the key.
+
+ .osm maps eliminated
+ Since binned scale levels are no longer supported, the .osm
+ extension is no longer needed. .osm file will not be
+ installed.
+
+ If your maps directory (typically
+ /usr/local/share/xastir/maps/Online/) contains .osm file from
+ an
+ previous install you will have to remove them by hand.
+
+ You should also re-index your files
+ (Map->Configure->Index:Reindex ALL maps) to remove them from
+ the
+ Map Chooser.
+
+ OSM map files (.geo) built from a single template:
+ This is primarily of interest to developers and results in a
+ cleaner source tree.
+
+2010-06-28 12:01 we7u
+
+ * configure.ac: Commenting out the tests for libgps, which we're
+ currently not using.
+
+2010-06-18 22:35 we7u
+
+ * src/interface.c: Skipping the hostname lookup if we pass an IP
+ address instead of a hostname.
+
+2010-06-18 22:11 we7u
+
+ * src/interface_gui.c: Changing default GPSD port to 2947.
+
+2010-06-18 21:57 we7u
+
+ * configure.ac, src/interface.c: Changes to support pre-2.90 and
+ post-2.90 versions of GPSD network connections. We now send the
+ "R\r\n" command across (old method), then then send:
+ ?WATCH={"enable":true,"nmea":true}\r\n (new method). Between the
+ two strings either version of GPSD daemon gets kick-started into
+ sending us NMEA strings.
+
+2010-06-17 20:41 we7u
+
+ * configure.ac: Changing one summary line (text only).
+
+2010-06-17 20:07 we7u
+
+ * configure.ac, src/interface.c: Added the configure test for
+ libgps and the gps.h header file, necessary to continue with
+ adding gpsd support into Xastir. More to do yet.
+
+2010-06-17 16:24 we7u
+
+ * src/util.c: Added a debugging statement, but it's commented out.
+ Useful at times.
+
+2010-06-15 07:29 we7u
+
+ * OpenStreetMaps.osm: Part of the OSM linear patch by Jerry
+ Dunmire.
+
+2010-06-15 07:28 we7u
+
+ * Makefile.am, OSM_cloudmade_1.geo, OSM_cloudmade_1.osm,
+ OSM_cloudmade_2.geo, OSM_cloudmade_2.osm, OSM_cloudmade_5.geo,
+ OSM_cloudmade_5.osm, OSM_cloudmade_998.geo,
+ OSM_cloudmade_998.osm, OSM_cloudmade_999.geo,
+ OSM_cloudmade_999.osm, OSM_cycle.geo, OSM_cycle.osm,
+ OSM_mapnik.geo, OSM_mapnik.osm, OSM_osmarender.geo,
+ OSM_osmarender.osm, OSM_skiing.geo, OSM_skiing.osm,
+ src/map_OSM.c, src/map_OSM.h, src/map_geo.c: OpenStreetMaps
+ linear scaling patches by Jerry Dunmire. Thanks!
+
+2010-06-10 19:04 we7u
+
+ * OpenStreetMaps.geo: Another patch by Jerry Dunmire, KA6HLD.
+
+2010-06-10 19:02 we7u
+
+ * Makefile.am, OpenStreetMaps.osm, src/main.c, src/map_geo.c,
+ src/maps.c: Another OSM patch by Jerry Dunmire, KA6HLD.
+
+2010-06-09 16:28 we7u
+
+ * src/: db.c, igate.c, interface.c, interface_gui.c, main.c,
+ map_OSM.c, map_WMS.c, map_shp.c, map_tiger.c, maps.c,
+ messages_gui.c, objects.c, view_message_gui.c, wx_gui.c: More
+ tweaks by Jerry Dunmire, KA6HLD. These get rid of some compiler
+ warnings with newer GCC compilers.
+
+2010-06-09 11:51 we7u
+
+ * AUTHORS, Makefile.am, OpenStreetMaps.geo, src/Makefile.am,
+ src/main.c, src/map_OSM.c, src/map_OSM.h, src/map_geo.c: Initial
+ patches to use Open Street Maps with Xastir. This appears to be
+ a good replacement for the now-defunct Tigermap server. Patches
+ contributed by Jerry Dunmire, KA6HLD. Thanks Jerry!
+
+2010-05-27 07:01 gstueve
+
+ * scripts/: get-fcc-rac.pl, get-gnis: Uodate copyright info in a
+ couple of scripts.
+
+2010-05-07 09:23 tvrusso
+
+ * src/main.c: Add a very simple hack cribbed from the "Grace"
+ project
+
+ http://patch-tracker.debian.org/patch/series/view/grace/1:5.1.22-5/motiflockup.diff
+
+ to work around some extreme breakage introduced by Xorg server
+ around version 1.7.5. This breakage changed the way the server
+ handles "passive grabs" and has broken *all* motif programs that
+ use XmCreatePopupMenu (among other things); such programs will
+ grab the mouse cursor upon creating the pop-up and restrict
+ cursor motion to within the parent widget of the intended popup,
+ rendering the desktop completely unusable until the X server is
+ killed. The correct fix is to update Xorg server (the fix is
+ apparently in the yet-to-be-released 1.7.6), but that is not an
+ option for some users of systems that only use stable releases of
+ Xorg, and sometimes not even then (think Ubuntu, where they tend
+ to stick only to bug-fix updates in a given LTS tree, and don't
+ go to the next release number). Thus, it is necessary either to
+ patch motif libraries or work-around the issue in applications.
+ Since patching motif libraries is not a reasonable thing to
+ require of our users, it's worthwhile to hack Xastir.
+
+ The work-around ungrabs the mouse cursor immediately after the
+ call to XmCreatePopupMenu. It's an almost trivial modification
+ of the code.
+
+ Tested on Xorg-server 1.6.5 and Xorg-server 1.7.5. Looks good,
+ so committing it.
+
+ The fix does have one unfortunate side effect on the newer server
+ , as it is somewhat more difficult to tap the right mouse button
+ and get the right-click menu to stay up, but it is possible. On
+ the older server it appears to have no effect at all, which is
+ good.
+
+2010-04-23 07:00 gstueve
+
+ * src/bulletin_gui.c: Remove annoying blank line from end of
+ bulletin list.
+
+2010-04-21 12:36 gstueve
+
+ * config/Makefile.am: Fix source identification to work for BSD
+ make. Should now work for new and old make utilities. I like
+ these derived language files to test for added labels as I admit
+ to a language deficiency.
+
+2010-04-19 10:48 gstueve
+
+ * config/Makefile.am: Permit derived language files to be generated
+ from source file w/o requiring configure elements to be rerun.
+
+2010-04-19 10:45 gstueve
+
+ * config/Makefile.am, config/nwsz_ddmmyy_10.dbfawk,
+ scripts/get-NWSdata: Add matching dbfawk file for new zone
+ description file from NWS.
+
+2010-03-10 22:24 we7u
+
+ * src/db.c: Initializing a temp area object's color to a value to
+ get rid of a compiler warning.
+
+2010-03-10 20:03 chicoreus
+
+ * src/: db.c, db_gis.c, db_gis.h, interface.c, interface_gui.c,
+ main.c: Mike, W2SWR, attempted to deploy Xastir over a MySQL
+ database, and in the process helped to find multiple issues,
+ including both an inability to compile xastir with just
+ --with-mysql, and multiple causes for segfaults starting and
+ stopping database interfaces and saving data. This commit
+ addresses these issues.
+
+ Xastir now compiles and runs with either or both --with-mysql and
+ --with-postgis, as reqired definitions for each have now been
+ appropriately included with preprocessor directives.
+
+ The key fix for stability is in db_gis.h, the connection array
+ has been redefined from an array pointer to an array, and the
+ MYSQL object in the Connection struct has been changed from a
+ MYSQL pointer to a MYSQL. Calls to methods that pass database
+ connections have been rewritten to pass the address of the
+ connection (&aDbConnection), rather than the connection.
+
+ Multiple other fixes, mostly involving correcting the use of
+ pointers, have been made to the db_gis.c code, and these have
+ been tested and found to work with storage and retrieval of large
+ quantities of internet feed data (on the order of 800,000
+ records) to both MySQL and Postgis databases, with xastir
+ compiled with --with-mysql, --with-postgis separately, and with
+ --with-mysql --with-postgis together.
+
+ Also fixed a user interface bug that prevented retention of a
+ selection of mysql(spatial) as a database type.
+
+2010-03-05 21:52 we7u
+
+ * FAQ: Adding more info to the Fedora 12 right-click bug
+ problem/solution.
+
+2010-02-28 07:47 we7u
+
+ * scripts/inf2geo.pl: Added some comments about GM/IM
+ prerequisites. Made it clear what the script does for the user.
+
+2010-02-27 17:33 we7u
+
+ * src/x_spider.c: Client connections to Xastir's server port had
+ this problem: The last connected client, if it disconnected,
+ would lock up the server. The pointer code taking care of
+ removing objects in the linked list has been reworked. It no
+ longer matters which order of client connects/disconnects are
+ applied to the server. Thanks to Nathan Mills for helping me
+ figure this out and test this.
+
+2010-02-19 17:33 gstueve
+
+ * src/interface.c: Fix spelling in error message that lintian
+ found.
+
+2010-02-16 20:13 chicoreus
+
+ * src/db_gis.c: The node_path stored to a mysql database is not
+ being truncated correctly with xastir_snprintf(), as the current
+ length of the station->node_path_ptr that is providing the
+ character array is used as the limit, rather than the maximum
+ length allocated for the node_path into which it is being placed,
+ thus causing a crash on trying to store a MySQL record for a
+ position when the path exceeds 56 characters in length.
+
+2010-02-16 17:47 we7u
+
+ * FAQ: Tweaked the Fedora 12 right-click answer to point to "yum
+ update".
+
+2010-02-11 21:13 we7u
+
+ * src/util.c: Taking an initial WIDE2-1 out of the equation which
+ looks for WIDEn-N following WIDEn-N.
+
+2010-02-06 19:48 we7u
+
+ * Makefile.am: Setting up README.CYGWIN so that it gets copied to
+ the docs directory with the rest of the docs during the install
+ step.
+
+2010-02-03 09:37 we7u
+
+ * FAQ: Added Kevin K1KWP's note about getting right-click menus
+ working in Fedora 12.
+
+2010-02-01 10:37 gstueve
+
+ * testdbfawk.1, xastir_udp_client.1: Quiet some warnings from
+ manpages about hyphens and minus signs.
+
+2010-01-31 12:10 we7u
+
+ * configure.ac: Bumping the revision number for new development.
+
+2010-01-31 12:09 we7u
+
+ * README.Contributing: Updating text to call out the new place for
+ the developers instructions (Xastir.org Wiki).
+
+2010-01-31 00:45 we7u
+
+ * ChangeLog: Committing latest ChangeLog (derived from cvs log)
+ before release.
+
+2010-01-31 00:44 we7u
+
+ * symbols/symbols.dat: Updated wheelchair symbol plus new power
+ plant symbol by Kyle Mills. Thanks!
+
+2010-01-31 00:24 we7u
+
+ * README.CYGWIN: A re-written Cygwin install by David Flood,
+ KD7MYC. Thanks!
+
+2010-01-31 00:19 we7u
+
+ * README.MAPS: Tweaks by David Aitcheson, kb3efs. Thanks! A few
+ minor tweaks by we7u.
+
+2010-01-30 23:42 we7u
+
+ * ChangeLog: Committing latest changelog before release.
+
+2010-01-30 23:41 we7u
+
+ * configure.ac, scripts/BUILDRPMS, scripts/LSB-BUILD,
+ scripts/do_xastir_release_dev, scripts/do_xastir_release_stable:
+ Preparing for 1.9.8 stable release. Changing revision numbers.
+
+2010-01-30 18:12 we7u
+
+ * AUTHORS, DEBUG_LEVELS, FAQ, INSTALL, LICENSE, Makefile.am, NEWS,
+ README, README.CVS, README.Contributing, README.Getting-Started,
+ README.MAPS, README.win32, REGRESSION_TESTS, UPGRADE,
+ acinclude.m4, bootstrap.sh, callpass.1, changes.txt,
+ configure.ac, install-xastir, testdbfawk.1, update-xastir,
+ xastir.1, xastir_udp_client.1, Davis/Makefile.am, Davis/README,
+ Davis/bootstrap.sh, Davis/configure.ac, Davis/src/Makefile.am,
+ Davis/src/db2APRS.c, Davis/src/defs.h, LaCrosse/AUTHORS,
+ LaCrosse/Makefile.am, LaCrosse/README, LaCrosse/bootstrap.sh,
+ LaCrosse/configure.ac, LaCrosse/src/Makefile.am,
+ LaCrosse/src/defs.h, LaCrosse/src/open2300db2APRS.c,
+ callpass/Makefile.am, callpass/callpass.c, config/24kgrid.dbfawk,
+ config/Makefile.am, config/arealm.dbfawk,
+ config/areawater.dbfawk, config/cousub.dbfawk,
+ config/cousub00.dbfawk, config/edge.dbfawk,
+ config/featnames.dbfawk, config/gps_wpt.dbfawk,
+ config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, config/nwsc_ddmmyy.dbfawk,
+ config/nwsc_ddmmyy_09.dbfawk, config/nwsc_ddmmyy_09b.dbfawk,
+ config/nwsmzddmmyy.dbfawk, config/nwsmzddmmyy_09.dbfawk,
+ config/nwsmzoddmmyy.dbfawk, config/nwsozddmmyy.dbfawk,
+ config/nwsozddmmyy_09.dbfawk, config/nwsw_ddmmyy.dbfawk,
+ config/nwsw_ddmmyy_09.dbfawk, config/nwsz1ddmmyy.dbfawk,
+ config/nwsz_ddmmyy.dbfawk, config/nwsz_ddmmyy_09.dbfawk,
+ config/nwszoddmmyy.dbfawk, config/pointlm.dbfawk,
+ config/predefined_EVENT.sys, config/predefined_SAR.sys,
+ config/stored_track.dbfawk, config/tabblock.dbfawk,
+ config/tgr2shp.dbfawk, config/tgr2shppoly.dbfawk,
+ config/tgr2shppoly_2006.dbfawk, config/tgrcty.dbfawk,
+ config/tgrkgl.dbfawk, config/tgrlk.dbfawk, config/tgrlpt.dbfawk,
+ config/tgrlpy.dbfawk, config/tgrplc00.dbfawk,
+ config/tgrwat.dbfawk, config/tnc-startup.aea,
+ config/tnc-startup.d700, config/tnc-startup.kam,
+ config/tnc-startup.kpc2, config/tnc-startup.kpc3,
+ config/tnc-startup.paccomm, config/tnc-startup.pico,
+ config/tnc-startup.sys, config/tnc-startup.thd7,
+ config/tnc-startup.tnc2, config/tnc-startup.tnc2-ui,
+ config/tnc-stop.d700, config/tnc-stop.sys, config/tnc-stop.thd7,
+ config/tnc-stop.tnc2-ui, help/Makefile.am, help/help-Dutch.dat,
+ help/help-English.dat, help/help-French.dat,
+ help/help-German.dat, help/help-Italian.dat,
+ help/help-Portuguese.dat, help/help-Spanish.dat, m4/Makefile.am,
+ scripts/Coordinate.pm, scripts/LSB-BUILD, scripts/LSB-BUILD-ALL,
+ scripts/LSB-BUILD-CURL, scripts/LSB-BUILD-DB,
+ scripts/LSB-BUILD-GDAL, scripts/LSB-BUILD-GRAPHICSMAGICK,
+ scripts/LSB-BUILD-JASPER, scripts/LSB-BUILD-JPEG,
+ scripts/LSB-BUILD-LESSTIF, scripts/LSB-BUILD-PCRE,
+ scripts/LSB-BUILD-PNG, scripts/LSB-BUILD-ZLIB,
+ scripts/Makefile.am, scripts/UIView2XastirLog.pl,
+ scripts/Xastir_tigerpoly.py, scripts/example_objects.log,
+ scripts/get-NWSdata, scripts/get-fcc-rac.pl, scripts/get-gnis,
+ scripts/get-maptools.sh, scripts/get-pop,
+ scripts/get_shapelib.sh, scripts/inf2geo.pl, scripts/kiss-off.pl,
+ scripts/langElmerFudd.pl, scripts/langMuppetsChef.pl,
+ scripts/langOldeEnglish.pl, scripts/langPigLatin.pl,
+ scripts/langPirateEnglish.pl, scripts/object2shp.pl,
+ scripts/overlay.pl, scripts/ozi2geo.pl, scripts/permutations.pl,
+ scripts/pos2shp.pl, scripts/slideshow.pl, scripts/test_coord.pl,
+ scripts/toporama250k.pl, scripts/toporama50k.pl,
+ scripts/track-get.pl, scripts/waypoint-get.pl,
+ scripts/xastir-fixcfg.sh, scripts/xastir-migrate.sh,
+ src/Makefile.am, src/alert.c, src/alert.h, src/awk.c, src/awk.h,
+ src/bulletin_gui.c, src/bulletin_gui.h, src/color.c, src/color.h,
+ src/database.h, src/datum.c, src/datum.h, src/db.c, src/db_gis.c,
+ src/db_gis.h, src/dbfawk.c, src/dbfawk.h, src/draw_symbols.c,
+ src/draw_symbols.h, src/fcc_data.c, src/fcc_data.h,
+ src/festival.c, src/festival.h, src/geo-client.c, src/geo-find.c,
+ src/geo.h, src/geocoder_gui.c, src/gps.c, src/gps.h,
+ src/hashtable.c, src/hashtable.h, src/hashtable_itr.c,
+ src/hashtable_itr.h, src/hashtable_private.h, src/hostname.c,
+ src/hostname.h, src/igate.c, src/igate.h, src/interface.c,
+ src/interface.h, src/interface_gui.c, src/io-common.c,
+ src/io-mmap.c, src/io.h, src/lang.c, src/lang.h,
+ src/leak_detection.h, src/list_gui.c, src/list_gui.h,
+ src/locate_gui.c, src/location.c, src/location_gui.c,
+ src/macspeech.c, src/main.c, src/main.h, src/map_WMS.c,
+ src/map_cache.c, src/map_cache.h, src/map_dos.c, src/map_gdal.c,
+ src/map_geo.c, src/map_gnis.c, src/map_pdb.c, src/map_pop.c,
+ src/map_shp.c, src/map_tif.c, src/map_tiger.c, src/maps.c,
+ src/maps.h, src/messages.c, src/messages.h, src/messages_gui.c,
+ src/objects.c, src/objects.h, src/popup.h, src/popup_gui.c,
+ src/rac_data.c, src/rac_data.h, src/rotated.c, src/rotated.h,
+ src/rpl_malloc.c, src/rpl_malloc.h, src/shp_hash.c,
+ src/shp_hash.h, src/snprintf.c, src/snprintf.h, src/sound.c,
+ src/symbols.h, src/testdbfawk.c, src/track_gui.c,
+ src/track_gui.h, src/util.c, src/util.h, src/view_message_gui.c,
+ src/wx.c, src/wx.h, src/wx_gui.c, src/x_spider.c, src/x_spider.h,
+ src/xa_config.c, src/xa_config.h, src/xastir.h,
+ src/xastir_udp_client.c, src/rtree/Makefile.am, src/rtree/card.c,
+ src/rtree/card.h, src/rtree/gammavol.c, src/rtree/index.c,
+ src/rtree/index.h, src/rtree/node.c, src/rtree/rect.c,
+ src/rtree/sphvol.c, src/rtree/split_l.c, src/rtree/split_l.h,
+ src/rtree/split_q.c, src/rtree/split_q.h,
+ src/shapelib/Makefile.am, src/shapelib/contrib/Makefile.am,
+ symbols/Makefile.am, symbols/symbols.dat: Updating Copyright
+ notice for 2010.
+
+2010-01-25 20:09 chicoreus
+
+ * src/db_gis.c: Make fails with errors when configured with just
+ --with-mysql. Fixing nesting of HAVE_POSTGIS and HAVE_MYSQL
+ directives so that xastir will build with just --with-mysql.
+ Both compiler warnings and runtime errors remain when built
+ --with-mysql --without-postgis.
+
+2010-01-16 22:27 tvrusso
+
+ * src/main.c: Fix three instances of a string compare being
+ attempted by: char chararray[EXTENT] read chararray from
+ some file if (chararray == "string literal") { }
+
+ which is bad form in C and could lead to undefined behavior. The
+ correct way to do this is with strcmp or strncmp. I replaced
+ this with:
+
+ if (strncmp(chararray,"string literal",strlen(chararray))==0)
+ {
+ }
+
+ This is silently accepted by most older compilers, but is warned
+ about by gcc 4.4 (the default compiler in Ubuntu 9.10).
+
+2010-01-12 11:32 tvrusso
+
+ * src/objects.c: Fix to my most recent fix; make sure that the code
+ that doesn't get the compiler warning actually does the same
+ thing that it did before the fix.
+
+2010-01-12 09:47 tvrusso
+
+ * src/objects.c: Minor tweak to silence a warning about
+ "dereferencing type-punned pointer breaks strict-aliasing rules."
+
+2010-01-11 19:30 tvrusso
+
+ * src/: db.c, objects.c:
+ Fix two bugs.
+
+ 1) Bug 1698474 in the sourceforge tracker (Expire code messes up
+ internal linked-list order)
+
+ The title of the bug is erroneous. The expire code doesn't
+ mess up
+ any internal linked-list order. The expire code was being
+ messed
+ up by a broken linked-list order. What was breaking the list
+ was
+ the handling of our own objects. Code throughout objects.c
+ was
+ continually resetting the time stamp of station records to
+ sec_now() withouth then moving the station record to the end
+ of the
+ time-sorted list. This led to the time-sorted list not being
+ time-sorted anymore. The expire code explicitly depends on
+ the
+ list remaining sorted at all times.
+
+ There was also a small block of code dating back to version
+ 1.1 of
+ db.c that also skipped moving a station record in the
+ time-sorted
+ list if it was our object or item. This very old code appears
+ to
+ do nothing at all. I have removed it. The time sorted list
+ MUST
+ be kept in time-sorted order. There was also a variable
+ (object_is_mine_previous) that was set by this block of code
+ but never
+ accessed anywhere else. I've removed that variable, too.
+
+ Additionally, the check_station_remove function erroneously
+ checks
+ "is_my_station" to determine if the station or object in
+ question is
+ owned by "me." It should be checking (is_my_station ||
+ is_my_object_item)
+ to be consistent with the older conditional that is commented
+ out just
+ above it.
+
+ 2) Creating an object that has the same name as a previously
+ killed object would lead to an "immovable" object being
+ created. This bug was never entered into the issue tracker.
+
+ Prior to this commit, the following actions would create an
+ object that
+ could not be moved:
+
+ create object a
+ delete object a
+ create object a
+
+ Once the second create was done, the object a could not be
+ moved by any
+ means on the screen -- either by dragging with the Move button
+ down or
+ using the Modify Object dialog.
+
+ The reason was that the code to handle resurrecting a killed
+ object
+ was improperly flagging the new object as being "my station"
+ in
+ addition to being flagged as "my object." The code that
+ decodes
+ position strings would see this flag and refuse to move the
+ object
+ "because I know my position better." Furthermore, the
+ resurrection
+ code would remove the old killed record from the name-sorted
+ list,
+ but not really delete the station record, leaving it in the
+ time-sorted list. This also impacted expiration. This commit
+ fixes the improper flagging as "my station" and completely
+ deletes
+ the station record for a killed object when we create a new
+ object
+ with the same name.
+
+2010-01-01 15:04 we7u
+
+ * src/main.c: Fixed some side-effects regarding zoom boxes when map
+ lock is enabled.
+
+2010-01-01 06:22 gstueve
+
+ * src/db.c: Recall one of my tests from the wild. It escaped before
+ its' time.
+
+2009-12-31 03:10 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Finishing up the map
+ lock code.
+
+2009-12-29 13:56 we7u
+
+ * src/main.c: Detaching the map lock from three areas where they
+ are more complicated operations and therefore aren't easily done
+ by mistake. Therefore no map lock required for those three.
+
+2009-12-27 08:26 gstueve
+
+ * callpass.1, testdbfawk.1, xastir.1, xastir_udp_client.1: Update
+ APRS site reference to useful URL.
+
+2009-12-27 07:29 gstueve
+
+ * callpass.1: Add reference to xastir in NAME section to allow
+ `apropos` to associate.
+
+2009-12-25 07:20 we7u
+
+ * README: Updating the SuSE 11.x ham repository info.
+
+2009-12-22 13:37 gstueve
+
+ * Makefile.am, src/db.c, src/lclint.script: Add additional man
+ pages to list for publication.
+
+2009-12-22 13:20 gstueve
+
+ * callpass.1, testdbfawk.1, xastir.1, xastir_udp_client.1: Add
+ simple documentation for all applications. Provide APRS reference
+ in NAME section for 'apropos' & 'whatis' lookup. Make sure NAME
+ section is parseable for scanning.
+
+2009-12-22 02:56 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/xa_config.c,
+ src/xastir.h: Adding map zoom/pan lock feature to the Map menu.
+
+2009-12-17 09:44 gstueve
+
+ * xastir.spec.in: Allow rpmbuild spec to work for 64bit
+ environments also.
+
+2009-12-08 11:34 we7u
+
+ * README.MAPS: Updating the location of the RAC callsign manual
+ download to match the URL in the get-fcc-rac.pl script.
+
+2009-12-07 16:34 tvrusso
+
+ * FAQ: Update FAQ to include updated answer to the "black images
+ from imagemagick" question, and add a FAQ about compilation woes
+ due to use of ImageMagick with HDRI support.
+
+2009-12-04 10:54 tvrusso
+
+ * src/: map_WMS.c, map_geo.c, map_tiger.c:
+ Fix for the problem where Xastir will display black images when
+ compiled against GraphicsMagick with its new default QuantumDepth
+ of 8, or ImageMagick with its optional QuantumDepth of 8.
+
+ The problem was that when the image was not a colormapped image
+ (e.g. JPEG or other full color type), Xastir was assuming
+ (incorrectly) that a Quantum was the same type as the red, green,
+ and blue components of an XColor, and using the Quantums directly
+ out of the pixel_pack in a call that required the latter. The
+ result was that when pack_pixel_bits returned, the result was
+ always that the packed pixel bits were always 0x000000, because
+ it was taking the high-order 8 bits from the unsigned short to
+ which the unsigned char was being cast.
+
+ What was needed was a little block of code that massaged the
+ pixel_pack values into unsigned shorts at that point if
+ QuantumDepth is 8.
+
+ This fix applies the same fix to map_tiger, map_geo and map_WMS,
+ all of which had duplicated code (ugh) that made the same
+ mistaken assumption of Quantum/unsigned short equivalence.
+
+ This fix does NOT address the problem that exists on a few
+ systems, where ImageMagick has been compiled with HDRI (High
+ Dynamic Range Image) support. On those systems, a Quantum is not
+ even an integer type, it's a float or double. Dealing with
+ *that* mess will be harder.
+
+ Ideally, the duplicated code between map_WMS, map_geo, and
+ map_tiger should be consolidated according to good software
+ engineering principles.
+
+2009-11-26 08:52 tvrusso
+
+ * LaCrosse/src/open2300db2APRS.c:
+ Fix for an insidious bug in open2300db2APRS that relied on an
+ unsafe internal behavior of the mysql API.
+
+ The function Get_Latest_WX makes 2 SQL queries to the server, one
+ to get the highest value of the "timestamp" field present in the
+ DB, an another to get the row with that timestamp. Only after
+ the first query was the function calling "row =
+ mysql_fetch_row(&result)". That function returns a char ** that
+ can be used to pick off the field values. Somehow, despite never
+ being called after the second query, the row array still managed
+ (on some systems) to have the right data in it --- presumably
+ because the API call was returning a pointer to an internal block
+ of memory that contained the field values, and on the systems
+ where this worked that block wasn't moving.
+
+ When I upgraded my BSD system and recompiled mysql, this started
+ failing, and open2300db2APRS would segfault.
+
+ Calling mysql_fetch_row after the second query fixes it.
+
+ While I was at it, I fixed a mistake in some debug output that
+ prints the number of fields retrieved by the query.
+
+2009-11-09 12:46 we7u
+
+ * scripts/UIView2XastirLog.pl: New script to convert UI-View log
+ files to Xastir-format log files. Timestamp info is currently
+ removed during the conversion.
+
+2009-10-13 23:25 we7u
+
+ * scripts/get-NWSdata: Updating the get-NWSdata script to snag the
+ latest-latest NWS Shapefile maps used for weather alerts.
+
+2009-10-13 23:24 we7u
+
+ * config/: Makefile.am, nwsc_ddmmyy_09b.dbfawk,
+ nwsmzddmmyy_09.dbfawk, nwsozddmmyy_09.dbfawk,
+ nwsw_ddmmyy_09.dbfawk, nwsz_ddmmyy_09.dbfawk: Adding yet another
+ round of dbfawk files to match new NWS Shapefile signatures.
+
+2009-10-11 22:18 we7u
+
+ * configure.ac: Bumping devel version up to 1.9.7
+
+2009-10-10 11:28 we7u
+
+ * scripts/: do_xastir_release_dev, do_xastir_release_stable:
+ Updating to new SourceForge release process.
+
+2009-10-10 10:41 we7u
+
+ * ChangeLog, configure.ac, scripts/BUILDRPMS, scripts/LSB-BUILD,
+ scripts/do_xastir_release_dev, scripts/do_xastir_release_stable:
+ Preparing for 1.9.6 stable release.
+
+2009-08-12 11:59 we7u
+
+ * src/main.c: Adding minWidth and minHeight to the fallback
+ resources string in main() to attempt fixing the compiz/fusion
+ bug with tiny unsizeable dialogs.
+
+2009-08-12 11:14 we7u
+
+ * FAQ: Adding a blurb regarding "compiz" and cigar-shaped windows
+ in Xastir. Thanks to Tom R. for this text which I modified
+ somewhat.
+
+2009-07-31 21:19 tvrusso
+
+ * config/nwsc_ddmmyy_09.dbfawk: Add a comment about the difference
+ between this file and the nwsc_ddmmyy file.
+
+2009-07-31 21:17 tvrusso
+
+ * config/: Makefile.am, nwsc_ddmmyy_09.dbfawk: Add a new
+ nwsc_ddmmyy file with different signature to match the very
+ latest shapefiles.
+
+ I am adding this as a new dbfawk instead of modifying the
+ existing one so that those who don't wish to update their
+ shapefiles will not have to, and those who have only the new ones
+ will actually be able to use them. Xastir will pick the dbfawk
+ file with the matching signature.
+
+2009-07-31 15:38 we7u
+
+ * src/wx_gui.c: Changing the weather alert FINGER server since
+ WXSVR.net has been offline for a while. We're switching to
+ Pete's new system (AE5PL) which is already online and functional.
+
+2009-07-30 12:41 tvrusso
+
+ * symbols/symbols.dat: Change color of ICP (Incident Command Post,
+ /c) symbol to match the color specified in FEMA and NWCG ICS
+ materials. (I'm working through lots of these courses while
+ simultaneously trying to get Xastir integrated more into our
+ local SAR system, and getting these discrepancies of terminology
+ and symbology fixed is important).
+
+2009-07-28 15:51 tvrusso
+
+ * config/predefined_SAR.sys: Make predefined SAR objects conform
+ with NIMS standard ICS terminology.
+
+ There is no "Helipoint" in that terminology. The term "Helispot"
+ is used for what we were previously calling a "Helipoint."
+
+2009-07-28 15:49 tvrusso
+
+ * src/objects.c: Fix predefined object name to conform with
+ standard ICS terminology. A "Helispot" is a temporary landing
+ place for helicopters. There is no "Helipoint" in standard ICS
+ terminology.
+
+2009-07-28 14:35 we7u
+
+ * src/alert.c: Temporary change to allow viewing of compressed-zone
+ format alerts sent by Pete Loveall, AE5PL's server.
+
+2009-07-27 18:44 we7u
+
+ * src/: db.c, draw_symbols.c, draw_symbols.h: Display of latest
+ comment if H2O symbol plus object or item, and the comment time =
+ the latest object/item update time. This is to support fast
+ viewing of flood gauges during emergencies, using the data from
+ the Firenet gage.pl script.
+
+2009-06-29 00:14 we7u
+
+ * src/db.c: Fixing Canadian callsign lookup to add VO and VY
+ prefixes.
+
+2009-06-19 23:01 tvrusso
+
+ * src/shp_hash.c: Insert a conditional around code that uses a
+ pointer returned by SHPReadObject. A user is finding that
+ SHPReadObject is having an fread problem on one of his
+ shapefiles, and returning NULL. This commit prevents Xastir from
+ trying to dereference the null pointer.
+
+2009-06-03 21:25 we7u
+
+ * src/shapelib/: dbfadd.c, dbfcreate.c, shpadd.c, shpcreate.c,
+ shpdump.c, shptest.c, shptreedump.c, shputils.c: Getting rid of
+ compiler warnings due to unused variable.
+
+2009-06-03 15:24 we7u
+
+ * src/shapelib/: dbfadd.c, shpcreate.c: Adding includes for
+ string.h to get rid of compiler warnings.
+
+2009-06-03 14:57 tvrusso
+
+ * src/shapelib/Makefile.am: Not really sure why this worked before
+ but now doesn't work for Curt, but there was nothing in the
+ src/shapelib/Makefile.am to make the {shp,dbf}{add,create}
+ programs link with the shapelib we just built.
+
+ Put that in.
+
+ Rebootstrap before trying.
+
+2009-05-22 16:23 we7u
+
+ * scripts/pos2shp.pl: Changed some comments WRT the TODO for the
+ comment field.
+
+2009-05-22 14:41 we7u
+
+ * README.MAPS: Adding bits about APRS Overlay files and the
+ pos2shp.pl script.
+
+2009-05-22 14:35 we7u
+
+ * scripts/Makefile.am: Adding pos2shp.pl to list of scripts to
+ install.
+
+2009-05-22 14:23 we7u
+
+ * scripts/pos2shp.pl: Better version. Limits $name to 9 chars and
+ chops trailing spaces on same.
+
+2009-05-22 14:14 we7u
+
+ * scripts/pos2shp.pl: First working version. Needs more error
+ checking, needs to assure the name field is properly formatted,
+ and needs to do something with the comment field yet.
+
+2009-05-22 13:16 we7u
+
+ * scripts/pos2shp.pl: Updated comments, removed live_or_dead code.
+ Has NOT been converted to parse POS format files yet (Overlay
+ files).
+
+2009-05-22 11:19 we7u
+
+ * scripts/pos2shp.pl: Start of a pos2shp.pl script. No code
+ changes yet from the original object2shp.pl script it started
+ from.
+
+2009-05-22 10:44 tvrusso
+
+ * src/shapelib/Makefile.am: Change internal shapelib makefile so
+ that it *does* install the create and add programs if we're
+ building with internal shapelib.
+
+ Note: This should not be tested by those who have shapelib tools
+ installed from a package unless you know how to do it without
+ clobbering them.
+
+ Hint: configure --prefix=/some/other/base/than/usr/local will
+ make sure that the new test install doesn't clober anything that
+ the normal install created.
+
+2009-05-22 10:30 tvrusso
+
+ * src/shapelib/Makefile.am: Add "noinst_PROGRAMS" to the internal
+ shapelib build so that shpcreate, shpadd, dbfcreate and dbfadd
+ are built if the user is building the local shapelib.
+
+ They are not installed, because I didn't want to test that
+ feature. To make it so that they *are* installed when make
+ install is called, one needs only change "noinst_PROGRAMS" in
+ src/shapelib/Makefile.am to "bin_PROGRAMS" .
+
+2009-05-19 13:47 tvrusso
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/database.h, src/wx.c: Add
+ support for the Davis 6540 "Weatherlink for APRS" with "Streaming
+ Data Logger". This attachment to the Davis Vantage Pro causes
+ the device to stream APRS posits (sans fromcall, tocall, and
+ path) to the serial port instead of requiring polling. With such
+ a device, Meteo and the associated glue program (db2APRS or
+ whatever it's called) are unnecessary, so long as this patch is
+ in place.
+
+ Also update language files as needed.
+
+2009-05-09 07:15 tvrusso
+
+ * src/db.c: Move "create_garmin_waypoint" call outside of "if
+ (sound_play_prox_message)" conditional.
+
+ A local user was completely confused why his garmin wasn't
+ receiving waypoint data from Xastir, and when I hunted through
+ the coude found that this feature only works if you have audio
+ alerts for proximity warnings turned on. This seems wrong, so I
+ moved the conditionals around so that waypoints are created if
+ you're within proximity warning distance, whether or not you've
+ actually got the old audio alarm turned on for proximity
+ warnings.
+
+2009-04-30 12:25 gstueve
+
+ * src/: database.h, db.c: Fix band opening logic to ignore 3rd
+ party traffic. Should make this really work for band opening and
+ not messages from network. Fix Bug ID:2749796.
+
+2009-04-30 11:52 gstueve
+
+ * src/: main.c, shp_hash.c, shp_hash.h: We already know the current
+ time, there is no need to ask again.
+
+2009-04-29 20:08 gstueve
+
+ * scripts/get-fcc-rac.pl: Minimize memory footprint for constrained
+ systems. Do memory intense activity as late as possible.
+
+2009-04-25 23:40 tvrusso
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c:
+ Fix an annoyance related to DF bearing reports.
+
+ Sometimes a bad parse of garbled Mic-E data causes Xastir to
+ think that a D700 (or other mobile) is sending a DF report. Even
+ if only a single such garbled transmission is received, the
+ station is shown with DF bearing information for as long as it's
+ in the database. Watching a mobile drive around with randomly
+ moving DF beam lines is distracting. Not being able to make it
+ go away without restarting Xastir has been annoying.
+
+ Another way for this to happen is for some bonehead (such as
+ KM5VY) to create a series of DF objects from an external program
+ with his callsign as base name and sequential numbers to identify
+ the reports (say "KM5VY-1", "KM5VY-2", etc.) until he happens to
+ hit the SSID of the station that's sending the reports (say,
+ KM5VY-8). What happens is the "object" data gets attached to the
+ Xastir instance itself. This bogus beam heading shows up forever
+ until shutting down Xastir. This happened today on a SAR ELT DF
+ practice. The name of the bonehead has not been changed to
+ protect the bonehead.
+
+ This commit adds the ability to clear such bogosity. Now, the
+ "Station Info" dialog for any station with DF bearing information
+ has a "Clear DF Bearing" button that will zero out the bearing
+ and NRQ strings for the station, removing the unwanted (and
+ presumably incorrect) bearing lines until the station transmits
+ them again (which probably means they're wanted and not
+ incorrect).
+
+2009-04-25 21:53 tvrusso
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/draw_symbols.c,
+ src/draw_symbols.h, src/main.c, src/main.h, src/xa_config.c:
+ Add a map-decluttering option.
+
+ Prior to this commit, "Station->Filter Display->Display DF
+ Attributes" would draw a pair of bearing lines for every DF
+ object. The lines drawn represented the stated beamwidth of the
+ report.
+
+ Unfortunately, in a big DFing operation, this rapidly leads to a
+ huge clutter on the map, making it very difficult, if not
+ impossible, to read. I saw this during a big DF practice this
+ morning, and just had to change it.
+
+ I have added two new buttons under Display DF Attributes:
+ "Display DF Beamwidth" and "Display DF Bearing." Selecting the
+ first and not the second gives the current behavior. Selecting
+ the second and not the first draws only the stated bearing, not
+ the beamwidth. Selecting both draws all three lines for those
+ who really, really like cluttered maps. The color of red used
+ for the bearing line and the beamwidth lines is slightly
+ different.
+
+ I tried to set up xa_config so that when people first start up
+ Xastir after updating, they'll recover the original behavior ---
+ "Display DF Bearing" defaults to off if it's not found in the
+ config file. Unless the new option is deliberately selected,
+ users should not notice the change.
+
+ Both Display DF Bearing and Display DF Beamwidth are greyed out
+ if "Display DF Attributes" is deselected.
+
+ Updated all the language files with the "update-language.pl"
+ script to support the new menu items. A lot of other things got
+ changed in the language files with this action, but those seemed
+ mostly to be comments.
+
+2009-04-24 13:10 gstueve
+
+ * scripts/get-fcc-rac.pl: Move sort back to system package. PERL
+ does parsing well, not sorting.
+
+2009-04-17 16:10 we7u
+
+ * config/: arealm.dbfawk, areawater.dbfawk, cousub.dbfawk,
+ cousub00.dbfawk, edge.dbfawk, featnames.dbfawk, pointlm.dbfawk,
+ tabblock.dbfawk: Updating the URL for the Shapefiles to point to
+ the 2008 shapefiles instead of 2007!
+
+2009-04-17 09:12 we7u
+
+ * config/: Makefile.am, arealm.dbfawk, areawater.dbfawk,
+ cousub.dbfawk, cousub00.dbfawk, edge.dbfawk, featnames.dbfawk,
+ pointlm.dbfawk, tabblock.dbfawk: Adding the dbfawk files worked
+ on by Richard Polivka, N6NKO, Craig Anderson, N6YXK, and Dale
+ Seaburg, KG5LT, which help to nicely render 2008 Tiger Shapeline
+ files.
+
+ A note from Craig about layering:
+
+ "...use "vi" on the map_index.sys file while xastir is not
+ running.
+ Once you are editing the file, use the following 3 commands in
+ "vi"
+ to change the layers. This assumes that, like with my xastir,
+ new
+ maps get added into the list at layer 1000.
+
+ :g/tabblock/s/01000/00995/
+ :g/pointlm/s/01000/00996/
+ :g/arealm/s/01000/00997/
+
+ (translation: global search throughout the file for lines with
+ "arealm" and substitute on that line for "01000", a "00997")
+
+ This moves the tabblock (& tabblock00) files, pointlm files,
+ and
+ arealm files down underneath the roads maps. Otherwise the
+ roads
+ can get covered up by urban background coloring. Or you can do
+ this
+ through the GUI interface as well."
+
+2009-04-16 19:55 we7u
+
+ * src/wx.c: Fixing up the Peet Bros 2000 data logging and packet
+ mode decoding for wind direction. These were really 4-character
+ fields but the first two chars should be zeroed out. We were
+ reading in only the 2nd two characters and then zeroing them out
+ (the reading of interest).
+
+2009-04-16 14:20 tvrusso
+
+ * scripts/values.pl.in: Change values.pl.in so it references
+ #!/usr/bin/perl instead of #!/bin/perl.
+
+ Neither is strictly correct since perl could be installed just
+ about anywhere on any system, but this brings it in line with all
+ the rest of the scripts here.
+
+ Ideally the location of the perl interpreter should be probed by
+ configure and substituted in all the scripts, but that is
+ probably more work than it's worth given that all of our scripts
+ have had /usr/bin/perl hardcoded all this time.
+
+ #!/usr/bin/env perl
+
+ is sometimes suggested to make such scripts system-independent,
+ but this is generally considered a security vulnerability because
+ it uses the first "perl" that appears in the user's path, which
+ might be a malicious bit of code.
+
+2009-04-16 12:34 tvrusso
+
+ * configure.ac, scripts/Makefile.am, scripts/values.in,
+ scripts/values.pl.in: Remove inappropriate use of GNU Make
+ extensions in scripts/Makefile.am.
+
+ These were introduced to generate scripts/values and
+ scripts/values.pl from scripts/values.in and
+ scripts/values.pl.in, but this is the wrong approach. Generating
+ these files from the .in's should be done by adding them to the
+ configure.ac AC_CONFIG_FILES list and by using standard
+ substitution strings in the .in files. Non-standard substitution
+ strings can also be used if one also adds AC_SUBST calls to the
+ configure.ac file.
+
+ The standard substitution string for prefix is @prefix@ not
+ @PREFIX at .
+
+2009-04-16 12:26 gstueve
+
+ * scripts/Makefile.am: Makefile should actually work properly for
+ split source/build configuration.
+
+2009-04-16 11:56 gstueve
+
+ * scripts/Makefile.am: Make sure proper Makefile is updated when
+ Makefile.am is updated.
+
+2009-04-16 11:39 we7u
+
+ * src/: main.c, messages.h, view_message_gui.c, xa_config.c:
+ Saving/restoring the status of the CAD Objects buttons and the
+ View Messages TNC/NET/MINE selection buttons.
+
+2009-04-16 11:28 gstueve
+
+ * scripts/: get-NWSdata, get-gnis, get-pop: Remove another possible
+ bashism reported by checkbashisms script.
+
+2009-04-16 09:25 we7u
+
+ * scripts/: Makefile.am, slideshow.pl: Adding slideshow.pl, a
+ script which snags the snapshot.png files into a separate
+ directory and renames them for possible later use as a slideshow
+ or animated movie.
+
+2009-04-13 13:18 gstueve
+
+ * scripts/get-pop: Position files are only ASCII, don't push AK or
+ HI through recoding.
+
+2009-04-13 13:10 gstueve
+
+ * scripts/get-pop: Adjust download site to complete list. Retain
+ tamu site for reference.
+
+2009-04-13 11:34 gstueve
+
+ * src/: locate_gui.c, maps.h: Add ability to locate map features
+ from population format files.
+
+2009-04-13 11:13 gstueve
+
+ * src/map_pop.c: Missed these. Had compiled on other system.
+ Mistyped entry.
+
+2009-04-13 10:32 gstueve
+
+ * src/: map_gnis.c, map_pop.c: Found a couple of locations that
+ could get unhappy about trying to read bad data.
+
+2009-04-13 10:16 gstueve
+
+ * scripts/Makefile.am, scripts/get-pop, src/Makefile.am,
+ src/map_pop.c, src/maps.c: Reintroduce previous population
+ geolocator processing into new file type. The .pop file
+ extension will reflect the old information. GNIS does not have
+ authorative population data, we should use census info. The
+ script will look to aprs.tamu.edu but I was not able to locate
+ all of the states data files.
+
+2009-04-08 09:24 gstueve
+
+ * scripts/get-gnis: Get rid of bashism that escaped my first tests.
+
+2009-04-08 09:17 gstueve
+
+ * scripts/get-gnis: Add recode to convert AK & HI UTF-16 files to
+ UTF-8 to give us a fighting chance to actually locate anything in
+ those states.
+
+2009-04-07 14:17 gstueve
+
+ * scripts/get-gnis: USGS has made geocodes a moving target. Current
+ file is 20090401.
+
+2009-04-07 02:23 gstueve
+
+ * src/main.c: Repair damage to map properties dialog inflicted by
+ last check-in.
+
+2009-04-06 09:07 gstueve
+
+ * src/interface_gui.c: Move Path entries around to reduce vertical
+ challenge.
+
+2009-04-05 17:28 gstueve
+
+ * src/map_gnis.c: Update field sequence to match current GNIS file
+ layout.
+
+2009-04-04 23:10 gstueve
+
+ * src/list_gui.c: Update max display list to symbolic count.
+
+2009-04-04 21:14 gstueve
+
+ * src/list_gui.c: Clean up station list to actually line up with
+ icon and line height.
+
+2009-04-04 19:21 gstueve
+
+ * src/objects.c: Maintain pointer to cursor to keep memory usage
+ clean.
+
+2009-04-04 11:37 gstueve
+
+ * scripts/: .cvsignore, Makefile.am, coord-convert.pl, get-NWSdata,
+ get-fcc-rac.pl, get-gnis, icontable.pl, values.in, values.pl.in,
+ xastir-fixcfg.sh, xastir-migrate.sh: Fix the scripts to match the
+ structure for placement of files by using -prefix from configure
+ process to allow matchup to FHS placement.
+
+2009-04-04 11:28 gstueve
+
+ * m4/xmhtml.m4: Wrap macro name to keep everyone happy. Remove
+ autoreconf complaint.
+
+2009-04-03 07:08 gstueve
+
+ * src/: main.c, main.h: Upgrade to session aware application space.
+ Permit GNOME window manager to clean up without warning message
+ about unsaved data. Permit restart to keep proper character
+ translations for display. Clean up some free memory leaks and
+ update for Motif 2.0 XmString functions.
+
+2009-04-02 18:22 gstueve
+
+ * src/interface.c: Remove extraneous include entry.
+
+2009-04-02 15:09 gstueve
+
+ * src/xastir.h: Remove external reference to internal application
+ close out function.
+
+2009-03-31 20:06 tvrusso
+
+ * scripts/object2shp.pl: Fix a minor, but completely
+ inconsequential error in this script. It would produce
+ shapefiles with every shape having the same ID attribute.
+ Doesn't matter at all since ID is not used for anything, but this
+ is the right fix.
+
+2009-03-31 12:56 we7u
+
+ * src/rac_data.c: Fixing a 64-bit mode bug in the RAC callsign
+ lookup code.
+
+2009-02-06 09:22 gstueve
+
+ * README.MAPS: Add hint for Australian rules Weather Alerts &
+ update address for FCC data.
+
+2009-02-06 08:51 gstueve
+
+ * scripts/get-NWSdata: Update to latest from US NWS.
+
+2009-01-08 17:53 we7u
+
+ * README.win32: Adding notes WRT a Cygwin xorg-x11-devel 7.x
+ compile error and how to fix it, courtesy of David Flood, KD7MYC.
+
+2009-01-02 00:15 we7u
+
+ * src/Makefile.am, src/alert.c, src/alert.h, src/awk.c, src/awk.h,
+ src/bulletin_gui.c, src/bulletin_gui.h, src/color.c, src/color.h,
+ src/database.h, src/datum.c, src/datum.h, src/db.c, src/db_gis.c,
+ src/db_gis.h, src/dbfawk.c, src/dbfawk.h, src/draw_symbols.c,
+ src/draw_symbols.h, src/fcc_data.c, src/fcc_data.h,
+ src/festival.c, src/festival.h, src/geo-client.c, src/geo-find.c,
+ src/geo.h, src/geocoder_gui.c, src/gps.c, src/gps.h,
+ src/hashtable.c, src/hashtable.h, src/hashtable_itr.c,
+ src/hashtable_itr.h, src/hashtable_private.h, src/hostname.c,
+ src/hostname.h, src/igate.c, src/igate.h, src/interface.c,
+ src/interface.h, src/interface_gui.c, src/io-common.c,
+ src/io-mmap.c, src/io.h, src/lang.c, src/lang.h,
+ src/leak_detection.h, src/list_gui.c, src/list_gui.h,
+ src/locate_gui.c, src/location.c, src/location_gui.c,
+ src/macspeech.c, src/main.c, src/main.h, src/map_WMS.c,
+ src/map_cache.c, src/map_cache.h, src/map_dos.c, src/map_gdal.c,
+ src/map_geo.c, src/map_gnis.c, src/map_pdb.c, src/map_shp.c,
+ src/map_tif.c, src/map_tiger.c, src/maps.c, src/maps.h,
+ src/messages.c, src/messages.h, src/messages_gui.c,
+ src/objects.c, src/objects.h, src/popup.h, src/popup_gui.c,
+ src/rac_data.c, src/rac_data.h, src/rotated.c, src/rotated.h,
+ src/rpl_malloc.c, src/rpl_malloc.h, src/shp_hash.c,
+ src/shp_hash.h, src/snprintf.c, src/snprintf.h, src/sound.c,
+ src/symbols.h, src/testdbfawk.c, src/track_gui.c,
+ src/track_gui.h, src/util.c, src/util.h, src/view_message_gui.c,
+ src/wx.c, src/wx.h, src/wx_gui.c, src/x_spider.c, src/x_spider.h,
+ src/xa_config.c, src/xa_config.h, src/xastir.h,
+ src/xastir_udp_client.c, AUTHORS, DEBUG_LEVELS, FAQ, INSTALL,
+ LICENSE, Makefile.am, NEWS, README, README.CVS,
+ README.Contributing, README.Getting-Started, README.MAPS,
+ README.win32, REGRESSION_TESTS, UPGRADE, acinclude.m4,
+ bootstrap.sh, changes.txt, configure.ac, install-xastir,
+ update-xastir, xastir.1, m4/Makefile.am: Updating copyright
+ notices for 2009.
+
+2009-01-01 23:58 we7u
+
+ * src/: rtree/Makefile.am, rtree/card.c, rtree/card.h,
+ rtree/gammavol.c, rtree/index.c, rtree/index.h, rtree/node.c,
+ rtree/rect.c, rtree/sphvol.c, rtree/split_l.c, rtree/split_l.h,
+ rtree/split_q.c, rtree/split_q.h, shapelib/Makefile.am,
+ shapelib/contrib/Makefile.am: Updating the copyright notices for
+ 2009.
+
+2009-01-01 23:56 we7u
+
+ * scripts/: LSB-BUILD, LSB-BUILD-ALL, LSB-BUILD-CURL, LSB-BUILD-DB,
+ LSB-BUILD-GDAL, LSB-BUILD-GRAPHICSMAGICK, LSB-BUILD-JASPER,
+ LSB-BUILD-JPEG, LSB-BUILD-LESSTIF, LSB-BUILD-PCRE, LSB-BUILD-PNG,
+ LSB-BUILD-ZLIB, Makefile.am, Xastir_tigerpoly.py,
+ example_objects.log, get-NWSdata, get-fcc-rac.pl, get-gnis,
+ get-maptools.sh, get_shapelib.sh, langElmerFudd.pl,
+ langMuppetsChef.pl, langOldeEnglish.pl, langPigLatin.pl,
+ langPirateEnglish.pl, toporama250k.pl, toporama50k.pl,
+ xastir-fixcfg.sh, xastir-migrate.sh: Updating copyright notices
+ for 2009.
+
+2009-01-01 23:54 we7u
+
+ * callpass/: Makefile.am, callpass.c: Updating the copyright
+ notices for 2009.
+
+2009-01-01 23:51 we7u
+
+ * symbols/Makefile.am, symbols/symbols.dat, LaCrosse/Makefile.am,
+ LaCrosse/README, LaCrosse/bootstrap.sh, LaCrosse/configure.ac,
+ LaCrosse/src/Makefile.am, LaCrosse/src/defs.h,
+ LaCrosse/src/open2300db2APRS.c, help/Makefile.am,
+ help/help-Dutch.dat, help/help-English.dat, help/help-French.dat,
+ help/help-German.dat, help/help-Italian.dat,
+ help/help-Portuguese.dat, help/help-Spanish.dat,
+ Davis/Makefile.am, Davis/README, Davis/bootstrap.sh,
+ Davis/configure.ac, Davis/src/Makefile.am, Davis/src/db2APRS.c,
+ Davis/src/defs.h, config/24kgrid.dbfawk, config/Makefile.am,
+ config/gps_wpt.dbfawk, config/language-Dutch.sys,
+ config/language-English.sys, config/language-French.sys,
+ config/language-German.sys, config/language-Italian.sys,
+ config/language-Portuguese.sys, config/language-Spanish.sys,
+ config/nwsc_ddmmyy.dbfawk, config/nwsmzddmmyy.dbfawk,
+ config/nwsmzoddmmyy.dbfawk, config/nwsozddmmyy.dbfawk,
+ config/nwsw_ddmmyy.dbfawk, config/nwsz1ddmmyy.dbfawk,
+ config/nwsz_ddmmyy.dbfawk, config/nwszoddmmyy.dbfawk,
+ config/predefined_EVENT.sys, config/predefined_SAR.sys,
+ config/tgr2shp.dbfawk, config/tgr2shppoly.dbfawk,
+ config/tgr2shppoly_2006.dbfawk, config/tgrcty.dbfawk,
+ config/tgrkgl.dbfawk, config/tgrlk.dbfawk, config/tgrlpt.dbfawk,
+ config/tgrlpy.dbfawk, config/tgrplc00.dbfawk,
+ config/tgrwat.dbfawk, config/tnc-startup.aea,
+ config/tnc-startup.d700, config/tnc-startup.kam,
+ config/tnc-startup.kpc2, config/tnc-startup.kpc3,
+ config/tnc-startup.paccomm, config/tnc-startup.pico,
+ config/tnc-startup.sys, config/tnc-startup.thd7,
+ config/tnc-startup.tnc2, config/tnc-startup.tnc2-ui,
+ config/tnc-stop.d700, config/tnc-stop.sys, config/tnc-stop.thd7,
+ config/tnc-stop.tnc2-ui: Updating the copyright notices for 2009.
+
+2008-12-31 20:37 we7u
+
+ * src/xa_config.c: Changing xastir.cnf -> xastir.cnf.1 to a
+ copy_file() call instead of a move(). This assures that we'll
+ always have a config file in place even if we error-out before we
+ can complete the next block which renames xastir.cnf.tmp ->
+ xastir.cnf.
+
+2008-12-31 20:18 we7u
+
+ * src/xa_config.c: A better ordering for writing the config file.
+ We now write a temporary file. If successful, we rename all the
+ backups and then rename the temporary file as the current config
+ file. This should help to minimize the instances of config file
+ corruption.
+
+2008-12-09 08:10 we7u
+
+ * FAQ, README, README.Contributing, README.Getting-Started,
+ README.win32: Adding notes about having to subscribe to the
+ mailing lists before posting.
+
+2008-11-26 09:39 we7u
+
+ * src/draw_symbols.c: Correcting a comment.
+
+2008-11-24 12:27 we7u
+
+ * scripts/example_objects.log: Adding a link to the Xastir Wiki
+ where images of these objects can be seen.
+
+2008-11-12 15:26 tvrusso
+
+ * src/map_geo.c: Comment out the use of GetOnePixel and the
+ variable it assigns to.
+
+ This is for two reasons:
+
+ 1) F*!#*ng ImageMagick has broken its API yet again with version
+ 6.4.5,
+ making GetOnePixel no longer compatible with usage prior to
+ 6.4.4
+ 2) map_geo.c does this:
+ PixelPacket target;
+ target=GetOnePixel(image,0,0)
+ after which it does NOTHING with the pixel so retrieved. So
+ commenting
+ out this useless line is less work than what I had started
+ doing,
+ which was hacking the configure detection of ImageMagick to
+ distinguish
+ between pre-6.4.5 and post-6.4.5, and coding around this
+ garbage.
+
+ I Hate ImageMagick.
+
+2008-10-17 00:18 we7u
+
+ * config/tnc-startup.aea: Turning on the HID function which is
+ required on AEA TNC's for proper identification if they're
+ digipeating. Since we have digipeating turned on in this file...
+
+2008-10-16 09:20 we7u
+
+ * ChangeLog: Updating for devel release.
+
+2008-10-08 21:57 we7u
+
+ * src/map_shp.c: Getting rid of a 64-bit compiler warning by
+ changing an "(int)NULL" to a "0".
+
+2008-10-08 21:56 we7u
+
+ * src/db.c: Changing a debug format so that it doesn't cause a
+ warning on 64-bit machines.
+
+2008-10-08 08:11 we7u
+
+ * src/maps.c: Getting rid of two compiler warnings: One by forcing
+ a terminator into the first char of a string buffer instead of
+ doing an empty xastir_snprintf(), another by casting a strlen()
+ result to an int for an fprintf.
+
+2008-10-07 23:10 we7u
+
+ * src/shp_hash.c: Reverting back to the original code for strncpy()
+ in this module: The previous change caused a panic.
+
+2008-10-07 22:59 we7u
+
+ * src/shp_hash.c: Getting rid of another strncpy() call.
+
+2008-10-07 22:43 we7u
+
+ * src/util.c: Forcibly terminating a string as an added precaution.
+
+2008-10-07 22:42 we7u
+
+ * src/shp_hash.c: Adding some blank lines to delimit an strcpy()
+ call.
+
+2008-10-07 22:41 we7u
+
+ * src/objects.c: Getting rid of an strcat() call.
+
+2008-10-07 22:41 we7u
+
+ * src/db.c: Getting rid of some strncpy() calls.
+
+2008-10-07 22:40 we7u
+
+ * src/awk.c: Updating a comment.
+
+2008-10-07 22:14 we7u
+
+ * src/: db.c, fcc_data.c, hostname.c, igate.c, interface.c,
+ interface_gui.c, locate_gui.c, map_WMS.c, map_geo.c, map_shp.c,
+ map_tiger.c, maps.c, messages.c, objects.c, util.c, wx.c,
+ x_spider.c, xa_config.c: Fixing some off-by-one errors in string
+ handling.
+
+2008-10-07 21:42 we7u
+
+ * src/: alert.c, main.c: Fixing some off-by-one errors in string
+ handling.
+
+2008-10-06 22:04 we7u
+
+ * src/main.c: Fixing the my_text string buffer in TrackMouse() so
+ that it won't get overrun. The worst conditions are English
+ Units, Dist/Bearing Status enabled, Degrees/Minutes/Seconds,
+ zoomed out to world view and putting the mouse in the "corner" of
+ the world (10,000+ miles). This results in about 54 characters
+ being used whereas the original string buffer was only capable of
+ holding 49.
+
+2008-09-26 07:30 gstueve
+
+ * src/x_spider.c: Make sure both sides of the pipe are satisfied
+ before releasing the memory. The system is not happy about trying
+ to read data from free space.
+
+2008-09-24 12:44 we7u
+
+ * .cvsignore: Ignore the derived file "xastir-lsb.spec" as well.
+
+2008-09-24 12:18 we7u
+
+ * src/.cvsignore: Ignoring testdbfawk now instead of testawk file.
+
+2008-09-24 11:03 gstueve
+
+ * src/map_tiger.c: Found one more place that needed to release
+ ExceptionInfo when interrupted.
+
+2008-09-24 09:16 tvrusso
+
+ * README.MAPS, scripts/LSB-BUILD, src/Makefile.am, src/testawk.c,
+ src/testdbfawk.c: Rename "testawk" to "testdbfawk" and add it to
+ the list of programs that "make install" will install.
+
+ This addresses a couple of issues: 0) Testawk is a *terrible*
+ name for this program, because in fact it does not test
+ "awk", the system program, but rather "dbfawk," the Xastir
+ feature inspired by awk but completely unrelated to awk in any
+ other sense. 1) testawk was never installed by Xastir's build
+ process, meaning that packagers of Xastir binaries for
+ various systems did not bundle this little program with
+ their binary packages. There is even a bug in debian's bug
+ tracker from an Xastir user asking that the xastir package
+ have testawk installed (in a non-standard place because of its
+ "generic, even misleading name") by the .deb package.
+
+ I've updated README.MAPS and the LSB-BUILD script to make them
+ refer to testdbfawk instead of testawk. I'll still have to
+ change various web resources so they point at the new program,
+ too.
+
+2008-09-22 13:19 we7u
+
+ * src/x_spider.c: Removing an earlier change 'cuz it makes the
+ server ports die when a client disconnects. Without this line
+ they appear to be solid again.
+
+2008-09-11 06:07 we7u
+
+ * src/main.c: Grey'ing out the xfontsel buttons when that app's not
+ available.
+
+2008-09-09 22:38 we7u
+
+ * src/xa_config.c: Saving/restoring the tracking station callsign
+ to/from the config file, but not saving the state of the tracking
+ toggle. This means that the last tracked callsign will be
+ remembered but tracking will not be on when Xastir starts up.
+
+2008-09-09 22:17 we7u
+
+ * src/db.c: A proper label for the new "Track Station" button on
+ the Station Info dialog.
+
+2008-09-09 22:11 we7u
+
+ * src/db.c: Initial working version of "Track Station" from the
+ Station Info dialog. Still needs additions to the language files
+ for the button label.
+
+2008-09-09 20:10 we7u
+
+ * src/interface.c: Adding some comments near four areas that cause
+ compiler warnings which we can currently do nothing about.
+
+2008-09-09 20:09 we7u
+
+ * src/testawk.c: Changing an int* to an int to get rid of a
+ compiler warning about a mismatch.
+
+2008-09-09 20:07 we7u
+
+ * acinclude.m4: Adding /opt/local/ directory to the test for
+ binaries (MacPorts). Changing the order of some compiler flags
+ to help find GM before IM on FreeBSD systems.
+
+2008-09-09 08:47 we7u
+
+ * src/util.c: Changing the return type for a curl function to get
+ rid of a warning caused by newer versions of libcurl.
+
+2008-09-09 08:37 we7u
+
+ * src/: main.c, track_gui.c: Adding #ifdef's around SED and MV
+ calls.
+
+2008-09-09 08:20 we7u
+
+ * src/main.c: Added #ifdef around XFONTSEL call so that absence of
+ the binary won't cause compile problems.
+
+2008-09-08 09:13 we7u
+
+ * ChangeLog, scripts/Makefile.am: Adding lang* scripts to package
+ build. Updating ChangeLog to latest.
+
+2008-09-03 08:46 gstueve
+
+ * config/.cvsignore: Get CVS to forget about the generated language
+ files.
+
+2008-09-03 08:43 gstueve
+
+ * src/main.c: Get valgrind to stop complaining about the lost
+ blocks in the app_context.
+
+2008-09-03 06:06 we7u
+
+ * scripts/langPirateEnglish.pl: Translating "Maps" as well as
+ "Map".
+
+2008-08-31 16:45 we7u
+
+ * scripts/langMuppetsChef.pl: Enabling more of the regex. Much
+ better "translation".
+
+2008-08-31 16:27 we7u
+
+ * scripts/: langElmerFudd.pl, langMuppetsChef.pl, langPigLatin.pl,
+ langPirateEnglish.pl: More updates to the derived language
+ scripts.
+
+2008-08-31 15:31 we7u
+
+ * scripts/langOldeEnglish.pl: Rewriting the script so that
+ anchoring & substitutions work in the regex.
+
+2008-08-31 13:52 we7u
+
+ * bootstrap.sh, scripts/langElmerFudd.pl,
+ scripts/langMuppetsChef.pl, scripts/langOldeEnglish.pl,
+ scripts/langPigLatin.pl, scripts/langPirateEnglish.pl: Updates to
+ derived languages scripts, preparing for possible future uses.
+
+2008-08-31 09:26 we7u
+
+ * scripts/langPirateEnglish.pl: More for TLAPD.
+
+2008-08-30 18:56 we7u
+
+ * scripts/langPirateEnglish.pl: More Pirate updates.
+
+2008-08-30 18:14 we7u
+
+ * scripts/langPirateEnglish.pl: Latest Pirate updates.
+
+2008-08-30 17:31 we7u
+
+ * scripts/langPirateEnglish.pl: Added a few more Xastir-specific
+ translations.
+
+2008-08-30 16:30 we7u
+
+ * INSTALL, README.Getting-Started, README.win32, bootstrap.sh,
+ config/Makefile.am, help/help-English.dat, help/help-German.dat,
+ help/help-Italian.dat, help/help-Portuguese.dat,
+ help/help-Spanish.dat, src/main.c: Adding five new official
+ languages to the "-l" flag in Xastir.
+
+2008-08-30 16:28 we7u
+
+ * scripts/: langElmerFudd.pl, langMuppetsChef.pl,
+ langOldeEnglish.pl, langPirateEnglish.pl: Adding more official
+ languages.
+
+2008-08-29 22:21 we7u
+
+ * scripts/langPigLatin.pl: Changing a comment to avoid the RCS tag
+ substitution as well.
+
+2008-08-29 22:19 we7u
+
+ * scripts/langPigLatin.pl: Changed the match string so that RCS/CVS
+ won't substitute a new Id: string in our REGEX expression.
+
+2008-08-29 22:12 we7u
+
+ * scripts/langPigLatin.pl: Renamed from PigLatin.pl
+
+2008-08-29 22:11 we7u
+
+ * scripts/PigLatin.pl: Moving this file to langPigLatin.pl
+
+2008-08-28 08:14 gstueve
+
+ * scripts/: get-maptools.sh, get_shapelib.sh: Use available
+ resources to make use of temporary file as safe as possible.
+
+2008-08-28 07:24 gstueve
+
+ * scripts/get_shapelib.sh: Use same library logic as
+ get-maptools.sh and clear temporary file for our use.
+
+2008-08-28 07:22 gstueve
+
+ * scripts/get-maptools.sh: Make sure to get temporary file out of
+ way so we don't copy into something outside our expectation.
+
+2008-08-27 06:25 tvrusso
+
+ * acinclude.m4: Introduce proper quoting of AC_CACHE_CHECK
+ arguments in XASTIR_GUESS_RUNPATH_SWITCH macro.
+
+2008-08-27 06:23 tvrusso
+
+ * acinclude.m4: Fix the XASTIR_GUESS_RUNPATH_SWITCH macro so that
+ it uses AC_CACHE_CHECK with a CACHE-ID that conforms to the
+ naming conventions expected.
+
+ In versions of autoconf 2.62 and later, using a CACHE-ID without
+ the "_cv_" string included in its name produces an annoying and
+ possibly confusing warning message:
+
+ configure.ac:572: warning: AC_CACHE_VAL(xastir_runpath_switch,
+ ...): suspicious cache-id, must contain _cv_ to be cached
+ ../../lib/autoconf/general.m4:1973: AC_CACHE_VAL is expanded
+ from...
+ ../../lib/autoconf/general.m4:1993: AC_CACHE_CHECK is expanded
+ from...
+ acinclude.m4:1131: XASTIR_GUESS_RUNPATH_SWITCH is expanded
+ from...
+ acinclude.m4:1120: XASTIR_ADD_LIBPATH_TO is expanded from...
+ acinclude.m4:964: XASTIR_BERKELEY_DB_CHK_LIB is expanded from...
+ ../../lib/m4sugar/m4sh.m4:508: AS_IF is expanded from...
+ ../../lib/autoconf/general.m4:2461: AC_COMPILE_IFELSE is
+ expanded from...
+ ../../lib/autoconf/general.m4:2469: AC_TRY_COMPILE is expanded
+ from...
+ acinclude.m4:1059: XASTIR_BERKELEY_DB_CHK is expanded from...
+ configure.ac:572: the top level
+
+ several times during bootstrap. By renaming
+ "xastir_runpath_switch" to "xastir_cv_runpath_switch" throughout
+ acinclude.m4, this warning is silenced and the variable is cached
+ as intended.
+
+ According to the autoconf documentation, cache variables *MUST*
+ have the "_cv_" string in their names. It is only in recent
+ versions of autoconf that violating this requirement is actually
+ flagged as a warning.
+
+2008-08-25 08:19 gstueve
+
+ * src/testawk.c: Add prefix to indicate that we are printing
+ hexadecimal value.
+
+2008-08-21 09:50 gstueve
+
+ * src/bulletin_gui.c: Make sure everything is allocated for
+ bulletins before use.
+
+2008-08-21 09:48 gstueve
+
+ * src/dbfawk.c: Release memory & directory after we finish with
+ them.
+
+2008-08-18 19:02 gstueve
+
+ * scripts/get-fcc-rac.pl: No need to extract unsorted file to disk.
+ Process directly into script.
+
+2008-08-15 13:24 we7u
+
+ * configure.ac, scripts/BUILDRPMS: Setting up for 1.9.5 development
+ versions.
+
+2008-08-15 12:51 we7u
+
+ * ChangeLog: Updating ChangeLog to match latest changes (for
+ upcoming stable release).
+
+2008-08-15 12:50 we7u
+
+ * configure.ac, scripts/BUILDRPMS, scripts/LSB-BUILD,
+ scripts/do_xastir_release_dev, scripts/do_xastir_release_stable:
+ Updating version numbers for upcoming stable release.
+
+2008-08-15 12:41 we7u
+
+ * configure.ac: Checking for curl/curl.h include file in the
+ libcurl test to make sure we can actually compile with it. Also
+ only check for wget if the libcurl tests fail.
+
+2008-08-14 21:39 we7u
+
+ * configure.ac: Adding a "--without-libcurl" option to configure.
+
+2008-08-14 21:36 we7u
+
+ * acinclude.m4: Slight reformatting of help text (added spaces).
+
+2008-08-12 12:16 we7u
+
+ * src/db.c: Changing a tab to a newline at the end of Tactical Call
+ in Station Info box. This prepares us for longer tactical calls.
+
+2008-08-05 20:03 gstueve
+
+ * src/map_geo.c: Found one more place to release ExceptionInfo for
+ ImageMagick, hopefully last needed to minimize unbalanced memory
+ usage in maps.
+
+2008-08-04 07:27 we7u
+
+ * xastir-min.spec.in, xastir.spec.in, scripts/BUILDRPMS: Getting
+ rid of include/Xm/Xm.h requirement in RPM build spec files.
+ Uncommenting a few print statements in the BUILDRPMS script that
+ were commented out by mistake.
+
+2008-08-03 10:26 we7u
+
+ * xastir-min.spec.in, xastir.spec.in: Updating to new path for
+ Motif include files.
+
+2008-08-03 09:18 we7u
+
+ * scripts/BUILDRPMS: Preparing for creation of SuSE-11.0 RPM's.
+
+2008-08-01 19:14 we7u
+
+ * src/db.c: Adding debug_level filtering to the TACTICAL code.
+
+2008-08-01 07:55 we7u
+
+ * ChangeLog: Updating ChangeLog before doing -dev release.
+
+2008-08-01 05:42 gstueve
+
+ * src/: map_geo.c, map_WMS.c, map_tiger.c: Make sure that error
+ returns are covered by ImageMagick release code.
+
+2008-07-31 23:21 gstueve
+
+ * src/map_gdal.c: Give GDAL a chance to release data from
+ GDALAllRegister at end of run.
+
+2008-07-31 20:24 gstueve
+
+ * src/map_WMS.c: Make sure to deal with cleaning up ExceptionInfo
+ when finished with map.
+
+2008-07-31 20:20 gstueve
+
+ * src/map_tiger.c: Make sure to cleanup allocated space before
+ returning to caller. ImageMagick exceptionInfo needed to be
+ destroyed when finished.
+
+2008-07-31 17:09 we7u
+
+ * src/: main.c, xa_config.c: Reverting to "fixed" font as the
+ default for the SYSTEM and STATION fonts.
+
+2008-07-30 08:24 we7u
+
+ * src/: database.h, db.c, util.c: More Tactical Call changes:
+ Assignments before a station shows up work. Clearing an
+ assignment causes the string to be freed and the pointer nulled.
+ Max tactical call length is now 57.
+
+2008-07-28 02:10 we7u
+
+ * src/db.c: Cleaning up the input parameters for one of the new
+ tactical call helper routines. Leading/trailing spaces on
+ callsign or tac-callsign affect the results little now.
+ Lower-case callsigns are converted to upper case now. One minor
+ annoyance: Blanking out callsigns using messages to TACTICAL
+ results in this being displayed in the station chooser when there
+ are more than one station under the mouse: "()". The proper
+ display should be the callsign in that case, so perhaps spaces
+ are still getting saved in the tactical callsign slot -or- the
+ tactical callsign string isn't getting free'd and the pointer
+ NULLed out (the latter is most likely).
+
+2008-07-28 01:37 we7u
+
+ * src/: db.c, util.c, util.h: The beginnings of being able to share
+ Tactical Call data with others over the air. This code works,
+ decoding messages sent to "TACTICAL" which are in one of these
+ four formats: My Home WE7U-3=My Home WE7U-3=My
+ Home;WE7U-12=Curt's Jeep;WE7U-15=I Don't Know
+ WE7U-3=;WE7U-12=;WE7U-15= In the first case it'll assign "My
+ Home" as the tactical callsign for the station that sent the
+ message. In the last case it'll remove tactical callsigns for
+ the listed stations. For testing remember that you can't send a
+ new message to TACTICAL until the previous message has either
+ timed-out or been cancelled.
+
+2008-07-18 08:26 gstueve
+
+ * scripts/get-NWSdata: Update to current Marine Zone. There are
+ changes due in September for a few of the zone files. Need to
+ watch for implementation date.
+
+2008-07-11 15:03 tvrusso
+
+ * acinclude.m4: Fix spelling error in AC_SEARCH_LIBS line for
+ Magick/MagickCore. This is mostly irrelevant, because LIBS
+ already has the right stuff in it if Magick-config --libs isn't
+ lying, and for most users this test will be a no-op.
+
+2008-07-10 08:46 chicoreus
+
+ * src/db_gis.c: Issue: 2015173 Missing #ifdef for MySQL causes
+ xastir to segfault when built with only --with-postgis. Found by
+ Jeffrey Johnson.
+
+2008-07-07 15:26 tvrusso
+
+ * src/maps.c: Fix map metadata for upper left corner.
+
+ Previously, the code was using the same coordinate pair to
+ compute the upper left and lower right corner strings. For some
+ reason, this ultimately made somewhat correct labels for UTM, but
+ completely wrong labels for Lat/Lon.
+
+ Since this simple change makes the code produce correct labels
+ for all coordinate systems, and the other shouldn't have worked
+ for any, I feel safe committing it. But I would have liked to
+ understand why it worked at all for UTM.
+
+2008-07-07 09:53 we7u
+
+ * ChangeLog: [no log message]
+
+2008-07-03 07:55 gstueve
+
+ * src/alert.c: Increase size of titles for alerts to allow for
+ large area alerts to be processed w/o loss of compressed info.
+
+2008-07-03 06:12 we7u
+
+ * src/db.c: If text on black background style selected, draw a
+ black rectangle in that corner of the map first so that the scale
+ lines show up well.
+
+2008-07-02 17:12 gstueve
+
+ * AUTHORS, src/main.h: Update current callsign for K4INT.
+
+2008-07-02 12:06 gstueve
+
+ * src/map_WMS.c: Remove extra fclose(f) of already closed file.
+ Keep everyone happy.
+
+2008-07-02 11:03 we7u
+
+ * src/db.c: Decode DAO patch by Tapio Sokura, OH2KKU. This doesn't
+ do anything with any datum transmitted, but does give us the
+ extra precision sent via the DAO extension. We still need to
+ change the white precision rectangle for the station on our map
+ to make it smaller (not included in this change).
+
+2008-07-02 06:54 we7u
+
+ * src/db.c: Feature request 756236: Have Range Scale and Ruler
+ text at bottom of map screen follow the same text style selection
+ as the station text, to make them easier to read.
+
+2008-07-01 20:04 we7u
+
+ * src/: bulletin_gui.c, db.c, draw_symbols.c, geocoder_gui.c,
+ interface_gui.c, list_gui.c, locate_gui.c, location_gui.c,
+ main.c, map_geo.c, maps.c, messages_gui.c, objects.c,
+ popup_gui.c, track_gui.c, view_message_gui.c, wx_gui.c, xastir.h:
+ The remaining major updates to allow changing the "system" or
+ "menu" font throughout the applicaton.
+
+2008-06-30 18:47 gstueve
+
+ * scripts/get-gnis: Remove extra path separator.
+
+2008-06-30 16:40 we7u
+
+ * src/: draw_symbols.c, main.c, maps.c, popup_gui.c, xa_config.c,
+ xastir.h: Patches to implement a GUI interface for changing
+ fonts, plus added error-checking to some of the font code.
+
+2008-06-30 16:39 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: The first of two
+ commits adding a GUI interface for changing system/
+ station/atv_id fonts.
+
+2008-06-30 07:02 gstueve
+
+ * scripts/get-gnis: Update path for file from USGS and adjust
+ suffix for current file layout.
+
+2008-06-27 13:10 we7u
+
+ * src/main.c: More menus converted to allow using user-specified
+ fonts.
+
+2008-06-27 12:48 we7u
+
+ * src/: main.c, popup_gui.c, xa_config.c, xastir.h: Adding the
+ capability for users to specify the fonts used for the system
+ fonts, station fonts (on map screen), and the ATV_ID font.
+ Currently the users will have to edit the fonts in xastir.cnf,
+ but later a GUI access method for editing can be added.
+
+2008-06-27 12:45 we7u
+
+ * src/maps.c: Fixing the initialization of arrays for map labels.
+
+2008-06-27 06:41 we7u
+
+ * configure.ac, src/main.c, src/track_gui.c: Adding path tests for
+ "mv", "sed", and "xfontsel", plus the correct bits of code in the
+ .c files to use those paths.
+
+2008-06-26 12:10 we7u
+
+ * src/main.c: Specifying more of the font characteristics for the
+ font used when USE_LARGE_STATION_FONT is defined.
+
+2008-06-26 07:41 we7u
+
+ * src/db.c: A fix for the Citizen's Weather filter to get rid of
+ the new "DW" prefixed stations, plus more strict filtering so
+ that we don't also get rid of Uruguay and Phillipines weather
+ stations with this same filter.
+
+2008-06-25 16:30 we7u
+
+ * src/main.c: Fixing the system fonts so that they work on more
+ systems.
+
+2008-06-25 06:41 we7u
+
+ * scripts/toporama250k.pl: Updated the instructions for running the
+ script plus got rid of DOS line-end characters that had somehow
+ crept in. Those line-end characters prevented the Perl
+ interpreter from running on Linux.
+
+2008-06-25 06:39 we7u
+
+ * scripts/toporama50k.pl: Updated the instructions for running the
+ script.
+
+2008-06-25 06:38 we7u
+
+ * help/help-English.dat: Changed the name of the fcc-get script to
+ get-fcc-rac.pl
+
+2008-06-25 06:37 we7u
+
+ * src/db.c: Station Info: Special-case check for objects sent by
+ "WINLINK". We keep the object name as the "origin" in this case
+ instead of "WINLINK". This solves the "FCC" instead of "RAC"
+ button problem for objects with Canadian callsigns, allowing us
+ to look of RAC licensing information.
+
+2008-06-24 08:52 we7u
+
+ * README.Getting-Started, README.MAPS: Updating the name of the
+ get-fcc-rac.pl script in the docs.
+
+2008-06-24 08:48 we7u
+
+ * scripts/: Makefile.am, fcc-get, fcc-get.pl, get-fcc-rac.pl:
+ Combined fcc-get and fcc-get.pl into one script called
+ get-fcc-rac.pl
+
+2008-06-23 15:42 we7u
+
+ * README: Adding the SuSE-11.0 Ham Radio repository URL.
+
+2008-06-13 06:43 gstueve
+
+ * scripts/get-NWSdata: Remove the bashism to keep people happy.
+
+2008-06-13 00:37 gstueve
+
+ * config/nwsz_ddmmyy.dbfawk: Actually get the signature template
+ right for Watches.
+
+2008-06-13 00:25 gstueve
+
+ * config/: nwsmzddmmyy.dbfawk, nwsz_ddmmyy.dbfawk: Actually get the
+ template to match the available dataset.
+
+2008-06-12 20:27 gstueve
+
+ * scripts/get-NWSdata: Missed that one of the files was in a
+ different directory.
+
+2008-06-12 18:49 gstueve
+
+ * scripts/get-NWSdata: Introduced bashism to reduce size & improve
+ consistency for all files.
+
+2008-06-12 12:30 gstueve
+
+ * config/Makefile.am, config/nwsz1ddmmyy.dbfawk,
+ config/nwsz_ddmmyy.dbfawk, scripts/get-NWSdata: Adjust script and
+ dbfawk for current set of files from NWS. There are newer sets
+ of files for upcoming dates.
+
+2008-06-11 06:39 gstueve
+
+ * src/x_spider.c: Reduce side effects of free memory by clearing
+ pointer after deallocation.
+
+2008-06-09 12:28 we7u
+
+ * scripts/: LSB-BUILD, LSB-BUILD-ALL, LSB-BUILD-GRAPHICSMAGICK:
+ Committing latest changes for LSB build. Am not done yet getting
+ LSB to build properly on OpenSUSE-10.3, but this is a good start.
+
+2008-06-09 12:25 we7u
+
+ * ChangeLog: Keeping it up to date with CVS commits.
+
+2008-06-09 12:23 we7u
+
+ * scripts/do_xastir_release_stable: Changed SF upload process to
+ match what they currently allow.
+
+2008-06-09 12:23 we7u
+
+ * scripts/do_xastir_release_dev: Change SF upload process to match
+ what they currently allow.
+
+2008-06-04 04:23 gstueve
+
+ * src/db.c: Allow Objects that have space in name to work with
+ Tactical Call Sign addition.
+
+2008-05-30 08:32 gstueve
+
+ * src/db.c: Add tactical call sign to station pick list when
+ multiple stations under cursor.
+
+2008-05-29 10:15 we7u
+
+ * FAQ, README.Getting-Started: Updating some of the PATH wording.
+
+2008-05-27 12:04 gstueve
+
+ * src/messages.c: Start fixing elements to allow Group & Bulletin
+ messages to go unacknowledged.
+
+2008-05-21 09:08 tvrusso
+
+ * src/util.c: Fix makeMultiline (an unused function) so that it
+ produces offsets in the same sense that xastir decodes them ---
+ i.e. that positive longitude offsets are west of the reference
+ point.
+
+2008-05-09 11:20 gstueve
+
+ * src/interface.c: Make sure not to add break character if no
+ altitude to be reported.
+
+2008-05-09 11:18 gstueve
+
+ * src/: util.c, util.h: Make sure course and speed are treated as
+ non-negative numbers only.
+
+2008-05-06 04:05 gstueve
+
+ * scripts/fcc-get.pl: Remove extra CR at end of each line and deal
+ with full list only once.
+
+2008-05-05 13:00 gstueve
+
+ * scripts/: Makefile.am, fcc-get, fcc-get.pl: Adjust fcc file
+ processing to deal with vanity call update.
+
+2008-05-02 09:58 tvrusso
+
+ * acinclude.m4: Change "AC_CHECK_LIB" to "AC_SEARCH_LIBS" for
+ ImageMagick.
+
+ A recent update to ImageMagick stuffs the "WriteImage" function
+ into libMagickCore instead of libMagick, and the older probe was
+ missing it.
+
+ With this change, I see that WriteImage gets found without adding
+ anything to LIBS, because "Magick-config" already stuffed the
+ right thing into LIBS.
+
+2008-04-13 22:31 we7u
+
+ * src/util.c: Fixing a bug found with latest wget: --timestamping
+ and -O options can't be used together. Getting rid of the
+ timestamping option which we can live without.
+
+2008-04-13 21:31 we7u
+
+ * src/util.c: Updating wget and libcurl fetches to specify "Xastir"
+ as the user-agent string in the request. This is to support the
+ new restrictions that findu.com has implemented.
+
+2008-03-20 21:11 chicoreus
+
+ * src/: db.c, interface_gui.c, main.c: Minor cleanup of comments
+ and un-needed code from testing problems with database
+ connections.
+
+2008-03-20 21:00 chicoreus
+
+ * src/: db.c, db_gis.c, db_gis.h, interface.c, interface_gui.c,
+ main.c: Identified and fixed problem underlying stability of
+ multiple database connections (space for connection structures
+ was incorrectly allocated so that writing an error message into
+ one connection overwrote memory used by another connection).
+ Fixed additional problems related to connection failures and
+ added more resilience to database connection problems.
+
+2008-03-18 19:10 chicoreus
+
+ * src/: db.c, db_gis.c, db_gis.h, interface.c, interface_gui.c,
+ main.c, main.h: Overhaul of the way sql database connections are
+ handled, reducing the complexity by eliminating the
+ ConnectionList struct, and creating an array of Connections, one
+ for each interface. More than one database connection can now be
+ run at once, though there is still an issue with pointers or
+ memory handling somewhere and instabilites can be produced by
+ stopping and starting database connections.
+
+ Moved all the db_gis related debug_level tests from 1 to 4096.
+
+2008-03-11 20:27 tvrusso
+
+ * acinclude.m4: Fix a fairly dumb thing in the probe for Berkeley
+ DB --- it was always resetting the result (BDB_LIB_FOUND) to
+ "-ldb" even if the actual library found was something else. This
+ variable was used only to report to the user what library was
+ found, never as the actual "-l" flag. This could have led to
+ confusion, but not improper operation.
+
+2008-03-06 12:47 we7u
+
+ * scripts/BUILDRPMS: Updating to SuSE-10.3 for generation of RPM's.
+
+2008-03-03 20:00 tvrusso
+
+ * README.MAPS: Add link to FAA digital data products web site. You
+ can purchase FAA sectionals in GeoTIFF format there.
+
+2008-02-29 08:54 chicoreus
+
+ * src/: database.h, db.c, db_gis.c, interface_gui.c: Added trails
+ to db_gis code. Multiple points from one station retrieved from a
+ database query are added as trailpoints. Existing stations heard
+ from other sources and retrieved from a database query aren't
+ duplicated as DataRows, but have appropriate trail points added
+ (if the existing position is older than the database data, the
+ existing position becomes as trailpoint; if the database data is
+ older, it gets added as trailpoints).
+
+ Added timeformat to add_simple_station, as Postgresql and MySQL
+ timestamps don't both include the local timezone "%z" in the
+ current simple station query formats.
+
+ Added APRS_WXn character constants as a workaround, since
+ AprsTypes and Record Type character constants are used
+ inconsistently in DataRow.record_type, and AprsTypes without
+ character constants don't write cleanly into MySQL or Postgresql
+ database records.
+
+ Added and commented out lines to start database connections from
+ interfaces Left commented out as multiple open database
+ connections are still unstable and segfault.
+
+2008-02-27 20:02 gstueve
+
+ * scripts/fcc-get: FCC moved the database again. Look for it in new
+ place.
+
+2008-02-21 20:57 chicoreus
+
+ * src/: database.h, db.c, db_gis.c, interface.c: Improvements to
+ the tollerance of the db_gis code to problems with connections to
+ databases and improved reporting of problems in making
+ connections.
+
+ Added code to add tracks for stations retrieved from the
+ database. Still needs work, as the existing db.c code for adding
+ stations and points to the tracks of stations makes different
+ assumptions about the order in which positions are recieved than
+ the order of records queried in db_gis.c.
+
+2008-02-21 20:51 chicoreus
+
+ * scripts/: db_gis_mysql.sql, db_gis_postgis.sql: Adding some
+ indexes to speed up retrieval of station records. Adding a view
+ that could be used with mapserver to return icon files for each
+ station.
+
+2008-02-16 08:15 we7u
+
+ * src/main.c: Switching the Garmin RINO processing to use
+ uncompressed packets for now as there is a problem with either
+ this section of code or the Compressed encoding code for
+ particular positions. Change the ABOUT message to include
+ additional copyright information.
+
+2008-02-07 18:47 chicoreus
+
+ * src/: main.c, main.h, maps.c, maps.h, xa_config.c: Adding two new
+ KML export features:
+
+ 1) KML Snapshots - on a regular basis (using the same timing as
+ PNG snapshots), write all currently known stations to a kml file.
+
+ 2) KML file to accompany PNG snapshots. After converting
+ snapshot.png to snapshot.jpg, the accompanying snapshot.kml file
+ can be used to layer the snapshot.jpg image on the landscape in a
+ kml application.
+
+ The KML produced is valid and appears to work, but hasn't been
+ extensively tested.
+
+ This (along with the allready committed export a single station
+ track to kml feeature) should complete the feature request for
+ KML export:
+ http://sourceforge.net/tracker/index.php?func=detail&aid=1863377&group_id=45562&atid=443274
+
+2008-02-07 18:35 chicoreus
+
+ * help/help-English.dat: Added help text describing KML export and
+ snapshot features.
+
+2008-02-07 18:33 chicoreus
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Adding menu item
+ for regular snapshots of all heard stations to a kml file,
+ analogus to png snapshots.
+
+2008-02-07 18:29 chicoreus
+
+ * scripts/: kml_snapshot_feed.kml, kml_snapshot_to_web.sh: An
+ example kml file and a shell script to allow png snapshots with
+ their accompanying snapshot.kml file to be used as a regularly
+ updated kml feed on a webserver (allowing the current snapshot
+ from xastir to be draped over the landscape in a kml application
+ remotely subscribing to the feed.)
+
+2008-01-29 19:08 chicoreus
+
+ * help/help-English.dat: Correcting a spelling error (found by
+ Curt).
+
+ Placing more references to button titles in quotes to make the
+ description of the station info dialog more consistent.
+
+ Clarifying (hopefully) some of the description of saving tracks
+ from the station info dialog.
+
+2008-01-25 21:45 chicoreus
+
+ * src/: db.c, util.c, util.h: Added a utility function to return a
+ date/time in w3c timestamp format, required for valid timestamps
+ in kml files.
+
+ Rearranged the log station to kml code, and added timestamped
+ placemarks for each location of a station in a track. This
+ produces kml output that validates, and should behave like the
+ "Shroeder" whale shark example file (moving a station location
+ along its track as a time slider control is moved in Google
+ Earth). This has not yet been tested to see if the behavior is
+ as desired.
+
+2008-01-24 22:21 chicoreus
+
+ * INSTALL, config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, help/help-English.dat: Localization
+ for Station->Export All->Export kml menu items.
+
+ User documentation of KML export.
+
+ User documentation for spatial database support.
+
+ Added some fault recovery comments to spatial database
+ configuration section of INSTALL.
+
+2008-01-24 22:18 chicoreus
+
+ * src/: database.h, db.c, main.c: Adding Station->Export all menu,
+ with option to export all station records to a single kml file.
+
+2008-01-24 14:36 chicoreus
+
+ * src/: interface_gui.c, main.c, objects.c: Fix for bug 1863228.
+ Lesstif doesn't yet fully support combo boxes, which are used in
+ 4 places in Xastir (for user configurable predefined objects file
+ in defaults dialog, cad object line type in the cad object
+ details dialog, and twice in the interface properties dialog when
+ defining a sql database interface.
+
+ An alternate lesstif menu that mimics a combo box control
+ (modified from xpdf's XPDFViewer.cc), is applied in three of
+ these four cases (the fourth currently only has a single option,
+ and might not be the best control for the situation, picking
+ database schema type[s]).
+
+ This has been tested on lesstif 0.94.4 and openmotif 2.3.0.
+
+2008-01-23 00:23 we7u
+
+ * src/interface.c: Added "volatile" keyword to a couple of
+ variables to assure they don't get overwritten by longjmp.
+
+2008-01-22 23:34 we7u
+
+ * src/track_gui.c: Converting from mucking with pointers to pass to
+ variables to a thread, to passing a pointer to a struct instead.
+ This last method should avoid architecture-dependent problems in
+ the download findu trail processing.
+
+2008-01-22 23:08 we7u
+
+ * src/track_gui.c: Added a comment regarding a section of code
+ which does type-punning and may be architecture-dependent.
+
+2008-01-22 23:07 we7u
+
+ * src/messages.c: Commented out "altgroup" section of conditional
+ which always equates to true ('cuz it's an address).
+
+2008-01-22 23:05 we7u
+
+ * src/interface.c: Added a couple of comments.
+
+2008-01-22 22:00 we7u
+
+ * src/map_cache.c: Reformatting debug statement so that it won't
+ generate compiler warnings.
+
+2008-01-22 20:49 we7u
+
+ * src/wx.c: Fixing a buffer overrun. Found via a compiler warning
+ on OpenSuSE-10.3
+
+2008-01-22 20:48 we7u
+
+ * src/map_geo.c: Reformatting a debug statement so it won't cause
+ compiler warnings.
+
+2008-01-22 20:47 we7u
+
+ * src/map_gdal.c: Getting rid of a conditional that always
+ evaluates as true: The address of "label".
+
+2008-01-22 20:46 we7u
+
+ * src/map_dos.c: Fixing an array overflow condition that has
+ existed for a LONG time. Found via a compiler warning on
+ OpenSuSE-10.3
+
+2008-01-22 20:45 we7u
+
+ * src/map_WMS.c: Changing debug statement format so it won't cause
+ a compiler warning to be issued.
+
+2008-01-22 20:43 we7u
+
+ * INSTALL: Adding a note about RINO's: That Xastir cannot cause a
+ poll of the remote RINO units over the air.
+
+2008-01-18 18:49 chicoreus
+
+ * src/db_gis.c: More cleanup of db_gis code.
+
+2008-01-18 18:48 chicoreus
+
+ * src/main.c: Adding test in UpdateTime to avoid opening the same
+ database interface twice during startup if it is marked to both
+ activate on startup and load stations on startup.
+
+2008-01-17 19:21 chicoreus
+
+ * src/: db.c, db_gis.c, main.c: Minor stability improvements to
+ db_gis code. Adding some sanity checks for null database
+ connections when running queries to reduce segfaults.
+
+ Begining cleanup of the db_gis code. Removing some leftover
+ unused variables and code. Explicit type casting of some
+ pointers in function calls to suppress compiler warnings.
+
+2008-01-16 20:33 chicoreus
+
+ * src/: database.h, db.c, db_gis.c, main.c, objects.c: First pass
+ at exporting station tracks as kml files. On clicking store
+ track on the station information dialog, both an xastir format
+ file and a kml file for the selected station will be written to
+ ~/.xastir/tracklogs
+
+ Added more comments on how database schema version and series
+ compatability should work.
+
+ Fixed (superficially) a bug where station data would be written
+ to a non-open database connection causing a segfault. Connection
+ handling in db_gis is fragile and needs review.
+
+2008-01-16 11:38 we7u
+
+ * scripts/: BUILDRPMS, LSB-BUILD: Updating to 1.9.3 release number.
+
+2008-01-16 11:33 we7u
+
+ * AUTHORS, ChangeLog, DEBUG_LEVELS, FAQ, INSTALL, LICENSE,
+ Makefile.am, NEWS, README, README.CVS, README.Contributing,
+ README.Getting-Started, README.MAPS, README.win32,
+ REGRESSION_TESTS, UPGRADE, acinclude.m4, bootstrap.sh,
+ changes.txt, configure.ac, install-xastir, update-xastir,
+ xastir.1, Davis/Makefile.am, Davis/README, Davis/bootstrap.sh,
+ Davis/configure.ac, Davis/src/Makefile.am, Davis/src/db2APRS.c,
+ Davis/src/defs.h, LaCrosse/Makefile.am, LaCrosse/README,
+ LaCrosse/bootstrap.sh, LaCrosse/configure.ac,
+ LaCrosse/src/Makefile.am, LaCrosse/src/defs.h,
+ LaCrosse/src/open2300db2APRS.c, callpass/Makefile.am,
+ callpass/callpass.c, config/24kgrid.dbfawk, config/Makefile.am,
+ config/gps_wpt.dbfawk, config/language-Dutch.sys,
+ config/language-English.sys, config/language-French.sys,
+ config/language-German.sys, config/language-Italian.sys,
+ config/language-Portuguese.sys, config/language-Spanish.sys,
+ config/nwsc_ddmmyy.dbfawk, config/nwsmzddmmyy.dbfawk,
+ config/nwsmzoddmmyy.dbfawk, config/nwsozddmmyy.dbfawk,
+ config/nwsw_ddmmyy.dbfawk, config/nwsz_ddmmyy.dbfawk,
+ config/nwszoddmmyy.dbfawk, config/predefined_EVENT.sys,
+ config/predefined_SAR.sys, config/tgr2shp.dbfawk,
+ config/tgr2shppoly.dbfawk, config/tgr2shppoly_2006.dbfawk,
+ config/tgrcty.dbfawk, config/tgrkgl.dbfawk, config/tgrlk.dbfawk,
+ config/tgrlpt.dbfawk, config/tgrlpy.dbfawk,
+ config/tgrplc00.dbfawk, config/tgrwat.dbfawk,
+ config/tnc-startup.aea, config/tnc-startup.d700,
+ config/tnc-startup.kam, config/tnc-startup.kpc2,
+ config/tnc-startup.kpc3, config/tnc-startup.paccomm,
+ config/tnc-startup.pico, config/tnc-startup.sys,
+ config/tnc-startup.thd7, config/tnc-startup.tnc2,
+ config/tnc-startup.tnc2-ui, config/tnc-stop.d700,
+ config/tnc-stop.sys, config/tnc-stop.thd7,
+ config/tnc-stop.tnc2-ui, help/Makefile.am, help/help-Dutch.dat,
+ help/help-English.dat, help/help-French.dat,
+ help/help-German.dat, help/help-Italian.dat,
+ help/help-Portuguese.dat, help/help-Spanish.dat, m4/Makefile.am,
+ scripts/LSB-BUILD, scripts/LSB-BUILD-ALL, scripts/LSB-BUILD-CURL,
+ scripts/LSB-BUILD-DB, scripts/LSB-BUILD-GDAL,
+ scripts/LSB-BUILD-GRAPHICSMAGICK, scripts/LSB-BUILD-JASPER,
+ scripts/LSB-BUILD-JPEG, scripts/LSB-BUILD-LESSTIF,
+ scripts/LSB-BUILD-PCRE, scripts/LSB-BUILD-PNG,
+ scripts/LSB-BUILD-ZLIB, scripts/Makefile.am, scripts/PigLatin.pl,
+ scripts/Xastir_tigerpoly.py, scripts/example_objects.log,
+ scripts/fcc-get, scripts/get-NWSdata, scripts/get-gnis,
+ scripts/get-maptools.sh, scripts/get_shapelib.sh,
+ scripts/toporama250k.pl, scripts/toporama50k.pl,
+ scripts/xastir-fixcfg.sh, scripts/xastir-migrate.sh,
+ src/Makefile.am, src/alert.c, src/alert.h, src/awk.c, src/awk.h,
+ src/bulletin_gui.c, src/bulletin_gui.h, src/color.c, src/color.h,
+ src/database.h, src/datum.c, src/datum.h, src/db.c, src/db_gis.c,
+ src/db_gis.h, src/dbfawk.c, src/dbfawk.h, src/draw_symbols.c,
+ src/draw_symbols.h, src/fcc_data.c, src/fcc_data.h,
+ src/festival.c, src/festival.h, src/geo-client.c, src/geo-find.c,
+ src/geo.h, src/geocoder_gui.c, src/gps.c, src/gps.h,
+ src/hashtable.c, src/hashtable.h, src/hashtable_itr.c,
+ src/hashtable_itr.h, src/hashtable_private.h, src/hostname.c,
+ src/hostname.h, src/igate.c, src/igate.h, src/interface.c,
+ src/interface.h, src/interface_gui.c, src/io-common.c,
+ src/io-mmap.c, src/io.h, src/lang.c, src/lang.h,
+ src/leak_detection.h, src/list_gui.c, src/list_gui.h,
+ src/locate_gui.c, src/location.c, src/location_gui.c,
+ src/macspeech.c, src/main.c, src/main.h, src/map_WMS.c,
+ src/map_cache.c, src/map_cache.h, src/map_dos.c, src/map_gdal.c,
+ src/map_geo.c, src/map_gnis.c, src/map_pdb.c, src/map_shp.c,
+ src/map_tif.c, src/map_tiger.c, src/maps.c, src/maps.h,
+ src/messages.c, src/messages.h, src/messages_gui.c,
+ src/objects.c, src/objects.h, src/popup.h, src/popup_gui.c,
+ src/rac_data.c, src/rac_data.h, src/rotated.c, src/rotated.h,
+ src/rpl_malloc.c, src/rpl_malloc.h, src/shp_hash.c,
+ src/shp_hash.h, src/snprintf.c, src/snprintf.h, src/sound.c,
+ src/symbols.h, src/testawk.c, src/track_gui.c, src/track_gui.h,
+ src/util.c, src/util.h, src/view_message_gui.c, src/wx.c,
+ src/wx.h, src/wx_gui.c, src/x_spider.c, src/x_spider.h,
+ src/xa_config.c, src/xa_config.h, src/xastir.h,
+ src/xastir_udp_client.c, src/rtree/Makefile.am, src/rtree/card.c,
+ src/rtree/card.h, src/rtree/gammavol.c, src/rtree/index.c,
+ src/rtree/index.h, src/rtree/node.c, src/rtree/rect.c,
+ src/rtree/sphvol.c, src/rtree/split_l.c, src/rtree/split_l.h,
+ src/rtree/split_q.c, src/rtree/split_q.h,
+ src/shapelib/Makefile.am, src/shapelib/contrib/Makefile.am,
+ symbols/Makefile.am, symbols/symbols.dat: Updating the copyright
+ notices for 2008.
+
+2008-01-16 10:32 we7u
+
+ * configure.ac: Preparing for devel release, bumping revision
+ number.
+
+2008-01-10 07:35 chicoreus
+
+ * src/: interface.c, main.c, objects.c: Fixing bug where
+ objects/items created by the user are not displayed until Xastir
+ is restarted.
+
+ Adding more debugging information when loading predefined objects
+ from a file.
+
+2008-01-09 21:06 chicoreus
+
+ * src/: db.c, db_gis.c: Fix from Curt for some compile warnings in
+ xastirWKTPointToLatitude().
+
+ Fix to incorrect data being written to MySQL table
+ simpleStationSpatial in the origin and node_path fields.
+
+ Note: When selecting data from MySQL simpleStationSpatial, use
+ the AsText() function on position. For example, to retrieve the
+ 10 most recently heard stations: select station, symbol, overlay,
+ aprstype, AsText(position), transmit_time, origin, record_type,
+ node_path from simpleStationSpatial order by transmit_time desc
+ limit 10 ;
+
+2008-01-08 17:22 chicoreus
+
+ * src/interface.c: Possible bug fix for the can't have two sql
+ database interfaces open at the same time issue.
+
+ Pointers around Connections need review.
+
+2008-01-08 07:00 chicoreus
+
+ * src/: db_gis.c, db_gis.h, interface.c, main.c: db_gis.c
+ closeConnection now linked to stop button on interfaces.
+
+ SQL database state (open,closed,error[on connect only]) state
+ shown on interface list.
+
+2008-01-07 20:35 chicoreus
+
+ * INSTALL, scripts/db_gis_mysql.sql, scripts/db_gis_postgis.sql,
+ src/db_gis.c, src/interface_gui.c, src/objects.c: Added some
+ installation instructions for spatial database support.
+
+ Added a workaround for lesstif not having full implementation of
+ combo boxes (borrowed from xpdf's XPDFViewer.cc) to the dbms
+ selection control on the spatial database interface dialog. Fix
+ needs to be propagated to several other places.
+
+ Fixes to sql scripts to build mysql and postgis database tables.
+
+2008-01-01 14:58 chicoreus
+
+ * src/: database.h, db.c, db_gis.c, db_gis.h, interface.c,
+ interface.h, interface_gui.c, main.c, main.h, xa_config.c:
+ Significant updates to db_gis code, supporting storage of station
+ data to both MySQL and postgis enabled Postgresql databases.
+ Stations heard in Xastir can have the core station information
+ logged to either a Postgres or MySQL database (Bug: currently
+ both aren't working at the same time), and then retrieved in a
+ subsequent Xastir session (or by a different Xastir instance, or
+ by another GIS application (such as QGIS over a postgis database
+ populated from Xastir)).
+
+ Tested with MySQL 5.0.32, may not work with MySQL 4.1. Tested
+ with Postgres 8.1.9
+
+2008-01-01 14:50 chicoreus
+
+ * scripts/: db_gis_mysql.sql, db_gis_postgis.sql: Adding sql
+ scripts to create tables for persistent storage of basic station
+ data. One script for mysql, another for postgis enabled
+ postgresql. Currently only supports a single simple table with
+ the minimun station information.
+
+2007-12-18 12:56 tvrusso
+
+ * configure.ac: Fix improper probing of curl library when LSB is
+ not being used.
+
+ AC_CHECK_LIB can have two or three arguments. With two arguments
+ it tests for the presence of a function named in the second
+ argument in the library named by the first argument, and if found
+ defines HAVE_LIBxxxxx and adds -lxxxxx to LIBS.
+
+ In the three-argument case, it does the probe the same way, but
+ instead of the default "define HAVE_LIBxxxxx and add -lxxxxx to
+ LIBS" it does what it's told in the third argument. That means
+ if you want to rely on HAVE_LIBxxxxx and LIBS="${LIBS} -lxxxxx"
+ then you have to do it yourself in the third argument.
+
+ The AC_CHECK_LIB for curl was only doing the extra thing, which
+ was to set "use_curl" to "yes".
+
+ I recently discovered this by trying to build and use xastir on a
+ freshly installed system that had libcurl but no wget (most of my
+ other systems have both). The bug in the use of AC_CHECK_LIB
+ meant that libcurl was found, but never linked in nor was
+ HAVE_LIBCURL ever set in config.h.
+
+ With this fix, curl is now both properly detected *and* the
+ detection properly communicated to the code.
+
+2007-12-13 22:23 tvrusso
+
+ * config/tgr2shp.dbfawk: Add "P" feature class to handle
+ "Provisional" road data in TIGER/Line shapefiles. According to
+ the TIGER/Line Technical Documentation for feature class "P"
+
+ The U.S. Census Bureau has created a new CFCC type that may
+ appear on
+ street features only. Some streets that normally would be
+ classified as
+ "A" class features may be coded with a "P" instead of the "A"
+ to indicate
+ that the feature is a a "provisional" feature. Provisional
+ features are
+ those streets that were added from reference sources or other
+ programs
+ in preparation for Census 2000, but were not field verified by
+ census staff
+ during field operations or through the use of aerial
+ photography or imagery.
+ As these featues are verified in futuer operations the
+ provisional flag
+ will be removed for subsequent TIGER/Line releases. The
+ numeric portion
+ of the CFCC still classifies the street as if an "A" were
+ preceding it.
+
+ So this just involves changing the matching pattern from
+ CFCC=A... to CFCC=[AP]... in all the feature-class A rules.
+
+2007-12-05 08:40 tvrusso
+
+ * README.MAPS: Add more text to the section on Geocommuity's DRG
+ Data Bundle deals. Turns out that some areas have DRGs produced
+ by some agency other than the USGS, and those agencies don't
+ necessarily produce GeoTiff files with proper metadata. The
+ Tennesee Valley Authority is among those agencies that don't
+ properly include GeoTiff tags for projection and datum. This
+ renders DRG data bundles for states with portions of their area
+ covered by the TVA partially defective --- special preprocessing
+ is necessary to get the files into a state that can be used in
+ Xastir.
+
+2007-11-14 07:05 tvrusso
+
+ * README.MAPS: Add a pointer to a vendor of inexpensive GeoTIFF
+ format DRGs for the US. They're one of the USGS's data partners
+ that is listed elsewhere in the document, but in a different
+ context.
+
+ Thanks to Eric, KZ5ED, for calling it to my attention.
+
+2007-11-07 13:37 tvrusso
+
+ * src/: main.c, map_WMS.c, map_geo.c, map_tiger.c, maps.c: Work
+ around the fact that ImageMagick's api.h rudely includes their
+ autoconf-generated config.h, which therefore defines the same
+ PACKAGE and VERSION macros that we do.
+
+ In most files, this produces an annoying but harmless warning
+ message about a redefinition. For main.c, however, it cause
+ Magick's PACKAGE name and VERSION to be used in place of our own.
+ That is, our About window will announce that we're ImageMagick
+ version 6.3.x.
+
+ For the files in which it's a harmless warning, I've done an
+ #undef of the two macros to shut up the compiler warnings.
+
+ In main.c, I've created two new char* variables and initialized
+ them to PACKAGE and VERSION before including magick's api.h, and
+ then undef'd them. This preservs the contents of our macros by
+ substituting them in C code right away, then gets rid of them so
+ the warnings are shut up.
+
+ Attempting to do: #define XASTIR_PACKAGE PACKAGE #undef
+ PACKAGE #include <magick/api.h> #undef PACKAGE #define
+ PACKAGE XASTIR_PACKAGE
+
+ doesn't help. All that does is silence the warning. Magick's
+ package name is still used when we try to use the PACKAGE macro
+ later. Macro expansions aren't variable assignments, and the
+ code above does nothing more than define PACKAGE to PACKAGE and
+ thence to "ImageMagick", after briefly allowing api.h to change
+ its meaning without warning.
+
+ Adding an "#undef XASTIR_PACKAGE" after all that is even worse,
+ and results in fatal compilation errors. There's probably some
+ preprocessor game that can be played to kludge this, but saving
+ the string we want to keep somewhere where it's safe from
+ preprocessor meddling seems the better choice.
+
+2007-11-06 09:10 we7u
+
+ * configure.ac, scripts/BUILDRPMS, scripts/LSB-BUILD,
+ scripts/do_xastir_release_dev, scripts/do_xastir_release_stable:
+ Preparing for 1.9.2 stable release.
+
+2007-09-24 19:41 we7u
+
+ * src/track_gui.c: Finished the regex code for converting
+ HTML->Text for downloaded findu.com tracks.
+
+2007-09-22 03:53 we7u
+
+ * src/track_gui.c: Commenting out unused variable.
+
+2007-09-22 03:25 we7u
+
+ * configure.ac: Commenting out the html2text discovery code.
+
+2007-09-22 03:25 we7u
+
+ * configure.ac: Checking in the html2text discovery code in case we
+ may want it in the future.
+
+2007-09-22 03:24 we7u
+
+ * src/track_gui.c: Doing the html2text via sed statements.
+
+2007-09-22 01:29 we7u
+
+ * src/track_gui.c: Converting the downloaded findu.com raw packets
+ from HTML to text. Still need to look for "html2text" and find
+ out it's path in the autoconf scripts in order to integrate this
+ properly.
+
+2007-09-16 18:31 tvrusso
+
+ * src/interface_gui.c: Fix misplaced #endif /* HAVE_DB */ that was
+ breaking the gui for networked AGWPE.
+
+2007-09-04 13:09 we7u
+
+ * src/db.c: Changing the new variable "i" to "ii" to make it easier
+ to search for in the sources, plus getting rid of the declaration
+ for the case where we're not using an SQL database (to get rid of
+ a compiler warning).
+
+2007-08-31 05:20 gstueve
+
+ * src/map_geo.c: Add subroutine to release memory consistently for
+ exit points.
+
+2007-08-28 16:16 we7u
+
+ * scripts/PigLatin.pl: Updated one comment.
+
+2007-08-28 15:32 we7u
+
+ * scripts/PigLatin.pl: Initial commit.
+
+2007-08-24 06:44 gstueve
+
+ * src/igate.c: Push active groups through the gateway between
+ RF<->INet.
+
+2007-08-24 06:42 gstueve
+
+ * src/: messages.c, messages.h: Export group_active for use in
+ igate of group transmission list.
+
+2007-08-22 08:42 gstueve
+
+ * src/alert.c: Make sure to test against initialized data.
+
+2007-08-20 20:10 chicoreus
+
+ * src/db.c, src/db_gis.c, src/db_gis.h, src/interface.c,
+ src/interface_gui.c, src/main.c, symbols/symbols.dat: Cleaning up
+ db_gis code.
+
+ Some cleanup of error messages. Moved some debugging messages
+ into debug_level & 1.
+
+ Altered simpleStation table structure to add three more columns:
+
+ alter table simpleStation add column origin varchar(9) not null
+ default ''; alter table simpleStation add column record_type
+ varchar(1); alter table simpleStation add column node_path
+ varchar(56);
+
+ These seem necessary for recreating DataRow records out of
+ simpleStation database records.
+
+ Added more testing and handling of data that is to be written to
+ database records. Still needs better sanitizing. Tested saving
+ DataRow records derived from internet feeds to MySQL (old), and
+ Postgresql(8)/Postgis records.
+
+2007-08-20 12:22 we7u
+
+ * src/main.c: Adding two casts to (int *) back in. They are
+ required to get rid of compiler warnings with some versions of
+ GCC.
+
+2007-08-17 15:08 gstueve
+
+ * src/: map_WMS.c, map_cache.c, map_geo.c, map_tiger.c: Make sure
+ to free allocated memory after we are done playing with it.
+
+2007-08-16 12:28 gstueve
+
+ * src/main.c: Make sure colors are identified as Pixel not int
+ types.
+
+2007-08-16 12:26 gstueve
+
+ * src/list_gui.c: Make sure SL_scroll is initialized for full
+ operation.
+
+2007-08-16 10:36 gstueve
+
+ * src/map_geo.c: Make sure we return the exception data to free
+ space when done. Don't leave it as unclaimed uggage.
+
+2007-08-16 10:01 gstueve
+
+ * src/list_gui.c: Make sure the station_list displays give back the
+ memory after they are done playing with it. They are not expected
+ to lose it.
+
+2007-08-15 10:57 gstueve
+
+ * src/draw_symbols.c: Pixel values are 'unsigned long' not 'int' on
+ 64 bit machines.
+
+2007-08-15 10:41 gstueve
+
+ * src/: main.c, main.h, xastir.h: Type of colors & trail_colors is
+ Pixel, not int. Especially on 64 bit machines.
+
+2007-08-15 08:44 we7u
+
+ * src/map_cache.c: Backing out this change as it caused this error
+ and Xastir to blow up when a new map image was cached to disk:
+ "glibc detected *** double free or corruption"
+
+2007-08-14 09:41 we7u
+
+ * src/util.c: Adding a minor comment. Thanks to Gerald Stueve for
+ re-examining all this code. He's doing a WONDERFUL job of
+ finding/fixing bugs!
+
+2007-08-14 09:28 we7u
+
+ * src/: db_gis.c, db_gis.h: Adding the RCS ID tag and tweaking the
+ copyright statements to show correct dates and attribution for
+ these two files.
+
+2007-08-13 13:23 gstueve
+
+ * src/main.c: Clear entire block of appshell, not just first
+ pointer space.
+
+2007-08-13 13:22 gstueve
+
+ * src/x_spider.c: No need to have extra layer of callback, go
+ directly to exit.
+
+2007-08-13 12:55 gstueve
+
+ * src/x_spider.c: Allow the subprocesses to cleanup and exit on
+ interrupt.
+
+2007-08-13 12:54 gstueve
+
+ * src/rac_data.c: Make sure we aren't checking against unitialized
+ data.
+
+2007-08-13 09:17 tvrusso
+
+ * README.MAPS:
+ Add the answer to a frequently asked question about TIGER/Line
+ 2006 SE shapefile zip files ("what's the difference between the
+ Polylines and Polygons directory?").
+
+2007-08-11 19:00 chicoreus
+
+ * src/: db_gis.c, db_gis.h: Simple schema insert added for
+ Postgresql/postgis. Tested with Postgresql 8.2 and postgis
+ 1.2.1.
+
+ Simple station records can now be written to MySQL and
+ Postgresql/Postgis databases, but xastir can't yet extract any
+ data back.
+
+2007-08-10 16:15 gstueve
+
+ * src/util.c: Make sure to initialize string before testing fixed
+ offset values. Valgrind identified the dereferences with errors.
+
+2007-08-10 16:11 gstueve
+
+ * src/map_cache.c: Valgrind again. Make sure to release memory
+ after using it.
+
+2007-08-10 16:09 gstueve
+
+ * src/db.c: More valgrind identified errors. Make sure to
+ initialize tested variables.
+
+2007-08-10 15:48 gstueve
+
+ * src/x_spider.c: Add clear_proc_title to clean up environment
+ pointers.
+
+2007-08-10 07:06 gstueve
+
+ * src/x_spider.c: valgrind is our friend. Make sure not to step
+ back too far for line end.
+
+2007-08-09 13:12 gstueve
+
+ * src/map_shp.c: Make sure to Destroy a region before overwriting
+ the value. Identified by valgrind.
+
+2007-08-09 07:07 gstueve
+
+ * src/wx_gui.c: change to newer function - item =
+ XmStringCreateLtoR(temp, XmFONTLIST_DEFAULT_TAG); +
+ item = XmStringGenerate(temp, XmFONTLIST_DEFAULT_TAG,
+ XmCHARSET_TEXT, NULL); to replace deprecated function.
+
+2007-08-08 08:29 we7u
+
+ * src/interface.c: Moving one of the SQL debug printf's inside an
+ #ifdef block so that we won't normally see it.
+
+2007-08-07 18:55 chicoreus
+
+ * src/: db_gis.c, db_gis.h: Change to error handling in the event
+ of an xastir coordinate for a station that doesn't translate to a
+ valid lat/long - returns error message indicating conversion
+ problem rather than as database problem.
+
+2007-08-07 13:33 gstueve
+
+ * src/map_pdb.c: Allow more granularity for debugging actions.
+ Remove unneeded global definitions.
+
+2007-08-07 10:29 chicoreus
+
+ * src/interface_gui.c: Removing some unecessary debugging messages.
+
+2007-08-07 09:24 chicoreus
+
+ * src/: interface.c, interface_gui.c: Bug fix - SQL database
+ interface definitions were always being placed as interface 0 in
+ the interface list.
+
+2007-08-07 09:08 we7u
+
+ * src/interface.c: Adding "#ifdef HAVE_DB" around the SQL database
+ interface type so that it doesn't appear in the list unless
+ configure finds that we have support for it.
+
+2007-08-07 09:05 we7u
+
+ * config/: language-Dutch.sys, language-French.sys,
+ language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Adding the SQL
+ Database string to the other language files.
+
+2007-08-07 08:31 we7u
+
+ * src/messages_gui.c: Commenting out an unused variable which
+ causes a compiler warning.
+
+2007-08-07 08:31 we7u
+
+ * src/interface_gui.c: Adding "#ifdef HAVE_DB" around a couple of
+ fprintf's.
+
+2007-08-06 18:06 chicoreus
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/database.h, src/db.c,
+ src/db_gis.c, src/db_gis.h, src/interface.c, src/interface.h,
+ src/interface_gui.c, src/main.c, src/messages_gui.c, src/util.c,
+ src/util.h, src/xa_config.c: Further work on sql server
+ (MySQL/Postgis) support. Began integration of sql connection
+ management with interface UI. Able to create a connection to a
+ MySQL database, and on starting it, save list of all current
+ stations to a simple single table db.
+
+ Code still needs substantial work before it is usable.
+
+2007-07-30 10:13 we7u
+
+ * INSTALL: Updating libgeotiff instructions for latest released
+ version (1.2.4).
+
+2007-07-27 08:55 we7u
+
+ * README.Getting-Started: Adding another note explaining that
+ "internal" on the Shapelib summary line is ok.
+
+2007-07-27 08:48 we7u
+
+ * README.Getting-Started, configure.ac: Getting rid of the
+ "Building with" text on the configure summary line. Fixing one
+ of the README's to match.
+
+2007-07-25 08:53 we7u
+
+ * INSTALL: Revising the install instructions for the optional
+ Shapefile utilities to correspond to the current sources.
+
+2007-07-25 08:45 we7u
+
+ * src/shapelib/contrib/: dbfcat.c, dbfinfo.c, shpcat.c,
+ shpcentrd.c, shpdxf.c, shpfix.c, shpgeo.c, shpinfo.c, shpproj.c:
+ Adding includes necessary for warning-free compiles.
+
+2007-07-25 08:45 we7u
+
+ * src/shapelib/contrib/.cvsignore: Adding shpproj executable to CVS
+ ignore.
+
+2007-07-25 08:37 we7u
+
+ * src/shapelib/: Makefile_shapelib_orig, shpcreate.c, shpdump.c,
+ shprewind.c: Added shprewind.c to the "clean" target of the
+ original Makefile. Added stdlib.h includes to some of the
+ utilities to get a clean compile.
+
+2007-07-25 08:10 we7u
+
+ * INSTALL: Adding instructions for compiling some of the optional
+ Shapelib utilities and contributed Shapelib utilities.
+
+2007-07-23 09:58 we7u
+
+ * src/db_gis.c: Moving the strtof test below the config.h include.
+
+2007-07-23 08:58 tvrusso
+
+ * configure.ac, src/db_gis.c: Fix up usage of strtof for systems
+ that are so old they don't have this function.
+
+2007-07-18 09:20 we7u
+
+ * src/db.c: Correcting a spelling error in a debug statement.
+
+2007-07-16 07:38 chicoreus
+
+ * INSTALL: Fixing typo in install documentation. Patch from Jim
+ Tittsler - jtittsler Tracker: [ 1695864 ] INSTALL typo
+ ImageMagick->GraphicsMagick
+
+2007-07-14 20:39 chicoreus
+
+ * src/main.c: [no log message]
+
+2007-07-14 20:37 chicoreus
+
+ * src/: Makefile.am, db_gis.c, db_gis.h, lclint.script: Framework
+ for spatial database support. Should compile, but won't do
+ anything yet.
+
+2007-07-14 20:33 chicoreus
+
+ * acinclude.m4, configure.ac: Adding tests for MySQL, Postgresql,
+ and Postgis for spatial database support
+
+2007-07-09 20:03 tvrusso
+
+ * README.MAPS: Fix up mistaken information about TIGER/Line data.
+ Update pointers to geocoding files (we were still pointing users
+ to the 2003 data, which is a poor match to recent TIGER/Line
+ shapefiles).
+
+2007-07-06 15:43 we7u
+
+ * configure.ac: For the summary, we now refuse to display the
+ developer section unless one of those options has been enabled.
+ This is so normal users don't have to worry about that section.
+
+2007-07-06 15:06 we7u
+
+ * configure.ac: More additions to the summary output.
+
+2007-07-06 14:32 we7u
+
+ * configure.ac: Changing some of the summary text.
+
+2007-07-06 12:24 we7u
+
+ * src/main.c: Bumping up the size of the Help->About "Libraries
+ Used" string.
+
+2007-07-06 12:17 we7u
+
+ * configure.ac: A few more small tweaks to the configure summary
+ output.
+
+2007-07-06 12:04 we7u
+
+ * configure.ac: Reformatting the configure summary output. Adding
+ wget/libcurl to the summary as well.
+
+2007-07-02 16:43 tvrusso
+
+ * configure.ac: Remove hack to use external rtree library ---
+ differences between GRASS's rtree library and ours make it so
+ that we can't use them interchangably. The difference is in the
+ size of floating point variables used in the Rect structure (we
+ use floats as did the original author, GRASS uses it modified to
+ have doubles, which vastly increases memory usage for no real
+ gain).
+
+ This should remedy all of the Fedora users problems. Unless it
+ doesn't.
+
+2007-07-02 16:37 tvrusso
+
+ * src/: map_shp.c, shp_hash.c, rtree/card.c, rtree/card.h,
+ rtree/index.c, rtree/index.h, rtree/node.c, rtree/rect.c,
+ rtree/split_l.c, rtree/split_l.h: Turns out that putting a suffix
+ on all symbols in the rtree library was very simple and fast, so
+ I Just Did It.
+
+ This should probably fix the problem for Fedora users with GDAL
+ installed from repository, once I remove the "external rtree" bit
+ from configure.ac.
+
+2007-07-02 15:08 we7u
+
+ * FAQ: Adding a section to the Map Problems/Solutions question
+ about deleting the Xastir user directory and starting over when
+ all else fails.
+
+2007-07-02 14:34 we7u
+
+ * FAQ: Added some debugging instructions for maps not working.
+
+2007-07-02 14:19 we7u
+
+ * FAQ: Updating the version number where "APX" is quoted.
+
+2007-07-02 12:34 we7u
+
+ * FAQ: Added a question/answer about how to solve the problem:
+ station trail not displaying.
+
+2007-07-02 12:12 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Changing the ALTNET box
+ so that it is smaller and has a label.
+
+2007-07-02 05:55 tvrusso
+
+ * src/rtree/: split_l.c, split_l.h: Undo the
+ CoverSplit->l_CoverSplit change made last week.
+
+ The real issue was that some repositories have a GDAL that
+ includes GRASS libraries including a libgrass_rtree that
+ duplicates the rtree functionality. Xastir's rtree library is
+ precisely the one that GRASS uses (based on public domain (i.e.
+ uncopyrighted) software from www.superliminal.com), and this
+ leads to a link conflict that produces an obscure and cryptic
+ error message at link time.
+
+ Renaming the CoverSplit variable was just a band-aid that was
+ suggested for a trial run while diagnosing the problem, not a
+ recommended fix.
+
+2007-07-01 21:20 tvrusso
+
+ * configure.ac: Add a note at the end that tells whether we're
+ using external rtree (e.g. from GDAL) or our own internal
+ version.
+
+2007-07-01 21:12 tvrusso
+
+ * configure.ac: Fix configure so that it checks for the presence of
+ RTreeSearch in other libraries before it builds our own rtree
+ library.
+
+ This is necessary because some repositories have a GDAL that was
+ built with GRASS support (against current recommendations), and
+ that brings in an rtree library unbidden. The result of trying
+ to link our own in unconditionally is a cryptic message about
+ CoverSplit not being relocatable.
+
+ The only testing I've done is that this doesn't break builds with
+ GDAL that has no GRASS support. I am unable to test it in the
+ case for which it is intended. I'll have to ask that someone
+ with an F7 system do that.
+
+2007-06-29 13:22 we7u
+
+ * src/rtree/: split_l.c, split_l.h: Trying a rename of CoverSplit
+ to l_CoverSplit to see if this fixes the Fedora linking problem.
+
+2007-06-21 12:10 we7u
+
+ * src/interface.c: Removing stale lockfiles when it was our own
+ process group which created them earlier.
+
+2007-06-20 09:25 we7u
+
+ * src/map_geo.c: Adding a few comments to the code for the new
+ transparent color linked list functions.
+
+2007-06-20 09:18 we7u
+
+ * README.MAPS: Tweaking the TRANSPARENT note to state that multiple
+ lines may be used.
+
+2007-06-20 09:11 we7u
+
+ * WMSRadar.geo, src/map_geo.c: Commenting out debug fprintf plus
+ adding another black and a white color as transparent colors to
+ WMSRadar.geo.
+
+2007-06-20 08:42 we7u
+
+ * src/: main.h, map_WMS.c, map_geo.c, maps.h: First attempt at
+ multiple TRANSPARENT support for .geo files. Not fully tested
+ yet, but doesn't appear to fall over either.
+
+2007-06-15 11:44 we7u
+
+ * scripts/LSB-BUILD: Updating to latest rev number for release.
+
+2007-06-10 09:53 tvrusso
+
+ * scripts/get-NWSdata: Update get-NWSdata to pull down the new
+ files instead of trying to get some old and now non-existent
+ files.
+
+2007-05-28 16:59 chicoreus
+
+ * src/: main.c, main.h, objects.c: Disabling close polygon item on
+ CAD menu when not in draw mode.
+
+2007-05-28 12:53 tvrusso
+
+ * src/util.c: Fix a comment about multiline length.
+
+2007-05-28 12:51 tvrusso
+
+ * src/: db.c, util.c, util.h:
+ Make the add_comment function stop stripping leading spaces.
+ This is to allow multiline objects with no leading text, which
+ otherwise get broken.
+
+ Add a makeMultiline function to util.c. Given arrays of lat/lon
+ pairs, will produce a multiline string representing that array
+ and a centroid value that can be used for creating an object.
+
+ Bunch of debugging output added to extract_multipoint that I
+ needed to help me track down why my multilines were disappearing
+ (it was because of the leading space stripping).
+
+ Nobody is calling makeMultiline yet. It could be used for
+ transmitting CAD objects if someone wanted to hack that in.
+
+ I've tested makeMultiline in an external program to generate
+ strings, then created objects by pasting the strings into the
+ comment box of the create object dialog.
+
+2007-05-21 07:51 tvrusso
+
+ * README.MAPS: Update the TIGER/Line information.
+
+2007-05-09 10:36 tvrusso
+
+ * config/: Makefile.am, tgr2shppoly_2006.dbfawk: Add a new DBFAWK
+ file for the 2006 TIGER/Line data.
+
+ This data has "UACU" and "URCU" fields instead of the RS_A15 and
+ RS_A16 fields that older TIGER/Line data had.
+
+2007-05-04 13:18 we7u
+
+ * help/help-English.dat: Added a note stating that all PHG values
+ must be specified before Xastir will transmit the values.
+
+2007-05-02 13:58 we7u
+
+ * src/interface.c: Checking the result code, providing more info on
+ why an "open" failed.
+
+2007-05-02 12:54 we7u
+
+ * configure.ac, scripts/BUILDRPMS: Setting up for the next devel
+ release.
+
+2007-05-02 12:14 we7u
+
+ * ChangeLog, configure.ac, scripts/BUILDRPMS, scripts/LSB-BUILD,
+ scripts/do_xastir_release_dev, scripts/do_xastir_release_stable:
+ Preparing for stable 1.9.0 release.
+
+2007-04-27 09:55 tvrusso
+
+ * src/db.c: Cast the time_t value to (long int) before passing to
+ fprintf. On some systems (e.g. FreeBSD) time_t isn't a long, and
+ using a %ld format for it generates a warning. On other systems,
+ time_t *is* a long int and using a %d format generates a warning.
+
+ So punt: cast to (long int) and use %ld. This should make all
+ those systems shut up with their warnings.
+
+2007-04-27 06:52 we7u
+
+ * src/db.c: Changing some debug printf's from %d to %ld for
+ printing some time variables.
+
+2007-04-27 06:47 we7u
+
+ * src/db.c: Changing some printf's to %ld instead of %d for some
+ debug time printouts.
+
+2007-04-27 06:45 we7u
+
+ * src/db.c: Adding a missing "void" in a function header.
+
+2007-04-27 06:44 we7u
+
+ * src/database.h: Adding a missing "void" in a function
+ declaration.
+
+2007-04-20 10:03 we7u
+
+ * FAQ: Added some debugging instructions for the missing
+ "xastir.rgb" file and/or other files upon Xastir startup.
+
+2007-04-16 11:17 tvrusso
+
+ * src/: database.h, db.c: More debugging code to look into bug
+ #1698474
+
+ Add a "dump_time_sorted_list" method and calls to it so we can
+ actually view the entire time sorted list as soon as the sanity
+ check fails.
+
+ Also reduce the debugging expire time from 1 hour to 5 minutes.
+
+2007-04-12 08:40 we7u
+
+ * FAQ: Adding a link to the timing slider dialog screen capture.
+
+2007-04-11 10:33 we7u
+
+ * FAQ: Added section 4.28 describing the problem with missing
+ labels on the Configure->Timing dialog. It also describes what
+ the labels should be.
+
+2007-04-09 08:20 we7u
+
+ * config/language-German.sys: Updates by Rolf Bleher, DK7IN.
+ Thanks!
+
+2007-03-31 12:49 tvrusso
+
+ * src/: database.h, db.c: Add some sanity checking to the
+ EXPIRE_DEBUG logic.
+
+ I am still seeing that every few weeks my xastir run starts to
+ have stations that should have expired 10 days ago, but still has
+ 'em. This really screws up the ALOHA calculations.
+
+ This sanity checking just goes through the entire time-sorted
+ list and checks to see if any stations are older than the expire
+ time, and does this immediately after the expiration is
+ processed. The sanity checking only happens when EXPIRE_DEBUG is
+ defined.
+
+ The expire code assumes that the list is sorted by time, and
+ stops when it finds a station newer than the expire time. If the
+ list is somehow getting corrupted and no longer properly sorted,
+ that would explain the behavior I'm seeing. I still haven't
+ found the problem, but this should at least tell me if the list
+ management has a bug or not.
+
+2007-03-22 10:05 gstueve
+
+ * scripts/fcc-get: Sort only on callsign. Don't use following
+ fields.
+
+2007-03-13 07:55 gstueve
+
+ * scripts/fcc-get: Actually use web instead of older ftp server to
+ get fcc data.
+
+2007-03-13 07:32 gstueve
+
+ * scripts/fcc-get: Make sure not to get rid of an old fcc data file
+ if unable to get replacement file.
+
+2007-03-07 21:17 tvrusso
+
+ * src/: database.h, db.c: Change "check_station_remove" and
+ "check_message_remove" to take a time_t for curr_time instead of
+ an int. time_t's are what's passed in, so let's keep it
+ consistent.
+
+ I do not believe this has anything at all to do with the fact
+ that my xastir instance isn't deleting stations on the 1-day
+ cycle I ask it to --- on my system a time_t and an int are the
+ same size, and time_t is defined as an int32, not an unsigned or
+ anything. But it's still the right thing to do.
+
+2007-03-06 13:58 we7u
+
+ * src/map_geo.c: Getting rid of a compiler warning when we compile
+ with ImageMagick.
+
+2007-03-06 11:31 we7u
+
+ * src/: map_WMS.c, map_geo.c, map_tiger.c, maps.c: Changing the
+ path to the GraphicsMagick api.h file to match what we're
+ currently compiling against.
+
+2007-03-06 11:30 we7u
+
+ * scripts/LSB-BUILD: Forcing the use of GraphicsMagick instead of
+ ImageMagick, per the newer command-line flags we use for Xastir's
+ configure.
+
+2007-02-27 15:19 gstueve
+
+ * src/bulletin_gui.c: Move display update until after the new data
+ is posted to list.
+
+2007-02-27 13:33 gstueve
+
+ * src/alert.c: Keep trying to clear out old data for new messages.
+
+2007-02-24 14:08 gstueve
+
+ * src/wx_gui.c: Make sure updating Wx Alert List doesn't crash
+ because selected item was replaced by unselected item.
+
+2007-02-22 08:29 we7u
+
+ * INSTALL: Adding "ldconfig" invocations for GM/IM installs.
+
+2007-02-22 08:14 we7u
+
+ * INSTALL: Changing the command-line options for configuring
+ GraphicsMagick to something a bit simpler.
+
+2007-02-22 07:26 gstueve
+
+ * src/alert.c: Compressed Wx alerts are precisely 3 elements long.
+
+2007-02-22 07:20 gstueve
+
+ * src/: alert.c, util.c: Really, really take care of NWS_ message
+ from Thailand. Remove stale compressed weather alerts from
+ consideration.
+
+2007-02-21 08:47 gstueve
+
+ * src/util.c: Fix error case from Thailand station sending message
+ to NWS_ about 80th birthday anniversary of King.
+
+2007-02-21 08:02 gstueve
+
+ * src/db.c: Make conditional look like what it is (a for loop, not
+ simple while).
+
+2007-02-16 20:11 gstueve
+
+ * src/db.c: Make sure debug_level is tested as BitWise value NOT
+ logical value.
+
+2007-02-16 13:01 we7u
+
+ * INSTALL: Grammar error. Fixed.
+
+2007-02-16 12:22 gstueve
+
+ * src/main.c: Fixed [ 1553641 ] Zoom Error (Integer Math?).
+ Increment by 1 for 10% zoom-out when less than zoom level 10.
+
+2007-02-16 11:48 we7u
+
+ * scripts/get-NWSdata: Updating the script to snag the
+ latest-latest files.
+
+2007-02-16 11:48 we7u
+
+ * src/map_geo.c: Getting rid of a compiler warning having to do
+ with the wrong size specified in an printf.
+
+2007-02-16 11:48 we7u
+
+ * INSTALL: Adding GraphicsMagick instructions.
+
+2007-02-16 09:05 we7u
+
+ * scripts/LSB-BUILD: Moving the defines for the REV and FILENAME
+ near the top. Deleting old xastir-lsb-*.bz2 files before we
+ start so that we don't upload old files each time.
+
+2007-02-15 08:41 we7u
+
+ * README.Getting-Started: Adding a comment about how to test audio
+ file playing from the command-line.
+
+2007-02-14 07:20 we7u
+
+ * src/maps.c: Adding more comments. No code changes.
+
+2007-02-13 12:22 gstueve
+
+ * src/maps.c: Make sure all sides of the box are checked, not just
+ three of them. Also make sure if an alert is not on screen clear
+ it off.
+
+2007-02-13 07:30 we7u
+
+ * src/interface_gui.c: Changing the defaults for new internet
+ connections to: rotate.aprs.net, port 14580, filter "m/500",
+ reconnect enabled.
+
+2007-02-13 05:21 gstueve
+
+ * scripts/fcc-get: Update script to retrieve Canadian callsign data
+ from new location. I had not gotten a new update from previous
+ location since September, 2006.
+
+2007-02-09 22:52 we7u
+
+ * README.Getting-Started: Adding an entry for the new "Home" key
+ function.
+
+2007-02-09 22:49 we7u
+
+ * src/main.c: The "Home" key now centers the map on your station's
+ position.
+
+2007-02-09 19:31 we7u
+
+ * src/map_geo.c: Changing back to the original path for the
+ Toposerver images. The problem was fixed on findu's end.
+
+2007-02-09 19:04 we7u
+
+ * src/map_cache.c: Commenting out one assignment (not used) which
+ causes a compiler warning on some systems.
+
+2007-02-09 18:24 we7u
+
+ * Davis/README: Fixing an errant path in the instructions.
+
+2007-02-08 13:02 we7u
+
+ * src/map_geo.c: Hopefully a tweak that will help make online
+ Toporama maps work again in the future. Have to wait for Gerry
+ to look at the server configuration before we'll know for sure.
+
+2007-02-06 12:30 we7u
+
+ * src/maps.c: Casting some long int results to int's.
+
+2007-02-06 08:24 we7u
+
+ * src/maps.c: A fix for the UTM/MGRS major grid lines not
+ appearing.
+
+2007-02-06 06:55 we7u
+
+ * scripts/inf2geo.pl: Updating the script to use GraphicsMagick's
+ "gm" program. If not found, try ImageMagick's "identify"
+ program. If that not found, output an error message suggesting
+ that one or the other be installed.
+
+2007-02-06 06:14 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Changing "MGRS"
+ label to "MGRS2". When it was implemented they were calling the
+ two available ones "MGRS-Old" and "MGRS-New". Now "MGRS-New" is
+ called "MGRS2" and there's talk of an "MGRS3" soon...
+
+2007-01-27 10:41 tvrusso
+
+ * configure.ac: re-enable check for the X Printing Extension
+ library. Apparently this is needed by libXm and some systems do
+ not properly bring in the indirect dependence through the dynamic
+ loader.
+
+ It would probably be better to detect that condition than just
+ blindly checking for Xp (which we don't use).
+
+ Regardless, it should never be necessary to install development
+ headers for libXp just to build xastir, which was what one user
+ was confused about and which led me to remove the check in the
+ first place.
+
+2007-01-24 13:19 tvrusso
+
+ * configure.ac: Remove probe for the X Printing Extension library.
+
+ Xastir doesn't use it, and there's no point probing for it.
+
+ Someone was confused into thinking they needed to install it on
+ Ubuntu 6.10 because configure said it couldn't find the library.
+ They don't, coz we don't use it.
+
+2007-01-16 07:15 we7u
+
+ * scripts/LSB-BUILD: We now remove /opt/Xastir/* during the build
+ so that we get a clean tar file, plus dates have been added to
+ the filename.
+
+2007-01-13 19:57 we7u
+
+ * src/messages_gui.c: We now check whether Lesstif is compiled in
+ and skip doing the dynamic widget thing on the Send Message
+ dialog if so.
+
+2007-01-12 11:52 we7u
+
+ * src/messages_gui.c: Another LSB/Lesstif tweak, plus making sure
+ we fill in the history on Send Message dialogs brought up through
+ the new "Show Pending Messages" menu entry.
+
+2007-01-12 10:39 we7u
+
+ * src/maps.c: Changing strcasestr to strstr for Cygwin
+ compatibility. We don't really need case-insensitive matching
+ there anyway.
+
+2007-01-12 09:13 we7u
+
+ * acinclude.m4: A fix for the GraphicsMagick/ImageMagick problem
+ where GM is not on the system but Xastir tries to compile with
+ it.
+
+2007-01-12 08:49 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/messages.h,
+ src/messages_gui.c: Adding a "Show Pending Messages" menu option
+ to the Message menu. This one looks through the outgoing queue
+ and brings up a Send Message dialog for each current QSO.
+
+2007-01-09 09:33 we7u
+
+ * src/messages_gui.c: Another couple of tweaks to keep Lesstif from
+ segfaulting with the LSB compile.
+
+2007-01-08 13:47 we7u
+
+ * src/xa_config.c: Updated some comments. No code changes.
+
+2007-01-08 13:21 we7u
+
+ * src/messages_gui.c: Fixes to prevent segfaults with LSB-Xastir.
+ It appears that Lesstif cannot currently handle removing/adding
+ widgets to an already-realized dialog without segfaulting. Here
+ we stick with the default one-long-input-field if we're compiling
+ for LSB.
+
+2007-01-05 12:20 we7u
+
+ * src/db.c: Moved the code which _only_ depends on
+ search_station_name() higher in the Station_data() function so
+ that the dialog doesn't get drawn if not needed.
+
+2007-01-05 12:00 we7u
+
+ * scripts/LSB-BUILD-ALL: Switching back to Lesstif-0.95.0 as 0.94.4
+ didn't improve things.
+
+2007-01-05 11:52 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/maps.c: Fixing the print
+ properties dialog so that it only comes up if "gv" is detected.
+ Getting rid of gv-specific options on the command-line when "gv"
+ is not being used as a print-previewer. Adding a couple of
+ strings to the language files.
+
+2007-01-04 12:28 we7u
+
+ * scripts/LSB-BUILD-ALL: Changing some comments. No code changes.
+
+2007-01-04 10:12 we7u
+
+ * scripts/LSB-BUILD-ALL: Switching from Lesstif-0.95.0 to 0.94.4
+ for a while to see if the resulting binary is more stable.
+
+2007-01-03 11:38 we7u
+
+ * symbols/Makefile.am, symbols/symbols.dat, src/rtree/Makefile.am,
+ src/rtree/card.c, src/rtree/card.h, src/rtree/gammavol.c,
+ src/rtree/index.c, src/rtree/index.h, src/rtree/node.c,
+ src/rtree/rect.c, src/rtree/sphvol.c, src/rtree/split_l.c,
+ src/rtree/split_l.h, src/rtree/split_q.c, src/rtree/split_q.h,
+ src/Makefile.am, src/alert.c, src/alert.h, src/awk.c, src/awk.h,
+ src/bulletin_gui.c, src/bulletin_gui.h, src/color.c, src/color.h,
+ src/database.h, src/datum.c, src/datum.h, src/db.c, src/dbfawk.c,
+ src/dbfawk.h, src/draw_symbols.c, src/draw_symbols.h,
+ src/fcc_data.c, src/fcc_data.h, src/festival.c, src/festival.h,
+ src/geo-client.c, src/geo-find.c, src/geo.h, src/geocoder_gui.c,
+ src/gps.c, src/gps.h, src/hashtable.c, src/hashtable.h,
+ src/hashtable_itr.c, src/hashtable_itr.h,
+ src/hashtable_private.h, src/hostname.c, src/hostname.h,
+ src/igate.c, src/igate.h, src/interface.c, src/interface.h,
+ src/interface_gui.c, src/io-common.c, src/io-mmap.c, src/io.h,
+ src/lang.c, src/lang.h, src/leak_detection.h, src/list_gui.c,
+ src/list_gui.h, src/locate_gui.c, src/location.c,
+ src/location_gui.c, src/macspeech.c, src/main.c, src/main.h,
+ src/map_WMS.c, src/map_cache.c, src/map_cache.h, src/map_dos.c,
+ src/map_gdal.c, src/map_geo.c, src/map_gnis.c, src/map_pdb.c,
+ src/map_shp.c, src/map_tif.c, src/map_tiger.c, src/maps.c,
+ src/maps.h, src/messages.c, src/messages.h, src/messages_gui.c,
+ src/objects.c, src/objects.h, src/popup.h, src/popup_gui.c,
+ src/rac_data.c, src/rac_data.h, src/rotated.c, src/rotated.h,
+ src/rpl_malloc.c, src/rpl_malloc.h, src/shp_hash.c,
+ src/shp_hash.h, src/snprintf.c, src/snprintf.h, src/sound.c,
+ src/symbols.h, src/testawk.c, src/track_gui.c, src/track_gui.h,
+ src/util.c, src/util.h, src/view_message_gui.c, src/wx.c,
+ src/wx.h, src/wx_gui.c, src/x_spider.c, src/x_spider.h,
+ src/xa_config.c, src/xa_config.h, src/xastir.h,
+ src/xastir_udp_client.c, src/shapelib/Makefile.am,
+ src/shapelib/contrib/Makefile.am, config/24kgrid.dbfawk,
+ config/Makefile.am, config/gps_wpt.dbfawk,
+ config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, config/nwsc_ddmmyy.dbfawk,
+ config/nwsmzddmmyy.dbfawk, config/nwsmzoddmmyy.dbfawk,
+ config/nwsozddmmyy.dbfawk, config/nwsw_ddmmyy.dbfawk,
+ config/nwsz_ddmmyy.dbfawk, config/nwszoddmmyy.dbfawk,
+ config/predefined_EVENT.sys, config/predefined_SAR.sys,
+ config/tgr2shp.dbfawk, config/tgr2shppoly.dbfawk,
+ config/tgrcty.dbfawk, config/tgrkgl.dbfawk, config/tgrlk.dbfawk,
+ config/tgrlpt.dbfawk, config/tgrlpy.dbfawk,
+ config/tgrplc00.dbfawk, config/tgrwat.dbfawk,
+ config/tnc-startup.aea, config/tnc-startup.d700,
+ config/tnc-startup.kam, config/tnc-startup.kpc2,
+ config/tnc-startup.kpc3, config/tnc-startup.paccomm,
+ config/tnc-startup.pico, config/tnc-startup.sys,
+ config/tnc-startup.thd7, config/tnc-startup.tnc2,
+ config/tnc-startup.tnc2-ui, config/tnc-stop.d700,
+ config/tnc-stop.sys, config/tnc-stop.thd7,
+ config/tnc-stop.tnc2-ui, scripts/LSB-BUILD,
+ scripts/LSB-BUILD-ALL, scripts/LSB-BUILD-CURL,
+ scripts/LSB-BUILD-DB, scripts/LSB-BUILD-GDAL,
+ scripts/LSB-BUILD-GRAPHICSMAGICK, scripts/LSB-BUILD-JASPER,
+ scripts/LSB-BUILD-JPEG, scripts/LSB-BUILD-LESSTIF,
+ scripts/LSB-BUILD-PCRE, scripts/LSB-BUILD-PNG,
+ scripts/LSB-BUILD-ZLIB, scripts/Makefile.am,
+ scripts/Xastir_tigerpoly.py, scripts/example_objects.log,
+ scripts/fcc-get, scripts/get-NWSdata, scripts/get-gnis,
+ scripts/get-maptools.sh, scripts/get_shapelib.sh,
+ scripts/toporama250k.pl, scripts/toporama50k.pl,
+ scripts/xastir-fixcfg.sh, scripts/xastir-migrate.sh, AUTHORS,
+ DEBUG_LEVELS, FAQ, INSTALL, LICENSE, Makefile.am, NEWS, README,
+ README.CVS, README.Contributing, README.Getting-Started,
+ README.MAPS, README.win32, REGRESSION_TESTS, UPGRADE,
+ acinclude.m4, bootstrap.sh, changes.txt, configure.ac,
+ install-xastir, update-xastir, xastir.1, Davis/Makefile.am,
+ Davis/README, Davis/bootstrap.sh, Davis/configure.ac,
+ Davis/src/Makefile.am, Davis/src/db2APRS.c, Davis/src/defs.h,
+ LaCrosse/Makefile.am, LaCrosse/README, LaCrosse/bootstrap.sh,
+ LaCrosse/configure.ac, LaCrosse/src/Makefile.am,
+ LaCrosse/src/defs.h, LaCrosse/src/open2300db2APRS.c,
+ callpass/Makefile.am, callpass/callpass.c, help/Makefile.am,
+ help/help-Dutch.dat, help/help-English.dat, help/help-French.dat,
+ help/help-German.dat, help/help-Italian.dat,
+ help/help-Portuguese.dat, help/help-Spanish.dat, m4/Makefile.am:
+ Updating Copyright info.
+
+2006-12-29 18:35 we7u
+
+ * src/maps.c: Moving a new variable declaration above statements in
+ the function.
+
+2006-12-29 10:57 we7u
+
+ * src/maps.c: Moving many of the error messages to pop-up dialogs
+ for the user-instigated print and print preview functions. We
+ also now allow a previewer other than "gv" to be used, although
+ we're still passing gv-specific parameters to it (something more
+ to fix).
+
+2006-12-29 10:10 we7u
+
+ * src/: maps.c, xa_config.c: Added #ifdef's for GV_PATH and
+ LPR_PATH so that we compile ok on systems which don't have these
+ two utilities.
+
+2006-12-28 23:27 we7u
+
+ * src/maps.c: More changes to printing. Printing direct should be
+ functional now.
+
+2006-12-28 22:37 we7u
+
+ * src/: maps.c, maps.h, xa_config.c: Revising the new printing code
+ a bit more. Now saves/restores the printer and previewer paths
+ from file plus allows the user to change them. More to do yet.
+
+2006-12-28 16:14 we7u
+
+ * src/: main.c, maps.c, maps.h: A start towards having a separate
+ dialog for printing or print previewing/printing. Not complete
+ yet, but shows the direction I'm heading.
+
+2006-12-20 18:51 we7u
+
+ * acinclude.m4: Removing the libdb-5.0 options.
+
+2006-12-20 16:04 we7u
+
+ * acinclude.m4: Fixing the variable save/restore code for the
+ GraphicsMagick and ImageMagick tests.
+
+2006-12-19 22:54 we7u
+
+ * scripts/get-maptools.sh: Adding checks for "wget", "gtar",
+ "bsdtar", "tar", and "gunzip". The script will attempt to
+ configure to the set of utilities that are available. If the
+ proper utilities cannot be found the script will exit before
+ downloading any files.
+
+2006-12-19 17:38 we7u
+
+ * scripts/get-maptools.sh: Searching for GNU tar before continuing
+ with the script.
+
+2006-12-19 13:45 tvrusso
+
+ * src/map_shp.c: Remove unused variable to silence warnings.
+
+2006-12-19 13:39 tvrusso
+
+ * src/: main.c, map_shp.c, util.c, util.h: A tiny addition: make
+ sure we always write out a valid ".prj" file to go with any of
+ the shapefiles we create (currently, that's GPS downloads and
+ saved APRS tracks).
+
+ Doing so makes sure that tools other than Xastir that use the
+ .prj file to determine the coordinate system of a shapefile will
+ know what's in there. This includes OGR's projection
+ transformation tools, the QGIS GIS data viewer, and other GIS
+ software such as GRASS or (ugh) ESRI products. It is a cardinal
+ sin to create GIS data that doesn't tell you what coordinate
+ system it's in.
+
+ Strike one dark stain from our souls.
+
+2006-12-18 23:31 tvrusso
+
+ * configure.ac: Switch default for rtree from no to yes. It will
+ now build as long as shapefile support is building, unless
+ explicitly disabled.
+
+ Disabling rtree now requires "--without-rtree".
+
+2006-12-18 13:09 we7u
+
+ * xastir.spec.in: Forcing ImageMagick over GraphicsMagick, as that
+ is what is supplied with SuSE. Also enabling rtree.
+
+2006-12-18 13:09 we7u
+
+ * xastir-min.spec.in: Forcing ImageMagick over GraphicsMagick for
+ this package, as that's what is supplied with SuSE.
+
+2006-12-18 11:45 we7u
+
+ * acinclude.m4: Removing "/opt/lib" and "/opt/bin" for OSX search
+ paths as these are not used by DarwinPorts/MacPorts.
+
+2006-12-18 11:35 we7u
+
+ * acinclude.m4: Simplifying the ImageMagick and GraphicsMagick
+ tests, but adding extra search paths when configuring on OSX.
+ Adding more libdb paths to the search paths for that library.
+
+2006-12-18 11:30 we7u
+
+ * configure.ac: Commenting out some warnings regarding ImageMagick
+ and GraphicsMagick: This info is self-evident in the configure
+ output now.
+
+2006-12-16 22:55 we7u
+
+ * scripts/get-maptools.sh: Taking out the hard-coded path to "tar".
+
+2006-12-15 12:56 we7u
+
+ * acinclude.m4: Adding searches for ImageMagick and GraphicsMagick
+ in "/opt/local/bin" (OSX DarwinPorts).
+
+2006-12-15 12:53 we7u
+
+ * configure.ac: Correcting the GM/IM logic, adding comments.
+
+2006-12-15 10:32 tvrusso
+
+ * config/Makefile.am, config/stored_track.dbfawk, src/map_shp.c:
+ Add a Label field to the dbf file created by the "Store Track"
+ feature when shapelib is available. Add a dbfawk file so that
+ stored tracks can be rendered properly even if they aren't in the
+ GPS directory. Users can customize presentation of the stored
+ track by copying the global dbfawk file to the directory with the
+ shapefile, giving it the same basename as the shapefile, and
+ tweaking it as needed.
+
+ This should allow more convenient use of the maps created by
+ storing tracks than the method that based rendering on the file
+ name and directory.
+
+2006-12-15 09:43 we7u
+
+ * src/main.c: Reversing the order of the
+ HAVE_GRAPHICSMAGICK/HAVE_IMAGEMAGICK #ifdef's.
+
+2006-12-15 08:06 we7u
+
+ * acinclude.m4: Reformatting a couple of lines. No code changes.
+
+2006-12-14 22:02 tvrusso
+
+ * src/map_shp.c: Fix of my previous fix to the GPS vs. DBFAWK
+ issue. Somehow I managed to get it to ignore the fact that the
+ file was in the GPS directory even when there *WAS* no dbfawk
+ file. The problem was that I tested for the non-nullness of
+ "sig_info" after sig_info was filled in with a default
+ signature's pointer. Needed to put the test before that default
+ case.
+
+2006-12-14 13:22 we7u
+
+ * configure.ac: Giving up for now on skipping the wget tests if
+ libcurl is found. Also moved "rtree" out of the experimental
+ category, putting it up with the other regular options (above the
+ dashed line in the summary).
+
+2006-12-14 12:17 we7u
+
+ * scripts/LSB-BUILD: Added a comment.
+
+2006-12-14 12:17 we7u
+
+ * acinclude.m4, configure.ac: Removing the tests for "cat" and
+ "cp". Tweaking the "wget" code a bit more (but still not skipped
+ if libcurl is found first).
+
+2006-12-14 12:15 we7u
+
+ * src/: main.c, objects.c: Using the new copy_file() function
+ instead of /bin/cp.
+
+2006-12-14 12:14 we7u
+
+ * src/: util.c, util.h: Added copy_file() function written by Adam
+ Hahn, AI4QB, and contributed to the public domain. We've
+ modified it from his initial code so any bugs are our fault.
+
+2006-12-14 09:06 we7u
+
+ * acinclude.m4: Commenting out the code which checks for the "cat"
+ command. We don't use it anywhere in our code.
+
+2006-12-13 21:34 we7u
+
+ * acinclude.m4: Fixing some errors I introduced with the last
+ commit.
+
+2006-12-13 21:02 we7u
+
+ * acinclude.m4: Improvements in the ImageMagick and GraphicsMagick
+ detection.
+
+2006-12-12 22:50 tvrusso
+
+ * src/: main.c, map_shp.c: Make DBFAWK trump the gps_flag.
+
+ This means that if a file is in the GPS directory and there is a
+ DBFAWK file to go with it, the DBFAWK file controls the
+ rendering. It is still the case that if there is NO dbfawk file,
+ or if DBFAWK is not enabled, the hard-coded GPS stuff (i.e. fixed
+ width and line style, color taken from file name) is used.
+
+ Also, change the dbfawk file created upon GPS download to match
+ the style that the hard-coded GPS stuff would use.
+
+2006-12-12 22:46 we7u
+
+ * acinclude.m4, configure.ac: A few tweaks to the
+ GraphicsMagick/ImageMagick tests.
+
+2006-12-12 19:06 we7u
+
+ * acinclude.m4, configure.ac, src/objects.c, src/xa_config.c,
+ src/xastir.h, src/maps.h, src/maps.c, src/main.c, src/map_WMS.c,
+ src/map_geo.c, src/map_tiger.c: Changes to allow using
+ GraphicsMagick library and "gm convert" in place of the
+ ImageMagick library and "convert". Xastir will now prefer
+ GraphicsMagick over ImageMagick if both are present on the
+ system.
+
+2006-12-12 09:57 we7u
+
+ * scripts/: LSB-BUILD-ALL, LSB-BUILD-CURL, LSB-BUILD-DB,
+ LSB-BUILD-GDAL, LSB-BUILD-GRAPHICSMAGICK, LSB-BUILD-JASPER,
+ LSB-BUILD-JPEG, LSB-BUILD-LESSTIF, LSB-BUILD-PCRE, LSB-BUILD-PNG,
+ LSB-BUILD-ZLIB: Updating some comments.
+
+2006-12-12 08:38 we7u
+
+ * scripts/LSB-BUILD: Enabling the Festival client to be compiled
+ into LSB. This has a couple of small downsides: 1) The user
+ will get a "cannot connect to Festival" message on start up if
+ they haven't installed/run the festival daemon, and 2) If
+ anything else is running on localhost TCP port 1314 Xastir may
+ try to talk to it. The upside is that installing/running a
+ Festival daemon will work with the LSB binary to produce speech.
+
+2006-12-12 08:36 we7u
+
+ * acinclude.m4: Removing define for FESTIVAL_PATH. We don't use
+ this in our code, plus if we chose to later it'd make another
+ external dependency that'd need to be solved for the LSB
+ distribution. I believe this was originally added in case we
+ wished to call the festival binary directly instead of doing a
+ TCP connection to the festival daemon on port 1314.
+
+2006-12-12 07:49 we7u
+
+ * README.win32, acinclude.m4, src/wx_gui.c: Getting rid of our
+ dependence on the "/usr/bin/finger" external executable. It's
+ been replaced by our own TCP/IP finger code. This is used for
+ fetching the NOAA weather text from "wxsvr.net".
+
+2006-12-12 06:35 we7u
+
+ * src/db.c: Comment correction.
+
+2006-12-11 12:39 we7u
+
+ * scripts/LSB-BUILD: Cleaning up the lsbappchk calls.
+
+2006-12-11 12:38 we7u
+
+ * LICENSE: Minor changes to comments.
+
+2006-12-11 09:22 we7u
+
+ * scripts/LSB-BUILD: A minor change to the flags for lsbappchk.
+
+2006-12-10 20:19 tvrusso
+
+ * src/main.c: Change the "display_level" value in the stuff output
+ as a dbfawk file for downloaded gps tracks.
+
+ The value that was there was absurdly low.
+
+2006-12-08 21:02 we7u
+
+ * scripts/LSB-BUILD-XPM: We don't appear to need a separate libXpm
+ so deleting the build script for it.
+
+2006-12-08 21:00 we7u
+
+ * scripts/LSB-BUILD-ALL: Removing the libXpm build as we're picking
+ it up automatically from somewhere else now that we've enabled
+ the header files for it.
+
+2006-12-08 20:56 we7u
+
+ * LICENSE: Removing libXpm license as we don't appear to need to
+ include a separate libXpm anyway. We're already picking it up
+ from LSB or from Motif or something.
+
+2006-12-08 13:48 we7u
+
+ * scripts/LSB-BUILD-ALL: Putting the XPM build one step later.
+
+2006-12-08 13:16 we7u
+
+ * scripts/LSB-BUILD-ALL: Adding a comment about libXpm.
+
+2006-12-08 13:14 we7u
+
+ * scripts/LSB-BUILD-ALL: Adding libXpm build to the script.
+
+2006-12-08 13:12 we7u
+
+ * scripts/LSB-BUILD-XPM: An LSB build script for libXpm.
+
+2006-12-08 13:11 we7u
+
+ * scripts/LSB-BUILD: Adding libXpm instructions for the LSB build.
+
+2006-12-08 13:10 we7u
+
+ * configure.ac: Adding libXpm to the LSB build. Needed for
+ Snapshots and Printing.
+
+2006-12-08 13:09 we7u
+
+ * LICENSE: Adding the license for libXpm.
+
+2006-12-08 12:16 we7u
+
+ * scripts/LSB-BUILD: Copying "gm" from GraphicsMagick into our LSB
+ build.
+
+2006-12-08 12:15 we7u
+
+ * scripts/LSB-BUILD-GRAPHICSMAGICK: Installing "gm" utility as well
+ (that's where we can get to "convert" in GraphicsMagick).
+
+2006-12-08 12:14 we7u
+
+ * src/main.c: Restarting the Xastir binary no matter where it was
+ configured to be installed.
+
+2006-12-08 12:13 we7u
+
+ * configure.ac: Setting defines for Xastir paths. We can use them
+ in the C-code to do things like restart ourselves.
+
+2006-12-08 12:12 we7u
+
+ * acinclude.m4: Setting up to be able to do Printing and Snapshots
+ with the LSB version.
+
+2006-12-08 12:12 we7u
+
+ * INSTALL: Documenting the depending on Xpm for Printing and
+ Snapshots.
+
+2006-12-08 08:04 we7u
+
+ * src/wx_gui.c: Fixing up the finger code for fetching NOAA weather
+ alert text. We now pipe STDERR to STDOUT so that we can see any
+ errors in the dialog. The syntax is shell-specific so we perhaps
+ need a better way to do it. The syntax used should work for SH
+ or BASH shells, and I think Korn shell, but not for CSH? We also
+ now use HAVE_FINGER defines to enable/disable the actual finger
+ call in the code.
+
+2006-12-08 06:58 we7u
+
+ * LICENSE: Changing some comments.
+
+2006-12-08 06:45 we7u
+
+ * src/wx_gui.c: Using the new FINGER_PATH that we now put into
+ config.h via acinclude.m4.
+
+2006-12-08 06:44 we7u
+
+ * acinclude.m4: Adding a search for the "finger" binary.
+
+2006-12-07 12:22 we7u
+
+ * xastir-lsb.spec.in, scripts/LSB-BUILD: Changing install location
+ for LSB-like (non-certified) version from /opt/lsb-xastir/ to
+ /opt/Xastir/
+
+2006-12-07 12:09 we7u
+
+ * xastir-lsb.spec.in: Changing the install location from
+ /opt/lsb-xastir to /opt/xastir. We don't have (and probably will
+ never request/pay for) LSB compliance.
+
+2006-12-07 11:58 we7u
+
+ * Makefile.am, xastir-lsb.spec.in: Adding more docs to the install
+ locations.
+
+2006-12-07 11:49 we7u
+
+ * scripts/: LSB-BUILD-ALL, LSB-BUILD-CURL, LSB-BUILD-DB,
+ LSB-BUILD-GDAL, LSB-BUILD-GRAPHICSMAGICK, LSB-BUILD-JASPER,
+ LSB-BUILD-JPEG, LSB-BUILD-LESSTIF, LSB-BUILD-PCRE, LSB-BUILD-PNG,
+ LSB-BUILD-ZLIB: Adding a comment which states we do NOT have LSB
+ compliance.
+
+2006-12-07 11:48 we7u
+
+ * xastir-lsb.spec.in, scripts/LSB-BUILD: Adding a comment which
+ states that we do NOT have LSB-compliance.
+
+2006-12-07 11:47 we7u
+
+ * LICENSE: Documenting the licenses for the optional libraries that
+ we might distribute with an Xastir statically-linked binary.
+
+2006-12-07 11:47 we7u
+
+ * COPYING.LIB.LESSTIF: Adding the license file for Lesstif, for the
+ case where we're distributing an Xastir statically-linked binary.
+
+2006-12-07 09:33 we7u
+
+ * configure.ac, scripts/LSB-BUILD, scripts/LSB-BUILD-ALL,
+ scripts/LSB-BUILD-CURL, scripts/LSB-BUILD-DB,
+ scripts/LSB-BUILD-GRAPHICSMAGICK, scripts/LSB-BUILD-JASPER,
+ scripts/LSB-BUILD-JPEG, scripts/LSB-BUILD-LESSTIF,
+ scripts/LSB-BUILD-PCRE, scripts/LSB-BUILD-PNG,
+ scripts/LSB-BUILD-ZLIB: More changes to the LSB Xastir build and
+ the LSB build for the optional libraries. We now install the
+ libraries in /opt/lsb-tmp/ and then compile Xastir statically
+ against the libraries there, via symlinks from the
+ /opt/lsb/include/ and /opt/lsb/lib/ directories.
+
+2006-12-06 11:46 we7u
+
+ * scripts/: LSB-BUILD, LSB-BUILD-CURL, LSB-BUILD-DB,
+ LSB-BUILD-GDAL, LSB-BUILD-GRAPHICSMAGICK, LSB-BUILD-JASPER,
+ LSB-BUILD-JPEG, LSB-BUILD-LESSTIF, LSB-BUILD-PCRE, LSB-BUILD-PNG,
+ LSB-BUILD-ZLIB: Minor tweaks for LSB compiling.
+
+2006-12-06 11:45 we7u
+
+ * scripts/LSB-BUILD-ALL: An one-stop-shopping script to build the
+ optional libraries under LSB before we compile Xastir under LSB.
+
+2006-12-05 12:45 we7u
+
+ * src/main.c: Correcting one comment.
+
+2006-12-05 06:43 we7u
+
+ * scripts/LSB-BUILD: Removing the gdal symlinks from the comments
+ as we've handled them in configure.ac/acinclude.m4 instead.
+ Xastir will look for gdal in /opt/lsb-gdal/lib and
+ /opt/lsb-gdal/include directories.
+
+2006-12-05 06:42 we7u
+
+ * configure.ac: Removing "(Experimental)" from the LSB summary
+ line. Changing "lsb" to "LSB" which is more proper.
+
+2006-12-04 11:52 we7u
+
+ * scripts/LSB-BUILD-GDAL: Adding a commented-out option. No effect
+ to the code.
+
+2006-12-04 09:51 tvrusso
+
+ * src/shapelib/contrib/: doc/shpproj.txt, tests/shpproj.sh: Just
+ noticed that I never cvs added these two files from the shapelib
+ distribution. Since we are currently distributing the whole
+ shapelib distribution with unmodified license, it is necessary to
+ include all of the whole shapelib distribution.
+
+2006-12-04 09:30 we7u
+
+ * scripts/LSB-BUILD-GDAL: Initial attempt to get GDAL compiled
+ under LSB. Not functional yet.
+
+2006-12-04 09:29 we7u
+
+ * scripts/LSB-BUILD: Added a couple of steps to create the .tar.bz2
+ file and transfer it to the download site.
+
+2006-12-04 08:27 we7u
+
+ * src/util.c: Enabling CURLOPT_NOSIGNAL option to libcurl if the
+ libcurl version supports it. This prevents segfaults for the
+ case where we get a DNS timeout when initiating a libcurl
+ transfer.
+
+2006-12-03 14:01 we7u
+
+ * scripts/LSB-BUILD: Changes in comments for GDAL compiling under
+ LSB. GDAL is not working yet though for LSB.
+
+2006-12-03 13:58 we7u
+
+ * configure.ac: Enabling GDAL library for LSB compile.
+
+2006-12-03 13:54 we7u
+
+ * src/util.c: Enabling another curl option if compiling w/LSB.
+
+2006-12-03 13:50 we7u
+
+ * src/track_gui.c: Adding a comment.
+
+2006-12-01 13:47 we7u
+
+ * configure.ac: Changing some of the text to GraphicsMagick when
+ doing LSB compiles.
+
+2006-12-01 13:47 we7u
+
+ * USRadar.geo: Changing the black value to match the LSB
+ GraphicsMagick.
+
+2006-12-01 13:38 we7u
+
+ * src/: map_geo.c, maps.c: Updating some messages to include
+ GraphicsMagick.
+
+2006-12-01 13:27 we7u
+
+ * scripts/: LSB-BUILD-DB, LSB-BUILD: Adding Berkeley DB to the LSB
+ build to enable map caching.
+
+2006-12-01 12:47 we7u
+
+ * scripts/LSB-BUILD-GRAPHICSMAGICK: Enabling PNG in the build. It
+ works now.
+
+2006-12-01 12:46 we7u
+
+ * scripts/LSB-BUILD: Updating the build comments.
+
+2006-12-01 12:21 we7u
+
+ * scripts/LSB-BUILD-JASPER: An LSB build script for the Jasper
+ library, to give us jpeg-2000 support in GraphicsMagick.
+
+2006-12-01 12:20 we7u
+
+ * scripts/LSB-BUILD-GRAPHICSMAGICK: Making jpeg images work for us.
+
+2006-12-01 11:34 we7u
+
+ * scripts/LSB-BUILD: Updating some comments.
+
+2006-12-01 11:32 we7u
+
+ * configure.ac: GrahicsMagick-LSB changes.
+
+2006-12-01 09:49 we7u
+
+ * scripts/LSB-BUILD-GRAPHICSMAGICK: A build script for
+ GraphicsMagick under LSB.
+
+2006-12-01 09:48 we7u
+
+ * scripts/LSB-BUILD: Adding GrahicsMagick support.
+
+2006-12-01 07:49 we7u
+
+ * scripts/LSB-BUILD-PNG: Adding an LSB build script for the libpng
+ library, needed for GraphicsMagick or ImageMagick.
+
+2006-11-30 21:05 we7u
+
+ * scripts/LSB-BUILD-CURL: Adding an LSB build script for libcurl.
+
+2006-11-30 21:03 we7u
+
+ * scripts/LSB-BUILD: Updating the notes.
+
+2006-11-30 21:01 we7u
+
+ * configure.ac: Enabling libcurl for LSB.
+
+2006-11-30 13:20 we7u
+
+ * scripts/LSB-BUILD: Updating the comments.
+
+2006-11-30 13:15 we7u
+
+ * scripts/LSB-BUILD: Adding pcre and dbfawk to the LSB build
+ script.
+
+2006-11-30 13:14 we7u
+
+ * scripts/LSB-BUILD-PCRE: An LSB build script for the PCRE library.
+
+2006-11-30 12:33 we7u
+
+ * scripts/LSB-BUILD: Adding some comments.
+
+2006-11-30 12:04 we7u
+
+ * scripts/LSB-BUILD-LESSTIF: Adding a commented out command which
+ is useful to see what will be installed without actually
+ installing anything.
+
+2006-11-30 12:04 we7u
+
+ * scripts/LSB-BUILD: Modifying build to include geotiff and proj
+ support.
+
+2006-11-30 12:03 we7u
+
+ * scripts/: LSB-BUILD-JPEG, LSB-BUILD-ZLIB: Adding scripts to build
+ libjpeg and libz under LSB. Needed for geotiff support.
+
+2006-11-30 12:02 we7u
+
+ * configure.ac: LSB mods for geotiff.
+
+2006-11-30 09:26 we7u
+
+ * scripts/LSB-BUILD: Adding libproj to the mix. It is
+ LSB-compliant.
+
+2006-11-27 08:35 we7u
+
+ * scripts/LSB-BUILD: Adding rtree to the LSB build.
+
+2006-11-27 08:19 we7u
+
+ * scripts/LSB-BUILD-LESSTIF: Changes to comments.
+
+2006-11-27 08:18 we7u
+
+ * scripts/LSB-BUILD: Updating to match my current working copy of
+ the file.
+
+2006-11-27 08:17 we7u
+
+ * xastir-lsb.spec.in: Updating to match my current copy.
+
+2006-11-27 08:06 we7u
+
+ * src/map_geo.c: Adding an LF to one warning message.
+
+2006-11-24 11:57 we7u
+
+ * configure.ac: Adding the RPM spec file for LSB.
+
+2006-11-24 11:51 we7u
+
+ * xastir-lsb.spec.in: Inital attempt at an RPM spec file for LSB.
+ Not complete yet.
+
+2006-11-24 11:46 we7u
+
+ * xastir-min.spec.in, xastir.spec.in: Correcting the "Source" line
+ in the header so the version number comes out right.
+
+2006-11-22 11:48 we7u
+
+ * scripts/LSB-BUILD-LESSTIF: Updating comments.
+
+2006-11-22 11:46 we7u
+
+ * scripts/LSB-BUILD: Stripping the executables created, adding some
+ more comments.
+
+2006-11-22 11:30 we7u
+
+ * scripts/LSB-BUILD-LESSTIF: Updating the notes at the top to show
+ the SUCCESSFUL way of compiling Lesstif against LSB.
+
+2006-11-22 11:27 we7u
+
+ * scripts/LSB-BUILD: Updated to show latest LSB build method.
+
+2006-11-21 07:52 we7u
+
+ * scripts/LSB-BUILD: Updating the comments.
+
+2006-11-21 07:35 we7u
+
+ * scripts/LSB-BUILD-LESSTIF: Adding more comments at the top.
+
+2006-11-20 15:37 we7u
+
+ * scripts/LSB-BUILD-LESSTIF: Adding a comment, commenting out a
+ currently-unused line, and enabling shared libs to be created.
+
+2006-11-20 15:33 we7u
+
+ * scripts/LSB-BUILD: Adding a comment plus commenting out a
+ currently-unused line.
+
+2006-11-20 15:17 we7u
+
+ * configure.ac: Another LSB mod.
+
+2006-11-20 14:52 we7u
+
+ * scripts/: LSB-BUILD, LSB-BUILD-LESSTIF: Preliminary scripts for
+ building LSB-compatible Lesstif and Xastir. They're not fully
+ functional yet.
+
+2006-11-20 14:50 we7u
+
+ * scripts/fcc-get: Fixing the RCS tag.
+
+2006-11-20 10:31 we7u
+
+ * src/shapelib/Makefile.am: Updating the Copyright year.
+
+2006-11-20 10:24 we7u
+
+ * scripts/fcc-get: Changing the RAC portion of the script to match
+ their current server configuration.
+
+2006-11-19 14:05 tvrusso
+
+ * README.win32: Another tiny update to README.win32 to bring it
+ up-to-date with the reality of today's cygwin and sync with the
+ Wiki HowTo:Windows page.
+
+2006-11-19 14:00 tvrusso
+
+ * README.win32: Fix up another little issue with this document.
+
+ I'm doing this piecemeal, because I'm finding things as I'm
+ editing the same information on the Wiki, and want this file to
+ be consistent with that.
+
+2006-11-19 13:56 tvrusso
+
+ * README.win32: Fix up a little error in the "building shapelib
+ from source" section. It referred to a "_reent" error when
+ really it was about the error involving "__getreent".
+
+2006-11-19 13:34 tvrusso
+
+ * README.win32: Add note about preferring internal shapelib support
+ unless the external is needed for something other than xastir.
+
+ This should cut down on our "How do I get around this error
+ message..." support questions from new Cygwin users.
+
+2006-11-17 07:45 kg4ijb
+
+ * ChangeLog: [no log message]
+
+2006-11-17 00:53 tvrusso
+
+ * scripts/get-maptools.sh: Found yet another annoying issue with
+ libgeotiff build on ubuntu (and probably anywhere where gcc 4 is
+ used).
+
+ The problem is that the official tarball has the modification
+ times of configure.in newer than configure, and a makefile that
+ regenerates configure whenever it's older than configure.in ---
+ and then runs it with no arguments. Since we need to run
+ configure with some arguments, that completely messes everything
+ up.
+
+ Add a "touch configure" command to the commented-out part of the
+ script that makes configure newer than configure.in and bypasses
+ that part of the Makefile. A kludge upon a kludge upon a
+ kludge.
+
+ I missed this subtlety because when I finally tracked down the
+ "ld -shared" issue, it was in a dirty directory -- one that had
+ already had configure regenerated and which therefore no longer
+ had the broken timestamps.
+
+2006-11-16 21:31 tvrusso
+
+ * scripts/get-maptools.sh: Add commented-out fix for GCC 4.x issues
+ with libgeotiff.
+
+ Not uncommenting them, because it might be wrong on some
+ platforms that don't use GCC at all.
+
+2006-11-16 20:13 tvrusso
+
+ * scripts/get-maptools.sh: A number of small fixes to the
+ get-maptools script: 1) Make sure $XASTIR_TMP exists before
+ trying to download files into it 2) Fix a typo (LDCONf_FILE vs.
+ LDCONF_FILE) 3) Update version of gdal to 1.3.2 (1.3.1 does not
+ compile in recent GCC) 4) Build geotiff before gdal, since gdal
+ will use the libgeotiff if it finds it.
+
+2006-11-16 09:12 we7u
+
+ * Makefile.am: Getting rid of the symlink I recently added which
+ pointed from /usr/local/share/xastir/doc to
+ /usr/local/doc/xastir. Near as I can tell we're fairly well
+ FHS-compliant now with Xastir.
+
+2006-11-15 12:11 we7u
+
+ * Makefile.am: Forcing the removal of the old
+ $prefix/share/xastir/doc directory and creating a symlink to the
+ new location.
+
+2006-11-15 11:49 we7u
+
+ * Makefile.am, xastir-min.spec.in, xastir.spec.in: Moving the doc
+ files to an FHS-compliant directory. For a user installing from
+ sources they'll get installed in "/usr/local/share/doc/xastir/"
+ instead of the old location of "/usr/local/share/xastir/doc".
+
+2006-11-15 08:45 we7u
+
+ * Makefile.am, xastir-min.spec.in, xastir.spec.in: Changing the man
+ page directory from $prefix/man to $prefix/share/man, per FHS-2.3
+ and LSB-3.1
+
+2006-11-15 07:50 we7u
+
+ * xastir-min.spec.in: Changing "--without-shapelib" to
+ "--with-internal-shapelib" to take adantage of the new shapelib
+ library we include with Xastir.
+
+2006-11-15 07:48 we7u
+
+ * .cvsignore: Adding two derived files back in.
+
+2006-11-15 07:47 we7u
+
+ * xastir-min.spec, xastir.spec: Put these files into CVS by
+ mistake. They are derived files. Silly me.
+
+2006-11-15 07:08 we7u
+
+ * scripts/BUILDRPMS: Changing the "minimum" description to include
+ building with internal Shapelib.
+
+2006-11-15 07:08 we7u
+
+ * .cvsignore: Updating for current list of files.
+
+2006-11-15 07:07 we7u
+
+ * xastir-min.spec, xastir.spec: Adding the spec files that I've
+ been using. I'm surprised that they weren't added before, but I
+ had added them to my .cvsignore file and so didn't notice.
+
+2006-11-14 13:30 we7u
+
+ * src/shapelib/dbfopen.c: The last revision also commented out an
+ unused variable that I forgot to mention in the cvs log.
+
+2006-11-14 13:28 we7u
+
+ * src/shapelib/: shpopen.c, shptree.c: Commenting out some
+ variables that give off compiler warnings.
+
+2006-11-14 13:28 we7u
+
+ * src/shapelib/dbfopen.c: Casting a couple of variables to int's to
+ get rid of compiler warnings.
+
+2006-11-14 12:58 we7u
+
+ * README.Getting-Started: Adding missing command-line options to
+ the docs.
+
+2006-11-14 12:42 we7u
+
+ * src/xa_config.c: Changing some default settings, useful for
+ first-time users of Xastir to see what more of the options might
+ be plus give them a good operational starting point.
+
+2006-11-14 12:09 kg4ijb
+
+ * ChangeLog: [no log message]
+
+2006-11-14 11:52 we7u
+
+ * configure.ac: Fixing up the Shapelib config options.
+
+2006-11-14 11:52 we7u
+
+ * xastir.1: Updating the man page a bit.
+
+2006-11-14 08:28 we7u
+
+ * configure.ac: Changes to make it obvious in the configure output
+ text and in Help->About that we're using the internal Shapelib.
+ This change doesn't affect summary.log.
+
+2006-11-14 07:41 we7u
+
+ * src/main.c: Putting a newline in front of the Motif version
+ string in Help->About.
+
+2006-11-14 00:19 tvrusso
+
+ * configure.ac: Fix the "-I" flag in CPPFLAGS when local shapelib
+ is being built.
+
+ As it was, the compiler would not find the local shapefil.h file
+ unless you were building in the actual xastir source code
+ directory, or if shapefil.h was already installed system-wide.
+
+ Noticed this while attempting a fresh build on a brand new
+ laptop, on which I'd decided to attempt the simplest possible
+ build, with no shapelib installed.
+
+2006-11-13 11:46 we7u
+
+ * README.Getting-Started: Added notes about the private copy of
+ Shapelib and when it might be used, the "wget" requirement for
+ the get-NWSdata script, putting in a callsign when initially
+ starting Xastir, and a list of various places to get Xastir help.
+
+2006-11-13 11:43 we7u
+
+ * README.win32: Mentioning the private Shapelib version and when it
+ might be used.
+
+2006-11-13 11:43 we7u
+
+ * README.MAPS: Mentioning "wget" as a requirement for get-NWSdata.
+ Mentioning the private install of Shapelib.
+
+2006-11-13 11:41 we7u
+
+ * INSTALL: Adding info about the alternate method of getting
+ Shapefile support.
+
+2006-11-13 07:10 tvrusso
+
+ * README.Contributing: Fix up a mistake in the description of
+ "build directories", and add a reference to that technique to an
+ earlier section that advocates doing all the builds in the source
+ directory.
+
+ Build directories are such a powerful tool for developers, we
+ should make sure we recommend it when talking about doing
+ multiple builds.
+
+2006-11-13 06:56 tvrusso
+
+ * README.win32: Attach a date to qualify the meaning of "latest" in
+ the ImageMagick section.
+
+2006-11-13 06:48 tvrusso
+
+ * src/Makefile.am: Add a testawk_LDADD line to src/Makefile.am so
+ that this test program can link if shapelib is not installed.
+
+ I have no idea why this didn't fail when I was testing the
+ shapelib addition.
+
+2006-11-13 06:25 we7u
+
+ * README.win32: Updating the description for ImageMagick bug.
+
+2006-11-13 06:24 we7u
+
+ * src/: .cvsignore, shapelib/.cvsignore: Adding another couple of
+ derived files to the .cvsignore file.
+
+2006-11-12 17:36 we7u
+
+ * src/main.c: Enabling default map on initial startup, plus if the
+ callsign is "NOCALL", bring up the Configure->Station dialog.
+
+2006-11-12 17:26 we7u
+
+ * src/xa_config.c: Getting rid of many of the messages you get on
+ startup when config file settings are missing.
+
+2006-11-11 16:26 tvrusso
+
+ * src/shapelib/contrib/Makefile.am: Add CVS revision information
+ and copyright.
+
+2006-11-11 16:11 we7u
+
+ * README.MAPS: Adding attribution for the default map.
+
+2006-11-11 15:46 tvrusso
+
+ * configure.ac, src/shapelib/Makefile.am, src/shapelib/shprewind,
+ src/shapelib/contrib/.cvsignore, src/shapelib/contrib/Makefile,
+ src/shapelib/contrib/Makefile.am,
+ src/shapelib/contrib/Makefile_orig: Add EXTRA_DIST and
+ DIST_SUBDIRS lines so that the shapelib stuff is properly bundled
+ when doing a "make dist" for release.
+
+ The Makefile.am in the contrib directory does not actually build
+ any of the contrib codes. That's another step for another
+ moment. I just wanted to make sure that any make dist that is
+ done is sure to bundle the entire shapelib directory in order to
+ comply with the terms of the license.
+
+ The "Makefile_orig" script in the shapelib/contrib directory
+ could be used temporarily to build the shapelib tools.
+ Ultimately, they could be built by the new makefile, but it's not
+ really the goal of this exercise to do all that. In fact, at
+ some point it might be reasonable for xastir's shapelib directory
+ to contain only the files needed for building the library, but
+ that will probably require modifying it to be under GPL instead
+ of LGPL. That's just a matter of editing some license files, not
+ any code.
+
+ Also, removed the shprewind file from the shapelib directory.
+ This is a linux binary that for some reason was in the shapelib
+ source tarball I had. It should never have been added to
+ xastir's CVS repository.
+
+2006-11-11 15:01 we7u
+
+ * Makefile.am: Adding a default map to the distribution.
+
+2006-11-11 14:51 we7u
+
+ * worldhi.map: Adding a default map. Map was created by Keith
+ Sproul, WU2Z, and used with his permission.
+
+2006-11-10 13:49 tvrusso
+
+ * src/shapelib/.cvsignore: Add .cvsignore.
+
+2006-11-10 13:49 tvrusso
+
+ * src/shapelib/Makefile.in: CVS cleanup.
+
+2006-11-10 13:48 tvrusso
+
+ * configure.ac, src/Makefile.am, src/shapelib/ChangeLog,
+ src/shapelib/LICENSE.LGPL, src/shapelib/Makefile.am,
+ src/shapelib/Makefile.in, src/shapelib/Makefile_shapelib_orig,
+ src/shapelib/README, src/shapelib/README.tree,
+ src/shapelib/dbf_api.html, src/shapelib/dbfadd.c,
+ src/shapelib/dbfcreate.c, src/shapelib/dbfdump.c,
+ src/shapelib/dbfopen.c, src/shapelib/libtool,
+ src/shapelib/makefile.vc, src/shapelib/makeshape.sh,
+ src/shapelib/mkinstalldirs, src/shapelib/shapefil.h,
+ src/shapelib/shapelib.def, src/shapelib/shapelib.html,
+ src/shapelib/shp_api.html, src/shapelib/shpadd.c,
+ src/shapelib/shpcreate.c, src/shapelib/shpdump.c,
+ src/shapelib/shpopen.c, src/shapelib/shprewind,
+ src/shapelib/shprewind.c, src/shapelib/shptest.c,
+ src/shapelib/shptree.c, src/shapelib/shptreedump.c,
+ src/shapelib/shputils.c, src/shapelib/stream1.out,
+ src/shapelib/stream1.sh, src/shapelib/stream2.out,
+ src/shapelib/stream2.sh, src/shapelib/stream3.out,
+ src/shapelib/contrib/Makefile,
+ src/shapelib/contrib/ShapeFileII.pas,
+ src/shapelib/contrib/dbfcat.c, src/shapelib/contrib/dbfinfo.c,
+ src/shapelib/contrib/makefile.vc, src/shapelib/contrib/my_nan.h,
+ src/shapelib/contrib/shpcat.c, src/shapelib/contrib/shpcentrd.c,
+ src/shapelib/contrib/shpdata.c, src/shapelib/contrib/shpdxf.c,
+ src/shapelib/contrib/shpfix.c, src/shapelib/contrib/shpgeo.c,
+ src/shapelib/contrib/shpgeo.h, src/shapelib/contrib/shpinfo.c,
+ src/shapelib/contrib/shpproj.c, src/shapelib/contrib/shpwkb.c:
+ Add shapelib as an internal library, and use it if we don't find
+ an external one.
+
+ Make a loud warning if we do so, because the result of this is
+ that we'll have a bigger executable.
+
+ This commit is bigger than it needs to be, because it includes
+ all of shapelib, including the contrib directory.
+
+ Added an automake-generated Makefile for this thing.
+
+ Builds only a static library, and calls it "libshape.a" instead
+ of "libshp.a" so that if we use ask to use the static one while
+ there is also an external one installed, the linker doesn't pull
+ in the shared library one unbidden.
+
+ This stuff can be tested on a system with libshp installed by
+ configuring with "--without-shapelib"
+
+ I will be removing Makefile.in because it's not supposed to be in
+ CVS. My mistake.
+
+2006-11-09 14:34 kg4ijb
+
+ * ChangeLog: [no log message]
+
+2006-11-09 08:23 we7u
+
+ * src/xa_config.c: Changing the default window size on initial
+ startup. The minimum width/height are set up in
+ main.c:create_appshell() anyway, so we can't reduce the window
+ small enough to cause segfaults by doing this change.
+
+2006-11-09 08:21 we7u
+
+ * src/main.c: Changed one comment. No code changes.
+
+2006-11-05 17:16 tvrusso
+
+ * README.win32: Add information about problems with Cygwin
+ ImageMagick. The notes in the README.win32 refer to "recent
+ versions" of cygwin containing ImageMagick 5.5.7, which is very
+ outdated. Current versions of Cygwin come with 6.0.4, and there
+ are real problems due to that version being linked with Display
+ Postscript support --- X.org stopped supporting that, and now
+ ImageMagick doesn't work on Cygwin unless you find a few DLLs off
+ the net.
+
+ The paragraph I added here points the user at an article that
+ explains the issue and shows two workarounds (installing the DLLs
+ or building ImageMagick from source code instead).
+
+2006-11-03 12:31 we7u
+
+ * src/util.c: Adding a diff by Tapio Sokura, which a few comment
+ changes by me. Thanks! This fixes the lower-case callsigns
+ problem for internet paths.
+
+2006-11-02 10:34 we7u
+
+ * scripts/BUILDRPMS: Setting up for building RPM's for the current
+ development version.
+
+2006-11-02 08:03 we7u
+
+ * configure.ac: Setting up for the next development source version
+ number.
+
+2006-11-02 06:43 we7u
+
+ * configure.ac, scripts/BUILDRPMS, scripts/do_xastir_release_dev,
+ scripts/do_xastir_release_stable: Setting up to do the 1.8.4
+ release.
+
+2006-11-01 06:57 we7u
+
+ * config/language-German.sys: Updates by Rolf Bleher. Thanks!
+
+2006-10-26 08:52 we7u
+
+ * Davis/: configure.ac, src/db2APRS.c, src/defs.h: Tweaks by Bruce
+ Bennett: "I fixed some issues brought out by the latest MySQL
+ (5.0.x ver), added metric/english switch, rooted out some old
+ bugs and made some improvement on debug messages."
+
+2006-10-26 06:50 we7u
+
+ * src/db.c: Fixing problems with Aloha circle units in multiple
+ places.
+
+2006-10-25 08:16 we7u
+
+ * REGRESSION_TESTS: Lining up the line to match the rest.
+
+2006-10-24 11:03 we7u
+
+ * REGRESSION_TESTS: Adding another test which disables the
+ /usr/include/magick/ directory before attempting a compile. This
+ disables ImageMagick.
+
+2006-10-24 11:02 we7u
+
+ * src/map_geo.c: Adding another two ifdef's so that the code will
+ compile in the case that we have XPM support but no ImageMagick
+ support.
+
+2006-10-11 14:39 we7u
+
+ * src/db.c: Another patch by Jesse, KF4HZU. Thanks!
+
+2006-10-05 09:11 we7u
+
+ * src/db.c: Skipping any processing of lines from logfiles that
+ begin with '#'.
+
+2006-10-05 08:29 we7u
+
+ * src/db.c: A fix for numeric overlays on base-91 packets by Jesse,
+ KF4HZU.
+
+2006-10-05 07:46 we7u
+
+ * src/db.c: Some SKY bulletins came in that had "EMERGENCY" in the
+ text. This caused Xastir to try to process the packets twice on
+ order to get a position first and then pop up the emergency
+ dialogs. Since there was no position in the packet this caused
+ an infinite loop as Xastir passed the packet through the
+ processing again and again. The fix is to NOT send a packet
+ through the processing again, which will make it necessary for
+ Xastir to receive two EMERGENCY packets if a position is not
+ known yet for the station, but it will at least not cause Xastir
+ to get in an infinite loop. We also skip storing any SKY packets
+ now as they just take up memory and we never do anything further
+ with the packets.
+
+2006-09-27 12:23 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Adding US National
+ Grid designator to the MGRS label. If in NAD83/WGS84 they are
+ equivalent.
+
+2006-09-25 06:24 we7u
+
+ * src/main.c: A tweak by Dick Reichenbach, KC8OBZ, to split the
+ status line into two lines when using a 640x480 display. Thanks!
+
+2006-09-20 08:22 tvrusso
+
+ * src/interface.c: Add comments to show where it is necessary to
+ fix data_out_ax25 so that it isn't confused by leading
+ white-space in commands.
+
+ No code changes. The idea was to document what I know I need to
+ do to fix the problem that Mike Fenske saw when the \r was added
+ before MYCALL commands. The quick fix was not to add the \r if
+ sending to an AX25 port, but the clean fix would be to make
+ data_out_ax25 not care about leading white space.
+
+2006-09-19 20:14 tvrusso
+
+ * src/interface.c: What might be a less intrusive way of
+ introducing that extra carriage return into the MYCALL line.
+
+ The code for AX25 ports tries to decode the mycall line, and that
+ decoding was getting confused by the leading \r. This quick
+ "fix" simply checks to see if we're writing to an AX25 port, and
+ if so, doesn't add the \r.
+
+ A more correct way to fix this would be to fix the decoding of
+ MYCALLs by data_out_ax25 so it doesn't get tripped up by the
+ first \r. This is meant to be a quick hack to let both things
+ work properly until I figure out how to desensitize
+ data_out_ax25.
+
+2006-09-19 19:55 tvrusso
+
+ * src/interface.c: Removing carriage return I had put in before
+ MYCALL sent to TNCs.
+
+ The original intent was to do what was supposed to be an
+ inconsequential extra carriage return when writing to the TNC to
+ work around some garbled data issues that are happening on
+ D700s.
+
+ Unfortunately, some bit of code downstream of
+ "output_my_aprs_data" is seeing the extra carriage return and
+ screwing up. Bleah.
+
+ Removing the "fix" until I figure out what is going on.
+
+2006-09-19 09:12 chicoreus
+
+ * src/list_gui.c: Removing double cast.
+
+2006-09-19 08:58 chicoreus
+
+ * src/: database.h, db.c, list_gui.c: Fixing bugs in previous
+ commit. Added note about database.h being name used instead of
+ db.h Previous commit email message bounced, changes were:
+
+ 1) Converted hard coded MY_TRAIL_DIFF_COLOR to user configurable
+ my_trail_diff_color and added to configuration ui and config
+ file. 2) Linked station icon in station list to an onclick
+ callback to center the map on the station. Included alternate
+ callback to pop up station details window. Needs checking, as I
+ think the callback needs to filter mouse events. 3) Added, but
+ haven't yet internationalized display of area in acres when
+ measuring distances/areas on the map. Needs to be generalised
+ and linked to all the places display of an area might be desired.
+
+2006-09-19 07:43 chicoreus
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, help/help-English.dat, src/db.c,
+ src/list_gui.c, src/main.c, src/main.h, src/xa_config.c: Three
+ changes: 1) Converted hard coded MY_TRAIL_DIFF_COLOR to user
+ configurable my_trail_diff_color and added to configuration ui
+ and config file. 2) Linked station icon in station list to an
+ onclick callback to center the map on the station. Included
+ alternate callback to pop up station details window. Needs
+ checking, as I think the callback needs to filter mouse events.
+ 3) Added, but haven't yet internationalized display of area in
+ acres when measuring distances/areas on the map. Needs to be
+ generalised and linked to all the places display of an area might
+ be desired.
+
+2006-09-19 06:55 we7u
+
+ * src/db.c: Removing the '*' after our callsign when injecting
+ packets into the internet (our injection ID that we add).
+
+2006-09-15 09:59 tvrusso
+
+ * src/interface.c: Inexplicable fix for an equally inexplicable but
+ very persistent problem.
+
+ My Kenwood D700 complains loudly ("EH?") almost every time Xastir
+ tries to set MYCALL before a posit.
+
+ This commit adds a carriage return right before MYCALL is sent.
+ For whatever reason, this eliminates the problem. Clearly, the
+ d700 gets in some strange state where the first command sent
+ after re-entering command mode is not recognized every time.
+
+ Since a failure of MYCALL to be set before transmit can mean the
+ wrong callsign (or NOCALL) being attached to a posit, this is
+ potentially a significant fix. I will comment more on it in a
+ follow-up email to the users mailing list.
+
+2006-09-15 09:53 we7u
+
+ * INSTALL: A tweak by Chip, N1MIE.
+
+2006-09-10 18:03 we7u
+
+ * src/db.c: Backing out the igate changes until they can be tested
+ further. They appear to have broken most or all igating -> RF.
+
+2006-09-08 17:35 we7u
+
+ * src/: db.c, main.c, main.h, messages.c, messages_gui.c,
+ popup_gui.c, track_gui.c: Implementing command-line flags for
+ tracking a station and for disabling popups plus disabling Send
+ Message dialogs on incoming messages. May need some more
+ tweaking to get rid of all popups, but this should be a good
+ start.
+
+2006-09-08 11:10 we7u
+
+ * src/db.c: Attempting to igate more types of packets to RF, for
+ the cases where it is appropriate to do so. This should fix the
+ directed query problem, at least when gating _to_ RF. Will look
+ at the other case as well (gating->INET), which may not be
+ broken.
+
+2006-09-02 16:43 we7u
+
+ * src/db.c: Adding parsing for RDF packets, with checking to make
+ sure they really _are_ RDF packets this time.
+
+2006-09-01 06:21 we7u
+
+ * src/db.c: Added a date/timestamp to bearing/distance popup for
+ emergency packets.
+
+2006-09-01 06:05 we7u
+
+ * src/db.c: Tweaking the processing of emergency packets (Mic_E
+ packets and standard packets) so that the packet gets processed
+ twice if the first time comes up with a 0.0 distance (which means
+ an unknown distance). This often allows us to match our distance
+ check ( < 280 miles ) the first time a packet is received,
+ instead of having to wait for the 2nd occurrence of the packet.
+ Also: We now bring up a popup with the bearing and distance to
+ the emergency station if it passes our checks.
+
+2006-09-01 04:46 we7u
+
+ * src/db.c: Added another comment in the RDF section.
+
+2006-09-01 04:45 we7u
+
+ * src/messages_gui.c: Changing input focus to the first message box
+ after sending each message. For D700 or D7 mode to make typing
+ messages easier.
+
+2006-08-31 14:36 we7u
+
+ * src/: db.c, main.c, maps.c, maps.h, util.c, util.h: Writing wx
+ alerts to file in the correct format now. Storing/restoring wx
+ alerts from file. Fixed a bug in the weather alerts code where
+ they wouldn't draw right away.
+
+2006-08-31 14:27 we7u
+
+ * src/wx_gui.c: Skipping NULL alert entries instead of returning
+ when we hit the first one. This lets us see all of the active
+ alerts.
+
+2006-08-30 12:29 we7u
+
+ * src/: db.c, main.c, main.h, messages_gui.c, xa_config.c: Logging
+ for messages and weather alerts. Starting to add more buttons to
+ the Send Message->Change Path dialog.
+
+2006-08-30 12:21 we7u
+
+ * src/Makefile.am: Putting the files in correct alphabetical order.
+
+2006-08-30 04:38 we7u
+
+ * src/db.c: This change implements the capability to receive
+ messages that were sent to our other SSID's. We don't ack them.
+ They cause a Send Message box to pop up like normal except
+ there's a special note prepended to each message line stating
+ which SSID the message was sent to. This allows us to catch
+ messages sent to our other stations and respond to them if
+ desired. We skip displaying these messages if the message
+ originated from our station, as two message boxes for the same
+ QSO is very confusing (and unnecessary).
+
+2006-08-30 04:12 we7u
+
+ * src/interface.c: Fixes for KISS mode when using "DIRECT PATH".
+
+2006-08-29 15:34 we7u
+
+ * src/: db.c, main.c: Adding context-sensitive Send Message To
+ option to the mouse menu.
+
+2006-08-29 15:26 we7u
+
+ * src/messages_gui.c: Changing to APRHH and APHH as the TOCALLS
+ which mean a HamHUD.
+
+2006-08-29 15:24 we7u
+
+ * src/view_message_gui.c: Making "Mine Only" take precedence over
+ the range in the View->Messages dialog.
+
+2006-08-29 07:31 we7u
+
+ * src/messages_gui.c: Minor fixes to the Send Message changes.
+ Tied the select_station_type capability into the New/Refresh
+ Callsign button as well.
+
+2006-08-29 05:15 we7u
+
+ * src/xa_config.c: Checking for blank strings in config file,
+ replacing with defaults where it makes sense.
+
+2006-08-28 18:01 we7u
+
+ * src/messages_gui.c: Fixing HamHUD-II detect and setting max size
+ of messages to 20 for that device.
+
+2006-08-28 16:23 we7u
+
+ * src/messages_gui.c: Initial attempt to have the Send Message
+ dialog automatically choose the HamHUD/D700/D7 settings based on
+ the remote station.
+
+2006-08-28 12:29 we7u
+
+ * src/: messages.c, messages.h, messages_gui.c: Added Send Message
+ formatting for HamHUD 20-character display.
+
+2006-08-25 15:33 we7u
+
+ * src/: db.c, messages.c, messages.h, messages_gui.c: Adding error
+ messages to the Send Message dialog. Fixing directed queries.
+ Adding D7A and D700 input modes to the Send Message dialog.
+ Fixed a long message bug so 67-char messages can now be sent.
+
+2006-08-25 15:24 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Adding some
+ warning messages for the Send Message dialog.
+
+2006-08-25 04:42 we7u
+
+ * src/db.c: Changed the Capabilities display in View Incoming Data
+ so that it shows my own outgoing ?IGATE? packets as well.
+
+2006-08-25 04:25 we7u
+
+ * src/messages_gui.c: Updated some comments. No code changes.
+
+2006-08-24 16:49 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c, src/main.h,
+ src/messages_gui.c, src/view_message_gui.c: Implementing Station
+ Capabilities and Mine Only options on Incoming Data dialog.
+ Added Mine Only and interface selection options to View Messages
+ dialog.
+
+2006-08-24 16:29 we7u
+
+ * src/popup_gui.c: Protecting popup functions from possible bad
+ inputs.
+
+2006-08-23 13:45 we7u
+
+ * src/db.c: Implemented 120-second random delay before responding
+ to an ?IGATE? query. Implemented the response for an ?APRS?
+ query, including the 120-second random delay.
+
+2006-08-23 08:53 we7u
+
+ * src/main.c: Refuse to print out the measured angle for the case
+ where we're doing on-screen measuring at zoom==1. Angles change
+ at that zoom level.
+
+2006-08-23 08:09 we7u
+
+ * src/map_geo.c: Adding a comment about a future Terra/Toposerver
+ enhancement: Crossing UTM zone boundaries, splitting the map
+ fetch into two fetches.
+
+2006-08-23 07:14 we7u
+
+ * src/maps.c: Added more debug output from map_visible()
+
+2006-08-23 07:14 we7u
+
+ * src/map_geo.c: Separating "zstr" used in UTM->lat/long calls into
+ zstr0 and ztr1. We were running into problems when we crossed
+ UTM zones with a map.
+
+2006-08-23 07:12 we7u
+
+ * src/main.c: Added a method to have Xastir spit out coordinates in
+ Xastir Coordinate System. Change a global variable at the top of
+ main.c to a 1 to enable it.
+
+2006-08-23 05:19 we7u
+
+ * src/maps.c: Adding some debug statements.
+
+2006-08-23 05:17 we7u
+
+ * src/map_geo.c: Changing one comment.
+
+2006-08-23 05:17 we7u
+
+ * src/main.c: Moving reload_object_item() and
+ Restore_CAD_Objects_from_file() from main() up into UpdateTime().
+ This is so that the image can be created and the global map
+ corner variables updates first. Points were getting rejected on
+ loading because these variables were not initialized yet.
+
+2006-08-22 11:20 tvrusso
+
+ * src/messages_gui.c: Fix the
+ Send_message_change_path_destroy_shell function so it doesn't
+ ever try to destroy a shell when the pointer is null.
+
+ This was causing segfaults for me whenever a messaging dialog was
+ closed, whether I'd accessed a change_path dialog or not.
+
+2006-08-22 08:27 we7u
+
+ * src/messages_gui.c: Closing the Change Path dialog if the Send
+ Message dialog is closed.
+
+2006-08-22 07:20 we7u
+
+ * src/messages_gui.c: Setting the path and change path widgets so
+ that they stretch properly with the dialog.
+
+2006-08-22 07:12 we7u
+
+ * src/messages_gui.c: Simplifying the Send Message dialog a bit
+ more, taking the Reverse Path widgets out of that dialog. They
+ still exist in the Change Path dialog.
+
+2006-08-22 05:35 we7u
+
+ * src/messages_gui.c: Minor adjustments to the widgets of the Send
+ Message and Change Path dialogs.
+
+2006-08-22 04:55 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/messages_gui.c: Swapping a
+ couple of lines of widgets in the Send Message dialog. More
+ tweaks to lang strings for Send Message and Change path dialogs.
+
+2006-08-22 04:40 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/messages.h, src/messages_gui.c:
+ Creating language file entries for new Send Message and Change
+ Path widgets. Adding "Reverse Path:" labels to both dialogs.
+
+2006-08-22 04:08 we7u
+
+ * src/messages_gui.c: Changing reverse-path calculation to get rid
+ of Q-construct and anything after it before reversing the path.
+
+2006-08-21 19:35 we7u
+
+ * src/messages_gui.c: A better Send Message dialog. More testing
+ to be done yet, but so far it looks better than the old.
+
+2006-08-21 18:01 we7u
+
+ * src/: interface.c, messages.c, messages.h, messages_gui.c: The
+ beginnings of a separate dialog for changing the path from the
+ Send Message dialog. Mostly working as-is but not very pretty.
+
+2006-08-21 09:18 we7u
+
+ * src/messages_gui.c: Added some TODO comments to Send_Message().
+
+2006-08-21 06:58 we7u
+
+ * src/popup.h: Cranking up max popups to 30.
+
+2006-08-21 06:33 we7u
+
+ * src/db.c: A fix for bug #1474401, where an auto-answer or some
+ other message to us which doesn't have a message-ID ends up
+ showing up in a Group Message dialog. This fix makes them appear
+ in a Send Message dialog, plus we refuse to ack them which is
+ correct behavior.
+
+2006-08-21 04:44 we7u
+
+ * src/main.c: Changing from a 1us delay to a 2ms delay inside
+ UpdateTime(). Adding/ changing some comments.
+
+2006-08-21 04:42 we7u
+
+ * src/interface.c: Moving one debug line inside the data_lock block
+ to make sure it doesn't get corrupted by another thread.
+
+2006-08-19 15:19 we7u
+
+ * src/interface.c: More correct fixes for truncation problem with
+ new incoming data queue code.
+
+2006-08-19 11:54 we7u
+
+ * src/interface.c: A fix for the circular queue pointer problem.
+ The read pointer was not getting advanced in the same manner
+ around the queue as the write pointer, giving us an off-by-one
+ error.
+
+2006-08-19 10:42 we7u
+
+ * src/interface.c: A temporary fix to the new queue code problem
+ where it truncates the last character off the strings.
+
+2006-08-18 14:52 tvrusso
+
+ * src/map_shp.c: Remove commented-out ifndef of label-skipping
+ code. It won't be needed.
+
+2006-08-18 08:28 we7u
+
+ * src/map_shp.c: Adding an #ifndef block for Tom Russo to play
+ with. Currently commented out. If the block is enabled it will
+ cause Xastir to draw every label for each polyline instead of
+ skipping some based on zoom level.
+
+2006-08-18 06:57 we7u
+
+ * src/map_shp.c: Added some comments.
+
+2006-08-18 04:07 we7u
+
+ * src/: interface.c, interface.h, main.c: Shortening the delay at
+ the end of UpdateTime() again to 10. Global variables for
+ passing data from the read threads to main have been changed to a
+ circular queue. This lets us queue up data from the read threads
+ when we're busy drawing maps and such, then process it quickly
+ when we're freed up.
+
+2006-08-18 04:02 we7u
+
+ * src/x_spider.c: Shortening delays so that we don't corrupt
+ packets if we're fed them quickly by the pipe from Xastir.
+
+2006-08-17 05:59 we7u
+
+ * src/database.h: Renaming a function parameter so that it's not
+ confused with a global variable name.
+
+2006-08-17 05:47 we7u
+
+ * src/db.c: Renaming a function parameter so that it won't be
+ confused with a global variable name.
+
+2006-08-15 03:38 we7u
+
+ * src/map_shp.c: Patch for RTREE functionality with the new
+ Shapefile speed mods.
+
+2006-08-14 13:06 we7u
+
+ * src/map_shp.c: Fixing an infinite loop condition that can happen
+ if a Shapefile has points below -180.0 or above 180.0.
+
+2006-08-14 12:38 we7u
+
+ * src/track_gui.c: Changing from "sed --in-place" to "sed -i",
+ perhaps more compatible across versions?
+
+2006-08-14 12:34 we7u
+
+ * src/track_gui.c: Fixing findu.com fetch trail function for
+ base-91 packets w/no comment/course/speed/altitude.
+
+2006-08-14 11:01 we7u
+
+ * FAQ: Added another bit to the "remote restart" section.
+
+2006-08-14 08:53 we7u
+
+ * src/map_gnis.c: Reorganization to provide speedups. This one
+ cuts about 50% of the time when zoomed in.
+
+2006-08-14 08:52 we7u
+
+ * src/map_gdal.c: Limiting to screen size instead of +/-32767.
+ Added a comment about another possible optimization.
+
+2006-08-14 05:24 we7u
+
+ * INSTALL: Adding an invocation line for gprof that I use so I
+ don't need to figure it out each time.
+
+2006-08-14 05:12 we7u
+
+ * src/: map_gdal.c, map_shp.c, maps.c, maps.h: Removing error-text
+ parameter from map_visible_lat_lon() as we're not using it.
+ Changed the order of checks in map_visible_lat_lon() to perhaps
+ speed things up slightly based on which lines get his most often
+ (gprof). Changed skip parameter for HandlePendingEvents in
+ map_shp.c from 50 to 64, which is a power of 2 (perhaps faster?)
+ and roughly the switchover point (via gprof) for lower CPU.
+
+2006-08-11 16:58 we7u
+
+ * src/: db.c, draw_symbols.c, map_gdal.c, map_shp.c, maps.c,
+ maps.h, objects.c: Added dupe-checking for screen points to
+ draw_vector and draw_point. Reduced the number of
+ HandlePendingEvents calls we're doing inside the inner loop of
+ map_shp.c. The end result is a speedup in Shapefile drawing.
+
+2006-08-11 05:04 we7u
+
+ * src/maps.h: Getting rid of stub for recompute_lat_lon() function
+ which was deleted.
+
+2006-08-11 05:03 we7u
+
+ * src/: maps.c, util.c: Getting rid of duplicate code in the form
+ of recompute_lat_long() and the global variables it populated.
+ We have duplicate functionality in the f_NW_corner_longitude,
+ f_SE_corner_longitude, f_SE_corner_latitude, and
+ f_NW_corner_latitude global variables and the code that populates
+ them.
+
+2006-08-10 09:15 we7u
+
+ * src/db.c: Took out a bit too much on one of the previous 2 or 3
+ revisions. Adding computation of screen coordinates back in for
+ trail labels.
+
+2006-08-10 09:09 we7u
+
+ * src/: db.c, draw_symbols.c, map_gnis.c, map_shp.c, objects.c:
+ Moving screen boundary checks into draw_nice_string() and
+ removing them from lots of other places.
+
+2006-08-10 09:08 we7u
+
+ * src/maps.c: Adding a clip2d_screen() function for line-clipping
+ to screen boundaries. Not used yet.
+
+2006-08-10 06:01 we7u
+
+ * src/maps.c: Added some sanity checking for dbfawk font_size
+ variable.
+
+2006-08-10 05:41 we7u
+
+ * src/map_gdal.c: Added some comments.
+
+2006-08-10 04:35 we7u
+
+ * src/db.c: Changing to draw_point() instead of XDrawPoint for the
+ vertice point drawing of tracklines.
+
+2006-08-09 21:02 we7u
+
+ * src/: db.c, draw_symbols.c, util.h, main.c, map_dos.c,
+ map_gdal.c, map_gnis.c, map_shp.c, maps.c: Adding protection for
+ the parameters of the XDraw* calls, making sure they don't go
+ over 16 bits.
+
+2006-08-09 07:56 we7u
+
+ * src/draw_symbols.c: Changing the lu16 inline function to pass
+ back the correct type and check against the correct max number.
+ Added a bunch of comments elsewhere.
+
+2006-08-09 07:03 we7u
+
+ * src/draw_symbols.c: Limiting params to X11 drawing calls to
+ 16-bit values. This should help prevent segfaults. We're
+ actually limiting them more than we need to in most cases, but
+ this should be ok.
+
+2006-08-09 04:36 we7u
+
+ * src/db.c: Added a debug line and comment. This one lets us play
+ with/display aloha circles on startup if uncommented.
+
+2006-08-09 04:35 we7u
+
+ * src/draw_symbols.c: Fix for Aloha circle not getting drawn if it
+ doesn't fit entirely on the screen.
+
+2006-08-08 15:32 we7u
+
+ * src/Makefile.am: A fix for a permissions problem that happens
+ with compiledate.c every once in a while. This fix is by Dan
+ Brown.
+
+2006-08-08 15:30 we7u
+
+ * src/draw_symbols.h: Checking in a header file that didn't get
+ checked in with the other sources during the last commit.
+ Dropped a couple of parameters from the draw_symbol() function.
+
+2006-08-08 12:41 we7u
+
+ * src/: db.c, draw_symbols.c: Fixed draw_pod_circle(),
+ draw_bearing(), draw_phg_rng() and draw_DF_circle() so that they
+ draw even when the symbol is off-screen.
+
+2006-08-08 07:34 we7u
+
+ * src/db.c: Fix for ambiguity box not getting disabled.
+
+2006-08-08 06:05 we7u
+
+ * src/maps.c: Added some comments about possible optimizations in
+ the draw_point and draw_point_ll functions. Commented out the
+ check against drawing long vectors to screen there as the clip2d*
+ algorithms should take care of that for us.
+
+2006-08-08 05:36 we7u
+
+ * src/maps.c: Moving some of the functions to a different order
+ that makes more sense. No real code changes.
+
+2006-08-07 13:19 tvrusso
+
+ * config/: 24kgrid.dbfawk, nwsc_ddmmyy.dbfawk, nwsmzddmmyy.dbfawk,
+ nwsmzoddmmyy.dbfawk, nwsozddmmyy.dbfawk, nwsw_ddmmyy.dbfawk,
+ nwsz_ddmmyy.dbfawk, nwszoddmmyy.dbfawk, tgr2shp.dbfawk,
+ tgr2shppoly.dbfawk, tgrcty.dbfawk, tgrkgl.dbfawk, tgrlk.dbfawk,
+ tgrlpt.dbfawk, tgrlpy.dbfawk, tgrplc00.dbfawk, tgrwat.dbfawk: Fix
+ broken dbffields variables in all dbfawk files.
+
+ The dbfawk file is supposed to have semicolon-terminated
+ statements. Unfortunately, the parser is busted and doesn't
+ actually handle the case where the semicolons are omitted
+ correctly. So, for example,
+
+ BEGIN {
+ dbfinfo="Blah:Diblah:Diblahdiblah";
+ dbffields="Blah:Diblah:Diblahdiblah"
+ }
+
+ winds up getting the newline-space at the end of the line added
+ to dbffields, and thus in the list of names to be retrieved from
+ the dbf file. This never matches the last field when applied to
+ the dbf files, which have no such extra characters in the field
+ names.
+
+ This bug is masked by *how* the dbffields variables were actually
+ set in the included dbfawk files: BEGIN {
+ dbfinfo="Blah:Diblah:Diblahdiblah";
+ dbffields="Blah:Diblah:Diblahdiblah"}
+
+ That is, since there was no newline between " and }, dbfawk
+ didn't do the wrong thing.
+
+ Unfortunately, many people have patterned their own dbfawk files
+ after the ones in the config directory, and so this
+ missing-semicolon deal got propagated (I am among those
+ propagating it, as all my shape_web dbfawk files omitted the
+ semicolon, but also put the brace right after the "). The
+ problem only gets exposed when the user inserts a newline after
+ the quote.
+
+ This commit adds the semicolon (and a newline) after the
+ dbffields closing quote.
+
+ The real fix is to fix the dbfawk/awk parser so it doesn't let
+ syntax errors like this slip through.
+
+2006-08-07 12:56 we7u
+
+ * src/maps.c: Renaming the window corner global variables.
+
+2006-08-07 12:55 we7u
+
+ * src/main.c: Renaming the window corner global variables.
+ Updating some new global variables describing the SE corner in
+ float and long format when necessary.
+
+2006-08-07 12:53 we7u
+
+ * src/: objects.c, xa_config.c, util.c: Renaming the window corner
+ global variables.
+
+2006-08-07 12:50 we7u
+
+ * src/: location.c, location_gui.c, map_WMS.c, map_dos.c,
+ map_gdal.c, map_geo.c, map_gnis.c, map_pdb.c, map_shp.c,
+ map_tif.c, map_tiger.c: Renaming the window corner global
+ variables.
+
+2006-08-07 12:49 we7u
+
+ * src/: db.c, draw_symbols.c, xastir.h: Renaming the global
+ variables describing the corners of the map window. Fixes for
+ aloha circles and multipoing drawings so that they should appear
+ if the symbol they're attached to is off-screen.
+
+2006-08-07 06:49 we7u
+
+ * src/draw_symbols.c: Getting rid of unused code.
+
+2006-08-07 06:37 we7u
+
+ * src/maps.c: Adding clipt(), clip2d(), clipt_long(), and
+ clip2d_long() functions. These are implementations of the
+ Liang/Barsky/Slater line-clipping algorithm. Modified
+ draw_vector() and draw_vector_ll() to use them. Changing cutoff
+ points for points/vectors to be consistent (+/-16000).
+
+2006-08-07 06:33 we7u
+
+ * src/db.c: Changing draw_trail() to use the draw_vector()
+ function.
+
+2006-08-07 06:27 we7u
+
+ * src/: map_gdal.c, map_shp.c: Tweaking the pixel min/max cutoff
+ numbers to make them consistent throughout the code.
+
+2006-08-07 04:13 we7u
+
+ * src/draw_symbols.c: Changed one comment. No code changes.
+
+2006-08-04 07:35 we7u
+
+ * src/maps.c: Changed draw_point() so that if it lies outside the
+ screen we don't call the X11 draw routine.
+
+2006-08-04 05:57 we7u
+
+ * src/draw_symbols.c: A fix for dead-reckoning where the angle goes
+ whacko at close-in zoom levels.
+
+2006-08-04 04:42 we7u
+
+ * src/db.c: Setting the precision rectangle sizes for our own
+ station, whether transmit is enabled or not.
+
+2006-08-04 04:17 we7u
+
+ * src/track_gui.c: Using raw.cgi instead of rawposit.cgi to fetch
+ packets from findu. This allows us to snag ALL packets from the
+ station during the specified period instead of just posits.
+ Weather, status, etc.
+
+2006-08-04 03:55 we7u
+
+ * src/db.c: Fixing the display of altnet's. Somewhere along the
+ line we reversed it accidentally.
+
+2006-08-03 16:32 we7u
+
+ * src/db.c: Tweaking the NMEA decoding routines so that they pass
+ back the number of digits after the decimal point. Changing the
+ display for NMEA so that the number of digits changes the size of
+ the "precision" rectangle.
+
+2006-08-03 16:26 we7u
+
+ * src/util.c: Fixing convert_lat_s2l() and convert_lon_s2l() so
+ that they can handle from 0 to 6 characters after the decimal
+ point for lat/long conversions.
+
+2006-08-03 08:57 we7u
+
+ * src/: db.c, objects.c: Fixing the problem where objects don't
+ appear on the map after created. Also fixed transmission of
+ objects so that if they have a course/speed the new position is
+ sent out at the transmit interval.
+
+2006-08-03 03:46 we7u
+
+ * src/: database.h, db.c, draw_symbols.c, draw_symbols.h: The
+ beginnings of the correct way of drawing the "precision"
+ rectangles. Not all of the different types of packets are
+ correctly sized yet, but many are.
+
+2006-08-02 17:19 we7u
+
+ * src/: db.c, draw_symbols.c, draw_symbols.h: Changing "precision"
+ circles to rectangles, with the correct direction offset from the
+ symbol for the different hemispheres. They are slightly too
+ large at the moment, but at least of reasonable size.
+
+2006-08-02 08:26 we7u
+
+ * src/util.c: The chdir() call in log_data() appears to corrupt our
+ "file" parameter. We don't appear to need the chdir() function
+ call anyway, so have commented it out. We get passed the
+ complete root-anchored path/filename as-is.
+
+2006-08-02 05:30 we7u
+
+ * src/db.c: Allowing the Station Chooser dialog to be closed
+ without forcing the Station Info dialog to be closed. Commenting
+ out the restore_position section in Station_data() as it isn't
+ working correctly.
+
+2006-08-02 04:58 we7u
+
+ * src/objects.c: Changed/added some comments. No code changes.
+
+2006-08-02 04:53 we7u
+
+ * src/objects.c: Backing out the update of the Edit & Delete CAD
+ Objects dialogs when allocating the first vertice of a new CAD
+ Object. It's a bit confusing when the windows move on top of the
+ drawing area when you do the first click, so I decided not to
+ update then.
+
+2006-08-02 04:47 we7u
+
+ * src/objects.c: Updating the Edit and Delete CAD Objects dialogs
+ at more places: *) When we create the first vertice on a new
+ polygon *) When we hit either the Done or Cancel buttons on the
+ Close Polygon dialog.
+
+2006-08-01 07:49 we7u
+
+ * src/: objects.c, util.c: Effectively removing the rounding code
+ that was added on 6/21/2006. The rounding was not done properly
+ to take into account overflow from seconds to minutes, or from
+ minutes to degrees.
+
+2006-08-01 05:49 we7u
+
+ * src/popup_gui.c: Bumping up the min size for popup messages
+ slightly.
+
+2006-08-01 05:40 we7u
+
+ * src/popup_gui.c: A start at fixing the problem where a popup
+ message will come up too small on the screen and can't be
+ resized. We now set a minimum size and don't fix the size, so it
+ can be resized if necessary to read the message.
+
+2006-07-31 06:42 we7u
+
+ * src/objects.c: Fixed double-dash option for CAD objects. Update
+ Edit/Erase CAD object dialogs if objects are changed. Use
+ "<Empty Label>" names if no actual label is selected. Commented
+ out one message to STDERR during normal pre-defined objects
+ processing, fixed up another message here to use
+ get_user_base_dir() or get_data_base_dir() as appropriate.
+
+2006-07-31 06:30 we7u
+
+ * src/interface.c: Notifying the operator if emergency beacon mode
+ is enabled but no transmits are actually occuring, for various
+ reasons.
+
+2006-07-31 06:28 we7u
+
+ * src/messages.h: Cranking up max message windows from 10 to 25.
+
+2006-07-31 06:27 we7u
+
+ * src/main.c: Warning the user if ALTNET is enabled on startup (can
+ be confusing when a new user sets this and then sees no
+ stations). Setting a fixed beacon interval of 60 seconds if
+ emergency beacon mode is enabled.
+
+2006-07-31 06:25 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Adding more
+ strings for popup messages throughout the code, plus language
+ strings for CAD Objects.
+
+2006-07-25 07:53 we7u
+
+ * src/util.c: A first attempt at snagging course/speed out of the
+ previous posit if the last posit doesn't have it, for
+ dead-reckoning purposes. It will only do this if the previous
+ posit is still within the dead-reckoning timeout period. The
+ goal here is to do dead-reckoning properly for stations which
+ alternate GPGGA/GPRMC sentences (GPGGA don't have course/speed).
+
+2006-07-24 12:04 we7u
+
+ * src/draw_symbols.c: Removing dead or useless code. Reorganizing
+ some of the tests where we determine whether to draw a particular
+ symbol or attribute based on whether it is in the current view.
+
+2006-07-24 12:01 we7u
+
+ * src/db.c: Changing to setting flags in the station record when
+ it's our station or object/item, then checking flags, instead of
+ checking the "call_sign" or "origin" constantly throughout the
+ code with string compares. Got rid of the second drawing
+ iteration where we were drawing new stations to the screen _and_
+ to pixmap_final. We now draw to the screen and rely on the next
+ full screen-update to do the rest.
+
+2006-07-24 11:54 we7u
+
+ * src/main.c: Fixing the -geometry flag so that it works for
+ strings like: "-geometry -0-0"
+
+2006-07-22 07:47 tvrusso
+
+ * src/dbfawk.c: Possible fix for bug that prevents dbfawk files
+ with a single field in the dbffields list from working unless a
+ colon is added to the end of the list.
+
+ This appears to be a very platform dependent bug, as I have never
+ been able to reproduce the problem. But the fix is still valid
+ --- the issue is that no null terminator is added to a field name
+ unless a colon is found.
+
+ This fix doesn't break anything, but I'm unable to verify that it
+ actually fixes the problem reported, since I have never actually
+ seen that problem in action.
+
+2006-07-20 13:05 we7u
+
+ * src/maps.c: Dump a couple of messages out from map_indexer() to
+ STDERR. This makes it evident why Xastir is so busy when first
+ started up in a fresh config directory, if there are a lot of
+ maps present on the system.
+
+2006-07-20 12:28 we7u
+
+ * src/main.c: Nope, 50 was too slow, but 25 looks good so far.
+
+2006-07-20 12:23 we7u
+
+ * src/main.c: Slowing down the main UpdateTime() loop again. We
+ seem to keep up with a 2.6 kernel with nexttime=50. Previously
+ 10.
+
+2006-07-19 07:40 we7u
+
+ * src/: igate.c, interface.c, main.c, maps.c, messages.c,
+ xa_config.c: Fixes to get rid of complete path in the config file
+ for variables that need to change between different configs. If
+ a user has specified a complete path (other than the default
+ path), Xastir will honor it. If the default path is there,
+ Xastir will shorten it so that multiple configs may use it.
+
+2006-07-19 04:27 we7u
+
+ * src/: database.h, db.c, list_gui.c, objects.c: Getting rid of
+ many of the is_my_call() invocations, instead setting flag bits
+ in the DataRow->flag variable to specify whether it's our
+ callsign-SSID or whether it's an object/item owned by us. This
+ gets rid of literally millions of string compares.
+
+2006-07-17 17:41 we7u
+
+ * src/db.c: Skip doing dead-reckoning if scale > 8000. Doing
+ point-caching of last-point-drawn in draw_trail() to reduce the
+ amount of drawing we do when it's the same screen pixel over and
+ over (when zoomed out).
+
+2006-07-17 17:38 we7u
+
+ * src/database.h: Adding a new flag definition in preparation for a
+ rewrite of the is_my_call() function.
+
+2006-07-17 09:12 we7u
+
+ * src/: map_WMS.c, map_geo.c, map_tiger.c: Patch for bug 1522493 by
+ Dan Brown, n8ysz: The caching "bad" files problem. It should
+ whack things out of the cache if, for whatever reason, they're
+ unusable.
+
+2006-07-17 04:57 we7u
+
+ * src/: main.c, xa_config.c, xa_config.h: More tweaks by Dan Brown,
+ n8ysz: Cleaned up the get_user_base_dir() in xa_config.c to be
+ more careful about returning complete paths.
+
+2006-07-16 12:02 tvrusso
+
+ * src/: color.c, map_geo.c: Clean up transparency code for .geo
+ maps, removing debug output.
+
+ This now works properly for 16 and 24 bit DirectColor/TrueColor
+ displays. It is horribly broken for 8-bit displays, but as far
+ as I can tell it was horribly broken *before* I started. On
+ 8-bit displays the WMSRadar image doesn't even get displayed,
+ transparent or not, before *and* after my changes. I was unable
+ to figure out why.
+
+2006-07-16 10:21 tvrusso
+
+ * src/: color.c, map_geo.c: An interim commit of partial fixes to
+ the transparency problem on .geo files.
+
+ Mostly committing this to get it to a machine that has a display
+ that isn't 24-bit for testing.
+
+ Lots of cruft in here needs editing out after testing is
+ complete.
+
+2006-07-14 11:50 we7u
+
+ * README.Getting-Started, xastir.1: Updates by Dan Brown, n8ysz.
+
+2006-07-14 08:53 we7u
+
+ * src/: main.c, xa_config.c: Additions/fixes to implement alternate
+ Xastir config directories. Patch submitted by Dan Brown, n8ysz.
+
+2006-07-13 05:10 we7u
+
+ * scripts/get-NWSdata: Fixing up the domain names so that they all
+ match (for consistency).
+
+2006-07-12 10:47 we7u
+
+ * scripts/get-NWSdata: Updating one NWS shapefile name to latest
+ version.
+
+2006-07-12 10:47 we7u
+
+ * README.MAPS: Updating the text for NWS Shapefile names to match
+ the NOAA website.
+
+2006-07-12 07:24 we7u
+
+ * src/draw_symbols.c: A fix for the bug where text-on-black obscure
+ text above/below slightly due to the black background. We now
+ separate the text by another pixel and the problem goes away.
+
+2006-07-11 09:06 tvrusso
+
+ * WMSRadar.geo: Tweak transparency value. For some time now, the
+ actual "no reflection" value that's been coming in has been hex
+ value 0x010101, not "0x000000". On 24-bit displays that means
+ that the default file was displaying with an opaque nearly-black
+ background instead of a transparent one.
+
+ The actual no-reflection value returned by the WMS server has
+ changed back and forth between 0x000000 and 0x010101 often in the
+ history of the WMSRadar file and will probably need to be changed
+ again some time in the future. It has been pretty consistently
+ 0x010101 for several weeks now.
+
+2006-07-11 07:38 we7u
+
+ * src/db.c: Fixing incorrect timestamps for local station. This
+ was causing track points to get expired immediately so that the
+ station didn't show a track if being run with only a GPS
+ interface.
+
+2006-07-11 06:02 we7u
+
+ * src/draw_symbols.c: Fixes for dead-reckoning 180 degree problem
+ and for the DR arc being slightly off.
+
+2006-07-11 05:18 we7u
+
+ * src/draw_symbols.c: Removing dead code.
+
+2006-07-11 05:06 we7u
+
+ * src/draw_symbols.c: More efficient dead-reckoning code plus
+ commenting out unused sections of code.
+
+2006-07-11 04:41 we7u
+
+ * src/draw_symbols.c: More tweaks to dead-reckoning. We now
+ attempt to display the arc and the DR'ed trail if either the
+ symbol or the DR'ed symbol are on-screen. Added an "if" clause
+ to the DR'ed symbol drawing so it is only drawn when on-screen.
+ Commented out old code that we're not using anymore.
+
+2006-07-11 04:01 we7u
+
+ * src/util.c: Another fix by Dan Brown, n8ysz. This one keeps the
+ log files at or below the max logfile size.
+
+2006-07-11 03:59 we7u
+
+ * src/interface.c: Removing a duplicate include line. Thanks to
+ Dan Brown for finding it.
+
+2006-07-10 20:15 we7u
+
+ * src/draw_symbols.c: Implenting DR arcs again. Problems near/at
+ 180 degrees, but other than that it seems to work fine.
+
+2006-07-10 10:24 we7u
+
+ * src/db.c: Disabling the XtRemoveGrab() function call which causes
+ warnings on some OS'es. I don't believe we actually need it.
+ We'll find out for sure when more users try out this version.
+
+2006-07-10 10:23 we7u
+
+ * src/draw_symbols.c: Test code for re-enabling the dead-reckoning
+ arc's. Not complete/correct yet, but it's a start.
+
+2006-07-10 09:40 we7u
+
+ * src/wx.c: Fixes by Mike Loebl, kb1mts, to add barometric pressure
+ and humidity decoding to ARNE format.
+
+2006-07-10 05:57 we7u
+
+ * src/main.c: Fixing high CPU usage problems on FreeBSD, changing
+ nexttime from 2ms to 10ms. Thanks to Carl Makin for this tweak.
+
+2006-07-10 04:09 we7u
+
+ * src/util.c: Fixes by Dan Brown, n8ysz, for Xastir bug 1518805:
+ "Log files can fill up hard drive". We now limit a log file to
+ about 2MB at which point we roll it over to a new filename and
+ create a new empty file to write to. We keep up to 3 of these
+ backup files plus the current log file at any given time, which
+ makes for between 6MB and 8MB of data that we keep.
+
+2006-07-07 09:10 we7u
+
+ * README.Contributing: Added a section by Dan Brown.
+
+2006-07-07 08:06 we7u
+
+ * scripts/BUILDRPMS: Tweaking the rev number.
+
+2006-07-06 09:23 we7u
+
+ * src/main.c: Fixes by Dan Brown, n8ysz, for Xastir bugs 1515197
+ "segfault if XASTIR_USER_BASE no existing" and 1517761, "No error
+ check on config dir mkdir".
+
+2006-07-06 08:36 we7u
+
+ * src/: main.c, track_gui.c: Fixes for the blank label problem on
+ sliders with certain releases of OpenMotif. This relates to
+ problems with using XtVaTypedArg within an
+ XtVaCreateManagedWidget() function. Instead we now call
+ XmStringCreateLocalized() before the call, and XmStringFree()
+ afterwards.
+
+2006-07-05 07:17 we7u
+
+ * src/: Makefile.am, main.c: A patch to add compile time/date to
+ the Help->About dialog, by Dan Brown, N8YSZ.
+
+2006-06-29 10:04 we7u
+
+ * src/xa_config.c: Making the igate -> RF path default be
+ "WIDE2-1".
+
+2006-06-27 07:25 we7u
+
+ * src/igate.c: Reorganizing the logic slightly to make it easier to
+ understand w.r.t. the gating of objects/items/stations to RF via
+ the nws-stations.txt file. Added/updated several comments.
+
+2006-06-23 09:03 we7u
+
+ * src/db.c: Adding more comments. No code changes.
+
+2006-06-23 08:31 we7u
+
+ * src/igate.c: Changing igating->RF around so that if a station or
+ object name is found in the nws-stations.txt file, it will get
+ gated to RF whether or not "TCPXX" is found in the path. This
+ allows more types of things to be gated to RF if manually
+ specified in the nws-stations.txt file.
+
+2006-06-22 05:42 we7u
+
+ * src/db.c: Mostly changes to comments, but changed the error
+ ellipses from black to white. Still need to draw truncation
+ rectangles instead in some cases.
+
+2006-06-21 07:49 we7u
+
+ * src/objects.c: Tweaking the rounding in objects.c
+
+2006-06-21 06:12 we7u
+
+ * src/util.c: Changing some comments.
+
+2006-06-21 05:41 we7u
+
+ * src/: interface.c, util.c: Fixing up posits so that we round
+ properly instead of truncating the higher resolution digits. For
+ some-odd reason the fprintf doesn't round up properly at 0.5, so
+ we add a 0.01 to the number so that it rounds up.
+
+2006-06-21 04:51 we7u
+
+ * src/db.c: Changing one comment.
+
+2006-06-20 05:55 we7u
+
+ * src/: database.h, db.c, draw_symbols.c: An attempt to do the
+ error ellipses for position packets. This is most likely not the
+ display we'll finalize on, but it's a start. We draw circles for
+ the less-precise posits, but as Tom Russo pointed out they should
+ probably be rectangles. Also, the GPGGA/GPRMC/GPGLL code needs
+ some work w.r.t. these.
+
+2006-06-19 14:47 we7u
+
+ * src/: db.c, draw_symbols.c, draw_symbols.h: Making sure we don't
+ try to do dead-reckoning on stations that have position ambiguity
+ enabled.
+
+2006-06-19 11:58 we7u
+
+ * README: Adding notes for OpenSuSE 10.1
+
+2006-06-16 13:29 we7u
+
+ * src/: db.c, draw_symbols.c, draw_symbols.h: More ambiguity fixes.
+
+2006-06-16 12:58 we7u
+
+ * src/: database.h, db.c: Correcting the spelling of "ellipse".
+
+2006-06-16 12:08 we7u
+
+ * src/draw_symbols.c: Changes to a few comments.
+
+2006-06-16 12:06 we7u
+
+ * src/: database.h, db.c, draw_symbols.c, draw_symbols.h: Adding a
+ variable for doing error_ellipses around posits. Not in use yet.
+ Changed the position ambiguity around so that it is correct and
+ the symbol position inside the rectangle is correct. Still need
+ to fix up the grid-square code in the draw_ambiguity function
+ though.
+
+2006-06-15 14:28 we7u
+
+ * src/draw_symbols.c: Fixing up some of the ambiguity rectangle
+ stuff. All but the grid squares look ok now, but the smallest
+ rectangle ends up with the symbol placed off-center, which still
+ needs to be fixed.
+
+2006-06-15 12:46 we7u
+
+ * src/draw_symbols.c: Changing from stippled ambiguity rectangles
+ to solid lines.
+
+2006-06-15 07:33 we7u
+
+ * src/draw_symbols.c: Changing ambiguity rectangles from filled to
+ unfilled, plus drawing lines from symbol to each corner of
+ rectangle so we know which symbol is being drawn with the
+ ambiguity.
+
+2006-06-14 13:55 we7u
+
+ * src/database.h: Doesn't make much sense to add the new parameter
+ to the station database at this time when code doesn't use it.
+ It would only take up memory. Commenting it out for now until we
+ get to using it.
+
+2006-06-14 13:50 we7u
+
+ * src/database.h: Preliminary addition of an error_elipse storage
+ area for the station record. Not actually used in the code yet
+ as we're still discussing how it should best be used/displayed.
+
+2006-06-14 07:17 gstueve
+
+ * src/util.c: Only check VHF porion of path. Still need to process
+ 2nd portion for proper behavior.
+
+2006-06-14 07:13 gstueve
+
+ * src/util.c: Only change lower case characters to uppper, don't
+ bother to rewrite upper.
+
+2006-06-14 07:10 gstueve
+
+ * src/util.c: Fix spelling in comment.
+
+2006-06-12 09:17 we7u
+
+ * FAQ: Added "socat" to the FAQ.
+
+2006-06-08 14:04 we7u
+
+ * src/: db.c, objects.c: Changed some comments to show the last
+ GPROF percentages for the heavy-hitters. No code changes here.
+
+2006-06-07 07:18 we7u
+
+ * config/tnc-startup.d700: Changed the comments at the top. Added
+ note about Alinco's.
+
+2006-06-07 07:03 tvrusso
+
+ * FAQ: Update pointer to latest version of the FAQ. The URLs that
+ were here were very outdated.
+
+2006-06-06 12:22 we7u
+
+ * src/db.c: Some packets with an extra digit in the latitude end up
+ going through the compressed packet decode routine. This fix
+ causes those packets to be rejected from that routine.
+
+2006-06-05 15:01 we7u
+
+ * Davis/src/db2APRS.c: Davis mods by Clay Jackson, n7qnm. Added
+ some MySQL error checking, set it up so it would always get the
+ 'latest' records, and generally improved the error handling
+ (things like 0 or >100 pct humidity, pressure below 26 or above
+ 31, and so on).
+
+2006-06-05 12:20 we7u
+
+ * scripts/get-NWSdata: Tweaking the script so that it only fetches
+ files we don't already have.
+
+2006-06-05 12:19 we7u
+
+ * configure.ac: Bumping revision for devel to 1.8.3.
+
+2006-06-05 11:50 we7u
+
+ * configure.ac, scripts/BUILDRPMS, scripts/do_xastir_release_dev:
+ Updating to 1.8.2 to get ready for stable release.
+
+2006-06-05 11:43 we7u
+
+ * scripts/do_xastir_release_stable: Updating default version
+ number.
+
+2006-06-05 10:14 we7u
+
+ * README.MAPS: Added a section describing how to create your own
+ Shapefile maps with Xastir. Added a section describing CAD
+ Object polygons.
+
+2006-06-05 09:46 we7u
+
+ * scripts/fcc-get: Updating to match newer "sort" function's
+ syntax.
+
+2006-06-02 09:43 we7u
+
+ * config/language-German.sys: Updates by DK7IN. Thanks!
+
+2006-06-02 08:35 we7u
+
+ * scripts/get-NWSdata: Updating to latest NOAA filenames.
+
+2006-06-01 10:05 we7u
+
+ * README.MAPS: Fixing the path for gpx2shape so that people look
+ for it in the scripts directory.
+
+2006-06-01 10:04 we7u
+
+ * scripts/Makefile.am: Adding gpx2shape to the build.
+
+2006-06-01 10:04 we7u
+
+ * scripts/gpx2shape: A nice contribution by James Washer. Convert
+ GPX files to Shapefiles.
+
+2006-06-01 09:35 we7u
+
+ * README.MAPS: Added a blurb about National Geographic's Topo,
+ TPO/TPG files, mapXchange, gpsbabel, and gpx2shape.pl.
+
+2006-06-01 07:17 we7u
+
+ * README.MAPS: A bit added by Kyle Kienapfel regarding the Canada
+ topo file. Thanks!
+
+2006-05-31 13:39 we7u
+
+ * src/igate.c: Disallowing igating of general queries in either
+ direction. Directed queries still get gated as appropriate.
+
+2006-05-31 13:36 we7u
+
+ * src/db.c: Added some comments.
+
+2006-05-31 12:57 we7u
+
+ * src/: db.c, wx.c: Fixing the backwards conversions for wind speed
+ for Peet Bros. Ultimeter-II weather stations. The correct units
+ are km/h if the sentence begins with '#', and mph if the sentence
+ begins with '*'.
+
+2006-05-31 12:30 we7u
+
+ * src/wx.c: Changes to comments/added some comments.
+
+2006-05-31 11:39 we7u
+
+ * src/wx.c: Zeroing the first two digits on wind speed for Peet
+ Bros 2k as per the docs.
+
+2006-05-31 11:25 we7u
+
+ * src/wx.c: Changing a few variables to make the code more
+ consistent. Instead of pointing back to the original data to
+ check for ">7", we look at the first character of our substring
+ temp_data1[0].
+
+2006-05-31 11:09 we7u
+
+ * src/wx.c: Fixes for Peet weather stations, negative value
+ decoding.
+
+2006-05-30 13:06 we7u
+
+ * src/map_gnis.c: Fixes to make Xastir handle the type of GNIS
+ files found at:
+ <http://geonames.usgs.gov/domestic/download_data.htm> which have
+ shorter lines than the ones at:
+ <http://geonames.usgs.gov/stategaz/>
+
+2006-05-30 11:50 we7u
+
+ * src/interface.c: Really complicated fix for Xastir dropping the
+ last character of a packet. A fix for the last fix I put in.
+
+2006-05-30 09:07 we7u
+
+ * src/db.c: Changed one comment.
+
+2006-05-30 08:18 we7u
+
+ * src/: database.h, db.c, interface.c, main.c: A bug fix for KISS
+ or AGWPE ports. The AX.25 header increases in size when it gets
+ converted to TAPR2-style headers. If there were enough
+ digipeaters in the path then the complete packet can get
+ truncated on the tail-end. This patch fixes it by allocating a
+ separate buffer that is quite large for each packet before the
+ header decoding function.
+
+2006-05-17 12:28 we7u
+
+ * src/db.c: Fixing the reply-ack problem during messaging. It was
+ an off-by-one error. Our ack_string looked like "}5o" instead of
+ "5o", which made the comparison fail.
+
+2006-05-13 09:27 we7u
+
+ * src/Makefile.am: Adding rpl_malloc.h to the build.
+
+2006-05-12 13:32 tvrusso
+
+ * FAQ: Add command for converting Root files to new scheme.
+
+ Of course, if someone could check this file out to see the
+ commands, they've already done the conversion...
+
+2006-05-12 13:05 we7u
+
+ * scripts/do_xastir_release_dev: Fixing a typo.
+
+2006-05-12 13:03 we7u
+
+ * install-xastir: Updating to the latest SourceForge CVS server
+ names.
+
+2006-05-12 13:00 we7u
+
+ * scripts/: do_xastir_release_dev, do_xastir_release_stable:
+ Updating to correspond to latest CVS server names.
+
+2006-05-12 12:44 we7u
+
+ * FAQ, README.CVS, README.win32: Updating the CVS instructions to
+ correspond to the changes implemented today on SourceForge.
+
+2006-05-12 12:44 we7u
+
+ * config/tnc-startup.d700: Adding "HEADERLN off", which we appear
+ to have missed at some point.
+
+2006-05-04 08:01 we7u
+
+ * README.win32: Added a note about what to call COM1/COM2 in
+ Cygwin.
+
+2006-04-29 10:19 tvrusso
+
+ * symbols/symbols.dat: Change \V symbol (VORTAC) to something that
+ looks like what the other APRS codes use, matching the VORTAC
+ symbol on aviation charts.
+
+2006-04-24 12:21 we7u
+
+ * src/: alert.c, awk.c, bulletin_gui.c, color.c, datum.c, db.c,
+ dbfawk.c, draw_symbols.c, fcc_data.c, festival.c, geo-find.c,
+ geocoder_gui.c, gps.c, hashtable.c, hashtable_itr.c, hostname.c,
+ igate.c, interface.c, interface_gui.c, io-common.c, io-mmap.c,
+ lang.c, list_gui.c, locate_gui.c, location.c, location_gui.c,
+ macspeech.c, main.c, map_WMS.c, map_cache.c, map_dos.c,
+ map_gdal.c, map_geo.c, map_gnis.c, map_pdb.c, map_shp.c,
+ map_tif.c, map_tiger.c, maps.c, messages.c, messages_gui.c,
+ objects.c, rotated.c, rpl_malloc.c, shp_hash.c, snprintf.c,
+ sound.c, testawk.c, track_gui.c, util.c, view_message_gui.c,
+ wx.c, wx_gui.c, x_spider.c, xastir_udp_client.c: More fixes for
+ rpl_malloc, plus made the callouts for config.h more consistent.
+
+2006-04-24 10:20 we7u
+
+ * src/: Makefile.am, festival.c, rotated.c, util.c, util.h:
+ Separating out the rpl_malloc code so that it can be used in
+ other programs like testawk.
+
+2006-04-24 10:19 we7u
+
+ * src/: rpl_malloc.c, rpl_malloc.h: Separating out the rpl_malloc
+ stuff so that it can be used in other programs like testawk.
+
+2006-04-21 14:01 we7u
+
+ * src/db.c: Correcting spelling in one comment.
+
+2006-04-21 13:51 we7u
+
+ * src/db.c: This change clears the transmitted message so it won't
+ get transmitted again after a REJ packet, and gets rid of a
+ printf to STDERR for each REJ.
+
+2006-04-21 12:58 we7u
+
+ * src/db.c: Added support for REJ packets, including igating of
+ same. Yet to be tested.
+
+2006-04-21 12:57 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Added a "*REJECT*"
+ string for REJ packets.
+
+2006-04-20 09:47 we7u
+
+ * README.win32: A tweak by Wes Johnston for getting bootstrap.sh to
+ run properly.
+
+2006-04-20 08:05 we7u
+
+ * src/wx.c: Reverting back to the code for version 1.54, as the
+ rounding for negative numbers wasn't done correctly and caused
+ more harm than good.
+
+2006-04-20 07:22 we7u
+
+ * symbols/: alert.xbm, flood.xbm, red_flag.xbm, snow.xbm,
+ tornado.xbm, wind.xbm, winter_wx.xbm, wntr_strm.xbm: Thanks to
+ Jason Winningham, kg4wsv, for these weather alert pics that stack
+ up much more nicely than the originals, while leaving more of the
+ map below visible.
+
+2006-04-10 07:31 we7u
+
+ * scripts/get-maptools.sh: Script to get/install several of the map
+ libraries, written by Dan Brown, N8YSZ.
+
+2006-04-05 09:13 we7u
+
+ * scripts/Makefile.am: Adding two of the newer scripts into the
+ Makefile.
+
+2006-04-05 09:09 we7u
+
+ * README.win32: A tweak by Joe Cotton to get the finger command
+ working in Xastir/Cygwin.
+
+2006-03-16 18:32 tvrusso
+
+ * INSTALL: Put the word "shapelib" closer to the place where we
+ explain how to install it, so it is more quickly found by a
+ search with "less" or "grep".
+
+2006-03-16 00:03 tvrusso
+
+ * README.MAPS: Fixx mispleling.
+
+2006-03-16 00:02 tvrusso
+
+ * README.MAPS: Added a little commentary about the mrsiddecode
+ program.
+
+2006-03-13 17:40 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/objects.c: Shortening "Area" to
+ "A" for CAD objects. Also shortening the unit descriptions.
+
+2006-03-13 17:32 we7u
+
+ * src/db.c: Refusing to do the emergency popups until/unless we
+ have a position for a station. It's hard to help someone if we
+ don't know where they are at. This keeps Xastir from annoying
+ the crap out of people every 30 minutes if a posit for that
+ station isn't coming in, but a packet with certain keywords _is_
+ coming in regularly.
+
+2006-03-10 12:56 we7u
+
+ * INSTALL: Added another note about libtiff-3.8.0
+
+2006-03-10 12:45 we7u
+
+ * INSTALL: Adding solution text regarding the libgdal/libgeotiff
+ GTIFProj4ToLatLong problem.
+
+2006-03-10 12:28 tvrusso
+
+ * README.MAPS: Fix a handful of mispleellings and mistales.
+
+2006-03-10 12:09 tvrusso
+
+ * README.MAPS: Rearrange some of the discussion of how to
+ manipulate randomly mutilated GeoTIFF files.
+
+2006-03-10 08:16 we7u
+
+ * README.MAPS: Adding a section about using gdal_translate to
+ convert crappy geoTIFF's to usable ones. Thanks to Tom Russo for
+ the info on how to do this.
+
+2006-03-10 08:15 we7u
+
+ * INSTALL: Slightly changing some wording in the gdal section.
+ Nothing of importance.
+
+2006-03-09 12:47 we7u
+
+ * INSTALL: Updating various library revision numbers. Added a note
+ about a possible geoTIFF conflict when installing GDAL.
+
+2006-03-09 12:46 we7u
+
+ * src/map_tif.c: Making sure that Proj.4 error messages appear only
+ under the correct circumstances.
+
+2006-03-08 18:43 we7u
+
+ * src/db.c: Initial implementation of a distance check for
+ warnings/alerts. Default is set to 280 miles or kilometers
+ (whichever mode you are set in), and the check defaults to ON,
+ meaning it will check each time whether the station is within
+ that distance. This version has no user controls for the new
+ functionality implemented yet.
+
+2006-03-07 18:44 we7u
+
+ * src/wx.c: Fixing the rounding for some of the values that can be
+ negative, coming from weather stations.
+
+2006-03-07 16:41 we7u
+
+ * FAQ, README.Getting-Started, README.win32: Updating/Adding
+ instructions for snagging NWS files via new script.
+
+2006-03-07 09:56 we7u
+
+ * README.MAPS: Adding filename patterns to the NWS file
+ descriptions.
+
+2006-03-07 09:56 we7u
+
+ * scripts/get-NWSdata: Adding the fire weather zones to the mix.
+
+2006-03-07 09:05 we7u
+
+ * README.MAPS: Adding a bit about the get-NWSdata script.
+
+2006-03-07 09:04 we7u
+
+ * scripts/get-NWSdata: Modified the script to do one
+ download/unzip/delete the .zip file, then start on the next.
+ This will keep disk space requirements down plus not have the
+ .zip files hanging around when we're all done.
+
+2006-03-07 08:53 we7u
+
+ * scripts/get-NWSdata: A new script to fetch NWS data files used
+ for weather alerts. Curt, WE7U and Steven, WM5Z had a hand in
+ writing it.
+
+2006-03-03 12:31 we7u
+
+ * src/db.c: Checking for 8-bit characters in Mic-E packets, except
+ for the case of 8-bit telemetry extension fields where we skip
+ the check.
+
+2006-03-03 08:19 we7u
+
+ * src/track_gui.c: Re-enabling the popup on findu track download
+ failure, as it doesn't appear to be the source of James Ewen's
+ segfaults when his DNS failure occurs. It appears to be a
+ segfault from libcurl itself.
+
+2006-03-02 14:53 we7u
+
+ * README.win32: Added a note about compiling libproj into gdal
+ statically in order to install on Cygwin.
+
+2006-03-01 10:37 we7u
+
+ * config/tnc-startup.thd7: Commenting out the hbaud line and adding
+ a comment about it.
+
+2006-03-01 08:30 we7u
+
+ * README.Contributing: Added a note about core files appearing
+ where you least expect them.
+
+2006-03-01 08:02 we7u
+
+ * src/track_gui.c: Adding comments near another popup message that
+ could conceivably cause segfaults: The "Success" message from
+ fetching a findu trail. This particular popup has worked
+ properly for me with no segfaults so far. We may need to
+ investigate whether multiple threads writing to X11 at the same
+ time can cause segfaults. I believe I've seen this in other
+ cases, but my memory may be faulty on this matter.
+
+2006-02-28 11:29 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/maps.c, src/maps.h,
+ src/xa_config.c: Checking in mods by Dalen Kruse, KC0OVU, which
+ implement a timing slider for snapshots with a range from 1 to 30
+ minutes.
+
+2006-02-28 00:01 we7u
+
+ * src/track_gui.c: Getting rid of the GUI stuff in fetch findu
+ trail: It happens in a separate thread now and we can't write to
+ the GUI from two threads at once due to possible segfaults.
+
+2006-02-27 13:02 we7u
+
+ * src/wx.c: A fix for negative values being interpreted incorrectly
+ due to varying sizes of INT on different systems.
+
+2006-02-27 11:40 we7u
+
+ * config/tnc-startup.thd7: Changing HBAUD to 9600 so that it
+ matches the default serial port speed.
+
+2006-02-24 19:01 tvrusso
+
+ * src/db.c: Fix appallingly stupid mistake in passing arguments to
+ XtVaSetValues.
+
+ I coulda *sworn* I had just copied what was already there, but
+ apparently not.
+
+ This fixes the problem where the Incoming Data scrolled text
+ widget was not scrolling to the bottom of the incoming data as
+ new stuff was added.
+
+2006-02-24 10:38 tvrusso
+
+ * src/db.c: Complete refactor of how the "packet_data_string" stuff
+ is updated and displayed.
+
+ We no longer do "memmove" to cycle old data out of the array, but
+ rather use a two-dimensional array of strings treated as a ring.
+ Data is shifted out of the Display Incoming Data dialog box using
+ XmReplaceText calls.
+
+ I have tested this out in several ways and it appears to function
+ precisely as the old one was intended to do. This *might* be the
+ solution to the sporadic segfaults we've been seeing and the less
+ harmful "line too long for array" warnings.
+
+2006-02-23 16:38 we7u
+
+ * src/db.c: Add a null pointer check to delete_station_memory().
+ Changed an "if" to an "else" clause in insert_new_station(),
+ which just made the code slightly simpler but didn't change any
+ operation. Multiple comment changes.
+
+2006-02-23 16:01 we7u
+
+ * src/xa_config.c: Increasing the default for Internet Map Timeout
+ from 90 to 120 seconds.
+
+2006-02-23 15:59 we7u
+
+ * src/util.c: Adding messages something like "Possible timeout, try
+ increasing Internet Map Timeout" to the libcurl and wget code.
+
+2006-02-22 08:53 chicoreus
+
+ * src/maps.c: Adding grid labels for UTM major grid. All grid
+ types and resolutions now have some kind of labeling available.
+
+2006-02-22 08:51 chicoreus
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Added metadata
+ text for UTM major zones.
+
+2006-02-19 12:50 rzg
+
+ * src/dbfawk.c:
+ Small memory leak found by valgrind; I think this should fix it.
+
+2006-02-19 12:02 tvrusso
+
+ * scripts/object2shp.pl: Bug fix. Make sure to ignore comment
+ lines in the object file, or any other lines that don't start
+ with semicolon.
+
+2006-02-19 11:56 tvrusso
+
+ * README.MAPS: Add explanation of how to use object2shp.pl into
+ README.MAPS under the "Rolling your own shapefile maps" section.
+
+2006-02-19 11:48 tvrusso
+
+ * scripts/: Makefile.am, object2shp.pl: Per discussion on xastir
+ mailing list, a script to create shapefile maps from the
+ object.log file. This will enable quick and dirty generation of
+ special purpose map overlays by plunking down objects, creating
+ shapefiles, then deleting the objects.
+
+2006-02-16 21:50 we7u
+
+ * src/: database.h, db.c, list_gui.c: Changing the names of
+ pointers so that their function is more easily recognizable.
+
+2006-02-16 12:45 we7u
+
+ * src/x_spider.c: Added more output messages in case of error which
+ suggest killing old Xastir processes in order to remove the
+ error.
+
+2006-02-16 12:44 we7u
+
+ * src/: db.c, messages.c: Fixing up msg_data_add() so that we can
+ tell when we've rejected a message. Tweaked the code which
+ invokes it so that it knows the difference between
+ new/old/rejected messages.
+
+2006-02-15 08:46 chicoreus
+
+ * src/: maps.c, maps.h: Refinements to the calculation of latitude
+ and longitude grid spacing. Triming the latitude and longitude
+ strings in the grid border when zoomed out. Reduced the number
+ of variables being passed in the functions called by draw_grid()
+ by moving them to function calls or constants.
+
+2006-02-14 14:00 we7u
+
+ * src/db.c: Initializing struct pointers to NULL right after malloc
+ of the struct, before we try inserting it into any linked lists.
+
+2006-02-14 13:11 we7u
+
+ * src/: database.h, db.c, gps.c, igate.c, objects.c: Converting all
+ MAX_TNC_LINE_SIZE (was 300) to MAX_LINE_SIZE (currently 512).
+ Just simplifying things.
+
+2006-02-14 12:07 we7u
+
+ * src/db.c: Printing out ALL of the guard bands that get corrupted,
+ not just the first one that's noticed.
+
+2006-02-14 11:59 we7u
+
+ * src/db.c: Adding a couple more guard bands, changing them to only
+ 10 chars each, making the error text print out which guard band
+ was corrupted.
+
+2006-02-14 11:34 we7u
+
+ * src/db.c: Making the Incoming Data display's char array
+ manipulation code a bit less scary. It had the potential to
+ overflow if conditions were just right, but the conditions were
+ extremely unlikely to occur.
+
+2006-02-14 11:33 we7u
+
+ * src/interface.c: Bumping up the sizes of some char arrays. Just
+ because. Probably don't help much, but don't hurt either.
+
+2006-02-14 11:32 we7u
+
+ * src/main.h: Removing some unused defines.
+
+2006-02-13 12:30 we7u
+
+ * src/: db.c, interface.c, interface.h, main.c: Adding guard bands
+ around the main station pointer variables, plus code to check for
+ intrusion into those guard bands. This may help us to find the
+ current segfault problem.
+
+2006-02-12 16:13 chicoreus
+
+ * help/help-English.dat: Changing the grid border help to include
+ latitude and longitude.
+
+2006-02-12 16:10 chicoreus
+
+ * src/maps.c: First cut at an algorithmic method for determining
+ the spacing of latitude and longitude grid lines at a scale
+ appropriate for the current window size and map zoom.
+
+2006-02-12 10:03 we7u
+
+ * src/db.c: Correcting some debug output message text.
+
+2006-02-11 18:10 we7u
+
+ * src/db.c: Doing some more error-checking in the station record
+ pointers. We do an abort() if we end up with dangling pointers,
+ which should give us a core dump immediately.
+
+2006-02-10 12:27 we7u
+
+ * REGRESSION_TESTS, configure.ac: Tweaks to add more regression
+ tests and format the output so that it's easier to read.
+
+2006-02-10 11:13 tvrusso
+
+ * README.Contributing: Add a section on using separate "build
+ directories" to maintain specialized builds rather than building
+ in the source tree.
+
+2006-02-09 17:08 we7u
+
+ * src/maps.c: Fixes for the map grid segfault problem.
+
+2006-02-09 15:14 tvrusso
+
+ * README.Contributing: Change commentary on how to do debugging
+ builds.
+
+2006-02-09 14:32 we7u
+
+ * README.Contributing: Adding a debugging note from Tom Russo.
+
+2006-02-09 13:27 tvrusso
+
+ * acinclude.m4: Change XASTIR_COMPILER_FLAGS so that it doesn't
+ insert "-g -O2" unconditionally. That is unnecessary since we
+ call AC_PROG_CC, which *conditionally* inserts "-g -O2" into
+ CFLAGS if the user hasn't specified CFLAGS on the configure line.
+
+ This should allow users to build specialized debugging versions
+ such as ./configure CFLAGS="-O -g -fno-inline" and not have
+ configure stick a "-O2" in unbidden.
+
+2006-02-09 12:41 we7u
+
+ * src/maps.c: A temporary fix to skip computing the UTM/MGRS grid
+ if we run into a problem, before we segfault.
+
+2006-02-09 12:14 we7u
+
+ * src/maps.c: Adding some comments.
+
+2006-02-09 12:12 we7u
+
+ * src/maps.c: Again splitting the minor UTM grid stuff into
+ separate functions.
+
+2006-02-09 11:40 we7u
+
+ * src/maps.c: Reorganizing the draw_grid() function. Breaking it
+ up into smaller pieces.
+
+2006-02-08 07:11 we7u
+
+ * src/main.c: Checking for proper status of unlink in
+ pid_file_check().
+
+2006-02-08 06:28 we7u
+
+ * src/main.c: Removing some code that doesn't get used in the RINO
+ download section of the switch.
+
+2006-02-06 18:37 we7u
+
+ * src/maps.c: Commenting out unnecessary code.
+
+2006-02-06 18:33 we7u
+
+ * INSTALL, README.Getting-Started, UPGRADE, update-xastir:
+ Clarifying the use of SUID root a bit. Removing that command
+ from update-xastir so that the default will be to create a core
+ file.
+
+2006-02-06 13:35 we7u
+
+ * src/maps.c: Some fixes for segfaults and divide-by-zero faults in
+ the draw_grid() function. At least one more segfault path
+ remains in this body of code.
+
+2006-02-06 09:03 we7u
+
+ * README.Contributing: Adding more info to the debugger info.
+
+2006-02-06 08:21 we7u
+
+ * src/db.c: Tweaking Mic-E decoding logic to properly decode
+ overlay characters.
+
+2006-02-03 10:09 chicoreus
+
+ * src/util.h: Missing an extern
+
+2006-02-03 09:47 chicoreus
+
+ * src/: maps.c, util.c, util.h: Adding MGRS to labeled grid border.
+
+2006-02-03 09:46 chicoreus
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Changing grid
+ metadata text to allow MGRS support.
+
+2006-02-02 14:02 we7u
+
+ * src/maps.c: Extending some char arrays so that they're long
+ enough to hold the terminator.
+
+2006-02-02 10:58 chicoreus
+
+ * src/: main.c, maps.c, util.c, xastir.h: Added degree and minutes
+ symbols to lat/long grid border labels by adding constants for
+ convert_xastir_to_UTM() to produce strings containing these
+ symbols. Truncation of trailing zeroes on UTM grid labels, with
+ number of zeroes removed depending on utm_grid_spacing_m.
+ Changed following feedback from use of printed maps during a
+ GPSAR training. Added internationalization for lat/long and UTM
+ grid border metadata. Added metadata on top border for labeled
+ lat/long grids. Latitude drawn on both left and right borders.
+ Put the xastir coordinate to MGRS conversion into a function that
+ extracts the components of the MGRS string separately, then made
+ convert_xastir_to_MGRS_str() a wrapper around this function in
+ prepration for labeling the MGRS grid.
+
+2006-02-02 09:57 we7u
+
+ * README.Contributing: Adding info about core dumps and how to
+ bring up a debugger.
+
+2006-02-02 08:49 we7u
+
+ * README.Getting-Started, src/main.c: Reversing the meaning of the
+ "-t" command-line flag: The segfault handler is now turned off
+ by default (meaning we'll dump core instead). The "-t" flag
+ turns on the internal segfault handler now instead of disabling
+ it.
+
+2006-02-02 08:04 we7u
+
+ * configure.ac: Commenting out the code that removed the "-g" GCC
+ option. As Tom pointed out, it was a bad idea.
+
+2006-02-02 07:29 chicoreus
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Added
+ internationalization strings for metadata line for top border of
+ map when map grid border is displayed.
+
+2006-02-02 07:10 we7u
+
+ * src/util.c: A fix for the missing UTM grids with gcc-4.x problem.
+
+2006-02-02 07:10 we7u
+
+ * src/maps.c: Changing one debug output line.
+
+2006-02-01 08:42 we7u
+
+ * acinclude.m4: Patching the search list for Berkely DB library by
+ adding 4.3 and 4.4 search paths.
+
+2006-02-01 08:24 chicoreus
+
+ * src/maps.c: Added border labels for latitude and longitude grid.
+
+2006-01-31 10:32 chicoreus
+
+ * src/maps.c: More tuning of labeled border for UTM grid. Added
+ Zone number and letter in all four corners when two zones are
+ shown. All text in border changed to black with border color
+ outline. For two zones, northings for one zone appear on the
+ left side of the screen northings for the other on the right.
+ The left zone is labeled in black, the right zone labeled in
+ blue. Minor fixes to turn off display of labels where they run
+ off the screen.
+
+2006-01-30 07:31 tvrusso
+
+ * configure.ac, src/maps.c: "roundf", recently used in maps.c, is a
+ newer extension that is not present in systems that still have
+ old C compilers.
+
+ Insert a check for roundf, and a workaround for systems that
+ don't support it.
+
+2006-01-28 11:21 we7u
+
+ * bootstrap.sh: Fixing the file test syntax to use Bourne syntax
+ instead of Bash.
+
+2006-01-27 20:36 chicoreus
+
+ * src/maps.c: Minor changes and bug fixes to the UTM grid border
+ labeling code. Includes rounding of the grid labels to correctly
+ label 10,000 m, 1,000m, and 100m grids, not just the 100m grid.
+
+2006-01-27 15:40 chicoreus
+
+ * src/: maps.c, rotated.c: Added code to RotatedTextItem in
+ rotated.c library to handle special case of rotation of text 90
+ degrees counter clockwise. In this case, text is rotated by
+ directly transposing x and y coordinates, rather than by applying
+ a sine and cosine transformation to rotate the text, something
+ that produces an italic appearance to the rotated text (making it
+ harder to read, especially when printed). This change is to
+ support more legible text on the labeled UTM grid on the border
+ of the map, especially for producing maps to be printed.
+
+ Also made minor changes to border label code in maps.c to make
+ quick and dirty improvements to appearance.
+
+2006-01-27 08:30 we7u
+
+ * Davis/bootstrap.sh, LaCrosse/bootstrap.sh: Since the three
+ bootstrap.sh scripts are the same anyway, run the one from one
+ directory up instead so that we don't have to keep rev'ing all
+ three of them when a change is needed. Like, duh!
+
+2006-01-27 08:14 we7u
+
+ * Davis/bootstrap.sh, LaCrosse/bootstrap.sh: Updating for Solaris.
+
+2006-01-27 08:10 we7u
+
+ * bootstrap.sh: Removing the comment marks that I shouldn't have
+ committed to CVS.
+
+2006-01-27 08:05 we7u
+
+ * bootstrap.sh: Updating for automake system directories on
+ Solaris.
+
+2006-01-27 06:57 we7u
+
+ * README: Updating the SuSE 10 notes to mention libcurl-dev as
+ well.
+
+2006-01-26 14:51 we7u
+
+ * Davis/src/Makefile.am: Installing the compiled db2APRS into the
+ bin directory.
+
+2006-01-26 12:57 we7u
+
+ * scripts/BUILDRPMS: Getting rid of some shell warnings.
+
+2006-01-26 12:39 we7u
+
+ * Makefile.am, scripts/BUILDRPMS: Adding LaCrosse directory into
+ the build.
+
+2006-01-26 11:06 we7u
+
+ * Davis/.cvsignore, LaCrosse/.cvsignore: Updating the list of files
+ that CVS should skip.
+
+2006-01-26 08:59 we7u
+
+ * Davis/bootstrap.sh, LaCrosse/bootstrap.sh: Updating bootstrap.sh
+ for separate weather apps so they are the same as the main Xastir
+ bootstrap.sh
+
+2006-01-26 07:55 n0vh
+
+ * LaCrosse/: weatherdump.sql, src/Makefile.am: SQL file of open2300
+ database
+
+2006-01-26 07:44 we7u
+
+ * Davis/: .cvsignore, src/.cvsignore: Adding .cvsignore files for
+ the Davis directories to reduce the amount of "noise" that cvs
+ status returns.
+
+2006-01-26 07:42 we7u
+
+ * LaCrosse/: .cvsignore, src/.cvsignore: Adding .cvsignore files
+ for these two new directories so that cvs status doesn't return
+ too many unneeded lines.
+
+2006-01-26 07:38 n0vh
+
+ * LaCrosse/src/open2300db2APRS.c: Fixed an issue with SIGPWR on
+ non-Linux systems
+
+2006-01-26 07:38 n0vh
+
+ * LaCrosse/configure.ac: Minor updates to compile on non-linux
+ systems
+
+2006-01-25 15:11 n0vh
+
+ * LaCrosse/README: Minor correction to directory in BUILD section
+
+2006-01-25 14:46 n0vh
+
+ * LaCrosse/README: Changed to make it more relavent to
+ open2300db2APRS
+
+2006-01-25 12:34 n0vh
+
+ * LaCrosse/src/open2300db2APRS.c.bak: Not needed.
+
+2006-01-25 12:26 we7u
+
+ * LaCrosse/src/open2300db2APRS.c: Fixing a warning given by gcc-4.
+ clen must be a socklen_t instead of an int.
+
+2006-01-25 11:52 n0vh
+
+ * LaCrosse/src/: Makefile, Makefile.in, open2300db2APRS,
+ open2300db2APRS.o: Removed files that should be in CVS
+
+2006-01-25 11:50 n0vh
+
+ * LaCrosse/Makefile.am: Put back this needed file
+
+2006-01-25 11:49 n0vh
+
+ * LaCrosse/: Makefile, Makefile.am, Makefile.in, aclocal.m4,
+ config.h, config.h.in, config.log, config.status, configure,
+ stamp-h1: Removed files that should be there
+
+2006-01-25 11:36 n0vh
+
+ * LaCrosse/: AUTHORS, COPYING, ChangeLog, INSTALL, Makefile,
+ Makefile.am, Makefile.in, NEWS, README, aclocal.m4, bootstrap.sh,
+ config.h, config.h.in, config.log, config.status, configure,
+ configure.ac, stamp-h1, src/Makefile, src/Makefile.am,
+ src/Makefile.in, src/defs.h, src/open2300db2APRS,
+ src/open2300db2APRS.c, src/open2300db2APRS.c.bak,
+ src/open2300db2APRS.o: Support for LaCrosse WX-23xx weather
+ station support
+
+2006-01-25 11:33 n0vh
+
+ * config/: language-English.sys, language-French.sys,
+ language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Update for future
+ LaCrosse 23xx weather station support.
+
+2006-01-25 11:32 n0vh
+
+ * config/language-Dutch.sys: Updated with future LaCrosse 23xx
+ stuff.
+
+2006-01-25 08:46 chicoreus
+
+ * config/: language-Dutch.sys, language-French.sys,
+ language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Added missing
+ "MAPFONT008|Border Labels||" to support user selectable font for
+ drawing labels on the UTM tickmarks on the labled border.
+
+2006-01-23 21:46 we7u
+
+ * src/: maps.c, maps.h: Fixing up some function prototypes to get
+ rid of some compiler warnings.
+
+2006-01-23 15:47 chicoreus
+
+ * config/language-English.sys, src/db.c, src/main.c, src/maps.c,
+ src/xa_config.c, src/xastir.h: Drawing fonts with an outline on
+ the border results in text that is very difficult to read on a
+ printout. Added a user selectable font for drawing labels on the
+ UTM tickmarks on the labled border.
+
+2006-01-23 12:41 we7u
+
+ * src/map_tif.c: Getting rid of dependencies on cpl_csv.h, which
+ contains a private (not public) interface.
+
+2006-01-23 12:02 we7u
+
+ * src/: main.c, main.h: Testing for old/new kernel based on number
+ of signals available. We then use this to decide whether to set
+ "OLD_PTHREADS", which enables or disables the SIGUSR1 handler in
+ the code. Old kernels only has 32 signals, therefore Linux
+ Pthreads used SIGUSR1 and SIGUSR2 in their implementation. We
+ use SIGUSR1 for our Snapshot-on-demand function, therefore we
+ must disable this code if we're running older Pthreads on Linux.
+
+2006-01-23 12:00 we7u
+
+ * configure.ac, src/util.c: Testing for deprecated/new pthread
+ functions, modifying code to correspond based on what's found.
+
+2006-01-20 13:15 we7u
+
+ * src/x_spider.c: Another small tweak for Linux Standard Base 3.0
+ compliance.
+
+2006-01-20 09:58 we7u
+
+ * README: Tweaked the SuSE 10 notes regarding a bootstrap.sh
+ warning.
+
+2006-01-20 08:52 we7u
+
+ * README, bootstrap.sh: Formatting changes to bootstrap.sh. Added
+ a section to README which details getting rid of an SuSE-10
+ warning when running bootstrap.sh.
+
+2006-01-19 12:43 we7u
+
+ * README: Adding a note about SuSE 10.0 and problems with AX.25
+ kernel mode.
+
+2006-01-19 12:24 we7u
+
+ * bootstrap.sh: Fixing a problem in Automake 1.9 (on SuSE 10 at
+ least) where the mkinstalldir script doesn't get copied over by
+ Automake. We have to copy it over ourselves after we invoke
+ Automake.
+
+2006-01-19 09:20 we7u
+
+ * REGRESSION_TESTS: Updated the format a bit.
+
+2006-01-19 09:17 we7u
+
+ * src/db.c: A fix for another killer packet. This one had to do
+ with a while loop overrunning an ack_string variable. Changed to
+ xastir_snprintf() functions there and it solved the immediate
+ problem.
+
+2006-01-18 14:40 we7u
+
+ * src/map_tif.c: Commenting out an include because it causes an
+ error on Cygwin. Of course it causes a warning under gcc-4.0 on
+ Linux when it's commented out...
+
+2006-01-18 12:13 we7u
+
+ * REGRESSION_TESTS: Updating the tests for LSB and to make them
+ more convenient to run.
+
+2006-01-18 09:10 we7u
+
+ * FAQ: Adding some VNC configuration info.
+
+2006-01-18 08:50 we7u
+
+ * INSTALL: Updating/re-ordering the list of configure options.
+
+2006-01-18 08:49 we7u
+
+ * src/map_tif.c: Getting rid of some gcc-4.0 compiler warnings.
+
+2006-01-18 08:49 we7u
+
+ * Davis/src/db2APRS.c: Getting rid of a gcc-4.0 compiler warning
+ about signedness.
+
+2006-01-18 08:48 we7u
+
+ * Davis/bootstrap.sh: Making the script parallel the main Xastir
+ bootstrap script.
+
+2006-01-18 07:31 we7u
+
+ * src/interface_gui.c: Mods to comply with maximum baud rates
+ allowed under LSB.
+
+2006-01-18 07:11 we7u
+
+ * acinclude.m4, configure.ac, src/util.c: Initial tweaks to help
+ get Xastir compiled under Linux Standard Base 3.0 (LSB 3.0).
+ Have more work to do to get there, but this is a good start.
+
+2006-01-18 07:00 we7u
+
+ * src/: main.c, map_cache.c: A fix for the X11 fault caused when
+ the DB Library header/library versions don't match. The code
+ should now just disable map caching and keep right on going.
+
+2006-01-18 06:48 we7u
+
+ * src/x_spider.c: Changing one declaration to get rid of one gcc4.0
+ warning.
+
+2006-01-17 13:06 we7u
+
+ * src/alert.c, src/awk.c, src/bulletin_gui.c, src/color.c,
+ src/datum.c, src/db.c, src/dbfawk.c, src/draw_symbols.c,
+ src/fcc_data.c, src/festival.c, src/geo-client.c, src/geo-find.c,
+ src/geocoder_gui.c, src/gps.c, src/hashtable.c,
+ src/hashtable_itr.c, src/hostname.c, src/igate.c,
+ src/interface.c, src/interface_gui.c, src/io-common.c,
+ src/io-mmap.c, src/lang.c, src/list_gui.c, src/locate_gui.c,
+ src/location.c, src/location_gui.c, src/macspeech.c, src/main.c,
+ src/map_cache.c, src/Makefile.am, src/map_WMS.c, src/map_dos.c,
+ src/map_gdal.c, src/map_geo.c, src/map_gnis.c, src/map_pdb.c,
+ src/map_shp.c, src/map_tif.c, src/map_tiger.c, src/maps.c,
+ src/messages.c, src/messages_gui.c, src/objects.c,
+ src/popup_gui.c, src/rac_data.c, src/rotated.c, src/shp_hash.c,
+ src/snprintf.c, src/sound.c, src/testawk.c, src/track_gui.c,
+ src/util.c, src/view_message_gui.c, src/wx.c, src/wx_gui.c,
+ src/x_spider.c, src/xa_config.c, src/xastir_udp_client.c,
+ AUTHORS, DEBUG_LEVELS, FAQ, INSTALL, LICENSE, Makefile.am, NEWS,
+ README, README.CVS, README.Contributing, README.Getting-Started,
+ README.MAPS, README.win32, REGRESSION_TESTS, UPGRADE,
+ acinclude.m4, bootstrap.sh, changes.txt, configure.ac,
+ install-xastir, update-xastir, xastir.1, help/Makefile.am,
+ help/help-Dutch.dat, help/help-English.dat, help/help-French.dat,
+ help/help-German.dat, help/help-Italian.dat,
+ help/help-Portuguese.dat, help/help-Spanish.dat, m4/Makefile.am,
+ scripts/Makefile.am, scripts/Xastir_tigerpoly.py,
+ scripts/example_objects.log, scripts/fcc-get, scripts/get-gnis,
+ scripts/get_shapelib.sh, scripts/inf2geo.pl, scripts/ozi2geo.pl,
+ scripts/toporama250k.pl, scripts/toporama50k.pl,
+ scripts/xastir-fixcfg.sh, scripts/xastir-migrate.sh: Updating
+ copyright info.
+
+2006-01-17 13:03 we7u
+
+ * symbols/Makefile.am, symbols/symbols.dat, config/24kgrid.dbfawk,
+ config/gps_wpt.dbfawk, config/language-Dutch.sys,
+ config/language-English.sys, config/language-French.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, config/nwsc_ddmmyy.dbfawk,
+ config/tnc-startup.aea, config/tnc-startup.d700,
+ config/tnc-startup.kam, config/tnc-startup.kpc2,
+ config/tnc-startup.kpc3, config/tnc-startup.paccomm,
+ config/tnc-startup.pico, config/tnc-startup.sys,
+ config/tnc-startup.thd7, config/tnc-startup.tnc2,
+ config/tnc-startup.tnc2-ui, config/tnc-stop.d700,
+ config/tnc-stop.sys, config/tnc-stop.thd7,
+ config/tnc-stop.tnc2-ui, config/Makefile.am,
+ config/nwsmzddmmyy.dbfawk, config/nwsmzoddmmyy.dbfawk,
+ config/nwsozddmmyy.dbfawk, config/nwsw_ddmmyy.dbfawk,
+ config/nwsz_ddmmyy.dbfawk, config/nwszoddmmyy.dbfawk,
+ config/predefined_EVENT.sys, config/predefined_SAR.sys,
+ config/tgr2shp.dbfawk, config/tgr2shppoly.dbfawk,
+ config/tgrcty.dbfawk, config/tgrkgl.dbfawk, config/tgrlk.dbfawk,
+ config/tgrlpt.dbfawk, config/tgrlpy.dbfawk,
+ config/tgrplc00.dbfawk, config/tgrwat.dbfawk,
+ callpass/Makefile.am, callpass/callpass.c, Davis/Makefile.am,
+ Davis/README, Davis/bootstrap.sh, Davis/configure.ac,
+ Davis/src/Makefile.am, Davis/src/db2APRS.c, Davis/src/defs.h,
+ src/alert.h, src/awk.h, src/bulletin_gui.h, src/color.h,
+ src/database.h, src/datum.h, src/dbfawk.h, src/draw_symbols.h,
+ src/fcc_data.h, src/festival.h, src/geo.h, src/gps.h,
+ src/hashtable.h, src/hashtable_itr.h, src/hashtable_private.h,
+ src/hostname.h, src/igate.h, src/interface.h, src/io.h,
+ src/lang.h, src/leak_detection.h, src/list_gui.h, src/main.h,
+ src/map_cache.h, src/maps.h, src/messages.h, src/objects.h,
+ src/popup.h, src/rac_data.h, src/rotated.h, src/shp_hash.h,
+ src/snprintf.h, src/symbols.h, src/track_gui.h, src/util.h,
+ src/wx.h, src/x_spider.h, src/xa_config.h, src/xastir.h: Updating
+ copyright info.
+
+2006-01-17 12:10 we7u
+
+ * scripts/BUILDRPMS: Correcting bugs that crept in.
+
+2006-01-17 11:58 we7u
+
+ * scripts/BUILDRPMS: Updating script for latest SuSE RPM build.
+
+2006-01-17 11:47 we7u
+
+ * INSTALL, README: Updating notes to call out latest packages.
+ Adding SuSE 10.0 instructions to README.
+
+2006-01-16 10:21 we7u
+
+ * scripts/BUILDRPMS: Updating script for latest release numbers.
+
+2006-01-16 09:12 we7u
+
+ * configure.ac: Bumping version to 1.8.1 for new mods.
+
+2006-01-16 09:04 we7u
+
+ * configure.ac, scripts/do_xastir_release_dev,
+ scripts/do_xastir_release_stable: Preparing for 1.8.0 release.
+
+2006-01-13 07:34 we7u
+
+ * bootstrap.sh: Changing the prompts a bit. We now see a countdown
+ to completion.
+
+2006-01-12 16:06 tvrusso
+
+ * README.MAPS: Fix error in command line for sorting the EN.dat
+ file from FCC.
+
+2006-01-12 08:58 we7u
+
+ * config/language-German.sys: Another update from Rolf.
+
+2006-01-12 07:25 we7u
+
+ * config/language-German.sys: Updates by Rolf Bleher, DK7IN.
+ Thanks!
+
+2006-01-11 12:28 we7u
+
+ * src/db.c: Processing/decoding the altitude extension on more
+ packet types. Altitude wasn't being decoded for some weather and
+ grid packets. It is now.
+
+2006-01-11 12:27 we7u
+
+ * help/help-English.dat: Adding some notes about lack of altitude
+ in compressed-mode posits.
+
+2006-01-11 07:43 we7u
+
+ * src/db.c: Fixing a decoding bug w.r.t. lower-case N/S/E/W in a
+ couple of types of packets.
+
+2006-01-10 09:03 francais1
+
+ * config/language-French.sys: More updates from Jacques Chion, with
+ some tweaks and translation of GPSS* strings.
+
+2006-01-09 14:10 we7u
+
+ * config/language-Dutch.sys: Updates by Han Sytsma, PE1FAM.
+ Thanks!
+
+2006-01-06 18:45 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Fixing a bug on the GPS
+ Status dialog. It wasn't reporting the correct status for WAAS.
+ Corrected that and added more possibilities for status.
+
+2006-01-03 13:59 chicoreus
+
+ * src/db.c: Minor bugfix: Range Scale and Scale bar were drawn
+ displaced when border was on and grid was off (even though border
+ is only shown when grid is on).
+
+2006-01-02 13:34 we7u
+
+ * src/db.c: Fixing segfault that occurs in extract_multipoints()
+ when data == NULL.
+
+2005-12-31 18:38 chicoreus
+
+ * help/help-English.dat: Added Documentation of Map/Enable Map
+ Border.
+
+2005-12-31 07:13 chicoreus
+
+ * src/maps.c: Bug fixes in the labeling of utm zones, northing
+ lines, and easting lines when the grid is labeled. When grid is
+ finely spaced on the screen, only alternate lines are labeled.
+ Grid and zones are labeled correctly and reasonably most of the
+ time when more than one lettered zone row appears on the screen.
+ Still has some problems, but works for most places.
+
+2005-12-29 13:11 we7u
+
+ * INSTALL: Added instructions for updating /etc/ld.so.conf.d/
+ directory for those systems that use this alternate method.
+ Courtesy of Dale, KB9JJA. Thanks!
+
+2005-12-20 18:01 chicoreus
+
+ * src/: main.c, objects.c: Performance tuning: Moved call to
+ redraw_symbols out of CAD_vertice_allocate to prevent repeated
+ redrawing on each vertex of each cad object loaded from a file at
+ startup.
+
+2005-12-20 10:24 chicoreus
+
+ * src/maps.c: In trying to work out what draw_grid is doing, added
+ some documentation to the utm_grid structures. Added a test
+ inside draw_grid so that the utm grid labeling code is only
+ running for utm_grid.zone elements that contain rows and columns.
+
+2005-12-19 10:18 chicoreus
+
+ * src/maps.c: Minor bugfix and additional comments on code for
+ labeling UTM grid. Changed format to include leading zeroes for
+ easting and northing.
+
+2005-12-19 09:40 chicoreus
+
+ * README.MAPS: Added brief discussion of gdalinfo and
+ gdal_translate for handling geotiff files that aren't in byte
+ form or contain multiple bands.
+
+2005-12-16 14:13 chicoreus
+
+ * src/maps.c: Added the ability to draw a 1 pixel outline in a
+ different color to rotated text in
+ draw_rotated_label_text_common() and some of its wrappers.
+
+2005-12-16 14:09 chicoreus
+
+ * src/xa_config.c: Making draw_labeled_grid_border persistent
+ between restarts.
+
+2005-12-15 14:10 chicoreus
+
+ * src/: db.c, main.c, main.h, maps.c: First cut at adding a labeled
+ border to the map shown on the screen for printing. This can be
+ used, for example, to print maps with a labeled UTM grid for a
+ SAR task team showing the area they are to search. Metadata
+ about the map is displayed in the top border, coordinates of grid
+ lines are displayed on the bottom and right borders (to make it
+ easier for people to correctly read and report UTM coordinates in
+ the form zone easting northing. The labeled border is displayed
+ when both the grid and the border are enabled. There are still
+ problems and missing features. The rotated font on the right
+ border is not the pretty font used on the rest of the border.
+ The border and grid labels are only drawn for a UTM grid, not for
+ a Lat/Lon grid. Zone designators are not properly displayed when
+ more than one zone is visible on the screen. When grid lines are
+ closely spaced, the grid labels overlap on the screen.
+
+2005-12-15 10:31 we7u
+
+ * README.win32: Fixing a typo.
+
+2005-12-15 10:24 chicoreus
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: First rough cut at
+ adding a labeled border to a map to allow the printing of
+ arbitrary maps with a labeled grid (that can, for example, be
+ printed and given to SAR task teams). If the map grid is
+ enabled, and the border is enabled, a white border is drawn as
+ part of the grid and labels for each grid line are added in this
+ border. Metadata describing the map are also added in the
+ border. This is a first rough cut with several problems. It is
+ only implemented for a UTM grid, not for a Lat/Long grid. The
+ rotated numbers do not use the same clean font as the non-rotated
+ numbers. The labels in the border are not clearly
+ distinguishable when the grid is tightly spaced on the screen.
+ The zone labels do not work properly when more than one zone is
+ on the screen. The choice of labeling the bottom border and the
+ right border with the UTM grid line easting and northings is
+ deliberate to help people to correctly read the map and report
+ UTM coordinates in the form: zone easting northing.
+
+2005-12-13 14:11 we7u
+
+ * config/Makefile.am: Correcting the name of the dbfawk file that
+ we want automatically removed. I forgot the underline first time
+ around.
+
+2005-12-13 07:54 we7u
+
+ * src/objects.c: Tweaking a debug statement so we don't get a
+ segfault if we hit a null pointer.
+
+2005-12-12 18:50 chicoreus
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Added localization
+ strings for map display of CAD object metadata. Added update of
+ CAD objects on toggle of display of metadata.
+
+2005-12-12 14:56 chicoreus
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/database.h, src/main.c,
+ src/main.h, src/objects.c, src/objects.h: Adding more user
+ interface elements to CAD Object display 1) Clarifying user side
+ handling of raw_probability as a percent 2) Allow user to set CAD
+ boundary line type 3) Allow user to toggle on and off display of
+ CAD Polygons, Label, Area, and probability.
+
+2005-12-11 10:20 we7u
+
+ * src/main.c: Fixing the Station->Configure submenu. Wasn't
+ working on Lesstif but was fine on OpenMotif. Should work on
+ both now.
+
+2005-12-07 18:55 chicoreus
+
+ * help/help-English.dat: Edited CAD object text to reflect the
+ movement of the CAD object functions from the mouse menu to the
+ toolbar and the View and Map menus. Added some text for
+ Probability Circle Objects.
+
+2005-12-07 17:04 we7u
+
+ * src/interface.c: Only twiddle DTR on HSP ports if global transmit
+ is enabled.
+
+2005-12-07 17:02 we7u
+
+ * src/objects.c: Very minor formatting change. No code changes.
+
+2005-12-07 12:40 we7u
+
+ * config/Makefile.am: Automating the deletion of the
+ nwsfzddmmyy.dbfawk file from the /usr/local/share/xastir/config
+ directory during install. We don't use it anymore and it causes
+ problems if present.
+
+2005-12-07 10:38 we7u
+
+ * src/interface.c: Patch by Paul Morris, modified slightly by me,
+ to make objects work for the case when global transmits have been
+ disabled.
+
+2005-12-07 09:32 tvrusso
+
+ * config/: Makefile.am, nwsfz_ddmmyy.dbfawk: Remove unnecessary
+ (and problematic) nwsfz_ddmmyy.dbfawk file.
+
+2005-12-07 08:09 we7u
+
+ * src/map_gdal.c: Moving some struct typedef's and nested functions
+ out of the main function so that it will compile with latest
+ MacOSX GCC compiler.
+
+2005-12-06 22:41 we7u
+
+ * src/map_shp.c: Made code more correct by changing alert->title to
+ modified_title in a couple of places. modified_title is a copy
+ of alert->title so the real-world effects of this change are
+ little to none. Tweaked some comments in the area as well.
+
+2005-12-06 19:04 tvrusso
+
+ * config/nwsmzddmmyy.dbfawk: Fix incorrect key generation for
+ mzddmmyy.shp file.
+
+ The key produced by the dbfawk rule must match the key that comes
+ from the NWS alert. These will generally be "XX_Zyyy". The "ID"
+ field of the mzddmmyy.dbf record is of form "XXZyyy", and prior
+ to this commit it was used directly as the key, thereby never
+ matching any alerts. This fix inserts the _ character after the
+ first to characters of the ID field to produce a usable key.
+
+2005-12-06 13:35 we7u
+
+ * src/map_shp.c: Added more debugging text for dbfawk and wx
+ alerts.
+
+2005-12-06 12:53 we7u
+
+ * src/maps.c: Correcting some comments.
+
+2005-12-06 12:50 we7u
+
+ * src/maps.c: Adding a bit more text to one wx alert debug message.
+
+2005-12-06 12:26 we7u
+
+ * src/interface.c: Moving a nested function so that it is no longer
+ nested. This is necessary in order to compile on MacOSX with
+ their latest GCC compiler.
+
+2005-12-06 11:34 we7u
+
+ * src/util.c: Changing a nested function to non-nested in order to
+ enable compiling with the latest MacOSX compiler.
+
+2005-12-04 19:05 we7u
+
+ * src/: main.c, xastir.h, festival.c: Adding a "Test" button to the
+ Configure->Speech dialog for testing the speech subsystem and for
+ adjusting the audio levels (by an external program).
+
+2005-12-01 11:32 we7u
+
+ * update-xastir: Changing the "make" step so that it doesn't run as
+ root.
+
+2005-12-01 09:22 we7u
+
+ * src/map_gdal.c: Commenting out and include that we're currently
+ not using.
+
+2005-11-29 22:36 we7u
+
+ * src/map_pdb.c: Implementing the same sorts of map interruption
+ capability for PocketAPRS maps that we just did for the other
+ types of maps.
+
+2005-11-28 19:16 we7u
+
+ * src/: map_WMS.c, map_gdal.c, map_geo.c, map_shp.c, map_tif.c,
+ map_tiger.c: Adding more map interrupt code, to make it
+ easier/faster to interrupt map drawing by panning or zooming.
+
+2005-11-28 12:51 we7u
+
+ * src/map_shp.c: Adding capability to interrupt map drawing and
+ start over in the inner loops of the GNIS and DOS map drawing
+ functions. This makes panning or zooming cause an interrupt much
+ quicker while drawing maps, allowing Xastir to restart the redraw
+ process sooner.
+
+2005-11-28 12:43 we7u
+
+ * src/: map_dos.c, map_gnis.c: Adding capability to interrupt map
+ drawing and start over in the inner loops of the GNIS and DOS map
+ drawing functions. This makes panning or zooming cause an
+ interrupt much quicker while drawing maps, allowing Xastir to
+ restart the redraw process sooner.
+
+2005-11-23 14:37 we7u
+
+ * scripts/do_xastir_release_stable: Adding another admin script so
+ that it won't get lost.
+
+2005-11-23 14:32 we7u
+
+ * scripts/do_xastir_release_dev: Adding another couple of admin
+ scripts so they won't ever get lost.
+
+2005-11-23 14:28 we7u
+
+ * scripts/STABLE: Adding another admin script to the repository so
+ that it won't get lost.
+
+2005-11-23 14:27 we7u
+
+ * scripts/BUILDRPMS: Adding the RPM Build script so that it will be
+ available as an example to others.
+
+2005-11-23 11:34 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/map_cache.c: Disabling map
+ caching if dblib header/library mismatch, to help prevent
+ segfaults. Also doing a popup now when this condition is found
+ as Xastir starts up.
+
+2005-11-23 11:33 we7u
+
+ * NWS-TEST.log: Changed some comments.
+
+2005-11-23 11:33 we7u
+
+ * README.MAPS: Added a blurb about how to test weather alert
+ functionality.
+
+2005-11-22 14:31 we7u
+
+ * NWS-TEST.log: Added some more notes.
+
+2005-11-22 12:49 we7u
+
+ * NWS-TEST.log: Moved one OR alert over to the coast and made it
+ blue, to stand out more against the other alerts.
+
+2005-11-22 12:35 we7u
+
+ * NWS-TEST.log: Moving all of the tests to the Northwest region so
+ we don't have to look all over the country for them.
+
+2005-11-22 11:57 we7u
+
+ * NWS-TEST.log: Changing the colors for adjacent alerts, making it
+ easier to differentiate between them.
+
+2005-11-22 10:41 we7u
+
+ * NWS-TEST.log: Adding a file which can be used to test out the
+ weather alert functionality.
+
+2005-11-18 16:36 we7u
+
+ * src/map_shp.c: Fix for RED_FLAG weather alerts.
+
+2005-11-18 12:00 we7u
+
+ * src/main.c: Making more menus detachable. Splitting the toolbar
+ buttons vertically by a few more pixels to make it look better on
+ Cygwin.
+
+2005-11-18 11:59 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Getting rid of a
+ couple of unused labels, reclaiming one for the new "Draw"
+ toolbar togglebutton.
+
+2005-11-18 07:48 we7u
+
+ * src/wx_gui.c: Changed tab to spaces.
+
+2005-11-17 09:04 we7u
+
+ * src/main.c: Adding the cad polygons list to the map->CAD Objects
+ submenu. It still has a link in the View menu as well.
+
+2005-11-17 08:56 we7u
+
+ * src/main.c: Moving the remaining CAD Object stuff to the Map menu
+ (from the mouse menu)
+
+2005-11-17 07:41 we7u
+
+ * src/objects.c: Changing colors of CAD Polygon labels and
+ probability. Extending string so that it display 0.00% through
+ 100.00% and displays the '%' sign.
+
+2005-11-17 06:57 we7u
+
+ * .cvsignore: Added make.log and xastir-min.spec
+
+2005-11-16 22:55 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/objects.c,
+ src/objects.h: Moving Draw CAD functions to main menu and
+ toolbar.
+
+2005-11-16 18:43 we7u
+
+ * src/objects.c: Adding a cancel button to the CAD Objects detailed
+ info dialog. Fixing the area size as listed in the same dialog.
+
+2005-11-16 13:50 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Changing from
+ "Erase All" to "Erase" for menu entry.
+
+2005-11-16 13:50 we7u
+
+ * src/main.c: Changing one comment.
+
+2005-11-16 13:00 we7u
+
+ * src/objects.c: Changing "Cancel" to "Close" on CAD Object list
+ dialog.
+
+2005-11-16 12:52 we7u
+
+ * src/objects.c: Fixing CAD area labels and comments so that they
+ get retrieved properly from file.
+
+2005-11-16 12:19 we7u
+
+ * src/main.c: Moving some items from the Map and Station menu into
+ Configure submenus.
+
+2005-11-16 11:33 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/main.h,
+ src/objects.c, src/objects.h: More from Paul Morris: Allows
+ edits of the data associated with CAD objects and moving more of
+ the Close CAD object code into functions. It also adds
+ localization to the delete CAD object dialog.
+
+2005-11-16 10:08 we7u
+
+ * xastir-min.spec.in, Makefile.am, configure.ac: Adding a new
+ spec.in file which skips all of the optional libraries except for
+ ImageMagick.
+
+2005-11-10 14:38 gstueve
+
+ * src/map_shp.c: Add test for debugging alert match to reduce noise
+ on display.
+
+2005-11-10 08:57 we7u
+
+ * scripts/fcc-get: Yet another try to fix the Id string.
+
+2005-11-10 08:37 we7u
+
+ * scripts/fcc-get: Trying to fix Id string again.
+
+2005-11-10 08:36 we7u
+
+ * scripts/fcc-get: Fixing the RCS Id: string so that it gets
+ populated by CVS.
+
+2005-11-10 07:51 gstueve
+
+ * src/objects.c: Use the time that was already provided. Don't
+ bother system for it again.
+
+2005-11-10 07:28 gstueve
+
+ * src/: alert.c, alert.h, bulletin_gui.c, bulletin_gui.h,
+ database.h, db.c, main.c, messages.c, messages.h, popup.h,
+ popup_gui.c: Use the time that we already have from UpdateTime
+ and not keep asking the system for it over and over again.
+
+2005-11-10 06:59 gstueve
+
+ * scripts/fcc-get: Remove the extra CR where ever possible, real OS
+ has no need for such.
+
+2005-11-09 06:03 gstueve
+
+ * src/interface.c: Adjust error messages to describe problem in
+ current function.
+
+2005-11-08 21:57 gstueve
+
+ * config/Makefile.am: Add old zone file dbf into Makefile list.
+
+2005-11-08 21:44 gstueve
+
+ * config/: Makefile.am, nwsmzoddmmyy.dbfawk: Add back in the old mz
+ dbf definition.
+
+2005-11-08 17:40 gstueve
+
+ * src/maps.c: Add cancelled Alerts to list of mapped but don't draw
+ on display.
+
+2005-11-08 16:07 gstueve
+
+ * config/nwszoddmmyy.dbfawk: Add old Zone file match for older dbf
+ structure.
+
+2005-11-08 11:15 gstueve
+
+ * src/main.c: We already have a good idea of what time it is inside
+ UpdateTime. It is NOT necessary to always be asking the system
+ what time it is within one function and its support routines.
+ This is not a '25 or 6 to 4' need.
+
+2005-11-08 06:52 gstueve
+
+ * src/: database.h, db.c, main.c: Make packet display logic much
+ more efficient. Do it all in fewest moves.
+
+2005-11-08 06:35 gstueve
+
+ * src/map_gnis.c: Visual optimization. Make things easier to read.
+
+2005-11-07 14:33 we7u
+
+ * src/db.c: Changing comments about KISS variants.
+
+2005-11-07 12:33 we7u
+
+ * src/db.c: Changed one comment.
+
+2005-11-07 09:04 we7u
+
+ * src/main.c: Adding a NULL parameter to close out the parameter
+ list for two XtVaGetValues() calls.
+
+2005-11-07 06:14 gstueve
+
+ * src/fcc_data.c: Optimize the use of substr so the function is
+ MUCH more efficient.
+
+2005-11-07 06:12 gstueve
+
+ * config/: nwsmzddmmyy.dbfawk, nwsz_ddmmyy.dbfawk: The newer
+ shapefiles no longer have the additional fields, so system was
+ not matching file structure. Make it match better.
+
+2005-11-06 16:14 we7u
+
+ * src/util.c: Fixing the remove_trailing_dash_zero() routine. It
+ was changing "-10" into "-1" which is quite wrong.
+
+2005-11-03 12:15 we7u
+
+ * src/: db.c, interface.c: Making sure we don't transmit if the
+ global disable or the individual interface disables are
+ activated.
+
+2005-11-02 11:01 we7u
+
+ * src/db.c: Adding some notes about KISS and CRC's.
+
+2005-11-02 07:40 we7u
+
+ * src/xastir_udp_client.c: Changed length from int to socklen_t to
+ get rid of warning messages for some compilers.
+
+2005-11-01 13:32 gstueve
+
+ * src/util.c: Go back to whining about dual-band TNC separator.
+
+2005-11-01 11:21 gstueve
+
+ * src/alert.c: Add debugging detail for unparsed alerts.
+
+2005-11-01 11:18 gstueve
+
+ * src/util.c: First cut to stop whining on dual-band TNC with
+ WIDEn-m paradigm.
+
+2005-10-26 21:58 we7u
+
+ * src/interface.c: Truncating transmitted posits at the
+ spec-specified length. Long comments can't make us transmit
+ out-of-spec packets anymore.
+
+2005-10-26 21:52 we7u
+
+ * src/sound.c: Added a missing include that causes a problem on
+ Solaris if missing.
+
+2005-10-26 12:16 we7u
+
+ * src/main.c: Re-enabling the messages to STDERR when SIGHUP is
+ sent to the main process and a restart is occurring. Add comment
+ about disabling SIGHUP handler in child processes.
+
+2005-10-26 12:14 we7u
+
+ * src/interface.c: Tweaks to assure that the global disables on the
+ Interface menu have the correct effect.
+
+2005-10-26 12:11 we7u
+
+ * src/: hostname.c, macspeech.c, sound.c, x_spider.c: Regressing to
+ default SIGHUP handler in child processes instead of our special
+ restart() signal handler.
+
+2005-10-26 12:07 we7u
+
+ * REGRESSION_TESTS: Added date stamps and more comments.
+
+2005-10-26 08:46 we7u
+
+ * src/main.c: Changing the messages that appear as Xastir shuts
+ down, putting them back under debug_level control in restart().
+ restart() gets called multiple times due to sending SIGHUP to the
+ TCP/UDP servers during shutdown, and the messages were appearing
+ multiple times if those servers were running.
+
+2005-10-25 18:01 we7u
+
+ * src/util.c: Fixing the alert expiration problem. May need to be
+ checked when we switch out of daylight savings time again.
+
+2005-10-25 13:08 we7u
+
+ * src/main.c: Adding an include so that we can use the ComboBox
+ widget.
+
+2005-10-25 13:04 we7u
+
+ * src/main.c: Limiting the selection box for preconfigured object
+ filenames on the Configure->Defaults dialog to three items.
+
+2005-10-25 12:53 we7u
+
+ * src/main.c: Minor cleanups of the predefined object code: Added
+ a few free's for XmStrings, allocated memory before an
+ XtGetValues call.
+
+2005-10-25 12:25 we7u
+
+ * src/: util.c, util.h: Making rpl_malloc() compile in all cases
+ and put a prototype for it in util.h to get rid of more compiler
+ warnings. rpl_malloc() only gets used if AC_FUNC_MALLOC detetcs
+ a version of malloc that doesn't return a valid pointer if you
+ try to malloc zero bytes.
+
+ These changes make it compile ok on FC4.
+
+2005-10-25 08:18 we7u
+
+ * src/util.c: Added some comments.
+
+2005-10-24 20:37 we7u
+
+ * REGRESSION_TESTS: Added some notes about future directions we
+ could go to make the tests a bit more complete.
+
+2005-10-24 20:36 we7u
+
+ * FAQ: Tweaked the "restart Xastir" paragraph to keep it
+ up-to-date.
+
+2005-10-24 12:29 we7u
+
+ * src/: main.c, main.h: Patch to allow SIGHUP to cause Xastir to
+ restart properly. This patch also appears to carry along the
+ original command-line parameters and environment to the new task.
+ The xastir.pid file is correct in all cases, and in fact the
+ main process ID doesn't change between restarts.
+
+2005-10-24 12:27 we7u
+
+ * src/macspeech.c: Spawning a separate process for sending the text
+ to the Mac OSX speech subsystem. We also incorporate a limit of
+ 10 processes that can be waiting for the subsystem to be freed
+ up. If 10 processes are waiting and another speech request is
+ made, the latter is dropped. No provision is made for the ORDER
+ that the (up to) ten processes get access to the speech subsystem
+ either so the order will most likely get mixed up if you're
+ trying to send speech strings out too fast.
+
+2005-10-24 08:52 we7u
+
+ * help/help-English.dat, src/main.c, src/objects.c, src/objects.h:
+ Another SAR patch from Paul Morris. Here's what he says: This
+ one implements a dialog for selecting CAD objects to delete from
+ the Erase All CAD polygon menu item along with implementing
+ delete by name in CAD_object_delete(). It also adds some help
+ text on prepared objects and CAD objects and changes the
+ XmStringCreateLocalized() calls to XmStringCreateLtoR().
+
+2005-10-21 21:46 we7u
+
+ * src/main.c: Restarting on SIGHUP a bit better. It now sends
+ argv[] at least the first time around. Need to figure out why
+ the 2nd time doesn't work at all. Perhaps signal handlers are
+ getting messed up on reboot?
+
+2005-10-21 13:28 we7u
+
+ * src/objects.c: Another tweak by Paul Morris for proper handling
+ of CAD objects.
+
+2005-10-21 12:33 we7u
+
+ * FAQ: Reworded text for SIGHUP.
+
+2005-10-21 12:27 we7u
+
+ * FAQ: Adding the SIGHUP stuff to the FAQ.
+
+2005-10-21 12:18 we7u
+
+ * README.Getting-Started: Added some more signals to the External
+ Stimuli section.
+
+2005-10-21 12:11 we7u
+
+ * src/main.c: Adding support for SIGHUP. Xastir will
+ save/exit/restart if a SIGHUP is received. Also enabled a
+ #define near the top of main.c that enables the xastir.pid
+ processing. If someone attempts to start Xastir and there's a
+ process running with that PID, Xastir will exit.
+
+ The SIGHUP support works, but the command-line parameters aren't
+ carried through as the normal processing for them devours them
+ out of the argv[] array. We need to save that array away or use
+ a non-destructive method of processing the parameters.
+
+2005-10-21 11:02 we7u
+
+ * src/objects.c: Small tweak so that the code looks in the
+ /usr/local/share/xastir/config directory for the predefined
+ objects for now. Later we'll add the capability of overriding
+ the system files with local user files.
+
+2005-10-21 10:41 we7u
+
+ * src/interface_gui.c: Reordering the management & positioning
+ statements so that it doesn't appear on the screen until it gets
+ positioned.
+
+2005-10-21 07:27 tvrusso
+
+ * src/: main.c, objects.c: Move variable declarations to tops of
+ blocks to satisfy old-fashioned compilers that hate the modern
+ practice of declaring variables just before their use.
+
+2005-10-20 15:47 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Changing
+ pre-defined objects labels to more descriptive words.
+
+2005-10-20 15:02 we7u
+
+ * src/main.c: Getting rid of Button1 assignment for CAD objects.
+ This prevents us from zooming/panning/measuring while creating a
+ CAD object.
+
+2005-10-20 14:52 we7u
+
+ * config/Makefile.am: Adding predefined files to Makefile so
+ they'll get installed.
+
+2005-10-20 14:52 we7u
+
+ * config/: predefined_EVENT.sys, predefined_SAR.sys: Example
+ pre-defined SAR/Event object files by Paul Morris.
+
+2005-10-20 14:40 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, help/help-English.dat,
+ src/database.h, src/main.c, src/main.h, src/objects.c,
+ src/objects.h, src/xa_config.c: Patch by Paul Morris, AA3SD, to
+ tweak CAD objects functionality a bit and add pre-defined
+ SAR/Event objects from files.
+
+2005-10-20 13:34 we7u
+
+ * src/color.c: Reformatting. No real code changes.
+
+2005-10-20 13:12 gstueve
+
+ * src/: alert.c, alert.h, wx_gui.c: Reintroduce SKYWARN addendum to
+ Wx Messages & sort Wx Alert list. Only sort list if window is
+ activated.
+
+2005-10-20 13:08 gstueve
+
+ * src/: map_shp.c, maps.c: Move the on_screen decision to a
+ position where it really works.
+
+2005-10-20 10:58 we7u
+
+ * README.MAPS: Changing one sentence to make things more clear.
+
+2005-10-20 10:57 we7u
+
+ * README.MAPS: Removing an unnecessary statement.
+
+2005-10-20 10:53 we7u
+
+ * README.MAPS: Was missing a pipe symbol in the new sort command.
+ Also use the same command for all operating systems with this
+ tweak.
+
+2005-10-20 10:21 we7u
+
+ * README.MAPS: Fix submitted by A. Carver for FCC database sorting
+ for Cygwin.
+
+2005-10-20 09:35 we7u
+
+ * src/interface_gui.c: Changing default path to WIDE2-2 instead of
+ WIDE for new interfaces.
+
+2005-10-20 05:41 gstueve
+
+ * src/maps.c: Activate debugging messages from commented fprintf
+ messages.
+
+2005-10-20 05:35 gstueve
+
+ * src/util.c: Clamp limits of map to nearest edge. Not
+ clipping/clamping & report error.
+
+2005-10-19 18:29 we7u
+
+ * src/: map_WMS.c, map_geo.c, map_tif.c, map_tiger.c: Commenting
+ out the XFreeColors() calls for now. Cygwin seems to be much
+ more sensitive to these calls than Linux.
+
+2005-10-19 13:24 we7u
+
+ * src/interface.c: Disabling sending of my own posits to x_spider
+ if transmit_disable is non-zero.
+
+2005-10-19 13:19 we7u
+
+ * src/interface.c: Cease sending packets to x_spider if
+ loopback_only is in effect.
+
+2005-10-19 13:19 we7u
+
+ * src/objects.c: Added some comments.
+
+2005-10-19 12:54 we7u
+
+ * src/objects.c: Getting rid of "Transmitting objects/items"
+ statusline message if transmit of those types of packets is
+ disabled globally.
+
+2005-10-19 12:21 we7u
+
+ * src/: map_WMS.c, map_geo.c, map_tif.c, map_tiger.c: Adding
+ XFreeColors() calls just before each XAllocColor() call. This is
+ to keep the counters in sync that count how many times each color
+ is allocated, hopefully preventing the can't allocate color
+ warning messages.
+
+2005-10-19 12:20 we7u
+
+ * src/color.c: Adding a comment. No code changes.
+
+2005-10-17 14:35 we7u
+
+ * configure.ac: Bumping version number to 1.7.1 for further
+ development.
+
+2005-10-17 14:12 we7u
+
+ * configure.ac: Bumping the release number to 1.7.0.
+
+2005-10-17 13:46 francais1
+
+ * config/language-French.sys: Merci a Jacques Chion, F6CWO
+
+2005-10-17 13:41 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Fixing some typos:
+ Missing pipe symbols at the end of strings. French language file
+ will be fixed shortly too, along with a few more translations.
+ Thanks to Olivier for catching these.
+
+2005-10-17 12:16 we7u
+
+ * README, help/help-English.dat: Added notes about Bob Bruninga's
+ list of generic callsigns that should be gated to RF.
+
+2005-10-17 11:53 we7u
+
+ * help/help-English.dat: Added a What's New section for
+ up-and-coming 1.7.0 release. Added notes regarding gating
+ specific stations to RF and which generic callsigns that Bob
+ Bruninga recommends doing that with.
+
+2005-10-17 11:51 we7u
+
+ * README.win32: Reformatting the list of languages available.
+
+2005-10-17 11:50 we7u
+
+ * README.Getting-Started: Changing the revision number in an
+ example. Updating the example Xastir help text.
+
+2005-10-17 11:49 we7u
+
+ * README.Contributing: Changing a revision number in an example.
+
+2005-10-17 11:49 we7u
+
+ * README: Adding a note about a few calls that Bob Bruninga
+ recommends always gating to RF.
+
+2005-10-17 11:47 we7u
+
+ * INSTALL: Tweaking formatting of -l language notes.
+
+2005-10-16 10:16 we7u
+
+ * config/language-German.sys: An update to the German language file
+ by Rolf Bleher, DK7IN. Thanks!
+
+2005-10-15 18:51 we7u
+
+ * config/language-Dutch.sys: Updates by Han Sytsma. Thanks!
+
+2005-10-15 18:50 we7u
+
+ * config/language-English.sys: Fixing a typo.
+
+2005-10-15 10:30 we7u
+
+ * src/map_tif.c: Making sure the projects.h include isn't needed
+ unless libgdal is compiled in as well. Got rid of UV define and
+ changed invocation to "projUV" instead.
+
+2005-10-15 09:42 we7u
+
+ * src/map_tif.c: Fixing a problem caused by the new code which
+ fixes the gdal/geotiff bug. This fix cuases the original
+ functions to be called if gdal isn't installed.
+
+2005-10-14 11:06 we7u
+
+ * src/map_tif.c: Received permission from Frank Warmerdam to use
+ some of his code inside Xastir, relicensing it under GPL. We use
+ this new right to include one function in map_tif.c which allows
+ us to keep topo maps support even when libgdal is compiled in.
+
+2005-10-14 08:11 we7u
+
+ * README.win32: Added a note about running configure from an xterm
+ so that "gv" support will be compiled in. If run from a non-X11
+ window, "gv" configure test fails.
+
+2005-10-13 13:51 francais1
+
+ * config/language-French.sys: Some more strings translated, but not
+ all...
+
+2005-10-13 08:39 gstueve
+
+ * src/main.c: Put the full title back on the window, so we can know
+ what machine is running the app.
+
+2005-10-12 17:09 we7u
+
+ * src/messages.c: Added code that will switch back to RF if no
+ TX-enabled INET interfaces are up.
+
+2005-10-12 13:09 we7u
+
+ * src/messages.c: New message routing which should take care of a
+ bug-list item: Ceasing to transmit when messaging with internet
+ station and internet interfaces go down. Problem remaining with
+ this code: We transmit out RF interfaces even if QSO'ing with
+ station over internet interface.
+
+2005-10-12 11:33 we7u
+
+ * src/: locate_gui.c, main.c, messages_gui.c, track_gui.c, util.c,
+ util.h: Fixing all of the callsign entry fields so that "-0" is
+ truncated from the end of the string when used.
+
+2005-10-11 16:52 we7u
+
+ * src/main.c: Tweaks to convert callsign-0 to callsign for
+ configure station dialog.
+
+2005-10-11 10:12 we7u
+
+ * src/db.c: Added a bit of debugging. No effect for normal
+ operation.
+
+2005-10-11 08:16 we7u
+
+ * src/db.c: Slightly better igating of messages. This versions
+ saves the message+acks away and then uses that exact string again
+ when igating it, instead of putting together the bits and pieces
+ at that point like the previous code.
+
+2005-10-10 22:07 we7u
+
+ * src/db.c: Another tweak to get reply-ack's propagated through an
+ Xastir igate to RF. This one is tested and works.
+
+2005-10-10 18:29 we7u
+
+ * src/db.c: Comment changes. Also changed the fprintf() for REJ
+ packets to only dump text to STDERR if the REJ was sent to
+ my_callsign.
+
+2005-10-10 12:11 we7u
+
+ * src/db.c: Changed one comment.
+
+2005-10-10 11:52 we7u
+
+ * src/db.c: Added comments. fprintf() to stderr when we receive a
+ REJ packet. We can receive those when a Kenwood radio's message
+ buffer is full.
+
+2005-10-10 11:48 we7u
+
+ * src/messages.c: Minor tweaks w.r.t. REPLY-ACK protocol. Making
+ sure we strip off the unneeded portion before we check the ACK.
+
+2005-10-10 09:31 we7u
+
+ * src/db.c: Fixing igating of messages to RF for messages with
+ REPLY-ACK protocol at the end. We were originally sending our
+ processed ACK at the end which knocked off the free-ack portion.
+ Now we send the full five-character unprocessed REPLY-ACK.
+
+2005-10-10 09:29 we7u
+
+ * src/igate.c: Adding some comments.
+
+2005-10-10 08:23 we7u
+
+ * src/main.c: Fixing a couple of compiler problems via casting.
+ Problems were not seen with SuSE compiler but were seen on other
+ systems.
+
+2005-10-07 18:16 we7u
+
+ * src/objects.c: Tweaks to avoid other object/item/station names
+ when creating SAR objects. Xastir will now add a number to the
+ end of the typical name (starting at "2") in order to create a
+ unique name. This makes for extremely fast placement of
+ important mission objects without worrying about old mission
+ objects or conflicting with other people's current missions.
+
+2005-10-07 18:13 we7u
+
+ * src/main.c: Added some comments.
+
+2005-10-07 18:10 we7u
+
+ * src/db.c: Added some comments.
+
+2005-10-07 18:07 we7u
+
+ * src/track_gui.c: Added a comment.
+
+2005-10-07 18:05 we7u
+
+ * src/list_gui.c: Added some comments.
+
+2005-10-07 13:16 we7u
+
+ * src/objects.c: Added some comments.
+
+2005-10-07 12:49 we7u
+
+ * src/objects.c: Adding fprintf() statements to help work on the
+ SAR objects code.
+
+2005-10-07 12:26 we7u
+
+ * src/: main.c, xa_config.c, xastir.h: Checking in some work having
+ to do with saving/restoring X/Y offsets for the main window. The
+ code doesn't work yet so it commented out.
+
+2005-10-07 12:25 we7u
+
+ * src/objects.c: Adding some comments about future coding that
+ needs to be done w.r.t. SAR objects.
+
+2005-10-07 11:16 we7u
+
+ * src/Makefile.am: Another minor tweak for the icon.
+
+2005-10-07 11:15 we7u
+
+ * src/Makefile.am: Adding the icon.xbm file into the Makefiles.
+
+2005-10-06 13:50 tvrusso
+
+ * src/: main.c, objects.c: Move declarations of variables to before
+ first executable lines of code, to satisfy old-fashioned
+ compilers (gcc 2.95, etc.)
+
+2005-10-06 13:45 we7u
+
+ * src/icon.xbm: Someone pointed out that the RF radiation wasn't
+ symmetrical. Now it is.
+
+2005-10-06 12:46 we7u
+
+ * src/objects.c: Commenting out a debug statement.
+
+2005-10-06 12:39 we7u
+
+ * src/: main.c, objects.c, objects.h: Commenting out the wm_hints
+ code. Adding a "Create SAR Objects" entry to the mouse menu.
+ That last was written and contributed by Paul J. Morris, aa3sd.
+ Thanks!
+
+2005-10-06 12:37 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Adding "Create SAR
+ Objects" right-click mouse menu.
+
+2005-10-06 12:19 we7u
+
+ * src/icon.xbm: Added radio transmissions emanating from the
+ antenna.
+
+2005-10-05 23:47 we7u
+
+ * src/: icon.xbm, main.c: Separating out the icon into its own
+ file.
+
+2005-10-05 22:49 we7u
+
+ * src/main.c: Casting to type "Dimension" is not proper for
+ parameters passed to XtSetArg(). Have changed to variables of
+ that type for parameter passing. Also cleaned up the -geometry
+ code a bit. The windows are now sized properly per the
+ command-line parameters.
+
+2005-10-05 17:25 we7u
+
+ * src/main.c: A better version of the -geometry code that is
+ starting to work on Cygwin. The size is larger than specified,
+ perhaps because it is based on char sizes instead of pixels?
+ Anyway, this part of the code is starting to work.
+
+2005-10-05 11:37 we7u
+
+ * src/main.c: Rearranging things. No code changes.
+
+2005-10-05 08:34 we7u
+
+ * src/main.c: Another attempt at the -geometry stuff. Here we only
+ use size_hints in one case, plus we lock down the minWidth and
+ minHeight of the main widget when we create it (to the size we
+ want it to appear as), but change those parameters before we map
+ the window to the screen. This method was borrowed from the
+ Lincity project where they do similar things. As usual, this
+ stuff works for me on Linux/FVWM2.
+
+2005-10-04 12:12 we7u
+
+ * src/: main.c, xa_config.c: Another shot at this -geometry stuff.
+ Moved the size_hints stuff after the window is mapped. Added an
+ icon.
+
+2005-10-04 09:11 we7u
+
+ * src/main.c: Reducing the number of size_hints variables I'm
+ setting. Changing XtPopup() to XMapWindow() for appshell.
+
+2005-10-03 13:13 we7u
+
+ * src/xa_config.c: Tweaking SCREEN_ZOOM to match new
+ highest-allowed value for zoom level.
+
+2005-10-03 13:11 we7u
+
+ * src/main.c: Allow a higher zoom level for entire world, for
+ rather small map windows.
+
+2005-10-03 13:05 we7u
+
+ * src/main.c: Attempting to recenter view when zooming out all the
+ way. Doesn't quite work yet.
+
+2005-10-03 12:56 we7u
+
+ * src/main.c: Getting rid of the X-dimension checks in
+ check_range() in order to make it easier to play at the +/-180
+ boundaries.
+
+2005-10-03 12:51 we7u
+
+ * src/main.c: A slightly better system for controlling left/right
+ edges of map when at left/right edge of world. check_range().
+
+2005-10-03 11:34 we7u
+
+ * src/main.c: Fixes for -geometry support and main window
+ save/restore support.
+
+2005-10-03 11:33 we7u
+
+ * src/xa_config.c: Changing the minimum size that can be restored
+ to for Xastir's main window.
+
+2005-10-02 12:27 we7u
+
+ * src/main.c: Adding window manager hints back in.
+
+2005-10-01 23:26 we7u
+
+ * src/: db.c, draw_symbols.c, geocoder_gui.c, interface_gui.c,
+ list_gui.c, locate_gui.c, maps.c, xastir.h, bulletin_gui.c,
+ main.c, messages_gui.c, objects.c, popup_gui.c, track_gui.c,
+ view_message_gui.c, wx_gui.c: Getting rid of the Global.top
+ widget which was unmapped. Making appshell be the top level
+ widget. Added parsing for the -geometry command-line variable
+ via XParseGeometry() so that we can tell when either the
+ height/width or the x/y offsets have been specified. We then set
+ up appshell based on that info or using the config file data if
+ it wasn't specified on the command-line.
+
+2005-10-01 17:46 we7u
+
+ * src/main.c: Commenting out the 100x100 minimum window size
+ parameters.
+
+2005-09-30 13:16 we7u
+
+ * src/main.c: Commenting out the code which sets
+ min_width/min_height in the XSizeHints struct.
+
+2005-09-30 11:25 we7u
+
+ * src/main.c: Commenting out base_width and base_height parameters
+ as they override the min_width/min_height parameters if
+ specified. We only need one set.
+
+2005-09-30 11:02 we7u
+
+ * src/main.c: Another shot at the XSizeHints stuff (-geometry).
+ Learning a bit more with each iteration.
+
+2005-09-30 08:58 we7u
+
+ * src/main.c: Of course some of those I commented out previously
+ appear to matter, so here they are, enabled in the code again.
+
+2005-09-30 08:51 we7u
+
+ * src/main.c: Getting rid of a few unused variables. Commenting
+ out sections in the geometry setting portions that appear to have
+ no effect.
+
+2005-09-30 07:44 tvrusso
+
+ * DEBUG_LEVELS: Change statement that the highest debug level is
+ 2047 to 4095. There is now a debug level of 2048 (ALOHA
+ calculation and multipoint object debugging).
+
+2005-09-30 07:27 we7u
+
+ * INSTALL, help/help-English.dat: Updating the docs regarding TCP
+ and UDP server ports.
+
+2005-09-30 07:01 we7u
+
+ * src/main.c: Changed PSize flag to USSize to indicate that the
+ user had specified the size of the window in that one case. This
+ gives it a higher priority.
+
+2005-09-30 06:46 we7u
+
+ * help/help-English.dat: Updating the xastir_udp_client
+ description.
+
+2005-09-30 05:26 we7u
+
+ * src/db.c: Telemetry fix which adds it as status to the station
+ record, submitted by Andrew Rich, vk4tec. Thanks!
+
+2005-09-30 02:50 we7u
+
+ * src/main.c: Took another look at the XSizeHints struct. Might
+ work better now to provide proper geometry hints to window
+ managers.
+
+2005-09-29 12:19 we7u
+
+ * src/map_tif.c: Casting to the correct type for X11 calls.
+
+2005-09-29 12:19 we7u
+
+ * src/: db.c, location.c, main.c, map_WMS.c, map_dos.c, map_geo.c,
+ map_gnis.c, map_pdb.c, map_shp.c, map_tiger.c, maps.c, objects.c,
+ popup_gui.c: Casting to the correct type in X11 calls. Adding
+ more debug output to create_appshell() for -geometry stuff.
+
+2005-09-29 11:00 we7u
+
+ * acinclude.m4: Fix by Thorsten Lockert. Fixes a problem on
+ MacOSX where -lgdal can have revision numbers after it. Without
+ this fix the test compile using gdal fails.
+
+2005-09-29 08:42 we7u
+
+ * src/main.c: Added more debugging output for -geometry.
+
+2005-09-29 07:59 we7u
+
+ * src/main.c: Moving some variable declarations to the correct
+ spot. Ended up originally putting them after a bit of functional
+ code, but they must be at the start of a block for many
+ compilers.
+
+2005-09-29 07:37 we7u
+
+ * src/main.c: Changing to 3rd-party packets for packets sent from
+ UDP to the RF ports.
+
+2005-09-28 13:21 we7u
+
+ * src/main.c: Commenting out some unused variables.
+
+2005-09-28 13:02 we7u
+
+ * src/main.c: More mods for UDP->RF. This version may be working
+ but it needs testing on a system with real RF interfaces to see
+ if it behaves properly.
+
+2005-09-28 09:24 we7u
+
+ * src/: main.c, x_spider.c, x_spider.h: Continuing work on support
+ for UDP server port. We're getting closer now to supporting
+ sending of packets to RF.
+
+2005-09-28 09:22 we7u
+
+ * src/xastir_udp_client.c: Changed the help text.
+
+2005-09-28 09:03 we7u
+
+ * symbols/symbols.dat: Adding the /F, Farm Equipment, symbol, as a
+ green tractor. Also added hash mark delimiters between each
+ symbol definition.
+
+2005-09-28 07:50 we7u
+
+ * config/language-German.sys: Updates by Andreas Bier, dl1hrc.
+ Thanks!
+
+2005-09-27 08:16 we7u
+
+ * src/main.c: Simplifying startup of the application in main().
+ Changing to XtVaOpenApplication, which supersedes the function
+ call we were using before, and removing some explicit function
+ calls that are handled automatically by both the old and the new
+ function call (unnecessary code). These changes are being made
+ to implement proper support for the "-geometry" command-line
+ flag.
+
+2005-09-25 19:35 we7u
+
+ * src/: alert.h, database.h, db.c, draw_symbols.c, geocoder_gui.c,
+ interface.c, main.h, maps.h, track_gui.c, util.h, Makefile.am,
+ main.c, maps.c, util.c: Moving the Object/Item/Cad_Object code
+ into objects.h and objects.c.
+
+2005-09-25 19:26 we7u
+
+ * src/: objects.c, objects.h: Moving nearly all of the
+ Object/Item/CAD Object code into one header and one source file.
+ This makes main.c quite a bit smaller.
+
+2005-09-24 11:21 we7u
+
+ * src/main.c: Proper numeric checks for Global.top size/offsets,
+ for deciding whether to make the 2nd Xastir window (the first
+ visible window) copy either set of parameters.
+
+2005-09-24 11:00 we7u
+
+ * src/: list_gui.c, main.c: Changing variables used in
+ XtVaGetValues() calls to "Dimension" or "Position". Adding an
+ out-of-range check for dimension for the case where we're
+ attempting to discover whether the first window has had -geometry
+ specified.
+
+2005-09-23 17:18 we7u
+
+ * src/main.c: First working version of the "-geometry" command-line
+ flag. Will hopefully know soon if it works on all platforms we
+ support. Let the testing begin!
+
+2005-09-23 12:01 we7u
+
+ * src/main.c: "-geometry" switch now works for sizing the
+ application (instead of "-g"), but the X/Y offsets still don't
+ work.
+
+2005-09-22 19:18 tvrusso
+
+ * src/main.c: Give "appshell_width" and "appshell_height" initial
+ values of 0. This allows the contents of the xastir.cnf file's
+ SCREEN_WIDTH and SCREEN_HEIGHT to be used if no geometry is
+ specified in -g. As it was, if one didn't give -g then these two
+ settings in the config file were ignored and a 100x100 window
+ appeared on every start-up.
+
+2005-09-22 13:32 we7u
+
+ * src/main.c: A fix for Xastir hanging if the -g flag is used but
+ only offsets are specified.
+
+2005-09-22 13:07 we7u
+
+ * src/main.c: Initial implementation of the "-g" geometry
+ command-line flag. It supports sizing the application, but
+ doesn't support X/Y offsets yet. That's in the works though.
+
+2005-09-21 22:29 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c, src/main.h,
+ src/track_gui.c: Added success/failure popups to findu trail
+ download. Changed max_trail_colors to a define instead of an
+ int. Added a Change Trail Color button to the Station Info
+ dialog.
+
+2005-09-21 11:51 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/track_gui.c: Popping up an error
+ if the new backgrounded fetch findu trail fails. Changing
+ variables that the thread depends on to "static" so they'll be
+ around when the thread needs them.
+
+2005-09-20 17:35 tvrusso
+
+ * acinclude.m4: Restructure test for gv slightly, so that
+ AC_PATH_PROG is called first, and version is tested if gv is
+ found. The case where gv is found, but `gv -v | cut -d ' ' -f 1`
+ not being "gv" is in fact a sign of error that needs to be
+ reported in a meaningful way.
+
+ Turns out that when I do my normal cygwin build (which is usually
+ done in a non-X cygwin run to save memory), the old way of
+ probing gv found the gv executable, but because "gv -v" tries to
+ connect to the X server and reports failure if it can't,
+ configure was telling me that gv was found, but the build would
+ actually happen without gv. This was quite confusing.
+
+ With the new test as committed here, I still can't build with gv
+ outside of an xterm on cygwin, but the reason actually shows up
+ in the configure output.
+
+2005-09-17 11:33 we7u
+
+ * src/lang.h: Bumping up the size of the language buffer as we're
+ bumping up against the limits now for some languages.
+
+2005-09-16 16:46 we7u
+
+ * src/xastir_udp_client.c: Changing some comments and the usage
+ text.
+
+2005-09-16 16:45 we7u
+
+ * src/track_gui.c: Trying to protect the track download so that
+ only one can be done at once. Not perfect yet as sometimes the
+ GUI locks up. More to do.
+
+2005-09-16 16:34 we7u
+
+ * config/language-English.sys: Changing "New Call" to "New Station"
+ for the speech strings. I think it sounds better.
+
+2005-09-16 14:09 we7u
+
+ * config/language-English.sys: Adding an 's' to the end of "Enable
+ Server Ports".
+
+2005-09-16 14:09 we7u
+
+ * config/language-German.sys: Updates courtesy of Andreas Bier,
+ dl1hrc. Thanks!
+
+2005-09-16 13:18 we7u
+
+ * help/help-English.dat: Tweaking the text regarding the UDP
+ server/client. Adding more about the -identify command-line
+ flag.
+
+2005-09-16 13:14 we7u
+
+ * src/xastir_udp_client.c: Making the output from the -identify
+ response go to STDOUT instead of STDERR. Only makes sense so it
+ can be piped more easily into scripts and such.
+
+2005-09-16 13:09 we7u
+
+ * src/xastir_udp_client.c: Implemented the "-identify" command-line
+ flag. The "message" portion must have at least a single char in
+ order for the identify query to be sent to the server.
+
+2005-09-16 12:37 we7u
+
+ * help/help-English.dat, src/x_spider.c: Now we send UDP packets
+ out the x_spider TCP ports as well, if the packet is
+ authenticated properly.
+
+2005-09-16 12:26 we7u
+
+ * src/x_spider.c: Adding a "-identify" option to the UDP server.
+ It returns a UDP packet containing the callsign.
+
+2005-09-16 11:48 we7u
+
+ * src/track_gui.c: Putting the fetch_findu_trail function into a
+ separate background thread.
+
+2005-09-16 11:48 we7u
+
+ * help/help-English.dat: Adding text about the UDP server feature
+ and the xastir_udp_client.
+
+2005-09-16 07:38 we7u
+
+ * src/: x_spider.h, xastir_udp_client.c: Moving the default port
+ for UDP from 2024 to 2023, as TCP and UDP can co-exist on the
+ same port number.
+
+2005-09-15 16:59 we7u
+
+ * src/xastir_udp_client.c: Fixed the hostname lookup. You can now
+ specify any hostname and port.
+
+2005-09-15 12:38 we7u
+
+ * src/util.c: Adding the long integer time at the beginning of the
+ timestamp line for the log files. Makes sorting easy.
+
+2005-09-15 11:56 we7u
+
+ * src/: util.c, wx.c: Changing timestamping to add a timestamp line
+ per packet instead of once per 30 seconds.
+
+2005-09-15 11:47 we7u
+
+ * src/: x_spider.c, xastir_udp_client.c: Adding authentication to
+ the UDP packets.
+
+2005-09-15 11:45 we7u
+
+ * src/db.c: Allowing user-defined and telemetry packets to be
+ gated.
+
+2005-09-15 07:54 we7u
+
+ * src/.cvsignore: Adding xastir_udp_client to the ignore list.
+
+2005-09-15 07:52 we7u
+
+ * src/: Makefile.am, x_spider.c: Renaming the UDP client from
+ udp_client to xastir_udp_client.
+
+2005-09-15 07:51 we7u
+
+ * src/xastir_udp_client.c: Renaming this file from udp_client.c to
+ xastir_udp_client.c, to avoid similar names for UDP clients.
+
+2005-09-15 07:50 we7u
+
+ * src/udp_client.c: Renaming this file to xastir_udp_client.c
+
+2005-09-14 21:53 we7u
+
+ * src/: interface.c, main.c, x_spider.c, x_spider.h: Adding a UDP
+ server at port 2024.
+
+2005-09-14 21:45 we7u
+
+ * src/Makefile.am: Adding the udp client.
+
+2005-09-14 21:44 we7u
+
+ * src/udp_client.c: Initial checkin of a UDP client. Currently
+ this is hard-coded to talk to the localhost address, but that can
+ be fixed later. It also hangs currently if the server isn't
+ responding.
+
+2005-09-09 13:08 we7u
+
+ * src/db.c: Fixing a typo in one of the new langcode() string
+ callouts.
+
+2005-09-09 12:20 we7u
+
+ * src/: db.c, main.c, util.c: Replacing a bunch of hard-coded
+ strings with langcode() strings.
+
+2005-09-09 12:19 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Adding more
+ language strings to replace hard-coded strings.
+
+2005-09-08 21:46 we7u
+
+ * src/: draw_symbols.c, fcc_data.c, geocoder_gui.c, map_cache.c,
+ rac_data.c, view_message_gui.c, xa_config.c: Adding language
+ strings for previously hard-coded values. Changed get_long and
+ get_int functions in xa_config.c to give better output when
+ variables are missing or out-of-range in the config file upon
+ Xastir startup.
+
+2005-09-08 21:40 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Adding more
+ language strings for previously hard-coded English values.
+
+2005-09-08 09:49 we7u
+
+ * INSTALL: Adding a blurb about conflicts between GDAL internal
+ libraries and external libraries that Xastir can use.
+
+2005-09-08 09:39 tvrusso
+
+ * acinclude.m4: Move -lgdal to end of LIBS line if it's found.
+
+ It is possible for gdal to be using its own internal geotiff
+ library, and this can interfere with use of an external one in
+ xastir. Having it later in the line than geotiff can fix that.
+
+ This could cause problems for systems with busted linkers that
+ need gdal to be earlier than everything it depends on. If that
+ happens, it might be necessary to add the contents of
+ "gdal-config --dep-libs" to LIBS after -lgdal.
+
+2005-09-08 08:58 we7u
+
+ * src/map_tif.c: Commenting out some unnecessary includes. Adding
+ some error messages when function calls fail. Minor reformatting
+ w.r.t. braces to match the Xastir project standard.
+
+2005-09-07 12:30 we7u
+
+ * src/main.c: Assuring that the "System time jumped backwards 1
+ seconds!" message doesn't say "0 seconds!", as I've seen recently
+ due to the way the code was originally written.
+
+2005-09-02 18:42 we7u
+
+ * acinclude.m4: More appropriate output for the case where gv is
+ not found by configure.
+
+2005-09-02 16:00 we7u
+
+ * acinclude.m4: Adding a clause for the case where no usable "gv"
+ is found.
+
+2005-09-02 15:34 we7u
+
+ * acinclude.m4: Another stab at trying to do the "gv" revision
+ tests.
+
+2005-09-02 15:34 we7u
+
+ * src/maps.c: Pop up warning messages if we try to print but don't
+ have the proper support compiled in.
+
+2005-09-02 13:54 we7u
+
+ * acinclude.m4, src/maps.c: Tweaks to hopefully determine
+ automatically which version of "gv" is being used and change the
+ code to correspond to the proper API.
+
+2005-09-02 12:30 we7u
+
+ * src/maps.c: Preparing for configure.ac tests that will determine
+ the "gv" version, then we can change how we call up "gv" based on
+ that.
+
+2005-09-02 08:47 we7u
+
+ * src/x_spider.c: Changing to a <CR><LF> combination for the
+ "Hello" server message, per the APRS INET conventions.
+
+2005-09-01 10:00 we7u
+
+ * README.Getting-Started: Modified the note regarding geocode
+ files.
+
+2005-09-01 08:08 we7u
+
+ * configure.ac, src/main.c: Adding a test for sigignore() to
+ configure.ac, and code to use it in main.c. We were getting a
+ warning under Solaris by using signal() with SIG_IGN as the
+ parameter.
+
+2005-09-01 07:43 we7u
+
+ * src/util.c: Adding strings.h include. Need for Solaris.
+
+2005-08-31 21:16 we7u
+
+ * config/tnc-startup.kpc3: Removing "exp on" from the file. I
+ guess SOMEBODY doesn't think we need AEA commands in a KANTRONICS
+ config file. The nerve!
+
+2005-08-31 14:42 we7u
+
+ * REGRESSION_TESTS: Blowing away the autom4te.cache directory at
+ the start of each run, to make sure that we start out
+ ultra-clean.
+
+2005-08-31 09:59 we7u
+
+ * configure.ac: Attempt to remove "-no-unused" from linking stage
+ for Cygwin builds, as GCC links to complain about that flag
+ during linking.
+
+2005-08-30 14:19 we7u
+
+ * acinclude.m4: Changing grep syntax so that it will work with
+ non-GNU grep (Solaris). Getting rid of dash near the end.
+
+2005-08-30 13:52 we7u
+
+ * src/: awk.c, bulletin_gui.c, db.c, main.c, map_WMS.c, map_dos.c,
+ map_gdal.c, map_geo.c, map_gnis.c, map_pdb.c, map_shp.c,
+ map_tif.c, map_tiger.c, maps.c: Mucking about with the strings.h
+ includes.
+
+2005-08-30 13:28 kd6zwr
+
+ * src/: awk.c, geo-find.c, io-common.c, map_gnis.c: protecting the
+ strings.h with an ifdef, and casting isspace() family of macros
+ to match man page (int).
+
+2005-08-30 12:41 we7u
+
+ * src/awk.c: Adding a strings.h include for Solaris support.
+
+2005-08-30 11:33 we7u
+
+ * src/db.c: Displaying the raw packet in a dialog for the case
+ where we detect "EMERGENCY" in the comment field or one of the
+ emergency-type destination callsigns in a packet.
+
+2005-08-30 11:31 we7u
+
+ * config/tnc-startup.paccomm: Commenting out a "WIDE" alias that
+ remained. Changed it to "LOCAL" also.
+
+2005-08-30 11:31 we7u
+
+ * src/locate_gui.c: Skipping the dialog destroy call if you hit the
+ FCC/RAC lookup or the Locate button. The dialog now has to be
+ manually cleared by hitting the Cancel button.
+
+2005-08-29 08:06 we7u
+
+ * src/: db.c, interface.c, wx.c: Fixing warnings seen on OSX 10.4.
+ Very minor "signedness" warnings in string functions.
+
+2005-08-27 17:21 we7u
+
+ * src/x_spider.c: Tweaking a patch provided by James Washer that
+ will send a string out the server port on each connect. My
+ chances were merely to the format of the string. Thanks go to
+ James for the patch itself.
+
+2005-08-26 14:12 tvrusso
+
+ * configure.ac, src/hostname.c: Fix so that hostname.c can compile
+ on systems that define neither sighandler_t nor sig_t. This is
+ necessary because of the new cast to sighandler_t of the second
+ argument of signal() that was put there to shut gcc warnings up.
+
+2005-08-25 14:29 we7u
+
+ * acinclude.m4: Getting rid of some extra restores of variables
+ that I shouldn't have added last go-around.
+
+2005-08-25 13:48 we7u
+
+ * acinclude.m4: Summary text and summary.log were incorrect if gdal
+ wasn't found. Fixed.
+
+2005-08-25 08:11 we7u
+
+ * src/db.c: Commenting out some debug code.
+
+2005-08-24 21:27 we7u
+
+ * src/xa_config.c: Simplifying the get_long() and get_int() code
+ per discussions with Tom Russo. Also attempting to get rid of
+ some compiler warnings that we see with FreeBSD.
+
+2005-08-24 10:58 we7u
+
+ * src/main.c: Switching the state of trap_segfault variable to make
+ more sense.
+
+2005-08-24 09:50 we7u
+
+ * src/main.c: Change in text suggested by James Washer. Also added
+ the -t option to the command-flag help text.
+
+2005-08-24 09:07 we7u
+
+ * src/xa_config.c: Removing some ill-advised casts to time_t's.
+ Was trying to get rid of warnings that appear on FreeBSD, but
+ this was the wrong approach and didn't fix the problem.
+
+2005-08-23 21:08 tvrusso
+
+ * configure.ac, src/hostname.c: Change logic for deciding when to
+ use a sigjmp_buf vs. a jmp_buf.
+
+ The code that was originally here would only work if sigjmp_buf
+ was a #define, but on some systems it's a typedef. The new code
+ works for both.
+
+2005-08-23 19:53 we7u
+
+ * src/: awk.c, bulletin_gui.c, map_gdal.c, maps.c: Fixing up
+ function headers to be ANSI-C compliant.
+
+2005-08-23 16:25 we7u
+
+ * INSTALL: Tweaking the GDAL install instructions a bit more.
+
+2005-08-23 16:04 we7u
+
+ * INSTALL: Updating the GDAL install instructions.
+
+2005-08-23 14:38 we7u
+
+ * configure.ac: Changing the summary format slightly. No code
+ changes.
+
+2005-08-23 14:23 we7u
+
+ * configure.ac: Drawing a line in the configure summary between the
+ normal and the more unusual parameters.
+
+2005-08-23 14:18 we7u
+
+ * configure.ac: Changing some text on the summary output. No code
+ changes.
+
+2005-08-23 13:52 tvrusso
+
+ * acinclude.m4: Add configure-time check for usability of
+ -Wno-unused-parameter. Older compilers (not newer as was
+ indicated in the comments) don't like that and need -Wno-unused
+ instead.
+
+ Return -W to the CFLAGS, and use whatever -Wno-unused* works.
+
+2005-08-23 12:39 we7u
+
+ * src/interface.c: Added a new time_t variable that we can use to
+ call ctime() with, in order to avoid a compiler warning.
+
+2005-08-23 12:38 we7u
+
+ * src/xa_config.c: Changing a bunch of pointer casts from "long *"
+ to "time_t *" to avoid compiler warnings.
+
+2005-08-23 12:36 we7u
+
+ * src/util.c: Casting some time_t's to long's to avoid compiler
+ warnings.
+
+2005-08-23 12:35 we7u
+
+ * src/main.c: Casting a time_t to an unsigned long to remove a
+ compiler warning. Fixing up a function header to make it ANSI-C
+ compliant.
+
+2005-08-23 12:32 we7u
+
+ * src/db.c: Casting some time_t's to long's to get rid of warnings.
+
+2005-08-23 12:32 we7u
+
+ * src/alert.c: Casting some time_t's to unsigned long's to get rid
+ of warnings.
+
+2005-08-23 12:30 we7u
+
+ * acinclude.m4: Taking some of the new compiler flags back out as
+ one of them isn't recognized on some versions of GCC, and the
+ other causes too many warnings without it. Hopefully we can add
+ the "-W" back in at a later date once we figure out how to get
+ rid of the "unused parameter" warnings on a case-by-case basis.
+
+2005-08-22 16:02 we7u
+
+ * src/io-mmap.c: Cleaning up compiler warnings.
+
+2005-08-22 15:21 we7u
+
+ * acinclude.m4: Adding "-W" and "-Wno-unused_parameter" compiler
+ flags. Still a clean compile with SuSE Linux 9.0. No errors, no
+ warnings.
+
+2005-08-22 11:45 we7u
+
+ * src/: db.c, interface.c, interface.h: Added is_local_interface()
+ and is_network_interface() functions. Changed packet_data_add()
+ to use them, and to changes it functionality so that packets
+ transmitted to local interfaces would be visible in the incoming
+ data dialog.
+
+2005-08-22 11:37 we7u
+
+ * src/: shp_hash.c, shp_hash.h: Fixing up prototypes and function
+ headers so that they are ANSI-C compatible.
+
+2005-08-22 11:36 we7u
+
+ * src/rtree/: card.c, gammavol.c, index.c, index.h, node.c, rect.c:
+ Fixing up prototypes and function headers so they are ANSI-C
+ compatible.
+
+2005-08-22 11:35 we7u
+
+ * REGRESSION_TESTS: Tweaking to match new format for summary.log
+ file (we only want to show the first line now).
+
+2005-08-19 18:53 we7u
+
+ * src/: database.h, db.c, map_cache.c, map_cache.h, map_shp.c,
+ maps.c, testawk.c: Fixing up function and prototype definitions
+ so they are ansi-C standard and will pass the new compiler tests
+ that were just added.
+
+2005-08-19 18:40 we7u
+
+ * acinclude.m4: Adding more strict compiler checking.
+
+2005-08-19 18:27 we7u
+
+ * INSTALL: Adding notes about malloc debugging.
+
+2005-08-19 14:31 we7u
+
+ * src/draw_symbols.c: Adding/changing some comments.
+
+2005-08-19 14:26 we7u
+
+ * src/draw_symbols.c: Real fix for memory leak in the font metrics
+ code. Don't know why we need a '1' parameter for this system
+ call, but with a '0' we end up with a leak.
+
+2005-08-19 13:32 we7u
+
+ * src/draw_symbols.c: Fix for big memory leak.
+
+2005-08-19 11:33 tvrusso
+
+ * configure.ac, src/hostname.c: Add probe for sighandler_t
+ definition, and code to work around it being missing.
+
+2005-08-18 16:54 we7u
+
+ * src/interface.c: Fooled myself. Last fixes weren't fixes but
+ stopped the compile. Will rework that fix later.
+
+2005-08-18 16:51 we7u
+
+ * src/interface.c: Putting a few casts in to get rid of "-pedantic"
+ warnings.
+
+2005-08-18 16:21 we7u
+
+ * src/map_cache.c: Getting rid of three more "-pedantic" warnings.
+
+2005-08-18 16:09 we7u
+
+ * src/interface.c: More tweaks so that the "-pedantic" compiler
+ flag will show fewer warnings.
+
+2005-08-18 15:56 we7u
+
+ * src/: hostname.c, shp_hash.c: Fixing up minor warnings that the
+ "-pedantic" compiler flag revealed.
+
+2005-08-18 15:27 we7u
+
+ * src/: alert.c, db.c: Getting rid of another couple of warnings
+ that the "-pedantic" compiler flag revealed. Very minor stuff.
+
+2005-08-18 15:11 we7u
+
+ * src/hashtable_private.h: Removing the semicolon at the end of a
+ function that "-pedantic" compiler flag caught.
+
+2005-08-18 14:49 tvrusso
+
+ * acinclude.m4, src/testawk.c: Make use of LIBS in the gdal probe
+ without gdal-config match the usage with gdal-config
+
+ fix bogon in awk_rule table in testawk.c
+
+2005-08-18 14:43 we7u
+
+ * src/messages_gui.c: Casting to an "int" in order to get around a
+ compiler warning that we get if we turn on stricter checking.
+
+2005-08-18 14:42 we7u
+
+ * src/main.c: Adding a missing initializer.
+
+2005-08-18 14:00 we7u
+
+ * src/: leak_detection.h, util.h: Tweaks by Tom Russo to make the
+ new include arrangement work on FreeBSD. Evidently I broke that
+ platform with my most recent include file changes.
+
+2005-08-18 08:28 we7u
+
+ * src/view_message_gui.c: Moving the dmalloc code to a separate
+ header file.
+
+2005-08-18 08:27 we7u
+
+ * src/util.c: Messing with the hash iterator free's again. Moving
+ dmalloc code to a separate header file.
+
+2005-08-18 08:26 we7u
+
+ * src/: map_gdal.c, maps.c, wx_gui.c: Messing with the hash
+ iterator free's again.
+
+2005-08-18 08:26 we7u
+
+ * src/leak_detection.h: Here's where the malloc and dmalloc code
+ was moved to. The order in which this is done with respect to
+ the libgc code is critical, therefore it has all been moved to
+ this one header file so the order can be closely guarded.
+
+2005-08-18 08:24 we7u
+
+ * src/interface_gui.c: Removing the dmalloc code.
+
+2005-08-18 08:23 we7u
+
+ * src/: hashtable_private.h, hashtable_itr.c: Removing the xastir.h
+ include.
+
+2005-08-18 08:22 we7u
+
+ * src/hashtable.c: Moving a comment.
+
+2005-08-18 08:22 we7u
+
+ * src/db.c: Removing dmalloc ifdef's.
+
+2005-08-18 08:21 we7u
+
+ * src/alert.c: Getting rid of dmalloc ifdef's. We use libgc to do
+ similar things. Messing with the iterator ifdef's again.
+
+2005-08-17 13:16 we7u
+
+ * src/util.c: Skipping the free() of the hashtable iterator in all
+ cases.
+
+2005-08-17 13:13 we7u
+
+ * src/maps.c: Moving alert-related code to debug level 2. Skipping
+ hash iterator free() calls for now as they cause segfaults if
+ libgc is compiled in.
+
+2005-08-17 13:11 we7u
+
+ * src/db.c: Changing debug_level to 2 for wx_alert-related code.
+
+2005-08-17 13:10 we7u
+
+ * src/alert.c: Added some debug statements. Skipping hash iterator
+ free() as it causes segfaults.
+
+2005-08-17 12:13 we7u
+
+ * src/util.c: Adding leak_detector.h include. Simplifying
+ add_tactical_to_hash() function.
+
+2005-08-17 12:12 we7u
+
+ * src/: map_WMS.c, map_cache.c, map_dos.c, map_gdal.c, map_geo.c,
+ map_gnis.c, map_pdb.c, map_shp.c, map_tif.c, map_tiger.c, maps.c,
+ messages.c, messages_gui.c, popup_gui.c, rac_data.c, rotated.c,
+ shp_hash.c, snprintf.c, sound.c, testawk.c, track_gui.c, util.h,
+ view_message_gui.c, wx.c, wx_gui.c, x_spider.c, x_spider.h,
+ xa_config.c, xastir.h: Adding leak_detector.h include.
+
+2005-08-17 12:11 we7u
+
+ * src/main.c: Adding leak_detector.h include. Changing memory leak
+ check to every 60 seconds (from 5 minutes).
+
+2005-08-17 12:08 we7u
+
+ * src/: awk.c, bulletin_gui.c, color.c, datum.c, db.c, dbfawk.c,
+ draw_symbols.c, fcc_data.c, festival.c, geo-find.c,
+ geocoder_gui.c, gps.c, hashtable.c, hashtable_itr.c, hostname.c,
+ igate.c, interface.c, interface.h, interface_gui.c, io-common.c,
+ io-mmap.c, lang.c, list_gui.c, locate_gui.c, location.c,
+ location_gui.c, macspeech.c: Adding leak_detector.h include.
+
+2005-08-17 12:06 we7u
+
+ * src/alert.c: Adding leak_detector.h include. Simplifying the
+ add_wx_alert_to_hash function.
+
+2005-08-17 12:04 we7u
+
+ * src/Makefile.am: Adding the leak_detector.h file.
+
+2005-08-17 12:02 we7u
+
+ * src/leak_detection.h: Moving the LIBGC defines/includes into a
+ new header file. The order in which these are used in a C module
+ is important, as is the order that the thread includes are done.
+ This will help assure that the order remains consistent so that
+ the memory leak detection will work.
+
+2005-08-17 11:59 we7u
+
+ * INSTALL: Tweaking the libgc instructions.
+
+2005-08-15 17:47 we7u
+
+ * src/util.c: Separating out the pointers so we can better keep
+ track of them, assuring that we're not overwriting anything we
+ shouldn't. Freeing some malloc'ed space for the case where hash
+ inserts fail.
+
+2005-08-15 17:45 we7u
+
+ * src/shp_hash.c: Freeing some malloc'ed space for the case where
+ hash inserts fail.
+
+2005-08-15 17:44 we7u
+
+ * src/map_gdal.c: Freeing some malloc'ed space for the cases where
+ hash inserts fail.
+
+2005-08-15 17:44 we7u
+
+ * src/alert.c: Changing a memcpy to an xastir_snprintf call in
+ order to assure that the string is terminated. Added some
+ debugging set_dangerous/clear_dangerous calls.
+
+2005-08-15 17:42 we7u
+
+ * src/main.c: Making the RINO download timeout slider always
+ visible in the timing dialog, but insensitive if gpsman is not
+ compiled in.
+
+2005-08-15 13:01 we7u
+
+ * configure.ac: Adding a very short summary of the configure tests
+ and results to summary.log. This should aid in debugging as we
+ can more quickly see what passed/failed on a particular user's
+ machine.
+
+2005-08-14 23:43 we7u
+
+ * src/map_shp.c: Committing Tom Russo's fix to remove colon chars
+ in track->shapefile save routine. Seems Cygwin doesn't like
+ colons in filenames.
+
+2005-08-13 09:43 we7u
+
+ * README.win32: Fixing a couple of typos.
+
+2005-08-12 22:21 we7u
+
+ * src/main.c: Moving one define to the top of the file. This one
+ contains some copyright dates and appears in the Help dialog, so
+ must be updated periodically. This new location for it is much
+ better than having it hidden in the middle of the file.
+
+2005-08-12 22:07 we7u
+
+ * src/util.c: Adding spaces around the "==" in the #if statement
+ added today.
+
+2005-08-12 20:17 we7u
+
+ * acinclude.m4, configure.ac: Taking out the new MALLOC test added
+ today as AC_FUNC_MALLOC already does what we need.
+
+2005-08-12 14:37 we7u
+
+ * acinclude.m4, configure.ac, src/util.c: Adding rpl_malloc()
+ function in util.c, and the associated hooks into acinclude.m4
+ and configure.ac to get it called. This is to replace malloc()
+ for those cases where malloc() doesn't behave properly.
+
+2005-08-12 14:36 we7u
+
+ * INSTALL: Adding a note about libgc's extra memory usage.
+
+2005-08-12 13:41 we7u
+
+ * config/language-Portuguese.sys: Shortening the Portuguese version
+ of "Enable Weather Alerts" string.
+
+2005-08-12 12:37 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Added a Reset
+ button to the Change Debug Level dialog.
+
+2005-08-12 12:36 we7u
+
+ * src/: alert.c, main.c, map_gdal.c, maps.c, util.c, wx_gui.c:
+ Added a reset button to the Change Debug Level dialog. Made the
+ Enable WX Alerts menu item be grey'ed out if Shapelib not
+ installed. Added debug statements multiple places. Put
+ #ifndef's around a bunch of free(iterator) statements for the
+ case when libgc is configured into the compile (else segfaults
+ occur).
+
+2005-08-12 12:27 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-German.sys, language-Italian.sys, language-Spanish.sys:
+ Removing "Counties" from the Enable Weather Alerts text.
+
+2005-08-12 08:38 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Adding a custom zoom
+ option to the right-click zoom levels menu.
+
+2005-08-11 13:40 we7u
+
+ * src/main.c: Moving the Center & Zoom dialog to the Maps menu.
+
+2005-08-11 12:46 we7u
+
+ * REGRESSION_TESTS: Added a default configure/compile at the end,
+ both to test this case and to get the codebase back to normal for
+ the system it's run on.
+
+2005-08-11 12:20 we7u
+
+ * REGRESSION_TESTS: Removed a couple of el-stupido test cases.
+ Nice'ed everything.
+
+2005-08-10 18:37 we7u
+
+ * configure.ac: Adding warnings so that library dependencies are
+ obvious. Adding code so that missing dependencies cause
+ dependent libraries to be skipped.
+
+2005-08-10 18:35 we7u
+
+ * INSTALL: Added an ASCII-art drawing showing the library
+ dependencies.
+
+2005-08-10 14:06 we7u
+
+ * configure.ac: Adding another configure warning for missing
+ library.
+
+2005-08-10 12:00 we7u
+
+ * REGRESSION_TESTS: Adding tests for ALL libraries minus one, each
+ in turn.
+
+2005-08-10 11:58 we7u
+
+ * configure.ac: Forcing use_rtree to OFF and issuing a warning if
+ Shapelib is not being used.
+
+2005-08-10 11:39 we7u
+
+ * src/: main.c, shp_hash.c: Fixing the code for the case where
+ rtree has been requested buy Shapelib is not compiled in. It
+ makes no sense to do this, but at least it will compile for this
+ case now.
+
+2005-08-10 11:38 we7u
+
+ * src/track_gui.c: Tweaking the Fetch Findu Trail function so that
+ it matches what findu is capable of for the trail duration.
+ Changed the start time and duration time max values to #defines
+ at the top of the file so we can change it more easily next time
+ around.
+
+2005-08-09 08:57 tvrusso
+
+ * acinclude.m4: Fix for broken fix of broken fix of probe for gdal.
+
+ After I fixed the multiply-included -lgdal issue and made sure
+ that I'd separated out -Ls from -ls, I never made sure that the
+ -l got into LIBS. I was counting on AC_CHECK_LIB to do that, but
+ it only does so if you don't provide an ACTION-IF-FOUND.
+
+2005-08-08 20:53 tvrusso
+
+ * acinclude.m4: Add ugly hack to work around gdal-config's
+ idiosyncratic merging of LDFLAGS and LIBS data with the single
+ "gdal-config --libs" command. Other programs with -config
+ scripts have --ldflags and --libs to keep the stuff separate.
+
+2005-08-08 20:18 tvrusso
+
+ * acinclude.m4: Fix broken attempt to replace old flags into
+ variables after failing test.
+
+2005-08-08 14:12 francais1
+
+ * config/language-French.sys: Incorporated most changes from
+ Jacques Chion
+
+2005-08-08 12:27 we7u
+
+ * src/track_gui.c: Adding a debug statement.
+
+2005-08-06 11:11 tvrusso
+
+ * acinclude.m4: Fix up AC_CHECK_GDAL so it uses LIBS instead of
+ LDFLAGS. This makes it more consistent with other usages.
+ gdal-config --libs actuall returns both LDFLAGS and LIBS type
+ information, and using its output for LDFLAGS winds up putting
+ the -lgdal flag very early in the link line. This could be a
+ problem on some systems.
+
+2005-08-06 11:05 tvrusso
+
+ * acinclude.m4: Fix dumb mistake in the section that handles the
+ "gdal-config not found" condition.
+
+2005-08-06 11:01 tvrusso
+
+ * acinclude.m4, configure.ac: Make probe for gdal use gdal-config
+ if it can be found.
+
+ If gdal-config is in the user's path, use it to get LDFLAGS and
+ CPPFLAGS to help the probe for gdal.h and libgdal.a. Otherwise,
+ use the current settings of LDFLAGS and CPPFLAGS and hope they're
+ found.
+
+ In doing this, I think I see that the probe
+ XASTIR_CHECK_IMAGEMAGICK has a few bugs in it.
+
+2005-08-06 00:14 tvrusso
+
+ * src/db.c: Fix new emergency processing in decode_ax25_line so
+ that it only attempts to work on valid packets. This was causing
+ segfaults at strcmp(my_callsign,call_sign) when connecting to an
+ internet server (upon receiving the # javAPRServ line), because
+ call_sign was NULL.
+
+2005-08-05 18:14 we7u
+
+ * REGRESSION_TESTS: Making the output a bit easier to understand.
+
+2005-08-04 20:13 we7u
+
+ * src/draw_symbols.c: Using font metrics to determine size of font.
+ We then use that to determine the size for the black rectangle
+ underneath the font.
+
+2005-08-04 12:34 we7u
+
+ * src/: db.c, draw_symbols.h, draw_symbols.c: Drawing a line
+ between the waypoint symbol and the station that originated it.
+ Per the spec.
+
+2005-08-03 18:52 we7u
+
+ * symbols/symbols.dat: Updating a symbol or three.
+
+2005-08-03 13:16 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface.c, src/main.c,
+ src/main.h: Have implemented an EMERGENCY BEACON transmit
+ capability. Look for it under the "Help" menu (appropriate,
+ no?).
+
+2005-08-03 12:15 we7u
+
+ * REGRESSION_TESTS: More minor cleanups. No real changes.
+
+2005-08-03 12:01 we7u
+
+ * src/db.c: Added emergency beacon decode for the string
+ "EMERGENCY" anywhere in the packet, plus the strings: ALARM
+ ALERT WARNING WXALARM EM If seen in the TO: field
+ of the packet. This matches the decoding provided by APRS+SA for
+ this feature.
+
+2005-08-02 13:22 we7u
+
+ * REGRESSION_TESTS: Small tweaks to improve the output and give us
+ info while it is running instead of all the output at the end.
+
+2005-08-01 21:40 we7u
+
+ * REGRESSION_TESTS: Changing the order of the individual flag tests
+ to match the summary output order from "configure".
+
+2005-08-01 21:18 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Taking "RELAY" out
+ of the digipeat? label.
+
+2005-08-01 21:16 we7u
+
+ * REGRESSION_TESTS: Fiximg the grep at the end.
+
+2005-08-01 19:33 we7u
+
+ * REGRESSION_TESTS: Initial checkin. A "dumb" script the way it is
+ currently written, but it could be made much more intelligent
+ over time, and extended to perform more tests.
+
+2005-08-01 19:29 we7u
+
+ * symbols/symbols.dat: Changing the symbols to be more
+ spec-compliant. The spec keeps changing on us. Added an SUV
+ symbol. Moved the Shelter symbol to the secondary table.
+ Changed the background on the Storm Watch symbol to orange
+ instead of red. Still need to do the waypoint symbol so it is a
+ red circle and have a line going between it and the mobile
+ transmitting it, plus need to change "No Sym Yet" to a circle
+ with a slash through it, per the latest spec addendum. It would
+ be worth taking a look at all the symbols to verify compliance.
+
+2005-08-01 19:26 we7u
+
+ * src/map_geo.c: Getting rid of a compiler warning (unused
+ variable) when ImageMagick isn't compiled in.
+
+2005-08-01 15:08 tvrusso
+
+ * src/map_shp.c: Move declaration of draw_filled out of WITH_DBFAWK
+ ifdef.
+
+2005-08-01 14:34 we7u
+
+ * src/main.c: Updating the year on the Help->About copyright
+ notice.
+
+2005-08-01 12:43 we7u
+
+ * configure.ac, help/help-English.dat: Bumping version to 1.6.1 for
+ further development.
+
+2005-08-01 11:11 we7u
+
+ * help/help-English.dat: Updating the what's new section for 1.6.0.
+
+2005-08-01 10:54 we7u
+
+ * README.Contributing, README.Getting-Started, configure.ac,
+ help/help-English.dat: Bumping the version to 1.6.0.
+
+2005-07-30 23:19 we7u
+
+ * src/: bulletin_gui.c, db.c, interface_gui.c, maps.h,
+ locate_gui.c, location_gui.c, main.c, map_gnis.c, messages_gui.c,
+ wx_gui.c: Adding new capability to the Map Feature Search
+ function: Now returns a chooser dialog that allows seeing up to
+ the first fifty matches for the search, then centering the map on
+ any of them. Also tweaked array sizes throughout the code used
+ for sending parameters to X11 calls.
+
+2005-07-29 12:32 we7u
+
+ * src/: locate_gui.c, map_gnis.c, maps.h: Changing locate_place()
+ to gnis_locate_place() because it is too similar to the function
+ Locate_place(). Added some comments w.r.t. putting in a chooser
+ option for the Locate Map Feature function.
+
+2005-07-29 12:31 we7u
+
+ * src/db.c: Changing some comments. No code changes.
+
+2005-07-29 12:29 we7u
+
+ * src/xa_config.c: Calling the new remove_all_spaces() function on
+ one variable read in from the config file.
+
+2005-07-29 12:29 we7u
+
+ * src/: util.c, util.h: Added a "remove_all_spaces" function.
+
+2005-07-28 13:41 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/map_tif.c,
+ src/xa_config.c: Implementing the XOR function for combining USGS
+ DRG colors with underlying map colors. Changed some labels with
+ respect to this new function.
+
+2005-07-26 12:50 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Changing the DRG
+ Color Filtering labels to the correct color names.
+
+2005-07-26 12:39 tvrusso
+
+ * src/map_gdal.c: Fix extern declaration of draw_shapefile_map
+
+2005-07-26 12:32 tvrusso
+
+ * src/main.c: Add a comment.
+
+2005-07-26 12:16 tvrusso
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/map_dos.c,
+ src/map_gdal.c, src/map_geo.c, src/map_gnis.c, src/map_pdb.c,
+ src/map_shp.c, src/map_tif.c, src/maps.c, src/maps.h: Implement
+ auto detection of USGS DRG topo maps (the ones actually from
+ USGS, with proper GeoTIFF tags).
+
+ Changed map driver interface to take a struct of map flags
+ instead of a single "draw_filled" integer.
+
+ Changed map properties to support setting of Yes/No/Auto for a
+ given map's "USGS DRG" field. If Yes, the color map is assumed
+ to be USGS's and the color settings in Map->Configure USGS DRG
+ are used. If No, all colors in the colormap are displayed. If
+ Auto, the tiff's Image Description tag is queried and if it
+ begins with "USGS DRG GeoTIFF" then it's as if the setting was
+ Yes, and if it doesn't (or the tag does not exist) then it is as
+ if the setting was No.
+
+ Added rowcol to map properties dialog to handle the extra buttons
+ without widening the window.
+
+ Cleaned up the code in main.c that locates the filename in a map
+ properties line. It was being done by hardcoding the offset in 8
+ places to 31. Moved the magic number to a preprocessor symbol so
+ it only needs to be changed once now. There has got to be a
+ cleaner way still, but that's enough for now.
+
+ Changed all map drivers to support the new map_data_flags struct
+ instead of the int draw_filled.
+
+ Changed language files. Not sure I got all of them right.
+
+2005-07-25 10:00 tvrusso
+
+ * src/xa_config.c: Change DRG_COLORS settings so that they default
+ to ON if a config file is read in that doesn't contain the
+ settings. This will make sure that users who upgrade don't get
+ surprised by having all their topo maps disappear upon upgrading.
+
+2005-07-23 19:29 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/map_tif.c,
+ src/xa_config.c, src/xastir.h: Added a Configure USGS DRG dialog.
+ Allows turning on/off various drawing colors on geoTIFF images.
+
+2005-07-22 18:27 we7u
+
+ * src/map_tif.c: Added a couple of defines at the top that control
+ whether we display an entire topo map or just the contours, and
+ which color we display them in.
+
+2005-07-22 12:42 we7u
+
+ * src/util.c: Cleaning up the curl code a bit more: Removed
+ unnecssary includes and moved the one remaining include up to the
+ top of the file.
+
+2005-07-21 23:17 we7u
+
+ * config/language-Dutch.sys: Translating one label.
+
+2005-07-21 23:08 we7u
+
+ * src/: track_gui.c, map_WMS.c, map_geo.c, map_tiger.c, maps.c,
+ util.c, util.h: Consolidating all of the libcurl and wget
+ functionality into util.c:fetch_remote_file(). This should make
+ the code much easier to maintain and extend.
+
+2005-07-21 21:33 we7u
+
+ * INSTALL: Adding some instructions provided by Tom Russo for
+ specifying an unusual location of libdb to configure.
+
+2005-07-21 13:04 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/geocoder_gui.c:
+ Correcting the "Find Address" label in several spots.
+
+2005-07-21 12:53 we7u
+
+ * INSTALL: Adding a list of libraries for a full-up Xastir compile
+ on SuSE 9.0 to aid people in deciding which libraries might be
+ needed.
+
+2005-07-20 19:19 we7u
+
+ * src/: map_cache.c, map_cache.h, main.c: Added a run-time check
+ for matching versions in db.h and libdb.so.
+
+2005-07-20 19:12 we7u
+
+ * src/track_gui.c: Fixing the duration hours slider so that it
+ can't be any larger than the start hours slider.
+
+2005-07-20 11:50 we7u
+
+ * INSTALL: Adding some text having to do with using the optional
+ Berkeley DB Library for map caching.
+
+2005-07-20 11:49 we7u
+
+ * acinclude.m4: Adding some comments to the
+ XASTIR_BERKELEY_DB_CHK_LIB function. Things we need to
+ add/figure out in order to assure that the Berkeley DB Library
+ can be successfully used with Xastir.
+
+2005-07-19 22:13 we7u
+
+ * help/help-English.dat: Added an example of how to use the Fetch
+ trail from Findu timing sliders.
+
+2005-07-19 22:09 we7u
+
+ * src/: main.h, db.c, xa_config.c: Implementing user-configurable
+ digipeater callsigns. Users will now be able to edit the
+ comma-delimited string in their xastir.cnf file. There are no
+ GUI tie-ins for editing the string at this point.
+
+2005-07-19 21:43 we7u
+
+ * help/help-English.dat: Adding some more detail about the Map
+ Chooser->Properties dialog. Adding some new text about the
+ user-configurable relay digipeater callsigns which will be
+ committed to CVS shortly.
+
+2005-07-19 21:41 we7u
+
+ * configure.ac: Reordering the summary.log and Help->About library
+ strings plus adding the few that were missing.
+
+2005-07-19 21:38 we7u
+
+ * README.MAPS: Minor tweak to one comment. Nothing substantial.
+
+2005-07-19 12:24 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Fixing up the displayed
+ string for Beam Heading objects, "Bearing:" string.
+
+2005-07-18 11:12 tvrusso
+
+ * src/draw_symbols.c: Fix for broken DF directional lines when
+ zoomed in tight. Restricts range of lines to something close to
+ the screen, rather than the full range allowed by the DF object's
+ NRQ (or the default of 512 nautical miles.
+
+2005-07-16 23:19 we7u
+
+ * src/interface_gui.c: Allowing the passcode to be longer (up to 20
+ chars). Useful in a few instances, and similar to what's allowed
+ currently in the AGWPE code.
+
+2005-07-16 23:17 we7u
+
+ * src/x_spider.c: Adding a #define and some #ifdef's that allow
+ compiling the code in either standalone daemon mode or
+ called-function mode.
+
+2005-07-15 09:30 we7u
+
+ * src/main.c: Adding spaces to the help text.
+
+2005-07-15 09:18 we7u
+
+ * xastir.spec.in: Re-ordering the docs alphabetically. No real
+ change.
+
+2005-07-13 12:37 we7u
+
+ * src/util.c: Adding some comments. Preparatory to redoing some
+ code.
+
+2005-07-12 19:44 tvrusso
+
+ * config/tgr2shppoly.dbfawk: Make polygon boundaries the same color
+ as fill. Now that boundaries are no longer stippled the same way
+ as the fill, the black boundaries are too glaring.
+
+2005-07-12 16:06 tvrusso
+
+ * src/map_shp.c: Reset stipple style to solid when drawing
+ boundaries of polygons with dbfawk. They were getting drawin in
+ the stipple pattern used for fill, which made for fuzzy
+ boundaries.
+
+2005-07-11 12:25 we7u
+
+ * configure.ac: Fixing the Geotiff summary line so that it says
+ "no" if libproj isn't found. It was blank until now in this
+ case.
+
+2005-07-11 12:24 we7u
+
+ * src/map_geo.c: Moving one line so that this will compile ok
+ without warnings if no ImageMagick.
+
+2005-07-11 10:50 we7u
+
+ * src/xastir.h: If ImageMagick is not found, util.c compile will
+ fail without this change.
+
+2005-07-11 07:55 tvrusso
+
+ * src/main.c: Put use of map_cache_fetch_disable into the same
+ ifdef as the definition of that variable, so that people who
+ aren't using map caching can link.
+
+2005-07-10 10:56 tvrusso
+
+ * FAQ: Change question 5.4 to actually have "5.4" in its title.
+
+2005-07-10 08:37 tvrusso
+
+ * scripts/Xastir_tigerpoly.py: Add -d flag to the Usage error
+ message.
+
+2005-07-10 08:36 tvrusso
+
+ * scripts/Xastir_tigerpoly.py: Add "-d" option to this script to
+ allow dissolution of common boundaries between polygons with the
+ same Landmark designation.
+
+ This is done by scanning all PolyChainLink records, checking that
+ both left and right polygon have associated AreaLandmark records,
+ and that both AreaLandmark records point to the same Land record.
+ If they do, then the two polygons are dissolved into one.
+
+ The option is not the default.
+
+ Using this option makes the output shapefile be topologically
+ inequivalent to the original TIGER/Line data, and as such they
+ are suitable only for display. Distributing data produced in
+ this manner should be done with a prominient disclaimer pointing
+ out that the shapefiles are for display purposes, not serious GIS
+ use.
+
+ Dissolving polygons in this way makes the TIGER data look much
+ nicer (but still pretty ugly) in xastir -- large landmarks no
+ longer have many copies of the labels, and no longer have ugly
+ internal dashed boundaries that mean nothing.
+
+2005-07-08 20:30 we7u
+
+ * src/dbfawk.c: A fix for the emacs temp-file bug that is invoked
+ by temp file symlinks of the form ".*.dbfawk" while editing
+ dbfawk files. The code will now ignore anything but regular
+ files, and ignores directories and files that have a leading
+ period.
+
+2005-07-08 20:27 we7u
+
+ * src/: main.c, map_WMS.c, map_cache.c, map_cache.h, map_geo.c,
+ map_tiger.c: Enabling the reload maps (without cache) option on
+ the Map menu, with the back-end code in place to implement it. A
+ few tweaks to the map_cache_del() function to return with error
+ code under certain conditions.
+
+2005-07-08 13:19 we7u
+
+ * src/main.c: Comment changes only.
+
+2005-07-08 12:24 we7u
+
+ * src/main.c: Changed some comments.
+
+2005-07-08 00:07 we7u
+
+ * src/main.c: Implemented "Flush Entire Map Cache" function.
+
+2005-07-07 19:22 we7u
+
+ * src/xastir.h: Renaming tigermap_timeout to net_map_timeout.
+
+2005-07-07 19:21 we7u
+
+ * src/: map_geo.c, main.c, map_WMS.c, map_tiger.c, util.c,
+ xa_config.c: Moving the tigermap slider to the
+ file->configure->timing dialog. Changing it's label so that it
+ is obvious it is for all internet map downloads, not just
+ Tigermaps. Changing the tigermap_timeout global variable to
+ net_map_timeout to more fully reflect its use.
+
+2005-07-07 18:52 we7u
+
+ * help/help-English.dat: Updating map caching lingo. Adding more
+ special .GEO file keywords and updating some that were there to
+ match the latest code.
+
+2005-07-07 18:49 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Adding some
+ strings for map caching controls. Tweaking another string having
+ to do with the map download timeout slider.
+
+2005-07-07 18:47 we7u
+
+ * README.MAPS: Updating the lingo w.r.t. map caching.
+
+2005-07-07 18:46 we7u
+
+ * INSTALL: Minor comment change.
+
+2005-07-06 22:38 we7u
+
+ * src/: map_WMS.c, map_geo.c, map_tiger.c, util.c: Making the curl
+ timeouts track with the tigermap_timeout global variable.
+ Previously they were set to a fixed 30 second timeout. Not
+ enough for slow links.
+
+2005-07-06 20:38 tvrusso
+
+ * config/tgr2shppoly.dbfawk: Make intermittent water polygons a
+ pale stippled fill.
+
+2005-07-06 18:25 we7u
+
+ * src/map_geo.c: Added some comments. Made one fprintf only active
+ in debug mode.
+
+2005-07-06 13:35 tvrusso
+
+ * scripts/Xastir_tigerpoly.py: While trying to understand why my
+ TIGER polygon maps have so many identically-named small polygons,
+ I discovered an error in the Xastir_tigerpoly.py script that was
+ propagated from the original GDAL tigerpoly.py script.
+
+ The TIGER/Line format has a "Type I" record that links complete
+ chains (Type 1) to "GT-Polygons" through the "POLYIDL" and
+ "POLYIDR" attributes. But according to the TIGER/Line
+ documentation, a Type I record that contains identical POLYIDL
+ and POLYIDR attributes is a line that is internal to a polygon,
+ and should not be included in its boundary. The original
+ tigerpoly.py script from which Xastir_tigerpoly.py was derived
+ simply added all lines with either POLYIDL or POLYIDR to the
+ boundary of polygon POLYID. That means that these internal
+ points were not only incorrectly added to the boundary of POLYID,
+ they were added twice.
+
+ A simple test to throw away such "PolyChainLink" data (in the OGR
+ parlance, "Type I record" in the TIGER parlance) removes this
+ incorrect assembly of polygon boundaries.
+
+ This does *not* fix the issue of there being lots of tiny,
+ identically-named polygons in a given area (that's just how the
+ data is), but it DOES correct the "Error in computing fill/hole
+ ring" warnings I've been getting since forever, every time these
+ TIGER/Line-converted polygon shapefiles are loaded. It also
+ fixes the problem I had trying to import these polygon shapefiles
+ into GRASS, which noticed and griped angrily about the
+ topological incorrectness of the data.
+
+ Unfortunately, taking advantage of this fix would require
+ regenerating all the TIGER polygon shapefiles that are up on
+ xastir.tamu.edu --- probably not worth the effort. But should
+ there be a new round of corrected TIGER data that gets processed,
+ the script is now producing (more) topologically correct
+ shapefiles.
+
+ It might be a good idea to feed this back to Frank Warmerdam, on
+ whose tigerpoly.py script Xastir_tigerpoly.py was based.
+
+2005-07-06 12:58 we7u
+
+ * src/: main.h, map_geo.c, map_tiger.c: Adding a parameter to the
+ draw_tiger_map() function, to be used for future implementation
+ in the tiger code for a "refresh map w/o cache" option.
+
+2005-07-06 12:28 we7u
+
+ * src/: main.h, map_WMS.c, map_geo.c: Added caching for all types
+ of internet maps, disabled by adding a "REFRESH" tag to the .geo
+ file.
+
+2005-07-06 12:27 we7u
+
+ * src/map_cache.c: Added some bulletproofing and some more debug
+ messages.
+
+2005-07-06 12:26 we7u
+
+ * src/map_tiger.c: Changed one debug message.
+
+2005-07-06 08:27 we7u
+
+ * src/map_tiger.c: Adding some comments.
+
+2005-07-06 08:25 we7u
+
+ * src/map_tif.c: Changing a printf into an fprintf.
+
+2005-07-06 08:22 we7u
+
+ * src/: hostname.c, main.c, messages.c, sound.c, x_spider.c:
+ Changing some printf's to fprintf's, snprintf's to
+ xastir_snprintf's. Adding timestamp to x_spider messages which
+ are sent to the console.
+
+2005-07-01 15:23 we7u
+
+ * INSTALL, README.Getting-Started, configure.ac: Adding a
+ "--without-map-cache" flag to configure. Updating docs to match.
+
+2005-06-30 17:12 we7u
+
+ * src/map_tiger.c: Fixing a compile problem that occurs if
+ ImageMagick isn't installed.
+
+2005-06-30 17:11 we7u
+
+ * src/map_gdal.c: Removing "static" from the function returns of
+ functions defined inside functions. Evidently the latest GCC
+ enforces that restriction.
+
+2005-06-30 17:09 we7u
+
+ * README.MAPS, FAQ, README.win32, help/help-English.dat,
+ help/help-German.dat, help/help-Portuguese.dat: Cleaning up some
+ docs w.r.t. Terraserver info. Adding a few more FAQ entries that
+ come up from time to time.
+
+2005-06-30 13:29 we7u
+
+ * FAQ: Adding a bit about the Terraserver zone-crossing problem.
+
+2005-06-30 13:16 we7u
+
+ * Makefile.am, terraserver-reflectivity.geo, terraserver-topo.geo,
+ terraserver-urban.geo, terraserver.geo, toposerver.geo,
+ src/map_geo.c: Changed the name of toposerver.geo to
+ terraserver-topo.geo. Added more options for terraserver so that
+ we can use all four options available currently. Put a bit more
+ debugging code and parameter checking code into map_geo.c.
+
+2005-06-29 09:29 we7u
+
+ * src/map_gdal.c: Putting draw_shapefile_map() between ifdef's, as
+ it isn't defined in some cases (if shapelib isn't available).
+
+2005-06-25 17:46 tvrusso
+
+ * FAQ: Just copy a FAQ heading into the TOC.
+
+2005-06-25 17:30 tvrusso
+
+ * src/maps.c: Undo bonehead commit by KM5VY (me).
+
+ I had mistakenly thought that "draw_filled" was a new map index
+ parameter, and tried to get the index_retrieve_from_file function
+ to set defaults for shapefiles differently.
+
+ This was an error, as draw_filled has always existed.
+
+ There is no way to "fix up" the index when running with new code
+ -- the user is simply going to have to go through the map
+ properties and turn Auto on if he/she wants filled shapefiles to
+ respect the dbfawk file's settings.
+
+ The reason I thought the commit was right was that I was testing
+ it on an index that had been passed through awk to remove the
+ draw_filled variable. It then inserted reasonable defaults, but
+ that's not the point.
+
+ It's unfortunate that a user with an existing batch of filled
+ shapefiles and dbfawk enabled will wind up surprised that they
+ stopped being filled, but that's the way it is.
+
+2005-06-25 09:02 we7u
+
+ * src/util.c: A fix for digipeating: valid_path() was adding an
+ asterisk on to the end of wideN-n/traceN-n digi's that had n!=N.
+ This caused unused digi's that were earlier in the path to be
+ skipped in the relay_digipeat() code. For instance a path of
+ "wide1-1,wide2-2" was working, but a path of "wide1-1,wide2-1"
+ was being changed into "wide1-1,wide2-1*", and the wide1-1 digi
+ would be skipped.
+
+2005-06-24 16:09 we7u
+
+ * src/db.c: Length of temp variable was too short to handle max
+ header length.
+
+2005-06-23 22:55 we7u
+
+ * src/map_cache.c: Adding a bunch of segfault debug code in order
+ to find a problem that one user is having with map caching of
+ tigermaps.
+
+2005-06-23 13:26 we7u
+
+ * AUTHORS: Adding Dan Brown to the list.
+
+2005-06-23 13:14 we7u
+
+ * AUTHORS: Adding Alan Crosswell to the list.
+
+2005-06-23 13:10 we7u
+
+ * AUTHORS: Adding Tom Russo to the list.
+
+2005-06-23 12:27 we7u
+
+ * AUTHORS: Adding Derrick to the list.
+
+2005-06-23 09:07 tvrusso
+
+ * src/maps.c: Fix migration of pre-"auto fill" map_index.sys to new
+ format.
+
+2005-06-22 22:47 tvrusso
+
+ * src/map_shp.c: Fix broken handling of "auto" shapefile filling.
+
+ There was a test of "draw_filled" to see if it was set to "auto",
+ but if it was, then draw_filled was changed to whatever the
+ dbfawk file "filled" value was. Since that was always 0 or 1, it
+ meant that every shape after the first one would not have
+ "draw_filled" set to auto anymore, and the entire shapefile would
+ be filled with whatever that first shape's value was (on or off).
+
+2005-06-22 12:47 we7u
+
+ * src/map_shp.c: Fixing up the default polygon fill condition for
+ when dbfawk file is not present (just a comment change) or for
+ when dbfawk support is not compiled into Xastir, for the case
+ where "Auto" fill is selected.
+
+2005-06-22 12:30 we7u
+
+ * README.MAPS, config/language-Dutch.sys,
+ config/language-English.sys, config/language-French.sys,
+ config/language-German.sys, config/language-Italian.sys,
+ config/language-Portuguese.sys, config/language-Spanish.sys,
+ src/main.c, src/map_shp.c, src/maps.c, src/maps.h: Implementing
+ an "Auto" function in the Map Properties dialog for polygon
+ fills. "Auto" will cause a dbfawk file to be used, if it is
+ present. The "Yes" (On) and "No" (Off) filled options that
+ existed before will now override a dbfawk file, so you can use a
+ Shapefile map in three different ways now from the Map Properties
+ dialog. I use this "No" option for instance to make the NOAA
+ Counties Shapefile into a vector map so I can overlay it on top
+ of a raster map, use the "Yes" function to use it as a base map
+ of the U.S., or use the "Auto" function to get all the advanced
+ per-object coloring possible from the dbfawk file, including
+ county names, border colors, etc.
+
+ The default setting for new Shapefiles will be "Auto". Default
+ for all other types of maps will be "No" or "Off".
+
+2005-06-21 18:15 we7u
+
+ * src/db.c: Updating some comments.
+
+2005-06-21 18:12 we7u
+
+ * src/map_tiger.c: Adding set/clear_dangerous() calls to aid in
+ debugging segfaults.
+
+2005-06-21 18:10 we7u
+
+ * src/: util.c, util.h, map_gdal.c: Moving set_dangerous() and
+ clear_dangerous to util.c/util.h and making them globally
+ available. These routines set/clear a string which gets dumped
+ out upon segfault. A debugging tool mostly.
+
+2005-06-21 13:13 we7u
+
+ * src/db.c: Moved check for zero unused digipeater fields in
+ relay_digipeat() function down a few lines in the code, to AFTER
+ where we reposition past the destination callsign.
+
+2005-06-21 12:43 we7u
+
+ * src/util.c: Adding checks for used-up WIDEn-N/TRACEn-N digipeater
+ slots and for maximum total digipeats to the check_unproto_path()
+ function. Max digipeats is only allowed to be as high as
+ MAX_WIDES + 1, no more. For instance, if MAX_WIDES is 4, then
+ "WIDE1-1,WIDE4-4" is legal, "WIDE1-1,WIDE,WIDE4-4", "WIDE5-5", or
+ "WIDE,WIDE,WIDE,WIDE,WIDE,WIDE" are not.
+
+2005-06-21 08:18 we7u
+
+ * config/nwsc_ddmmyy.dbfawk: Changing back to filled and black
+ border for the counties. It just makes too excellent of a base
+ map at present as-is. Will tweak back to non-filled once the
+ Xastir code is changed to allow overriding that parameter in Map
+ Properties.
+
+2005-06-21 08:09 we7u
+
+ * config/nwsc_ddmmyy.dbfawk: Reducing the line width for the county
+ borders.
+
+2005-06-21 08:05 we7u
+
+ * config/: nwsc_ddmmyy.dbfawk, nwsfz_ddmmyy.dbfawk,
+ nwsmzddmmyy.dbfawk, nwsozddmmyy.dbfawk, nwsw_ddmmyy.dbfawk,
+ nwsz_ddmmyy.dbfawk: Changing to non-filled. Will soon try to
+ tweak Xastir code so that the filled option can be chosen in the
+ map properties and override the dbfawk setting, so at least the
+ counties file can be selectively chosen to be filled. It makes a
+ good base map sometimes.
+
+2005-06-20 13:34 we7u
+
+ * src/map_cache.c: A tweak by Dan Brown to help eliminate segfaults
+ in Tigermap caching.
+
+2005-06-20 08:05 we7u
+
+ * config/: nwsc_ddmmyy.dbfawk, nwsfz_ddmmyy.dbfawk,
+ nwsmzddmmyy.dbfawk, nwsozddmmyy.dbfawk, nwsw_ddmmyy.dbfawk,
+ nwsz_ddmmyy.dbfawk: Changing default fill color to dark grey
+ instead of purple.
+
+2005-06-17 07:35 we7u
+
+ * WMSRadar.geo: Changing a comment.
+
+2005-06-14 14:01 we7u
+
+ * src/interface.c: Commenting out a debug fprintf statement.
+
+2005-06-14 12:59 we7u
+
+ * src/: interface.c, interface.h: Adding a #define in interface.h
+ called CONVERSE_MODE. This can be set to "k" or "conv" via
+ different defines to account for different TNC command sets.
+
+2005-06-14 12:39 we7u
+
+ * src/interface.c: Changed some comments.
+
+2005-06-13 19:45 we7u
+
+ * config/: Makefile.am, tnc-startup.tnc2: Adding a TAPR-2 style
+ startup file. This one is mostly a copy of the
+ tnc-startup.paccomm file for the moment, but will probably
+ diverge from it over time.
+
+2005-06-10 09:55 tvrusso
+
+ * src/db.c: Add additional check on wx stations to aloha
+ calculations. APRSDos only checks the symbol for "_", we were
+ only checking if there's any WX data. I was finding that some
+ stations with _ symbols were not being classed as wx stations,
+ apparently because their last posit had no weather or something.
+
+ Add "_" to the test.
+
+2005-06-09 18:19 we7u
+
+ * DEBUG_LEVELS: Adding Multipoint to the 2048 level description.
+ Naming the function in main.c that must be changed if more levels
+ are added.
+
+2005-06-08 22:08 tvrusso
+
+ * DEBUG_LEVELS, config/language-Dutch.sys,
+ config/language-English.sys, config/language-French.sys,
+ config/language-German.sys, config/language-Italian.sys,
+ config/language-Portuguese.sys, config/language-Spanish.sys,
+ src/database.h, src/db.c, src/main.c: Several improvements of
+ ALOHA reporting, as discussed on xastir-dev
+
+ 1) Change #ifdef DEBUG_ALOHA to a debug level test (2048) 2) Add
+ periodic display of ALOHA range in status line 3) Add a
+ "View->ALOHA Statistics" menu option. Pops up a dialog with
+ ALOHA range, number of stations in ALOHA circle, count of
+ various types of stations, and age of ALOHA calculation.
+
+2005-06-08 09:00 we7u
+
+ * FAQ: Adding a bit about how to turn off the aloha circle display.
+
+2005-06-08 08:45 we7u
+
+ * src/main.c: Calculating the Aloha circle even if the feature is
+ turned off. This means that if the feature is turned back on
+ again the circle will be accurate. The processing occurs so
+ seldom anyway that it's not much of a hit.
+
+2005-06-07 22:33 tvrusso
+
+ * src/map_tiger.c: Fix initialization of local_filename[0] so that
+ gcc 2.95 can compile this file.
+
+2005-06-07 22:16 tvrusso
+
+ * src/db.c: Fix mistake in logic of aloha_distance() that was
+ letting some oddly configured mobiles to slip through the cracks
+ (those with trackpoints and no speed).
+
+2005-06-07 13:04 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Changing the aloha
+ circle string to "Display" instead of "Disable".
+
+2005-06-07 13:01 we7u
+
+ * src/: db.c, main.c: Fixing some minor errors in the aloha toggle
+ code. Changing the name of the toggle and callback to be more
+ consistent with the rest of the code.
+
+2005-06-07 12:54 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c, src/main.h:
+ Adding an option to disable the Aloha Circle. This option is not
+ saved to the config file, by choice. It's intended that the
+ Aloha circle be on the map for the default case so that people
+ might make use of it. The toggle has been added for those rare
+ cases where the Aloha Circle needs to be removed from the screen.
+
+2005-06-07 09:25 we7u
+
+ * src/map_tiger.c: Reorganization by Dan Brown, n8ysz. This is in
+ preparation for another way-cool feature that Dan is working on.
+ Stay tuned!
+
+2005-06-07 05:33 tvrusso
+
+ * src/draw_symbols.h: Declare draw_aloha_circle to suppress
+ compilation warnings.
+
+2005-06-06 23:06 tvrusso
+
+ * src/database.h: Put an ifdef around a struct element only used
+ for debugging. This should cut down on memory use during ALOHA
+ calculation when not debugging.
+
+2005-06-06 22:54 tvrusso
+
+ * FAQ, src/database.h, src/db.c, src/draw_symbols.c, src/main.c:
+ Feature request 1043058
+
+ Add function to display ALOHA circles on the map. ALOHA radius
+ calculated according to Bob Bruninga's alohacir.txt file, and
+ private communications.
+
+2005-06-02 08:27 we7u
+
+ * README.win32: Adding a note about shutting down applications
+ before updating files.
+
+2005-06-01 13:11 we7u
+
+ * scripts/Makefile.am: Adding get_shapelib.sh to list of scripts to
+ install.
+
+2005-06-01 13:06 we7u
+
+ * INSTALL, README.win32: Adding notes about the
+ xastir/scripts/get_shapelib.sh script.
+
+2005-06-01 13:04 we7u
+
+ * scripts/get_shapelib.sh: Script to get/install Shapelib by Dan
+ Brown, n8ysz. Thanks!
+
+2005-06-01 12:24 we7u
+
+ * INSTALL, README.win32, src/db.c, src/gps.c: Adding some notes
+ about building Shapelib that Dan Brown came up with. Tweaking
+ the GPS GPGGA and GPRMC comments in the sources.
+
+2005-05-31 19:48 tvrusso
+
+ * README.MAPS: Remove statement that is no longer true.
+
+2005-05-31 15:25 tvrusso
+
+ * src/map_tif.c: Make lat/lon rasters subject to same kinds of
+ scan-line-skipping optimizations as UTM rasters have always had.
+
+ The trick was to realize that "scale_y" has units of "hundredths
+ of seconds per pixel" and that PixelScale in lat/long rasters has
+ the units of "degrees per pixel".
+
+2005-05-31 12:32 we7u
+
+ * WMSRadar.geo, src/main.h, src/map_WMS.c, src/map_geo.c,
+ src/maps.h: Implementing TRANSPARENT keyword for WMS maps and
+ changing WMSradar.geo to correspond.
+
+2005-05-25 12:12 gstueve
+
+ * src/alert.c: Fix spelling in comment.
+
+2005-05-25 11:42 we7u
+
+ * WMSRadar.geo, src/map_WMS.c: Moving the VERSION tag into the .geo
+ file. Some servers are picky about this, so it can't be
+ hard-coded.
+
+2005-05-24 12:49 we7u
+
+ * src/map_WMS.c: Adding/changing some comments.
+
+2005-05-24 12:21 we7u
+
+ * src/map_WMS.c: Moving more of the WMS parameters into the .geo
+ file instead of hard-coding them.
+
+2005-05-24 12:20 we7u
+
+ * WMSRadar.geo: Moving more of the parameters into the .geo file
+ instead of hard-coding them.
+
+2005-05-24 07:23 we7u
+
+ * WMSRadar.geo: Getting rid of the county outlines in the
+ downloaded image.
+
+2005-05-23 13:16 we7u
+
+ * src/map_WMS.c: Corected some comments. Turned off debug output.
+
+2005-05-23 12:59 we7u
+
+ * WMSRadar.geo, src/map_WMS.c: Moving more of the parameters into
+ the .geo file instead of hard-coded (allows more options to be
+ specified via the .geo files). Tweaked the scaling so that the
+ vertical scaling is correct now.
+
+2005-05-23 12:30 we7u
+
+ * src/util.c: Tweaking the lat/long string conversion routines so
+ they'll handle more input formats.
+
+2005-05-20 07:33 we7u
+
+ * src/map_WMS.c: Small tweaks to the URL generation for WMS
+ servers. Map registration is not correct yet.
+
+2005-05-19 08:43 we7u
+
+ * src/.cvsignore: Adding "xastir" as well so that we won't see that
+ in the CVS status listings. It's obviously a derived file.
+
+2005-05-19 08:26 we7u
+
+ * .cvsignore, callpass/.cvsignore, config/.cvsignore,
+ help/.cvsignore, m4/.cvsignore, scripts/.cvsignore,
+ src/.cvsignore, src/rtree/.cvsignore, symbols/.cvsignore: Adding
+ more lines to the .cvsignore files in order to clean up CVS
+ status listings.
+
+2005-05-19 08:01 we7u
+
+ * Makefile.am, WMSRadar.geo, src/Makefile.am, src/main.h,
+ src/map_WMS.c, src/map_geo.c: Adding initial support for WMS map
+ formats. This is not complete yet, but the functionality is
+ enough to give a taste for what is possible in the near future.
+ Registration is still a bit off plus we need to add methods for
+ the user to specify layers desired, specifying WMS servers from
+ the GUI, etc.
+
+2005-05-18 12:24 we7u
+
+ * src/gps.c: Modified parsing of GPGGA and GPRMC NMEA sentences to
+ handle more variations in the sentence structure.
+
+2005-05-18 12:23 we7u
+
+ * src/db.c: Changing some comments and debug statements having to
+ do with GPGGA and GPRMC NMEA sentence parsing.
+
+2005-05-18 09:41 we7u
+
+ * src/gps.c: Tweak to the GPGGA parsing to allow a '3' for GPS fix
+ quality.
+
+2005-05-17 13:41 we7u
+
+ * src/util.c: I've had this patch around for a couple of weeks. It
+ should allow matching on non-numeric SSID's for messaging now,
+ such as "WHO-IS" and "AE5PL-EM", which are the two test cases
+ that broke messaging earlier. It has not been fully tested on RF
+ yet, but appears to work when directly on the internet feeds.
+
+2005-05-09 10:09 we7u
+
+ * configure.ac, help/help-English.dat: Setting up for further CVS
+ development of Xastir. Changing rev to 1.5.1 to differentiate it
+ from the 1.5.0 stable release. Added a new "What's New in Xastir
+ BETA" section to the help-English.dat file.
+
+2005-05-09 09:34 we7u
+
+ * README.Contributing, README.Getting-Started, configure.ac,
+ help/help-English.dat: Updating for soon to be done 1.5.0
+ release.
+
+2005-05-09 09:32 we7u
+
+ * src/db.c: Spelling fix in comment. No code changes.
+
+2005-05-06 13:59 we7u
+
+ * src/awk.c: Another tweak by by John Laxson, KC0PZN. This one
+ fixes something that I messed up when I incorporated his first
+ patch.
+
+2005-05-05 12:36 we7u
+
+ * src/interface.c: Changed one comment. No code changes.
+
+2005-05-05 12:23 we7u
+
+ * src/awk.c: Tweak by John Laxson, KC0PZN, to speed up dbfawk on
+ MacOSX. Thanks!
+
+2005-05-05 12:19 we7u
+
+ * README: Getting rid of version number where it's not needed.
+ Will save us some work in the future.
+
+2005-04-29 15:06 kd6zwr
+
+ * src/interface.c: Fixes for segmentation faults on Solaris.
+ Sending a NULL pointer to a %s argument to any of the *printf()
+ functions (actually strlen() inside it) causes the fault. This
+ patch intializes two vars to "" instead of NULL, {Which is OK!!}
+ protects a function by whacking NULLs into ""s, and moves a debug
+ printf below a NULL check.
+
+2005-04-26 11:24 we7u
+
+ * src/interface.c: If an interface goes down due to a connection
+ being lost or inactivity, the 1st check_ports() call will bring
+ it back up now. Previously it would wait for the 2nd
+ check_ports() call before bringing it back up.
+
+2005-04-25 12:44 we7u
+
+ * README.MAPS: Added a paragraph about splitting large Shapefiles
+ into tiles.
+
+2005-04-25 12:44 we7u
+
+ * README.Getting-Started: Minor changes to a couple of sentences.
+
+2005-04-19 10:39 we7u
+
+ * src/track_gui.c: Fix by David Flood, kd7myc. Turns of TrackMe
+ button if you leave tracking on but change the call being tracked
+ via the menus. Thanks!
+
+2005-04-17 21:31 rzg
+
+ * help/help-English.dat: Updated the "what's new", shamelessly
+ ripping parts of curt's release notes because I'm behind in
+ keeping up with CVS. :-P
+
+2005-04-15 10:42 we7u
+
+ * xastir.spec.in: Adding a few more docs to the doc list.
+
+2005-04-15 10:02 we7u
+
+ * src/: interface.c, interface.h, interface_gui.c, xa_config.c:
+ Changes by Andreas Bier, DL1HRC, to allow setting a tnc2multi
+ into KISS mode via a togglebutton on the interface dialog. We
+ can probably extend this later to put other types of TNC's into
+ KISS mode and/or to take them out of KISS mode when shutting down
+ the interface.
+
+ I also changed the default for new interfaces to have
+ RELAY/WIDE1-1 digipeat turned off.
+
+2005-04-15 09:30 we7u
+
+ * README.Contributing: More info about diff's and patching.
+
+2005-04-15 09:01 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Changes by Andreas
+ Bier, DL1HRC. Thanks!
+
+2005-04-14 12:38 we7u
+
+ * README.Getting-Started: Adding more notes about the 2nd-tier
+ servers.
+
+2005-04-14 11:31 we7u
+
+ * Makefile.am: Adding the new doc into the Makefile structure.
+
+2005-04-14 10:35 we7u
+
+ * README.Contributing: Adding a document to assist budding
+ developers.
+
+2005-04-13 08:50 we7u
+
+ * src/util.c: Fixing a path check problem. It wasn't verifying
+ that the char before the '-' was a digit before applying N-n
+ checks to the callsign.
+
+2005-04-12 21:12 we7u
+
+ * README.Getting-Started: Pointing to a list of 2nd-tier servers
+ instead of suggesting Firenet.us.
+
+2005-04-12 08:50 we7u
+
+ * help/help-Dutch.dat, help/help-English.dat, help/help-French.dat,
+ help/help-German.dat, help/help-Italian.dat,
+ help/help-Portuguese.dat, help/help-Spanish.dat, src/interface.c:
+ Changing the default path. Changing the docs to match.
+
+2005-04-11 13:07 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys, tnc-startup.aea,
+ tnc-startup.kam, tnc-startup.kpc2, tnc-startup.kpc3,
+ tnc-startup.paccomm, tnc-startup.pico, tnc-startup.sys: Changing
+ from RELAY to WIDE1-1 in prompts and TNC startup files.
+
+2005-04-11 12:51 we7u
+
+ * FAQ, README.Getting-Started: Updating the path discussions to
+ cover the new scheme (WIDE1-1 instead of RELAY).
+
+2005-04-06 12:26 we7u
+
+ * src/: db.c, util.c: Making the "RELAY" digipeat work with either
+ RELAY or WIDE1-1, per the latest APRSSIG recommendations on how
+ to do paths and digipeating.
+
+2005-04-06 10:03 we7u
+
+ * src/util.c: Allowing WIDE1-1 as a RELAY type of callsign per the
+ new paradism.
+
+2005-03-31 12:43 we7u
+
+ * src/: db.c, util.c: Fixes to make the new WHO-IS server work with
+ Xastir.
+
+2005-03-30 09:12 we7u
+
+ * src/: map_geo.c, map_tiger.c, util.c: Changing text of one type
+ of error message.
+
+2005-03-25 22:33 we7u
+
+ * README.MAPS: Added a note about a blemish in the Haversine
+ formula we use for distance calculation.
+
+2005-03-25 12:53 we7u
+
+ * scripts/permutations.pl: Changes to the comments/description.
+
+2005-03-25 12:26 we7u
+
+ * src/datum.h: Changing some comments.
+
+2005-03-25 09:06 we7u
+
+ * README.MAPS: Added a summary regarding our distance/angle/area
+ calculations.
+
+2005-03-24 12:25 we7u
+
+ * src/: datum.h, main.c, util.c: Switching to Gerry-recommended
+ Earth radii plus putting them into central defines in datum.h.
+ That makes them easier to update in the future.
+
+2005-03-23 22:05 we7u
+
+ * src/main.c: Converting the Measure function from calculating area
+ via planar geometry to computing it using spherical calculations.
+ It should be much closer to reality now, particularly as one
+ zooms out.
+
+2005-03-23 21:57 we7u
+
+ * src/util.c: Changing some comments.
+
+2005-03-23 21:51 we7u
+
+ * src/util.h: Making a couple of routines available to other
+ modules.
+
+2005-03-23 12:36 we7u
+
+ * src/util.c: Converting the distance calculations from using the
+ Law of Cosines for Spherical Geometry to using the Haversine
+ Formula. This should be more accurate for shorter distances, no
+ real change for longer distances.
+
+2005-03-23 09:33 we7u
+
+ * src/main.c: Bumping the check interval for inactivity from 1
+ minute to 5 minutes. This means that if we lose an internet
+ connection we might not get it back for between 10 to 15 minutes
+ (instead of the current 2 to 3 minutes), but it also means that
+ server connections won't bounce up and down as much if there are
+ few packets coming down the pipe. One packet every 5 minutes is
+ enough to keep the connection going.
+
+2005-03-22 15:10 we7u
+
+ * src/util.c: Changed some comments.
+
+2005-03-22 13:11 we7u
+
+ * src/draw_symbols.c: Added/changed some comments.
+
+2005-03-22 12:38 we7u
+
+ * README.Getting-Started: Added an enumeration of the various ways
+ of controlling Xastir itself.
+
+2005-03-21 20:57 we7u
+
+ * src/: database.h, db.c, draw_symbols.c: Fixes for DF objects to
+ make the beamwidths and angles correct. Also fixed the
+ "Unusable" beamwidth so that it still appears as a DF object in
+ the Object->Modify dialog.
+
+2005-03-20 16:33 tvrusso
+
+ * src/testawk.c: Add initializer for pattern, add variable for
+ label_color, and add appropriate code so that dbfawk files that
+ set label_color can be tested.
+
+2005-03-18 13:20 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/util.c, src/db.c: Fixing
+ decoding of compressed DF beam objects/items. Fixing the display
+ in Station Info of DF stations.
+
+2005-03-18 12:09 we7u
+
+ * src/: db.c, main.c: Fixes for varying truncation on object/item
+ comments. We were allowing comments that were longer than 43
+ chars, which were truncated during later transmits by
+ check_and_transmit_objects_items(). We now no longer allow the
+ extra length packets to be transmitted. The spaces that were
+ added for Pmin/Pmax are now no longer added: that was another
+ cause for the varying truncation of the comment.
+
+ Fixed the object/item transmit routines so that we can now send
+ compressed-mode for all types. The decode routines now have to
+ catch up.
+
+2005-03-17 13:16 we7u
+
+ * src/db.c: Better implmentation of my debug tweak that will work
+ with more compilers.
+
+2005-03-17 13:07 we7u
+
+ * src/db.c: Removing some comments.
+
+2005-03-17 12:30 we7u
+
+ * src/draw_symbols.c: More work on dead-reckoning to position the
+ ghost symbols and the dashed lines correctly. Have disabled the
+ arcs for now as the positioning is not correct for them with the
+ current code.
+
+2005-03-17 12:28 we7u
+
+ * src/util.c: Added poor-man's rounding to the places we construct
+ the transmitted lat/long's. This helps with dead-reckoning of
+ symbols at close-in zoom levels.
+
+2005-03-17 12:27 we7u
+
+ * src/db.c: Added a define and some ifndef's to make some debug
+ easier.
+
+2005-03-17 07:34 we7u
+
+ * src/map_cache.c: Tweaks by Dan Brown, N8YSZ.
+
+2005-03-17 07:21 we7u
+
+ * src/database.h: Changed one comment.
+
+2005-03-16 13:36 we7u
+
+ * src/: igate.c, interface.c, interface_gui.c, location_gui.c,
+ main.c, map_geo.c, map_gnis.c, map_shp.c, map_tif.c, maps.c,
+ util.c, wx.c, xa_config.c: Checking the return codes for
+ scanf/sscanf/fscanf functions.
+
+2005-03-16 12:15 we7u
+
+ * src/: alert.c, db.c: Checking the return codes of
+ scanf/sscanf/fscanf functions.
+
+2005-03-16 11:34 we7u
+
+ * src/util.c: A workaround for an sscanf() bug that shows up on
+ Cygwin. It wasn't parsing the lat/long properly in
+ compress_posit(). Re-coded the routine to do everything
+ manually. The other 60 or so places that scanf() and it's
+ variants are used should also be checked for correct operation on
+ Cygwin.
+
+2005-03-15 16:50 we7u
+
+ * src/util.c: Fix for incorrect compressed packets on Cygwin.
+ Evidently the 'N' in the latitude is getting passed to the
+ routine as an 'n', which causes the problem. The root cause of
+ the problem is probably that the latitude variable is getting
+ messed up sometime earlier.
+
+2005-03-15 11:25 we7u
+
+ * src/wx.c: Tweaks for Davis WX station by Clay Jackson, n7qnm.
+
+2005-03-14 17:58 we7u
+
+ * src/: database.h, db.c: Decoding weather from "Position with
+ Timestamp no APRS messaging" packets.
+
+2005-03-14 13:15 we7u
+
+ * src/: database.h, db.c, main.c: Fixing a bug that crept in while
+ coding some object/item stuff. Moving some comments to a more
+ appropriate place. Commenting out the last_modified_time
+ variable for now, as it's not actually implemented in the
+ dead-reckoning code yet.
+
+2005-03-13 19:11 we7u
+
+ * src/: database.h, db.c, main.c: Dead-reckoning of objects and
+ items: Working a bit better with this version. We now use the
+ latest DR'ed position when making a change to the object/item.
+ Moving a DR'ed object/item works. One thing that doesn't work
+ now is trying to update the position of a moving object/item
+ using the Modify dialog: The lat/long boxes are ignored now in
+ favor of the DR'ed position. Also note that the on-screen DR
+ function is a bit off in speed and direction from the more
+ accurate function that actually moves the object along. This is
+ yet to be fixed.
+
+2005-03-11 22:38 we7u
+
+ * src/db.c: Dead-reckoning for compressed objects/items as well.
+
+2005-03-11 22:10 we7u
+
+ * src/db.c: Better accuracy for the angle calculations for object
+ dead-reckoning.
+
+2005-03-11 21:19 we7u
+
+ * src/db.c: Transmitting dead-reckoned object/item positions is
+ starting to work in this version. More to do yet, but it could
+ be useful as-is.
+
+2005-03-11 08:45 we7u
+
+ * src/db.c: Commenting out the code that moves dead-reckoned
+ objects. Not correct yet.
+
+2005-03-11 07:52 we7u
+
+ * src/db.c: Initial version of dead-reckoning for objects.
+ Dead-reckoned positions are transmitted now at the decaying
+ transmit interval. Still need to do more work on this, like
+ computing the latest dead-reckoned position and transmitting that
+ position at the point an object/item is changed, correcting the
+ disparity between the on-screen DR and the transmitted DR
+ (on-screen DR appears to compute angle based on screen pixels,
+ while the transmitted DR computes angle based on lat/long). The
+ log file is ignored in these changes also: If Xastir crashes or
+ is shut down, time for the DR object will be lost and it will
+ start DR'ing at the point it was last transmitted at before
+ shutdown.
+
+2005-03-10 13:02 we7u
+
+ * src/: database.h, db.c, main.c: Preliminary work for fixing
+ dead-reckoning of objects/items. More to do yet, but this
+ last_modified_time variable is needed to get started on the
+ problem.
+
+2005-03-08 13:05 we7u
+
+ * src/main.c: Mods by Dan Brown, N8YSZ. Prevent multiple Xastir's
+ from getting run by a single user. The prevents config files
+ from getting corrupted.
+
+2005-03-08 10:31 we7u
+
+ * FAQ: Updates by Dan Brown and myself.
+
+2005-03-08 09:16 tvrusso
+
+ * configure.ac: Fix dummm mistake in help text for --with-rtree
+
+2005-03-03 11:41 we7u
+
+ * README.MAPS: Added the temporary Wiki location.
+
+2005-03-03 11:39 we7u
+
+ * README.MAPS: Added a note about the populated places GNIS file.
+
+2005-03-03 09:24 we7u
+
+ * README: Adding a note about n1ofz's web page and binary Xastir
+ installation.
+
+2005-03-02 11:47 we7u
+
+ * README: Added a note about gating stations, objects, and items to
+ RF.
+
+2005-03-02 11:41 we7u
+
+ * src/igate.c: Removing a debug printf that is used for checking
+ out gating to RF.
+
+2005-03-02 09:39 we7u
+
+ * src/interface_gui.c: Fix for an annoying warning that X11 puts
+ out when you add an interface in Xastir.
+
+2005-03-02 08:56 tvrusso
+
+ * src/map_tif.c: Comment out warning when a geotiff file has no
+ PCS.
+
+ Geotiffs without PCS (Projected Coordinate System) tags are
+ assumed to be lat/lon rasters. Now that this capability is being
+ more widely used, especially by users outside the US, this
+ warning is just an annoyance. It was only there because it was
+ once cause to reject a raster if it had no PCS.
+
+2005-03-01 12:55 we7u
+
+ * src/igate.c: Allowing nws-stations.txt changes to take effect
+ right away for stations being gated to RF. If the file has been
+ changed, the in-memory database gets updated.
+
+2005-03-01 12:32 we7u
+
+ * src/main.c: Allow re-creating of an object or item that has been
+ killed and is still in the database. Previous code wouldn't
+ allow that and brought up a warning popup. Now the popup happens
+ only if a "live" object/item is in the database with the same
+ name.
+
+2005-03-01 12:05 we7u
+
+ * src/: igate.h, db.c, igate.c: Igating of specific objects/items
+ to RF is now possible by listing the object or item name in
+ data/nws-stations.txt. The listing is case-insensitive. Putting
+ a wild-card source callsign in that file doesn't get
+ objects/items from that station igated to RF, but other packets
+ from that callsign do get gated. Objects/items have to be
+ specifically listed by name, as the code stands now.
+
+2005-03-01 11:36 we7u
+
+ * src/db.c: Proper RF gating of objects/items when the originating
+ callsign is specified in the data/nws-stations.txt file. The
+ previous code was incorrect w.r.t. object/item gating.
+
+2005-03-01 09:09 we7u
+
+ * src/: db.c, igate.c: Initial attempt at gating individual
+ stations through to RF, if those stations are spelled out in the
+ data/nws-stations.txt file. Wildcarding is inherent, so "we7u"
+ will match "we7u", "we7ua", and "we7uaa" through "we7uzz". This
+ change also means that any packets (like posits perhaps) from an
+ NWS station that are not weather alerts will now get gated to RF.
+ Hopefully this won't be a problem. I've left an fprintf() in
+ the code so you'll see which new packets are gated through to RF
+ (prints to STDERR). We'll remove that fprintf() later once we're
+ satisfied with the new operation.
+
+2005-02-28 09:11 we7u
+
+ * src/: db.c, draw_symbols.c, draw_symbols.h: Fixing the selected
+ stations count (on status bar) for dead-reckoned stations. They
+ were getting counted twice, once for the non-ghosted and once for
+ the ghosted symbol.
+
+2005-02-26 18:04 shadow
+
+ * INSTALL: update imagemagick info
+
+2005-02-24 16:01 we7u
+
+ * FAQ: Adding instructions for running more than one Xastir at once
+ on the same machine.
+
+2005-02-20 10:07 tvrusso
+
+ * README: Bring some of the FreeBSD notes up to date. It is no
+ longer necessary to use "gmake" instead of "make" with xastir's
+ build on FreeBSD, and the comments about autoconf versions were
+ very old.
+
+ Also, change reference to the "current" version 1.1.x of xastir.
+
+2005-02-18 11:38 we7u
+
+ * README: Changes suggested by Dan Brown, plus another one or two
+ added by me. Fixing mailing list and Xastir link addresses.
+
+2005-02-17 01:14 we7u
+
+ * src/util.c: Better version of the function which checks the
+ unproto paths as they are entered by the user. This one checks
+ for all the proper relations between the n-N numbers, and limits
+ them to MAX_WIDES (which is set in util.h).
+
+2005-02-16 15:20 tvrusso
+
+ * src/util.c: Repair check_unproto_path to fix mistakes I'd made in
+ last commit (atoi() on a character rather than string), and
+ rearrange things so that some odd usages in the original code
+ still work.
+
+ I have not cleaned it up properly. Instances of changing
+ character pointers in a conditional remain as they were in
+ original code, and flagging "bad" paths like "WIDE1-2" results in
+ "Path too long" error message when it should say instead "very
+ strange path". But it will NOT reject paths like WIDE2-1
+ anymore, and will accept paths like WIDE7-2 (even though the
+ first digit is essentially meaningless when used this way).
+
+ This time I actually tested these fixes and they work.
+
+2005-02-16 13:38 tvrusso
+
+ * src/util.c: Simple change to stop "WIDEN-n" where N!=n being
+ flagged as a "Bad Path"
+
+ Instead, it now checks that N>=n, and only reports "N<n" as a bad
+ path.
+
+ The "N!=n is bad" has been there since October 2004, when the
+ path-checking code was first added.
+
+ This addresses comment raised on xastir mailing list on 16 Feb
+ 2005.
+
+2005-02-16 09:14 we7u
+
+ * README.MAPS: Added notes about 2004 Tiger/Line data plus methods
+ of converting Tiger/Line data to Shapefile data. Thanks go to
+ Tom Russo for most of the added text.
+
+2005-02-16 08:46 we7u
+
+ * README: Adding notes provided by Carl Makin regarding FreeBSD
+ ports.
+
+2005-02-15 11:42 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/track_gui.c: Fixing a problem
+ where you can request another findu track while the previous
+ track or some other file is still being processed by Xastir. A
+ popup now asks you to wait and then retry the request.
+
+2005-02-14 16:32 we7u
+
+ * config/language-Dutch.sys: Updates by Han Sytsma, PE1FAM.
+ Thanks!
+
+2005-02-14 14:38 we7u
+
+ * scripts/toporama250k.pl: Modifications for latitudes above 67
+ degrees north contributed by Tom
+ Tessier, VE4TRT. Thanks!
+
+2005-02-07 11:28 we7u
+
+ * README.win32: Updating the note about spaces in usernames.
+
+2005-02-04 11:36 we7u
+
+ * scripts/fcc-get, src/fcc_data.c, src/main.c, src/rac_data.c,
+ src/xa_config.c: Minor tweaks to fcc-get script. Dump text to
+ stderr if we're re-indexing the fcc or rac data. Bumped max
+ tiger timeout from 180 sec to 300 sec.
+
+2005-02-04 10:34 we7u
+
+ * scripts/fcc-get: Still attemping to get the CVS ID string
+ correct. Didn't accept the correct format the first go-around.
+
+2005-02-04 10:26 we7u
+
+ * scripts/fcc-get: Fixing the CVS Id string.
+
+2005-02-04 10:26 we7u
+
+ * scripts/fcc-get: Added comments. Added a filter for the FCC data
+ to get rid of extra control chars in the middle of the lines.
+
+2005-02-01 08:15 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Adding (tm) to
+ "APRS" strings.
+
+2005-02-01 08:12 we7u
+
+ * AUTHORS, FAQ, INSTALL, README, README.Getting-Started,
+ README.MAPS, README.win32, changes.txt, xastir.1, xastir.spec.in,
+ help/help-English.dat: Fixing up the APRS trademark text.
+
+2005-01-29 09:32 we7u
+
+ * src/: interface.c, messages_gui.c: Fix for the "(null)" text
+ appearing in the Packet Data dialog when using custom messages.
+ It now reports the path being used.
+
+2005-01-28 17:16 we7u
+
+ * src/maps.c: More speedups, this time in index_retrieve(). This
+ takes it way down the profiling list so that it isn't an issue
+ anymore.
+
+2005-01-26 13:36 we7u
+
+ * src/util.c: Fix for bug pointed out by Tapio Sokura. We could
+ end up with an item name with a ';' character in it, an the
+ previous if/then contructs would guess wrong.
+
+2005-01-26 13:30 we7u
+
+ * src/db.c: Fix for objects/items deleted by someone else. Xastir
+ wasn't calling the disown_object_item() function previously for
+ this case.
+
+2005-01-26 13:27 we7u
+
+ * src/util.c: Added debug statement. Currently commented out.
+
+2005-01-26 13:11 we7u
+
+ * src/interface.c: Making sure that any paths are in upper-case as
+ transmitted.
+
+2005-01-25 18:11 we7u
+
+ * src/interface.c: Tweaks so that any transmit will show in the
+ Display Packet Data dialog, one per interface which has transmit
+ enabled and is active. This allows the user to see the paths
+ being used for each transmit for each interface. The transmit
+ string used to show a generic path before, plus would appear in
+ that dialog whether any interfaces were up/transmit enabled.
+ Also, if transmit objects was disabled, the dialog used to show a
+ transmit as if something went out. This has been fixed. Minor
+ problems remain such as a "(null)" as a path for x-spider
+ interface transmits. Perhaps other interfaces might have the
+ similar problems.
+
+2005-01-25 15:43 we7u
+
+ * src/interface.c: Added some debug code for testing Serial KISS
+ interfaces.
+
+2005-01-24 22:05 we7u
+
+ * DEBUG_LEVELS, FAQ, INSTALL, README, README.CVS,
+ README.Getting-Started, README.MAPS, README.win32, UPGRADE,
+ help/help-English.dat: Spelling corrections.
+
+2005-01-24 13:52 we7u
+
+ * README.win32: Tweaks to the gdal install instructions: *)
+ Requires Shapelib so that Xastir can configure in GDAL *) More
+ configure options needed for GDAL so that it will
+ configure/compile on Win32 systems.
+
+2005-01-23 12:49 we7u
+
+ * src/: alert.c, alert.h, map_shp.c, util.c, wx_gui.c, maps.c,
+ db.c: Hash table implementation for weather alert storage. This
+ makes things much faster. Still have alert_list[] array used in
+ one place in alert.c. That bit of code needs to be rewritten.
+
+2005-01-21 12:40 we7u
+
+ * src/alert.c: Another minor speedup for the weather alert code.
+ Getting rid of a couple of unnecessary calls. Renaming one
+ function so that it's uses are clear.
+
+2005-01-20 15:57 we7u
+
+ * src/db.c: Faster-yet is_my_call() function.
+
+2005-01-20 15:40 we7u
+
+ * src/db.c: Minor efficiency increase for is_my_call() function.
+ We don't need to check the length of the two strings as strcmp()
+ does that already.
+
+2005-01-20 09:51 tvrusso
+
+ * configure.ac: Move AH_BOTTOM call up to near the AC_CHECK_TYPES
+ that tests for socklen_t
+
+2005-01-20 09:38 tvrusso
+
+ * acconfig.h, configure.ac: Remove deprecated acconfig.h file.
+
+ Add "modern" usage of AH_BOTTOM to configure.ac to accomplish the
+ same thing.
+
+2005-01-19 23:27 tvrusso
+
+ * src/map_gnis.c: Add check that latitude and longitude fields
+ actually begin with digits before attempting to use the fields as
+ lat/lon values.
+
+ This fixes the bogus bounding box problem that was leading to
+ xastir loading gnis files that should have been out of view. It
+ had been showing all GNIS files as having the equator as lower
+ boundary, for example.
+
+2005-01-19 16:45 shadow
+
+ * acconfig.h, src/interface.c: deal with socklen_t not being
+ defined everywhere
+
+2005-01-18 09:06 we7u
+
+ * src/: db.c, draw_symbols.c: Fixing the selected station count (on
+ the status line) so that it more accuractely reflects the number
+ of stations on the screen (whatever made it through the station
+ filters).
+
+2005-01-15 21:15 rzg
+
+ * help/help-English.dat: Updates to the helpfile.
+
+2005-01-14 09:07 tvrusso
+
+ * INSTALL: Add a brief note about enabling spatial indexing, and a
+ reference to the original author's web site per request.
+
+2005-01-13 20:16 tvrusso
+
+ * src/rtree/: card.c, card.h, gammavol.c, index.c, index.h, node.c,
+ rect.c, sources.htm, sphvol.c, split_l.c, split_l.h, split_q.c,
+ split_q.h: Correct name and contact information for author of the
+ rtree code per her request.
+
+2005-01-12 20:02 tvrusso
+
+ * src/map_shp.c: Add a couple of lines of debugging output
+ (selectable with debug level 16) to try to track down why labels
+ for weather alerts aren't showing up until the map is refreshed,
+ and not the first time it's drawn.
+
+2005-01-11 17:30 we7u
+
+ * src/: main.c, db.c, util.c, util.h: New code which uses a hash
+ table to store the tactical callsigns. This gets the tactical
+ callsign number out of the total stations received number, plus
+ should be a better implementation all the way around after all
+ the minor bugs are found.
+
+2005-01-10 18:06 we7u
+
+ * src/: main.c, util.c: Fixing the slight Maidenhead grid problem
+ (off by one). Starting to implement a new set of tactical call
+ functions, but the old system is currently still in place. When
+ fully implemented the tactical call quantity won't add to our
+ received station count number.
+
+2005-01-10 13:39 we7u
+
+ * src/util.c: Added some comments.
+
+2005-01-10 13:39 we7u
+
+ * src/map_shp.c: Changes to comments/white-space only.
+
+2005-01-09 16:09 tvrusso
+
+ * src/map_shp.c: Add additional cases for switch statement to allow
+ 3D point and polygon files to be recognized and displayed. All
+ these do is let the 3D versions be treated by the same code as
+ the 2D versions --- the Z coordinate is simply ignored.
+
+ If xastir ever becomes a 3D-rendering APRS code these cases could
+ be handled differently.
+
+ I have no instances of 3D point or polygon shapefiles, so did not
+ test these changes. The 3D polyline cases I have do display
+ properly.
+
+2005-01-09 15:10 tvrusso
+
+ * src/map_shp.c: Add two tiny changes that allow 3-D polyline
+ shapefiles to be displayed.
+
+ All this does is allow xastir to recognize 3D polyline shapefiles
+ (SHPT_ARCZ) and display them as if they were 2-D (by ignoring all
+ but the X and Y coordinates). The finnish shapefiles that were
+ causing the crash fixed by the previous commit were 3D shapefiles
+ that can now be displayed without first being converted to 2D
+ with ogr2ogr.
+
+2005-01-09 15:06 tvrusso
+
+ * src/: map_shp.c, shp_hash.c: map_shp.c: move block of code that
+ accesses rtrees and shapefile hashes to after the block that
+ includes the "return if just indexing". This lets us skip the
+ hashtable lookup and rtree generation for maps that are merely
+ being index.
+
+ shp_hash.c: add a test before RTreeInsertRect to make sure that
+ the bounding box being passed is valid (i.e. that it won't fail
+ the assertion inside the RTreeInsertRect routine), and skip the
+ shape if not.
+
+ This should fix the crashes Curt was seeing a few days ago when
+ including some defective Finland shapefiles in his map directory.
+
+2005-01-09 11:46 tvrusso
+
+ * src/: Makefile.am, rtree/Makefile.am: Fix for distribution
+ problems:
+
+ add DIST_SUBDIRS line so that distribution generation doesn't
+ have a
+ conditional. This allows conditional compilation, but
+ unconditional
+ distribution of the directory.
+
+ fix SOURCES line in src/rtree/Makefile.am to reference only
+ files that exist
+
+2005-01-09 11:30 tvrusso
+
+ * src/Makefile.am: Undo change made this morning. Forcing rtree
+ into the SUBDIRS means that it will be built even if the user
+ hasn't specified --with-rtree. If it fails to build Makefile.in
+ in the rtree directory then a different solution (perhaps
+ changing configure.ac so it doesn't try to generate
+ src/rtree/Makefile) is needed.
+
+ But I can't reproduce the problem --- every time I run bootstrap
+ it generates the Makefile.in in the rtree directory.
+
+2005-01-09 10:54 we7u
+
+ * src/Makefile.am: Adding rtree as a subdirectory in the make
+ process.
+
+2005-01-08 02:24 we7u
+
+ * src/rtree/Makefile.am, src/rtree/card.c, src/rtree/card.h,
+ src/rtree/gammavol.c, src/rtree/index.c, src/rtree/index.h,
+ src/rtree/node.c, src/rtree/rect.c, src/rtree/sphvol.c,
+ src/rtree/split_l.c, src/rtree/split_l.h, src/rtree/split_q.c,
+ src/rtree/split_q.h, update-xastir: Updating Copyright notice.
+
+2005-01-08 02:19 we7u
+
+ * AUTHORS, FAQ, INSTALL, LICENSE, Makefile.am, NEWS, README,
+ README.CVS, README.Getting-Started, README.MAPS, README.win32,
+ UPGRADE, acinclude.m4, bootstrap.sh, changes.txt, configure.ac,
+ install-xastir, xastir.1, src/Makefile.am: Updating Copyright
+ notice.
+
+2005-01-08 02:06 we7u
+
+ * src/: alert.c, awk.c, bulletin_gui.c, color.c, datum.c, dbfawk.c,
+ draw_symbols.c, fcc_data.c, festival.c, geocoder_gui.c, gps.c,
+ hostname.c, igate.c, interface.c, interface_gui.c, lang.c,
+ list_gui.c, locate_gui.c, location.c, location_gui.c,
+ macspeech.c, map_cache.c, map_dos.c, map_gdal.c, map_geo.c,
+ map_gnis.c, map_pdb.c, map_shp.c, map_tif.c, map_tiger.c, maps.c,
+ messages.c, messages_gui.c, popup_gui.c, rac_data.c, rotated.c,
+ shp_hash.c, snprintf.c, sound.c, testawk.c, track_gui.c, util.c:
+ Updating Copyright notice.
+
+2005-01-08 01:54 we7u
+
+ * src/: geo-find.c, io-common.c, io-mmap.c, geo-client.c,
+ hashtable.c, hashtable_itr.c, main.c, view_message_gui.c, wx.c,
+ wx_gui.c, x_spider.c, xa_config.c, db.c: Updating Copyright
+ notice.
+
+2005-01-08 01:46 we7u
+
+ * src/: alert.h, awk.h, bulletin_gui.h, color.h, database.h,
+ datum.h, dbfawk.h, draw_symbols.h, fcc_data.h, festival.h, geo.h,
+ gps.h, hashtable.h, hashtable_itr.h, hashtable_private.h,
+ hostname.h, igate.h, interface.h, io.h, lang.h, list_gui.h,
+ main.h, map_cache.h, maps.h, messages.h, popup.h, rac_data.h,
+ rotated.h, shp_hash.h, snprintf.h, symbols.h, track_gui.h,
+ util.h, wx.h, x_spider.h, xa_config.h, xastir.h: Updating
+ Copyright notice.
+
+2005-01-08 01:33 we7u
+
+ * Davis/src/: Makefile.am, db2APRS.c, defs.h: Updating Copyright
+ notice.
+
+2005-01-08 01:30 we7u
+
+ * Davis/: Makefile.am, bootstrap.sh, README, configure.ac: Updating
+ Copyright notice.
+
+2005-01-08 01:27 we7u
+
+ * scripts/Makefile.am, scripts/Xastir_tigerpoly.py,
+ scripts/example_objects.log, scripts/fcc-get, scripts/get-gnis,
+ scripts/inf2geo.pl, scripts/ozi2geo.pl, scripts/toporama250k.pl,
+ scripts/toporama50k.pl, scripts/xastir-fixcfg.sh,
+ scripts/xastir-migrate.sh, symbols/Makefile.am,
+ symbols/symbols.dat: Updating Copyright notice.
+
+2005-01-08 01:23 we7u
+
+ * help/Makefile.am, help/help-Dutch.dat, help/help-English.dat,
+ help/help-French.dat, help/help-German.dat,
+ help/help-Italian.dat, help/help-Portuguese.dat,
+ help/help-Spanish.dat, m4/Makefile.am: Updating Copyright notice.
+
+2005-01-08 01:19 we7u
+
+ * config/24kgrid.dbfawk, config/Makefile.am, config/gps_wpt.dbfawk,
+ config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, config/nwsc_ddmmyy.dbfawk,
+ config/nwsmzddmmyy.dbfawk, config/nwsozddmmyy.dbfawk,
+ config/nwsz_ddmmyy.dbfawk, config/tgr2shp.dbfawk,
+ config/tgr2shppoly.dbfawk, config/tgrcty.dbfawk,
+ config/tgrkgl.dbfawk, config/tgrlk.dbfawk, config/tgrlpt.dbfawk,
+ config/tgrplc00.dbfawk, config/tgrwat.dbfawk,
+ config/tnc-startup.aea, config/tnc-startup.d700,
+ config/tnc-startup.kam, config/tnc-startup.kpc2,
+ config/tnc-startup.kpc3, config/tnc-startup.paccomm,
+ config/tnc-startup.pico, config/tnc-startup.sys,
+ config/tnc-startup.thd7, config/tnc-startup.tnc2-ui,
+ config/tnc-stop.d700, config/tnc-stop.sys, config/tnc-stop.thd7,
+ config/tnc-stop.tnc2-ui, config/nwsfz_ddmmyy.dbfawk,
+ config/nwsw_ddmmyy.dbfawk, config/tgrlpy.dbfawk,
+ callpass/Makefile.am, callpass/callpass.c: Updating Copyright
+ notice.
+
+2005-01-06 22:14 we7u
+
+ * DEBUG_LEVELS: More tweaks by Dan Brown, n8ysz.
+
+2005-01-05 09:16 we7u
+
+ * DEBUG_LEVELS: Tweaks by several members of the mailing list,
+ compiled by Dan Brown, n8ysz. Thanks!
+
+2005-01-04 09:20 we7u
+
+ * src/: messages.c, messages_gui.c: Last commit on these two files
+ was done in error, and caused the previous commit to be undone.
+
+2005-01-04 09:06 we7u
+
+ * src/: interface.h, interface.c, interface_gui.c: Fixing the
+ Interface Control dialog so that it updates immediately whenever
+ status of an interface changes.
+
+2005-01-03 17:28 we7u
+
+ * src/: messages.c, messages_gui.c: Interface control dialog now
+ changes quickly when status on an interface changes.
+
+2005-01-03 11:30 we7u
+
+ * src/maps.c: The XpmWriteFileFromPixmap() library call was changed
+ so as to not allow absolute paths. We had to change our code to
+ comply with the new XPM API.
+
+2005-01-03 10:28 we7u
+
+ * src/maps.c: Tweaks suggested by Tom Russo to more fully report
+ errors from XpmWriteFileFromPixmap(). I added returns for the
+ cases where we get these errors so that we don't try to continue
+ processing non-existent or ancient snapshot or print files.
+
+2005-01-01 21:26 tvrusso
+
+ * scripts/split_gnis.pl, src/map_gnis.c: split_gnis.pl: remove
+ dependency on Text::CSV_XS, change to work with current gnis
+ files. The script was apparently written when gnis files were
+ still comma separated, but that's not true anymore.
+
+ map_gnis: changes to a few comments.
+
+2004-12-30 23:56 we7u
+
+ * src/: messages.c, messages_gui.c: Fixes so that the current path
+ setting in the Send Message dialog takes effect for messages in
+ the outgoing queue and ack's in the delayed ack queue.
+
+2004-12-30 13:21 we7u
+
+ * src/: util.c, util.h: Adding the xastir_debug() function which we
+ can use instead of our current scheme for dumping out extra
+ messages to STDERR during various stages of debugging.
+
+2004-12-30 08:36 we7u
+
+ * src/messages.c: Tweak to cause Send Message and Send Group
+ Message dialogs to pop to the top of the window stack when new
+ messages are received.
+
+2004-12-30 08:34 we7u
+
+ * src/db.c: Fix for directed version query so that it doesn't pop
+ up a Send Group Message dialog when received.
+
+2004-12-29 12:59 we7u
+
+ * src/db.c: Storing the 3rd-party path in the station record for
+ the case were we hear the 3rd-party packet on RF and haven't
+ heard the station directly on RF for at least the last hour.
+
+2004-12-29 12:31 we7u
+
+ * src/: db.c, interface.c: Adding the transmitted packets into the
+ Incoming Data dialog. Doesn't include posits that we're sending.
+ Only one copy of the outgoing data is shown, no matter how many
+ ports we have open, and the path that is shown is the one we'd
+ use for a network interface, as we change the transmitted path
+ based on the interface type normally.
+
+2004-12-29 08:40 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/messages.c, src/messages.h,
+ src/messages_gui.c: Tweaks to allow ACK's to follow a custom path
+ set in the Send Message dialog, change the path on delayed ACK's
+ to match the current custom path, and tweaks to change the path
+ on pending TX messages to match the current custom path. Also
+ have a change in here to bring up a popup if a custom message is
+ entered and the Send Message dialog is closed (thereby throwing
+ away the custom path), but couldn't get it to trigger only when
+ desired, so that function is commented out at present.
+
+2004-12-28 13:04 we7u
+
+ * src/interface.c: Changing one debug fprintf statement.
+
+2004-12-28 12:29 we7u
+
+ * src/: db.c, messages.h, messages_gui.c, view_message_gui.c,
+ xa_config.c: Making sure VIEW_MESSAGE_LIMIT can't be set too low.
+ Adding some tweaks so that the custom path set in the Send
+ Message dialog will get used for ACK's as well, assuming the
+ dialog doesn't get closed.
+
+2004-12-28 08:14 we7u
+
+ * README.win32: Updating the notes about the CD's a bit.
+
+2004-12-27 22:16 tvrusso
+
+ * config/nwsc_ddmmyy.dbfawk, config/nwsfz_ddmmyy.dbfawk,
+ config/nwsmzddmmyy.dbfawk, config/nwsozddmmyy.dbfawk,
+ config/nwsw_ddmmyy.dbfawk, config/nwsz_ddmmyy.dbfawk,
+ src/map_shp.c: Change all dbfawk files for NWS county/zone
+ shapefiles so the display_level is very high.
+
+ Until last week or so, display_level was always ignored for
+ polygon shapefiles, so this didn't matter. Now that
+ draw_shapefile_map actually uses the parameter for these it
+ becomes important that the value be big enough to display such
+ shapefiles at reasonable zooms.
+
+ map_shp.c: change display_level in default dbfawk rule (the one
+ used when no dbfawk file is found) to have display_level=65536.
+ This means that a shapefile for which no dbfawk file is found
+ will always have all of its lines and polygons displayed at
+ almost all zoom levels, unless the user disables display of that
+ shapefile using map properties min/max zoom parameters.
+
+2004-12-26 13:13 we7u
+
+ * src/: db.c, messages.c: More tweaks to the delayed ack queue for
+ messaging. We now check for ack's that are too close together
+ time-wise in the queue and refuse to queue them up. We don't
+ want to send too many ack's all together and trash the channel.
+
+2004-12-26 10:57 tvrusso
+
+ * src/: map_shp.c, maps.c: Add facility to purge dbfawk signatures
+ on map index operation. They are reloaded upon first shapefile
+ redraw.
+
+2004-12-26 10:54 tvrusso
+
+ * src/rtree/.cvsignore: Add a .cvsignore file to the rtree
+ directory, ignore Makefile.in
+
+2004-12-26 01:10 we7u
+
+ * src/: db.c, messages.c, messages.h, main.c: Adding the capability
+ to schedule ACK's some number of seconds out. We now use this to
+ schedule ack's at t+30, t+60, and t+90 seconds if we find that
+ we're getting duplicate messages from a station we're conversing
+ with.
+
+2004-12-25 18:15 we7u
+
+ * src/: db.c, bulletin_gui.c: Fixing bulletins so that they don't
+ pop up unless we wish them to. Must have broken that recently
+ with some other changes.
+
+2004-12-24 15:28 we7u
+
+ * src/db.c: Making the Send Message window update when we get an
+ ACK.
+
+2004-12-24 12:27 we7u
+
+ * src/db.c: There _are_ code changes in this commit. This tweak
+ gets rid of the constantly popping-up Send Message dialogs when
+ you're doing messaging. If you start a QSO and then close the
+ dialog, it should pop up again on the FIRST ACK that you receive,
+ on a TIMEOUT of the message, or on the FIRST INSTANCE OF A NEW
+ MESSAGE from the other party.
+
+2004-12-24 12:16 we7u
+
+ * src/messages_gui.c: Added a debug message, then commented it out.
+ No code changes.
+
+2004-12-24 12:15 we7u
+
+ * src/messages.c: Comment changes. No code changes.
+
+2004-12-24 12:12 we7u
+
+ * src/messages.h: Added a comment. No code changes.
+
+2004-12-24 10:55 tvrusso
+
+ * src/: messages_gui.c, shp_hash.c: message_gui.c: add test to
+ get_path_data to make sure it never tries to use a null pointer
+ in xastir_snprintf. It is now possible for xastir to leave a
+ path null when it receives a posit or message via RF that has
+ been gated to RF from an Igate. Until that's fixed, it's
+ important not to try to dereference the null pointer.
+
+ shp_hash.c add standard xastir header comments.
+
+2004-12-24 00:50 tvrusso
+
+ * src/: hashtable_itr.c, shp_hash.c: Re-insert line I accidentally
+ deleted along with debugging cruft, comment out line that
+ declared variable only used in debugging to silence warnings.
+
+2004-12-23 23:39 tvrusso
+
+ * src/: hashtable_itr.c, hashtable_itr.h, shp_hash.c: For-sure fix
+ of segfaults in the new "decaying rtree" stuff.
+
+ Turns out that the hashtable_iterator code has some built-in
+ assumptions that we'll never actually have an empty hashtable.
+ The hashtable_iterator_value routine always dereferenced the
+ entry it pointed to, even though hashtable_iterator sets that to
+ null if the table's empty.
+
+ Rather than insert code all over the place that tests the
+ internals of the iterator structure, I've hacked on the
+ hashtable_iterator code to return null if it was asked for
+ nonsense, and tests for null pointers before dereferencing.
+
+ Also, the hashtable_itr.h file defined inline versions of the
+ hashtable_iterator_key and hashtable_iterator_value functions
+ even though hashtable_iterator.c defined them as regular
+ functions. This was a source of much additional baldness when
+ trying to debug until I realized it. Ifdef'd those out.
+
+2004-12-23 23:19 we7u
+
+ * src/db.c: Getting rid of the multiple audio alerts or speech
+ alerts upon receipt of a message. Should only alert on the first
+ copy of each now.
+
+2004-12-23 21:51 we7u
+
+ * src/: messages.h, messages_gui.c: In the Send Message dialog:
+ Moving the reverse path test into its own uneditable text field.
+ It is too problematic trying to use it by default for messaging,
+ but it's a useful reference for choosing the outgoing custom path
+ for the QSO.
+
+2004-12-23 21:48 we7u
+
+ * README.win32: Munging the e-mail addresses so that spammers have
+ to work harder to pick them up.
+
+2004-12-23 20:26 we7u
+
+ * README.win32: Updating the CD & Network install blurbs at the
+ top.
+
+2004-12-23 10:49 we7u
+
+ * src/map_cache.c: Tweaks by Dan Brown, N8YSZ.
+
+2004-12-23 07:57 tvrusso
+
+ * src/: map_shp.c, shp_hash.c: Add check for hashtable iterator
+ being null before using it. If we've been idle for a long time
+ then it could be the case that the entire hashtable's been purged
+ and so this test is necessary. I think this was the source of
+ the segfaults I saw over the past couple of days after several
+ hours of unattended operation.
+
+2004-12-22 23:54 we7u
+
+ * src/view_message_gui.c: Changing the format of messages in the
+ View->Message Traffic window to single-line format, unless the
+ line is long in which case it wraps.
+
+2004-12-22 19:09 tvrusso
+
+ * src/map_shp.c: Fix for a logic mistake I introduced last night.
+
+ This might be the source of the unpredictable segfaults I'm
+ seeing at random times hours apart. If not, I'll get that one
+ pinned down ASAP. This was still a mistake, even if it's not the
+ source of those.
+
+2004-12-22 14:56 we7u
+
+ * src/: database.h, db.c, main.c, main.h: Fixing selected station
+ count so that it updates immediately on the status line if the
+ number changes. Change the "stations" variable to
+ "station_count" to make it easier to grep for in the future.
+
+2004-12-22 14:49 we7u
+
+ * src/interface_gui.c: Fixing Interface Control dialog so that it
+ looks the same after properties have been changed. It had been
+ missing the up/down designation per port.
+
+2004-12-22 10:07 we7u
+
+ * src/: main.c, main.h, db.c: Making the selected stations count on
+ the status line update quickly when it changes.
+
+2004-12-22 08:44 we7u
+
+ * src/main.c: Fixing the Select All button in Map
+ Chooser->Properties so that it doesn't toggle the selections, but
+ actually does what its label says it'll do.
+
+2004-12-21 23:18 we7u
+
+ * src/db.c: Changes to Group Messages/Queries so that multi-line
+ messages will show in the dialog, and so that messages that don't
+ require ack's don't show up as unacked (highlighted) in the
+ dialog.
+
+2004-12-21 22:48 tvrusso
+
+ * src/rtree/node.c: Clean up debugging output mistakenly committed.
+
+2004-12-21 22:22 tvrusso
+
+ * src/: main.c, map_shp.c, maps.c, maps.h, shp_hash.c, shp_hash.h,
+ rtree/node.c: Round of RTree usage optimizations.
+
+ 1) If a shapefile's bounding box is entirely contained in the
+ current viewport, don't bother doing an RTreeSearch for
+ visible shapes --- just read the file sequentially. Don't
+ even bother accessing the hash table for the file.
+
+ 2) Store a time stamp every time a shapefiles hash table entry is
+ accessed.
+
+ 3) Every hour, walk through the hash table and purge records that
+ have not been accessed in 1 hour. (this needs to become a
+ configurable time)
+
+ This should improve memory usage for a few special use cases, and
+ free up RAM wasted on shapefiles that are not really going to
+ benefit from having the RTree fast lookup.
+
+ I've not run this for long times to see how the memory usage
+ behaves --- once the RTree is allocated and freed, the processes
+ resident size doesn't seem to drop down, but it does make the
+ space that was freed available for indexing a different
+ shapefile.
+
+ There are probably many ways to make this even more flexible and
+ automatically adaptive to the users' usage patterns. This should
+ be a good start, though.
+
+2004-12-21 21:08 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.h, src/main.c:
+ The ST_DIRECT stuff appears to be fixed now. This tweak makes
+ the APRS-Direct query work properly again plus adds a
+ selected/total stations display to the status line where there
+ was just total stations listed before.
+
+2004-12-21 19:23 we7u
+
+ * src/db.c: Another tweak to the ST_DIRECT stuff. This tweak
+ causes us to overwrite the saved path only if 1) the current
+ packet is direct, 2) the ST_DIRECT path is not set, or 3)
+ ST_DIRECT is set but nothing has been heard direct for the last
+ hour. The end result is that we should see the most recent
+ directly-heard path in Station Info, unless the station has not
+ been heard direct for the last hour, in which case we may see a
+ digipeated path or an INET path there.
+
+2004-12-21 17:35 we7u
+
+ * src/db.c: More work on fixing up the ST_DIRECT flag.
+
+2004-12-21 12:29 we7u
+
+ * src/: database.h, db.c: Attempting a fix to the ST_DIRECT bit
+ being set incorrectly at times, for stations that straddle both
+ RF and INET feeds. Lots of things were inter-related here, so
+ this may not be the final fix. It should be better than the old
+ code though.
+
+2004-12-20 17:58 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface_gui.c, src/main.c,
+ src/messages.c: Combining the two Interface dialogs into one
+ dialog. Fixing the Map Chooser->Properties dialog so that it
+ keeps the selected list each time you change something.
+
+2004-12-20 14:14 tvrusso
+
+ * src/: map_shp.c, shp_hash.c, rtree/index.c, rtree/index.h,
+ rtree/node.c, rtree/split_l.c: Give GCC fewer things to whine
+ about.
+
+ In each case here where gcc whined about possible use of
+ variables before initialization, code was in place that would
+ always set that variable first. But it was all in conditionals
+ that gcc couldn't possibly know were always true before any use
+ of the variables. Added initializers to shut it up.
+
+2004-12-19 21:39 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/messages_gui.c: Fixing transmit
+ of messags so that the three illegal chars (per the spec) cannot
+ be transmitted. We now substitute '.' for any of those three,
+ then alert the operator that we've done so via a popup message.
+
+2004-12-19 18:56 we7u
+
+ * src/db.c: Added code to check for incorrect case in queries and
+ notify us. This may be used to send a message back to the
+ originator asking them to please follow the APRS spec, or the
+ messages may be ignored. They go to STDERR currently. The same
+ code was added to the unimplemented query sections, but commented
+ out.
+
+2004-12-19 00:44 we7u
+
+ * src/db.c: Fixing the Station Info dialog so that it will display
+ stations in the Station Chooser dialog +/- 20 pixels in either
+ direction from the mouse pointer.
+
+2004-12-18 17:08 we7u
+
+ * src/x_spider.c: Adding some returns in the case of a few socket &
+ pipe errors, to get the process to close and not waste CPU on
+ Cygwin.
+
+2004-12-18 13:06 tvrusso
+
+ * configure.ac, src/Makefile.am: Change configure and makefiles so
+ that if the user does not ask for rtree, the library isn't even
+ built and the -L/-l options aren't used.
+
+ Not doing this before was just laziness on my part.
+
+2004-12-18 12:43 tvrusso
+
+ * src/rtree/Makefile.in: Removing something that should not have
+ been committed --- Makefile.in is supposed to be created by
+ bootstrap.
+
+2004-12-18 12:29 tvrusso
+
+ * src/rtree/sources.htm: Fix up pointers to original source code
+ location and author's web site.
+
+2004-12-17 23:51 we7u
+
+ * src/shp_hash.c: Fixing up some #ifdef's for the shapefil.h
+ include.
+
+2004-12-17 17:58 we7u
+
+ * src/x_spider.c: Changing some error messages.
+
+2004-12-17 04:15 tvrusso
+
+ * configure.ac, src/Makefile.am, src/map_shp.c, src/maps.c,
+ src/maps.h, src/shp_hash.c, src/shp_hash.h,
+ src/rtree/Makefile.am, src/rtree/Makefile.in, src/rtree/card.c,
+ src/rtree/card.h, src/rtree/gammavol.c, src/rtree/index.c,
+ src/rtree/index.h, src/rtree/node.c, src/rtree/rect.c,
+ src/rtree/sources.htm, src/rtree/sphvol.c, src/rtree/split_l.c,
+ src/rtree/split_l.h, src/rtree/split_q.c, src/rtree/split_q.h:
+ Experimental "RTree" spatial indexing feature.
+
+ To enable, use "--with-rtree" in configure.
+
+ Current implementation is very memory intensive, but speeds up
+ rendering of large shapefiles. Needs further work.
+
+ without the "--with-rtree" option the code behaves as before, all
+ changes are ifdef'd out.
+
+2004-12-16 20:36 we7u
+
+ * src/x_spider.c: Added a couple of test for a closed pipe or
+ socket. Trying to solve an x_spider problem on Cygwin where we
+ get error messages at the server's STDERR when a client
+ disconnects.
+
+2004-12-16 12:40 tvrusso
+
+ * src/db.c: Exclude own station from "DIRECTS" reply to APRSD
+ query.
+
+2004-12-15 22:01 tvrusso
+
+ * src/testawk.c: Minor tweaks to README.MAPS
+
+ Change testawk.c to remove a feature that uses command line args
+ as a dbfawk program literal --- this is why usages like testawk
+ foo.dbfawk foo.bar (a likely guess at usage) lead to segfaults
+ instead of helpful messages. Change usage string to reflect
+ reality.
+
+ I hope nobody really used that feature, but it doesn't seem
+ likely, and it was definitely the case that the segfaults were
+ confusing users.
+
+2004-12-15 21:29 tvrusso
+
+ * README.MAPS, src/db.c: README.MAPS: add a little explanation of
+ how to use testawk (which has the habit of segfaulting on
+ commandlines it doesn't understand)
+
+ db.c: An attempt to make APRSD (Direct Station Query) responses
+ not be limited to a single line when there are too many direct
+ stations to fit on that line.
+
+ I have not been able to test the db.c change yet, as I can't hear
+ more than 5 stations directly, so I have to commit this and wait
+ till my partner in crime in Albuquerque can get this update,
+ rebuild xastir, and run long enough to hear a few dozen direct
+ stations so I can query him.
+
+2004-12-15 13:58 tvrusso
+
+ * config/Makefile.am: Add 24kgrid.dbfawk to list of things to
+ install.
+
+2004-12-15 09:56 tvrusso
+
+ * config/24kgrid.dbfawk: Adding dbfawk for the 24kgrid shapefile
+ from geocomm.com.
+
+2004-12-15 09:03 we7u
+
+ * README.MAPS: Added a pointer to the Canadian shapefile street
+ maps.
+
+2004-12-14 20:30 we7u
+
+ * src/map_tiger.c: Moving the "Loading..." message to below where
+ the variable is initialized which it uses to print.
+
+2004-12-14 13:26 we7u
+
+ * README.MAPS: Making the IMAGESIZE line requirements more
+ noticeable.
+
+2004-12-14 12:17 we7u
+
+ * src/: database.h, db.c, main.c: Adding interface numbers to the
+ Incoming Data dialog. "sp" for packet received on the server
+ port (port 2023), 1 or 2-digit numbers for anything else.
+
+2004-12-14 11:39 we7u
+
+ * src/interface.c: Fixing the double-header problem for packets
+ heading out port 2023. Hopefully this is the last of it.
+
+2004-12-14 08:01 we7u
+
+ * src/interface_gui.c: Fix to prevent bringing up an interface upon
+ changing its properties. Fix by Dan Brown, n8ysz.
+
+2004-12-12 19:19 tvrusso
+
+ * src/db.c: Change to look for message ID after *final* "{" in a
+ message rather than first. This improves interoperability with
+ UI-View, which will ack a malformed message like:
+ KB7ZVA-1>APU25N,TCPIP*,qAC,KB7ZVA-1::KM5VY :{Duh{76 (the first
+ { is technically illegal) by acking message 76, whereas prior to
+ this commit xastir would see the message ID as "Duh{7" and do:
+ KM5VY>APX142,TCPIP*::KB7ZVA-1 :ackDuh{7 causing UI-View to ack
+ message 7, and assorted other nonsense.
+
+ Tested only by having one instance of xastir send a malformed
+ message to another and seeing the ack of the real message ID.
+
+2004-12-12 14:21 tvrusso
+
+ * config/tgr2shppoly.dbfawk, src/map_shp.c: Make polygon draws
+ respect the "skip_it" step --- until now it was not possible to
+ use the dbfawk variable "display_level" to shut off drawing
+ specific polygons at large zooms. Don't know why I hadn't
+ noticed that all that wasn't working.
+
+ Now that they're being paid attention to, had to tweak all the
+ display_levels in tgr2shppoly.dbfawk so things show up at
+ reasonable levels.
+
+2004-12-09 18:35 we7u
+
+ * configure.ac: Fixing the comment so that it is accurate.
+
+2004-12-09 18:32 we7u
+
+ * configure.ac: Adding a case statement for Cygwin that will change
+ "-O2" compiler flags to " ". This should speed up Cygwin
+ compiling a great deal, at the expense of slightly larger, more
+ inefficent executables.
+
+2004-12-09 12:27 we7u
+
+ * INSTALL, README.Getting-Started, configure.ac, update-xastir:
+ Making --without-errorpopups be the default. Must add
+ "--with-errorpopups" in order to get the previous operation now.
+ Added some code to configure.ac to remove the "-g" compiler
+ option, so we'll get stripped executables by default now.
+
+2004-12-08 08:57 we7u
+
+ * src/: gps.c, interface_gui.c: Disabling the time-set togglebutton
+ when running Cygwin.
+
+2004-12-08 06:58 we7u
+
+ * src/main.c: Finally, a fix for the keyboard modifiers problem,
+ where any modifiers enabled will mess up the mouse menus. The
+ problem turned out to be a Motif 2.x function that doesn't work
+ properly with modifiers. Switching to the Motif 1.x function
+ that accomplishes the same thing fixed it.
+
+2004-12-07 21:45 we7u
+
+ * src/: map_geo.c, map_tiger.c, util.c: Conditionally compiling
+ various libcurl calls into the code based on libcurl version.
+
+2004-12-07 11:39 we7u
+
+ * src/: map_geo.c, map_tiger.c, util.c: Adding some currently
+ unused options for libcurl. These are options that were added
+ recently, so only some libcurl versions have them. They have to
+ do with ftp and http proxying.
+
+2004-12-07 10:48 we7u
+
+ * FAQ: Changed the proxy note a bit.
+
+2004-12-07 09:48 we7u
+
+ * FAQ: Added instructions for getting through and http proxy
+ server.
+
+2004-12-07 09:32 we7u
+
+ * src/: map_geo.c, map_tiger.c, util.c: Adding another libcurl
+ option so that it can read the ~/.netrc file. This is needed by
+ those using http proxy servers so they can get through the
+ firewall.
+
+2004-12-07 00:05 we7u
+
+ * src/: util.c, util.h: Added a new define to util.h so that the
+ maximum WIDE/TRACE digi's can be specified.
+
+2004-12-06 23:16 we7u
+
+ * src/util.c: Fix to allow multiple specific callsigns in path
+ without Xastir complaining about it.
+
+2004-12-06 22:01 we7u
+
+ * src/: interface.c, messages.c, view_message_gui.c: Some HP/UX
+ fixes by Dan Brown. Another fix for transmit KISS packets,
+ getting rid of 0x00 bytes between the KISS frames.
+
+2004-12-05 13:46 we7u
+
+ * scripts/Makefile.am: Added get-gnis to the list.
+
+2004-12-05 13:41 we7u
+
+ * scripts/get-gnis: Script to snag GNIS files from the download
+ site. Written by Dan Brown, N8YSZ.
+
+2004-12-05 13:20 we7u
+
+ * src/: map_cache.c, map_cache.h: More good tweaks by Dan Brown,
+ N8YSZ.
+
+2004-12-04 10:05 we7u
+
+ * README.MAPS: Added a writeup for map caching, courtesy of Dan
+ Brown, n8ysz.
+
+2004-12-04 08:56 we7u
+
+ * FAQ: Added a bit about the MAGICK_HOME variable.
+
+2004-12-04 08:49 we7u
+
+ * FAQ: Added Festival debugging info.
+
+2004-12-01 11:45 we7u
+
+ * src/: messages.c, messages_gui.c: Added some comments. Fixed
+ multi-line messages so that they appear correctly in the Send
+ Message dialog.
+
+2004-11-30 20:34 we7u
+
+ * src/: database.h, db.c, messages.c: Adding the tries counter to
+ the Send Message dialog.
+
+2004-11-30 14:59 tvrusso
+
+ * config/tgr2shppoly.dbfawk: Another really minor tweak to tiger
+ polygon shapefile colorings.
+
+ Looks like there are no easily selected (by CFCC) city boundaries
+ in the files created by Xastir_tigerpoly.py, which makes it
+ impossible to color them with the current dbfawk file. Gonna
+ have to figure that out.
+
+2004-11-30 13:23 we7u
+
+ * src/db.c: Variable-length non-highlighting for the interval timer
+ value. Lets us keep the line as short as possible yet still do
+ the highlighting in the correct place (the message text).
+
+2004-11-30 13:12 we7u
+
+ * src/: database.h, db.c, messages.c: Displaying the message timer
+ interval in the Send Message dialog for active messages.
+
+2004-11-30 12:24 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/messages.c, src/messages.h,
+ src/messages_gui.c: Updates to messenging. We can now see queued
+ messages before they get to the transmit stage. New button added
+ to kick the timer back to original values (to get a QSO going
+ again). Timer value is currently sent to STDERR, but will
+ eventually be placed into the Send Message GUI as well.
+
+2004-11-30 10:43 tvrusso
+
+ * config/tgr2shppoly.dbfawk, config/xastir.rgb, src/color.h,
+ src/main.c: changes to coloration of shapefile tiger polygons.
+ Matches online colors a little better now.
+
+2004-11-29 22:56 we7u
+
+ * src/: map_tiger.c, map_cache.c, map_cache.h: More map caching
+ mods by Dan Brown, n8ysz.
+
+2004-11-29 21:14 we7u
+
+ * src/messages.c: Getting rid of extra message transmit before
+ timeout. This causes us to transmit exactly MAX_TRIES times,
+ instead of MAX_TRIES + 1.
+
+2004-11-29 12:55 we7u
+
+ * src/: database.h, db.c, messages.c: Adding a "CANCELLED"
+ indicator to the Send Message box for those messages that made it
+ to transmit from the queue but got manually cancelled by the
+ user.
+
+2004-11-29 11:58 we7u
+
+ * src/: messages.h, messages.c: More RF-friendly decaying algorithm
+ for messages. We start at 7 seconds and double the interval each
+ time. Timeout occurs at about 2 hours if no ACK received.
+
+2004-11-29 11:37 we7u
+
+ * src/x_spider.c: Changing from LF to CRLF in lines sent to clients
+ which have connected to the server port.
+
+2004-11-28 10:03 tvrusso
+
+ * acinclude.m4: Change probe for db.h to use AC_TRY_COMPILE instead
+ of AC_CHECK_HEADER, so that we can apply the same usability test
+ that is present in map_cache.c.
+
+2004-11-27 18:56 we7u
+
+ * src/x_spider.c: Making sure that lines sent out the server port
+ have "\r\n" at the end. Before we just had '\r', which doesn't
+ correspond to the way the internet servers did it.
+
+2004-11-25 22:10 we7u
+
+ * README.win32: Completing the GDAL/OGR library instructions for
+ Cygwin.
+
+2004-11-25 17:35 we7u
+
+ * README.win32: Adding Dave Flood's comments about compiling
+ GDAL/OGR under Cygwin.
+
+2004-11-23 09:19 we7u
+
+ * scripts/inf2geo.pl: Added usage messages if invoked without
+ parameters.
+
+2004-11-22 08:59 we7u
+
+ * update-xastir: Adding timestamps and output to make.log for each
+ step.
+
+2004-11-20 22:26 we7u
+
+ * acinclude.m4: A small change to hopefully make configure find the
+ correct convert.exe on Cygwin/Windows installations.
+
+2004-11-19 22:13 we7u
+
+ * README.win32: Adding a note about documenting the system
+ variables soas to guard against changes in the future.
+
+2004-11-19 19:15 we7u
+
+ * README.win32: Adding info at the top about CD installs that are
+ available.
+
+2004-11-19 18:49 we7u
+
+ * src/: map_geo.c, map_tiger.c, util.c: Backing out a few libcurl
+ options that aren't in earlier libcurl packages.
+
+2004-11-19 11:01 we7u
+
+ * README.win32: Getting the db libraries listed properly.
+
+2004-11-19 08:26 we7u
+
+ * update-xastir: Change in a comment.
+
+2004-11-19 08:11 we7u
+
+ * README.win32: Fixing the order of the Cygwin packages.
+
+2004-11-19 07:20 we7u
+
+ * update-xastir: Tweaks for Cygwin to eliminate the "sudo" keyword
+ there.
+
+2004-11-18 16:03 we7u
+
+ * install-xastir: Changing the comments around at the end to
+ simplify things.
+
+2004-11-18 14:16 we7u
+
+ * install-xastir: Adding more comments at the end.
+
+2004-11-18 13:06 we7u
+
+ * update-xastir: Adding a couple of command-line options to the cvs
+ update command.
+
+2004-11-18 12:51 we7u
+
+ * install-xastir: A script to help in the initial install of Xastir
+ via CVS. For those folks challenged by the Unix way of doing
+ things.
+
+2004-11-18 12:29 we7u
+
+ * README.CVS, README.win32: Updating the instructions with respect
+ to the "update-xastir" script.
+
+2004-11-18 12:23 we7u
+
+ * update-xastir: Added a comment.
+
+2004-11-18 10:59 we7u
+
+ * INSTALL, README.CVS, README.win32, UPGRADE, update-xastir: Adding
+ an update-xastir script and tweaking updating instructions a bit.
+
+2004-11-17 10:48 we7u
+
+ * README: Added HP/UX instructions per Dan Brown, N8YSZ. Current
+ state of HP/UX port is: Segfaults when connected to internet
+ server, but appears to run otherwise. Not fully tested.
+
+2004-11-17 10:28 we7u
+
+ * src/main.c: Fixing up a return that shouldn't pass back a
+ parameter.
+
+2004-11-17 09:57 we7u
+
+ * src/main.c: Checking for map interrupts and returning, just
+ before each call to display_file(), which is the function which
+ draws objects/tracks.
+
+2004-11-17 09:46 we7u
+
+ * src/: map_geo.c, map_tiger.c, util.c: Adding timeouts to libcurl
+ calls. Wget calls already have them.
+
+2004-11-17 09:00 we7u
+
+ * src/map_geo.c: If ImageMagick is not found, we now refuse to load
+ a .geo map unless "xpm" is found in the filename.
+
+2004-11-17 08:11 we7u
+
+ * src/: maps.c, maps.h, map_gdal.c, map_geo.c, map_gnis.c,
+ map_pdb.c, map_shp.c, map_tif.c, map_tiger.c, map_dos.c: Setting
+ default map layers based on the type of file. Raster map = 0,
+ vector maps = 1000, GNIS = 99,999.
+
+2004-11-16 14:50 we7u
+
+ * configure.ac: Reversing the order of the map caching/Imagemagick
+ checks. Just in case. We've had trouble before where if
+ ImageMagick checks fail, they corrupt some of the settings for
+ the other checks, unless ImageMagick is the last of the bunch.
+
+2004-11-16 12:09 we7u
+
+ * FAQ: Getting rid of "localhost" on the netcat example line.
+ Redundant.
+
+2004-11-16 12:04 we7u
+
+ * FAQ: Updating the netcat info in the FAQ.
+
+2004-11-16 10:15 we7u
+
+ * README.win32: Tweaking the library install instructions per David
+ Flood.
+
+2004-11-15 21:05 we7u
+
+ * src/maps.c: Prevent a segfault when Xastir is having trouble
+ writing the map objects to file.
+
+2004-11-15 10:05 tvrusso
+
+ * acinclude.m4: Fix of fix for fix of fix of probe for db library.
+
+ Amounts to removing a comment character from a critical line that
+ I'd accidentally commented out.
+
+ Without this fix, building xastir on a machine without a db
+ library installed will fail with an error message at link stage
+ about a missing "-ldb". That's because the configure script
+ never reset the LIBS variable after the probe.
+
+2004-11-15 08:52 we7u
+
+ * src/map_cache.c: Moving more of the includes inside the #ifdef.
+ Including config.h so we get a direct answer as to whether
+ USE_MAP_CACHE is defined before we include anything else.
+
+2004-11-15 08:22 we7u
+
+ * src/map_cache.c: Moving a couple of includes below the
+ USE_MAP_CACHE #ifdef. Makes it compile on systems that don't
+ have the map caching enabled.
+
+2004-11-13 17:10 tvrusso
+
+ * acinclude.m4:
+ Handful of changes to improve probe of db for map caching.
+
+ 1) remove attempts to probe db version 3 libraries, coz the code
+ that uses db actually won't work unless the version is 4 or
+ above.
+
+ 2) make the probe stop probing when it finds a library that
+ works. Otherwise the probe keeps overwriting the "dblib"
+ variable with "no".
+
+ 3) comment out the attempt to probe for db_open if db_create
+ isn't found. That would only work if the code that uses
+ db_create were inside appropriate ifdefs, which was probably
+ the case in the package from which the autoconf macro was
+ obtained.
+
+ 4) Change the comment about "FreeBSD puts this in a weird place"
+ enough to give a reader an idea of where to look.
+
+2004-11-13 16:54 we7u
+
+ * src/map_cache.c: Moving the #ifdef below the #includes, so that
+ we have a chance of having the USE_MAP_CACHE variable be defined.
+
+2004-11-13 16:12 tvrusso
+
+ * acinclude.m4, configure.ac: A minor tweak to add "Building with
+ map caching.....: " to the list of things that are printed out at
+ the end of the configuration run.
+
+2004-11-13 06:00 tvrusso
+
+ * src/map_cache.c: Move the #endif for USE_MAP_CACHE to a place
+ where it actually takes out code that can't compile if
+ USE_MAP_CACHE isn't defined.
+
+2004-11-12 16:40 shadow
+
+ * acinclude.m4: link against the real libdb we found; use the
+ header path for it we found
+
+2004-11-12 16:17 we7u
+
+ * README.win32: Adding libdb and libdb-devel as necessary libs.
+
+2004-11-12 15:50 we7u
+
+ * INSTALL: Adding a blurb about libdb.
+
+2004-11-12 11:31 we7u
+
+ * README.win32: Added info about NTFS "convert.exe" getting run
+ instead of ImageMagick's "convert.exe". Added instructions
+ written up by Randy, KK6RW, regarding auto-starting Xastir.
+ William McKeehan, KI4HDU, contributed to those instructions and
+ was the inspiration for them.
+
+2004-11-12 10:52 we7u
+
+ * src/: map_cache.c, map_cache.h: Moving variables to the top of
+ the blocks (for the BSD guys), changing the expire time for maps
+ to 6 months instead of one hour.
+
+2004-11-12 10:47 we7u
+
+ * src/map_tiger.c: Moving the variable declaration up to the top of
+ the block before those FreeBSD guys get on my case!
+
+2004-11-12 10:24 we7u
+
+ * acinclude.m4, src/Makefile.am: The final two pieces to enable the
+ new feature, if the Berkeley DB libraries are installed and
+ usable.
+
+2004-11-12 09:17 we7u
+
+ * configure.ac: Added a comment.
+
+2004-11-12 09:10 we7u
+
+ * acinclude.m4: A tweak to add "-ldb" to the LIBS line if the DB
+ library is found.
+
+2004-11-12 09:09 we7u
+
+ * src/: map_cache.c, map_cache.h, map_tiger.c: Adding code that
+ performs caching of tigermaps, courtesy of Dan Brown, N8YSZ.
+
+2004-11-12 09:03 we7u
+
+ * src/main.c: Preliminary work to include a new map feature.
+
+2004-11-12 08:37 we7u
+
+ * INSTALL: Adding another link for a list of internet servers, plus
+ a link to the filtering syntax web page. Links courtesy of Rick
+ Green. Thanks!
+
+2004-11-11 09:19 we7u
+
+ * INSTALL: Updating the GDAL instructions somewhat.
+
+2004-11-10 11:58 we7u
+
+ * src/db.h: Removing db.h. It has been renamed as database.h.
+
+2004-11-10 11:58 shadow
+
+ * acinclude.m4, configure.ac:
+ berkeley db configure test. may need slight tweaking for which
+ function it tests for (db_open/db_create/solmething else)
+
+2004-11-10 11:58 we7u
+
+ * src/: Makefile.am, alert.h, db.c, draw_symbols.c, util.c, util.h,
+ wx.h, xastir.h: Renaming db.h to database.h in order to avoid a
+ conflict with Berkeley DB include file of the same name.
+
+2004-11-10 11:56 we7u
+
+ * src/database.h: Renaming db.h to database.h, in order to avoid a
+ potential conflict with the berkeley DB include file of the same
+ name.
+
+2004-11-05 15:07 we7u
+
+ * src/festival.c: Closing the file descriptor for the socket at the
+ point where the Festival connect fails.
+
+2004-11-05 08:57 we7u
+
+ * configure.ac: Bumping the development sources up to 1.4.2. Just
+ released 1.4.1 stable.
+
+2004-11-05 08:37 we7u
+
+ * src/: igate.c, util.c: Assuring that we don't igate packets while
+ reading tactical calls in from file.
+
+2004-11-04 12:27 we7u
+
+ * src/: db.c, igate.c, main.c: Fixing the problem where reading in
+ a log file causes the packets to be igated to the NET.
+
+2004-11-04 10:53 we7u
+
+ * src/map_gdal.c: Free'ing the hash iterators at the correct
+ points.
+
+2004-11-02 12:37 we7u
+
+ * src/: hashtable.c, hashtable_itr.c, hashtable_private.h: Tweaks
+ so that the GC_MALLOC/GC_FREE defines apply to the hashtable code
+ as well.
+
+2004-11-02 07:20 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface.c: Making the transmit
+ and Interface->Properties long-path warning messages different.
+
+2004-11-02 07:19 we7u
+
+ * src/util.c: Changing one variable so that it local to where it is
+ used instead of at the top of the routine. Changed flags to be
+ counting flags instead of booleans, so we can later use them to
+ count digipeater types. Added some comments.
+
+2004-11-01 12:34 we7u
+
+ * src/util.c: Tweaking the path-check code so that trace,wide2-2
+ and wide,wide2-2 paths and similar are allowed.
+
+2004-11-01 09:11 tvrusso
+
+ * configure.ac, src/util.c: Add probe for strndup to configure.ac.
+ Ifdef use of strndup in src/util.c.
+
+ strndup is a GNU extension and not portable to non-GNU systems.
+
+ strdup is portable, so is used if strndup isn't available.
+
+2004-10-30 14:13 we7u
+
+ * src/: interface.c, interface_gui.c: Adding path checks to the
+ igate path.
+
+2004-10-30 14:01 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Adding another
+ string for igate path checking.
+
+2004-10-30 13:23 tvrusso
+
+ * README.win32: Add note to section on installing libproj and
+ libgeotiff.
+
+ Both of these libraries are now available directly through cygwin
+ setup, simplifying the installation.
+
+2004-10-30 12:06 we7u
+
+ * src/interface.c: Adding the path check code into each posit and
+ object/item transmit, at the spot where the unproto path is
+ selected. This probably needs to be added to the igate path code
+ as well.
+
+2004-10-29 13:15 we7u
+
+ * src/interface_gui.c: Another tweak by Ryan Butler, KB0JQO, to
+ check UNPROTO paths on more types of interfaces.
+
+2004-10-29 13:00 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface_gui.c, src/util.c,
+ src/util.h: Tweaks by Ryan Butler, KB0JQO, to check the unproto
+ paths on interfaces for excessively long paths. Performs the
+ path checks when you hit the OK button on the
+ Interface->Properties dialog.
+
+2004-10-29 08:53 we7u
+
+ * src/map_gdal.c: Enabling tiger polygons for normal use. Tweaked
+ the code so that the polygon reassembly only gets done if we have
+ "filled" enabled for that map.
+
+2004-10-29 07:53 we7u
+
+ * src/map_gdal.c: Experimentally derived at better hash sizes
+ (twice the max size needed for any county in the state of WA).
+ Correct code now for free'ing the landmark hash. Sped up the
+ TLID linked list code, but still testing that to make sure the
+ polygons are made correctly (it reverses the order that the line
+ segments are added to the geometryCollection).
+
+2004-10-28 22:14 we7u
+
+ * src/map_gdal.c: More tweaks to the tiger code. Still not enabled
+ for general use.
+
+2004-10-27 10:03 we7u
+
+ * src/map_gdal.c: First working version of Tiger polygon code.
+ #ifdef'ed out of the compile at present.
+
+2004-10-27 10:02 we7u
+
+ * src/Makefile.am: Adding the hashtable files.
+
+2004-10-27 09:58 we7u
+
+ * src/: hashtable.c, hashtable.h, hashtable_itr.c, hashtable_itr.h,
+ hashtable_private.h: Adding generic hashtable functions.
+
+2004-10-26 23:24 we7u
+
+ * src/map_gdal.c: Starting to draw some filled polygons for Tiger
+ maps. Still not ready for prime-time so the code is still
+ disabled by an #ifdef.
+
+2004-10-26 22:44 we7u
+
+ * src/map_gdal.c: More Tiger polygon code changes. The code is
+ generating polygon geometries from the tiger data now, so the
+ next step is to start drawing them.
+
+2004-10-26 19:55 we7u
+
+ * src/map_gdal.c: Implementing hash functions for the Tiger polygon
+ code. Still #ifdef'ed out, so it won't get compiled in
+ currently.
+
+2004-10-23 20:38 tvrusso
+
+ * README.MAPS: Mention the Xastir_tigerpoly.py script in the place
+ where this file previously said that shapefile conversion of
+ TIGER/Line data didn't contain polygon features.
+
+2004-10-23 15:24 we7u
+
+ * src/main.c: Fixing the segfault caused by closing the Map labels
+ font dialag before closing xfontsel. Had to put in a couple of
+ "xfontsel_query = 0" statements in the callbacks for the Map
+ labels font dialog.
+
+2004-10-22 08:25 we7u
+
+ * src/map_gdal.c: Added some debug code. It's not enabled
+ currently.
+
+2004-10-21 19:54 we7u
+
+ * src/map_gdal.c: Added much of the code needed to reconstruct the
+ Tiger polygons. The new code is commented out right now as it's
+ not quite complete and it really slows things down as well.
+ Optimization will happen AFTER the code is working.
+
+2004-10-21 12:45 we7u
+
+ * src/map_gdal.c: Changed some comments.
+
+2004-10-21 12:28 we7u
+
+ * src/map_gdal.c: Changed one variable name from i to ii (easier to
+ grep for). Added some comments.
+
+2004-10-21 01:55 tvrusso
+
+ * config/tgr2shppoly.dbfawk: Don't display name of feature if it is
+ "None" (what some fields output by Xastir_tigerpoly.py get, a
+ feature inherited from tigerpoly.py -- haven't figured out why).
+
+2004-10-21 01:51 tvrusso
+
+ * config/Makefile.am, config/tgr2shppoly.dbfawk,
+ scripts/Makefile.am, scripts/Xastir_tigerpoly.py: Add python/OGR
+ script to generate polygon shapefiles from TIGER/Line data. Add
+ dbfawk file to make them look less ugly than if there weren't
+ one.
+
+ Putting this in CVS merely to get it out there for community
+ hackage.
+
+2004-10-20 21:19 we7u
+
+ * src/map_gdal.c: Added some comments.
+
+2004-10-20 14:30 we7u
+
+ * src/: geo-find.c, geocoder_gui.c: Find Address works again.
+
+2004-10-20 12:37 tvrusso
+
+ * src/map_gdal.c: Fix mid-function declarations to allow
+ compilation by gcc 2.95.
+
+2004-10-20 09:42 we7u
+
+ * src/map_gdal.c: Changes to comments only.
+
+2004-10-20 08:37 we7u
+
+ * src/map_gdal.c: More messing with water layers. Nothing major.
+
+2004-10-19 19:17 we7u
+
+ * src/map_gdal.c: Commenting out the "Loading" message.
+
+2004-10-19 18:13 we7u
+
+ * src/map_gdal.c: Shapefiles are working again in GDAL.
+
+2004-10-19 11:36 we7u
+
+ * src/map_gdal.c: More color and line tweaks. This change probably
+ disables Shapefiles, but SDTS and TIGER/Line files display
+ properly now.
+
+2004-10-19 09:02 we7u
+
+ * src/map_gdal.c: Moving all of the color code into the
+ guess_vector_attributes function. Later we'll be able to convert
+ this function into our map preferences system once that is fully
+ defined. Added color to the SDTS files.
+
+2004-10-19 07:45 we7u
+
+ * src/map_gdal.c: Faster determination of layer name.
+
+2004-10-18 22:22 we7u
+
+ * src/map_gdal.c: Starting to support proper color scheme for
+ SDTS-format maps. At least have contours in yellow and other
+ layers in black now.
+
+2004-10-18 21:08 we7u
+
+ * src/map_gdal.c: Fixing OGR indexing so that the transform is
+ invoked every time. Required for UTM/State-plane maps.
+
+2004-10-18 13:17 we7u
+
+ * src/maps.c: Changing default Shapefile translator back to
+ Shapelib.
+
+2004-10-18 13:09 we7u
+
+ * src/map_gdal.c: Truncating the points better. Was truncating at
+ 0 for negative values, which doesn't work. We just need to keep
+ away from the +16000/-16000 points and greater, which invoke X11
+ drawing bugs. Truncating at zero creates dummy lines along our
+ top and left window borders.
+
+2004-10-18 12:58 we7u
+
+ * src/map_gdal.c: Very weak attempt at detecting hypsography and
+ hydropraphy SDTS files to decide to color them yellow, keyed off
+ "HY"or "HP" anywhere in the full filename (that's why it is
+ weak). Other SDTS maps get colored black currently.
+
+2004-10-18 11:57 we7u
+
+ * src/: bulletin_gui.c, db.c, list_gui.c, main.c, main.h,
+ map_gdal.c, maps.c, util.c, view_message_gui.c, wx_gui.c,
+ xa_config.c: Changing the name of a global variable. Tweaking
+ elevation for SDTS contours so that they are in the correct
+ units.
+
+2004-10-18 09:39 we7u
+
+ * src/map_gdal.c: Outputting the correct label on elevations now
+ from SDTS files. Later will try to switch it to match the
+ setting of the Enable English Units togglebutton so that we can
+ get a consistent display.
+
+2004-10-18 07:55 we7u
+
+ * src/map_gdal.c: Added some notes. No code changes.
+
+2004-10-15 21:25 we7u
+
+ * src/map_gdal.c: Changing text from "ft" to "m" for elevation.
+ SDTS file appear to have elevation in meters. Also changing back
+ to yellow for the contour lines as it is highly visible whereas
+ the white/gray is not in many cases.
+
+2004-10-15 12:24 we7u
+
+ * src/map_gdal.c: Default coloring for raw Tiger/Line maps.
+
+2004-10-15 09:27 we7u
+
+ * src/map_gdal.c: Repositioning labels slightly. Fixing segfault
+ caused by earlier "skip" option.
+
+2004-10-15 08:36 we7u
+
+ * src/map_gdal.c: Changing to lighter colors again for contours and
+ their labels. They need to show up on top of terraserver images.
+ Brown doesn't cut it. Changed the contours to gray80 and the
+ labels to white.
+
+2004-10-15 07:56 we7u
+
+ * src/map_gdal.c: Changing to brown for the contours and
+ corresponding labels. Closer to the USGS topo map colors.
+
+2004-10-15 07:44 we7u
+
+ * src/map_gdal.c: Drawing more labels along each object. Tied to
+ zoom level so that we reduce the quantity of labels as we zoom
+ out.
+
+2004-10-15 07:22 we7u
+
+ * src/map_gdal.c: Setting a few hard-coded default colors from some
+ types of map objects. Later we'll redo this so that the
+ preferences come from a file. Re-enabled code that dumps out the
+ layer information. Added elevation display for SDTS-format DLG
+ contours.
+
+2004-10-14 21:12 we7u
+
+ * src/map_gdal.c: Several fixes. Spatial filtering now works
+ properly.
+
+2004-10-14 12:52 we7u
+
+ * src/map_gdal.c: Simplified some of the code. Have SDTS contours
+ working again, but have a problem with those files and spatial
+ filtering yet. This version works but puts out error messages to
+ STDERR with SDTS files.
+
+2004-10-13 23:05 we7u
+
+ * src/map_gdal.c: Sped up GDAL maps: Implemented the spatial
+ filtering mechanism inherent in the library. We now filter using
+ our viewport as the bounding rectangle, which really speeds
+ things up as you zoom in.
+
+2004-10-13 22:57 we7u
+
+ * src/maps.c: Fix for draw_vector function. It now rearranges the
+ bottom/top/left/right if it's called with things out of order,
+ before calling map_visible. This gets fewer vectors rejected due
+ to being off-screen/more vectors actually get drawn.
+
+2004-10-12 08:34 we7u
+
+ * src/map_gdal.c: Fixing up debug messages. Sending weather alerts
+ off to the draw_shapefile_map function for now.
+
+2004-10-11 19:11 we7u
+
+ * src/map_gdal.c: Nicer labels for OGR plus rotation.
+
+2004-10-11 13:12 we7u
+
+ * src/map_gdal.c: Slight reformatting. No code changes.
+
+2004-10-11 13:06 we7u
+
+ * src/map_gdal.c: Labels for OGR point files as well. Untested.
+
+2004-10-11 12:56 we7u
+
+ * src/map_gdal.c: Initial labels for OGR vector maps. Not colored
+ yet, not rotated, but better than nothing, which is what we had
+ before!
+
+2004-10-11 12:15 tvrusso
+
+ * src/map_tif.c: Add some error messages to the "geoTIFF file not
+ in proper format" block, so the user can see what is actually
+ wrong with the file.
+
+2004-10-11 09:27 we7u
+
+ * scripts/: toporama250k.pl, toporama50k.pl: Tweaking one comment
+ that gets written out to the .geo files.
+
+2004-10-10 12:16 tvrusso
+
+ * src/testawk.c: Fix mistake in font_size output --- make sure
+ appears on correct line.
+
+2004-10-10 12:01 tvrusso
+
+ * src/testawk.c: Add "font_size" variable to those that are read
+ and output by testawk. testawk still lags significantly behind
+ xastir in what it reads and outputs.
+
+2004-10-08 11:33 we7u
+
+ * scripts/: toporama250k.pl, toporama50k.pl: Oops. Changing
+ copyright to correct one.
+
+2004-10-08 11:31 we7u
+
+ * scripts/: toporama250k.pl, toporama50k.pl: Adding copyright and
+ licensing info.
+
+2004-10-08 11:20 we7u
+
+ * scripts/: Makefile.am, toporama250k.pl, toporama50k.pl: Scripts
+ to snag Canadian toporama map files and create .geo files for
+ them. Created mostly from code submitted by Adi Linden, VA3ADI.
+
+2004-10-07 19:15 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Making a few more
+ warnings go to popups instead of STDERR. Fixing object/item code
+ so that you can't create a new object/item that has the same name
+ as another station/object/item in the database.
+
+2004-10-07 14:43 we7u
+
+ * src/: db.c, geocoder_gui.c: Removing some white space.
+
+2004-10-07 10:16 we7u
+
+ * src/main.c: Fixing another Xt call that should have a NULL at the
+ end.
+
+2004-10-07 09:29 we7u
+
+ * src/main.c: Slightly better check_range() function. This one
+ snaps the left/right of the map to the left/right of the display
+ in most cases. Still more work to do before I'll be satisfied
+ with the operation though.
+
+2004-10-07 08:44 we7u
+
+ * src/main.c: Tweaking check_range() so that it doesn't allow us to
+ zoom out beyond the N/S poles. It will resize the Y scale factor
+ so that it fits the window perfectly N/S. More work will
+ probably be done on this function later so that we fit E/W
+ perfectly as we zoom out as well (depending on the window's
+ aspect ratio).
+
+2004-10-07 08:14 shadow
+
+ * src/: db.c, main.c: update calls to XrtVaGetValues to terminate
+ with NULL
+
+2004-10-06 22:45 we7u
+
+ * src/main.c: Minor tweak to how center/zoom is calculated. Check
+ for edge of earth now. May be more tweaks to come for this part
+ of the code.
+
+2004-10-06 22:17 we7u
+
+ * src/main.c: Tweaking a few more minor GUI things for Map View
+ object creation.
+
+2004-10-06 21:44 we7u
+
+ * src/main.c: Computes proper range now when creating Map View
+ objects.
+
+2004-10-06 20:28 we7u
+
+ * src/db.c: Fixing transmit of objects/items so that they send out
+ PHG or RNG as the first parameter in the comment field.
+
+2004-10-06 17:15 we7u
+
+ * src/main.c: Fixing the language command-line switch. Initial
+ implementation of the code for creating Map View objects (not
+ complete yet).
+
+2004-10-05 22:17 shadow
+
+ * src/awk.c: awk_find_sym can return NULL; don't assume src->type
+ is valid.
+
+2004-10-05 17:20 shadow
+
+ * config/tgr2shp.dbfawk: dd missing double-quote in FENAME default
+ case handling
+
+2004-10-05 10:11 we7u
+
+ * src/: db.c, main.c: Fixing the Move Object function so that we
+ can only move objects that we already own. Any SSID will work.
+ If we don't own it, we have to adopt the object first before we
+ can move it. This keeps us from accidentally moving objects if
+ we accidentally leave the Move function on and then click/drag on
+ the map display.
+
+2004-10-05 08:54 we7u
+
+ * Makefile.am: Adding a new Texas radar geo file.
+
+2004-10-05 08:54 we7u
+
+ * TXRadar.geo: Adding a new geo file for Texas radar, contributed
+ by Gerry Creager.
+
+2004-10-04 22:12 we7u
+
+ * src/db.c: Fixing a typo in extract_powergain_range() which caused
+ it to skip parsing PHG strings.
+
+2004-10-04 13:20 we7u
+
+ * FAQ: Adding another link for the remote serial port stuff.
+
+2004-10-04 12:58 we7u
+
+ * src/db.c: Reducing the number of positions displayed in Station
+ Info from 100 to 50. This is in order to speed up the automatic
+ updates version of the Station Info dialog.
+
+2004-10-04 12:25 we7u
+
+ * FAQ: Adding links to the serial port redirectory programs,
+ courtesy of Mike Fenske.
+
+2004-10-04 10:17 we7u
+
+ * src/wx.c: Fixing the 000/360 wind course problem. We should now
+ transmit "360" when the wind direction is 0, as the APRS spec
+ requires.
+
+2004-10-04 10:16 we7u
+
+ * README.CVS: Adding a note about the "wheel" group and sudo.
+
+2004-10-04 09:20 we7u
+
+ * FAQ: Adding info regarding connecting to remote serial ports.
+
+2004-10-04 09:17 we7u
+
+ * README.MAPS: Adding a link to the national transportation atlas
+ map files, link provided by Derrick J Brashear.
+
+2004-10-04 08:32 we7u
+
+ * src/xa_config.c: Changing default fonts to be non-italic. A bit
+ more readable.
+
+2004-10-03 12:46 we7u
+
+ * configure.ac: Small tweak to avoid a conflict with a
+ similarly-named define in the GDAL library.
+
+2004-10-03 00:04 we7u
+
+ * src/testawk.c: Giving up on this file for now in terms of
+ compiling with strict error-checking.
+
+2004-10-02 23:17 we7u
+
+ * src/interface.c: Fixing a few more problems that were found by
+ compiling with strict error-checking.
+
+2004-10-02 22:43 we7u
+
+ * src/: interface.c, testawk.c, x_spider.c: More tweaks from
+ compiling with stronger error-checking.
+
+2004-10-02 22:19 we7u
+
+ * src/main.c: Fixing up a few things found by running with these
+ compile flags: "-g -O2 -pipe -Wall -pthread -Wpointer-arith -W
+ -pedantic"
+
+2004-10-02 21:58 we7u
+
+ * src/: db.c, draw_symbols.c, geo-find.c, hostname.c, map_shp.c,
+ map_tif.c, maps.c, util.c, wx.c, x_spider.c: Fixing up a few
+ things found by running with these compile flags: "-g -O2 -pipe
+ -Wall -pthread -Wpointer-arith -W -pedantic"
+
+2004-10-02 11:08 we7u
+
+ * src/: draw_symbols.c, locate_gui.c, maps.c, messages_gui.c,
+ testawk.c, xastir.h, main.c: Tweaks to get rid of compiler
+ warnings on 64-bit CPU's. Fixing up mostly casts to/from
+ pointers and int's using some macros from the FreeCIV project to
+ help us.
+
+2004-10-01 09:19 we7u
+
+ * README.CVS: Adding "sudo" instructions.
+
+2004-09-29 09:04 tvrusso
+
+ * src/map_shp.c: Repair broken stippling of filled polygons under
+ dbfawk.
+
+ Before this commit, stippling was set too early in the code and
+ not turned off before label drawing began, rendering map labels
+ for stippled polygons unreadable.
+
+2004-09-29 00:10 tvrusso
+
+ * README.MAPS, src/map_shp.c: Add "fill_stipple" dbfawk variable,
+ and support for it.
+
+ Now, if a dbfawk file sets filled=1, fill_style=2, and
+ fill_stipple={0,1,2}, the filled polygons will be stippled
+ instead of solid.
+
+ fill_stipple=0 gives 13% stipple fill_stipple=1 gives 25% stipple
+ fill_stipple=2 gives 50% stipple.
+
+ "fill_style=2" corresponds to FillStippled per XSetFillStyle.
+
+2004-09-28 14:53 gstueve
+
+ * src/messages.c: Add check for DOS EOL markup.
+
+2004-09-28 11:01 we7u
+
+ * FAQ: Added a bit about NumLock/ScrollLock/CapsLock messing up
+ Motif programs, and one way to solve it.
+
+2004-09-28 08:40 we7u
+
+ * src/db.c: Fixing Station Chooser dialog so that it expands
+ properly. It used to increase the size of the buttons instead of
+ increasing the size of the station window.
+
+2004-09-27 09:49 tvrusso
+
+ * FAQ: Add FAQ entries for autoconf-related FAQs.
+
+2004-09-27 08:04 tvrusso
+
+ * Makefile.am: Return "dist-bzip2" to the AUTOMAKE_OPTIONS
+ variable.
+
+ it is true that --dist-bzip2 is not a valid automake option, but
+ the AUTOMAKE_OPTIONS variable doesn't generate --options for
+ automake, it has an effect on the generated makefile itself. In
+ this case, dist-bzip2 adds a dist-bzip2 target to the makefile.
+
+ As far as I can tell, the folks who are having trouble with this
+ option are not in fact using automake 1.6.3 or later. In ha2vr's
+ case it turned out he was actually using automake 1.4, even
+ though automake 1.9 was supposedly installed on his system.
+
+2004-09-26 17:29 tvrusso
+
+ * Makefile.am, acinclude.m4, bootstrap.sh: Per discussions on
+ xastir mailing list:
+
+ - remove "dist-bzip2" from "AUTOMAKE_OPTIONS" in Makefile.am.
+ - Fix underquoted AC_DEFUN of AC_CHECK_GMTOFF
+
+ Also, add a print statement to end of "bootstrap.sh" so it's
+ clear when it's finished successfully.
+
+2004-09-24 14:16 we7u
+
+ * src/wx.c: Fixing the offsets and data length for the Peet
+ Complete-mode wind speed fields.
+
+2004-09-24 12:42 we7u
+
+ * src/main.c: Commenting out some debug code.
+
+2004-09-24 12:42 we7u
+
+ * src/util.c: Removing some dead code from the compressed posit
+ routine.
+
+2004-09-24 12:35 we7u
+
+ * src/db.c: Fixing symbol drawing so that Map View objects "range"
+ circles aren't drawn. Fixing compressed posits so that csT bytes
+ are always removed when decoding. Adding "Current Range:" output
+ to Station Info dialog.
+
+2004-09-24 12:32 we7u
+
+ * src/draw_symbols.c: Reducing the size of the wind barbs as we
+ zoom out.
+
+2004-09-24 12:30 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Added range output
+ to Station Info dialog. Added missing tactical call string to
+ some language files.
+
+2004-09-24 09:49 tvrusso
+
+ * src/db.h: Remove DOS line terminators. Reformat long lines.
+
+2004-09-23 20:29 we7u
+
+ * src/: db.c, main.c, main.h: This change implements decoding for
+ Map View "eyeball" objects.
+
+2004-09-22 13:00 we7u
+
+ * src/main.c: Adding a bit more output to the "time has reversed"
+ fprintf's. We now dump out the number of seconds we went
+ backwards and the date/time of the event.
+
+2004-09-22 12:25 we7u
+
+ * README.CVS: Added a note about autoconf and automake.
+
+2004-09-20 12:15 we7u
+
+ * src/x_spider.c: Another tweak to allow multiple spaces between
+ "pass" and the passcode.
+
+2004-09-20 12:10 we7u
+
+ * src/x_spider.c: Fixing user/pass login in the Server code so that
+ both of them are position-independent.
+
+2004-09-19 19:29 tvrusso
+
+ * src/main.c: Add the base file name to the dbfawk file for
+ downloaded GPS tracks and routes. This allows the name of the
+ track to be displayed along with the line data when these files
+ are used outside of the GPS directory.
+
+ I forgot to add this component of the data in in my first commit.
+
+2004-09-19 16:52 tvrusso
+
+ * README.MAPS: A little cleanup of the discussion involving
+ "gdalwarp."
+
+2004-09-19 16:39 tvrusso
+
+ * README.MAPS, src/map_tif.c: This is a patch I've been using for
+ several months now: it allows xastir to use geotiff files that
+ are already unprojected lat/lon maps. It simply checks the "PCS"
+ key in the geotif file, and if it's not there then the file is
+ assumed to be in lat/lon and can be used as is without
+ transformation.
+
+ It has no effect on maps that are not already in lat/lon, and so
+ will be invisible to anyone who hasn't needed the ability to read
+ in unprojected geotiff files.
+
+ README.MAPS updated to explain that gdalwarp can be used to
+ convert maps into lat/lon unprojected maps. Also added a place
+ to find useful geotiff maps that need such conversion (FAA
+ sectionals from aviationtoolbox.org).
+
+ Tweaked the stuff on shapefile reprojection. What was there were
+ verbose snippets from an email exchange between Curt and me.
+ Made them a bit shorter and more to-the-point.
+
+ The importing of lat/lon geotiff files is significantly slower
+ than the importing of USGS quads, because the optimized reads
+ that skip over scanlines based on zoom level don't work. I
+ intended to figure out how to make them work, but never did the
+ work. If folks start using this a lot and get me to bump it up
+ in priority I can revisit it.
+
+2004-09-19 15:50 tvrusso
+
+ * config/Makefile.am, config/gps_wpt.dbfawk, src/main.c: config:
+ New DBFAWK file for waypoints files downloaded through GPSMan.
+ Now, DBFAWK- enabled xastir will display names of waypoints next
+ to the symbol, no matter what directory they're put in.
+
+ Add gps_wpt.dbfawk file to makefile.
+
+ src: make xastir write out a simple dbfawk file to go along with
+ GPSMan track and route shapefiles. Prior to this, these files
+ would only display in the selected color if they were copied
+ into /usr/local/share/xastir/maps/GPS, and would display in all
+ black if they were anywhere else.
+
+ Unfortunately, because we have no control over the fields created
+ by GPSMan for these shapefiles, it is not possible to stick the
+ color itself into the dbf file, as Alan had suggested in various
+ comments in the code.
+
+ To use these new things: for waypoints, do nothing -- the
+ dbfawk file is generic and applies to any GPSMan waypoint file.
+
+ For tracks and routes: Make sure to copy the dbfawk file when
+ you copy the
+ shapefile and dbf file to a maps directory. Xastir will use
+ it.
+
+ For tracks and routes downloaded prior to this patch: the
+ dbfawk file is
+ simple, just copy one for a map of the same color.
+
+2004-09-18 13:30 we7u
+
+ * src/map_shp.c: Fixing the "Loading" and "Indexing" messages so
+ that they don't overrun our limited real estate on the status
+ line.
+
+2004-09-18 13:25 we7u
+
+ * src/: map_dos.c, map_geo.c, map_gnis.c, map_pdb.c, map_tif.c,
+ map_tiger.c: Fixing the "Loading" and "Indexing" messages during
+ map activity so that they don't overrun our limited real estate
+ on the status line.
+
+2004-09-17 13:44 we7u
+
+ * src/interface.c: Increasing the wait time in the loop where we're
+ connecting up network interfaces. Was 20ms, now 250ms.
+
+2004-09-17 12:56 we7u
+
+ * src/: fcc_data.c, geocoder_gui.c, locate_gui.c, location_gui.c,
+ map_gnis.c, rac_data.c, track_gui.c: Bypassing the new configure
+ flag with a few more popups that are user-requested.
+
+2004-09-17 12:46 we7u
+
+ * src/: main.c, popup_gui.c, xastir.h: Tweaks so that a few of the
+ popups will continue to display in that manner (instead of
+ heading to STDERR).
+
+2004-09-17 12:22 we7u
+
+ * INSTALL, README.Getting-Started, acinclude.m4, configure.ac,
+ src/popup_gui.c: Implementing the "--without-errorpopups"
+ configure flag. If invoked, popup_messages() writes to STDERR
+ instead of causing a popup dialog to appear.
+
+2004-09-17 10:12 tvrusso
+
+ * src/main.c: Put Cygwin-specific setting of nexttime into the
+ UpdateTime function.
+
+ Remove the two Cygwin-specific usleep(2) from the end of
+ UpdateTime.
+
+ With these changes, running xastir on Cygwin under Win2K on a
+ 2GHz machine went from taking up 90+% of the CPU to taking around
+ 20% --- most of that in system processes, and mostly that high
+ when X events are being processed.
+
+2004-09-16 12:31 we7u
+
+ * configure.ac: Bumping the revision to 1.4.1, as we just did a
+ stable release at 1.4.0.
+
+2004-09-16 07:47 we7u
+
+ * src/xa_config.c: Changing default sound command from "vplay" to
+ "play" as it is much more common.
+
+2004-09-16 07:00 tvrusso
+
+ * src/map_gnis.c: Quick, trivial commit both to make sure I'm set
+ up right and to remove a slightly annoying error message when I'm
+ looking at New Mexico with GNIS: Add "ruin" as a recognized gnis
+ entry type.
+
+ Ideally, this mapping of gnis entries to zoom level limits should
+ be in metadata rather than a large if/elseif/elseif... block, but
+ that's another issue.
+
+2004-09-15 13:19 we7u
+
+ * src/db.c: Re-ordering "if" statements to speed things up
+ slightly.
+
+2004-09-15 12:59 we7u
+
+ * src/db.c: Another speedup (lower CPU usage).
+
+2004-09-15 12:44 we7u
+
+ * src/alert.c: Reducing CPU usage of normal_title().
+
+2004-09-15 12:43 we7u
+
+ * src/db.h: Slowing down minimum object timing by another five
+ seconds. Reduces how often we look through our database, keeping
+ CPU usage down.
+
+2004-09-15 10:08 we7u
+
+ * src/db.c: Swapping two "if" statements in a loop, as the
+ is_my_call() function appears to be faster than the boolean
+ operations to determine whether it's an object/item.
+
+2004-09-14 12:32 we7u
+
+ * src/db.c: Making is_my_call() and
+ check_and_transmit_objects_items() more efficient. Found during
+ profiling that these routines were eating up CPU.
+
+2004-09-13 19:50 we7u
+
+ * INSTALL, configure.ac: Adding the "--with-profiling" flag.
+ Updating docs to reflect it.
+
+2004-09-13 12:56 we7u
+
+ * src/map_shp.c: Changing label storage to a hash table instead of
+ an array, to speed things up. Using the first character of the
+ string as the hash index. Tried using lower 7 bits of first two
+ chars, and lower 6 bits of first two chars: Profiling showed that
+ using the first character was faster.
+
+2004-09-13 12:54 we7u
+
+ * src/rotated.c: Moving math into appropriate parts of loop to
+ speed it up. Anything that is static through all iterations of a
+ loop is moved outside that loop for speed.
+
+2004-09-10 16:09 we7u
+
+ * src/draw_symbols.c: Implementing a cache for the most recent five
+ symbols used. Speeds up drawing by quite a bit (found by
+ profiling).
+
+2004-09-10 12:26 we7u
+
+ * src/main.c: More speedups found by profiling. Checking for new
+ gps map only once per second now, updating the stations count on
+ the status line once per second instead of continuously.
+
+2004-09-10 09:19 we7u
+
+ * src/main.c: Adding some Cygwin-specific usleep's in UpdateTime()
+ in order to reduce CPU usage on those systems.
+
+2004-09-10 08:49 we7u
+
+ * src/awk.c: Sped up awk_find_sym() a bit.
+
+2004-09-10 08:37 we7u
+
+ * src/rotated.c: Sped up font rotation by moving some
+ floating-point math outside the inner loop.
+
+2004-09-10 08:27 we7u
+
+ * src/alert.c: Fixing a minor compiler warning.
+
+2004-09-09 20:37 we7u
+
+ * src/maps.c: Fixing a bug I introduced earlier today while
+ speeding up map indexing.
+
+2004-09-09 12:59 we7u
+
+ * src/maps.c: Speeding up the maps.c:index_retrieve() function.
+ Making it more efficient. Perhaps the next step would be to turn
+ it into a hash lookup, but that would require changing perhaps
+ several other routines to match.
+
+2004-09-09 09:11 we7u
+
+ * README.Getting-Started: Adding another note about callpass.
+
+2004-09-09 08:06 we7u
+
+ * INSTALL: Adding another note to the profiling section.
+
+2004-09-08 20:43 we7u
+
+ * src/alert.c: Major speedup in weather alert code, found through
+ profiling.
+
+2004-09-08 12:22 we7u
+
+ * INSTALL: Adding a section on checking for memory leaks.
+
+2004-09-08 10:48 we7u
+
+ * INSTALL: Adding profiling instructions.
+
+2004-09-07 14:40 we7u
+
+ * FAQ: Added a bit about MacOSX USB adapters, courtesy of Jeff
+ Wigal, WY7Q.
+
+2004-09-07 14:06 we7u
+
+ * src/util.c: Changing format for time so that Cygwin can
+ understand more of it. Tweak courtesy of Henk de Groot.
+
+2004-09-07 10:15 we7u
+
+ * README.Getting-Started, README.win32: Tweaking the notes about
+ GPSMan/gpsmanshp.
+
+2004-09-07 08:39 we7u
+
+ * src/festival.c: Adding some usleep() function calls for the case
+ where we can't open a socket to Festival, so that we don't spin
+ our wheels too fast trying to open sockets.
+
+2004-09-06 21:06 rzg
+
+ * help/help-English.dat: Done the body, just "whats new" section
+ left.
+
+2004-09-06 18:44 we7u
+
+ * src/main.c: Fixes for the Filled and Automaps columns in Map
+ Chooser->Properties dialog.
+
+2004-09-04 23:24 rzg
+
+ * help/help-English.dat: Updating helpfile some more, still have
+ last 1/3rd to go over and "whats new" section to write. FIXMEs up
+ for grabs; and if anyone otherwise wants to help let me know.
+
+2004-09-03 08:16 we7u
+
+ * src/db.c: Drawing symbol after we draw circles and other items.
+ Trying to keep the text on top so that it is more readable.
+
+2004-09-02 22:37 we7u
+
+ * src/db.c: Moving the weather info to the top of the Station Info
+ dialog, for the cases where we have weather info stored. The
+ weather info is the most important info for that station in that
+ case, so it should be readable without scrolling. Stations
+ without weather data are unaffected by this change.
+
+2004-09-02 20:19 we7u
+
+ * src/db.c: Fixed a small bug in positionless weather decoding
+ where it wasn't decoding course/speed fields. We now take
+ another look for course/speed if either of them are empty.
+ Before both of them had to be empty before we tried another type
+ of parsing for them. Did the and->or conversion in several
+ places in extract_weather(), so the change affects more than just
+ positionless weather packets.
+
+2004-09-02 13:58 we7u
+
+ * config/language-Dutch.sys: Another tweak from Henk & Han.
+
+2004-09-02 11:36 we7u
+
+ * config/language-Dutch.sys: More mods by Henk.
+
+2004-09-02 10:51 we7u
+
+ * FAQ: Updating the locale-specific answers.
+
+2004-09-02 10:45 we7u
+
+ * src/main.c: Fixing the locale for numbers to "C". We require
+ this in order to be able to write and parse our config files and
+ .geo files properly when the LC_NUMERIC or LANG environment
+ variables are set to something else. This affects the printf and
+ scanf sorts of functions.
+
+2004-09-02 07:49 we7u
+
+ * src/: main.c, xa_config.c: Bumping the max timeout for tigermaps
+ from 120 to 180 seconds since so many people are getting timeouts
+ with it.
+
+2004-09-01 12:34 we7u
+
+ * config/language-Dutch.sys: Updates by Han Sytsma, PE1FAM, and
+ Henk de Groot, PE1DNN. Thanks!
+
+2004-09-01 10:51 we7u
+
+ * README.Getting-Started, configure.ac: Bumping to the next release
+ number, 1.4.
+
+2004-09-01 08:37 we7u
+
+ * config/language-Spanish.sys: A few translations by Charles
+ Twardy. Thanks!
+
+2004-08-31 11:56 we7u
+
+ * config/language-Dutch.sys: Updates by Henk de Groot, PE1DNN.
+ Thanks!
+
+2004-08-31 11:05 we7u
+
+ * help/help-English.dat: Minor tweaks to descriptions about object
+ timing.
+
+2004-08-31 10:30 francais1
+
+ * config/language-French.sys: Updated
+
+2004-08-31 09:52 we7u
+
+ * config/language-Portuguese.sys: Updates by David Quental, CT1DRB.
+ Thanks!
+
+2004-08-31 09:46 we7u
+
+ * src/db.c: Tweak which helps to prevent parsing of weather fields
+ out of comment data.
+
+2004-08-31 09:08 rzg
+
+ * help/help-English.dat: Updating helpfile for release, about 1/3rd
+ done.
+
+2004-08-31 07:40 we7u
+
+ * config/language-Italian.sys: Updates by Alessandro Frigeri,
+ IK0YUP. Thanks!
+
+2004-08-30 08:49 we7u
+
+ * src/interface.c: Adding a terminating zero to the AGWPE packets
+ in port_read() instead of in parse_agwpe_packet().
+
+2004-08-30 08:28 we7u
+
+ * src/interface.c: Adding a string terminator to the end of the
+ AGWPE raw packets before we start processing them. This keeps
+ portions of previously received packets from getting appended to
+ our current string during our processing.
+
+2004-08-30 07:38 we7u
+
+ * README.win32: Changing to Henk de Groot's optimized Festival
+ install instructions.
+
+2004-08-28 15:43 we7u
+
+ * README.win32: Added Festival instructions for Win32 courtesy of
+ Tom Russo. Thanks!
+
+2004-08-27 13:09 we7u
+
+ * src/main.c: Fix for high CPU-usage when time skips backwards.
+ This fix causes Xastir to sleep a bit in the UpdateTime() loop
+ until time catches up again, thereby avoiding the problem. It
+ also dumps a message out to STDERR as it goes into/out of this
+ mode.
+
+2004-08-27 07:44 we7u
+
+ * src/map_gdal.c: Changed the gdal output on startup to show only
+ those map formats that have been enabled in Xastir AND are
+ supported by the GDAL library that we're compiled against.
+
+2004-08-27 07:16 we7u
+
+ * config/language-German.sys: Tweaks by Rolf Bleher, DK7IN.
+ Thanks!
+
+2004-08-26 18:07 shadow
+
+ * configure.ac: update libgeotiff/libtiff/libproj configure tests
+ such that 1) libproj is checked for only once 2) libtiff is used
+ if found when testing for libgeotiff
+
+ revised test from Tom Russo KM5VY and tested on MacOS X and
+ Linux.
+
+2004-08-26 14:03 we7u
+
+ * src/db.c: Fixing the code so that snow can be parsed out of a
+ weather report only if course/speed has already been
+ parsed/deleted from the string.
+
+2004-08-26 11:09 we7u
+
+ * src/alert.c: Fix for high-CPU bug when malformed NWS weather
+ alert packet is received.
+
+2004-08-25 12:45 we7u
+
+ * src/db.c: Fix for truncated lines when using AGWPE or Serial KISS
+ TNC interfaces.
+
+2004-08-25 12:40 we7u
+
+ * src/interface.c: Changed comments. No code changes.
+
+2004-08-25 12:39 we7u
+
+ * src/main.c: Changed a comment. No code changes.
+
+2004-08-24 18:59 we7u
+
+ * scripts/: Makefile.am, kiss-off.pl: Adding a kiss-off script to
+ take a TNC out of KISS mode.
+
+2004-08-24 18:53 we7u
+
+ * src/: main.c, db.c: Fixing the object/item comment-field bug.
+
+2004-08-23 21:47 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, help/help-English.dat,
+ src/messages.c, src/messages.h, src/messages_gui.c: Changing the
+ label on the Clear Messages button, adding a new button for
+ deleting the outgoing messages to that station, relocating the
+ buttons to the bottom row.
+
+2004-08-23 12:48 we7u
+
+ * README.Getting-Started: Added notes about where to look for
+ instructions for other OS'es.
+
+2004-08-22 11:39 we7u
+
+ * src/main.c: Changed one comment.
+
+2004-08-21 17:01 we7u
+
+ * src/: db.c, util.c, util.h: More fixes for xastir_snprintf size
+ parameter, including adding a size parameter to a few other
+ functions that can be used to prevent overrunning strings.
+
+2004-08-21 16:55 we7u
+
+ * src/wx.c: Reformatting of code and rechecking the size parameter
+ for xastir_snprintf function calls.
+
+2004-08-20 23:48 we7u
+
+ * src/wx_gui.c: Reformatting some code.
+
+2004-08-20 23:35 we7u
+
+ * src/: view_message_gui.c, x_spider.c: More cleanup of the size
+ parameter for xastir_snprintf calls.
+
+2004-08-20 23:13 we7u
+
+ * src/: db.c, geocoder_gui.c, gps.c, hostname.c, igate.c,
+ interface.c, maps.c: Cleaning up the size parameter for a bunch
+ of xastir_snprintf calls.
+
+2004-08-20 13:50 we7u
+
+ * src/db.c: Fix for bad longitude for your own station.
+
+2004-08-20 11:38 we7u
+
+ * src/db.c: Fixing problem with truncated comment/status strings.
+ Was setting the length in the xastir_snprintf() call to the
+ length of the pointer instead of the length of the malloc'ed
+ string buffer.
+
+2004-08-20 10:27 we7u
+
+ * src/maps.c: Added a comment.
+
+2004-08-20 10:25 we7u
+
+ * src/: awk.c, geo-find.c: Reformatting of geo-find.c. Added
+ comment to both files.
+
+2004-08-20 10:22 we7u
+
+ * src/db.c: Moving ptr into the block where it is used.
+
+2004-08-20 10:19 kd6zwr
+
+ * src/db.c: Moving a declaration up to the top to allow it to be
+ compiled.
+
+2004-08-20 09:52 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Reducing the
+ resolution on the snow reports, as they are only reported by
+ inch, not by 100's of an inch.
+
+2004-08-19 21:06 we7u
+
+ * src/: alert.c, awk.c, db.c, geo-find.c, igate.c, interface.c,
+ messages_gui.c, util.c, view_message_gui.c, wx.c, x_spider.c:
+ More on the strcat/strcpy/strncpy reduction/elimination. I think
+ this finishes off all the strcat/strcpy calls, and there are only
+ 24 strncpy calls left in the code.
+
+2004-08-19 13:10 we7u
+
+ * README.Getting-Started: Attempting to answer the question: "Why
+ must I compile from sources?"
+
+2004-08-19 12:54 we7u
+
+ * Makefile.am: Adding the new README.Getting-Started into the
+ installation scripts.
+
+2004-08-19 12:48 we7u
+
+ * README.Getting-Started: Spellling fix.
+
+2004-08-19 12:45 we7u
+
+ * README.Getting-Started: First checkin. Fairly complete.
+
+2004-08-19 12:38 we7u
+
+ * src/: alert.c, bulletin_gui.c, db.c, dbfawk.c, gps.c, gps.h,
+ hostname.c, hostname.h, igate.c, interface.c, interface_gui.c,
+ location_gui.c, main.c, map_shp.c, map_tiger.c, messages_gui.c,
+ rotated.c, view_message_gui.c, wx_gui.c: More work to eliminate
+ strcat/strcpy/strncpy from the code.
+
+2004-08-18 23:45 we7u
+
+ * src/: map_tiger.c, maps.c, x_spider.c: More strcat/strcpy fixes.
+ Changing to safer string-handling routines.
+
+2004-08-18 23:38 we7u
+
+ * src/: db.c, interface.c, main.c, map_dos.c, messages_gui.c,
+ popup_gui.c, rac_data.c, sound.c, track_gui.c, xa_config.c,
+ location_gui.c, alert.c, datum.c, draw_symbols.c, fcc_data.c,
+ festival.c, geocoder_gui.c, gps.c, igate.c, list_gui.c,
+ locate_gui.c, map_geo.c, map_gnis.c, messages.c, util.c, wx.c,
+ map_shp.c: More strcat/strcpy fixes. Changing to much safer
+ string-handling routines.
+
+2004-08-18 23:31 we7u
+
+ * src/: geo.h, gps.h, main.h, messages.h, wx.h, xastir.h:
+ strcat/strcpy fixes. Changing to much safer string-handling
+ routines.
+
+2004-08-18 13:35 we7u
+
+ * src/: alert.c, fcc_data.c, hostname.c, igate.c, interface_gui.c,
+ locate_gui.c, map_geo.c, map_shp.c, maps.c, messages.c,
+ messages_gui.c, util.c, x_spider.c: Converting more strcat()
+ function calls to strncat(). Safer.
+
+2004-08-17 21:59 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/db.h, src/list_gui.c,
+ src/maps.c, src/wx.c: Changed wx_snow to be inches instead of
+ 1/100 inch. We now ghost the weather info (mostly) separately
+ from posit info. Got rid of "<br>" from track logs read in from
+ findu.com. Fixed realloc's in maps.c so that they won't cause a
+ memory leak if they fail. Fixed Peet Bros. complete mode
+ decoding so that the proper wind speed is parsed. Fix by Matt
+ Werner, kb0kqa, for the 3-hour barometric pressure reading for
+ Peet Bros. complete mode parsing.
+
+2004-08-17 17:17 we7u
+
+ * src/main.c: Changed formatting, added comments. No code changes.
+
+2004-08-17 09:41 we7u
+
+ * src/wx.c: Fix for 3-hour barometer with Peet U2000 in complete
+ mode. Still testing to see if this is the proper fix, but so far
+ it looks good.
+
+2004-08-16 17:51 we7u
+
+ * src/db.c: Fixing the "Move" function so that you can drag/drop
+ objects/items that are right on top of each other. The selection
+ dialog will pop up so you can choose which one to move.
+
+2004-08-14 09:43 we7u
+
+ * src/main.c: Fixing object/item generation so that a space is
+ prefixed to the comment field only in the case where multipoint
+ polygons are present. The space is necessary in order to parse
+ multipoint objects properly, but is not desired for other
+ objects/items where it would limit the extent of the comment.
+
+2004-08-12 17:26 we7u
+
+ * src/map_gnis.c: Update to GNIS search code for new pipe-delimited
+ file format that the USGS is distributing.
+
+2004-08-12 17:25 we7u
+
+ * INSTALL, README.MAPS, help/help-English.dat: Updates to the docs
+ to match new RINO, Server Port, and other interface changes that
+ were done recently.
+
+2004-08-12 13:46 kd6zwr
+
+ * src/x_spider.c: Moved some declarations up to the top of
+ Server(). Inline decls cause problems on some compilers... (like
+ my gcc 2.96 under linux).
+
+2004-08-12 13:00 we7u
+
+ * src/map_gnis.c: Updating the GNIS map code to handle the latest
+ pipe-delimited files from the USGS. Still need to update the
+ search code, but the display code appears to work fine now.
+
+2004-08-12 10:03 we7u
+
+ * src/interface.c: Added some debug code for tracking down errant
+ raw packets in the AGWPE code.
+
+2004-08-11 13:15 we7u
+
+ * src/main.c: A bit of reformatting, plus sending to the x_spider
+ server after raw packets have been converted to TAPR-2 format
+ packets.
+
+2004-08-11 10:40 we7u
+
+ * src/: main.c, x_spider.c: Tweaks by Tom Russo for FreeBSD
+ compatibility. Thanks!
+
+2004-08-10 19:16 we7u
+
+ * src/: hostname.c, main.h, sound.c, x_spider.c: More fun with
+ process naming.
+
+2004-08-10 12:59 we7u
+
+ * src/x_spider.c: Added a note about future plans for process
+ naming.
+
+2004-08-10 12:51 we7u
+
+ * src/: main.c, x_spider.c, x_spider.h: Code that changes the
+ process name in "ps" listings for the x_spider daemon and client
+ connections. Doesn't work on other operating systems, and
+ doesn't work for "top" listings.
+
+2004-08-09 11:32 we7u
+
+ * src/x_spider.c: Disabling the Nagle algorithm and enabling
+ SO_KEEPALIVE for the server port connections.
+
+2004-08-07 11:12 we7u
+
+ * src/interface.c: Modified AGWPE parsing routine and associated
+ code. We've now turned off "monitor" mode and turned on "raw"
+ mode in AGWPE. The "raw" packets get thrown into our standard
+ KISS decoding routines, which gives us the possibility of
+ supporting OpenTrac (a binary protocol) and digipeating on AGWPE
+ ports in the future. The "monitor" mode decoding has been left
+ for now, but later on we'll probably delete it. Also: Added
+ output to STDERR for the AGWPE server version and for the port
+ descriptions.
+
+2004-08-06 12:57 we7u
+
+ * src/db.c: Change to comment. No code changes.
+
+2004-08-06 09:29 we7u
+
+ * src/interface.c: Minor changes to comments and debug output
+ messages.
+
+2004-08-05 13:02 we7u
+
+ * src/: db.c, festival.c, main.c, interface.c, sound.c, util.c,
+ util.h: Re-wrote the agwpe parsing code. It should be more
+ bulletproof now, but still has some debug stuff in it for NWS_
+ and NWS- messages. Fixed a segfault caused by one of the new
+ strncpy() functions that I switched to in util.c:spell_it_out().
+
+2004-08-04 13:04 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Changing the Modify
+ Object/Item dialogs so that you must adopt an object/item that
+ you don't own before you're allowed to delete it. Adopting or
+ Modifying someone else's object causes you to transmit it as a
+ live object owned by you. After that, you may delete it. If the
+ client that previously owned it saw your live object, it'll know
+ that you own it and that you can delete it. Without this
+ adoption process, UI-View32 clients will hold on to an object
+ that you're trying to kill.
+
+2004-08-04 12:07 we7u
+
+ * help/help-English.dat: Tweaking the note about AGWPE network
+ authentication. We can use that now.
+
+2004-08-04 11:54 we7u
+
+ * src/: interface.c, interface_gui.c: Fixes for AGWPE. Network
+ loging with authentication should work now.
+
+2004-08-03 14:21 we7u
+
+ * src/db.c: Fix to allow objects/items to get through the server
+ port and get igated.
+
+2004-08-03 13:04 we7u
+
+ * src/util.c: Small tweak to valid_inet_name() where it is checking
+ for the "aprsd" string. It didn't appear to be general enough to
+ catch all possibilities. Now it should be.
+
+2004-08-03 12:57 we7u
+
+ * src/db.c: Changed one sizeof() to a strlen() for emergency
+ messages. Fixing object/item timing intervals so that if the
+ timing slider is reduced, the max interval is reduced for already
+ existing objects as well.
+
+2004-08-03 12:42 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Changing the
+ displayed label for the object/item timing. It's a max interval
+ now. The actual timing is under the control of an exponential
+ decay algorithm.
+
+2004-07-30 16:15 we7u
+
+ * src/util.c: A fix for the csT bytes on compressed posits. Turns
+ out we need to send the spaces, and the compressed posit field is
+ a fixed length.
+
+2004-07-30 15:24 we7u
+
+ * src/db.c: Adding some debug output.
+
+2004-07-29 21:06 we7u
+
+ * src/sound.c: Replacing strcpy function with safer ones.
+
+2004-07-29 21:02 we7u
+
+ * src/: list_gui.c, locate_gui.c, location_gui.c, map_tif.c,
+ map_tiger.c, maps.c, messages_gui.c, rotated.c, track_gui.c,
+ util.c, view_message_gui.c: Replacing strcpy functions with safer
+ ones.
+
+2004-07-29 20:57 we7u
+
+ * src/: color.c, color.h, dbfawk.c, draw_symbols.c, fcc_data.c,
+ geo-find.c, geocoder_gui.c, hostname.c, igate.c, interface_gui.c,
+ lang.c: Getting rid of strcpy functions. Replacing them with
+ safer functions.
+
+2004-07-29 17:02 we7u
+
+ * callpass/callpass.c: Geting rid of strcpy() function call.
+
+2004-07-29 14:15 we7u
+
+ * src/db.c: Changed some strcopy() functions to xastir_snprintf()
+ functions.
+
+2004-07-29 13:48 we7u
+
+ * src/util.c: Reformatting to match the rest of the code. No
+ actual code changes.
+
+2004-07-28 22:42 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.h, src/xa_config.c,
+ src/db.c, src/main.c: Adding CWOP WX station filtering toggle.
+ Letting Xastir display wind speed when wind course is not
+ available.
+
+2004-07-28 12:17 we7u
+
+ * src/: db.c, igate.c, x_spider.c: Fixing message igating through
+ x_spider connects.
+
+2004-07-28 10:48 we7u
+
+ * src/x_spider.c: Fix for FreeBSD courtesy of Tom Russo. Thanks!
+
+2004-07-26 17:08 we7u
+
+ * src/: db.c, x_spider.c: Per-client authentication for the
+ x_spider listening port. Printf's for each client
+ connect/disconnect, and each successful authentication.
+ Non-authenticated clients can talk to each other and the server,
+ and can receive data from the server, but can't sent anything
+ through the server. Igating must also be turned on to get data
+ from authenticated clients up to the internet connections.
+
+2004-07-26 16:57 we7u
+
+ * symbols/symbols.dat: Adding the new Rocket symbol that Bob. B.
+ just added to the spec.
+
+2004-07-26 16:55 we7u
+
+ * config/: tnc-startup.aea, tnc-startup.d700, tnc-startup.kam,
+ tnc-startup.kpc2, tnc-startup.kpc3, tnc-startup.paccomm,
+ tnc-startup.pico, tnc-startup.sys, tnc-startup.thd7,
+ tnc-startup.tnc2-ui: Reenabling the CWID stuff. Some countries
+ evidently require it.
+
+2004-07-26 14:02 we7u
+
+ * src/x_spider.c: Changing the authentication comments slightly for
+ x_spider.
+
+2004-07-26 13:59 we7u
+
+ * src/x_spider.c: Adding client authentication to the x_spider
+ server. Clients cannot send data upstream until they
+ authenticate. Clients can still receive data without
+ authenticating or send data to other connected clients.
+
+2004-07-26 13:57 we7u
+
+ * src/util.c: Removing unused define.
+
+2004-07-26 12:39 we7u
+
+ * config/tnc-startup.sys: Adding another CWID command that will
+ turn off that feature for some TNC's.
+
+2004-07-26 12:21 we7u
+
+ * config/: tnc-startup.paccomm, tnc-startup.pico: Correct CWID
+ commands for Paccomm TNC's.
+
+2004-07-26 11:49 we7u
+
+ * config/: tnc-startup.kpc2, tnc-startup.kpc3: Correct commands to
+ turn off CWID.
+
+2004-07-26 11:44 we7u
+
+ * config/tnc-startup.kam: The correct command for turning of CWID.
+
+2004-07-26 11:16 we7u
+
+ * config/tnc-startup.kam: Turning off CWID.
+
+2004-07-26 10:04 we7u
+
+ * config/: tnc-startup.aea, tnc-startup.d700, tnc-startup.kpc2,
+ tnc-startup.kpc3, tnc-startup.paccomm, tnc-startup.pico,
+ tnc-startup.sys, tnc-startup.thd7, tnc-startup.tnc2-ui: Adding
+ "CWID off" command.
+
+2004-07-25 07:19 rzg
+
+ * help/help-English.dat: Updated the list of new features.
+
+2004-07-24 15:49 we7u
+
+ * src/: db.c, igate.c, interface.c, main.c, util.c: Tweaking the
+ server stuff so that connected clients get igated through the
+ "master" Xastir instance if igating -> Net is enabled.
+
+2004-07-23 09:57 we7u
+
+ * src/db.c: Ignore case when comparing newly received
+ comment/status strings with previously received ones, to decide
+ which ones to throw into the list. With a case-sensitive
+ compare, we were getting two instances of similar comment/status
+ strings cluttering up our lists, when it was really the same info
+ being presented but in a different case.
+
+2004-07-23 09:31 we7u
+
+ * src/main.c: Cygwin fixes by KJ5O. Thanks!
+
+2004-07-22 19:31 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface.c, src/main.c,
+ src/main.h, src/x_spider.c, src/xa_config.c: GUI support for the
+ new server port.
+
+2004-07-21 18:56 we7u
+
+ * src/: Makefile.am, db.c, igate.c, interface.c, main.c, main.h,
+ x_spider.c, x_spider.h: Adding a listener socket for multiple
+ clients. Currently this must be enabled by uncommenting a
+ #define near the top of main.c. Adds a listening socket at port
+ 2023 which allows any number of clients to connect. Spawns a
+ listener for each active client, kills them when the client
+ disconnects. All packets received or transmitted by Xastir go to
+ these clients, all packets sent by the clients are received by
+ Xastir and by all of the other connected clients. "telnet
+ localhost 2023" to test out the functionality after compiling in
+ the server support.
+
+2004-07-21 11:38 gstueve
+
+ * src/view_message_gui.c: Add macro so someone's comment can be
+ answered. Don't try to put too many arguments into a fixed array.
+
+2004-07-20 11:41 we7u
+
+ * src/db.c: Sorting and display of status/comment records by
+ date/time.
+
+2004-07-20 11:14 we7u
+
+ * src/db.h: Bumping max status/comment lines per station from 10 to
+ 20. Am testing with 50 locally to see whether bumping it up more
+ will seriously affect memory usage. Depending on the results,
+ may bump these numbers up even more.
+
+2004-07-19 19:42 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/db.h, src/x_spider.c:
+ Adding date/timestamps to Status and Comment records.
+
+2004-07-19 14:17 we7u
+
+ * src/: alert.c, alert.h, db.c, db.h: Moving a couple of define's
+ to the .h files and increasing the number of alerts and messages
+ that we allocate when we run out. This hopefully will help to
+ keep the number of large allocations down plus keep the larger
+ allocations from ending up at the very end of the heap. If we
+ keep a small increment, we realloc() more often plus the large
+ blocks will end up closer to the end of the heap, meaning we
+ won't be able to reduce our memory impact much later.
+
+2004-07-19 09:13 we7u
+
+ * config/: tnc-startup.aea, tnc-startup.d700, tnc-startup.kpc2,
+ tnc-startup.kpc3, tnc-startup.paccomm, tnc-startup.sys,
+ tnc-startup.thd7, tnc-startup.tnc2-ui: Adding "HID off" where it
+ was missed. Some TNC's may require slightly different commands
+ for this. I don't have them to test with so I'll have to wait
+ for users to let me know the proper commands.
+
+2004-07-16 11:27 we7u
+
+ * configure.ac, src/alert.c, src/db.c, src/main.c, src/map_gdal.c,
+ src/xastir.h: Adding support for "libgc", which is a
+ Boehm-Demers-Weiser garbage collection library. The advantage
+ for us is that it can find/report memory leaks. Install it, then
+ add "--with-libgc" to the configure line to compile it in. It
+ will report memory leaks on the console. This patch fixes two
+ leaks found by libgc, plus changes the increments used for
+ relloc'ing alerts and messages.
+
+2004-07-15 14:32 we7u
+
+ * src/: awk.c, db.c, dbfawk.c, igate.c, main.c, map_gdal.c,
+ map_shp.c, maps.c, rotated.c: Protection for
+ malloc/calloc/realloc calls. Checking the return value for
+ non-NULL.
+
+2004-07-15 13:01 we7u
+
+ * src/maps.c: Added some comments.
+
+2004-07-15 12:58 we7u
+
+ * src/: alert.c, db.c, igate.c, messages.c: Added/changed warning
+ messages when realloc's fail.
+
+2004-07-15 10:26 we7u
+
+ * src/main.c: Reuven found a missing #ifdef for the RINO stuff.
+ Thanks!
+
+2004-07-15 10:16 we7u
+
+ * src/messages.c: Reformatting to take out tabs.
+
+2004-07-15 10:09 we7u
+
+ * src/db.c: Changed some debug code that is used to test expire
+ times for messages and stations.
+
+2004-07-15 08:29 gstueve
+
+ * src/messages.c: Make sure to look for Special groups and safety
+ check group names.
+
+2004-07-14 14:07 we7u
+
+ * FAQ, INSTALL, acinclude.m4, configure.ac: Motif detection tweaks
+ by Tom Russo.
+
+2004-07-14 12:48 we7u
+
+ * src/db.c: Reformatting and comment changes. No code changes.
+
+2004-07-14 12:13 we7u
+
+ * src/db.c: Better code for drawing callsign at each trackpoint.
+ This draws the callsign at every single point.
+
+2004-07-14 09:31 we7u
+
+ * src/main.c: An attempt to fix the menu GPS Status so that it
+ works. Still need an expiration mechanism for the data here.
+
+2004-07-14 09:29 we7u
+
+ * FAQ: Added an LDD note, inspired by Jack Twilley.
+
+2004-07-13 14:02 we7u
+
+ * src/db.c: Comment changes.
+
+2004-07-13 12:21 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c, src/main.h,
+ src/xa_config.c: Added a new button to the Station Filter dialog:
+ "Label All Points". Doesn't actually label _ALL_ trackpoints,
+ but labels most of them with the callsign. This is helpful to
+ identify whose tracks belong to who.
+
+2004-07-13 07:54 we7u
+
+ * src/: alert.c, db.c, db.h, list_gui.c, main.c, main.h,
+ messages.c, messages.h, messages_gui.c, track_gui.c, util.c:
+ Combined MAX_CALL and MAX_CALLSIGN defines into MAX_CALLSIGN,
+ reduced the size of it from 20 chars. Added MAX_COMMENT_LINES
+ and MAX_STATUS_LINES, currently set to 10 each, which limit how
+ many unique status/comment lines are saved per station. Added
+ MAX_TACTICAL_CALL in order to separate that parameter from
+ MAX_CALLSIGN, as the tactical call needs to be longer but didn't
+ want to waste the memory for all callsigns by making them all
+ long. Changed the alert memory allocation from 100 alert blocks
+ to 25 alert blocks (finer grained malloc's). Added more
+ comments.
+
+2004-07-09 14:11 we7u
+
+ * src/main.c: Throwing Base-91 Compressed APRS packets into our
+ decoding instead of standard APRS packets. This keeps the
+ resolution that the RINO's are capable of. Doesn't affect how
+ the Object packets are transmitted: For that setting refer to the
+ toggle on the File->Configure->Defaults dialog.
+
+2004-07-09 10:32 we7u
+
+ * src/main.c: Better timestamp for RINO-derived APRS Objects.
+ Issues: currently sends localtime instead of UTC, plus the
+ gpstrans files we're getting the timestamp from appear to have
+ the download time/date instead of the waypoint creation
+ time/date. These need to be fixed at some point.
+
+2004-07-09 08:19 rzg
+
+ * src/alert.c: Fixed read of unitialized data according to
+ valgrind.
+
+2004-07-08 16:34 rzg
+
+ * src/main.c: Fixed comparisions of unitialized variables, and
+ another small bug.
+
+2004-07-08 14:49 we7u
+
+ * src/main.c: Initializing some variables as they are defined.
+
+2004-07-08 14:49 we7u
+
+ * src/map_geo.c: Added some comments.
+
+2004-07-08 14:48 we7u
+
+ * src/interface.c: Reformatting. No code changes.
+
+2004-07-08 14:48 we7u
+
+ * src/draw_symbols.c: Initializing a variable as it is defined.
+
+2004-07-08 12:38 we7u
+
+ * src/main.c: Commenting out RINO debug fprintf() statements.
+
+2004-07-08 12:07 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/main.h,
+ src/xa_config.c: Implemented auto-download capability for the
+ RINO waypoints. A new slider added to the
+ File->Configure->Timing dialog. A setting of 0 disables the
+ function. Anything else invokes GPSMan at the interval selected,
+ downloading all waypoints from a RINO, and creating APRS objects
+ out of those that have "APRS" as the beginning four characters of
+ the waypoint name.
+
+2004-07-08 08:50 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Initial support for
+ Garmin RINO "contact" waypoints. A new entry on the Interface
+ menu allows snagging waypoints from a RINO. Any that begin with
+ the letters "APRS" will have those four letters removed and then
+ a standard APRS object is created from them and starts
+ transmitting out from Xastir over APRS. We're using
+ non-compressed Objects so that they will be visible on Kenwood
+ displays, at the expense of throwing away some of the position
+ resolution. The menu link-in may change, as we'll eventually go
+ to an automatic poll scheme of the RINO instead of this manual
+ operation. Currently requires a connected RINO on a serial port
+ and GPSMan support compiled into Xastir.
+
+2004-07-07 11:15 we7u
+
+ * INSTALL: Tweaked the instructions for GDAL ever so slightly.
+
+2004-07-07 09:30 we7u
+
+ * configure.ac: Added a comment from Tom Russo. We need to make
+ some changes to the Motif detect so that we're assured we have
+ working headers/libraries before we get to the compile stage.
+
+2004-07-06 15:29 we7u
+
+ * configure.ac: Replacing our Motif search code with better code
+ from the "vim" project. This code is purported to find the most
+ recent variant of Motif on the system and use that, if there's
+ more than one on the system. It also looks quite a few more
+ places for the libraries/headers than our old code.
+
+2004-07-06 11:23 we7u
+
+ * src/main.c: Added comments.
+
+2004-07-02 13:19 we7u
+
+ * src/locate_gui.c: Fixed one printf format that had too many
+ format specifiers in it.
+
+2004-07-01 17:20 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/gps.c, src/gps.h, src/main.c:
+ Adding GPS Quality info to the command line and to a new
+ View->GPS Status option.
+
+2004-07-01 14:33 we7u
+
+ * src/xa_config.c: Setting more reasonable lower defaults for a
+ couple of timing parameters.
+
+2004-07-01 14:16 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/locate_gui.c: FCC/RAC callsign
+ lookup which doesn't depend on stations being on the screen.
+
+2004-07-01 09:26 we7u
+
+ * src/bulletin_gui.c: Fix by Tom Russo for FreeBSD.
+
+2004-06-30 22:00 we7u
+
+ * src/maps.c: Converting from a strcpy() to a memmove() due to
+ another bug that Reuven found. strcpy() cannot handle
+ overlapping strings, while memmove() can.
+
+2004-06-30 21:16 we7u
+
+ * src/main.c: Fixing memory leaks.
+
+2004-06-30 21:13 we7u
+
+ * src/db.c: Fixing memory leaks.
+
+2004-06-30 21:09 we7u
+
+ * src/: messages_gui.c, track_gui.c, view_message_gui.c: Fixing
+ memory leaks.
+
+2004-06-30 21:05 we7u
+
+ * src/: list_gui.c, locate_gui.c, location_gui.c, messages.c:
+ Fixing memory leaks.
+
+2004-06-30 21:00 we7u
+
+ * src/interface_gui.c: Fixing memory leaks.
+
+2004-06-30 20:55 we7u
+
+ * src/: bulletin_gui.c, geocoder_gui.c: Fixing memory leaks.
+
+2004-06-30 14:00 we7u
+
+ * src/db.c: Fixing a bug Reuven found: Doing an "if" based on the
+ value of an uninitialized variable.
+
+2004-06-30 13:53 we7u
+
+ * src/db.c: Fixing an indexing bug that Reuven found (via
+ "valgrind"). We can't go past index 0 if we've assigned '\0' to
+ a string.
+
+2004-06-30 13:36 rzg
+
+ * src/: color.c, dbfawk.c, main.c: Minor memory leak fixes.
+
+2004-06-30 13:32 we7u
+
+ * src/list_gui.c: Fixing a memory leak that Reuven discovered.
+
+2004-06-30 12:43 we7u
+
+ * src/db.c: Fixing a bug found by Reuven in the GLL decode routine.
+
+2004-06-30 10:54 we7u
+
+ * src/: db.h, db.c: Moved multipoints into a separate record,
+ allocating only when needed. This provides additional memory
+ savings over the tweaks that went in yesterday, with no loss in
+ speed/efficiency.
+
+2004-06-29 20:45 we7u
+
+ * src/: db.c, db.h: Tweaks to significantly reduce memory usage.
+
+2004-06-29 12:42 we7u
+
+ * src/wx.c: Fixing all the 2^16 constants. Ten of them were
+ incorrect.
+
+2004-06-29 11:41 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c: Added language
+ strings for CAD objects and tactical calls.
+
+2004-06-28 09:56 we7u
+
+ * src/main.c: Added a comment. No code changes.
+
+2004-06-27 17:15 rzg
+
+ * src/main.c: Fixed array size error, to fix stack smashing issue.
+
+2004-06-25 16:24 we7u
+
+ * config/: Makefile.am, tnc-startup.tnc2-ui, tnc-stop.tnc2-ui:
+ Start/stop TNC files contributed by Alessio Sangalli, IW2NYD, for
+ the TNC2-UI TNC used in Europe.
+
+2004-06-24 14:23 we7u
+
+ * FAQ: Added a bit about ImageMagick and color-depth.
+
+2004-06-24 13:49 we7u
+
+ * src/: db.c, main.c: Adding some debug stuff to the expire code.
+ Tweaking the status line station readout so it will reflect the
+ current number of stations in all cases.
+
+2004-06-24 13:08 we7u
+
+ * src/main.c: Erasing box after Measure operation.
+
+2004-06-24 13:00 we7u
+
+ * src/: db.c, main.c: Removing tac-call capability for
+ objects/items. The saving/restoring of these on startup is a
+ problem. Perhaps we can add the functionality back in later for
+ these, but probably only if we own the objects/items ourselves.
+ Even then, deleting the objects/items needs to be looked at
+ carefully.
+
+2004-06-24 12:29 we7u
+
+ * src/: db.c, db.h, main.c, util.c: Fix for Move function. Also
+ changed tactical call so that it takes up less memory.
+
+2004-06-23 16:19 we7u
+
+ * src/main.c: Rearranging the Station menu slightly so that it is
+ harder to delete all stations by mistake. It's now at the bottom
+ of the menu.
+
+2004-06-23 12:54 we7u
+
+ * src/main.c: Adding a define, commented out currently, which sets
+ all flags properly for a 640x480 touch-screen. Has no effect
+ unless comments are removed.
+
+2004-06-23 12:25 we7u
+
+ * src/: interface.c, main.c: Backing out the changes that were just
+ made for the Serial TNC Aux GPS interface. Turns out the code
+ was right all along. The user that is experiencing difficulties
+ with a KAM+ must have some other sort of problem.
+
+2004-06-23 11:10 we7u
+
+ * src/interface.c: Serial TNC AUX GPS interfaces weren't parsing
+ GPS data out of the datastream. This should fix it. More
+ testing to come.
+
+2004-06-23 11:05 we7u
+
+ * src/main.c: Comment changes.
+
+2004-06-23 10:30 we7u
+
+ * src/main.c: Changing one debug printf()
+
+2004-06-22 13:44 we7u
+
+ * src/main.c: Fixing the code so that the SWAP_MOUSE_BUTTONS #ifdef
+ works properly again.
+
+2004-06-22 12:36 we7u
+
+ * src/db.c: Adding tactical call button to Station Info dialog.
+ This is required for cases where multiple calls are near the
+ pointer, else we can't assign tactical calls.
+
+2004-06-22 10:41 we7u
+
+ * src/db.c: Fixed a memory leak in the expire routines, where
+ status data was not getting free'd.
+
+2004-06-22 10:20 we7u
+
+ * src/db.c: Fixing bug in expire code introduced by newly-added
+ tactical call code.
+
+2004-06-21 14:10 we7u
+
+ * src/: db.c, main.c, main.h, xa_config.c: Adding a toggle flag for
+ selecting only stations with tactical callsigns.
+
+2004-06-21 11:03 we7u
+
+ * src/: db.c, util.c: Restoring of tactical calls from file when
+ Xastir starts up or after all stations are cleared. Dummy
+ records are created which then get coupled to the real info when
+ the station gets heard on the air. Also tweaked the expire code
+ so that stations with tac-calls don't get expired. They should
+ still get cleared from the screen, but the station and all it's
+ original data, including tac-call, should appear again when the
+ station re-appears on frequency. That new addition to the expire
+ code is not tested fully yet.
+
+2004-06-21 09:08 we7u
+
+ * src/: db.c, main.c, util.c, util.h: Logging of tactical calls to
+ disk. Added Clear Tactical Calls and Clear Tactical History menu
+ options. Restore of tactical calls from disk at startup is not
+ coded yet.
+
+2004-06-18 22:24 we7u
+
+ * src/db.c: Adding the callsign or the object/item name as a label
+ in the Assign Tactical Call dialog, so that we know what we're
+ renaming.
+
+2004-06-18 13:32 we7u
+
+ * src/db.c: Instant update when changing a tactical call.
+
+2004-06-18 13:01 we7u
+
+ * src/db.c: Minor tweaks to the tactical call stuff. Allows 19
+ chars now for the name.
+
+2004-06-18 12:28 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/db.h, src/main.c:
+ Implementing Tactical Calls. Added to the right-click mouse
+ menu.
+
+2004-06-18 10:09 we7u
+
+ * src/interface.c: Comment changes.
+
+2004-06-18 10:07 we7u
+
+ * src/interface.c: Mostly comment changes. Added "Counts" to the
+ generic measurements table ( units[] ).
+
+2004-06-18 08:46 we7u
+
+ * src/interface.c: Changing some comments.
+
+2004-06-18 08:38 we7u
+
+ * src/interface.c: Minor comment change.
+
+2004-06-18 08:35 we7u
+
+ * src/interface.c: Minor tweaks to the OpenTrac classification
+ messages.
+
+2004-06-18 08:24 we7u
+
+ * src/interface.c: Adding in catch-all clauses for OpenTrac
+ elements that are new or not-yet-implemented.
+
+2004-06-18 08:03 we7u
+
+ * src/interface.c: Putting in more dummy routines for the
+ unimplemented OpenTrac element decoding.
+
+2004-06-18 07:30 we7u
+
+ * src/main.c: Fixing the AUX-TNC type so that it actually tries to
+ parse the GPS sentences. It didn't appear to do that with the
+ earlier code, while other types of interfaces did parse them.
+
+2004-06-18 06:51 we7u
+
+ * src/interface.c: Adding parsing for more OpenTrac elements. Not
+ much is done with the data yet, but the placeholders are there
+ now. Added better reporting for various classes of unknown
+ OpenTrac element types also.
+
+2004-06-18 00:08 we7u
+
+ * src/interface.c: Added some comments.
+
+2004-06-17 16:33 we7u
+
+ * src/interface.c: More very minor OpenTrac tweaks.
+
+2004-06-17 15:46 we7u
+
+ * src/interface.c: Minor tweaks so that the OpenTrac comment field
+ gets cleared before we process each piece, plus adding a space
+ before the displayname part of the OpenTrac comment.
+
+2004-06-17 15:11 we7u
+
+ * FAQ: Added another question/answer about problems caused by the
+ LANG environment variable setting.
+
+2004-06-17 12:28 we7u
+
+ * src/interface.c: Limiting the comment field on the converted
+ OpenTrac packets to 40 chars, which is the max for a Base-91
+ compressed APRS packet.
+
+2004-06-17 12:18 we7u
+
+ * src/interface.c: Converting strcat() to strncat() functions in
+ the OpenTrac routines.
+
+2004-06-17 12:03 we7u
+
+ * src/interface.c: Changed some comments. No code changes.
+
+2004-06-17 11:10 we7u
+
+ * src/interface.c: Higher-resolution OpenTrac positioning. We now
+ convert to Base-91 Compressed APRS packets before throwing them
+ into our standard decoding. This should give us 1/100 sec
+ lat/long resolution, instead of the 60' resolution we had before.
+ This new code is untested as of yet.
+
+2004-06-17 10:46 we7u
+
+ * src/: util.c, xastir.h: Adding a higher-resolution lat/long
+ format, so we can make better use of OpenTrac resolution.
+
+2004-06-17 08:06 we7u
+
+ * src/interface.c: Changing from issuing the "conv" command to
+ issuing the "k" command to get the TNC into converse mode. One
+ european TNC doesn't implement the "conv" command.
+
+2004-06-16 16:27 we7u
+
+ * config/: tnc-startup.d700, tnc-startup.thd7: Adding TXD settings
+ to the Kenwood startup files.
+
+2004-06-14 23:23 we7u
+
+ * src/interface.c: Added a comment.
+
+2004-06-14 22:31 we7u
+
+ * config/: Makefile.am, tnc-startup.kpc2: Initial kpc2 startup file
+ by Tom Russo. Thanks!
+
+2004-06-14 20:10 we7u
+
+ * src/util.c: Changing one debug fprintf.
+
+2004-06-14 13:40 we7u
+
+ * src/interface.c: Removing an error messaging having to do with
+ the tnc-start/stop META tag. This error message gets thrown out
+ at odd times if you happen to have META in a comment in those
+ file. Not needed.
+
+2004-06-14 13:14 we7u
+
+ * README.win32: Liblcms is now a Cygwin package, so changing the
+ instructions to match. Thanks to Henk de Groot for this info!
+
+2004-06-14 12:53 we7u
+
+ * config/Makefile.am: Adding a new stop file for the TH-D7A.
+
+2004-06-14 12:49 we7u
+
+ * config/: tnc-stop.thd7, tnc-startup.thd7: Changes to the
+ tnc-startup.d7a startup file by Henk de Groot, PE1DNN. Also a
+ new tnc-stop.d7a file from him. Thanks!
+
+2004-06-11 12:45 we7u
+
+ * config/Makefile.am: Adding the new D700 start/stop files.
+
+2004-06-11 12:44 we7u
+
+ * config/: tnc-startup.d700, tnc-stop.d700: Adding files that David
+ Flood, KD7MYC, came up with to start/top a Kenwood D700A and put
+ it into the proper modes in each case.
+
+2004-06-10 19:26 we7u
+
+ * src/interface.c: Tweaks to allow more control in the
+ tnc-startup.sys file. Adds a pause and a no-ctrl-C capability.
+
+2004-06-10 16:51 we7u
+
+ * Davis/src/db2APRS.c: Memory leak update by Bruce Bennett, KB8ROP.
+ Thanks!
+
+2004-06-08 08:37 we7u
+
+ * config/language-Dutch.sys: Updates by Han Sytsma. Thanks!
+
+2004-06-07 14:13 we7u
+
+ * configure.ac: Bumping the development rev. up to 1.3.3.
+
+2004-06-07 13:01 we7u
+
+ * INSTALL: A note about adding a flag to the configure command-line
+ to help it find the Motif include files.
+
+2004-06-07 11:11 we7u
+
+ * src/alert.c: Fixing string overflow problem triggered by extreme
+ number of compressed alerts.
+
+2004-06-04 15:47 we7u
+
+ * src/: rac_data.c, rac_data.h: Fixing a possible buffer overflow
+ problem that Tom Russo found. Thanks!
+
+2004-06-04 13:39 we7u
+
+ * config/: tnc-startup.aea, tnc-startup.paccomm, tnc-startup.pico,
+ tnc-startup.sys: More PID filtering stuff.
+
+2004-06-04 12:42 we7u
+
+ * config/: tnc-startup.aea, tnc-startup.kam, tnc-startup.kpc3,
+ tnc-startup.paccomm, tnc-startup.pico, tnc-startup.sys: Adding
+ PID filtering so that only 0xf0 PID's make it through in converse
+ mode (APRS packets).
+
+2004-06-04 10:36 we7u
+
+ * src/fcc_data.c: Fix by Tom Russo.
+
+2004-06-04 10:20 we7u
+
+ * config/tnc-startup.kam: Adding PID OFF.
+
+2004-06-04 09:53 we7u
+
+ * config/tnc-startup.kpc3: Adding "PID off" so that other protocols
+ don't show up in converse/monitor mode.
+
+2004-06-03 22:49 we7u
+
+ * src/main.c: Zoom-in box tweaks. These prevent the vectors from
+ being drawn over again if a screen update has happened. Keeps
+ extra line segments from appearing while doing the zoom-in box
+ mouse operation.
+
+2004-06-03 16:01 we7u
+
+ * config/language-Dutch.sys: Updates by Han Sytsma, PE1FAM.
+ Thanks!
+
+2004-06-03 15:00 francais1
+
+ * config/language-French.sys: Updated somewhat
+
+2004-06-03 14:36 we7u
+
+ * src/main.c: Widening the zoom-in line width slightly. Looks very
+ nice now/more visible.
+
+2004-06-03 14:11 we7u
+
+ * config/language-Italian.sys: Updates by Alessandro Frigeri,
+ IK0YUP. Thanks!
+
+2004-06-03 13:47 we7u
+
+ * config/language-German.sys: Updates by Rolf Bleher, DK7IN.
+ Thanks!
+
+2004-06-03 09:49 we7u
+
+ * src/main.c: Better zoom-in box operation. Much better!
+
+2004-06-02 14:28 we7u
+
+ * src/main.c: Added another variable which we check against in
+ order to NOT draw the zoom-in box when we're in the menus.
+
+2004-06-02 12:43 we7u
+
+ * src/map_gdal.c: Fixing the out-of-bounds check after the
+ coordinate conversion.
+
+2004-06-02 11:19 we7u
+
+ * src/main.c: Adding a visible selection outline to the zoom-in
+ function. The outline updates once per second currently and
+ doesn't clean up after itself, but they disappear fairly quickly
+ anyway.
+
+2004-06-02 09:41 we7u
+
+ * configure.ac: Adding Davis stuff.
+
+2004-06-02 09:40 we7u
+
+ * Makefile.am: Adding Davis directory.
+
+2004-06-02 09:38 we7u
+
+ * Davis/src/: Makefile.am, db2APRS.c, defs.h: Moved these from
+ xastir/src/Davis/src to xastir/Davis/src
+
+2004-06-02 09:37 we7u
+
+ * Davis/: AUTHORS, COPYING, ChangeLog, INSTALL, Makefile.am, NEWS,
+ README, bootstrap.sh, configure.ac: Moved these from
+ xastir/src/Davis to xastir/Davis
+
+2004-06-01 20:28 we7u
+
+ * src/Makefile.am: Removing Davis from the list of subdirectories
+ for now.
+
+2004-06-01 15:49 we7u
+
+ * src/Makefile.am: Tweaks to include the Davis code in the released
+ tgz files.
+
+2004-05-30 22:34 we7u
+
+ * src/: dbfawk.c, map_shp.c: More Tom Russo fixes, also removing
+ some debug code that I added earlier.
+
+2004-05-30 18:28 rzg
+
+ * INSTALL, README.MAPS, help/help-English.dat: Updates to all the
+ docs, some more README.MAPS cleanups/updates.
+
+2004-05-28 17:45 we7u
+
+ * src/map_shp.c: Correcting what I submitted earlier to match what
+ Tom Russo sent me. My oops.
+
+2004-05-28 16:02 we7u
+
+ * src/: alert.c, map_shp.c: Tom Russo's tweak to allow red flag
+ alerts in their current transmitted form to be displayed by
+ Xastir. Thanks!
+
+2004-05-28 15:44 we7u
+
+ * symbols/Makefile.am: Adding new red_flag.xbm file to the mix.
+
+2004-05-28 15:43 we7u
+
+ * symbols/red_flag.xbm: New warning by Tom Russo.
+
+2004-05-28 12:23 we7u
+
+ * config/: nwsc_ddmmyy.dbfawk, nwsfz_ddmmyy.dbfawk,
+ nwsmzddmmyy.dbfawk, nwsozddmmyy.dbfawk, nwsw_ddmmyy.dbfawk,
+ nwsz_ddmmyy.dbfawk: More tweaks from Tom Russo. This one is
+ intended to supply a "BOGUS" default value for the key if the
+ shapefile has NULL entries.
+
+2004-05-28 12:16 we7u
+
+ * src/main.c: Mostly comment changes. Also removing the exit when
+ Festival can't be connected to (which I don't think worked
+ anyway).
+
+2004-05-28 12:03 we7u
+
+ * src/map_shp.c: Changed an exit() to a return() for the case where
+ dbfawk fails.
+
+2004-05-28 12:03 we7u
+
+ * src/: hostname.c, sound.c: Added some comments.
+
+2004-05-28 11:34 we7u
+
+ * src/map_shp.c: Comment change.
+
+2004-05-28 11:09 we7u
+
+ * src/map_shp.c: Here's a fix for the missing weather alert
+ problem, when using dbfawk. Turns out the latest zone file from
+ NOAA has an unexpected mostly-NULL entry for shape 144, which
+ caused our compare to match on that shape in all cases. It's
+ definitely an incorrect shapefile entry, but it caused a problem
+ in our code as well which needed to be fixed. We now check again
+ using the title length if we got a match due to the key length
+ being 0.
+
+2004-05-28 07:48 we7u
+
+ * config/: nwsc_ddmmyy.dbfawk, nwsfz_ddmmyy.dbfawk,
+ nwsmzddmmyy.dbfawk, nwsozddmmyy.dbfawk, nwsw_ddmmyy.dbfawk,
+ nwsz_ddmmyy.dbfawk: Tweaks by Tom Russo to reset fill_style in
+ each dbfawk file. Thanks!
+
+2004-05-26 19:11 we7u
+
+ * src/: awk.c, dbfawk.c, map_shp.c: More of Tom Russo's memory leak
+ fixes. Thanks!
+
+2004-05-26 14:14 we7u
+
+ * src/: awk.c, dbfawk.c, map_shp.c: Minor comment changes. Changed
+ to correct cleanup routine for one type of object. More memory
+ leak fixes.
+
+2004-05-26 12:15 we7u
+
+ * src/map_shp.c: Adding some more "free" stuff before yet another
+ return.
+
+2004-05-26 09:11 we7u
+
+ * src/xa_config.c: Changing default for weather alert updates to 60
+ seconds instead of 30.
+
+2004-05-25 22:57 we7u
+
+ * src/awk.c: Closing another small memory leak.
+
+2004-05-25 21:42 we7u
+
+ * src/map_shp.c: Handling another error condition.
+
+2004-05-25 21:37 we7u
+
+ * src/dbfawk.c: More comments. Handled a few error conditions.
+ Perhaps closed a few minor memory leaks.
+
+2004-05-25 16:17 we7u
+
+ * src/map_shp.c: More comments.
+
+2004-05-25 13:45 we7u
+
+ * src/: awk.c, map_shp.c: More comments.
+
+2004-05-25 13:01 we7u
+
+ * src/: dbfawk.c, awk.c: Added some comments.
+
+2004-05-25 13:00 we7u
+
+ * src/rotated.c: Added some comments regarding malloc's/free's.
+
+2004-05-25 00:30 we7u
+
+ * src/dbfawk.c: More comments.
+
+2004-05-24 23:53 we7u
+
+ * src/dbfawk.c: Moving some free() code to the proper places.
+
+2004-05-24 23:08 we7u
+
+ * src/map_shp.c: More comments.
+
+2004-05-24 21:34 we7u
+
+ * src/dbfawk.c: Adding more comments.
+
+2004-05-24 21:18 we7u
+
+ * src/: dbfawk.c, map_shp.c: Adding comments/printf's regarding
+ allocation/deallocation of memory.
+
+2004-05-24 21:11 we7u
+
+ * src/: awk.c, testawk.c: Adding comments regarding allocations and
+ free'ing of memory.
+
+2004-05-24 18:55 we7u
+
+ * src/: dbfawk.c, map_shp.c: More memory leak fixes for dbfawk.
+ Getting better!
+
+2004-05-24 14:53 we7u
+
+ * src/: map_shp.c, dbfawk.c: Adding some free() statements to exit
+ points in map_shp.c, to de-allocate memory that was allocated
+ earlier in the function via dbfawk calls.
+
+2004-05-24 11:02 gstueve
+
+ * src/main.c: Actually maintain count of visible alerts on screen
+ for increasing alert count.
+
+2004-05-24 10:51 we7u
+
+ * FAQ: Added a few more notes about what do do for "missing Motif"
+ messages.
+
+2004-05-23 17:01 n2ygk
+
+ * src/: dbfawk.c, dbfawk.h, map_shp.c: Tom's "bloatpatch" for
+ memory leak.
+
+2004-05-22 18:54 rzg
+
+ * README.MAPS: Some formatting fixes, updated URL for quad index
+ shapefile.
+
+2004-05-22 12:42 we7u
+
+ * acinclude.m4, configure.ac: Mods by Tom Russo to allow the
+ --without flags to work properly for festival and gpsman.
+ Thanks!
+
+2004-05-21 11:49 jtwilley
+
+ * configure.ac: applied Tom Russo's emergency patch - will examine
+ later
+
+2004-05-20 14:46 we7u
+
+ * src/map_shp.c: Closing a small memory leak in the dbfawk stuff.
+ More to come. Thanks to Tom Russo for finding this one.
+
+2004-05-19 16:23 we7u
+
+ * src/main.c: Fixing the local station so that compressed posits
+ turn off ambiguity.
+
+2004-05-19 16:08 we7u
+
+ * INSTALL, README.MAPS, configure.ac, xastir.spec.in: Making dbfawk
+ be compiled in by default. Added --without-* flags for all of
+ the optional libraries so that they can be disabled. Made
+ geotiff compilation dependent on libproj being present. Made
+ dbfawk compilation dependent on shapelib and pcre being present.
+ The tests for the libraries are skipped entirely if the proper
+ --without-* flag is passed to configure.
+
+2004-05-19 09:05 we7u
+
+ * config/Makefile.am: Adding the fire alert dbfawk file to the
+ distribution.
+
+2004-05-19 09:04 we7u
+
+ * config/nwsfz_ddmmyy.dbfawk: Adding a dbfawk file for Fire weather
+ alerts.
+
+2004-05-19 08:55 we7u
+
+ * config/nwsz_ddmmyy.dbfawk: Latest dbfawk file for weather zone
+ shapefile.
+
+2004-05-18 13:28 we7u
+
+ * config/nwsz_ddmmyy.dbfawk: Added a commented line which works
+ with fire zone files. Can't add it in yet as it appears to be
+ mutually exclusive with the other line before it which works for
+ regular zone files.
+
+2004-05-18 13:26 we7u
+
+ * src/map_shp.c: Added a comment.
+
+2004-05-18 12:54 we7u
+
+ * README.MAPS, src/map_shp.c, src/maps.c: Adding support for fire
+ zone maps. Works now for non-dbfawk compiles, but need to get
+ dbfawk working with them as well. The WXSVR should eventually
+ start sending these types of alerts to us on firenet.
+
+2004-05-18 09:42 we7u
+
+ * src/db.c: Had to move the variable declarations up in the code
+ block, else it fails compile on FreeBSD. Thanks to Tom Russo for
+ this fix.
+
+2004-05-17 13:06 we7u
+
+ * src/db.c: A small tweak to make the FCC/RAC lookup for
+ objects/items look at the FROM callsign instead of the
+ object/item names. Now we can look up who is sending the objects
+ in our database.
+
+2004-05-17 12:44 we7u
+
+ * src/db.c: Fixing the weather alert by "Station Info" lookups so
+ that it works for more objects from the weather server.
+
+2004-05-17 11:45 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/wx.h, src/wx_gui.c:
+ Adding the capability to finger the WXSVR if an object/item and
+ has "WXSVR" in the path. This is from a new button "Fetch NWS
+ Alert" in the Station Info dialog. It takes the place of the
+ FCC/RAC button if the above conditions are met.
+
+2004-05-13 10:17 we7u
+
+ * configure.ac: Moving the ImageMagick check so that it is the
+ absolute last check, so that it doesn't mess up the GDAL check
+ either. Added comments stating that the IM check should stay as
+ the last check.
+
+2004-05-13 09:51 we7u
+
+ * configure.ac: Moving the ImageMagick test to later in the
+ configuration. It appears to mess up the tests for other
+ libraries if it fails. Now only the GDAL test is below it.
+
+2004-05-12 13:49 we7u
+
+ * src/alert.c: Additional comments.
+
+2004-05-12 12:33 we7u
+
+ * scripts/overlay.pl: Correcting the math for lat/long.
+
+2004-05-12 11:56 we7u
+
+ * src/interface.c: Making sure that the AGWPE path is upper-case.
+
+2004-05-12 11:45 we7u
+
+ * src/interface.c: Fixing a bug in AGWPE path for objects/items.
+ This bug was caused by a different use of variables between the
+ output_aprs_data() and output_my_aprs_data() functions, and then
+ copying code from one to the other without changing the
+ variables. Variable names are now more common between them, so
+ this problem should be less likely to occur in the future.
+
+2004-05-12 09:44 we7u
+
+ * scripts/overlay.pl: Changes to comments.
+
+2004-05-12 09:16 we7u
+
+ * scripts/: overlay.pl, Makefile.am: Adding overlay.pl, which
+ creates either Xastir log file format or Xastir object.log format
+ files from CSV files. Used to create object overlays (actually
+ APRS Items in this case) out of spreadsheet data.
+
+2004-05-11 10:07 we7u
+
+ * README.win32: Added a comment about an error caused by line-wrap
+ in the Shapelib Makefile.
+
+2004-05-10 13:51 we7u
+
+ * src/: main.h, main.c: Adding #ifdef's for "OLD_PTHREADS", which
+ knock out the SIGUSR1 handler if "OLD_PTHREADS" is defined in
+ "main.h".
+
+2004-05-10 12:33 we7u
+
+ * src/db.c: Proper code for randomizing the object/item transmit
+ times a bit.
+
+2004-05-10 09:39 we7u
+
+ * scripts/Makefile.am: Adding a few of the newer scripts to the
+ install portion.
+
+2004-05-08 19:54 we7u
+
+ * src/: main.c, db.c: Tweaking the object/item timing to make sure
+ that any changes to an object cause the object to immediately go
+ to the initial state of the decay algorithm.
+
+2004-05-08 18:55 we7u
+
+ * src/db.c: Fixing the random number modulus operations for
+ transmitting objects/items. It appears however that the rand()
+ and random() functions are broken on this system, always
+ returning 0.
+
+2004-05-07 14:09 we7u
+
+ * src/db.c: Reducing the randomizing of object/item TX times from
+ 33% of interval to 20% of interval.
+
+2004-05-07 13:45 we7u
+
+ * src/db.c: Randomizing object/item transmit a bit so that they
+ don't get transmitted together when restarting with active
+ objects/items. This causes them to diverse fairly well after
+ about the third transmit iteration.
+
+2004-05-07 13:21 we7u
+
+ * src/util.c: Adding some comments.
+
+2004-05-07 11:02 we7u
+
+ * src/db.c: Fix for objects/items: If we're using the name of one
+ that has already been killed, we now delete the old record
+ completely before creating the new one. This keeps us from
+ drawing tracklines from one to the other or keeping info that
+ doesn't apply to the new object/item.
+
+2004-05-07 09:19 we7u
+
+ * src/util.c: Fixing the logging of objects/items. There were
+ problems with removing spaces from Items which made them not
+ found in the search, and problems with comments in front of lines
+ in the log file.
+
+2004-05-07 09:16 we7u
+
+ * src/: db.c, db.h: Comment changes. No code changes.
+
+2004-05-06 16:27 we7u
+
+ * src/messages.c: Reducing the initial time interval between
+ transmitted messages from 15 to 7 seconds.
+
+2004-05-06 16:19 we7u
+
+ * src/: db.h, messages.c: Minor comment changes.
+
+2004-05-06 14:40 we7u
+
+ * src/: db.h, db.c, main.c: Implementing the decaying algorithm for
+ timing of object/item transmits, similar to how Bob Bruninga does
+ it in aprsDOS. Also added a segfault fix for moving Items (same
+ fix as done earlier for moving Objects).
+
+2004-05-04 10:59 we7u
+
+ * INSTALL: Bumping rev. numbers for some of the optional libraries.
+
+2004-05-03 11:58 we7u
+
+ * README.MAPS: Added some geodesy links.
+
+2004-04-30 13:27 we7u
+
+ * INSTALL: Adding more URL's to lists of internet servers.
+
+2004-04-29 15:30 we7u
+
+ * FAQ: Adding a section describing the fixes for the CVS hostname
+ change at SourceForge.
+
+2004-04-28 14:43 shadow
+
+ * configure.ac: Test for linker support of -Wl,--no-keep-memory
+ rather than assuming it's safe everywhere; MacOS 10.3.x doesn't
+ support it.
+
+2004-04-27 09:23 we7u
+
+ * INSTALL: Added instructions for connecting to an internet server
+ plus a pointer to the current list of servers.
+
+2004-04-26 12:31 we7u
+
+ * README.win32: Additions by Henk de Groot. Thanks!
+
+2004-04-26 11:14 we7u
+
+ * INSTALL, README.win32: Shapelib links updates, thanks to Wes
+ Johnston for pointing this out.
+
+2004-04-23 10:46 we7u
+
+ * src/interface.c: OpenTrac patch by J. Lance Cotton, KJ5O.
+ Thanks!
+
+2004-04-23 10:35 we7u
+
+ * src/igate.c: Refusing to gate OpenTrac packets (which have been
+ converted to APRS-format by Xastir) to/from RF or the INET.
+
+2004-04-21 16:01 we7u
+
+ * src/main.c: Working version of the new Center & Zoom mouse menu
+ function.
+
+2004-04-21 14:59 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Starting to add a new
+ mouse menu entry: "Center & Zoom". Non-functional so far but
+ won't take much more work to finish it.
+
+2004-04-15 14:19 we7u
+
+ * README.win32: An update to the link-step memory-hog note.
+
+2004-04-15 10:12 we7u
+
+ * README.win32: Added a note about the link-stage being very memory
+ hungry/taking a lot of time to complete on Cygwin.
+
+2004-04-14 14:31 we7u
+
+ * configure.ac: Adding the no-keep-memory flag to LDFLAGS which
+ makes the link stage on Cygwin much faster.
+
+2004-04-14 10:12 we7u
+
+ * README.win32: Specifying a minimum set of xorg packages necessary
+ for installing the X11 stuff. Thanks to Henk for figuring this
+ out for us!
+
+2004-04-12 14:21 we7u
+
+ * configure.ac: Removing one line to make output prettier.
+
+2004-04-12 14:14 we7u
+
+ * README.win32: Updating the package names for X11 plus removing a
+ few packages that are unnecessary.
+
+2004-04-12 13:18 we7u
+
+ * README.win32: Changing names of Cygwin packages to correspond to
+ Cygwin's current naming scheme for the X11 server.
+
+2004-04-12 12:40 we7u
+
+ * README.win32: Removed the xwinclip package from the requirements
+ per Henk de Groot. Added notes by James Cour, K1ZC, and Tim
+ Baggett, AA5DF, regarding the network audio instructions.
+
+2004-04-09 13:07 we7u
+
+ * README.win32: Removing the "for future development" notes from
+ the pcre descriptions. We use that library for dbfawk support.
+
+2004-04-09 09:44 we7u
+
+ * README.MAPS: Adding more notes that might make the initial user's
+ decision easier as to which libraries to compile in for the
+ desired functionality.
+
+2004-04-08 09:14 we7u
+
+ * config/: Makefile.am, tgr2shp.dbfawk: Adding Tom Russo's
+ tgr2shp.dbfawk file to our standard set. Useful for the 2003
+ tiger data that just came out.
+
+2004-04-06 21:13 we7u
+
+ * INSTALL: Adding a note about needing "pcre" to compile in dbfawk
+ support.
+
+2004-04-06 09:21 we7u
+
+ * src/main.c: Adding a command-line option to deselect all maps:
+ "-m"
+
+2004-04-06 08:08 we7u
+
+ * src/map_shp.c: Fix by Tom Russo: If running with dbfawk, sets
+ everything to defaults in case a dbfawk file fails to reset
+ things when done.
+
+2004-04-05 13:14 we7u
+
+ * README.win32: Added a note about winclip.
+
+2004-04-02 17:19 we7u
+
+ * src/: geo.h, geocoder_gui.c: Extending the lengths of the input
+ fields for the Find Address function.
+
+2004-04-02 14:16 we7u
+
+ * README.win32: Added a note by Henk regarind lcms.
+
+2004-04-02 13:30 we7u
+
+ * README.MAPS: Added the Wiki page.
+
+2004-04-02 08:03 we7u
+
+ * configure.ac: Bumping the rev number.
+
+2004-04-01 09:11 we7u
+
+ * src/geo-find.c: Getting rid of some more compiler warnings.
+
+2004-04-01 07:25 we7u
+
+ * src/geocoder_gui.c: Fixing a compiler warning.
+
+2004-03-31 22:11 we7u
+
+ * src/util.c: Better implementation of the higher resolution s2l
+ routines.
+
+2004-03-31 20:46 shadow
+
+ * INSTALL, help/help-English.dat: document the find address feature
+
+2004-03-31 20:26 we7u
+
+ * src/util.c: Backing out the changes done earlier today. Will try
+ again to implement higher resolution NMEA strings at a later
+ date.
+
+2004-03-31 20:16 shadow
+
+ * README.MAPS: Add pointer to Census 2003 data. Add pointer to
+ geocoder data files.
+
+2004-03-31 10:56 we7u
+
+ * src/util.c: Extending the NMEA sentence decoding to handle DD
+ MM.MMMM format, which the new Tinytrak-3 chips can put out. That
+ resolution ends up being 0.6 counts of our Xastir coordinate
+ system, so we need to resolve down to that level to avoid losing
+ much.
+
+2004-03-30 14:58 we7u
+
+ * src/db.c: Changing from circles to an 'X' for marking a found
+ address.
+
+2004-03-30 12:49 we7u
+
+ * src/xa_config.c: Saving/restoring the Mark Destination button
+ state for the Find Address function.
+
+2004-03-30 12:44 we7u
+
+ * src/: db.c, geo.h, geocoder_gui.c: Added a togglebutton that
+ enables/disables the marking of the destination for the Find
+ Address function.
+
+2004-03-30 12:21 we7u
+
+ * src/: db.c, geo.h, geocoder_gui.c: Initial attempt at marking the
+ destination target for a Find Address query. There's not
+ capability yet for removing the marking, but you can always seek
+ another address and it will move to the new one. Will probably
+ change to some other marking at some point (a big 'X' perhaps?),
+ and need to find a way to remove the mark that makes sense.
+
+2004-03-30 08:58 we7u
+
+ * src/geocoder_gui.c: Minor re-arranging of the Find Address
+ dialog's widgets.
+
+2004-03-29 15:57 we7u
+
+ * src/io-mmap.c: Adding an include to get rid of compiler warnings
+ about memcpy().
+
+2004-03-29 15:40 we7u
+
+ * src/: LICENSE.geocoder, geo-client.c, geo-find.c, geo.h,
+ geocoder_gui.c, io-common.c, io-mmap.c, io.h, Makefile.am,
+ main.c, main.h, xa_config.c: Geocoding support added by Derrick J
+ Brashear, based off code written by Daniel Egenor that was
+ released under GPL license.
+
+2004-03-26 10:17 we7u
+
+ * Makefile.am: Moving the .geo files into a subdirectory called
+ "Online".
+
+2004-03-25 08:35 we7u
+
+ * src/gps.c: Enabling setuid priviledge at the point where
+ settimeofday() is called. Thanks to William Baguhn, kc9asi, for
+ pointing this out.
+
+2004-03-24 17:29 shadow
+
+ * src/macspeech.c: macspeech support, but i need to write autoconf
+ gunk, it just pretends to be festival
+
+2004-03-23 15:12 we7u
+
+ * INSTALL, README.win32: Updating Cygwin instructions: com1 ->
+ /dev/ttyS0 and similar for com2.
+
+2004-03-23 14:59 we7u
+
+ * acinclude.m4: Tweaking Cygwin serial ports to more standard port
+ names.
+
+2004-03-23 10:01 we7u
+
+ * src/wx.c: Changes by Bruce Bennett.
+
+2004-03-22 14:12 we7u
+
+ * src/map_geo.c: Moving an #ifdef so that no compiler warnings are
+ generated when ImageMagick support is missing.
+
+2004-03-22 13:52 we7u
+
+ * acinclude.m4: Fixes for Cygwin regarding comm ports.
+
+2004-03-22 09:23 we7u
+
+ * README.win32: Adding instructions to side-step the "detecting
+ devices" hang on WinXP.
+
+2004-03-21 12:58 rzg
+
+ * help/help-English.dat: Added info on the comment field in
+ interfaces; started a new tally of what changed since release.
+
+2004-03-19 14:38 we7u
+
+ * src/map_gnis.c: Removing trailing spaces while reading lines in
+ from GNIS files. They are notorious for having many spaces at
+ the ends of the lines.
+
+2004-03-19 12:37 we7u
+
+ * src/map_shp.c: The rest of the code needed for the
+ XReadBitmapFile() call failure, in order to make sure everything
+ keeps running.
+
+2004-03-19 12:34 we7u
+
+ * src/map_shp.c: Getting rid of the exit(1) that we were doing when
+ the XReadBitmapFile() call was failing during long runtimes.
+ It's annoying if the bitmap is not found but it shouldn't kill
+ all of Xastir in that case. I'll be checking to see if further
+ changes to the code are necessary though to prevent segfaults
+ happening later in that part of the code.
+
+2004-03-19 09:52 we7u
+
+ * scripts/split_gnis.pl: Added an RCS tag. Still needs a copyright
+ blurb.
+
+2004-03-19 09:51 we7u
+
+ * src/interface.c: Fixing the long transmit delay, which was in
+ port_write at the final select() call.
+
+2004-03-18 19:21 jtwilley
+
+ * scripts/split_gnis.pl:
+
+ Added split_gnis.pl to scripts directory.
+
+ The split_gnis.pl script will take any number of state-wide GNIS
+ files listed on the command line and create smaller files based
+ on county names.
+
+2004-03-18 15:14 we7u
+
+ * src/maps.c: Adding S57 map format to Xastir's supported map
+ types. File extension currently has to be ".s57" for these types
+ of maps to be recognized by Xastir.
+
+2004-03-18 10:11 we7u
+
+ * scripts/ozi2geo.pl: Changed one comment.
+
+2004-03-18 09:58 we7u
+
+ * scripts/ozi2geo.pl: Initial attempt at a conversion script from
+ OziExplorer .map format to Xastir's .geo format. This version
+ works with the one example map I had to work with. More than
+ likely more work will be needed on the script as more types of
+ maps are tried.
+
+2004-03-15 15:49 we7u
+
+ * scripts/split_gnis.bash: Added a comment about "dos2unix".
+
+2004-03-15 15:47 we7u
+
+ * scripts/split_gnis.bash: Script written by William Baguhn,
+ kc9asi. Splits a GNIS files into smaller pieces which are more
+ quickly loaded by Xastir when zoomed in.
+
+2004-03-15 09:08 we7u
+
+ * USRadar.geo: Tweaks by Gerry Creager.
+
+2004-03-12 20:54 we7u
+
+ * USRadar.geo: Mods by Gerry Creager.
+
+2004-03-10 20:11 we7u
+
+ * src/interface_gui.c: Implementing GUI input fields for the
+ Interface->Properties "comment" field for each interface.
+
+2004-03-10 09:50 we7u
+
+ * src/interface_gui.c: Minor comment change.
+
+2004-03-09 14:59 we7u
+
+ * README.MAPS: Another note from Tom Russo on converting between
+ datums.
+
+2004-03-09 13:18 we7u
+
+ * src/interface_gui.c: Adding some bookmarks. Places that might
+ need to be tweaked for MKISS.
+
+2004-03-09 08:47 we7u
+
+ * src/interface_gui.c: Wiping out old interface params from config
+ file when an interface is deleted.
+
+2004-03-09 08:34 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface_gui.c: Minor tweaks to
+ the MKISS GUI. Not functional yet.
+
+2004-03-08 22:54 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Updated language
+ strings for MKISS and interface comments.
+
+2004-03-08 22:42 we7u
+
+ * src/: db.c, interface_gui.c, xa_config.c: Adding new MKISS
+ interface (not complete yet). Adding interface comment
+ capability.
+
+2004-03-08 22:32 we7u
+
+ * src/interface.h: Adding new fields. Needed for MKISS interface
+ and for adding comments to interfaces.
+
+2004-03-08 13:16 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Updates to
+ language strings for MKISS TNC's.
+
+2004-03-08 13:13 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/igate.c,
+ src/interface.c, src/interface.h, src/interface_gui.c,
+ src/main.c: Initial stab at creating a new SERIAL_MKISS interface
+ type. So far it's an identical copy of the SERIAL_KISS interface
+ type, but that will change soon. Intent is to support multi-port
+ KISS TNC's such as the Kantronics KAM.
+
+2004-03-04 15:12 we7u
+
+ * USRadar.geo, help/help-English.dat, src/color.c, src/color.h,
+ src/map_geo.c, src/maps.h: Fix for the TRANSPARENT tag in .geo's:
+ Wasn't working right on 16-bit versus 24-bit Xwindows servers.
+
+2004-03-03 14:54 we7u
+
+ * src/map_geo.c: Toporama map speedups made possible by Steve
+ Dimse's changes on the server.
+
+2004-03-02 13:19 we7u
+
+ * README.win32: A note by Steve Peters, N1TYE, regarding the lcms
+ library on Cygwin.
+
+2004-03-02 09:56 we7u
+
+ * src/map_geo.c: Terraserver is playing games, changing their URL
+ again. Changing back to the original one we used to use, which
+ works for us again. The newer URL was returning all black
+ images.
+
+2004-03-02 00:10 we7u
+
+ * src/map_geo.c: Commenting out debug output.
+
+2004-03-02 00:07 we7u
+
+ * src/maps.c: Sending tab map files to draw_ogr_map().
+
+2004-03-01 23:50 we7u
+
+ * Makefile.am, src/map_geo.c: Initial version of code to support
+ Canadian Toporama maps, downloading them automatically over the
+ 'net from mm.aprs.net, including the dynamically generated .geo
+ files.
+
+2004-03-01 23:47 we7u
+
+ * CanadaTopo250k.geo, CanadaTopo50k.geo: Initial checkin.
+
+2004-03-01 09:31 we7u
+
+ * README.MAPS: Changing notes regarding where to find free DRG
+ maps.
+
+2004-02-29 18:40 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface_gui.c: Tweaking the
+ Interface Start/Stop dialog so that it is much more readable.
+
+2004-02-29 12:31 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c, src/main.h,
+ src/xa_config.c: Added two new trail sliders to the timing
+ dialog. They both control whether trails are displayed, one
+ based on max distance, one based on max time. If either max
+ distance or max time are exceeded for new trails, that segment is
+ not drawn. Does not affect trail points that have already been
+ received, just new trail points.
+
+2004-02-27 19:12 we7u
+
+ * src/main.c: Modifying the Move function so that it drops through
+ all the dialogs and doesn't require any OK buttons to be pressed
+ to effect the move. This is useful for drawing the expected
+ route of a SAR team and documenting it via Shapefiles. It's much
+ faster to do so now. Downside: Unintentionally moving an object
+ gets an automatic confirm, and you'll have to move it back
+ manually or else edit the object.log file by hand and read it in
+ again.
+
+2004-02-27 18:00 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/xa_config.c: Adding
+ a "Disable Posit Dupe-Checks" option to Configure->Defaults.
+ Disables the 30-minute dupe-checks that Xastir does when each
+ packet is received. Does not affect igate dupe-checks.
+
+2004-02-27 17:26 we7u
+
+ * src/: db.c, main.h, util.c: Turning off trail-point dupe-checking
+ when reading in objects/items from file. This lets us show SAR
+ teams leaving and returning to base later, without having the
+ last trail segment missing.
+
+2004-02-27 17:00 we7u
+
+ * src/db.c: Updating some comments.
+
+2004-02-27 15:42 we7u
+
+ * help/help-English.dat: Adding notes about trails and why some
+ segments don't display.
+
+2004-02-27 14:58 we7u
+
+ * src/db.c: Changing the distance at which Xastir will skip a track
+ segment, from >1 degree lat/long to >2 degrees. Any track
+ segment less than 2 degrees in N/S and E/W length will get drawn,
+ as long as the time between posits is less than 45 minutes. If
+ over 45 minutes, the segment gets skipped as well.
+
+2004-02-26 15:25 we7u
+
+ * src/interface.c: New code to avoid opening the same serial port
+ twice for two different interfaces.
+
+2004-02-26 15:19 we7u
+
+ * src/db.c: Changing some debug code.
+
+2004-02-26 13:48 we7u
+
+ * INSTALL: Added a note about how to test the festival server by
+ telnet'ing to it.
+
+2004-02-26 12:30 we7u
+
+ * src/: map_geo.c, map_tiger.c, track_gui.c: Fixing the problem
+ where a failed internet download (map or tracklog) would cause an
+ older version of the same to get displayed. We now delete the
+ old filename from our ~/.xastir/tmp directory before attempting
+ the download each time.
+
+2004-02-26 12:07 we7u
+
+ * src/: db.c, db.h: Adding a retry timeout for killed object/items.
+ We'll now transmit killed objects 11 times before ceasing to
+ transmit them.
+
+2004-02-24 11:34 we7u
+
+ * README: Additions by Alan Shackelford, NG3B.
+
+2004-02-24 09:28 we7u
+
+ * README.MAPS: More good info from Tom Russo, KM5VY.
+
+2004-02-23 14:52 we7u
+
+ * README.MAPS: Added the FIPS locator URL. Useful stuff!
+
+2004-02-21 22:32 we7u
+
+ * INSTALL: Updating some libtiff/libgeotiff notes.
+
+2004-02-21 12:35 kd6zwr
+
+ * src/map_shp.c: Add label levels for point style shapefiles when
+ using dbfawk
+
+2004-02-13 13:40 we7u
+
+ * src/maps.c: Fixing the prime meridian line for UTM grid. Wasn't
+ being drawn at all zoom levels.
+
+2004-02-13 08:54 we7u
+
+ * README.win32: Added a warning about KDE.
+
+2004-02-12 14:18 we7u
+
+ * src/: interface.h, interface.c: New method of waiting for data to
+ get to serial TNC's before closing the port. Method and most of
+ the code contributed by Erik G. Burrows, KG6HEA. Additional code
+ by WE7U to prevent locking up with poorly-behaved serial devices.
+
+2004-02-11 14:40 we7u
+
+ * src/map_geo.c: Making transparent images work again after the
+ raster_intensity changes a few weeks back.
+
+2004-02-11 13:35 we7u
+
+ * src/main.c: Fixing an annoying floating-point conversion bug in
+ the Map Intensity menus. For 70% and 90%, they were reported as
+ 60% and 80% in the menus.
+
+2004-02-11 10:24 we7u
+
+ * Makefile.am, USRadar.geo, src/map_geo.c, src/maps.h: Changing to
+ an unsigned long for holding the transparency value. Adding
+ USRadar.geo as an installed map ('cuz it's just way cool).
+
+2004-02-10 14:18 we7u
+
+ * src/db.c: Making the 'h' in timestamp be case-insensitive on
+ receive.
+
+2004-02-10 14:18 we7u
+
+ * src/db.c: Making the 'h' in a timestamp be case-insensitive on
+ receive.
+
+2004-02-09 12:20 we7u
+
+ * src/db.c: Making N/S/E/W and the timestamp 'Z' non case-specific.
+ This was requested by Bob Bruninga on the APRSSIG mailing list
+ recently (sometime in january 2004, before our last stable
+ release).
+
+2004-02-06 14:39 we7u
+
+ * src/interface_gui.c: Changing default path from RELAY,WIDE to
+ WIDE.
+
+2004-02-06 13:33 we7u
+
+ * configure.ac, src/main.c: Adding a list of the compiled-in
+ libraries to the Help->About dialog.
+
+2004-02-05 11:00 we7u
+
+ * INSTALL, README.CVS, README.win32: Updating CVS instructions
+ because SourceForge isn't handling compression currently.
+
+2004-02-04 12:41 we7u
+
+ * bootstrap.sh: Adding the CVS tag line.
+
+2004-02-04 08:49 we7u
+
+ * src/: main.c, map_shp.c: Changing some error messages to provide
+ more detail.
+
+2004-02-02 23:10 we7u
+
+ * README.win32: Mods by David Flood, KD7MYC. Thanks!
+
+2004-02-02 14:31 we7u
+
+ * configure.ac: Bumping the patch number so we can separate
+ development versions from most recent stable release.
+
+2004-02-02 13:41 we7u
+
+ * config/language-German.sys: Updates by Rolf, DK7IN.
+
+2004-02-02 12:58 we7u
+
+ * src/main.c: Updating the Help->About message. Thanks for
+ reminding me Ren!
+
+2004-02-02 08:37 we7u
+
+ * configure.ac: Bumping the revision to 1.3.0. Getting ready for
+ stable release.
+
+2004-02-02 08:35 we7u
+
+ * help/help-English.dat: Very minor changes to the What's New
+ section.
+
+2004-02-01 23:26 rzg
+
+ * help/help-English.dat: Moved old "What's new" list out of the
+ way.
+
+2004-02-01 23:23 rzg
+
+ * help/help-English.dat: What's new section. Could use proofreading
+ and the addition of stuff I forgot.
+
+2004-01-30 15:48 shadow
+
+ * README: update README to reflect what's needed to get MacOS X
+ with GDAL.
+
+2004-01-30 13:51 we7u
+
+ * xastir.spec.in: Correcting the path to the man pages.
+
+2004-01-30 10:12 we7u
+
+ * symbols/symbols.dat: Implemented Wheelchair, Shelter, and
+ proposed Waypoint symbol. Also changed one description from "HF
+ Gateway" to "Any Gateway (w/overlay char)". The "Any Gateway"
+ symbol still needs to be changed into something which would
+ display an overlay char nicely. The Shelter symbol may need to
+ be changed into something more recognizable.
+
+2004-01-29 17:47 n2ygk
+
+ * xastir.spec.in: --with-dbfawk. Curt: toss this if you feel
+ dbfawk is not cooked enough.
+
+2004-01-29 08:53 we7u
+
+ * INSTALL: Updating the gpsman/gpsmanshp instructions for systems
+ with tcl8.4 instead of tcl8.3.
+
+2004-01-28 10:42 we7u
+
+ * AUTHORS: Got rid of reference to non-existent file. Add note
+ stating we don't try to keep this file up to date.
+
+2004-01-28 10:11 we7u
+
+ * UPGRADE: Added more notes about migrating to latest Xastir.
+
+2004-01-28 09:42 we7u
+
+ * README.CVS: Added another note about sticky tags.
+
+2004-01-26 12:50 we7u
+
+ * INSTALL: Adding a note about the port names for Cygwin.
+
+2004-01-26 08:18 we7u
+
+ * src/: Makefile.am, alert.c, alert.h, awk.c, awk.h,
+ bulletin_gui.c, bulletin_gui.h, color.c, color.h, datum.c,
+ datum.h, db.c, db.h, dbfawk.c, dbfawk.h, draw_symbols.c,
+ draw_symbols.h, fcc_data.c, fcc_data.h, festival.c, festival.h,
+ gps.c, gps.h, hostname.c, hostname.h, igate.c, igate.h,
+ interface.c, interface.h, interface_gui.c, lang.c, lang.h,
+ list_gui.c, list_gui.h, locate_gui.c, location.c, location_gui.c,
+ main.c, main.h, map_dos.c, map_gdal.c, map_geo.c, map_gnis.c,
+ map_pdb.c, map_shp.c, map_tif.c, map_tiger.c, maps.c, maps.h,
+ messages.c, messages.h, messages_gui.c, popup.h, popup_gui.c,
+ rac_data.c, rac_data.h, rotated.c, rotated.h, snprintf.c,
+ snprintf.h, sound.c, symbols.h, testawk.c, track_gui.c,
+ track_gui.h, util.c, util.h, view_message_gui.c, wx.c, wx.h,
+ wx_gui.c, x_spider.c, x_spider.h, xa_config.c, xa_config.h,
+ xastir.h: Updating copyright notices.
+
+2004-01-26 08:11 we7u
+
+ * LICENSE, README.win32, callpass/Makefile.am, callpass/callpass.c,
+ config/Makefile.am, config/language-Dutch.sys,
+ config/language-English.sys, config/language-French.sys,
+ config/language-German.sys, config/language-Italian.sys,
+ config/language-Portuguese.sys, config/language-Spanish.sys,
+ config/nwsc_ddmmyy.dbfawk, config/nwsmzddmmyy.dbfawk,
+ config/nwsozddmmyy.dbfawk, config/nwsw_ddmmyy.dbfawk,
+ config/nwsz_ddmmyy.dbfawk, config/tgrcty.dbfawk,
+ config/tgrkgl.dbfawk, config/tgrlk.dbfawk, config/tgrlpt.dbfawk,
+ config/tgrlpy.dbfawk, config/tgrplc00.dbfawk,
+ config/tgrwat.dbfawk, config/tnc-startup.aea,
+ config/tnc-startup.kam, config/tnc-startup.kpc3,
+ config/tnc-startup.paccomm, config/tnc-startup.pico,
+ config/tnc-startup.sys, config/tnc-startup.thd7,
+ config/tnc-stop.sys, help/Makefile.am, help/help-Dutch.dat,
+ help/help-English.dat, help/help-French.dat,
+ help/help-German.dat, help/help-Italian.dat,
+ help/help-Portuguese.dat, help/help-Spanish.dat, m4/Makefile.am,
+ scripts/Makefile.am, scripts/example_objects.log,
+ scripts/fcc-get, scripts/xastir-fixcfg.sh,
+ scripts/xastir-migrate.sh, symbols/Makefile.am,
+ symbols/symbols.dat: Updating copyright notices.
+
+2004-01-26 08:09 we7u
+
+ * AUTHORS, DEBUG_LEVELS, INSTALL, Makefile.am, NEWS, README,
+ README.CVS, README.MAPS, UPGRADE, acinclude.m4, bootstrap.sh,
+ changes.txt, configure.ac, xastir.1, xastir.spec.in: Updating
+ copyright notices. Adding a few more docs to the spec file.
+
+2004-01-22 19:26 we7u
+
+ * src/xa_config.c: Adding sys/stat.h call that is needed to compile
+ this file on MacOSX.
+
+2004-01-22 18:34 we7u
+
+ * README.CVS: Updating the "unsticky" instructions for CVS.
+
+2004-01-21 16:14 rzg
+
+ * FAQ: Added a bit on support, fixed numbering, a typo, and
+ copyright year.
+
+2004-01-21 15:48 we7u
+
+ * README.CVS: Added the "diff" line to .cvsrc note. Added "sticky"
+ tags STABLE and RELEASE and explanations of how to use them.
+
+2004-01-21 08:47 we7u
+
+ * src/xa_config.c: Changing default for "Expand Dirs" in Map
+ Chooser to 1. Better for new users.
+
+2004-01-20 13:34 we7u
+
+ * FAQ: Another note about ImageMagick dependencies and "spec"
+ files.
+
+2004-01-20 13:32 we7u
+
+ * FAQ: Adding some notes about ImageMagick and failed dependencies.
+
+2004-01-19 15:02 we7u
+
+ * src/maps.c: Attempting to fix an indexing bug. New files are not
+ picked up by indexing. This fix picks the later of ctime/mtime
+ to use for the timestamp. Contributed by Reuven.
+
+2004-01-19 13:33 we7u
+
+ * src/: main.c, maps.c: Commented out some dead code in maps.c.
+ Added new USR1 signal handler code by Tim Gimmel, KB4AMA. Just
+ send a USR1 signal via "kill -USR1 <pid>" and Xastir will create
+ a new snapshot. Useful for web page front-ends.
+
+2004-01-16 12:25 gstueve
+
+ * src/: alert.c, alert.h: Change numeric index references in flags
+ to symbolic and fixed end-of-data to match sizeof data not fixed
+ numeric values.
+
+2004-01-16 12:18 gstueve
+
+ * scripts/fcc-get: Update for new diretory layout with generic path
+ name & add passive ftp.
+
+2004-01-16 10:14 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.h, src/wx.c: Initial support
+ for Davis Weather Monitor II, Wizard III, and Vantage Pro weather
+ stations, written by Bruce Bennett. Thanks Bruce!
+
+2004-01-15 13:28 we7u
+
+ * src/xa_config.c: Attempting to recover from backup file renaming
+ when things go wrong. We'll try to get as close to the original
+ state of the files as we can.
+
+2004-01-15 13:09 we7u
+
+ * src/xa_config.c: More config file backup copies code. We now
+ back out the renaming if the new config file can't be created, so
+ we're left with the original config and two backups in that case.
+
+2004-01-15 11:02 we7u
+
+ * FAQ, src/interface.c, src/interface_gui.c, src/xa_config.c:
+ Simplified the all interfaces up/down logic. It should work
+ better now. Changed the config file backup code so that
+ xastir.cnf.1 through xastir.cnf.3 are created. This should help
+ insulate us a bit better from crashes, as we'll have more old
+ copies of the config file to draw from if the main config file
+ (xastir.cnf) gets trashed.
+
+2004-01-15 08:56 we7u
+
+ * configure.ac: Adding a line in for getting rid of duplicates in
+ the LIBS variable. Commented out while testing so that it
+ doesn't hurt any installations.
+
+2004-01-14 15:07 we7u
+
+ * src/main.c: Adding more sprintf's in cases of failure to create
+ symlinks.
+
+2004-01-14 12:07 we7u
+
+ * configure.ac: Extending one comment. No code changes.
+
+2004-01-14 12:00 we7u
+
+ * src/main.c: Minor tweak to two fprintf strings.
+
+2004-01-12 11:44 we7u
+
+ * src/main.c: Changing back to a previous configuration for the end
+ of the create_appshell() function. Attempting to get rid of this
+ problem: "attempt to add non-widget child "DropSiteManager" to
+ parent "xastir" which support only widgets" while not
+ re-creating this problem: "Shell widget xastir has zero width
+ and/or height".
+
+2004-01-09 10:57 rzg
+
+ * help/help-English.dat, src/maps.c: Map index checking now allows
+ negative layer numbers. Minor helpfile updates
+
+2004-01-09 08:11 we7u
+
+ * src/map_gdal.c: More checks for invalid extents while indexing.
+ If all 0's or outside indexes of the earth, we skip adding it to
+ the index.
+
+2004-01-08 13:38 we7u
+
+ * src/main.c: Re-establishing the XtRealizeWidget() call in main
+ that was commented out to help fix the "zero width or height"
+ error on startup. Now we specify a minimum size in the
+ XtVaAppInitialize() call that preceeds it, so the old problem
+ shouldn't reoccur.
+
+2004-01-08 13:34 we7u
+
+ * src/main.c: Gives an initial size to the application. Makes it
+ appear to come up faster. Whether or not it actually does is
+ beside the point. May help to get rid of the initial sizing
+ problem: "Error: Shell widget xastir has zero width and/or
+ height".
+
+2004-01-07 08:42 we7u
+
+ * configure.ac: Minor tweaks to some AC_MSG_ERROR calls.
+
+2004-01-07 08:42 we7u
+
+ * INSTALL: Minor tweaks to the make instructions here and there.
+
+2004-01-04 13:37 we7u
+
+ * src/map_gdal.c: Correcting the limits for OGR indexing.
+
+2003-12-30 07:38 we7u
+
+ * src/maps.c: Changing startup STDERR output to show which library
+ (Shapelib/OGR) is providing Shapefile support.
+
+2003-12-26 09:26 we7u
+
+ * src/interface.c: Bumping the read/write loop timeouts to 100ms.
+ This should provide reasonable response time when killing ports,
+ yet keep CPU usage low when no data is being read/written.
+
+2003-12-26 08:17 we7u
+
+ * src/interface.c: Bumping the timeout in port_write() select to
+ 500ms. That timeout is used to jump out of the select() so that
+ we can check whether the interface has gone down. It does not
+ need to be very small, and in fact causes high CPU usage on
+ freebsd systems if it's below about 1ms. Linux can handle
+ somewhat smaller delays (100us is ok on Linux).
+
+2003-12-24 17:07 rzg
+
+ * help/help-English.dat: Whatsnew update, and tigermap.geo is
+ back...
+
+2003-12-23 17:49 we7u
+
+ * src/: main.c, map_gdal.c, maps.c, xastir.h: Added another output
+ line to the segfault handler. Minor tweaks to the OGR code.
+
+2003-12-23 07:25 we7u
+
+ * src/map_gdal.c: Added some comments.
+
+2003-12-22 18:59 we7u
+
+ * src/map_gdal.c: Starting to add map preferences code to the OGR
+ map-drawing functions.
+
+2003-12-20 16:18 we7u
+
+ * src/main.c: Getting rid of a couple of messages used for cad
+ object debug. Put them inside ifdef's.
+
+2003-12-19 16:28 we7u
+
+ * src/: map_geo.c, map_shp.c, map_tiger.c: Fixing
+ raster_map_intensity for tiger and .geo maps. Changes in
+ comments and remove of debugging code in map_shp.c
+
+2003-12-19 13:33 we7u
+
+ * src/map_geo.c: Minor tweak to make toposerver files work again
+ and make the .geo code look like the tiger code w.r.t. image
+ intensity.
+
+2003-12-19 12:59 we7u
+
+ * src/map_gdal.c: Improvements to the line drawing routines mostly.
+ OGR stuff.
+
+2003-12-19 12:59 we7u
+
+ * src/maps.c: Major speed improvements to map_onscreen(),
+ map_visible(), and map_visible_lat_lon() routines.
+
+2003-12-19 12:58 we7u
+
+ * src/main.c: Moved routines around. No code changes.
+
+2003-12-18 16:04 we7u
+
+ * src/map_gdal.c: Tweaks to OGR polygons.
+
+2003-12-18 13:06 we7u
+
+ * src/map_gdal.c: Working X11 Regions for drawing OGR "hole" or
+ innner polygons.
+
+2003-12-18 07:06 we7u
+
+ * src/alert.c: Zero'ing out newly-added alert entries after each
+ realloc() call.
+
+2003-12-17 22:45 we7u
+
+ * src/map_tiger.c: ImageMagick brightness code change by Jim
+ Chandler, N0VH.
+
+2003-12-17 22:40 we7u
+
+ * src/map_gdal.c: Starting to add the framework for doing X11
+ Regions. Will allow doing "fill" and "hole" polygons as we
+ currently do in the Shapelib code.
+
+2003-12-17 13:07 we7u
+
+ * src/map_gdal.c: More comments.
+
+2003-12-17 12:58 we7u
+
+ * src/map_gdal.c: Minor comment changes.
+
+2003-12-17 12:56 we7u
+
+ * src/map_gdal.c: More fill/hole polygon stuff. Currently drawing
+ polygons with dashed lines for "hole" polygons, solid for "fill"
+ polygons. This is if the use has decided not to fill the shapes.
+ For filled shapes, the hole polygons aren't drawn at all
+ currently.
+
+2003-12-17 12:36 we7u
+
+ * src/map_gdal.c: More comments. Starting to add polygon fill/hole
+ differentiation code.
+
+2003-12-17 12:06 we7u
+
+ * src/map_gdal.c: More comments.
+
+2003-12-17 10:24 we7u
+
+ * src/map_gdal.c: Comment changes only.
+
+2003-12-17 07:42 we7u
+
+ * src/map_gdal.c: Fixing OGR polygons so they work again, still
+ non-filled though.
+
+2003-12-17 07:14 we7u
+
+ * src/map_gdal.c: More comment changes.
+
+2003-12-17 07:04 we7u
+
+ * src/map_gdal.c: Changing default colors and changing a few
+ comments. The colors won't stay, but they're useful at the
+ moment for debugging.
+
+2003-12-16 12:08 we7u
+
+ * src/maps.c: Added some comments.
+
+2003-12-16 10:16 we7u
+
+ * src/interface.c: Fixes to make the OpenTrac tweaks compile
+ properly.
+
+2003-12-16 10:09 we7u
+
+ * src/interface.c: Fixes to OpenTrac decoding by Scott Miller.
+
+2003-12-16 08:19 we7u
+
+ * src/alert.c: An attempt to skip over alert_list[] entries that
+ are zeroed (title has '\0' as the first character) while doing an
+ alert_match().
+
+2003-12-15 09:19 we7u
+
+ * src/interface.c: Patch by Brian Heaton to prefix the port number
+ to the incoming string we dump out via our segfault handler.
+
+2003-12-15 07:56 we7u
+
+ * README.MAPS: Added another SDTS note.
+
+2003-12-13 10:36 we7u
+
+ * INSTALL: Added another GDAL comment.
+
+2003-12-13 10:33 we7u
+
+ * src/map_gdal.c: Moved some XSet... calls down into the OGR
+ drawing section. Above the indexing section they caused
+ segfaults. We must not be calling the indexing functions with a
+ valid widget?
+
+2003-12-12 17:16 we7u
+
+ * README.MAPS: Adding more map links for some new map formats.
+
+2003-12-12 13:20 we7u
+
+ * src/map_gdal.c: Faster OGR polygons. Transforming all of the
+ points at once for each polygon.
+
+2003-12-12 13:02 we7u
+
+ * src/map_gdal.c: Faster OGR line drawing. Recognize more datums
+ that we don't have to convert (faster again).
+
+2003-12-12 12:31 we7u
+
+ * src/map_gdal.c: Removing unneeded code. Adding more comments.
+
+2003-12-12 12:24 we7u
+
+ * src/map_gdal.c: Adding comments.
+
+2003-12-12 12:20 we7u
+
+ * src/map_gdal.c: Renaming OGR helper functions to make sure there
+ aren't any clashes later with similar functions.
+
+2003-12-12 12:17 we7u
+
+ * src/map_gdal.c: Speeding up OGR Point drawing. Changing default
+ point color to white.
+
+2003-12-12 12:03 we7u
+
+ * src/map_gdal.c: Faster OGR line/polygon drawing by checking
+ extents on those datatypes that allow fast extent checking.
+
+2003-12-12 12:02 we7u
+
+ * configure.ac: Minor summary text change.
+
+2003-12-12 08:23 we7u
+
+ * src/map_gdal.c: Added TODO list for OGR and moved the Draw
+ routines above the main OGR routine (getting rid of the
+ prototypes).
+
+2003-12-12 08:04 we7u
+
+ * README.MAPS: Added a note about SDTS files.
+
+2003-12-12 07:46 we7u
+
+ * src/map_gdal.c: A bit of cleanup in the new OGR routines.
+
+2003-12-12 07:30 we7u
+
+ * src/map_gdal.c: Creating OGR Draw_Points() function which is
+ similar to the Draw_Lines() and Draw_Polygons() functions. Skips
+ drawing points that are outside the view.
+
+2003-12-12 06:55 we7u
+
+ * INSTALL: Changes to the GDAL/OGR notes.
+
+2003-12-11 17:50 we7u
+
+ * src/map_gdal.c: Optimizing Draw_Lines() and Draw_Polygons()
+ functions in the OGR routines. We now check the extents of each
+ feature and skip drawing it if it's not in our view.
+
+2003-12-11 12:35 we7u
+
+ * src/: main.c, map_gdal.c: Fixing map_interrupts so that they work
+ properly and quickly. A few places were broken, including the
+ new OGR code.
+
+2003-12-11 11:42 we7u
+
+ * src/map_gdal.c: Changed some variable names. Added some debug
+ code, looking for sources of memory leaks.
+
+2003-12-10 22:43 we7u
+
+ * INSTALL: Added a new site for Shapelib.
+
+2003-12-10 16:31 we7u
+
+ * src/map_gdal.c: On-the-fly coordinate transforms while drawing.
+
+2003-12-10 11:14 we7u
+
+ * src/maps.c: Adding more map types that are accepted by OGR.
+
+2003-12-10 10:18 we7u
+
+ * src/map_gdal.c: Changed some comments.
+
+2003-12-10 10:16 we7u
+
+ * src/maps.c: Adding mif/mid (Mapinfo) to list of accepted map
+ types for OGR.
+
+2003-12-10 00:01 we7u
+
+ * src/map_gdal.c: Minor reformatting.
+
+2003-12-09 23:13 we7u
+
+ * src/map_gdal.c: Added a comment.
+
+2003-12-09 17:03 we7u
+
+ * src/map_gdal.c: Better Polygons for OGR.
+
+2003-12-09 12:27 we7u
+
+ * src/map_gdal.c: Drawing of OGR polygons is now working.
+
+2003-12-09 08:55 we7u
+
+ * src/map_gdal.c: Slightly faster drawing code due to fewer sets of
+ debug loops. More comments.
+
+2003-12-09 00:22 we7u
+
+ * src/: map_gdal.c, maps.c, maps.h: Added a new draw function for
+ points. More tweaks to the OGR code.
+
+2003-12-08 15:43 we7u
+
+ * src/interface.c: Checking that I can stat a file and that it is a
+ regular file before attempting to send a file of commands to the
+ TNC.
+
+2003-12-08 13:22 we7u
+
+ * src/map_gdal.c: Adding indexing for files where spatial
+ coordinate system is not known, but they still fall within the
+ normal lat/long boundaries for file extents. We're assuming
+ they're in geographic WGS84 coordinates in this case and allowing
+ the indexing to complete.
+
+2003-12-08 12:56 jtwilley
+
+ * config/tnc-startup.null: Added a zero-byte file named
+ 'tnc-startup.null' for those times when users do not want their
+ TNC configurations changed by xastir.
+
+2003-12-08 12:19 we7u
+
+ * src/map_gdal.c: Comment updates. No code changes this time.
+
+2003-12-08 12:10 we7u
+
+ * src/map_gdal.c: Took out some debug stuff that messed with
+ converting to nad27 datum for test runs. Generalized the code so
+ that it works with projected coordinate systems. No computes
+ file extents for state-plane coordinate systems. It should also
+ work for UTM projected coordinate systems.
+
+2003-12-07 23:50 we7u
+
+ * src/map_gdal.c: For file extents (indexing): Datum translation
+ is working now for geographic coordinate systems. Not
+ implemented yet for projected coordinate systems. Haven't
+ implemented datum translation for drawing yet.
+
+2003-12-07 23:47 we7u
+
+ * src/maps.c: Forcing shapefiles back to the old code for now.
+
+2003-12-07 23:46 we7u
+
+ * src/maps.c: More debug for map_driver stuff.
+
+2003-12-07 12:23 we7u
+
+ * src/interface.c: Reducing delay in port_write for checking queue.
+ Down to 100us from 200ms. Makes writing to interfaces much
+ snappier, but doesn't bog down CPU. Cranking up channel_data()
+ busy wait from 1 to 2us.
+
+2003-12-07 09:16 we7u
+
+ * src/: main.c, xa_config.c: Fixing the 10% zoom in bug when at
+ zoom level 1.
+
+2003-12-06 12:10 we7u
+
+ * src/map_gdal.c: Filling in a bit more for the OGR indexing code.
+
+2003-12-06 09:20 we7u
+
+ * src/interface.c: Reducing many of the usleep() delays while
+ transmitting to serial TNC's. Users will have to rely on the new
+ delay slider to add delays if they get into weird operation with
+ any particular TNC.
+
+2003-12-05 23:44 we7u
+
+ * src/map_gdal.c: More changes to debug output.
+
+2003-12-05 23:36 we7u
+
+ * src/map_gdal.c: Partial map indexing working for OGR. Must be
+ geographic coordinate system. Haven't implemented conversions
+ from other datums or coordinate systems to geographic WGS84/NAD83
+ yet.
+
+2003-12-05 22:33 we7u
+
+ * src/map_gdal.c: Printing out extents now. Should have indexing
+ implemented soon.
+
+2003-12-05 22:02 we7u
+
+ * src/map_gdal.c: More reformatting for debug purposes.
+
+2003-12-05 19:11 we7u
+
+ * src/map_gdal.c: Better formatting for OGR debug statements.
+
+2003-12-05 17:36 we7u
+
+ * src/map_gdal.c: Filling in more features. Slowly.
+
+2003-12-05 14:07 we7u
+
+ * src/xa_config.c: Changing the default serial_char_pacing to 1ms
+ instead of 25ms.
+
+2003-12-05 13:08 we7u
+
+ * src/map_gdal.c: Working version of what I checked in last time.
+ ;-)
+
+2003-12-05 13:01 we7u
+
+ * src/map_gdal.c: More good info in the OGR code.
+
+2003-12-05 12:40 we7u
+
+ * src/map_gdal.c: Fleshing out more details in the OGR driver.
+
+2003-12-05 11:39 we7u
+
+ * src/xa_config.c: Adding save/restore for serial character pacing.
+
+2003-12-05 11:14 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface.c, src/main.c,
+ src/main.h, src/map_gdal.c: Speeding up OGR. Adding a new
+ inter-character delay timing slider that affects serial-port
+ TNC's.
+
+2003-12-04 10:58 we7u
+
+ * src/map_gdal.c: Changed some comments.
+
+2003-12-04 10:08 we7u
+
+ * src/map_gdal.c: Adding map interrupt capability to the OGR code.
+
+2003-12-04 08:39 we7u
+
+ * src/maps.c: Fixing up the callouts to GDAL/OGR. We direct
+ Shapefile stuff to draw_shapefile_map() right now instead of
+ GDAL/OGR. Tiger goes to GDAL/OGR. This can be changed via a
+ define near the top of maps.c so that Shapefile goes to OGR as
+ well.
+
+2003-12-04 08:36 we7u
+
+ * src/map_shp.c: Getting rid of duplicate definition of font_size.
+
+2003-12-04 08:21 n2ygk
+
+ * src/map_shp.c: fix the font_size fix to use FONT_DEFAULT
+
+2003-12-04 00:43 we7u
+
+ * src/maps.c: Adding more vector types. Currently commented out,
+ but the GDAL/OGR code will eventually support them.
+
+2003-12-04 00:36 we7u
+
+ * src/main.c: Added more vector formats to the Vector button in Map
+ Chooser.
+
+2003-12-04 00:25 we7u
+
+ * src/map_gdal.c: Several segfaults fixed. Handles polyline
+ shapefiles and raw Tiger/Line polylines so far.
+
+2003-12-03 23:23 we7u
+
+ * src/map_shp.c: Fixing a compile problem for non-dbfawk compiles.
+
+2003-12-03 17:08 n2ygk
+
+ * src/: main.c, map_dos.c, map_pdb.c, map_shp.c, maps.c, maps.h,
+ xa_config.c, xastir.h: multiple font_sizes in maps/config/map
+ label font
+
+2003-12-03 17:05 n2ygk
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys,
+ nwsc_ddmmyy.dbfawk, nwsmzddmmyy.dbfawk, nwsozddmmyy.dbfawk,
+ nwsw_ddmmyy.dbfawk, nwsz_ddmmyy.dbfawk, tgrcty.dbfawk,
+ tgrkgl.dbfawk, tgrlk.dbfawk, tgrlpt.dbfawk, tgrlpy.dbfawk,
+ tgrplc00.dbfawk, tgrwat.dbfawk: font_size
+
+2003-12-03 14:18 we7u
+
+ * README.MAPS: Added a note about Tiger/Line maps (coming soon).
+
+2003-12-03 13:08 we7u
+
+ * src/map_gdal.c: Added some comments.
+
+2003-12-03 12:53 we7u
+
+ * src/map_shp.c: Removing the debug OGR code for the moment.
+
+2003-12-03 12:52 we7u
+
+ * src/map_gdal.c: OGR drawing for Shapefile polylines is starting
+ to work. Not pretty yet. Points/Polygons not working yet.
+
+2003-12-03 12:51 we7u
+
+ * src/maps.h: Adding a prototype for a function needed in
+ draw_gdal.c
+
+2003-12-03 12:07 we7u
+
+ * src/map_gdal.c: More OGR library stuff. Am at the point where I
+ have access to the points/polylines/polygons...
+
+2003-12-03 08:19 we7u
+
+ * src/: main.c, maps.h: Changing the Map Properties dialog so that
+ it only shows maps that were selected in the Map Chooser. Also
+ the Ok and Cancel buttons in the Map Chooser are greyed-out when
+ the Properties dialog is active (necessary due to the way I
+ implemented the new feature).
+
+2003-12-03 00:18 we7u
+
+ * src/main.c: Added some comments.
+
+2003-12-02 23:42 jtwilley
+
+ * config/: language-Dutch.sys, language-French.sys,
+ language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Added "Select All"
+ line to the other language files.
+
+2003-12-02 23:04 jtwilley
+
+ * config/language-English.sys, src/main.c: Added "Select All"
+ button to "Map Properties" dialog.
+
+2003-12-02 16:25 we7u
+
+ * src/map_shp.c: Forgot an #ifdef.
+
+2003-12-02 16:23 we7u
+
+ * src/: map_gdal.c, map_shp.c, maps.c: Debug OGR code. Nothing
+ truly functional yet. Just getting a feel for how to go about
+ it.
+
+2003-12-02 15:06 we7u
+
+ * configure.ac: Broke libproj check out into its own section and
+ summary line. We still need it checked in the libgeotiff section
+ as well though, as we depend on proj there too.
+
+2003-12-02 14:16 we7u
+
+ * src/: map_gdal.c, maps.c: Changing some warning messages.
+
+2003-12-02 14:02 we7u
+
+ * src/map_gdal.c: Getting rid of compiler warnings.
+
+2003-12-02 13:50 we7u
+
+ * configure.ac: Moving the pcre summary next to the dbfawk summary
+ at the end of configure. Reordered some of the rest as well,
+ putting all of the map libraries together.
+
+2003-12-01 13:13 we7u
+
+ * src/x_spider.c: Adding an include to make a compiler warning
+ disappear.
+
+2003-12-01 12:56 we7u
+
+ * INSTALL: Removing a note that is no longer needed. CVS GDAL has
+ been tweaked to fix it.
+
+2003-11-29 11:12 we7u
+
+ * src/x_spider.c: Flushing out the feature set for x_spider. Not
+ ready for prime-time yet, but getting closer. It now echoes
+ anything received from one client out to all other connected
+ clients. No provision yet for detecting disconnected clients and
+ removing their pipe structures.
+
+2003-11-29 00:44 we7u
+
+ * src/x_spider.c: Filling in more details for x_spider. Not
+ functional yet.
+
+2003-11-29 00:10 we7u
+
+ * src/: x_spider.c, x_spider.h: More of the x_spider server code
+ filled in. Not functional yet.
+
+2003-11-28 22:34 we7u
+
+ * src/: Makefile.am, x_spider.c, x_spider.h: Initial code for
+ x_spider server. This is an APRS multiplexer that will
+ eventually allow multiple other clients (Xastir or otherwise) to
+ connect to a running Xastir and TX/RX APRS data between them.
+ This will allow the other clients to share the TNC, AX.25, and
+ network ports that Xastir is hooked up to. The code is not
+ functional in that capacity yet, but it is a nice multi-connect
+ echo server as it stands.
+
+2003-11-28 22:26 we7u
+
+ * src/: map_gdal.c, maps.c: Adding prototype for draw_ogr_map().
+ No real code yet.
+
+2003-11-28 22:10 we7u
+
+ * src/main.c: Fix for the stupid "PACKAGE" warnings that the GDAL
+ include file causes. Fix figured out originally by Jack for the
+ ImageMagick stuff, duplicated by me in the GDAL include area.
+
+2003-11-28 21:57 we7u
+
+ * src/main.c: Slowing down the UpdateTime() loop iteration. Some
+ systems (RedHat/FreeBSD) appear to use up a lot of CPU time if
+ this is set to '1' or '0'. Setting it to '2'. Will crank it up
+ some more if people still report high CPU usage.
+
+2003-11-28 14:55 kd6zwr
+
+ * src/: main.c, map_gdal.c, maps.c: Cleaning up GDAL init, starting
+ gdal code.
+
+2003-11-26 18:47 we7u
+
+ * src/maps.c: Changing from strstr() to strncmp() for matching
+ selected directories with files inside them. Much more exact.
+
+2003-11-26 14:10 we7u
+
+ * src/main.c: Clearing the selected bits in the in-memory map index
+ before we try to resync with the selected_maps.sys file's idea of
+ what maps are selected.
+
+2003-11-26 12:04 we7u
+
+ * INSTALL: Adding GDAL instructions (not that there's much that can
+ be done with it yet, but it's still nice to see the future list
+ of supported map formats on startup!).
+
+2003-11-26 09:37 we7u
+
+ * src/maps.c: Getting rid of compiler warning when XPM is not
+ available. This fix makes sure that the snapshot thread doesn't
+ even get defined in that case.
+
+2003-11-26 09:00 we7u
+
+ * src/testawk.c: Fixing another couple of compiler warnings.
+
+2003-11-26 08:54 we7u
+
+ * src/awk.c: Fixing more compiler warnings. Trivial stuff.
+
+2003-11-26 08:43 we7u
+
+ * src/maps.c: Getting rid of another compiler warning.
+
+2003-11-26 08:35 we7u
+
+ * src/map_tif.c: Getting rid of compiler warnings.
+
+2003-11-26 08:29 we7u
+
+ * src/maps.c: Getting rid of compiler warnings and removing dead
+ code.
+
+2003-11-26 08:25 we7u
+
+ * src/map_tiger.c: Fixing a compiler warning, although I can't for
+ the life of me figure out why the compiler is confused. Perhaps
+ all of the #ifdef's confused it.
+
+2003-11-26 08:14 we7u
+
+ * src/map_shp.c: Fixing a compiler warning.
+
+2003-11-26 08:01 we7u
+
+ * src/interface.c: Changing one variable to unsigned to get rid of
+ a compiler warning. We don't need a signed variable there
+ anyway.
+
+2003-11-25 18:19 we7u
+
+ * src/main.c: Converting to square meters/feet when the CAD
+ object's area is too small for miles/km.
+
+2003-11-25 14:34 n2ygk
+
+ * config/tgrlk.dbfawk: label color blue for water
+
+2003-11-25 14:14 we7u
+
+ * src/main.c: Making the End Draw Mode function write the CAD
+ objects out to disk as well. This makes it possible to save open
+ polygons (polylines) instead of only closed polygons.
+
+2003-11-25 12:49 we7u
+
+ * src/main.c: Persistent CAD Objects. They get save/restored
+ to/from file now.
+
+2003-11-25 10:32 we7u
+
+ * src/db.h: Changing the saved polygon area from an int to a float.
+
+2003-11-25 10:31 we7u
+
+ * src/main.c: Leaving the calculations in square nautical miles
+ until we're finished, then converting to what the user needs.
+ Saving the area now in the object in units of square kilometers.
+
+2003-11-25 10:01 we7u
+
+ * src/main.c: Issuing a popup message with the area measurement.
+
+2003-11-25 09:49 we7u
+
+ * src/main.c: More corrections to the area calculation.
+
+2003-11-25 09:33 we7u
+
+ * src/main.c: Forgot to add in the minus signs again. Area should
+ be closer to being correct now for polygons.
+
+2003-11-25 09:25 we7u
+
+ * src/main.c: Computing area of a polygon. Correctly now I think.
+
+2003-11-25 07:29 we7u
+
+ * src/main.c: More CAD Drawing stuff. We now only compute area on
+ polygons with 3 or more points, and don't "close" a polygon
+ unless it has 3 or more points.
+
+2003-11-25 07:14 we7u
+
+ * src/main.c: More CAD Drawing stuff.
+
+2003-11-25 07:05 n2ygk
+
+ * src/map_shp.c: update comments
+
+2003-11-25 00:46 we7u
+
+ * src/main.c: Beginnings of computing area for a drawn polygon.
+
+2003-11-24 23:42 we7u
+
+ * src/: db.c, db.h, main.c, main.h, util.c, util.h: First
+ semi-functional implementation of CAD drawing functions. No
+ persistent storage has been implemented yet.
+
+2003-11-24 16:45 we7u
+
+ * src/maps.h: Exporting another function I'll need later in another
+ module.
+
+2003-11-24 14:38 we7u
+
+ * src/main.c: Renaming one function.
+
+2003-11-24 14:33 we7u
+
+ * src/main.c: Changing a few comments.
+
+2003-11-24 13:55 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/datum.c, src/db.c,
+ src/list_gui.c, src/main.c, src/main.h, src/maps.c,
+ src/xa_config.c: Adding the capability to use the special UTM
+ zones with a new UTM selection, instead of using them only for
+ MGRS. Seems some areas use them for regular UTM as well.
+
+2003-11-24 13:32 we7u
+
+ * src/main.c: Added more comments and some function prototypes for
+ CAD objects.
+
+2003-11-24 12:49 we7u
+
+ * src/main.c: Non-blocking xfontsel code. Main app keeps humming
+ along now even when xfontsel is up and running.
+
+2003-11-24 11:20 rzg
+
+ * help/help-English.dat: Updates for recent changes.
+
+2003-11-24 10:35 we7u
+
+ * src/main.c: Added some comments to the xfontsel code.
+
+2003-11-24 10:24 n2ygk
+
+ * src/main.c: simplified implementation of xfontsel using popen.
+
+2003-11-23 23:07 we7u
+
+ * src/main.c: Added another comment regarding xfontsel and possible
+ conversion to another thread.
+
+2003-11-23 22:50 we7u
+
+ * src/main.c: We now write the output of xfontsel back into the Map
+ Label Font dialog via the use of an intermediate file we write to
+ ~/.xastir/tmp.
+
+2003-11-23 21:50 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Added xfontsel option to
+ map label font dialog.
+
+2003-11-22 20:38 we7u
+
+ * src/main.c: More temporary CAD drawing changes. These allow
+ experimentation without the drawings disappearing. Drawings do
+ not survive pan or zoom though.
+
+2003-11-22 15:40 we7u
+
+ * src/main.c: Added crosshair cursor for Measure/Move modes, and
+ pencil cursor for CAD Draw mode.
+
+2003-11-21 13:55 we7u
+
+ * src/db.c: Fixing a pointer problem that Jack Twilley found. This
+ one occurs when we're deleting expired stations from our database
+ in time order. We weren't saving a pointer to the next
+ time-ordered record before free'ing the memory for the first.
+
+2003-11-16 22:14 we7u
+
+ * src/main.c: Adding some comments. No code changes.
+
+2003-11-16 15:33 we7u
+
+ * README.MAPS: Added a note from Tom Russo regarding limitations of
+ shpproj.
+
+2003-11-13 10:37 we7u
+
+ * src/main.c: Added an erase option for the CAD objects.
+ Non-functional so far.
+
+2003-11-13 10:11 we7u
+
+ * src/main.c: Moving more menu stuff around. Making it harder to
+ move my station using the mouse. Put Pan stuff in a submenu to
+ make the main mouse menu shorter.
+
+2003-11-13 09:52 we7u
+
+ * src/main.c: More Draw CAD-mode stuff.
+
+2003-11-13 09:29 we7u
+
+ * src/main.c: More draw CAD objects stuff. Not ready for
+ prime-time yet.
+
+2003-11-13 08:16 we7u
+
+ * src/main.c: Moving the "Move my station here" menu option to the
+ very bottom, more out of the way.
+
+2003-11-13 07:27 n2ygk
+
+ * config/nwsc_ddmmyy.dbfawk, config/nwsmzddmmyy.dbfawk,
+ config/nwsozddmmyy.dbfawk, config/nwsw_ddmmyy.dbfawk,
+ config/nwsz_ddmmyy.dbfawk, config/tgrcty.dbfawk,
+ config/tgrkgl.dbfawk, config/tgrlk.dbfawk, config/tgrlpt.dbfawk,
+ config/tgrlpy.dbfawk, config/tgrplc00.dbfawk,
+ config/tgrwat.dbfawk, src/map_shp.c, src/maps.c, src/maps.h:
+ Centered area polygon labels. Use light blue for area label
+ color.
+
+2003-11-12 13:23 we7u
+
+ * INSTALL: Changing some instructions to use "su -c" instead of
+ "su" and "exit".
+
+2003-11-11 21:37 we7u
+
+ * src/main.c: Very preliminary etch-a-sketch mode. Allows the
+ operator to draw lines on top of the map display. Eventually
+ this will be turned into something useful. Right now the lines
+ disappear at the next screen refresh.
+
+2003-11-11 07:03 n2ygk
+
+ * config/: nwsc_ddmmyy.dbfawk, nwsmzddmmyy.dbfawk,
+ nwsozddmmyy.dbfawk, nwsw_ddmmyy.dbfawk, nwsz_ddmmyy.dbfawk,
+ tgrcty.dbfawk, tgrkgl.dbfawk, tgrlk.dbfawk, tgrlpt.dbfawk,
+ tgrlpy.dbfawk, tgrplc00.dbfawk, tgrwat.dbfawk: "pattern" set to
+ match X line attribute. Also some other minor tweaking.
+
+2003-11-11 07:02 n2ygk
+
+ * src/map_shp.c: add default dbfawk when signature not found.
+ change "pattern" to just be the X line attribute pattern (0, 1,
+ or 2).
+
+2003-11-10 09:18 we7u
+
+ * src/main.c: Changing the default symbol to a dot. Used to be the
+ emergency symbol, which is probably not a good idea as a default.
+
+2003-11-10 08:39 we7u
+
+ * src/main.c: Saving/restoring comment and name fields when
+ switching between different types of Create Object/Item dialogs.
+
+2003-11-10 07:20 n2ygk
+
+ * src/map_shp.c: Use 'fill_color' to fill polygons; 'color' for
+ polygon border.
+
+2003-11-10 06:57 n2ygk
+
+ * config/: tgrlk.dbfawk, tgrlpt.dbfawk, tgrwat.dbfawk: fill_color
+
+2003-11-10 06:56 n2ygk
+
+ * config/: Makefile.am, tgrlpy.dbfawk, tgrplc00.dbfawk: More
+ dbfawk's
+
+2003-11-10 06:55 n2ygk
+
+ * README.MAPS: use consistent style for variable names
+
+2003-11-08 17:42 jtwilley
+
+ * configure.ac, src/dbfawk.c, src/testawk.c: Tom Russo's patch to
+ help dbfawk build under FreeBSD.
+
+2003-11-07 22:57 we7u
+
+ * src/main.c: Added some comments.
+
+2003-11-07 22:49 we7u
+
+ * src/main.c: Fixes for Map Chooser Properties buttons. The string
+ offset was incorrect after the strings were shortened. Fixed
+ now.
+
+2003-11-07 13:46 we7u
+
+ * src/maps.c: Fixing a problem whereby the weather alert filenames
+ are guessed wrong if there are similarly-names zip files in the
+ Counties directory.
+
+2003-11-07 10:15 we7u
+
+ * src/main.c: Fixing objects/items with respect to probability
+ circles and multipoint polygons. We can now do compressed
+ objects/items with these features, and we get a space before the
+ multipoint string, as the spec requires.
+
+2003-11-06 15:27 we7u
+
+ * src/db.c: Changing the extract_multipoints() function so that it
+ doesn't remove the multipoint string from the comment field of
+ objects or items. This allows us to transmit the multipoint
+ string every time we transmit the object/item.
+
+2003-11-06 15:26 we7u
+
+ * src/draw_symbols.c: Changed one comment.
+
+2003-11-06 09:21 we7u
+
+ * src/interface.c: OpenTrac bug-fix by Henk. Thanks!
+
+2003-11-06 09:13 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Spanish.sys,
+ src/main.c: Fixing Map Properties columns for other languages.
+
+2003-11-06 09:02 we7u
+
+ * config/language-English.sys, src/main.c: Making Map Properites
+ even narrower.
+
+2003-11-06 08:21 we7u
+
+ * src/main.c: Reorganizing the buttons on Map Chooser->Properties
+ so that the dialog will be narrower.
+
+2003-11-06 07:56 we7u
+
+ * src/main.c: Moving some of the Map menu into a submenu.
+ Lesser-used stuff now resides in a Configure submenu off the Map
+ menu.
+
+2003-11-06 07:44 we7u
+
+ * config/language-English.sys: Changing a few labels in the menus.
+ Minor stuff.
+
+2003-11-05 22:54 jtwilley
+
+ * config/tnc-startup.aea: Moved 'EXP on' to the top of the file and
+ commented out lines which produce errors on my AEA PK-232.
+
+2003-11-05 10:35 we7u
+
+ * src/maps.c: Fixing the high CPU-usage bug with XDrawLines() in
+ draw_grid with UTM grids.
+
+2003-11-05 10:10 we7u
+
+ * src/maps.c: Added an interation max to the while loop in
+ draw_grid(). Just in case.
+
+2003-11-05 07:06 n2ygk
+
+ * src/map_shp.c: Fix WX alerts
+
+2003-11-04 15:24 we7u
+
+ * src/map_shp.c: Patch submitted by Tom Russo, KM5VY. Allows
+ dbfawk to control more than just color.
+
+2003-11-04 15:00 we7u
+
+ * src/main.c: Added a rather stupid fix for the problem: 'Error:
+ attempt to add non-widget child "DropSiteManager" to parent
+ "xastir"'. Making a couple of harmless Motif calls before
+ calling XtVaCreateWidget in create_appshell().
+
+2003-11-04 14:24 we7u
+
+ * src/map_geo.c: Wrapping a call with ifdef's for people that don't
+ have ImageMagick compiled in.
+
+2003-11-04 14:20 we7u
+
+ * tigermap.geo: Adding this file so that Tigermap may be a normal
+ option in the Map Chooser.
+
+2003-11-04 13:46 we7u
+
+ * src/main.c: Moving things around to different menus. Cleaning up
+ the interface just a bit.
+
+2003-11-04 11:28 we7u
+
+ * src/xa_config.c: Remembering Tigermap config settings between
+ sessions.
+
+2003-11-04 09:17 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-Italian.sys,
+ config/language-Portuguese.sys, config/language-Spanish.sys,
+ src/main.c, src/map_tiger.c, src/xa_config.c, src/xastir.h:
+ Making the regular Map Intensity controls work for the TigerMap
+ intensity as well. Simplifying the user interface a bit.
+
+2003-11-04 08:46 we7u
+
+ * Makefile.am, src/main.c, src/main.h, src/map_geo.c,
+ src/map_tiger.c, src/xa_config.c: Moving Tigermap enable to the
+ Map Chooser (so that all maps are selected/deselected from one
+ dialog). Removed the Enable button from the Tigermap config
+ dialog.
+
+2003-11-03 13:22 we7u
+
+ * src/location_gui.c: Removing unnecessary db.h include.
+
+2003-11-03 13:22 we7u
+
+ * src/: bulletin_gui.c, datum.c, db.c, db.h, gps.c, interface.c,
+ interface_gui.c, list_gui.c, locate_gui.c, main.c, messages.c,
+ messages_gui.c, track_gui.c, util.c, util.h, view_message_gui.c,
+ wx.c, xa_config.c: Fixed the problem with coordinate calc and
+ inputting UPS coordinates. Moved some routines from db.c to
+ util.c that were general-purpose string routines. Got rid of
+ unnecessary db.h includes.
+
+2003-11-03 12:59 we7u
+
+ * src/main.c: Added a debug line.
+
+2003-11-03 11:04 we7u
+
+ * src/util.c: Fixing the "nice" formatting for UTM so that extra
+ spaces aren't added on the status line for MGRS coordinates.
+
+2003-11-03 10:59 we7u
+
+ * src/: datum.c, db.c, list_gui.c, main.c, util.c, util.h: Cleaning
+ up the MGRS_string stuff. Formatting the string nicely for the
+ Coordinate Calculator.
+
+2003-11-03 09:19 we7u
+
+ * src/datum.c: Fixed utm_ups_to_ll() function for the south polar
+ region.
+
+2003-11-03 09:13 we7u
+
+ * src/util.c: Switching back to original math.
+
+2003-11-03 08:33 we7u
+
+ * src/datum.c: Added a comment about the problems with
+ utm_ups_to_ll() function in the south polar region.
+
+2003-11-03 08:14 we7u
+
+ * src/main.c: Adding MGRS to Coordinate Calculator as an output
+ format. Still has problems in the south polar region, but other
+ than that it appears to work properly.
+
+2003-11-03 08:10 we7u
+
+ * src/util.c: Switching to MGRS zones when doing MGRS conversions,
+ and restoring the "coordinate_system" variable when done.
+ Changed some math to make it more understandable what was going
+ on.
+
+2003-11-03 08:08 we7u
+
+ * src/datum.c: Changed a comment.
+
+2003-11-01 10:57 we7u
+
+ * src/util.c: Correct 2-letter digraphs now for the UPS regions
+ while using MGRS coordinates.
+
+2003-10-31 21:15 we7u
+
+ * src/util.c: Changing the formatting for MGRS.
+
+2003-10-31 16:35 we7u
+
+ * src/util.c: MGRS appears to be functional in the UTM area. Still
+ needs work in the UPS (polar) areas.
+
+2003-10-31 15:35 we7u
+
+ * src/: datum.c, datum.h, db.c, list_gui.c, main.c, main.h, maps.c,
+ util.c, util.h, xa_config.c: Initial code for implementing MGRS
+ coordinates. Not quite ready for prime-time yet.
+
+2003-10-31 15:34 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Adding a label for
+ selecting MGRS coordinates.
+
+2003-10-30 14:32 we7u
+
+ * config/: language-Dutch.sys, language-French.sys,
+ language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Adding Max/Min
+ Zoom headings to Map Chooser->Properties dialog for other
+ language files.
+
+2003-10-30 10:50 we7u
+
+ * src/xa_config.c: More error-checking for lat/long as read in from
+ the config file. In case someone hand-edits the station location
+ and gets the format wrong.
+
+2003-10-29 19:38 we7u
+
+ * src/maps.c: Fixing the edges of the earth, UTM grid style.
+
+2003-10-29 13:03 we7u
+
+ * src/: datum.c, datum.h, maps.c: Fixing the UTM grid. Added
+ "MGRS_grid" variable. If set, we draw the irregular grids and
+ report UTM coordinates using those grids. If zero, we draw the
+ regularly-spaced six-degree zones and report using those regular
+ zones.
+
+2003-10-29 12:50 we7u
+
+ * src/maps.c: Correcting UTM grid for the civilian UTM grid
+ (non-MGRS grid).
+
+2003-10-29 12:27 we7u
+
+ * src/main.c: Saving our place in the Map Properties dialog. No
+ more scrolling trying to get back to where you were.
+
+2003-10-29 11:59 we7u
+
+ * src/main.c: Commenting out debug code.
+
+2003-10-29 11:51 we7u
+
+ * src/main.c: Commenting out a debug line.
+
+2003-10-29 11:23 we7u
+
+ * src/maps.c: Adding code to migrate from old map_index.sys format
+ to the new format. Accepts either 8 or 10 parameters per line
+ and writes out the new 10-parameter format if the 8-parameter
+ format is found. Swapped the max_zoom and min_zoom parameters to
+ further down the data line.
+
+2003-10-28 22:26 jtwilley
+
+ * config/language-English.sys, src/main.c, src/maps.c, src/maps.h:
+ Added support for max/min zoom levels. Work still needs to be
+ done on removing existing zoom-level-sensitive code and
+ supporting other languages.
+
+2003-10-28 16:35 we7u
+
+ * src/main.c: Moved the "XtRealize" call down lower in the routine,
+ after the size has been specified. This is to help get rid of
+ the "Error: Shell widget xastir has zero width and/or height"
+ problem that some users have been having.
+
+2003-10-28 16:29 we7u
+
+ * src/main.c: Moving the "manage" call for the main app down lower
+ after the size of the widget has been specified. Attempting to
+ get rid of the "Error: Shell widget xastir has zero width and/or
+ height" problem that some users are still having.
+
+2003-10-28 15:46 we7u
+
+ * src/xa_config.c: Setting screen_height and screen_width to
+ minimums of 40 and 100.
+
+2003-10-28 15:20 we7u
+
+ * src/main.c: Getting rid of the auto-clear function for the map
+ chooser topo and vector buttons. They are now additive instead
+ of exclusive.
+
+2003-10-28 07:02 n2ygk
+
+ * src/list_gui.c: Fix X crash when list width/height somehow get
+ set to zero.
+
+2003-10-27 17:40 rzg
+
+ * INSTALL, README.MAPS: Minor updates. I'm still around. :-)
+
+2003-10-23 12:48 uid74947
+
+ * src/maps.c: Another comment.
+
+2003-10-22 17:30 we7u
+
+ * src/maps.c: Comment changes.
+
+2003-10-22 17:22 we7u
+
+ * src/maps.c: More comments.
+
+2003-10-22 17:19 we7u
+
+ * src/maps.c: Changing the scale at which the UTM subgrid starts to
+ be drawn. We weren't drawing it properly at scales of 2048 and
+ up anyway.
+
+2003-10-22 17:15 we7u
+
+ * src/maps.c: More comment changes.
+
+2003-10-22 16:44 we7u
+
+ * src/maps.c: Adding comments. More checking for invalid numbers
+ in draw_grid().
+
+2003-10-22 16:19 we7u
+
+ * src/maps.c: Commenting out some debug lines.
+
+2003-10-22 16:06 we7u
+
+ * src/maps.c: Fixing another bug in draw_grid() that caused a
+ segfault while drawing UTM grids. Added more debug and comments.
+ The segfault fix causes some grid lines to get skipped but
+ that's better than a segfault.
+
+2003-10-22 14:39 we7u
+
+ * src/maps.c: More comment changes.
+
+2003-10-22 14:08 we7u
+
+ * src/maps.c: Correcting some comments.
+
+2003-10-22 13:53 we7u
+
+ * src/maps.c: Correcting some comments based on input from Peter
+ Dana.
+
+2003-10-22 13:50 we7u
+
+ * src/maps.c: Added another comment.
+
+2003-10-22 12:50 we7u
+
+ * src/maps.c: Adding lots of comments in the draw_grid() function.
+ Trying to understand Olivier's code for drawing UTM grids, so it
+ can be improved in the areas of major grid intersections, and in
+ handling the irregular zone widths.
+
+2003-10-22 11:43 we7u
+
+ * src/maps.c: Changed some comments.
+
+2003-10-22 09:33 we7u
+
+ * src/maps.c: Last log message should have said: Changed/updated
+ some comments. No code changes. Same for this log message.
+
+2003-10-22 09:32 we7u
+
+ * src/maps.c: [no log message]
+
+2003-10-22 06:57 n2ygk
+
+ * README.MAPS, config/tgrlpt.dbfawk, src/map_shp.c: dbfawk symbol
+ support for point shapefiles
+
+2003-10-21 08:22 n2ygk
+
+ * src/map_shp.c: duh - sym[4] to fit the null at the end!
+
+2003-10-21 08:21 n2ygk
+
+ * src/map_shp.c: sym[3] to allow for overlay char too
+
+2003-10-21 08:20 n2ygk
+
+ * README.MAPS: document "roll your own shapefile maps"
+
+2003-10-19 15:31 we7u
+
+ * src/main.c: Added a comment. No code changes.
+
+2003-10-19 15:28 we7u
+
+ * src/maps.c: Changing the UTM/UPS grid so that only two zones each
+ are drawn at the poles (in the UPS region).
+
+2003-10-19 15:26 we7u
+
+ * src/datum.c: Fixing the output zone number in the UPS regions to
+ "00".
+
+2003-10-17 23:13 we7u
+
+ * src/maps.c: Tweaking the UTM grid so that it extends to the
+ poles, now that I know what the UPS grid (near the poles) should
+ look like.
+
+2003-10-17 22:55 we7u
+
+ * src/: datum.c, datum.h, main.c, map_geo.c, maps.c, util.c:
+ Implemented proper UTM/UPS to Lat/Long conversions. Also fixed
+ the coordinate calculator so it would accept UPS coordinates.
+
+2003-10-17 21:49 we7u
+
+ * src/: datum.c, datum.h, main.c, map_geo.c, maps.c, util.c:
+ Implemented proper UPS output, when using UTM/UPS and near the
+ poles.
+
+2003-10-17 20:22 we7u
+
+ * src/datum.c: Temporarily making the easting and northing for the
+ UPS areas (near the poles) equal to all zeroes. This is to
+ prevent someone thinking that the numbers we're showing are valid
+ coordinates. We haven't been computing proper coordinates in the
+ UPS areas. Am still working on the problem and hope to have
+ valid UPS numbers by the end of the weekend.
+
+2003-10-17 14:21 we7u
+
+ * src/datum.c: Changed some comments. Added some output if we're
+ trying to convert a UPS coordinate to Lat/Long.
+
+2003-10-17 13:39 we7u
+
+ * src/: datum.c, datum.h: Changed utm_letter_designator() to
+ properly handle the zones for UPS grid. Still need to get the
+ easting/northing numbers to work right, but the zone letters are
+ now correct.
+
+2003-10-17 12:50 we7u
+
+ * src/datum.c: Modified utm_letter_designator() function so that
+ 'Z' is displayed above 84N, and 'A' is displayed below 80S. It's
+ better than it was, but we still need to implement full UPS
+ coordinate systems in the pole regions.
+
+2003-10-17 12:38 we7u
+
+ * src/main.c: Tweaking TrackMouse() so that the coordinates stop
+ changing when the mouse goes off the edge of the earth.
+
+2003-10-17 08:21 n2ygk
+
+ * src/map_shp.c: still incomplete attempt at handling fill styles.
+
+2003-10-17 08:19 n2ygk
+
+ * config/: Makefile.am, tgrlpt.dbfawk: add tgrlpt (Tiger/Line
+ landmark points)
+
+2003-10-17 08:18 n2ygk
+
+ * config/tgrlk.dbfawk: add complete documentation of CFCC codes
+
+2003-10-17 02:13 we7u
+
+ * bootstrap.sh: Added a line to remove the autom4te.cache directory
+ and contents. This sometimes gets in the way when running
+ autoheader, and I have to delete it manually in that case. No
+ more.
+
+2003-10-16 16:38 we7u
+
+ * src/map_geo.c: Excluding map indexing from being able to set the
+ map refresh interval.
+
+2003-10-16 16:09 we7u
+
+ * src/: map_gdal.c, maps.c: Minor comment changes.
+
+2003-10-16 15:59 we7u
+
+ * src/: map_gdal.c, maps.c: Dumping out map types on startup.
+
+2003-10-16 14:48 we7u
+
+ * src/map_gdal.c: Changed comments. No code changes.
+
+2003-10-16 14:44 we7u
+
+ * configure.ac: Moving the GDAL stuff after shapelib and
+ libgeotiff. We want GDAL to get linked AFTER the other
+ libraries, at least until we get GDAL fully integrated. If GDAL
+ is linked earlier than these other libraries, function calls get
+ made to GDAL instead of the correct libraries.
+
+2003-10-16 14:42 we7u
+
+ * src/map_tif.c: Added more debugging output.
+
+2003-10-16 14:39 we7u
+
+ * src/maps.c: Added more debug info.
+
+2003-10-16 14:11 we7u
+
+ * src/map_gdal.c: Minor stuff, getting ready to try to open a file.
+
+2003-10-16 12:40 we7u
+
+ * src/map_gdal.c: Printing out OGR drivers as well now.
+
+2003-10-16 12:33 we7u
+
+ * src/map_gdal.c: Nicer formatting for the GDAL drivers.
+
+2003-10-16 12:30 we7u
+
+ * src/map_gdal.c: Better formatting for listing GDAL drivers.
+ Starting to add code to list OGR drivers as well.
+
+2003-10-16 11:58 we7u
+
+ * src/map_gdal.c: Print out a list of all registered GDAL drivers
+ upon Xastir startup.
+
+2003-10-16 09:56 we7u
+
+ * src/map_gdal.c: Moved the #warning text inside the #ifdef block.
+ Will only see the warning if GDAL is installed and usable on your
+ system.
+
+2003-10-16 09:48 we7u
+
+ * src/map_gdal.c: Minor changes to comments. Removed a #define
+ that shouldn't have been committed.
+
+2003-10-16 09:42 we7u
+
+ * src/map_gdal.c: Added example code snippets from the GDAL
+ tutorial.
+
+2003-10-16 09:07 we7u
+
+ * configure.ac, src/main.c, src/map_gdal.c, src/maps.h: More
+ initial framework for GDAL integration. Now adds it to the list
+ of supported libraries in "configure", and adds the library to
+ the link line.
+
+2003-10-16 08:30 we7u
+
+ * src/Makefile.am: Adding map_gdal.c to the list of files.
+
+2003-10-16 08:29 we7u
+
+ * src/map_gdal.c: Adding initial file framework for integrating the
+ GDAL library. No real code here yet.
+
+2003-10-14 13:49 we7u
+
+ * src/map_geo.c: Another #ifdef fix regarding raster_map_intensity.
+
+2003-10-14 13:44 we7u
+
+ * src/main.c: More #ifdef cleanup regarding raster_map_intensity.
+
+2003-10-14 13:37 we7u
+
+ * src/: main.c, maps.h, xa_config.c: Fixing #ifdef's, consistent
+ with new uses of raster_map_intensity variable (used to be
+ geotiff_map_intensity).
+
+2003-10-13 14:46 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/draw_symbols.c,
+ src/draw_symbols.h, src/main.c, src/main.h, src/xa_config.c:
+ Implementing Henk de Groot's icon outline code. Added code to
+ make the changes instantly visible in the drawing area. Thanks
+ Henk!
+
+2003-10-13 14:30 we7u
+
+ * src/: main.c, map_geo.c, map_tif.c, maps.c, maps.h, xa_config.c:
+ Attached geo files to the raster intensity variable, so they can
+ be darkened from the menus now. Had to hard-code toposerver
+ images to be 100% brightness though, as the colors get strange on
+ that particular image. Other images can be fixed by adding the
+ "modulate" tag to the .geo file, if this problem should surface
+ elsewhere.
+
+2003-10-13 13:22 we7u
+
+ * src/maps.c: More efficient snapshot code: Moved the .geo code
+ back into the separate thread now that the symbol-blanking bug is
+ fixed.
+
+2003-10-13 12:57 we7u
+
+ * src/maps.c: Fixed snapshots so that .geo file creation works
+ without blanking symbols on the screen. The code was leaving
+ incorrect values in global variables that were later used by the
+ symbol drawing code.
+
+2003-10-13 10:57 we7u
+
+ * src/: main.c, maps.c, xastir.h: Fixing the
+ symbols-going-away-after-snapshot problem. Unfortunately it
+ appears that the .geo code for snapshots is the problem. Will
+ have to figure out why yet and then reinstate that part of the
+ code.
+
+2003-10-12 21:22 we7u
+
+ * src/: main.c, maps.c, xastir.h: Attempting to fix the snapshot
+ problem where stations disappear off the display. Created
+ another Pixmap: pixmap_snapshot, and copy pixmap_final to it
+ just before the snapshot thread is started. This should separate
+ any accesses to the data so that no conflicts occur while making
+ the snapshot.
+
+2003-10-09 19:20 we7u
+
+ * src/maps.c: Tweaking the width of the equator line in UTM grid
+ (again).
+
+2003-10-09 19:14 we7u
+
+ * src/maps.c: Minor changes to equator/prime meridian again for
+ UTM.
+
+2003-10-09 18:41 we7u
+
+ * src/maps.c: Changing line widths for the lat/long grid and the
+ major UTM zones to width 2. This makes them more noticeable
+ against the smaller UTM subgrid and against map lines.
+
+2003-10-09 13:16 we7u
+
+ * src/maps.c: Changing the color for lat/long grids as well so that
+ they work with the gc_tint stuff and show up on maps well.
+
+2003-10-09 13:09 we7u
+
+ * src/maps.c: Changing to gc_tint for map grids so that the grid
+ can always be seen on top of maps.
+
+2003-10-09 12:52 we7u
+
+ * src/maps.c: Switching to purple lines as they show up well on
+ topo and terraserver maps.
+
+2003-10-09 12:47 we7u
+
+ * src/maps.c: Changing the smaller UTM grids to display in bright
+ yellow. Easier to see on maps.
+
+2003-10-09 09:18 we7u
+
+ * src/maps.c: Initial attempt at finer UTM grids, using preliminary
+ code by Olivier Calle (N7TAP). The code handles the irregular
+ regions near/above Norway for the major UTM grid zones only (not
+ for the minor grids yet). There are known problems near the zone
+ boundaries with lines not getting drawn or incorrect lines
+ getting drawn. For the most part, if you're inside a zone and
+ not in the irregular zone area, this code works very well, and is
+ very fast!
+
+2003-10-09 09:03 we7u
+
+ * src/: db.c, main.c, map_geo.c: Changing a few printf's to
+ fprintf's.
+
+2003-10-08 12:48 we7u
+
+ * src/maps.c: Simplified code for drawing UTM grid.
+
+2003-10-08 12:12 we7u
+
+ * src/maps.c: Changing the UTM grid to dashed lines instead of
+ solid.
+
+2003-10-08 11:31 we7u
+
+ * src/maps.c: Proper UTM grid, including irregular areas near
+ Norway. Area from 84N to 90N and 80S to 90S is still in
+ question, as that is in the UPS coordinate system area (the
+ poles). Also, the UTM coordinates on the status line are
+ incorrect when the mouse pointer is moved into these areas.
+
+2003-10-08 10:16 we7u
+
+ * src/maps.c: More draw_vector stuff. Both Xastir coordinate
+ system and lat/long vector drawing functions work now. Still
+ need to work on the "is it in the view" code, as it's not working
+ correctly..
+
+2003-10-08 09:42 we7u
+
+ * src/maps.c: Added more UTM grid comments.
+
+2003-10-08 09:37 we7u
+
+ * src/maps.c: Adding a new draw_vector() function, which I'll use
+ for drawing the UTM grid shortly. Changed/added a bunch of
+ comments in draw_grid() regarding UTM.
+
+2003-10-07 12:59 we7u
+
+ * src/maps.c: Changed some comments.
+
+2003-10-07 11:51 we7u
+
+ * src/maps.c: Tweaked the boundary checks before the XDrawLine
+ call. Added/changed some comments regarding UTM grid.
+
+2003-10-06 19:41 we7u
+
+ * src/maps.c: Initial UTM grid attempt. This mod causes the six
+ degree vertical lines to be drawn that define the major UTM
+ zones. It will draw them if the map grid is enabled and UTM is
+ the selected coordinate system.
+
+2003-10-02 16:51 we7u
+
+ * src/db.c: Fixing the Pmin/Pmax stuff so that it gets transmitted
+ properly across the air.
+
+2003-10-02 13:21 we7u
+
+ * src/maps.c: Xastir now creates a snapshot.geo file corresponding
+ to the snapshot.png file.
+
+2003-10-02 10:08 we7u
+
+ * README.win32: Added a note about removing the "-local" option for
+ nasd.
+
+2003-10-02 07:09 n2ygk
+
+ * src/main.c: Duh. Hung Map_font off of Gamma_correct button.
+
+2003-09-30 06:57 n2ygk
+
+ * INSTALL, README.MAPS: document dbfawk
+
+2003-09-28 15:39 n2ygk
+
+ * config/: language-Dutch.sys, language-French.sys,
+ language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Add map label font
+ selection (please translate these!)
+
+2003-09-28 00:03 we7u
+
+ * src/xastir.h: Minor tweak to fix a compile problem in main.c with
+ sizeof().
+
+2003-09-27 07:18 n2ygk
+
+ * config/language-English.sys, src/awk.c, src/awk.h, src/dbfawk.c,
+ src/main.c, src/map_shp.c, src/maps.c, src/xa_config.c,
+ src/xastir.h: Add user-selectable MAPS_LABEL_FONT. Add
+ dbfawk-selectable label color. Add "skip" keyword to dbfawk to
+ permit overriding bad shapefile dbf data.
+
+2003-09-26 16:34 we7u
+
+ * README.win32: Clarified that maps can go in the maps directory
+ and subdirectories thereof.
+
+2003-09-26 16:26 we7u
+
+ * README.win32: Added a note about possible problems with IM-5.5.7.
+
+2003-09-26 16:22 we7u
+
+ * README.MAPS: Specified where the sound files go.
+
+2003-09-26 10:06 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Added an "Apply" button
+ to the Map Chooser that applies the changes immediately without
+ destroying the Map Chooser.
+
+2003-09-26 09:16 we7u
+
+ * README.win32: Added note about Perl 5.8 and page faults while
+ compiling.
+
+2003-09-19 16:48 we7u
+
+ * README.win32: Added a note about ImageMagick being necessary to
+ view .geo maps.
+
+2003-09-19 16:41 we7u
+
+ * README.win32: Added a Win2k note.
+
+2003-09-19 16:34 we7u
+
+ * README.win32: Minor edits.
+
+2003-09-19 16:06 we7u
+
+ * README.win32: Added to more XFree86 packages to the selections.
+
+2003-09-19 15:40 we7u
+
+ * README.win32: Better fix for the _reent bug.
+
+2003-09-19 15:37 we7u
+
+ * README.win32: Added another note about the _reent bug.
+
+2003-09-19 10:58 we7u
+
+ * README.MAPS: Minor changes to the download NOAA weather alert
+ maps section.
+
+2003-09-19 10:57 we7u
+
+ * src/util.c: Caused the code to recognize "NWS_" as valid. Didn't
+ appear to be doing so, which might have been knocking out a lot
+ of compressed weather alerts.
+
+2003-09-19 10:57 we7u
+
+ * src/db.c: Changed some comments.
+
+2003-09-19 10:56 we7u
+
+ * src/alert.c: Minor changes to comments and added another possible
+ case for SOLAR that can get parsed (don't know if it'll ever get
+ used).
+
+2003-09-18 12:38 we7u
+
+ * src/main.c: Setting the initial symbol to be a hiker when
+ creating new object/item with probability circle toggle enabled.
+
+2003-09-18 12:04 we7u
+
+ * src/: main.c, db.c: Working implementation of SAR probability
+ circles.
+
+2003-09-17 17:24 we7u
+
+ * src/: db.c, db.h, draw_symbols.c, draw_symbols.h, main.c: Half of
+ an implementation for drawing Search & Rescue probability
+ circles. Have the encoding parts and display parts done. Next
+ need to do the decoding so that the circles show up on the map.
+
+2003-09-16 10:46 we7u
+
+ * src/xastir.h: Adding preliminary support for the libgc garbage
+ collection library. Disabled by default. This gives automatic
+ garbage collection of unused memory space to Xastir. During long
+ runtimes, this seems to improve memory usage a bit.
+
+2003-09-16 10:13 we7u
+
+ * src/map_geo.c: Fixing trans_skip for the non-ImageMagick case.
+
+2003-09-15 11:49 we7u
+
+ * README.win32: Very minor wording change in the CVS instructions.
+
+2003-09-12 07:48 n2ygk
+
+ * configure.ac, src/dbfawk.c, src/map_shp.c: properly
+ conditionalize WITH_DBFAWK. More dbfawk tweaks in map_shp
+
+2003-09-11 15:04 jtwilley
+
+ * src/dbfawk.c: Added check for DBFAWK define.
+
+2003-09-11 13:19 n2ygk
+
+ * config/nwsc_ddmmyy.dbfawk, src/map_shp.c: Fix a stupid error in
+ symtbl
+
+2003-09-10 13:53 rzg
+
+ * help/help-English.dat: whatsnew update
+
+2003-09-10 13:27 kd6zwr
+
+ * README.MAPS, help/help-English.dat, src/map_geo.c, src/maps.h:
+ Changing TRANSPARENT geo tag to accept a user defined color to
+ zap.
+
+2003-09-09 06:56 n2ygk
+
+ * config/nwsc_ddmmyy.dbfawk, config/tgrcty.dbfawk,
+ config/tgrkgl.dbfawk, config/tgrwat.dbfawk, src/map_shp.c: more
+ dbfawk tweaking
+
+2003-09-08 07:37 n2ygk
+
+ * config/nwsc_ddmmyy.dbfawk, config/nwsozddmmyy.dbfawk,
+ config/nwsw_ddmmyy.dbfawk, config/nwsz_ddmmyy.dbfawk,
+ src/map_shp.c: more dbfawk tweaks. WX alerts now search
+ properly.
+
+2003-09-05 14:25 we7u
+
+ * src/main.c: Removed some unneeded comments.
+
+2003-09-05 14:12 we7u
+
+ * src/main.c: Taking out the Move/Measure menu prevention logic for
+ the case where the mouse buttons are _not_ swapped.
+
+2003-09-05 13:20 we7u
+
+ * src/main.c: Preventing the mouse menu from coming up if SWAP
+ buttons is enabled and we're doing the Move or Measure functions.
+
+2003-09-05 12:47 we7u
+
+ * src/main.c: Added another define that allows moving the mouse
+ menu to button1.
+
+2003-09-05 12:07 we7u
+
+ * src/main.c: Swapping zoom/pan buttons so that zoom buttons are
+ more often on the screen with a small window size.
+
+2003-09-05 06:56 n2ygk
+
+ * config/: Makefile.am, nwsc_ddmmyy.dbfawk, nwsmzddmmyy.dbfawk,
+ nwsozddmmyy.dbfawk, nwsw_ddmmyy.dbfawk, nwsz_ddmmyy.dbfawk: First
+ pass at handling WX alerts with dbfawk
+
+2003-09-04 23:37 we7u
+
+ * src/main.c: Added some notes about xmodmap for swapping mouse
+ buttons in a touchscreen configuraton.
+
+2003-09-04 15:48 we7u
+
+ * config/language-English.sys: Making Z-In/Z-Out labels shorter to
+ help fit on 640x480 LCD screen.
+
+2003-09-04 15:28 we7u
+
+ * src/main.c: Changing the optional SMALL system font.
+
+2003-09-04 14:39 n2ygk
+
+ * src/testawk.c: Make it compile even without DBFAWK
+
+2003-09-04 14:22 we7u
+
+ * INSTALL: Added a bit more about libgeotiff's private include
+ directory.
+
+2003-09-04 11:00 we7u
+
+ * src/main.c: Another tweak for fixed-size small displays. This
+ new define forces dialogs to pop up over the main application,
+ near the left top corner.
+
+2003-09-04 10:11 we7u
+
+ * src/main.c: Adding an option for a much smaller default system
+ font. Useful for smaller displays.
+
+2003-09-04 10:10 we7u
+
+ * config/language-English.sys: Making Zoom buttons smaller by
+ shortening the string. Needed for smaller displays.
+
+2003-09-04 09:40 we7u
+
+ * src/: main.c, xa_config.c: Allowing much smaller screen sizes for
+ Xastir. It should start up in roughly the same size as saved now
+ also.
+
+2003-09-04 09:18 we7u
+
+ * src/main.c: Changing the minimum size for the main window down to
+ 1/4 VGA. This allows it to be resized much smaller than before.
+ Useful for fixed-size LCD displays.
+
+2003-09-04 09:11 we7u
+
+ * FAQ: Added a few more words about why stations might not appear
+ on the screen.
+
+2003-09-04 07:38 n2ygk
+
+ * src/map_shp.c: more dbfawk tweaking
+
+2003-09-03 17:01 we7u
+
+ * INSTALL: Revised the libgeotiff instructions slightly.
+
+2003-09-03 12:37 we7u
+
+ * README.win32: Added "touch .cvspass" to the instructions. Some
+ Windows boxes fail without this.
+
+2003-09-03 11:26 kd6zwr
+
+ * README.MAPS, help/help-English.dat: Documenting the new
+ TRANSPARENT and CROP .geo file tags.
+
+2003-09-03 08:19 n2ygk
+
+ * configure.ac, src/Makefile.am, src/awk.c, src/dbfawk.c,
+ src/dbfawk.h, src/map_shp.c, src/testawk.c: change to use
+ WITH_DBFAWK. dbfawk now searches for mapfilename.dbfawk before
+ looking in config/*.dbfawk, enabling map-specific special cases.
+
+2003-09-03 00:28 kd6zwr
+
+ * src/: map_geo.c, maps.h: Adding TRANSPARENT and CROP tags to the
+ geo file. First cut at transparent, needs to be augmented to
+ allow a list of colors to zap.
+
+2003-09-02 16:43 jtwilley
+
+ * configure.ac: Moved AM_INIT_AUTOMAKE and added arguments.
+
+ Added documentation for AM_INIT_AUTOMAKE.
+
+2003-09-02 14:05 n2ygk
+
+ * config/tgrcty.dbfawk, src/map_shp.c: tgrcty: fix Louisiana FIPS
+ code map_shp: start adding layer setting via dbfawk too
+
+2003-09-02 10:50 we7u
+
+ * README.win32: Added another comment about "nano" being more
+ user-friendly than "vi", for people coming from a Windows
+ background.
+
+2003-08-30 13:41 jtwilley
+
+ * src/awk.c: Added reference to <sys/types.h> to match dbfawk.c
+
+2003-08-29 09:50 n2ygk
+
+ * configure.ac, config/Makefile.am, config/tgrcty.dbfawk,
+ config/tgrkgl.dbfawk, config/tgrlk.dbfawk, config/tgrwat.dbfawk,
+ src/Makefile.am, src/awk.c, src/awk.h, src/dbfawk.c,
+ src/dbfawk.h, src/gps.c, src/map_shp.c, src/testawk.c,
+ src/tgrcty.dbfawk, src/tgrkgl.dbfawk, src/tgrlk.dbfawk: gps.c:
+ handle spurious compile time warning everything else: add dbfawk
+ support for shapefile maps. Enable with: ./configure
+ --with-dbfawk
+
+2003-08-22 21:37 we7u
+
+ * src/interface_gui.c: Adding another #include, needed for usleep()
+ call.
+
+2003-08-21 15:01 we7u
+
+ * src/db.c: Changed some comment formatting.
+
+2003-08-21 14:10 we7u
+
+ * src/interface_gui.c: Adding a delay after shutting down a port
+ before it is brought up again. These delays are in the
+ interfaces->properties menu when changing an interface that's
+ running.
+
+2003-08-21 12:31 we7u
+
+ * src/: db.c, db.h: Added a new flag to WeatherRow called wx_storm.
+ We wet it when we find any kind of a severe storm, then use that
+ flag in our logic that decides how to draw things. This gets rid
+ of wind barbs for some severe storms.
+
+2003-08-21 11:01 we7u
+
+ * scripts/inf2geo.pl: New revisions by ZL2UMF. Thanks!
+
+2003-08-21 09:42 we7u
+
+ * src/igate.c: We now drop generic queries heading to RF. Also
+ tweaked the log reject messages to be more consistent.
+
+2003-08-21 09:30 we7u
+
+ * src/igate.c: Removed the '*' requirement for TCPXX*, so we now
+ reject anything with TCPXX in it. Added NOGATE options for
+ dropping packets to all igate functions. Added generic query
+ rejection for gating to 'net. Still need to add it into the
+ gate-to-rf code.
+
+2003-08-20 12:55 we7u
+
+ * symbols/symbols.dat: Changing the "smoke" symbol so that it shows
+ a volcano instead of a smokestack. This is more inline with the
+ reason the weather server puts out these symbols, and is more
+ recognizable than the smokestack symbol anyway.
+
+2003-08-20 11:05 we7u
+
+ * src/main.c: Changing the network port check from 7.5 minutes down
+ to one minute. This should reconnect ports more quickly if/when
+ they go down.
+
+2003-08-18 16:16 we7u
+
+ * src/db.c: Removing a back-slash that got in there accidentally.
+
+2003-08-18 15:46 we7u
+
+ * src/db.c: Getting the sort order correct for inserting records
+ into the station database. Didn't work well with the wrong
+ order.
+
+2003-08-18 11:09 we7u
+
+ * src/db.c: Commenting out some speedup code in
+ station_shortcuts_update_function() that may be causing problems
+ at present.
+
+2003-08-18 10:40 we7u
+
+ * src/maps.c: Henk's fix to a pointer problem that I created
+ recently.
+
+2003-08-16 23:04 we7u
+
+ * src/db.c: Fixing a bug in the hash table code which looks for
+ station matches. Making the clear all stations function faster
+ by clearing out the hash table first.
+
+2003-08-15 18:40 we7u
+
+ * src/maps.c: Making index_retrieve() faster by relying on
+ alphanumerical ordering of the map files in the index list. We
+ now save the pointer between runs, and start searching the list
+ at the point we left off.
+
+2003-08-15 18:12 we7u
+
+ * src/main.c: Minor comment cleanup and removing dead code.
+
+2003-08-15 18:04 we7u
+
+ * src/main.c: Better pointers for Map Chooser select updates.
+
+2003-08-15 17:53 we7u
+
+ * src/main.c: Changing from n*n searches to n searches for updating
+ selected bits when closing Map Chooser.
+
+2003-08-15 17:12 we7u
+
+ * src/interface.c: Bumping out of port_read less often. This is
+ only to check whether the thread should be taken down anyway. If
+ a packet is waiting for us to read it, we'll wake up out of the
+ select() anyway.
+
+2003-08-15 16:55 we7u
+
+ * src/main.c: Rearranging some if statements to get a little more
+ speed out of it.
+
+2003-08-15 16:11 we7u
+
+ * src/: main.c, maps.c, maps.h: Added caching of XmString values
+ corresponding to the map filenames for the Map Chooser. The
+ first time bringing up Map Chooser will be at the same speed as
+ before. Second and succeeding invocations of the Map Chooser
+ should be a bit faster because the XmString's are used from the
+ map index records again instead of being created from scratch
+ each time.
+
+2003-08-15 12:30 we7u
+
+ * src/interface.c: CPU-usage optimization tweak to port_read().
+
+2003-08-15 12:11 we7u
+
+ * src/: interface.c, main.c: CPU-usage tweak for dtr_all_set calls.
+ It was getting called constantly whenever an HSP port was
+ enabled.
+
+2003-08-15 11:51 we7u
+
+ * src/maps.c: CPU-usage tweak to index_retrieve().
+
+2003-08-15 11:20 we7u
+
+ * src/db.c: Yet another CPU-usage tweak. This one is to
+ search_station_name(). It's more efficient now at finding
+ stations in the linked list, using a hash table as a jumping-off
+ point.
+
+2003-08-14 15:02 we7u
+
+ * src/map_shp.c: Changing the level at which shorelines get drawn.
+
+2003-08-14 14:59 we7u
+
+ * src/map_shp.c: Setting up more levels at which things won't be
+ drawn. Will make things faster/less cluttered.
+
+2003-08-14 14:46 we7u
+
+ * src/map_shp.c: Optimizing shapefile vector drawing. We don't
+ convert the coordinates for each point now unless we're going to
+ draw the darn thing.
+
+2003-08-14 13:52 we7u
+
+ * src/maps.c: More speedups.
+
+2003-08-14 13:27 we7u
+
+ * src/map_shp.c: Added some comments.
+
+2003-08-14 09:12 we7u
+
+ * src/: main.c, maps.c, maps.h, xastir.h: First part of speeding up
+ Shapefile drawing by staying with lat/long values as much as
+ possible, rather than doing conversions to Xastir coordinate
+ system at every step. The end goal is to do as little math as
+ possible to put pixels on the screen. These changes give a
+ slight speedup to shapefile drawing, noticeable only when loading
+ lots of maps.
+
+2003-08-13 16:26 we7u
+
+ * src/map_shp.c: Reverting back to last version. Floats made
+ CPU-usage worse in this case.
+
+2003-08-13 15:49 we7u
+
+ * src/map_shp.c: Speedups. Using floating point operations instead
+ of unsigned longs.
+
+2003-08-13 12:45 gstueve
+
+ * .cvsignore, callpass/.cvsignore, config/.cvsignore,
+ help/.cvsignore, m4/.cvsignore, scripts/.cvsignore,
+ src/.cvsignore, symbols/.cvsignore: Ignore generated files within
+ CVS base.
+
+2003-08-13 12:38 we7u
+
+ * src/draw_symbols.c: Made the symbol() routine more efficient.
+ Uses much less CPU now.
+
+2003-08-12 11:48 we7u
+
+ * src/interface.c: More performance improvements.
+
+2003-08-12 11:45 we7u
+
+ * src/popup_gui.c: Another performance improvement. Only check for
+ expired popups every two minutes.
+
+2003-08-12 10:29 we7u
+
+ * src/bulletin_gui.c: Another performance improvement. The timing
+ was set up such that find_zero_position_bulletins() ran every
+ time UpdateTime() was started. We now wait 15 seconds between
+ each invocation.
+
+2003-08-11 16:57 we7u
+
+ * src/: db.c, messages.c: More optimizations for speed/CPU-usage.
+ Hash table entry creation is now more efficient.
+ Check_and_transmit_messages now gets skipped if we ran it already
+ that second.
+
+2003-08-11 16:15 we7u
+
+ * src/main.c: Added a comment.
+
+2003-08-11 16:05 we7u
+
+ * INSTALL: Added RH9 ImageMagick instructions, courtesy of Wes
+ Johnston.
+
+2003-08-11 15:40 we7u
+
+ * src/: db.c, main.c: Moved station # display code from db.c to
+ main.c:UpdateTime() so that the number of stations will
+ accurately reflect our count even when no packets are coming in.
+
+2003-08-11 15:08 we7u
+
+ * src/interface.c: Another performance/CPU-usage tweak.
+
+2003-08-11 14:48 we7u
+
+ * src/main.c: Another performance tweak. This one lets you handle
+ multiple high-speed 'net connections and keeps up with the
+ receive queues.
+
+2003-08-11 14:07 we7u
+
+ * src/interface.c: Performance enhancements. Helps Xastir to keep
+ up with very fast network interfaces.
+
+2003-08-11 13:24 we7u
+
+ * src/main.c: Making UpdateTime() run more often, which helps us
+ keep up with fast internet feeds.
+
+2003-08-11 12:57 we7u
+
+ * src/db.c: Changing how often we check for stations and messages
+ to expire from our database. This should also reduce CPU usage.
+
+2003-08-11 11:31 we7u
+
+ * src/bulletin_gui.c: Another CPU-usage tweak. Running through all
+ of the messages looking for new bulletins every 15 seconds
+ instead of every 2. Keeps mscan_file() calls down a bit, which
+ is using a lot of CPU if run often.
+
+2003-08-11 07:04 n2ygk
+
+ * src/: awk.c, awk.h, dbfawk.c, dbfawk.h, testawk.c: Save a newer
+ snapshot of in-progress code. Still not baked.
+
+2003-08-08 18:03 we7u
+
+ * src/db.c: Implementing a 14-bit hash table for station record
+ lookup. This appears to have a BIG effect on CPU usage. May be
+ a bit before the codebase is stable again though, but the gains
+ are definitely worth it. It gives us a feeling for what an SQL
+ database will do for us.
+
+2003-08-08 16:16 we7u
+
+ * src/db.c: Implemented an array of pointers for the station linked
+ list. Each entry represents one possible starting letter/number
+ for the callsign. We use this to speed up the search for a
+ particular record, which is our hardest hitter in terms of
+ CPU-usage right now. This appears to reduce Xastir's CPU
+ requirements by quite a bit, particularly when a lot of stations
+ are in the database.
+
+2003-08-07 13:47 we7u
+
+ * src/draw_symbols.c: Backing out one change which broke the port
+ activity symbols. They're working again now.
+
+2003-08-07 10:01 we7u
+
+ * src/Makefile.am: Taking out the awk/dbfawk stuff temporarily
+ until it can be compiled on most systems again.
+
+2003-08-06 17:54 we7u
+
+ * src/maps.c: Another speedup.
+
+2003-08-06 16:19 we7u
+
+ * src/draw_symbols.c: Speeding up the loading of symbols.
+
+2003-08-06 16:18 we7u
+
+ * src/lang.c: Breaking out of a loop as soon as we get a non-match.
+
+2003-08-06 10:43 we7u
+
+ * README.win32: Added a note regarding Windows not allowing access
+ to files at times.
+
+2003-08-05 07:34 n2ygk
+
+ * src/: Makefile.am, awk.c, dbfawk.c, dbfawk.h, testawk.c: more
+ dbfawk utility functions. I'll be integrating this into
+ map_shp.c RSN!
+
+2003-08-04 16:13 we7u
+
+ * src/main.c: Another small change which makes a difference in CPU
+ usage.
+
+2003-08-04 15:36 we7u
+
+ * src/draw_symbols.c: Changing draw colors only when necessary.
+ Found this one while profiling using gprof. May be more to
+ change in this procedure to speed things up a bit..
+
+2003-08-02 10:00 we7u
+
+ * src/main.c: Tweaked Coordinate Calculator so that it checks
+ lat/long minutes/seconds values for negative numbers and >= 60.0.
+ If out-of-range numbers are found, the error text is displayed
+ in the dialog and a warning message is written to STDERR with a
+ bit more detail on the problem found. Later this STDERR output
+ should probably go to a popup or the main dialog instead, and
+ language strings should be created for them.
+
+2003-07-31 09:01 we7u
+
+ * src/view_message_gui.c: Making the Close button larger.
+
+2003-07-31 08:21 we7u
+
+ * src/view_message_gui.c: Made the View->All Messages dialog
+ resizable in both directions.
+
+2003-07-31 06:00 we7u
+
+ * src/bulletin_gui.c: Fixed View->Bulletins dialog so that it is
+ resizable in both directions.
+
+2003-07-27 22:20 we7u
+
+ * src/: db.c, main.c: Improved Display Packet Data dialog. This
+ one is resizable and very fast. Much better than the previous
+ implementation.
+
+2003-07-26 17:11 we7u
+
+ * symbols/symbols.dat: Added the MODIS Earth Observation symbol.
+ Added a comment specifying where to find the color definitions
+ used for symbols.
+
+2003-07-26 09:35 we7u
+
+ * src/map_dos.c: Commented out some fprintf's that were getting
+ quite verbose when certain Win/DOS maps were loaded. Warnings
+ were that we were trying to call draw/fill polygon routines with
+ 1 or 2 points.
+
+2003-07-25 13:00 we7u
+
+ * src/main.c: Cranked up the delay on REDRAW from 2 to 3 seconds.
+ Changed the dead-reckoning code to schedule a map redraw instead
+ of doing on itself (which probably duplicated some drawing). CPU
+ usage seems to be down because of these changes.
+
+2003-07-25 11:18 we7u
+
+ * src/gps.c: Improved GPS parsing code. Fixed buffer overflow
+ problems and restructured code.
+
+2003-07-25 07:36 we7u
+
+ * src/: gps.c, interface.c: Added line-terminations after strncpy()
+ calls and a bunch of comments at those places as well.
+
+2003-07-24 14:18 we7u
+
+ * src/main.c: Adding more comments.
+
+2003-07-24 14:14 we7u
+
+ * src/: db.c, main.c: Adding uncompressed altitude extension to
+ compressed objects/items.
+
+2003-07-24 09:17 we7u
+
+ * README.win32: Some very minor changes to the Cygwin instructions.
+
+2003-07-24 06:33 n2ygk
+
+ * src/: awk.c, testawk.c, tgrcty.dbfawk, tgrkgl.dbfawk,
+ tgrlk.dbfawk: Add some samples dbfawk files. Remove incorrect
+ "re" pointer.
+
+2003-07-23 14:34 we7u
+
+ * src/: map_dos.c, map_geo.c, map_gnis.c, map_pdb.c, map_shp.c,
+ map_tif.c, map_tiger.c, maps.c, util.c: We now copy the map
+ pixmap to the display if we're loading maps when the
+ interrupt_drawing_now variable gets set.
+
+2003-07-23 13:29 we7u
+
+ * src/map_shp.c: Changing the quantites of labels drawn for each
+ zoom level.
+
+2003-07-23 12:17 we7u
+
+ * src/: Makefile.am, map_geo.c, map_tiger.c, maps.c: Fixes for
+ handling various combinations of Xpm/ImageMagick libraries
+ installed/not-installed. Re-ordered the compile order for the
+ source files to mostly alphabetical order.
+
+2003-07-23 10:33 we7u
+
+ * src/: db.c, location.c, main.c, main.h: Adding more map interrupt
+ capability to tracking and button callback functions.
+
+2003-07-23 09:20 we7u
+
+ * README.win32: Added a note about spaces in
+ filenames/directories/user accounts.
+
+2003-07-22 13:13 we7u
+
+ * src/map_shp.c: Fixing colors so that generated map files put into
+ the maps/GPS directory will show up properly.
+
+2003-07-22 11:15 we7u
+
+ * README.win32: Changed View to Full for selecting packages. Added
+ pcre and pcre-devel to the list.
+
+2003-07-22 07:11 n2ygk
+
+ * src/: awk.c, awk.h, testawk.c: add begin, end_rec. Add some dbf
+ stuff to testawk.c
+
+2003-07-21 09:51 we7u
+
+ * src/awk.c: Initializing a pointer to NULL to get rid of another
+ compiler warning.
+
+2003-07-20 10:44 n2ygk
+
+ * src/: awk.c, awk.h, testawk.c: Make awk.* cleanly compile with
+ -Wall
+
+2003-07-18 14:05 we7u
+
+ * src/: main.h, main.c, maps.c: Setting up code so that the Disable
+ All Maps toggle will immediately take effect while loading maps.
+
+2003-07-18 13:58 we7u
+
+ * configure.ac: Removing -Wall from configure.ac. Jack Twilley
+ added the correct fix to acinclude.m4.
+
+2003-07-18 13:52 jtwilley
+
+ * acinclude.m4: Wrapped gcc-specific tests in an if test for gcc.
+ Added -Wall to CFLAGS when using gcc.
+
+2003-07-18 13:15 we7u
+
+ * configure.ac: Adding "-Wall" to CFLAGS. Not sure if this is the
+ perfect way to get it included into src/Makefile, but this method
+ definitely works.
+
+2003-07-18 12:49 we7u
+
+ * src/gps.c: Adding a define necessary before including time.h, in
+ order to get strptime() function defined on some versions of
+ Linux.
+
+2003-07-18 12:12 we7u
+
+ * src/interface.c: Adding casts to first parameter of
+ pthread_cleanup_push() so that after macro substitution the
+ compiler is still happy with the 2nd parameter of
+ _pthread_cleanup_push().
+
+2003-07-18 11:13 we7u
+
+ * INSTALL: Removing tabs.
+
+2003-07-18 06:14 rzg
+
+ * help/help-English.dat: Moved some stuff around, AGWPE now a
+ section, minor corrections.
+
+2003-07-17 19:29 n2ygk
+
+ * INSTALL, configure.ac, src/Makefile.am, src/awk.c, src/awk.h,
+ src/testawk.c: Start adding support for my awk-like metadata for
+ shapefiles: Tests for -lpcre, documentation of where to find
+ pcre, and awk.c, awk.h which is the code that will be called once
+ I get the nerve to do some serious hacking on map_shp.c:-)
+
+2003-07-17 14:54 we7u
+
+ * README.win32: Added another note about the .cvspass file.
+
+2003-07-17 12:37 we7u
+
+ * src/util.c: Fixing timezone for non Cygwin systems. #ifdef's
+ were a bit wrong.
+
+2003-07-17 12:25 we7u
+
+ * README.win32: Adding a few more error messages that might occur
+ while doing CVS operations.
+
+2003-07-17 08:28 we7u
+
+ * src/db.c: Making Tropical Storm/Tropical Depression/Hurricane
+ wind speed rings disappear at the ghosting time.
+
+2003-07-16 14:07 we7u
+
+ * src/interface.c: Installing thread cleanup routines. These
+ should take care of unlocking mutex's when the threads terminate
+ for any reason. Should keep the rest of the program running.
+
+2003-07-15 22:25 we7u
+
+ * README.win32: Changing the note about creating the .cvsrc file.
+ Trying to make it VERY CLEAR that a Unix-type editor must be
+ used.
+
+2003-07-15 15:58 we7u
+
+ * src/util.c: Changing the begin_critical_section() functio (mutex
+ locks). If a resource has already been locked, output a warning
+ message and skip trying to lock again. This should allow Xastir
+ to recover should locks or unlocks be tried twice or more in
+ sequence. Warning messages will get printed, but the threads
+ should continue to run.
+
+2003-07-15 15:42 we7u
+
+ * src/main.c: Adding the busy cursor in a couple of places so that
+ we have a better indication of when map drawing is taking place.
+
+2003-07-15 13:46 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Cranking up the GPS
+ timing if it is set lower than 3 seconds. We also now present a
+ popup to the user to notify them that the GPS timing has been
+ changed.
+
+2003-07-15 13:23 we7u
+
+ * src/main.c: Adding a timeout for HSP ports for GPS listener mode.
+
+2003-07-15 12:34 we7u
+
+ * src/interface.c: First attempt at fixing some of the HSP
+ interface's problems. This one will send strings other than
+ GPGGA and GPRMC through the normal decoding sequence. That will
+ at least process received TNC strings, which the previous code
+ did not.
+
+2003-07-15 11:13 we7u
+
+ * src/util.c: Skip copying final pixmap to display if we have a map
+ interrupt.
+
+2003-07-15 11:08 we7u
+
+ * src/map_tiger.c: Commenting out a bunc of the map interrupt code
+ to see if it eliminates segfaults that some users are seeing.
+
+2003-07-15 07:17 n2ygk
+
+ * src/: alert.c, color.c, color.h, db.c, list_gui.c, main.c,
+ map_dos.c, map_geo.c, map_gnis.c, map_pdb.c, map_shp.c,
+ map_tif.c, map_tiger.c, maps.c, maps.h, util.c, xa_config.c,
+ xastir.h: Update to newer emacs c-basic-offset
+
+2003-07-14 14:37 we7u
+
+ * README.win32: Changed "diff" to "diffutils", as they apparently
+ changed what package "diff" could be found in.
+
+2003-07-14 14:26 we7u
+
+ * README.win32: Adding a blurb about the final-final dialog for
+ Cygwin installs that must have it's OK button pressed for the
+ whole thing to finish.
+
+2003-07-14 13:31 we7u
+
+ * help/: help-English.dat, help-German.dat, help-Italian.dat,
+ help-Portuguese.dat, help-Spanish.dat: Changing docs to match new
+ /usr/local/share/xastir/* directories.
+
+2003-07-14 13:24 we7u
+
+ * FAQ, INSTALL, README.MAPS, README.win32, UPGRADE: Changing docs
+ to match newer /usr/local/share directory structure.
+
+2003-07-11 08:44 we7u
+
+ * src/util.c: GMT -> Localtime fixes for both Unix and Cygwin.
+
+2003-07-10 13:25 we7u
+
+ * src/util.c: Timezone changes for Cygwin.
+
+2003-07-10 12:06 we7u
+
+ * src/interface.c: Changes for HSP.
+
+2003-07-10 12:00 we7u
+
+ * src/draw_symbols.c: Forcing expire of severe weather polygons at
+ a 10 minute interval, ignoring the user-settable ghosting period
+ for these objects.
+
+2003-07-09 17:18 we7u
+
+ * src/main.c: Changing one comment.
+
+2003-07-09 17:18 we7u
+
+ * src/interface.c: Changing some usleep's throughout. Mostly
+ making them larger, having to do with starting/stopping
+ interfaces.
+
+2003-07-09 17:04 we7u
+
+ * src/interface_gui.c: Backing out a few of the TAB_GROUP items.
+ Don't work for some widgets. Cause segfaults. This version
+ appears to work properly.
+
+2003-07-09 16:34 we7u
+
+ * src/interface_gui.c: Setting up tab groups for all of the
+ interface GUI dialogs.
+
+2003-07-09 15:55 we7u
+
+ * src/interface_gui.c: Fixing tab groups for Interfaces->Properties
+ dialog for internet servers. Probably more to come for other
+ interface types.
+
+2003-07-09 15:26 we7u
+
+ * src/draw_symbols.c: Detaching multipoint object drawing from the
+ "Include Expired Data" toggle. They now expire at the ghosting
+ interval.
+
+2003-07-09 15:02 we7u
+
+ * src/xa_config.c: Making the default for displaying old data equal
+ to zero now instead of 1.
+
+2003-07-07 16:51 we7u
+
+ * src/main.c: Causing display updates once per 60 seconds, even
+ with no input triggers.
+
+2003-07-07 16:19 we7u
+
+ * src/map_shp.c: Adding in maximum zoom levels for various water
+ features. They still need fine-tuning.
+
+2003-07-07 14:30 we7u
+
+ * src/db.c: Added a limit to the number of trackpoints displayed in
+ Station Info. This prevents lockups when display Station Info on
+ extremely long paths, for instance: TrackMe with GPS enabled,
+ displaying Station Info on my own station.
+
+2003-07-07 14:20 we7u
+
+ * src/main.c: Added in the map interrupt stuff for drawing
+ symbols/tracks. Maps and symbols/tracks now appear to be drawn &
+ interrupted together.
+
+2003-07-07 13:56 we7u
+
+ * src/interface.c: Tweaks for HSP interfaces. DTR should be reset
+ now after sending waypoint strings out to the GPS on an HSP port.
+
+2003-07-07 13:23 we7u
+
+ * src/main.c: Changed some comments.
+
+2003-07-07 13:22 we7u
+
+ * src/interface.c: Changed a comment.
+
+2003-07-07 11:09 we7u
+
+ * scripts/xastir-fixcfg.sh: Script now removes the map_index.sys
+ file and moves the selected_maps.sys file to
+ selected_maps.sys.backup
+
+2003-07-07 10:57 we7u
+
+ * src/maps.c: Changed some comments.
+
+2003-07-07 10:17 we7u
+
+ * scripts/icontable.pl: Changed path to match new Xastir directory
+ structure.
+
+2003-07-07 09:33 we7u
+
+ * UPGRADE: Added instructions for migrating to Xastir's new
+ directory structure.
+
+2003-07-05 08:28 n0vh
+
+ * scripts/fcc-get: Updated to reflect the new directory structure.
+
+2003-07-04 15:17 we7u
+
+ * scripts/xastir-migrate.sh: Changing script so that it deletes the
+ old files and not the new.
+
+2003-07-04 12:32 we7u
+
+ * src/: db.c, location.c, main.c, main.h, map_dos.c, map_geo.c,
+ map_gnis.c, map_pdb.c, map_shp.c, map_tif.c, map_tiger.c, maps.c:
+ A better implementation of the interrupt-map-loading function.
+ We still end up with tracks/stations drawn strangely when we
+ first interrupt, but that's the next problem I'll tackle.
+
+2003-07-04 10:10 rzg
+
+ * help/help-English.dat: Listing the last few changes...
+
+2003-07-04 02:11 we7u
+
+ * src/main.c: Made some of the mouse and keyboard operations
+ interruptible.
+
+2003-07-03 14:30 we7u
+
+ * src/: map_dos.c, map_geo.c, map_gnis.c, map_pdb.c, map_shp.c,
+ map_tif.c, map_tiger.c: More map interrupting capability.
+ Currently works for resizing quite nicely.
+
+2003-07-03 13:23 we7u
+
+ * src/: map_geo.c, maps.c: Adding in more map drawing interruption
+ capability.
+
+2003-07-03 12:13 we7u
+
+ * src/: main.c, main.h, maps.c: Added some flags that get set by
+ da_resize, which then immediately exits allowing X11 to continue.
+ If interrupt_drawing_now is set, map drawing ceases after the
+ map we're currently loading is finished. If request_resize is
+ set, then a resize operation is started by UpdateTime. We can
+ add checks for interrupt_drawing_now to other routines later in
+ order to stop map drawing more quickly. Next is to do a similar
+ thing for the da_input function, so that a keypress or mouse
+ click can interrupt map loading.
+
+2003-07-03 10:32 n2ygk
+
+ * scripts/Makefile.am: eliminate duplicate config data
+
+2003-07-03 10:07 n2ygk
+
+ * xastir.spec.in: Patches are now integrated in the main trunk.
+
+2003-07-02 14:49 we7u
+
+ * scripts/: migrate-config.sh, migrate-dirs.sh: Removed these two
+ files in favor of two new files by Alan.
+
+2003-07-02 14:48 we7u
+
+ * scripts/: xastir-fixcfg.sh, xastir-migrate.sh: Minor tweaks.
+ Added Id tags for CVS and more directories.
+
+2003-07-02 14:19 n2ygk
+
+ * Makefile.am, configure.ac, config/Makefile.am, help/Makefile.am,
+ scripts/Makefile.am, symbols/Makefile.am: Changed locations of
+ shared xastir files. After make install you should run
+ scripts/xastir-migrate.sh and scripts/xastir-fixcfg.sh. The
+ former fixes the shared files directory. The latter fixes your
+ personal xastir.cnf references to those shared files.
+
+2003-07-02 14:03 n2ygk
+
+ * scripts/: Makefile.am, xastir-fixcfg.sh, xastir-migrate.sh: Add
+ xastir-fixcfg.sh and xastir-migrate.sh
+
+2003-07-02 08:49 we7u
+
+ * README.win32: Added a chmod command for creating a script for
+ starting Xastir.
+
+2003-07-02 07:11 n2ygk
+
+ * src/map_dos.c: fix reversed cleanup of __LCLINT__ ifdef that was
+ wrong.
+
+2003-07-01 23:10 we7u
+
+ * src/map_dos.c: Fixed some minor bugs w.r.t. DOS map decoding.
+
+2003-06-30 14:37 we7u
+
+ * src/maps.c: Fixing a naming problem for a variable.
+
+2003-06-30 09:53 we7u
+
+ * src/maps.h: Adding more prototypes needed by some of the map
+ files that have been newly separated out from maps.c.
+
+2003-06-30 09:52 we7u
+
+ * src/maps.c: Commenting out an unused function.
+
+2003-06-30 09:52 we7u
+
+ * src/map_dos.c: Commenting out some unused variables.
+
+2003-06-26 08:37 n2ygk
+
+ * src/: Makefile.am, map_dos.c, map_geo.c, map_gnis.c, map_pdb.c,
+ map_shp.c, map_tif.c, map_tiger.c, maps.c, maps.h: split maps.c
+ into several map-specific files.
+
+2003-06-25 12:00 we7u
+
+ * src/main.c: Update tracking station call if TrackMe is enabled
+ when we change our own station callsign.
+
+2003-06-22 12:48 we7u
+
+ * src/maps.c: Decoding school district types in shapefiles and
+ displaying as a yellow border.
+
+2003-06-20 19:06 we7u
+
+ * src/main.c: More moving save station trail and GPSMAN functions
+ to use the local users' ~/.xastir/gps and ~/.xastir/tracklogs
+ directories.
+
+2003-06-20 19:05 we7u
+
+ * src/maps.c: Starting to move GPS and Save station trail functions
+ so that they use ~/.xastir/gps and ~/.xastir/tracklogs
+ directories.
+
+2003-06-20 18:27 we7u
+
+ * src/: maps.c, track_gui.c: Shortening the temp files to get rid
+ of "xastir_" and the username.
+
+2003-06-20 16:55 we7u
+
+ * src/: main.c, track_gui.c, maps.c: Moving temporary files into
+ the users ~/.xastir/tmp directory.
+
+2003-06-20 16:10 we7u
+
+ * src/maps.c: Changing default auto_maps for directories and .geo
+ files to 0.
+
+2003-06-20 15:52 we7u
+
+ * scripts/: migrate-config.sh, migrate-dirs.sh: Migration scripts
+ by Alan Crosswell, N2YGK.
+
+2003-06-20 15:29 we7u
+
+ * src/track_gui.c: Added some comments regarding the date/timestamp
+ that's available on findu.com for track downloads.
+
+2003-06-20 14:57 we7u
+
+ * src/: db.c, draw_symbols.c, draw_symbols.h, main.c: Tweaks to
+ display signpost symbol data next to symbol. Also allow letters
+ now instead of just digits, as the spec appears to allow this.
+ Next thing to bring us fully into compliance is to only show the
+ signpost data at close-in zoom levels (minor), and perhaps also
+ to show the data on top of the sign (also minor).
+
+2003-06-18 11:40 we7u
+
+ * src/main.c, config/language-Dutch.sys,
+ config/language-English.sys, config/language-French.sys,
+ config/language-German.sys, config/language-Italian.sys,
+ config/language-Portuguese.sys, config/language-Spanish.sys:
+ Fixes for the Map Chooser confusion regarding the clear and the
+ map-type selection buttons.
+
+2003-06-18 11:12 we7u
+
+ * src/maps.c: Tweaks by Derrick J Brashear, KB3EGH, to handle
+ non-USGS geotiff images properly.
+
+2003-06-17 21:13 rzg
+
+ * help/help-English.dat: Beginnings of new BETA section, list
+ form...
+
+2003-06-17 18:29 kd6zwr
+
+ * src/maps.c: Adding check for raster maps that are too big or
+ small for display. define FUZZYRASTER to enable.
+
+2003-06-17 17:24 we7u
+
+ * config/xastir.rgb, src/main.c: Making a color change that Henk
+ wanted, so that yellow tracks can be seen on top of yellow map
+ fills.
+
+2003-06-17 17:02 we7u
+
+ * src/maps.c: Added MAP_SCALE_CHECK define and associated code.
+ Will skip maps whose extents are smaller than 4% of the view
+ size. The define is commented out by default so that the check
+ is not performed.
+
+2003-06-17 12:48 we7u
+
+ * src/xa_config.c: Added a comment.
+
+2003-06-16 15:56 we7u
+
+ * src/interface.c: Support for sequence numbers in OpenTrac
+ packets. Can send multiple positions in one packet.
+
+2003-06-16 13:48 we7u
+
+ * help/help-English.dat: More details on the REFRESH .geo tag.
+
+2003-06-16 11:50 we7u
+
+ * src/interface.c: Fixing a small bug in the OpenTrac text output
+ regarding symbols.
+
+2003-06-16 11:49 we7u
+
+ * src/: db.c, maps.c, util.c: Changing puts() calls to fprintf().
+
+2003-06-16 10:34 we7u
+
+ * help/help-English.dat: Added the REFRESH tag description for .geo
+ files.
+
+2003-06-15 17:33 we7u
+
+ * configure.ac: Bumping rev number past the last stable rev number.
+
+2003-06-14 00:19 we7u
+
+ * src/interface.c: Translating from OpenTrac symbols to APRS
+ symbols.
+
+2003-06-13 22:35 we7u
+
+ * src/interface.c: Taking out devel code that's not working yet.
+
+2003-06-13 18:47 kd6zwr
+
+ * src/: main.c, main.h, maps.c: Added REFRESH tag to geo files.
+
+2003-06-13 16:34 we7u
+
+ * src/interface.c: Terminating the list with empty strings.
+
+2003-06-13 16:08 we7u
+
+ * src/interface.c: Adding a symbol translation table for OpenTrac.
+ Not used in the code yet.
+
+2003-06-13 15:22 we7u
+
+ * src/interface.c: Initial OpenTrac decode routines. Implemented
+ only for AX.25 interfaces to date.
+
+2003-06-13 15:17 we7u
+
+ * src/maps.h: Adding an export for a routine which will be needed
+ in interface.c soon.
+
+2003-06-13 14:15 we7u
+
+ * configure.ac: Bumping rev up to 1.2.0 in preparation for stable
+ release.
+
+2003-06-13 13:42 rzg
+
+ * help/help-English.dat: Adding a bit about the green and blue
+ weather boxes (multipoints)
+
+2003-06-11 11:15 we7u
+
+ * help/: help-English.dat, help-Portuguese.dat: Fixed some of the
+ FIXME's.
+
+2003-06-11 10:42 we7u
+
+ * help/: help-German.dat, help-Portuguese.dat: Changed "BETA" to
+ "1.2".
+
+2003-06-11 10:32 rzg
+
+ * help/help-English.dat: Release will be 1.2
+
+2003-06-08 09:15 we7u
+
+ * src/gps.c: Removing tabs (again).
+
+2003-06-07 15:43 kd6zwr
+
+ * src/gps.c: fixing null pointer reference
+
+2003-06-07 15:43 kd6zwr
+
+ * src/db.c: fixing compiler warnings
+
+2003-06-07 07:19 francais1
+
+ * config/language-French.sys: Updated
+
+2003-06-07 00:29 we7u
+
+ * config/language-Italian.sys: A few more translations by Marco
+ Calistri, IK5BCU.
+
+2003-06-06 17:34 we7u
+
+ * src/draw_symbols.c: Changing tabs to spaces.
+
+2003-06-06 17:19 we7u
+
+ * src/main.c: Converting more tabs to spaces.
+
+2003-06-06 17:12 we7u
+
+ * src/track_gui.c: Changing more tabs to spaces.
+
+2003-06-06 17:04 we7u
+
+ * src/: interface.c, maps.c: Changing more tabs to spaces.
+
+2003-06-06 16:57 we7u
+
+ * src/: db.c, igate.c, popup_gui.c, wx_gui.c, xa_config.c: Removing
+ tabs that snuck into the source code. Replaced with spaces.
+
+2003-06-06 12:50 we7u
+
+ * src/maps.c: Adding another error message in Snapshot thread. If
+ we get a system() call error but errno is zero, this fprintf()
+ will get triggered.
+
+2003-06-06 12:49 we7u
+
+ * src/db.c: Changes by Henk de Groot, PE1DNN.
+
+2003-06-06 12:37 we7u
+
+ * README.win32: More revisions to the note about modifier keys.
+
+2003-06-05 17:02 we7u
+
+ * README.win32: Added a few notes about the libraries which
+ currently cannot be used with Cygwin.
+
+2003-06-05 16:56 we7u
+
+ * README.win32: Revising a few notes. Added a new section
+ detailing how to keep Cygwin and Xastir up-to-date.
+
+2003-06-05 13:55 we7u
+
+ * src/maps.c: Checking errno in snapshot routine if the system call
+ returns a possible error.
+
+2003-06-05 13:11 we7u
+
+ * acinclude.m4, src/maps.c: Reverting back to older snapshot
+ method. Removing configure message regarding old ImageMagick
+ versions, as even the old versions appear to currently work with
+ the Tigermap intensity slider.
+
+2003-06-05 10:54 we7u
+
+ * src/db.c: Changes by Henk de Groot, PE1DNN. Fixes weather packet
+ parsing problems for packets containing spaces or dots in place
+ of data.
+
+2003-06-05 10:05 we7u
+
+ * README.win32: Added notes about X modifier keys and Cygwin web
+ sites.
+
+2003-06-05 09:53 we7u
+
+ * README.win32: Adding more notes about Cygwin's network installer.
+
+2003-06-04 15:35 rzg
+
+ * help/help-English.dat: Fixing the formatting in a few spots and
+ correcting an unlear statment.
+
+2003-06-04 09:05 we7u
+
+ * src/: maps.c, track_gui.c, util.c, util.h: Fixing a bug where we
+ don't return from map routines properly on a libcurl error.
+
+2003-06-03 14:49 we7u
+
+ * src/main.c: Fixing a bug in the Map Chooser which occurs when
+ deselecting files. It was putting a warning message to STDERR.
+
+2003-06-03 14:31 we7u
+
+ * FAQ: Added a note about color tinting using Hummingbird eXceed.
+
+2003-06-03 14:01 we7u
+
+ * README.win32: Added notes about totally black images for geotiff
+ files and how to fix it.
+
+2003-06-02 16:58 we7u
+
+ * src/maps.c: Knocking out the snapshot code for the case where
+ ImageMagick isn't present. When Jack is finished, he can take
+ the #ifdef back out.
+
+2003-06-02 16:23 jtwilley
+
+ * src/maps.c: Use new acinclude.m4 logic to include correct
+ ImageMagick header.
+
+2003-06-02 16:20 jtwilley
+
+ * acinclude.m4: Added extra header checks for ImageMagick.
+
+2003-06-02 02:49 jtwilley
+
+ * src/maps.c: Replaced XpmWriteFileFromPixmap + system("convert")
+ with ImageMagick code
+
+2003-05-30 22:47 we7u
+
+ * src/maps.c: Fixing some ambiguous if/else bracing.
+
+2003-05-30 22:43 we7u
+
+ * src/db.c: Fixing some ambiguous if/else braces.
+
+2003-05-30 15:51 jtwilley
+
+ * acinclude.m4: Checked in fabulous new ImageMagick code.
+
+2003-05-30 12:16 we7u
+
+ * src/maps.c: Protecting some draw functions from getting called
+ with too few vertices.
+
+2003-05-30 11:54 we7u
+
+ * src/rotated.c: Added code to skip XFillPolygon() call if the
+ number of points is too few or negative.
+
+2003-05-30 11:44 we7u
+
+ * src/draw_symbols.c: Added some comments. No code changes.
+
+2003-05-29 08:27 we7u
+
+ * config/: language-Dutch.sys, language-French.sys,
+ language-German.sys, language-Spanish.sys: Changing spacing
+ slightly to align Map Properties dialog column headings.
+
+2003-05-29 08:26 we7u
+
+ * config/language-Portuguese.sys: Changes by David Quental, CT1DRB.
+
+2003-05-29 08:25 we7u
+
+ * config/language-Italian.sys: Changes by Alessandro Frigeri,
+ IK0YUP.
+
+2003-05-28 17:12 we7u
+
+ * README.win32: Added instructions for snagging/installing liblcms,
+ needed by later versions of ImageMagick.
+
+2003-05-28 16:21 we7u
+
+ * src/maps.c: Terraserver changed to a new hostname. Changing to
+ correspond.
+
+2003-05-28 13:33 we7u
+
+ * config/language-German.sys, help/help-German.dat: Changes by Rolf
+ Bleher, DK7IN.
+
+2003-05-28 13:24 we7u
+
+ * config/language-German.sys: Changes by Rolf Bleher, DK7IN.
+
+2003-05-28 12:58 we7u
+
+ * config/language-Dutch.sys: Changes by Han Sytsma, PE1FAM.
+
+2003-05-28 12:57 we7u
+
+ * config/language-Spanish.sys: Changes by Jose R. Marte A., HI8GN.
+
+2003-05-28 11:49 we7u
+
+ * config/language-German.sys: Changes by Rolf Bleher, DK7IN.
+
+2003-05-28 11:18 we7u
+
+ * config/language-German.sys: Changes by Rolf Bleher, DK7IN.
+
+2003-05-28 11:09 we7u
+
+ * config/language-German.sys: Translation of "Moisture" by Rolf
+ Bleher, DK7IN.
+
+2003-05-28 10:33 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c: More
+ translations. Also changing "meters" to "m".
+
+2003-05-28 10:14 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c: Changing a few
+ more hard-coded strings.
+
+2003-05-27 18:00 rzg
+
+ * help/help-English.dat: Grammar corrections. :-P
+
+2003-05-27 16:44 we7u
+
+ * INSTALL, README.win32: More ImageMagick notes.
+
+2003-05-27 15:24 we7u
+
+ * src/db.c: Fixed how we handle space/dot-filled
+ temperature/humidity fields.
+
+2003-05-27 13:43 we7u
+
+ * src/main.c: Commenting out the new ifdef. Forgot to after
+ testing.
+
+2003-05-27 13:40 we7u
+
+ * src/: main.c, interface_gui.c: Separated out the LARGE_FONT
+ #ifdef's into two: USE_LARGE_SYSTEM_FONT and
+ USE_LARGE_STATION_FONT. This is to help the visually impaired.
+ Made the cursor position visible in more of the
+ Interfaces->Properties dialogs.
+
+2003-05-27 13:25 we7u
+
+ * config/language-Portuguese.sys: Changes by David Quental, CT1DRB.
+
+2003-05-27 10:57 we7u
+
+ * help/help-English.dat: Clarified the note about IMAGESIZE being
+ required for .geo files with URL's, optional for local images.
+
+2003-05-27 10:56 we7u
+
+ * README.MAPS: Another note about IMAGESIZE being a required
+ parameter for .geo files with URL's in them.
+
+2003-05-24 22:52 we7u
+
+ * src/: maps.c, popup_gui.c: Moved some code and added comments to
+ make it very obvious that fonts are not to be loaded often.
+ Causes memory leaks.
+
+2003-05-24 21:58 we7u
+
+ * src/main.c: Adding a method to switch to larger fonts, helpful to
+ visually-impaired users. Uncomment the USE_LARGE_FONTS #ifdef at
+ the top of main.c to enable these larger fonts. Off by default.
+
+2003-05-24 00:57 we7u
+
+ * src/main.c: Re-doing the widget geometry for the Configure->Audio
+ Alarms dialog. It now works with large or small fonts.
+
+2003-05-24 00:05 we7u
+
+ * src/draw_symbols.c: Added some comments.
+
+2003-05-23 16:30 we7u
+
+ * src/maps.c: Fixing intensity slider for Tigermap by switching
+ from LevelImage() call to ModulateImage() call.
+
+2003-05-23 15:59 we7u
+
+ * config/language-Spanish.sys: Changes by Jose R. Marte A., HI8GN.
+
+2003-05-23 15:59 we7u
+
+ * config/: language-Dutch.sys: Changes by Han Sytsma, PE1FAM.
+
+2003-05-23 14:58 we7u
+
+ * config/language-Spanish.sys: Changes by Jose R. Marte A., HI8GN.
+
+2003-05-23 14:18 we7u
+
+ * src/xa_config.c: Setting initial default for
+ MAP_CHOOSER_EXPAND_DIRS to 1, so that the terraserver.geo and
+ toposerver.geo files will appear by default for new users.
+
+2003-05-23 13:32 we7u
+
+ * terraserver.geo, toposerver.geo: Adding these files to the
+ sources.
+
+2003-05-23 13:32 we7u
+
+ * Makefile.am: Auto-installing terraserver.geo and toposerver.geo
+ in the maps directory.
+
+2003-05-23 13:29 we7u
+
+ * README.win32: More explanation of CVS errors when SourceForge is
+ too busy.
+
+2003-05-23 13:19 we7u
+
+ * README.win32, help/help-English.dat: Added TOPOSERVER
+ instructions.
+
+2003-05-23 13:16 we7u
+
+ * README.MAPS: Added the TOPOSERVER keyword and explanation.
+
+2003-05-23 13:11 we7u
+
+ * src/maps.c: On-line topo maps. I considered the utility of this
+ versus not adding it until after release. This is just too
+ useful for new (and old) users not to have put it in. Enjoy!
+ Geo file with "TOPOSERVER" in it will get you online topo maps.
+
+2003-05-23 12:06 we7u
+
+ * src/main.c: Fixing SmartBeaconing dialog so that it's aligned
+ properly.
+
+2003-05-23 11:44 we7u
+
+ * src/main.c: SmartBeaconing dialog now supports metric units.
+
+2003-05-23 10:52 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface_gui.c,
+ src/track_gui.c: Changing more hard-coded strings into
+ language-specific strings.
+
+2003-05-23 10:08 we7u
+
+ * help/help-English.dat: More minor spelling on consistency
+ changes.
+
+2003-05-23 09:14 we7u
+
+ * config/language-Portuguese.sys: Making the time periods
+ correspond with the English file.
+
+2003-05-22 22:14 we7u
+
+ * help/help-English.dat: Lots of minor tweaks throughout the file.
+
+2003-05-22 14:01 we7u
+
+ * help/help-English.dat: Minor updates.
+
+2003-05-22 13:20 we7u
+
+ * README.MAPS: Updating the NOAA filenames for the alert
+ shapefiles.
+
+2003-05-22 12:37 we7u
+
+ * README: Correcting spelling.
+
+2003-05-22 12:33 we7u
+
+ * README.MAPS: Added notes about setting up permissions for
+ maps/GPS directory.
+
+2003-05-22 12:22 we7u
+
+ * AUTHORS, INSTALL, NEWS, README.MAPS: Tweaking docs here and
+ there.
+
+2003-05-22 12:02 we7u
+
+ * DEBUG_LEVELS: Swapped the two sections. Most useful info at the
+ top of the file now.
+
+2003-05-22 11:58 we7u
+
+ * DEBUG_LEVELS, FAQ, INSTALL, LICENSE, NEWS, README, README.CVS,
+ README.MAPS, README.win32, UPGRADE: Adding/changing copyright
+ notice.
+
+2003-05-22 11:48 we7u
+
+ * README.win32: Adding more notes. Reworking existing notes to
+ make them more understandable to Windows-folk.
+
+2003-05-22 09:32 we7u
+
+ * INSTALL: Adding info regarding matching up the libtiff/libgeotiff
+ versions.
+
+2003-05-21 16:16 we7u
+
+ * src/: db.h, main.c: Reversing the direction of the two Area
+ Object lines, to correspond with dos/winAPRS and UI-View.
+
+2003-05-21 16:16 we7u
+
+ * src/draw_symbols.c: Added some comments.
+
+2003-05-21 15:40 francais1
+
+ * src/: db.c, db.h, draw_symbols.c, draw_symbols.h: Fixed corridor
+ > 127 bug (now works up to 999, which I believe is the spec
+ limit)
+
+2003-05-21 15:34 we7u
+
+ * src/draw_symbols.c: Added some comments.
+
+2003-05-21 14:18 we7u
+
+ * src/draw_symbols.c: Implemented area object ellipse display
+ exactly the same as circle display. This is what UI-View is
+ doing. dos/WinAPRS don't implement ellipses at all.
+
+2003-05-21 13:31 we7u
+
+ * config/language-German.sys, help/help-German.dat: Changes by Rolf
+ Bleher, DK7IN.
+
+2003-05-21 12:56 we7u
+
+ * src/maps.c: Canceling certain warning messages while indexing.
+
+2003-05-21 12:30 we7u
+
+ * README.CVS: Updates to match our current codebase and how we do
+ things.
+
+2003-05-21 12:22 we7u
+
+ * src/main.c: Fixing the Map Properties strings so that they are
+ auto-centered in the columns and truncated to the column widths.
+
+2003-05-21 11:45 we7u
+
+ * src/main.c: Truncating language strings in Map Properties columns
+ (the "yes" string) so that it fits our column width.
+
+2003-05-21 10:01 we7u
+
+ * config/language-Portuguese.sys: Changes by David Quental, CT1DRB.
+
+2003-05-21 09:45 we7u
+
+ * config/language-Portuguese.sys: Changes by David Quental, CT1DRB.
+
+2003-05-21 09:44 we7u
+
+ * config/language-Spanish.sys: Changes by Jose R. Marte A., HI8GN.
+
+2003-05-21 09:44 we7u
+
+ * config/language-German.sys: Changes by Rolf Bleher, DK7IN.
+
+2003-05-21 09:22 francais1
+
+ * config/language-French.sys: Translated added English
+
+2003-05-20 17:15 we7u
+
+ * src/: interface.c, main.c: Correcting some grammar.
+
+2003-05-20 17:14 we7u
+
+ * README.win32: Removing the Perl 5.6 restriction. Perl 5.8
+ appears to work properly now with Xastir and it's optional
+ libraries.
+
+2003-05-20 14:28 we7u
+
+ * config/language-Dutch.sys: Changes by Han Sytsma, PE1FAM.
+
+2003-05-20 12:51 we7u
+
+ * config/language-Italian.sys: Adding some missing strings.
+
+2003-05-20 12:22 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Fixing more hard-coded
+ language strings.
+
+2003-05-20 12:09 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Fixing hard-coded
+ strings. Added missing GPS strings in Italian file.
+
+2003-05-20 11:16 we7u
+
+ * FAQ: Added two more questions/answers.
+
+2003-05-20 10:34 we7u
+
+ * src/: bulletin_gui.c, fcc_data.c, gps.c, interface.c, lang.c,
+ main.c, maps.c, messages.c, rac_data.c, util.c,
+ view_message_gui.c, wx.c, alert.h: Fixing up the <time.h> and
+ <sys/time.h> includes with the proper ifdef's.
+
+2003-05-19 20:42 rzg
+
+ * help/help-English.dat: Typo fixes pointed out by Rolf, minor
+ other things.
+
+2003-05-19 20:28 rzg
+
+ * INSTALL, README.CVS, README.MAPS, UPGRADE: Adding copyright
+ notices to the docs that lack.
+
+2003-05-19 13:14 we7u
+
+ * README.win32: Changes by Kirk Mefford, KC2ELO.
+
+2003-05-19 12:52 we7u
+
+ * src/main.c: Correcting the time.h include to make it sys/time.h.
+
+2003-05-19 11:24 we7u
+
+ * README.win32: Adding checkboxes.
+
+2003-05-19 11:13 we7u
+
+ * config/language-German.sys: Changes by Rolf Bleher, DK7IN.
+
+2003-05-19 10:57 we7u
+
+ * README.win32: Changes by Wes Johnston, edited slightly by me.
+
+2003-05-19 10:35 we7u
+
+ * INSTALL: Added another festival note from Alan Crosswell.
+
+2003-05-19 09:59 we7u
+
+ * config/language-German.sys: Changes by Rolf Bleher, DK7IN.
+
+2003-05-18 11:29 we7u
+
+ * config/language-Italian.sys: Changes by Marco Calistri, IK5BCU.
+
+2003-05-16 17:07 we7u
+
+ * src/maps.c: Removing the debug fprintf() statement.
+
+2003-05-16 17:03 we7u
+
+ * src/maps.c: Fix for wrong guessing of road widths for some types
+ of Shapefiles.
+
+2003-05-16 16:06 we7u
+
+ * INSTALL: Shapelib instructions for MacOSX.
+
+2003-05-16 14:44 we7u
+
+ * README.win32: More detailed instructions for Shapelib
+ integration.
+
+2003-05-16 13:12 we7u
+
+ * README.win32: More ImageMagick notes for Cygwin. Setting the
+ MAGICK_HOME variable with the new X configuration.
+
+2003-05-16 11:16 we7u
+
+ * README.win32: Adding a note about the 'X' in the system tray.
+
+2003-05-16 11:10 we7u
+
+ * README.win32: Changing desktop shortcut to start from Cygwin home
+ directory.
+
+2003-05-16 11:02 we7u
+
+ * README.win32: Updated Cygwin instructions to allow using Xwindows
+ apps and Windows apps from the same desktop transparently. No
+ Xwindows large box anymore!
+
+2003-05-15 12:32 we7u
+
+ * src/maps.c: Adding another helpful message for the case where a
+ GEO file is being opened, but perhaps no support is compiled in
+ for the map format.
+
+2003-05-15 12:18 we7u
+
+ * src/maps.c: Spit out appropriate error messages if various
+ optional map libraries are not installed and the user tries to
+ load unsupported map types.
+
+2003-05-15 11:12 we7u
+
+ * src/: maps.c, track_gui.c: Changing one warning message.
+
+2003-05-15 08:09 we7u
+
+ * configure.ac: Bumping the revision up to 1.1.5.
+
+2003-05-15 07:47 we7u
+
+ * Makefile.am: Getting rid of the last remnants of README.1ST.
+ Adding other doc files.
+
+2003-05-14 22:18 rzg
+
+ * FAQ, README.1ST, README.win32: Docs cleanup take 5.
+
+2003-05-14 22:07 jtwilley
+
+ * Makefile.am, xastir.spec.in: Removed references to README.1ST and
+ TODO
+
+2003-05-14 21:02 we7u
+
+ * config/language-Spanish.sys: Changes by Jose R. Marte A., HI8GN.
+
+2003-05-14 20:59 we7u
+
+ * src/main.c: Moving the time.h include outside the
+ HAVE_IMAGEMAGICK ifdef's.
+
+2003-05-14 19:14 rzg
+
+ * README: Took last important bit from README.1ST, ready to trash
+ it...
+
+2003-05-14 17:14 we7u
+
+ * config/language-Dutch.sys: Changes by Han Sytsma, PE1FAM.
+
+2003-05-14 17:08 we7u
+
+ * config/language-Portuguese.sys: Changes by David Quental, CT1DRB.
+
+2003-05-14 16:30 we7u
+
+ * config/language-Spanish.sys: Changes by Jose R. Marte A., HI8GN.
+
+2003-05-14 16:29 we7u
+
+ * config/language-Dutch.sys: Changes by Han Sytsma, PE1FAM.
+
+2003-05-14 16:06 francais1
+
+ * config/language-French.sys: Updated 2 strings to match English.
+
+2003-05-14 16:02 we7u
+
+ * config/language-English.sys: Updating the reindexing strings.
+
+2003-05-14 15:50 we7u
+
+ * AUTHORS, DEBUG_LEVELS, FAQ, INSTALL, NEWS, README, README.CVS,
+ README.MAPS, UPGRADE, changes.txt: Adding/Changing to Id: RCS tag
+ in files.
+
+2003-05-14 15:41 we7u
+
+ * README.MAPS: Updating a NOAA URL.
+
+2003-05-14 13:47 we7u
+
+ * config/language-Spanish.sys: Changed by Jose R. Marte A., HI8GN.
+
+2003-05-14 12:44 francais1
+
+ * config/language-French.sys: Updated
+
+2003-05-14 09:28 rzg
+
+ * README.MAPS, help/help-English.dat: Docs- big cleanup take 4!
+
+2003-05-14 09:14 rzg
+
+ * INSTALL, README, README.1ST, UPGRADE: Docs- big cleanup take 3!
+
+2003-05-14 08:42 rzg
+
+ * INSTALL, README.1ST, README.CVS, README.MAPS: Docs- big cleanup
+ take 2!
+
+2003-05-14 08:40 rzg
+
+ * TODO, UPDATES: Docs - big clean up take 1!
+
+2003-05-13 14:56 jtwilley
+
+ * README.win32: Added Kirk Mefford's suggestion re: creating .cvsrc
+ file
+
+2003-05-12 23:59 we7u
+
+ * src/db.c: CPU Usage fixes. We no longer do complete symbol
+ updates at a high rate. We update only the new symbol, then do
+ cleanup at a 60-second rate sometime later. CPU usage drops a
+ bit with this latest code.
+
+2003-05-12 16:59 we7u
+
+ * src/main.c: Slowed down UpdateTime() iterations so that the
+ read/write threads would have time to do their thing. Cranked up
+ the maximum packets processed by UpdateTime() in one iteration.
+ Added a usleep() after processing each packet so that the read
+ threads would have time to put another packet in the queue. CPU
+ time has gone down by these changes, but we still appear to keep
+ up with the incoming packets.
+
+2003-05-12 16:56 we7u
+
+ * src/interface.c: Speeding up the receive threads. They don't
+ take any CPU time anyway, so this doesn't hurt CPU usage. They
+ process one line then wait for the main thread to pick it up
+ before they process the next line.
+
+2003-05-12 13:59 we7u
+
+ * src/main.c: Changing main.c:UpdateTime() to wait 15ms between
+ each run instead of 10. This reduces CPU time a bit, yet still
+ allows packets to get processed from the receive queues. 20ms
+ appeared to be too slow. Will investigate adding longer delays
+ between graphics updates in this routine, yet allowing packet
+ processing to proceed at a fast pace. That should further reduce
+ CPU cycles yet not get behind in the receive queues. At that
+ point we might reduce the delay again between UpdateTime() runs.
+
+2003-05-12 12:39 we7u
+
+ * README.win32: Updating the list of Cygwin packages to include
+ tcl/tk and Curl.
+
+2003-05-11 22:18 we7u
+
+ * config/language-Italian.sys: Another phrase translated by Marco
+ Calistri, IK5BCU.
+
+2003-05-11 08:06 we7u
+
+ * config/language-Italian.sys: Adding a missing string. In English
+ so far (until I get an Italian translation of it).
+
+2003-05-10 16:42 we7u
+
+ * src/maps.c: Fix by Magne M�hre, la1bfa, for segfault generated
+ when Shapefiles can't be created on the file system, usually due
+ to permissions problems in /usr/local/maps/GPS.
+
+2003-05-10 00:31 we7u
+
+ * src/alert.c: Converting one more strcpy to strncpy.
+
+2003-05-10 00:15 we7u
+
+ * src/alert.c: Fixing another killer packet bug in the alert code.
+
+2003-05-09 14:13 we7u
+
+ * config/language-English.sys: Changing one label slightly
+ regarding reindexing.
+
+2003-05-09 10:43 we7u
+
+ * src/maps.c: Tweaks to maintain selected map properties when a
+ full reindexing is requested.
+
+2003-05-08 23:39 we7u
+
+ * src/: maps.c, maps.h, main.c: Implementing an indexing scheme
+ that takes care of finding updated files quickly, deleting
+ records for deleted files, and wasting everything and starting
+ from scratch to build a new index. This code can do all of that.
+
+2003-05-08 23:32 we7u
+
+ * README.win32: Removed an email address so that Kirk won't get
+ spammed by the spambots.
+
+2003-05-08 23:28 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Changing/Adding
+ Map Re-Index strings for menus.
+
+2003-05-08 17:44 rzg
+
+ * README.win32: Sound Alert information from Kirk Mefford
+ kc2elo at softhome.net
+
+2003-05-08 14:36 we7u
+
+ * src/main.c: Changed a comment.
+
+2003-05-08 12:31 we7u
+
+ * src/db.c: Fixing the Station Info dialog so that the multipoint
+ strings aren't shown. They're now removed from the string inside
+ the extract_multipoint() function.
+
+2003-05-07 22:26 we7u
+
+ * src/alert.c: Fixing the alert matching so that a new alert will
+ match a pre-existing CANCL packet in the list. This is in
+ response to a bug on the bug-list.
+
+2003-05-07 13:32 francais1
+
+ * src/maps.c: Fixed relative paths to images in .geo files
+
+2003-05-06 21:32 kd6zwr
+
+ * src/maps.c: Made IMAGESIZE tag optional for geo files,
+ (imagemagic ping to autodetect size) Also allow absolute
+ pathnames in geo files, as well as relative.
+
+2003-05-06 14:49 we7u
+
+ * src/db.c: Don't draw wind barbs for severe storm objects.
+
+2003-05-06 13:33 we7u
+
+ * src/db.c: Adding the other types of severe storms that the
+ weather server can issue. This is part of the general hurricane
+ bug fix on the bug list.
+
+2003-05-06 13:19 we7u
+
+ * src/db.c, src/db.h, symbols/symbols.dat: Moving wind speed into
+ the proper field (so that it shows up in Station Info) for
+ hurricanes. This is a partial fix for a bug on the buglist.
+ Changing the tornado symbol so that it stands out more (thanks to
+ Dale Huguley for that one).
+
+2003-05-06 08:17 we7u
+
+ * help/help-English.dat: Added a description of the weather watch
+ box colors/patterns, courtesy of Dale Huguley.
+
+2003-05-05 21:22 we7u
+
+ * src/util.c: Correcting for daylight savings time when converting
+ from zulu time to Unix epoch time. Also added some debug code.
+
+2003-05-05 16:08 jtwilley
+
+ * README.1ST: Minor correction to FreeBSD notes.
+
+2003-05-05 13:36 we7u
+
+ * src/alert.c: Changed some comments. No code changes.
+
+2003-05-05 11:00 we7u
+
+ * src/alert.c: Fixing another "killer packet" problem: If we got
+ an uncompressed message that looked like a weather alert but was
+ simply a test message, we segfaulted while trying to move
+ uninitialized strings around.
+
+2003-05-02 17:31 we7u
+
+ * src/: db.c, alert.c: Rewrote weather alert handling so that
+ compressed format weather alert packets are parsed/displayed
+ correctly.
+
+2003-05-02 11:03 kd6zwr
+
+ * src/maps.c: Initialize a few variables to NULL to shut up -Wall
+
+2003-05-02 10:43 we7u
+
+ * help/help-English.dat: Added a note about IMAGESIZE now being a
+ required keyword in .GEO files.
+
+2003-05-02 01:44 we7u
+
+ * src/db.c: Re-wrote relay_digipeat() so that it is more correct.
+ It now appears to get to the correct part of the path before
+ checking for my_call or RELAY.
+
+2003-05-01 09:47 kd6zwr
+
+ * src/: maps.c, maps.h: Changed reading in map index to much faster
+ mode, and added a sort routine to make sure it is still sorted
+ correctly.
+
+2003-05-01 09:38 we7u
+
+ * src/db.c: Reordered the widgets in the Station Info dialog so
+ that it can be resized properly. This is to take another bug off
+ the buglist regarding oversized Station Info dialog that can't be
+ resized. It can now.
+
+2003-04-30 23:38 we7u
+
+ * README.1ST: Added some notes about tiger file types and NOAA
+ weather alert shapefiles.
+
+2003-04-30 21:19 we7u
+
+ * src/maps.c: Working code for Shapefile polygon "holes"!!!
+
+2003-04-30 13:22 we7u
+
+ * src/util.c: Adding two more lower-case letters to those accepted
+ by valid_path() for Q-constructs.
+
+2003-04-30 13:10 we7u
+
+ * src/maps.c: More debug stuff. More work on Shapefile holes in
+ polygons.
+
+2003-04-30 12:50 we7u
+
+ * src/util.c: Added more debug statements to valid_path().
+
+2003-04-30 10:50 rzg
+
+ * help/help-English.dat, FAQ: Qxx, and other minor updates to help
+ and FAQ.
+
+2003-04-30 09:02 we7u
+
+ * src/maps.c: Comment changes. No code changes (yet!).
+
+2003-04-29 14:37 jtwilley
+
+ * src/main.c: Fixed warnings with libcurl.
+
+ Started GDAL integration.
+
+2003-04-29 13:24 we7u
+
+ * src/maps.c: Changing/adding comments.
+
+2003-04-29 13:02 we7u
+
+ * src/maps.c: Implementing a better fill/hole ring-direction
+ algorithm for Shapefiles. This one is snagged directly from
+ Shapelib and used by permission of the author, Frank Warmerdam.
+
+2003-04-28 23:03 we7u
+
+ * src/maps.c: More tweaks to the Shapefile "hole" ring code. Not
+ fully implemented yet, but added some speed improvements. Next
+ is to implement a clip-mask in the form of regions.
+
+2003-04-28 22:59 we7u
+
+ * src/interface.c: Getting rid of an unused variable.
+
+2003-04-28 21:59 rzg
+
+ * README.1ST: Updates WTR igating weather alerts, minor spacing
+ changes, and nicer libcurl URL.
+
+2003-04-28 21:24 jtwilley
+
+ * README.1ST: Added URL for libcurl.
+
+2003-04-28 20:57 we7u
+
+ * src/db.c: Changed the extract_GLL() function from using strtok()
+ to split_string().
+
+2003-04-28 17:04 we7u
+
+ * src/db.c: Converted extract_RMC() to using split_string() instead
+ of strtok().
+
+2003-04-28 16:17 we7u
+
+ * src/db.c: Removing unused variables.
+
+2003-04-28 16:08 we7u
+
+ * src/db.c: Re-wrote extract_GGA() to avoid a segfault with a
+ killer packet. Need to re-write extract_RMC() and extract_GLL()
+ in a similar manner. The fix is to get rid of strtok() and use
+ util.c:split_string() instead.
+
+2003-04-28 14:50 we7u
+
+ * src/: interface.c, util.c, util.h: Moved split_string() function
+ to util.c/util.h in preparation for using it from more places in
+ the code (instead of just interface.c).
+
+2003-04-28 11:47 we7u
+
+ * src/maps.c: Making debug levels more consistent.
+
+2003-04-28 11:43 we7u
+
+ * src/maps.c: Adding new routine which can determine whether a
+ Shape ring is a fill or a hole ring. This is part of the work to
+ implement the "holes" properly for Shapefiles.
+
+2003-04-28 10:27 we7u
+
+ * config/language-Spanish.sys: Changes by Jose R. Marte A., HI8GN.
+
+2003-04-27 20:45 we7u
+
+ * src/maps.c: Adding more comments.
+
+2003-04-26 23:38 we7u
+
+ * src/maps.c: More comment changes. No code changes.
+
+2003-04-26 23:15 we7u
+
+ * README.1ST: Changed the location for the Tiger/Line->Shapefile
+ downloads.
+
+2003-04-26 18:21 we7u
+
+ * src/maps.c: Working on the Shapelib drawing function "hole"
+ problem. So far just adding comments and example code in
+ comments. No code changes yet.
+
+2003-04-25 17:32 we7u
+
+ * src/maps.c: Adding more comments.
+
+2003-04-25 17:09 we7u
+
+ * src/maps.c: Added comments.
+
+2003-04-25 15:49 we7u
+
+ * config/language-Italian.sys: Another tweak by Marco Calistri,
+ IK5BCU.
+
+2003-04-25 15:45 we7u
+
+ * src/maps.c: Changing to "Nonconvex" parameter for the rest of the
+ XFillPolygon calls. This should speed up drawing a bit.
+
+2003-04-25 15:30 we7u
+
+ * src/maps.c: Changing XFillPolygons to use Nonconvex parameter,
+ which speeds up map drawing for cases where the line doesn't
+ cross its own path. Added some comments.
+
+2003-04-25 15:29 we7u
+
+ * config/: language-Dutch.sys, language-French.sys,
+ language-Italian.sys, language-Spanish.sys: Correcting one bug
+ left in the files due to a mistyped character. Checking in
+ latest Italian translation by Marco Calistri, IK5BCU.
+
+2003-04-25 13:36 we7u
+
+ * README.win32, README.1ST: Added notes about libcurl.
+
+2003-04-24 17:25 jtwilley
+
+ * src/maps.c: Added code to support libcurl. Added code to remove
+ PACKAGE_* warnings.
+
+2003-04-24 17:24 jtwilley
+
+ * src/track_gui.c: Added code to support libcurl.
+
+2003-04-24 17:20 jtwilley
+
+ * src/main.c: Added code to support libcurl. Added code to remove
+ PACKAGE_* warnings.
+
+2003-04-24 17:19 jtwilley
+
+ * src/util.c: Added code for curl_fwrite and curl_getfile.
+
+2003-04-24 17:15 jtwilley
+
+ * src/util.h: Added declarations for curl_fwrite and curl_getfile.
+
+2003-04-24 17:04 jtwilley
+
+ * configure.ac: Added check for libcurl.
+
+2003-04-24 15:25 we7u
+
+ * src/: interface.c, maps.c: Adding comments.
+
+2003-04-24 14:06 we7u
+
+ * README.win32: Revising the Perl interpreter to install. There
+ are problems with 5.8.0 yet.
+
+2003-04-23 13:16 we7u
+
+ * src/interface.c: Changing port_read() to a 50ms delay instead of
+ 20ms. Last checkin was a slight oops.
+
+2003-04-23 13:15 we7u
+
+ * src/interface.c: Speeding up the port_read() and port_write()
+ delays again. We were starting to get behind at processing
+ packets from full-feeds, with 100ms delays. Changed to 50ms
+ delays and we appear to catch up when we get a bit behind. The
+ correct solution for this is to use select() to wait for data to
+ process, instead of using it as a short sleep function.
+ Something to change another day...
+
+2003-04-22 23:08 we7u
+
+ * src/maps.c: Minor revisions to the create_shapefile from APRS
+ Trail functions. Maps are now saved in the /maps/GPS/ directory
+ and are red dashed lines by default. They appear in the Map
+ Chooser once re-index maps has been run.
+
+2003-04-22 10:34 we7u
+
+ * src/: db.c, main.c, main.h, maps.c, maps.h: The "Store Track"
+ button on the Station Info dialog now saves the station track as
+ a Shapefile map in /var/tmp/, if Shapelib has been compiled in.
+ The Shapefile filename will contain the callsign and a
+ date/timestamp. The original function of the button still
+ remains as well: It also saves the info in the original text
+ format.
+
+2003-04-22 01:35 jtwilley
+
+ * src/main.c: Added tnc_data_clean call to static TNC case.
+
+2003-04-22 01:30 jtwilley
+
+ * src/interface.c: Replaced broken routine in tnc_data_clean with
+ working routine.
+
+2003-04-21 15:45 we7u
+
+ * src/interface.c: Changed port_write() so that it'll send blocks
+ of characters across network interfaces, single chars with
+ inter-character pacing across serial interfaces.
+
+2003-04-18 17:21 we7u
+
+ * xastir.spec.in: Updated spec input file. Starting to work.
+
+2003-04-18 17:21 we7u
+
+ * Makefile.am: Adding xastir/GNIS/ directory to install. Used for
+ searching.
+
+2003-04-18 15:37 we7u
+
+ * README.win32: Updating library versions that we've tested with.
+
+2003-04-18 13:59 we7u
+
+ * README.1ST: Updating optional library versions that Xastir has
+ been tested with.
+
+2003-04-18 13:48 we7u
+
+ * xastir.spec.in: Fixes so that man page gets installed correctly.
+
+2003-04-18 12:47 we7u
+
+ * xastir.spec.in: Tweaks to make the spec file more up-to-date.
+ The changes fix several of the failures in building RPM's, but
+ still fails building the man page.
+
+2003-04-18 12:09 we7u
+
+ * README.win32: Updating docs to latest Shapefile version tested.
+
+2003-04-18 11:46 we7u
+
+ * README.1ST: Updating version of Shapelib library to latest
+ tested.
+
+2003-04-17 15:08 we7u
+
+ * src/igate.c: Added a comment.
+
+2003-04-17 14:32 we7u
+
+ * src/igate.c: Adding AGWPE devices to the dupe queues for igating.
+
+2003-04-17 13:35 we7u
+
+ * README.1ST: Adding another map link.
+
+2003-04-17 10:24 we7u
+
+ * README.1ST: Another GPSMan note.
+
+2003-04-17 10:21 we7u
+
+ * README.1ST: Updating the libgeotiff instructions.
+
+2003-04-17 10:11 we7u
+
+ * README.1ST, README.win32: Re-organization of the wetnet
+ directories. Changed links in README's to match.
+
+2003-04-17 09:56 we7u
+
+ * README.1ST, README.win32: Changed from eskimo.com to wetnet.net
+ for some of the optional map library download sites.
+
+2003-04-16 17:12 we7u
+
+ * src/igate.c: We now allow partial matches of NWS data, but the
+ strings defined in the nws-stations.txt file must be at least
+ three characters long in order to create a valid match.
+
+2003-04-16 16:42 we7u
+
+ * src/: interface.c, interface_gui.c, location_gui.c, maps.c:
+ Fixing more possible scanf()/sscanf() buffer overflow conditions.
+
+2003-04-16 16:40 we7u
+
+ * config/language-Spanish.sys: Updates by Jose R. Marte A., HI8GN.
+
+2003-04-16 16:27 we7u
+
+ * src/igate.c: Fixing a possible buffer overflow condition where
+ we're reading the nws-stations.txt file into an array.
+
+2003-04-16 16:14 we7u
+
+ * README.1ST: Miscellaneous maps notes. Put in eskimo.com as an
+ alternate location for some of the map libaries.
+
+2003-04-16 15:56 we7u
+
+ * README.win32: Added more download sites for the optional map
+ libraries.
+
+2003-04-16 14:12 we7u
+
+ * config/language-Portuguese.sys: Changes by David Quental, CT1DRB.
+
+2003-04-16 14:04 we7u
+
+ * config/language-Dutch.sys: Changes by Han Sytsma, PE1FAM.
+
+2003-04-16 12:32 we7u
+
+ * config/language-Spanish.sys: Adding the strings back in that were
+ added yesterday but left out of the last translation.
+
+2003-04-16 12:29 we7u
+
+ * config/language-Spanish.sys: Updates by Jose R. Marte A., HI8GN.
+
+2003-04-16 10:14 we7u
+
+ * src/interface.c: Added comments. Added character pacing on write
+ again for the DEVICE_NET_AGWPE interface. It's separate from the
+ others so that it can be fine-tuned.
+
+2003-04-15 17:24 we7u
+
+ * src/interface.c: Adding some debug statements.
+
+2003-04-15 15:14 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Putting in language
+ strings instead of hard-coded English for Configure->Timing
+ dialog.
+
+2003-04-15 15:04 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Fixes for hard-coded
+ English strings in Maps->Enable/Configure Tigermap dialog.
+
+2003-04-15 14:34 we7u
+
+ * src/main.c: Fixing Configure->Defaults dialog so that all of the
+ widgets are visible in all of our supported languages.
+
+2003-04-15 13:41 we7u
+
+ * config/language-Dutch.sys: Changes by Han Sytsma, PE1FAM.
+
+2003-04-15 13:00 we7u
+
+ * src/interface_gui.c: Disabling relay digipeat for AGWPE interface
+ until raw transmit packet frames can be implemented.
+
+2003-04-15 12:52 we7u
+
+ * src/db.c: Added a comment.
+
+2003-04-15 12:51 we7u
+
+ * src/interface.c: Comments. Changed test packet callsigns.
+
+2003-04-15 09:04 we7u
+
+ * config/language-German.sys: Changes by Rolf Bleher, DK7IN.
+
+2003-04-15 08:41 we7u
+
+ * config/language-English.sys: Committing changes for Rolf Bleher,
+ DK7IN.
+
+2003-04-15 01:21 we7u
+
+ * src/interface.c: Fix to igate_path for AGWPE interfaces.
+
+2003-04-14 09:32 we7u
+
+ * config/language-Spanish.sys: Updates by Jose R. Marte A., HI8GN.
+
+2003-04-13 08:51 rzg
+
+ * help/help-English.dat: Various updates for new features, and typo
+ fixes, more to come.
+
+2003-04-11 18:32 we7u
+
+ * src/: db.c, db.h, festival.c, festival.h, main.c, main.h,
+ rotated.c, rotated.h, wx.c, wx_gui.c: Corrected some
+ inconsistencies found by running the compiler at higher warning &
+ pedantic levels.
+
+2003-04-11 17:07 we7u
+
+ * src/: maps.c, messages_gui.c, util.c: More minor cleanups.
+
+2003-04-11 16:59 we7u
+
+ * src/: bulletin_gui.c, db.c, gps.c, interface.c, interface.h,
+ main.c, maps.c: Minor cleanups. Lots of them.
+
+2003-04-11 16:58 we7u
+
+ * config/language-Portuguese.sys: Changes by David Quental, CT1DRB.
+
+2003-04-11 15:36 we7u
+
+ * config/language-Portuguese.sys: Tweaks to add missing strings.
+
+2003-04-11 15:30 we7u
+
+ * config/language-Portuguese.sys: Changes by David Quental, CT1DRB.
+
+2003-04-11 15:13 we7u
+
+ * README.1ST: Another tweak by J. Lance Cotton.
+
+2003-04-11 15:08 we7u
+
+ * README.1ST: Added instructions for reprojecting Shapefiles,
+ courtesy of Derrick J Brashear and J. Lance Cotton.
+
+2003-04-11 14:07 we7u
+
+ * src/: db.c, interface_gui.c: Setting up for relay digipeating
+ using AGWPE interfaces. Untested.
+
+2003-04-11 13:49 we7u
+
+ * src/igate.c: Added AGWPE to igating code.
+
+2003-04-11 13:42 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface.c,
+ src/interface_gui.c: Implemented the transmit radioport option
+ for AGWPE interfaces. This can be adapted to other multi-port
+ TNC interfaces later.
+
+2003-04-11 13:26 we7u
+
+ * src/interface.c: Backing out one change to avoid high CPU-usage
+ in the port_write() function. Added comments to the port_read()
+ and port_write() threads to hopefully eliminate this sort of
+ problem in the future.
+
+2003-04-11 11:17 we7u
+
+ * src/interface.c: Added code to disable Nagle's algorithm for
+ TCP/IP sockets : TCP_NODELAY setsockopt().
+
+2003-04-11 10:25 we7u
+
+ * src/interface.c: Eliminated line pacing for network connections.
+ Added more serial types to the character pacing code.
+
+2003-04-10 17:10 we7u
+
+ * src/interface.c: Fixing a lock problem and commenting out some
+ debug packets for AGWPE.
+
+2003-04-10 14:17 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Tweaking AGWPE
+ labels.
+
+2003-04-10 14:13 we7u
+
+ * src/interface_gui.c: Removing filter options from AGWPE
+ Properties dialog. Doesn't apply.
+
+2003-04-10 14:05 we7u
+
+ * src/interface_gui.c: Extending the length for AGWPE passwords.
+
+2003-04-10 13:58 we7u
+
+ * src/interface_gui.c: More AGWPE stuff.
+
+2003-04-10 12:49 kd6zwr
+
+ * src/maps.c: Fix for systems with both Xpm.h and XpmI.h
+
+2003-04-10 12:46 we7u
+
+ * src/interface.c: Getting rid of unused variables and old code.
+
+2003-04-10 12:40 we7u
+
+ * src/interface.c: Moved the unproto path selection into its own
+ routine. More code changes to support agwpe.
+
+2003-04-10 11:14 we7u
+
+ * README.1ST: Specifying an alternate ftp site to get the radar
+ geo's from.
+
+2003-04-10 09:45 we7u
+
+ * README.1ST, help/help-English.dat: Adding a few notes about the
+ .GEO file format specifying that decimal degrees are used for
+ lat/lon in these files.
+
+2003-04-08 14:30 we7u
+
+ * src/interface.c: Changing input parameter for send_agwpe_packet()
+ to accept a digi path instead of a list of digi's. This will
+ integrate into the Xastir method of specifiying paths more
+ easily.
+
+2003-04-08 13:33 we7u
+
+ * src/interface.c: Changing the AGWPE login ID to be callsign minus
+ SSID (removed SSID).
+
+2003-04-07 23:17 we7u
+
+ * src/interface.c: Initial transmit capability for AGWPE
+ interfaces. Currently the path is hard-coded to RELAY,WIDE2-2,
+ but that will change given time. The method of specifying the
+ path differs greatly from Xastir's original method, plus the
+ Properties GUI for AGWPE needs to be reworked to add in the
+ optional path fields.
+
+2003-04-07 10:26 we7u
+
+ * src/interface.c: Commenting out some debugging printf's.
+
+2003-04-06 13:25 we7u
+
+ * src/main.c: The other small tweak needed in order to decode AGWPE
+ packets.
+
+2003-04-06 13:22 we7u
+
+ * src/interface.c: AGWPE interface receive mode is not functional.
+ Transmit is still being worked on.
+
+2003-04-05 11:16 we7u
+
+ * src/interface.c: More AGWPE code. We're getting packets sent in
+ both directions now, although the login/password packet doesn't
+ appear to be accepted properly yet. No decoding/encoding of real
+ packets is implemented yet.
+
+2003-04-04 16:55 we7u
+
+ * src/xa_config.c: Fixing this so that it handles the correct types
+ of interfaces.
+
+2003-04-04 14:04 we7u
+
+ * src/interface.c: Added some comments.
+
+2003-04-04 13:50 we7u
+
+ * src/interface.c: More AGWPE stuff. Not functional yet.
+
+2003-04-04 12:52 we7u
+
+ * src/interface.c: Send the login packet to AGWPE only if the
+ passwd string has something in it.
+
+2003-04-04 11:48 we7u
+
+ * src/interface.c: More AGWPE interface code. Now sending
+ login/password string and command to ask AGWPE to send us the
+ monitored packets. Don't have transmit or the receive decode of
+ those packets completed yet, but debug code is in place that
+ looks for complete headers and packets and notifies us on
+ reception.
+
+2003-04-03 23:48 we7u
+
+ * src/interface.c: More AGWPE stuff. Not functional yet.
+
+2003-04-03 17:12 we7u
+
+ * src/interface.c: More AGWPE work. Not functional yet.
+
+2003-04-03 14:40 we7u
+
+ * src/interface.c: Reformatting. No code changes.
+
+2003-04-03 14:24 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface.c, src/interface.h,
+ src/interface_gui.c: Initial steps at adding network support for
+ AGWPE.
+
+2003-04-03 12:57 we7u
+
+ * src/: main.c, maps.h: Adding my test_create_shapefile stuff back
+ in, this time with the proper #ifdef's so that everybody can
+ still compile the code whether they have shapelib installed or
+ not.
+
+2003-04-03 11:52 we7u
+
+ * src/: main.c, maps.c: Spawning off a separate thread for doing
+ the Snapshot() function.
+
+2003-04-03 09:39 we7u
+
+ * src/maps.c: Changing the Snapshot function so that it can reduce
+ to 256 colors if necessary when converting from XPM to PNG.
+
+2003-04-02 13:01 francais1
+
+ * src/interface.c: Enable suid privileges around bind to reset from
+ callsign (RELAY digipeat bugfix with 2.2.19 kernels, I hope.)
+
+2003-04-02 11:30 we7u
+
+ * src/main.c: Disabling my test_create_shapefile_map entry. Some
+ people can't get Xastir to compile with it in there, and it's
+ test code anyway.
+
+2003-04-01 16:27 we7u
+
+ * src/: main.c, maps.c, maps.h: Testing of the shapefile creation
+ function. Attached to the "Test" button on the menus.
+
+2003-04-01 15:25 we7u
+
+ * src/maps.c: Changed to comments. No code changes.
+
+2003-04-01 13:13 we7u
+
+ * src/interface.c: Adding some white space. No code changes this
+ time.
+
+2003-04-01 09:55 we7u
+
+ * src/xastir.h: Enabling serial KISS tnc relay digipeat
+ functionality by default. Initial testing shows that this
+ portions of relay digipeat is working. AX.25 relay digipeat
+ still needs a bit of work to get the source callsign to be set
+ properly.
+
+2003-04-01 01:09 we7u
+
+ * src/: db.c, interface.c: Changes to make RELAY digipeating
+ functional for Serial KISS TNC interfaces. May have fixed AX.25
+ interfaces as well.
+
+2003-03-31 23:16 we7u
+
+ * src/db.c: Better debug output for relay_digipeat() function.
+
+2003-03-31 15:31 we7u
+
+ * src/db.c: More debug messages for relay_digipeat() function.
+ Again, will be removed later.
+
+2003-03-31 14:59 we7u
+
+ * src/db.c: Adding some debug output for relay digipeat. It'll be
+ removed later when we get things working properly.
+
+2003-03-28 17:05 we7u
+
+ * src/db.c: More KISS variant comments.
+
+2003-03-28 16:37 we7u
+
+ * src/db.c: Added another kiss variant to the comments.
+
+2003-03-28 16:34 we7u
+
+ * src/db.c: Added some notes about KISS protocol variants. No code
+ changes.
+
+2003-03-28 11:13 we7u
+
+ * src/maps.c: Changing point shapefiles so that if labels are
+ turned off, the symbols still get drawn.
+
+2003-03-28 10:33 we7u
+
+ * src/: interface.c, db.c: Added comments. Now mask off the AX.25
+ P/F bit before checking the control byte for 0x03 (UI Frame).
+ Now drop the Serial KISS packet if the final result is not 0x03.
+
+2003-03-27 15:57 we7u
+
+ * src/db.c: Taking out the control byte == 0x03 restriction for
+ Serial KISS packets. MKISS TNC's encode the channel number in
+ the control byte.
+
+2003-03-27 15:46 we7u
+
+ * src/db.c: Added a note to decode_ax25_header() function.
+
+2003-03-27 15:42 we7u
+
+ * README.1ST: Added a GPSMan install step to set the permissions on
+ the /usr/local/xastir/maps/GPS/ directory so that files could be
+ written there.
+
+2003-03-27 15:33 we7u
+
+ * src/db.c: Changing the Serial KISS interface to ignore packets if
+ the control byte != 0x03 and the PID byte != 0x0f. This will
+ make it co-exist on channels that might have other protocols on
+ them (net/rom, tcp/ip, etc.). The AX.25 interface code already
+ had the PID==0x0f restriction on it.
+
+2003-03-27 14:32 we7u
+
+ * README.win32: Changed "go.bat" to just "go". Less typing to get
+ things rolling that way.
+
+2003-03-27 14:16 we7u
+
+ * README.win32: Added zip/unzip to the list of packages to install.
+ Helps when installing some map files later.
+
+2003-03-27 11:21 we7u
+
+ * README.win32: Added some blank lines.
+
+2003-03-27 11:17 we7u
+
+ * README.1ST: Added notes about how to decompress the World
+ shapefile.
+
+2003-03-27 11:11 francais1
+
+ * FAQ: Added a lesstif/openmotif entry
+
+2003-03-26 22:10 we7u
+
+ * README.win32: More details for the user in terms of creating
+ subdirectories while adding in the optional libraries.
+
+2003-03-26 11:55 we7u
+
+ * Makefile.am: Added the xastir/maps/GPS/ directory to the
+ directories created during install. This directory is required
+ for GPSMan to operate with Xastir properly.
+
+2003-03-26 11:28 we7u
+
+ * src/main.c: Updating about message to contain 2003 instead of
+ 2002.
+
+2003-03-26 10:41 we7u
+
+ * src/main.c: Changing the method of parameter passing between
+ GPS_operations() and gps_transfer_thread() in order to solve a
+ user's problem.
+
+2003-03-26 10:00 we7u
+
+ * src/main.c: A few minor tweaks to GPS_operations and
+ gps_transfer_thread, mostly to debug problems with parameter
+ passing.
+
+2003-03-24 15:28 we7u
+
+ * README.win32: One more note to get libgeotiff working on Cygwin.
+ Must rename the libtiff dll's in order to be compatible with the
+ version of libgeotiff.
+
+2003-03-24 13:36 we7u
+
+ * README.win32: Removed warning note above the geotiff
+ instructions: It is working again with the current instructions.
+
+2003-03-24 12:52 we7u
+
+ * README.win32: Some minor additions to the libproj install that
+ helps the libgeotiff install to complete.
+
+2003-03-23 18:46 we7u
+
+ * README.win32: Added more notes to clarify places where some users
+ were tripping up.
+
+2003-03-23 18:45 we7u
+
+ * README.1ST: Added asterisks next to the note about the Shapefile
+ world map.
+
+2003-03-22 00:28 we7u
+
+ * src/interface.h: Reversed order of arguments for socklen_t
+ typedef.
+
+2003-03-21 16:50 we7u
+
+ * README.win32: Taking out some old notes that aren't applicable
+ anymore.
+
+2003-03-21 16:49 jtwilley
+
+ * configure.ac: Forgot to actually include -lax25 when detecting it
+
+2003-03-21 16:48 we7u
+
+ * README.win32: Another minor Cygwin tweak.
+
+2003-03-21 16:28 we7u
+
+ * src/util.c: Another minor Cygwin tweak.
+
+2003-03-21 16:25 we7u
+
+ * README.win32: More Cygwin tweaks.
+
+2003-03-21 16:02 jtwilley
+
+ * src/: interface.c, interface_gui.c: Changed references of
+ HAVE_AX25 to HAVE_LIBAX25 to match new configure.
+
+2003-03-21 12:44 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Removing the "Are You
+ Sure?" button on exit (to keep peace with the other war-monger
+ developers ;-)
+
+2003-03-20 14:29 jtwilley
+
+ * acinclude.m4, configure.ac, src/hostname.c, src/interface.c,
+ src/interface.h, src/main.c, src/maps.c, src/maps.h, src/util.c,
+ src/wx_gui.c, src/xa_config.c: Massive configuration overhaul --
+ moving functions from configure.ac to acinclude.m4 and beginning
+ to streamline configure.ac, with attendant changes in various
+ source files.
+
+2003-03-18 14:59 we7u
+
+ * src/: db.c, interface_gui.c, xastir.h: Tweaks to enable testing
+ of RELAY digipeat with serial KISS TNC's. One define in xastir.h
+ needs to be changed in order to enable it.
+
+2003-03-18 14:39 francais1
+
+ * src/: db.c, interface_gui.c: Allowed selection of AX25 relay
+ digipeat
+
+2003-03-18 14:28 we7u
+
+ * src/: gps.c, gps.h, main.c: Changing how GPS status messages are
+ done.
+
+2003-03-18 13:50 we7u
+
+ * src/: gps.c, interface.c, main.c, xastir.h: Fixes for the GPS
+ high-CPU usage. We now save GPRMC and GPGGA strings in global
+ variables, dropping all other strings. At the GPS Check
+ Interval, we decode up to two strings that we have saved most
+ recently.
+
+2003-03-17 14:58 we7u
+
+ * configure.ac: Another ImageMagick tweak for Cygwin.
+
+2003-03-17 12:39 we7u
+
+ * configure.ac: Trying another small tweak for Cygwin. It's not
+ currently recognizing the ImageMagick libraries installed in
+ /usr/lib.
+
+2003-03-16 23:29 we7u
+
+ * src/main.c: We now call reload_object_item() after we clear all
+ stations. This keeps locally-owned objects on our screen and in
+ our in-memory database.
+
+2003-03-16 21:54 we7u
+
+ * README.1ST: Added a Festival note from J. Lance Cotton.
+
+2003-03-14 21:59 we7u
+
+ * src/main.c: Fixing an errand comment on a #endif statement.
+
+2003-03-14 17:01 we7u
+
+ * README.win32: Tweaking the Cygwin/ImageMagick notes.
+
+2003-03-14 16:41 we7u
+
+ * README.win32: More optional library notes. Trying to work
+ through the problems with the latest
+ ImageMagick/proj.4/libgeotiff libraries.
+
+2003-03-14 13:10 we7u
+
+ * README.win32: More notes about problems with geotiff maps and
+ current Cygwin versions.
+
+2003-03-14 11:51 we7u
+
+ * README.win32: Adding more notes about the impure_ptr problem.
+
+2003-03-14 11:43 we7u
+
+ * README.win32: Changing the version of libgeotiff called out.
+
+2003-03-14 11:41 we7u
+
+ * README.1ST: Removed Cygwin info. It now tells Windows users to
+ refer to the README.win32 file instead.
+
+2003-03-13 10:29 we7u
+
+ * README.1ST: Added a bit to the GPSMan notes.
+
+2003-03-12 20:43 we7u
+
+ * README.1ST: Minor fixes to the gpsman instructions.
+
+2003-03-12 13:20 francais1
+
+ * src/interface.c: Fix to remove the star before the
+ ax25_aton_entry call because it would call it a bad callsign.
+
+2003-03-12 11:23 we7u
+
+ * src/main.c, configure.ac, README.1ST: Added support for the
+ production version of GPSMan. Have at it!
+
+2003-03-11 17:02 we7u
+
+ * README.win32: Minor cygwin changes.
+
+2003-03-11 16:43 we7u
+
+ * README.1ST, README.win32: Slight changes to Cygwin instructions.
+
+2003-03-11 16:26 we7u
+
+ * README.win32: Adding a Cygwin/Win32 specific README file to make
+ it easier for Windows users to get up and running with Xastir.
+ Initial check-in.
+
+2003-03-07 17:31 we7u
+
+ * README.1ST: More Cygwin changes.
+
+2003-03-07 17:25 we7u
+
+ * README.1ST: More Cygwin changes.
+
+2003-03-07 16:36 we7u
+
+ * README.1ST: More Cygwin notes.
+
+2003-03-07 16:15 we7u
+
+ * README.1ST: Correcting some Cygwin libproj notes.
+
+2003-03-07 14:07 we7u
+
+ * README.1ST: Minor change to library revision number for Cygwin.
+
+2003-03-07 14:02 we7u
+
+ * README.1ST: More Cygwin notes.
+
+2003-03-07 13:46 we7u
+
+ * README.1ST: Added notes regarding "make install-strip" option.
+
+2003-03-07 13:10 we7u
+
+ * configure.ac: libproj/libgeotiff fixes for Cygwin.
+
+2003-03-07 11:07 we7u
+
+ * README.1ST: Tweaked the comments about creating the terraserver
+ .geo file.
+
+2003-03-07 11:03 we7u
+
+ * src/maps.c: Starting to add shapefile creation functions. Intend
+ to use these to save station trails to map files eventually.
+
+2003-03-06 14:41 we7u
+
+ * configure.ac, src/main.c: Changed some comments.
+
+2003-03-06 14:21 we7u
+
+ * README.1ST: Added initial notes regarding gpsmanshp and GPSMan.
+
+2003-03-06 14:04 we7u
+
+ * configure.ac: Adding checks for GPSman and gpsmanshp.so. Not
+ ready for prime-time yet, but should be soon.
+
+2003-03-06 10:47 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/gps.c, src/interface.c,
+ src/main.c: Added a popup when GPS data goes stale. We now allow
+ one posit when GPS interfaces are first enabled before we
+ consider the data stale and disable transmit of My Position.
+ Removed the statusline messages that happen when we successfully
+ decode GPRMC or GPGGA sentences: They were causing too much CPU
+ time on Yellow Dog Linux (powerPC).
+
+2003-03-05 16:39 we7u
+
+ * src/interface.c: Fix the case where someone plays with a GPS
+ interface and then turns it off again. Before this change,
+ posits would be disabled unless GPS interface was re-enabled that
+ had good data coming in, or unless the user restarted Xastir.
+
+2003-03-05 15:32 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/maps.c: Language
+ strings for GPS operations. Added more colors. Create default
+ time/date filename if no filename given.
+
+2003-03-05 14:04 we7u
+
+ * src/main.c: Added a UI to the gps transfer code. Not enabled yet
+ for users.
+
+2003-03-05 13:54 we7u
+
+ * src/maps.c: Minor changes to new GPS stuff.
+
+2003-03-04 16:51 we7u
+
+ * src/maps.c: Removing the color portion of the filename for GPS
+ map labels.
+
+2003-03-04 16:49 we7u
+
+ * src/main.c: Changed a few comments.
+
+2003-03-04 16:34 we7u
+
+ * src/main.c: Minor updates to new GPS stuff. Not enabled for
+ normal use yet.
+
+2003-03-04 15:55 we7u
+
+ * src/main.c: Converted to switch statement in new GPS transfer
+ routines. Can now because it's an int.
+
+2003-03-04 15:42 we7u
+
+ * src/main.c: Separated the GPS transfer functions into their own
+ thread. GPS transfers now run concurrently with the other
+ threads, updating the map view when they complete.
+
+2003-03-04 12:34 we7u
+
+ * README.1ST: More Cygwin libproj and libgeotiff notes.
+
+2003-03-04 11:13 we7u
+
+ * README.1ST: Correcting spelling.
+
+2003-03-04 10:51 we7u
+
+ * src/: main.c, maps.c: More experimental GPSMan stuff. Not ready
+ for release yet.
+
+2003-02-28 17:52 we7u
+
+ * README.1ST: More Cygwin libgeotiff notes.
+
+2003-02-28 17:48 we7u
+
+ * src/maps.c: Changing the line style for GPS info.
+
+2003-02-28 17:38 we7u
+
+ * README.1ST: More Cygwin notes.
+
+2003-02-28 17:31 we7u
+
+ * README.1ST: More Cygwin stuff: libgeotiff.
+
+2003-02-28 16:30 we7u
+
+ * src/maps.c: Rotating the labels to horizontal for GPS maps.
+ Changing orange to lighter orange.
+
+2003-02-28 16:20 we7u
+
+ * src/maps.c: Chopping off the ".shp" portion of the GPS labels.
+
+2003-02-28 16:00 we7u
+
+ * src/maps.c: More label/color stuff for gps maps.
+
+2003-02-28 15:48 we7u
+
+ * src/maps.c: Adding labels to the GPS tracks/routes.
+
+2003-02-28 13:39 we7u
+
+ * src/maps.c: More GPS stuff. Not enabled yet.
+
+2003-02-28 13:19 we7u
+
+ * src/main.c: Turning off the new GPS stuff.
+
+2003-02-28 12:48 we7u
+
+ * src/main.c: More gps transfer stuff. Not ready for prime-time
+ yet.
+
+2003-02-27 16:40 we7u
+
+ * configure.ac: Reversing the order of lib checking for libproj and
+ libgeotiff.
+
+2003-02-27 16:30 jtwilley
+
+ * ChangeLog, configure.ac: Cleaned up XASTIR_TOCALL in configure.ac
+ to no longer require SHORT_VERSION
+
+2003-02-27 15:52 we7u
+
+ * README.1ST: More Cygwin notes. libgeotiff stuff.
+
+2003-02-27 15:31 we7u
+
+ * README.1ST: More changes for Cygwin. Installation of Proj.4 now
+ complete and documented. I'm still working on installation of
+ libgeotiff.
+
+2003-02-27 12:53 we7u
+
+ * src/main.c: Preliminary support for GPSMan: Downloads track,
+ creates Shapefile map, auto-imports and displays said map in
+ Xastir. Requires pre-release GPSMan plus gpsmanshp.tgz file
+ installed. Also requires that the "WE7U" define at the top of
+ main.c be defined to put the new code into operation.
+
+2003-02-27 09:39 we7u
+
+ * configure.ac: Added a tweak to look for the Shapelib include file
+ in subdirectory _not_ ending in /libshp/
+
+2003-02-26 10:09 we7u
+
+ * src/: alert.c, alert.h: Removing dead code. Changed/added a few
+ comments and debug messages. Removed prototypes from alert.h
+ that aren't being used.
+
+2003-02-26 09:38 we7u
+
+ * configure.ac: Taking out extra X11 include path that was just
+ added for linux recently.
+
+2003-02-25 17:55 we7u
+
+ * src/: bulletin_gui.c, bulletin_gui.h, db.c, db.h: Fixes for
+ bulletin popups.
+
+2003-02-25 13:45 we7u
+
+ * src/db.c: Changes to comments only.
+
+2003-02-25 12:50 we7u
+
+ * src/: alert.c, alert.h, db.c, maps.c: Changing NWS weather alerts
+ so that they are no longer stored in the message database and
+ rescanned periodically. They now go straight to the alert_list.
+
+2003-02-25 10:04 we7u
+
+ * src/: bulletin_gui.c, bulletin_gui.h: Fixing another bug having
+ to do with zero-distance bulletins popping up when the user
+ settings tell Xastir not to.
+
+2003-02-25 09:31 we7u
+
+ * src/main.c: Added Map Display Bookmarks button to right-click
+ mouse menu.
+
+2003-02-24 23:03 we7u
+
+ * configure.ac: Adding a path for Linux configure to help find
+ Motif include files on some systems.
+
+2003-02-24 22:30 kd6zwr
+
+ * ChangeLog, src/db.c: Made my_station_gps_change update sec_heard
+ to fix DR of my station.
+
+2003-02-24 16:41 we7u
+
+ * configure.ac: Adding /usr/X11R6/include/Xm as an include path for
+ Motif/Lesstif for Slackware 8.1. May need additional things in
+ order to link to the library as well.
+
+2003-02-24 16:29 we7u
+
+ * src/db.c: Added more comments.
+
+2003-02-24 16:26 we7u
+
+ * src/db.c: Added some comments.
+
+2003-02-24 15:40 we7u
+
+ * src/maps.c: Getting rid of unneeded code.
+
+2003-02-24 15:40 we7u
+
+ * src/db.c: Added some comments.
+
+2003-02-24 15:26 we7u
+
+ * src/: db.c, maps.c, maps.h: Starting to change the weather alert
+ code to make it independent of the message database. Part-way to
+ that goal. This version just relocates the weather alerts scan
+ of the message database into the db.c code at the point where we
+ received the alert. The next step is to just throw the alert
+ onto the alert_list and skip the message database portion
+ altogether. This current code appears to still be fully
+ functional w.r.t. weather alerts.
+
+2003-02-24 14:45 we7u
+
+ * src/maps.c: Re-org of a bit of code w.r.t. weather alerts (no
+ major changes though). Lots of comment changes.
+
+2003-02-24 13:58 we7u
+
+ * src/draw_symbols.c: Tweaks to watch boxes for Gerry Wheeler.
+
+2003-02-24 13:35 we7u
+
+ * src/maps.c: Removed dead code. Changed some comments.
+
+2003-02-24 13:04 we7u
+
+ * src/: alert.c, maps.c: Changes to comments only.
+
+2003-02-24 12:46 we7u
+
+ * src/: alert.c, main.c: Setting the proper variables so that a
+ screen update happens in a timely manner after WX alerts expire.
+
+2003-02-24 12:23 we7u
+
+ * src/: alert.c, main.c, maps.c, wx_gui.c: We now expire wx alerts
+ only in main.c:UpdateTime(), and only every 60 seconds. If any
+ are expired, it schedules a screen update.
+
+2003-02-24 11:41 we7u
+
+ * src/: alert.c, alert.h, maps.c: More minor work on wx alerts.
+
+2003-02-24 11:28 jtwilley
+
+ * ChangeLog: Added entry for change made to src/interface.c
+
+2003-02-24 11:25 jtwilley
+
+ * src/interface.c: Changed timeouts to 100 milliseconds from 100
+ microseconds.
+
+2003-02-24 10:25 we7u
+
+ * src/: alert.c, alert.h, maps.c, wx_gui.c, xa_config.c: Moved
+ alert expiration code into common alert_expire() function.
+
+2003-02-23 08:58 we7u
+
+ * src/alert.c: Making an int more global. Needed for wx alert
+ expire code elsewhere.
+
+2003-02-23 08:56 we7u
+
+ * src/alert.h: Adding an extern int that other code needs now for
+ wx alert expiration.
+
+2003-02-23 08:48 we7u
+
+ * src/alert.c: Changed a comment.
+
+2003-02-23 08:44 we7u
+
+ * src/maps.c: Another tweak to wx alert expiration.
+
+2003-02-23 08:40 we7u
+
+ * src/wx_gui.c: Another small tweak to expiration for wx alerts.
+
+2003-02-23 08:37 we7u
+
+ * src/util.c: Tweaking the alert expiration stuff some more.
+
+2003-02-23 01:52 we7u
+
+ * src/: alert.c, alert.h, maps.c, util.c, wx_gui.c: Fixed incorrect
+ expiration times for weather alerts. Proper local expiration
+ time is now computed and stored. View->WX Alerts dialog appears
+ to update correctly as alerts come and go. Weather alert slots
+ get re-used by new alerts properly. We might have incorrect
+ expiration times for weather alerts twice a year when daylight
+ savings time switches though.
+
+2003-02-22 08:41 n0vh
+
+ * src/main.c: Fixed the intensity slider since 0 was causing xastir
+ to crash. Set the minimum to something reasonable.
+
+2003-02-21 17:16 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Added a new button the
+ Stations menu: Reload Object/Item History.
+
+2003-02-21 16:58 we7u
+
+ * src/sound.c: Adding some spacing. No code changes.
+
+2003-02-21 15:53 we7u
+
+ * src/: alert.c, alert.h, maps.c, wx_gui.c: Fixes to weather
+ alerts. Should re-use weather alert slots in the array now, and
+ should expire things properly as well.
+
+2003-02-21 12:46 we7u
+
+ * configure.ac: Modifying the error messages to make them
+ consistent and provide useful info to the user.
+
+2003-02-21 11:47 we7u
+
+ * configure.ac: Taking out some commented-out code and some
+ irrelevant comments.
+
+2003-02-20 21:10 n0vh
+
+ * src/main.c: Logging indicator now changes color to highlight that
+ it's logging.
+
+2003-02-20 20:31 n0vh
+
+ * src/: main.c, main.h: Added a status text box at the bottom of
+ the window that indicates that xastir is logging to disk.
+
+2003-02-20 15:31 we7u
+
+ * src/bulletin_gui.c: A few fixes for bulletins. Also added a
+ callback for the togglebutton on the View->Bulletins dialog.
+
+2003-02-20 14:34 we7u
+
+ * src/db.c: Added a debugging message.
+
+2003-02-20 14:18 we7u
+
+ * src/main.c: Changing the "Test" function a bit.
+
+2003-02-20 12:00 we7u
+
+ * src/bulletin_gui.c: Changing time between receiving a new
+ bulletin and checking whether it is within our range: From 15
+ seconds to 60 seconds. This actually delays our getting notice
+ of each new bulletin, but helps to prevent popping up bulletins
+ when a bulletin comes in and then a posit comes in later for that
+ station (putting that station outside our range). The cause of
+ the bulletin window popping up appears to be these
+ inside-our-range/ outside-our-range-when-a-posit-comes-in
+ bulletins.
+
+2003-02-20 11:32 we7u
+
+ * src/maps.c: Changed/added some comments. No code changes.
+
+2003-02-20 10:31 we7u
+
+ * configure.ac: Added more search paths for Solaris 8/9 binaries.
+
+2003-02-20 02:10 we7u
+
+ * bootstrap.sh: Added status messages.
+
+2003-02-20 01:51 we7u
+
+ * src/: alert.c, bulletin_gui.c, db.c, draw_symbols.c, gps.c,
+ hostname.c, interface.c, interface_gui.c, list_gui.c,
+ locate_gui.c, main.c, maps.c, popup_gui.c, rac_data.c, rotated.c,
+ snprintf.c, track_gui.c, util.c, view_message_gui.c, wx_gui.c,
+ xa_config.c: Added comments.
+
+2003-02-20 01:45 we7u
+
+ * src/: bulletin_gui.h, db.h, draw_symbols.h, festival.h, gps.h,
+ hostname.h, igate.h, list_gui.h, main.h, maps.h, rotated.h,
+ snprintf.h, track_gui.h, util.h, wx.h, xastir.h: Added comments.
+
+2003-02-20 01:00 we7u
+
+ * src/: maps.c, track_gui.c, util.c: More fixes for calling
+ external programs.
+
+2003-02-20 00:33 we7u
+
+ * src/: maps.c, track_gui.c, util.c: Checking for existence of
+ external programs before trying to invoke them. If they don't
+ exist, we call "echo" instead (relatively harmless).
+
+2003-02-19 23:56 we7u
+
+ * src/: alert.c, wx_gui.c: Added code to clear out expired weather
+ alerts so that later alerts can use that slot. Also caused the
+ View->Weather Alerts dialog to skip empty slots.
+
+2003-02-19 22:47 we7u
+
+ * bootstrap.sh: Separating out the -a and -c params on the automake
+ line, for Cygwin.
+
+2003-02-19 17:22 francais1
+
+ * configure.ac: A little tweakage
+
+2003-02-19 17:13 we7u
+
+ * src/: maps.c, util.c: Changing code to use new paths computed via
+ configure.
+
+2003-02-19 17:07 we7u
+
+ * configure.ac: Changing the quoting on some of the newer code I
+ just added.
+
+2003-02-19 16:46 we7u
+
+ * configure.ac: Removing the "cat" checks as we don't use it
+ currently.
+
+2003-02-19 16:31 we7u
+
+ * configure.ac: Path discovery for more utilities that we use from
+ within Xastir.
+
+2003-02-19 15:43 we7u
+
+ * configure.ac, src/interface.c, src/maps.c, src/track_gui.c:
+ Removing __CYGWIN__ #ifdef's.
+
+2003-02-19 14:40 we7u
+
+ * configure.ac, src/util.c: Getting rid of __FreeBSD__ #ifdef,
+ replacing it with HAVE_GMTOFF test/ variable/#ifdef.
+
+2003-02-19 13:55 we7u
+
+ * configure.ac, src/gps.c, src/interface_gui.c: Getting rid of
+ OS-specific #ifdef's related to settimeofday() function, where
+ the GPS time can be used to set system time.
+
+2003-02-19 13:15 we7u
+
+ * configure.ac: Streamlined the ImageMagick checks. Added more
+ comments. Temporarily commented out the "-Ldir -llibrary"
+ MacOSX/ImagMagick line which is probably unnecessary. Will add
+ it back if tests on MacOSX show it to be required.
+
+2003-02-19 12:44 we7u
+
+ * configure.ac: Streamlining geotiff and libintl code. Added
+ comments here and there.
+
+2003-02-19 11:44 we7u
+
+ * configure.ac: Streamlining the X11 library checking code.
+
+2003-02-19 10:51 we7u
+
+ * configure.ac: A bit of housecleaning. Pretty'ing up the
+ warning/error messages. Re-ordering the operating
+ system-specific areas.
+
+2003-02-19 10:00 we7u
+
+ * configure.ac: Making all of the MacOSX comments have exactly the
+ same spelling/case. Easier to grep for in the future. No code
+ changes.
+
+2003-02-19 09:35 we7u
+
+ * configure.ac: MacOSX/ImageMagick fix.
+
+2003-02-18 22:20 we7u
+
+ * configure.ac: Removing two brackets that give Mandrake linux
+ fits.
+
+2003-02-18 14:11 kg4ijb
+
+ * Makefile.am: bzip mod didn't propagate
+
+2003-02-18 14:05 kg4ijb
+
+ * src/Makefile.am: yikes!, automake_option was my bad, removed.
+
+2003-02-18 13:33 we7u
+
+ * src/Makefile.am: Moving the AUTOMAKE_OPTIONS to before the line
+ continuation char. It doesn't work where it was put. Is it
+ necessary? Should it be somewhere else in the file?
+
+2003-02-18 13:16 we7u
+
+ * configure.ac: Added some debugging info back in. Commented out
+ so a typical user won't be bothered by it.
+
+2003-02-18 12:49 kg4ijb
+
+ * callpass/Makefile.am, config/Makefile.am, help/Makefile.am,
+ symbols/Makefile.am, m4/Makefile.am, scripts/Makefile.am,
+ src/Makefile.am: ID message
+
+2003-02-18 12:44 kg4ijb
+
+ * configure.ac: cleaned output and removed all libtool dependancies
+
+2003-02-18 12:43 kg4ijb
+
+ * Makefile.am: removed unecessary automake_options
+
+2003-02-18 12:04 we7u
+
+ * scripts/Makefile.am: Adding missing scripts. Fixing things so
+ that "make dist" works properly.
+
+2003-02-18 11:56 we7u
+
+ * bootstrap.sh: Copying the files into the directory instead of
+ making symlinks.
+
+2003-02-18 11:36 we7u
+
+ * Makefile.am, configure.ac: More fixes to allow "make dest" to
+ work.
+
+2003-02-18 11:04 we7u
+
+ * Makefile.am: Adding a forgotten subdirectory that makes "make
+ dist" fail if not present.
+
+2003-02-18 10:57 we7u
+
+ * Makefile.am: Removing the lt* files.
+
+2003-02-18 09:34 we7u
+
+ * src/: main.c, xa_config.c: Changing range for Tigermap intensity
+ from 50-100% to 0-100%.
+
+2003-02-18 08:23 we7u
+
+ * configure.ac: Bumping revision up to 1.1.4
+
+2003-02-16 22:53 we7u
+
+ * README.1ST: Added a few notes after the lines calling out
+ bootstrap.sh.
+
+2003-02-16 21:25 we7u
+
+ * configure.ac: Another tweak for ImageMagick on MacOSX.
+
+2003-02-16 09:37 we7u
+
+ * README.1ST: Added a note to the MacOSX section: Installing
+ Xastir into /sw.
+
+2003-02-16 09:30 we7u
+
+ * configure.ac: Another ImageMagick fix for MacOSX.
+
+2003-02-16 01:49 we7u
+
+ * README.1ST: Added some more Solaris notes, courtesy of Chris
+ Bell.
+
+2003-02-16 01:35 we7u
+
+ * configure.ac: Added check for sched_yield() function in librt
+ (needed for Solaris).
+
+2003-02-15 15:44 we7u
+
+ * src/util.c: Changing back to a __solaris__ ifdef for now.
+
+2003-02-15 14:35 we7u
+
+ * configure.ac: Another fix for ImageMagick on MacOSX.
+
+2003-02-15 14:30 we7u
+
+ * configure.ac, src/hostname.c, src/interface.c,
+ src/interface_gui.c, src/main.c, src/maps.c, src/snprintf.h,
+ src/util.c, src/xa_config.c: Removing a lot of OS-specific
+ #ifdef's, changing to function-specific #ifdef's instead.
+
+2003-02-15 12:10 we7u
+
+ * src/xa_config.c: Temporarily removing the CYGWIN #ifdef, to see
+ if we have the proper configure.ac support for Cygwin now.
+
+2003-02-15 12:09 we7u
+
+ * src/gps.c: Cygwin change. Getting rid of CYGWIN tag and
+ replacing with config.h stuff.
+
+2003-02-15 11:39 we7u
+
+ * configure.ac, src/gps.c, src/interface.c: More MacOSX fixes.
+ Using variables in config.h now instead of #ifdef MACOSX.
+
+2003-02-15 10:45 we7u
+
+ * src/: gps.c, interface.c: Changing __MacOSX__ tag to MACOSX.
+
+2003-02-15 09:59 we7u
+
+ * configure.ac, src/gps.c, src/hostname.c, src/interface.c,
+ src/main.c, src/maps.c, src/snprintf.h, src/util.c: MacOSX and
+ Solaris fixes related to the new Autoconf stuff.
+
+2003-02-14 19:55 kg4ijb
+
+ * configure.ac: *BSD CFLAGS and pthread check
+
+2003-02-14 17:15 we7u
+
+ * configure.ac: Fix for finding Motif libraries on Solaris.
+
+2003-02-14 16:11 we7u
+
+ * configure.ac: Another MacOSX change.
+
+2003-02-14 15:13 we7u
+
+ * configure.ac: Another fix for MacOSX regarding Xm/Xm.h
+
+2003-02-14 14:47 we7u
+
+ * README.1ST: Cygwin/fvwm2 window manager instructions.
+
+2003-02-14 13:55 we7u
+
+ * configure.ac: Changing the old ImageMagick warning message
+ slightly.
+
+2003-02-14 13:39 we7u
+
+ * configure.ac: Mac OSX/Fink ImageMagick fixes. Also moved the old
+ version warning to the end of that section.
+
+2003-02-14 12:59 we7u
+
+ * configure.ac: Mac OSX/Fink mods to help find Shapelib.
+
+2003-02-14 10:30 we7u
+
+ * README.1ST: Added cvs update note to Cygwin section.
+
+2003-02-14 10:15 we7u
+
+ * configure.ac: Tweaking some comments.
+
+2003-02-14 10:09 we7u
+
+ * configure.ac: Adding an RCS tag so we can track revisions.
+
+2003-02-14 09:50 kg4ijb
+
+ * configure.ac: Fixed the tocall problem. Versioning only needs to
+ be done in ac_init
+
+2003-02-14 01:34 we7u
+
+ * README.1ST: More Cygwin changes.
+
+2003-02-13 15:39 we7u
+
+ * README.1ST: More Cygwin updates.
+
+2003-02-13 15:22 we7u
+
+ * README.1ST: Updated to reflect new configure.ac stuff.
+
+2003-02-13 14:46 we7u
+
+ * configure.ac: Fixing the TOCALL. The "APX$SHORT_VERSION" thing
+ doesn't work. :-(
+
+2003-02-13 13:42 we7u
+
+ * src/: interface.c, interface.h, interface_gui.c: Added "Networked
+ Database" GUI code for Brenda Wallace to have as a front-end for
+ her database code.
+
+2003-02-13 13:40 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Adding strings for
+ future networked database GUI.
+
+2003-02-13 13:35 kg4ijb
+
+ * ChangeLog:
+ * bootstrap.sh - routine to rebuild autostuff environment
+
+2003-02-13 13:31 kg4ijb
+
+ * bootstrap.sh: builds necessary autostuff files in appropriate
+ order
+
+2003-02-13 13:12 kg4ijb
+
+ * ChangeLog: [no log message]
+
+2003-02-13 13:05 kg4ijb
+
+ * symbols/Makefile.in: removed, locally generated
+
+2003-02-13 13:00 kg4ijb
+
+ * src/Makefile.in, scripts/Makefile.in, m4/Makefile.in,
+ help/Makefile.in, config/Makefile.in, callpass/Makefile.in:
+ removed files that are generated locally
+
+2003-02-13 12:48 kg4ijb
+
+ * ChangeLog, Makefile.in: removed remote files that are generated
+ locally
+
+2003-02-13 12:38 kg4ijb
+
+ * acconfig.h, acinclude.m4: Removed old configure files and added
+ new ac
+
+2003-02-13 12:33 kg4ijb
+
+ * configure.ac: * Removed old configure files and added new ac
+
+2003-02-13 12:29 kg4ijb
+
+ * config.guess, config.h.in, config.sub, configure, configure.in,
+ install-sh, ltconfig, ltmain.sh, missing, mkinstalldirs: make way
+ for new configure
+
+2003-02-13 09:24 we7u
+
+ * README.1ST: More changes to the Cygwin notes.
+
+2003-02-12 15:00 we7u
+
+ * src/: main.c, track_gui.c: Fixing some errant string lengths on
+ some XtVaTypedArg calls.
+
+2003-02-12 14:31 we7u
+
+ * README.1ST: Slight changes to Cygwin notes.
+
+2003-02-11 20:18 we7u
+
+ * src/main.c: Correcting a slight misspelling.
+
+2003-02-11 11:14 we7u
+
+ * README.1ST: More CVS/Cygwin info.
+
+2003-02-10 15:42 we7u
+
+ * README.1ST: Changes to the Shapelib portion of the Cygwin notes.
+
+2003-02-10 14:29 we7u
+
+ * acinclude.m4: Formatting for better readability. No code
+ changes.
+
+2003-02-10 13:54 we7u
+
+ * acinclude.m4, config.h.in, configure: Adding more error output
+ for Shapelib file searches during configure.
+
+2003-02-10 13:27 we7u
+
+ * configure, configure.in: Small change to wording of Cygwin
+ warning message.
+
+2003-02-10 13:17 we7u
+
+ * acconfig.h, config.h.in, configure, configure.in: Starting to add
+ Cygwin support to autotools.
+
+2003-02-10 12:20 we7u
+
+ * src/db.c: Fix for 3rd-party packets being marked as local
+ stations in Xastir. We now check the "third-party" variable at
+ that stage of the code.
+
+2003-02-10 10:54 we7u
+
+ * src/db.c: A fix by Reuven w.r.t. setting the messaging-capable
+ flag for the case of '@' packets. Curt added some run-time debug
+ code for finding own object deletions that'll be in effect until
+ we're sure the problem has gone away.
+
+2003-02-10 03:26 we7u
+
+ * src/maps.c: Adding Map Labels On/Off capability to pocketAPRS
+ maps.
+
+2003-02-07 17:35 we7u
+
+ * README.1ST: Reformatted some Cygwin notes.
+
+2003-02-07 17:33 we7u
+
+ * README.1ST: More Cygwin.
+
+2003-02-07 17:33 we7u
+
+ * README.1ST: More Cygwin stuff.
+
+2003-02-07 16:29 we7u
+
+ * README.1ST: More Cygwin note changes.
+
+2003-02-07 09:31 we7u
+
+ * README.1ST: Updated Cygwin information regarding CVS and extra
+ map libraries.
+
+2003-02-06 12:29 we7u
+
+ * README.1ST: Added general notes about how to
+ configure/compile/install Xastir. Several people have mentioned
+ to me that it's not clear how to go about this.
+
+2003-02-06 11:45 we7u
+
+ * src/: maps.c, track_gui.c: Specifying path to wget directly only
+ on Cygwin systems.
+
+2003-02-06 11:28 we7u
+
+ * README.1ST: Adding notes about Cygwin/ImageMagick, which works by
+ the way!
+
+2003-02-06 10:11 we7u
+
+ * README.1ST: Another Cygwin note.
+
+2003-02-06 09:36 we7u
+
+ * README.1ST: Tweaking the Cygwin/CVS note.
+
+2003-02-05 23:57 we7u
+
+ * src/: maps.c, track_gui.c: Adding a path for the "wget"
+ executable. Hard-coding it to /usr/bin right now.
+
+2003-02-05 17:13 we7u
+
+ * README.1ST: More Cygwin stuff.
+
+2003-02-05 14:57 we7u
+
+ * README.1ST: Added Cygwin/Shapelib notes.
+
+2003-02-05 11:38 we7u
+
+ * README.1ST: More Cygwin.
+
+2003-02-05 11:19 we7u
+
+ * README.1ST: More Cygwin notes.
+
+2003-02-05 10:33 we7u
+
+ * README.1ST: More Cygwin notes.
+
+2003-02-05 09:34 we7u
+
+ * README.1ST: Added notes about Xastir on Cygwin.
+
+2003-02-04 22:14 rzg
+
+ * help/help-English.dat: Some updates to helpfile for config|timing
+ and filtering.
+
+2003-02-04 17:02 we7u
+
+ * src/gps.c: Adding some more CYGWIN flags around variable
+ definitions. This part of the code isn't used under Cygwin.
+
+2003-02-04 11:30 we7u
+
+ * src/interface.c: Changing default paths from "RELAY,WIDE" to
+ "WIDE,WIDE2-2".
+
+2003-02-04 00:43 we7u
+
+ * src/maps.c: Getting rid of warning output that really isn't all
+ that useful.
+
+2003-02-04 00:06 we7u
+
+ * src/main.c: Added zoom in/out buttons to toolbar.
+
+2003-02-03 20:08 jtwilley
+
+ * src/: alert.c, bulletin_gui.c, color.c, db.c, draw_symbols.c,
+ fcc_data.c, gps.c, hostname.c, interface.c, interface_gui.c,
+ lang.c, list_gui.c, locate_gui.c, location_gui.c, maps.c,
+ messages.c, messages_gui.c, popup_gui.c, rac_data.c, rotated.c,
+ sound.c, track_gui.c, util.c, wx.c, wx_gui.c, xa_config.c:
+ Changed all printf's to write to stderr instead of stdout
+
+2003-02-03 19:52 jtwilley
+
+ * src/: igate.c, main.c: Changed all printf's to write to stderr
+ instead of stdout
+
+2003-02-03 17:19 we7u
+
+ * src/igate.c: Changes to formatting and comments only. No code
+ changes.
+
+2003-02-03 17:03 we7u
+
+ * src/main.c: Re-ordered the timing params on the Configure-Timing
+ dialog to make more sense.
+
+2003-02-03 16:42 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Changing the label for
+ the Configure->Timing dialog.
+
+2003-02-03 16:19 we7u
+
+ * src/main.c: Added another slider for setting the station removal
+ time from the database.
+
+2003-02-03 14:29 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/igate.c, src/main.c: Separated
+ the timing sliders from the Configure->Defaults dialog, making a
+ new Configure->Timing dialog out of them.
+
+2003-02-03 13:12 we7u
+
+ * src/main.c: Changing max posit rate to every 60 minutes instead
+ of every 45.
+
+2003-02-03 12:56 we7u
+
+ * src/main.c: Added separate object/item TX timer and associated
+ slider in Configure->Defaults. Now people with WX stations that
+ want to transmit every 5 minutes can set their object/item TX
+ rate separately. Also changed the posit rate slider to go from
+ 0.5 to 45 minutes (30 seconds to 45 minutes).
+
+2003-02-03 12:21 we7u
+
+ * src/: db.c, main.c, main.h, util.c, xa_config.c: Separate TX
+ timer for objects and items. New slider in Configure->Defaults
+ for it as well. Probably needs more testing to assure that it's
+ working correctly.
+
+2003-02-03 11:38 we7u
+
+ * src/: db.c, db.h, main.c, main.h: Added a slider for setting the
+ dead-reckoning timeout value.
+
+2003-02-03 11:21 we7u
+
+ * src/main.c: Changed Configure->Defaults timing values to sliders.
+ Makes the code much simpler plus gives the users more options in
+ setting the values.
+
+2003-02-02 23:21 jtwilley
+
+ * acinclude.m4, config.guess, config.sub, missing, mkinstalldirs:
+
+ Modified files to work with autoconf 2.53. There are some minor
+ bugs still, but they are being worked on.
+
+2003-02-02 23:19 jtwilley
+
+ * COPYING: Changed example to be Y2K-compliant.
+
+2003-02-02 23:19 jtwilley
+
+ * ChangeLog:
+
+ Updated autoconf files for new version. Fixed COPYING Y2K
+ distraction.
+
+2003-02-02 21:49 we7u
+
+ * src/: db.c, db.h, draw_symbols.c, xa_config.c: Added
+ DEAD_RECKONING_TIMEOUT value to xastir.cnf. The function is no
+ longer tied to the ghosting interval.
+
+2003-02-02 21:05 we7u
+
+ * src/: db.c, db.h, xa_config.c: Added a global variable
+ st_direct_timeout which is saved in the config file. This
+ specifies the timeout value for the ST_DIRECT bit.
+
+2003-02-02 08:42 we7u
+
+ * src/db.c: Added comments around the ST_DIRECT bit
+ setting/clearing code. Change the ST_DIRECT bit timeout from 1
+ minute to 1 hour. This gives stations that transmit only every
+ 30 minutes (common) a chance to be seen as an ST_DIRECT station.
+ As the comments show in that section of code, that timeout value
+ will in the future probably change into a global variable that is
+ set within the config file.
+
+2003-02-01 23:22 we7u
+
+ * src/db.c: Fixed a pointer-to-integer comparison (compiler
+ warning). Reformatted the code per Xastir project specs.
+
+2003-02-01 20:45 jtwilley
+
+ * ChangeLog:
+
+ Updated ChangeLog for solution for request ID #678322
+
+2003-02-01 20:42 jtwilley
+
+ * src/db.h:
+
+ Added direct_heard variable to station data structure. This
+ variable is set each time a direct packet is received from a
+ station.
+
+2003-02-01 20:40 jtwilley
+
+ * src/db.c:
+
+ Removed old support for direct stations and added new complete
+ direct station support. Paths with WIDE and TRACE entries of all
+ kinds are properly checked for directness.
+
+2003-02-01 02:14 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/db.h, src/interface.c,
+ src/main.c, src/util.c: Partial fixes for GUI lockups due to lots
+ of locally-controlled objects: Moved delays in interface routine
+ so that they'd only take effect if the interface was up and
+ transmit was enabled (both global and per-interface transmit
+ controls). Added a statusline() the lets us know when we're
+ retransmitting our objects/items. Delayed transmit of our items
+ for 30 seconds after initial startup. We will still have delays
+ each POSIT_interval when our objects get sent: Something like 2
+ seconds * number of up/tx-enabled interfaces * number of objects.
+
+2003-01-31 17:04 we7u
+
+ * src/draw_symbols.c: Added code to prevent wind barbs from getting
+ drawn if their position is off-screen.
+
+2003-01-30 17:17 we7u
+
+ * src/db.c: Adding code to assure that locally-controlled objects
+ don't expire.
+
+2003-01-30 16:15 we7u
+
+ * src/interface_gui.c: Reducing the length of the filtering input
+ box to 190.
+
+2003-01-30 14:48 we7u
+
+ * src/interface.c: Checking for NULL pointer for filter_string.
+
+2003-01-30 14:09 we7u
+
+ * src/: interface_gui.c, interface.c: Changed to sending empty
+ string instead of NULL if filter_string not specified when
+ calling add_device().
+
+2003-01-30 13:34 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface.h, src/interface.c,
+ src/interface_gui.c, src/xa_config.c: Implemented a user
+ interface for specifying filter parameters for internet servers.
+
+2003-01-30 11:48 kd6zwr
+
+ * src/main.c: commented out some unfinished code that slipped
+ out...
+
+2003-01-30 11:45 kd6zwr
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/xa_config.c,
+ src/xastir.h: added toggle for skipping map index on startup,
+ moved index-now button to map pulldown.
+
+2003-01-29 16:12 we7u
+
+ * src/db.c: Changed comments. No code changes.
+
+2003-01-29 14:08 we7u
+
+ * src/igate.c: Implemented passcode checking before sending packets
+ to each inet server.
+
+2003-01-29 12:14 we7u
+
+ * src/: util.c, util.h: Adding hashing functions into the code.
+ This will be used soon to verify igate transmit permissions.
+
+2003-01-29 10:17 we7u
+
+ * src/maps.c: Tweaking the Locate Map Feature code to handle GNIS
+ files that aren't formatted correctly (missing double quotes on
+ fields).
+
+2003-01-28 13:12 we7u
+
+ * symbols/symbols.dat: Made the 'X' smaller on the laptop.
+
+2003-01-28 13:11 we7u
+
+ * symbols/symbols.dat: Added laptop computer. Put X-windows on
+ both of the new computers. ;-)
+
+2003-01-28 13:05 we7u
+
+ * symbols/symbols.dat: Created desktop computer symbol.
+
+2003-01-28 12:49 we7u
+
+ * symbols/symbols.dat: A better helicopter. Easier to recognize
+ both with maps and without.
+
+2003-01-27 23:51 we7u
+
+ * symbols/symbols.dat: Second attempt at a Skywarn symbol.
+
+2003-01-27 23:34 we7u
+
+ * symbols/symbols.dat: Initial attempt at a Skywarn symbol.
+
+2003-01-27 23:07 we7u
+
+ * symbols/symbols.dat: Added blank symbols for /L, /l, and \y
+ (desktop computer, laptop computer, Skywarn symbols).
+
+2003-01-27 15:58 we7u
+
+ * src/main.c: Tweaking the update symbol portion of Create
+ Object/Item dialog: Invalid overlays won't update the symbol in
+ the dialog.
+
+2003-01-27 15:18 we7u
+
+ * src/: db.c, main.c: Fixing the compressed posit overlay problems
+ and the illegal overlay problems.
+
+2003-01-27 13:15 we7u
+
+ * src/: db.c, main.c: Fix for modify object/item dialog: Overlay
+ characters.
+
+2003-01-27 13:01 francais1
+
+ * symbols/symbols.dat: Shrunk box back down a bit
+
+2003-01-27 12:08 we7u
+
+ * src/db.c: Fixed Create_object_item_tx_string() such that the
+ overlay characters for objects/items don't get lost on
+ retransmit.
+
+2003-01-27 10:48 we7u
+
+ * symbols/symbols.dat: Made white square box larger and gave it
+ single-pixel border.
+
+2003-01-27 10:37 we7u
+
+ * symbols/symbols.dat: Made the white circle symbol (used with
+ overlays) bigger.
+
+2003-01-27 00:53 we7u
+
+ * symbols/symbols.dat: Changed the overlay circle (alternate
+ table). Made it a bit bigger so that the overlayed characters
+ are easier to read.
+
+2003-01-26 23:13 we7u
+
+ * symbols/symbols.dat: Added Incident Command Post symbol at "q"
+ position. Square split diagonally, half white/half green.
+
+2003-01-25 20:09 we7u
+
+ * src/list_gui.c: View->Weather Stations: Didn't convert
+ barometric pressure to inches mercury when english units
+ selected. Now it does.
+
+2003-01-23 20:57 we7u
+
+ * src/xa_config.c: Correcting error messages for get_int() and
+ get_long() functions.
+
+2003-01-23 20:49 we7u
+
+ * src/xa_config.c: Tweaked lower limit in xa_config.c for
+ TIGERMAP_INTENSITY from 60 to 50. This was causing user
+ problems, and should have been 50 to begin with.
+
+2003-01-23 16:38 we7u
+
+ * help/: help-Dutch.dat, help-English.dat, help-French.dat,
+ help-German.dat, help-Italian.dat, help-Portuguese.dat,
+ help-Spanish.dat: Updated copyright notice.
+
+2003-01-23 16:34 we7u
+
+ * src/main.c, src/main.h, src/maps.c, src/maps.h, src/messages.c,
+ src/messages.h, src/messages_gui.c, src/popup.h, src/popup_gui.c,
+ src/rac_data.c, src/rac_data.h, src/snprintf.c, src/snprintf.h,
+ src/sound.c, src/symbols.h, src/track_gui.c, src/track_gui.h,
+ src/util.c, src/util.h, src/view_message_gui.c, src/wx.c,
+ src/wx.h, src/wx_gui.c, src/xa_config.c, src/xa_config.h,
+ src/xastir.h, src/location_gui.c, src/draw_symbols.c,
+ src/draw_symbols.h, src/fcc_data.c, src/fcc_data.h, src/gps.c,
+ src/gps.h, src/hostname.c, src/hostname.h, src/igate.c,
+ src/igate.h, src/interface.c, src/interface.h,
+ src/interface_gui.c, src/lang.c, src/lang.h, src/list_gui.c,
+ src/list_gui.h, src/locate_gui.c, src/location.c, src/db.c,
+ src/db.h, AUTHORS, README, xastir.1, callpass/callpass.c,
+ src/alert.c, src/alert.h, src/bulletin_gui.c, src/bulletin_gui.h,
+ src/color.c, src/color.h, symbols/symbols.dat: Updating copyright
+ notice.
+
+2003-01-23 14:10 rzg
+
+ * help/help-English.dat: Updates for most recent stations menu
+ changes, copyright year.
+
+2003-01-23 11:42 we7u
+
+ * src/igate.c: Implemented NOGATE and RFONLY options in igate.c.
+ If either of these are seen, the packet won't be gated into the
+ internet.
+
+2003-01-23 11:17 francais1
+
+ * src/main.c: Fixed up overlooking of old_data sensitiveness
+ Removed unnecessary code
+
+2003-01-22 17:21 francais1
+
+ * src/: main.h, main.c, db.c, xa_config.c: Added display selection
+ for wind barb. No more storing 0,1,2 in config, split out to
+ match the structs.
+
+2003-01-22 17:18 francais1
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Added strings for
+ change to weather display selection because I added wind barb
+ display selection.
+
+2003-01-22 12:07 we7u
+
+ * src/xa_config.c: We now save/restore the filter togglebutton
+ settings.
+
+2003-01-20 18:12 francais1
+
+ * src/db.c: Fixed dead reckoning disappears when course or speed
+ display disabled bug.
+
+2003-01-18 17:09 rzg
+
+ * help/help-English.dat: Updated for stations menu changes.
+
+2003-01-17 10:28 francais1
+
+ * src/xa_config.c: Storing of speed/short and weather/temp_only was
+ backwards
+
+2003-01-17 09:22 we7u
+
+ * src/db.c: Fixed direct stations query to also check ST_DIRECT to
+ choose stations. Thanks Reuven for pointing that out!
+
+2003-01-17 00:10 we7u
+
+ * src/db.c: Added some comments about ST_DIRECT.
+
+2003-01-16 22:58 we7u
+
+ * src/db.c: Temporary tweak to the ST_VIATNC code: Changed from 20
+ to 50 the quantity of packets required from a 'net interface that
+ will cause a reset of the ST_VIATNC bit in the station record.
+ Later this should be changed to a timer.
+
+2003-01-16 13:38 francais1
+
+ * src/db.c, src/main.c, src/main.h, src/xa_config.c,
+ config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys: Added Mine, Via Digi, Stations and
+ Objects to Select
+
+2003-01-16 10:19 francais1
+
+ * config/: language-French.sys, language-Spanish.sys: Tweaked
+ French and Spanish a bit
+
+2003-01-16 10:08 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Changed "Select
+ Local" to "Select Direct".
+
+2003-01-16 09:56 we7u
+
+ * config/: tnc-startup.aea, tnc-startup.kam, tnc-startup.kpc3,
+ tnc-startup.paccomm, tnc-startup.pico, tnc-startup.sys,
+ tnc-startup.thd7: Added "PASSALL off" to the tnc startup files.
+
+2003-01-16 09:22 we7u
+
+ * src/: db.c, db.h: Changed ST_LOCAL flag to ST_DIRECT. Makes more
+ sense.
+
+2003-01-15 14:25 francais1
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/draw_symbols.c,
+ src/draw_symbols.h, src/main.c, src/main.h, src/xa_config.c:
+ Update of data filtering and display menus
+
+2003-01-15 12:12 we7u
+
+ * src/main.c: Tweak to dead-reckoning. Moved the
+ sec_last_dr_update variable to the main.c globals area. This
+ should preserve the last time between runs of UpdateTime().
+
+2003-01-14 23:46 we7u
+
+ * src/festival.c: Added some more error checking.
+
+2003-01-14 13:08 we7u
+
+ * src/: festival.h, festival.c: Fixed the non-connect to Festival
+ Server problem. This problem existed when Festival was started
+ up after Xastir. Now Xastir will try to connect to the server
+ when speech is desired, but will not try a new socket connection
+ any more often than every 60 seconds.
+
+2003-01-14 09:19 we7u
+
+ * src/maps.c: Print a warning in draw_geo_image_map() if the image
+ file cannot be read for some reason (typically permissions
+ problems).
+
+2003-01-13 22:23 kd6zwr
+
+ * src/main.c: Added error checking for setting my station postion
+ from mouse popup menu.
+
+2003-01-13 21:33 kd6zwr
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Added mouse popup menu
+ item to set my station position
+
+2003-01-12 22:22 we7u
+
+ * src/: db.c, interface.c, interface.h, main.c: Added some
+ debugging statements in the extract_weather functions. Added a
+ new global string that holds the last packet processed by file
+ read or channel_data functions. If a segfault occurs, this last
+ packet is dumped to STDERR along with the segfault message. This
+ might help in the future to find "killer" packets.
+
+2003-01-12 08:22 we7u
+
+ * src/maps.c: Changed wget parameters to more verbose keywords. No
+ real code changes.
+
+2003-01-11 18:28 rzg
+
+ * help/help-English.dat, README.1ST: Updated helpfile for findu.com
+ old code removal, minor readme changes.
+
+2003-01-11 08:38 we7u
+
+ * src/maps.c: Removed old dead findu.com code (older method of
+ accessing it, no longer used) from maps.c
+
+2003-01-11 08:30 we7u
+
+ * src/track_gui.c: Fixed findu.com get station tracks. Was using
+ hard-coded IP address before, now uses domain name in URL.
+
+2003-01-09 17:15 we7u
+
+ * src/db.c: Implemented a range scale display.
+
+2003-01-08 13:55 we7u
+
+ * FAQ: Added a question/answer about ImageMagick's
+ CompressImageColormap() function call.
+
+2003-01-07 21:13 kg4ijb
+
+ * src/interface.c: Check for glibc version on socket call line ~840
+
+2003-01-07 20:43 rzg
+
+ * FAQ, README.1ST:
+ Minor updates about -devel files, minor spacing changes to
+ README.1ST.
+
+2003-01-07 14:26 francais1
+
+ * Makefile.am, Makefile.in, xastir.spec.in: Removed creation of
+ placeholder map directories.
+
+2003-01-06 14:42 we7u
+
+ * scripts/: Coordinate.pm, inf2geo.pl, permutations.pl,
+ test_coord.pl, track-get.pl, waypoint-get.pl: Changed to
+ inf2geo.pl to accomodate other image formats. Tweaks to other
+ scripts regarding copyright notices only.
+
+2003-01-06 14:22 rzg
+
+ * help/help-English.dat, README.1ST:
+ Finished off "What's new", updates to map properties help,
+ addition of fcc-get script.
+
+2003-01-06 09:07 kg4ijb
+
+ * src/: festival.c, interface.c: remove deprecated params to socket
+
+2003-01-06 08:54 gstueve
+
+ * scripts/Makefile.am: Add helper script to retrieve FCC & RAC
+ files for XASTIR use.
+
+2003-01-06 08:42 gstueve
+
+ * scripts/: Makefile.in, fcc-get: Add helper script to retrieve RCC
+ & RAC data files for XASTIR use.
+
+2003-01-05 11:54 kd6zwr
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/main.h,
+ src/xa_config.c: Adding distance/bearing on status line.
+
+2003-01-03 10:25 we7u
+
+ * src/main.c: Dead code go bye-bye.
+
+2003-01-02 13:48 we7u
+
+ * src/maps.c: Adding more parameter checking after the sscanf in
+ the map_index restore_from_file function.
+
+2003-01-01 21:58 we7u
+
+ * README.1ST: A few updates to the map directory portions.
+
+2003-01-01 20:08 rzg
+
+ * help/help-English.dat:
+ More updates to "What's new", added instructions for rain gauge
+ reporting size correction.
+
+2002-12-31 13:57 we7u
+
+ * src/: draw_symbols.c, maps.c, util.c: Speeding up get_line again
+ (don't need all the filtering anymore since the Map Chooser bug
+ was found). Fixing get_line() calls so that the arrays are long
+ enough to contains what's read from file.
+
+2002-12-30 11:06 we7u
+
+ * src/maps.c: Fixing segfaults that could occur if GNIS files had
+ short lines or lines containing control characters. Now checking
+ for NULL returns from index() calls.
+
+2002-12-29 16:36 rzg
+
+ * help/help-English.dat:
+ More updates to "whats new" section; typo fixes.
+
+2002-12-29 15:04 rzg
+
+ * README.1ST, help/help-English.dat: Round 1 of "pre-release"
+ changes: Reorganized and cleaned up README.1ST, updated some
+ portions as needed. Updated helpfile for map chooser changes.
+
+ Still need more README work, especially doing something with all
+ that security stuff and perhaps the OS specific stuff. And the
+ helpfile "Whats new" needs to be written more nicely, I started
+ but ran out of time.
+
+2002-12-28 15:41 kd6zwr
+
+ * src/maps.c: Changed the sscanf fix... cleared the string to all
+ nulls before sscanf. The temp string broke solaris... *sigh*.
+ This works everywhere now??
+
+2002-12-28 12:55 kd6zwr
+
+ * src/maps.c: Added a temp string to avoid a sscanf bug(?) to
+ prevent junk showing up in the map chooser window.
+
+2002-12-27 14:18 we7u
+
+ * src/util.c: Fixing tabs in util.c:get_line().
+
+2002-12-27 12:54 we7u
+
+ * src/maps.c: Looking for control characters in the routine that
+ parses the map_index.sys file and creates the in-memory map
+ index.
+
+2002-12-27 11:53 we7u
+
+ * src/maps.c: More error-checking w.r.t. map indexing.
+
+2002-12-26 17:09 we7u
+
+ * src/maps.c: Checking for control characters as we're saving the
+ map_index data to disk.
+
+2002-12-26 16:33 we7u
+
+ * src/maps.c: Looking for all control characters instead of just
+ '\r' or '\n'. Added another warning message if control chars are
+ found. Changed some comments.
+
+2002-12-25 07:32 we7u
+
+ * src/: draw_symbols.c, main.c, maps.c: Added error checking at the
+ points where different xbitmap files were being loaded, and where
+ symbols.data is loaded. Xastir will now output an error message
+ before croaking if these files are not present.
+
+2002-12-24 17:26 we7u
+
+ * src/: maps.c, util.c: More filtering changes in and around
+ get_line(). Intended to help with the weird characters Map
+ Chooser problem.
+
+2002-12-24 14:27 we7u
+
+ * src/maps.c: Commenting out debug printf statements.
+
+2002-12-24 12:00 we7u
+
+ * src/maps.c: More error checking: Looking for control characters
+ in file/directory names during map indexing.
+
+2002-12-24 08:24 we7u
+
+ * src/maps.c: Added some code to spit out warning messages to
+ STDOUT if control characters other then '\n' are found in
+ map_index.sys.
+
+2002-12-23 00:16 we7u
+
+ * src/maps.c: Initial implementation of the draw_filled flag in the
+ map drawing routines which can make use of it.
+
+2002-12-22 11:24 we7u
+
+ * src/maps.c: Deleting dead code. Adding comments. Set a pointer
+ to NULL after calling a routine that might free the memory space.
+
+2002-12-22 10:54 we7u
+
+ * src/maps.c: Changed function which reads map_index.sys in from
+ disk so that it forces a sorted order for in-memory map list.
+
+2002-12-21 23:29 we7u
+
+ * src/maps.c: More error-checking while creating map indexes.
+
+2002-12-21 08:25 we7u
+
+ * src/maps.c: Added comments. Changed a few compares to read
+ better. No real code changes.
+
+2002-12-21 08:08 we7u
+
+ * src/maps.c: Added more error-checking and debug output to the map
+ indexing routines.
+
+2002-12-21 00:27 we7u
+
+ * src/: main.c, maps.c: Fully functional automaps selection from
+ the Map Chooser->Properties dialog.
+
+2002-12-21 00:08 we7u
+
+ * src/main.c: More automaps stuff. Can now tweak the value in the
+ map_index.sys file from the Map Chooser->Properties dialog.
+ Back-end code still has to be written to use this information.
+
+2002-12-20 23:46 we7u
+
+ * src/: main.c, maps.c, maps.h: Adding automaps enable/disable to
+ the Map Chooser->Properties dialog. More to do yet.
+
+2002-12-20 22:38 we7u
+
+ * src/maps.c: Added some debug lines.
+
+2002-12-20 21:40 we7u
+
+ * src/main.c: Moved some of the widgets to the bottom rowcol form
+ in the Map Properties dialog.
+
+2002-12-20 17:18 we7u
+
+ * src/: main.c, maps.h: Map Chooser->Properties now brings up new
+ dialog which allows setting map layers and draw_filled fields.
+ draw_filled is not used yet in the code.
+
+2002-12-20 12:59 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Changed to Dirs/Maps
+ Selected in map chooser instead of just files.
+
+2002-12-20 12:36 we7u
+
+ * src/maps.c: Added some comments.
+
+2002-12-20 12:07 we7u
+
+ * src/main.c: Changing the manual map index button back to its
+ original code, where it only updates the map index instead of
+ re-indexing from scratch. This keeps the manually-tweaked
+ map_level & draw_filled fields intact. The original reason for
+ starting from scratch was to remove deleted maps. This happens
+ anyway after two Xastir restarts, so starting the list from
+ scratch isn't really needed anyway.
+
+2002-12-20 11:52 we7u
+
+ * src/maps.c: Fixes to re-indexing so that files and directories
+ get good default values in the index.
+
+2002-12-20 11:52 we7u
+
+ * src/main.c: New stuff having to do with Map Chooser Properties
+ button. Not fully implemented yet.
+
+2002-12-20 11:51 we7u
+
+ * src/maps.h: Added a prototype for a function that I need to use
+ in main.c
+
+2002-12-19 17:04 we7u
+
+ * src/: main.c, main.h, maps.c: Initial attempt at sorting/drawing
+ maps based on map layer. It works! Next step is to get some more
+ GUI hooks for it so that the user can specify which maps go on
+ which layer, and which layers to enable for drawing.
+
+2002-12-19 12:36 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Added a count of how
+ many maps are currently selected to the map chooser. Doesn't
+ quite work the way I'd like yet, but it is useful. It shows how
+ many maps are marked in the in-memory map index as selected.
+ That quantity can change when you tweak things in the map chooser
+ and then hit OK.
+
+2002-12-18 22:03 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/maps.h: More tweaks
+ to the Map Chooser. Fully resizable now. Add new button at the
+ top which will eventually be used to change map properties.
+ Changed how the "None" button works, and renamed it to "Clear".
+
+2002-12-15 23:56 we7u
+
+ * src/maps.c: Yet another attempt to clean up garbage that some
+ people are seeing in the map index. In this tweak I check the
+ sscanf call to make sure that the proper number of fields have
+ been parsed from each input line. If not, that record in the
+ map_index is dropped.
+
+2002-12-15 23:07 we7u
+
+ * README.1ST: Tweaks by Tate, KC7ZRU. Thanks!
+
+2002-12-15 23:03 we7u
+
+ * src/main.c: Changed map re-indexing button so that it deletes the
+ entire in-memory index, then re-creates it from scratch. It is
+ slower than the old method, but guarantees that deleted/added
+ maps will show up in the map chooser without have to restart
+ Xastir to do it.
+
+2002-12-15 21:41 we7u
+
+ * src/festival.c: Change to some debug code.
+
+2002-12-15 18:28 we7u
+
+ * src/festival.c: Now doing a check in the festival code for
+ duplicate strings. Only one string is held in the queue for 30
+ seconds. If the same string comes in, festival refuses to speak
+ it.
+
+2002-12-14 23:00 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/main.h,
+ src/xa_config.c: Added an "Expand Directories" button to the map
+ chooser.
+
+2002-12-14 21:34 we7u
+
+ * src/: main.c, maps.c: Better implementation of map directory
+ select/de-select in the Map Chooser.
+
+2002-12-14 15:04 we7u
+
+ * src/maps.c: A few small tweaks to how map_index strings get
+ created for directories.
+
+2002-12-14 00:16 we7u
+
+ * src/main.c: Commented out a couple of debugging statements.
+
+2002-12-13 23:52 we7u
+
+ * src/: main.c, maps.c: First functional version of Map Chooser
+ where clicking on a directory will select all maps below it.
+ Still a few bugs left to squash, but it works!
+
+2002-12-13 22:35 we7u
+
+ * src/maps.c: Finished getting map directories to show up properly
+ and in sorted order in the Map Chooser. They're selectable as
+ well. Still have to write the code to recurse through these
+ directories when selected/de-selected. Not fully functional yet.
+
+2002-12-13 17:04 we7u
+
+ * src/maps.c: Starting to implement storage of map directories in
+ the map index. Not complete yet.
+
+2002-12-13 12:04 we7u
+
+ * src/main.c: Tweaks to comments.
+
+2002-12-13 09:42 we7u
+
+ * src/main.c: Including Chris Bell's new routines for
+ directory-at-a-time map file selection. These routines are not
+ integrated into Xastir yet. They need to be tweaked to fit into
+ the new map_index method of map selection, and the Lesstif/Motif
+ functions need to be combined into one function. This is a work
+ in progress.
+
+2002-12-10 14:51 we7u
+
+ * src/db.c: Fix for dead-reckoning for compressed objects/items.
+
+2002-12-10 14:13 we7u
+
+ * FAQ: Added a note about the missing freetype library during
+ linking.
+
+2002-12-10 13:52 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Added a new "Re-index
+ Maps" button to the configure menu. Useful for those instances
+ where you've added a new map but don't want to restart Xastir in
+ order to start using it.
+
+2002-12-10 13:15 we7u
+
+ * README.1ST: Added a note about James Jefferson's nice world map
+ in Shapefile format.
+
+2002-12-10 12:48 we7u
+
+ * src/main.c: Fixed to map chooser. Changes now apply only to the
+ in-dialog list until/unless the OK button is pressed. If Cancel
+ or any other button is pressed, the changes do not take effect or
+ get written to the selected_maps.sys disk file.
+
+2002-12-09 09:18 we7u
+
+ * README.1ST: Updating e-mail address.
+
+2002-12-07 20:57 we7u
+
+ * src/: draw_symbols.c, igate.c, maps.c, maps.h, util.c: Tweaks to
+ help fix buffer overflows in several areas of the code. Some of
+ them may have been caused by get_line() in util.c, which has been
+ rewritten to prevent overflowing the string passed into it. Also
+ added a new define: MAX_FILENAME, which is used to declare sizes
+ of char arrays.
+
+2002-12-07 00:00 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/locate_gui.c: Upon
+ receipt of a Mic-E emergency packet: No longer bring up a popup
+ dialog. Now bring up only a Locate Station dialog, but the
+ titlebar has been changed to read "Emergency Locate!".
+
+2002-11-26 16:35 we7u
+
+ * src/xa_config.c: More water gage stuff.
+
+2002-11-26 15:56 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c, src/main.h:
+ Adding a display toggle for water gage objects.
+
+2002-11-26 09:12 we7u
+
+ * config/language-Portuguese.sys: Changes by David Quental, CT1DRB.
+
+2002-11-25 23:05 we7u
+
+ * src/: bulletin_gui.c, db.c: Finishing up the
+ bulletins-before-posits code. Now bulletins come up as soon as
+ the posits for that station are received.
+
+2002-11-25 17:10 we7u
+
+ * src/: db.c, db.h: Start of trying to fix distance=0 bulletins for
+ when posit comes in later. A bit more code to write, but this
+ keeps track of whether or now the posit is currently known.
+
+2002-11-25 13:19 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/bulletin_gui.c, src/main.c,
+ src/main.h, src/xa_config.c: Something several of you have asked
+ about in the past: A way to stop the popup and display of
+ bulletins with zero distances. Two togglebuttons in this case
+ control the same global variable: One toggle on the
+ Configure->Defaults dialog, and another on the View->Bulletins
+ dialog.
+
+2002-11-25 10:40 rzg
+
+ * help/help-English.dat: Updates for dead-reckoning, other minor
+ changes.
+
+2002-11-25 09:42 we7u
+
+ * README.1ST: A bit more about installing festival from RPM's and
+ changing the default voice.
+
+2002-11-23 22:11 we7u
+
+ * src/util.c: Tweaks to the speech stuff so that we don't add
+ commas to the SSID portion of a callsign. This makes it speak
+ -12 as "dash twelve".
+
+2002-11-23 20:20 we7u
+
+ * README.1ST: Added a blurb about festival and starting it in
+ server mode. Useful for those that can't read the English help
+ file (where it is also documented).
+
+2002-11-23 08:18 we7u
+
+ * src/util.c: Speech stuff now looks for a number in the text
+ (before a dash). If found, it adds commas so that Festival will
+ speak each letter. If not found, it feeds the string directly to
+ Festival to let it try to pronounce it.
+
+2002-11-23 00:40 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/festival.c,
+ src/main.c, src/popup_gui.c, src/util.c, src/util.h: Changes to
+ make Festival speak callsigns out letter by letter.
+
+2002-11-22 17:16 we7u
+
+ * scripts/inf2geo.pl: Tweaked to handle different cases for
+ filenames, and to put the proper case into the GEO file for the
+ GIF file.
+
+2002-11-22 15:39 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c: Separated out
+ more festival speech strings from the other language strings.
+ Changed the "New Station" speech string to just "New" to speed
+ things up a bit.
+
+2002-11-22 11:20 we7u
+
+ * README.1ST: Added the su & exit around the "make lib_install" for
+ the Shapelib install. Thanks Bob!
+
+2002-11-21 21:15 we7u
+
+ * src/: maps.c, popup_gui.c: Code fixes for when required fonts
+ can't be found. Error messages are output and Xastir recovers,
+ instead of segfaulting.
+
+2002-11-21 17:56 we7u
+
+ * src/popup_gui.c: Changing to another font.
+
+2002-11-21 17:44 we7u
+
+ * src/xa_config.c: Deleting a duplicated variable.
+
+2002-11-21 17:38 we7u
+
+ * README.1ST: Added notes about the two new auto-identification
+ methods.
+
+2002-11-21 17:06 we7u
+
+ * src/popup_gui.c: Correcting small error in variable name.
+
+2002-11-21 16:53 we7u
+
+ * src/popup_gui.c: Moved the Speech ID stuff to the beginning of
+ the ID routine so that the spoken text and the screen ID will
+ occur at roughly the same time.
+
+2002-11-21 16:50 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c, src/main.h,
+ src/popup_gui.c, src/xa_config.c, src/xastir.h: Added station ID
+ in the form of large text across the screen, and spoken station
+ ID via festival. Occurs every 9.5 minutes if two new variables
+ in the config file are enabled.
+
+2002-11-21 10:20 we7u
+
+ * src/util.c: Minor tweak to make sure that objects/items only get
+ one hash mark added to the front of the line in the
+ ~.xastir/config/object.log file.
+
+2002-11-19 10:29 francais1
+
+ * src/: main.c, main.h, xa_config.c: Added "hidden" conf file value
+ to adjust DR update rate Default is 30 s
+
+2002-11-19 10:20 we7u
+
+ * src/db.c: Fixes so that dead-reckoning and "Display Moving
+ Stations" work properly even when we only have one position from
+ a station. They are now classified with ST_MOVING flag if the
+ speed is non-zero.
+
+2002-11-19 09:59 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/draw_symbols.c, src/main.c,
+ src/main.h, src/xa_config.c: Added new buttons to enable/disable
+ the different dead-reckoning display objects. This allows users
+ to get the display as cluttered or uncluttered as they like.
+
+2002-11-19 09:10 we7u
+
+ * src/xa_config.c: Changing default for dead-reckoning to ON.
+
+2002-11-18 16:25 francais1
+
+ * src/: draw_symbols.c, main.c: Added call to draw_symbols in
+ UpdateTime at least every 30 s if dead reckoning drawing is
+ turned on. Tweaked dead reckoning graphics to draw the DR trail
+ in a dashed line and draw an arc that gets larger as time from
+ last posit grows until it turns into a circle.
+
+2002-11-18 13:19 we7u
+
+ * src/draw_symbols.c: Fixing the bug where weather stations hit the
+ clear interval but wind barbs still get drawn.
+
+2002-11-17 21:48 kd6zwr
+
+ * src/main.c: added keysyms for pgup/pgdn on sun keyboards
+
+2002-11-14 18:02 we7u
+
+ * src/util.c: Code to handle disowning of object that other people
+ take over, and to comment out our own objects from the object.log
+ file when we delete them. This keeps us from retransmitting the
+ objects when Xastir restarts.
+
+2002-11-14 16:25 we7u
+
+ * src/: main.c, util.c, util.h: More object stuff. More to do yet.
+
+2002-11-14 15:50 we7u
+
+ * src/: db.c, util.c, util.h: The start of code to allow disowning
+ an object that someone else is assuming control over. Xastir
+ already does this while running, but it doesn't write the data to
+ the object.log file, so when it starts up, it owns the object
+ again.
+
+2002-11-14 14:07 we7u
+
+ * src/db.c: Saving empty-string for speed instead of "0" if speed
+ is unknown on a parsed packet.
+
+2002-11-14 12:40 we7u
+
+ * src/db.c: Unlinking DR functions from Display Course/Speed
+ toggles.
+
+2002-11-14 11:30 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/draw_symbols.c,
+ src/draw_symbols.h, src/main.c, src/main.h, src/xa_config.c:
+ Initial implementation of dead-reckoning by J. Lance Cotton,
+ KJ5O. Thanks very much to him for doing this!!!
+
+2002-11-13 15:31 we7u
+
+ * src/maps.c: Forcing terraserver map extents in the index to be at
+ the edges of the earth. Added more statusline messages for
+ loading/indexing maps (more consistent now).
+
+2002-11-13 14:13 we7u
+
+ * src/maps.c: An attempt to fix the buffer overflow problems with
+ map indexing.
+
+2002-11-13 13:19 we7u
+
+ * src/main.c: We now delete/recreate our own station record only if
+ we change our callsign. All other changes just cause an update
+ to the current record.
+
+2002-11-13 12:43 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: New "Waiting for
+ GPS data.." string.
+
+2002-11-13 12:40 we7u
+
+ * src/: db.c, interface.c, main.c, main.h: Implemented a countdown
+ from when GPS data goes invalid. It is decremented each time a
+ posit occurs. When it reaches zero, posits stop. Valid GPS data
+ parsing will reset it back to the starting count. Also reduced
+ the size of the tracked station circles in order to more easily
+ read the station data.
+
+2002-11-12 18:23 we7u
+
+ * src/db.c: Added another blue circle for tracked stations. Now
+ three concentric circles.
+
+2002-11-12 18:17 we7u
+
+ * src/db.c: Making a tracked station have both a yellow and red
+ circle to make it easier to see against different map
+ backgrounds.
+
+2002-11-12 18:07 we7u
+
+ * src/: db.c, interface.c, main.c, main.h: Added
+ "my_position_valid" variable, initially set to 1. As soon as a
+ GPS interface of any type is started up, this variable gets set
+ to zero, and it holds off posits. Once the first valid GPS
+ position is parsed, this variable is again set to 1, and posits
+ proceed normally. As Xastir comes up, interfaces are brought up
+ before the first posit, so if a GPS interface is enabled on
+ startup, no posits will occur until the first GPS posit is parsed
+ properly. This variable could be used later to disable posits
+ when GPS data becomes unusable or stops coming in. This feature
+ is not implemented yet though.
+
+2002-11-12 15:23 we7u
+
+ * src/db.c: Changed tracked stations circle from Red to Yellow to
+ make it easier for partially colorblind people to see against a
+ background of topo maps.
+
+2002-11-12 14:56 we7u
+
+ * src/db.c: Got rid of another bug off the buglist. Now only
+ stations that are currently visible will be selected for Station
+ Info operations.
+
+2002-11-12 14:15 we7u
+
+ * src/main.c: Changed the order of startup so that map indexing is
+ completed before interfaces are brought up.
+
+2002-11-12 10:56 we7u
+
+ * src/maps.c: Changes intended to keep variables from going
+ out-of-bounds. I'm attempting to get more DRG-Enhanced map
+ formats working. These changes don't quite make them work, but
+ they do make it better and catch some out-of-bounds problems.
+
+2002-11-11 15:01 we7u
+
+ * configure, configure.in, ltconfig: OpenBSD 3.1/IA32 patches by
+ Yasholomew Yashinski. Thanks!
+
+2002-11-09 18:04 kd6zwr
+
+ * src/main.c: Fix for white foreground on solaris (uninitialized
+ color)
+
+2002-11-07 16:14 we7u
+
+ * README.1ST: Added a note about MrSID file compression.
+
+2002-11-07 16:10 we7u
+
+ * README.1ST: Added some notes about DRG-E files.
+
+2002-11-06 22:40 we7u
+
+ * README.1ST: Added some "su" lines and some comments about
+ "ginstall".
+
+2002-11-06 15:15 we7u
+
+ * FAQ: Added a section about geoTIFF's causing segfaults.
+
+2002-11-06 12:47 we7u
+
+ * README.1ST: Added a section describing the FGD file format
+ portion that we use.
+
+2002-11-01 16:56 we7u
+
+ * src/maps.c: Changed one comment.
+
+2002-10-31 16:27 we7u
+
+ * src/maps.c: Added checks in the geoTIFF code for neat-line map
+ boundaries being outside normal limits. If found, output warning
+ message, reset the corner to something more reasonable, and
+ continue on.
+
+2002-10-31 13:52 we7u
+
+ * src/: datum.h, maps.c: Converting from using proj.4 to using
+ datum.h/datum.c in order to do our datum translations for geoTIFF
+ maps.
+
+2002-10-30 13:40 francais1
+
+ * src/: draw_symbols.c, main.c, xastir.h: Added support for 25% and
+ 12.5% stipples when drawing station ambiguity.
+
+2002-10-30 13:38 francais1
+
+ * symbols/: 13pct.xbm, 25pct.xbm, Makefile.am, Makefile.in: Added
+ pixmaps for 25% and 12.5% stipples
+
+2002-10-30 11:08 we7u
+
+ * src/: db.c, draw_symbols.c, main.c: Fixed some conversion
+ problems for speed/wind speed. Added some notes. Wind barbs are
+ not shown properly in knots instead of mph.
+
+2002-10-29 14:26 we7u
+
+ * src/db.c: Tweaks to the wind direction/wind speed decoding for
+ weather stations. We were missing speed/direction for many
+ weather packets. Many more wind barbs are now showing up.
+
+2002-10-28 22:34 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/main.h,
+ src/xa_config.c: Added a new toggle to the Defaults dialog for
+ enabling/disabling warnings for modifier keys.
+
+2002-10-25 15:04 we7u
+
+ * README.1ST: Changing some notes regarding map permissions and
+ running as the root user.
+
+2002-10-25 13:34 we7u
+
+ * README.1ST: Added a note about map and map directory permissions.
+ Added warnings regarding running programs as the root user.
+
+2002-10-24 17:32 rzg
+
+ * help/help-English.dat: Updates for the Map and Station menu
+ changes.
+
+2002-10-23 16:12 we7u
+
+ * src/draw_symbols.c: Cleanup of debug code & comments for the wind
+ barb stuff.
+
+2002-10-23 13:28 we7u
+
+ * src/: db.c, draw_symbols.c, draw_symbols.h, main.c: Wind Barb
+ implementation. Enable/Disable togglebutton has yet to be added
+ to disable these.
+
+2002-10-22 15:16 we7u
+
+ * config/language-Portuguese.sys: Changes by David Quental, CT1DRB.
+
+2002-10-22 14:37 we7u
+
+ * help/help-English.dat: Another item for your todo list.
+
+2002-10-22 14:12 we7u
+
+ * src/maps.c: Tweak to weather alert code to compensate for NULL
+ fields in the NOAA shapefiles. Weather alerts should now appear
+ in the proper places even if using newer NOAA files.
+
+2002-10-21 23:35 rzg
+
+ * README.1ST: Oops, didn't mean to revert that stuff...
+
+2002-10-21 23:29 rzg
+
+ * README.1ST, FAQ, help/help-English.dat: Minor fixes/updates to
+ docs.
+
+2002-10-20 22:53 francais1
+
+ * src/db.c: ST_VIATNC is what I really wanted...
+
+2002-10-20 22:26 we7u
+
+ * src/interface.c: Moved a variable inside the proper #ifdef
+ statements. It was causing a compiler warning on systems without
+ kernel AX.25 interface support.
+
+2002-10-20 21:30 francais1
+
+ * src/: main.c, maps.c, maps.h: Enabled +/= and - to change the
+ grid size a bit.
+
+2002-10-20 20:15 francais1
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c, src/main.h:
+ Expanded "Display Stations" into "Display Local Stations" and
+ "Display Non-Local Stations"
+
+2002-10-20 18:06 francais1
+
+ * src/: db.c, interface.c, interface_gui.c: First pass at relay
+ digipeating over an ax25 interface. Look for the define
+ I_WANT_TO_TRY_AX25_RELAY_DIGIPEAT in db.c and interface_gui.c
+
+2002-10-19 12:06 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c: Added an ID
+ string to the status line for the periods when no traffic is
+ coming in. If the ID string doesn't appear for 9 minutes
+ straight, it is forced onto the statusline for a few seconds in
+ order to meet ID requirements. This is useful for beaming an
+ Xastir image over amateur fast-scan television. Tweaked the
+ Configure->Station callsign block so that all characters of a
+ full callsign plus SSID are displayed. Tweaked the weather
+ symbol display code so that " " and "..." are not taken to be a
+ zero reading.
+
+2002-10-18 15:42 we7u
+
+ * src/maps.c: Changes in the GNIS map-reading code to accomodate
+ the lack of consistency in how the GNIS files are formatted.
+
+2002-10-18 14:04 we7u
+
+ * README.1ST: Added a note from Chris about GNIS file.
+
+2002-10-18 12:34 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Broke up Stations menu
+ into submenus.
+
+2002-10-18 10:13 we7u
+
+ * src/main.c: Set default ON for new togglebuttons on stations
+ menu.
+
+2002-10-17 22:30 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c, src/main.h:
+ Initial attempt at some station/object display filtering. What
+ is coded so far works, but most of the variables are not saved in
+ the config file yet. May need more togglebuttons & variables
+ implemented yet.
+
+2002-10-17 15:41 we7u
+
+ * AUTHORS: Minor cleanups and added a few contributors.
+
+2002-10-17 15:23 we7u
+
+ * README.1ST: Move "Previous Install Notes" section to a later
+ point in the file.
+
+2002-10-17 15:05 we7u
+
+ * src/db.c: Tweaks to get rid of compiler warnings for Debian/S390.
+ Changed char's to int's and got rid of some casts.
+
+2002-10-17 12:13 we7u
+
+ * config/language-Portuguese.sys: Changes by David Quental, CT1DRB.
+
+2002-10-16 14:10 we7u
+
+ * src/db.c: Added draw_symbol_filtered() function. Will eventually
+ add code to this function which implements display filtering.
+
+2002-10-15 14:28 we7u
+
+ * src/: db.c, draw_symbols.c, draw_symbols.h: Implemented different
+ colors for tropical storm/depression and hurricane packets, for
+ the three different wind speeds: Green = gale force wind radius,
+ yellow = tropical storm wind radius, red = hurricane wind radius.
+
+2002-10-15 13:38 we7u
+
+ * src/db.c: Converted storm circles from nautical miles to miles
+ before calling draw_pod_circle. Ranges are now correct. Added a
+ couple of comments as well regarding things yet to be done.
+
+2002-10-11 16:25 we7u
+
+ * src/wx.c: Added a comment about Dallas rain gauge.
+
+2002-10-11 12:55 we7u
+
+ * src/db.c: Initial attempt at drawing circles around storm objects
+ (radius of winds). Need to convert from nautical miles to miles
+ and perhaps change to a different method of drawing, but this
+ works for now.
+
+2002-10-11 12:54 we7u
+
+ * src/wx.c: Commented out a debug line.
+
+2002-10-11 12:53 we7u
+
+ * src/draw_symbols.c: Added some comments.
+
+2002-10-10 15:56 we7u
+
+ * src/wx.c: Wind speed for Dallas one-wire WX station.
+
+2002-10-10 15:21 we7u
+
+ * src/wx.c: Correction to temperature conversion for Dallas WX
+ station.
+
+2002-10-10 15:19 we7u
+
+ * src/wx.c: Support for wind direction for Dallas WX station (using
+ OWW daemon for the data feed).
+
+2002-10-10 13:40 we7u
+
+ * src/interface.c: Now handle 0x00 characters in port_read, for the
+ case where the One-Wire Weather daemon ("OWW") sends them to us.
+ Temperature from a Dallas one-wire station is now initially coded
+ and appears to be working.
+
+2002-10-10 13:38 we7u
+
+ * src/wx.c: Changed some comments and put one message under
+ debug_level control.
+
+2002-10-10 13:05 francais1
+
+ * src/util.c: phg_decode was missing the phg circle radius/2 stuff
+ put into phg_decode.
+
+2002-10-10 01:48 we7u
+
+ * src/: db.h, wx.c: Initial support for Dallas One-Wire weather
+ station. Xastir gets it's data from the OWW server. We
+ currently only parse out the temperature, and it appears we only
+ do that once when the network port is brought up. More
+ functionality to be added later.
+
+2002-10-08 22:52 we7u
+
+ * src/: main.h, maps.c, maps.h, track_gui.c: Fixed bug where
+ TrackMe button didn't get disabled when tracking was cleared from
+ the menus. Map indexing now removes indexes for deleted files.
+ Another ImageMagick API change is now handled in our code.
+
+2002-10-08 21:32 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: We now check for
+ modifier keys when the third mouse button press is detected and
+ dump out a warning message asking the user to turn off the
+ modifier keys.
+
+2002-10-04 00:20 we7u
+
+ * src/db.c: More correct parsing of Storm Data.
+
+2002-10-03 17:31 we7u
+
+ * src/db.c: Commenting out debug statements.
+
+2002-10-03 17:29 we7u
+
+ * src/: db.c, db.h: The start of decoding storm data. More to do
+ in terms of units conversion and display, but the basic packet
+ decoding is coded and working.
+
+2002-10-03 16:06 we7u
+
+ * src/maps.c: Added a comment.
+
+2002-10-03 11:35 we7u
+
+ * src/: maps.c, track_gui.c: Small tweaks to wget error messages.
+
+2002-10-03 11:25 we7u
+
+ * src/: main.c, maps.c, maps.h: Updates to map indexing. Starting
+ to work as intended now.
+
+2002-10-02 16:39 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/maps.c,
+ src/xa_config.c, src/xastir.h: Added a Disable Raster Map
+ togglebutton to the maps menu. Added "Indexing" text to the
+ statusline as we're indexing maps.
+
+2002-10-02 15:28 we7u
+
+ * src/maps.c: Changed auto_maps to use the in-memory map index.
+ Lot's of tweaks to sort the map index. Now use the .geo
+ filenames instead of the http/ftp URL's. Got rid of shx/dbf
+ filenames (using shp instead). This got rid of the
+ triple-drawing of shapefiles that was ocurring with automaps.
+ Added statusline() calls to all of the draw functions.
+
+2002-10-01 10:43 we7u
+
+ * src/maps.c: Added more error output for geoTIFF's, where proj may
+ not have been installed correctly.
+
+2002-09-30 16:50 we7u
+
+ * src/interface_gui.c: Minor correction. This window was WAY too
+ long when I defined 30 interfaces. The new length is more
+ reasonable.
+
+2002-09-30 16:06 we7u
+
+ * src/: interface.h, interface_gui.c, main.c: Upp'ed the number of
+ interface to 15. Tweaked the GUI and other portions of the code
+ to handle whatever MAX_IFACE_DEVICES is set to. Xastir should
+ theoretically be able to handle any number of interfaces now, but
+ it's only been tested so far up to 15.
+
+2002-09-30 00:19 we7u
+
+ * README.1ST: Added a note about the 24kgrid file available from
+ gisdatadepot.
+
+2002-09-29 23:41 we7u
+
+ * README.1ST: Added a more specific path for getting GNIS
+ datafiles.
+
+2002-09-29 22:04 we7u
+
+ * README.1ST: Added a few more sources of Shapefile maps.
+
+2002-09-26 16:11 we7u
+
+ * src/maps.c: Fixes for Tigermap and GEO file segfaults. Saw
+ segfaults with Tigermaps when "wget" returned a zero-length file.
+ These changes fix this problem.
+
+2002-09-26 13:39 we7u
+
+ * src/db.c: Limiting the new togglebutton to work only on objects
+ containing weather, not on all objects.
+
+2002-09-26 13:29 we7u
+
+ * src/: db.c, main.c: A better logical relation between the
+ togglebuttons for the new "Display WX Object/Item" button.
+
+2002-09-26 12:39 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Minor change to
+ Display Weather Object strings.
+
+2002-09-26 12:30 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c, src/main.h,
+ src/xa_config.c: Added a new toggle for enable/disabling weather
+ objects.
+
+2002-09-25 15:23 we7u
+
+ * src/wx_gui.c: Widening some fields by one character width in Own
+ Weather Data dialog.
+
+2002-09-25 15:13 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/wx_gui.c: Changing barometric
+ pressure display in inches Mercury to have two digits after the
+ decimal point.
+
+2002-09-25 01:28 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/wx.c, src/wx.h,
+ src/wx_gui.c: Implemented English/Metric barometric pressure for
+ Own Weather Station dialog and for Station Info dialog.
+
+2002-09-25 00:49 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Added another
+ string for weather stuff.
+
+2002-09-24 16:49 we7u
+
+ * src/maps.c: Just adding some blank lines to delineate the
+ different functions. More real code changes to come later.
+
+2002-09-24 13:11 we7u
+
+ * src/db.c: Better handling of weather stations and weather
+ objects. We now try to parse the course/speed field _and_ the
+ 'c' and 's' fields in all cases, and can handle some of the
+ different field positions that some of the RAWS weather objects
+ present to us.
+
+2002-09-24 10:34 we7u
+
+ * src/db.c: Changed wx_fuel_moisture so that a 00 reading equates
+ to 100%.
+
+2002-09-23 23:48 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/db.h: Added parsing of
+ Fuel Temperature and Fuel Moisture for RAWS weather objects, and
+ the corresponding display in the Station Info dialog.
+
+2002-09-23 22:53 we7u
+
+ * src/db.c: Added some comments.
+
+2002-09-23 11:46 we7u
+
+ * help/help-English.dat: _Very_ minor spelling fixes.
+
+2002-09-23 11:40 we7u
+
+ * src/maps.c: Changes to the lat/long gridlines by Thierry Leconte:
+ "Now, the code draw solid line and 3 types of dashed lines.
+ Solid line is, as previously, for equator and Greenwich meridian.
+ The 3 dashed line corespond to locator coord scheme : 1st dasher
+ line for big square (2 first letters) 2nd dashed line for the 2
+ numbers 3rd dashed line for small square (2 last letter).
+ Depending of the zooming, the code could draw 1,2 or the 3 line
+ types." We might wish to change the sizes of the boxes, but the
+ ideas behind it and the implementation are great! Thanks
+ Thierry!
+
+2002-09-23 11:29 rzg
+
+ * help/help-English.dat: Updates for object persistance and a few
+ more on the new features list to be documented at some point. I
+ still exist. :-)
+
+2002-09-23 10:38 we7u
+
+ * src/: maps.c, util.c: Fixes by Tom Russo for map indexing of GNIS
+ files and for reading in zero-length files. Thanks Tom!
+
+2002-09-19 15:52 we7u
+
+ * src/main.c: Changes by Thierry Leconte which make degrees/minutes
+ symbols appear in the status line, and add the Maidenhead grid
+ locator to it as well. Small changes by we7u to tweak the widths
+ of the textfields on the status line.
+
+2002-09-19 14:13 we7u
+
+ * src/wx.c: More changes for Peet Bros. U2K weather station
+ decoding by David L. Norris.
+
+2002-09-19 13:57 we7u
+
+ * src/: main.c, main.h, maps.c, xa_config.c: Getting rid of WIN_MAP
+ variables once and for all.
+
+2002-09-19 13:49 we7u
+
+ * src/db.c: More careful string copying of callsigns in a couple of
+ places. There was a possibility of overrunning the destination
+ string before.
+
+2002-09-19 13:27 we7u
+
+ * src/db.c: Adjusting buffer lengths to handle longer packets.
+
+2002-09-19 12:28 we7u
+
+ * src/: main.h, xastir.h: Change to allow u2k complete record mode
+ (long packets) to get through the decoding functions.
+
+2002-09-19 12:16 we7u
+
+ * src/wx.c: Another small tweak to rain totals for u2k.
+
+2002-09-19 11:12 we7u
+
+ * src/wx.c: Changes for Peet Bros. U2K weather station decoding by
+ David L. Norris.
+
+2002-09-19 09:32 we7u
+
+ * src/maps.c: Commenting out the map index printf's in maps.c
+
+2002-09-19 01:08 we7u
+
+ * src/main.c: Adding new language string for TrackMe button.
+
+2002-09-19 01:03 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Added new language
+ string for TrackMe button.
+
+2002-09-19 00:56 we7u
+
+ * src/: main.c, track_gui.c, track_gui.h, xa_config.c: Implemented
+ new TrackMe button on the main window. State is saved in config
+ file so that Xastir starts up in the correct mode.
+
+2002-09-18 15:48 we7u
+
+ * src/: main.c, maps.c, xa_config.c: Added more map types to the
+ VECTOR button on map chooser. Now selects ".map", ".gnis",
+ ".pdb", and ".shp" files. Changed default name of "winmaps.sys"
+ file to "selected_maps.sys". This last change will only take
+ effect on new installations, or if the winmaps.sys file is
+ deleted.
+
+2002-09-18 14:21 we7u
+
+ * src/: main.c, maps.c: Map indexing, saving/restoring from files.
+ This version is more space-efficient. We could do more speedups
+ by doing a sort and binary search through the index, or using a
+ hash.
+
+2002-09-18 12:35 we7u
+
+ * src/maps.c: Small tweak to correct code which creates the empty
+ map index file.
+
+2002-09-18 12:30 we7u
+
+ * src/maps.c: Killing off the saving of the map index for now.
+ Plan on implementing a more space-efficient storage.
+
+2002-09-18 12:17 we7u
+
+ * src/: maps.h, main.c, maps.c: Now saving/restoring the map index
+ to a file.
+
+2002-09-18 11:41 we7u
+
+ * src/: main.c, main.h, maps.c, maps.h, xa_config.c: Initial
+ implementation of map indexing, still need to save/restore the
+ map index linked list to a file. Currently the indexing occurs
+ _after_ the first map draw, then succeeding map draws check the
+ index which speeds things up considerably. The plan is to write
+ the index to a file, read it in _before_ the first map draw, and
+ then re-index only when new files appear or files are changed in
+ the map directory.
+
+2002-09-12 10:48 we7u
+
+ * src/main.c: Added the Station Last Heard button into the
+ Sensitive enable/disable for Symbols in the menu. It was getting
+ grey'ed out and not returning to the Sensitive state as the
+ Symbols Enable button was toggled.
+
+2002-09-12 09:56 we7u
+
+ * src/maps.c: Fixes to draw_shapefile_map() to set a default line
+ width, for cases where specific maps are not recognized later in
+ the code. The problem was that other areas in the drawing code
+ (probably tracklines) where causing map lines to get drawn in
+ double or triple width at times.
+
+2002-09-10 16:35 we7u
+
+ * src/maps.c: Added a default line width setting to the start of
+ the polyline drawing portion of draw_shapefile_map(). This is an
+ attempt to get rid of the double line-widths that are sometimes
+ seen on the screen.
+
+2002-09-10 16:14 we7u
+
+ * src/db.c: Fixing the new track detector for the save track
+ function.
+
+2002-09-10 15:14 we7u
+
+ * src/: db.c, db.h: A bit of housekeeping. Renaming the TrackRow2
+ struct to TrackRow, since the old TrackRow is now deleted from
+ the code.
+
+2002-09-10 12:22 we7u
+
+ * src/: db.h, db.c: Fixes for station track storage.
+
+2002-09-10 10:04 we7u
+
+ * src/main.c: Creating the .xastir/tracklogs directory
+ automatically on startup.
+
+2002-09-09 16:29 we7u
+
+ * src/maps.c: Tweak to handle parsing of newer format bounding
+ coordinates from USGS .fgd files.
+
+2002-09-03 09:23 francais1
+
+ * src/list_gui.c: Bug 604044 All station names were ghosted.
+ Fixed.
+
+2002-08-29 17:44 we7u
+
+ * src/maps.c: Changed some comments.
+
+2002-08-29 14:01 we7u
+
+ * src/main.c: Changing language list to alphabetical.
+
+2002-08-29 08:49 we7u
+
+ * src/: bulletin_gui.c, db.c, util.c: Putting several debug
+ printf's under debug_level control.
+
+2002-08-28 13:41 we7u
+
+ * src/: db.c, util.c: Fix for bulletins popping up that are out of
+ range. We were computing the distance from our station based on
+ the destination callsign (BLNx) instead of the originating
+ callsign.
+
+2002-08-27 15:43 we7u
+
+ * src/: util.h, util.c: Added higher precision timers in order to
+ time code sections.
+
+2002-08-27 15:42 we7u
+
+ * config/language-Dutch.sys: Changed by Han Sytsma, PE1FAM.
+
+2002-08-26 14:52 we7u
+
+ * scripts/: coord-convert.pl, permutations.pl, test_coord.pl:
+ Modifying each script to add a path to /usr/local/lib in order to
+ find the Coordinate.pm module.
+
+2002-08-26 12:08 we7u
+
+ * src/db.c: Added a few comments.
+
+2002-08-24 11:52 kd6zwr
+
+ * src/maps.c: Explicitly defined shorts as unsigned to fix wrapping
+ problems with palm maps.
+
+2002-08-23 10:06 we7u
+
+ * README.1ST: Added a note about Tiger 2000 maps converted to
+ Shapefiles.
+
+2002-08-22 15:43 we7u
+
+ * src/maps.c: Added some casts.
+
+2002-08-22 14:58 we7u
+
+ * README.1ST: Updated the fcc/rac call lookup installation
+ instructions.
+
+2002-08-22 13:58 we7u
+
+ * src/maps.c: More comments.
+
+2002-08-22 12:47 we7u
+
+ * src/maps.c: More comments.
+
+2002-08-22 12:12 we7u
+
+ * scripts/: Makefile.am, Makefile.in: Adding coord-convert.pl and
+ permutations.pl to install.
+
+2002-08-22 11:33 we7u
+
+ * src/maps.c: Changing some comments. No code changes.
+
+2002-08-22 09:51 we7u
+
+ * src/maps.c: Adding some comments to the palm map routine.
+
+2002-08-22 09:43 we7u
+
+ * src/maps.c: Changed a single-letter variable to two letters to
+ make it easier to grep for in the code.
+
+2002-08-21 17:19 we7u
+
+ * src/: bulletin_gui.c, bulletin_gui.h, db.c, main.c: Fixes for
+ bulletins popping up. Now waits 15 seconds to see if a posit
+ comes in before attempting to pop up the bulletins dialog. Added
+ filtering for characters output by an extract_multipoints debug
+ message.
+
+2002-08-21 11:24 we7u
+
+ * src/list_gui.c: Now grey out the object/item name as well if it
+ has been deleted. In the View->Object & Item dialogs.
+
+2002-08-21 11:17 we7u
+
+ * src/db.c: Putting out debug message in order to debug possible
+ bulletin problem.
+
+2002-08-21 11:16 we7u
+
+ * src/list_gui.c: We now show deleted objects/items in the "View"
+ dialogs as ghosted.
+
+2002-08-20 15:07 kd6zwr
+
+ * src/main.c: Bumped up the test for debug level dialog.
+
+2002-08-16 15:54 we7u
+
+ * FAQ: More minor tweaks to the same section.
+
+2002-08-16 15:50 we7u
+
+ * FAQ: Minor addition to the "why can't I see stations" paragraph.
+
+2002-08-15 16:57 we7u
+
+ * src/maps.c: Moved the USGS Quad labels left by one square. They
+ appear to be in the correct places now.
+
+2002-08-15 14:27 we7u
+
+ * config/tnc-startup.paccomm: New startup file for Pac-Comm TNC's
+ with version 5.x firmware.
+
+2002-08-15 10:22 we7u
+
+ * scripts/coord-convert.pl: Added the capability to handle "48N
+ 122W" and similar inputs. Fixed a bug in DD MM.MM conversions.
+
+2002-08-14 15:04 we7u
+
+ * src/db.c: An attempt to prevent Emergency popups about the same
+ callsign from appearing more often than every 30 minutes.
+
+2002-08-14 13:51 we7u
+
+ * scripts/: coord-convert.pl, permutations.pl: Adding a blank line
+ between user input and output lines.
+
+2002-08-14 11:21 we7u
+
+ * scripts/permutations.pl: And handling yet another format...
+
+2002-08-14 11:15 we7u
+
+ * scripts/permutations.pl: Tweaks to more properly format some
+ inputs.
+
+2002-08-14 10:55 we7u
+
+ * scripts/permutations.pl: Tweaks to allow shorter lat/lon strings
+ to be processed.
+
+2002-08-14 10:12 we7u
+
+ * scripts/permutations.pl: Added the capability to write APRS Items
+ to a log file that can be sucked in by Xastir.
+
+2002-08-14 09:52 we7u
+
+ * src/db.c: Minor tweak to get rid of compiler warning.
+
+2002-08-14 08:49 francais1
+
+ * src/util.c: Nasty lat/lon to/from UTM conversion bug. (Wasn't
+ referencing correct ellipsoid.) Also made last 2 characters of
+ grid square location lowercase since that seems more common.
+
+2002-08-14 08:49 francais1
+
+ * src/main.c: Nasty lat/lon to/from UTM conversion bug. (Wasn't
+ referencing correct ellipsoid.)
+
+2002-08-13 17:12 we7u
+
+ * scripts/permutations.pl: New script which will show various
+ permutations for a lat/lon or UTM input. Eventually plan to have
+ this script write a log file containing objects so that Xastir
+ can plot each of the positions. This will be useful in quickly
+ determining which of the formats is within the area of interest.
+ Developed this for Search & Rescue applications.
+
+2002-08-13 16:51 we7u
+
+ * scripts/coord-convert.pl: Added a range check for the Easting
+ value. Not exact, but better than nothing.
+
+2002-08-13 15:34 we7u
+
+ * scripts/coord-convert.pl: Added capability to use UTM as the
+ input coordinate.
+
+2002-08-13 14:36 we7u
+
+ * scripts/: Coordinate.pm, test_coord.pl: Getting the dates right
+ for the copyright.
+
+2002-08-13 14:34 we7u
+
+ * scripts/: Coordinate.pm, coord-convert.pl, test_coord.pl: Tweaks
+ to headers.
+
+2002-08-13 14:01 we7u
+
+ * src/db.c: Commenting out debug statement.
+
+2002-08-13 13:47 we7u
+
+ * src/db.c: Fixed Mic-E decoding problem having to do with position
+ ambiguity. We have to specifically test for 'L' in the
+ destination field as it doesn't match the general bit patterns.
+ Stupid spec anyway.
+
+2002-08-13 11:39 we7u
+
+ * src/: db.c, db.h, draw_symbols.c, draw_symbols.h: Severe storm
+ objects by Gerry Wheeler, KG4NBB. Dale Huguley, KG5QD's weather
+ server (on the 'net) generates severe storm objects and
+ boundaries based on NWS data. These objects are now decoded and
+ drawn by Gerry's new code additions.
+
+2002-08-12 17:03 we7u
+
+ * scripts/: Coordinate.pm, coord-convert.pl, test_coord.pl: Utility
+ for converting between coordinates, written in Perl. Also has
+ UMS coordinates.
+
+2002-08-12 12:04 we7u
+
+ * src/maps.c: Pre-pending the quad index to the quad name.
+
+2002-08-12 11:36 we7u
+
+ * src/maps.c: Fix for some labels on quad overlay shapefile.
+
+2002-08-11 09:57 we7u
+
+ * README.1ST: Changed the URL where the Mac OS X instructions
+ reside.
+
+2002-08-09 17:34 we7u
+
+ * src/maps.c: Nicer labels for the quad names.
+
+2002-08-09 17:26 we7u
+
+ * src/maps.c: Initial support for USGS Quad overlay shapefile.
+
+2002-08-09 16:33 we7u
+
+ * README.1ST: A bit more about ldconfig.
+
+2002-08-08 23:33 we7u
+
+ * src/: util.c, util.h, wx.c: Changes to 30-second timestamps in
+ logfiles: Now closely emulate the date/time string that the
+ date(1) command generates.
+
+2002-08-06 16:14 we7u
+
+ * src/util.c: Getting rid of a message that appears if the
+ .xastir/config/object.log file doesn't exist.
+
+2002-08-06 13:42 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Added a clear button for
+ the object/item history file.
+
+2002-08-06 13:00 we7u
+
+ * src/: main.c, util.c, util.h, xastir.h: Implementation of
+ persistent objects/items. Each new, deleted, or moved
+ object/item is logged to "~/.xastir/config/object.log". This
+ file is read in and each line processed on startup. This will
+ also show tracklines for moved objects as each change is logged
+ to the file.
+
+2002-08-06 11:33 we7u
+
+ * src/db.c: Adding "AA:" to the beginning of auto-response
+ messages.
+
+2002-08-06 09:52 francais1
+
+ * src/maps.c: IsPseudoClass in ImageMagick 5.3.1 doesn't quite act
+ like I would have thought. Changed to different check.
+
+2002-08-05 15:29 we7u
+
+ * src/: messages_gui.c, view_message_gui.c: More tweaks regarding
+ fonts. Seems we can set foreground color but not background on a
+ couple of widgets. Trying to set background color causes a
+ segfault.
+
+2002-08-05 15:07 we7u
+
+ * src/: messages_gui.c, view_message_gui.c: Move segfault fixes in
+ new code.
+
+2002-08-05 15:05 we7u
+
+ * src/view_message_gui.c: Fix for segfault in newly introduced
+ code.
+
+2002-08-05 13:48 we7u
+
+ * src/: bulletin_gui.c, draw_symbols.c, location_gui.c, main.c,
+ messages_gui.c, track_gui.c, view_message_gui.c, xastir.h: Added
+ defines for foreground and background font colors. This and the
+ associated code changes should help to alleviate the problem
+ where font colors would accidentally change during runtime due to
+ color-ls being run in the starting Xterm.
+
+2002-07-26 09:35 we7u
+
+ * help/help-English.dat: Very minor changes to the new scripts
+ section.
+
+2002-07-26 09:30 we7u
+
+ * src/messages_gui.c: Put another message under debug_level
+ control.
+
+2002-07-26 08:45 rzg
+
+ * help/help-English.dat: Added scripts section, minor update to new
+ features list.
+
+2002-07-25 22:24 we7u
+
+ * src/messages_gui.c: Commenting out some debug messages.
+
+2002-07-25 20:29 we7u
+
+ * src/: db.c, igate.c, igate.h, main.c: Implemented SENT and HEARD
+ queues for igating->RF. Dupes are now eliminated. This includes
+ if another igate beat us to getting a packet on RF: In that case
+ we don't add to the traffic on RF by sending it out too.
+
+2002-07-24 12:58 we7u
+
+ * src/db.c: Fix for igating: We were testing the ST_VIATNC flag
+ for a station first to see if it had been heard via a TNC
+ interface. This flag gets reset if the last 20 packets were
+ heard from non-TNC interfaces. We now check the
+ heard_via_tnc_last_time timestamp to see if it's nonzero. This
+ timestamp does _not_ get set to 0. The code in
+ heard_via_tnc_in_past_hour() should work better for igating now.
+
+2002-07-23 15:04 we7u
+
+ * src/: interface_gui.c, xa_config.c: Changing txtail default value
+ to from 10ms to 30ms. Should be proper for 1200 baud.
+
+2002-07-23 14:37 we7u
+
+ * README.1ST: Added Lindows to the list.
+
+2002-07-23 14:27 we7u
+
+ * src/: interface.c, interface.h, interface_gui.c, xa_config.c:
+ Turned "Full Duplex" KISS parameter into a togglebutton.
+
+2002-07-23 13:43 we7u
+
+ * src/: interface.c, interface.h, interface_gui.c, xa_config.c:
+ Added TxTail parameter to the KISS properties dialog.
+
+2002-07-23 13:07 we7u
+
+ * src/messages_gui.c: Putting more debug messages under debug_level
+ control.
+
+2002-07-22 19:41 rzg
+
+ * help/help-English.dat: Added mention of RELAY digipeating and
+ fixed a formatting thing.
+
+2002-07-22 11:08 we7u
+
+ * configure, configure.in: Bumping it to version 1.1.3. Getting
+ ready for another development release.
+
+2002-07-22 10:41 we7u
+
+ * src/: db.c, interface_gui.c: Commenting out debug message.
+ Making Relay Digipeat togglebuttons insensitive until the code to
+ implement them is functional.
+
+2002-07-20 00:44 we7u
+
+ * src/db.c: Don't relay from KISS interface if transmit for that
+ interface is turned off.
+
+2002-07-20 00:31 we7u
+
+ * src/interface_gui.c: Changes to make RELAY digipeat insensitive
+ when transmit is disabled for that interface.
+
+2002-07-19 23:50 we7u
+
+ * src/interface.c: Commenting out another debug statement.
+
+2002-07-19 23:48 we7u
+
+ * src/interface.c: Fixes to AX.25 interfaces that were broken
+ earlier by KISS TNC changes.
+
+2002-07-19 17:02 we7u
+
+ * src/interface.c: Changes to serial lockfiles. Now closes port
+ before removing lock. Attempts to close port and remove lock if
+ open fails for any number of reasons.
+
+2002-07-19 15:19 we7u
+
+ * src/interface.c: Fixes for errant long packets. Code had the
+ wrong number for the length of the incoming strings.
+
+2002-07-19 13:51 we7u
+
+ * src/: db.c, interface.c: Found an off-by-one error in
+ incoming_data_length. Changed a lot of comments w.r.t. KISS
+ interfaces.
+
+2002-07-19 01:06 we7u
+
+ * src/: db.c, db.h, interface.c, interface.h, main.c: More work on
+ RELAY digipeating for Serial KISS TNC interfaces. Getting
+ closer, but this version is still non-functional.
+
+2002-07-18 17:02 we7u
+
+ * src/: db.c, db.h, main.c: More preparation for later coding of
+ the RELAY digipeat function. Not implemented yet.
+
+2002-07-18 16:49 we7u
+
+ * src/: db.c, main.c: More comments.
+
+2002-07-18 16:48 we7u
+
+ * src/interface.c: Fixing another double-lock problem.
+
+2002-07-18 16:36 we7u
+
+ * src/main.c: Added an important comment.
+
+2002-07-18 16:34 we7u
+
+ * src/interface.c: Fixing a double-lock problem that I introduced
+ earlier today.
+
+2002-07-18 14:55 we7u
+
+ * src/interface_gui.c: Adding a debug_level statement in that was
+ missing.
+
+2002-07-18 14:47 we7u
+
+ * src/interface_gui.c: Adding relay_digipeat stuff to the AX.25
+ interface GUI.
+
+2002-07-18 14:40 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/interface.h,
+ src/interface_gui.c, src/xa_config.c: Preliminary code including
+ GUI support for RELAY digipeating on Serial KISS TNC interfaces.
+ The back-end code is not implemented yet, so right now it looks
+ pretty but doesn't do anything. The plan is to add similar
+ support for AX.25 kernel interfaces. Regular serial TNC
+ interfaces and NET interfaces don't need this capability. For
+ regular serial TNC's RELAY digipeating is turned on/off in the
+ config file for that interface.
+
+2002-07-18 13:01 we7u
+
+ * help/help-English.dat: Removed the serial port settings from the
+ Serial KISS TNC descriptions. The port is set to 8N1 by default
+ now and cannot be changed.
+
+2002-07-18 12:59 we7u
+
+ * src/interface_gui.c: Changed interface properties dialog when
+ dealing with Serial KISS TNC interfaces: No longer is the user
+ presented with serial parameter choices which are not allowed to
+ be changed anyway.
+
+2002-07-18 12:39 we7u
+
+ * help/help-English.dat: Changed KISS interface description to
+ agree with the code, which forces the N81 option for serial port
+ parameters now.
+
+2002-07-18 12:37 we7u
+
+ * src/interface_gui.c: Forcing KISS interfaces to N81 for the
+ serial port parameters.
+
+2002-07-18 12:17 we7u
+
+ * help/help-English.dat: Just spelling fixes.
+
+2002-07-18 12:14 we7u
+
+ * help/help-English.dat: A few minor additions/corrections to the
+ KISS, TNC, and AX.25 interface descriptions.
+
+2002-07-18 12:04 we7u
+
+ * src/interface.c: Added some locks where a few were missing.
+ Added code to send the KISS parameters down to the TNC when the
+ port is first opened.
+
+2002-07-18 10:45 rzg
+
+ * help/help-English.dat: Updates for serial KISS TNC, message
+ paths, igate paths, and more..
+
+2002-07-18 09:31 we7u
+
+ * src/: db.c, db.h, interface.c, interface.h, interface_gui.c,
+ main.c, messages_gui.c: Reorganized KISS parameter widgets in the
+ dialog. Changed to string,length instead of relying on the
+ terminating zero in the string for transmitting strings. This is
+ due to the fact that KISS packets can have 0x00 in them as data.
+ Fixed the problems with non-posit packet transmission and the
+ Serial KISS TNC interface.
+
+2002-07-17 18:01 we7u
+
+ * src/: interface.c, interface.h, interface_gui.c, xa_config.c:
+ Added kiss parameters to the properties dialog.
+
+2002-07-17 16:17 we7u
+
+ * src/main.c: Better behaved positioning of dialogs. They won't
+ get positioned quite as far down the screen now.
+
+2002-07-17 16:06 we7u
+
+ * src/igate.c: Reformatted all of the igating routines. Added a
+ specific check so that we don't re-inject TCPIP or TCPXX packets
+ back into the internet (we don't want looping). The routines are
+ much more understandable now and should be easier to maintain.
+
+2002-07-17 13:54 we7u
+
+ * src/interface.c: Changed/added comments. Deleted the section of
+ code in port_read() that looked for AX.25 flag characters, as
+ KISS packets should not normally contain them. We instead will
+ try breaking apart the KISS packets based on \n and \r
+ characters.
+
+2002-07-17 13:05 we7u
+
+ * src/: db.c, db.h: Changing to unsigned char for one parameter so
+ that we can check all eight bits of each char.
+
+2002-07-17 13:01 we7u
+
+ * src/db.c: Lots of comment changes. Added check code to the
+ decoding functions to look for and correct concatenated KISS
+ packets. Currently the tacked-on packets will get deleted. This
+ should get fixed in later revisions.
+
+2002-07-17 12:25 we7u
+
+ * src/interface.c: Reformatted, changed/added comments. No code
+ changes.
+
+2002-07-17 02:04 we7u
+
+ * src/interface.c: Initial code to implement Serial KISS TNC
+ transmit.
+
+2002-07-16 17:00 we7u
+
+ * src/interface.c: More preparation for doing KISS TNC transmit.
+ Not finished yet.
+
+2002-07-16 15:33 we7u
+
+ * src/interface.c: Tweak to check for NULL in igate_path. Lot's of
+ comment changes.
+
+2002-07-16 14:32 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface_gui.c: Fixed language
+ string for KISS TNC dialog. Added comments.
+
+2002-07-16 14:09 we7u
+
+ * src/interface.c: A few more small tweaks to help with closing
+ Serial KISS TNC interfaces.
+
+2002-07-16 11:26 we7u
+
+ * src/db.c: Added some comments.
+
+2002-07-16 09:47 we7u
+
+ * src/: db.c, db.h, interface.c, interface_gui.c, main.c: Initial
+ implementation of Serial KISS TNC support. This one is
+ receive-only. Still have to write the code to generate the
+ outgoing AX.25 header for transmitting. This one may be unstable
+ yet, but the instability should only affect Xastir instances with
+ this port enabled.
+
+2002-07-15 16:25 we7u
+
+ * src/interface.c: Commented out some debugging code.
+
+2002-07-15 16:24 we7u
+
+ * src/: igate.c, interface.h, interface_gui.c, xa_config.c, main.c,
+ interface.c: The start of code to implement serial port KISS tnc
+ functionality (without using kernel-mode AX.25 ports). Not
+ functional yet.
+
+2002-07-15 16:03 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Just starting to
+ add Serial KISS TNC capability. Not functional yet.
+
+2002-07-15 01:02 we7u
+
+ * src/interface.c: Fixed one problem with igate_path. Added a
+ bunch of comments, reformatted some code, changed some variable
+ names.
+
+2002-07-13 10:38 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/igate.c,
+ src/interface.c, src/interface.h, src/main.c, src/messages.c,
+ src/messages.h, src/messages_gui.c, src/wx.c, src/xastir.h:
+ Implemented reverse path for messaging. Xastir now tries to
+ figure out a reasonable return path when doing messaging.
+
+2002-07-12 16:59 we7u
+
+ * src/messages_gui.c: Adding some code in preparation for setting
+ up individual return paths for messaging. This code figures out
+ the return path from the last path received for that station,
+ including dropping "RELAY" callsigns and asterisks and converting
+ WIDEn-N callsigns to their original glory. Converts TRACE and
+ TRACEn-N callsigns to WIDE and WIDEn-N as well.
+
+2002-07-12 14:09 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/igate.c,
+ src/interface.c, src/interface.h, src/interface_gui.c,
+ src/main.c, src/messages.c, src/wx.c, src/xa_config.c:
+ Implemented separate unproto path for igating. Change it via the
+ properties dialog for affected interfaces. If nothing entered,
+ it will round-robin between the other three interfaces or select
+ a default path.
+
+2002-07-12 12:15 we7u
+
+ * src/db.c: Now have red circle around tracked station.
+
+2002-07-12 11:08 we7u
+
+ * src/: db.c, main.c: Added Maidenhead Grid Locator output to the
+ Coordinate Calculator.
+
+2002-07-12 09:52 we7u
+
+ * src/main.c: Added mnemonics keys to the right mouse button menu.
+ Now if you select it via the Maps menu you can still navigate
+ through it via keyboard. Note that some of the options won't
+ work properly without a mouse pointer pointing to an object on
+ the screen, like Station Info. For those options needing to snag
+ the mouse pointer, it appears to use whatever point the mouse
+ pointer is on (as usual). If the pointer is outside the drawing
+ area, all bets are off.
+
+2002-07-11 17:20 we7u
+
+ * src/db.c: Proper rounding of course when saving track data.
+
+2002-07-11 16:54 we7u
+
+ * src/db.c: Tweaking altitude/speed/course displays to skip over
+ the first trackpoint, which is the same as our current data. We
+ now look at the next oldest trackpoint to try to pull out
+ slightly older data for display purposes.
+
+2002-07-11 16:31 we7u
+
+ * help/help-English.dat: A few changes to the SmartBeaconing
+ parameter descriptions.
+
+2002-07-11 16:22 we7u
+
+ * src/db.c: Decoupling speed/course from each other for display
+ purposes.
+
+2002-07-11 16:10 we7u
+
+ * src/util.c: Reducing PHG circles by 1/2, per Bob Bruninga's
+ recommendations.
+
+2002-07-11 15:46 we7u
+
+ * src/db.c: Skipping first tracklog entry when filling in the
+ Station Info dialog. It's the same as the first line or "Last
+ Position".
+
+2002-07-11 15:07 we7u
+
+ * src/util.c: Small change to valid_path() to allow "qAC" and
+ similar q-codes to pass through. This is a new addition from
+ Dale Heatherington to the aprsd server for anti-looping purposes.
+
+2002-07-11 14:45 we7u
+
+ * src/db.c: Changed minimum length check for GGA/RMC strings and
+ put one debug message inside debug_level logic.
+
+2002-07-11 14:36 we7u
+
+ * src/db.c: More general code for parsing RMC and GGA sentences.
+ Now allows any number of digits after the decimal point for the
+ lat/long fields.
+
+2002-07-11 12:51 we7u
+
+ * src/db.c: Tweak to make bad Mic-E positions not draw tracks.
+
+2002-07-11 09:03 rzg
+
+ * help/help-English.dat: Updates to new features list, added
+ smartbeaconing help, other minor stuff.
+
+2002-07-09 15:38 we7u
+
+ * src/db.c: Expire code for trackpoints. Currently uses the
+ station expire variable for choosing when to expire each
+ trackpoint. Called from draw_trail() for each station.
+
+2002-07-09 14:12 we7u
+
+ * src/maps.c: Now outputs warning messages for Shapefile maps that
+ have bad lat/lon values. This lets the user know which map files
+ or which shapes within the file have problems.
+
+2002-07-09 13:00 we7u
+
+ * src/interface.c: Searching for excessively long packets earlier
+ in the process. Now we drop them on the floor before the decode
+ routines.
+
+2002-07-09 11:12 we7u
+
+ * src/db.c: Tweaked a debug line to output more data.
+
+2002-07-09 10:55 we7u
+
+ * src/: db.c, gps.c, interface.c, interface.h, main.c, util.c,
+ wx.c: String lengths can be MAX_DEVICE_BUFFER length, currently
+ defined to be 4096 characters, when going into the decode
+ routines. These are fixes to handle these long line lengths in a
+ graceful manner.
+
+2002-07-08 20:17 rzg
+
+ * src/db.c: Moving a newline in debugging code so it won't get
+ lost.
+
+2002-07-08 18:02 kd6zwr
+
+ * src/maps.c: One more GNIS icon - parks.
+
+2002-07-08 15:43 we7u
+
+ * src/: alert.c, db.c, draw_symbols.c, interface.c, main.c, maps.c,
+ messages.c, view_message_gui.c: Changing a bunch of comments.
+ Mostly removing "we7u" bookmarks.
+
+2002-07-07 18:30 rzg
+
+ * README.1ST: Weather shapefiles are moving...
+
+2002-07-04 11:26 we7u
+
+ * src/: db.c, db.h, list_gui.c: Changes which implement
+ dynamically-allocated tracklogs. Expiration and function which
+ writes track to file need to be worked on yet.
+
+2002-07-03 23:28 we7u
+
+ * src/db.c: Slight reformatting and added a few comments. No real
+ code changes.
+
+2002-07-03 17:03 we7u
+
+ * src/db.c: Commenting out some debug statements.
+
+2002-07-03 16:59 we7u
+
+ * src/db.c: Added a few comments.
+
+2002-07-03 16:46 we7u
+
+ * src/db.c: Found that the first trackpoint was getting skipped
+ when displaying in Station Info dialog. Fixed it. We also now
+ look in the first tracklog point for course/speed/altitude if any
+ of these parameters are missing in the current data. Found other
+ problems in tracklog indexing in db.c that need to be fixed yet.
+
+2002-07-03 12:16 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c, src/main.h,
+ src/maps.c, src/xa_config.c: Added a new togglebutton that
+ enables bulletin popup for new bulletins. Moved the smartbeacon
+ enable button to its dialog.
+
+2002-07-03 11:22 we7u
+
+ * src/db.c: Reverting back to old Bulletin method for now. New
+ method doesn't work right if bulletin received w/no posit, then
+ posit is received later.
+
+2002-07-03 11:14 we7u
+
+ * README.1ST: Added a blurb about LD_LIBRARY_PATH variable being
+ ignored when running Xastir as SUID root.
+
+2002-07-03 11:10 we7u
+
+ * src/: bulletin_gui.c, db.c: Fixed bulletins so that they don't
+ pop up if distance is zero, unless the range setting is set to
+ zero. It was getting much too annoying the other way when
+ connected to a cached network feed. With the new code these
+ things will cause bulletins to pop up: Distance non-zero and
+ within range setting. Range setting set to zero. The user can
+ also bring up the View->Bulletins dialog and it will still show
+ the zero-range bulletins in any case.
+
+2002-07-03 09:09 francais1
+
+ * src/maps.c: Applied, slightly tweaked and tested patch from
+ Derrick Brashear which adds support for different PHOTOMETRIC
+ geotiffs.
+
+2002-07-02 16:25 we7u
+
+ * src/: db.c, util.c, util.h: Added Maidenhead grid locators to
+ Station Info dialog. Code by dl9sau which was derived from
+ Wampes util/qth.c code by dk5sg.
+
+2002-07-02 14:31 we7u
+
+ * src/maps.c: Added more detailed debug messages for the case where
+ lat/lon to be converted is outside the proper ranges.
+
+2002-07-02 14:30 we7u
+
+ * src/alert.c: Quieting some debug messages having to do with
+ compressed weather alerts (which aren't implemented yet).
+
+2002-07-02 12:40 we7u
+
+ * src/main.c: Tweaked TigerMap config dialog so that strings in
+ different languages would cause a resize of the dialog, and the
+ dialog would be smaller/easier to use with smaller screen
+ resolutions.
+
+2002-07-02 11:10 n0vh
+
+ * src/: main.c, maps.c, xa_config.c, xastir.h: Added code to allow
+ the user to set the timeout for getting tigermaps from the menu.
+
+2002-06-28 14:03 we7u
+
+ * src/maps.c: Patch for corrupt fgd files by Derrick J Brashear.
+
+2002-06-28 13:44 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/db.h: Separated out
+ storage and display of comments/status.
+
+2002-06-28 11:18 we7u
+
+ * src/maps.c: Added an 'X' symbol and a nicely-drawn label for
+ waypoing shapefiles.
+
+2002-06-28 10:47 we7u
+
+ * src/maps.c: Changes to make waypoint Shapefiles appear properly
+ in Xastir.
+
+2002-06-27 20:30 n0vh
+
+ * src/main.c: More minor updates.
+
+2002-06-27 20:21 n0vh
+
+ * src/: main.c, track_gui.c: Clean up some of the tigermap menu
+ items and reformatted them.
+
+2002-06-27 13:12 we7u
+
+ * README.1ST: Added notes regarding ld.so.cache to the Shapelib
+ section.
+
+2002-06-26 10:34 we7u
+
+ * src/maps.c: Fix for missing IMAGESIZE tag in .geo file: We
+ output an error message and skip loading that file. Someday we
+ may wish to try to find out the imagesize via calls to the
+ imagemagick or xpm libraries.
+
+2002-06-26 09:46 we7u
+
+ * src/db.c: Bulletins no longer cause a refresh of the Send Message
+ dialogs.
+
+2002-06-26 08:50 francais1
+
+ * src/: list_gui.c, list_gui.h, xa_config.c: Added a number of
+ lists definition to the end of the list number definitions so
+ that the code doesn't need touching every time you add a new
+ list. Moved list number definitions to list_gui.h so that I can
+ see them from xa_config.c.
+
+2002-06-25 17:20 we7u
+
+ * src/db.h: Added a line for is_my_call().
+
+2002-06-25 17:13 we7u
+
+ * src/: list_gui.c, main.c, xa_config.c: New list for viewing
+ objects/items that we own.
+
+2002-06-25 17:12 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: New strings for
+ new list.
+
+2002-06-25 16:45 we7u
+
+ * help/help-English.dat: Spelling.
+
+2002-06-25 16:28 rzg
+
+ * help/help-English.dat: Updated helpfile for recent changes.
+
+2002-06-25 15:03 we7u
+
+ * src/: bulletin_gui.c, bulletin_gui.h, db.c: Fixes for annoying
+ bulletins. It should only pop up the bulletin dialog now when
+ new bulletins come in that are within range. It's possible to
+ receive a bulletin without having a posit from that station, then
+ get a posit, making it outside the range. In this case you may
+ get a popup without knowing why. It's better than what it was
+ doing before though.
+
+2002-06-25 12:41 we7u
+
+ * src/: list_gui.c, main.c, xa_config.c: Added "View->Objects &
+ Items" list.
+
+2002-06-25 12:33 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Added string for
+ new View->Objects & Items dialog.
+
+2002-06-24 15:40 we7u
+
+ * src/draw_symbols.c: Changed DF beam-heading objects to draw in
+ red3. Using stippling the lines were not visible on some map
+ backgrounds. Also narrowed the lines for pod_circles (not fully
+ implemented yet).
+
+2002-06-24 12:28 we7u
+
+ * src/main.c: Added comments. No code changes.
+
+2002-06-24 12:27 we7u
+
+ * config/language-Portuguese.sys: Updates by David Quental, CT1DRB.
+ Thanks!
+
+2002-06-22 11:01 n0vh
+
+ * src/track_gui.c: Update GUI so that the length of the track
+ downloaded from FINDU can be selected.
+
+2002-06-21 20:28 n0vh
+
+ * src/maps.c: Commented all the findu code out from maps.c since
+ it's now done from track_gui.c. It will be removed in the
+ future.
+
+2002-06-21 14:20 we7u
+
+ * src/: draw_symbols.c, draw_symbols.h: Added draw_pod_circle()
+ function. It has yet to be tied to a GUI anywhere.
+
+2002-06-21 12:36 we7u
+
+ * src/db.c: Added some comments.
+
+2002-06-21 12:36 we7u
+
+ * src/util.c: Added a comment.
+
+2002-06-21 12:21 we7u
+
+ * src/db.c: Leave my_last_speed in knots so it is consistent
+ throughout the code.
+
+2002-06-21 12:18 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Converted more strings
+ to use langcode().
+
+2002-06-21 12:17 we7u
+
+ * src/interface.c: Added some comments.
+
+2002-06-21 12:15 we7u
+
+ * src/gps.c: Added a commented-out debug statement.
+
+2002-06-21 12:15 we7u
+
+ * src/: draw_symbols.c, main.h: Added a comment.
+
+2002-06-21 07:49 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Converted Coordinate
+ Calculator to use langcode() strings.
+
+2002-06-21 07:35 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Added langcode() strings
+ for the new Configure->SmartBeaconing dialog.
+
+2002-06-21 07:02 we7u
+
+ * src/main.c: Initial GUI for setting SmartBeaconing parameters.
+
+2002-06-20 15:41 we7u
+
+ * src/main.c: Adding bearing degrees to the Measure function.
+
+2002-06-20 15:23 we7u
+
+ * src/bulletin_gui.c: We now create the View->Bulletins dialog when
+ bulletins come in.
+
+2002-06-20 14:01 we7u
+
+ * src/: igate.c, interface.c, messages.c: Added/modified some
+ comments.
+
+2002-06-20 12:47 we7u
+
+ * src/interface.c: Added a 250ms delay after writing each waypoint.
+
+2002-06-20 10:44 we7u
+
+ * src/gps.c: Added some notes to the waypoint creation routine.
+
+2002-06-20 10:36 we7u
+
+ * src/gps.c: Fixed problem with lower-case characters when creating
+ waypoints.
+
+2002-06-19 17:17 we7u
+
+ * src/: db.c, gps.c, gps.h, interface.c, interface.h: For those of
+ you with Garmin GPS units: Set up the audio proximity alarm
+ range for some distance around your station and Xastir will now
+ create waypoints for each APRS station/object/item that it hears
+ within that range. They'll appear on your Garmin map display as
+ waypoints. Enjoy! You can delete the waypoints by type. They
+ appear as the circle with the 'X' in the middle. You may want to
+ change other waypoints to some other type before you play with
+ this new Xastir feature.
+
+2002-06-19 10:53 we7u
+
+ * src/db.c: Fixed remove_leading_spaces() as it didn't work at all
+ as coded. It liked to truncate after the first word. Also fixed
+ some malloc sizes added recently.
+
+2002-06-19 10:44 francais1
+
+ * src/db.c: strlen, not sizeof
+
+2002-06-18 17:06 we7u
+
+ * src/: db.c, db.h, list_gui.c: Additional memory savings for the
+ node_path variable in the station database. Changed it to a
+ pointer and allocate exact space for the string when stored or
+ updated.
+
+2002-06-18 16:19 we7u
+
+ * src/: db.c, db.h, list_gui.c, main.c: More space savings. Turned
+ comment into a pointer in the station record and allocate just
+ the space we need for it.
+
+2002-06-18 15:21 we7u
+
+ * src/: db.c, db.h, list_gui.c, main.c: Changed to
+ dynamically-allocated linked list of comment strings in the
+ station database. This results in memory savings due to no empty
+ strings being stored for stations without comment fields. It
+ also shows all status and comment strings that have been seen for
+ each station now in the Station Info dialog. We'll have loads of
+ fun tracking MIC-E expansion on the internet servers now!
+
+2002-06-18 11:55 we7u
+
+ * src/draw_symbols.c: Simplifying the logic a bit. Same general
+ idea.
+
+2002-06-18 11:13 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c: Added "(tm)"
+ everywhere "SmartBeaconing" was listed.
+
+2002-06-18 11:07 we7u
+
+ * AUTHORS, README.1ST: Notes and credit for the SmartBeaconing(tm)
+ algorithm added.
+
+2002-06-18 10:58 we7u
+
+ * src/db.c: Changes to comments only.
+
+2002-06-18 10:35 we7u
+
+ * src/: db.c, draw_symbols.c: Changed they symbol time-since-heard
+ color to white if over 24 hours. Added a bunch of comments for
+ SmartBeaconing.
+
+2002-06-17 16:16 we7u
+
+ * src/db.c: Minor comment change.
+
+2002-06-17 15:13 we7u
+
+ * src/: db.c, main.c: Commenting out debug printf's. Changed some
+ other comments.
+
+2002-06-17 14:40 we7u
+
+ * src/db.c: More comments. Another tweak to SmartBeaconing: If
+ we've sped up a bit the code will now bring the next beacon in
+ closer (in time), instead of waiting for the next slow beacon to
+ reset to the slower interval.
+
+2002-06-17 14:16 we7u
+
+ * src/db.c: Added a few SmartBeaconing comments.
+
+2002-06-17 13:11 we7u
+
+ * src/: db.c, main.c: Another few SmartBeaconing tweaks. Setting
+ defaults for variables to prevent multiple beacons as we get
+ started.
+
+2002-06-17 12:19 we7u
+
+ * src/: db.c, main.c: A few SmartBeaconing tweaks. Commented out
+ the experimental SmartBeaconing tweaks that caused a beacon when
+ entering/exiting stop mode. Changed how other SmartBeaconing
+ math was done.
+
+2002-06-17 11:42 we7u
+
+ * src/draw_symbols.c: Added color-coding for time-since-last-heard
+ display. Green for 0-29 mins, Yellow for 30-59 minutes, Red for
+ 60 mins to infinity. This is to help keep track of which
+ stations are active and which haven't been heard for a while.
+
+2002-06-17 10:16 we7u
+
+ * src/db.c: Moved the "reversed symbol" message into a debug level.
+
+2002-06-14 17:19 we7u
+
+ * src/xa_config.c: Tweaking SmartBeaconing defaults to something
+ more reasonable.
+
+2002-06-14 15:51 we7u
+
+ * src/xa_config.c: Saving SmartBeaconing parameters (all 7) in the
+ config file.
+
+2002-06-14 15:28 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c, src/xa_config.c: Added
+ Enable SmartBeaconing togglebutton, language strings for it, and
+ save its state in the config file. More to do.
+
+2002-06-14 14:15 we7u
+
+ * src/: db.c, main.c, main.h: The beginnings of SmartBeaconing
+ support. The working code is in there but the GUI interface is
+ not coded yet.
+
+2002-06-14 10:58 we7u
+
+ * src/draw_symbols.c: Changed "time since last report" display to
+ show "hr" and "min" based on time.
+
+2002-06-13 16:42 we7u
+
+ * src/db.c: Fix for compressed object/item comments getting eaten.
+
+2002-06-13 15:53 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/draw_symbols.c,
+ src/draw_symbols.h, src/main.c, src/main.h, src/xa_config.c:
+ Added "Display Last Report Time" option to stations menu.
+
+2002-06-13 14:07 we7u
+
+ * src/db.c: Final fix for trail expiring on active objects/items.
+
+2002-06-13 12:22 we7u
+
+ * src/db.c: Fixes which check for locally controlled object/item
+ which has moved. If it has, update the time-sorting of the
+ record and update the timestamp in the station record. This
+ should fix the problem where an expired object, when moved, stays
+ ghosted.
+
+2002-06-13 11:47 we7u
+
+ * src/messages_gui.c: Making Send Message dialog wide enough so
+ that spec-compliant-length messages won't wrap to a new line.
+
+2002-06-13 11:21 we7u
+
+ * src/: alert.c, maps.c: Converting a few more snprintf's to
+ xastir_snprintf's. This change is necessary for those systems
+ that don't have snprintf in their libraries.
+
+2002-06-12 17:12 we7u
+
+ * src/db.c: Added some notes regarding expiration of objects.
+
+2002-06-12 16:29 we7u
+
+ * src/: db.c, main.c, util.c: More fixes for compressed
+ objects/items. Speed/course seem to be working now.
+
+2002-06-12 16:23 we7u
+
+ * help/help-English.dat: Minor changes regarding compressed
+ objects/items.
+
+2002-06-12 15:57 rzg
+
+ * help/help-English.dat: Updates wrt. compressed objects/posits,
+ and satellite ack mode.
+
+2002-06-12 14:52 we7u
+
+ * src/: db.c, main.c, util.c: A few fixes for compressed position
+ objects/items. Adding course/speed to compressed objects/items
+ as well.
+
+2002-06-10 17:08 we7u
+
+ * src/main.c: A minor tweak the position ambiguity togglebuttons
+ having to do with switching compressed mode on and off.
+
+2002-06-10 16:52 we7u
+
+ * src/db.c: Disabling position ambiguity on receive end if a
+ compressed posit is received for that station.
+
+2002-06-10 16:46 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c, src/main.h,
+ src/xa_config.c: Moved the compressed_posit togglebutton to the
+ Configure->Station dialog. Added a compress_objects_items
+ togglebutton to the Configure->Defaults dialog.
+
+2002-06-10 15:02 we7u
+
+ * src/main.c: Fixes to give increased resolution for lat/lon when
+ using compressed packets for objects/items.
+
+2002-06-10 14:43 we7u
+
+ * src/: db.c, util.c: Fixed compressed positions so that we can
+ take advantage of the higher resolution.
+
+2002-06-08 12:05 n0vh
+
+ * src/xa_config.c: Added some missing #ifdef statements for
+ tigermap data in the config file
+
+2002-06-07 18:34 we7u
+
+ * src/: db.c, main.c: Initial support for transmitting
+ objects/items with compressed positions. They're not displaying
+ in the proper positions on the map yet though.
+
+2002-06-07 13:48 we7u
+
+ * src/interface.c: Added debugging into to interface.c. Changed
+ the way that we run through all interfaces when transmitting.
+
+2002-06-07 13:42 we7u
+
+ * src/util.c: Added support for lat/lon string conversions where we
+ have more digits after the decimal point.
+
+2002-06-07 11:10 we7u
+
+ * src/: db.c, xastir.h: Bring up Locate Station window if an
+ Emergency message is received. The operator has a choice whether
+ to center on the station or just dismiss the dialog.
+
+2002-06-07 09:48 n0vh
+
+ * src/main.c: Load Tigermaps prior to disk maps so disk maps can be
+ overlayed if desired.
+
+2002-06-07 08:52 n0vh
+
+ * src/main.c: Disable all maps now also functions with new
+ TigerMaps routines.
+
+2002-06-06 18:40 n0vh
+
+ * src/maps.c: More code cleanup in the tigermap section. Still
+ some optimizations to go.
+
+2002-06-06 18:12 n0vh
+
+ * src/xa_config.c: Updated to save the tiger_flag and
+ tigermap_intensity in the users config file.
+
+2002-06-06 17:02 we7u
+
+ * src/db.c: Added a popup dialog for MIC-E emergency messages.
+ Displays the callsign of the station in trouble.
+
+2002-06-06 15:03 we7u
+
+ * src/: messages.c, xa_config.c: Moved range checking for
+ message_counter to xa_config. More efficient. Only needs to be
+ done once when starting up.
+
+2002-06-06 14:45 we7u
+
+ * src/: messages.c, xa_config.c, xastir.h: Converted
+ message_counter to a string. Changed message sequence numbers to
+ be 2 characters within this range: 0-9A-Za-z. This prevents
+ lockups when messaging with APRS+ stations.
+
+2002-06-06 14:43 we7u
+
+ * src/db.c: Removed old code.
+
+2002-06-06 11:00 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/db.c, src/main.c, src/xastir.h:
+ Implemented satellite ack mode, where the Reply/Ack protocol is
+ used to send ack's through satellites, and ack's like "ack001"
+ are disabled entirely.
+
+2002-06-06 10:03 we7u
+
+ * src/: db.c, db.h, messages.c: Changes which implement full
+ Reply/Ack protocol. This should speed up messaging dramatically
+ when involved in live QSO's with the APRS programs that support
+ this protocol. This lists currently includes aprsDOS, APRS+, and
+ Xastir.
+
+2002-06-05 13:28 we7u
+
+ * src/: db.c, db.h, messages.c: Marking timed-out messages in Send
+ Message dialog properly. Small changes to Reply/Ack sequence
+ numbers.
+
+2002-06-04 16:13 we7u
+
+ * src/: messages.c, xa_config.c: Switching to base-90 for message
+ sequence numbers (all the way to lower-case 'z'). Also tweaked
+ xa_config.c to help us avoid the message_counter rollover
+ problem.
+
+2002-06-04 15:47 we7u
+
+ * src/messages.c: Changed from base-91 to base-89 format for
+ message sequence numbers. This is to avoid use of the '{'
+ character within the sequence.
+
+2002-06-04 15:25 we7u
+
+ * src/messages.c: Converted outgoing sequence numbers to
+ 2-character base-91 encoding. Added a trailing '}' character to
+ signify that we're Reply-Ack protocol capable.
+
+2002-06-04 14:32 we7u
+
+ * src/messages.c: Had to take out the '}' from the sequence number
+ as it messed things up.
+
+2002-06-04 14:20 we7u
+
+ * src/: db.c, messages.c: Message sequence numbers are saved
+ through restarts now. Added more comments.
+
+2002-06-04 13:27 we7u
+
+ * src/db.c: Changed several comments. Decoding of Reply/Ack
+ protocol (free-ride ACK's) is now tested and working. This
+ really speeds up live messaging. When encoding of the free-ride
+ ACK's is implemented as well it'll speed up messaging even more.
+
+2002-06-03 17:50 rzg
+
+ * README.1ST, help/help-English.dat: Updates for tigermap changes
+ and minor bits I missed in the previous update.
+
+2002-06-03 13:30 we7u
+
+ * src/db.c: Minor changes to Reply/Ack's.
+
+2002-06-03 13:14 we7u
+
+ * src/db.c: The beginnings of Reply/Ack protocol decode. Not fully
+ tested. Encode not implemented yet.
+
+2002-06-03 09:45 francais1
+
+ * src/maps.c: Fixed up imagemagick_options struct a bit. Removed
+ some imagemagick_options stuff from draw_tiger_map because it is
+ not being setup since there is no .geo file. Fixed
+ draw_tiger_map intensity/levels bug.
+
+2002-06-03 09:21 we7u
+
+ * src/maps.c: Changing some line widths and colors back to what we
+ had before the weekend. We're not trying to duplicate the
+ TigerMap servers colors or look-and-feel. We need more subdued
+ colors so that symbols and tracks show up better on top of the
+ maps. The line widths are necessary in order to more quickly
+ identify major roads without having to rely only on color.
+
+2002-06-03 09:18 francais1
+
+ * src/maps.c: Removed extraneous ifdef
+
+2002-06-03 08:38 we7u
+
+ * src/gps.c: Fixes for decoding GPS NMEA sentences where there are
+ 4 digits after the decimal point. Garmin GPS-35 and the NavMan
+ both put out an extra digit.
+
+2002-06-03 07:59 we7u
+
+ * src/main.c: Fixed segfault bug in Config_tiger.
+
+2002-06-03 07:23 we7u
+
+ * src/maps.c: Added another #ifdef around a LevelImage() call.
+
+2002-06-02 14:59 n0vh
+
+ * config/language-English.sys, config/language-French.sys,
+ config/language-German.sys, config/language-Italian.sys,
+ config/language-Portuguese.sys, config/language-Spanish.sys,
+ src/main.c, src/main.h, src/maps.c, src/xastir.h: Made more
+ updates to support tigermap menu item. A file is no longer
+ required. Also, I made display of tigermaps a separate
+ subroutine. This should probably be done with some of the other
+ items in draw_geo_image_map as well. N0VH
+
+2002-06-02 14:54 n0vh
+
+ * config/language-Dutch.sys: Made more updates to support tigermap
+ menu item. A file is no longer required. Also, I made display
+ of tigermaps a separate subroutine. This should probably be done
+ with some of the other items in draw_geo_image_map as well. N0VH
+
+2002-06-01 12:00 n0vh
+
+ * src/: main.c, maps.c: Added Tigermap menu support.
+
+2002-06-01 11:59 n0vh
+
+ * src/xastir.h: Added some external vars to support Tigermap menus.
+
+2002-06-01 11:54 n0vh
+
+ * config/language-Spanish.sys: Added items to support Tigermap
+ menus.
+
+2002-06-01 11:52 n0vh
+
+ * config/language-Italian.sys: Added items to support Tigermap
+ menu.
+
+2002-06-01 11:50 n0vh
+
+ * config/: language-French.sys, language-German.sys,
+ language-Portuguese.sys: Added items to support Tigermap menus.
+
+2002-06-01 11:49 n0vh
+
+ * config/language-English.sys: Added items to support Tigermap
+ configuration menus.
+
+2002-06-01 11:47 n0vh
+
+ * config/language-Dutch.sys: Added new lines to support the
+ Tigermap configuration menus.
+
+2002-06-01 11:46 n0vh
+
+ * README.1ST: Removed reference to putting TIGERMAP in a .geo file
+ which no longer works.
+
+2002-05-31 17:32 we7u
+
+ * src/db.c: Initial attempt to handle Reply/Ack messaging protocol
+ (on the receive side only). Only implemented for APRS messaging,
+ not UI-View messaging.
+
+2002-05-31 14:24 we7u
+
+ * src/db.c: Fixes for last_ack timer. We now refuse to send ack's
+ or auto_answer messages any faster than every 30 seconds, even if
+ multiple interfaces are sending us copies of the same message.
+
+2002-05-31 12:36 we7u
+
+ * src/maps.c: Simplified the print properties dialog. Commented
+ out unused options.
+
+2002-05-30 08:04 n0vh
+
+ * src/igate.c: More cleanup of the status messages written to the
+ console.
+
+2002-05-29 21:32 n0vh
+
+ * src/igate.c: Cleaned up some of the status messages by adding a
+ newline to the end.
+
+2002-05-29 17:07 francais1
+
+ * src/maps.c: Imagemagick drawing speedup for some cases.
+
+2002-05-29 16:59 francais1
+
+ * src/: util.c, util.h: Added a simple function to roughly time
+ code execution.
+
+2002-05-28 09:48 we7u
+
+ * src/xa_config.c: Patch for incorrect lat/long limits by Henk de
+ Groot, PE1DNN. Thanks Henk!
+
+2002-05-24 17:07 we7u
+
+ * src/: db.c, db.h: Attempting to get rid of duplicate ack's and
+ autoreply messages. This attempt is at least partially
+ successful.
+
+2002-05-24 15:01 we7u
+
+ * src/: db.c, util.c: Fixed spelling error in util.c. Fixes for
+ incorrect sorting in Send Message window for the case where the
+ remote client has restarted and is re-using sequence numbers:
+ Xastir will now replace the older messages in the database and
+ update the timestamp, which keeps the proper ordering for a QSO.
+ Messages older than 8 hours with the same text will also get
+ replaced and get a new timestamp.
+
+2002-05-22 14:05 we7u
+
+ * src/: gps.c, interface.c, interface_gui.c, xa_config.c: Mods for
+ CYGWIN by Charles Suprin, AA1VS.
+
+2002-05-21 14:33 we7u
+
+ * src/db.c: Getting rid of unneeded extra message_update() calls.
+
+2002-05-21 12:27 we7u
+
+ * src/db.c: More messaging fixes.
+
+2002-05-21 12:02 we7u
+
+ * src/: messages_gui.c, db.c: Fixes for text corruption in Send
+ Message window. Needs further testing.
+
+2002-05-21 10:19 we7u
+
+ * src/: util.c, view_message_gui.c: Fixing distance calculation
+ such that it returns 0.0 if we haven't heard a posit from the
+ remote station yet.
+
+2002-05-21 09:18 we7u
+
+ * src/view_message_gui.c: View->Messages history dump now obeys the
+ distance limit set at the top of the form.
+
+2002-05-20 14:49 we7u
+
+ * src/: view_message_gui.c, xa_config.c: We now dump all currently
+ active messages out to the view->messages window when it's first
+ opened. Different format, but still useful. The format is
+ easily tweaked later. Also changed the default
+ VIEW_MESSAGE_LIMIT to 10000. This can be tweaked by the user in
+ the ~/.xastir/xastir.cnf file. Max allowed by the code is now
+ 99999.
+
+2002-05-18 00:06 kd6zwr
+
+ * src/maps.c: Draw symbols for GNIS files.
+
+2002-05-17 16:55 we7u
+
+ * src/interface.c: Temporary fix for CYGWIN. Disables use of HSP
+ adapter. Better fix needs to be implemented.
+
+2002-05-17 16:52 we7u
+
+ * src/interface_gui.c: Mods for CYGWIN.
+
+2002-05-17 15:56 we7u
+
+ * src/: main.c, messages_gui.c: Added <Enter> as another method to
+ send a message in the Send Message dialog.
+
+2002-05-17 15:26 we7u
+
+ * src/db.c: Quick check for a zero time in the message database.
+ If found, fill in with current time and print out a warning.
+
+2002-05-17 14:14 we7u
+
+ * src/db.c: Only cause a Send Message dialog update on the first
+ ack. Subsequent ack's cause no update.
+
+2002-05-17 11:37 we7u
+
+ * src/db.c: Update message windows only when the first message or
+ the first ack comes in, or when the message doesn't match the
+ same sequence number message already stored. This helps to
+ reduce flashing of the messages windows due to multiple copies of
+ ack's/messages being received.
+
+2002-05-17 00:01 we7u
+
+ * src/db.c: Changes to eliminate dupes in Send Message dialog.
+ Also changes to keep the message sequence more normal.
+
+2002-05-16 16:29 we7u
+
+ * src/: db.c, interface.c: Fixes for reverse video instantly on
+ sending a message, before it's acked.
+
+2002-05-16 15:35 we7u
+
+ * src/db.c: Messaging fixes. Outstanding packets are now reverse
+ video.
+
+2002-05-16 14:47 we7u
+
+ * src/: db.c, db.h, messages.c: The start of visual indicators for
+ unacked messages. Not completely working yet, but doesn't break
+ functionality either.
+
+2002-05-16 09:38 we7u
+
+ * src/: gps.c, interface_gui.c: Fixes for Mac OS X (no strptime
+ call), and for non-linux systems. The "Set System Clock from GPS
+ Data?" togglebutton should be grey'ed out now for non-linux
+ systems.
+
+2002-05-14 20:26 rzg
+
+ * help/help-English.dat: Updated/rewrote .geo section for n7tap's
+ new additions.
+
+2002-05-14 11:56 francais1
+
+ * src/maps.c: Backed out previous change.
+
+2002-05-14 09:56 n0vh
+
+ * src/maps.c: [no log message]
+
+2002-05-10 17:22 we7u
+
+ * src/messages_gui.c: Allowing multiple messages to be queued up
+ without having to wait for an ack for each one.
+
+2002-05-10 17:21 we7u
+
+ * src/messages.c: Allowing multiple messages to get queued up
+ without having to wait for an ack for each one.
+
+2002-05-10 17:20 we7u
+
+ * src/db.c: Reformatted one line. No code changes.
+
+2002-05-10 15:50 we7u
+
+ * src/: messages.c, messages.h: Slightly better timing of
+ messaging. Also free's up the queue after a message times out.
+ More work to be done.
+
+2002-05-10 15:22 we7u
+
+ * src/db.c: Added some notes about a bug in messaging.
+
+2002-05-10 08:08 francais1
+
+ * src/main.c: Added a missing if defined HAVE_IMAGEMAGICK
+
+2002-05-09 22:59 we7u
+
+ * src/: db.c, main.c, messages.c, messages_gui.c: Messaging in the
+ Send Message dialog are now sorted by time. The window is also
+ resizable now in both directions. The 5-second update of the
+ window has been replaced by code which updates the window
+ whenever new messages arrive.
+
+2002-05-09 16:34 francais1
+
+ * src/maps.c: Fixes for older imagemagick versions.
+
+2002-05-09 15:29 francais1
+
+ * src/: color.c, color.h, main.c, maps.c, maps.h, xa_config.c: Sped
+ up drawing of DirectColor images on a DirectColor screen. It was
+ very slow because it called XAllocColor for every pixel in a
+ jpeg. It now uses saved information on the default display
+ visual to pack the RGB into the correct bits for the pixel. I
+ did this because I was finding some nasty color effects with the
+ image intensity settings. I decided to leave image intensity
+ around for geotiffs, but now use gamma correction from
+ Imagemagick for all other image formats that go through
+ imagemagick. There can now be a gamma setting in each .geo file
+ and there is an overall adjustment which will subtract or add to
+ the individual image gamma. While I was at it, I enabled the
+ ability to specify several of the imagemagick enhancement
+ functions in .geo files.
+
+2002-05-09 14:31 we7u
+
+ * src/main.c: Filling the drawing area with grey right away. Gets
+ rid of garbage that shows up on the screen sometimes when
+ starting Xastir.
+
+2002-05-09 13:28 we7u
+
+ * xastir.spec.in, scripts/Makefile.am, scripts/Makefile.in: Tweaks
+ to make the appropriate scripts get installed in /usr/local/bin,
+ with the appropriate execute permissions.
+
+2002-05-09 13:07 we7u
+
+ * help/help-English.dat: Correcting spelling of "finger".
+
+2002-05-09 13:04 we7u
+
+ * Makefile.am, Makefile.in: Adding the scripts directory as a
+ target of the Makefiles.
+
+2002-05-09 12:58 rzg
+
+ * README, README.1ST, help/help-English.dat: Assorted helpfile
+ updates: point shapefiles, weather stipples, and random work on
+ README.
+
+2002-05-09 12:55 rzg
+
+ * FAQ: Changes "XASTIR" to "Xastir" to match other docs.
+
+2002-05-09 12:34 we7u
+
+ * configure, configure.in, xastir.spec.in: Tweaks to install
+ scripts into /usr/local/xastir/script/ directory.
+
+2002-05-09 12:33 we7u
+
+ * scripts/: Makefile.am, Makefile.in: Adding Makefiles to install
+ scripts into /usr/local/xastir/scripts/ directory.
+
+2002-05-08 13:52 we7u
+
+ * scripts/waypoint-get.pl: Here's the companion script to
+ track-get.pl. This one will snag all of the waypoints out of a
+ Garmin GPS and create an APRS item out of each one. The
+ resulting file can be read in by Xastir as a log file to make the
+ waypoints appear on the map screen.
+
+2002-05-08 12:48 we7u
+
+ * scripts/track-get.pl: Added another message at the end.
+
+2002-05-08 12:38 we7u
+
+ * src/: db.c, main.c, main.h: Fixes for some compiler warnings, by
+ Chris Bell, KD6ZWR.
+
+2002-05-08 12:04 we7u
+
+ * scripts/track-get.pl: New Perl script which can fetch the
+ tracklog from a Garmin GPS, then create a log file which can be
+ read by Xastir. Read in the log file and you'll have a track on
+ Xastir's map screen. Needs tweaks to Xastir in order to view
+ more than 100 points of the track at a time.
+
+2002-05-07 22:45 we7u
+
+ * src/maps.c: GNIS code fixes by Chris Bell, KD6ZWR.
+
+2002-05-07 11:40 we7u
+
+ * src/: main.c, maps.h: Xastir will now do a PNG snapshot every
+ time the "Enable PNG Snapshots" button is re-enabled. This beats
+ waiting 5 minutes for the next snapshot while you're
+ experimenting with things.
+
+2002-05-06 22:19 we7u
+
+ * src/maps.c: First implementation of Point-type Shapefiles. Seems
+ to work fine so far.
+
+2002-05-06 16:04 we7u
+
+ * src/db.c: Reformatting a warning message to make sure that we
+ only output printable chars to STDOUT.
+
+2002-05-06 15:01 we7u
+
+ * src/: db.c, util.c: Fixes for AEA formatted headers. They now
+ should get converted properly to TAPR-2 style headers. What was
+ missing was the re-arranging of the callsigns in the header to
+ the correct order.
+
+2002-05-05 17:53 we7u
+
+ * src/maps.c: Changing default color for pedestrian trails, used if
+ later code doesn't set the color explicitly.
+
+2002-05-04 09:55 we7u
+
+ * src/xa_config.c: Another tweak to limits checking.
+
+2002-05-03 22:38 we7u
+
+ * src/xa_config.c: Tweaking the value limits for list window sizes.
+
+2002-05-03 16:52 we7u
+
+ * src/maps.c: Fixing a segfault for non Tiger-based Shapefiles
+ (like the NOAA interstates file).
+
+2002-05-03 15:58 we7u
+
+ * src/maps.c: Fix for incorrect line colors at times for
+ Shapefiles. We also make city borders narrower as we zoom out.
+
+2002-05-03 15:16 francais1
+
+ * src/list_gui.c: Added mouse scroll wheel support to list dialogs.
+ Uses standard button4/5 method no modifier moves 2 lines shift
+ moves 1 line control moves 10 lines
+
+2002-05-03 13:52 we7u
+
+ * src/maps.c: Changing colors of cities and borders around/between
+ cities.
+
+2002-05-03 12:28 we7u
+
+ * src/maps.c: More subdued colors for the major roads. Cranked the
+ width down a bit too.
+
+2002-05-03 12:14 we7u
+
+ * src/maps.c: Setting up more default colors. Pedestrian trails
+ are now red. Dashed lines for trails, 4WD roads, ferry
+ crossings. Glaciers are now white.
+
+2002-05-03 10:22 we7u
+
+ * src/maps.c: Getting rid of compiler warning by adding "color.h"
+ as an include file. This is needed for the GetPixelByName() call
+ I added.
+
+2002-05-03 09:57 we7u
+
+ * src/maps.c: Cleaning up properly with warning message for Point
+ and Multipoint Shapefiles, which aren't implemented yet in
+ Xastir.
+
+2002-05-02 16:53 we7u
+
+ * src/maps.c: This ones for Ken: Download and select plc00 files
+ from GeographyNetwork to get the "designated places" boundaries
+ filled in with PaleGoldenrod color. The code will also label
+ these areas. Create the following subdirectories to get the
+ layering right:
+
+ county (cty00)
+ designated_places (plc00)
+ h2o (lkH and wat)
+ misc (lkC)
+ rail (lkB)
+ roads (lkA)
+
+2002-05-02 14:25 we7u
+
+ * src/maps.c: Changing water back to Steel Blue.
+
+2002-05-02 13:58 we7u
+
+ * src/maps.c: More comments. Shortened another string "State
+ Route" to "State" that occurs in the ESRI Tiger/Line Shapefiles.
+ Changed the county polygon back to gray so that tracks show up
+ better.
+
+2002-05-02 12:28 we7u
+
+ * src/maps.c: Added comments. Made some optimizations in the
+ Shapefile code. Shortened some labels that get drawn.
+
+2002-05-01 20:28 rzg
+
+ * README.1ST: Update to README.1ST with more shapefile locations
+ and other minor edits.
+
+2002-05-01 15:43 we7u
+
+ * src/maps.c: Changing how many labels appear at certain zoom
+ levels with Shapefiles.
+
+2002-05-01 15:12 we7u
+
+ * src/maps.c: Optimization: Only doing floating point operations
+ for label rotation when we know we're going to be drawing the
+ label. Changes by Chris Bell to help alleviate upside-down
+ labels.
+
+2002-05-01 14:23 we7u
+
+ * src/maps.c: Rotated labels for Shapefile maps. This be a good
+ thing!
+
+2002-05-01 12:11 we7u
+
+ * src/maps.c: Better label drawing. Quantities of identical labels
+ drawn in the viewport are now determined by zoom level.
+
+2002-04-30 17:08 we7u
+
+ * src/db.c: Fixing directed query responses. They now show up in a
+ popup window.
+
+2002-04-30 15:53 we7u
+
+ * src/: main.c, xa_config.c, xa_config.h: get_int() and get_long()
+ now check for min/max values, and assign a default value if the
+ number is outside this range. Also prints a warning message if
+ it has to assign the default.
+
+2002-04-30 13:50 we7u
+
+ * src/maps.c: Changing the levels at which smaller roads and labels
+ for those roads get drawn. All roads are drawn at zoom 64 and
+ lower. Labels for small roads start showing up at zoom 16 and
+ lower.
+
+2002-04-30 11:57 we7u
+
+ * src/maps.c: Converting back to "convert" without path until we
+ get configure support for figuring out the path.
+
+2002-04-30 11:31 we7u
+
+ * src/maps.c: Adding another path to convert.
+
+2002-04-30 11:30 we7u
+
+ * src/maps.c: Added path to "convert" command. Added checks around
+ system() command.
+
+2002-04-29 17:02 we7u
+
+ * src/maps.c: Fixed some conversion problems when converting to
+ screen coordinate system.
+
+2002-04-29 10:40 we7u
+
+ * src/maps.c: Implemented map levels for the Shapefile code. The
+ togglebutton in the Maps menu now works for Shapefiles.
+
+2002-04-27 16:47 we7u
+
+ * src/maps.c: Setting up more zoom levels for Shapefile roads.
+
+2002-04-27 16:03 we7u
+
+ * src/maps.c: Created linked list for Shapelib labels already
+ drawn. Keeps us from drawing 50 labels that all say the same
+ thing. Added some zoom levels for labels of various types.
+
+2002-04-27 12:52 we7u
+
+ * src/maps.c: Getting rid of lesser roads at zoom levels 100 and
+ above.
+
+2002-04-27 07:59 we7u
+
+ * src/maps.c: Reducing the width of water until I can figure out
+ how Tigermap decided to determine their width.
+
+2002-04-26 23:39 we7u
+
+ * src/maps.c: A few color & width changes for shapefile maps.
+
+2002-04-26 16:51 we7u
+
+ * src/maps.c: Setting number of lanes (line width) for Tiger and
+ Mapshots maps.
+
+2002-04-26 11:27 we7u
+
+ * src/maps.c: Changed paths to a brown color.
+
+2002-04-26 11:14 we7u
+
+ * src/maps.c: Corrected some of the headings. Split railroads out
+ as a separate flag and a new color.
+
+2002-04-26 10:16 we7u
+
+ * src/: main.c, main.h, xa_config.c: Created a #define in main.h
+ for enabling/disabling the "Transmit Raw WX data" togglebutton.
+ The #define enabling this button is commented out. Most likely
+ the only people interested in this button would be people
+ debugging code for certain Peet Bros. weather stations where the
+ raw data from them is allowed over the air by the APRS spec.
+
+2002-04-26 08:53 francais1
+
+ * src/: main.c, maps.h, xa_config.c: Make map intensity menu show
+ up in the correct cases.
+
+2002-04-26 08:50 francais1
+
+ * src/maps.c: Make GNIS labels more readable
+
+2002-04-25 16:04 we7u
+
+ * src/maps.c: Fixing up mapshots maps for rivers/lakes. Also being
+ proactive in trying to eliminate possible future segfaults in the
+ Shapelib code.
+
+2002-04-25 14:23 we7u
+
+ * src/maps.c: Label fix for mapshots.com roads.
+
+2002-04-25 13:18 we7u
+
+ * src/maps.c: Changed fill color for land masses from darkgray to
+ grey73 (a bit lighter, and the same color as the menus).
+
+2002-04-25 11:56 we7u
+
+ * src/maps.c: Added shapefile decoding of colors/types for
+ mapshots.com county maps made from tiger data.
+
+2002-04-25 10:52 we7u
+
+ * src/maps.c: Added some comments.
+
+2002-04-25 00:00 we7u
+
+ * src/: maps.c, maps.h: Fixes for Shapefile segfaults: Can't
+ retrieve a field that's higher than fieldcount, else segfault.
+
+2002-04-24 16:00 we7u
+
+ * src/: maps.c, maps.h: Fix for segfaults in Shapefiles.
+
+2002-04-24 15:23 francais1
+
+ * src/maps.c: Tweaked some color problems with turning labels on.
+ Tweaked river drawing slightly.
+
+2002-04-24 15:09 francais1
+
+ * src/maps.c: Made gnis map files draw regardless of the labels
+ setting since a gnis map is all labels, so if you picked it, you
+ want it drawn, period.
+
+2002-04-24 14:23 we7u
+
+ * src/maps.c: Adding missing free() calls in draw_shapefile_map().
+
+2002-04-24 13:06 we7u
+
+ * src/maps.c: Fixing segfault problem with Shapefile maps.
+
+2002-04-24 11:28 francais1
+
+ * src/maps.c: IMHO, I've improved the guessing of what shapefile we
+ are dealing with and also the drawing colors and style...
+
+2002-04-24 11:24 francais1
+
+ * src/: draw_symbols.c, main.c, xastir.h: Changed name of
+ pixmap_stipple to pixmap_2x2_stipple and made it load from an xbm
+
+2002-04-24 11:23 we7u
+
+ * src/maps.c: Minor change to get rid of compiler warning. Changed
+ static variable to non-static.
+
+2002-04-24 11:08 francais1
+
+ * symbols/: 2x2.xbm, Makefile.am, Makefile.in: Added bitmap for 50%
+ stipple
+
+2002-04-24 10:51 francais1
+
+ * src/: util.c, util.h: A couple new functions that will be useful
+ for UTM grid
+
+2002-04-24 10:50 francais1
+
+ * src/main.c: Added SteelBlue for drawing lakes, rivers (plain blue
+ seemed pretty harsh and SteelBlue is a background color as well,
+ so that it can be the ocean)
+
+2002-04-24 09:58 we7u
+
+ * src/xa_config.c: Commented out annoying debug statements that get
+ in the way each time.
+
+2002-04-24 09:54 we7u
+
+ * src/: alert.h, maps.c: Speedups for weather alerts. Once we know
+ what the bounding rectangle is for an alert, we stuff it into the
+ alert struct. load_alert_maps() then uses that info to determine
+ whether a shape is within the viewport, without having to snag
+ that info from the Shapefile each time.
+
+2002-04-24 09:20 we7u
+
+ * src/maps.c: Removed old code. Put in warning printf for old
+ weather alert stuff in routine that doesn't handle it anymore.
+ Changed some comments.
+
+2002-04-24 08:41 francais1
+
+ * src/maps.c: Added equator and central meridian drawing as a black
+ line when a grid is asked for. Teasing for utm grid drawing.
+
+2002-04-24 01:06 we7u
+
+ * src/: alert.c, alert.h, maps.c: Added "index" field to alert
+ records, initially set to -1. This gets filled in with the index
+ into the Shapefile when the shape is searched for. This
+ dramatically speeds up drawing of weather alerts 'cuz the search
+ is skipped on the 2nd and later uses of the alert.
+
+2002-04-23 23:03 francais1
+
+ * src/: main.c, maps.c, xastir.h: Initial support for using
+ stipples for weather alerts with a description of the alert
+ event.
+
+2002-04-23 22:57 francais1
+
+ * symbols/: Makefile.am, Makefile.in, alert.xbm, flood.xbm,
+ snow.xbm, tornado.xbm, wind.xbm, winter_wx.xbm, wntr_strm.xbm:
+ Added bitmap files for use as weather map stipples
+
+2002-04-23 22:08 francais1
+
+ * src/maps.c: Fixed indentation
+
+2002-04-23 17:01 we7u
+
+ * src/wx_gui.c: Detailed weather alerts now show up in their own
+ resizable dialog.
+
+2002-04-23 16:39 francais1
+
+ * src/main.c: Added support for zooming in and out with buttons 6 &
+ 7 and for panning up and down with the scroll wheel.
+
+2002-04-23 00:31 we7u
+
+ * src/: alert.c, wx_gui.c: Cleaning up some debug messages I put in
+ for the weather alert code.
+
+2002-04-22 23:32 we7u
+
+ * src/wx_gui.c: Added the capability to finger the weather server
+ by double-clicking on a weather alert line in the View->Weather
+ Alerts dialog. The output currently appears in the xterm that
+ you start Xastir from.
+
+2002-04-22 23:14 we7u
+
+ * src/wx_gui.c: Changed View->Weather Alerts dialog to
+ single-select mode. Added a callback and callback function for
+ the double-click operation.
+
+2002-04-22 22:46 we7u
+
+ * src/wx_gui.c: Changed View->Weather Alerts dialog so that it can
+ be resized.
+
+2002-04-22 22:16 we7u
+
+ * src/: alert.c, alert.h, db.c, wx_gui.c: Decoded SKY alerts. They
+ now get associated with the proper weather alert packets.
+ Tweaked View->Weather Alerts dialog to display them properly and
+ added a horizontal scrollbar to that dialog.
+
+2002-04-22 17:03 rzg
+
+ * FAQ:
+ Fixed the numbering....
+
+2002-04-22 16:57 rzg
+
+ * FAQ, README.1ST, help/help-English.dat:
+ Updates to FAQ, README.1ST. and help=English.dat, mostly with
+ regard to the weather alert changeover to shapefile format.
+
+2002-04-22 14:08 we7u
+
+ * src/alert.c: Fix to weather alerts. Expired alerts will now be
+ removed from the View->Weather Alert dialog after they've been
+ expired more than one hour.
+
+2002-04-22 09:57 we7u
+
+ * src/alert.c: The start of adding "CIVIL" as another weather
+ alert. Not completely functional yet. Also added more of Dale
+ Hugueley's comments.
+
+2002-04-22 09:47 we7u
+
+ * config/language-Portuguese.sys: Changes by David Quental, CT1DRB.
+ Thanks!
+
+2002-04-20 21:26 we7u
+
+ * src/db.c: Slight reformatting.
+
+2002-04-20 15:13 we7u
+
+ * src/alert.c: Took out last patch. New alerts will now create a
+ new entry, even if there is a cancel with the same zone that was
+ received earlier.
+
+2002-04-20 12:23 we7u
+
+ * src/maps.c: Fix for changing line widths on shapefile maps.
+
+2002-04-20 10:48 we7u
+
+ * config/language-Portuguese.sys: Changes by David Quental, CT1DRB.
+ Thanks!
+
+2002-04-20 10:34 we7u
+
+ * README.1ST: Updated the APRS Server list.
+
+2002-04-19 21:16 we7u
+
+ * src/: alert.c, maps.c: Fixes for weather alerts. CANCL packets
+ are starting to work now.
+
+2002-04-19 16:27 we7u
+
+ * src/: alert.c, alert.h, maps.c: Changed global variable
+ "alert_tag" to "alert_status" so that it won't be confused with
+ the alert struct "alert_tag" field. Added loads of comments.
+
+2002-04-19 13:58 we7u
+
+ * src/alert.c: More comments.
+
+2002-04-19 12:30 we7u
+
+ * src/alert.c: Updated some comments.
+
+2002-04-19 09:29 we7u
+
+ * src/wx_gui.c: Slight reformatting of View->Weather Alerts dialog.
+
+2002-04-19 00:11 we7u
+
+ * src/wx_gui.c: Reformatted View->Weather Alerts dialog slightly:
+ Shorter lines and easier to read.
+
+2002-04-18 23:42 we7u
+
+ * src/: alert.c, alert.h, wx_gui.c: Added issue date/time to
+ weather alerts and View->Weather Alerts dialog.
+
+2002-04-18 21:42 we7u
+
+ * xastir.1: Minor tweaks to eliminate redundancy, shorten the
+ copyright years, make the words flow better.
+
+2002-04-18 17:38 rzg
+
+ * xastir.1:
+ Minor formatting changes to look more manpage-like.
+
+2002-04-18 16:39 we7u
+
+ * src/maps.c: Speedup for weather alerts. Skip searching through
+ Shapefiles if we already have a filename for the alert.
+
+2002-04-18 15:59 we7u
+
+ * xastir.1: Added the "-i" flag (private colormap) to the man page.
+
+2002-04-18 15:46 francais1
+
+ * src/: main.c, maps.c: I don't believe we need to check if it is a
+ symbolic link when we use stat, because it will follow the link.
+
+2002-04-18 15:28 we7u
+
+ * src/: color.c, db.c, main.c, maps.c, xa_config.c, xastir.h:
+ Private colormap changes by Chris Bell, KD6ZWR. Change to
+ weather alert timing by WE7U.
+
+2002-04-18 12:58 we7u
+
+ * config/language-Portuguese.sys: Changes by David Quental, CT1DRB.
+
+2002-04-18 09:11 we7u
+
+ * src/maps.c: Corrected some comments. Corrected some filename
+ prefixes. Added the capability to use symbolic linked files as
+ weather alerts (I think, not fully tested yet).
+
+2002-04-18 09:10 we7u
+
+ * src/wx_gui.c: Added "Expired:" tag to expired weather alerts in
+ the View->Weather Alerts dialog.
+
+2002-04-18 09:09 we7u
+
+ * src/main.c: Added the capability to read symbolic links as maps
+ (I think). Not fully tested yet.
+
+2002-04-18 09:08 we7u
+
+ * src/alert.c: Added some comments.
+
+2002-04-17 16:57 we7u
+
+ * src/alert.c: Changed some comments.
+
+2002-04-17 16:48 we7u
+
+ * src/: alert.c, main.c, maps.c, xa_config.c: More weather alert
+ tweaks, including the beginning of compressed weather alert
+ decoding.
+
+2002-04-17 13:58 we7u
+
+ * src/wx_gui.c: Reformatted weather alert expire date/time in
+ View->Weather Alerts dialog.
+
+2002-04-17 13:52 we7u
+
+ * src/: alert.c, wx_gui.c: Fixed parsing problem for weather alerts
+ where objects after a space were being parsed as new alerts.
+
+2002-04-17 12:58 we7u
+
+ * src/: alert.c, alert.h, db.c, wx_gui.c: Changing View->Weather
+ Alerts dialog so that it displays the data we'll need for
+ fingering the weather server to get additional data about a
+ particular alert.
+
+2002-04-17 11:36 we7u
+
+ * src/maps.c: Fix for weather alerts disappearing at different zoom
+ levels or while panning around. The problem had to do with the
+ alert getting marked as being outside the viewport, then they
+ wouldn't be looked at again.
+
+2002-04-16 18:02 we7u
+
+ * src/maps.c: closedir() to go with the opendir(). ;-)
+
+2002-04-16 16:17 we7u
+
+ * src/maps.c: Fixes for "too many open files" in shapefile weather
+ alerts.
+
+2002-04-16 14:16 we7u
+
+ * src/: alert.c, db.c, maps.c: Fixes to regular shapefile maps.
+ Cleanup after shapefile weather alert additions.
+
+2002-04-16 12:44 we7u
+
+ * src/maps.c: Fixes for county weather warning alerts.
+
+2002-04-16 11:34 we7u
+
+ * src/: alert.c, maps.c, xa_config.c: Shapefile wx alert changes.
+ Starting to work for zones. More work to do on other types.
+
+2002-04-16 09:17 we7u
+
+ * src/maps.c: Fix for Shapefile weather alerts. Nearly there now.
+
+2002-04-16 02:19 we7u
+
+ * src/maps.c: More shapefile wx alert changes.
+
+2002-04-16 01:03 we7u
+
+ * src/maps.c: More weather alert shapefile coding done.
+
+2002-04-15 21:30 we7u
+
+ * src/maps.c: We now figure out the complete filename starting with
+ the first few characters of the shapefile. We look in the
+ directory to figure out a match for the zone. This should make
+ it so that we can update the shapefiles at any time and won't
+ have to change any configuration or code in order to use the new
+ files.
+
+2002-04-15 20:30 we7u
+
+ * src/maps.c: Initial decoding for the different types of weather
+ alerts. Soon we'll be able to match up real filenames to the
+ zones and start drawing them.
+
+2002-04-15 17:07 we7u
+
+ * src/maps.c: Added some more comments.
+
+2002-04-15 16:04 we7u
+
+ * src/: alert.c, db.c, maps.c: I'm breaking the weather alerts by
+ checking in this code, but have tagged the "stable" repository
+ with a "we7u-safe" tag, so we can recover if things get broken
+ too badly. Forward we go!
+
+ I've also released xastir-1.1.2 in the development area of the
+ Files section on SourceForge. That is the "we7u-safe" tagged
+ version of the sources.
+
+2002-04-12 15:49 we7u
+
+ * src/wx.c: Changing to capital 'X' for the weather-station-type
+ designator in our transmitted weather reports, per Bob Bruninga's
+ ok on the APRSSPEC mailing list, 04/12/2002.
+
+2002-04-12 14:50 we7u
+
+ * src/maps.c: Shapefile wx alert small changes. We're not there
+ yet.
+
+2002-04-12 12:50 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Portuguese.sys, language-Spanish.sys: Tweaked one popup
+ message.
+
+2002-04-12 11:11 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: We now allow four
+ different symbols for weather stations, but print a warning if
+ trying to use an NWS symbol. If trying to run a weather station
+ with a different symbol, the software will set the symbol to the
+ standard weather symbol automatically.
+
+2002-04-11 23:04 we7u
+
+ * src/alert.c: Changed some comments.
+
+2002-04-11 16:02 we7u
+
+ * src/alert.c: More comments.
+
+2002-04-11 14:49 we7u
+
+ * src/alert.c: More comments.
+
+2002-04-11 12:58 we7u
+
+ * src/alert.c: Changed a comment.
+
+2002-04-11 12:58 we7u
+
+ * src/alert.c: Changed some comments.
+
+2002-04-11 12:53 we7u
+
+ * src/alert.c: More comments.
+
+2002-04-11 12:52 we7u
+
+ * src/alert.c: More comments added.
+
+2002-04-11 12:46 we7u
+
+ * src/alert.c: More comments added.
+
+2002-04-11 12:01 we7u
+
+ * src/alert.c: More comments.
+
+2002-04-11 11:40 we7u
+
+ * src/alert.c: More comments.
+
+2002-04-11 11:27 we7u
+
+ * src/alert.c: Reformatted some of the code, added comments.
+ Preparing for Shapefile weather alert coding.
+
+2002-04-11 10:13 we7u
+
+ * src/alert.c: Fixed possible string overrun. Added a few
+ comments.
+
+2002-04-10 21:28 we7u
+
+ * xastir.1: Updates by Jose Marte, HI8GN.
+
+2002-04-10 16:59 we7u
+
+ * src/alert.c: Added more comments.
+
+2002-04-10 16:02 we7u
+
+ * src/alert.c: Added a bunch of comments.
+
+2002-04-10 14:35 we7u
+
+ * src/db.c: Changed one output message to make it more correct.
+
+2002-04-10 13:03 we7u
+
+ * src/util.c: Fixing a compile warning for MacOS X.
+
+2002-04-10 12:58 we7u
+
+ * src/lang.c: Fixing a warning which shows up while compiling on
+ MacOS X.
+
+2002-04-10 12:00 we7u
+
+ * Makefile.am, Makefile.in: Changed to more standard way of
+ specifying man pages.
+
+2002-04-10 10:21 we7u
+
+ * configure, configure.in, src/wx.c: Bumped up to version number
+ 1.1.2 to more easily see who's running the latest weather code.
+ Added some comments to wx.c
+
+2002-04-09 23:28 we7u
+
+ * src/wx.c: Adding more casts back in.
+
+2002-04-09 23:04 we7u
+
+ * src/wx.c: Adding some necessary casts back in to the weather
+ code.
+
+2002-04-09 21:53 we7u
+
+ * Makefile.am, Makefile.in: Tweaked Makefiles to install new Xastir
+ man page.
+
+2002-04-09 21:41 we7u
+
+ * xastir.1: A few small tweaks.
+
+2002-04-09 21:33 we7u
+
+ * xastir.1: Initial man page by Jose R. Marte A., HI8GN.
+
+2002-04-09 21:33 we7u
+
+ * xastir.spec.in: Man page added by Jose R. Marte A., HI8GN.
+
+2002-04-09 21:30 we7u
+
+ * config/language-Spanish.sys: Updates by Jose R. Marte A., HI8GN.
+
+2002-04-09 21:23 we7u
+
+ * help/help-Spanish.dat: Updates by Jose R. Marte A., HI8GN.
+
+2002-04-09 16:04 we7u
+
+ * src/wx.c: Commented out the Peet Brothers U2000 Complete Record
+ Mode parsing of today's rain total. It conflicts with the more
+ generic method of calling compute_rain() from the incrementing
+ long-term rain total.
+
+2002-04-09 15:38 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface_gui.c, src/wx.c,
+ src/xa_config.c: Preparation for correcting rain gauge
+ measurements for various types of weather stations.
+
+2002-04-09 13:34 we7u
+
+ * src/: interface_gui.c, main.c: Moving "default:" cases to end of
+ switch statements.
+
+2002-04-09 09:35 francais1
+
+ * src/main.c: Force redraw on coordinate system change. This will
+ make sense when I check in the UTM grid code.
+
+2002-04-09 02:25 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/interface_gui.c, src/wx.c: Code
+ to handle different types of rain gauges. Nearly complete.
+
+2002-04-09 00:51 we7u
+
+ * src/: db.c, wx.c: Added some comments.
+
+2002-04-08 23:13 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Portuguese.sys,
+ config/language-Spanish.sys, src/main.c: Added code to force the
+ symbol to one of the two weather symbols that are legal in the
+ APRS spec, for the cases where we're transmitting weather data.
+
+2002-04-08 14:15 rzg
+
+ * help/help-English.dat: Minor helpfile update.
+
+2002-04-08 13:29 we7u
+
+ * src/: main.c, main.h, maps.c: Fixed zooming-by-dragging, a mouse
+ operation, so that the entire box that is dragged will appear in
+ the final view.
+
+2002-04-08 11:57 we7u
+
+ * src/wx.c: Preparing to tweak Peet Bros code for 0.1mm and 0.01"
+ rain gauges. No real code changes yet.
+
+2002-04-07 11:48 we7u
+
+ * config/language-Spanish.sys: Deleted duplicate lines.
+
+2002-04-06 11:47 we7u
+
+ * config/language-Italian.sys: Updated to correspond more closely
+ with the English language file.
+
+2002-04-06 11:11 we7u
+
+ * config/: language-Dutch.sys, language-French.sys,
+ language-German.sys, language-Spanish.sys: Keeping the other
+ language files in sync with the English file.
+
+2002-04-06 10:56 we7u
+
+ * config/language-Portuguese.sys: Adding some missing strings.
+
+2002-04-06 10:11 we7u
+
+ * help/: Makefile.am, Makefile.in: Portuguese help file stuff.
+
+2002-04-06 10:09 we7u
+
+ * xastir.spec.in, help/help-Portuguese.dat, src/main.c: Potuguese
+ help file stuff.
+
+2002-04-06 09:56 we7u
+
+ * config/Makefile.in: Adding Portuguese language.
+
+2002-04-06 09:53 we7u
+
+ * README.1ST, xastir.spec.in, config/Makefile.am,
+ config/language-English.sys, config/language-Portuguese.sys,
+ src/main.c: Tweaks to add Portuguese language to Xastir.
+
+2002-04-06 08:06 we7u
+
+ * config/language-Portuguese.sys: Thanks to David Quental for
+ tranlating the language file to Portuguese!
+
+2002-04-05 19:31 we7u
+
+ * src/main.c: Tweak to make gps interval time switch as soon as the
+ user changes it in the default menu.
+
+2002-04-05 14:50 we7u
+
+ * src/: main.c, main.h, maps.c: Modifying zooming in with the mouse
+ such that it now figures out whether most of the mouse movement
+ was in the horizontal or in the vertical direction, then computes
+ the new zoom level based on that. Previous to this change
+ zooming was calculated based only on vertical movement.
+
+2002-04-05 11:14 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Spanish.sys: Changed the final exit label.
+
+2002-04-05 08:25 gstueve
+
+ * src/db.c: Reintroduce groups to the land of messaging.
+
+2002-04-04 16:59 we7u
+
+ * src/main.c: Tweaked one hotkey string that I forgot to.
+
+2002-04-04 16:41 we7u
+
+ * src/main.c: Fixed Map Chooser so that the list approriately shows
+ what was most recently selected/de-selected via the buttons.
+
+2002-04-04 15:37 we7u
+
+ * src/main.c: Mapped the coordinate calculator to a button in the
+ maps menu.
+
+2002-04-04 01:39 we7u
+
+ * src/main.c: Changed "About" text to say 1999-2002.
+
+2002-04-04 01:24 we7u
+
+ * src/db.c: Changed Station_data() code so that it's not destroyed
+ and re-created each time if "Automatic Updates" are enabled.
+ Broke out code that filled in the text into a separate function.
+
+2002-04-03 23:33 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Spanish.sys,
+ src/main.c: Implemented "Exit Now!" submenu off the File->Exit
+ menu to make it harder to exit the program by mistake. It takes
+ a deliberate effort now to do so.
+
+2002-04-03 23:10 we7u
+
+ * src/main.c: Changed Map Chooser so that only the OK and Cancel
+ buttons will dismiss the dialog.
+
+2002-04-03 22:56 we7u
+
+ * src/maps.c: First attempt to make Shapefiles more bulletproof.
+ Missing fields shouldn't cause segfaults anymore.
+
+2002-04-02 23:13 we7u
+
+ * src/rac_data.c: Added a popup to the RAC data search for the case
+ where the callsign isn't found.
+
+2002-04-02 22:25 we7u
+
+ * src/fcc_data.c: Fixed severe wait when a U.S. callsign is not in
+ the database. Also added a popup for the cases where the
+ callsign isn't found.
+
+2002-04-02 14:01 we7u
+
+ * src/main.c: Coordinate calculator OK button is now grey'ed out
+ until a successful calculation occurs.
+
+2002-04-02 13:44 we7u
+
+ * src/main.c: Added some debug_level statements for some printf's.
+
+2002-04-02 13:37 we7u
+
+ * src/main.c: Fixed truncation problems affecting accuracy in the
+ last digits for the Coordinate Calculator dialog.
+
+2002-04-02 13:21 we7u
+
+ * src/main.c: Most of the coordinate calculator stuff is working
+ now. Still a few minor truncation problems to track down and
+ fix.
+
+2002-04-02 09:32 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Spanish.sys,
+ src/main.c: Now change title on Coordinate Calculator dialog
+ based on which dialog called us. Also changed some strings to
+ langcode strings for Coordinate Calculator and associated code.
+
+2002-04-02 08:55 we7u
+
+ * src/main.c: Added a bunch more comments having to do with the
+ Coordinate Calculator.
+
+2002-04-01 23:43 we7u
+
+ * src/: main.c, wx_gui.c: Added linkages between Coordinate
+ Calculator and the calling dialogs, in both directions.
+
+2002-04-01 15:42 we7u
+
+ * src/: main.c, util.c: Fixing coordinate calculator. Got rid of
+ rounding errors by going to fixed-point arithmetic. Added
+ comments to util.c.
+
+2002-04-01 14:53 we7u
+
+ * src/util.c: Switched to fixed-point arithmetic for lat/lon
+ conversions to strings. Got rid of floating-point rounding
+ errors.
+
+2002-04-01 14:52 we7u
+
+ * src/main.c: Added space between lat/lon values on status line.
+ More readable.
+
+2002-04-01 13:37 we7u
+
+ * src/main.c: Changed Coordinate Calculator to use higher precision
+ DD MM SS.S format.
+
+2002-04-01 12:52 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Spanish.sys,
+ src/list_gui.c, src/util.c: Changed dd mm ss format to dd mm ss.s
+ for more precision. It's more similar now to the precision of
+ the other formats.
+
+2002-04-01 12:28 we7u
+
+ * src/util.c: Correct some comments.
+
+2002-03-31 23:57 we7u
+
+ * src/wx.c: Updated some comments.
+
+2002-03-31 22:50 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Spanish.sys,
+ src/interface.h, src/interface_gui.c, src/xa_config.c: Added
+ KD6VPE's changes to add tenth/hundredth rain gauge types to the
+ weather interfaces. This is to support the two types of rain
+ gauges for Peet Brothers weather stations. This patch implements
+ a global variable and the interface widgets needed to manipulate
+ it, but does _not_ implement the code to do anything with the
+ variable yet.
+
+2002-03-30 10:00 we7u
+
+ * src/main.c: Changed Coordinate Calc help text so that it is
+ obviously not good output data.
+
+2002-03-30 09:23 we7u
+
+ * src/main.c: Added some help text output to Coordinate Calculator
+ if the user enters something that isn't recognized.
+
+2002-03-30 01:17 we7u
+
+ * src/main.c: Very minor changes to Coordinate Calculator. No
+ additional functionality.
+
+2002-03-30 00:12 we7u
+
+ * src/main.c: More Coordinate Calculator stuff. UTM input is
+ working now.
+
+2002-03-29 18:40 we7u
+
+ * src/main.c: Added some simulated output for what the Coordinate
+ Calculator should display.
+
+2002-03-29 15:47 we7u
+
+ * src/main.c: More code for the Coordinate Calculator.
+
+2002-03-29 15:00 we7u
+
+ * src/main.c: Added Coordinate_calc button to Object Create/Modify.
+
+2002-03-29 14:45 we7u
+
+ * src/main.c: More coordinate calculator code. Not functional yet.
+
+2002-03-29 10:43 francais1
+
+ * src/alert.c: Fixed errant tabs
+
+2002-03-28 21:53 francais1
+
+ * src/alert.c: There were several strncpy's without a following
+ str[last] = `\0` statement. One of them caused a segfault. This
+ whole file probably needs looking over for such problems. I
+ fixed a few I thought need the statement or in the case of some
+ memmove's, seemed wrong to me.
+
+2002-03-28 16:19 we7u
+
+ * src/: lang.c, main.c: Fixed langcode segfault. Fixed a
+ lang_hotkey that was wrong.
+
+2002-03-28 15:52 we7u
+
+ * src/main.c: The beginnings of a coordinate calculator for
+ inputting coordinates in different formats.
+
+2002-03-28 15:31 we7u
+
+ * src/list_gui.h: Knocking off a compiler warning.
+
+2002-03-28 11:28 we7u
+
+ * src/: list_gui.c, main.c: View->Mobile Stations list now updates
+ instantly when the coordinate system is changed.
+
+2002-03-28 11:02 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Spanish.sys,
+ src/list_gui.c: Added multiple coordinate display capability to
+ View->Mobile Stations dialog.
+
+2002-03-28 10:41 francais1
+
+ * src/main.c: Added calls to TrackMouse for the map-moving key
+ events so that the position status line gets updated.
+
+2002-03-28 10:27 francais1
+
+ * src/main.c: Commented out code that clears mouse pointer location
+ status line when we leave Xastir window because I believe we may
+ be trying to write down that information in another window or
+ some such action.
+
+2002-03-27 16:54 francais1
+
+ * src/: db.c, main.c, util.c, xastir.h: Added and enabled DDMMSS
+ coordinate format.
+
+2002-03-27 16:21 we7u
+
+ * src/db.c: Added dd.dddd and UTM capability to the Station Info
+ dialog as well.
+
+2002-03-27 14:26 we7u
+
+ * src/main.c: Removed unused variables. Changed some comments.
+
+2002-03-27 13:22 we7u
+
+ * src/: main.c, util.c, util.h: Created convert_xastir_to_UTM_str()
+ function to create a UTM string.
+
+2002-03-27 12:59 we7u
+
+ * src/util.c: Added some comments.
+
+2002-03-27 12:49 we7u
+
+ * src/main.c: Enclosed some calculations used only in debug mode
+ inside if (debug_level) construct. Added a few comments here and
+ there.
+
+2002-03-27 10:21 we7u
+
+ * src/db.c: Fixed a problem caused by the mass update to new debug
+ levels: The station callsign was truncated in Station Info
+ dialog if in debug level that wasn't 0 or 1. Also changed this
+ dialog such that the characters which make up the symbol are
+ always visible between the symbol and the callsign, whether in
+ debug mode or not. I want to see this information.
+
+2002-03-27 09:38 we7u
+
+ * scripts/mapfgd.pl: Updates by Derrick J. Brashear, KB3EGH, to
+ handle 1:63360 maps.
+
+2002-03-26 23:57 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Spanish.sys,
+ src/main.c, src/main.h, src/xa_config.c: Added a
+ File->Configure->Coordinate System menu option which allows
+ selecting between four different methods of displaying
+ coordinates. Currently this only modifies the status bar
+ display. Only three of the four options are currently
+ implemented.
+
+2002-03-26 15:43 we7u
+
+ * src/main.c: Added timestamp output to stderr on segfault.
+
+2002-03-26 15:36 we7u
+
+ * src/: util.c, util.h, wx.c: Added 30 second timestamps to each
+ logfile. Moved hour() and minute() routines from wx.c to util.c,
+ renamed to get_hours() and get_minutes(). Added get_seconds()
+ routine. Added code to wx.c:cycle_weather() routine to do the
+ logfile timestamps. Cycle_weather currently runs every 30
+ seconds.
+
+2002-03-22 23:20 we7u
+
+ * xastir.spec.in: Trimmed down version that still works nicely.
+ Installs /usr/local/bin/xastir as SUID root.
+
+2002-03-22 22:34 we7u
+
+ * xastir.spec.in: Fixed for binary RPM's.
+
+2002-03-22 14:46 we7u
+
+ * xastir.spec.in: Updated link to project sources.
+
+2002-03-22 14:33 we7u
+
+ * xastir.spec.in: Corrected misspelling.
+
+2002-03-19 08:37 we7u
+
+ * config/tnc-startup.kpc3: More tweaks to the kpc3 startup file by
+ we7u.
+
+2002-03-18 22:00 we7u
+
+ * config/tnc-startup.pico: A few more pico changes by we7u.
+
+2002-03-18 21:41 we7u
+
+ * config/: tnc-startup.aea, tnc-startup.sys: Added "echo off" to
+ two tnc startup files. This prevents echo'ed commands from
+ showing up in the middle of tnc data.
+
+2002-03-18 21:25 we7u
+
+ * config/tnc-startup.pico: Changes hinted at by Jeff Brenton,
+ KA9VNV. Changed into PicoPacket syntax by Curt, WE7U.
+
+2002-03-18 21:07 we7u
+
+ * config/tnc-startup.kpc3: Added changes suggested by Jeff Brenton,
+ KA9VNV.
+
+2002-03-18 10:00 we7u
+
+ * config/language-Italian.sys: Fixes by Marco Calistri, IK5BCU.
+
+2002-03-15 09:39 we7u
+
+ * help/help-English.dat: Fixed minor spelling errors.
+
+2002-03-15 09:35 we7u
+
+ * README.1ST: Fixed minor spelling errors.
+
+2002-03-14 20:58 rzg
+
+ * README.1ST, help/help-English.dat:
+ Updated helpfile and README.1ST.
+
+2002-03-13 09:22 we7u
+
+ * scripts/mapfgd.pl: Fixes by Derrick J. Brashear for "k" format
+ maps.
+
+2002-03-12 09:00 we7u
+
+ * src/maps.c: Fixing some segfaults that can occur in the geoTIFF
+ code if certain TIFF tags aren't present in the image. Thanks to
+ Derrick J. Brashear for pointing this out. I used his patch with
+ modifications.
+
+2002-03-11 15:36 we7u
+
+ * config/: tnc-startup.kam, tnc-startup.kpc3, tnc-startup.sys:
+ Changed "mfilter off" to "filter off" for kam and kpc3. Added
+ "filter off" to tnc-startup.sys as well. Both mfilter and filter
+ are in that file, making it work for both types of TNC's.
+
+2002-03-11 12:53 we7u
+
+ * src/lang.c: Added a bit of bulletproofing for lang.c.
+
+2002-03-11 10:49 we7u
+
+ * config/: Makefile.am, Makefile.in, tnc-startup.aea: Added
+ tnc-startup.aea file and tweaked Makefiles to install it.
+
+2002-03-11 10:06 we7u
+
+ * config/: tnc-startup.kam, tnc-startup.kpc3, tnc-startup.sys:
+ Adding "mfilter off" to most tnc startup files.
+
+2002-03-11 01:17 we7u
+
+ * src/interface.c: Increased inter-character delay to 25ms.
+ PicoPacket doesn't work with 20ms. This is only for writes on
+ serial port TNC's.
+
+2002-03-11 00:06 we7u
+
+ * config/tnc-startup.pico: Fullduplex not recognized by my
+ PicoPacket. Fulldup is.
+
+2002-03-10 23:39 we7u
+
+ * src/interface.c: Moved character write pacing to the proper
+ routine.
+
+2002-03-10 23:01 we7u
+
+ * src/: interface.c, main.c, main.h: Setuid patches by Jack
+ Twilley. Serial port throttling by we7u.
+
+2002-03-08 14:48 we7u
+
+ * src/interface_gui.c: Fix for Xastir blowing up when changing
+ properties on a serial TNC interface.
+
+2002-03-07 15:33 we7u
+
+ * config/Makefile.in: Adding PicoPacket startup file.
+
+2002-03-07 15:31 we7u
+
+ * Makefile.in: Adding backslash back in at the appropriate point.
+
+2002-03-07 15:30 we7u
+
+ * acconfig.h, config.h.in, configure: Fixes for warning when
+ running autoheader.
+
+2002-03-07 15:03 we7u
+
+ * config/tnc-startup.pico: A few more tweaks to the picopacket
+ startup file.
+
+2002-03-07 12:58 we7u
+
+ * src/gps.c: Changed a few variables to globals. This is to allow
+ two different GPS sentences to update the current info, then
+ perform a screen update using the combined data. Fixed the code
+ so that receipt of one valid GPS sentence doesn't disable
+ decoding of the next.
+
+2002-03-07 12:49 we7u
+
+ * config/tnc-startup.pico: Swapped the order of the GPS string
+ captures.
+
+2002-03-07 12:49 we7u
+
+ * src/interface.c: Added some debugging statements.
+
+2002-03-07 10:56 we7u
+
+ * config/tnc-startup.pico: Proper commands for a Pico. Tested.
+
+2002-03-07 10:55 we7u
+
+ * src/interface.c: Added a delay after sending each init string to
+ a serial TNC. This is needed to allow the TNC enough time to
+ process the command before sending the next.
+
+2002-03-07 08:58 we7u
+
+ * Makefile.am: Adding a backslash that was erroneously deleted from
+ Makefile.am. Thanks to Jack Twilley for pointing this out.
+
+2002-03-06 17:02 we7u
+
+ * config/: Makefile.am, tnc-startup.pico: Added a startup file for
+ a Paccomm PicoPacket.
+
+2002-03-06 15:58 we7u
+
+ * src/gps.c: Setting the time from GPS data now requires only that
+ a $GPRMC string be received, the OS be Linux, and that the Xastir
+ binary must be SUID root. It no longer requires the $GPGGA
+ sentence to set the time.
+
+2002-03-06 13:57 we7u
+
+ * config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Spanish.sys,
+ src/main.c: Changed 20 & 10 second GPS update rates down to 15 &
+ 5.
+
+2002-03-06 13:13 we7u
+
+ * src/db.c: Added station trails for the local station. Improved
+ station/trail update rate for Track-Me mode.
+
+2002-03-06 11:48 we7u
+
+ * src/db.c: Added the capability to track ourselves. Uses the
+ Track Station facility, so the map moves when we get too near the
+ edge of the viewport.
+
+2002-03-06 10:11 we7u
+
+ * src/interface_gui.c: Added a missing mutex unlock that was
+ preventing getting to the properties dialog for the new interface
+ type.
+
+2002-03-06 01:52 we7u
+
+ * src/gps.c: Blanking out fields for which we don't have actual
+ data values.
+
+2002-03-06 01:44 we7u
+
+ * src/interface.c: Added else clause s.t. it changes the type to
+ "aprs data" if the nmea tests fail.
+
+2002-03-06 01:29 we7u
+
+ * src/interface.c: A few small tweaks to tnc_get_data_type().
+ Wasn't detecting NMEA data properly.
+
+2002-03-06 01:17 we7u
+
+ * src/gps.c: Updating local position after decoding each GPRMC or
+ GPGGA string.
+
+2002-03-06 01:03 we7u
+
+ * src/gps.c: Now updates local position when either $GPRMC or
+ $GPGGA are received. Both are not required except for setting
+ time. Added #ifdef __linux__ around the settime call.
+
+2002-03-06 00:30 we7u
+
+ * src/interface.c: Modified tnc_get_data_type() function so that it
+ doesn't call the decode_ax25_line() function. The latter
+ function is destructive to its first parameter, which is the APRS
+ packet. It was causing the packet to be destroyed before it
+ could be parsed and added to the database.
+
+2002-03-06 00:27 we7u
+
+ * src/db.c: Corrected spelling error in debug output.
+
+2002-03-06 00:25 we7u
+
+ * src/main.c: Added a couple of comments.
+
+2002-03-05 23:53 we7u
+
+ * src/interface_gui.c: Added "Set Time" button to two more GPS
+ interfaces. Took it away from the "Serial TNC" interface.
+
+2002-03-05 22:42 we7u
+
+ * src/main.c: Widening the debug_level form to handle up to debug
+ level 2047.
+
+2002-03-05 13:28 we7u
+
+ * AUTHORS, ChangeLog, DEBUG_LEVELS, Makefile.am, README.1ST,
+ acinclude.m4, config.guess, config.sub, configure.in, install-sh,
+ missing, mkinstalldirs, help/help-English.dat,
+ help/help-French.dat, help/help-German.dat,
+ help/help-Italian.dat, help/help-Spanish.dat,
+ scripts/icontable.pl, scripts/mapblast2geo.pl, scripts/mapfgd.pl,
+ src/datum.c, src/datum.h, src/db.c, src/draw_symbols.c,
+ src/festival.c, src/gps.c, src/interface.c, src/interface.h,
+ src/interface_gui.c, src/list_gui.c, src/main.c, src/maps.c,
+ src/messages.c, src/rotated.c, src/rotated.h, src/snprintf.c,
+ src/snprintf.h, src/util.c, src/xa_config.c: Expanded tabs.
+
+2002-03-05 00:18 we7u
+
+ * src/: db.c, db.h, gps.c, igate.c, interface.c, interface.h,
+ interface_gui.c, lang.c, main.c, maps.c, util.c, xa_config.c:
+ Changes by Owen DeLong <owen at delong.com>: Changing to bit-mapped
+ debug levels. Added new interface type "Serial TNC w/GPS on AUX
+ port", which is for Kantronics KAM, KPC3+, and Paccomm PicoPacket
+ TNC's that respond to <CTRL>-E for fetching GPS strings. Added
+ new DEBUG_LEVELS file that describes the new standard levels.
+ Added more debug statements througout the code. Added comments
+ for GPGGA sentence. Added "dbadd" parameter to decode_ax25_line,
+ if it's set on return, add the data to the database. Filter
+ "cmd:" out of incoming data. Decode time/data from GPRMC and
+ GPGGA strings, used to set system time to GPS time. Altitude
+ units now decoded from GPGGA strings. Changed hard-coded device
+ numbers to ennumerated values. New black background choice.
+ Added "char *envp[]" to parameters for main.
+
+ Still needed: Set time fixes for other operating systems. Smooth
+ time transition instead of force to new value. "Set Time" button
+ for remaining two GPS interface types.
+
+2002-03-04 13:41 we7u
+
+ * DEBUG_LEVELS: Added by Owen DeLong <owen at delong.com>: Changing
+ to bit-mapped debug levels. This file documents what each level
+ is for.
+
+2002-03-04 13:36 we7u
+
+ * src/: track_gui.c, wx.c: Changes by Owen DeLong
+ <owen at delong.com>: Changing to bit-mapped debug levels.
+
+2002-03-04 13:33 we7u
+
+ * src/: alert.c, hostname.c, maps.c, messages.c: Changes by Owen
+ DeLong <owen at delong.com>: Changing to bit-mapped debug levels.
+
+2002-03-04 13:20 we7u
+
+ * symbols/symbols.dat: Changes by Owen DeLong <owen at delong.com>,
+ KB6MER to support: New interface type.
+
+2002-03-04 13:19 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Spanish.sys: Changes by Owen DeLong <owen at delong.com>,
+ KB6MER to support: New interface type, setting time via GPS, new
+ Black map background color, more debugging messages.
+
+2002-02-25 16:10 we7u
+
+ * README.1ST: Minor tweaks to again test mailing list notification.
+
+2002-02-25 16:06 we7u
+
+ * README.1ST: Minor tweaks to test new mailing list.
+
+2002-02-25 14:29 we7u
+
+ * README.1ST: Added a blurb about the "--prefix" config option.
+
+2002-02-25 12:43 francais1
+
+ * config.h.in, configure, configure.in, src/xa_config.h,
+ src/xa_config.c: Changes to allow the use of --prefix with
+ configure. By default should install and run from
+ /usr/local/xastir as before.
+
+2002-02-25 01:22 we7u
+
+ * src/interface.c: Added a couple of debug messages. Fixed the
+ AX.25 reconnect problem. Decreased several fixed waits.
+
+2002-02-22 23:41 we7u
+
+ * src/db.c: Added more debug output in decode_Mic_E function. One
+ statement will print out even without debug mode if the symbol
+ table and symbol characters are switched.
+
+2002-02-19 16:28 rzg
+
+ * help/help-English.dat: Updated helpfile.
+
+2002-02-16 23:52 we7u
+
+ * src/main.c: Changed "Measure" function to go to feet or meters if
+ the total length is less than a mile or kilometer.
+
+2002-02-16 21:21 we7u
+
+ * src/util.c: FreeBSD time fix by Jack Twilley <jmt at twilley.org>.
+
+2002-02-15 21:51 we7u
+
+ * src/main.c: Fixing the main window (actually the main popup!) so
+ that it initially shows at the correct size, instead of resizing
+ shortly after.
+
+2002-02-15 15:55 we7u
+
+ * src/maps.c: Fixed Shapefile maps so that they work with more
+ shapefiles. Unknown shapes are drawn in black just like the
+ roads. Lakes shapefiles have to start with "lk" in the filename
+ now to be recognized and drawn as blue lakes.
+
+2002-02-15 12:49 we7u
+
+ * src/main.c: Reordering the management of the appshell popup in an
+ attempt to get rid of the bug: "Shell widget has zero width or
+ height" that occurs on some systems.
+
+2002-02-14 14:37 we7u
+
+ * src/xa_config.c: Changing default greying out of stations from
+ 120 minutes down to 80 minutes. This works better for some of
+ the satellites we can use for APRS, per Bob Bruninga's
+ recommendations.
+
+2002-02-14 09:33 we7u
+
+ * src/: db.c, main.c, main.h, util.c, util.h, xa_config.c: Tracked
+ station speech patches contributed by Alan Crosswell
+ <alan at columbia.edu>, n2ygk.
+
+2002-02-14 09:08 we7u
+
+ * config/: language-Dutch.sys, language-English.sys,
+ language-French.sys, language-German.sys, language-Italian.sys,
+ language-Spanish.sys: Tracked station speech patches contributed
+ by Alan Crosswell <alan at columbia.edu>, n2ygk.
+
+2002-02-13 12:55 we7u
+
+ * src/maps.c: Tiger map tweaks submitted by Jim Chandler, N0VH.
+
+2002-02-13 11:14 we7u
+
+ * src/wx.c: Added a comment at the top describing the weather
+ stations we currently support.
+
+2002-02-13 10:40 we7u
+
+ * config.guess, config.sub, missing: Checking in latest versions of
+ these files, snagged from:
+ http://subversions.gnu.org/cgi-bin/cvsweb/autoconf/config/
+
+2002-02-13 09:36 we7u
+
+ * configure, configure.in: Bumping the development version up to
+ version 1.1.1
+
+2002-02-13 08:44 we7u
+
+ * missing, config.sub: Updated file sent to me by Jack Twilley
+ <jmt at twilley.org>.
+
+2002-02-11 17:27 dk7in
+
+ * scripts/: mapblast2geo.pl, update_langfile.pl:
+ Old E-Mail deleted.
+
+2002-02-11 16:08 dk7in
+
+ * scripts/icontable.pl:
+ Old E-Mail address deleted.
+
+2002-02-11 15:21 we7u
+
+ * scripts/mapfgd.pl: New script by Derrick J Brashear, KB3EGH.
+ This one creates .fgd files from geotiff .tif files. Useful for
+ topo maps you find on the net that don't come with .fgd files.
+
+2002-02-11 14:22 we7u
+
+ * src/maps.c: A tweak by Derrick J Brashear, KB3EGH, which avoids
+ problems with user defined horizontal datums in geoTIFF.
+
+2002-02-10 12:04 kg4ijb
+
+ * Makefile.am: didn't get committed :/
+
+2002-02-10 01:06 we7u
+
+ * callpass/Makefile: Removing Makefile. This is created
+ automatically during the "configure" stage.
+
+2002-02-09 16:56 kg4ijb
+
+ * Makefile.in, configure, configure.in, callpass/Makefile,
+ callpass/Makefile.am, callpass/Makefile.in, callpass/callpass.c,
+ m4/Makefile.in: Moved callpass* to ./callpass. Automake doesn't
+ handle recursives very well
+
+2002-02-09 06:48 kg4ijb
+
+ * config.h.in, configure, configure.in, m4/Makefile.in: Added
+ config check for Xpm (hack) untill I can do something better.
+
+2002-02-09 06:14 kg4ijb
+
+ * configure, configure.in, m4/Makefile.in: updated release
+ information
+
+2002-02-07 20:45 kg4ijb
+
+ * m4/Makefile.in: rebuilds
+
+2002-02-06 16:58 we7u
+
+ * Makefile.am: Added a forgotten root-level Makefile.am file.
+
+2002-02-05 16:59 we7u
+
+ * help/: help-English.dat, help-Dutch.dat, help-French.dat,
+ help-German.dat, help-Italian.dat, help-Spanish.dat: Updated web
+ page pointers.
+
+2002-02-05 16:57 we7u
+
+ * AUTHORS, FAQ, README, README.1ST: Updated web page pointers and
+ CVS instructions.
+
+2002-02-05 16:22 we7u
+
+ * AUTHORS, FAQ, README, README.1ST: Tweaking web page addresses for
+ the new sourceforge project address.
+
+2002-02-04 21:00 we7u
+
+ * src/lclint.script: Added more debug statements. Added new files
+ to it.
+
+2002-02-04 20:58 we7u
+
+ * src/maps.c: Changed the ifdef's around that check for ImageMagick
+ and XPM libraries. The proper pieces of code should be
+ enabled/disabled now for whichever of these two libraries are
+ found on the system.
+
+2002-02-04 20:55 we7u
+
+ * src/main.h: Undef'ing VERSION only when lclint is being run
+ against the code.
+
+2002-02-04 20:54 we7u
+
+ * src/main.c: Added some debug statements.
+
+2002-02-01 19:18 kg4ijb
+
+ * src/list_gui.c, src/list_gui.h, src/locate_gui.c, src/location.c,
+ src/location_gui.c, src/main.c, src/main.h, src/maps.c,
+ src/maps.h, src/messages.c, src/messages.h, src/messages_gui.c,
+ src/popup.h, src/popup_gui.c, src/rac_data.c, src/rac_data.h,
+ src/rotated.c, src/rotated.h, src/sound.c, src/symbols.h,
+ src/track_gui.c, src/track_gui.h, src/util.c, src/util.h,
+ src/view_message_gui.c, src/wx.c, src/wx.h, src/wx_gui.c,
+ src/xa_config.c, src/xa_config.h, src/xastir.h, src/snprintf.h,
+ src/snprintf.c, symbols/Makefile.am, symbols/Makefile.in,
+ symbols/symbols.dat: Initial revision
+
+2002-02-01 19:18 kg4ijb
+
+ * src/list_gui.c, src/list_gui.h, src/locate_gui.c, src/location.c,
+ src/location_gui.c, src/main.c, src/main.h, src/maps.c,
+ src/maps.h, src/messages.c, src/messages.h, src/messages_gui.c,
+ src/popup.h, src/popup_gui.c, src/rac_data.c, src/rac_data.h,
+ src/rotated.c, src/rotated.h, src/sound.c, src/symbols.h,
+ src/track_gui.c, src/track_gui.h, src/util.c, src/util.h,
+ src/view_message_gui.c, src/wx.c, src/wx.h, src/wx_gui.c,
+ src/xa_config.c, src/xa_config.h, src/xastir.h, src/snprintf.h,
+ src/snprintf.c, symbols/Makefile.am, symbols/Makefile.in,
+ symbols/symbols.dat: rc1 intital import
+
+2002-02-01 19:15 kg4ijb
+
+ * ABOUT-NLS, AUTHORS, COPYING, ChangeLog, FAQ, INSTALL, LICENSE,
+ Makefile.in, NEWS, README, README.1ST, TODO, UPDATES, acconfig.h,
+ acinclude.m4, changes.txt, config.guess, config.h.in, config.sub,
+ configure, configure.in, install-sh, missing, mkinstalldirs,
+ placeholder, stamp-h.in, xastir.spec.in, ltconfig, ltmain.sh,
+ config/Makefile.am, config/Makefile.in,
+ config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Spanish.sys,
+ config/tnc-startup.kam, config/tnc-startup.kpc3,
+ config/tnc-startup.sys, config/tnc-startup.thd7,
+ config/tnc-stop.sys, config/xastir.rgb, help/Makefile.am,
+ help/Makefile.in, help/help-Dutch.dat, help/help-English.dat,
+ help/help-French.dat, help/help-German.dat,
+ help/help-Italian.dat, help/help-Spanish.dat, intl/Makefile.in,
+ intl/VERSION, intl/bindtextdom.c, intl/cat-compat.c,
+ intl/dcgettext.c, intl/dgettext.c, intl/explodename.c,
+ intl/finddomain.c, intl/gettext.c, intl/gettext.h,
+ intl/gettextP.h, intl/hash-string.h, intl/intl-compat.c,
+ intl/l10nflist.c, intl/libgettext.h, intl/libintl.h,
+ intl/linux-msg.sed, intl/loadinfo.h, intl/loadmsgcat.c,
+ intl/localealias.c, intl/po2tbl.sed, intl/po2tbl.sed.in,
+ intl/textdomain.c, intl/xopen-msg.sed, m4/Makefile.am,
+ m4/Makefile.in, m4/xmhtml.m4, po/Makefile.in, po/Makefile.in.in,
+ po/POTFILES, po/POTFILES.in, po/cat-id-tbl.c, po/en.po, po/fr.po,
+ po/nl.po, po/stamp-cat-id, po/xastir.pot,
+ scripts/example_objects.log, scripts/icontable.pl,
+ scripts/inf2geo.pl, scripts/mapblast2geo.pl,
+ scripts/update_langfile.pl, src/Makefile.am, src/Makefile.in,
+ src/alert.c, src/alert.h, src/bulletin_gui.c, src/bulletin_gui.h,
+ src/color.c, src/color.h, src/datum.c, src/datum.h, src/db.c,
+ src/db.h, src/draw_symbols.c, src/draw_symbols.h, src/fcc_data.c,
+ src/fcc_data.h, src/festival.c, src/festival.h, src/gps.c,
+ src/gps.h, src/hostname.c, src/hostname.h, src/igate.c,
+ src/igate.h, src/interface.c, src/interface.h,
+ src/interface_gui.c, src/lang.c, src/lang.h, src/lclint.script:
+ Initial revision
+
+2002-02-01 19:15 kg4ijb
+
+ * ABOUT-NLS, AUTHORS, COPYING, ChangeLog, FAQ, INSTALL, LICENSE,
+ Makefile.in, NEWS, README, README.1ST, TODO, UPDATES, acconfig.h,
+ acinclude.m4, changes.txt, config.guess, config.h.in, config.sub,
+ configure, configure.in, install-sh, missing, mkinstalldirs,
+ placeholder, stamp-h.in, xastir.spec.in, ltconfig, ltmain.sh,
+ config/Makefile.am, config/Makefile.in,
+ config/language-Dutch.sys, config/language-English.sys,
+ config/language-French.sys, config/language-German.sys,
+ config/language-Italian.sys, config/language-Spanish.sys,
+ config/tnc-startup.kam, config/tnc-startup.kpc3,
+ config/tnc-startup.sys, config/tnc-startup.thd7,
+ config/tnc-stop.sys, config/xastir.rgb, help/Makefile.am,
+ help/Makefile.in, help/help-Dutch.dat, help/help-English.dat,
+ help/help-French.dat, help/help-German.dat,
+ help/help-Italian.dat, help/help-Spanish.dat, intl/Makefile.in,
+ intl/VERSION, intl/bindtextdom.c, intl/cat-compat.c,
+ intl/dcgettext.c, intl/dgettext.c, intl/explodename.c,
+ intl/finddomain.c, intl/gettext.c, intl/gettext.h,
+ intl/gettextP.h, intl/hash-string.h, intl/intl-compat.c,
+ intl/l10nflist.c, intl/libgettext.h, intl/libintl.h,
+ intl/linux-msg.sed, intl/loadinfo.h, intl/loadmsgcat.c,
+ intl/localealias.c, intl/po2tbl.sed, intl/po2tbl.sed.in,
+ intl/textdomain.c, intl/xopen-msg.sed, m4/Makefile.am,
+ m4/Makefile.in, m4/xmhtml.m4, po/Makefile.in, po/Makefile.in.in,
+ po/POTFILES, po/POTFILES.in, po/cat-id-tbl.c, po/en.po, po/fr.po,
+ po/nl.po, po/stamp-cat-id, po/xastir.pot,
+ scripts/example_objects.log, scripts/icontable.pl,
+ scripts/inf2geo.pl, scripts/mapblast2geo.pl,
+ scripts/update_langfile.pl, src/Makefile.am, src/Makefile.in,
+ src/alert.c, src/alert.h, src/bulletin_gui.c, src/bulletin_gui.h,
+ src/color.c, src/color.h, src/datum.c, src/datum.h, src/db.c,
+ src/db.h, src/draw_symbols.c, src/draw_symbols.h, src/fcc_data.c,
+ src/fcc_data.h, src/festival.c, src/festival.h, src/gps.c,
+ src/gps.h, src/hostname.c, src/hostname.h, src/igate.c,
+ src/igate.h, src/interface.c, src/interface.h,
+ src/interface_gui.c, src/lang.c, src/lang.h, src/lclint.script:
+ rc1 intital import
+
diff --git a/DEBUG_LEVELS b/DEBUG_LEVELS
new file mode 100644
index 0000000..0e0887f
--- /dev/null
+++ b/DEBUG_LEVELS
@@ -0,0 +1,123 @@
+
+$Id: DEBUG_LEVELS,v 1.18 2012/11/01 18:57:18 we7u Exp $
+
+This file has three parts. The first part describes the new structure for
+debug levels. The second part describes the debug_level definitions that
+were in the old code and which files they were in. The third part
+describes how to use use debugging at run time. The debug level structure
+was modified in February of 2002 by KB6MER. Questions/comments/flames can
+be sent to kb6mer at arrl.net
+
+Here's how things are after KB6MER tweaked it all...
+
+New Scheme:
+-----------
+1 General basic debugging (any system)
+2 Messages, WX, Objects, and Items, Port Data Flow
+4 X Object Debugging
+8 X Window Object Debugging
+16 Map Debugging (maps.c)
+32 Language Debugging (maps.c)
+64 Database Object Debugging
+128 GPS Interface Detailed debugging
+256 station and trail display detailed debugging
+512 Map import/export function debugging
+1024 Internet Transaction debugging
+2048 ALOHA radius and Multipoint object debugging.
+
+4096 Levels 4096 and above will require modification to the
+ main.c:Change_debug_level_change_data() function to change
+ the bounds checking, and are available for future use.
+
+------------------------------------------------------------------
+
+Old Scheme:
+-----------
+Places where debug level is referenced in old code, and the levels
+referenced (if debug_level xx), where xx is >0, &1, etc.
+
+alert.c >0
+bulletin_gui.c &1
+db.c >=2 &1 &128 &32 &256 ()
+gps.c &128
+hostname.c &256
+igate.c &2
+interface.c &128 &2 &1
+interface_gui.c &128
+lang.c &32
+main.c &4 <0/>255(need to change limits) &8 &128 &1 &15
+maps.c &16 &2 >=2 &4 &1 &8
+messages.c >1 &1 >5
+messages_gui.c &2
+track_gui.c >=2
+util.c &1
+wx.c >2 &1
+xa_config.c &1 &2
+
+
+
+
+------------------------------------------------------------------
+
+How to Use the Debug Levels
+
+Xastir debugging is turned on at run time by using the "-v" command line
+option and/or the File -> Configure -> Change Debug Level pull-down.
+
+As laid out above, in the source code, debugging output is turned on by a
+bitwise "and" (&) of the currently set DEBUG_LEVEL against a number
+appropriate to the module currently being executed.
+
+For example, in the "maps.c" the following lines appear:
+
+ if ( debug_level & 512 )
+ fprintf(stderr,"Creating %s\n", xpm_filename );
+
+The highest debug level for Xastir is 4095, and debug levels are additive.
+If you want to have "general basic debugging" and "GPS interface Detail"
+and "Map Debugging" you'd use:
+
+1 + 128 + 512 = 641
+
+xastir -v 641
+
+Debug information typically is sent to "standard error" - which is normally
+File Descriptor #2 in Unix parlance. Using common Unix shells, such as
+Bash, you can "redirect" the output to be intermingled with the "standard
+output" (file descriptor #1). This allows you to get all of the normal
+output, plus all of the debug output in one stream, which can be "piped" to
+another command, such as grep. This can used to search for specific items
+in the debug output.
+
+For example, to check debug information to see whether or not map caching
+is working, you can turn on debug level 512, redirect stderr to stdout and
+the grep for map cache specific output:
+
+xastir -v 512 2>&1 |grep map_cache
+
+Another little trick, to be used when you're running programs that
+call other programs, or scripts that call other scripts/programs:
+
+ (xastir -v 512 2>&1) | grep map_cache
+
+The parenthesis cause that portion to be run in a sub-shell, and then
+that sub-shell's STDERR is piped to STDOUT by the "2>&1" portion, so
+you get ANYTHING that went to STDERR or STDOUT from that command or
+anything that it calls. This is how you can get a "make" command to
+spit everything into one file.
+
+Of course you can also do:
+
+ (xastir -v 512 2>&1) | tee xastir.log
+
+Which will pipe everything to your screen and to the xastir.log
+file. You could then type "tail -f xastir.log | grep map_cache" in
+another window and watch that subset of the error messages there.
+That way you won't miss anything.
+
+
+
+
+------------------------------------------------------------------
+Copyright (C) 2002-2012 The Xastir Group
+
diff --git a/Davis/.cvsignore b/Davis/.cvsignore
new file mode 100644
index 0000000..f7ead90
--- /dev/null
+++ b/Davis/.cvsignore
@@ -0,0 +1,15 @@
+make.log
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+config.h
+config.h.in
+config.log
+config.status
+configure
+stamp-h1
+mkinstalldirs
+depcomp
+install-sh
+missing
diff --git a/Davis/AUTHORS b/Davis/AUTHORS
new file mode 100644
index 0000000..350c4f6
--- /dev/null
+++ b/Davis/AUTHORS
@@ -0,0 +1,24 @@
+
+$Id: AUTHORS,v 1.1 2004/06/02 16:37:59 we7u Exp $
+
+
+ Developers and Contributions
+ _________________________________________________________________
+
+ First, thanks go out to the great folks at the xastir team - a
+ wonderful APRS application set and helpful folks!
+
+ Thanks also to Andreas Muller, author of meteo and a great
+ resource for information and help.
+
+ Elements of this software are taken from wx200d ver 1.2
+ by Tim Witham, and it is modeled after that application.
+
+ Finally, thanks to the MySQL folks for the key element - the
+ database.
+
+ KB8ROP Bruce Bennett bruts at adelphia.net
+ _________________________________________________________________
+
+ Copyright (C) 2003-2004 Bruce Bennett KB8ROP
+
diff --git a/Davis/COPYING b/Davis/COPYING
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/Davis/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Davis/CVS/Entries b/Davis/CVS/Entries
new file mode 100644
index 0000000..c97764a
--- /dev/null
+++ b/Davis/CVS/Entries
@@ -0,0 +1,11 @@
+/.cvsignore/1.2/Thu Jan 26 19:06:14 2006//
+/AUTHORS/1.1/Wed Jun 2 16:37:59 2004//
+/COPYING/1.1/Wed Jun 2 16:37:59 2004//
+/ChangeLog/1.1/Wed Jun 2 16:37:59 2004//
+/INSTALL/1.1/Wed Jun 2 16:37:59 2004//
+/Makefile.am/1.8/Thu Nov 1 18:57:18 2012//
+/NEWS/1.1/Wed Jun 2 16:37:59 2004//
+/README/1.9/Thu Nov 1 18:57:18 2012//
+/bootstrap.sh/1.12/Thu Nov 1 18:57:18 2012//
+/configure.ac/1.10/Thu Nov 1 18:57:18 2012//
+D
diff --git a/Davis/CVS/Entries.Log b/Davis/CVS/Entries.Log
new file mode 100644
index 0000000..d269bfe
--- /dev/null
+++ b/Davis/CVS/Entries.Log
@@ -0,0 +1 @@
+A D/src////
diff --git a/Davis/CVS/Repository b/Davis/CVS/Repository
new file mode 100644
index 0000000..7cd0aef
--- /dev/null
+++ b/Davis/CVS/Repository
@@ -0,0 +1 @@
+xastir/Davis
diff --git a/Davis/CVS/Root b/Davis/CVS/Root
new file mode 100644
index 0000000..6a998ee
--- /dev/null
+++ b/Davis/CVS/Root
@@ -0,0 +1 @@
+:ext:we7u at xastir.cvs.sourceforge.net:/cvsroot/xastir
diff --git a/Davis/ChangeLog b/Davis/ChangeLog
new file mode 100644
index 0000000..298ac9e
--- /dev/null
+++ b/Davis/ChangeLog
@@ -0,0 +1,3 @@
+
+# $Id: ChangeLog,v 1.1 2004/06/02 16:37:59 we7u Exp $
+
diff --git a/Davis/INSTALL b/Davis/INSTALL
new file mode 100644
index 0000000..dd6f3b3
--- /dev/null
+++ b/Davis/INSTALL
@@ -0,0 +1,232 @@
+
+$Id: INSTALL,v 1.1 2004/06/02 16:37:59 we7u Exp $
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
+Foundation, Inc.
+
+ This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory. After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/Davis/Makefile.am b/Davis/Makefile.am
new file mode 100644
index 0000000..bdccfa4
--- /dev/null
+++ b/Davis/Makefile.am
@@ -0,0 +1,43 @@
+
+# $Id: Makefile.am,v 1.8 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2004-2012 The Xastir Group
+#
+
+AUTOMAKE_OPTIONS = gnu dist-bzip2
+ACLOCAL_AMFLAGS = -I m4
+
+D= `date +%G%m%d.%H%M%S`
+
+SUBDIRS = src
+
+
+#if DAVIS
+#MyWX = davis
+#else
+#MyWX =
+#endif
+#noinst_PROGRAMS = $(MyWX)
+
+
+# Remove this file here (it is created via configure), not from within intl.
+# DISTCLEANFILES =
+
+EXTRA_DIST = aclocal.m4 AUTHORS bootstrap.sh ChangeLog config.h.in \
+ config.status configure.ac COPYING INSTALL NEWS \
+ README bootstrap.sh
+
+MAINTAINERCLEANFILES = configure config.status aclocal.m4 \
+ Makefile.in Makefile config.guess config.sub install-sh \
+ missing mkinstalldirs
+
+#docdir=${pkgdatadir}/doc
+#doc_DATA=AUTHORS FAQ ChangeLog LICENSE README README.CVS \
+# README.MAPS README.win32 COPYING INSTALL UPGRADE
+
+#mandir=${prefix}/man
+#man_MANS=xastir.1
+
+ChangeLog::
+
+
diff --git a/Davis/NEWS b/Davis/NEWS
new file mode 100644
index 0000000..42f428b
--- /dev/null
+++ b/Davis/NEWS
@@ -0,0 +1,3 @@
+
+$Id: NEWS,v 1.1 2004/06/02 16:37:59 we7u Exp $
+
diff --git a/Davis/README b/Davis/README
new file mode 100644
index 0000000..c3f19c1
--- /dev/null
+++ b/Davis/README
@@ -0,0 +1,211 @@
+
+$Id: README,v 1.9 2012/11/01 18:57:18 we7u Exp $
+
+Copyright (C) 2004 Bruce Bennett <bruts at adelphia.net>
+Portions Copyright (C) 2004-2012 The Xastir Group
+(Modified for the Xastir project under GPL license)
+
+
+Davis Weather Station support for Xastir - db2APRS
+
+
+OVERVIEW
+--------
+
+This is a bridge utility between "meteo", a Davis Weather Station
+data storage & display application by Andreas Muller (see
+http://meteo.othello.ch) and "Xastir", the APRS package for
+Linux (see http://www.xastir.org). It allows your Davis weather
+data to be used by Xastir for local station data.
+
+You will need to obtain and install Xastir, mysql and meteo as
+outlined in the following sections. After Xastir and meteo are
+in working order, this utility can be run as a daemon to provide
+weather data to Xastir (or any other APRS-format application).
+
+"db2APRS" watches for new weather data in the database, retrieves
+the new data, formats it in APRS "position less" ASCII format and
+makes it available on a TCP port of your choosing. Xastir is
+capable of reading this data (see note under Xastir installation).
+
+
+INSTALLATION
+------------
+
+Steps in order:
+
+1) Install mysql - initial tested version mysql-3.23.58
+ although version 4 is released and has some significant
+ improvements - and version 4 *should* work (to be tested yet).
+ If you use an RPM or DPK binary-image version, be sure to add
+ the mysql-devel headers. For the latest image-version, see
+ http://www.mysql.com and follow the links to the downloads.
+ I used mysql-3.23.58-pc-linux-i686.tar.gz from that site.
+
+2) Install meteo - tested versions meteo-0.9.4 and meteo-0.9.8
+ Version 0.9.9 is available and based on the change documented
+ will work. See the instructions for installing & then setting
+ up meteo that come with the tar ball. Obtain the latest meteo
+ at http://meteo.othello.ch - the setup is rather involved but
+ worth the efort. Some SQL/XML skills can help here, but are
+ not absolutely required...
+
+3) Install or update your installation for Xastir to the latest
+ version (http://www.sourceforge.net, project Xastir)
+
+4) Install db2APRS - version 0.1.2
+ See instructions below.
+
+
+SETTINGS & STARTUP
+------------------
+
+1) mysql - it is recommended by mysql to set up passwords, but for
+ this usage it doesn't matter. In fact, it's a bit of a pain.
+ TODO - db2APRS has the annoying fault of clearly displaying
+ the password used for the mysql database for anyone to see via
+ 'ps -ef'. Start mysqld before db2APRS, meteo and Xastir in your
+ boot-time initializations.
+
+2) meteo - my testing used a one minute data accumulation rate.
+ Thirty seconds would more closely match Xastir, but the
+ database growth rate would be twice as fast (about 600
+ Mbytes/year at 30 sec rate). Set your desired rate using the
+ meteopoll command line options. I run the full meteopoll
+ package with averaging, graphs and meteodequeue - but the
+ only *required* element is meteopoll. Start the meteopoll
+ daemon after mysqld is up. (meteodequeue is recommended - see
+ the doc's that come with meteo and man pages).
+
+3) db2APRS - see "db2APRS RUN OPTIONS" below. Start this daemon
+ after mysqld and before Xastir. When meteopoll isn't running,
+ you will get old weather data, time stamped by Xastir as new
+ data.
+
+4) xastir - start this last, if you are auto-opening the WX port.
+ Set the weather port as a network weather station on
+ "localhost", port number as chosen in "db2APRS RUN OPTIONS"
+ (default is 1313). Make sure your station is set to one of the
+ "w/weather data" and your Icon is set to a weather Icon.
+
+
+db2APRS RUN OPTIONS
+-------------------
+
+The db2APRS utility takes standard short & long command line
+options, which can be displayed by "db2APRS -?". Here's the list:
+
+ -h --help
+
+ Show help info and exit.
+
+ -v --verbose
+
+ Useful with the -n switch, for trouble-shooting, not for
+ normal operation. Tells you more than you really wanted to
+ know, but I recommend that you use this switch while you
+ try to initially set up db2APRS.
+
+ -c --cport [port#]
+
+ Choose which TCP/IP port data comes out from. If not used,
+ port number 1313 is the default. HINT: "telnet localhost
+ [port#]" is a handy way to verify db2APRS operation.
+
+ -s --sensor [sensor group#]
+
+ Indicate what group of sensors are the outdoor ones.
+ If not supplied, sensor number 1 is the default.
+ HINT: Tables "station" and "sensor" in the meteo
+ database control what your "sensor" (which means
+ sensor group) definitions are for your "station".
+
+ -u --user [database user]
+
+ Username for mysql database connection. If unspecfied
+ defaults to "meteo" (which is per the meteo setup intended
+ to be a read-only account for meteo).
+
+ -p --password [db passwd]
+
+ Password for mysql connection. If unspecfied, no password
+ is supplied. NOTE: this password is unfortunately visible
+ to anyone on your system running 'ps -ef'. TO BE FIXED.
+
+ -b --database [database]
+
+ Database name for mysql connection. If not supplied the
+ default is "meteo".
+
+ -n --nodaemon
+
+ Run in the fore-ground as a program. Useful for debugging
+ or initial setup, when used with -v.
+
+ -r --repeat
+
+ Keep going till killed - if not specified, one pass is
+ performed and then db2APRS exits. The only case where this
+ switch is *not* used is during initial setup/debug.
+
+Typical example: "./db2APRS -r -u meteo -p meteo" for normal use
+or "./db2APRS -r -n -v -u test -p password" for debugging.
+
+
+OPERATIONAL DETAILS
+-------------------
+
+db2APRS connects to the specified mysql database, extracts the
+latest timestamp and compares it to the last timestamp it read.
+If newer, the outdoor weather data (extception: air pressure is
+taken as indoor=outdoor) bearing this timestamp is extracted
+and formatted in the APRS "position less" string format with a
+Davis and X-APRS tag on the end. Any connecting client is given
+this string at 25 second intervals, after new database entries
+are checked for.
+
+This daemon could run on any networked Linux machine instead of
+the machine hosting Xastir, if desired (it's a good way around
+lack of processing power, disk space or serial ports!).
+
+Note that the db2APRS daemon keeps providing data to Xastir even
+when no new entries in the database have been made. This could
+lead to errors in the timestamp on the data that Xastir is
+transmitting.
+
+
+BUILD db2APRS
+-------------
+
+It's the usual:
+
+$ cd xastir/Davis
+$ ./bootstrap.sh
+$ ./configure
+$ make
+$ su -c 'make install'
+
+
+ACKNOWLEGEMENTS & AUTHORS
+-------------------------
+
+db2APRS is the product of Bruce Bennett, callsign KB8ROP
+<bruts at adelphia.net> It is freely available at no charge
+under the GNU GENERAL PUBLIC LICENSE (see "COPYING" document)
+NO WARRANTY, expressed or implied, use at your own risk.
+
+Please feel free to contact me with test results & comments
+at the above EMAIL address
+
+Code portions and style taken from wx200d by Tim Witham
+<twitham at quiknet.com>, et. al.
+
+meteo is the work of Andreas Muller <afm at othello.ch>, et. al.
+
+mysql is the product of MySQL - see http://www.mysql.com for
+team details.
+
+and finally, Xastir is the brain child of Frank Giannandrea et.
+al. (see http://www.xastir.org for current EMAIL addresses)
+
+
diff --git a/Davis/bootstrap.sh b/Davis/bootstrap.sh
new file mode 100755
index 0000000..84e7096
--- /dev/null
+++ b/Davis/bootstrap.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# $Id: bootstrap.sh,v 1.12 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+#
+
+../bootstrap.sh
+
diff --git a/Davis/configure.ac b/Davis/configure.ac
new file mode 100755
index 0000000..45003fd
--- /dev/null
+++ b/Davis/configure.ac
@@ -0,0 +1,67 @@
+#
+# $Id: configure.ac,v 1.10 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2004 Bruce Bennett <bruts at adelphia.net>
+# Portions Copyright (C) 2004-2012 The Xastir Group
+# (Modified for the Xastir project under GPL license)
+#
+#
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.53)
+AC_INIT(db2APRS, 0.2.0, bruts at adelphia.net)
+AM_INIT_AUTOMAKE(db2APRS, 0.2.0)
+AC_CONFIG_SRCDIR([src/db2APRS.c])
+AM_CONFIG_HEADER([config.h])
+
+# Checks for programs.
+AC_PROG_INSTALL
+AC_PROG_CC
+
+# Checks for libraries.
+# Use MySQL's script for library config, if available
+MYSQL_CONFIG=mysql_config
+AC_MSG_CHECKING(for a fully installed MySQL)
+if ${MYSQL_CONFIG} --libs > /dev/null 2>&1
+then
+ MYSQL_VERSION=`${MYSQL_CONFIG} --version`
+ MYSQL_LIBS=`${MYSQL_CONFIG} --libs`
+ LIBS=`${MYSQL_CONFIG} --libs`
+ MYSQL_CFLAGS=`${MYSQL_CONFIG} --cflags`
+ CFLAGS="$CFLAGS $MYSQL_CFLAGS"
+ AC_SUBST(MYSQL_LIBS)
+ AC_SUBST(MYSQL_CFLAGS)
+ AC_MSG_RESULT(...found ${MYSQL_VERSION})
+else
+ AC_MSG_RESULT(MySQL is not fully installed)
+ AC_MSG_CHECKING(if there at least are the needed MySQL client libs)
+ AC_CHECK_LIB(mysqlclient,mysql_close)
+ if test $ac_cv_lib_mysqlclient_mysql_close = no; then
+
+ AC_MSG_ERROR(*** No MySQL client library found - See README ***)
+ else
+ AC_MSG_RESULT(found a usable libmysqlclient)
+ fi
+fi
+# Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h syslog.h unistd.h])
+if ${MYSQL_CONFIG} --libs > /dev/null 2>&1
+then
+ AC_MSG_RESULT(mysql.h path defined in CFLAGS)
+else
+ AC_CHECK_HEADERS([mysql.h],MYSQL_INC="yes",AC_MSG_ERROR(*** MySQL include file mysql.h not found - See README ***))
+fi
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_HEADER_TIME
+
+# Checks for library functions.
+AC_FUNC_FORK
+AC_FUNC_SELECT_ARGTYPES
+AC_TYPE_SIGNAL
+AC_FUNC_STRTOD
+AC_CHECK_FUNCS([memset select socket strrchr strtol])
+AC_CONFIG_FILES([Makefile src/Makefile])
+AC_OUTPUT
diff --git a/Davis/src/.cvsignore b/Davis/src/.cvsignore
new file mode 100644
index 0000000..5f7f600
--- /dev/null
+++ b/Davis/src/.cvsignore
@@ -0,0 +1,4 @@
+.deps
+Makefile
+Makefile.in
+db2APRS
diff --git a/Davis/src/CVS/Entries b/Davis/src/CVS/Entries
new file mode 100644
index 0000000..43b520a
--- /dev/null
+++ b/Davis/src/CVS/Entries
@@ -0,0 +1,5 @@
+/.cvsignore/1.1/Thu Jan 26 15:44:36 2006//
+/Makefile.am/1.9/Thu Nov 1 18:57:18 2012//
+/db2APRS.c/1.15/Thu Nov 1 18:57:18 2012//
+/defs.h/1.9/Thu Nov 1 18:57:18 2012//
+D
diff --git a/Davis/src/CVS/Repository b/Davis/src/CVS/Repository
new file mode 100644
index 0000000..18c0af6
--- /dev/null
+++ b/Davis/src/CVS/Repository
@@ -0,0 +1 @@
+xastir/Davis/src
diff --git a/Davis/src/CVS/Root b/Davis/src/CVS/Root
new file mode 100644
index 0000000..6a998ee
--- /dev/null
+++ b/Davis/src/CVS/Root
@@ -0,0 +1 @@
+:ext:we7u at xastir.cvs.sourceforge.net:/cvsroot/xastir
diff --git a/Davis/src/Makefile.am b/Davis/src/Makefile.am
new file mode 100644
index 0000000..546c1db
--- /dev/null
+++ b/Davis/src/Makefile.am
@@ -0,0 +1,14 @@
+# $Id: Makefile.am,v 1.9 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2004-2012 The Xastir Group
+#
+
+bin_PROGRAMS = db2APRS
+noinst_PROGRAMS =
+
+db2APRS_SOURCES = \
+ db2APRS.c defs.h
+
+
+db2APRS_LINK=$(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+
diff --git a/Davis/src/db2APRS.c b/Davis/src/db2APRS.c
new file mode 100644
index 0000000..f97c41c
--- /dev/null
+++ b/Davis/src/db2APRS.c
@@ -0,0 +1,1132 @@
+/******************************************************************
+ *
+ * @(#)$Id: db2APRS.c,v 1.15 2012/11/01 18:57:18 we7u Exp $
+ *
+ * Copyright (C) 2004 Bruce Bennett <bruts at adelphia.net>
+ * Portions Copyright (C) 2004-2012 The Xastir Group
+ *
+ * (see the files README and COPYING for more details)
+ *
+ * This file implements all of the database to APRS daemon.
+ *
+ *
+
+ Davis/Data Base Weather --> APRS Weather
+
+ Intended use:
+
+ Create & provide APRS style packet string
+ without position information from MySQL database
+ weather information stored there by meteo-0.9.4
+ (See http://meteo.othello.ch for source) to
+ xastir-1.2.1 (See http://www.xastir.org for source)
+
+ Note: "meteo-0.9.x" is a weather data accumulator
+ aimed at Davis weather stations, which stores weather
+ data in a mysql database. It is configured in two
+ places, an XML file (default name meteo.xml) and in
+ the database named in the XML file (default database
+ name is "meteo")
+
+ Output is to the ip hostname:port required in the
+ command line.
+
+ ACKNOWLEGEMENTS:
+
+ Elements of this software are taken from wx200d ver 1.2
+ by Tim Witham <twitham at quiknet.com>, and it is modeled
+ after that application.
+
+*******************************************************************/
+#include <config.h>
+#include <defs.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <signal.h>
+#include <syslog.h>
+#include <errno.h>
+#include <getopt.h>
+#include <mysql.h>
+
+#define MAXARGS 20 /* maximum CGI args to parse */
+#define TMPLEN 128 /* max length of CGI */
+#define BUFLEN 32 /* max length of hostname:port */
+
+#define POLL_INTERVAL 90 // default polling interval
+
+#define VALID_WINDDIR 0x001
+#define VALID_WINDSPD 0x002
+#define VALID_WINDGST 0x004
+#define VALID_TEMP 0x008
+#define VALID_RAIN 0x010
+#define VALID_RAIN24H 0x020
+#define VALID_HUMIDITY 0x040
+#define VALID_AIRPRESS 0x080
+#define VALID_RAINDAY 0x100
+
+#define MTPS2MPH 2.2369
+#define DEGC2DEGF 1.8
+#define MM2IN100TH 3.937
+#define INHG2HPA10TH 338.638
+
+#define OUTDOOR_SENSOR 1
+
+ //---From the static table "mfield", which really should be dynamically read here---
+ // (but then I couldn't use a switch statement)
+
+#define TEMPERATURE 0
+#define TEMPERATURE_MIN 1
+#define TEMPERATURE_MAX 2
+#define HUMIDITY 10
+#define HUMIDITY_MIN 11
+#define HUMIDITY_MAX 12
+#define WETNESS 20
+#define WETNESS_MIN 21
+#define WETNESS_MAX 22
+#define AIR_PRESSURE 30
+#define AIR_PRESSURE_MIN 31
+#define AIR_PRESSURE_MAX 32
+#define SOLAR 40
+#define UV 41
+#define RAIN 50
+ // note: "51" is really rain total
+#define RAIN_PER_DAY 51
+#define RAIN_PER_HOUR 52
+#define WIND_SPEED 60
+#define WIND_DIRECTION 61
+#define WIND_GUST 62
+#define WIND_X 63
+#define WIND_Y 64
+#define MOISTURE 70
+#define WATERLEVEL 71
+#define WATERLEVEL_MIN 72
+#define WATERLEVEL_MAX 73
+#define BATTERY 110
+#define TRANSMITTER 111
+#define DURATION 120
+#define SAMPLES 121
+
+struct dbinfo {
+ char user[30];
+ char pswrd[15];
+ char name[30];
+} db;
+
+char *progname;
+char *query;
+int *current = 0;
+
+int opt;
+
+MYSQL mysql; // Yeah, globals...
+MYSQL_RES *result;
+MYSQL_ROW row;
+
+char last_timestamp[20];
+char last_datetime[20];
+char death_msg[120];
+
+int debug_level;
+
+char wxAPRShost[BUFLEN];
+int wxAPRSport = PORT;
+int outdoor_instr = OUTDOOR_SENSOR;
+
+/******************************************************************
+1/4/2003
+ Usage brief
+
+*******************************************************************/
+void usage(int ret)
+{
+ if (query)
+ printf("Content-type: text/plain\nStatus: 200\n\n");
+ printf("usage: %s [options] \n",progname);
+ printf("VERSION: %s\n",VERSION);
+ printf(" -h --help show this help and exit\n");
+ printf(" -v --verbose debugging info --> stderr\n");
+ printf(" -c --cport [port#] IP port for data output\n");
+ printf(" -s --sensor [sensor group#] from meteo, your OUTDOOR sensor set\n");
+ printf(" -u --user [database user] username for mysql - default meteo\n");
+ printf(" -p --password [db passwd] password for mysql - default none\n");
+ printf(" -b --database [database] database name - default meteo\n");
+ printf(" -n --nodaemon do not run as daemon\n");
+ printf(" -r --repeat keep running\n");
+ printf(" -i --interval [seconds] polling interval\n");
+ printf(" -m --metric data base is in metric units\n");
+ printf("options may be uniquely abbreviated; units are as defined in APRS\n");
+ printf("Specification 1.0.1 for positionless weather data (English/hPa).\n");
+ exit(ret);
+}
+
+
+
+
+
+/******************************************************************
+1/2/2003
+ Make an APRS string out of WX data
+
+*******************************************************************/
+
+int APRS_str(char *APRS_buf,
+ char *datetime,
+ double winddir,
+ double windspeed,
+ double windgust,
+ double temp,
+ double rain1hr,
+ double rain24hr,
+ double rainday,
+ double humidity,
+ double airpressure,
+ unsigned int valid_data_flgs,
+ int Metric_Data)
+{
+
+ int intval;
+ char pbuf[10];
+
+ if (APRS_buf == NULL) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Null string buffer for APRS string.\n");
+ return -1; // Ooo!! *****Nasty Bad Exit Point Here****
+
+ }
+// timestamp first
+ sprintf(APRS_buf, "_%s",datetime);
+//
+ if(valid_data_flgs & VALID_WINDDIR) {
+ intval = (winddir + 0.5); // rounding to whole degrees
+ if (intval > 360) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Wind direction > 360\n");
+ sprintf(APRS_buf, "c...");
+ }
+ else if (intval < 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Wind direction negative\n");
+ sprintf(APRS_buf, "c...");
+
+ }
+ else {
+ sprintf(pbuf, "c%0.3d", intval);
+ }
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Wind direction flagged as invalid\n");
+ sprintf(pbuf, "c...");
+
+ }
+ strcat(APRS_buf,pbuf);
+
+ if(valid_data_flgs & VALID_WINDSPD) {
+ if (Metric_Data)
+ intval = (windspeed*MTPS2MPH + 0.5); // converting & rounding to whole MPH
+ else
+ intval = (windspeed + 0.5); // rounding to whole MPH
+ if (intval > 600) { // Let's be reasonable here - center of a tornado??
+ if (debug_level & 1)
+ fprintf(stderr,"err: Wind speed > 600 MPH\n");
+ sprintf(pbuf, "s...");
+
+ }
+ else if (intval < 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Wind speed negative\n");
+ sprintf(pbuf, "s...");
+
+ }
+ else {
+ sprintf(pbuf, "s%0.3d", intval);
+ }
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Wind speed flagged as invalid\n");
+ sprintf(pbuf, "s...");
+
+ }
+ strcat(APRS_buf,pbuf);
+
+ if(valid_data_flgs & VALID_WINDGST) {
+ if (Metric_Data)
+ intval = (windgust*MTPS2MPH + 0.5); // converting & rounding to whole MPH
+ else
+ intval = (windgust + 0.5); // rounding to whole MPH
+ if (intval > 600) { // Let's be reasonable here - center of a tornado??
+ if (debug_level & 1)
+ fprintf(stderr,"err: Wind gust > 600 MPH\n");
+ sprintf(pbuf, "g...");
+
+ }
+ else if (intval < 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Wind speed negative\n");
+ sprintf(pbuf, "g...");
+
+ }
+ else {
+ sprintf(pbuf, "g%0.3d", intval);
+ }
+
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Wind speed flagged as invalid\n");
+ sprintf(pbuf, "g...");
+
+ }
+ strcat(APRS_buf,pbuf);
+
+ if(valid_data_flgs & VALID_TEMP) {
+ if (Metric_Data)
+ intval = ((temp)*DEGC2DEGF + 0.5)+32; // converting & rounding to whole Deg F
+ else
+ intval = (temp + 0.5); // rounding to whole Deg F
+ if (intval > 200) { // Let's be reasonable here - boiling?
+ if (debug_level & 1)
+ fprintf(stderr,"err: Temperature > 200 Deg F\n");
+ sprintf(pbuf, "t...");
+ }
+ else if (intval < -99) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Temperature < -99 Deg F\n");
+ sprintf(pbuf, "t...");
+ }
+ else {
+ if (intval < 0) sprintf(pbuf,"t%0.2d",intval);
+ else sprintf(pbuf, "t%0.3d", intval);
+ }
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Temperature flagged as invalid\n");
+ sprintf(pbuf, "t...");
+ }
+ strcat(APRS_buf,pbuf);
+
+ if(valid_data_flgs & VALID_RAIN) {
+ if (Metric_Data)
+ intval = ((rain1hr)*MM2IN100TH + 0.5); // converting & rounding to whole 1/100 inch
+ else
+ intval = (rain1hr*100.0 + 0.5); // rounding to whole 1/100 inch
+ if (intval > 999) { // 10 in/hr? Garden Hose -> rain gauge?
+ if (debug_level & 1)
+ fprintf(stderr,"err: Rainfall/Hr > 9.99 inch\n");
+ sprintf(pbuf, "\0\0\0\0");
+ }
+ else if (intval < -99) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Rainfall/Hr negative\n");
+ sprintf(pbuf, "\0\0\0\0");
+ }
+ else {
+ sprintf(pbuf, "r%0.3d", intval);
+ }
+ }
+ else {
+
+ if (debug_level & 1)
+ fprintf(stderr,"info: Rainfall/Hr flagged as invalid\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ strcat(APRS_buf,pbuf);
+
+ if(valid_data_flgs & VALID_RAIN24H) {
+ if (Metric_Data)
+ intval = ((rain24hr)*MM2IN100TH + 0.5); // converting & rounding to whole 1/100 inch
+ else
+ intval = (rain24hr*100.0 + 0.5); // rounding to whole 1/100 inch
+ if (intval > 999) { // Can't handle greater than 9.99 inches of rain in 24 hours
+ if (debug_level & 1)
+ fprintf(stderr,"err: Rainfall/24Hr > 9.99 inch - reporting 9.99 inches\n");
+ sprintf(pbuf, "p999");
+
+ }
+ else if (intval < -99) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Rainfall/Hr negative\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ else {
+ sprintf(pbuf, "p%0.3d", intval);
+ }
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Rainfall/24Hr flagged as invalid\n");
+ sprintf(pbuf, "\0\0\0\0");
+ }
+ strcat(APRS_buf,pbuf);
+
+ if(valid_data_flgs & VALID_RAINDAY) {
+ if (Metric_Data)
+ intval = ((rainday)*MM2IN100TH + 0.5); // converting & rounding to whole 1/100 inch
+ else
+ intval = (rainday*100.0 + 0.5); // rounding to whole 1/100 inch
+ if (intval > 999) { // Can't handle greater than 9.99 inches of rain per day
+ if (debug_level & 1)
+ fprintf(stderr,"err: Rainfall/day > 9.99 inch - reporting 9.99 inches\n");
+ sprintf(pbuf, "P999");
+ }
+ else if (intval < -99) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Rainfall/day negative\n");
+ sprintf(pbuf, "\0\0\0\0");
+ }
+ else {
+ sprintf(pbuf, "P%0.3d", intval);
+ }
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Rainfall/day flagged as invalid\n");
+ sprintf(pbuf, "\0\0\0\0");
+ }
+ strcat(APRS_buf,pbuf);
+
+ if(valid_data_flgs & VALID_HUMIDITY) {
+ intval = (humidity + 0.5); // rounding to whole percent
+ if (intval > 100) { // Unlike the space shuttle engines, 100 % is max
+ if (debug_level & 1)
+ fprintf(stderr,"err: Humidity reported > 100%\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ else if (intval < 1) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Humidity reported < 1%\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ else {
+ if (intval == 100) intval = 0; // Report 100% as 'h00'
+ sprintf(pbuf, "h%0.2d", intval);
+ }
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Humidity flagged as invalid\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ strcat(APRS_buf,pbuf);
+
+ if(valid_data_flgs & VALID_AIRPRESS) {
+ if (Metric_Data)
+ intval = (airpressure*10.0 + 0.5); // rounding to whole tenth of a hPa
+ else
+ intval = (airpressure*INHG2HPA10TH + 0.5); // convering In-Hg to 1/10 hPa and rounding
+ if (intval > 20000) { //two atmospheres - about 29 PSIA
+ if (debug_level & 1)
+ fprintf(stderr,"err: Air Pressure reported > 2 Atmospheres%\n");
+ sprintf(pbuf, "\0\0\0\0");
+ }
+ else if (intval < 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Air Pressure reported negative%\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ else {
+ sprintf(pbuf, "b%0.5d", intval);
+ }
+ } else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Air Pressure flagged as invalid\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ strcat(APRS_buf,pbuf);
+ strcat(APRS_buf,"xDvs\n"); // add X aprs and Davis WX station ID's and <lf>
+
+ if (debug_level & 1)
+ fprintf(stderr,"\ninfo: APRS Version of WX - %s\n\n",APRS_buf);
+ return strlen(APRS_buf);
+}
+
+
+
+
+
+/******************************************************************
+1/2/2003
+ Get the latest set of Weather Data from the Data Base
+
+*******************************************************************/
+
+int Get_Latest_WX( double *winddir,
+ double *windspeed,
+ double *windgust,
+ double *temp,
+ double *rain1hr,
+ double *rain24hr,
+ double *rainday,
+ double *humidity,
+ double *airpressure,
+ unsigned int *valid_data_flgs)
+{
+ long last_hour_timestamp;
+ long int last_24_timestamp;
+ long int last_day_timestamp;
+ char query_buffer[240];
+ int nrows, row_cnt, item_count;
+ int found_sensor;
+ long local_offset; // could be as big as 12 hrs times 3600 seconds...
+
+ // Find latest, see if it's new to us
+ // --new to us is a simple timestamp follower, so upon startup
+ // it will always read one set of data, assuming any exists
+
+ if (mysql_query(&mysql, "SELECT MAX(timekey) from sdata")) {
+ sprintf(death_msg,"err: Latest timestamp query failed - exiting: %s\n", mysql_error(&mysql));
+ if (debug_level & 1){
+ fprintf(stderr,"%s",death_msg);
+ }
+ return -1;
+ }
+
+ if (!(result = mysql_store_result(&mysql))) {
+ sprintf(death_msg,"err: Latest timestamp query failed - exiting: %s\n", mysql_error(&mysql));
+ if (debug_level & 1){
+ fprintf(stderr,"%s",death_msg);
+ }
+ return -1;
+ }
+
+ if (mysql_num_rows(result) != 1 ) {
+ sprintf(death_msg,"err: Latest timestamp query failed - exiting: number of results %d\n",
+ mysql_num_rows(result));
+ if (debug_level & 1){
+ fprintf(stderr,"%s",death_msg);
+ }
+ // release query buffer
+ mysql_free_result(result);
+ return -1;
+ }
+
+ row = mysql_fetch_row(result);
+
+ if( row[0] == NULL ) {
+ sprintf(death_msg,"err: NULL result for timestamp query\n");
+ if (debug_level & 1){
+ fprintf(stderr,"%s",death_msg);
+ }
+ // release query buffer
+ mysql_free_result(result);
+ return -1;
+ }
+ // if no new data, exit with zero status
+
+ if (!strncmp(last_timestamp, row[0], 11)) {
+ if (debug_level & 1)
+ fprintf(stderr,"info: No new weather data recorded - exiting: no data\n");
+ // release query buffer
+ mysql_free_result(result);
+ return 0;
+ }
+ strcpy(last_timestamp, row[0]); // For next pass & following query
+
+ if( debug_level & 1) fprintf(stdout,"Timestamp: %s\n",last_timestamp);
+
+ // release query buffer
+ mysql_free_result(result);
+
+ sprintf(query_buffer,"SELECT value,sensorid,fieldid,from_unixtime(timekey,'%%m%%d%%H%%i%%S') FROM sdata WHERE timekey = %s", last_timestamp);
+
+ if (mysql_query(&mysql, query_buffer)) {
+ sprintf(death_msg,"err: Latest Weather Data query failed - exiting: %s\n\t --Query: %s\n",
+ mysql_error(&mysql), query_buffer);
+ if (debug_level & 1){
+ fprintf(stderr,"%s",death_msg);
+ }
+ return -1;
+ }
+
+ if (!(result = mysql_store_result(&mysql))) {
+ sprintf(death_msg,"err: Latest Weather Data query failed - exiting: %s\n", mysql_error(&mysql));
+ if (debug_level & 1){
+ fprintf(stderr,"%s",death_msg);
+ }
+ return -1;
+ }
+ if ((nrows=mysql_num_rows(result)) < 1 ) {
+ sprintf(death_msg,"err: Latest Weather Data query failed - exiting: number of results %d\n",nrows);
+ if (debug_level & 1){
+ fprintf(stderr,"%s",death_msg);
+ }
+ // release query buffer
+ mysql_free_result(result);
+ return -1;
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Latest Weather Data query: number of types of readings %d\n",nrows);
+ }
+
+ *valid_data_flgs = 0;
+ item_count = 0;
+ for (row_cnt = 0; row_cnt < nrows; row_cnt++) {
+ row = mysql_fetch_row(result);
+ strcpy(last_datetime,row[3]);
+
+ if(atoi(row[1]) == outdoor_instr) { // sensors are really groups of data
+ found_sensor = atoi(row[1]);
+ if(debug_level & 1)
+ fprintf(stderr,"info: found an outdoor sensor: (%d) ",found_sensor);
+
+ switch (atoi(row[2])) { // type of reading
+ case WIND_DIRECTION :
+ *winddir = strtod(row[0],NULL);
+ *valid_data_flgs |= VALID_WINDDIR;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"wind direction %f\n ",*winddir);
+ break;
+ case WIND_SPEED :
+ *windspeed = strtod(row[0],NULL);
+ *valid_data_flgs |= VALID_WINDSPD;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"wind speed %f\n ",*windspeed);
+ break;
+ case WIND_GUST :
+ *windgust = strtod(row[0],NULL);
+ *valid_data_flgs |= VALID_WINDGST;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"wind gust speed %f\n ",*windgust);
+ break;
+ case TEMPERATURE :
+ *temp = strtod(row[0],NULL);
+ *valid_data_flgs |= VALID_TEMP;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"temperature %f\n ",*temp);
+ break;
+ case HUMIDITY :
+ *humidity = strtod(row[0],NULL);
+ *valid_data_flgs |= VALID_HUMIDITY;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"humidity %f\n ",*humidity);
+ break;
+ case AIR_PRESSURE :
+ *airpressure = strtod(row[0],NULL);
+ *valid_data_flgs |= VALID_AIRPRESS;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"air pressure %f\n ",*airpressure);
+ break;
+ case RAIN_PER_DAY :
+ if(debug_level & 1)
+ fprintf(stderr,"rain-per-day total (not used), now calculated...\n ");
+ break;
+ case WIND_X :
+ if(debug_level & 1)
+ fprintf(stderr,"wind x... not used \n");
+ break;
+ case WIND_Y :
+ if(debug_level & 1)
+ fprintf(stderr,"wind y... not used \n");
+ break;
+ case DURATION :
+ if(debug_level & 1)
+ fprintf(stderr,"duration... not used \n");
+ break;
+ case SAMPLES :
+ if(debug_level & 1)
+ fprintf(stderr,"samples... not used \n");
+ break;
+ default :
+ if(debug_level & 1) fprintf(stderr,"unknown field %s\n",row[2]);
+ break;
+ }
+ }
+ else { // Must be indoor
+ if (debug_level & 1) fprintf(stderr,"info: indoor sensor found\n");
+ switch (atoi(row[2])) { // type of reading
+ case AIR_PRESSURE :
+ *airpressure = strtod(row[0],NULL);
+ *valid_data_flgs |= VALID_AIRPRESS;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"air pressure %f\n ",*airpressure);
+ break;
+ default :
+ if(debug_level & 1) fprintf(stderr,"unused field %s\n",row[2]);
+ break;
+ }
+ }
+ }
+
+ if(debug_level & 1) fprintf(stderr,"loop ends\n");
+ // release query buffer
+ mysql_free_result(result);
+
+ /* get rain figures */
+ /*
+ /* hourly first */
+ last_hour_timestamp = atol(last_timestamp) - 3600;
+ sprintf(query_buffer,"SELECT round(sum(value),2) FROM sdata WHERE timekey > %ld and fieldid = %d", last_hour_timestamp,RAIN);
+
+ if (mysql_query(&mysql, query_buffer)) {
+ sprintf(death_msg,"err: rain 1 hour query failed - exiting: %s\n\t --Query: %s\n", mysql_error(&mysql), query_buffer);
+ if (debug_level & 1) fprintf(stderr,"%s",death_msg);
+ return -1;
+ }
+ if (!(result = mysql_store_result(&mysql))) {
+ sprintf(death_msg,"err: rain 1 hour store failed - exiting: %s\n", mysql_error(&mysql));
+ if (debug_level & 1) fprintf(stderr,"%s",death_msg);
+ return -1;
+ }
+ if ((mysql_num_rows(result)) > 0) {
+ row = mysql_fetch_row(result);
+ if (row[0] != NULL) {
+ *rain1hr = strtod(row[0],NULL);
+ if(debug_level & 1) fprintf(stderr,"rain last hour %f\n ",*rain1hr);
+ // *rain1hr = *rain1hr * 100; // AFTER metric conversion if needed
+ *valid_data_flgs |= VALID_RAIN;
+ item_count++;
+ }
+ else {
+ *rain1hr = 0;
+ *valid_data_flgs |= VALID_RAIN; //None, but valid
+ if(debug_level & 1) fprintf(stderr,"no rain recorded in last hour\n");
+ }
+ }
+ // release query buffer
+ mysql_free_result(result);
+
+/* Last 24 hours */
+
+ last_24_timestamp = atol(last_timestamp) - 86400;
+ sprintf(query_buffer,"SELECT round(sum(value),2) FROM sdata WHERE timekey > %ld and fieldid = %d", last_24_timestamp,RAIN);
+
+ if (mysql_query(&mysql, query_buffer)) {
+ sprintf(death_msg,"err: rain 24 hour query failed - exiting: %s\n\t --Query: %s\n", mysql_error(&mysql), query_buffer);
+ if (debug_level & 1) fprintf(stderr,"%s",death_msg);
+ return -1;
+ }
+ if (!(result = mysql_store_result(&mysql))) {
+ sprintf(death_msg,"err: rain 24 hour store failed - exiting: %s\n", mysql_error(&mysql));
+ if (debug_level & 1) fprintf(stderr,"%s",death_msg);
+ return -1;
+ }
+ if ((mysql_num_rows(result)) > 0) {
+ row = mysql_fetch_row(result);
+ if (row[0] != NULL) {
+ *rain24hr = strtod(row[0],NULL);
+ if(debug_level & 1) fprintf(stderr,"rain last 24 hours %f\n ",*rain24hr);
+ //*rain24hr = *rain24hr * 100; // After metric conversion, if needed
+ item_count++;
+ *valid_data_flgs |= VALID_RAIN24H;
+ }
+ else {
+ *rain24hr = 0;
+ *valid_data_flgs |= VALID_RAIN24H; // Zero is valid too
+ if(debug_level & 1) fprintf(stderr,"no rain recorded in last 24 hours\n");
+ }
+ }
+ // release query buffer
+ mysql_free_result(result);
+#define CALC_MIDNIGHT
+#ifdef CALC_MIDNIGHT
+ // Timestamps are seconds since midnight Jan 1 1970, so an integer divide and multiply by
+ // seconds in 24 hrs (86400) yields the latest midnight time stamp value.
+ last_day_timestamp = (atol(last_timestamp) / 86400)*86400;
+ if(debug_level & 1)
+ fprintf(stderr,"info: timestamp for prior midnight - %ld\n",last_day_timestamp);
+ sprintf(query_buffer,"SELECT offset FROM station WHERE id = (SELECT stationid from sensor WHERE id = %d)", found_sensor);
+ if (mysql_query(&mysql, query_buffer)) {
+ sprintf(death_msg,"err: station time offset query failed - exiting: %s\n\t --Query: %s\n", mysql_error(&mysql), query_buffer);
+ if (debug_level & 1) fprintf(stderr,"%s",death_msg);
+ return -1;
+ }
+ if (!(result = mysql_store_result(&mysql))) {
+ sprintf(death_msg,"err: station time offset store failed - exiting: %s\n", mysql_error(&mysql));
+ if (debug_level & 1) fprintf(stderr,"%s",death_msg);
+ return -1;
+ }
+ if ((mysql_num_rows(result)) > 0) {
+ row = mysql_fetch_row(result);
+ if (row[0] != NULL) {
+ local_offset = atol(row[0]);
+ if (debug_level & 1) fprintf(stderr,"info: station time offset: %ld\n", local_offset);
+ }
+ }
+ mysql_free_result(result);
+#else
+
+/* since midnite */
+
+/* we can get the timestamp for midnite from the avg table */
+ last_day_timestamp = 0;
+ sprintf(query_buffer,"SELECT max(timekey) FROM avg WHERE fieldid = %d and intval = 86400", last_hour_timestamp,RAIN);
+ if (mysql_query(&mysql, query_buffer)) {
+ sprintf(death_msg,"err: midnite timekey query failed - exiting: %s\n\t --Query: %s\n", mysql_error(&mysql), query_buffer);
+ if (debug_level & 1) fprintf(stderr,"%s",death_msg);
+ return -1;
+ }
+ if (!(result = mysql_store_result(&mysql))) {
+ sprintf(death_msg,"err: midnite timekey store failed - exiting: %s\n", mysql_error(&mysql));
+ if (debug_level & 1) fprintf(stderr,"%s",death_msg);
+ return -1;
+ }
+ if ((mysql_num_rows(result)) > 0) {
+ row = mysql_fetch_row(result);
+ if (row[0] != NULL) {
+ last_day_timestamp = strtod(row[0],NULL);
+ }
+ }
+ mysql_free_result(result);
+#endif
+
+ if (last_day_timestamp > 0) {
+#ifndef CALC_MIDNIGHT
+ last_day_timestamp += 115200; // add 8 hours for offset - this should really be queried
+#else
+ last_day_timestamp -= local_offset; // From the database
+#endif
+ sprintf(query_buffer,"SELECT round(sum(value),2) FROM sdata WHERE timekey > %ld and fieldid = %d", last_day_timestamp,RAIN);
+ if (mysql_query(&mysql, query_buffer)) {
+ sprintf(death_msg,"err: rain last day query failed - exiting: %s\n\t --Query: %s\n", mysql_error(&mysql), query_buffer);
+ if (debug_level & 1) fprintf(stderr,"%s",death_msg);
+ return -1;
+ }
+ if (!(result = mysql_store_result(&mysql))) {
+ sprintf(death_msg,"err: rain last day store failed - exiting: %s\n", mysql_error(&mysql));
+ if (debug_level & 1) fprintf(stderr,"%s",death_msg);
+ return -1;
+ }
+ if ((mysql_num_rows(result)) > 0) {
+ row = mysql_fetch_row(result);
+ if (row[0] != NULL) {
+ *rainday = strtod(row[0],NULL);
+ if(debug_level & 1) fprintf(stderr,"rain since midnite %f\n ",*rainday);
+ // *rainday = *rainday * 100; // AFTER metric conversion, if needed.
+ item_count++;
+ *valid_data_flgs |= VALID_RAINDAY;
+ }
+ else {
+ *rainday = 0;
+ *valid_data_flgs |= VALID_RAINDAY; // None is valid...
+ if(debug_level & 1) fprintf(stderr,"no rain recorded in last 24 hours\n");
+ }
+ }
+
+ // release query buffer (where used)
+ mysql_free_result(result);
+
+ }
+ if (debug_level & 1)
+ fprintf(stderr,"info: success - Weather Data number of reading types %d\n",item_count);
+
+ return item_count;
+}
+
+
+
+
+
+/******************************************************************
+1/5/2003
+ SIGPIPE signal handler
+
+*******************************************************************/
+void pipe_handler(int sig) /* */
+{
+ signal(SIGPIPE, SIG_IGN);
+ if (sig == SIGPIPE) { // client went bye-bye
+ shutdown(*current, 2);
+ close(*current);
+ *current = -1;
+ if (debug_level & 1)
+ fprintf(stderr, "info: %s - TCP client timed out", progname);
+ }
+}
+
+
+
+
+
+/******************************************************************
+1/5/2003
+ SIGTERM signal handler
+
+*******************************************************************/
+void term_handler(int sig)
+{
+ if (debug_level & 1)
+ fprintf(stderr, "info: %s - ordered to DIE, complying", progname);
+
+ // release query buffer & close connection
+ mysql_free_result(result);
+
+ mysql_close(&mysql);
+
+ exit( 0 );
+}
+
+
+
+
+
+/******************************************************************
+1/2/2003
+ Coordinating MAIN point
+
+*******************************************************************/
+int main(int argc, char **argv)
+{
+ const char *flags = "Hhvnmrc:u:p:d:s:i:";
+ char WX_APRS[120];
+ char logstr[80];
+ int data_len = 0 ;
+ double winddir;
+ double windspeed;
+ double windgust;
+ double temp;
+ double rain1hr;
+ double rain24hr;
+ double rainday;
+ double humidity;
+ double airpressure;
+ unsigned int valid_data_flgs;
+ int Metric_Dat, dsts = 0;
+ int pid, s, fd[CONNECTIONS];
+ socklen_t clen = sizeof(struct sockaddr_in);
+ int *max = 0, c;
+ int not_a_daemon = 0, repetitive = 0, tcp_wx_port = PORT;
+ int i, index = 0;
+ struct sockaddr_in server, client;
+ struct in_addr bind_address;
+ fd_set rfds;
+ struct timeval tv;
+ int poll_interval = POLL_INTERVAL;
+ int dly_cnt = 1;
+ FILE *pidfile;
+ const char *pidfilename = "/var/run/db2APRS.pid";
+ char cmd[120];
+
+ struct option longopt[] = {
+ {"help", 0, 0, 'h'},
+ {"refresh", 0, 0, 'r'},
+ {"verbose", 0, 0, 'v'},
+ {"user", 1, 0, 'u'},
+ {"password", 1, 0, 'p'},
+ {"database", 1, 0, 'd'},
+ {"cport", 1, 0, 'c'},
+ {"sensor",1, 0, 's'},
+ {"nodaemon", 0, 0, 'n'},
+ {"interval",1, 0, 'i'},
+ {"metric",0, 0, 'm'},
+ {0, 0, 0, 0}
+ };
+
+ debug_level = 0;
+
+ strcpy(db.user,"meteo"); // set default values for database access
+ strcpy(db.name,"meteo");
+ memset(db.pswrd,0,15);
+
+ mysql_init(&mysql);
+
+
+ progname = strrchr(argv[0], '/');
+ if (progname == NULL)
+ progname = argv[0];
+ else
+ progname++;
+
+ while ((opt = getopt_long(argc, argv, flags, longopt, &index)) != EOF) {
+ switch (opt) { /* parse command-line or CGI options */
+ case 'r':
+ repetitive = 1;
+ break;
+ case 'v':
+ fprintf(stdout,"Verbose mode set:\n");
+ debug_level = 1;
+ break;
+ case 'u': // mysql username
+ strncpy(db.user,(char *)optarg,30);
+ break;
+ case 'p': // mysql password
+ strncpy(db.pswrd,(char *)optarg,15);
+ break;
+ case 'd': // mysql database name
+ strncpy(db.name,(char *)optarg,30);
+ break;
+ case 'n': /* do not fork and become a daemon */
+ not_a_daemon = 1;
+ break;
+ case 'c': /* port to use */
+ tcp_wx_port = strtol(optarg, NULL, 0);
+ break;
+ case 's': /* sensor number for outdoor data */
+ outdoor_instr = atoi(optarg);
+ break;
+ case 'i': /* polling interval in seconds */
+ poll_interval = atoi(optarg);
+ break;
+ case 'm': // Metric data from data base
+ Metric_Dat = 1;
+ break;
+ case '?':
+ case 'h':
+ case 'H':
+ usage(0);
+ break;
+ default :
+ usage(1);
+ }
+ }
+ if (debug_level & 1) {
+ fprintf(stdout,"Starting...");
+ if (repetitive) fprintf(stdout, " forever ");
+ else fprintf(stdout, " one pass only ");
+ fprintf(stdout," with database user=%s, password=%s, for database=%s\n",
+ db.user, db.pswrd, db.name);
+ if(not_a_daemon) fprintf(stdout," as a program ");
+ else fprintf(stdout," as a daemon ");
+ fprintf(stdout, " using TCP port %d\n",tcp_wx_port);
+ fprintf(stdout, "an with an outdoor sensor group number of %d\n",outdoor_instr);
+ }
+
+ if (!not_a_daemon) { /* setup has worked; now become a daemon? */
+
+ if ((pid = fork()) == -1) {
+ syslog(LOG_ERR, "can't fork() to become daemon: %m");
+ exit(20);
+ }
+ else if (pid) {
+ pidfile = fopen(pidfilename, "w");
+ fprintf(pidfile,"%d\n",pid);
+ fclose(pidfile);
+ exit (0);
+ }
+ syslog(LOG_ERR, "Started\n");
+ setsid();
+ for (i = 0; i < NOFILE; i++) if ( i != s) close(i);
+ }
+
+ // Data base connection
+
+
+ if (!(mysql_real_connect(&mysql, "localhost", db.user, db.pswrd, db.name, 0, NULL, 0))) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Data Base connect for user:%s to database:%s failed - exiting: \n\t%s\n",
+ db.user, db.name, mysql_error(&mysql));
+ exit(9);
+ }
+
+ server.sin_family = AF_INET;
+ bind_address.s_addr = htonl(INADDR_ANY);
+ server.sin_addr = bind_address;
+ server.sin_port = htons(tcp_wx_port);
+
+ if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+ if (debug_level & 1)
+ fprintf(stderr, "err: %s - no socket", progname);
+ exit(10);
+ }
+ /* <dirkx at covalent.net> / April 2001 Minor change to allow quick
+ * (re)start of deamon or client while there are pending
+ * conncections during the quit. To avoid addresss/port in use
+ * error. */
+ i = 1;
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) == -1) {
+ if (debug_level & 1)
+ fprintf(stderr, "err: %s - setsockopt", progname);
+ }
+ if (bind(s, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1) {
+ if (debug_level & 1)
+ fprintf(stderr, "err: %s - cannot bind to socket", progname);
+ exit(11);
+ }
+ if (listen(s, CONNECTIONS) == -1) {
+ if (debug_level & 1)
+ fprintf(stderr, "err: %s - listen", progname);
+ exit(12);
+ }
+
+ if (debug_level & 1)
+ fprintf(stdout,"Sockets UP.\n");
+
+ umask(0022);
+ for (i = 0; i < CONNECTIONS; i++) fd[i] = -1;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+
+ /* catch signals to close the database connection */
+ signal( SIGTERM, term_handler );/* termination */
+#if defined(SIGPWR) /* SIGPWR is linux centric */
+ signal( SIGPWR, term_handler ); /* power failure */
+#endif
+ if (debug_level & 1) fprintf(stdout,"Main Loop...\n");
+ dly_cnt = 2; // initial delay
+ do {
+ if(!(dly_cnt--)) {
+ dly_cnt = poll_interval; // Every 'dly_cnt' passes check for WX data update
+ dsts = Get_Latest_WX(&winddir,&windspeed,&windgust,
+ &temp,&rain1hr,&rain24hr,&rainday,&humidity,&airpressure, &valid_data_flgs);
+ if ( dsts < 0 ) {
+ if (debug_level & 1) fprintf(stderr, "err: Get_Latest returned %d\n",dsts);
+ syslog(LOG_ERR,death_msg);
+ exit(dsts);
+ }
+ // If no new data, make no new string either...
+ if(dsts)
+ {
+ data_len = APRS_str(WX_APRS, last_datetime, winddir,windspeed,windgust,
+ temp, rain1hr, rain24hr, rainday, humidity, airpressure,
+ valid_data_flgs,Metric_Dat);
+
+ if (!data_len) {
+ if (debug_level & 1)
+ fprintf(stderr, "err: WX info formatting problem!");
+ syslog(LOG_ERR,"WX Data format error\n");
+ exit(13);
+ }
+ } else if (debug_level & 1)
+ fprintf(stderr,"Found no new data this pass...\n");
+ }
+ FD_ZERO(&rfds);
+ FD_SET(s, &rfds);
+ if (select(s + 1, &rfds, NULL, NULL, &tv) > 0) {
+ for (current = fd; (*current > 0) && (current < fd + CONNECTIONS - 1); current++);
+ if (current > max) max = current;
+ if ((*current = accept(s, (struct sockaddr *)&client, &clen)) != -1)
+ write(*current, WX_APRS, data_len);
+ }
+ if (dly_cnt == poll_interval) {
+ if (debug_level & 1) fprintf(stdout,"Updating clients:");
+ for (current = fd; current <=max; current++)
+ if (*current > 0) { // active socket
+ if (debug_level & 1) fprintf(stdout," #");
+ signal(SIGPIPE, pipe_handler);
+ write(*current, WX_APRS, data_len);
+ }
+ if (debug_level & 1) fprintf(stdout," done\n");
+ }
+ sleep(1);
+ } while (repetitive);
+
+ mysql_close(&mysql);
+
+ if (debug_level & 1) fprintf(stdout,"Exiting normally.\n");
+ syslog(LOG_ERR,"Terminated normally\n");
+ exit(0);
+}
diff --git a/Davis/src/defs.h b/Davis/src/defs.h
new file mode 100644
index 0000000..ad2dfa4
--- /dev/null
+++ b/Davis/src/defs.h
@@ -0,0 +1,14 @@
+
+// $Id: defs.h,v 1.9 2012/11/01 18:57:18 we7u Exp $
+//
+// Copyright (C) 2004 Bruce Bennett <bruts at adelphia.net>
+// Portions Copyright (C) 2004-2012 The Xastir Group
+//
+//
+// Dummy info here for now...
+//
+
+
+#define PORT 1313
+#define CONNECTIONS 20
+#define NOFILE 20
diff --git a/FAQ b/FAQ
new file mode 100644
index 0000000..91f41c5
--- /dev/null
+++ b/FAQ
@@ -0,0 +1,1270 @@
+ Xastir Frequently Asked Questions
+
+$Id: FAQ,v 1.89 2012/11/01 18:57:18 we7u Exp $
+
+The latest version of this FAQ is always available from the Xastir
+project's CVS repository on SourceForge, at
+<http://xastir.cvs.sourceforge.net/xastir/xastir/FAQ?&view=auto>.
+
+The Questions
+-------------
+
+1. Background
+
+ 1.1 What is Xastir?
+ 1.2 How and why was Xastir created?
+ 1.3 Why the name "Xastir"?
+ 1.4 OK, so how does Xastir compare to other APRS(tm) clients?
+ 1.5 How thoroughly tested is Xastir?
+ 1.6 Whom do I contact for support?
+ 1.7 Where can I submit Bug reports or feature requests?
+ 1.8 Is there any more information on Xastir?
+ 1.9 Where can I get Xastir?
+
+2. General Technical Questions
+
+ 2.1 "Why can't I...? Why won't...work?" What to do in case of problems
+ 2.2 How do I submit a patch to the Xastir Development Group?
+ 2.3 What's the best hardware/operating system/...
+ 2.4 Why isn't there a binary for my platform?
+
+3. Building Xastir
+
+ 3.1 Why do I get error messages when running "bootstrap.sh"?
+ 3.1a Why do I get strange warnings when I run bootstrap.sh?
+ 3.2 Why won't Xastir compile with my system's cc?
+ 3.3 I'm using gcc and I get some compilation errors, what is wrong?
+ 3.4 The linking stage is failing because it isn't linking in the
+ freetype library. What to do?
+ 3.5 During the linking stage, it's giving me "undefined reference to
+ `CompressImageColormap'". What to do?
+ 3.6 Some of the text looks strange, writes over itself and other
+ user interface weirdness occurs. Why?
+ 3.7 Why isn't ImageMagick recognized and used during Xastir's
+ "configure" stage?
+ 3.8 Why do I get an error now when trying to do a "cvs update"?
+ 3.9 Why does compilation of map_geo, map_WMS or map_tiger fail with "invalid operands to binary <<" errors?
+
+4. Running Xastir
+
+ 4.1 Why do I get wrong texts in menus or other places when using a
+ non-English language file?
+ 4.2 I run Xastir under Linux, and I get an error about loading a shared
+ library.
+ 4.3 I run Xastir under Linux, and try to set up an ax25 device, but get a
+ "Hard Fail" error on the interface. There is a "permission denied" error
+ in the terminal from which I started Xastir.
+ 4.4 I run Xastir, and get on the air, but nobody else sees me on their screens.
+ 4.5 I run Xastir, and get on the air, but none of the other stations
+ appear on my screen?
+ 4.6 Who is this APX190 guy who all my stuff is getting sent to? Who are these
+ RELAY, WIDE and TRACE people digipeating packets, and why are they putting
+ different callsigns in the fields where their names used to be? Why
+ doesn't anyone answer me when I connect to them? HELP!!!
+ 4.7 When weather alerts come in, the counties on my map don't highlight.
+ 4.8 I have geoTIFF support compiled and working, but when I select a map, it
+ gives me a -38 error converting the datum, and it doesn't display in the
+ right place.
+ 4.9 Xastir runs slowly/loads maps slowly.
+ 4.10 I installed a new version of lesstif, but the help menu shows the old
+ version.
+ 4.11 Why does Xastir seg-fault sometimes when indexing or loading
+ geoTIFF images?
+ 4.12 Why doesn't Xastir run on RedHat 9.0 properly?
+ 4.13 Why do I see "Character '\55' not supported in font"?
+ 4.14 Why do I see strong blue tinting for the maps?
+ 4.15 My config file got munged. How do I recover?
+ 4.16 Why can't I set my position in Xastir correctly?
+ 4.17 Why do I get black map images when I use ImageMagick?
+ 4.18 Why does my MacOSX machine w/USB->Serial adapters hang?
+ 4.19 Why do NumLock/ScrollLock/CapsLock interfere with mouse/keyboard operation?
+ 4.20 How to I redirect serial ports from one computer to another?
+ 4.21 I have Festival compiled in, but I can't get any speech, why?
+ 4.22 ImageMagick gives me: "no decode delegate", why?
+ 4.23 How do I get through an http proxy server with Xastir in
+ order to fetch maps?
+ 4.24 Can I run multiple copies of Xastir at once?
+ 4.25 Why doesn't Terraserver work for some locations?
+ 4.26 Some station or config settings are not getting saved, why?
+ 4.27 Why are my colors messed up when running via VNC?
+ 4.28 Why are the labels missing in the Configure->Timing dialog?
+ 4.29 Xastir can't find "xastir.rgb" or some other file. What's wrong?
+ 4.30 Why can't I see station trails as stations move around?
+ 4.31 Why don't the maps I installed show up in the Map Chooser?
+ 4.32 Dialogs are tiny bullet-shaped windows with no handles. Why?
+ 4.33 Fedora 12 right-click menus don't work.
+ 4.34 What about using Xastir with a TNC-X with built-in USB on a Mac?
+ 4.35 Why do I get "Bitmap not found? /usr/share/xastir/symbols/2x2.xbm"
+
+5. Features
+
+ 5.1 Why doesn't Xastir include <insert your feature here>?
+
+ 5.2 Why doesn't Xastir digipeat packets sent to the RELAY or
+ WIDE1-1 aliases?
+
+ 5.3 How do I take a snapshot of my current view?
+
+ 5.4 What is that yellow circle on my map?
+
+ 5.5 How can I restart Xastir remotely/from a script/command-line?
+
+
+The Answers
+-----------
+
+1. Background
+
+ 1.1 What is Xastir?
+
+
+ Xastir is an APRS(tm) client program that uses amateur radio and Internet
+ services to convey GPS mapping, weather, and positional data in a graphical
+ application. It has been developed by and for amateur radio enthusiasts to
+ provide real-time data in an easy to use package.
+
+ 1.2 How and why was Xastir created?
+
+ There were already several APRS(tm) client programs available to the
+ Mac/DOS world when Frank Giannandrea, KC2GJS decided to develop
+ a Unix client using X Window's and the Motif/LessTiff widget set.
+ From its meager beginnings, Xastir is now a very robust client that
+ meets the needs of the Ham community.
+
+ 1.3 Why the name Xastir?
+
+ Xastir is an acronym for X Amateur Station Tracking and Information
+ Reporting. Besides it sounds much cooler that those other names ;)
+
+ 1.4 OK, so how does Xastir compare to other APRS(tm) clients?
+
+ Being actively developed by and for Hams, Xastir is constantly being
+ improved upon to reflect the changing state of APRS(tm). Xastir has
+ all the functionality you would find in any other APRS(tm) client,
+ from any OS, and quite possibly some unique features.
+
+ 1.5 How thoroughly tested is Xastir?
+
+ Xastir is currently in use by hundreds of Hams from around the world.
+ The Xastir Group maintains rigorous standards before releasing new
+ versions of our client. When bugs do show up, we release patches and
+ new versions as soon as they are available.
+
+ 1.6 Whom do I contact for support?
+
+ This FAQ may answer many of users frequent questions. However, there are
+ two active mailing lists that users could use to help answer any other
+ questions. Both mailing list are by subscription only and can be accessed
+ through the Xastir web-site. See the top of this document for the
+ addresses. You must be subscribed in order to post messages.
+
+ 1.7 Where can I submit Bug reports or feature requests?
+
+ The mailing lists are a good place to bring up bugs or feature requests.
+ Note that you must be subscribed in order to post messages. See above.
+
+ Another good place to document the request or bug in a more permanent
+ manner is the sourceforge tracker. There are separate bug and feature
+ request trackers, both listed at the Xastir project page,
+ http://sourceforge.net/projects/xastir/
+
+ 1.8 Is there any more information on Xastir?
+
+ See the main Xastir web-site for more information. See the top of
+ this document for the addresses.
+
+ 1.9 Where can I get Xastir?
+
+ Source code and binaries for several popular Linux distributions is
+ available through the Xastir web-site
+
+
+2. General Technical Questions
+
+ 2.1 "Why can't I...? Why won't... work?" What to do in case of
+ problems.
+
+ If are having trouble running the Xastir software:
+
+ 1. Check the FAQ!
+
+ The latest version of the Xastir FAQ can be found on the
+ Xastir web-site. See the top of this document for the
+ addresses.
+
+ 2. Ask on the "xastir" mailing list.
+
+ Many Xastir users and developers can be found roaming its
+ virtual halls, so it is suggested that you seek wisdom there.
+ The chances are good that you'll get your question answered
+ there. You must be subscribed in order to post messages.
+
+ 2.2 How do I submit a patch to the Xastir Development Group?
+
+ The Xastir Development Group encourages patches from outside developers.
+ There are two main "types" of patches: small bug fixes and general
+ improvements. Improvements, modifications, and additions should
+ follow the instructions below:
+
+ In general, the first course of action is to be a member of the
+ "xastir-dev" mailing list. This indicates to the Group that you are
+ closely following the latest developments. Your patch file should be
+ generated using either 'diff -c' or 'diff -u' against the latest CVS
+ tree. To submit your patch, send email to the "xastir-dev" mailing list
+ with a Subject: line that starts with [PATCH] and includes a general
+ description of the patch. In the body of the message, the patch should be
+ clearly described and then included at the end of the message. If the
+ patch-file is long, you can note a URL to file itself. Use of MIME
+ enclosures/attachments should be avoided.
+
+ Be prepared to respond to any questions about your patches and possibly
+ defend your code. If your patch results in a lot of discussion, you
+ may be asked to submit an updated patch that incorporates all changes and
+ suggestions.
+
+ 2.3 What's the best hardware/operating system?
+
+ Anything that works for "you".
+
+ 2.4 Why isn't there a binary for my platform?
+
+ The developers make sure that the software builds and works correctly on
+ the platforms available to them; this does not necessarily mean that
+ your platform is one of them. In addition, the Xastir Project is primarily
+ source oriented, meaning that the distributing valid and build-able source
+ code is the purpose of a release, not making sure that there is a binary
+ package for all of the supported platforms.
+
+
+3. Building Xastir
+
+ 3.1 Why do I get error messages when running "bootstrap.sh"?
+
+ The xastir build procedure requires automake 1.6.3 or later and
+ autoconf 2.53 or later. Using anything older than those will
+ not work.
+
+ To be very sure of what version of autoconf and automake you're using
+ please examine the output of "automake --version" and "autoconf --version"
+ Do not trust your system's package management software to tell you what
+ version is installed. Some systems install more than one different
+ version of autoconf/automake and you can't be sure which one you're using
+ unless you look at the actual version number reported by the tools
+ themselves.
+
+ Worse still, some systems install multiple versions of autoconf
+ and automake and name them in ways that confuses everything
+ (e.g. "automake19" or "autoconf253"). If that's the case on your system,
+ you could either edit bootstrap.sh by hand to force it to find the right
+ ones (adding paths or suffixes or whatever it takes), or you could just
+ end-run the process and download the source code for a suitable version
+ of automake and autoconf from www.gnu.org, use "--prefix=" options when
+ configuring both of them, build them, and install them into
+ someplace your system won't care about. For example, assuming you've
+ untar'ed, say automake-1.6.3 and autoconf-2.57 into the current
+ directory, and that xastir lives in your directory as /home/me/src/xastir:
+ cd automake-1.6.3
+ ./configure --prefix=/home/me/src/xastir
+ make install
+ cd ../autoconf-2.57
+ ./configure --prefix=/home/me/src/xastir
+ make install
+ cd /home/me/src/xastir
+ export PATH=/home/me/src/xastir/bin:$PATH
+ ./bootstrap.sh
+
+ This will completely bypass any odd version of automake and autoconf that
+ your system might use, and will insulate you from incompatible changes
+ in those installed tools if you upgrade your OS.
+
+ 3.1a Why do I get strange warnings when I run bootstrap.sh
+
+ The various configure.ac, acinclude.m4, and Makefile.am files that are used
+ by Xastir's autoconf'd build process were designed for automake 1.6.3
+ and autoconf 2.53. Using a much more recent version than those could
+ result in warning messages because the tools aren't strictly backward
+ compatible. Most of these warnings are harmless.
+
+ 3.2. Why won't Xastir compile with my system's cc?
+
+ If Xastir won't compile on your system, it is probably due to
+ one of the following causes:
+
+ - The configure script doesn't recognize your system environment.
+
+ This might be either because it's completely unknown or because
+ the specific environment (include files, OS version, etc) isn't
+ explicitly handled. If this happens, you may need to port the
+ software to your OS yourself.
+
+ - Your systems C compiler is garbage.
+
+ Some operating systems include a default C compiler that is either
+ not ANSI C-compliant or suffers from other deficiencies. The
+ usual recommendation in cases like this is to acquire, install,
+ and use gcc.
+
+ - Your include files may be confused.
+
+ In some cases, we have found that a compiler installation or system
+ upgrade has left the C header files in an inconsistent state. Make
+ sure that your include directory tree is in sync with the compiler
+ and operating system.
+
+ - You haven't installed all the necessary libraries and include files.
+
+ Xastir depends on at least the X, and Motif or LessTif include files.
+ Be sure these are installed before trying to compile the application.
+ Many Linux distributions name these packages <packagename>-dev or
+ <packagename>-devel.
+ NOTE: If you installed ImageMagick from a binary distribution, it will be
+ dependent on the shared libraries for the various graphics formats
+ installed on system on which it was compiled. Be sure you have these same
+ libraries installed, or you'll get a link error.
+ NOTE: The ImageMagick-devel package included with RedHat 8 is missing
+ some files needed for Xastir. The version in the beta directory on
+ RedHat's ftp site works.
+
+ A message like "*** Cannot find Motif include files" either means that
+ you are missing the development package for Motif/OpenMotif/Lesstif, or
+ that it is installed in a place where configure can't find it. It is
+ recommended that you use Motif or OpenMotif instead of Lesstif, as you'll
+ have few problems with those libraries. For SuSE 9.0, install the
+ "openmotif-libs", "openmotif-devel", and "openmotif" packages. Other
+ distributions have similar naming. If you have the Motif libraries and
+ headers installed in a place where Xastir doesn't look for them, see
+ the references to the "--with-motif-includes" and
+ "--with-motif-libraries" configure options in the INSTALL file.
+
+ - Your operating system or compiler may be out of version.
+
+ Software vendors issue new releases for a reason; sometimes to add
+ functionality, but more often to fix bugs that have been
+ discovered. Try upgrading your compiler and/or your operating
+ system.
+
+ 3.3 I'm using gcc and I get some compilation errors, what is wrong?
+
+ GCC parses your system header files and produces a modified subset which
+ it uses for compiling. This behavior ties GCC tightly to the version of
+ your operating system. So, for example, if you were running IRIX 5.3 when
+ you built GCC and then upgrade to IRIX 6.2 later, you will have to
+ rebuild GCC. Similarly for Solaris 2.4, 2.5, or 2.5.1 when you upgrade
+ to 2.6. Sometimes you can type "gcc -v" and it will tell you the version
+ of the operating system it was built against.
+
+ If you fail to do this, then it is very likely that Xastir will fail to
+ build. One of the most common errors is with readv, writev, or uio.h.
+ This is not a bug with Xastir. You will need to re-install GCC.
+
+ 3.4 The linking stage is failing because it isn't linking in the
+ freetype library. What to do?
+
+ This is, yet again, an ImageMagick problem. ImageMagick as
+ installed on some systems needs this library linked in. The
+ "Magick-config" script is supposed to supply a list of all of the
+ libraries that ImageMagick needs, but evidently they forgot one.
+ To get around this problem, you can add "-lfreetype" to the link
+ line to get the compile to complete.
+
+ 3.5 During the linking stage, it's giving me "undefined reference to
+ `CompressImageColormap'". What to do?
+
+ This is, yet again, an ImageMagick problem. ImageMagick decided to change
+ their API on us again. Newer releases of Xastir work around this problem
+ by checking the version of ImageMagick you have and changing the function
+ call to match.
+
+ 3.6 Some of the text looks strange, writes over itself and other
+ user interface weirdness occurs. Why?
+
+ This has been seen to occur due to bugs in some versions of LessTif.
+ You may want to try OpenMotif instead if it is available for your
+ distribution. One caveat that was found on Slackware 8.1 is the need
+ to delete all the text in the /usr/X11R6/lib/X11/config/host.def file
+ otherwise it still refers to the LessTif installation.
+
+ 3.7 Why isn't ImageMagick recognized and used during Xastir's
+ "configure" stage?
+
+ You might have forgotten to install both ImageMagick and the
+ ImageMagick-devel RPM. Another possibility is that your particular RPM's
+ might not contain all of the library dependencies that you need, like
+ libcms or zlib. Check carefully through "config.log" to see if the
+ ImageMagick detection code says something like: "ld: cannot find -llcms",
+ "ld: cannot find -lz", or "ld: cannot find -ljpeg". Install the additional
+ libraries that it needs, and perhaps development packages for them as well.
+ NOTE: If the "spec" file for the ImageMagick/ImageMagick-devel RPM's had
+ the proper dependencies listed, you would have been asked to install all of
+ the dependent libraries before you could have even installed the
+ ImageMagick RPM's. Encourage your vendor to fix the "spec" files for those
+ RPM's to include all dependencies.
+
+ 3.8 Why do I get an error now when trying to do a "cvs update"?
+
+ SourceForge changed things around a bit on Apr 29th, 2004. The changes
+ they made broke CVS for everyone. The error message you get may look like
+ the following:
+
+ "Unknown host: cvs.xastir.sf.org"
+
+ Luckily the fix is simple. Run these commands from the top directory where
+ you have the Xastir sources:
+
+ find -name Root -path \*CVS\* -exec perl -pi.bak -e's/cvs.xastir.sf.net/cvs.sf.net/' \{\} \;
+ find -name Root -path \*CVS\* -exec perl -pi.bak -e's/cvs.xastir.sourceforge.net/cvs.sf.net/' \{\} \;
+
+ Okay, are we having fun yet? They changed things again for us
+ on May 12, 2006. We now want this as the name of the CVS server
+ in the CVS/Root files: "xastir.cvs.sourceforge.net", so the perl command
+ to use after that date has become:
+
+ find -name Root -path \*CVS\* -exec perl -pi.bak -e's/cvs.sf.net/xastir.cvs.sourceforge.net/' \{\} \;
+
+
+ 3.9 Why does compilation of map_geo, map_WMS or map_tiger fail with "invalid operands to binary <<" errors?
+
+ This is a problem with ImageMagick. In short, your ImageMagick
+ installation has been built with an option incompatible with
+ Xastir.
+
+ New versions of ImageMagick include experimental support for High
+ Dynamic Range Images (HDRI). This support changes the data type of
+ a Quantum (pixel value) from an 8- or 16-bit integer quantity to a
+ floating point. Xastir assumes that all pixel values are integer
+ types, and uses operations on those values based on that
+ assumption.
+
+ You have two choices for getting around this issue: rebuild
+ ImageMagick without HDRI support, or use GraphicsMagick instead.
+
+4. Running Xastir
+
+ 4.1 Why do I get wrong texts in menus or other places when using a
+ non-English language file?
+
+ The development is done mainly with the English language file, so
+ other languages may not be up to date.
+
+ Those texts like IC>PULDNMBC02 are placeholders for missing entries
+ in the language file. You can add the local meaning of that string
+ in the English language file to your language file. And send it to
+ the Xastir development team...
+
+ 4.2 I run Xastir under Linux, and I get an error about loading a shared
+ library.
+
+ Xastir uses many shared libraries, including lesstif, and perhaps libax25,
+ libproj, libtiff, libgeotiff, libz, libjpeg, etc. These errors indicate
+ ld.so, the Linux dynamic linker, can't find the shared libraries.
+ * First, check that all the libraries are installed. Check the INSTALL
+ file for the locations to get these libraries if you've accidently removed
+ one of them.
+ * Run "ldd /usr/local/bin/xastir". This will print out a list of libraries
+ that Xastir is looking for and the locations they are expected to be at.
+ * Check that the locations of the libraries are in /etc/ld.so.conf. This
+ should probably be set up by your Linux distribution, but if you've
+ added new library directories after install, you'll need to add them here.
+ This is most applicable to lesstif which installs its libraries in
+ non-standard locations. Read the lesstif installation instructions for
+ more information on this. (Very recent versions create symlinks in
+ /usr/local/lib, so you probably won't need to do anything aside from
+ running ldconfig.)
+ * If you had a libc5 system and hand upgraded it to libc6, and are
+ attempting to link against both libc5 and libc6 built libraries at once,
+ stop now and recompile all your libraries against libc6. The dynamic
+ linkers are different for libc5 and libc6 programs, and linking against
+ libraries built with both versions is bound to cause trouble. This setup
+ has caused many people lots of headaches. Just upgrade your distribution.
+
+ 4.3 I run Xastir under Linux, and try to set up an ax25 device, but get a
+ "Hard Fail" error on the interface. There is a "permission denied"
+ error in the terminal from which I started Xastir.
+
+ As mentioned in INSTALL and helpfile, Xastir must be setuid root to use
+ Linux ax25. This is required because Xastir needs the ability to edit its
+ source callsign, and use other advanced options that the Linux ax25 stack
+ restricts to root.
+
+ 4.4 I run Xastir, and get on the air, but nobody else sees me on their
+ screens.
+
+ From a software standpoint, check that you have transmitting enabled
+ on your interface, and that the disable transmission "all" and "my
+ position" options in the Interfaces menu are not enabled. Check that ALTNET
+ support in File|Configure|Defaults isn't enabled.
+
+ Also check that your digipeater path is set reasonably; other
+ hams in your area could probably help with this, as the exact settings
+ depend on your setup and on your area's network. The other possibilities
+ are hardware problems: Is the output level on your TNC or soundcard
+ correct? Is PTT on your radio getting triggered? Is your TXdelay set
+ reasonably? All of these possibilities are beyond the scope of this FAQ.
+ An easy way to determine if your hardware works correctly is to try it on
+ conventional packet.
+
+ 4.5 I run Xastir, and get on the air, but none of the other stations
+ appear on my screen?
+
+ Did you set up your TNC startup files correctly to remove any extra data
+ from the packet headers? Are you using the correct startup file? See
+ INSTALL.
+
+ Check that the Display Incoming Data windows is actually showing
+ data coming in. If not, check your radio's volume/squelch
+ levels and your cabling, both between the radio/TNC and between
+ the TNC/Computer.
+
+ Check that ALTNET support in File|Configure|Defaults is disabled.
+ If activated, it only shows stations transmitting TO the callsign
+ listed in the box. I sometimes set it to APX or APX190 in order to
+ see who's running Xastir/who's running the _latest_ Xastir. Set
+ it to "WEIRD" and you'll only see those transmitting to "WEIRD".
+
+ Check all of your Stations|Filter Data and Stations|Filter Display
+ settings. "Select Stations" and "Display Symbols" must be selected.
+
+ If you are using an older version of Xastir, Qxx packets are considered
+ invalid. This is a newer addition to APRS(tm), and recent Xastir releases
+ decode this correctly.
+
+ 4.6 Who is this APX190 guy who all my stuff is getting sent to? Who are
+ these RELAY, WIDE and TRACE people digipeating packets, and why are
+ they putting different callsigns in the fields where their names used
+ to be? Why doesn't anyone answer me when I connect to them? HELP!!!
+
+ You must be used to conventional packet. APRS(tm) is inherently different
+ from conventional packet. There are many online resources that explain the
+ basics of APRS(tm), but I'll try to summarize here. APRS(tm) is an
+ unconnected protocol, where you broadcast UI (unnumbered information)
+ packets to the world. Since these packets aren't directed toward a
+ specific user, the TO address of the packet is simply a summary of the
+ software you're running. AP=APRS(tm), X=X Windowing System, 110=Version 1.10.
+
+ RELAY, WIDE, TRACE, WIDEn-N, and TRACEn-N are aliases for generic
+ digipeaters, although all but the WIDEn-N variants are now deprecated
+ (should no longer be used). Some base stations have their TNC's configured
+ to digipeat with the call of "WIDE1-1" (we used to use "RELAY" for these,
+ but "WIDE1-1" has now taken its place). Newer digipeater software
+ substitutes their own call for "WIDEn-N" to enable people to see who
+ digipeated them. See the README.Getting-Started file for a bit more info
+ on paths, including recommended paths for different types of stations.
+
+ To talk to people, you send them messages from within Xastir, you don't
+ "call" them like on typical packet. Most TNC's are set up to ignore classic
+ packet "calls" so you won't get any response. When sending messages to
+ people in your area, do check in their comments that they are people and
+ not stand-alone digipeaters or similar. ;) Thanks to the worldwide APRSserv
+ Internet system, you can send messages to any APRS(tm) user anywhere in the
+ world, provided they're within range of an Igate. Most users are; if your
+ area isn't and you have a 24/7 Internet connection, Xastir can be your
+ area's Igate! (Please check your local laws, as Igating is illegal in some
+ countries!) There are also experimental systems for sending messages via
+ amateur radio satellites, but that is beyond the scope of this FAQ.
+
+
+ 4.7 When weather alerts come in, the counties on my map don't highlight.
+
+ First of all, did you download and install the new shapefile weather maps
+ as described in the INSTALL file? (Running scripts/get-NWSdata automates
+ this somewhat for you now)
+
+ Did you compile with shapefile support?
+
+ Check that Map|Enable Weather Alerts is enabled, and "Map|Disable All Maps"
+ is _not_ selected .
+
+ 4.8 I have geoTIFF support compiled and working, but when I select a map,
+ it gives me a -38 error converting the datum, and it doesn't display in
+ the right place.
+
+ Did you install libgeotiff before libproj? This error you'll see if you
+ ignored the note in the INSTALL file about this. Recompile libgeotiff and
+ the problem should vanish.
+ If this is not the case, check the datum of the geoTIFF file, and make
+ sure it is one of the ones supported by Xastir. The listgeo program
+ included with libgeotiff can tell you the datum of a map.
+
+ 4.9 Xastir runs slowly/loads maps slowly.
+
+ There are many things that can effect the speed of your Xastir software,
+ including the speed of the computer, the amount of memory available, the
+ number of active interfaces, the complexity/type/number of maps you use,
+ and the options you used to compile Xastir and helper libraries. The
+ developers aren't aware of any specific cases in which there would be
+ performance problems; generally these are limitations of your computer.
+ Xastir, when using only basic maps, runs reasonably on a Pentium 60. If
+ you use higher detail maps, such as the tiger line maps suggested in
+ README.MAPS, you'll need a faster computer to be able to load the maps
+ quickly. Also be sure you have a few Megabytes of memory available for
+ Xastir, because paging to disk decreases speed rapidly. If you have the
+ Internet interface, as well as TNC's and weather stations all active
+ at the same time, you'll see a slowdown on a slower computer. Also, if you
+ compiled Xastir or libax25/libtiff/libgeotiff/etc with debugging (-g),
+ recompile these software without debugging and with optimization ON (-O2).
+
+ 4.10 I installed a new version of lesstif, but the help menu shows the old
+ version.
+
+ The help menu shows the version of lesstif that Xastir was compiled with,
+ not necessarily the version you're running now. Assuming you compiled it
+ with the new version, check that the new version is the only copy
+ installed. If you install in /usr/local/LessTif/, the default location,
+ be sure you remove any older version from /usr/LessTif/ or
+ /usr/X11R6/LessTif/, as some distributions use those locations.
+
+ 4.11 Why does Xastir seg-fault sometimes when indexing or loading
+ geoTIFF images?
+
+ The geoTIFF code must use an API in the TIFF code that is non-public.
+ Unfortunately this means that the geoTIFF code must know more about TIFF
+ than the normal application using the TIFF library. If the private TIFF
+ include file included with the geoTIFF code doesn't match your installed
+ version of TIFF, you can run into seg-fault problems.
+
+ Solutions for this include: 1) Installing TIFF from sources, or
+ 2) Grabbing the sources for your installed version of TIFF, copying one
+ include file from TIFF into the geoTIFF sources and recompiling/installing
+ geoTIFF. Either of these solutions will make the geoTIFF code recognize
+ and use the proper structures in TIFF should prevent the seg-faulting.
+
+ In the future we hope that either the geoTIFF code will become part of
+ the TIFF code, or that the private TIFF API will become public. Either
+ of these changes should fix this problem for good.
+
+ 4.12 Why doesn't Xastir run on RedHat 9.0 properly?
+
+ The RH kernels have implemented the new(er) New Posix Threading Library
+ (NPTL) as well as back-ported many of the new bells and whistles set to
+ appear in the 2.6.x kernels. You might experience a great improvement
+ for apps that are heavily threaded. NPTL is supposed to be backward
+ compatible but we have seen apps that have had problems. You can revert
+ back to the older LinuxThreads implementation by setting the environment
+ variable:
+
+ LD_ASSUME_KERNEL=<kernel-version>
+
+ in a shell before starting the app The following versions are available:
+
+ - 2.4.1 - Linuxthreads with floating stacks
+
+ - 2.2.5 - Linuxthreads without floating stacks
+
+ or, you can disable NPTL altogether for dynamically linked
+ applications by using 'nosysinfo' as a boot time option.
+
+ 4.13 Why do I see "Character '\55' not supported in font"?
+
+ This message and similar have to do with localization and OpenMotif/
+ Lesstif. For most of us this is a benign message and can be ignored.
+ If you simply can't stand it any more set LANG="C" or LANG="en_US". In
+ RH 9 the default LANG is set to en_US.UTF-8 and this is where the warnings
+ are coming from.
+
+ A quick way to address this on RedHat 8 and 9 is to edit your
+ /etc/sysconfig/i18n config file. I believe the original file looks
+ like:
+
+ LANG="en_US.UTF-8"
+ SUPPORTED="en_US.UTF-8:en_US:en"
+ SYSFONT="latarcyrheb-sun16"
+
+ Change the "LANG=" line to:
+
+ LANG="en_US"
+
+ and reboot.
+
+ With the original setting you get some weird character mappings. For
+ example, running "man ls", all of the dashes (-) disappeared from my
+ screen until I changed the LANG setting.
+
+ 4.14 Why do I see strong blue tinting for the maps?
+
+ Strong blue (or perhaps other color) tinting of the image may be
+ due to running the display over a Hummingbird eXceed session.
+ Try running it locally and you should see the proper colors.
+ Try changing the eXceed session to use more bits of color.
+
+ 4.15 My config file got munged. How do I recover?
+
+ Xastir saves previous revisions of the config file as
+ "xastir.cnf.1" through "xastir.cnf.3". Look for them in the
+ ~/.xastir/config directory. Kill Xastir, then copy one of the
+ backup files to "xastir.cnf" in order to recover your previous
+ settings. Xastir will use the "xastir.cnf" file the next time
+ it starts up.
+
+ Older Xastir versions saved only one copy of the config file as
+ "xastir.bak".
+
+ 4.16 Why can't I set my position in Xastir correctly?
+
+ If your LC_NUMERIC environment variable is set to something other than
+ "C", it can cause commas and periods to be swapped when Xastir tries to
+ read/write files. We've tried to address this in the latest Xastir code,
+ forcing LC_NUMERIC="C" inside Xastir itself. Another solution is to type
+ this when starting Xastir (from a BASH shell. If you use another type of
+ shell, modify the syntax accordingly):
+
+ export LC_NUMERIC="C"; xastir &
+
+ 4.17 Why do I get black map images when I use ImageMagick?
+
+ There was a bug in versions of Xastir prior to the CVS version of
+ 4 December 2009 that caused this problem if ImageMagick (or
+ GraphicsMagick) were compiled with QuantumDepth not equal to 16
+ (GraphicsMagick now defaults this parameter to 8). The bug was
+ fixed, and current versions of Xastir should not have this
+ problem. If you are running an older version than 4 December
+ 2009, updating will likely solve this problem for you.
+
+ If you are running a version higher than 1.9.7 or a CVS version
+ checked out after 4 December 2009, then the problem lies
+ elsewhere. It may be due to bugs in your particular version of
+ ImageMagick, but more likely it's related to the color-depth of
+ your X-Server. If you are using 8-bit, 24-bit, or 32-bit
+ color-depth: Try 16-bit, which is the color-depth best supported
+ by the Xastir code.
+
+ 4.18 Why does my MacOSX machine w/USB->Serial adapters hang?
+
+ Use ports such as /dev/cu.usbserial0 for USB to serial adapters
+ on MacOSX.
+
+ 4.19 Why do NumLock/ScrollLock/CapsLock interfere with mouse/keyboard
+ operation?
+
+ Because they are treated as modifiers by Motif. Here's an FVWM2 document
+ (FVWM2 is a window manager) that talks about it:
+
+ http://www.fvwm.org/documentation/faq/index.php?theme=navigate
+
+ See section 5.5 of that document which talks about these keys. If you type
+ these commands and then restart your window manager it may take care of
+ your problem, but then those keys will be disabled and you won't be able to
+ use in other applications:
+
+ xmodmap -e "clear Lock"
+ xmodmap -e "clear Mod2"
+ xmodmap -e "clear Mod5"
+
+ 4.20 How to I redirect serial ports from one computer to another?
+
+ For Linux, try a program called "remserial". It works as a
+ client/server pair to do exactly what you want. Google should
+ find it for you. One user was able to use a spare serial port
+ on his windows box using "remserial" on the Linux computer and a
+ program called "serproxy" on the windows machine. Another one I
+ have to try for windows is comfoolery. See links below.
+
+ Another option is to use a Perl script on each end to do the
+ conversion.
+
+ Yet another is to use "netcat". "man nc" or "man netcat" should
+ tell you about it. It redirects tcpip data seamlessly under
+ Linux. On SuSE the docs for it are in
+ /usr/share/doc/packages/netcat. Try a command line like this:
+
+ cat /dev/ttyS0 | nc -l -p 3000
+ or
+ cat /dev/ttyS0 | netcat -l -p 3000
+
+ That should make a listening socket at port 3000 which listens
+ to the /dev/ttyS0 serial port. "telnet localhost 3000" should
+ show you any data coming in on that serial port. Connect Xastir
+ across the network to that listening socket to get the data.
+
+ If you want to put your GPS on a remote serial port, use the
+ gpsd daemon to do it.
+
+ if you wish to put your weather station on a remote serial port,
+ investigate using OWW (for Dallas weather stations), wx200d
+ daemon for some Radio Shack/Huger/Oregon Scientific weather
+ stations, or Meteo daemon for Davis weather stations.
+
+ You may also connect to a remote AGWPE instance for using remote
+ TNC's/soundcards. Note that AGWPE runs only on Windows.
+
+ Yet another which looks to be netcat recoded/extended: socat
+
+ Comfoolery: http://www.brianpoe.com/comfoolery/
+ Serproxy: http://freshmeat.net/projects/serproxy/
+ Serproxy: http://www.lspace.nildram.co.uk/freeware.html
+ Remserial: http://lpccomp.bc.ca/remserial/
+ Socat: http://www.dest-unreach.org/socat/
+
+
+ 4.21 I have Festival compiled in, but I can't get any speech, why?
+
+ a) You must start the Festival server daemon before starting Xastir.
+ Start it via this command :
+
+ festival_server &
+
+ b) If the server is running, but you get this: "festival_client:
+ connect to server failed", then you may have some tweaks to do
+ to your system files in order to allow Xastir (or anything else)
+ to connect to Festival. Try this first to see whether anything
+ can connect to Festival:
+
+ telnet localhost 1314
+
+ If the server is running properly it'll let you connect. If it
+ does, try typing:
+
+ (SayText "Hello, World")
+
+ If that doesn't work, check your audio mixer settings first, then
+ proceed to c) below:
+
+ c) Some people have an "/etc/hosts" file that has an incorrect
+ line for localhost. You should have a line which has 127.0.0.1
+ at the start, and has "localhost" somewhere on that line as well.
+ Like this:
+
+ 127.0.0.1 localhost localhost.localdomain
+
+ d) On one Debian box, it was an issue with "/etc/hosts.allow".
+ See "man 8 tcpd" or "man 5 hosts_access" for detailed info about
+ how to configure /etc/hosts.allow and /etc/hosts.deny. It's
+ part of the tcpwrappers stuff that allows you to configure which
+ hosts have access to which services on your system.
+
+ 4.22 ImageMagick gives me: "no decode delegate", why?
+
+ README.win32 has a bit of info about this one, as it most often happens
+ on Win32 systems. It has been seen on other systems as well though.
+ The short answer is that you may have to set the environment variable
+ "MAGICK_HOME" to the location where the ImageMagick modules reside.
+ This is only necessary if ImageMagick doesn't have the location
+ pre-compiled into it. The example for Win32 systems is:
+
+ export MAGICK_HOME=/usr
+
+ Added to the ~/.profile file, so that the BASH shell gets this defined
+ each time you log in. The location "/usr" will probably be different
+ on a non-Windows machine, so change the line above as required for your
+ system.
+
+ 4.23 How do I get through an http proxy server with Xastir in
+ order to fetch maps?
+
+ *) Install libcurl and/or wget.
+ *) Set the HTTP_PROXY and FTP_PROXY environment variables in
+ your ~/.profile file. Libcurl has additional options that
+ can be set: HTTPS_PROXY, GOPHER_PROXY, and ALL_PROXY.
+ *) Create and fill in the ~/.netrc and/or .wgetrc files with
+ proper values. Set the permissions on it so that only you
+ can read/write the file: "chmod 600 .netrc". Typical
+ contents of the file are shown below:
+
+ http_proxy = http://proxy.yoyodyne.com:18023/
+ ftp_proxy = http://proxy.yoyodyne.com:18023/
+
+ 4.24 Can I run multiple copies of Xastir at once?
+
+ Yes, but you must keep the configuration directories separate for
+ each copy by using a command-line flag. Xastir will create the new
+ config directory and fill it with defaults if it doesn't already
+ exist. Here's the method. Substitute your user name where it says
+ "<user>":
+
+ xastir & # starts up first Xastir copy against ".xastir" directory
+ xastir -c /home/<user>/.xastir2 & # starts up 2nd Xastir copy against ".xastir2" directory
+ xastir -c /home/<user>/.xastir3 & # starts up 3rd Xastir copy against ".xastir3" directory
+
+ To make the process easier if you use this method a lot, create
+ aliases by editing your .profile (This assumes you're running BASH
+ or Bourne shells):
+
+ alias xastir2='xastir -c /home/<user>/.xastir2 &'
+ alias xastir3='xastir -c /home/<user>/.xastir3 &'
+
+ After sourcing your new .profile (The command is ". .profile" from
+ your home directory) or logging out and back in again, you can type
+ "xastir2" or "xastir3" as a command to start up the additional
+ copies of Xastir.
+
+ Older methods, may still be useful at times:
+
+ Do this to allow more than one user to access your X display and to
+ create additional users, each capable of running one Xastir session:
+
+ xhost localhost
+
+ This lets other users on your machine use the X11 display.
+
+ Create another user (or two or three) using whatever facilities
+ your system uses to do this.
+
+ xterm & # Start up an xterm window in the background
+ su 2nduser. # su to one of your new usernames
+ xastir & # Start up Xastir as that user, in the background
+
+ Optional:
+ Set up your 1st Xastir instance with the server port enabled.
+ Connect the 2nd instance to localhost:2023. This way one Xastir
+ will get its feed from the other.
+
+ You can start up a third Xastir in the same manner, starting
+ with the "xterm &" command and then doing "su 3rduser" instead,
+ then "xastir &" as that third username.
+
+ Many Xastir sessions can all get their feed from one Xastir
+ session, or they can be connected to different TNC's or server
+ ports.
+
+ 4.25 Why doesn't Terraserver work for some locations?
+
+ Terraserver is based on the UTM coordinate system. If you're trying
+ to request map images that cross a UTM zone boundary, Terraserver
+ may not work at that location. Zoom in closer or pan left/right
+ in order to avoid this problem.
+
+ 4.26 Some station or config settings are not getting saved, why?
+
+ A few of the menu settings do not get saved. This is on purpose.
+ If you are having more serious troubles, like for instance your
+ station location setting isn't getting saved between Xastir runs,
+ check your LANG setting (see question 4.13 above).
+
+ 4.27 Why are my colors messed up when running via VNC?
+
+ VNC may have a different colormap or colordepth than the system Xastir is
+ running on. Here is one invocation that a user used which worked.
+ Substitute the appropriate parameters for your system of course:
+
+ vncserver :5 -name melecom -depth 24 -geometry 800x600 -pixelformat rgb565
+
+ 4.28 Why are the labels missing in the Configure->Timing dialog?
+
+ Some versions of the Lesstif widget set have this bug. Try
+ switching to a different version of Lesstif or switch to
+ OpenMotif and you should see the labels again. So that you can
+ actually operate Xastir, here's what you _should_ have seen:
+
+ On the left:
+ ------------
+ Posit TX Interval (min)
+ Object/Item TX Interval (min)
+ GPS Check Interval (sec)
+ Dead-Reckoning Timeout (min)
+ New Track Time (min)
+ RINO -> Objects Interval (min), 0=Disabled
+ Snapshot Interval (min)
+
+ On the right:
+ -------------
+ Station Ghosting Time (min)
+ Station Clear Time (hours)
+ Station Delete Time (days)
+ Serial Inter-Char Delay (ms)
+ New Track Interval (degrees)
+ Internet Map Timeout (sec)
+
+ A screenshot on the Wiki of this dialog:
+ <http://www.xastir.org/wiki/index.php/Notes:Timing_Slider_Dialog_Screenshot>
+
+ 4.29 Xastir can't find "xastir.rgb" or some other file. What's wrong?
+
+ This could be one of several things. We'll check them in order:
+
+ a) If you get this exact message:
+
+ "Error! can not find color file: /xastir/config/xastir.rgb"
+
+ Then it could be that you're not getting a variable defined on
+ the compile line. This text or similar should appear for each
+ file compiled:
+
+ -DXASTIR_DATA_BASE=\"/usr/local/share/xastir\"
+
+ If you're not seeing this, or the variable is defined to an
+ empty string or is otherwise incorrect, you may need to
+ upgrade/downgrade your autoconf or automake packages and rerun
+ the Xastir install starting at the "./bootstrap.sh" stage.
+
+ b) Did you run the "make install" stage as root or using "sudo"
+ after you compiled Xastir? If not, Xastir couldn't install
+ files it needs to run.
+
+ c) Another possible problem is a corrupt or very old
+ ~/.xastir/config/xastir.cnf file. Check for this by typing:
+
+ cd
+ mv .xastir .xastir.save
+ xastir
+
+ If it comes up ok this time, then either paths in your config
+ file are incorrect or the config file is corrupt. If there's no
+ change, go back to your original configuration by typing:
+
+ cd
+ rm -rf .xastir # NOTE: this will delete ~/.xastir and all contents!
+ mv .xastir.save .xastir
+
+ d) Yet another thing to check is the value in your LANG variable.
+ It should be either "en_US" or "C" for Xastir to read/write
+ config files correctly:
+
+ echo $LANG
+
+ If it is something else, start Xastir like this:
+
+ export LANG=en_US; xastir -geometry -0-0 &
+
+ You can create an alias in your shell for this so that you don't
+ have to remember to type it each time.
+
+ e) Perhaps you're trying to run an old Xastir executable that
+ was compiled with different paths, or you have an LSB-Xastir
+ installed and have compiled or installed Xastir in the normal
+ fashion as well. Type this to see where the executable is
+ trying to run from:
+
+ which xastir
+ -or-
+ whereis xastir
+
+ f) It's possible that your autoconf/automake packages need to be
+ upgraded or downgraded. These packages are somewhat version
+ dependent on each other, so it's likely that you'll have to do
+ this upgrade or downgrade as a pair for things to work correctly.
+ After the upgrade or downgrade, recompile Xastir starting at the
+ "./bootstrap.sh" stage so that the configure and Makefile
+ scripts are re-created.
+
+ ./bootstrap.sh
+ ./configure
+ make
+
+ Make sure that you now see a reasonable path for the
+ XASTIR_DATA_BASE variable on each compile line.
+
+ 4.30 Why can't I see station trails as stations move around?
+
+ Enable Station->Filter Display->Display Trail
+
+ File->Configure->Timing->"New Track Time" and "New Track Interval
+ should be set above zero. Defaults for these are 45 and 1
+ respectively.
+
+ If this problem and others occur, such as your latitude/longitude
+ getting lost between runs, this might indicate a problem with
+ your LANG variable. See question #4.26 above.
+
+ 4.31 Why don't the maps I installed show up in the Map Chooser?
+
+ Install the maps in the correct place, normally
+ "/usr/local/share/xastir/maps/" or subdirectories below there. If
+ running LSB-Xastir it's "/opt/Xastir/share/xastir/maps/".
+
+ Make sure the map directories and files have read permissions
+ for the user.
+
+ Select "Map->Configure->Index: Add New Maps", then check in Map
+ Chooser to see if the map is listed. If not, try the "Reindex
+ ALL Maps" option.
+
+ Verify that you have installed the map libraries necessary to
+ handle the types of maps you're wishing to use: "Help->About".
+ Also you can check the messages written to STDERR in the shell
+ you start Xastir from.
+
+ Check this file to see if map indexing found the file at all.
+ It's the same file that Map Chooser reads to display the map
+ selections:
+
+ ~/.xastir/config/map_index.sys
+
+ If the map is a raster map, you can check whether your installed
+ ImageMagick or GraphicsMagick can display the image.
+
+ For IM: display <filename>
+ For GM: gm display <filename>
+
+ If it's an internet-based map you're trying to download/display,
+ verify in the Xterm that you have internet maps enabled using
+ either libcurl or wget. Check manually whether curl or wget
+ (whichever Xastir is using) can fetch a remote file. Check
+ whether a file like ~/.xastir/tmp/map.gif or map.jpg shows up
+ after you try to fetch a file, even if Xastir doesn't display
+ it. See if one of the above "display" commands will display it
+ if so. Check the File->Configure->Timing dialog for the
+ "Internet Map Timeout" setting: Adjust it upwards if Xastir is
+ timing out fetching the remove map.
+
+ If all else fails, try removing the ~/.xastir directory and all
+ contents. Warning: This will cause you to lose all of your
+ personal Xastir configuration, including callsign, location,
+ bookmarks, map levels and other map settings, etc. Once you've
+ done this, verify that your LANG setting is either "C" or
+ "en_US", with no additional characters in there, then start
+ Xastir from that same shell with the correct LANG setting.
+ Xastir should index all of your maps on startup. After it is
+ complete, bring up the Map Chooser and all available maps should
+ be listed.
+
+ 4.32 Dialogs are tiny bullet-shaped windows with no handles. Why?
+
+ This is caused by an interaction between "Motif" and "compiz".
+ "compiz" is enabled in some versions of Ubuntu Linux with a
+ "Desktop Effects" menu item. They changed the default to *ON*
+ several releases ago. "compiz" is a window manager which
+ enables eye-candy effects such as animated window
+ opening/closing, 3-D effects, and so forth. To fix this
+ problem, turn *OFF* "Desktop Effects" which will disable
+ "compiz" and re-enable the default window manager.
+
+ 4.33 Fedora 12 right-click menus don't work.
+
+ This was a Fedora X11 bug and has been fixed. Do a "yum
+ update" on your system to get the latest Fedora fixes.
+
+ If you're having troubles with another OS, read this thread to
+ get some insight into the problem:
+ https://bugzilla.redhat.com/show_bug.cgi?id=543647
+
+ It appears to be a bug in the X11 server and can affect OpenMotif
+ and Lesstif apps. I didn't read every comment though. There were
+ definitely many dead-ends as they went along discussing it.
+
+ 4.34 What about using Xastir with a TNC-X with built-in USB on a Mac?
+
+ You will need the device drivers from FTDI, downloadable from their website at
+ http://www.ftdichip.com/Drivers/VCP.htm
+
+ Note: the TNC-X packet datarate is fixed at 1200 baud, however the serial
+ communication with the computer is configurable via internal jumpers. It's
+ been observed that setting the com port to 1200 baud results in a deaf TNC-X.
+ Setting the com port to 9600 baud works well, however.
+
+ 4.35 Why do I get "Bitmap not found? /usr/share/xastir/symbols/2x2.xbm"
+
+ The problem is that you probably have previously installed a binary version
+ of Xastir from your system's repository --- and Linux packages are set up
+ to install files in /usr (e.g. binaries to /usr/bin, libraries to /usr/lib/,
+ and supporting files to /usr/share). But CVS xastir, like almost all source
+ packages, installs to /usr/local (/usr/local/bin, /usr/local/lib,
+ /usr/local/share). When you de-installed your binary package and installed
+ the source version, it removed the /usr/ stuff and installed the files in
+ /usr/local/.
+
+ Your configuration files for Xastir still point to the old locations, and
+ Xastir is confused because files it's expecting aren't there.
+
+ You have two approaches to fix this:
+
+ 1) If you have not used Xastir a lot and don't have a whole lot of
+ custom configurations (map selections, interface properties, etc.) then
+ you can just move your ~/.xastir/config/xastir.cnf file and let Xastir
+ regenerate a default set-up. Many people here recommend that approach
+ because it's just a matter of one command:
+
+ mv .xastir/config/xastir.cnf .xastir/config/xastir.cnf_old
+
+ But this will blow away all your customizations, so it might not be the
+ best choice. Note that you can still glean information from the old
+ copy of the config file to help set up the new.
+
+ 2) Change all references to "/usr/" in your configuration files to "/usr/local".
+ Most of these will be in ~/.xastir/config/xastir.cnf so it's just a matter
+ of editing that one file and changing them all.
+
+ It is always an issue when you switch from a pre-compiled linux package to
+ a source build.
+
+5. Features
+
+ 5.1 Why doesn't Xastir include <insert your feature here>?
+
+ Probably because someone hasn't taken the time to write the feature or
+ enough people have complained loud enough that it wasn't there. The
+ feature set of Xastir is user/developer driven. So get busy!
+
+ 5.2 Why doesn't Xastir digipeat packets sent to the RELAY or
+ WIDE1-1 aliases?
+
+ If you're running serial-port connected TNC's, the "tnc-startup.*"
+ files that get installed in /usr/local/share/xastir/config should set up
+ your TNC to respond to these packets. Select Interfaces->Properties,
+ then select the interface, click Properties, then select the Setup
+ and Shutdown files at the bottom of that dialog. When an interface
+ is brought up the Setup file will be downloaded to the TNC.
+ "myalias WIDE1-1" is the command most TNC's accept for defining a
+ digipeating alias. That command or similar should be in the Setup file
+ that you use.
+
+ Use "myalias WIDE1-1" with the new path scheme discussed on
+ APRSSIG during early April, 2005: RELAY/WIDE/TRACE/TRACEn-n are
+ deprecated (should not be used).
+
+ If you're running kernel AX.25 interfaces, then you'll need to run
+ another package to handle digipeating on these interfaces, perhaps
+ digi_ned.
+
+
+ 5.3 How do I take a snapshot of my current view?
+
+ You can cause a snapshot to occur by enabling Snapshot in the File menu.
+ It takes a snapshot every five minutes starting immediately when the
+ togglebutton is first enabled. This means you can change views and
+ disable/enable to take an immediate snapshot each time as well.
+
+ You can also send a "SIGUSR1" signal from another process and Xastir
+ will take a snapshot. The feature was added so that someone could
+ press a button on a web page and cause Xastir to make a new snapshot.
+
+ For Example, from the shell you can do:
+
+ kill -SIGUSR1 `cat ~/.xastir/xastir.pid`
+
+ Snapshots will are stored under ~/.xastir/tmp/
+
+
+ 5.4 What is that yellow circle on my map?
+
+ Somewhere around a half-hour or an hour after you start Xastir with
+ a connected TNC, you will begin to see a yellow circle surrounding your
+ station at some zoom levels. This is your "ALOHA Circle,"
+ the circle containing approximately the number of stations that should
+ saturate your local APRS channel. See
+ http://web.usna.navy.mil/~bruninga/aprs/ALOHAcir.txt for details.
+ The short story is you should set your path so your packets don't
+ travel farther than this circle's radius.
+
+ This circle is shown when your station is in view and you are
+ zoomed out far enough to contain the circle in the viewport. Its
+ radius is recalculated once every half an hour from the stations
+ you've heard on RF. Stations you hear from internet servers or
+ other non-RF sources are not included in the calculation. The
+ circle can be turned off from the Station->Filter Display menu
+ but it will be enabled again each time you restart Xastir.
+
+ 5.5 How can I restart Xastir remotely/from a script/command-line?
+
+ Send a SIGHUP to the process. This will cause Xastir to save
+ its configs, exit, then restart with the same environment and
+ command-line parameters as it initially had.
+
+ For Example, from the shell you can do:
+
+ kill -SIGHUP `cat ~/.xastir/xastir.pid`
+
+ NOTE: This SIGHUP trick doesn't work if you've configured
+ Xastir with profiling ( "./configure --with-profiling" ).
+
+
+----------------------------------------------------------------
+
+APRS(tm) is a Trademark of Bob Bruninga
+
+If you find other problems, or would like to point out other caveats to add to
+this FAQ, please point them out to the developers on the Xastir-dev mailing
+list. The addresses for the mailing lists may be found on the main Xastir
+web pages, which are listed at the top of this document. You must be subscribed
+in order to post messages.
+
+
+Copyright (C) 2000-2012 The Xastir Group
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..574bc2f
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,1623 @@
+
+$Id: INSTALL,v 1.108 2012/11/01 18:57:18 we7u Exp $
+
+
+General steps to configure/compile/install Xastir:
+(See detailed steps and library installation instructions below)
+----------------------------------------------------------------------
+
+1) Get one of the source releases and explode it.
+
+ mkdir xastir
+ cp xastir*.tgz xastir
+ cd xastir
+ tar xzvf xastir*
+
+An alternative to the above steps is to use CVS to download the
+Xastir sources. See README.CVS for those instructions. CVS allows
+you to easily keep up to date with the developers.
+
+2) Go into the xastir directory to build the executable:
+
+ cd xastir*
+
+If you used CVS to fetch the sources, you need one more step here
+before you run configure: "./bootstrap.sh"
+
+ ./configure
+ make
+ su (become the root user)
+ make install (make install-strip can be used after the first time)
+ chmod 4555 /usr/local/bin/xastir (only if you use kernel ax.25, see below)
+ exit (from root)
+
+3) Xastir should be installed in /usr/local/bin (the default on most
+systems). You can run it by typing this from a shell:
+
+ xastir &
+
+
+Short summary of libraries Xastir can use:
+-------------------------------------------------------------------------
+Motif or OpenMotif or LessTiff Required The GUI widget set
+pthreads Required Threading capability
+Shapelib Recommended ESRI Shapefile maps and WX alerts
+pcre Recommended used with Shapefile maps
+Xpm Optional XPM images + Snapshots + Printing
+ImageMagick Optional MANY graphics images
+libtiff/libgeotiff/libproj Optional geoTIFF maps (USGS topos)
+AX.25 Optional Kernel AX.25 networking support
+festival Optional Speaking alerts
+libcurl or wget Optional Internet images as maps
+GPSMan/gpsmanshp Optional Converts GPS data to Shapefiles
+GDAL/OGR Optional Many formats (coming soon)
+libdb (4.0 or newer) Optional Internet map caching (fast!)
+libpq Experimental Persistent data with Postgis
+libmysqlclient Experimental Persistent data with MySQL
+
+Library/Option Heirarchy:
+-------------------------
+
+ ImageMagick (Usually requires additional libraries)
+
+ GDAL/OGR (Usually requires additional libraries)
+
+ error_popups (Annoying popups, turned off by default)
+
+ libgc (developer stuff: memory leak testing)
+
+ "festival --server &" (Xastir connects to this server)
+ |
+ `-----------> Festival
+
+ gprof
+ |
+ `-+---------> profiling (developer stuff)
+ /
+ |
+ gprof-helper.so
+
+ libax25
+ |
+ `-----------> AX25
+
+ libProj
+ |
+ `-+-------+-> GeoTiff
+ / /
+ / /
+ libtiff /
+ /
+ libgeotiff
+
+ gpsmanshp
+ |
+ `-+------+--> GPSMan
+ / /
+ | /
+ tcl/tk /
+ /
+ ShapeLib
+ |
+ +-----------> rtree
+ |
+ `-+---------> Dbfawk
+ /
+ |
+ PCRE
+
+ libcurl or wget
+ |
+ `-+--------> map_caching
+ /
+ |
+ Berkeley DB
+
+
+ MySQL --------> MySQL database interfaces (Experimental)
+ |
+ `-+---------> db2APRS (Xastir connects to this server)
+ /
+ |
+ Meteo
+
+ Postgresql
+ |
+ `-+--------> Postgis database interfaces (Experimental)
+ | +
+ / QGIS [station data in another GIS application]
+ |
+ Postgis
+
+---------------------------------
+
+
+Installing only the required libs gives you these capabilities:
+
+ PocketAPRS maps
+ aprsDOS maps
+ WinAPRS maps
+ MacAPRS maps
+ GNIS labels
+ Address searching
+ serial port and Internet gateway connectivity.
+
+Adding XPM or ImageMagick libs, ImageMagick's "convert" utility, and
+the "gv" utility gives you printing capability. Postscript or
+emulated postscript printing capability is required for this as well.
+
+Adding XPM or ImageMagick libs plus "convert" also give the
+capability to create automatic PNG images on disk from the map
+screen (useful for web pages!).
+
+Adding Shapelib support also gives you the capability to use Tiger
+2000 maps which were converted to Shapefile format by ESRI. This
+allows you to use free detailed street maps for any point in the
+U.S.
+
+Adding other libraries gives you the additional capabilities listed
+above.
+
+For those who would like to see the full list of libraries Xastir
+might use (to decide what packages to install), here's the ldd
+command run against a pretty much fully-loaded Xastir. Note that
+quite a few of these libraries are pulled in by the ImageMagick
+library, and your library list may look little like it due to
+differences in how ImageMagick was compiled:
+
+ > ldd /usr/local/bin/xastir
+ libXm.so.3 => /usr/X11R6/lib/libXm.so.3 (0x40030000)
+ libXt.so.6 => /usr/X11R6/lib/libXt.so.6 (0x40287000)
+ libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x402db000)
+ libMagick.so.0 => /usr/lib/libMagick.so.0 (0x403d7000)
+ liblcms.so.1 => /usr/lib/liblcms.so.1 (0x4052f000)
+ libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x40553000)
+ libexif.so.9 => /usr/lib/libexif.so.9 (0x405a9000)
+ libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x405be000)
+ libSM.so.6 => /usr/X11R6/lib/libSM.so.6 (0x405cc000)
+ libICE.so.6 => /usr/X11R6/lib/libICE.so.6 (0x405d5000)
+ libbz2.so.1 => /usr/lib/libbz2.so.1 (0x405ed000)
+ libz.so.1 => /usr/lib/libz.so.1 (0x405fd000)
+ libpthread.so.0 => /lib/i686/libpthread.so.0 (0x4060c000)
+ libm.so.6 => /lib/i686/libm.so.6 (0x4065d000)
+ libdb-4.1.so => /usr/lib/libdb-4.1.so (0x40680000)
+ libXpm.so.4 => /usr/X11R6/lib/libXpm.so.4 (0x40744000)
+ librt.so.1 => /lib/librt.so.1 (0x40755000)
+ libcurl.so.2 => /usr/lib/libcurl.so.2 (0x40768000)
+ libXp.so.6 => /usr/X11R6/lib/libXp.so.6 (0x4078f000)
+ libshp.so.1 => /usr/local/lib/libshp.so.1 (0x40797000)
+ libpcre.so.0 => /usr/lib/libpcre.so.0 (0x4079f000)
+ libproj.so.0 => /usr/local/lib/libproj.so.0 (0x407ab000)
+ libtiff.so.3 => /usr/lib/libtiff.so.3 (0x407e2000)
+ libgeotiff.so => /usr/local/lib/libgeotiff.so (0x4082b000)
+ libax25.so.0 => /usr/lib/libax25.so.0 (0x4084d000)
+ libgdal.so.1 => /usr/local/lib/libgdal.so.1 (0x40856000)
+ libc.so.6 => /lib/i686/libc.so.6 (0x40b64000)
+ libdl.so.2 => /lib/libdl.so.2 (0x40c97000)
+ /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
+ libssl.so.0.9.7 => /usr/lib/libssl.so.0.9.7 (0x40c9b000)
+ libcrypto.so.0.9.7 => /usr/lib/libcrypto.so.0.9.7 (0x40ccb000)
+ libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x40dbd000)
+ libjasper-1.700.so.2 => /usr/lib/libjasper-1.700.so.2 (0x40ddd000)
+ libpng.so.3 => /usr/lib/libpng.so.3 (0x40e2c000)
+ libstdc++.so.5 => /usr/lib/libstdc++.so.5 (0x40e5b000)
+ libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x40f1b000)
+
+
+
+Things you need for this version:
+---------------------------------
+ * Get Lesstif/OpenMotif from your favorite Linux/Unix distribution.
+-or-
+ * Lesstif: www.lesstif.org (look below for RED-HAT instructions)
+-or-
+ * OpenMotif: www.openmotif.org
+
+ * AX25 packages: (if you want support for kernel AX25 interfaces)
+ Lib AX25:http://prdownloads.sourceforge.net/ax25/libax25-0.0.7.tar.gz
+ AX25 apps:http://prdownloads.sourceforge.net/ax25/ax25-apps-0.0.4.tar.gz
+ AX25 tools:http://prdownloads.sourceforge.net/ax25/ax25-tools-0.0.8.tar.gz
+ The apps package is not required, but strongly suggested. These versions
+ are current as of the writing of this document; feel free to use newer
+ versions. Make sure the versions you choose match your kernel version.
+ Also note that there are patches required to the 2.4 kernel for AX.25
+ kernel networking. See the linux-hams mailing list for details.
+
+ * You should have glibc on your system that supports threads!
+
+
+For geoTIFF support (such as USGS DRG topo maps) you also need:
+
+ libtiff (should be on your distribution's CD's):
+ ------------------------------------------------
+ http://www.libtiff.org
+
+ libproj (proj-4.4.9):
+ ---------------------
+ http://proj.maptools.org/
+ http://www.remotesensing.org/proj/
+ http://wetnet.net/~we7u/xastir/
+
+ Datum translations (proj-nad27 or proj-datumgrid):
+ --------------------------------------------------
+ http://proj.maptools.org/
+ ftp://ftp.remotesensing.org/pub/proj/
+ http://wetnet.net/~we7u/xastir/
+
+ libgeotiff (libgeotiff-1.1.5 or libgeotiff-1.2.4):
+ --------------------------------------------------
+ http://dl.maptools.org/dl/geotiff/libgeotiff/
+ http://www.remotesensing.org/geotiff/geotiff.html
+ ftp://ftp.remotesensing.org/pub/geotiff/libgeotiff/
+ http://wetnet.net/~we7u/xastir/
+
+ Please note that the order of installation for the above libraries is
+ critical. Follow the instructions below carefully. Also, the particular
+ libgeotiff you use depends on the version of libtiff you have installed.
+
+For Linux kernel AX.25 interfaces, you require these packages:
+ Lib AX25:http://prdownloads.sourceforge.net/ax25/libax25-0.0.11.tar.gz
+ AX25 apps:http://prdownloads.sourceforge.net/ax25/ax25-apps-0.0.6.tar.gz
+ AX25 tools:http://prdownloads.sourceforge.net/ax25/ax25-tools-0.0.8.tar.gz
+ The apps package is not required, but strongly suggested. These versions
+ are current as of the writing of this document; feel free to use newer
+ versions. Make sure the versions you choose are compatible with your
+ kernel version. See the AX.25 HOWTO and the linux-hams mailing list for
+ details.
+
+For speech support via the festival speech synthesis software you need:
+ festival:
+ http://www.speech.cs.cmu.edu/festival/
+ http://at.rpmfind.net/opsys/linux/RPM/redhat/7.0/powertools/i386/festival-1.4.1-5.i386.html
+
+ If you're running a slightly older version of Linux you'll need to install
+ festival from sources to make it work properly.
+
+For ESRI Shapefile format maps/weather alert maps:
+ Shapelib:
+ http://shapelib.maptools.org/
+ http://wetnet.net/~we7u/xastir/
+ pcre:
+ http://www.pcre.org
+
+For GDAL/OGR:
+ http://www.gdal.org/
+ http://remotesensing.org/gdal/
+ http://www.maptools.org
+ http://wetnet.net/~we7u/xastir/
+
+For ImageMagick support for maps in any of 68 major graphics formats,
+ including the capability to use online maps and weather radar images:
+ ImageMagick:
+ http://www.imagemagick.org/
+
+To use online maps or findu.com historical data, you'll need wget or
+ libcurl/libcurl-devel installed. Many systems have these pre-installed,
+ so check first. You may need to upgrade your installed version for
+ this feature to work correctly from within Xastir:
+ Wget:
+ ftp://ftp.gnu.org/gnu/wget/
+ libcurl:
+ http://curl.sourceforge.net/
+
+
+To download GPS tracks/waypoints/routes from a Garmin GPS into Xastir,
+converting to Shapefile format maps as it runs, you'll need gpsmanshp and
+GPSMan. GPSMan 6.0 and later has command-line support built-in so that
+Xastir can control it directly, but only GPSMan 6.1 and later are currently
+usable with Xastir:
+ gpsmanshp:
+ http://www.ncc.up.pt/gpsmanshp/
+ GPSMan:
+ http://www.ncc.up.pt/gpsman/
+ http://sunsite.unc.edu/pub/Linux/science/cartography
+
+See below for instructions on installing all of these libraries. Once the
+ libraries are installed, ./configure should find the libraries and allow
+ compiling in support for the new features.
+
+
+If you wish to enable/disable configure's testing of certain
+features, you can add any of the following flags to configure:
+
+ --without-ax25
+ --without-festival
+ --without-gpsman
+ --without-imagemagick
+ --without-libproj
+ --without-geotiff
+ --without-gdal
+ --without-shapelib
+ --without-pcre
+ --without-dbfawk
+ --without-map-cache
+ --with-errorpopups
+ --with-libgc
+ --with-profiling
+ --with-rtree
+ --with-lsb
+ --with-postgis
+ --with-mysql
+
+For example, "./configure --without-ax25" will disable the AX.25
+networking code in Xastir.
+
+If you have installed Xastir before, read the "UPGRADE" file for
+information on changes in file location and permissions.
+
+
+First Time Install:
+-------------------
+
+ 1. OPTIONAL: If you wish to use AX.25 interfaces, install the AX.25
+ packages. Verify that they are configured and working. Use "listen"
+ to watch the packets fly by after getting AX.25 configured and hooked
+ to a TNC. Use the AX.25 HOWTO document to guide you in this process.
+
+
+ 2. Install LessTif or OpenMotif
+
+ If you already have Motif or OpenMotif on your system, including
+ the development headers, then you won't need to install LessTif. Most
+ distributions include one of these; step 2a describes building from
+ source, while 2b describes installing from pre-built packages on
+ your distribution. Now that OpenMotif is available, you may be happier
+ running it than LessTif, but either one should work with Xastir.
+
+ Some users have had problems with OpenMotif, and others have had troubles
+ with LessTif. Symptoms are often menu problems (menus don't draw
+ correctly, menus won't respond to clicks). If you encounter these
+ problems, then uninstall the current Motif and install the other. Several
+ Mac users have reported problems with OpenMotif, so LessTif may be a
+ better place to start.
+
+ 2a. Download LessTif version 0.91.1 or higher or download OpenMotif.
+ Follow the instructions provided, compile it and install it.
+
+ Usually,
+ ./configure
+ make
+ su (root)
+ make install
+ /sbin/ldconfig
+ exit (from root)
+
+ Or you can try any other OSF/Motif(R) version 1.2
+
+
+ 2b. Install LessTif or OpenMotif (from a package)
+
+ Download the lestif-devel (if it exists) and lestif, and install it
+ as your distribution instructs you to install packages.
+
+
+ 3. OPTIONAL: Install geoTIFF support. Allows using USGS DRG topo maps or
+ other types of geoTIFF maps/images and has the ability to tile smaller
+ maps into a larger contiguous map of an area:
+
+
+ 3a. Check/Edit your startup files:
+ -----------------------------
+ Check that /usr/local/lib, /usr/lib, and /usr/X11R6/lib are
+ all listed in /etc/ld.so.conf, and run /sbin/ldconfig to
+ re-create the system's cache file. If you don't have
+ permission to edit this file:
+ Edit ~/.bashrc, ~/.bash_profile, .cshrc, or
+ .login and add:
+
+ export LD_LIBRARY_PATH=/usr/local/lib:/usr/lib:/usr/X11R6/lib
+
+ This will let the loader find the shared libraries when it tries to
+ load Xastir into memory.
+
+ If you instead have a /etc/ld.so.conf.d directory, then this will add
+ the /usr/local/lib directory to the search: Create a file in the
+ /etc/ld.so.conf.d called "local.conf". The file should contain exactly
+ one line:
+
+ /usr/local/lib
+
+ Use your favorite text editor or use these commands:
+
+ echo "/usr/local/lib" > /etc/ld.so.conf.d/local.conf
+ ldconfig -v
+
+ Check that you aren't already defining LD_LIBRARY_PATH somewhere else.
+ If so, just add the paths above to it. Make sure this environment
+ variable is defined in the current shell you're using to compile Xastir.
+ Note that if you're running Xastir SUID root, the LD_LIBRARY_PATH
+ variable is ignored.
+
+
+ 3b. Install libproj:
+ --------------------
+ NOTE: You must install libproj BEFORE compiling libgeotiff, because
+ libgeotiff uses libproj to do the datum translations. If you install
+ libgeotiff first, datum translations won't work.
+
+ proj-nad27-1.1.tar.gz or proj-datumgrid-1.3.zip must be decompressed in
+ the nad subdirectory of the proj distribution directory before you run
+ configure.
+
+ tar xzvf proj-4.4.9.tar.gz (or newer)
+ cd proj-4.4.9/nad
+ unzip ../../proj-datumgrid-1.3.zip (or tar xzvf ../../proj-nad27-1.1.tar.gz)
+ cd ..
+ ./configure
+ make
+ su (root)
+ make install
+ /sbin/ldconfig
+ exit (from root)
+
+ libproj should now be installed in:
+
+ /usr/local/include/
+ /usr/local/lib/
+ /usr/local/bin/
+ /usr/local/share/proj/
+
+ You may need to do this (as root) if the "make install" portion fails
+ because it can't find "ginstall":
+
+ cd /usr/bin
+ ln -s install ginstall
+
+ Then retry the "make install" portion above.
+
+
+ 3c. Upgrade libtiff if needed:
+ -----------------------------
+ The best way to install libtiff is to get it from the ftp site
+ for your Linux distribution. You must have libtiff 3.5.5 or
+ newer for libgeotiff 1.1.x to compile and run correctly, or libtiff
+ 3.6.0 BETA or newer for libgeotiff 1.2.x to work correctly.
+
+ If you're using libtiff 3.6.0 BETA or newer, things are simplified.
+ Just use libgeotiff 1.2.x or newer and they should play nicely together.
+
+ ---------
+ Notes for older libtiff (less than 3.6.0 BETA):
+
+ If you are compiling libtiff from source, you must use
+ "make install_private" because the libtiff private include files
+ are required for libgeotiff to compile and work correctly.
+
+ You may also snag just the include files listed below from the
+ source distribution or the source RPM, and copy them manually to
+ their destinations.
+
+ The errors you'll get if you don't match up the older libtiff and
+ libgeotiff by way of the include files: Xastir will seg-fault when
+ it tries to read a geotiff file.
+ ---------
+
+ If you upgrade libtiff, check that programs like XV, ImageMagick, and
+ the Gimp still run (if you have these programs installed). Graphics
+ programs that read/write TIFF format depend on libtiff.
+
+
+ 3d. Install libgeotiff:
+ -----------------------
+
+ NOTE: Depending on your version of libtiff, either libgeotiff-1.1.5 or
+ libgeotiff-1.2.4 may compile properly. libgeotiff is intimately
+ tied to your version of libtiff. libgeotiff 1.2.x or greater
+ requires libtiff-3.6.0 BETA or later. If your version of libtiff is
+ older, get libgeotiff 1.1.4 or 1.1.5. For the latter case you may
+ also have to download the sources for your version of libtiff in
+ order to copy one libtiff header file into the libgeotiff source
+ directory.
+
+ -----------------------
+ Pre 3.6.0 libtiff NOTE: You may need to snag some files from your exact
+ libtiff source distribution and place them into your /usr/include
+ directory before libgeotiff will compile. Note: I said use files from
+ the EXACT same distribution of libtiff that you already have installed!
+
+ libtiff/tiffconf.h
+ libtiff/tiffiop.h
+ libtiff/tif_dir.h
+ contrib/dosdjgpp/port.h
+
+ Drop all four files into the /usr/include/ directory, creating no
+ subdirectories at all. This allows the libgeotiff code to "see"
+ into the libtiff library so that it can use some functions that
+ aren't normally (publicly) available. Try to make sure that
+ you're not overwriting any files in /usr/include/ by the same name.
+ Some of these files may already be present in /usr/local/. If so,
+ they should be exact duplicates. "diff filename1 filename2" will
+ tell you if there are any differences between two files.
+
+ If you'd rather not mess with the /usr/include directory,
+ you can drop the four files into the
+ libgeotiff-1.1.5/libtiff_private/ directory instead. Libgeotiff
+ will pick up the files there, issue a warning to you that you're
+ using private include files, yet still compile in support for your
+ particular version of libtiff.
+
+ With libgeotiff-1.2.4/libtiff-3.6.0-beta or newer you shouldn't
+ need to copy these files across. The newer libtiff and libgeotiff
+ can work together using public interfaces.
+ ------------------------
+
+ tar xzvf libgeotiff-1.2.4.tar.gz (or newer)
+ cd libgeotiff-1.2.4
+ ./configure
+ make
+ su (root)
+ make install
+ /sbin/ldconfig (tells the loader about the new libraries)
+ exit (from root)
+ libgeotiff should now be installed in:
+
+ /usr/local/include/
+ /usr/local/lib/
+ /usr/local/share/epsg_csv/
+ /usr/local/bin/
+
+ If you must re-run "configure" for any of these libraries, remember to
+ delete "config.status" and "config.cache" files first.
+
+
+ 4. RECOMMENDED: Install ESRI Shapefile support. Allows using many sources
+ of online polygon, polyline, and point maps, including ones from NOAA.
+ This is also the format for weather alert maps. This support is provided
+ by the shapelib package.
+
+ NOTE: There are TWO ways to install Shapelib, using the version of
+ Shapelib that comes with Xastir (statically linked with Xastir), or using
+ a separate Shapelib shared library (dynamically linked with Xastir). If
+ you ONLY require Shapelib for Xastir and won't need it for any other
+ program, then you may use the private copy distributed with Xastir,
+ skipping the Shapelib install instructions in this section. If you have
+ other programs which need Shapelib, then it is recommended that you
+ install Shapelib first as a shared library, per the instructions below.
+ If you skip the instructions in this sections, "./configure" will set the
+ compile up so that the private Shapelib code will be statically
+ linked to the executable.
+
+ It isn't clear from the install instructions in shapelib, but just
+ installing the library is sufficient, and just typing "make" and
+ "make install" doesn't make or install the libraries. Take these steps:
+
+ make lib
+ su (root)
+ make lib_install
+ /sbin/ldconfig
+ exit (from root)
+
+ and you should have what you need.
+
+ You may also need to tweak "/etc/ld.so.conf" to contain the proper path
+ to the libraries and then run /sbin/ldconfig to update "/etc/ld.so.cache".
+ Once this is done the loader should be able to find the Shapelib library.
+ Must run /sbin/ldconfig as root for the system to be able to re-create its
+ cache file. See the instructions earlier in this file if you have an
+ /etc/ld.so.conf.d directory instead (section 3A).
+
+ For MacOSX: Bill Owen, N2RKL, suggested the following for
+ ShapeLib:
+
+ "The shapelib Makefile wouldn't work out of the box, so I
+ figured out what the important bits were and built them by
+ hand:"
+
+ -----------------------------------------------
+ cc -c shpopen.c
+ cc -c shptree.c
+ cc -c dbfopen.c
+ ar cru libshp.a shpopen.o shptree.o dbfopen.o
+ sudo cp libshp.a /sw/lib
+ sudo ranlib /sw/lib/libshp.a
+ sudo mkdir /sw/include/libshp
+ sudo cp shapefil.h /sw/include/libshp/
+ -----------------------------------------------
+
+ Note that you'll have to set up /etc/sudoers file to allow those
+ commands to be run by a normal user before sudo will work for
+ you. See the README.CVS file for sudo instructions.
+
+
+ Note from Gale Wilkinson, kc4pl:
+ > >
+ > > How do you get shapelib to "make" properly under cygwin? I
+ > > have installed the latest cygwin (packages per the win32
+ > > install notes) and then downloaded and unpacked the latest
+ > > shapelib source package for compiling. But when trying to do
+ > > the "make lib" it errors out part way through the process.
+ > > The error seems to be:
+ > >
+ > > dbfopen.lo: In function 'DBFReadAttribute':
+ > > /home/gwilkinson/src/shapelib-1.2.10/dbfopen.c:724:undefined reference to '__getreent'
+ > > /home/gwilkinson/src/shapelib-1.2.10/dbfopen.c:716:undefined reference to '__getreent'
+ > > make: *** [lib] Error 1
+
+ Dan Brown, n8ysz, responded:
+ >
+ > I wrote this to get/make shapelib:
+ >
+ > http://brauhaus.org/xastir/get_shapelib.sh
+ > or
+ > http://brauhaus.org/xastir/get_shapelib.sh.txt
+
+ This script is now also in the Xastir sources as
+ "xastir/scripts/get_shapelib.sh".
+
+
+ COMPILING OPTIONAL UTILITIES FOR SHAPELIB:
+
+ These utilities are sometimes useful when writing dbfawk rules
+ but aren't necessary for running Xastir.
+
+ cd xastir/src/shapelib
+ make -f Makefile_shapelib_orig
+
+ cd contrib
+ make -f Makefile_orig
+
+ You'll be left with useful executables in the xastir/src/shapelib and
+ xastir/src/shapelib/contrib directories. It's your choice whether to
+ copy them to a directory in your path (perhaps /usr/local/bin?) to make
+ them easier to use.
+
+
+ 5. OPTIONAL: Install -either- GraphicsMagick or ImageMagick support as
+ shown below. Xastir will use one or the other but not both. It'll prefer
+ GraphicsMagick over ImageMagick if both are installed. Do step 5a -or- 5b
+ below to get this type of image support compiled into Xastir.
+
+ Allows using more than 68 different graphics format files as maps, by
+ creating an associated .geo file for each with tie-points. This support
+ will allow use of online Tiger and Terraserver maps with Xastir, and NOAA
+ weather radar images. Other people are working on integrating even more
+ online mapping sources. This will also allow you to use any GIF/JPG/XPM/
+ BMP/... image as an Xastir map. Installation instructions are included in
+ the package. If you choose to install from a binary install, be sure that
+ you have all the graphic format libraries that it was originally built
+ with.
+
+ The easiest way to install one of these is via a package from your linux
+ distribution's CD or ftp site. If you install from such a package, make
+ sure the header files are installed. These are often in a separate package
+ called GraphicsMagick-devel or ImageMagick-devel or similar.
+
+
+ 5a. OPTIONAL: Install GraphicsMagick support.
+
+ Download the GraphicsMagick sources from:
+
+ http://www.graphicsmagick.org
+
+ Uncompress/un-tar them...
+
+ tar -xzvf Gr*
+
+ Change directory to the newly created GraphicsMagick directory and
+ compile:
+
+ cd Gr*
+ ./configure --with-quantum-depth=16 --enable-shared
+ make
+ su -c 'make install'
+ su -c '/sbin/ldconfig'
+
+ Skip the next step (5b) as you only need ImageMagick support installed if
+ you _don't_ install GraphicsMagick.
+
+
+ 5b. OPTIONAL: Install ImageMagick graphics support.
+
+ Note that Xastir's "./configure" stage may fail trying to compile in
+ ImageMagick support. If this happens, make sure you have the ImageMagick
+ development package installed if using RPM packages, or have installed
+ the ImageMagick header files. If it still fails, check the "config.log"
+ file _very_ carefully. Often ImageMagick tests fail due to some other
+ library that ImageMagick depends upon being absent, such as liblcms,
+ libbz2, or others. This can also cause AX.25 support to be dropped in our
+ current "configure" script. We're working on that.
+
+ Until the RPM packagers for ImageMagick include all of the dependent
+ libraries in their RPM dependency list, the best way to assure that
+ ImageMagick is installed properly is to install it from sources.
+
+ -------------------------------------------------------------------------
+ Note: Red Hat 9.0's install of ImageMagick does not work with
+ XASTIR. It will need to be removed and installed from sources.
+ If w3m text based web browser is installed, you will need to remove
+ it before removing ImageMagick:
+
+ rpm -e w3m
+ rpm -e ImageMagick
+
+ Download the Imagemagick sources from:
+
+ ftp://ftp.imagemagick.org/pub/ImageMagick/
+
+ At the time of writing, this was
+
+ ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick-5.5.7-34.tar.gz
+
+ But you may need to get a newer version by the time you read this.
+
+ Uncompress/un-tar them...
+
+ tar -xzvf im*
+
+ Change directory to the newly created ImageMagick directory and
+ compile:
+
+ cd im*
+ ./configure
+ make
+ su -c 'make install'
+ su -c '/sbin/ldconfig'
+
+ These instructions are courtesy of Wes Johnston.
+ -------------------------------------------------------------------------
+
+
+ 6. OPTIONAL: If your system doesn't have wget or libcurl/libcurl-devel
+ installed, and you want to use online maps, install either or both of
+ those packages now. Installation instructions are included in the
+ package. Some older versions of wget don't work properly with
+ Xastir, so even if you already have wget you may need to upgrade it.
+
+ Please refer to the wget man pages or the web pages at
+ http://www.gnu.org/software/wget/wget.html for info concerning wget.
+
+ Note that if the remote server is down, Xastir can appear to hang
+ for a bit before wget times out. Xastir calls wget with no retries
+ and a 30-second timeout, but one user reported that wget takes one
+ minute fifteen seconds to time out. Also note that the users ~/.wgetrc
+ and the system-wide wgetrc file can change the timeouts and retries as
+ well. See the man pages for details. Pay particular attention to
+ which file/command-line-options take priority over others. It looks
+ like the command-line option "--execute command" will allow overriding
+ the .wgetrc files, which means the user can override the hard-coded
+ timeouts/retries in Xastir by specifying new defaults in their ~/.wgetrc
+ file.
+
+ Libcurl should be a drop-in replacement for the wget functionality that
+ we use, and it's a faster and more secure method.
+
+ 7. OPTIONAL: Installing gpsmanshp/GPSMan allows Xastir to fetch GPS
+ waypoints/routes/tracks from a GPS. Xastir can fetch the data
+ automatically, create a Shapefile map, then index/select/display the
+ new map.
+
+ Make sure you have Shapelib installed first (see above instructions).
+
+ Note that you may have to change the gpsmanshp Makefile to call out
+ "TCLVERSION = 8.4" instead of 8.3, depending upon which version of tcl is
+ installed on your system. Use your package manager to determine this
+ ("rpm -q -a | grep tcl"), or you may be able to find out in /usr/lib by
+ typing "ls -ld tcl*".
+
+ Install gpsmanshp:
+
+ tar xzvf gpsmanshp_1.2.2.tgz
+ cd gpsmanshp
+ make
+ su -c 'make install'
+
+ Install GPSMan:
+
+ tar xzvf gpsman-6.0.tgz
+ cd gpsman-6.0
+ vi gpsman.tcl
+ Change SRCDIR line to: "set SRCDIR /usr/lib/gpsman"
+ su (root)
+ mkdir /usr/lib/gpsman
+ cp gpsman.tcl /usr/lib/gpsman
+ ln -s /usr/lib/gpsman/gpsman.tcl /usr/X11R6/bin/gpsman
+ cd gmsrc
+ cp * /usr/lib/gpsman
+ cp -R gmicons /usr/lib/gpsman
+ chmod -R 755 /usr/lib/gpsman
+ chmod 644 /usr/lib/gpsman/gmicons
+ chmod 777 /usr/local/share/xastir/maps/GPS (IMPORTANT!)
+ exit (from root)
+
+ Verify that GPSMan will start up and will download information from a
+ Garmin GPS in Garmin-Garmin mode. This also creates the configuration
+ files needed to use GPSMan with Garmin GPS's from within Xastir (sets
+ GPS type, serial port, etc within GPSMan's configs).
+
+ 8. OPTIONAL: Install Festival for speech support
+ To use speech you must have a sound card and the 'festival' speech
+ synthesis software installed. Install Festival and start it in 'server'
+ mode prior to starting up XASTIR. The normal command for this is
+ "festival --server &". More info about the speech features is in the
+ Xastir help file. An easy way to get festival installed on some systems
+ is to go to rpmfind.com and search for both festival and festival-dev,
+ then install the RPM's found. Red Hat RPM's installed onto SuSE 7.3 with
+ no problems. Note that the default voice doesn't speak numbers very well.
+ Edit /usr/share/festival/voices.scm and put "ked_diphone" at the first of
+ the "defvar default-voice-priority-list". This will change the default
+ voice to "ked_diphone".
+
+ Note that you can start up the festival server and test it out manually
+ by typing these commands:
+
+ telnet localhost 1314
+ (SayText "Hello")
+
+ To exit, press control-] and then type "quit".
+
+ 9. OPTIONAL: Install GDAL/OGR for support of many more map formats.
+
+ NOTE: There are some cases where adding GDAL can mess up support for a
+ few of the other libraries, like Shapelib, libproj, or libgeotiff. GDAL
+ may be compiled with support these libraries internally and it is
+ possible to have Xastir linked against some of GDAL's internal libraries
+ but using the external library headers. If the versions of each are
+ sufficiently different, things may not work right. If you run into such
+ problems you can either reconfigure GDAL to use external libraries for
+ these three or configure Xastir without GDAL support. Also see the note
+ below about libtiff-3.8.0.
+
+ NOTE: This is currently being added to Xastir: Some support is there
+ now for the vector formats, but it isn't "pretty" yet. Should you wish
+ to see what map formats your system will support once GDAL/OGR are fully
+ integrated into Xastir, proceed with the following:
+
+ cd ~src (or wherever you keep your sources)
+ export CVSROOT=:pserver:cvsanon at cvs.maptools.org:/cvs/maptools/cvsroot
+ cvs login
+ Password: <ENTER>
+ cvs checkout gdal
+
+ Optionally you can also use one of the newer GDAL releases, so in that
+ case just download that instead of the above instructions, then do the
+ following instructions for either:
+
+ cd gdal
+ ./configure --without-mysql
+ make
+ su (root)
+ make install
+ /sbin/ldconfig
+ exit (from root)
+
+ A configure line that worked with older GDAL code was:
+
+ ./configure --without-jasper --without-ld-shared
+
+ Here's another GDAL configure command which forces GDAL to use its own
+ internal libraries for some of the formats:
+
+ ./configure --without-mysql --with-libz=internal --with-png=internal \
+ --with-jpeg=internal --with-geotiff=internal --with-libtiff=internal \
+ --with-gif=internal
+
+ Also note that as of Dec 11, 2003, a major memory leak bug in the OGR
+ code was fixed, having to do with Shapefiles. Please run a version of
+ GDAL/OGR that is newer than that date (or use the CVS version as
+ described above).
+
+ In one case linking in GDAL caused some GTIFProj4ToLatLong calls to break
+ in an odd manner due to Xastir linking in libgeotiff functions from the
+ GDAL library in that case instead of the libgeotiff library: GeoTIFF's
+ with UTM coordinates stop working. Configuring Xastir without GDAL
+ support -or- upgrading libtiff to 3.8.0 fixes the problem.
+
+ 10. OPTIONAL: Install Berkely DB Library to enable map caching
+ of internet maps.
+
+ Please note that segfaults (crashes) in Berkeley DB calls can be caused
+ by having multiple versions of the library installed. The programming
+ interface has changed between the versions. If you compile Xastir with
+ one version's header files but Xastir links to another version's
+ library, you can easily end up with segfaults when Xastir runs. SuSE
+ Linux for instance has these available which you _should_ install:
+
+ db
+ db-devel
+
+ Plus SuSE has these additional packages available which you should _not_
+ install. Remove them if they're on your system (using YaST or rpm):
+
+ db-40
+ db42
+
+ Xastir will normally try to use /usr/include/db.h as the header file,
+ and /usr/lib/libdb.so as the library it will link to (which is usually
+ a symlink to something else, like /usr/lib/libdb-4.1.so). If the
+ header file and the library file don't match, a segfault often occurs.
+ The easiest way to avoid problems is to keep one and only one version
+ of the Berkeley DB library on your system.
+
+ Here's how to test what version of include file and library file you're
+ using: Find the db.h file. It's usually in /usr/include/db.h.
+
+ grep DB_VERSION db.h
+
+ Mine shows this:
+
+ #define DB_VERSION_MAJOR 4
+ #define DB_VERSION_MINOR 1
+ #define DB_VERSION_PATCH 25
+ #define DB_VERSION_STRING "Sleepycat Software: Berkeley DB 4.1.25: (October 2, 2003)"
+
+ Now do this:
+
+ ldd /usr/local/bin/xastir | grep libdb
+
+ Mine shows this:
+
+ libdb-4.1.so => /usr/lib/libdb-4.1.so (0x40680000)
+
+ In this case, version 4.1 of the include file matches 4.1 of the library
+ file, so it works fine. A mismatch in the first two numbers can cause
+ segfaults when Xastir tries to do map caching.
+
+ If you install the Berkeley DB library in an unusual place (something
+ other than /usr/lib and /usr/include), you should still be able to tell
+ configure where to find it. This comes courtesy of Tom Russo:
+
+ > > Someone installed Berkeley DB Library here:
+ > >
+ > > /user/local/BerkeleyDB.4.3/include/db.h
+ > >
+ > > Perhaps I can assume that the library would be located here:
+ > >
+ > > /usr/local/BerkeleyDB.4.3/lib/libdb.so
+ > >
+ > > How does one go about specifying the location of the db.h file and
+ > > the libdb.so file so that configure/compile/loading of Xastir work
+ > > properly?
+
+ > --with-bdb-libdir=/usr/local/BerkeleyDB.4.3/lib
+ > and
+ > --with-bdb-incdir=/usr/local/BerkeleyDB4.3/include
+
+ 11. OPTIONAL: Compile db2APRS and install MySQL and Meteo to
+ allow Davis weather station support.
+
+ Install MySQL and Meteo.
+
+ "cd Davis"
+ "./bootstrap.sh"
+ "./configure"
+ "make"
+
+ This should build db2APRS in the "src" directory. Start up db2APRS.
+ Xastir should be able to connect to the db2APRS server in order to get
+ the Davis weather station data. See further instructions in the Davis
+ directory.
+
+ 12. OPTIONAL: Experimental. Add GIS database support.
+
+ Note: Database support is experimental and any aspect may change at
+ any time, including database structures. Scripts to create database
+ tables for MySQL and Postgres/Postgis are in the scripts directory
+ as db_gis_postgis.sql and db_gis_mysql.sql.
+
+ Warning: If you are connected to internet feeds for APRS data, it
+ is possible to accumulate several million station records per day
+ which could amount to around 300 MB of database records per day.
+
+ Postgres + Postgis:
+ Install Postgres. Include development packages (libpq).
+ Add Postgis spatial object support to Postgres.
+
+ Compile xastir with --with-postgis
+
+ After building xastir:
+ Create a database named xastir and a user with create rights on
+ that database.
+ Edit db_gis_postgis.sql to set username and password for an xastir
+ user with select access to the xastir database.
+ Default values are database=xastir, user=xastir_user
+ You may also need to set permissions in pg_hba.conf.
+ Run the queries in db_gis_postgis.sql.
+ Run xastir and add a SQL Database interface, start with the postgis
+ defaults, add the username and password of the xastir user.
+
+ Other GIS applications (e.g. QGIS, Mapserver, GRASS) can access and
+ display station data directly from the postgresql/postgis database.
+
+ You can configure the database interface to read station from the
+ database on startup and to save stations as they are heard to the
+ database. This provides persistance of station data between
+ xastir sessions.
+
+ MySQL:
+ Install MySQL. Include development packages (libmysqlclient).
+
+ Compile xastir with --with-mysql
+
+ After building xastir:
+ Create a database named xastir and a user with create rights on
+ that database.
+ Edit db_gis_mysql.sql to set username and password for an xastir
+ user with select access to the xastir database.
+ Default values are database=xastir, user=xastir_user
+ Run the queries in db_gis_mysql.sql
+ mysql xastir -p < db_gis_mysql.sql
+ Run xastir and add a SQL Database interface, start with the MySQL
+ defaults, add the username and password of the xastir user.
+
+ You can configure the database interface to read station from the
+ database on startup and to save stations as they are heard to the
+ database. This provides persistance of station data between
+ xastir sessions.
+
+ If you have one or more spatial database interfaces set to activate on
+ startup, and this produces a situation that won't let you start xastir
+ normally [e.g. Station data with unusual characters could concevable
+ cause xastir to segfault when retrieved from the database, and
+ interactions between multiple databases that are both writing are
+ reading station data at the same time from each other could potentally
+ be unstable], you should be able to start xastir by editing the
+ device configuration in ~/.xastir/config/xastir.cnf
+ Look for DEVICEn_TYPE:14 lines (where n is the interface number, between 0
+ and 14, TYPE:14 devices are sql database interfaces), and edit the
+ device to set both query on startup and on startup values to 0.
+ DEVICEn_QUERY_ON_STARTUP:0
+ DEVICEn_ONSTARTUP:0
+ If the cause is problematic data in your database, you may need to
+ run a delete query to eliminate the problematic row(s).
+
+
+ 13. Building XASTIR: Note that you'll need autoconf 2.53 or newer and
+ automake 1.6.3 or newer in order to run the "./bootstrap.sh" script.
+
+ "./bootstrap.sh" (This step needed only for those using CVS)
+ "./configure"
+ "make" ("gmake" for Solaris or *BSD)
+
+ This builds XASTIR, You should not get any error or warning messages.
+
+ If you get the message from Xastir's configure script saying:
+
+ "**** NO MOTIF HEADERS FOUND **** install Motif development headers or
+ use --with-motif-includes to specify location of Xm/Xm.h"
+
+ even though you've got the Motif libraries and headers installed in the
+ proper places, you might need to add this to the configure line:
+
+ "--x-includes=/usr/X11R6/include"
+
+ If that option does not help, then Motif is installed somewhere other
+ than with the standard X includes. You must locate the file "Xm.h,"
+ which should be in a subdirectory called "Xm" somewhere. Once located
+ (let's say in /usr/include/Motif/Xm/Xm.h), use the configure option:
+
+ "--with-motif-includes=/usr/include/Motif"
+
+ If you get the message:
+
+ "**** MOTIF LIBRARIES NOT FOUND **** Install Motif development
+ headers/libraries or use --with-motif-libraries to specify path
+ to libXm.a"
+
+ then your Motif libraries are not installed in the same directory as your
+ other X libraries, and you must find the file libXm.a, libXm.so,
+ or libXm.sl. Once found (say in /usr/lib/Motif, for example), tell
+ configure where to find it with:
+
+ "--with-motif-libraries=/usr/lib/Motif"
+
+ If you wish to install Xastir in a location other than the default
+ ("/usr/local/bin" and "/usr/local/share/xastir" directories), you may
+ add the "--prefix=<path>" flag to configure before compiling. i.e.
+
+ "./configure --prefix=/home/apps/xastir"
+
+ Which will cause executables to be installed in "/home/apps/xastir/bin/"
+ and the rest of Xastir to be installed under the
+ "/home/apps/xastir/xastir/" directory.
+
+ This is useful if you don't have root access on a machine, but still
+ wish to install and use Xastir from your home directory. There are
+ probably many other uses as well.
+
+ If you want to disable optional "dbfawk" support (see README.MAPS) then
+ add "--without-dbfawk" to your "./configure", i.e.
+
+ "./configure --without-dbfawk"
+
+ Most people will want the capability though.
+
+ You'll need the "pcre" package installed in order to compile in
+ dbfawk support.
+
+ To enable spatial indexing of shapefiles you can also add "--with-rtree"
+ to your configure command line. Using spatial indices can speed up access
+ of shapefiles that cover large areas if you're only viewing a smaller
+ area, but at the cost of some additional RAM to store the spatial
+ index. This feature is still in the experimental phase, but some users
+ have observed a noticeable speed-up in map redraws, especially
+ with very large shapefiles. The spatial indexing library used is based
+ on public domain code obtained from Melinda Green,
+ http://www.superliminal.com, but this code is included in xastir
+ so you don't need to download anything to use it.
+
+ If you see some errors, they might be because you are missing
+ GNU msgfmt or GNU gettext/xgettext? These packages are required
+ to compile the latest Xastir sources. Beware of packages with the
+ same names installed into /usr/openwin/bin, these are probably NOT
+ the GNU flavor of the executables and will not work for compiling
+ Xastir. For SuSE Linux: Install "development/gettext" using YaST.
+
+ If you do see some errors/warnings read the FAQ. If this doesn't help,
+ or you think you have a different problem, dump the errors/warnings to
+ a file, and send the file and the following information to the
+ developers:
+
+ System type (cpu), speed, memory,
+ Linux Distribution,
+ Linux Version,
+ X Window manager (KDE, GNOME, FVWM, etc..)
+
+
+ To install, type (as root)
+ "make install" (or make install-strip to remove debugging information)
+
+ If you later install additional libraries and just can't get
+ ./configure to see them, remove the config.cache file via this
+ command: "rm config.cache", and then re-run configure. Also
+ see the notes above about /sbin/ldconfig.
+
+
+ 14. Kernel AX.25 Interfaces
+
+ NOTE: Xastir is designed by amateur radio operators, for amateur
+ radio operators. It is intended to be used only by them. If there's
+ a way for unlicensed users to operate the amateur radio equipment
+ (this usually includes sending messages through it which key up the
+ transmitter), it is a violation of the rules and your license (and
+ more) may be at risk. The same goes for igating: Be aware of the
+ rules for your country with respect to gating traffic from the 'net
+ onto RF. If there's any question, don't do it.
+
+ Please read this entire section before typing anything, as there are
+ serious security implications for some of this!
+
+ Option 1)
+ If you compiled support for AX.25 in and wish to use Kernel-mode
+ AX-25 interfaces, you _may_ need to type this as root:
+
+ chmod 4555 /usr/local/bin/xastir
+
+ This command makes Xastir run as user "root", no matter who actually
+ started it. This allows Xastir to talk to the kernel AX.25 networking.
+ Note however that the above chmod command will prevent you from creating
+ a core file in case Xastir of a major program fault. This core file aids
+ in debugging to trace what went wrong.
+
+ GENERAL SECURITY WARNING:
+ Beware that Xastir has not been audited for security, and makes limited
+ effort to drop extra privileges. Use this in a multi-user environment
+ at your own risk! The developers have worked hard to fix remote buffer
+ overflows in the code to make Xastir safer to use, but there are _MANY_
+ potential security risks remaining in the code. User beware! We will
+ attempt to plug known security holes in future releases.
+
+ Also be aware that turning on the Interface->Server ports (TCP and UDP)
+ will allow other users who authenticate properly to send packets. In
+ the case of TCP they can only get routed to other TCP ports and to the
+ internet. UDP packets may also get routed to your RF ports (as
+ third-party packets).
+
+ LINUX-SPECIFIC SECURITY WARNING: If you're using Linux AX.25 kernel
+ networking, you'll need to either make Xastir SUID-root, or use a shim
+ (which itself is set to SUID-root) between Xastir and the AX.25 ports.
+ See Option #2 below for the (possibly safer) shim method. If you're the
+ paranoid type (and you should be if you're running a system with multiple
+ users), you may wish to skip SUID-root mode/kernel AX.25 interfaces and
+ use standard serial port TNC interfaces instead. Any program is safer if
+ run as a normal user (not safe, but safer). It is currently impossible
+ to use kernel-mode AX.25 interfaces without the program running with
+ root privileges.
+
+ Option 2)
+ A more security-conscious option is to use a shim program written by
+ Henk de Groot, PE1DNN. This program runs in SUID-root mode but is
+ much smaller and so is easier to audit for security, and provides a
+ new port that Xastir can connect to. The new port can be read/written
+ without having to be the root user. The program is called aprs_tty
+ and can be obtained here:
+
+ http://wetnet.net/~we7u/xastir/aprs_tty.0.0.2.tgz
+
+ It actually responds to some TNC commands. The code is straight forward
+ and works well. Run the program, telling it what port to use, and then
+ in XASTIR set up the TNC to point to the new TTY at 19200. It
+ transmits/receives UI frames, and sets the correct unproto path. In
+ this case DO NOT perform the chmod 4555 command on the Xastir executable.
+
+ Note again that the same SUID-root warnings that were giving in option
+ #1 above also apply to aprs_tty. Buyer beware! As far as we know,
+ aprs_tty has not been audited for security, and makes no effort to drop
+ extra privileges. Use this in a multi-user environment at your own risk!
+
+
+ 15. Serially-Connected TNC's
+
+ NOTE: Xastir is designed by amateur radio operators, for amateur
+ radio operators. It is intended to be used only by them. If there's
+ a way for unlicensed users to operate the amateur radio equipment
+ (this usually includes sending messages through it which key up the
+ transmitter), it is a violation of the rules and your license (and
+ more) may be at risk. The same goes for igating: Be aware of the
+ rules for your country with respect to gating traffic from the 'net
+ onto RF. If there's any question, don't do it.
+
+ Please read this entire section before typing anything, as there are
+ serious security implications for some of this!
+
+ If you're using a serial TNC, configure your TNC startup files in the
+ /usr/local/share/xastir/config directory:
+
+ tnc-startup.sys is used to set up your TNC for Xastir and tnc-stop.sys
+ is to change the TNC back to your normal settings. There are several
+ example TNC startup files in the directory. Choose the one that best
+ suits your TNC and edit to taste. See the note below about where to
+ edit the files. You might be unpleasantly surprised if after you type
+ "make install" next, all your custom changes to the startup files are
+ lost. As always, keep a backup.
+
+ Some people have had trouble getting Xastir to decode packets. While
+ packets were scrolling quite nicely in the View->Incoming Packet Data
+ dialog, stations weren't showing up on the Xastir screen at all. The
+ cause was incorrect settings in the tnc-startup files for that specific
+ TNC. If you change these files in the xastir source directories make sure
+ to do a "make install" to install them into the
+ /usr/local/share/xastir/config/ directory. Another option would be to
+ edit the files in /usr/local/share/xastir/config/ directly. Keep a copy
+ of them in a safe place in any case. You don't want to lose your custom
+ mods you worked so hard to create.
+
+ Some systems don't allow normal users to access the serial ports. It's
+ a permissions thing, but is actually the _correct_ way to configure the
+ serial ports. You can fix this in several ways:
+
+ 1) Add the Xastir user to the group owning the serial ports.
+ 2) Make Xastir run SGID-uucp (or whatever group owns the port).
+ 3) Change the permissions of the device so that any user can access it.
+ 4) Make Xastir run SUID-root.
+
+ Solutions 3 and 4 are highly discouraged. It can be a security nightmare
+ to start opening up files or devices to read/write access by all users,
+ and the same for SUID-root programs. Don't do either of these.
+
+ Exception: If you're going to be running AX.25 kernel networking, you
+ may need to be running Xastir SUID-root anyway, or else you need to
+ install a shim program between the port and Xastir. In the latter case
+ the shim is running SUID-root, not Xastir. See the section above
+ regarding AX.25 kernel networking.
+
+ Here are what the default permissions usually look like for the
+ two serial ports on a Linux box:
+
+ crw-rw---- 1 root uucp 4, 64 Oct 19 08:15 ttyS0
+ crw-rw---- 1 root uucp 4, 65 Apr 14 2001 ttyS1
+
+ (NOTE: For a Windows/Cygwin installation, a few details are different,
+ but the ttyS0 and ttyS1 keywords are the same. Verify that the
+ permissions of these ports are set appropriately for a normal user to read
+ and write to these devices.)
+
+ Solution #1: The root user would run the commands necessary to add
+ the Xastir user to the "uucp" group, which would then give the user
+ the necessary permissions to use the port. Usually this involves
+ editing the /etc/group file, but SysAdmin tools usually exist for
+ doing this more easily.
+
+ Solution #2: As root user, type these commands:
+
+ chgrp uucp /usr/local/bin/xastir
+ chmod 2555 /usr/local/bin/xastir
+
+ If you want to restrict Xastir so that only one user can run it,
+ (in this case "user1") type:
+
+ chown user1 /usr/local/bin/xastir
+ chmod 2500 /usr/local/bin/xastir
+ chgrp uucp /usr/local/bin/xastir
+
+ Solution #3:
+ You can change the permissions of the serial port to allow use by all
+ users, but this is highly discouraged.
+ Here's what Jack Twilley had to say with regards to "chmod uog+rw" (same
+ as chmod 555) for serial ports:
+
+ > This is not necessary, and opens up the possibility of abuse. Not all
+ > Xastir installations are Linux boxes used by a single person with a
+ > single purpose -- I know of several instances that are multi-user
+ > machines with access to the Internet by multiple parties, some of whom
+ > are not licensed amateurs, and another couple of instances where the
+ > serial port is not always used by a TNC but also by other devices such
+ > as Palm HotSync cradles and GPS receivers.
+ >
+ > Here are two more secure solutions:
+ >
+ > * use non-root users
+ > One way to use the setuid facilities in Unix would be to set
+ > the xastir binary's user ID to match the user that owns the serial
+ > port. Under Solaris, the default ownership of /dev/cua/a is
+ > uucp:tty, with a default permission of 0600. The command 'chown
+ > uucp /usr/local/bin/xastir' followed by the command 'chmod 4555
+ > /usr/local/bin/xastir' will allow xastir to run properly without
+ > changing the serial port's permissions or ownership, thus
+ > minimizing any impact on other applications that use the serial
+ > port.
+
+Note from Curt: This chmod command will prevent creation of "core"
+file that are useful for debugging in case Xastir crashes.
+
+ >
+ > * use groups
+ > A better way to use the setuid facilities in Unix is to set the
+ > xastir binary's *group* ID to match a group that already has the
+ > privilege to mess with the serial port. Under FreeBSD, the default
+ > ownership of /dev/cuaa0 is uucp:dialer, with a default permission
+ > of 0660. The command 'chgrp dialer /usr/local/bin/xastir' followed
+ > by the command 'chmod 2555 /usr/local/bin/xastir' will change
+ > Xastir's group to the serial port's group, and then add the setgid
+ > privilege to the binary. Now when xastir starts up, it will have
+ > the minimum privilege necessary to do what it needs to do, without
+ > being yet another root exploit-in-waiting.
+
+
+ 16. Serially-Connected Garmin RINO Radio/GPS
+
+ If you have a Garmin RINO attached to a serial port, have GPSMan
+ installed, and have support for GPSMan compiled into Xastir, then Xastir
+ has the capability to periodically download waypoints from the RINO unit
+ and create APRS(tm) Objects out of them. Any RINO waypoints that begin with
+ "APRS" will be automatically created, placed on the map, and transmitted
+ as your own Xastir APRS(tm) objects. If you wish to see them but not transmit
+ them, turn off Object/Item transmit or global transmit in the interface
+ menu. Another option is to turn off the transmit enable per interface.
+
+ Please note that Xastir cannot cause the attached RINO to poll the other
+ RINO units on the air. Xastir can only download the waypoints that the
+ attached RINO has collected from the other RINO units that it is passively
+ monitoring.
+
+ Here's a blurb from Wes Johnston about the RINO's:
+
+ "Lets say I have three RINO radios... two in the hands of the SAR teams on
+ the ground, and a third radio in a plane circling above. It is preferred
+ that the radio in the hands of the SAR teams be the nicer rino120 since it
+ does mapping. The radio in the plane can be the lowly rino110 since it
+ does not do mapping but you will have a copy of xastir with maps on the
+ laptop with you anyway.
+
+ If I set two of my rino radios to APRSSAR1 and APRSSAR2, and connect a
+ third rino radio to xastir with serial in the plane, xastir will query
+ rino radio #3 at any one minute interval between 0 and 30 minutes, get the
+ APRS* waypoints, lop off the first four characters and publish the shorter
+ named waypoints as SAR1 and SAR2 as APRS(tm) objects on to your TNC. The
+ hitch to this is that the rino radio cannot automatically poll the RINO
+ users' locations on the ground. You have to manually (on the radio)
+ select a menu item called POLL and poll the users that way. The reason
+ the first four characters of the rino callsign have to be "APRS" is that
+ when you send a query, rino only asks about the first 4 chars... so any
+ station with the first four that match will answer... ie all of them in
+ your group. The other method is to simply fly the plane overhead and
+ listen (eavesdrop) on the channel and passively pickup the locations of the
+ groups as they converse with one another. The rino will send it's
+ location just as you un-key the PTT if it has been >30 sec since the last
+ time you sent your position. It would be practical to simply ask each
+ team for an update... they just need to squeeze their PTT for a moment
+ (ie kerchunk) to send a position."
+
+
+ 17. Start up XASTIR and read the help files to configure it. If you have
+ problems, please consult the FAQ file.
+
+ You can now start XASTIR. On most systems that the path is set up in
+ FHS format just type "xastir". On other systems type
+ "/usr/local/bin/xastir" to start the program.
+
+ If you see errors at this point that say something like "Can't load
+ xxx library" this means you forgot to either update /etc/ld.so.conf (or
+ /etc/ld.so.conf.d directory on some systems) and run /sbin/ldconfig, or
+ add the LD_LIBRARY_PATH variable for your shell, and the "ld" loader
+ can't link the libraries with the Xastir executable to get it running in
+ memory. Note that if you're running Xastir as SUID root, the
+ LD_LIBRARY_PATH variable is ignored.
+
+ To set a new language or change the language current choice, use
+ this command line:
+
+ xastir -l <language>
+
+ Current choices are:
+
+ Dutch English French German Italian Portuguese Spanish
+ ElmerFudd MuppetsChef OldeEnglish PigLatin PirateEnglish
+
+ This option will be stored in the users config file for the next time
+ Xastir is run. On new installs Xastir will default to English unless
+ you use this command line option.
+
+
+ CONNECTING TO AN INTERNET SERVER:
+
+ Here are some lists of Internet servers:
+
+ http://members.aol.com/wa8lmf3/miscinfo/APRServe.txt
+ http://www.wa6oft.com/APRServe.txt
+ http://www.aprs-is.net/aprsservers.htm
+ http://www.aprs-is.net/APRSServers.htm
+
+
+ Filter port syntax (for those ports that allow user-selectable
+ filtering):
+
+ http://www.aprs-is.net/javaprssrvr/javaprsfilter.htm
+
+
+ The procedure to connect to one of them is this:
+
+ *) Select Interface->Properties.
+ *) Click Add.
+ *) Select Internet Server, click Add.
+ *) Fill in the "Host" and "Port" boxes.
+ *) Enter the Pass-code found by running "callpass" with your callsign
+ in an xterm window.
+ *) Set the togglebuttons and filter parameters per your preferences. The
+ "filter" keyword is added by Xastir, so you don't need to add that word
+ to the box. If the box has anything in it, "filter" is prepended to the
+ text when Xastir sends the string to the server
+ *) Optionally put in a comment. That shows up in the Interface and
+ Properties dialogs to remind you of the details for that connection.
+ *) Click OK.
+
+ A short list of the first-tier servers (you may want to connect to the
+ second-tier servers or regional/local servers instead):
+
+ first.aprs.net ports 10151 (history) or 10152 (no history)
+ second.aprs.net ports 10151 (history) or 10152 (no history)
+ third.aprs.net ports 10151 (history) or 10152 (no history)
+ fourth.aprs.net ports 10151 (history) or 10152 (no history)
+
+
+ FESTIVAL NOTE: From: J. Lance Cotton:
+ One thing that I found that I had to do to finally get festival to work was
+ to get rid of the 'only localhost can connect to the server' pref in the
+ festival configuration. I don't know if that's the default on a source
+ install (I installed festival from RPM's), but it might be.
+
+ I don't know why it doesn't let localhost connect, even though it's the
+ only one specifically allowed.
+
+ Here's what to do: Open the 'festival.scm' file (I found mine in
+ /usr/share/festival/' and look for the line that starts like:
+
+ (defvar server_access_list ...
+
+ Make it look like:
+
+ (defvar server_access_list nil
+
+ Then restart the festival server.
+ -Lance KJ5O
+
+ Additional note from Alan Crosswell: If you run the festival_server
+ script instead of festival -server, then the permissions for localhost
+ get set up for you.
+
+
+You probably want to download some maps and additional data files. The
+instructions for this are in the README.MAPS.
+
+-----------------------------------------------------------------------
+
+NOTES FOR DEVELOPERS:
+---------------------
+
+Profiling:
+----------
+1) "./configure --with-profiling"
+
+This will add "-pg" to the CFLAGS section of the Makefiles, which
+turns on the collection of profiling data while the executable is
+running (on Linux anyway).
+
+2) "make clean"
+
+3) "make install" (Don't do "make install-strip" here, as that will
+strip off the symbol table information that gprof requires)
+
+4) "xastir &"
+
+5) Let Xastir run for some period of time.
+
+6) Close Xastir
+
+7) "gprof /usr/local/bin/xastir | tee profile.txt"
+
+Gprof will use the Xastir binary and the gmon.out file created from
+running Xastir to give you the profile listing.
+
+Add the "-l" flag to the gprof line to give you a line-by-line
+profile listing, but be prepared for a long run-time and a lot of
+CPU to be used by gprof to generate it:
+
+ "gprof -l /usr/local/bin/xastir | tee profile.txt"
+
+Also see this link, which talks about how to profile multi-threaded
+applications:
+
+ http://sam.zoy.org/writings/programming/gprof.html
+
+With the method described, you compile/install their library code,
+then invoke Xastir like this:
+
+ LD_PRELOAD=xastir/src/gprof-helper.so xastir &
+
+
+ mv gmon.out gmon.old; gprof /usr/local/bin/xastir gmon.old \
+ | tee profile.txt; gprof -l /usr/local/bin/xastir gmon.old \
+ | tee profile2.txt
+
+
+Checking for Memory Leaks:
+--------------------------
+
+A simple method for just checking malloc's/free's is to set
+MALLOC_CHECK to a 1 or a 2, at least on Linux. See the malloc man
+page for more info.
+
+For more thorough checks, use libgc:
+
+1) Install libgc, the conservative garbage collector for C and C++.
+Find it at:
+
+ http://www.hpl.hp.com/personal/Hans_Boehm/gc
+
+Configure/install libgc like this:
+
+ ./configure --enable-threads=posix
+
+Make sure that "-DGC_LINUX_THREADS" and "-D_REENTRANT" are defined
+in the Makefile if you're compiling it on Linux.
+
+Optional: Change Makefile to add "-DSAVE_CALL_CHAIN" on the DEFS
+line. This will provide more of a stack trace each time a leak is
+found. This is sometimes useful but much more verbose.
+
+ make
+ make check
+ su
+ make install
+ exit (from root)
+
+2) Now, back in the xastir directory:
+
+ ./configure --with-libgc
+
+Make sure that "-fomit_frame_pointer" is _NOT_ in the Makefiles.
+This will mess up the optional stack trace if present.
+
+ make clean
+ make install
+ xastir &
+
+Let Xastir run for some period of time.
+
+Libgc will dump messages to the xterm as memory leaks are found.
+Any Xastir memory leaks should have a filename and a line number
+listed. Memory leaks from lower-level libraries will be missing the
+detailed information, so they are easy to spot (and mostly useless
+for the purpose of finding and patching memory leaks).
+
+Note also that libgc will take Xastir's memory usage up quite a bit,
+so don't be surprised if Xastir uses two or three times the normal
+amount of memory while you're debugging memory leaks with libgc.
+
+
+
+ ------------------------------------------------------------------------
+APRS(tm) is a Trademark of Bob Bruninga
+
+Copyright (C) 1999 Frank Giannandrea
+Copyright (C) 2000-2012 The Xastir Group
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7e48ee7
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,1775 @@
+
+$Id: LICENSE,v 1.15 2012/11/01 18:57:18 we7u Exp $
+
+
+*) The majority of the Xastir source code is under the GPL license.
+See the file named "COPYING" for details.
+
+
+-------------------------------
+-------------------------------
+
+
+*) Some of the programs in the scripts directory may contain other
+licensing information. See the individual files for details.
+
+
+-------------------------------
+-------------------------------
+
+
+*) datum.h and datum.c were derived from public domain source code.
+The name and copyright are listed in that file.
+
+
+-------------------------------
+-------------------------------
+
+
+*) rotated.h and rotated.c are available under the following license:
+
+/* xvertext 5.0, Copyright (c) 1993 Alan Richardson (mppa3 at uk.ac.sussex.syma)
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both the
+ * copyright notice and this permission notice appear in supporting
+ * documentation. All work developed as a consequence of the use of
+ * this program should duly acknowledge such use. No representations are
+ * made about the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+
+-------------------------------
+-------------------------------
+
+
+*) festival.h and festival.c are available under the following license:
+
+/*************************************************************************/
+/* */
+/* Centre for Speech Technology Research */
+/* University of Edinburgh, UK */
+/* Copyright (c) 1999 */
+/* All Rights Reserved. */
+/* */
+/* Permission is hereby granted, free of charge, to use and distribute */
+/* this software and its documentation without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of this work, and to */
+/* permit persons to whom this work is furnished to do so, subject to */
+/* the following conditions: */
+/* 1. The code must retain the above copyright notice, this list of */
+/* conditions and the following disclaimer. */
+/* 2. Any modifications must be clearly marked as such. */
+/* 3. Original authors' names are not deleted. */
+/* 4. The authors' names are not used to endorse or promote products */
+/* derived from this software without specific prior written */
+/* permission. */
+/* */
+/* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
+/* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
+/* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
+/* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
+/* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
+/* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
+/* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
+/* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
+/* THIS SOFTWARE. */
+/* */
+/*************************************************************************/
+
+
+-------------------------------
+-------------------------------
+
+
+*) "Free Standards Group, FSG, Linux Standard Base, LSB, Free
+Standards Certified, LSB Certified and the Free Standards Certified
+logo are trademarks, service marks and certification marks, as
+appropriate, of Free Standards Group in the United States and in
+other countries."
+
+We are in no way representing that Xastir has been certified by the
+FSG. To do so costs real money. We do intend some Xastir binaries
+to install and run properly on LSB-3.0 compliant x86 Linux systems
+though...
+
+
+-------------------------------
+-------------------------------
+
+
+*) libcurl (<http://curl.haxx.se/> is available under the following
+license. Note that this license is only applicable to a distributed
+Xastir BINARY which includes this library:
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 1996 - 2006, Daniel Stenberg, <daniel at haxx.se>.
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software for
+any purpose with or without fee is hereby granted, provided that the
+above copyright notice and this permission notice appear in all
+copies.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE AUTHORS
+OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in this Software without prior written
+authorization of the copyright holder.
+
+
+-------------------------------
+-------------------------------
+
+
+*) libdb (<http://www.sleepycat.com>) is available under the
+following license. Note that this license is only applicable to a
+distributed Xastir BINARY which includes this library:
+
+The following is the license that applies to this copy of the
+Berkeley DB software. For a license to use the Berkeley DB software
+under conditions other than those described here, or to purchase
+support for this software, please contact Sleepycat Software by
+email at info at sleepycat.com, or on the Web at
+http://www.sleepycat.com.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+/*
+ * Copyright (c) 1990-2005
+ * Sleepycat Software. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the DB software and any
+ * accompanying software that uses the DB software. The source code
+ * must either be included in the distribution or be available for no
+ * more than the cost of distribution plus a nominal fee, and must be
+ * freely redistributable under reasonable conditions. For an
+ * executable file, complete source code means the source code for all
+ * modules it contains. It does not include source code for modules or
+ * files that typically accompany the major components of the operating
+ * system on which the executable file runs.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SLEEPYCAT SOFTWARE ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SLEEPYCAT SOFTWARE
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994, 1995
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1995, 1996
+ * The President and Fellows of Harvard University. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY HARVARD AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL HARVARD OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+-------------------------------
+-------------------------------
+
+
+*) GraphicsMagick (<http://www.graphicsmagick.org/>) is available
+under the following license. Note that this license is only
+applicable to a distributed Xastir BINARY which includes this
+library:
+
+This file is part of the GraphicsMagick software distributed by the
+GraphicsMagick Group.
+
+[ Please note that the legal community considers 15 or more total lines
+of code or text (not necessarily contiguous) to be significant for the
+purposes of copyright. Repeated changes such as renaming a symbol has
+similar significance to changing one line of code. ]
+
+The licences which components of this software fall under are as follows.
+
+1)
+ In November 2002, the GraphicsMagick Group created GraphicsMagick
+ from ImageMagick Studio's ImageMagick and applied this license:
+
+ Copyright (C) 2002 GraphicsMagick Group, an organization dedicated
+ to making software imaging solutions freely available.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ ("GraphicsMagick"), to deal in GraphicsMagick without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of GraphicsMagick,
+ and to permit persons to whom GraphicsMagick is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of GraphicsMagick.
+
+ The software is provided "as is", without warranty of any kind, express
+ or implied, including but not limited to the warranties of
+ merchantability, fitness for a particular purpose and noninfringement.
+ In no event shall GraphicsMagick Group be liable for any claim,
+ damages or other liability, whether in an action of contract, tort or
+ otherwise, arising from, out of or in connection with GraphicsMagick
+ or the use or other dealings in GraphicsMagick.
+
+ Except as contained in this notice, the name of the GraphicsMagick
+ Group shall not be used in advertising or otherwise to promote the
+ sale, use or other dealings in GraphicsMagick without prior written
+ authorization from the GraphicsMagick Group.
+
+2)
+ In August 1999, ImageMagick Studio assumed the responsibility for the
+ development of ImageMagick and applied a new license:
+
+ Copyright (C) 2002 ImageMagick Studio, a non-profit organization dedicated
+ to making software imaging solutions freely available.
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files ("ImageMagick"),
+ to deal in ImageMagick without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of ImageMagick, and to permit persons to whom the
+ ImageMagick is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of ImageMagick.
+
+ The software is provided "as is", without warranty of any kind, express or
+ implied, including but not limited to the warranties of merchantability,
+ fitness for a particular purpose and noninfringement. In no event shall
+ ImageMagick Studio be liable for any claim, damages or other liability,
+ whether in an action of contract, tort or otherwise, arising from, out of
+ or in connection with ImageMagick or the use or other dealings in
+ ImageMagick.
+
+ Except as contained in this notice, the name of the ImageMagick Studio
+ shall not be used in advertising or otherwise to promote the sale, use or
+ other dealings in ImageMagick without prior written authorization from the
+ ImageMagick Studio.
+
+3)
+ From 1991 to August 1999, ImageMagick was developed and distributed by
+ E. I. du Pont de Nemours and Company:
+
+ Copyright 1999 E. I. du Pont de Nemours and Company
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files
+ ("ImageMagick"), to deal in ImageMagick without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of ImageMagick, and to
+ permit persons to whom the ImageMagick is furnished to do so, subject
+ to the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of ImageMagick.
+
+ The software is provided "as is", without warranty of any kind, express
+ or implied, including but not limited to the warranties of
+ merchantability, fitness for a particular purpose and noninfringement.
+ In no event shall E. I. du Pont de Nemours and Company be liable for
+ any claim, damages or other liability, whether in an action of
+ contract, tort or otherwise, arising from, out of or in connection with
+ ImageMagick or the use or other dealings in ImageMagick.
+
+ Except as contained in this notice, the name of the E. I. du Pont de
+ Nemours and Company shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in ImageMagick without prior
+ written authorization from the E. I. du Pont de Nemours and Company.
+
+4)
+ This copyright is limited to some code (for locating an installed
+ Ghostscript under Windows) in the file magick/nt_base.c which was
+ incorporated from the gsview package:
+
+ Copyright (C) 2000-2002, Ghostgum Software Pty Ltd. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this file ("Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies of
+ this Software, and to permit persons to whom this file is furnished to
+ do so, subject to the following conditions:
+
+ This Software is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing.
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+5)
+ The GraphicsMagick Base64Decode() and Base64Encode() functions are
+ based on source code obtained from OpenSSH.
+ This source code is distributed under the following license.
+
+ Copyright (c) 2000 Markus Friedl. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+6)
+ Many of the pattern images in coders/logo.c are derived from XFig,
+ which is distributed under the following license:
+
+ FIG : Facility for Interactive Generation of figures
+ Copyright (c) 1985-1988 by Supoj Sutanthavibul
+ Parts Copyright (c) 1989-2000 by Brian V. Smith
+ Parts Copyright (c) 1991 by Paul King
+
+ Any party obtaining a copy of these files is granted, free of charge, a
+ full and unrestricted irrevocable, world-wide, paid up, royalty-free,
+ nonexclusive right and license to deal in this software and
+ documentation files (the "Software"), including without limitation the
+ rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons who receive
+ copies from any such party to do so, with the only requirement being
+ that this copyright notice remain intact.
+
+7)
+ The documentation for the composition operators is copied from the
+ rlecomp manual page, which is authored by Rod Bogart and John W.
+ Peterson. Rlecomp is part of the Utah Raster Toolkit distributed by the
+ University of Michigan and the University of Utah. The copyright for
+ this manual page is as follows:
+
+ Copyright (c) 1986, University of Utah
+
+ This software is copyrighted as noted below. It may be freely copied,
+ modified, and redistributed, provided that the copyright notice is
+ preserved on all copies.
+
+ There is no warranty or other guarantee of fitness for this software,
+ it is provided solely "as is". Bug reports or fixes may be sent
+ to the author, who may or may not act on them as he desires.
+
+ You may not include this software in a program or other software product
+ without supplying the source, or without informing the end-user that the
+ source is available for no extra charge.
+
+ If you modify this software, you should include a notice giving the
+ name of the person performing the modification, the date of modification,
+ and the reason for such modification.
+
+8)
+ The C++ API known as "Magick++", and which resides in the Magick++
+ directory, is distributed under the following license:
+
+ Copyright 1999 - 2003 Bob Friesenhahn <bfriesen at simple.dallas.tx.us>
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of the source files and associated documentation
+ files ("Magick++"), to deal in Magick++ without restriction,
+ including without limitation of the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of
+ Magick++, and to permit persons to whom the Magick++ is furnished
+ to do so, subject to the following conditions:
+
+ This copyright notice shall be included in all copies or
+ substantial portions of Magick++. The copyright to Magick++ is
+ retained by its author and shall not be subsumed or replaced by any
+ other copyright.
+
+ The software is provided "as is", without warranty of any kind,
+ express or implied, including but not limited to the warranties of
+ merchantability, fitness for a particular purpose and
+ noninfringement. In no event shall Bob Friesenhahn be liable for
+ any claim, damages or other liability, whether in an action of
+ contract, tort or otherwise, arising from, out of or in connection
+ with Magick++ or the use or other dealings in Magick++.
+
+9)
+ GraphicsMagick makes use of third-party "delegate" libraries to
+ support certain optional features. These libraries bear their own
+ copyrights and licenses, which may be more or less restrictive than the
+ GraphicsMagick license. For convenience, when GraphicsMagick is
+ bundled with (or compiled with) "delegate" libraries, a copy of the
+ licenses for these libraries is provided in a "licenses" directory.
+
+
+-------------------------------
+-------------------------------
+
+
+*) Jasper (<http://www.ece.uvic.ca/~mdadams/jasper/>) is available
+under the following license. Note that this license is only
+applicable to a distributed Xastir BINARY which includes this
+library:
+
+JasPer License Version 2.0
+
+Copyright (c) 1999-2000 Image Power, Inc.
+Copyright (c) 1999-2000 The University of British Columbia
+Copyright (c) 2001-2003 Michael David Adams
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person (the
+"User") obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the
+following conditions:
+
+1. The above copyright notices and this permission notice (which
+includes the disclaimer below) shall be included in all copies or
+substantial portions of the Software.
+
+2. The name of a copyright holder shall not be used to endorse or
+promote products derived from the Software without specific prior
+written permission.
+
+THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
+LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
+"AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO
+EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE
+PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
+THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
+EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
+BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
+PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS
+GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
+ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE
+IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
+SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
+AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
+SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
+THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
+PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
+RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
+EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
+
+
+-------------------------------
+-------------------------------
+
+
+*) Jpeg (<http://www.ijg.org/>) is available under the following
+license. Note that this license is only applicable to a distributed
+Xastir BINARY which includes this library:
+
+In plain English:
+
+1. We don't promise that this software works. (But if you find any bugs,
+ please let us know!)
+2. You can use this software for whatever you want. You don't have to pay us.
+3. You may not pretend that you wrote this software. If you use it in a
+ program, you must acknowledge somewhere in your documentation that
+ you've used the IJG code.
+
+In legalese:
+
+The authors make NO WARRANTY or representation, either express or implied,
+with respect to this software, its quality, accuracy, merchantability, or
+fitness for a particular purpose. This software is provided "AS IS", and you,
+its user, assume the entire risk as to its quality and accuracy.
+
+This software is copyright (C) 1991-1998, Thomas G. Lane.
+All Rights Reserved except as specified below.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+software (or portions thereof) for any purpose, without fee, subject to these
+conditions:
+(1) If any part of the source code for this software is distributed, then this
+README file must be included, with this copyright and no-warranty notice
+unaltered; and any additions, deletions, or changes to the original files
+must be clearly indicated in accompanying documentation.
+(2) If only executable code is distributed, then the accompanying
+documentation must state that "this software is based in part on the work of
+the Independent JPEG Group".
+(3) Permission for use of this software is granted only if the user accepts
+full responsibility for any undesirable consequences; the authors accept
+NO LIABILITY for damages of any kind.
+
+These conditions apply to any software derived from or based on the IJG code,
+not just to the unmodified library. If you use our work, you ought to
+acknowledge us.
+
+Permission is NOT granted for the use of any IJG author's name or company name
+in advertising or publicity relating to this software or products derived from
+it. This software may be referred to only as "the Independent JPEG Group's
+software".
+
+We specifically permit and encourage the use of this software as the basis of
+commercial products, provided that all warranty or liability claims are
+assumed by the product vendor.
+
+
+ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
+sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
+ansi2knr.c is NOT covered by the above copyright and conditions, but instead
+by the usual distribution terms of the Free Software Foundation; principally,
+that you must include source code if you redistribute it. (See the file
+ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part
+of any program generated from the IJG code, this does not limit you more than
+the foregoing paragraphs do.
+
+The Unix configuration script "configure" was produced with GNU Autoconf.
+It is copyright by the Free Software Foundation but is freely distributable.
+The same holds for its supporting scripts (config.guess, config.sub,
+ltconfig, ltmain.sh). Another support script, install-sh, is copyright
+by M.I.T. but is also freely distributable.
+
+It appears that the arithmetic coding option of the JPEG spec is covered by
+patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot
+legally be used without obtaining one or more licenses. For this reason,
+support for arithmetic coding has been removed from the free JPEG software.
+(Since arithmetic coding provides only a marginal gain over the unpatented
+Huffman mode, it is unlikely that very many implementations will support it.)
+So far as we are aware, there are no patent restrictions on the remaining
+code.
+
+The IJG distribution formerly included code to read and write GIF files.
+To avoid entanglement with the Unisys LZW patent, GIF reading support has
+been removed altogether, and the GIF writer has been simplified to produce
+"uncompressed GIFs". This technique does not use the LZW algorithm; the
+resulting GIF files are larger than usual, but are readable by all standard
+GIF decoders.
+
+We are required to state that
+ "The Graphics Interchange Format(c) is the Copyright property of
+ CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ CompuServe Incorporated."
+
+
+-------------------------------
+-------------------------------
+
+
+*) Lesstif (<http://www.lesstif.org/>) is available under the
+following license. Note that this license is only applicable to a
+distributed Xastir BINARY which includes this library:
+
+The included files COPYING and COPYING.LIB.LESSTIF, as may apply.
+
+-------------------------------
+-------------------------------
+
+
+*) libpng (<http://www.libpng.org/pub/png/libpng.html>) is available
+under the following license. Note that this license is only
+applicable to a distributed Xastir BINARY which includes this
+library:
+
+This copy of the libpng notices is provided for your convenience. In case of
+any discrepancy between this copy and the notices in the file png.h that is
+included in the libpng distribution, the latter shall prevail.
+
+COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+
+If you modify libpng you may insert additional notices immediately following
+this sentence.
+
+libpng versions 1.2.6, August 15, 2004, through 1.2.14, November 28, 2006, are
+Copyright (c) 2004, 2006 Glenn Randers-Pehrson, and are
+distributed according to the same disclaimer and license as libpng-1.2.5
+with the following individual added to the list of Contributing Authors
+
+ Cosmin Truta
+
+libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are
+Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are
+distributed according to the same disclaimer and license as libpng-1.0.6
+with the following individuals added to the list of Contributing Authors
+
+ Simon-Pierre Cadieux
+ Eric S. Raymond
+ Gilles Vollant
+
+and with the following additions to the disclaimer:
+
+ There is no warranty against interference with your enjoyment of the
+ library or against infringement. There is no warranty that our
+ efforts or the library will fulfill any of your particular purposes
+ or needs. This library is provided with all faults, and the entire
+ risk of satisfactory quality, performance, accuracy, and effort is with
+ the user.
+
+libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are
+distributed according to the same disclaimer and license as libpng-0.96,
+with the following individuals added to the list of Contributing Authors:
+
+ Tom Lane
+ Glenn Randers-Pehrson
+ Willem van Schaik
+
+libpng versions 0.89, June 1996, through 0.96, May 1997, are
+Copyright (c) 1996, 1997 Andreas Dilger
+Distributed according to the same disclaimer and license as libpng-0.88,
+with the following individuals added to the list of Contributing Authors:
+
+ John Bowler
+ Kevin Bracey
+ Sam Bushell
+ Magnus Holmgren
+ Greg Roelofs
+ Tom Tanner
+
+libpng versions 0.5, May 1995, through 0.88, January 1996, are
+Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+
+For the purposes of this copyright and license, "Contributing Authors"
+is defined as the following set of individuals:
+
+ Andreas Dilger
+ Dave Martindale
+ Guy Eric Schalnat
+ Paul Schmidt
+ Tim Wegner
+
+The PNG Reference Library is supplied "AS IS". The Contributing Authors
+and Group 42, Inc. disclaim all warranties, expressed or implied,
+including, without limitation, the warranties of merchantability and of
+fitness for any purpose. The Contributing Authors and Group 42, Inc.
+assume no liability for direct, indirect, incidental, special, exemplary,
+or consequential damages, which may result from the use of the PNG
+Reference Library, even if advised of the possibility of such damage.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+source code, or portions hereof, for any purpose, without fee, subject
+to the following restrictions:
+
+1. The origin of this source code must not be misrepresented.
+
+2. Altered versions must be plainly marked as such and must not
+ be misrepresented as being the original source.
+
+3. This Copyright notice may not be removed or altered from any
+ source or altered source distribution.
+
+The Contributing Authors and Group 42, Inc. specifically permit, without
+fee, and encourage the use of this source code as a component to
+supporting the PNG file format in commercial products. If you use this
+source code in a product, acknowledgment is not required but would be
+appreciated.
+
+
+A "png_get_copyright" function is available, for convenient use in "about"
+boxes and the like:
+
+ printf("%s",png_get_copyright(NULL));
+
+Also, the PNG logo (in PNG format, of course) is supplied in the
+files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
+
+Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a
+certification mark of the Open Source Initiative.
+
+Glenn Randers-Pehrson
+glennrp at users.sourceforge.net
+November 28, 2006
+
+
+-------------------------------
+-------------------------------
+
+
+*) PCRE (<http://www.pcre.org/>) is available under the following
+license. Note that this license is only applicable to a distributed
+Xastir BINARY which includes this library:
+
+PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+Release 6 of PCRE is distributed under the terms of the "BSD" licence, as
+specified below. The documentation for PCRE, supplied in the "doc"
+directory, is distributed under the same terms as the software itself.
+
+The basic library functions are written in C and are freestanding. Also
+included in the distribution is a set of C++ wrapper functions.
+
+
+THE BASIC LIBRARY FUNCTIONS
+---------------------------
+
+Written by: Philip Hazel
+Email local part: ph10
+Email domain: cam.ac.uk
+
+University of Cambridge Computing Service,
+Cambridge, England. Phone: +44 1223 334714.
+
+Copyright (c) 1997-2006 University of Cambridge
+All rights reserved.
+
+
+THE C++ WRAPPER FUNCTIONS
+-------------------------
+
+Contributed by: Google Inc.
+
+Copyright (c) 2006, Google Inc.
+All rights reserved.
+
+
+THE "BSD" LICENCE
+-----------------
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above copyright
+ * notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ * copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the name
+ * of Google
+ Inc. nor the names of their contributors may be used to endorse or
+ promote products derived from this software without specific prior
+ written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+-------------------------------
+-------------------------------
+
+
+*) ZLIB (<http://www.zlib.net/>) is available under the following
+license. Note that this license is only applicable to a distributed
+Xastir BINARY which includes this library:
+
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup at gzip.org madler at alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not*
+receiving lengthy legal documents to sign. The sources are provided
+for free but without warranty of any kind. The library has been
+entirely written by Jean-loup Gailly and Mark Adler; it does not
+include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include
+in the file ChangeLog history information documenting your changes. Please
+read the FAQ for more information on the distribution of modified source
+versions.
+
+
+-------------------------------
+-------------------------------
+
+
+*) libXt.a (<http://gforge.freestandards.org/scm/?group_id=5>) is
+available under the following license. Note that this license is
+only applicable to a distributed Xastir BINARY which includes this
+library:
+
+ Licenses
+
+ The XFree86 Project
+
+ January 2002
+
+1. XFree86 License
+
+XFree86 code without an explicit copyright is covered by the following copy-
+right/license:
+
+Copyright (C) 1994-2002 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is fur-
+nished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
+NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other deal-
+ings in this Software without prior written authorization from the XFree86
+Project.
+
+2. Other Licenses
+
+Portions of code are covered by the following licenses/copyrights. See indi-
+vidual files for the copyright dates.
+
+2.1 X/MIT Copyrights
+
+2.1.1 X Consortium
+
+Copyright (C) <date> X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is fur-
+nished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X
+CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+X Window System is a trademark of X Consortium, Inc.
+
+2.1.2 The Open Group
+
+Copyright <date> The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open
+Group.
+
+2.2 Berkeley-based copyrights:
+
+2.2.1 General
+
+Redistribution and use in source and binary forms, with or without modifica-
+tion, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
+CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
+CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
+ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+2.2.2 UCB/LBL
+
+Copyright (c) 1993 The Regents of the University of California. All rights
+reserved.
+
+This software was developed by the Computer Systems Engineering group at
+Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and contributed to
+Berkeley.
+
+All advertising materials mentioning features or use of this software must
+display the following acknowledgement: This product includes software devel-
+oped by the University of California, Lawrence Berkeley Laboratory.
+
+Redistribution and use in source and binary forms, with or without modifica-
+tion, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement: This product includes soft-
+ ware developed by the University of California, Berkeley and its con-
+ tributors.
+
+ 4. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DIS-
+CLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+2.3 NVIDIA Corp
+
+Copyright (c) 1996 NVIDIA, Corp. All rights reserved.
+
+NOTICE TO USER: The source code is copyrighted under U.S. and international
+laws. NVIDIA, Corp. of Sunnyvale, California owns the copyright and as
+design patents pending on the design and interface of the NV chips. Users
+and possessors of this source code are hereby granted a nonexclusive, roy-
+alty-free copyright and design patent license to use this code in individual
+and commercial software.
+
+Any use of this source code must include, in the user documentation and
+internal comments to the code, notices to the end user as follows:
+
+Copyright (c) 1996 NVIDIA, Corp. NVIDIA design patents pending in the U.S.
+and foreign countries.
+
+NVIDIA, CORP. MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE
+CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WAR-
+RANTY OF ANY KIND. NVIDIA, CORP. DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA, CORP. BE LIABLE
+FOR ANY SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAM-
+AGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.
+
+2.4 GLX Public License
+
+GLX PUBLIC LICENSE (Version 1.0 (2/11/99)) ("License")
+
+Subject to any third party claims, Silicon Graphics, Inc. ("SGI") hereby
+grants permission to Recipient (defined below), under Recipient's copyrights
+in the Original Software (defined below), to use, copy, modify, merge, pub-
+lish, distribute, sublicense and/or sell copies of Subject Software (defined
+below), and to permit persons to whom the Subject Software is furnished in
+accordance with this License to do the same, subject to all of the following
+terms and conditions, which Recipient accepts by engaging in any such use,
+copying, modifying, merging, publishing, distributing, sublicensing or sell-
+ing:
+
+1. Definitions.
+
+ (a) "Original Software" means source code of computer software code
+ which is described in Exhibit A as Original Software.
+
+ (b) "Modifications" means any addition to or deletion from the sub-
+ stance or structure of either the Original Software or any previous
+ Modifications. When Subject Software is released as a series of
+ files, a Modification means (i) any addition to or deletion from
+ the contents of a file containing Original Software or previous
+ Modifications and (ii) any new file that contains any part of the
+ Original Code or previous Modifications.
+
+ (c) "Subject Software" means the Original Software or Modifications
+ or the combination of the Original Software and Modifications, or
+ portions of any of the foregoing.
+
+ (d) "Recipient" means an individual or a legal entity exercising
+ rights under, and complying with all of the terms of, this License.
+ For legal entities, "Recipient" includes any entity which controls,
+ is controlled by, or is under common control with Recipient. For
+ purposes of this definition, "control" of an entity means (a) the
+ power, direct or indirect, to direct or manage such entity, or (b)
+ ownership of fifty percent (50%) or more of the outstanding shares
+ or beneficial ownership of such entity.
+
+2. Redistribution of Source Code Subject to These Terms. Redistributions of
+Subject Software in source code form must retain the notice set forth in
+Exhibit A, below, in every file. A copy of this License must be included in
+any documentation for such Subject Software where the recipients' rights
+relating to Subject Software are described. Recipient may distribute the
+source code version of Subject Software under a license of Recipient's
+choice, which may contain terms different from this License, provided that
+(i) Recipient is in compliance with the terms of this License, and (ii) the
+license terms include this Section 2 and Sections 3, 4, 7, 8, 10, 12 and 13
+of this License, which terms may not be modified or superseded by any other
+terms of such license. If Recipient distributes the source code version under
+a different license Recipient must make it absolutely clear that any terms
+which differ from this License are offered by Recipient alone, not by SGI.
+Recipient hereby agrees to indemnify SGI for any liability incurred by SGI as
+a result of any such terms Recipient offers.
+
+3. Redistribution in Executable Form. The notice set forth in Exhibit A must
+be conspicuously included in any notice in an executable version of Subject
+Software, related documentation or collateral in which Recipient describes
+the user's rights relating to the Subject Software. Recipient may distribute
+the executable version of Subject Software under a license of Recipient's
+choice, which may contain terms different from this License, provided that
+(i) Recipient is in compliance with the terms of this License, and (ii) the
+license terms include this Section 3 and Sections 4, 7, 8, 10, 12 and 13 of
+this License, which terms may not be modified or superseded by any other
+terms of such license. If Recipient distributes the executable version under
+a different license Recipient must make it absolutely clear that any terms
+which differ from this License are offered by Recipient alone, not by SGI.
+Recipient hereby agrees to indemnify SGI for any liability incurred by SGI as
+a result of any such terms Recipient offers.
+
+4. Termination. This License and the rights granted hereunder will terminate
+automatically if Recipient fails to comply with terms herein and fails to
+cure such breach within 30 days of the breach. Any sublicense to the Subject
+Software which is properly granted shall survive any termination of this
+License absent termination by the terms of such sublicense. Provisions which,
+by their nature, must remain in effect beyond the termination of this License
+shall survive.
+
+5. No Trademark Rights. This License does not grant any rights to use any
+trade name, trademark or service mark whatsoever. No trade name, trademark or
+service mark of SGI may be used to endorse or promote products derived from
+the Subject Software without prior written permission of SGI.
+
+6. No Other Rights. This License does not grant any rights with respect to
+the OpenGL API or to any software or hardware implementation thereof or to
+any other software whatsoever, nor shall any other rights or licenses not
+expressly granted hereunder arise by implication, estoppel or otherwise with
+respect to the Subject Software. Title to and ownership of the Original Soft-
+ware at all times remains with SGI. All rights in the Original Software not
+expressly granted under this License are reserved.
+
+7. Compliance with Laws; Non-Infringement. Recipient shall comply with all
+applicable laws and regulations in connection with use and distribution of
+the Subject Software, including but not limited to, all export and import
+control laws and regulations of the U.S. government and other countries.
+Recipient may not distribute Subject Software that (i) in any way infringes
+(directly or contributorily) the rights (including patent, copyright, trade
+secret, trademark or other intellectual property rights of any kind) of any
+other person or entity or (ii) breaches any representation or warranty,
+express, implied or statutory, which under any applicable law it might be
+deemed to have been distributed.
+
+8. Claims of Infringement. If Recipient at any time has knowledge of any one
+or more third party claims that reproduction, modification, use, distribu-
+tion, import or sale of Subject Software (including particular functionality
+or code incorporated in Subject Software) infringes the third party's intel-
+lectual property rights, Recipient must place in a well-identified web page
+bearing the title "LEGAL" a description of each such claim and a description
+of the party making each such claim in sufficient detail that a user of the
+Subject Software will know whom to contact regarding the claim. Also, upon
+gaining such knowledge of any such claim, Recipient must conspicuously
+include the URL for such web page in the Exhibit A notice required under Sec-
+tions 2 and 3, above, and in the text of any related documentation, license
+agreement or collateral in which Recipient describes end user's rights relat-
+ing to the Subject Software. If Recipient obtains such knowledge after it
+makes Subject Software available to any other person or entity, Recipient
+shall take other steps (such as notifying appropriate mailing lists or news-
+groups) reasonably calculated to inform those who received the Subject Soft-
+ware that new knowledge has been obtained.
+
+9. DISCLAIMER OF WARRANTY. SUBJECT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
+WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT
+LIMITATION, WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, MER-
+CHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON- INFRINGING. SGI ASSUMES NO
+RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE. SHOULD ANY SOFTWARE
+PROVE DEFECTIVE IN ANY RESPECT, SGI ASSUMES NO COST OR LIABILITY FOR ANY SER-
+VICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN
+ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS AUTHORIZED
+HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+10. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THE-
+ORY, WHETHER TORT (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIA-
+BILITY), CONTRACT, OR OTHERWISE, SHALL SGI OR ANY SGI LICENSOR BE LIABLE FOR
+ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK
+STOPPAGE, LOSS OF DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF
+THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY
+TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SGI's NEGLIGENCE TO
+THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO
+NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES,
+SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO RECIPIENT.
+
+11. Indemnity. Recipient shall be solely responsible for damages arising,
+directly or indirectly, out of its utilization of rights under this License.
+Recipient will defend, indemnify and hold harmless Silicon Graphics, Inc.
+from and against any loss, liability, damages, costs or expenses (including
+the payment of reasonable attorneys fees) arising out of Recipient's use,
+modification, reproduction and distribution of the Subject Software or out of
+any representation or warranty made by Recipient.
+
+12. U.S. Government End Users. The Subject Software is a "commercial item"
+consisting of "commercial computer software" as such terms are defined in
+title 48 of the Code of Federal Regulations and all U.S. Government End
+Users acquire only the rights set forth in this License and are subject to
+the terms of this License.
+
+13. Miscellaneous. This License represents the complete agreement concerning
+subject matter hereof. If any provision of this License is held to be unen-
+forceable, such provision shall be reformed so as to achieve as nearly as
+possible the same economic effect as the original provision and the remainder
+of this License will remain in effect. This License shall be governed by and
+construed in accordance with the laws of the United States and the State of
+California as applied to agreements entered into and to be performed entirely
+within California between California residents. Any litigation relating to
+this License shall be subject to the exclusive jurisdiction of the Federal
+Courts of the Northern District of California (or, absent subject matter
+jurisdiction in such courts, the courts of the State of California), with
+venue lying exclusively in Santa Clara County, California, with the losing
+party responsible for costs, including without limitation, court costs and
+reasonable attorneys fees and expenses. The application of the United Nations
+Convention on Contracts for the International Sale of Goods is expressly
+excluded. Any law or regulation which provides that the language of a con-
+tract shall be construed against the drafter shall not apply to this License.
+
+Exhibit A
+
+The contents of this file are subject to Sections 2, 3, 4, 7, 8, 10, 12 and
+13 of the GLX Public License Version 1.0 (the "License"). You may not use
+this file except in compliance with those sections of the License. You may
+obtain a copy of the License at Silicon Graphics, Inc., attn: Legal Services,
+2011 N. Shoreline Blvd., Mountain View, CA 94043 or at
+http://www.sgi.com/software/opensource/glx/license.html.
+
+Software distributed under the License is distributed on an "AS IS" basis.
+ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED
+WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR PURPOSE OR OF NON-
+INFRINGEMENT. See the License for the specific language governing rights and
+limitations under the License.
+
+The Original Software is GLX version 1.2 source code, released February,
+1999. The developer of the Original Software is Silicon Graphics, Inc. Those
+portions of the Subject Software created by Silicon Graphics, Inc. are Copy-
+right (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved.
+
+2.5 CID Font Code Public License
+
+CID FONT CODE PUBLIC LICENSE (Version 1.0 (3/31/99))("License")
+
+Subject to any applicable third party claims, Silicon Graphics, Inc. ("SGI")
+hereby grants permission to Recipient (defined below), under SGI's copyrights
+in the Original Software (defined below), to use, copy, modify, merge, pub-
+lish, distribute, sublicense and/or sell copies of Subject Software (defined
+below) in both source code and executable form, and to permit persons to whom
+the Subject Software is furnished in accordance with this License to do the
+same, subject to all of the following terms and conditions, which Recipient
+accepts by engaging in any such use, copying, modifying, merging, publica-
+tion, distributing, sublicensing or selling:
+
+1. Definitions.
+
+ a. "Original Software" means source code of computer software code
+ that is described in Exhibit A as Original Software.
+
+ b. "Modifications" means any addition to or deletion from the sub-
+ stance or structure of either the Original Software or any previous
+ Modifications. When Subject Software is released as a series of
+ files, a Modification means (i) any addition to or deletion from
+ the contents of a file containing Original Software or previous
+ Modifications and (ii) any new file that contains any part of the
+ Original Code or previous Modifications.
+
+ c. "Subject Software" means the Original Software or Modifications
+ or the combination of the Original Software and Modifications, or
+ portions of any of the foregoing.
+
+ d. "Recipient" means an individual or a legal entity exercising
+ rights under the terms of this License. For legal entities, "Recip-
+ ient" includes any entity that controls, is controlled by, or is
+ under common control with Recipient. For purposes of this defini-
+ tion, "control" of an entity means (i) the power, direct or indi-
+ rect, to direct or manage such entity, or (ii) ownership of fifty
+ percent (50%) or more of the outstanding shares or beneficial own-
+ ership of such entity.
+
+ e. "Required Notice" means the notice set forth in Exhibit A to
+ this License.
+
+ f. "Accompanying Technology" means any software or other technology
+ that is not a Modification and that is distributed or made publicly
+ available by Recipient with the Subject Software. Separate soft-
+ ware files that do not contain any Original Software or any previ-
+ ous Modification shall not be deemed a Modification, even if such
+ software files are aggregated as part of a product, or in any
+ medium of storage, with any file that does contain Original Soft-
+ ware or any previous Modification.
+
+2. License Terms. All distribution of the Subject Software must be made sub-
+ject to the terms of this License. A copy of this License and the Required
+Notice must be included in any documentation for Subject Software where
+Recipient's rights relating to Subject Software and/or any Accompanying Tech-
+nology are described. Distributions of Subject Software in source code form
+must also include the Required Notice in every file distributed. In addition,
+a ReadMe file entitled "Important Legal Notice" must be distributed with each
+distribution of one or more files that incorporate Subject Software. That
+file must be included with distributions made in both source code and exe-
+cutable form. A copy of the License and the Required Notice must be included
+in that file. Recipient may distribute Accompanying Technology under a
+license of Recipient's choice, which may contain terms different from this
+License, provided that (i) Recipient is in compliance with the terms of this
+License, (ii) such other license terms do not modify or supersede the terms
+of this License as applicable to the Subject Software, (iii) Recipient hereby
+indemnifies SGI for any liability incurred by SGI as a result of the distri-
+bution of Accompanying Technology or the use of other license terms.
+
+3. Termination. This License and the rights granted hereunder will terminate
+automatically if Recipient fails to comply with terms herein and fails to
+cure such breach within 30 days of the breach. Any sublicense to the Subject
+Software that is properly granted shall survive any termination of this
+License absent termination by the terms of such sublicense. Provisions which,
+by their nature, must remain in effect beyond the termination of this License
+shall survive.
+
+4. Trademark Rights. This License does not grant any rights to use any trade
+name, trademark or service mark whatsoever. No trade name, trademark or ser-
+vice mark of SGI may be used to endorse or promote products derived from or
+incorporating any Subject Software without prior written permission of SGI.
+
+5. No Other Rights. No rights or licenses not expressly granted hereunder
+shall arise by implication, estoppel or otherwise. Title to and ownership of
+the Original Software at all times remains with SGI. All rights in the Origi-
+nal Software not expressly granted under this License are reserved.
+
+6. Compliance with Laws; Non-Infringement. Recipient shall comply with all
+applicable laws and regulations in connection with use and distribution of
+the Subject Software, including but not limited to, all export and import
+control laws and regulations of the U.S. government and other countries.
+Recipient may not distribute Subject Software that (i) in any way infringes
+(directly or contributorily) the rights (including patent, copyright, trade
+secret, trademark or other intellectual property rights of any kind) of any
+other person or entity, or (ii) breaches any representation or warranty,
+express, implied or statutory, which under any applicable law it might be
+deemed to have been distributed.
+
+7. Claims of Infringement. If Recipient at any time has knowledge of any one
+or more third party claims that reproduction, modification, use, distribu-
+tion, import or sale of Subject Software (including particular functionality
+or code incorporated in Subject Software) infringes the third party's intel-
+lectual property rights, Recipient must place in a well-identified web page
+bearing the title "LEGAL" a description of each such claim and a description
+of the party making each such claim in sufficient detail that a user of the
+Subject Software will know whom to contact regarding the claim. Also, upon
+gaining such knowledge of any such claim, Recipient must conspicuously
+include the URL for such web page in the Required Notice, and in the text of
+any related documentation, license agreement or collateral in which Recipient
+describes end user's rights relating to the Subject Software. If Recipient
+obtains such knowledge after it makes Subject Software available to any other
+person or entity, Recipient shall take other steps (such as notifying appro-
+priate mailing lists or newsgroups) reasonably calculated to provide such
+knowledge to those who received the Subject Software.
+
+8. DISCLAIMER OF WARRANTY. SUBJECT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
+WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT
+LIMITATION, WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, MER-
+CHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. SGI ASSUMES NO
+RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE. SHOULD ANY SOFTWARE
+PROVE DEFECTIVE IN ANY RESPECT, SGI ASSUMES NO COST OR LIABILITY FOR ANY SER-
+VICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN
+ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS AUTHORIZED
+HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+9. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY,
+WHETHER TORT (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIABILITY),
+CONTRACT, OR OTHERWISE, SHALL SGI OR ANY SGI LICENSOR BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SUBJECT SOFTWARE OR
+THE USE OR OTHER DEALINGS IN THE SUBJECT SOFTWARE. SOME JURISDICTIONS DO NOT
+ALLOW THE EXCLUSION OR LIMITATION OF CERTAIN DAMAGES, SO THIS EXCLUSION AND
+LIMITATION MAY NOT APPLY TO RECIPIENT TO THE EXTENT SO DISALLOWED.
+
+10. Indemnity. Recipient shall be solely responsible for damages arising,
+directly or indirectly, out of its utilization of rights under this License.
+Recipient will defend, indemnify and hold SGI and its successors and assigns
+harmless from and against any loss, liability, damages, costs or expenses
+(including the payment of reasonable attorneys fees) arising out of (Recipi-
+ent's use, modification, reproduction and distribution of the Subject Soft-
+ware or out of any representation or warranty made by Recipient.
+
+11. U.S. Government End Users. The Subject Software is a "commercial item"
+consisting of "commercial computer software" as such terms are defined in
+title 48 of the Code of Federal Regulations and all U.S. Government End Users
+acquire only the rights set forth in this License and are subject to the
+terms of this License.
+
+12. Miscellaneous. This License represents the complete agreement concerning
+subject matter hereof. If any provision of this License is held to be unen-
+forceable by any judicial or administrative authority having proper jurisdic-
+tion with respect thereto, such provision shall be reformed so as to achieve
+as nearly as possible the same economic effect as the original provision and
+the remainder of this License will remain in effect. This License shall be
+governed by and construed in accordance with the laws of the United States
+and the State of California as applied to agreements entered into and to be
+performed entirely within California between California residents. Any liti-
+gation relating to this License shall be subject to the exclusive jurisdic-
+tion of the Federal Courts of the Northern District of California (or, absent
+subject matter jurisdiction in such courts, the courts of the State of Cali-
+fornia), with venue lying exclusively in Santa Clara County, California, with
+the losing party responsible for costs, including without limitation, court
+costs and reasonable attorneys fees and expenses. The application of the
+United Nations Convention on Contracts for the International Sale of Goods is
+expressly excluded. Any law or regulation that provides that the language of
+a contract shall be construed against the drafter shall not apply to this
+License.
+
+Exhibit A
+
+Copyright (c) 1994-1999 Silicon Graphics, Inc.
+
+The contents of this file are subject to the CID Font Code Public License
+Version 1.0 (the "License"). You may not use this file except in compliance
+with the License. You may obtain a copy of the License at Silicon Graphics,
+Inc., attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043
+or at http://www.sgi.com/software/opensource/cid/license.html
+
+Software distributed under the License is distributed on an "AS IS" basis.
+ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED
+WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR PURPOSE OR OF NON-
+INFRINGEMENT. See the License for the specific language governing rights and
+limitations under the License.
+
+The Original Software (as defined in the License) is CID font code that was
+developed by Silicon Graphics, Inc. Those portions of the Subject Software
+(as defined in the License) that were created by Silicon Graphics, Inc. are
+Copyright (c) 1994-1999 Silicon Graphics, Inc. All Rights Reserved.
+
+[NOTE: When using this text in connection with Subject Software delivered
+solely in object code form, Recipient may replace the words "this file" with
+"this software" in both the first and second sentences.]
+
+********************************************************************************
+
+XFree86's LICENSE document does not appear to be completely comprehensive.
+
+Many files appear to be licensed under the "SGI FREE SOFTWARE
+LICENSE B (Version 1.1 [02/22/2000])":
+
+SGI FREE SOFTWARE LICENSE B (Version 1.1 [02/22/2000])
+
+1. Definitions.
+
+ 1.1. "Additional Notice Provisions" means such additional provisions as
+ appear in the Notice in Original Code under the heading "Additional
+ Notice Provisions."
+
+ 1.2. "Covered Code" means the Original Code or Modifications, or any
+ combination thereof.
+
+ 1.3. "Hardware" means any physical device that accepts input, processes
+ input, stores the results of processing, and/or provides output.
+
+ 1.4. "Larger Work" means a work that combines Covered Code or portions
+ thereof with code not governed by the terms of this License.
+
+ 1.5. "Licensable" means having the right to grant, to the maximum
+ extent possible, whether at the time of the initial grant or
+ subsequently acquired, any and all of the rights conveyed herein.
+
+ 1.6. "License" means this document.
+
+ 1.7. "Licensed Patents" means patent claims Licensable by SGI that are
+ infringed by the use or sale of Original Code or any Modifications
+ provided by SGI, or any combination thereof.
+
+ 1.8. "Modifications" means any addition to or deletion from the
+ substance or structure of the Original Code or any previous
+ Modifications. When Covered Code is released as a series of files, a
+ Modification is:
+
+ A. Any addition to the contents of a file containing Original Code
+ and/or addition to or deletion from the contents of a file
+ containing previous Modifications.
+
+ B. Any new file that contains any part of the Original Code or
+ previous Modifications.
+
+ 1.9. "Notice" means any notice in Original Code or Covered Code, as
+ required by and in compliance with this License.
+
+ 1.10. "Original Code" means source code of computer software code that
+ is described in the source code Notice required by Exhibit A as
+ Original Code, and updates and error corrections specifically thereto.
+
+ 1.11. "Recipient" means an individual or a legal entity exercising
+ rights under, and complying with all of the terms of, this License or a
+ future version of this License issued under Section 8. For legal
+ entities, "Recipient" includes any entity that controls, is controlled
+ by, or is under common control with Recipient. For purposes of this
+ definition, "control" of an entity means (a) the power, direct or
+ indirect, to direct or manage such entity, or (b) ownership of fifty
+ percent (50%) or more of the outstanding shares or beneficial ownership
+ of such entity.
+
+ 1.12. "Recipient Patents" means patent claims Licensable by a Recipient
+ that are infringed by the use or sale of Original Code or any
+ Modifications provided by SGI, or any combination thereof.
+
+ 1.13. "SGI" means Silicon Graphics, Inc.
+
+ 1.14. "SGI Patents" means patent claims Licensable by SGI other than
+ the Licensed Patents.
+
+2. License Grant and Restrictions.
+
+ 2.1. SGI License Grant. Subject to the terms of this License and any
+ third party intellectual property claims, for the duration of
+ intellectual property protections inherent in the Original Code, SGI
+ hereby grants Recipient a worldwide, royalty-free, non-exclusive
+ license, to do the following: (i) under copyrights Licensable by SGI,
+ to reproduce, distribute, create derivative works from, and, to the
+ extent applicable, display and perform the Original Code and/or any
+ Modifications provided by SGI alone and/or as part of a Larger Work;
+ and (ii) under any Licensable Patents, to make, have made, use, sell,
+ offer for sale, import and/or otherwise transfer the Original Code
+ and/or any Modifications provided by SGI. Recipient accepts the terms
+ and conditions of this License by undertaking any of the aforementioned
+ actions. The patent license shall apply to the Covered Code if, at the
+ time any related Modification is added, such addition of the
+ Modification causes such combination to be covered by the Licensed
+ Patents. The patent license in Section 2.1(ii) shall not apply to any
+ other combinations that include the Modification. No patent license is
+ provided under SGI Patents for infringements of SGI Patents by
+ Modifications not provided by SGI or combinations of Original Code and
+ Modifications not provided by SGI.
+
+ 2.2. Recipient License Grant. Subject to the terms of this License and
+ any third party intellectual property claims, Recipient hereby grants
+ SGI and any other Recipients a worldwide, royalty-free, non-exclusive
+ license, under any Recipient Patents, to make, have made, use, sell,
+ offer for sale, import and/or otherwise transfer the Original Code
+ and/or any Modifications provided by SGI.
+
+ 2.3. No License For Hardware Implementations. The licenses granted in
+ Section 2.1 and 2.2 are not applicable to implementation in Hardware of
+ the algorithms embodied in the Original Code or any Modifications
+ provided by SGI .
+
+3. Redistributions.
+
+ 3.1. Retention of Notice/Copy of License. The Notice set forth in
+ Exhibit A, below, must be conspicuously retained or included in any and
+ all redistributions of Covered Code. For distributions of the Covered
+ Code in source code form, the Notice must appear in every file that can
+ include a text comments field; in executable form, the Notice and a
+ copy of this License must appear in related documentation or collateral
+ where the Recipient's rights relating to Covered Code are described.
+ Any Additional Notice Provisions which actually appears in the Original
+ Code must also be retained or included in any and all redistributions
+ of Covered Code.
+
+ 3.2. Alternative License. Provided that Recipient is in compliance with
+ the terms of this License, Recipient may, so long as without derogation
+ of any of SGI's rights in and to the Original Code, distribute the
+ source code and/or executable version(s) of Covered Code under (1) this
+ License; (2) a license identical to this License but for only such
+ changes as are necessary in order to clarify Recipient's role as
+ licensor of Modifications; and/or (3) a license of Recipient's
+ choosing, containing terms different from this License, provided that
+ the license terms include this Section 3 and Sections 4, 6, 7, 10, 12,
+ and 13, which terms may not be modified or superseded by any other
+ terms of such license. If Recipient elects to use any license other
+ than this License, Recipient must make it absolutely clear that any of
+ its terms which differ from this License are offered by Recipient
+ alone, and not by SGI. It is emphasized that this License is a limited
+ license, and, regardless of the license form employed by Recipient in
+ accordance with this Section 3.2, Recipient may relicense only such
+ rights, in Original Code and Modifications by SGI, as it has actually
+ been granted by SGI in this License.
+
+ 3.3. Indemnity. Recipient hereby agrees to indemnify SGI for any
+ liability incurred by SGI as a result of any such alternative license
+ terms Recipient offers.
+
+4. Termination. This License and the rights granted hereunder will
+terminate automatically if Recipient breaches any term herein and fails to
+cure such breach within 30 days thereof. Any sublicense to the Covered Code
+that is properly granted shall survive any termination of this License,
+absent termination by the terms of such sublicense. Provisions that, by
+their nature, must remain in effect beyond the termination of this License,
+shall survive.
+
+5. No Trademark Or Other Rights. This License does not grant any rights to:
+(i) any software apart from the Covered Code, nor shall any other rights or
+licenses not expressly granted hereunder arise by implication, estoppel or
+otherwise with respect to the Covered Code; (ii) any trade name, trademark
+or service mark whatsoever, including without limitation any related right
+for purposes of endorsement or promotion of products derived from the
+Covered Code, without prior written permission of SGI; or (iii) any title
+to or ownership of the Original Code, which shall at all times remains with
+SGI. All rights in the Original Code not expressly granted under this
+License are reserved.
+
+6. Compliance with Laws; Non-Infringement. There are various worldwide
+laws, regulations, and executive orders applicable to dispositions of
+Covered Code, including without limitation export, re-export, and import
+control laws, regulations, and executive orders, of the U.S. government and
+other countries, and Recipient is reminded it is obliged to obey such laws,
+regulations, and executive orders. Recipient may not distribute Covered
+Code that (i) in any way infringes (directly or contributorily) any
+intellectual property rights of any kind of any other person or entity or
+(ii) breaches any representation or warranty, express, implied or
+statutory, to which, under any applicable law, it might be deemed to have
+been subject.
+
+7. Claims of Infringement. If Recipient learns of any third party claim
+that any disposition of Covered Code and/or functionality wholly or
+partially infringes the third party's intellectual property rights,
+Recipient will promptly notify SGI of such claim.
+
+8. Versions of the License. SGI may publish revised and/or new versions of
+the License from time to time, each with a distinguishing version number.
+Once Covered Code has been published under a particular version of the
+License, Recipient may, for the duration of the license, continue to use it
+under the terms of that version, or choose to use such Covered Code under
+the terms of any subsequent version published by SGI. Subject to the
+provisions of Sections 3 and 4 of this License, only SGI may modify the
+terms applicable to Covered Code created under this License.
+
+9. DISCLAIMER OF WARRANTY. COVERED CODE IS PROVIDED "AS IS." ALL EXPRESS
+AND IMPLIED WARRANTIES AND CONDITIONS ARE DISCLAIMED, INCLUDING, WITHOUT
+LIMITATION, ANY IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY,
+SATISFACTORY QUALITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT. SGI ASSUMES NO RISK AS TO THE QUALITY AND PERFORMANCE OF
+THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, SGI
+ASSUMES NO COST OR LIABILITY FOR SERVICING, REPAIR OR CORRECTION. THIS
+DISCLAIMER OF WARRANTY IS AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY
+COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT SUBJECT TO THIS
+DISCLAIMER.
+
+10. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES NOR LEGAL THEORY,
+WHETHER TORT (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE OR STRICT
+LIABILITY), CONTRACT, OR OTHERWISE, SHALL SGI OR ANY SGI LICENSOR BE LIABLE
+FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF
+ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+WORK STOPPAGE, LOSS OF DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND
+ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY
+SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM
+SGI's NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION.
+SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL
+OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO
+RECIPIENT.
+
+11. Indemnity. Recipient shall be solely responsible for damages arising,
+directly or indirectly, out of its utilization of rights under this
+License. Recipient will defend, indemnify and hold harmless Silicon
+Graphics, Inc. from and against any loss, liability, damages, costs or
+expenses (including the payment of reasonable attorneys fees) arising out
+of Recipient's use, modification, reproduction and distribution of the
+Covered Code or out of any representation or warranty made by
+Recipient.
+
+12. U.S. Government End Users. The Covered Code is a "commercial item"
+consisting of "commercial computer software" as such terms are defined in
+title 48 of the Code of Federal Regulations and all U.S. Government End
+Users acquire only the rights set forth in this License and are subject to
+the terms of this License.
+
+13. Miscellaneous. This License represents the complete agreement
+concerning the its subject matter. If any provision of this License is held
+to be unenforceable, such provision shall be reformed so as to achieve as
+nearly as possible the same legal and economic effect as the original
+provision and the remainder of this License will remain in effect. This
+License shall be governed by and construed in accordance with the laws of
+the United States and the State of California as applied to agreements
+entered into and to be performed entirely within California between
+California residents. Any litigation relating to this License shall be
+subject to the exclusive jurisdiction of the Federal Courts of the Northern
+District of California (or, absent subject matter jurisdiction in such
+courts, the courts of the State of California), with venue lying
+exclusively in Santa Clara County, California, with the losing party
+responsible for costs, including without limitation, court costs and
+reasonable attorneys fees and expenses. The application of the United
+Nations Convention on Contracts for the International Sale of Goods is
+expressly excluded. Any law or regulation that provides that the language
+of a contract shall be construed against the drafter shall not apply to
+this License.
+
+Exhibit A
+
+License Applicability. Except to the extent portions of this file are made
+subject to an alternative license as permitted in the SGI Free Software
+License B, Version 1.1 (the "License"), the contents of this file are
+subject only to the provisions of the License. You may not use this file
+except in compliance with the License. You may obtain a copy of the License
+at Silicon Graphics, Inc., attn: Legal Services, 1600 Amphitheatre Parkway,
+Mountain View, CA 94043-1351, or at: http://oss.sgi.com/projects/FreeB
+
+Note that, as provided in the License, the Software is distributed on an
+"AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+
+Original Code. The Original Code is: [name of software, version number, and
+release date], developed by Silicon Graphics, Inc. The Original Code is
+Copyright (c) [dates of first publication, as appearing in the Notice in
+the Original Code] Silicon Graphics, Inc. Copyright in any portions created
+by third parties is as indicated elsewhere herein. All Rights Reserved.
+Additional Notice Provisions: [such additional provisions, if any, as
+appear in the Notice in the Original Code under the heading "Additional
+Notice Provisions"]
+
+
+-------------------------------
+-------------------------------
+
+
+*) GDAL (<http://gdal.org/>). Not currently included in any Xastir
+binaries. This is a placeholder that we may use later.
+
+
+-------------------------------
+-------------------------------
+
+
+*) GV (<http://wwwthep.physik.uni-mainz.de/~plass/gv/>). Not
+currently included in any Xastir binaries. This is a placeholder
+that we may use later.
+
+
+-------------------------------
+-------------------------------
+
+
+To maintain compliance with the above licenses: Hear ye, hear ye!
+Be it known that the sources for each of the optional libraries
+listed may be obtained from their normal download sites on the
+internet.
+
+
+
+The file you're looking at (LICENSE) is
+Copyright (C) 2000-2012 The Xastir Group
+
diff --git a/LaCrosse/.cvsignore b/LaCrosse/.cvsignore
new file mode 100644
index 0000000..cfb964c
--- /dev/null
+++ b/LaCrosse/.cvsignore
@@ -0,0 +1,16 @@
+configure
+Makefile.in
+Makefile
+make.log
+stamp-h.in
+config.h
+config.log
+aclocal.m4
+autom4te.cache
+config.h.in
+config.status
+stamp-h1
+mkinstalldirs
+depcomp
+install-sh
+missing
diff --git a/LaCrosse/AUTHORS b/LaCrosse/AUTHORS
new file mode 100644
index 0000000..ea32601
--- /dev/null
+++ b/LaCrosse/AUTHORS
@@ -0,0 +1,26 @@
+
+$Id: AUTHORS,v 1.2 2010/01/31 02:12:23 we7u Exp $
+
+
+ Developers and Contributions
+ _________________________________________________________________
+
+ First, thanks go out to the great folks at the xastir team - a
+ wonderful APRS application set and helpful folks!
+
+ Thanks also to Andreas Muller, author of meteo and a great
+ resource for information and help.
+
+ Elements of this software are taken from wx200d ver 1.2
+ by Tim Witham, and it is modeled after that application.
+
+ Finally, thanks to the MySQL folks for the key element - the
+ database.
+
+ N0VH Jim Chandler jim at n0vh.org
+ KB8ROP Bruce Bennett bruts at adelphia.net
+ _________________________________________________________________
+
+ Copyright (C) 2003-2004 Bruce Bennett KB8ROP
+ Copyright (C) 2005 Jim Chandler N0VH
+
diff --git a/LaCrosse/COPYING b/LaCrosse/COPYING
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/LaCrosse/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/LaCrosse/CVS/Entries b/LaCrosse/CVS/Entries
new file mode 100644
index 0000000..5ede153
--- /dev/null
+++ b/LaCrosse/CVS/Entries
@@ -0,0 +1,12 @@
+/.cvsignore/1.2/Thu Jan 26 19:06:14 2006//
+/AUTHORS/1.2/Sun Jan 31 02:12:23 2010//
+/COPYING/1.1/Wed Jan 25 19:36:27 2006//
+/ChangeLog/1.1/Wed Jan 25 19:36:27 2006//
+/INSTALL/1.1/Wed Jan 25 19:36:27 2006//
+/Makefile.am/1.8/Thu Nov 1 18:57:18 2012//
+/NEWS/1.1/Wed Jan 25 19:36:27 2006//
+/README/1.8/Thu Nov 1 18:57:18 2012//
+/bootstrap.sh/1.9/Thu Nov 1 18:57:18 2012//
+/configure.ac/1.7/Thu Nov 1 18:57:18 2012//
+/weatherdump.sql/1.2/Wed Jul 25 00:17:35 2012//
+D
diff --git a/LaCrosse/CVS/Entries.Log b/LaCrosse/CVS/Entries.Log
new file mode 100644
index 0000000..40b1f89
--- /dev/null
+++ b/LaCrosse/CVS/Entries.Log
@@ -0,0 +1,2 @@
+A D/autom4te.cache////
+A D/src////
diff --git a/LaCrosse/CVS/Repository b/LaCrosse/CVS/Repository
new file mode 100644
index 0000000..cce1e32
--- /dev/null
+++ b/LaCrosse/CVS/Repository
@@ -0,0 +1 @@
+xastir/LaCrosse
diff --git a/LaCrosse/CVS/Root b/LaCrosse/CVS/Root
new file mode 100644
index 0000000..6a998ee
--- /dev/null
+++ b/LaCrosse/CVS/Root
@@ -0,0 +1 @@
+:ext:we7u at xastir.cvs.sourceforge.net:/cvsroot/xastir
diff --git a/LaCrosse/ChangeLog b/LaCrosse/ChangeLog
new file mode 100644
index 0000000..e3478e0
--- /dev/null
+++ b/LaCrosse/ChangeLog
@@ -0,0 +1,3 @@
+
+# $Id: ChangeLog,v 1.1 2006/01/25 19:36:27 n0vh Exp $
+
diff --git a/LaCrosse/INSTALL b/LaCrosse/INSTALL
new file mode 100644
index 0000000..0027478
--- /dev/null
+++ b/LaCrosse/INSTALL
@@ -0,0 +1,232 @@
+
+$Id: INSTALL,v 1.1 2006/01/25 19:36:27 n0vh Exp $
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
+Foundation, Inc.
+
+ This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory. After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/LaCrosse/Makefile.am b/LaCrosse/Makefile.am
new file mode 100644
index 0000000..bdccfa4
--- /dev/null
+++ b/LaCrosse/Makefile.am
@@ -0,0 +1,43 @@
+
+# $Id: Makefile.am,v 1.8 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2004-2012 The Xastir Group
+#
+
+AUTOMAKE_OPTIONS = gnu dist-bzip2
+ACLOCAL_AMFLAGS = -I m4
+
+D= `date +%G%m%d.%H%M%S`
+
+SUBDIRS = src
+
+
+#if DAVIS
+#MyWX = davis
+#else
+#MyWX =
+#endif
+#noinst_PROGRAMS = $(MyWX)
+
+
+# Remove this file here (it is created via configure), not from within intl.
+# DISTCLEANFILES =
+
+EXTRA_DIST = aclocal.m4 AUTHORS bootstrap.sh ChangeLog config.h.in \
+ config.status configure.ac COPYING INSTALL NEWS \
+ README bootstrap.sh
+
+MAINTAINERCLEANFILES = configure config.status aclocal.m4 \
+ Makefile.in Makefile config.guess config.sub install-sh \
+ missing mkinstalldirs
+
+#docdir=${pkgdatadir}/doc
+#doc_DATA=AUTHORS FAQ ChangeLog LICENSE README README.CVS \
+# README.MAPS README.win32 COPYING INSTALL UPGRADE
+
+#mandir=${prefix}/man
+#man_MANS=xastir.1
+
+ChangeLog::
+
+
diff --git a/LaCrosse/NEWS b/LaCrosse/NEWS
new file mode 100644
index 0000000..14262f5
--- /dev/null
+++ b/LaCrosse/NEWS
@@ -0,0 +1,3 @@
+
+$Id: NEWS,v 1.1 2006/01/25 19:36:27 n0vh Exp $
+
diff --git a/LaCrosse/README b/LaCrosse/README
new file mode 100644
index 0000000..295fb6f
--- /dev/null
+++ b/LaCrosse/README
@@ -0,0 +1,202 @@
+
+$Id: README,v 1.8 2012/11/01 18:57:18 we7u Exp $
+
+Copyright (C) 2006 Jim Chandler <jim at n0vh.org>
+Portions Copyright (C) 2004 Bruce Bennett <bruts at adelphia.net>
+Portions Copyright (C) 2004-2012 The Xastir Group
+(Modified for the Xastir project under GPL license)
+
+
+LaCrosse WS-23xx Weather Station support for Xastir - open2300db2APRS
+
+
+OVERVIEW
+--------
+
+This is a bridge utility between "open2300", a LaCrosse Weather Station
+data storage & display application by Kenneth Lavrsen (see
+http://www.lavrsen.dk/twiki/bin/view/Open2300/WebHome) and "Xastir",
+the APRS package for Linux (see http://www.xastir.org). It allows your
+LaCrosse WS-23xx weather data to be used by Xastir for local station data.
+
+You will need to obtain and install Xastir, mysql and open2300 as
+outlined in the following sections. After Xastir and open2300 are
+in working order, this utility can be run as a daemon to provide
+weather data to Xastir (or any other APRS-format application).
+
+"open2300db2APRS" watches for new weather data in the database, retrieves
+the new data, formats it in APRS "position less" ASCII format and
+makes it available on a TCP port of your choosing. Xastir is
+capable of reading this data (see note under Xastir installation).
+
+
+INSTALLATION
+------------
+
+Steps in order:
+
+1) Install mysql - initial tested version mysql-3.23.58
+ although version 4 is released and has some significant
+ improvements - and version 4 *should* work (to be tested yet).
+ If you use an RPM or DPK binary-image version, be sure to add
+ the mysql-devel headers. For the latest image-version, see
+ http://www.mysql.com and follow the links to the downloads.
+ I used mysql-3.23.58-pc-linux-i686.tar.gz from that site.
+
+2) Install open2300 - tested version open2300-1.10
+ See the instructions for installing & then setting
+ up open2300 that come with the tar ball. Obtain the latest open2300
+ at http://www.lavrsen.dk/twiki/bin/view/Open2300/WebHome - the setup
+ is rather involved but worth the efort. Some SQL/XML skills can help
+ here, but are not absolutely required...
+
+ The table setup for the mySQL portion of the open2300 database can be
+ found in the weatherdump.sql file. My database is setup for degree F,
+ inches of Mercury, inches of rain, and windspeed in knots.
+
+3) Install or update your installation for Xastir to the latest
+ version (http://www.sourceforge.net, project Xastir)
+
+4) Install open2300db2APRS
+ See instructions below.
+
+
+SETTINGS & STARTUP
+------------------
+
+1) mysql - it is recommended by mysql to set up passwords, but for
+ this usage it doesn't matter. In fact, it's a bit of a pain.
+ TODO - open2300db2APRS has the annoying fault of clearly displaying
+ the password used for the mysql database for anyone to see via
+ 'ps -ef'. Start mysqld before open2300db2APRS, meteo and Xastir in your
+ boot-time initializations.
+
+2) open2300 - my testing used a five minute data accumulation rate.
+ Thirty seconds would more closely match Xastir, but the
+ database growth rate would be twelve as fast (about 600
+ Mbytes/year at 30 sec rate). I run a cronjob every five minutes that
+ calls mysql2300 to populate the data. See the open2300 documentation.
+
+3) open2300db2APRS - see "open2300db2APRS RUN OPTIONS" below. Start this daemon
+ after mysqld and before Xastir. I start it with the command
+ "open2300db2APRS -r --password <db2passwd>
+
+4) xastir - start this last, if you are auto-opening the WX port.
+ Set the weather port as a network weather station on
+ "localhost", port number as chosen in "db2APRS RUN OPTIONS"
+ (default is 1313). Make sure your station is set to one of the
+ "w/weather data" and your Icon is set to a weather Icon.
+
+
+open2300db2APRS RUN OPTIONS
+-------------------
+
+The open2300db2APRS utility takes standard short & long command line
+options, which can be displayed by "open2300db2APRS -?". Here's the list:
+
+ -h --help
+
+ Show help info and exit.
+
+ -v --verbose
+
+ Useful with the -n switch, for trouble-shooting, not for
+ normal operation. Tells you more than you really wanted to
+ know, but I recommend that you use this switch while you
+ try to initially set up db2APRS.
+
+ -c --cport [port#]
+
+ Choose which TCP/IP port data comes out from. If not used,
+ port number 1313 is the default. HINT: "telnet localhost
+ [port#]" is a handy way to verify db2APRS operation.
+
+ -u --user [database user]
+
+ Username for mysql database connection. If unspecfied
+ defaults to "meteo" (which is per the meteo setup intended
+ to be a read-only account for meteo).
+
+ -p --password [db passwd]
+
+ Password for mysql connection. If unspecfied, no password
+ is supplied. NOTE: this password is unfortunately visible
+ to anyone on your system running 'ps -ef'. TO BE FIXED.
+
+ -b --database [database]
+
+ Database name for mysql connection. If not supplied the
+ default is "meteo".
+
+ -n --nodaemon
+
+ Run in the fore-ground as a program. Useful for debugging
+ or initial setup, when used with -v.
+
+ -r --repeat
+
+ Keep going till killed - if not specified, one pass is
+ performed and then db2APRS exits. The only case where this
+ switch is *not* used is during initial setup/debug.
+
+Typical example: "./open2300db2APRS -r -u open2300 -p mysql2300" for normal use
+or "./open2300db2APRS -r -n -v -u test -p password" for debugging.
+
+
+OPERATIONAL DETAILS
+-------------------
+
+open2300db2APRS connects to the specified mysql database, extracts the
+latest timestamp and compares it to the last timestamp it read.
+If newer, the outdoor weather data (extception: air pressure is
+taken as indoor=outdoor) bearing this timestamp is extracted
+and formatted in the APRS "position less" string format with a
+Davis and X-APRS tag on the end. Any connecting client is given
+this string at 25 second intervals, after new database entries
+are checked for.
+
+This daemon could run on any networked Linux machine instead of
+the machine hosting Xastir, if desired (it's a good way around
+lack of processing power, disk space or serial ports!).
+
+Note that the open2300db2APRS daemon keeps providing data to Xastir even
+when no new entries in the database have been made. This could
+lead to errors in the timestamp on the data that Xastir is
+transmitting.
+
+
+BUILD open2300db2APRS
+-------------
+
+It's the usual:
+
+$ cd xastir/LaCrosse
+$ ./bootstrap.sh
+$ ./configure
+$ make
+$ su -c 'make install'
+
+
+ACKNOWLEGEMENTS & AUTHORS
+-------------------------
+
+A large portion of this work taken from db2APRS (thanks Bruce!!)
+
+db2APRS is the product of Bruce Bennett, callsign KB8ROP
+<bruts at adelphia.net> It is freely available at no charge
+under the GNU GENERAL PUBLIC LICENSE (see "COPYING" document)
+NO WARRANTY, expressed or implied, use at your own risk.
+
+Please feel free to contact me with test results & comments
+at the above EMAIL address
+
+Code portions and style taken from wx200d by Tim Witham
+<twitham at quiknet.com>, et. al.
+
+mysql is the product of MySQL - see http://www.mysql.com for
+team details.
+
+and finally, Xastir is the brain child of Frank Giannandrea et.
+al. (see http://www.xastir.org for current EMAIL addresses)
+
+
diff --git a/LaCrosse/autom4te.cache/CVS/Entries b/LaCrosse/autom4te.cache/CVS/Entries
new file mode 100644
index 0000000..1784810
--- /dev/null
+++ b/LaCrosse/autom4te.cache/CVS/Entries
@@ -0,0 +1 @@
+D
diff --git a/LaCrosse/autom4te.cache/CVS/Repository b/LaCrosse/autom4te.cache/CVS/Repository
new file mode 100644
index 0000000..8168667
--- /dev/null
+++ b/LaCrosse/autom4te.cache/CVS/Repository
@@ -0,0 +1 @@
+xastir/LaCrosse/autom4te.cache
diff --git a/LaCrosse/autom4te.cache/CVS/Root b/LaCrosse/autom4te.cache/CVS/Root
new file mode 100644
index 0000000..6a998ee
--- /dev/null
+++ b/LaCrosse/autom4te.cache/CVS/Root
@@ -0,0 +1 @@
+:ext:we7u at xastir.cvs.sourceforge.net:/cvsroot/xastir
diff --git a/LaCrosse/bootstrap.sh b/LaCrosse/bootstrap.sh
new file mode 100755
index 0000000..43677b6
--- /dev/null
+++ b/LaCrosse/bootstrap.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# $Id: bootstrap.sh,v 1.9 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+#
+
+../bootstrap.sh
+
diff --git a/LaCrosse/configure.ac b/LaCrosse/configure.ac
new file mode 100755
index 0000000..a7ae58e
--- /dev/null
+++ b/LaCrosse/configure.ac
@@ -0,0 +1,68 @@
+#
+# $Id: configure.ac,v 1.7 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2004 Bruce Bennett <bruts at adelphia.net>
+# Portions Copyright (C) 2004-2012 The Xastir Group
+# (Modified for the Xastir project under GPL license)
+#
+#
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.53)
+AC_INIT(open2300db2APRS, 0.1.0, jim at n0vh.org)
+AM_INIT_AUTOMAKE(open2300db2APRS, 0.1.0)
+AC_CONFIG_SRCDIR([src/open2300db2APRS.c])
+AM_CONFIG_HEADER([config.h])
+
+# Checks for programs.
+AC_PROG_INSTALL
+AC_PROG_CC
+
+# Checks for libraries.
+# Use MySQL's script for library config, if available
+MYSQL_CONFIG=mysql_config
+AC_MSG_CHECKING(for a fully installed MySQL)
+if ${MYSQL_CONFIG} --libs > /dev/null 2>&1
+then
+ MYSQL_VERSION=`${MYSQL_CONFIG} --version`
+ MYSQL_LIBS=`${MYSQL_CONFIG} --libs`
+ LIBS=`${MYSQL_CONFIG} --libs`
+ MYSQL_CFLAGS=`${MYSQL_CONFIG} --cflags`
+ CFLAGS="$CFLAGS $MYSQL_CFLAGS"
+ AC_SUBST(MYSQL_LIBS)
+ AC_SUBST(MYSQL_CFLAGS)
+ AC_MSG_RESULT(...found ${MYSQL_VERSION})
+else
+ AC_MSG_RESULT(MySQL is not fully installed)
+ AC_MSG_CHECKING(if there at least are the needed MySQL client libs)
+ AC_CHECK_LIB(mysqlclient,mysql_close)
+ if test $ac_cv_lib_mysqlclient_mysql_close = no; then
+
+ AC_MSG_ERROR(*** No MySQL client library found - See README ***)
+ else
+ AC_MSG_RESULT(found a usable libmysqlclient)
+ fi
+fi
+# Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h syslog.h unistd.h])
+if ${MYSQL_CONFIG} --libs > /dev/null 2>&1
+then
+ AC_MSG_RESULT(mysql.h path defined in CFLAGS)
+else
+ AC_CHECK_HEADERS([mysql.h],MYSQL_INC="yes",AC_MSG_ERROR(*** MySQL include file mysql.h not found - See README ***))
+fi
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_HEADER_TIME
+
+# Checks for library functions.
+AC_FUNC_FORK
+AC_FUNC_SELECT_ARGTYPES
+AC_TYPE_SIGNAL
+AC_FUNC_STRTOD
+AC_CHECK_FUNCS([memset select socket strrchr strtol])
+AC_CONFIG_FILES([Makefile \
+ src/Makefile])
+AC_OUTPUT
diff --git a/LaCrosse/src/.cvsignore b/LaCrosse/src/.cvsignore
new file mode 100644
index 0000000..e8ea731
--- /dev/null
+++ b/LaCrosse/src/.cvsignore
@@ -0,0 +1,4 @@
+.deps
+Makefile
+Makefile.in
+open2300db2APRS
diff --git a/LaCrosse/src/CVS/Entries b/LaCrosse/src/CVS/Entries
new file mode 100644
index 0000000..309e53c
--- /dev/null
+++ b/LaCrosse/src/CVS/Entries
@@ -0,0 +1,5 @@
+/.cvsignore/1.1/Thu Jan 26 15:42:22 2006//
+/Makefile.am/1.7/Thu Nov 1 18:57:18 2012//
+/defs.h/1.6/Thu Nov 1 18:57:18 2012//
+/open2300db2APRS.c/1.11/Thu Nov 1 18:57:18 2012//
+D
diff --git a/LaCrosse/src/CVS/Repository b/LaCrosse/src/CVS/Repository
new file mode 100644
index 0000000..185c93b
--- /dev/null
+++ b/LaCrosse/src/CVS/Repository
@@ -0,0 +1 @@
+xastir/LaCrosse/src
diff --git a/LaCrosse/src/CVS/Root b/LaCrosse/src/CVS/Root
new file mode 100644
index 0000000..6a998ee
--- /dev/null
+++ b/LaCrosse/src/CVS/Root
@@ -0,0 +1 @@
+:ext:we7u at xastir.cvs.sourceforge.net:/cvsroot/xastir
diff --git a/LaCrosse/src/Makefile.am b/LaCrosse/src/Makefile.am
new file mode 100644
index 0000000..9380c94
--- /dev/null
+++ b/LaCrosse/src/Makefile.am
@@ -0,0 +1,15 @@
+#
+# $Id: Makefile.am,v 1.7 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2004-2012 The Xastir Group
+#
+
+bin_PROGRAMS = open2300db2APRS
+noinst_PROGRAMS =
+
+open2300db2APRS_SOURCES = \
+ open2300db2APRS.c defs.h
+
+
+open2300db2APRS_LINK=$(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+
diff --git a/LaCrosse/src/defs.h b/LaCrosse/src/defs.h
new file mode 100644
index 0000000..d27615a
--- /dev/null
+++ b/LaCrosse/src/defs.h
@@ -0,0 +1,15 @@
+//
+// $Id: defs.h,v 1.6 2012/11/01 18:57:18 we7u Exp $
+//
+// Copyright (C) 2005 Jim Chandler <jim at n0vh.org>
+// Portions Copyright (C) 2004-2012 The Xastir Group
+//
+//
+// Dummy info here for now...
+//
+
+
+#define VERSION "0.1.0"
+#define PORT 1313
+#define CONNECTIONS 20
+#define NOFILE 20
diff --git a/LaCrosse/src/open2300db2APRS.c b/LaCrosse/src/open2300db2APRS.c
new file mode 100644
index 0000000..e42de77
--- /dev/null
+++ b/LaCrosse/src/open2300db2APRS.c
@@ -0,0 +1,912 @@
+/******************************************************************
+ *
+ * $Id: open2300db2APRS.c,v 1.11 2012/11/01 18:57:18 we7u Exp $
+ *
+ * Copyright (C) 2005 Jim Chandler <jim at n0vh.org>
+ * Portions Copyright (C) 2004-2012 The Xastir Group
+ *
+ * Portions copied from Bruce Bennett's excellent Davis WX work
+ *
+ * (see the files README and COPYING for more details)
+ *
+ * This file implements all of the database to APRS daemon.
+ *
+ *
+
+ LaCrosse/Data Base Weather --> APRS Weather
+
+ Intended use:
+
+ Create & provide APRS style packet string
+ without position information from MySQL database
+ weather information stored there by open2300
+ (See http://open2300.sourceforge.net/ for source) to
+ xastir-1.2.1 (See http://www.xastir.org for source)
+
+ Note: Open2300 is a weather data accumulator
+ aimed at LaCrosse weather stations, which stores weather
+ data in a mysql database.
+
+ Output is to the ip hostname:port required in the
+ command line.
+
+ ACKNOWLEGEMENTS:
+
+ Elements of this software are taken from wx200d ver 1.2
+ by Tim Witham <twitham at quiknet.com>, and it is modeled
+ after that application and from db2APRS by
+ Bruce Bennett <bruts at adelphia.net>.
+
+*******************************************************************/
+#include <config.h>
+#include <defs.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <signal.h>
+#include <syslog.h>
+#include <errno.h>
+#include <getopt.h>
+#include <mysql.h>
+
+#define MAXARGS 20 /* maximum CGI args to parse */
+#define TMPLEN 128 /* max length of CGI */
+#define BUFLEN 32 /* max length of hostname:port */
+
+#define VALID_WINDDIR 0x01
+#define VALID_WINDSPD 0x02
+#define VALID_WINDGST 0x04
+#define VALID_TEMP 0x08
+#define VALID_RAIN1HR 0x10
+#define VALID_RAIN24H 0x20
+#define VALID_HUMIDITY 0x40
+#define VALID_AIRPRESS 0x80
+#define VALID_RAINTOT 0x100
+
+#define MTPS2MPH 2.2369
+#define DEGC2DEGF 1.8
+#define MM2IN100TH 3.937
+#define INHG2HPA10TH 338.638
+
+#define OUTDOOR_SENSOR 1
+
+ //---From the static table "mfield", which really should be dynamically read here---
+ // (but then I couldn't use a switch statement)
+
+#define TEMPERATURE 0
+#define TEMPERATURE_MIN 1
+#define TEMPERATURE_MAX 2
+#define HUMIDITY 10
+#define HUMIDITY_MIN 11
+#define HUMIDITY_MAX 12
+#define WETNESS 20
+#define WETNESS_MIN 21
+#define WETNESS_MAX 22
+#define AIR_PRESSURE 30
+#define AIR_PRESSURE_MIN 31
+#define AIR_PRESSURE_MAX 32
+#define SOLAR 40
+#define UV 41
+#define RAIN 50
+ // note: "51" is really rain total
+#define RAIN_PER_DAY 51
+#define RAIN_PER_HOUR 52
+#define WIND_SPEED 60
+#define WIND_DIRECTION 61
+#define WIND_GUST 62
+#define WIND_X 63
+#define WIND_Y 64
+#define MOISTURE 70
+#define WATERLEVEL 71
+#define WATERLEVEL_MIN 72
+#define WATERLEVEL_MAX 73
+#define BATTERY 110
+#define TRANSMITTER 111
+#define DURATION 120
+#define SAMPLES 121
+
+struct dbinfo {
+ char user[30];
+ char pswrd[15];
+ char name[30];
+} db;
+
+char *progname;
+char *query;
+int *current = 0;
+
+int opt;
+
+MYSQL mysql; // Yeah, globals...
+MYSQL_RES *result;
+MYSQL_ROW row;
+
+char last_timestamp[20];
+
+int debug_level;
+
+char wxAPRShost[BUFLEN];
+int wxAPRSport = PORT;
+int outdoor_instr = OUTDOOR_SENSOR;
+
+/******************************************************************
+1/4/2003
+ Usage brief
+
+*******************************************************************/
+void usage(int ret)
+{
+ if (query)
+ printf("Content-type: text/plain\nStatus: 200\n\n");
+ printf("usage: %s [options] \n",progname);
+ printf("VERSION: %s\n",VERSION);
+ printf(" -h --help show this help and exit\n");
+ printf(" -v --verbose debugging info --> stderr\n");
+ printf(" -c --cport [port#] IP port for data output\n");
+ printf(" -u --user [database user] username for mysql - default meteo\n");
+ printf(" -p --password [db passwd] password for mysql - default none\n");
+ printf(" -b --database [database] database name - default meteo\n");
+ printf(" -n --nodaemon do not run as daemon\n");
+ printf(" -r --repeat keep running\n");
+ printf("options may be uniquely abbreviated; units are as defined in APRS\n");
+ printf("Specification 1.0.1 for positionless weather data (English/hPa).\n");
+ exit(ret);
+}
+
+
+
+
+
+/******************************************************************
+1/2/2003
+ Make an APRS string out of WX data
+
+*******************************************************************/
+
+int APRS_str(char *APRS_buf,
+ double winddir,
+ double windspeed,
+ double windgust,
+ double temp,
+ double rain1hr,
+ double rain24h,
+ double raintot,
+ double humidity,
+ double airpressure,
+ unsigned int valid_data_flgs,
+ int Metric_Data)
+{
+
+ int intval;
+ char pbuf[10];
+
+ if (APRS_buf == NULL) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Null string buffer for APRS string.\n");
+ return 0; // Ooo!! *****Nasty Bad Exit Point Here****
+
+ }
+ if(valid_data_flgs & VALID_WINDDIR) {
+ intval = (winddir + 0.5); // rounding to whole degrees
+ if (intval > 360) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Wind direction > 360\n");
+ sprintf(APRS_buf, "c...");
+ }
+ else if (intval < 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Wind direction negative\n");
+ sprintf(APRS_buf, "c...");
+
+ }
+ else {
+ sprintf(APRS_buf, "c%0.3d", intval);
+ }
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Wind direction flagged as invalid\n");
+ sprintf(APRS_buf, "c...");
+
+ }
+
+ if(valid_data_flgs & VALID_WINDSPD) {
+ if (Metric_Data)
+ intval = (windspeed*MTPS2MPH + 0.5); // converting & rounding to whole MPH
+ else
+ intval = (windspeed + 0.5); // rounding to whole MPH
+ if (intval > 600) { // Let's be reasonable here - center of a tornado??
+ if (debug_level & 1)
+ fprintf(stderr,"err: Wind speed > 600 MPH\n");
+ sprintf(pbuf, "s...");
+
+ }
+ else if (intval < 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Wind speed negative\n");
+ sprintf(pbuf, "s...");
+
+ }
+ else {
+ sprintf(pbuf, "s%0.3d", intval);
+ }
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Wind speed flagged as invalid\n");
+ sprintf(pbuf, "s...");
+
+ }
+ strcat(APRS_buf,pbuf);
+
+ if(valid_data_flgs & VALID_WINDGST) {
+ if (Metric_Data)
+ intval = (windgust*MTPS2MPH + 0.5); // converting & rounding to whole MPH
+ else
+ intval = (windgust + 0.5); // rounding to whole MPH
+ if (intval > 600) { // Let's be reasonable here - center of a tornado??
+ if (debug_level & 1)
+ fprintf(stderr,"err: Wind gust > 600 MPH\n");
+ sprintf(pbuf, "g...");
+
+ }
+ else if (intval < 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Wind speed negative\n");
+ sprintf(pbuf, "g...");
+
+ }
+ else {
+ sprintf(pbuf, "g%0.3d", intval);
+ }
+
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Wind gust flagged as invalid\n");
+ sprintf(pbuf, "g...");
+
+ }
+ strcat(APRS_buf,pbuf);
+
+ if(valid_data_flgs & VALID_TEMP) {
+ if (Metric_Data)
+ intval = ((temp)*DEGC2DEGF + 0.5)+32; // converting & rounding to whole Deg F
+ else
+ intval = (temp + 0.5); // rounding to whole Deg F
+ if (intval > 200) { // Let's be reasonable here - boiling?
+ if (debug_level & 1)
+ fprintf(stderr,"err: Temperature > 200 Deg F\n");
+ sprintf(pbuf, "t...");
+
+ }
+ else if (intval < -99) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Temperature < -99 Deg F\n");
+ sprintf(pbuf, "t...");
+
+ }
+ else {
+ if (intval < 0) sprintf(pbuf,"t%0.2d",intval);
+ else sprintf(pbuf, "t%0.3d", intval);
+ }
+
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Temperature flagged as invalid\n");
+ sprintf(pbuf, "t...");
+
+ }
+ strcat(APRS_buf,pbuf);
+
+ if(valid_data_flgs & VALID_RAIN1HR) {
+ if (Metric_Data)
+ intval = ((rain1hr)*MM2IN100TH + 0.5); // converting & rounding to whole 1/100 inch
+ else
+ intval = (rain1hr*100.0 + 0.5); // rounding to whole 1/100 inch
+ if (intval > 999) { // 10 in/hr? Garden Hose -> rain gauge?
+ if (debug_level & 1)
+ fprintf(stderr,"err: Rainfall/Hr > 9.99 inch\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ else if (intval < -99) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Rainfall/Hr negative\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ else {
+ sprintf(pbuf, "r%0.3d", intval);
+ }
+ }
+ else {
+
+ if (debug_level & 1)
+ fprintf(stderr,"info: Rainfall/Hr flagged as invalid\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ strcat(APRS_buf,pbuf);
+
+ if(valid_data_flgs & VALID_RAIN24H) {
+ if (Metric_Data)
+ intval = ((rain24h)*MM2IN100TH + 0.5); // converting & rounding to whole 1/100 inch
+ else
+ intval = (rain24h*100.0 + 0.5); // rounding to whole 1/100 inch
+ if (intval > 999) { // Can't handle greater than 9.99 inches of rain in 24 hours
+ if (debug_level & 1)
+ fprintf(stderr,"err: Rainfall/24Hr > 9.99 inch - reporting 9.99 inches\n");
+ sprintf(pbuf, "p999");
+
+ }
+ else if (intval < -99) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Rainfall/Hr negative\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ else {
+ sprintf(pbuf, "p%0.3d", intval);
+ }
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Rainfall/24Hr flagged as invalid\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ strcat(APRS_buf,pbuf);
+
+
+ if(valid_data_flgs & VALID_HUMIDITY) {
+ intval = (humidity + 0.5); // rounding to whole percent
+ if (intval > 100) { // Unlike the space shuttle engines, 100 % is max
+ if (debug_level & 1)
+ fprintf(stderr,"err: Humidity reported > 100%\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ else if (intval < 1) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Humidity reported < 1%\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ else {
+ if (intval == 100) intval = 0; // Report 100% as 'h00'
+ sprintf(pbuf, "h%0.2d", intval);
+ }
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Humidity flagged as invalid\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ strcat(APRS_buf,pbuf);
+
+ if(valid_data_flgs & VALID_AIRPRESS) {
+ if (Metric_Data)
+ intval = (airpressure*10.0 + 0.5); // rounding to whole tenth of a hPa
+ else
+ intval = (airpressure*INHG2HPA10TH + 0.5); // convering In-Hg to 1/10 hPa and rounding
+ if (intval > 20000) { //two atmospheres - about 29 PSIA
+ if (debug_level & 1)
+ fprintf(stderr,"err: Air Pressure reported > 2 Atmospheres%\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ else if (intval < 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Air Pressure reported negative%\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ else {
+ sprintf(pbuf, "b%0.5d", intval);
+ }
+ } else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: Air Pressure flagged as invalid\n");
+ sprintf(pbuf, "\0\0\0\0");
+
+ }
+ strcat(APRS_buf,pbuf);
+
+ // NOW THIS MAKES THE STRING NO LONGER A VALID APRS WX REPORT, but
+ // we don't care: Xastir does NOT just transmit this string, it parses it
+ // and re-recreates the correct string to transmit. We do this because
+ // APRS doesn't have a "total rain" string in its weather report, but
+ // Xastir likes to have that value around.
+ if(valid_data_flgs & VALID_RAINTOT) {
+ if (Metric_Data)
+ intval = ((raintot)*MM2IN100TH + 0.5); // converting & rounding to whole 1/100 inch
+ else
+ intval = (raintot*100.0 + 0.5); // rounding to whole 1/100 inch
+
+ // Can't handle greater than 99.99 inches of total rain
+ if (intval > 9999) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: total Rainfall > 99.99 inch - reporting 9.99 inches\n");
+ sprintf(pbuf, "T9999");
+
+ }
+ else if (intval < -99) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: total Rainfall negative\n");
+ sprintf(pbuf, "\0\0\0\0\0");
+
+ }
+ else {
+ sprintf(pbuf, "T%0.4d", intval);
+ }
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"info: total Rainfall flagged as invalid\n");
+ sprintf(pbuf, "\0\0\0\0\0");
+
+ }
+ strcat(APRS_buf,pbuf);
+
+ strcat(APRS_buf,"xDvs\n"); // add X aprs and LaCrosse WX station ID's and <lf>
+
+ if (debug_level & 1)
+ fprintf(stderr,"\ninfo: APRS Version of WX - %s\n\n",APRS_buf);
+ return strlen(APRS_buf);
+}
+
+
+
+
+
+/******************************************************************
+1/2/2003
+ Get the latest set of Weather Data from the Data Base
+
+*******************************************************************/
+
+int Get_Latest_WX( double *winddir,
+ double *windspeed,
+ double *windgust,
+ double *temp,
+ double *rain1hr,
+ double *rain24h,
+ double *raintot,
+ double *humidity,
+ double *airpressure,
+ unsigned int *valid_data_flgs,
+ int *Metric_Data)
+
+{
+
+ char latest_timestamp[20];
+ char query_buffer[160];
+ int nrows, row_cnt, item_count;
+ int nfields;
+
+
+ // Find latest, see if it's new to us
+ // --new to us is a simple timestamp follower, so upon startup
+ // it will always read one set of data, assuming any exists
+
+ if (mysql_query(&mysql, "SELECT MAX(timestamp) from weather")) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Latest timestamp query failed - exiting: %s\n", mysql_error(&mysql));
+ return 0;
+ }
+
+ if (!(result = mysql_store_result(&mysql))) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Latest timestamp query failed - exiting: %s\n", mysql_error(&mysql));
+ return 0;
+ }
+
+ if (mysql_num_rows(result) != 1 ) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Latest timestamp query failed - exiting: number of results %d\n",
+ mysql_num_rows(result));
+ // release query buffer
+ mysql_free_result(result);
+ return 0;
+ }
+
+ row = mysql_fetch_row(result);
+
+ if( row[0] == NULL ) {
+ if(debug_level & 1)
+ fprintf(stderr,"err: NULL result for timestamp query\n");
+ // release query buffer
+ mysql_free_result(result);
+ return 0;
+ }
+ // if no new data. exit with negative status
+
+ if (!strncmp(last_timestamp, row[0], 14)) {
+ if (debug_level & 1)
+ fprintf(stderr,"info: No new weather data recorded - exiting: negative data\n");
+ // release query buffer
+ mysql_free_result(result);
+ return -1;
+ }
+ strcpy(last_timestamp, row[0]); // For next pass & following query
+
+ if( debug_level & 1) fprintf(stdout,"Timestamp: %s\n",last_timestamp);
+
+ // release query buffer
+ mysql_free_result(result);
+
+ sprintf(query_buffer,"SELECT wind_angle, windspeed, temp_out, rain_1h, rain_24h, rel_hum_out, rel_pressure, rain_total FROM weather WHERE timestamp = %s", last_timestamp);
+
+ if (mysql_query(&mysql, query_buffer)) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Latest Weather Data query failed - exiting: %s\n\t --Query: %s\n",
+ mysql_error(&mysql), query_buffer);
+ return 0;
+ }
+
+ if (!(result = mysql_store_result(&mysql))) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Latest Weather Data query failed - exiting: %s\n", mysql_error(&mysql));
+ return 0;
+ }
+ if ((nrows=mysql_num_rows(result)) < 1 ) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Latest Weather Data query failed - exiting: number of results %d\n",nrows);
+ // release query buffer
+ mysql_free_result(result);
+ return 0;
+ }
+ else {
+ nfields=mysql_num_fields(result);
+ row=mysql_fetch_row(result);
+ if (debug_level & 1)
+ fprintf(stderr,"info: Latest Weather Data query: number of types of readings %d\n",nfields);
+ }
+
+ *valid_data_flgs = 0;
+ item_count = 0;
+
+ //WIND_DIRECTION :
+ *winddir = strtod(row[0],NULL);
+ *valid_data_flgs |= VALID_WINDDIR;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"wind direction %f\n ",*winddir);
+ //case WIND_SPEED :
+ *windspeed = strtod(row[1],NULL);
+ *windspeed = *windspeed * 1.15077945; // Convert from knots to mph
+ *valid_data_flgs |= VALID_WINDSPD;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"wind speed %f\n ",*windspeed);
+ //case WIND_GUST :
+ *windgust = strtod("0",NULL);
+ //*valid_data_flgs |= VALID_WINDGST; No gust information from open2300
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"wind gust speed %f\n ",*windgust);
+ //case TEMPERATURE :
+ *temp = strtod(row[2],NULL);
+ *valid_data_flgs |= VALID_TEMP;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"temperature %f\n ",*temp);
+ //case RAIN_PER_HOUR :
+ *rain1hr = strtod(row[3],NULL);
+ *valid_data_flgs |= VALID_RAIN1HR;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"rainfall for 1 hr %f\n ",*rain1hr);
+ //case RAIN_PER_DAY :
+ *rain24h = strtod(row[4],NULL);
+ *valid_data_flgs |= VALID_RAIN24H;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"rainfall for 24 hrs %f\n ",*rain24h);
+ //case HUMIDITY :
+ *humidity = strtod(row[5],NULL);
+ *valid_data_flgs |= VALID_HUMIDITY;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"humidity %f\n ",*humidity);
+ //case AIR_PRESSURE :
+ *airpressure = strtod(row[6],NULL);
+ *valid_data_flgs |= VALID_AIRPRESS;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"air pressure %f\n ",*airpressure);
+ //case RAIN_TOTAL
+ *raintot = strtod(row[7],NULL);
+ *valid_data_flgs |= VALID_RAINTOT;
+ item_count++;
+ if(debug_level & 1)
+ fprintf(stderr,"rainfall since reset %f\n ",*raintot);
+
+ *Metric_Data = 0; // My station reports F, knots and inHG
+ // release query buffer & close connection
+ mysql_free_result(result);
+
+ if (debug_level & 1)
+ fprintf(stderr,"info: success - Weather Data number of reading types %d\n",
+ item_count);
+
+ return item_count;
+}
+
+
+/******************************************************************
+1/5/2003
+ SIGPIPE signal handler
+
+*******************************************************************/
+void pipe_handler(int sig) /* */
+{
+ signal(SIGPIPE, SIG_IGN);
+ if (sig == SIGPIPE) { // client went bye-bye
+ shutdown(*current, 2);
+ close(*current);
+ *current = -1;
+ if (debug_level & 1)
+ fprintf(stderr, "info: %s - TCP client timed out", progname);
+ }
+}
+
+
+
+
+
+/******************************************************************
+1/5/2003
+ SIGTERM signal handler
+
+*******************************************************************/
+void term_handler(int sig) /* */
+{
+ if (debug_level & 1)
+ fprintf(stderr, "info: %s - ordered to DIE, complying", progname);
+
+ // release query buffer & close connection
+ mysql_free_result(result);
+
+ mysql_close(&mysql);
+
+ exit( 0 );
+}
+
+
+
+
+
+/******************************************************************
+1/2/2003
+ Coordinating MAIN point
+
+*******************************************************************/
+int main(int argc, char **argv)
+{
+ const char *flags = "Hhvnc:u:p:d:s:r";
+ char WX_APRS[120];
+ int data_len = 0 ;
+ double winddir;
+ double windspeed;
+ double windgust;
+ double temp;
+ double rain1hr;
+ double rain24h;
+ double raintot;
+ double humidity;
+ double airpressure;
+ unsigned int valid_data_flgs;
+ int Metric_Data = 0, dsts = 0;
+ int pid, s;
+ socklen_t clen = sizeof(struct sockaddr_in);
+ int fd[CONNECTIONS];
+ int *max = 0, c, dly_cnt = 1;
+ int not_a_daemon = 0, repetitive = 0, tcp_wx_port = PORT;
+ int i, index = 0;
+ struct sockaddr_in server, client;
+ struct in_addr bind_address;
+ fd_set rfds;
+ struct timeval tv;
+
+ struct option longopt[] = {
+ {"help", 0, 0, 'h'},
+ {"refresh", 0, 0, 'r'},
+ {"verbose", 0, 0, 'v'},
+ {"user", 1, 0, 'u'},
+ {"password", 1, 0, 'p'},
+ {"database", 1, 0, 'd'},
+ {"cport", 1, 0, 'c'},
+ {"nodaemon", 0, 0, 'n'},
+ {0, 0, 0, 0}
+ };
+
+ debug_level = 0;
+
+ strcpy(db.user,"open2300"); // set default values for database access
+ strcpy(db.name,"open2300");
+ memset(db.pswrd,0,15);
+
+ mysql_init(&mysql);
+
+
+ progname = strrchr(argv[0], '/');
+ if (progname == NULL)
+ progname = argv[0];
+ else
+ progname++;
+
+ while ((opt = getopt_long(argc, argv, flags, longopt, &index)) != EOF) {
+ switch (opt) { /* parse command-line or CGI options */
+ case 'r':
+ repetitive = 1;
+ break;
+ case 'v':
+ fprintf(stdout,"Verbose mode set:\n");
+ debug_level = 1;
+ break;
+ case 'u': // mysql username
+ strncpy(db.user,(char *)optarg,30);
+ break;
+ case 'p': // mysql password
+ strncpy(db.pswrd,(char *)optarg,15);
+ break;
+ case 'd': // mysql database name
+ strncpy(db.name,(char *)optarg,30);
+ break;
+ case 'n': /* do not fork and become a daemon */
+ not_a_daemon = 1;
+ break;
+ case 'c': /* port to use */
+ tcp_wx_port = strtol(optarg, NULL, 0);
+ break;
+
+ case '?':
+ case 'h':
+ case 'H':
+ usage(0);
+ break;
+ default :
+ usage(1);
+ }
+ }
+ if (debug_level & 1) {
+ fprintf(stdout,"Starting...");
+ if (repetitive) fprintf(stdout, " forever ");
+ else fprintf(stdout, " one pass only ");
+ fprintf(stdout," with database user=%s, password=%s, for database=%s\n",
+ db.user, db.pswrd, db.name);
+ if(not_a_daemon) fprintf(stdout," as a program ");
+ else fprintf(stdout," as a daemon ");
+ fprintf(stdout, " using TCP port %d\n",tcp_wx_port);
+ }
+
+ // Data base connection
+
+
+ if (!(mysql_real_connect(&mysql, "localhost", db.user, db.pswrd, db.name, 0, NULL, 0))) {
+ if (debug_level & 1)
+ fprintf(stderr,"err: Data Base connect for user:%s to database:%s failed - exiting: \n\t%s\n",
+ db.user, db.name, mysql_error(&mysql));
+ exit(9);
+ }
+
+ server.sin_family = AF_INET;
+ bind_address.s_addr = htonl(INADDR_ANY);
+ server.sin_addr = bind_address;
+ server.sin_port = htons(tcp_wx_port);
+
+ if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+ if (debug_level & 1)
+ fprintf(stderr, "err: %s - no socket", progname);
+ exit(10);
+ }
+ /* <dirkx at covalent.net> / April 2001 Minor change to allow quick
+ * (re)start of deamon or client while there are pending
+ * conncections during the quit. To avoid addresss/port in use
+ * error. */
+ i = 1;
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) == -1) {
+ if (debug_level & 1)
+ fprintf(stderr, "err: %s - setsockopt", progname);
+ }
+ if (bind(s, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1) {
+ if (debug_level & 1)
+ fprintf(stderr, "err: %s - cannot bind to socket", progname);
+ exit(11);
+ }
+ if (listen(s, CONNECTIONS) == -1) {
+ if (debug_level & 1)
+ fprintf(stderr, "err: %s - listen", progname);
+ exit(12);
+ }
+
+ if (debug_level & 1)
+ fprintf(stdout,"Sockets UP.\n");
+
+ umask(0022);
+ for (i = 0; i < CONNECTIONS; i++) fd[i] = -1;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ if (!not_a_daemon) { /* setup has worked; now become a daemon? */
+
+ if ((pid = fork()) == -1) {
+ syslog(LOG_ERR, "can't fork() to become daemon: %m");
+ exit(20);
+ }
+ else if (pid)
+ exit (0);
+
+ setsid();
+ for (i = 0; i < NOFILE; i++) if ( i != s) close(i);
+ }
+
+ /* catch signals to close the database connection */
+ signal( SIGTERM, term_handler );/* termination */
+#if defined(SIGPWR) /* SIGPWR is linux centric */
+ signal( SIGPWR, term_handler ); /* power failure */
+#endif
+
+ if (debug_level & 1) fprintf(stdout,"Main Loop...\n");
+ dly_cnt = 1; //N0VH, change back to 1
+ do {
+ if(!(dly_cnt--)) {
+ dly_cnt = 25; // Every 'dly_cnt' passes check for WX data update
+ if((dsts = Get_Latest_WX(&winddir,&windspeed,&windgust,
+ &temp,&rain1hr,&rain24h,&raintot,
+ &humidity,&airpressure,
+ &valid_data_flgs,&Metric_Data)) !=0 ) {
+ if ( dsts > 0 ) {
+ data_len = APRS_str(WX_APRS, winddir,windspeed,windgust,
+ temp, rain1hr, rain24h, raintot,
+ humidity, airpressure,
+ valid_data_flgs, Metric_Data);
+
+ if (!data_len) {
+ if (debug_level & 1)
+ fprintf(stderr, "err: WX info formatting problem!");
+ exit(13);
+ }
+ }
+ }
+ else {
+ exit(dsts);
+ }
+ }
+ FD_ZERO(&rfds);
+ FD_SET(s, &rfds);
+ if (select(s + 1, &rfds, NULL, NULL, &tv) > 0) {
+ for (current = fd; (*current > 0) && (current < fd + CONNECTIONS - 1); current++);
+ if (current > max) max = current;
+ if ((*current = accept(s, (struct sockaddr *)&client, &clen)) != -1)
+ write(*current, WX_APRS, data_len);
+ }
+ if (dly_cnt == 25) {
+ if (debug_level & 1) fprintf(stdout,"Updating clients:");
+ for (current = fd; current <=max; current++)
+ if (*current > 0) { // active socket
+ if (debug_level & 1) fprintf(stdout," #");
+ signal(SIGPIPE, pipe_handler);
+ write(*current, WX_APRS, data_len);
+ }
+ if (debug_level & 1) fprintf(stdout," done\n");
+ }
+ sleep(1); //
+ } while (repetitive);
+
+ mysql_close(&mysql);
+
+ if (debug_level & 1) fprintf(stdout,"Exiting normally.\n");
+ exit(0);
+}
+
diff --git a/LaCrosse/weatherdump.sql b/LaCrosse/weatherdump.sql
new file mode 100644
index 0000000..bce633f
--- /dev/null
+++ b/LaCrosse/weatherdump.sql
@@ -0,0 +1,32 @@
+-- MySQL dump 8.23
+--
+-- Host: localhost Database: open2300
+---------------------------------------------------------
+-- Server version 3.23.58-log
+
+--
+-- Table structure for table `weather`
+--
+
+CREATE TABLE weather (
+ timestamp bigint(14) NOT NULL default '0',
+ rec_date date NOT NULL default '0000-00-00',
+ rec_time time NOT NULL default '00:00:00',
+ temp_in decimal(4,1) NOT NULL default '0.0',
+ temp_out decimal(4,1) NOT NULL default '0.0',
+ dewpoint decimal(4,1) NOT NULL default '0.0',
+ rel_hum_in tinyint(3) NOT NULL default '0',
+ rel_hum_out tinyint(3) NOT NULL default '0',
+ windspeed decimal(4,1) NOT NULL default '0.0',
+ wind_angle decimal(4,1) NOT NULL default '0.0',
+ wind_direction char(3) NOT NULL default '',
+ wind_chill decimal(4,1) NOT NULL default '0.0',
+ rain_1h decimal(4,2) NOT NULL default '0.00',
+ rain_24h decimal(4,2) NOT NULL default '0.00',
+ rain_total decimal(5,2) NOT NULL default '0.00',
+ rel_pressure decimal(4,2) NOT NULL default '0.00',
+ tendency varchar(7) NOT NULL default '',
+ forecast varchar(6) NOT NULL default '',
+ UNIQUE KEY timestamp (timestamp)
+) TYPE=MyISAM;
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..6b83bc7
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,153 @@
+
+# $Id: Makefile.am,v 1.60 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+
+AUTOMAKE_OPTIONS = gnu dist-bzip2
+ACLOCAL_AMFLAGS = -I m4
+
+D= `date +%G%m%d.%H%M%S`
+
+SUBDIRS = src m4 config help scripts symbols callpass
+
+# Remove this file here (it is created via configure), not from within intl.
+# DISTCLEANFILES = intl/libintl.h
+
+EXTRA_DIST = xastir.spec.in xastir.spec xastir-min.spec.in xastir-min.spec config.guess config.sub install-sh \
+ missing mkinstalldirs placeholder FAQ LICENSE README README.CVS \
+ README.CYGWIN README.Getting-Started README.Contributing \
+ README.MAPS README.win32 README.OSM_maps testdbfawk.1 \
+ DEBUG_LEVELS bootstrap.sh INSTALL UPGRADE callpass.1 xastir.1 xastir_udp_client.1 terraserver.geo \
+ terraserver-reflectivity.geo terraserver-urban.geo worldhi.map \
+ terraserver-topo.geo USRadar.geo CanadaTopo250k.geo \
+ CanadaTopo50k.geo TXRadar.geo WMSRadar.geo Davis LaCrosse \
+ OSM_template \
+ CC_OpenStreetMap_logo.png CC_OpenStreetMap_txt.png \
+ COPYING COPYING.LIB.LESSTIF AUTHORS
+
+MAINTAINERCLEANFILES = configure aclocal.m4 Makefile.in Makefile \
+ config.guess config.sub install-sh missing mkinstalldirs \
+ xastir.spec xastir-min.spec
+
+countydir=${pkgdatadir}/Counties
+county_DATA=placeholder
+
+fccdir=${pkgdatadir}/fcc
+fcc_DATA=placeholder
+
+gnisdir=${pkgdatadir}/GNIS
+gnis_DATA=placeholder
+
+mapdir=${pkgdatadir}/maps
+map_DATA=worldhi.map CC_OpenStreetMap_logo.png CC_OpenStreetMap_txt.png
+
+onlinedir=${pkgdatadir}/maps/Online
+online_DATA=terraserver.geo terraserver-topo.geo \
+ terraserver-reflectivity.geo terraserver-urban.geo \
+ USRadar.geo CanadaTopo250k.geo CanadaTopo50k.geo \
+ TXRadar.geo WMSRadar.geo \
+ OSM_cloudmade_1.geo OSM_cloudmade_2.geo \
+ OSM_cloudmade_5.geo OSM_cloudmade_998.geo \
+ OSM_cloudmade_999.geo OSM_tiled_cycle.geo OSM_tiled_mapnik.geo \
+ OSM_tiled_osmarender.geo OSM_tiled_skiing.geo \
+ OSM_tiled_topOSM_0_relief.geo \
+ OSM_tiled_topOSM_1_contour.geo OSM_tiled_topOSM_2_features.geo
+
+gpsdir=${pkgdatadir}/maps/GPS
+gps_DATA=placeholder
+
+sounddir=${pkgdatadir}/sounds
+sound_DATA=placeholder
+
+docdir=${prefix}/share/doc/xastir
+doc_DATA=AUTHORS FAQ ChangeLog LICENSE README README.CVS README.CYGWIN \
+ README.MAPS README.win32 COPYING INSTALL UPGRADE \
+ README.Getting-Started README.Contributing README.OSM_maps\
+ COPYING.LIB.LESSTIF
+
+# It'd be nice to remove the directory and contents at
+# "${pkgdatadir}/doc" then install a symlink called "doc" there pointing
+# to "${prefix}/share/doc/xastir/". The new location for the
+# documentation is FHS compliant.
+
+install-exec-hook:
+ -rm -rf $(DESTDIR)${pkgdatadir}/doc
+
+install-data-hook:
+ cd $(DESTDIR)$(mapdir) && \
+ rm -f CC_OpenStreetMap.png && \
+ $(LN_S) CC_OpenStreetMap_logo.png CC_OpenStreetMap.png
+
+mandir=${prefix}/share/man
+man_MANS=xastir.1 callpass.1 xastir_udp_client.1 testdbfawk.1
+
+# Tiles from cloudmade require an access code, so use the static map.
+OSM_cloudmade_1.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/-STYLE/-layer=cloudmade_1/' -e's/^#OSMSTATICMAP/OSMSTATICMAP/' < $(top_srcdir)/OSM_template >$@
+
+OSM_cloudmade_2.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/-STYLE/-layer=cloudmade_2/' -e's/^#OSMSTATICMAP/OSMSTATICMAP/' < $(top_srcdir)/OSM_template >$@
+
+OSM_cloudmade_5.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/-STYLE/-layer=cloudmade_5/' -e's/^#OSMSTATICMAP/OSMSTATICMAP/' < $(top_srcdir)/OSM_template >$@
+
+OSM_cloudmade_998.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/-STYLE/-layer=cloudmade_998/' -e's/^#OSMSTATICMAP/OSMSTATICMAP/' < $(top_srcdir)/OSM_template >$@
+
+OSM_cloudmade_999.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/-STYLE/-layer=cloudmade_999/' < $(top_srcdir)/OSM_template >$@
+
+# Use tiles for these maps
+OSM_tiled_cycle.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/^#OSM_TILED_MAP/OSM_TILED_MAP/' \
+ -e's!^#URL tileURL!URL http://tile.opencyclemap.org/cycle/!' \
+ -e 's/-STYLE/-cycle/' \
+ < $(top_srcdir)/OSM_template >$@
+
+OSM_tiled_mapnik.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/^#OSM_TILED_MAP/OSM_TILED_MAP/' \
+ -e's!^#URL tileURL!URL http://tile.openstreetmap.org/!' \
+ -e 's/-STYLE/-mapnik/' \
+ < $(top_srcdir)/OSM_template >$@
+
+OSM_tiled_osmarender.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/^#OSM_TILED_MAP/OSM_TILED_MAP/' \
+ -e's!^#URL tileURL!URL http://tah.openstreetmap.org/Tiles/tile/!' \
+ -e 's/-STYLE/-osmarender/' \
+ < $(top_srcdir)/OSM_template >$@
+
+OSM_tiled_skiing.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/^#OSM_TILED_MAP/OSM_TILED_MAP/' \
+ -e's!^#URL tileURL!URL http://tiles.openpistemap.org/contours/!' \
+ -e 's/-STYLE/-skiing/' \
+ < $(top_srcdir)/OSM_template >$@
+
+OSM_tiled_topOSM_0_relief.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/^#OSM_TILED_MAP/OSM_TILED_MAP/' \
+ -e's!^#URL tileURL!URL http://tile1.toposm.com/usw/color-relief/!' \
+ -e 's/-STYLE/-topOSMr/' \
+ -e 's/#TILE_EXT png/TILE_EXT jpg/' \
+ -e 's/#ZOOM_LEVEL_MIN 0/ZOOM_LEVEL_MIN 5/' \
+ -e 's/#ZOOM_LEVEL_MAX 18/ZOOM_LEVEL_MAX 15/' \
+ < $(top_srcdir)/OSM_template >$@
+
+OSM_tiled_topOSM_1_contour.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/^#OSM_TILED_MAP/OSM_TILED_MAP/' \
+ -e's!^#URL tileURL!URL http://tile1.toposm.com/usw/contours/!' \
+ -e 's/-STYLE/-topOSMc/' \
+ -e 's/#ZOOM_LEVEL_MIN 0/ZOOM_LEVEL_MIN 5/' \
+ -e 's/#ZOOM_LEVEL_MAX 18/ZOOM_LEVEL_MAX 15/' \
+ < $(top_srcdir)/OSM_template >$@
+
+OSM_tiled_topOSM_2_features.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/^#OSM_TILED_MAP/OSM_TILED_MAP/' \
+ -e's!^#URL tileURL!URL http://tile1.toposm.com/usw/features/!' \
+ -e 's/-STYLE/-topOSMf/' \
+ -e 's/#ZOOM_LEVEL_MIN 0/ZOOM_LEVEL_MIN 5/' \
+ -e 's/#ZOOM_LEVEL_MAX 18/ZOOM_LEVEL_MAX 15/' \
+ < $(top_srcdir)/OSM_template >$@
+
+ChangeLog::
+
+
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..8ce5853
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,1129 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+# $Id: Makefile.am,v 1.60 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/config.h.in \
+ $(srcdir)/xastir-lsb.spec.in $(srcdir)/xastir-min.spec.in \
+ $(srcdir)/xastir.spec.in $(top_srcdir)/configure ABOUT-NLS \
+ AUTHORS COPYING ChangeLog INSTALL NEWS config.guess config.sub \
+ depcomp install-sh missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = xastir.spec xastir-min.spec xastir-lsb.spec
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+man1dir = $(mandir)/man1
+am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(countydir)" \
+ "$(DESTDIR)$(docdir)" "$(DESTDIR)$(fccdir)" \
+ "$(DESTDIR)$(gnisdir)" "$(DESTDIR)$(gpsdir)" \
+ "$(DESTDIR)$(mapdir)" "$(DESTDIR)$(onlinedir)" \
+ "$(DESTDIR)$(sounddir)"
+NROFF = nroff
+MANS = $(man_MANS)
+DATA = $(county_DATA) $(doc_DATA) $(fcc_DATA) $(gnis_DATA) $(gps_DATA) \
+ $(map_DATA) $(online_DATA) $(sound_DATA)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir dist dist-all distcheck
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d "$(distdir)" \
+ || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr "$(distdir)"; }; }
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTSHP = @CONTSHP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GMAGIC_BIN = @GMAGIC_BIN@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBCOMPAT = @LIBCOMPAT@
+LIBOBJS = @LIBOBJS@
+LIBRTREE = @LIBRTREE@
+LIBS = @LIBS@
+LIBSHP = @LIBSHP@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LWPOSTGIS = @LWPOSTGIS@
+MAGIC_BIN = @MAGIC_BIN@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PG_CONFIG = @PG_CONFIG@
+POW_LIB = @POW_LIB@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUBRTREE = @SUBRTREE@
+SUBSHP = @SUBSHP@
+VERSION = @VERSION@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+convert = @convert@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = ${prefix}/share/doc/xastir
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+festival = @festival@
+found_gdal_config = @found_gdal_config@
+gm = @gm@
+gpsman = @gpsman@
+gv = @gv@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lpr = @lpr@
+mandir = ${prefix}/share/man
+mkdir_p = @mkdir_p@
+mv = @mv@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sed = @sed@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+wget = @wget@
+xfontsel = @xfontsel@
+AUTOMAKE_OPTIONS = gnu dist-bzip2
+ACLOCAL_AMFLAGS = -I m4
+D = `date +%G%m%d.%H%M%S`
+SUBDIRS = src m4 config help scripts symbols callpass
+
+# Remove this file here (it is created via configure), not from within intl.
+# DISTCLEANFILES = intl/libintl.h
+EXTRA_DIST = xastir.spec.in xastir.spec xastir-min.spec.in xastir-min.spec config.guess config.sub install-sh \
+ missing mkinstalldirs placeholder FAQ LICENSE README README.CVS \
+ README.CYGWIN README.Getting-Started README.Contributing \
+ README.MAPS README.win32 README.OSM_maps testdbfawk.1 \
+ DEBUG_LEVELS bootstrap.sh INSTALL UPGRADE callpass.1 xastir.1 xastir_udp_client.1 terraserver.geo \
+ terraserver-reflectivity.geo terraserver-urban.geo worldhi.map \
+ terraserver-topo.geo USRadar.geo CanadaTopo250k.geo \
+ CanadaTopo50k.geo TXRadar.geo WMSRadar.geo Davis LaCrosse \
+ OSM_template \
+ CC_OpenStreetMap_logo.png CC_OpenStreetMap_txt.png \
+ COPYING COPYING.LIB.LESSTIF AUTHORS
+
+MAINTAINERCLEANFILES = configure aclocal.m4 Makefile.in Makefile \
+ config.guess config.sub install-sh missing mkinstalldirs \
+ xastir.spec xastir-min.spec
+
+countydir = ${pkgdatadir}/Counties
+county_DATA = placeholder
+fccdir = ${pkgdatadir}/fcc
+fcc_DATA = placeholder
+gnisdir = ${pkgdatadir}/GNIS
+gnis_DATA = placeholder
+mapdir = ${pkgdatadir}/maps
+map_DATA = worldhi.map CC_OpenStreetMap_logo.png CC_OpenStreetMap_txt.png
+onlinedir = ${pkgdatadir}/maps/Online
+online_DATA = terraserver.geo terraserver-topo.geo \
+ terraserver-reflectivity.geo terraserver-urban.geo \
+ USRadar.geo CanadaTopo250k.geo CanadaTopo50k.geo \
+ TXRadar.geo WMSRadar.geo \
+ OSM_cloudmade_1.geo OSM_cloudmade_2.geo \
+ OSM_cloudmade_5.geo OSM_cloudmade_998.geo \
+ OSM_cloudmade_999.geo OSM_tiled_cycle.geo OSM_tiled_mapnik.geo \
+ OSM_tiled_osmarender.geo OSM_tiled_skiing.geo \
+ OSM_tiled_topOSM_0_relief.geo \
+ OSM_tiled_topOSM_1_contour.geo OSM_tiled_topOSM_2_features.geo
+
+gpsdir = ${pkgdatadir}/maps/GPS
+gps_DATA = placeholder
+sounddir = ${pkgdatadir}/sounds
+sound_DATA = placeholder
+doc_DATA = AUTHORS FAQ ChangeLog LICENSE README README.CVS README.CYGWIN \
+ README.MAPS README.win32 COPYING INSTALL UPGRADE \
+ README.Getting-Started README.Contributing README.OSM_maps\
+ COPYING.LIB.LESSTIF
+
+man_MANS = xastir.1 callpass.1 xastir_udp_client.1 testdbfawk.1
+all: config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
+ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ $(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+ @if test ! -f $@; then \
+ rm -f stamp-h1; \
+ $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+ else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: $(am__configure_deps)
+ ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+ rm -f stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f config.h stamp-h1
+xastir.spec: $(top_builddir)/config.status $(srcdir)/xastir.spec.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+xastir-min.spec: $(top_builddir)/config.status $(srcdir)/xastir-min.spec.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+xastir-lsb.spec: $(top_builddir)/config.status $(srcdir)/xastir-lsb.spec.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+install-man1: $(man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)"
+ @list=''; test -n "$(man1dir)" || exit 0; \
+ { for i in $$list; do echo "$$i"; done; \
+ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.1[a-z]*$$/p'; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man1dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.1[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ test -z "$$files" || { \
+ echo " ( cd '$(DESTDIR)$(man1dir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(man1dir)" && rm -f $$files; }
+install-countyDATA: $(county_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(countydir)" || $(MKDIR_P) "$(DESTDIR)$(countydir)"
+ @list='$(county_DATA)'; test -n "$(countydir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(countydir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(countydir)" || exit $$?; \
+ done
+
+uninstall-countyDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(county_DATA)'; test -n "$(countydir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(countydir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(countydir)" && rm -f $$files
+install-docDATA: $(doc_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)"
+ @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \
+ done
+
+uninstall-docDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(docdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(docdir)" && rm -f $$files
+install-fccDATA: $(fcc_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(fccdir)" || $(MKDIR_P) "$(DESTDIR)$(fccdir)"
+ @list='$(fcc_DATA)'; test -n "$(fccdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(fccdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(fccdir)" || exit $$?; \
+ done
+
+uninstall-fccDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(fcc_DATA)'; test -n "$(fccdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(fccdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(fccdir)" && rm -f $$files
+install-gnisDATA: $(gnis_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(gnisdir)" || $(MKDIR_P) "$(DESTDIR)$(gnisdir)"
+ @list='$(gnis_DATA)'; test -n "$(gnisdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(gnisdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(gnisdir)" || exit $$?; \
+ done
+
+uninstall-gnisDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(gnis_DATA)'; test -n "$(gnisdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(gnisdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(gnisdir)" && rm -f $$files
+install-gpsDATA: $(gps_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(gpsdir)" || $(MKDIR_P) "$(DESTDIR)$(gpsdir)"
+ @list='$(gps_DATA)'; test -n "$(gpsdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(gpsdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(gpsdir)" || exit $$?; \
+ done
+
+uninstall-gpsDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(gps_DATA)'; test -n "$(gpsdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(gpsdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(gpsdir)" && rm -f $$files
+install-mapDATA: $(map_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(mapdir)" || $(MKDIR_P) "$(DESTDIR)$(mapdir)"
+ @list='$(map_DATA)'; test -n "$(mapdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(mapdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(mapdir)" || exit $$?; \
+ done
+
+uninstall-mapDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(map_DATA)'; test -n "$(mapdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(mapdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(mapdir)" && rm -f $$files
+install-onlineDATA: $(online_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(onlinedir)" || $(MKDIR_P) "$(DESTDIR)$(onlinedir)"
+ @list='$(online_DATA)'; test -n "$(onlinedir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(onlinedir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(onlinedir)" || exit $$?; \
+ done
+
+uninstall-onlineDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(online_DATA)'; test -n "$(onlinedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(onlinedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(onlinedir)" && rm -f $$files
+install-soundDATA: $(sound_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(sounddir)" || $(MKDIR_P) "$(DESTDIR)$(sounddir)"
+ @list='$(sound_DATA)'; test -n "$(sounddir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(sounddir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(sounddir)" || exit $$?; \
+ done
+
+uninstall-soundDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sound_DATA)'; test -n "$(sounddir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sounddir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sounddir)" && rm -f $$files
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @list='$(MANS)'; if test -n "$$list"; then \
+ list=`for p in $$list; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
+ if test -n "$$list" && \
+ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
+ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
+ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
+ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
+ echo " typically \`make maintainer-clean' will remove them" >&2; \
+ exit 1; \
+ else :; fi; \
+ else :; fi
+ $(am__remove_distdir)
+ test -d "$(distdir)" || mkdir "$(distdir)"
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+ -test -n "$(am__skip_mode_fix)" \
+ || find "$(distdir)" -type d ! -perm -755 \
+ -exec chmod u+rwx,go+rx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-lzma: distdir
+ tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+ $(am__remove_distdir)
+
+dist-xz: distdir
+ tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lzma*) \
+ lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
+ *.tar.xz*) \
+ xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ test -d $(distdir)/_build || exit 0; \
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && am__cwd=`pwd` \
+ && $(am__cd) $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+ && cd "$$am__cwd" \
+ || exit 1
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @$(am__cd) '$(distuninstallcheck_dir)' \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(MANS) $(DATA) config.h
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(countydir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(fccdir)" "$(DESTDIR)$(gnisdir)" "$(DESTDIR)$(gpsdir)" "$(DESTDIR)$(mapdir)" "$(DESTDIR)$(onlinedir)" "$(DESTDIR)$(sounddir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-countyDATA install-docDATA install-fccDATA \
+ install-gnisDATA install-gpsDATA install-man install-mapDATA \
+ install-onlineDATA install-soundDATA
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-data-hook
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man: install-man1
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-countyDATA uninstall-docDATA uninstall-fccDATA \
+ uninstall-gnisDATA uninstall-gpsDATA uninstall-man \
+ uninstall-mapDATA uninstall-onlineDATA uninstall-soundDATA
+
+uninstall-man: uninstall-man1
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \
+ ctags-recursive install-am install-data-am install-exec-am \
+ install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am am--refresh check check-am clean clean-generic \
+ ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \
+ dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \
+ distclean distclean-generic distclean-hdr distclean-tags \
+ distcleancheck distdir distuninstallcheck dvi dvi-am html \
+ html-am info info-am install install-am install-countyDATA \
+ install-data install-data-am install-data-hook install-docDATA \
+ install-dvi install-dvi-am install-exec install-exec-am \
+ install-exec-hook install-fccDATA install-gnisDATA \
+ install-gpsDATA install-html install-html-am install-info \
+ install-info-am install-man install-man1 install-mapDATA \
+ install-onlineDATA install-pdf install-pdf-am install-ps \
+ install-ps-am install-soundDATA install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+ uninstall-countyDATA uninstall-docDATA uninstall-fccDATA \
+ uninstall-gnisDATA uninstall-gpsDATA uninstall-man \
+ uninstall-man1 uninstall-mapDATA uninstall-onlineDATA \
+ uninstall-soundDATA
+
+
+# It'd be nice to remove the directory and contents at
+# "${pkgdatadir}/doc" then install a symlink called "doc" there pointing
+# to "${prefix}/share/doc/xastir/". The new location for the
+# documentation is FHS compliant.
+
+install-exec-hook:
+ -rm -rf $(DESTDIR)${pkgdatadir}/doc
+
+install-data-hook:
+ cd $(DESTDIR)$(mapdir) && \
+ rm -f CC_OpenStreetMap.png && \
+ $(LN_S) CC_OpenStreetMap_logo.png CC_OpenStreetMap.png
+
+# Tiles from cloudmade require an access code, so use the static map.
+OSM_cloudmade_1.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/-STYLE/-layer=cloudmade_1/' -e's/^#OSMSTATICMAP/OSMSTATICMAP/' < $(top_srcdir)/OSM_template >$@
+
+OSM_cloudmade_2.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/-STYLE/-layer=cloudmade_2/' -e's/^#OSMSTATICMAP/OSMSTATICMAP/' < $(top_srcdir)/OSM_template >$@
+
+OSM_cloudmade_5.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/-STYLE/-layer=cloudmade_5/' -e's/^#OSMSTATICMAP/OSMSTATICMAP/' < $(top_srcdir)/OSM_template >$@
+
+OSM_cloudmade_998.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/-STYLE/-layer=cloudmade_998/' -e's/^#OSMSTATICMAP/OSMSTATICMAP/' < $(top_srcdir)/OSM_template >$@
+
+OSM_cloudmade_999.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/-STYLE/-layer=cloudmade_999/' < $(top_srcdir)/OSM_template >$@
+
+# Use tiles for these maps
+OSM_tiled_cycle.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/^#OSM_TILED_MAP/OSM_TILED_MAP/' \
+ -e's!^#URL tileURL!URL http://tile.opencyclemap.org/cycle/!' \
+ -e 's/-STYLE/-cycle/' \
+ < $(top_srcdir)/OSM_template >$@
+
+OSM_tiled_mapnik.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/^#OSM_TILED_MAP/OSM_TILED_MAP/' \
+ -e's!^#URL tileURL!URL http://tile.openstreetmap.org/!' \
+ -e 's/-STYLE/-mapnik/' \
+ < $(top_srcdir)/OSM_template >$@
+
+OSM_tiled_osmarender.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/^#OSM_TILED_MAP/OSM_TILED_MAP/' \
+ -e's!^#URL tileURL!URL http://tah.openstreetmap.org/Tiles/tile/!' \
+ -e 's/-STYLE/-osmarender/' \
+ < $(top_srcdir)/OSM_template >$@
+
+OSM_tiled_skiing.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/^#OSM_TILED_MAP/OSM_TILED_MAP/' \
+ -e's!^#URL tileURL!URL http://tiles.openpistemap.org/contours/!' \
+ -e 's/-STYLE/-skiing/' \
+ < $(top_srcdir)/OSM_template >$@
+
+OSM_tiled_topOSM_0_relief.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/^#OSM_TILED_MAP/OSM_TILED_MAP/' \
+ -e's!^#URL tileURL!URL http://tile1.toposm.com/usw/color-relief/!' \
+ -e 's/-STYLE/-topOSMr/' \
+ -e 's/#TILE_EXT png/TILE_EXT jpg/' \
+ -e 's/#ZOOM_LEVEL_MIN 0/ZOOM_LEVEL_MIN 5/' \
+ -e 's/#ZOOM_LEVEL_MAX 18/ZOOM_LEVEL_MAX 15/' \
+ < $(top_srcdir)/OSM_template >$@
+
+OSM_tiled_topOSM_1_contour.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/^#OSM_TILED_MAP/OSM_TILED_MAP/' \
+ -e's!^#URL tileURL!URL http://tile1.toposm.com/usw/contours/!' \
+ -e 's/-STYLE/-topOSMc/' \
+ -e 's/#ZOOM_LEVEL_MIN 0/ZOOM_LEVEL_MIN 5/' \
+ -e 's/#ZOOM_LEVEL_MAX 18/ZOOM_LEVEL_MAX 15/' \
+ < $(top_srcdir)/OSM_template >$@
+
+OSM_tiled_topOSM_2_features.geo: OSM_template
+ sed -e '/THIS IS A TEMPLATE FILE/d' -e's/^#OSM_TILED_MAP/OSM_TILED_MAP/' \
+ -e's!^#URL tileURL!URL http://tile1.toposm.com/usw/features/!' \
+ -e 's/-STYLE/-topOSMf/' \
+ -e 's/#ZOOM_LEVEL_MIN 0/ZOOM_LEVEL_MIN 5/' \
+ -e 's/#ZOOM_LEVEL_MAX 18/ZOOM_LEVEL_MAX 15/' \
+ < $(top_srcdir)/OSM_template >$@
+
+ChangeLog::
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..ec41cdb
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,39 @@
+
+$Id: NEWS,v 1.12 2012/11/01 18:57:18 we7u Exp $
+
+News - Updated 29 April 2001
+ ------------------------------------------------------------------------
+
+Whats new, first read the following documents:
+
+ INSTALL
+ README
+ ChangeLog
+
+All of these documents combined will fill you in on the latest changes to
+xastir in version 0.4.x.
+
+A lot of things have changed in this version so at a minimum read the
+ChangeLog text file. ChangeLog shows whats been added and fixed along the
+way.
+
+This version includes a "first try" at using the GNU Autotools for
+configuration. These scripts have not been throughly tested on all
+platforms. Any feedback is actively solicited.
+
+This version also includes several additional directories added in
+preparation for the implementation of GNU internationalization
+routines.
+
+
+CAUTION:
+
+ 1. Before you start Xastir for the first time BACKUP your
+ data files if this is an upgrade from a previous version.
+
+ 2. DON'T USE YOUR OLD CONFIG FILE.. MAKE A NEW ONE.........
+
+
+
+Copyright (C) 2000-2012 The Xastir Group
+
diff --git a/OSM_template b/OSM_template
new file mode 100644
index 0000000..d86ee49
--- /dev/null
+++ b/OSM_template
@@ -0,0 +1,52 @@
+#
+# $Id: OSM_template,v 1.3 2010/08/14 21:32:43 jedunmire Exp $
+#
+# THIS IS A TEMPLATE FILE
+#
+# Map data Copyright OpenStreetMap Contributors, CC-BY-SA
+# See www.openstreetmap.org and http://creativecommons.org/licenses/by-sa/2.0/
+#
+# The string following OSMSTATICMAP-, is appended to the URL
+# The string is typically expected to select a layer, and possibly style
+# options. If not set it defaults to:
+# layer=osmarander
+#
+# The string following OSM_TILED_MAP-, is the name of a sub-directory in
+# the tile cache. It can be empty (delete the '-' too), though that is a
+# bad idea if multiple map styles are using the same TILE_DIR.
+#
+# Select only one of the two map types: OSMSTATICMAP or OSM_TILED_MAP
+#
+#
+#OSMSTATICMAP-STYLE
+# or
+#OSM_TILED_MAP-STYLE
+#
+# The url for tiled maps defaults to http://tile.openstreetmap.org/. For
+# static maps it defaults to http://ojw.dev.openstreetmap.org/StaticMap/
+#URL tileURL
+
+# Tile extension defaults to png
+#TILE_EXT png
+
+#ZOOM_LEVEL_MIN 0
+#ZOOM_LEVEL_MAX 18
+
+# The tile cache can be changed from the default (~/.xastir/OSMtiles) by
+# setting the following variable. If path does not begin with a '/' then
+# it will be relative to ~/.xastir/.
+#
+#TILE_DIR OSMtiles
+
+
+# When defined:
+# OSM_OPTIMIZE_KEY will change the map scaling to the nearest OSM zoom level.
+# OSM_REPORT_SCALE_KEY will report the present, scale_x, scale_y,
+# and OSM zoom level, but only for debug level 512 (-v 512)
+#
+# The values are X KeySym values.
+# 65473 = F4
+# 65474 = F5
+OSM_OPTIMIZE_KEY 65473
+OSM_REPORT_SCALE_KEY 65474
+
diff --git a/README b/README
new file mode 100644
index 0000000..0ac951c
--- /dev/null
+++ b/README
@@ -0,0 +1,629 @@
+
+$Id: README,v 1.41 2012/11/01 18:57:18 we7u Exp $
+
+README
+ ------------------------------------------------------------------------
+
+ Please at least SKIM this document before asking questions. In fact,
+ READ IT if you've never successfully set up Xastir before. PLEASE!
+ READ IT! If you haven't read this file, and ask for help
+ expect to be told to READ the README file first! or RTFM :)
+
+ Contents
+
+ 0 Important notice
+ 1 What is Xastir?
+ 2 How do I get Xastir
+ 2a CVS usage
+ 3 Quick startup
+ 4 Upgrading
+ 5 Identification notes
+ 6 OS-specific notes
+ 7 Gating weather alerts
+ 8 Boring legal stuff
+ 9 Mailing list
+ 10 Documentation
+ 11 Obtaining help
+
+ ------------------------------------------------------------------------
+
+ (0) NOTICE
+
+ Please read this file carefully before trying to set up Xastir.
+ This software was developed to be used by licensed amateur radio
+ operators. You are responsible for any information transmitted
+ or propagated on any network.
+
+ (1) WHAT IS XASTIR?
+
+ Xastir is an open-source project to create a free X11 graphical
+ APRS(tm) client. APRS(tm) use amateur radio and Internet services to
+ convey GPS mapping, weather, and positional data in a graphical
+ application. It has been developed by and for amateur radio
+ enthusiasts to provide real-time data in an easy to use package.
+
+ Xastir currently runs under several flavors of Linux and BSD Unix.
+ A few people are running Xastir on Solaris Unix, FreeBSD, Lindows
+ and Mac OS X, but there may be small changes necessary in order to
+ get Xastir to configure/compile on some systems. There are a few
+ notes below which may help in this task. Most of the developers use
+ Linux which makes it the best supported platform at the moment.
+
+ Xastir is an open-source project: Most sources, documentation, and
+ binaries are available under the GPL license, with a few modules
+ available under other open-source or public domain licenses.
+
+ More information on Xastir can be found at:
+
+ http://www.xastir.org
+ http://xastir.sourceforge.net
+ http://sourceforge.net/projects/xastir/
+
+ including the latest releases, the anonymous CVS access (lets you
+ download the latest developers' code), and information on how to join
+ Xastir mailing lists. Note that you must be subscribed in order to
+ post to the mailing lists.
+
+ SmartBeaconing(tm) was invented by Tony Arnerich (KD7TA) and Steve
+ Bragg (KA9MVA) for the HamHUD project. They offer the algorithm to
+ other authors as long as proper credit is given and the term
+ SmartBeaconing(tm) is used. Thanks to Tony and Steve for that
+ contribution!
+
+ -- The Xastir Group.
+
+ (2) HOW TO GET XASTIR
+
+ Xastir is currently developed at
+ <http://sourceforge.net/projects/xastir/>
+ You can get the latest version of Xastir from there.
+
+ You might try www.xastir.org for help and information.
+ The web site is:
+ <http://xastir.sourceforge.net>.
+
+
+ (2a) CVS USAGE
+
+ You might obtain the *very latest* version of Xastir that
+ is still under development by using CVS.
+
+ See the file README.CVS for more details.
+
+ (3) QUICK STARTUP
+
+ INCLUDED IN 'INSTALL'
+ WINDOWS USERS: Please refer to the "README.win32" file for specific
+ instructions.
+
+ (4) UPGRADING
+
+ INCLUDED IN 'UPGRADE'
+
+ (5) IDENTIFICATION NOTES
+ Packet radio modes, by their very nature, typically identify
+ themselves with every transmission. Xastir has a few features
+ targeted to people who used Xastir in demonstrations and other
+ broadcasts where Xastir itself is used over radio.
+
+ Xastir can auto-ID via voice if Festival is compiled in and/or via a
+ message splashed across the screen. It does this identification
+ every 9.5 minutes if enabled. These identification modes were
+ designed for broadcasting Xastir across fast-scan television (for
+ events perhaps). Set the "ATV_SCREEN_ID" variable to 1 to enable the
+ screen message, and "SPEAK_ID" variable to 1 to enable festival to
+ speak the message. These variables are in the
+ ~/.xastir/config/xastir.cnf file.
+
+
+ (6) OS SPECIFIC NOTES
+ ----------------------------------------------------------------------
+ MAC OSX NOTES:
+
+ No changes necessary now for Mac OS X!
+
+ If you intend to run with GDAL installed, you may find that geotiff
+ projection doesn't work. To avoid this, install libtiff, libproj,
+ and libgeotiff first, then configure GDAL with
+ --with-libtiff=/path/to/libtiff --with-geotiff=/path/to/geotiff
+ It's important to not choose "yes" or "internal". You may also want
+ --with-libz=yes
+
+ If you have trouble building GDAL you may need this patch:
+ --- GDALmake.opt.in 7 Jan 2004 20:52:29 -0000 1.130
+ +++ GDALmake.opt.in 30 Jan 2004 22:08:58 -0000
+ @@ -78,8 +78,8 @@
+ endif
+
+ CPPFLAGS = @CPPFLAGS@ -I$(GDAL_ROOT)/port
+ -CFLAGS = @C_WFLAGS@ @C_PIC@ $(C_ODFLAGS) @EXTRA_INCLUDES@ $(USER_DEFS)
+ -CXXFLAGS = @CXX_WFLAGS@ @CXX_PIC@ $(CXX_ODFLAGS) \
+ +CFLAGS = @C_WFLAGS@ @C_PIC@ $(GDAL_INCLUDE) $(C_ODFLAGS) @EXTRA_INCLUDES@ $(USER_DEFS)
+ +CXXFLAGS = @CXX_WFLAGS@ @CXX_PIC@ $(GDAL_INCLUDE) $(CXX_ODFLAGS) \
+ @EXTRA_INCLUDES@ $(USER_DEFS)
+
+ RANLIB = @RANLIB@
+
+
+ You may want to install everything to /sw though, so that the normal
+ user can find it easily and add maps. To do this, run this instead:
+
+ ./configure --prefix=/sw
+
+ That will cause Xastir to be installed in /sw/xastir/* directories, and
+ the executable will go into /sw/bin/xastir.
+
+ Ports have been contributed to DarwinPorts. This will be updated with
+ instructions when those are committed.
+
+ Here's a web page which has specific instructions for installing on OSX,
+ including a binary version of Xastir (no compiling necessary):
+
+ http://n1ofz.connares.org/software/Xastir
+
+ END OF MAC OSX NOTES.
+ -----------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------
+ FreeBSD NOTES:
+
+ There are both a binary package and a port available as part of the
+ official FreeBSD ports system. Most FreeBSD users can either type
+ "pkg_add -r xastir" which will fetch the relevant binary for their
+ release, or preferably update their ports tree and use the port to get
+ the latest version.
+
+ Other options:
+
+ The FreeBSD port of xastir uses a development snapshot, and not
+ necessarily the latest snapshot, depending on how busy the port
+ maintainer is. If you wish to be on the bleeding edge you can build
+ xastir yourself from the latest development snapshot or from CVS,
+ without much more difficulty than Linux users have. There are a few
+ caveats, though.
+
+ The version of autoconf used to generate configuration files for
+ Xastir is 2.57 or later. If you have autoconf 2.13 installed,
+ there will be difficulties if you try to run "bootstrap.sh." It
+ is best to install recent, matching versions of autoconf and automake
+ directly from sources into a separate binary directory other than
+ /usr/local/bin, without relying on the FreeBSD ports system. The
+ ports system installs autoconf and automake with odd suffixes that
+ can interfere with the xastir build process.
+
+ Contact Jack Twilley <jmt at twilley.org> or Tom Russo <russo at bogodyn.org>
+ for more help in getting Xastir configured and built under FreeBSD.
+
+ END OF FreeBSD NOTES.
+ -----------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------
+ SOLARIS NOTES:
+
+ Changes required for Solaris 2.5 -> 7.0. Other versions may require
+ slightly different changes.
+
+ After running "configure", edit src/Makefile and make these changes:
+
+ Solaris 2.5 -> 2.6:
+ NOTE: Solaris 2.5 -> 2.6 do not install Xpm. If you've installed it
+ you'll need to delete "-DNO_XPM" from src/Makefile, make sure the
+ headers are in the search path, and add "-lXpm" to the LIBS or
+ LDFLAGS line in src/Makefile.
+
+ Solaris 7.0 notes from Chris Bell:
+ ----------------------------------
+ Date: Fri, 11 Jan 2002 16:38:57 -0800
+ From: Chris Bell <cbell at junknet.com>
+ To: "Curt Mills, WE7U" <hacker at tc.fluke.com>
+ Cc: xastir-dev
+ Subject: Re: [Xastir-Dev] Autoconf fixes for various OS's
+
+ YAY!!! Xpm is properly detected for solaris7!!!! On my system, (with
+ geotiff and ImageMagick) I still have to tweak the geotiff detection
+ to avoid the system libtiff:
+
+ ===================================================================
+ RCS file: /usr/local/cvs/xastir/configure,v
+ retrieving revision 1.51
+ diff -c -r1.51 configure
+ *** configure 2002/01/11 21:33:54 1.51
+ --- configure 2002/01/12 00:28:01
+ ***************
+ *** 4986,4992 ****
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ ac_save_LIBS="$LIBS"
+ ! LIBS="-lgeotiff $LIBS"
+ cat > conftest.$ac_ext <<EOF
+ #line 4992 "configure"
+ #include "confdefs.h"
+ --- 4986,4992 ----
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ ac_save_LIBS="$LIBS"
+ ! LIBS="-L/usr/local/lib -R/usr/local/lib -lgeotiff -ltiff $LIBS"
+ cat > conftest.$ac_ext <<EOF
+ #line 4992 "configure"
+ #include "confdefs.h"
+
+ Also, the generated Makefile needs the -L/usr/local/lib
+ -R/usr/local/lib added, and -lposix4 added to the link lib line.
+
+ It is compiling now, I will let you know if there are any runtime
+ problems.
+
+ I also installed the latest patches for the OS... the latest
+ Openwindows patch finally fixes the X header warnings, so we don't
+ have to fear turning -Wall back on. (patch # 108376-33) Probably a
+ good tidbit for the README...
+
+ I am trying to get enough parts to build more systems for testing
+ solaris 8. I tried it on my brother's system over the holidays, and
+ it worked just like 7.
+ -----------------------------------------------------------------------
+
+ Note that Solaris 2.5 doesn't have support for snprintf(). The code
+ has been tweaked to switch to sprintf() for these calls in this case,
+ which allows more places for buffer overflow problems (this is a
+ security issue as well as a stability issue). Solaris 2.6 and later
+ has support for snprintf().
+
+ Solaris 7.0 has Xpm support built into Motif, so you'll be able to
+ use Xpm map files within Xastir.
+
+ You need BSD-make installed on your system in order to compile Xastir.
+ Type "gmake" instead of "make" to build Xastir, and substitute "gmake"
+ for "make" in the following instructions.
+
+ ---
+ From: Chris Bell
+
+ A note to add, the auto* tools from sunfreeware (precompiled packages)
+ need the environment variable M4 set to gnu m4 (M4=/usr/local/bin/m4)
+ to work. I also set LDFLAGS to '-L/usr/local/lib -R/usr/local/lib' (to
+ avoid the ancient libtiff in /usr/openwin/lib) before running configure,
+ then the tests (and final link) work properly.
+
+ Chris.
+
+ ---
+ Solaris 9/AEA PK232MBX notes from Alan Shackelford:
+
+ Thanks to the advice of several of you both on the list and in private
+ email, the NG3B Xastir install is up and running. For future reference,
+ here are the steps I took, based on your advice combined with my
+ knowledge of Solaris and the AEA PK232MBX.
+
+ First, use admintool to set up the serial port at 8N1 9600.
+
+ Have a look at the /etc/uucp/Devices file and ensure you have the
+ following in there someplace (like at the very bottom):
+
+ ACU cua/b - Any hayes
+ Direct cua/b - Any direct
+
+
+ Then use 'cu' (solaris-ese for call unix) to send a '*' to the TNC.
+ You will receive a response from the TNC with copyright info, etc.
+
+ Close the 'cu' session and start Xastir from a terminal window.
+
+ Set the Interface to 9600 8N1 in the configuration screen. Start the
+ interface using the Interface Start/Stop window. The data will begin to
+ flow.
+
+ Alan NG3B
+ ---
+
+
+ END OF SOLARIS NOTES.
+ -----------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------
+ MANDRAKE LINUX NOTES:
+
+ With Mandrake Linux 8.x? you may get linker errors when it tries to
+ link in the "Xp" library. To fix this, edit xastir/src/Makefile,
+ adding "-lXp" to the LIBS line, then type "make" again.
+
+ END OF MANDRAKE LINUX NOTES.
+ -----------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------
+ OpenSuSE LINUX 10.0/10.1 NOTES:
+
+ Bring up YaST2 and add more download sites via:
+
+ Software->Installation Source
+
+ For OpenSuSE 10.0:
+
+ ftp://suse.mirrors.tds.net/pub/opensuse/distribution/SL-10.0-OSS/inst-source/suse
+ ftp://ftp.suse.com/pub/projects/ham/10.0-i386
+
+ For OpenSuSE 10.1:
+
+ ftp://suse.mirrors.tds.net/pub/opensuse/distribution/SL-10.1/inst-source/suse
+ http://dg7gt.osth.de/suse-10.1-ham/
+
+ For OpenSuSE 11.x (Use the one that matches your installation):
+
+ http://download.opensuse.org/repositories/hamradio/openSUSE_11.0/
+ http://download.opensuse.org/repositories/hamradio/openSUSE_11.1/
+ http://download.opensuse.org/repositories/hamradio/openSUSE_11.2/
+ http://download.opensuse.org/repositories/hamradio/openSUSE_11.3/
+
+ Adding these sites will allow you to find and install the ax25
+ libraries/devel headers, the OpenMotif development headers, and the
+ libcurl headers.
+
+ You'll see this warning if you run ./bootstrap.sh:
+
+ 4... Running aclocal
+ /usr/share/aclocal/pstoedit.m4:7: warning: underquoted definition of
+ AM_PATH_PSTOEDIT
+ run info '(automake)Extending aclocal'
+ or see
+ http://sources.redhat.com/automake/automake.html#Extending-aclocal
+
+ You may safely ignore this warning.
+
+ I've found that I need to do this when configuring for OpenSUSE in
+ order to pick up the libgeotiff include files:
+
+ ./configure CPPFLAGS="-I/usr/include/libgeotiff"
+
+ I just put it into a script called "configure.suse" so that I don't
+ have to remember it each time. Here are the complete contents of
+ the script:
+
+ #!/bin/sh
+ ./configure CPPFLAGS="-I/usr/include/libgeotiff"
+
+ then do "chmod 755 configure.suse", and run it like this:
+
+ ./configure.suse
+
+ You'll may also see these when compiling the code:
+
+ map_tif.c: In function `my_GTIFProj4FromLatLong':
+ map_tif.c:391: warning: implicit declaration of function `CSLTokenizeStringComplex'
+ map_tif.c:391: warning: assignment makes pointer from integer without a cast
+ map_tif.c:394: warning: implicit declaration of function `CSLCount'
+ map_tif.c:396: warning: implicit declaration of function `CSLDestroy'
+ x_spider.c: In function `UDP_Server':
+ x_spider.c:1203: warning: pointer targets in passing argument 6 of `recvfrom' differ in signedness
+
+ You may safely ignore them as well.
+
+ Optional but highly recommended: Install the colorgcc package, then go
+ into /usr/share/doc/packages/colorgcc and "cp colorgccrc ~/.colorgccrc"
+ This will cause any GCC warnings or errors to show up in a different
+ color in your Xterm window. VERY handy.
+
+ Please note that the AX.25 kernel support in SuSE 10.0 doesn't work.
+ There are patches being discussed on the linux-hams list, but these
+ patches are not currently part of SuSE. Use the Serial KISS TNC
+ interface in Xastir instead if you're using a KISS TNC with this
+ version of SuSE.
+
+ Note that you may see this warning when running bootstrap.sh:
+ "warning: underquoted definition of AM_PATH_PSTOEDIT"
+ but it is totally harmless. It bothered me enough during my software
+ development that I figured out how to get rid of it, but please note
+ that the following step is totally unnecessary: Remove the "pstoedit"
+ and "pstoedit-devel" packages plus packages that depend on them, like
+ inkscape. Remove via YaST2 or by typing:
+ "rpm -e pstoedit pstoedit-devel inkscape" as root.
+
+ END OF OpenSuSE LINUX 10.0 NOTES.
+ -----------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------
+ HP/UX NOTES:
+
+ - Installed various needed packages and libraries downloaded from:
+
+ http://hpux.cs.utah.edu/
+
+ I'm not sure all of the following are needed, and, this leaves out a few
+ like ImageMagick, but here's a list of the HPUX depot files I've
+ collected:
+
+ X11R6incs-4.3.0-sd-11.11.depot
+ XR6built-6.11-sd-9.03.tar
+ autoconf-2.59-sd-11.11.depot
+ automake-1.9-sd-11.11.depot
+ bash-3.0-sd-11.00.depot
+ bison-1.875-sd-11.11.depot
+ cvs-1.11.17-sd-11.11.depot
+ db-4.2.52-sd-11.11.depot
+ flex-2.5.4a-sd-11.11.depot
+ gawk-3.1.4-sd-11.11.depot
+ lesstif-0.93.94-sd-11.11.depot
+ libiconv-1.9.2-sd-11.11.depot
+ lsof-4.72-sd-11.11.depot
+ m4-1.4.2-sd-11.11.depot
+ make-3.80-sd-11.11.depot
+ perl-5.8.5-sd-11.11.depot
+ sudo-1.6.7p5-sd-11.00.depot
+ tusc-7.7-sd-11.11.depot
+ wget-1.9.1-sd-11.11.depot
+
+ - Installed HP's version of binutils and gcc off of:
+
+ http://h21007.www2.hp.com/dspp/tech/tech_TechDocumentDetailPage_IDX/1,1701,4682,00.html
+
+ binutils_2.15a_hppa-hp-hpux11.11_depot
+ gcc_3.4.2_hppa-hp-hpux11.11_depot
+
+ HPUX 11.11 doesn't seem to have seteuid and setegid calls so:
+
+ - Installed and linked against HP's Linux libraries:
+
+ http://devrsrc1.external.hp.com/LPK/
+
+ - Changed a couple #include <strings.h> to:
+
+ #ifdef HAVE_STRING_H
+ # include <string.h>
+ #else
+ # include <strings.h>
+ #endif
+
+ - added #include <sys/modem.h> to interface.h
+
+
+ Current status: It runs, but it seg-faults when connected to an APRS(tm)
+ IS server.
+
+ END OF HP/UX NOTES.
+ -----------------------------------------------------------------------
+
+
+
+ (7) GATING WEATHER ALERTS, STATIONS, OBJECTS/ITEMS TO RF
+
+ Gating NWS Weather Alerts to RF:
+ --------------------------------
+ If you wish to gate NWS weather alerts from the Internet onto RF, you'll
+ need to create a text file in the users directory as
+ ~/.xastir/data/nws-stations.txt
+ List each NWS station that you would like to transmit via RF. Wildcards
+ are implied for lengths of 3 or greater. Here's what an example file
+ looks like:
+
+ ------------- Cut Here -------------
+ #
+ # Seattle, WA
+ SEANPW
+ #
+ # Portland, OR (any alert type)
+ PDX
+ #
+ # Pendleton, OR
+ PDTNPW
+ #
+ # Medford, OR
+ MFRNPW
+ #
+ ------------- Cut Here -------------
+
+ All text should start at the beginning of the line.
+
+ Once that file is in place, you'll need to hook up to at least one
+ Internet server that is feeding you the weather alerts. You'll also need
+ to have at least one RF interface up and running with transmit enabled on
+ that interface. Make sure that "Interfaces->Disable Transmit: All" is not
+ selected. You should now be gating NWS weather messages to RF.
+
+ Turn on igate logging and look at that log file to view what you're
+ sending out via RF. Don't forget to turn off logging or set up
+ auto-rollover of the log files, else your hard drive might fill up with
+ logging info. Auto-rollover of log files is typically accomplished via
+ CRON.
+
+ Gating Stations, Objects/Items to RF:
+ -------------------------------------
+ The latest code also allows gating packets from specific stations to RF
+ using the above method (except object/item packets). You can also gate
+ objects/items to RF by name. The same wildcarding rules apply as listed
+ above. Callsigns or object/item names listed in this file are
+ case-insensitive, so they'll match any case in received packets.
+
+ Bob Bruninga, WB4APR, recommends gating these calls to RF:
+
+ SCOUTS, SATERN, KIDS, REDCROSS, FOUR-H, YOUTH, GUARD, MARS, JOTA
+
+ See his link: "Generic Callsigns for National Events" off this web page
+ for his current list of recommended callsigns:
+
+ http://www.ew.usna.edu/~bruninga/aprs.html
+
+
+ (8) BORING LEGAL STUFF
+
+ Xastir is Copyright � by Frank Giannandrea. Xastir is
+ distributed according to the GNU General Public
+ License. There should be a copy of this license in the
+ file COPYING. If not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA
+ 02139, USA.
+
+ As of Xastir 0.4.0 all changes made by the Xastir
+ development team to the Xastir source code and any related
+ files are Copyright � 2001-2012 by The Xastir Group. The source
+ code will still be distributed according to the GNU General
+ Public License as Frank Giannandrea did in the past.
+
+ There is no warranty, implied or whatever. You use this
+ software at your own risk, no matter what purpose you put
+ it to.
+
+ You didn't pay for it, so don't expect magic.
+
+
+ (9) MAILING LIST
+
+ There are currently a couple of mailing lists about Xastir.
+ xastir at xastir.org is the one relevant for posts about
+ Xastir 0.4.0 and up (and bug fixes, and suggestions, etc).
+ You must be subscribed to the list in order to post messages.
+
+ To subscribe to the Xastir mailing list, send email to:
+ xastir-request at xastir.org In the body of the message,
+ put "subscribe xastir"; or go to
+ http://www.xastir.org and click on "User List" or
+ "Developer List" links on the left to subscribe.
+
+ ### DO NOT SEND FRANK EMAIL ABOUT XASTIR ###
+
+ Frank is no longer developing the Xastir code (although
+ he does put a word in every now and then) so don't bother
+ e-mailing him. If you have a serious problem, email the
+ Xastir mailing list and it will get to the coders.
+
+ Please, before posting to this list, see what things are
+ like, and when you do post, read over your post for
+ readability, spelling, and grammar mistakes. Obviously,
+ we're all human (or are we?) and we all make mistakes (heck,
+ look at this document! ;).
+
+ Open discussion and debate is integral to change and
+ progress. Don't flame others over mere form (grammar and
+ spelling), or even substantive issues either for that
+ matter. Please read and follow the mailing list rules.
+
+ The xastir at xastir.org mail-list is dedicated to Bug
+ reports, technical questions, your thoughts or
+ suggestions on new features being added to Xastir, things
+ that should be removed or fixed, amazing problems that even
+ stump the guru's, etc... are what we want to see here. You
+ must be subscribed to the list in order to post messages.
+
+ (10) DOCUMENTATION
+
+ We're trying to keep the documentation up to date. If you
+ feel that anything is missing here, or that anything should
+ be added etc, please email xastir at xastir.org about it,
+ thank you.
+
+ (11) OBTAINING HELP
+
+ Please read the file FAQ, and make sure you've followed any relevant
+ instructions in INSTALL. If the problem still exists, feel free to
+ ask on the Xastir mailing-list, as described above.
+
+
+ ------------------------------------------------------------------------
+APRS(tm) is a Trademark of Bob Bruninga
+
+Copyright (C) 1999 Frank Giannandrea
+Copyright (C) 2000-2012 The Xastir Group
+
diff --git a/README.CVS b/README.CVS
new file mode 100644
index 0000000..6cc6359
--- /dev/null
+++ b/README.CVS
@@ -0,0 +1,414 @@
+
+$Id: README.CVS,v 1.29 2012/11/16 03:22:40 we7u Exp $
+
+
+CVS Instructions:
+-----------------
+ For those who think CVS might be a bit too complicated to deal with,
+ here are (I think) the minimal commands. See the "SUDO" section
+ below though for ideas on how to make updating Xastir even simpler.
+
+ Initial CVS Checkout:
+ ---------------------
+ 1) Create a ".cvsrc" file in your home directory containing the
+ following lines. Use whatever Unix-type editor you're
+ comfortable with. Choices might be pico, vi, emacs, others:
+
+ ##cvs -z3
+ update -P -d
+ status -v
+ diff -u
+
+ These are just some of the CVS options that I prefer, and make some
+ things easier. They are not required.
+
+ The "cvs -z3" option isn't accepted by SourceForge currently. Comment
+ it out by adding a couple of '#' marks in front of the line. You can
+ test it at a later date by removing the '#' marks and trying a cvs
+ command.
+
+ 2) Start up a shell window of some type, perhaps an xterm or an rxvt.
+ Type the following commands into this one shell. You'll be setting
+ an environment variable which will then allow you check out the full
+ sources for the first time. After that, the environment variable
+ won't be needed anymore and all shells you use will be able to
+ work with the remote CVS repository. The checked-out sources contain
+ administration info which the CVS commands use to know which remote
+ server to talk to, and which account/encrypted password to use from
+ your ~/.cvspass file.
+
+ 3) Follow the instructions listed under "Anonymous CVS Access". Go to:
+ <http://sourceforge.net/projects/xastir/>, then click on "CVS" to
+ find the instructions.
+
+ For those that are Internet-challenged, here are the two commands,
+ customized for the Xastir project:
+
+ cvs -d:pserver:anonymous at xastir.cvs.sourceforge.net:/cvsroot/xastir login
+
+ Press the <ENTER> key when it asks you for a password. That creates
+ a ".cvspass" file in your home directory with the anonymous login
+ information inside it.
+
+ cvs -d:pserver:anonymous at xastir.cvs.sourceforge.net:/cvsroot/xastir co xastir
+
+ That creates a subdirectory called "xastir" that has all the latest
+ sources in it.
+
+ You may want to use this instead, to get the sources corresponding to the
+ latest release:
+
+ cvs -d:pserver:anonymous at xastir.cvs.sourceforge.net:/cvsroot/xastir co -r RELEASE xastir
+
+ or use this line to get the latest version deemed "stable" by the developers
+ (generally newer than the RELEASE version):
+
+ cvs -d:pserver:anonymous at xastir.cvs.sourceforge.net:/cvsroot/xastir co -r STABLE xastir
+
+ All done! You now have the latest development sources on your computer.
+ Now you can forget about all of the previous instructions unless you
+ delete the entire tree and want to start over from scratch.
+
+ Note that if you choose the "RELEASE" or "STABLE" tags, those tags will
+ become sticky, so that "cvs update" commands will update to the latest
+ versions of files containing those tags. If you wish to remove this
+ sticky option so that you can synchronize to a different tag or the latest
+ developer's CVS, see the "cvs update -A" command below.
+
+
+ CVS Commands for Maintaining the Current Development Sources:
+ -------------------------------------------------------------
+ Once all this is in place, just cd into the "xastir" directory at any
+ time, type "cvs update", then type "make install" and you'll have the
+ latest development stuff installed on your system.
+
+ Here are the commands to do if you want a clean build of the latest
+ sources, and want configure to recheck all the libraries and header
+ files that Xastir needs:
+
+ cd xastir
+ cvs update (snag all the latest changes)
+ ./bootstrap.sh
+ ./configure
+ (make clean;make -j3 2>&1) | tee make.log
+ su
+ make install (make install-strip can be used after the first time,
+ it removes debugging info from executable)
+ chmod 4555 /usr/local/bin/xastir (only needed if using kernel AX.25)
+ exit (from root)
+ xastir
+
+ Note that you'll need autoconf 2.53 or newer and automake 1.6.3 or newer
+ in order to run the "./bootstrap.sh" script.
+
+ For the "cvs update" line, you can also choose which version to update to,
+ just like the "cvs co" lines shown above:
+
+ cvs update -r RELEASE
+ or
+ cvs update -r STABLE
+
+ Once you specify a revision tag (RELEASE or STABLE), that option becomes
+ "sticky" for future checkouts and updates. That means you only need to
+ type "cvs update" in order to update your code to the latest sources
+ containing that tag.
+
+ cvs update -A
+
+ will make the cvs update command track to the most recently submitted
+ versions again (will make the RELEASE or STABLE options un-sticky). To
+ review:
+
+ cvs update -A # To get to developers sources.
+ cvs update -r STABLE # To get to latest stable sources.
+ cvs update -r RELEASE # To get to latest released sources.
+
+
+ Even more CVS commands (most people won't need these):
+ ------------------------------------------------------
+ I use these aliases the most (defined in my bash shell startup files):
+
+ alias cvsdiff='cvs diff -w -r HEAD'
+ alias cvsstat2='cvs -n -q update'
+ alias cvsstat3='(cvs status 2>&1) | grep -E "Status: | Examining" | grep -v Up-to-date | grep -v Makefile.in'
+
+ to see if anything has changed. cvsstat3 is the most useful one
+ for me as a developer. If anything has, I can use this alias to
+ see the details on a particular file:
+
+ alias cvsdiff='cvs diff -w -r HEAD'
+
+ As in:
+
+ cvsdiff main.c
+
+ -or- (not using the alias)
+
+ cvs diff -w -r HEAD main.c
+
+ Then perhaps do an update on that file alone:
+
+ cvs update main.c
+
+
+ Checking out a branch (for anonymous-CVS users):
+ ------------------------------------------------
+
+ Go to a new directory structure (not CVS controlled) and type this:
+
+ export CVS_RSH=ssh
+ mkdir <branchname>
+ cd <branchname>
+ cvs -d:pserver:anonymous at xastir.cvs.sourceforge.net:/cvsroot/xastir login
+
+ Press the <ENTER> key when it asks for your password, then:
+
+ cvs -d:pserver:anonymous at xastir.cvs.sourceforge.net:/cvsroot/xastir co -r BRANCH_<branchname> xastir
+
+ The above command will create a directory "xastir" in the <branchname>
+ directory containing the latest sources from that branch.
+
+ A complete example (Using an imaginary branch "xastir99"):
+
+ export CVS_RSH=ssh
+ cd ~/src
+ mkdir xastir99
+ cd xastir99
+ cvs -d:pserver:anonymous at xastir.cvs.sourceforge.net:/cvsroot/xastir login
+ Hit <ENTER> when asked for passwd.
+ cvs -d:pserver:anonymous at xastir.cvs.sourceforge.net:/cvsroot/xastir co -r BRANCH_xastir99 xastir
+
+ will fetch the BRANCH_xastir99 code branch and deposit it into:
+
+ /home/<user>/src/xastir99/xastir/
+
+
+ There are many more CVS commands and options. Many of them are more of
+ use to the developers. Some of those are listed below. The above should
+ be enough for most people to keep their copies in sync with the latest CVS
+ development sources.
+
+
+SUDO Instructions:
+------------------
+
+ "sudo" is a command that can make your life much simpler. After you set
+ it up that is! By adding a couple of lines to your /etc/sudoers file
+ (using the "visudo" command to edit this file), you'll be able to run a few
+ commands as root without having to type the root password each time.
+ Another thing you can do at that point is automate the entire
+ "cvs update;./configure;su;make install" process via a script. Here's how
+ to set all of this up:
+
+ Type "su" to become the root user, then type "visudo". This will bring up
+ the "vi" editor on the /etc/sudoers file. If you'd like to learn more
+ about what I'm going to describe, type "man sudoers" in another window and
+ read about this file. Another man-page that is useful here is the "man
+ sudo" page.
+
+ Back to the editing: There's a section in there for user alias. Mine is
+ labeled "# User alias specification". Add a line there that reads like
+ this:
+
+ User_Alias XASTIR = username1, username2, username3
+
+ where username1, etc, are valid usernames that you wish to be able to do
+ Xastir installs. For instance you might have:
+
+ User_Alias XASTIR = mikey
+
+ Next, add a line near the bottom that reads like this:
+
+ XASTIR ALL = NOPASSWD: /bin/chmod, /usr/bin/make
+
+ Now write out and close the file. At this point the "mikey" user will have
+ root permissions when he/she runs the commands "/bin/chmod" or
+ "/usr/bin/make". Make sure the paths to those programs are correct for
+ your system.
+
+ Exit from "su" so that you're a regular (non-root) user again.
+
+ Now, in the "xastir" source directory (mine is in "~/src/xastir"), create a
+ script that reads like this. I named my script "update-xastir" but nearly
+ any name for the script will do:
+
+ -----------------cut here--------------------
+ #! /bin/sh
+
+ cvs update
+ ./bootstrap.sh
+ ./configure
+ sudo make clean
+ sudo make install
+ sudo chmod 4755 /usr/local/bin/xastir
+ -----------------cut here--------------------
+
+ Now type "chmod u+rwx update-xastir" to make that script executable.
+
+ Actually, we've just created a script for Xastir that implements the above
+ and called it "update-xastir". Do a "cvs update" to get it.
+
+ Try out the script. Type:
+
+ ./update-xastir
+
+ It should run through the entire update/configure/make/install process for
+ Xastir. Remember to either change to the proper xastir directory before
+ running it, or add a "cd" command at the beginning of the script so that it
+ will run in the proper directory in all cases. If you add the proper "cd"
+ command you can copy the script to /usr/local/bin and then run it as
+ "update-xastir" from anywhere.
+
+ Windows users: You may need to remove the "sudo" keyword on each line to
+ have it work properly for you.
+
+ A note from Gerry Creager as to another way to set up the sudoers file:
+
+ "I now consider it a good idea to add the "gifted" users to the 'wheel'
+ group and then solely enable wheel in /etc/sudoers; I've seen a recent
+ article also supporting this."
+
+
+Developer's CVS Instructions:
+-----------------------------
+
+ Read this doc first. Why did they have to put spaces in the URL???:
+
+ http://sourceforge.net/apps/trac/sourceforge/wiki/CVS%20client%20instructions
+
+ For branching/merging, read these as well:
+
+ http://www.drdobbs.com/programmers-toolchest/184404280 # Recommended by Tom Russo
+ http://ioctl.org/unix/cvs/branches/
+ http://www.astro.princeton.edu/~rhl/cvs-branches.html
+ http://users.csc.calpoly.edu/~jdalbey/205/Resources/cvsBranchMerge.html
+
+
+ A suggested organization (directory names), to keep branches separate from trunk:
+
+ /home/<user>/src/xastir/head/ # Trunk (or HEAD), mainline development
+ /home/<user>/src/xastir/branchname1/ # branchname1 development
+ /home/<user>/src/xastir/branchname2/ # branchname2 development
+
+
+ Checking out HEAD (Also known as "trunk", default, or main branch):
+ -------------------------------------------------------------------
+
+ These commands will create a directory "xastir" in your current directory which
+ contains the latest Xastir sources from the "trunk" branch. Replace "<devel>"
+ with your Sourceforge developer's login name. To keep the trunk code from
+ getting confused with any branches, consider putting it into a subdirectory
+ labeled "trunk" or "head", something like "/home/<user>/src/xastir/head/".
+ These commands will create just such a directory and populate it with the
+ latest development sources (HEAD branch):
+
+ export CVS_RSH=ssh
+ cd ~src/xastir
+ mkdir head
+ cd head
+ cvs -z3 -d:ext:<devel>@xastir.cvs.sourceforge.net:/cvsroot/xastir co xastir
+
+
+ Checking out a branch:
+ ----------------------
+
+ To check out a branch to a fresh directory:
+
+ cd ~/src/xastir
+ mkdir <my_branchdir> # /home/<user>/src/xastir/<my_branchdir>/
+ cd <my_branchdir>
+ cvs -z3 -d:ext:<devel>@xastir.cvs.sourceforge.net:/cvsroot/xastir co -r BRANCH_<branchname> xastir
+
+ Replace "<devel>" above with your Sourceforge developer's login name, and
+ "<branchname>" with the name of the branch you wish to check out. "my_branchdir" can
+ be any directory name you like, but naming it the same as <branchname> may be less
+ confusing.
+
+ The above command will create a directory "xastir" under <my_branchdir> containing
+ the sources from the branch you specified. The selected branch will remain "sticky"
+ in your checked-out working directory unless/until you override it via additional CVS
+ commands. Any cvs commits done there will commit to the new branch instead of the
+ trunk. Commits done to a working copy of "trunk" won't appear on your new branch.
+ Pay attention to your directory structure from that point on, whether you're working
+ on a checked-out copy of a branch or a checked-out copy of the trunk, and commit
+ responsibly.
+
+ With the fictitional "xastir99" branch we used before, example commands would be:
+
+ cd ~/src/xastir
+ mkdir xastir99 # /home/<user>/src/xastir/xastir99/
+ cd xastir99
+ cvs -z3 -d:ext:<devel>@xastir.cvs.sourceforge.net:/cvsroot/xastir co -r BRANCH_xastir99 xastir
+
+ NOTE: The trunk has version numbers like "dd.dd", while branches have version numbers
+ like "dd.dd.dd.dd".
+
+ You can run the "cvs status <filename>" command and look at the "Sticky Tag" near the
+ top of the listing to see which branch you're working with:
+
+ cvs status README.CVS | head -15
+
+
+ Creating a branch:
+ ------------------
+
+ NOTE: This is a special operation. Do _not_ attempt unless you are familiar with
+ CVS tagging, branches, and merging. We plan to do development on the trunk for
+ the mainline (trunk) code and use branches only for a few special development bits:
+ Experimental code that we're not sure will make it to production, or porting to
+ a new widget set for instance... Something that might lead to a dead-end, a major
+ refactor, or any code that might not see the light of day for some time.
+
+ NOTE: We've adopted the convention that all branch tags begin with
+ "TAG_BRANCH_" and all branches begin with "BRANCH_". This makes it easy
+ to see where branches diverge or merge back with "trunk" and to determine
+ which tags are related to branching/merging.
+
+ In a checked-out CVS copy of Xastir, make sure your working copy is up-to-date
+ ("cvs -nq update") if you wish all current development changes to this point to
+ make it to the new branch you're creating:
+
+ cvs update
+
+ Then:
+
+ # Create a tag called "TAG_BRANCH_<branchname>"
+ cvs rtag TAG_BRANCH_<branchname> xastir
+
+ # Create branch "BRANCH_<branchname>" starting at the tag you created above
+ cvs rtag -b -r TAG_BRANCH_<branchname> BRANCH_<branchname> xastir
+
+ Replace "branchname" with a name of your choosing. For instance to create
+ a branch called "xastir99":
+
+ cvs rtag TAG_BRANCH_xastir99 xastir
+ cvs rtag -b -r TAG_BRANCH_xastir99 BRANCH_xastir99 xastir
+
+ Follow the "Checking out a branch" section above to create a NEW directory area to
+ work on the new branch. It's important to keep your directories separate, because
+ commits made on a branch will apply only to that branch; Commits made to trunk
+ will apply only to the trunk.
+
+
+ Listing the tags on a file:
+ ---------------------------
+
+ cvs log -t README.CVS
+
+
+ Merging between trunk and a branch:
+ -----------------------------------
+ TBD.
+
+ A note from Tom regarding merges: Use the "-kk" option on all merges, otherwise every
+ file that has "$Revision: 1.29 $" or "$Date: 2012/11/16 03:22:40 $" in it will get
+ flagged as a change -- possibly even a conflict -- even if that's the only difference
+ between branch and head. "-kk" on a cvs update doesn't do substitution on those tags,
+ and so only files with real changes will get updated.
+
+
+
+ ------------------------------------------------------------------------
+Copyright (C) 1999 Frank Giannandrea
+Copyright (C) 2000-2012 The Xastir Group
+
diff --git a/README.CYGWIN b/README.CYGWIN
new file mode 100644
index 0000000..893a499
--- /dev/null
+++ b/README.CYGWIN
@@ -0,0 +1,857 @@
+
+$Id: README.CYGWIN,v 1.2 2012/11/01 18:57:18 we7u Exp $
+
+
+---------------------------------------------------------------------
+Note that there are other options to get Xastir running on Win32.
+The method described below in this document is for getting Xastir
+running under Cygwin which can be problematic. Other methods exist
+on the Xastir Wiki pages which are typically easier and more robust:
+
+ http://www.xastir.org/wiki/index.php/Installation_Notes
+---------------------------------------------------------------------
+
+ In the past, two companies have created simpler installs of
+ Cygwin/Xastir than described in this document. Contact one of
+ these folks for more info. Remember to replace the "at" below
+ with the "@" symbol to arrive at the correct e-mail addresses.
+ We have to do that to prevent large amounts of spam from going to
+ addresses harvested from web pages:
+
+
+ Lintronix:
+ Internet install of Xastir available for free, CD-ROM available
+ for a nominal fee. Everything needed to install Cygwin/Xastir
+ online (Internet install) or off-line (CD-ROM). Walks you
+ through an automated install:
+
+ http://www.lintronix.com/winxastir/
+ E-mail: winxastir at lintronix.com
+
+
+ Inuit Nunaani Wireless Inc:
+ CD-ROM available for a nominal fee. Everything needed to
+ install Cygwin/Xastir off-line. Walks you through an
+ automated install. This install is verified to work on WinXP
+ and Win98 (known _not_ to work on Win95/WinME). Contact:
+
+ E-mail: Tom Tessier <ttessier at trtdigital.ca>
+
+
+
+------------------------------------
+Installing Xastir on Windows/Cygwin:
+------------------------------------
+
+These directions assume that you installed Cygwin after the new version
+was released in January of 2010. If you had Cygwin installed before
+then, it is simpler to delete the Cygwin directory and the Start Menu
+entries than to upgrade your existing install to the new version.
+
+System Requirements:
+
+CPU: at least 1Ghz
+Memory: at least 512Meg with at least 1Gig of swap space
+OS: Windows 2000 or later
+Time: At least 6 hours if not using the get-maptools.sh script
+ 24 to 48 hours if using the script
+
+
+Please Note: It's beneficial to actually log in to your Windows
+computer rather than skipping that step of the Windows login process
+(Don't hit escape just to get rid of the dialog!). If you log into
+Windows properly, Cygwin will be able to figure out where to put your
+home directory. If you don't do this, you'll be referred to as
+"unknown" and you won't have a home directory in Cygwin. This means
+there won't be a good place to put your Xastir startup files. Of
+course, log in as the same user each time in order for Cygwin to use
+the proper home directory for you.
+
+CAN'T REPLACE FILES: Every once in a while Windows will refuse to
+allow you to delete/rename one of the files. The only way I've
+found to get around this problem is to reboot. Also, Windows
+typically won't allow you to replace a file that Windows currently
+has open. If you're going to be recompiling/reinstalling Xastir, or
+updating Cygwin, make sure that these applications are shut down
+before doing so. You can get VERY strange results if only some
+files get updated.
+
+SPACES IN USERNAMES: Cygwin specifically, and Unix boxes in
+general, don't much like spaces in filenames, directories, or login
+names. Any of these may cause you headaches while playing with
+Cygwin. Create a new login that doesn't have spaces and log in as
+that user before installing Cygwin, and whenever you intend to run
+Cygwin/Xastir. It's very likely that Xastir won't work for you if
+you use a login that has spaces embedded in it. For additional
+info, see this link:
+
+ http://cygwin.com/faq/faq_2.html#SEC17
+
+Explanation of this login box for those that don't see it: If you
+have the option of running networking, you'll have a login box show
+up when you first start up Windows. It'll ask for you user name and
+password, then let you in. If you escape out of that dialog, Windows
+may start right up but networking will be disabled.
+
+If you don't see that box, there are two options that I know about,
+either you or someone else set it up to auto-login with your user/
+password combo, or you don't have networking installed at all.
+
+The following steps direct you through installing Cygwin, Xastir, and
+a few optional map libraries that Xastir can use. Note that in most
+of the places below where the directions state to type commands, this
+must be done from within a Cygwin BASH shell, not a DOS window.
+Where you are asked to edit files, it's best to use Wordpad instead
+of Notepad, as Notepad doesn't do nice things to Unix-format files.
+
+Cygwin now allows you to have Xwindows apps and Windows apps all on
+the screen and visible at the same time! The instructions here set
+it up in that manner, so you can have Xastir as just another app on
+your Windows desktop.
+
+Please subscribe to the "xastir" mailing list at
+"http://www.xastir.org". There are lots of helpful people there
+that can aid you in installing/running Xastir. You must be subscribed
+in order to post messages there.
+
+
+[ ] Step 1) Install Cygwin, a free download.
+
+
+[ ] Step 1a) Go to http://www.cygwin.com with your web browser.
+Look for the black and green Cygwin icon, then click on "Install
+now!".
+
+This will load the Cygwin network installer program onto your
+computer. Remember where you decide to put this program. I put
+mine in "c:\<login>\cygwin\setup.exe", (for instance
+"c:\hacker\cygwin\setup.exe"). This program will allow you to do a
+network install of Cygwin. After you install Cygwin (see the steps
+below for details) you'll have a package directory (in my case
+"c:\hacker\cygwin\") and a Cygwin directory (in my case
+"c:\cygwin"). The un-installed packages go into the package
+directory as they are downloaded from the 'net.
+
+It will be beneficial to re-run the Cygwin network installer from
+time to time in order to keep Cygwin up to date. Each time you run
+it you'll update any packages that have been changed since you last
+ran it.
+
+[ ] Step 1b) Find the "setup.exe" program and execute it either by:
+
+ a) Clicking on it with File Explorer, or
+ b) Start->Run->path to executable, or
+ c) Opening a DOS window and typing the name.
+
+This will start installing Cygwin over the network. Answers to
+provide to the program:
+
+ Install from Internet (*)
+ "C:\cygwin"
+ Install For All Users
+ Default Text File Type Unix (*)
+ Local Package Directory "C:\hacker\cygwin"
+ Select Your Internet Connection (choose one)
+ Choose A Download Site (choose one nearby if you can determine that)
+
+Note: Responses above listed with a "(*)" are required. Others are
+up to the individual user to answer as they wish. You'll get to a
+"Progress" page where "setup.bz2" is downloaded from the 'net. If
+it hangs at this step, you may wish to "Cancel" and try another
+server until you obtain this file and are presented with a list of
+packages to install.
+
+
+[ ] Step 1c) Select Packages: Leave the packages selected that
+were selected by default, plus select the additional packages listed
+below. Note that enabling some of these packages causes others to
+be selected as well, that's OK and necessary.
+
+[ ] Press the "View" button until it says "Full" next to it. All
+packages are now in alphanumeric sorted order.
+
+Selecting a package involves clicking on the little circle symbol
+until the option you want is displayed. You can choose older
+versions of a package, choose to keep the package you have installed
+already, or choose to remove or install a package in this manner.
+If you're running Cygwin install again and see "Keep" as an option,
+that means you've already installed that package. We're only
+concerned with the "bin" packages here (stands for "binary") and not
+the "src" packages (source code).
+
+It's suggested that you keep whatever was selected by default, and
+just add the below packages to the selection. As you select
+packages, other packages may be selected for you that are also
+required:
+
+[ ] autoconf
+[ ] automake
+[ ] binutils
+[ ] bzip2
+[ ] curl
+[ ] cvs
+[ ] db4.x (pick the highest number listed for x)
+[ ] diffutils
+[ ] font-adobe-* (pick all of them)
+[ ] font-bitstream-* (pick all of them)
+[ ] font-util
+[ ] font-xfree86-type1
+[ ] gcc4
+
+[ ] gcc4-fortran (if you are going to use the get-maptools script)
+[ ] gcc4-objc (if you are going to use the get-maptools script)
+
+[ ] GraphicsMagick
+[ ] gv
+[ ] gzip
+[ ] jasper
+[ ] jbigkit
+[ ] lcms
+[ ] less
+[ ] lesstif
+[ ] libbz2-devel
+[ ] libcurl-devel
+[ ] libjasper-devel
+[ ] liblcms-devel
+[ ] libdb4.x (pick the same x as db2.x above)
+[ ] libdb4.x-devel (pick the same x as db2.x above)
+[ ] libfontconfig-devel
+
+[ ] libgeotiff (if you are NOT going to use the get-maptools script)
+[ ] libgeotiff-devel (if you are NOT going to use the get-maptools script)
+[ ] libgeotiff1 (if you are NOT going to use the get-maptools script)
+
+[ ] libGraphicsMagick-devel
+[ ] libGraphicsMagick3
+[ ] libjbig-devel
+[ ] libpcrecpp-devel
+[ ] libpng*-devel (pick the number that matches the already selected libpng* library)
+
+[ ] libproj-devel (if you are NOT going to use the get-maptools script)
+[ ] libproj1 (if you are NOT going to use the get-maptools script)
+
+[ ] libtiff-devel
+[ ] libtool
+[ ] libwmf-devel
+[ ] libX11-devel
+[ ] libXext-devel
+[ ] libXm-devel
+[ ] libxml2-devel
+[ ] m4
+[ ] make
+[ ] nano (a windows-style text editor, optional)
+[ ] patch
+[ ] pcre
+[ ] perl
+
+[ ] proj (if you are NOT going to use the get-maptools script)
+
+[ ] python
+[ ] rcs
+[ ] tcltk
+[ ] tiff
+[ ] unzip
+[ ] vim (a Unix-style text editor, optional)
+[ ] wget (Optional: Can use libcurl instead)
+[ ] X-start-menu-icons (may take a minute to respond because it turns on many others)
+[ ] xextproto
+
+[ ] zip
+
+Clicking on the small circle with the two arrows will run you
+through the various select/de-select options for each package.
+
+
+[ ] Step 1d) Click Next and the packages will get downloaded and
+installed. Repeat the above if you have network difficulties, until
+the install succeeds completely.
+
+Some servers fail to download some files and require the user to
+press enter between downloads when it fails on these files. If this
+happens, back up and select another server.
+
+
+[ ] Step 1e) At the end of the install it'll ask you if you wish to
+create desktop icons and menu entries. Definitely select these! It
+doesn't mean that Cygwin will start automatically each time you
+reboot your computer or login (it doesn't start automatically). It
+_does_ mean that you'll have an icon to click on manually to get
+things going.
+
+This will create a Black/Green Cygwin icon on the desktop and a menu
+entry so that you can start Cygwin through the menu system as well.
+
+[ ] Step 1f) Click "Finish". Cygwin is now installed. One more
+pop-up informs you Cygwin has been installed. Sometimes this last
+dialog gets hidden behind other windows, and it does seem to need OK
+clicked to complete the installation. Click the OK button on that
+last dialog to _really_ complete the installation.
+
+The Black/Green Cygwin icon will start up a BASH window, without
+starting up Xwindows. Think of it as being similar to a DOS window,
+but with a lot more power. It understands Unix commands though, not
+DOS commands.
+
+[ ] Note: I've had the Cygwin network install fail before during
+the downloading stage without informing me in any recognizable
+manner. You might which to re-do step 1 to make sure nothing
+further gets downloaded/installed. Once you get to that point, Step
+1 is complete.
+
+[ ] Step 2) Reboot. Yes, I know that "modern Windows" doesn't always
+require this but you just installed a lot of stuff including a DLL.
+
+[ ] Step 3) (optional) Create shortcut for starting X:
+
+Click on START / Programs (or All Programs) / Cywgin-X
+
+Right-click on XWin-Server and then click on Send-to / Desktop
+(create Shortcut) to copy that Start Menu entry to a icon
+on your Desktop
+
+[ ] Step 4) Test Cygwin and create startup shortcuts:
+
+Double-click on the shortcut you just made. You should get a shell
+window that looks very much like a DOS window. It's a BASH shell
+window and understands Unix commands instead of DOS commands.
+
+You should see an 'X' in your system tray. That's the
+X-server running.
+
+Once you've gotten to this stage, you now have Cygwin and Xwindows
+installed and operational. Next we go after Xastir itself.
+
+[ ] Step 5) Create a file at C:\cygwin\home\<user>\ called
+".cvsrc", where the "<user>" part is your Windows login name. Don't
+forget the leading period in the filename as it's important. For
+instance, I created a file: "C:\cygwin\home\hacker\.cvsrc". The
+file should contain the following lines:
+
+ cvs -z3
+ update -P -d
+ status -v
+ diff -u
+
+The '#' marks comment out the first line. "cvs -z3" invokes
+compression, and the SourceForge site isn't performing compression
+currently.
+
+PLEASE NOTE: this file must be created in Unix format, not DOS
+format. DO NOT USE Notepad or other Windows tools to create the
+file, as CVS will not recognize the contents. Thanks to Kirk
+Mefford <kc2elo at softhome.net> for noticing this. The editor "nano"
+can be invoked from a Cygwin window to create this file, or for
+those of you who know "vi" or have Windows editors available that
+can save in Unix format, use those. If you don't, the "cvs update"
+commands won't work for you, at least until you recreate the file in
+Unix format. You've been warned!
+
+The "." in ".cvsrc" makes it a Unix hidden file, and it won't appear
+in most Unix listings. Unix files don't need a file extension, so
+don't create a file that has one (or else rename it to ".cvsrc" when
+done).
+
+Another option is to create the file using a Windows editor, then
+run a dos2unix program on it to convert it to the proper format.
+
+
+[ ] Step 5) Download Xastir sources. Start up Xwindows using your
+shortcut. Type the six lines below into the shell exactly as shown.
+Hit <ENTER> when asked for a password after typing line four (the
+"login" command):
+
+ cd ~
+ touch .cvspass
+ mkdir src
+ cd src
+ cvs -d:pserver:anonymous at xastir.cvs.sourceforge.net:/cvsroot/xastir login
+ cvs -d:pserver:anonymous at xastir.cvs.sourceforge.net:/cvsroot/xastir co xastir
+
+NOTE: The "login" command must complete without errors in order to
+create a dummy blank password in your .cvspass file. Without this
+password you'll have trouble with later CVS commands. If you see
+"EOF", "connection reset by peer", "connection refused", or "timed
+out", it means that the anonymous CVS server at SourceForge is
+overloaded (too many users). Keep trying the failed commands until
+they succeed! Notice that up-arrow (on the keyboard) and then
+<ENTER> will repeat the last command, saving you some typing.
+
+The end result when it succeeds will be a new directory
+"C:\cygwin\home\<user>\src\xastir\" which contains all of the Xastir
+source code. You can type "ls xastir" (that's lower-case LS) to see
+the file listing.
+
+Side Note: Here's the coolest thing about CVS: Once you've done
+this initial source-code download, you'll never have to do the whole
+Xastir download again. You'll just go into the "src/xastir"
+directory and type "cvs update", which will snag just the _changes_
+to the files since you last updated, and is very fast. Compile and
+install at that point and you'll be running the latest developer's
+version in just a few minutes! It's very easy to keep up with the
+developers this way.
+
+
+[ ] Step 6) Configure/compile/install Xastir. Type these commands
+into the BASH shell, waiting until each one completes before typing
+the next command:
+
+ cd ~/src/xastir
+ ./bootstrap.sh
+ ./configure
+ make
+ make install
+
+NOTE: You'll probably want to run the configure step from an xterm
+window with the X11 server running of course. If you do this from a
+non-X11 window then the configure test for "gv" will fail, as "gv"
+requires an X11 server even when asking it for it's version number.
+Without "gv" support you won't be able to print from Xastir.
+
+NOTE: The "make" step can be extremely memory hungry. If you don't
+have much free memory, that step might take a long time to run. One
+Win2k machine with only 20MB of free RAM (128MB total RAM) couldn't
+complete this step, but adding another 128MB of RAM to that machine
+caused it to succeed. Another machine running Win2k with 64MB free
+(128MB total RAM) took six hours (but keep reading!). Free up
+memory if you're having trouble completing that step. This behavior
+is only seen on Windows/Cygwin, not on the Unix-based systems. On a
+typical Linux box that step takes under two seconds. Hopefully
+Cygwin linking will improve over time to alleviate this issue.
+We've added a new link-stage parameter to reduce the memory usage
+for that step, but it doesn't totally resolve the problem. The
+machine that took six hours originally now takes 60 seconds to
+complete that step.
+
+Ignore the "PACKAGE_* redefined" warnings. They won't break
+anything and are just an annoyance.
+
+Once you get through the above commands, Xastir is compiled and
+installed on your system, with minimal map support. Later sections
+of this document detail adding additional map libraries in order to
+give you access to the full mapping capability of Xastir.
+
+NOTE: If you get the below errors during the compile it means that
+Cygwin has changed one of their packages to be incompatible with the
+rest (and needs to change a lot more of their packages to
+correspond). It also means that you probably had Cygwin installed
+previous to January 2010 and upgraded rather than replaced your
+installation.
+
+---------------------------------------------------------------------
+/usr/include/Xm/Print.h:28:34: X11/extensions/Print.h: No such file or directory
+In file included from /usr/include/Xm/XmAll.h:79,
+ from alert.c:308:
+/usr/include/Xm/Print.h:40: error: parse error before "XPContext"
+/usr/include/Xm/Print.h:43: error: parse error before '}' token
+/usr/include/Xm/Print.h:61: error: parse error before "XPFinishProc"
+make[3]: *** [alert.o] Error 1
+---------------------------------------------------------------------
+A temporary fix for the above errors (until Cygwin gets their act
+together) is to do the following:
+---------------------------------------------------------------------
+ Launch the Cygwin setup program
+ When you get to the list of packages change the list to FULL mode
+ Uncheck "Hide Obsolete Packages"
+ Scroll down the list until you find xorg-x11-devel
+ Click on the word "keep" until it changes to a 6.x version of the file
+ Click Next and finish the setup
+ Unfortunately you'll have to perform the same fix each time you
+ use the Cygwin setup program or it will "upgrade" to the
+ broken package again.
+---------------------------------------------------------------------
+
+[ ] Step 8) Actually run the darn thing:
+
+Let's start from scratch to make sure it all works. Close any
+Cygwin/BASH windows you may have.
+
+Click on the shortcut you created to start Xwindows.
+
+From the resulting BASH window, type "LANG=C xastir &". Xastir should
+start up shortly.
+
+Note: Xastir has support for PocketAPRS, DosAPRS, WinAPRS, MacAPRS
+and GNIS maps by default. For additional types of maps, you'll need
+to install some libraries, then recompile Xastir so that it knows to
+use them. See the instructions below.
+
+The README.MAPS file has instructions for where to get maps and where
+to put them under the Xastir hierarchy.
+
+If you have any WinAPRS, DosAPRS, or PocketAPRS maps, now is a good
+time to place them in the /cygwin/usr/local/share/xastir/maps folder
+(or a subdirectory of it). You can also use "*.geo" files and the
+associated image files with Xastir. You may place them in this
+directory (or a subdirectory of it) as well, though most of the .geo
+files won't work for you until you install the ImageMagick library.
+
+What Xastir paths look like from within Windows (in case you're
+moving maps around with Explorer): Just prefix them all with
+"cygwin/". For instance, maps go into
+/cygwin/usr/local/share/xastir/maps instead of
+/usr/local/share/xastir/maps. Xastir will continue to see them as
+"/usr/local/share/xastir/maps" though from inside Cygwin. It kind
+of looks like a miniature Unix box from inside Cygwin.
+
+Run Windows in 15-bit color or better (32768 colors or more) or
+you'll get lots of warnings about Xastir not being able to allocate
+colors when it starts up, and the display will be rather stark
+looking.
+
+To set a new language or change the language current choice, use
+this command line instead from inside an Xterm:
+
+ xastir -l <language>
+
+Current choices are:
+
+ Dutch English French German Italian Portuguese Spanish
+ ElmerFudd MuppetsChef OldeEnglish PigLatin PirateEnglish
+
+This option will be stored in the users config file for the next
+time Xastir is run. On new installs Xastir will default to English
+until you use this command line option once.
+
+Another difference with Cygwin as opposed to Unix-like operating
+systems: You can't do the make install portion if Xastir is up and
+running. You have to kill Xastir first before you do "make install"
+or "make install-strip". Otherwise the newly compiled Xastir won't
+replace the old one.
+
+Note that one user running Cygwin on XP had it crash every time his
+screen-saver kicked in. Disabling the screen-server fixed that
+problem.
+
+Another interesting "feature" of Cygwin/Xwindows is that some of the
+modifier keys like ScrollLock/CapsLock/NumLock must be pressed while
+that X-window is the active foreground window. If not, the event
+can be missed, and Xwindows can get out of sync with the actual
+state of the key. This doesn't appear to be an Xastir-specific
+problem, but a Cygwin/Xwindow problem. With just a BASH shell under
+Cygwin (not involving Xwindows), the problem doesn't appear to
+happen. Just inside Xwindows on Cygwin.
+
+Some users have experienced problems with their Windows box running
+the NTFS "convert.exe" program instead of the ImageMagick
+"convert.exe" program, usually when enabling snapshots in Xastir.
+If you experience this, check your path settings and make sure that
+ImageMagick's path is first.
+
+When specifying serial ports to use with Xastir,
+
+ "COM1" is called "/dev/ttyS0" in Cygwin (and Linux)
+ "COM2" is called "/dev/ttyS1" in Cygwin (and Linux)
+
+Note the capital 'S'.
+
+
+[ ] Step 9) Document & Back Up the Configuration
+
+One user had a problem where after Cygwin/Xastir was installed, he
+installed another program, in this case Java, and it wiped out some
+of the environment variables that Cygwin set. $HOME was one
+variable that got changed.
+
+To guard against such changes, go to My Computer and right-click on
+properties. Write down the Advanced System Variables and keep the
+note in a safe place.
+
+
+Optional
+
+
+Please see the INSTALL file and the Help menu in Xastir itself
+for additional information not mentioned in this document.
+
+Additional info can be found on the cygwin web-site:
+
+ http://www.cygwin.com
+
+or the Cygwin/XFree86 web-site:
+
+ http://cygwin.com/xfree/
+
+
+[ ] Step 10) Keeping up-to-date:
+
+Once a week or once a month, run the Cygwin network installer
+program (step 1b above). After it finishes, open a Cygwin window
+and type these commands to update the Xastir source code:
+
+ cd ~/src/xastir
+ cvs update
+
+If you see "EOF" or "connection reset by peer" it means that the
+anonymous CVS server at SourceForge is overloaded (too many users).
+Keep trying the failed commands until they succeed! Notice that
+up-arrow (on the keyboard) and then <ENTER> will repeat the last
+command, saving you some typing.
+
+Every once in a while Windows will refuse to allow you to
+delete/rename one of the files. The only way I've found to get
+around this problem is to reboot. I sometimes see this when trying
+to do a CVS update, and Windows won't allow one or more files to get
+updated.
+
+Repeat step 6) above to recompile/reinstall the latest Xastir.
+
+A very good option is to read the SUDO instructions in the
+README.CVS file, setting up the /etc/sudoers file and creating an
+update-xastir script as shown. Then you can type "./update-xastir"
+at any time to snag down the latest Xastir changes, compile, and
+install it. We've just included an update-xastir script with
+Xastir, so you don't have to create it anymore. You may however
+need to remove the "sudo" keyword from each line for it to work
+properly on Cygwin.
+
+
+-----
+
+-------------------------------------------
+OPTIONAL: ADDING ADDITIONAL MAP LIBRARIES:
+-------------------------------------------
+
+These additional Xastir libraries have been tested on Cygwin:
+
+ ImageMagick
+ Shapelib
+ libtiff
+ libproj
+ libgeotiff
+ Festival
+ GDAL/OGR (broken as of January 2010 - kd7myc)
+
+Anyone testing additional libraries is encouraged to share their
+findings on the Xastir mailing lists (you must be subscribed in
+order to post messages there). The libraries which have _not_ been
+made to work yet on Cygwin are:
+
+ AX25
+ GPSMan/gpsmanshp
+
+The AX25 libraries will probably never work, as they are for Linux
+only. GPSMan/gpsmanshp may work on Cygwin at some point if enough
+work is done to figure out and document the process.
+
+
+RECOMMENDED: Adding maptools:
+------------------------------------------------------------
+
+*******************************NOTE**************************************
+As of 10 November 2006, xastir's source tree contains a copy of shapelib
+1.2.10, and automatically builds shapelib if you don't have it installed.
+************************************************************************
+
+
+[ ] From a BASH shell, type:
+
+ cd ~/src/xastir/scripts
+ ./get-maptools.sh
+ come back in six to 48 hours
+
+The last thing the script tries to do is compile GDAL. This is currently
+broken. Don't worry. The rest should have been installed just fine.
+
+[ ] Now you should be ready to configure and compile Xastir with
+Shapelib support. Type these commands:
+
+ cd ~/src/xastir
+ cvs update
+ ./bootstrap.sh
+ ./configure
+ make
+ make install
+
+
+See the README.MAPS file for where to get the maps.
+
+
+OPTIONAL: Install Festival support:
+------------------------------------
+Allows using a synthesized voice from within Xastir for alerts,
+reading messages to you, and other cool things. Tom Russo did the
+initial work on this, Henk de Groot optimized it:
+
+1) Start BASH shell in Cygwin
+
+2) Make ~/festival download directory and
+ /usr/local/festival installation directory
+
+3) Download festival components from festvox.org into ~/festival, in
+ the Windows environment the corresponding path is:
+
+ C:\Cygwin\home\%USERNAME%\festival
+
+ get the following files:
+
+ speech_tools-1.2.95-beta.tar.gz
+ festival-1.95-beta.tar.gz
+ festlex-CMU.tar.gz
+ festlex-POSLEX.tar.gz
+ festvox-kallpc16k.tar.gz
+
+4) Build festival and company:
+
+ cd /usr/local/festival
+ tar xzf ~/festival/speech_tools-1.2.95-beta.tar.gz
+ tar xzf ~/festival/festival-1.95-beta.tar.gz
+ tar xzf ~/festival/festlex_CMU.tar.gz
+ tar xzf ~/festival/festlex_POSLEX.tar.gz
+ tar xzf ~/festival/festvox_kallpc16k.tar.gz
+
+ cd speech_tools
+ ./configure && make
+ cd ../festival
+ ./configure && make
+
+ These packages are build and used where they are compiled.
+
+5) Test festival:
+
+ cd /usr/local/festival/festival/examples
+ sh saytime
+
+ Festival should say the time if everything went fine
+
+6) Add /festival/festival/bin to PATH in .profile and .bashrc. For
+ me both files look like this:
+
+ .profile and .bashrc:
+ -------------------
+ export PATH=$PATH:/lib:/usr/lib:/usr/X11R6/lib:/usr/local/lib:/usr/local/bin:/usr/local/festival/festival/bin:~/bin:.
+
+ -------------------
+
+7) Configure and build xastir. Configure should report that
+ festival is found.
+
+8) Start the festival server:
+
+ festival --server &
+
+ To do this automatically I added the following lines to my
+ .bash_profile:
+
+ -------------------
+ if [ `ps -ef | grep festival | wc -l` -eq 0 ]
+ then
+ festival --server &
+ sleep 1
+ fi
+ -------------------
+
+9) Run xastir, do File->Configure->Speech, add things to say, and
+ listen.
+
+
+
+How to make Sound Alerts work under Cygwin
+------------------------------------------
+(from Kirk Mefford, kc2elo)
+"I figured I'd share exactly what I did to make the sound alerts work in
+xastir under Cygwin. Sound support seems to be just one of the many quirks
+of trying to use *nix native software under Microsoft OS's. Hope this helps
+someone else.
+
+FYI: This was tested under Win2000
+
+Sound alert support under Cygwin using Network Audio Server (NAS)
+
+I downloaded http://nas.intra-links.net/files/nas-1.6-win-binary.zip and
+decompressed the archive with winzip (any zip utility should work fine) into
+a temporary folder.
+
+I deleted the "cygwin1.dll" and "README.txt" files that came in the package
+since they aren't needed and the extra cygwin1.dll can cause problems.
+
+
+ Note from James Cour, K1ZC:
+ ---------------------------
+ "The procedure he (Kirk) outlines there works fine EXCEPT that
+ there is a valuable piece of information in that Readme.txt file...
+ The user must have a folder named /DEV under the Cygwin folder in
+ order for NASD to work. NASD will not create it automatically, and
+ NASD will not run without it. The default set-up instructions for
+ Xastir and Cygwin do not create this folder, so the user needs to
+ manually create the folder from Windows."
+
+
+ Note from Tim Baggett, AA5DF:
+ -----------------------------
+ "I recommend running the script (create_devices.sh) found attached
+ to the email located at the URL below to create the /dev directory,
+ and all supported devices under Cygwin."
+
+ "http://cygwin.com/ml/cygwin-xfree/2004-01/msg00353.html"
+
+
+Then copy the remaining files from the package into the /bin directory under
+cygwin.
+
+All that is needed to make nas available to xastir is to load the server
+before running xastir.
+
+To load NAS for xastir to use simply type "nasd -local -b" from cygwin. This
+command will load the NAS server in the background and will only allow local
+users to access it. For more command options type "nasd -help" from within
+cygwin. Some people have trouble with the "-local" option, so try
+it without that option as well ("nasd -b").
+
+After NAS is loaded you can load xastir as you normally would.
+
+Once xastir is running, to play sound alerts you need to change the default
+configuration to use "auplay"
+
+From within xastir click on File>Configure>Audio Alarms.
+The "Audio Play Command" box should be changed to "auplay"
+Then ensure the audio files listed to play are located in
+"/usr/local/share/xastir/sounds" directory.
+
+Click OK to accept the changes and be sure to save your config before
+exiting xastir or sound will not work the next time it is loaded.
+
+Turn up the volume on your PC speakers and enjoy the noise xastir makes."
+
+
+OPTIONAL: Install GDAL/OGR support:
+------------------------------------
+One user has been successful in compiling GDAL/OGR support into
+Xastir. One thing he mentioned:
+
+"Now the word of warning. If you try to compile GDAL under Cygwin
+and the compile blows up, you are better rm -rvf'ing the entire
+directory and re-untaring the source again than trying to recompile
+in that blown directory. Make Clean doesn't do a thing and the old
+settings and mistakes stick around no matter what you try."
+
+Make sure you've got Shapelib installed on your system else Xastir
+won't find GDAL (the private Xastir copy of Shapelib is fine). Both
+are needed.
+
+Download "gdal-1.2.0b.tar.gz". In a cygwin window, type the
+following:
+
+
+ tar xzvf gdal-1.2.0b.tar.gz
+ cd gdal-1.2.0b
+ ./configure --with-jpeg=internal --with-libtiff=internal
+ make
+ make install
+
+
+The GDAL/OGR library should now be installed on your system. Return
+to the xastir directory and start with the ./configure command. It
+should pick up the fact that GDAL/OGR has been installed and compile
+support for it into Xastir. Follow with the rest of the commands to
+make/install Xastir.
+
+One user required the below GDAL configure line as otherwise it
+complained about not finding libproj:
+
+ ./configure --with-jpeg=internal --with-libtiff=internal --with-static-proj4
+
+
+APRS(tm) is a Trademark of Bob Bruninga
+
+Copyright (C) 2003-2012 The Xastir Group
+
diff --git a/README.Contributing b/README.Contributing
new file mode 100644
index 0000000..134dfcc
--- /dev/null
+++ b/README.Contributing
@@ -0,0 +1,327 @@
+
+$Id: README.Contributing,v 1.21 2012/11/01 18:57:18 we7u Exp $
+
+
+Hello possible new developer, and welcome to the Xastir project!
+
+In order to get contributed patches accepted more easily by the
+Xastir developers:
+
+*) Read "Developer Guidelines and Notes" in the "HowTos" section of
+Xastir's Wiki (http://www.xastir.org). Make sure to follow the
+formatting and indentation rules, and in particular the tab format
+(spaces, not tabs). If you don't like some of the formatting rules,
+abide by them anyway for consistency (Hey, I don't like some of them
+either, but consistency is more important than ideas I might have of
+coding style! --we7u).
+
+*) Check the Xastir pages at Sourceforge. There are sections for bug
+reports and feature requests. Anyone can log new bugs or feature requests,
+whether or not they are logged into Sourceforge. This is one of the best
+places to see what needs to be worked on, and to see if anyone else has
+had a similar idea.
+
+*) Check with the Xastir-Dev list first to see if anyone else is
+working on that particular idea or section of code.
+
+*) Verify on the Xastir-Dev list that your idea has some merit and
+chance of being accepted before you put your valuable time into the
+patch.
+
+*) Make sure you're willing to abide by the GPL license with respect
+to your patch.
+
+*) Use as generic C as possible, and comment what you've done, in
+English please!
+
+*) Keep in mind that Xastir runs on multiple operating systems, so
+code for that. Some #ifdef's may be required in order to make it
+work for the various operating systems.
+
+*) Xastir can be run in multiple languages, so code for that. If
+any user text is added, make sure to add language strings for them
+to the language files. If you don't know a particular language, add
+it to all of the language files in English. It will be translated
+by others later.
+
+*) Put your patches into either "context diff" or "unified diff"
+format. Don't submit complete files. Make sure your diff is
+against the latest CVS sources, as that is the version that the
+developers work from. Create the diff file against the directories
+recursively if more than one file has been changed:
+
+ diff -ur xastir-1.7.0 xastir-modified-directory > mypatch
+
+Here's a shorthand method if you're doing all this against the CVS
+version. Do this from the top-level Xastir directory:
+
+ cvs diff -u > mypatch
+
+*) By compressing the patch and attaching it to an e-mail you
+preserve the lines exactly so that the "patch" program will have no
+trouble with it:
+
+ gzip mypatch
+
+This creates mypatch.gz, which you can attach to an e-mail or put up
+on an ftp or http site for download.
+
+*) Contribute patches either directly to one of the active
+developers or to the Xastir-Dev mailing list (you must be subscribed
+in order to post messages there).
+
+*) To apply a patch I typically do this:
+
+ gzip -d mypatch.gz
+
+Check the path listed inside the patch:
+
+ head mypatch
+
+Based on the paths listed inside the patch and the directory at
+which you're currently sitting, adjust the "p" number below so that
+the proper number of directories are stripped from the patch. This
+example strips off the first two directories:
+
+ patch -p2 <mypatch
+
+
+
+DEBUGGING HINTS:
+----------------
+Xastir is a multi-threaded and multi-process application. It uses
+both threads and forks to do it's work. You must have a debugger
+that is capable of following these kinds of twists and turns in a
+program. Many older versions cannot.
+
+Notes from Tom Russo:
+---------------------
+According to everything I can find about GDB, debugging of
+multithreaded apps has been supported in gdb for some time, and are
+certainly supported in gdb 6.x. For the last couple days I've been
+running xastir inside gdb instead of at the command prompt ---
+perhaps I won't keep forgetting to start it with -t now, and when it
+crashes I'll be where I need to be.
+
+Jim --- this is possibly an option for you, too, if you're seeing
+segfaults frequently enough and can't solve the core file question.
+Try this:
+
+ gdb /usr/local/bin/xastir
+ > run -t
+
+When it crashes, it'll pop you right out into the debugger, whether
+a core file was created or not. You could then view the active
+threads:
+ > info threads
+
+and get a stack trace of where the crash happened:
+ > where
+
+You could also probably list the code near where the crash happened:
+ > list
+
+If you send the output of those three commands to the xastir-dev
+list then it might help us narrow down the causes.
+
+
+Notes from Curt:
+----------------
+Note that the meaning of the "-t" command-line flag has been
+reversed. "xastir -?" should show the change once you compile it.
+This means that we'll do core dumps by default upon segfault instead
+of using the internal Xastir segfault handler. We've also
+re-enabled the "-g" compile option for GCC so that debugging
+information will remain embedded in the executable (unless you strip
+it). This should aid the development team to debug problems.
+
+> Also, I cannot find anything in man bash that talks about core
+> dumps nor segmentation faults.
+
+Seems like some stuff we're just supposed to know. _How_ we're
+supposed to know I don't know either... ;-)
+
+Perhaps that last bit about SUID/SGID might be a clue: There are
+often exceptions to the rules for SUID/SGID programs. Try _not_
+setting Xastir SUID (if you're not using AX.25 kernel networking
+ports that is) to see if you get a core file. Can you send a
+SIGSEGV to the running process and make it dump? I just tried this
+and I'm not getting a core file either.
+
+Ah, I see in the "man bash" page:
+
+ ulimit
+ -a All current limits are reported
+
+This gives me:
+
+ core file size (blocks, -c) 0
+ data seg size (kbytes, -d) unlimited
+ file size (blocks, -f) unlimited
+ max locked memory (kbytes, -l) 32
+ max memory size (kbytes, -m) unlimited
+ open files (-n) 1024
+ pipe size (512 bytes, -p) 8
+ stack size (kbytes, -s) unlimited
+ cpu time (seconds, -t) unlimited
+ max user processes (-u) 6139
+ virtual memory (kbytes, -v) unlimited
+
+So... Looks like I need to set "ulimit -c" and try again:
+
+ ulimit -c unlimited
+
+Now when I do "kill -11 <pid>" I get this:
+
+ [1]+ Segmentation fault (core dumped) xastir
+
+and this:
+
+ -rw------- 1 archer users 12320768 2006-02-02 09:31 core.7586
+
+I just added "ulimit -c unlimited" to my .profile. For what it's
+worth, if Xastir has SUID permission bit set (4755) I don't get a
+core dump, but if it is reset I do (0755).
+
+I can invoke ddd like this (it uses gdb under the hood):
+
+ ddd /usr/local/bin/xastir core.7586 &
+
+or gdb like this:
+
+ gdb -c core.7586 /usr/local/bin/xastir
+
+Once you have the program and core file loaded into the debugger you
+can display a backtrace to see where the program died. In the case
+of ddd, it's Status->Backtrace, then you click on one of the entries
+to make the source code window display the exact location.
+
+Another good debugger to try is "UPS".
+
+Another note about core files: Sometimes they get written where you
+don't expect. I just had one appear in ~/.xastir/tmp, so if you
+think you should have a core file and can't find it, try:
+
+ find . -type f | grep core
+
+The core file may be written to a directory that Xastir is currently
+in, instead of where you started Xastir from.
+
+Customized debugging builds
+---------------------------
+
+Sometimes it is helpful to build xastir with specialized compiler
+options to aid in debugging. For example, if you're trying to hunt
+down elusive segfaults, and you're using GCC, it might be wise to
+build with "-O -g -fno-inline" to prevent the compiler from optimizing
+quite so vigorously; aggressive optimization can sometimes lead to the
+debugger saying the code died on one line when in fact it's happening
+somewhere else.
+
+To build with custom CFLAGS like this, just tell configure what you
+want CFLAGS to be:
+ ./configure CFLAGS="-O -g -fno-inline"
+
+Naturally, unless you're using build directories separate from the
+source directory (see below under "Segregating specialized builds"),
+you need to build every file after changing configure like this, so do
+a make clean before building:
+
+ make clean
+ make
+ make install
+
+Remember not to "make install-strip" when trying to do debugging
+builds, or your core files will not have debugging symbols in them and
+it will be harder to get useful information out of the debugger.
+
+Segregating specialized builds
+------------------------------
+
+The automake/autoconf setup of xastir makes it easy to maintain several
+different builds of the code without having to clean out the directory and
+rebuild every time. One does this with "build directories" and executable
+suffixes.
+
+To use this capability, make sure you're starting with a completely
+clean source directory. In the directory where you normally do your
+"cvs update", do a make distclean. This will remove anything that
+configure created as well as anything that make created. From this
+point forward, you don't build xastir in the source code directory
+anymore.
+
+Make an empty directory somewhere --- this will be your build directory.
+I put my build directories in parallel with the source code directory. So
+my tree looks like this:
+
+ XASTIR-DEV
+ |
+ +----/xastir (source directory)
+ |
+ +---/build-normal
+ |
+ +---/build-debug
+and so on.
+
+So I would do:
+ cd XASTIR-DEV
+ mkdir build-normal
+
+In the build directory, you run configure using the path to the configure
+script:
+
+ cd build-normal
+ ../xastir/configure
+ make
+ make install
+
+The configure script uses the path that you gave when you ran it to figure
+out where to find the source code.
+
+The beauty of this is you can make a second build without doing a make clean:
+ cd XASTIR-DEV
+ mkdir build-debug
+ cd build-debug
+ ../xastir/configure --program-suffix="-debug" CFLAGS="-O -g -fno-inline"
+ make && sudo make install
+
+This will build a second binary called "xastir-debug" and install it,
+but because you've done the buil in a separate directory, your normal
+compile is untouched.
+
+ cd ~/XASTIR-DEV/xastir
+ cvs update
+ cd ../build-normal
+ make && sudo make install
+ cd ../build-debug
+ make && sudo make install
+
+will update both of your builds.
+
+I also use this technique to share a single xastir source tree over
+NFS, building the code for multiple operating systems in separate
+build directories.
+ (log in to CYGWIN machine, mount NFS directory)
+ cd /mounted/directory/XASTIR-DEV
+ mkdir build-cygnus
+ ../xastir/configure
+ make && make install
+
+It can also be used to maintain specialized configurations, for
+example a build with "rtree" disabled, a build with map caching
+disabled, etc. This is a good development trick to keep yourself
+honest --- make sure you can still build all your custom builds when
+you've done a large hacking run, and want to check if you have broken
+things inside ifdefs. Doing that without build directories requires a
+huge number of configure/make/make distclean cycles.
+
+More?
+-----
+Anything else? Let's hear about what's still confusing or needs to
+be expanded in this document. Thanks!
+
+
+APRS(tm) is a Trademark of Bob Bruninga
+
+Copyright (C) 2006-2012 The Xastir Group
+
diff --git a/README.Getting-Started b/README.Getting-Started
new file mode 100644
index 0000000..843252d
--- /dev/null
+++ b/README.Getting-Started
@@ -0,0 +1,902 @@
+
+$Id: README.Getting-Started,v 1.45 2012/08/26 18:34:34 tvrusso Exp $
+
+
+Hello new user, and welcome to Xastir!
+
+
+This document will take you through the steps necessary to get
+Xastir up and running in one of the following configurations:
+
+
+1) Minimal install, which will get you up and running quickly. It's
+ recommended that you try this configuration first then add to it.
+
+2) Typical install including maps, weather alerts, geo-coding files,
+ etc. so that full regular operation is achieved.
+
+3) Maximum install with all configure options enabled and most of
+ the useful maps loaded/enabled. All the bells and whistles.
+
+
+Note that you can start with either of the first two options and add
+only the options you wish in order to come up with your own custom
+configuration of Xastir.
+
+These instructions are written for Linux users. Windows users
+should refer to the README.win32 document instead.
+MacOSX/Solaris/FreeBSD users should refer to the README document
+first, then the INSTALL document and the below instructions for
+further notes.
+
+One question you might ask is whether you can just find a binary on
+the 'net somewhere and install it instead of compiling Xastir from
+sources. Yes, this is possible. Xastir changes so often (bug fixes
+and of course adding new features) that you're really limiting
+yourself by using pre-compiled binaries. Binaries are typically not
+updated all that often, if at all, so you'll forever be behind the
+curve.
+
+Another reason to compile from sources is to customize it to use all
+of the features you have available on your system. As you add more
+libraries that Xastir can use, you can do a quick
+configure/compile/install and Xastir will be able to take advantage
+of them.
+
+For those that really must have the latest-latest: Download the
+Xastir sources using CVS instead, then issue the command "cvs
+update" periodically in order to snag the latest changes. If
+anything comes down the pipe, just configure/make/install and then
+use the latest version. This avoids large file downloads (after the
+initial download) as it just grabs _changes_ to the sources off the
+'net each time you issue the "cvs update" command. This is the
+power-user's method of keeping Xastir up-to-date. See README.CVS
+for details.
+
+After the three configuration sections there's a section on
+operating, which simply talks you through the initial configuration
+settings and how things work. After that you can refer to the Help
+menu option in Xastir itself, plus the INSTALL and README.* text
+files for additional information. Please note that the non-English
+help files lag severely behind the English help file.
+
+First of all, NEVER RUN XASTIR AS THE ROOT USER! You're risking the
+security of your system by attempting it. Create another regular
+user on your system and use that user for all of your normal
+activity. This goes for any other normal activity on the system as
+well. Only use the "root" account for maintenance activities, not
+for regular user activities. You'll thank me later!
+
+Before we begin, consider subscribing to the Xastir mailing list.
+That's where everyone is kept up-to-date on the latest features,
+plus lots of questions are asked/answered there on a weekly or
+sometimes daily basis. It's a great way to learn and to stay
+connected with the other Xastir users. See the mailing links on the
+left of the Xastir home page: http://www.xastir.org
+You must be subscribed in order to post messages there.
+
+So... Let's get started!
+
+
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+
+
+Latest info:
+
+*) Xastir starts up with a default world map the first time you run
+it plus pops up a dialog where you can enter your callsign. Enter
+a callsign, then close/restart Xastir or save the configuration via
+"File->Configure->Save Config Now!". Either of these methods saves
+the callsign to disk.
+
+*) Xastir includes "Shapefile" map capability by default. Run the
+script:
+
+ "/usr/local/share/xastir/scripts/get-NWSdata"
+
+as root to download/install NOAA Shapefile maps using the "wget"
+utility. You'll of course need wget installed in order to fetch the
+files using this method. Installing the NWS files enables weather
+alert support in Xastir. Verify that "Map->Enable Weather Alerts" is
+selected and that "Map->Disable All Maps" is _not_ selected, else
+you won't see weather alerts on your screen.
+
+
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+
+
+Sources of help you may find useful:
+
+*) "FAQ" file
+
+*) "INSTALL" file: Non-Windows instructions for installing Xastir
+ and optional map libraries may be found here.
+
+*) "README" file: General info and some OS-specific notes.
+
+*) "README.Contributing" file: Info on how to contribute to the
+ Xastir project.
+
+*) "README.CVS" file: Info on a more advanced way to keep up-to-date
+ on the latest Xastir sources.
+
+*) "README.Getting-Started" file: The file you're reading.
+
+*) "README.MAPS" file: Much of the info about maps and where to get
+ them may be found here. Also see the Xastir Documentation
+ section, the Wiki pages, at <http://www.xastir.org>
+
+*) "README.win32" file: For Windows/Cygwin users.
+
+*) "UPGRADE" file: Useful info for updating some old versions of
+ Xastir.
+
+*) Xastir Web-based documentation, including a set of Wiki pages,
+ found at <http://www.xastir.org>
+
+*) Xastir man page, accessed by typing "man xastir" on a Unix or
+ Unix-like system. This page is a bit out-of-date.
+
+*) "Help->Help Index" in the Xastir program itself. Note that only
+ the English language variation of this is somewhat up-to-date.
+
+*) Mailing lists at <http://www.xastir.org>
+
+*) User forums at <http://www.xastir.org>
+
+
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+
+
+Minimal Install:
+----------------
+
+First, let's describe it: This will get Xastir up and running with
+a few built-in map types. You'll be on the air or on the 'net
+quickly, then can build upon this working base to add more map
+libraries and other cool features later.
+
+
+Getting the package:
+--------------------
+*) Option 1: Download one of stable or development snapshots from
+http://www.xastir.org. There are links from that page or you can go
+to the SourceForge page and click on Files to see the entire set
+that is available.
+
+Once you have the file, create a subdirectory for it to reside. I
+usually do this:
+
+ cd # Go to my home directory
+ mkdir src # Make a "src" subdirectory
+ cd src # Change to it
+ mkdir xastir # Make an "xastir" subdirectory
+ cd xastir # Change to it
+ cp /path/filename . # Copy the downloaded file here
+ tar xzvf filename # Un-archive the sources
+
+That last step will create yet another xastir directory underneath
+the first one but will have the version number in it, so your full
+path might be something like (starting at your home directory):
+~/src/xastir/xastir-1.7.0
+
+The path just listed is where you'll go in order to run the
+configure and make commands listed below.
+
+ cd ~/src/xastir/xastir-1.7.0
+
+from an xterm window should take you there.
+
+*) Option 2: An alternative is to use CVS to snag the sources for
+you. Using this method you can periodically update to the latest
+released version, the latest "stable" version, or the latest
+development sources. See README.CVS for info about that option.
+One of the advantages of CVS is that you only pull down the changes
+since you last updated, instead of doing very large file downloads
+each time. Another advantage is that you can keep up with the
+latest features on a daily basis if you wish, nearly effortlessly.
+
+
+Configure:
+----------
+In order to complete the configure/compile/install of Xastir, you'll
+need some of the development tools and headers installed. Here's a
+list of a few items you'll need to have installed. Look for them in
+the development tools sections on your Linux distribution:
+
+
+ bash
+ binutils
+ gcc
+ gcc development headers
+ cpp
+ glibc
+ glibc development headers?
+ freetype2
+ freetype2 development headers
+ openmotif (or Lesstiff or Motif)
+ openmotif development headers (or Lesstiff or Motif)
+ XFree86
+ XFree86 development headers
+ XFree86 fonts
+ XFree86 libraries
+ make (GNU flavor, not BSD flavor)
+ gzip
+ m4
+ grep
+
+
+Note: Only install one of the Motif packages and the corresponding
+development package to go with it. Recommendation: OpenMotif.
+
+If you'd like to install additional packages at this point that may
+be needed later, install these as well:
+
+
+ patch
+ diffutils
+ perl
+ autoconf
+ automake
+ less
+ bzip2
+ curl
+ curl development headers
+ cvs
+ rcs
+ tar
+ liblcms
+ liblcms development headers
+ libtiff
+ less
+ pcre
+ pcre development headers
+ tcl
+ tcl development headers
+ tk
+ zip
+ unzip
+ wget
+ ax25-apps
+ ax25-doc
+ ax25-tools
+ libax25
+ festival
+ festival development headers
+ gawk
+ ghostscript-x11
+ ghostscript-fonts
+ ghostview
+ gv
+ ImageMagick
+ ImageMagick development headers
+
+
+Note that some packages may have dependencies on yet more packages.
+Hopefully your package installation tool will take care of those for
+you. It's also common for at least one of these packages to forget
+to list some of it's dependencies (ImageMagick is known for that).
+In that case you may have to rely on the compiler to tell you what
+is missing, then go back and re-install a package or two.
+
+When you run the "./configure" step from the "xastir" directory, the
+script will attempt to figure out what facilities are available that
+Xastir can take advantage of. Sometimes the script guesses wrong
+and you must disable an option and try again. The correct way to do
+this is (Festival speech synthesizer is used as an example, not that
+I'm picking on Festival or anything):
+
+ ./configure --without-festival
+
+That will guarantee that configure will skip Festival entirely,
+which will set up the Makefiles to skip it, and the Xastir binary
+will be created without any support for it. Other configure options
+are:
+
+ --without-ax25
+ --without-festival
+ --without-gpsman
+ --without-shapelib
+ --without-imagemagick
+ --without-libproj
+ --without-geotiff
+ --without-gdal
+ --without-pcre
+ --without-dbfawk
+ --without-map-cache
+ --with-errorpopups
+ --with-rtree
+
+
+That said, you probably won't have to use any of these! Type
+"./configure" all by itself and the script should eventually give
+you a summary of the packages that it will try to compile support
+into Xastir for. The only time you may want to add some of the
+above options is if the compile hangs up because of one of them.
+You can then add the option to configure, re-create the Makefiles to
+skip that feature, and get Xastir compiled without it. Once you get
+the problem solved, you can reconfigure and recompile to add that
+feature back in.
+
+At this point, if some things don't appear in the summary that you'd
+like/expect to appear, as long as you get to the "Type 'make' to
+build Xastir" message, you're doing fine. You can work on getting
+more things in there later.
+
+This is what you'd like to see at the end of the "./configure" run
+(minimum, there may be more "yes" answers):
+
+ AX25.......... : no
+ Festival...... : no
+ GPSMan........ : no
+ ImageMagick... : no
+ libproj....... : no
+ GeoTiff....... : no
+ GDAL/OGR...... : no
+ ShapeLib...... : no
+ pcre.......... : no
+ dbfawk........ : no
+ libgc (Debug). : no
+
+In other words, Xastir should build/compile with NO optional
+libraries installed! This will still give you USGS GNIS maps,
+APRSdos maps, WinAPRS maps, and PocketAPRS maps, plus audio alerts
+if you have a suitable audio player installed on your system.
+You'll also be able to attach a TNC either in command-line or KISS
+mode and connect it to Xastir. Mobile support will work with an
+attached serial GPS. Attached weather stations should work fine
+too. You won't get online maps or weather alerts with this
+configuration though. Worry about that stuff later once you get the
+minimal configuration working.
+
+
+Make:
+-----
+Type "make". That stage should complete with no errors. You may
+have a warning or two show up, depending on your compiler version
+and your operating system.
+
+
+Make install:
+-------------
+For this stage you need to have root privileges. "root" is the
+user on a Unix/Linux box that has the ultimate authority over
+everything. Follow these steps:
+
+ su
+ make install
+ chmod 4755 /usr/local/bin/xastir (optional, see below)
+ exit
+
+The first step takes you to root user privileges. You'll need to
+type in the root password when it asks for it. The "make install"
+step installs all of the pieces of Xastir in the appropriate places
+on your system.
+
+The "chmod" step sets up the Xastir executable so that it can assume
+root privileges at the points where it needs to, usually when it
+needs to access serial ports or AX.25 kernel networking ports. Note
+that if you don't need the above chmod command, don't use it. It
+will prevent creation of "core" files in case Xastir crashes, which
+makes debugging to figure out the root cause much more difficult.
+There are also some security risks in doing "chmod 4755", as it
+makes Xastir run as the root user at times. We've tried to minimize
+the risk by giving up root permissions when we don't absolutely
+require them, so the risks are smaller.
+
+At this point you have a minimal Xastir installed. Jump down to the
+"Operating Xastir" step below.
+
+
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+
+
+Typical Install:
+----------------
+
+First, let's describe it: This will give you a working Xastir with
+local Shapefile maps, online street/topo/satellite-image maps,
+weather alerts, and audio alerts. Optionally you can add
+synthesized speech to the mix.
+
+You'll need to run /usr/local/share/xastir/scripts/get-NWSdata as root
+after you do the install in order to get the NOAA data files you'll
+need for the weather alerts. "get-NWSdata" requires "wget" in order
+to work.
+
+This is what you'd like to see at the end of the "./configure" run
+(minimum, there may be more "yes" answers):
+
+
+-------------------------------------------------------------------
+ MINIMUM OPTIONS:
+ ShapeLib (Vector maps) ................. : yes
+
+ RECOMMENDED OPTIONS:
+ GraphicsMagick/ImageMagick (Raster maps) : yes (GraphicsMagick)
+ pcre (Shapefile customization) ......... : yes
+ dbfawk (Shapefile customization) ....... : yes
+ rtree indexing (Shapefile speedups) .... : no
+ map caching (Raster map speedups) ...... : no
+ internet map retrieval ................. : yes (libcurl)
+
+ FOR THE ADVENTUROUS:
+ AX25 (Linux Kernel I/O Drivers) ........ : no
+ libproj (USGS Topos & Aerial Photos) ... : no
+ GeoTiff (USGS Topos & Aerial Photos) ... : no
+ Festival (Text-to-speech) .............. : no
+ GDAL/OGR (Obtuse map formats) .......... : no
+ GPSMan/gpsmanshp (GPS downloads) ....... : no
+-------------------------------------------------------------------
+
+
+Note: You may see "ImageMagick" instead of "GraphicsMagick" and/or
+"wget" instead of "libcurl" for your installation of Xastir. Those
+are alternative packages that give similar functionality. You may
+also see "(internal)" at the end of the Shapelib line, which is fine
+also.
+
+
+TBD
+
+
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+
+
+Maximum Install:
+----------------
+
+First, let's describe it: This will give you a working Xastir with
+all of the non-debug "configure" options enabled, local maps, online
+street/topo/satellite-image maps, weather alerts, audio alerts,
+synthesized speech, Garmin RINO support, GPS download support,
+search for street address capability, FCC/RAC callsign lookups, and
+all of the supported map types.
+
+This is what you'd like to see at the end of the "./configure" run:
+
+
+-------------------------------------------------------------------
+ MINIMUM OPTIONS:
+ ShapeLib (Vector maps) ................. : yes
+
+ RECOMMENDED OPTIONS:
+ GraphicsMagick/ImageMagick (Raster maps) : yes (GraphicsMagick)
+ pcre (Shapefile customization) ......... : yes
+ dbfawk (Shapefile customization) ....... : yes
+ rtree indexing (Shapefile speedups) .... : yes
+ map caching (Raster map speedups) ...... : yes
+ internet map retrieval ................. : yes (libcurl)
+
+ FOR THE ADVENTUROUS:
+ AX25 (Linux Kernel I/O Drivers) ........ : yes
+ libproj (USGS Topos & Aerial Photos) ... : yes
+ GeoTiff (USGS Topos & Aerial Photos) ... : yes
+ Festival (Text-to-speech) .............. : yes
+ GDAL/OGR (Obtuse map formats) .......... : yes
+ GPSMan/gpsmanshp (GPS downloads) ....... : yes
+-------------------------------------------------------------------
+
+
+Note: You may see "ImageMagick" instead of "GraphicsMagick" and/or
+"wget" instead of "libcurl" for your installation of Xastir. Those
+are alternative packages that give similar functionality. You may
+also see "(internal)" at the end of the Shapelib line, which is fine
+also.
+
+
+TBD
+
+
+--------------------------------------------------------------------
+--------------------------------------------------------------------
+
+
+Operating Xastir:
+-----------------
+
+Again, NEVER RUN XASTIR AS THE ROOT USER! You're risking the
+security of your system by attempting it. Create another regular
+user on your system and use that user for all of your normal
+activity. This goes for any other normal activity on the system as
+well. Only use the "root" account for maintenance activities, not
+for regular user activities. You'll thank me later!
+
+Assuming you want to start Xastir up in the English language, you
+can type (from an xterm window):
+
+ xastir
+
+which will start up the program without giving you back a
+command-prompt in your xterm window (until Xastir exits), or you can
+type (from an xterm window):
+
+ xastir &
+
+which will start Xastir in the background, giving you back your
+xterm for more commands. The typical way to start it is with
+"xastir &". Of course you can get fancier and attach it to your
+window manager's menus or create an icon on your desktop which
+starts it. Those are operating system/window manager-specific, so
+we won't cover how to do that here.
+
+The first time you start Xastir it will show a default map of the
+world plus pop up the File->Configure->Station dialog. Enter a
+callsign on that dialog and press the OK button.
+
+
+Changing the Language:
+
+If you want to start Xastir using some other language, you do that
+with command-line switches when you start Xastir. Once you use one
+of these switches, that language option becomes "sticky", meaning
+you won't have to enter that command-line switch again unless you
+wish to change languages.
+
+There are some command-line switches that you can
+If you type "xastir -?", which is an invalid command-line option,
+you'll see this:
+
+ xastir: invalid option -- h
+
+ Xastir Command line Options
+
+ -c /path/dir Xastir config dir
+ -f callsign Track callsign
+ -i Install private Colormap
+ -geometry WxH+X+Y Set Window Geometry
+ -l Dutch Set the language to Dutch
+ -l English Set the language to English
+ -l French Set the language to French
+ -l German Set the language to German
+ -l Italian Set the language to Italian
+ -l Portuguese Set the language to Portuguese
+ -l Spanish Set the language to Spanish
+ -l ElmerFudd Set the language to ElmerFudd
+ -l MuppetsChef Set the language to MuppetsChef
+ -l OldeEnglish Set the language to OldeEnglish
+ -l PigLatin Set the language to PigLatin
+ -l PirateEnglish Set the language to PirateEnglish
+ -m Deselect Maps
+ -p Disable popups
+ -t Internal SIGSEGV handler enabled
+ -v level Set the debug level
+
+
+Ignore those for now unless you need to change the Language.
+
+OK, Xastir should show up on your screen at this point. We're
+assuming that you're already running X-Windows graphical environment
+at this point. If you're in command-line Linux/Unix only, Xastir
+won't run.
+
+If you've configured in ShapeLib capability, you'll need to run
+/usr/local/share/xastir/scripts/get-NWSdata as the root user in order
+to get the NOAA data files you'll need for the weather alerts. The
+script requires "wget" in order to work. Run this script periodically
+(once every six months perhaps?) to keep your weather alert maps
+up-to-date. If you're not in the U.S. or one of it's possessions then
+you can safely ignore this download.
+
+
+Various ways to manipulate Xastir:
+
+
+Context-Dependent Operations:
+-----------------------------
+ Normal Draw-CAD Measure Move
+ ------ -------- ------- ----
+Cursor Arrow Pencil Crosshairs Crosshairs
+LeftClick SelectObject
+LeftDrag ZoomToArea ZoomToArea MeasureArea MoveObject
+MiddleClick ZoomOut SetCADPoint ZoomOut ZoomOut
+
+Alt-F, Alt-V, etc to bring up main menus via the keyboard. Use
+arrow keys to navigate menus and/or single letters corresponding to
+the "hot" letter (underlined lettter) for each menu item.
+
+"ESC" to back out of the menu system.
+
+
+Global Operations:
+------------------
+LeftClick Select Menu or GUI Item (when in menus or dialogs)
+LeftDblClick FetchAlertText (when in View->Wx Alerts dialog)
+RightClick OptionsMenu
+Home Center the map on your home station
+PageUp ZoomOut
+PageDown ZoomIn
+ArrowUp PanUp
+ArrowDown PanDown
+ArrowLeft PanLeft
+ArrowRight PanRight
+"=" GridSize++
+"+" GridSize++
+"Num+" GridSize++
+"-" GridSize--
+"Num-" GridSize--
+"Space" Activate current widget
+"Tab" Rotate among widgets
+"Back-Tab" Rotate among widgets backwards
+
+
+Other Possible External Stimuli:
+--------------------------------
+Send a SIGUSR1 to cause a snapshot to be taken.
+Send a SIGHUP to cause Xastir to save/quit/restart.
+Send a SIGINT, SIGQUIT, or SIGTERM to cause Xastir to quit.
+Connect to TCP port 2023 if Server Port is enabled to send/receive packets.
+Send to UDP port 2023 via the xastir_udp_client program to inject packets.
+
+
+Note that you can also tweak a define/recompile to reverse the
+left/right button functions.
+
+
+
+Configuring Xastir:
+-------------------
+*) Note that the menu's have a dashed line near the top. If you
+click on that dashed line it acts like a cut-line for the menu and
+detaches that menu from the main menu. You can then move that menu
+off to another area of your screen. You might try that with the
+File->Configure menu at this time.
+
+*) Go to File->Configure->Station and set your callsign. Set up
+other parameters/comment fields on this dialog that may need
+setting.
+
+*) Go to File->Configure->Defaults and set parameters there.
+
+You have the main parameters set now. Next is to enable some
+interfaces so that you can see some packets come across. Easiest
+might be the Internet interfaces, assuming the computer you're on
+has Internet access and is hooked up to it currently.
+
+*) Run "callpass" in another Xterm window in order to generate your
+Pass-code number. Save that number as you'll need it for each
+Interface dialog where you might need to authenticate your callsign.
+Of course you can always run callpass again if you forget it!
+
+*) Go to Interface->Properties then click on "Add". Click "Internet
+Server". Another dialog will come up that allows you to enter the
+Host, and the Port. Enter your Pass-code number here. People often
+check the "Activate on Startup?" and the "Reconnect on NET failure?"
+options on this box. You may also assign a comment to this
+interface which describes the interface better for you. Click "OK"
+to create the interface. If you checked "Activate on Startup?" then
+the interface will start as well and you'll be receiving packets.
+
+Browse "http://www.aprs2.net/" to find a reasonable set of servers
+to start with. Another possibility is to use "rotate.aprs2.net"
+port 14580, which theoretically should rotate among the available
+second-tier servers. See "http://www.aprs2.net" for more info.
+You'll need to put in a filter string, such as "r/35/-106/500" which
+shows you stations that are within 500km of 35dN/106dW (Thanks for
+that one Tom!). For additional filter settings check out:
+
+ http://www.aprs-is.net/javaprssrvr/javaprsfilter.htm
+
+*) Start that interface from the Interface->Start/Stop dialog if
+it's not started already. You'll see icons in the lower right
+toggling and see callsigns in the lower left status box if packets
+are coming in.
+
+One thing about configuration: Most things don't get written to
+Xastir's config file until you choose either "File->Configure->Save
+Config Now!" or you exit Xastir. Map Selections however are
+immediate.
+
+*) Creating/starting interfaces for other types of devices is
+similar. If you're wanting to create AX.25 kernel networking ports
+you'll have to refer to the HAM HOWTO documents and perhaps the
+linux-hams mailing list for help. For AGWPE connections refer to
+that AGWPE docs and mailing list.
+
+It's recommended that if you run a local TNC, you run it in KISS
+mode. You can do that via the Serial KISS TNC interface, or via
+AX.25 Kernel Networking ports.
+
+Some of the more esoteric types of interfaces may require some
+questions on the Xastir list. Don't be afraid to ask them as we've
+all been there before.
+
+
+A Note About Paths:
+-------------------
+New path methods were discussed early April, 2005, and are being
+implemented world-wide:
+
+ "WIDE2-2" for fixed stations, balloons, aeronautical-mobile
+ "WIDE1-1,WIDE2-1" for mobiles/portables
+
+With this system, "WIDE1-1" has replaced "RELAY". Never use
+"WIDE1-1" in anything but the first path slot. "RELAY", "WIDE",
+"TRACE", and "TRACEn-N" are deprecated and should not be used
+anymore.
+
+If you want to insert a single hop callsign later in the path use
+"WIDE2-1" instead, for example: "WIDE1-1,WIDE2-1" will go exactly
+two hops and use _either_ home fill-in digi's or mountaintop digi's
+for the first hop, mountaintop digi's only for the second hop.
+
+Home fill-in digi's (only where absolutely needed) should be set up
+to respond to "WIDE1-1" instead of "RELAY".
+
+
+A Note About the Map Directory:
+-------------------------------
+The map directory (/usr/local/share/xastir/maps/) is free-form,
+meaning you can have links in there, subdirectories, etc. Organize
+it in any way that makes sense to you. From within the Map Chooser
+you can select a directory name, which will select every map
+underneath that directory, so keep that in mind while organizing
+your maps.
+
+
+Enabling Weather Alerts:
+------------------------
+You must have Shapelib compiled into Xastir. Xastir now comes with
+Shapelib support built-in. PRCE/dbfawk are optional. Install NOAA
+shapefile maps as specified in README.MAPS. These files must be
+installed into the /usr/local/share/xastir/Counties/ directory. You
+may use this script to download/install them for you:
+
+ "/usr/local/share/xastir/scripts/get-NWSdata"
+
+which must be run as the root user, and requires "wget" to work.
+
+A neat trick: You can copy some of these maps into the
+/usr/local/share/xastir/maps directory somewhere (a new subdirectory
+under there is always fine), then you can select some of these maps
+as regular Xastir maps as well.
+
+
+Enabling FCC/RAC Callsign Lookup:
+---------------------------------
+
+Run the /usr/local/share/xastir/scripts/get-fcc-rac.pl script as root,
+which will download and install the proper databases into the
+/usr/local/share/xastir/fcc/ directory. At that point the callsign
+lookup features in the Station Info dialog and in the "Station->Find
+Station" menu option should be functional.
+
+
+Enabling Map Feature Lookup:
+----------------------------
+Install USGS GNIS files into the /usr/local/share/xastir/GNIS/
+directory. Call out the proper file when invoking the "Map->Locate
+Map Feature" menu option. Note that if you also link a subdirectory
+name under the maps directory back to the
+/usr/local/share/xastir/GNIS/ directory, you'll be able to use the
+GNIS files as maps under the Map Chooser as well. See README.MAPS
+for how to do this.
+
+
+Enabling Street Address Lookup:
+-------------------------------
+Download the USA.geocode file and install it into the
+/usr/local/share/xastir/GNIS/ directory. This will enable the
+"Map->Find Address" menu option to work. Xastir will place a big
+"X" on the map at the street address it finds for you. This file is
+sometimes available at http://www.dementia.org/geocoder/tgr2003/
+As an alternative you can download the individual state files that
+are located there.
+
+
+Enabling Audio Alarms:
+----------------------
+Download and install sample audio files from Xastir's SourceForge
+download site. Install the audio files in
+/usr/local/share/xastir/sounds/ directory.
+
+Install a command-line audio player. Call out the path/name of that
+player in the File->Configure->Audio Alarms dialog. Common ones are
+vplay and auplay, but there are many others. Enable the types of
+alarms you desire in that same dialog.
+
+You should be able to test it manually from a shell by typing the
+command in something like this: vplay filename
+
+Once you find a command that works, type it into Xastir's Audio
+Alarms dialog exactly the same except omit the filename.
+
+
+Enabling Synthesized Speech:
+----------------------------
+*) MacOSX
+ TBD
+
+*) Windows
+ TBD
+
+*) Linux/FreeBSD/Solaris
+Install the Festival Speech Synthesizer. Configure/compile support
+for it into Xastir. Start up the Festival server before starting
+Xastir. Xastir should start up and connect to the server. Use the
+options in File->Configure->Speech to decide which things you'd like
+Xastir to speak to you about.
+
+Note that the Proximity Alert option in the File->Configure->Speech
+dialog uses the distances set in the File->Configure->Audio Alarms
+dialog.
+
+
+Enabling GPS Waypoint/Track/Route Download Support:
+---------------------------------------------------
+Install GPSMan and gpsmanshp. Configure/compile support for it in
+Xastir. Start up GPSMan separately and configure it for your GPS
+and serial port. You'll see download options for each type on the
+Interface menu.
+
+Note that Xastir requires a version of gpsman at least as recent as 6.1. Older
+versions of gpsman may not work.
+
+
+Enabling Garmin RINO Support:
+-----------------------------
+Install GPSMan (and gpsmanshp if you wish normal GPS download
+support as well). Configure/compile support for it in Xastir.
+Start up GPSMan separately and configure it for your GPS and serial
+port. In the "File->Configure->Timing" dialog you'll see an option
+for "RINO -> Objects Interval". That sets the interval at which
+Xastir will download waypoints from an attached RINO unit. Any
+waypoints that begin with "APRS" will have the "APRS" chopped off,
+and the remaining name will be used to create APRS(tm) Objects. Those
+objects will be plotted on the map and transmitted as well if
+transmit for objects/items is enabled.
+TBD
+
+
+Transmit Enable/Disable Options:
+--------------------------------
+Each interface has a separate transmit enable. The Interface menu
+also has a few global transmit enables. All of these must be
+enabled for a particular interface to transmit. Also, for Internet
+servers, you typically need to authenticate with the server using
+your callsign/pass-code before you're allowed to inject packets into
+the Internet stream which may get gated out to RF. If you just want
+to talk to other Internet users, you don't need a pass-code to
+authenticate to the servers.
+
+
+Igating Options:
+----------------
+There are igating options on each local TNC interface. There are
+other global igating options on the File->Configure->Defaults
+dialog. The global option sets restrictions on all igating.
+
+
+Where stuff is kept:
+--------------------
+
+Per-user configurations are kept in each user's ~/.xastir directory, by
+default. In particular the ~/.xastir/config/xastir.cnf file is where most
+of the configs are kept. This directory can be optionally specified using
+the -c /path/dir command line option. Make sure you specify a directory,
+not a file! Xastir will create the directory and several subdirectories if
+they do not exist when you start up.
+
+A few executables are installed in /usr/local/bin/.
+
+Scripts are installed in /usr/local/share/xastir/scripts.
+
+Maps are installed in /usr/local/share/xastir/maps/. Lots of other
+directories are under /usr/local/share/xastir/.
+
+
+More?
+-----
+Anything else? Let's hear about what's still confusing or needs to
+be expanded in this document. Thanks!
+
+
+APRS(tm) is a Trademark of Bob Bruninga
+
+Copyright (C) 2005-2012 The Xastir Group
+
diff --git a/README.MAPS b/README.MAPS
new file mode 100644
index 0000000..6337229
--- /dev/null
+++ b/README.MAPS
@@ -0,0 +1,1518 @@
+
+$Id: README.MAPS,v 1.106 2012/03/02 20:28:17 we7u Exp $
+
+
+Recommended Configurations for:
+
+ U.S. Users:
+ -----------
+
+ Minimum: Shapelib, pcre
+ --------
+ Allows use of all built-in map types plus 2003 (and later) Tigermap data,
+ shapefile weather alerts, and local ESRI Shapefile format
+ maps, including U.S. satellite/image/topo maps via Internet.
+
+ Medium: Shapelib, pcre, lcms, ImageMagick, libcurl/wget,
+ -------
+
+ Allows use of all the above plus Internet maps and local image
+ maps.
+
+ Maximum: Shapelib, pcre, lcms, ImageMagick, libcurl/wget,
+ -------- libtif, libproj, libgeotiff
+
+ Allows use of all the above plus USGS topo maps.
+
+ Bleeding edge: GDAL/OGR
+ --------------
+ Adds more map types, but they're not fully supported yet. You
+ can certainly get some use out of them though, like overlaying
+ SDTS contour vectors on top of terraserver satellite images.
+
+ Rest of World:
+ --------------
+
+ Minimum: lcms, ImageMagick, libcurl/wget
+ --------
+ Allows use of all built-in map types plus local and Internet
+ image maps, including Canadian topo maps via Internet.
+
+ Medium: lcms, ImageMagick, libcurl/wget, Shapelib, pcre,
+ -------
+
+ Allows use of all the above plus ESRI Shapefile maps.
+
+ Maximum: libproj/libtiff/libgeotiff/GDAL/OGR
+ --------
+ Adds more map types. Some of these may not be useful in your
+ part of the world. GDAL/OGR stuff is not fully supported yet.
+
+
+Map Type: Libraries Required/Notes:
+--------------- -------------------------
+DosAPRS Built-in.
+WinAPRS Built-in.
+X-APRS Built-in.
+MacAPRS Built-in.
+PocketAPRS Built-in.
+USGS GNIS Built-in. Can split into county-sized chunks
+ using xastir/scripts/split_gnis.pl to speed
+ things up.
+Address Lookup Built-in.
+Weather Alerts Shapelib
+pre-2003 Tigermaps Shapelib
+post-2003 Tigermaps Shapelib, pcre
+ESRI Shapefiles Shapelib
+Image Maps ImageMagick. Often need lcms library and others
+ as well (whatever it takes to make ImageMagick
+ happy). Can also use the XPM library for some
+ image types without installing ImageMagick.
+Internet Maps ImageMagick plus wget or libcurl. Often need
+ lcms library and others as well (whatever it
+ takes to make ImageMagick happy).
+UI-View Maps Convert from .INF to .GEO format using
+ xastir/scripts/inf2geo.pl
+OziExplorer Maps Convert some maps to .GEO format using
+ xastir/scripts/ozi2geo.pl
+USGS DRG Topo libtiff, libtiff-devel, libproj, libgeotiff
+USGS SDTS GDAL/OGR. Preliminary.
+MapInfo GDAL/OGR. Preliminary.
+Tiger/Line Raw GDAL/OGR. Preliminary.
+Microstation DGN GDAL/OGR. Preliminary.
+S57 GDAL/OGR. Preliminary.
+APRS Overlays Convert to Shapefile maps with scripts/pos2shp.pl
+
+
+The default map, "worldhi.map", is used with permission of its creator, Keith Sproul, WU2Z.
+
+
+How to Use APRS Overlay Maps (*.POS files) within Xastir:
+---------------------------------------------------------
+ Use the "xastir/scripts/pos2shp.pl" script to convert the
+ overlay files to ESRI Shapefile maps:
+
+ # ./pos2shp.pl test.pos testmap
+ # cp testmap* /usr/local/share/xastir/maps/.
+
+ Xastir: Map->Configure->Index: Add New Maps
+ Map Chooser: Select the "testmap" map
+
+
+Getting Maps and other Data Files for Xastir:
+---------------------------------------------
+
+ NOTE: Set map FILES to permissions 644 ("rw-r--r--"), map
+ DIRECTORIES to 755 ("rwxr-xr-x") using the "chmod" command.
+ These permissions will allow anyone on the box to read the map
+ files, and access the map directories. Type these
+ commands exactly as shown in order to set the map directory's
+ permissions properly. Do this as the root user:
+
+ cd /usr/local/share/xastir/maps
+ find . -type d -exec chmod 755 {} \;
+ find . -type f -exec chmod 644 {} \;
+
+ You can repeat these commands at anytime, to fix up errant map
+ permissions that are created by downloading/installing new
+ maps.
+
+ Currently the maps/GPS directory needs to be writable by normal users
+ in order to support downloading GPS data using GPSMan. This will be
+ changed at some future date, moving this directory into the user's
+ home directory instead.
+
+ cd /usr/local/share/xastir/maps
+ chmod 777 GPS
+ find GPS -type d -exec chmod 777 {} \;
+ find GPS -type f -exec chmod 777 {} \;
+
+
+
+ Download some maps:
+
+ If you compiled with ImageMagick and have wget or libcurl installed,
+ you can skip this step and use the online Tiger/Terraserver maps
+ exclusively. However, having maps on your computer is often faster
+ than transferring images over a modem, and is not subject to the
+ failures of your Internet connection. See the section below on map
+ caching for an exciting feature that works with most online maps to
+ really speed things up!
+
+ You can have any number of maps in the /usr/local/share/xastir/maps
+ directory. You can organize the maps however you like. You can also
+ use symbolic links to link to files/directories on other disks. Map
+ files are loaded in the order that they appear in the chooser unless
+ you adjust the layering priorities in the "Properties" dialog (it's
+ recommended that you use these now instead of a directory hierarchy to
+ choose the layering).
+
+ There are many methods for organizing many maps. Create a map
+ hierarchy using something that makes sense to you. The old method of
+ creating transparent/filled or raster/vector directories has been
+ superceded by the new map layering features in the Map
+ Chooser->Properties dialog. It's now suggested that the map layering
+ be done there, and the directory layout designed to make it easiest
+ for the user to select maps. Perhaps a good start would be:
+
+ World/
+ Canada/
+ Canada/Province/
+ USA/
+ USA/State/WA/
+ USA/State/WA/County/
+ ...
+ GNIS/
+ Overlay/
+
+ Please note that the map directories are entirely up to the user
+ now. Use the map layering facilities (Map Chooser->Properties) to
+ determine the order in which they will be drawn, and to determine
+ which will draw filled areas. Note that raster maps will always draw
+ filled, not matter what the setting suggests. For vector maps, you
+ have a choice of:
+
+ Fill = No Polygons will never be filled
+ Fill = Yes Polygons will always be filled
+ Fill = Auto Polygon fill is determined by map (or if it's a
+ Shapefile, by any associated dbfawk file).
+
+ Map types available by extension:
+
+ Vector Format:
+ .shp/.shx/.dbf Shapefile vector map (need all three files)
+ .pdb PocketAPRS vector map
+ .map APRSdos/WinAPRS/MacAPRS vector map
+ .gnis GNIS labels file (actually points instead of vectors)
+ .geo Vector map or Internet vector map. Note that for
+ http/ftp-based maps Xastir requires an IMAGESIZE line.
+
+ Raster Format:
+ .tif/.fgd geoTIFF raster image map
+ .geo Raster image map or Internet raster image map. Note that
+ for http/ftp-based maps Xastir requires an IMAGESIZE line.
+
+ Note: .geo is listed twice because it can fit in both categories,
+ depending on the base format of the map file that the .geo file
+ points to. .geo files are handled by the XPM library or by
+ ImageMagick, so most anything that can be handled by those installed
+ libraries can by handled by Xastir.
+
+ A few maps of various types are available from:
+
+ http://wetnet.net/~we7u/xastir/maps/
+
+ Here's a page that we'll try to keep up-to-date which will have lots of
+ links to download-able maps on it:
+
+ http://www.xastir.org/wiki/index.php/Xastir_Maps
+
+ Dos/Win/MacAPRS style vector/fill maps:
+
+ http://www.winaprs.com/Maps.htm
+ http://www.cnunix.com/ftp/hamradio/rutgers.mirror/maps/maps2/
+ ftp://ftp.tapr.org/aprssig/maps/
+
+ WORLDHI.MAP is suggested as a basic view of the world map.
+
+ You can use any of the other maps available from this site. Many of
+ them were created from Tiger/Line maps, but they are several years out of
+ date. It is suggested that you don't use these as your primary
+ street-level maps; the newer shapefile-based maps are usually preferable.
+ In cases where you cannot compile shapefile support, these maps suffice.
+
+
+ PocketAPRS vector maps:
+
+ The WinAPRS 2.51 distribution included the full collection of
+ PocketAPRS vector maps for the USA. The download is about 60MB, from the
+ TAPR ftp site.
+
+ ftp://ftp.tapr.org/aprssig/winstuff/WinAPRS/waprs251.zip
+
+
+ Raster Maps:
+
+ For Canada there is a country wide set of topographic map images available
+ from the "Department of Natural Resources Geomatics Canada". Running
+ /scripts/toporama250k.pl will pull down 430mb of 1:250k map images
+ from that departments site. If thats not enough data, running
+ /scripts/toporama50k.pl will pull down around 10gigs
+
+**** Note that recent changes at the "Department of Natural Resources Geomatics
+Canada" have made these scripts fail. Changes to the scripts are being coded
+and tested. CVS well be updated once the scripts are proven to work again. ****
+
+
+ For Ireland, EI8IC (http://www.mapability.com) has produced a set of overlay
+ maps that show the County Borders, Main Towns and Roads. John, EI7IG, has
+ created a set of ".geo" files to go with them and they are all available in one
+ tarball from [http://ireland.aprs2.net/xastir/IrelandMaps/Ireland.tar.gz
+ ireland.aprs2.net] They are free for non-commercial use.
+
+ Also available are a map of the
+ [http://ireland.aprs2.net/xastir/IrelandMaps/Ireland1600x2000.bmp country], with
+ an associated [http://ireland.aprs2.net/xastir/IrelandMapsIreland1600x2000.geo
+ geo] file, the [http://ireland.aprs2.net/xastir/IrelandMaps/Ireland1600x2000.bmp
+ South East], it's associated
+ [http://ireland.aprs2.net/xastir/IrelandMapsIreland1600x2000.geo geo] and a
+ [http://ireland.aprs2.net/xastir/IrelandMaps/IrishMET.geo Weather Radar] .geo file.
+
+
+ Shapefile format maps (Requires shapefile support):
+
+ Shapefile format maps are slowly becoming the standard vector format of
+ maps used with Xastir. Xastir 1.3.2 and above by default enable dbfawk
+ support for parsing shapefile metadata, see below.
+
+ A nice world map is available at http://aprsworld.net/gisdata/world/
+ thanks to James Jefferson, TerraSpace, Russia, and the Digital Chart
+ of the World (for Antarctica). Note that this file is currently
+ available only in uncompressed or in tar/bzip2 format. To decompress
+ the latter file, you'd type "bunzip2 filename" and then
+ "tar xvf filename".
+
+ TIGER/Line Shapefiles:
+
+ Tiger/Line 2006 Second Edition data converted to shapefile format is
+ available from ftp://aprs.tamu.edu/. Look in the "pub/TIGER_2006_SE"
+ directory. These maps only work with dbfawk support
+
+ Unpack the zipfiles in your maps directory. I recommend creating
+ a "TIGER_2006_SE" subdirectory or something similar, and unpacking
+ the zipfile there. When unpacked, each state zipfile will produce
+ a directory with the state's postal abbreviation as its name, and
+ two subdirectories, "Polylines" and "Polygons." These directories
+ each contain shapefiles with different information in them --- Polylines
+ are linear features such as roads and streams, Polygons are area features
+ such as parks and airports. You need both, even though they have the
+ same names (the name of the county they cover).
+
+ You can also create your own TIGER/Line shapefiles from the raw
+ data at the Census web site,
+ http://www.census.gov/geo/www/tiger/index.html.
+ The process requires two conversions: converting the linear
+ features, and assembling the polygon features. The TIGER/Line data is
+ a topological format, and polygons are not stored in a simple manner;
+ this second step is time consuming.
+
+ To convert the polylines:
+ Download the county files you want. Then unzip each one into its
+ own directory (call it "in_directory"). Then cd to in_directory and
+ run the following command:
+
+ ogr2ogr -f "ESRI Shapefile" -t_srs EPSG:4326 foo .
+
+ This will create a subdirectory of in_directory called "foo" which
+ will contain a number of shapefiles and auxiliary data. The files
+ called "CompleteChain.*" are the ones you want; they are the polylines
+ corresponding to roads and other linear features. Copy these to your
+ xastir maps directory and rename them to the name of the county they
+ represent. Then install tgr2shp.dbfawk in your share/xastir/config
+ directory and reindex maps. Ta da. See above: tgr2shp.dbfawk is now
+ part of the xastir distribution..."
+
+ Note that you'll need dbfawk support compiled into Xastir to make
+ these Tiger/Line maps look nice. For the 2003 TIGER/Line data,
+ Derrick Breshear created scripts to process all of the Tiger/Line raw
+ data into Shapefiles, then they were put on a download site made
+ available by Kevin Glueck, "http://xastir.tamu.edu/". The 2006 Second
+ Edition data were processed by Jason Winningham and made available on
+ the ftp://aprs.tamu.edu/ site by Gerry Creager. Thanks go to Tom,
+ Derrick, Kevin, Jason and Gerry for making these maps so accessible to
+ the rest of us.
+
+ The second step to rolling your own TIGER/Line shapefiles is to
+ assemble the polygons. This requires GDAL/OGR configured with python
+ support, and requires that you have the Python language installed.
+ Use the script Xastir_tigerpoly.py included in the "scripts" directory
+ of Xastir's source tree.
+
+ As an example, if you have un-zipped the file TGR35001.zip (the
+ TIGER/Line file for Bernalillo County, NM) into a directory called
+ TGR35001, then
+
+ Xastir_tigerpoly.py TGR35001 Bernalillo_County_NM_Polys.shp
+
+ would create a shapefile of TIGER polygons (water bodies, political
+ boundaries, parks, wilderness areas) that you can install in your maps
+ directory and read directly using normal shapefile support.
+
+ Viewing these shapefiles as filled polygons requires dbfawk support,
+ and the rules for displaying them are contained in the file
+ tgr2shppoly.dbfawk.
+
+
+ Tiger/Line 2000 map data is available from:
+ http://www.esri.com/data/download/census2000_tigerline/index.html
+ but requires free registration. A example of these types of files can
+ be found at "http://wetnet.net/~we7u/xastir/maps/shapefile/USA/WA/".
+ You'll need to run "tar xzvf <filename>" on each one of the files
+ from that last site after downloading. Some layers that may be of
+ interest:
+
+
+ CMSA/MSA Polygons 2000 tgr*msa00.shp
+ PMSA Polygons 2000 tgr*pms00.shp
+ Consolidated Cities tgr*city.shp
+ County - Current tgr*cty.shp
+ County 2000 tgr*cty00.shp
+ Designated Places 2000 tgr*plc00.shp
+ Designated Places Current tgr*plccu.shp
+ Key Geographic Locations tgr*kgl.shp
+ Landmark Points tgr*lpt.shp
+ Landmark Polygons tgr*lpy.shp
+ Line Features - Hydrography tgr*lkH.shp
+ Line Features - Landmarks tgr*lkD.shp
+ Line Features - Misc. Transport tgr*lkC.shp
+ Line Features - Non-visible tgr*lkF.shp
+ Line Features - Physical tgr*lkE.shp
+ Line Features - Rails tgr*lkB.shp
+ Line Features - Roads tgr*lkA.shp
+ Line Features - Unknown tgr*lkX.shp
+ School Districts - Elementary tgr*elm.shp
+ School Districts - Middle tgr*mid.shp
+ School Districts - Secondary tgr*sec.shp
+ School Districts - Unified tgr*uni.shp
+ Traffic Analysis Zones tgr*taz.shp
+ Urban Areas tgr*urb.shp
+ Water Polygons tgr*wat.shp
+ Alternate Feature Names tgr*alt.shp
+ Address Matching Info tgr*add2.shp
+ ZIP+4 Left and Right Info tgr*zip.shp
+ Key Geographic Location Addresses tgr*add.shp
+ Landmark Polygon Names tgr*lpy2.shp
+ Landmark Polygons Multi-Landmark tgr*lpy3.shp
+ Water Polygons Multi-Names tgr*wat2.shp
+
+ Older Tiger97 maps converted to shapefile download-able from:
+ http://www.mapshots.com
+
+ Some other shapefile format maps are available at:
+ http://www.nws.noaa.gov/geodata/
+
+ Still other shapefiles are available from esri.com, geographynetwork.com
+ and gisdatadepot.com (from their "free data" link). Lot's of useful
+ stuff at these sites, just look around. You can also check
+ with your County GIS office for shapefiles of your county. You can
+ convert them from State Plane to Lat/Long projection using
+ instructions later in this document.
+
+ Canada street maps in Shapefile format are available at
+ http://www.geobase.ca
+
+ If you also use GeoTIFF images, get the handy usgs_24kgrid.zip file from
+ http://data.geocomm.com/quadindex/. This file provides a grid of all of
+ the 7.5' maps and their names for the U.S.
+
+ A nice world map is available at http://aprsworld.net/gisdata/world/
+ thanks to James Jefferson, TerraSpace, Russia, and the Digital Chart
+ of the World (for Antarctica). Note that this file is currently
+ available only in uncompressed or in tar/bzip2 format. To decompress
+ the latter file, you'd type "bunzip2 filename" and then
+ "tar xvf filename".
+
+ www.bts.gov has the "National Transportation Atlas" that you can download
+ pieces of (at least for the larger layers) or ask for (free) CD-ROM's to be
+ mailed to you.
+
+ -----
+ Re-projecting shapefiles (or: why doesn't my shapefile show up?)
+
+ A shapefile is pretty much just a collection of points and lines
+ between points. Xastir expects that those points are expressed in
+ degrees of longitude and latitude with positive values indicating N
+ and E and negative values indicating S and W.
+
+ One often comes across shapefiles with data in some other format, such
+ as UTM or state-plane projections with units in meters or feet. You
+ must re-project these sorts of shapefiles in order to use them in
+ Xastir. You must either know what the current format is of the
+ shapefile you wish to re-project, or have the .prj file that some
+ shapefiles come with.
+
+ Fortunately, the shapelib-1.2.10 distribution (which you probably
+ compiled and installed to enable shapefile maps in Xastir) includes a
+ tool for performing this re-projection.
+
+ First make the shpproj utility by:
+
+ 1. change to directory: <shapelib source directory>/contrib
+ 2. type 'make' to compile the contrib files
+ 3. Optionally install shpproj by copying it to /usr/local/bin
+
+ shpproj takes 4 arguments:
+
+ shpproj shp_file new_shp -i="in_params" -o="out_params"
+
+ shp_file is the name of your existing shapefile triad (without the
+ extension).
+
+ new_shp is the name of your new shapefile triad (which doesn't exist
+ yet).
+
+ -i="in_params" are the parameters describing the existing shapefile.
+
+ -o="out_params" are the parameters describing the new shapefile. We
+ want this to be "geographic".
+
+ Examples:
+
+ Convert shapefile triad from US State-plane, South Central Texas region
+ (FIPS code 4204), in feet to geographic:
+
+ shpproj stateplane_shapefile geographic_shapefile \
+ -i="init=nad83:4204 units=us-ft" -o=geographic
+
+ Convert UTM zone 15 to geographic:
+
+ shpproj utm_shapefile geographic_shapefile \
+ -i="proj=utm zone=15 units=m" -o=geographic
+
+ To get a listing of the FIPS codes, you need to have proj installed
+ (see elsewhere in this file for more information). Look in the
+ "<proj source directory>/nad/nad.lst" file.
+
+ For more detailed documentation, see the shpproj.txt file in the
+ "<shapelib source directory>/contrib/doc" directory.
+
+ There's a resource for looking up the FIPS codes for a particular
+ area:
+
+ http://www.aprs.net/fips/
+
+ An important note about using shpproj to re-project maps
+
+ The shpproj program cannot be used to convert shapefiles unless they're
+ already using the NAD83 or WGS84 datum. shpproj will do the conversion
+ if you ask it to, but it will do it incorrectly.
+
+ A simple program to convert shapefiles between various projections
+ that does do datum conversions correctly is "shpcs2cs," available
+ from
+ <http://www.swcp.com/~russo/shape_web/>
+ That program requires libproj to be installed properly, and uses a
+ command line format similar to the "cs2cs" program that comes with
+ libproj.
+
+ If you already have GDAL installed, you should have the "ogr2ogr"
+ program available to you. ogr2ogr will not only convert projections
+ and geodetic datum correctly, but will also convert format (ArcView
+ binary format to shapefile, TIGER/Line files to shapefile, etc.).
+ Some detailed instructions for using ogr2ogr to do this conversion
+ are available at
+ <http://www.swcp.com/~russo/shape_web/>
+
+ -----
+
+ Using "dbfawk" to interpret shapefile DBF data: Each shapefile
+ map (*.shp, *.shx) comes with a DBase data file (*.dbf) in which
+ each shape in the .shp file has a corresponding set of descriptive
+ data about that shape in the .dbf file. While shapefiles are all
+ a standard format and will most always draw (possibly after having
+ been re-projected with shpproj), the corresponding .dbf data varies
+ widely depending on the data source. For example, US Census
+ Tiger/Line files contain 20 attributes for each shape including such
+ values as the name of the shape (i.e. street name), and a "Census
+ Feature Class Code" (CFCC) which indicates whether a shape is a
+ dirt road or a superhighway, for example.
+
+ In "pre-dbfawk" Xastir, knowledge of the various sources of
+ shape files was built into the program and it was necessary to
+ add code to support new shapefile sources (such as those
+ produced by local government agencies, non-US, etc.). Xastir
+ with dbfawk moves this logic into metadata files named *.dbfawk.
+ These files are linked to the .shp/.dbf files they belong with in
+ one of two ways:
+ 1. "Signature" recognition. .dbfawk files located in the config/
+ directory are read to find the "dbfinfo" signature, which is
+ simply the ordered list of attribute names found in the .dbf file.
+ If you browse config/*.dbfawk you will see dbfawk's for the most
+ well know shapefile types. For example, tgrlk.dbfawk matches
+ all the "tgr*lk?.dbf" US Census Tiger/Line files. When a shapefile
+ map is displayed, it's .dbf signature is matched up with one of
+ the config/*.dbfawk files.
+ 2. "Tied" to a file. If you installed a .dbfawk file in the same
+ directory as the .shp and .dbf files (e.g. sample.shp, sample.dbf
+ get a corresponding sample.dbfawk) then that file is used instead
+ of signature matching.
+ The first method allows a single .dbfawk file to be automatically
+ used for hundreds of standard shapefile maps. The later allows you
+ to customize how your particular shapefile map displays.
+
+ What's in a .dbfawk file? The best documentation of these files
+ is found by looking at the commented examples in config/*.dbfawk.
+ dbfawk is modeled after the "awk" pattern scanning and processing
+ language -- but, it is *not* exactly awk:
+ - Regular expression syntax is that used by Perl (the pcre library
+ is used) rather than pure awk.
+ - Action statements are much more limited than full-blown awk.
+ - The concept of records and fields is used since a .dbf record
+ is structured of usually several fields (name, feature type, etc.).
+ That said, what dbfawk does is allow a great degree of control of
+ how and when shapes and their names are displayed. This is done by
+ setting the values of several "builtin" variables [Technically, these
+ are only built-in to shapefile support. Potentially the awk-like
+ code can be extended to other uses.]:
+ dbfinfo: the "signature" to match against.
+ dbffields: which fields to read from the .dbf file.
+ color: what color code to display the shape with.
+ lanes: width of the shape.
+ name: name of the shape.
+ key: search key (used for WX alerts to find the shape)
+ symbol: symbol for landmarks, etc.
+ filled: draw polygons filled. Filled="Yes" or "No" in the Map
+ Properties dialog will override this option. Set to "Auto"
+ in that dialog to have the dbfawk file control this.
+ fill_style: style of fill (0=solid, 1=FillTiled, 2=FillStippled, etc.)
+ fill_color: color of fill
+ fill_stipple: stipple pattern if fill_style=2 ("FillStipple")
+ 0=13 percent, 1=25 percent, 2=50 percent.
+ pattern: solid or dashed lines.
+ display_level: at what zoom level to begin displaying the shape
+ label_level: at what zoom level to begin displaying labels
+ label_color: color to use for labels
+
+ Execution of a dbfawk file: Just like awk, the file consists of
+ patterns that are matched against input data and actions to take
+ when the pattern matches. There are four special patterns in dbfawk:
+ BEGIN_RECORD: action is executed just before parsing a record.
+ BEGIN: action is executed just before parsing a field.
+ END: action is executed just after parsing the field.
+ END_RECORD: action is executed just after parsing a record.
+ All other patterns are regular expressions that are matched against
+ a data value of <fieldname>=<value>. For example:
+ FENAME=Main
+
+ Actions in dbfawk files consist of setting variables and two special
+ actions:
+ next: skips to the next field in the record.
+ skip: skips to the next record.
+ If neither next nor skip is given in the action, then processing falls
+ through to the next pattern/action pair in the dbfawk file.
+
+ The special dbffields variable is used to list which fields of the
+ record to be processed and in what order. The order is significant
+ since it may take several DBF fields to build up a complete name.
+ For example, in Tiger/Line, the street name is actually the
+ concatenation of FEDIRP, FENAME, TYPE, FEDIRS. Here's an excerpt
+ from tgrlk.dbfawk to demonstrate:
+ BEGIN {dbffields="TLID:FEDIRP:FENAME:FETYPE:FEDIRS:CFCC"}
+ ...
+ /^FEDIRP=(.+)$/ {name="$1 ";next}
+ /^FENAME=United States Highway (.*)$/ {name="$(name)US $1"; next}
+ /^FENAME=State Highway (.*)$/ {name="$(name)State $1";next}
+ /^FENAME=State Route (.*)$/ {name="$(name)SR $1";next}
+ /^FENAME=(.*)$/ {name="$(name)$1; next}
+ /^FETYPE=(.+)$/ {name="$(name) $1"; next}
+ /^FEDIRS=(.+)$/ {name="$(name) $1"; next}
+
+ Creating and testing dbfawk files: You can test an existing dbfawk
+ file by setting debug level 16 in Xastir (this will generate a huge
+ amount of map rendering debug output, including dbfawk info):
+ "./xastir -v 16 2>/tmp/log"
+ Or, use "testdbfawk" which reads a .dbf file (or single field assignments
+ on the command line). For example:
+ testdbfawk -D . -d tgr36119lkA.dbf 2>&1|less
+ 20 Columns, 42427 Records in file
+ sig: TLID:FNODE:TNODE:LENGTH:FEDIRP:FENAME:FETYPE:FEDIRS:CFCC:FRADDL:TOADDL:FRADDR:TOADDR:ZIPL:ZIPR:CENSUS1:CENSUS2:CFCC1:CFCC2:SOURCE
+ DBF Signatures match!
+ name=Hancock Ave, key=80309984, symbol=, color=40, lanes=1, filled=0, pattern=1,display_level=96,label_level=16
+
+ testdbfawk takes the following command line syntax:
+ testdbfawk --help
+ Prints command line usage
+ testdbfawk -D directory -d file.dbf
+ Scans directory for dbfawk files with signatures matching file.dbf,
+ runs the dbfawk program that matches if it's found.
+ testdbfawk -f file.dbfawk -d file.dbf
+ runs the dbfawk file "file.dbfawk" over the dbf file "file.dbf"
+
+ So in the example above, testdbfawk scans the current directory
+ for dbfawk files with signatures that match tgr36119lkA.dbf's
+ signature. testdbfawk dumps its output to standard error, so in
+ the example standard error is redirected to standard out and
+ piped into "less" for paging.
+
+ To create a .dbfawk file, you need to understand the layout and contents
+ of your .dbf file. Use "dbfinfo" and "dbfdump" which are in the shapelib
+ contrib directory. Dbfinfo will list the field names and dbfdump will
+ dump out all fields of all records. Take the field names from dbfinfo,
+ and concatenate them together in order, separated by ":" to make the
+ dbfinfo= signature variable assignment.
+
+ Your best bet is to start with an existing .dbfawk file as an example.
+
+ Dbfawk hints and kinks: You have to think like an awk programmer and
+ realize that the order that rules are listed matters, that it's important
+ to use "next" as soon as it makes sense so other rules aren't looked at
+ unnecessarily and, to use "skip" when you want to fix bad dbf data.
+ For example, my county's Tiger/Line maps have several coding errors
+ where a segment of a main highway is incorrectly labeled as a local
+ street. This rule overrides one of those incorrect records:
+ # This Furnace Dock Rd segment is really Rt 9!
+ /^TLID=139773160$/ {name="Briarcliff-Peekskill Pky"; display_level=8192; label_level=512; color=4; lanes=4; skip;}
+ TLID is the Tiger/Line ID which is the unique identifier for this
+ segment.
+ -----
+
+ Rolling your own shapefile maps:
+
+ It is relatively easy to create your own shapefile maps (for example,
+ if you want to highlight a walk-a-thon course). There are several
+ methods available with Xastir:
+
+ 1. Use GPSMan to download a GPS track to a shapefile.
+
+ 2. Save a station tracklog of an actual station or an object that
+ you manually move along the course. When you select Station Info,
+ you are presented with the option to save the track, which gets
+ put in
+ .xastir/tracklogs/<datestamp>_<callsign>_APRS_Trail_<color>.*
+ You can move the .shp, .shx, and .dbf files to your maps directory.
+ Use DBFAWK to make a map-specific .dbfawk file. For example:
+ BEGIN {dbfinfo="Credits:DateTime";dbffields="Credits:"}
+ BEGIN_RECORD {key=""; lanes=4; color=12; name=""; filled=0;
+ pattern=1; display_level=8192; label_level=32; symbol=""}
+ This makes the track width 4 and red (12).
+
+ 3. You can use xastir's "object" capability to generate shapefile maps.
+ a) Turn off object transmission using
+ Interface->Disable Transmit:Objects
+ b) Put objects where you want. Set the display symbol as you like it.
+ c) run the "object2shp.pl" script in the scripts directory
+ (/usr/local/share/xastir/scripts/object2shp.pl in most installations)
+ to generate a shapefile:
+ /usr/local/share/xastir/scripts/object2shp.pl ~/.xastir/object.log myshape
+ This requires the four shapelib utilities "dbfcreate", "shpcreate",
+ "shpadd" and "dbfadd" as described below.
+ d) EXIT XASTIR
+ e) REMOVE ~/.xastir/config/object.log
+ f) move "myshape.shp," "myshape.shx," and "myshape.dbf" to your maps
+ directory.
+ g) restart xastir.
+ h) select your newmap in the map chooser.
+ Creating maps in this way is basically just a scripted version of the
+ manual map generation technique in (4) below.
+
+ 4. You can also use the shapelib tools (shpproj was presented earlier)
+ to manually create a shapefile. For example, the following
+ marks out the mile-posts for a marathon, using tgrlpt.dbfawk
+ (US Census Tiger/Line landmark points with an APRS(tm) symbol extension)
+ for the metadata:
+ #!/bin/sh
+ # turn mileposts into a Tiger landmark shapefile
+
+ rm -f posts.shp posts.dbf
+ shpcreate posts point
+ dbfcreate posts -n ID 8 0 -s CFCC 3 -s NAME 30
+ shpadd posts -74.0570 40.6025
+ dbfadd posts 1 'X\m ' Start
+ shpadd posts -74.0443 40.6065
+ dbfadd posts 2 'X\m ' 1M
+ shpadd posts -74.0353 40.6093
+ dbfadd posts 3 'X\m ' 2M
+ shpadd posts -74.0268 40.6260
+ dbfadd posts 4 'X\m ' 3R
+ shpadd posts -74.0200 40.6277
+ dbfadd posts 5 'X\m ' 3G
+ shpadd posts -74.0270 40.6252
+ dbfadd posts 6 'X\m ' 3B
+ shpadd posts -74.0197 40.6395
+ dbfadd posts 7 'X\m ' 4R
+ shpadd posts -74.0203 40.6388
+ dbfadd posts 8 'X\m ' 4BG
+ shpadd posts -74.0077 40.6508
+ dbfadd posts 9 'X\m ' 5R
+ shpadd posts -74.0083 40.6503
+ dbfadd posts 10 'X\m ' 5BG
+ shpadd posts -73.9957 40.6623
+ dbfadd posts 11 'X\m ' 6R
+ shpadd posts -73.9962 40.6617
+ dbfadd posts 12 'X\m ' 6BG
+ shpadd posts -73.9850 40.6743
+ dbfadd posts 13 'X\m ' 7R
+ shpadd posts -73.9858 40.6738
+ dbfadd posts 14 'X\m ' 7BG
+ shpadd posts -73.9782 40.6865
+ dbfadd posts 15 'X\m ' 8M
+ shpadd posts -73.9597 40.6890
+ dbfadd posts 16 'X\m ' 9M
+ shpadd posts -73.9573 40.7007
+ dbfadd posts 17 'X\m ' 10M
+ shpadd posts -73.9622 40.7122
+ dbfadd posts 18 'X\m ' 11M
+ shpadd posts -73.9515 40.7230
+ dbfadd posts 19 'X\m ' 12M
+ shpadd posts -73.9520 40.7345
+ dbfadd posts 20 'X\m ' 13M
+ shpadd posts -73.9525 40.7465
+ dbfadd posts 22 'X\m ' 14M
+ shpadd posts -73.9403 40.7503
+ dbfadd posts 23 'X\m ' 15M
+ shpadd posts -73.9578 40.7587
+ dbfadd posts 24 'X\m ' 16M
+ shpadd posts -73.9556 40.7675
+ dbfadd posts 25 'X\m ' 17M
+ shpadd posts -73.9465 40.7808
+ dbfadd posts 26 'X\m ' 18M
+ shpadd posts -73.9372 40.7935
+ dbfadd posts 27 'X\m ' 19M
+ shpadd posts -73.9272 40.8047
+ dbfadd posts 28 'X\m ' 20M
+ shpadd posts -73.9343 40.8142
+ dbfadd posts 29 'X\m ' 21M
+ shpadd posts -73.9453 40.8050
+ dbfadd posts 30 'X\m ' 22M
+ shpadd posts -73.9525 40.7923
+ dbfadd posts 31 'X\m ' 23M
+ shpadd posts -73.9630 40.7810
+ dbfadd posts 32 'X\m ' 24M
+ shpadd posts -73.9720 40.7696
+ dbfadd posts 33 'X\m ' 25M
+ shpadd posts -73.9811 40.7683
+ dbfadd posts 34 'X\m ' 26M
+ shpadd posts -73.9763 40.7720
+ dbfadd posts 35 'X\m ' Finish
+ ---------
+
+ Splitting large Shapefile maps into regularly-sized tiles:
+
+ Look for "shp2tile" at http://imaptools.com/tools/, it does
+ exactly that. This can speed up Xastir tremendously if you're
+ zoomed in quite a bit on a large Shapefile map (or maps). If
+ it is broken into tiles Xastir only has to load the tiles of
+ interest instead of slogging through the entire large file
+ each time.
+
+
+ GeoTIFF Map files (requires GeoTIFF):
+
+ If you compiled in geoTIFF support, you can use USGS DRG topographic
+ maps. These are primarily useful to U.S. users. DRG topo maps can be
+ found for free for most states, and can be purchased for others.
+
+ http://www.bianifc.org/gis_gps/gps/drgfree.html
+ http://www.gisdatadepot.com
+
+ or try a google search with "free drg maps" as the search query.
+
+ If you have no luck finding free DRG maps, go to
+ http://www.geocomm.com/ and check out the "DRG Data Bundles"
+ they have available. You can purchase a DVD containing all the
+ DRGs for an entire state in three scales, all of them usable in
+ xastir, for a relatively low price. Be warned, however, that
+ parts of the US have DRGs that are produced by an agency other
+ than the United States Geological Survey, and these DRGs are not
+ necessarily in correct GeoTIFF format. The areas covered by the
+ Tennessee Valley Authority appear to be among those, as one
+ xastir user discovered when purchasing a DVD of DRGs for North
+ Carolina. It is still possible to use these DRG files, but they
+ need preprocessing. See the section below entitled "Defective
+ GeoTIFF files need even more special processing."
+
+ Many useful US maps can be downloaded from the National Map Viewer:
+ http://nmviewogc.cr.usgs.gov/viewer.htm
+
+ Free FAA sectional charts can be downloaded from
+ http://aviationtoolbox.org/raw_data/FAA_sectionals/current/
+ This site was set up by someone who had a subscription to the FAA
+ DVD collection and made them available on the web (this is legal per
+ FAA's terms of use). They are no longer being updated as of mid 2005.
+ These charts are in Lambert Conformal Conic projection, though, and
+ need to be converted with gdalwarp to be usable in xastir (see below).
+
+ Current, valid-for-navigation FAA sectional charts may be purchased
+ from the FAA at
+ https://naco.faa.gov/ecomp/Catalog.aspx?a=AERO+NOS+DIGITAL
+ for about $1.50US each. These files are also in GeoTIFF and are the
+ same type as those that are available on aviationtoolbox, but these are
+ updated every 6 months and are kept current. You will have to process
+ them before viewing in xastir.
+
+ The 7.5' topo maps work the best so far. Be sure to install the .tif AND
+ the .fgd files side-by-side into the map directories. Without the .fgd
+ file Xastir won't be able to crop the white border from the map. Xastir
+ currently knows how to handle NAD27, NAD83, and WGS84 geoTIFF files.
+ GeoTIFF files created in other datums will be displayed at an incorrect
+ location with Xastir. The .tfw files included with most geoTIFF images
+ are not used by Xastir.
+
+ If you must make FGD files by hand, the included script mapfgd.pl can
+ create them for you from the USGS geoTIFF files. The format Xastir is
+ looking for is the following:
+
+ 1.5.1.1 WEST BOUNDING COORDINATE: -122.000000
+ 1.5.1.2 EAST BOUNDING COORDINATE: -120.000000
+ 1.5.1.3 NORTH BOUNDING COORDINATE: 48.000000
+ 1.5.1.4 SOUTH BOUNDING COORDINATE: 47.000000
+
+ -or-
+
+ 1.5.1.1 West_Bounding_Coordinate: -122.000000
+ 1.5.1.2 East_Bounding_Coordinate: -120.000000
+ 1.5.1.3 North_Bounding_Coordinate: 48.000000
+ 1.5.1.4 South_Bounding_Coordinate: 47.000000
+
+ Notes about DRG-Enhanced (DRG-E) files:
+ * The DRG-E files will draw over the correct spots if you remove
+ the .fgd file, but will overflow their boundaries and
+
+ * The DRG-E files will draw over the correct spots with decent
+ boundary trimming (as far as I can tell, which isn't very far:
+ correct me!) if you use a .fgd file taken from 'real' DRG files
+ from USGS.
+
+ Basically: get rid of the .fgd file from the DRG-E!!
+
+ Highly Compressed MrSID image files:
+
+ Be wary of DRG-E or DOQQ files that are compressed with MrSID
+ compression. That is a proprietary compression format for
+ which we do not have access to the decoding algorithm. We
+ cannot use those from within Xastir. There's possible good news
+ lurking on the horizon though: LizardTech has mentioned on the
+ gdal-dev mailing list that they might be supporting open-source
+ with a driver for gdal sometime soon.
+
+ It is also possible to decompress these files with a free tool
+ from LizardTech called "mrsiddecode", available at
+ http://www.lizardtech.com/download/dl_options.php?page=tools
+
+ mrsiddecode can produce GeoTIFF output with the right command line
+ options. There is a Linux version of mrsiddecode, but one user
+ has observed that the Windows version running under Wine is a little
+ more robust. Your milage may vary.
+
+ Be warned that MrSID is a very effective compression algorithm, and
+ compressed MrSID files of size 5MB could easily decompress into 50MB
+ GeoTIFFs.
+
+ Note also that many GIS departments take perfectly usable
+ GeoTIFF files with all projection and datum tags and use ESRI products
+ to compress them down into MrSID files, thereby losing all the
+ GeoTIFF tags. See below.
+
+ GeoTIFF files in certain projections need special processing:
+
+ Not all geotiff files available on the net are usable directly in
+ xastir. Some of them are in projections that xastir can't use
+ properly, and others are missing all of the metadata information that
+ is needed to work out how to convert them to Lat/Lon unprojected rasters.
+ If you encounter a geotiff file that has the correct tags, but is
+ in some projection other than UTM, you can convert that file to a
+ lat/lon raster if you have gdal installed. Simply run the following
+ command:
+ gdalwarp -t_srs EPSG:4326 original_raster.tif usable_raster.tif
+
+ This will warp the geotiff file "original raster.tif" from
+ whatever projection it was in into an unprojected lat/lon raster
+ "usable_raster.tif" that can be directly read into xastir.
+ Depending on the source projection, you might get a map that
+ doesn't tile well with other maps due to the inclusion of opaque
+ border material, but it can sometimes be the only way to import
+ a map you need to use.
+
+ Defective GeoTIFF files need even more special processing:
+
+ It is unfortunately the case that the ESRI software in use by many
+ GIS departments produces GeoTIFF files that have NO information about
+ the coordinate system that applies to them --- they'll have just
+ enough information to know what the numerical coordinates of each
+ pixel are, but no information to tell you whether those coordinates are
+ UTM, Lat/Lon, State Plane, or anything else. For such maps you will
+ need to determine the coordinate system by finding external files
+ called "metadata" that are associated with the images. US
+ Federal datasources have a standardized file format (".fgd") that
+ provides this information, but many state or university GIS departments
+ just make some other format up for themselves. Most sources of
+ map data should have such metadata available, but sometimes it is a bit
+ of a chore to find it.
+
+ You can determine whether a .tif file has coordinate system information
+ in it using the "gdalinfo" command from the GDAL suite or "listgeo" from
+ the libgeotiff distribution. If gdalinfo shows something like this:
+
+ Driver: GTiff/GeoTIFF
+ Size is 5364, 7620
+ Coordinate System is `'
+ Origin = (588067.750000,5331248.500000)
+
+ you're the lucky owner of a file that has no coordinate system info
+ (because the only thing after "Coordinate System is" is a pair of
+ quotation marks). Another dead givaway would be:
+ Metadata:
+ TIFFTAG_SOFTWARE=Arc/Info
+ which tells you that the image was processed with a piece of software
+ that fails to put in all the right tags.
+
+ If you get maps whose metadata say are in UTM projection but for which
+ gdal indicates missing geoTIFF tags like it does in the example above,
+ xastir won't be able to display them unless you fix them up.
+ Fortunately, the GDAL library tool "gdal_translate" can do the
+ job. For example, if you have a source map with metadata that
+ says it's in UTM Zone 10, NAD83 datum, to make it suitable for
+ Xastir to read you can do something like this:
+
+ gdal_translate -a_srs EPSG:26910 original.tif georeferenced.tif
+
+ The inclusion of the "-a_srs" option to gdal_translate
+ forces the new tiff file to have the correct geotiff tags to
+ indicate that coordinate system.
+
+ The EPSG number to use for images in UTM projection with NAD83
+ datum is 26900 plus the UTM zone number. The EPSG number for UTM in
+ NAD27 is 26700 plus the zone number. The above command
+ will allow Xastir to read in the image and reference it
+ properly. If you do the gdalwarp option above instead, you can end up
+ with solid color areas between the edges of the original image
+ and the lat/long rectangle that the image will be warped to; these
+ extra pixels represent "no data" areas due to the difference in shape
+ between the original rectangular image and the warped image. The
+ color of this area depends on the colors present in the original
+ image; GDAL attempts to use a color that is different from any in the
+ source image. If those areas don't matter to you, then either
+ method will work for you. If you're planning to tile multiple
+ UTM images together, then the gdal_translate option is best.
+
+ If your maps are NOT in UTM, you must also gdalwarp, because xastir
+ cannot properly display geotiffs that are in projections other than
+ UTM or "unprojected" lat/lon.
+
+ EPSG numbers for odd-ball coordinate systems can be found at
+ http://www.remotesensing.org/geotiff/proj_list/Wkt_adam.zip
+
+ Maps that require gdalwarp include the FAA sectionals mentioned above,
+ and some topo maps in obscure state plane coordinates from various state
+ GIS departments.
+
+ XASTIR can only use GeoTIFF files that are 8-bit per pixel with one band
+
+ Some geotiff files contain multiple bands or multiple bytes per pixel.
+ Xastir currently uses only BYTE format, so you may need to convert the
+ geotiff file with gdal_translate. The number of bands, bytes per
+ pixel and other information about geotiff files can be obtained using
+ gdalinfo.
+
+ One-band, 16- or 32-bit-per-pixel:
+ The command "gdal_translate -ot BYTE original.tif new.tif"
+ can convert 16 and 32 bit per pixel geotiffs to ones that can be used
+ by xastir
+
+ Multiple band, 8-bit-per-pixel:
+
+ The command "gdal_translate -ot BYTE -b 1 old.tif new.tif"
+ can extract a single band as a grey scale layer from a multi-band
+ geotiff file, but this is probably not what you really want.
+ The command
+ rgb2pct.py old.tif new.tif
+ can create a single band palette based geotiff from a three band rgb
+ tif by dithering the colors down to a small pallette. This last
+ tool requires gdal built with Python support. See the gdal
+ documentation for these tools for further information.
+
+ More manipulations of GeoTIFF files:
+
+ gdal also provides several additional tools that can be used to
+ tile maps or chop them up into smaller pieces, but explaining the
+ details of that process is probably beyond the scope of this document.
+ See the man pages for "gdal_translate" and "gdal_merge.py" for
+ an explanation of how those tools could be used to accomplish this.
+
+ .geo files/online maps & graphics:
+
+ If you have ImageMagick and wget or libcurl installed, .geo files
+ for NWS radars are available from one of these sites:
+
+ ftp://gcpoolz.com/geos/Srb_geos.zip
+ http://wetnet.net/~we7u/xastir/maps/radar-geos.tgz
+
+ You'll probably want to add an IMAGESIZE line to each one to speed up
+ loading when some radars are offscreen: (bash syntax, modify for your
+ shell...)
+
+ for a in srb_*; do echo "IMAGESIZE 620 620" >> $a; done
+
+ NOTE: For .geo files with an ftp or http address for fetching the image,
+ IMAGESIZE is currently a REQUIRED parameter in the .geo file. For .geo
+ files where the image is resident on your hard drive, the IMAGESIZE tag
+ is optional.
+
+ Please also note that the coordinates in the .GEO files are expressed
+ in decimal degrees, and are listed with longitude first then latitude
+ on the TIEPOINT lines.
+
+ Tiger maps of the USA are available through the map menu under
+ "Enable/configure Tigermap". These maps are generated by the census
+ bureau web-server.
+
+ A .geo with only the word "TERRASERVER-SATELLITE" in it will retrieve a
+ satellite photo of the area from terraserver. You need "wget" or libcurl,
+ plus ImageMagick installed, and support for them compiled into Xastir. No
+ additional map downloads are needed if these are the only maps that you
+ want to use.
+
+ A .geo with only the word "TERRASERVER-TOPO" in it will retrieve a
+ topographic map of the area from terraserver. You need "wget" or
+ libcurl, plus ImageMagick installed, and support for them compiled into
+ Xastir. No additional map downloads are needed if these are the only
+ maps that you want to use. Other interesting keywords are
+ "TERRASERVER-URBAN" and "TERRASERVER-REFLECTIVITY".
+
+ Other tags you can put in a .geo file:
+ DATUM: (not used, yet...)
+ PROJECTION: Currently only supports "TM" for transverse Mercator.
+ REFRESH: number of seconds to reload the maps. Multiple maps
+ with different values pick the smallest value.
+ TRANSPARENT: Color to remove from the background (make it transparent).
+ Use a number, 0=black. Color-mapped images use the map value, so
+ white is usually 0xffff. Value can be decimal or hex if preceeded
+ by "0x". Multiple TRANSPARENT lines can be used in a file to make
+ multiple colors transparent.
+ CROP: removes borders. Values are [left top right bottom] with
+ (0,0) at the upper left. A good value for the NWS radar
+ images above is "CROP 35 20 616 600"
+ GAMMA, CONTRAST, NEGATE, EQUALIZE, NORMALIZE, LEVEL, MODULATE: These
+ are all ImageMagick options, and are documented there, and
+ briefly in the xastir help file.
+
+
+ "Find Address" feature (US only):
+
+ The "Find Address" feature is based on the open source geo-coder by
+ Dan Egnor and as such uses the same format for the data. You can
+ download preprocessed data based on Census Tiger 2003 data at:
+ http://www.dementia.org/geocoder/tgr2003/
+
+ Reprocessed geocoding files from the 2006 Second Edition TIGER/Line
+ data were produced by Jason Winningham in June of 2007 and made
+ available on the TAMU FTP server by Gerry Creager. They are much
+ better than the 2003 data, and it is recommended that they be used
+ instead. Download them from
+ ftp://aprs.tamu.edu/pub/geocode/
+
+ Geographic Names Information System Labels:
+
+ These aren't maps, but are collections of name labels for locations.
+ These display at various zoom levels like Dos/WinAPRS map labels, but are
+ also searchable from the Maps menu.
+
+ http://geonames.usgs.gov/
+
+ Click the link "Download GNIS Data: State and Topical Gazetteers" on
+ the left.
+
+ These files should be renamed in the form "<ST>.gnis" after download,
+ where <ST> is the abbreviation for the state that they cover, and
+ should be placed in the /usr/local/share/xastir/GNIS/ directory. To
+ make sure that maps are layered correctly with GNIS labels on the top
+ of the map stack, plus searchable, it is suggested that you link
+ /usr/local/share/xastir/maps/z to this GNIS directory.
+
+ Type this as root to create the link and directories:
+ cd /usr/local/share/xastir/maps
+ ln -s ../GNIS z
+
+ The map files must end in ".gnis" to be used by Xastir, and must be in
+ pipe delimited format. These are readily available from the above link
+ with such filenames as "AZ_DECI.TXT". The files must be renamed to
+ <ST>.gnis, and the trailing whitespace should be removed for speed. This
+ can be accomplished in one step with the following command. (bash
+ style...)
+
+ for a in *deci; do sed -e 's/[ ]*$//g' < $a > `basename $a _deci`.gnis; done
+
+ Individual files can have whitespace removed as follows:
+ sed -e 's/[ ]*$//g' < inputfile > outputfile
+
+ Populated places GNIS file can be had at:
+
+ http://geonames.usgs.gov/stategaz/POP_PLACES_DECI.zip
+
+ A note from Jason Winningham, kg4wsv:
+
+ "The file has over 181k records in it. You can use the following command
+ to weed out all places with populations less than 1000, and get it down
+ to just under 14k records, which is really fast to load:
+
+ awk -F\| '{if ($17 > 1000) print $0}' \
+ /usr/local/share/xastir/GNIS/0pop_places.gnis \
+ >/usr/local/share/xastir/GNIS/0pop_places_over_1k.gnis
+
+ I stuck a zero at the beginning of the filename so this would
+ show up in the GNIS directory before any of the state files."
+
+
+ County weather Warning maps (requires shapefile support):
+
+ The latest shapefile format weather maps may be found here:
+ http://www.nws.noaa.gov/geodata/
+
+ or more easily found here (but not guaranteed to be the most
+ current:
+ http://wetnet.net/~we7u/xastir/Counties/
+
+ We now have a script in the xastir/scripts directory called
+ "get-NWSdata" which fetches the files you need and plops them
+ into the correct directory and unzips them. Run that script
+ as root. It requires "wget" to work. You may then try the
+ NWS-TEST.log test shown below to verify proper operation.
+
+ --------------------------
+ The files of interest are:
+ --------------------------
+
+ NWSI Libraries:
+ ---------------
+ County Warning Area Boundaries (c_*.zip)
+ Public Zone Boundaries (z_*.zip)
+ Coastal and Offshore Marine Zones (mz*.zip, oz*.zip, hz*.zip)
+ Fire Weather Zone Boundaries (fz*.zip)
+
+ County Libraries:
+ -----------------
+ AWIPS Counties (w_*.zip)
+
+ Unzip those files in the /usr/local/share/xastir/Counties/ directory and
+ Xastir should find them and use them for weather alerts. Be sure to
+ include the .shp, .shx, .and dbf.
+
+ Note that you can also use the county file as the background polygon
+ filled map for drawing county lands and borders. Either make a link
+ to these files from your maps directory, or copy the files there so
+ that they show up in the Map Chooser.
+
+ To test whether the weather alerts are working (whether weather?), copy
+ the NWS-TEST.log file to your ~/.xastir/logs/ directory and then bring it
+ in to Xastir using the File->Open Log File option. Zoom in to the
+ WA/OR/ID area (Pacific Northwest) and you should see a picture that looks
+ like this: <http://www.eskimo.com/~archer/xastir/xastir-wx-alerts.png>
+ Note that you may have to change the dates embedded in the file if Xastir
+ thinks they are expired. See the notes at the top of that file. If the
+ alerts are still active they should appear in the View->Weather Alerts
+ dialog.
+
+ Australian rules Weather Alerts
+
+ http://wxsvr.aprs.net.au/implementation.html
+
+ Raw Tiger/Line format maps (requires GDAL/OGR):
+
+ If you have GDAL/OGR library added to Xastir, you should (very soon)
+ be able to use Tiger/Line maps. The developers are working to add
+ this capability.
+
+ 2002 map data can be found here:
+
+ http://www.census.gov/geo/www/tiger/tiger2002/tgr2002.html
+
+ 2003 map data can be found here:
+
+ http://www.census.gov/geo/www/tiger/tiger2003/tgr2003.html
+
+ SDTS format maps (requires GDAL/OGR):
+
+ http://edc.usgs.gov/geodata/
+
+ The "hypsography" maps contain topo lines. They look very nice overlaid
+ on top of terraserver satellite images. Note that for some types of maps
+ you also need to download a data dictionary file to go with them.
+
+ Also note that the various datasets appear to reuse filenames. You may
+ need to separate each one into its own subdirectory in order to keep all
+ of the files from getting overwritten by new maps.
+
+ MapInfo TAB/MID/MIF format maps (requires GDAL/OGR):
+
+ http://www.mapinfo.com
+ http://research.umbc.edu/~roswell/mipage.html
+
+
+ Download audio files:
+
+ To play the wav files you will need a program such as vplay to play the
+ audio file through your sound card.
+
+ Grab xastir-sounds.tgz at the ftp site you downloaded Xastir, or at
+ ftp://ftp.tapr.org/software_lib/Linux/xastir/xastir-sounds.tgz
+
+ Un-tar the file. Put the sounds files into the
+ /usr/local/share/xastir/sounds directory where Xastir can find them.
+ (FIXME: thunder.wav is missing?).
+
+ Download FCC and/or RAC Database files:
+
+ If the FCC database is installed, a Search FCC Database button will
+ appear in the station info box. If the RAC (Radio Amateurs of Canada)
+ database is installed, a Search RAC Database button will appear for
+ callsigns beginning with "VE" or "VA".
+
+ The download and installation of these is automated in the get-fcc-rac.pl
+ script included with Xastir, but you may install them by hand
+ individually if you wish as described here:
+
+ To use the FCC lookup:
+ ----------------------
+
+ Download:
+ http://wireless.fcc.gov/uls/data/complete/l_amat.zip
+
+ (The only file needed from this 87 Meg zip is the EN.dat file)
+
+ **** NOTE To use the data base file it must be sorted first!!! ****
+
+ unzip l_amat.zip
+
+ To sort the file, make sure you have plenty of disk space for this as
+ the file is BIG!
+
+ cat EN.dat | /usr/bin/perl -pe 's/\r\r\n//g' | sort +4 -t \| > EN.dat.sorted
+
+ Install it in the xastir/fcc directory:
+
+ su
+ mv EN.dat.sorted /usr/local/share/xastir/fcc/EN.dat
+
+
+ To use the RAC lookup:
+ ----------------------
+
+ Download:
+ http://205.236.99.41/%7Eindicatif/download/amateur.zip
+
+ unzip amateur.zip
+ mv AMATEUR.RPT /usr/local/share/xastir/fcc/AMACALL.LST
+
+
+ Hiking trails from National Geographic's Topo or mapXchange:
+ ------------------------------------------------------------
+
+ For those of you who may be familiar with National Geographic's Topo!
+ program, there's a way to use the user-saved data (but not topo maps
+ themselves) from within Xastir. Many users create TPG and/or TPO
+ files in TOPO from GPS data and/or hand-drawn routes. They can then
+ upload them to the mapXchange site, and in fact there are many hiking
+ trails that one can download for free from that site. Okay, how to use
+ them?
+
+ Go to <http://www.gpsbabel.org>. Go to the Project page and then the
+ CVS page and follow the instructions for grabbing the CVS gpsbabel
+ sources. Only CVS has the Topo version 3.x support, which was just
+ recently added (May 2006). Follow their instructions for building/
+ installing/using the program. It's a command-line program where you
+ specify the input and output formats and filenames. Using this program
+ you can snag the interesting data out of the files and convert it to
+ GPX format. Once you have that, you can use the "gpx2shape" script to
+ convert them to Shapefiles. Xastir can then use them as map files.
+
+
+
+WHERE TO FIND MORE INFO ON MAP DATUMS, ETC:
+
+ Geodesy:
+ http://oceanservice.noaa.gov/education/geodesy/welcome.html
+
+ "Geodesy for the Layman"
+ http://www.ngs.noaa.gov/PUBS_LIB/Geodesy4Layman/toc.htm
+
+
+
+MAP CACHING (WORKS WITH MOST ONLINE MAPS):
+
+ Map caching works in conjunction with the map download routines,
+ which fetch maps from http or ftp addresses. The map caching features
+ use functions found in Berkeley DB 4.0 library, AKA libdb (version 4.0
+ or better), to create and manage a cache directory and a persistent
+ database of information about the files in the cache directory. This
+ directory defaults to ~/.xastir/map_cache. The files under this
+ directory can be cleaned up or removed by hand at any time - the
+ caching routines will simply download the maps and put new entries
+ into the .db file.
+
+ Map files are saved with filenames that include the number of seconds
+ since the Unix epoch. This allows the caching routines to easily
+ determine the age of maps so that older cached maps can be deleted.
+ This is currently (Dec 2004) controlled with a compile time maximum
+ age setting. See map_cache.h for specifics and for brief
+ documentation about all of the map_cache functions.
+
+
+
+DRAWING YOUR OWN MAPS USING XASTIR ITSELF:
+
+ The final result here will be ESRI Shapefile vector maps that
+ you can then use within Xastir. You'll need Shapelib compiled
+ into Xastir to make use of this feature (the private copy of
+ Shapelib is fine for this).
+
+ Turn off Object Transmit first (Interface menu).
+
+ Place an object or item at the start location of your route.
+
+ Click on the "Move" button to active move mode, then move that
+ object around the map. Once you're done you'll have a bunch of
+ straight lines that depict the course.
+
+ Now bring up Station Info on that object and click on the Store
+ Track button. If you've got Shapelib compiled in, you'll get a
+ shapefile created with the track you just drew.
+
+ After you're done you can delete the object and then turn on the
+ Object Transmit toggle again. You'll end up transmitting the
+ deleted final position of the object for a few hours unless you
+ kill/restart Xastir, but that's ok. Nobody will see it on their
+ maps 'cuz it's a deleted object.
+
+ Look in ~/.xastir/tracklogs/ for the Shapefile. Copy it to your
+ maps directory, changing the name on the three files as you
+ like, then create a dbfawk file for it if you want to change how
+ it is drawn in Xastir.
+
+ Another way would be to drive the course with a GPS and then
+ download the track via Xastir/GPSman to create a Shapefile map.
+
+ Yet another way would be to drive it with an APRS rig and then
+ Store Track as described above. You could also drive with
+ GPS/Xastir (without APRS) to get a very detailed track and then
+ save your own track.
+
+
+
+DRAWING SAR SEARCH SEGMENTS IN XASTIR:
+
+ Turn on "Draw" mode (togglebutton at the top of the main
+ window). The cursor should change to the Measure/Draw symbol.
+
+ Using the middle mouse button, click on each vertice until you
+ are almost done describing a polygon (don't close it yet). If
+ you don't have a middle mouse button, clicking on BOTH mouse
+ buttons at once will do it if you have "emulate third mouse
+ button" enabled in your X-Windows configuration.
+
+ Go to Map->Draw CAD Objects->Close Polygon. The polygon will
+ get completed, the area enclosed will be computed, and a dialog
+ will pop up asking you for more information. You do not have to
+ enter any information in this dialog, but a name of some type is
+ helpful in order to be able to identify each segment when
+ modifying/deleting/viewing these segments.
+
+ Note that these CAD Objects get saved in a file and reloaded
+ each time you start Xastir, but they cannot currently be written
+ out as a map file and used as a general map.
+
+ Note also that these CAD Objects don't get transmitted. They
+ are currently for local display only.
+
+ The display of various kinds of data related to these segments
+ can be modified in the Map->Draw CAD Objects menu. Modifying
+ parameters for any segment is done in the
+ Map->Draw CAD Objects->CAD Polygons dialog.
+
+ Click on the dashed line in the menus in order to separate that
+ menu from the rest and allow you to keep the menu on the screen.
+ This is very useful when drawing CAD Objects or changing
+ display/filtering options.
+
+ Turn off "Draw" mode when you're done. The cursor should return
+ to normal.
+
+
+
+SUMMARY OF DISTANCE/AREA/ANGLE CALCULATIONS:
+
+
+ DISTANCE:
+ ---------
+ *) Haversine formula (2-parameter atan version) for computing
+ distance between two points, for our general distance routines:
+
+ calc_distance()
+ calc_distance_course()
+ distance_from_my_station()
+
+ *) Haversine formula (2-parameter atan version) in "Measure" for
+ both the X/Y offsets and the total distance.
+
+ Haversine formula is more accurate for shorter distances than
+ spherical trigonometry calculations. Both methods are equivalent
+ for longer distances. Both are Great-Circle calculations (as
+ opposed to Rhumb-line or planar geometry). See the GIS FAQ for info
+ on these methods. Dr. Math website mentions both of these and refers
+ people to the same GIS FAQ.
+
+ Also note that the Haversine formula is ill-conditioned if the
+ two points are antipodal (on opposite sides of the Earth). From the
+ GIS FAQ: "but the error, perhaps as large as 2km (1 mi), is in the
+ context of a distance near 20,000km (12,000 mi)." For our purposes
+ that's just fine.
+
+
+ AREA:
+ -----
+ *) Area of a spherical rectangle from Dr. Math's website for the
+ "Measure" function. There are errors in their last two derived
+ formulas. They have been notified of it. Our implemented code
+ is correct.
+
+ *) The area calculation for CAD Object Polygons is probably not
+ spherical, but closer to planar. It might take some doing to calculate
+ the area of irregular polygons on a spherical surface. We use Greene's
+ Theorem to compute the area based on the vectors. The lengths of each
+ vector are computed via the Haversine formula, so it's not strictly a
+ planar area calculation either. Somewhere in-between planar and spherical?
+ This should be plenty good enough for areas that are less than 12 miles on
+ a side (that's about where planar geometry starts to diverge from spherical
+ trigonometry), perhaps also for somewhat larger areas than this due to the
+ advantage of computing the vector lengths with the Haversine formula.
+
+
+ ANGLE:
+ ------
+ *) Great Circle departure angle for the "Measure" function.
+
+ *) Great Circle departure angle for the calc_distance_course()
+ function.
+
+ *) Dead-reckoning angle is essentially a Rhumb-line calculation
+ (constant heading), with a few caveats:
+
+ We compute the next point along a constant angle based on the last
+ position transmitted, the time elapsed, and the course desired.
+ This then gets corrupted a bit either by the standard APRS grid that
+ it has to snap to (and the position snapped to for the previous
+ position) and/or by the relatively course angle available for Base-91
+ compressed positions.
+
+ Standard APRS positions give 1-degree angular resolution but 60-foot or
+ so grid points. Base-91 Compressed positions give something like 1 to
+ 3-foot grid points but less angular resolution (+/- 2 degrees. We
+ can't win!
+
+ The end result is that we start off like a drunk sailer due to our
+ short transmit times and the above limitations, then the angle smooths
+ out as the time increases between the transmits. You can see this
+ easily at zoom level 1 when you place an object, when you make a change
+ to an object, or move an object (transmit rate goes up for any of these
+ conditions).
+
+ Dead-reckoning effectively does a Rhumb-Line calculation as it is
+ trying to do a constant heading. That means it is not the shortest
+ distance between the points. I'm still trying to get my head around
+ that last concept as it is counter-intuitive to someone versed in
+ compass/maps on land and with shorter distances.
+
+ A Great-Circle route is the shortest distance between two points on
+ a sphere, whereas a Rhumb-line is what you get if you move along a
+ constant compass heading and is a bit longer.
+
+ We probably do not need to go to ellipsoid calculations for Xastir.
+ Spherical calculations should be easily accurate enough for what we do.
+
+
+
+ ------------------------------------------------------------------------
+APRS(tm) is a Trademark of Bob Bruninga
+
+Copyright (C) 1999 Frank Giannandrea
+Copyright (C) 2000-2012 The Xastir Group
+
diff --git a/README.OSM_maps b/README.OSM_maps
new file mode 100644
index 0000000..c18df20
--- /dev/null
+++ b/README.OSM_maps
@@ -0,0 +1,216 @@
+$Id: README.OSM_maps,v 1.4 2012/11/01 18:57:18 we7u Exp $
+
+Copyright (C) 2012 The Xastir Group
+
+
+ Using OpenStreetMap in Xastir
+ ------------------------------------------------------------------------
+ CONTENTS
+ Introduction
+ Map Types
+ Map Sources and Renderings (Styles)
+ Map Cache
+ Sharing Tiles
+ Map Definition Files
+ Copyrights and Licenses
+
+
+ Introduction
+ ------------
+ What, you may ask is 'OpenStreetMap' (OSM)? From the web site,
+ www.openstreetmap.org, we read that
+
+ "OpenStreetMap is a free editable map of the whole world.
+ It is made by people like you".
+
+ The tag line for the map is "The Free Wiki World Map".
+
+ Xastir will display bitmap versions of the OSM. There are multiple
+ renderings of the OSM to choose from and, by default, nine (9)
+ are available in Xastir.
+
+ Map Types
+ ---------
+ Xastir can use two different map types based on OSM; static and
+ tiled. Static maps are bitmaps that are least as large as the Xastir
+ window. Tiled maps are built up from 256x256 pixel images.
+
+ Static maps are also assembled from tiles, but the assembly occurs
+ at the server and the full size image is downloaded to Xastir. There
+ is a major disadvantage to static maps- even slight changes in map
+ position requires a new map download.
+
+ Tiles have become the standard for bitmap map images. Their small
+ size allows for short download times and easy reuse. Tiles are the
+ basis of the 'slippy map' implementations on web sites,
+ applications, and portable devices. Note that Xastir is not a
+ 'slippy map' application and map motions and refresh times are not
+ as smooth or quick as you can find in other applications (Xastir's
+ strengths lie in other areas).
+
+ Bitmap images, whether static or tiled, are available for only a
+ limited number of zoom levels. There are 18 possible zoom levels.
+ It takes 2^zoom tiles to represent 360 degrees. Since the tiles are
+ 256 pixel squares, there are 2^(zoom + 8) pixels in 360 degrees.
+
+ When the Xastir scale does not equate to one of the 18 OSM zoom
+ levels, the bitmap image is scaled. However, scaled bitmaps tend to
+ look ugly. The scaled bitmap can have jagged lines, unequal pixel
+ sizes, and/or missing information. At best a scaled bitmap looks
+ blurred, but more typically some pixels will be enlarged into visible
+ blocks or compressed invisibility.
+
+ You can use the F4 key to adjust the Xastir scale to approximate the
+ OSM zoom level and refresh the display. (The key can be changed by
+ modifying a variable in the OSM definition (GEO) files.
+
+
+ Map Sources and Renderings (Styles)
+ -----------------------------------
+ The OSM data is rendered into tiles using different styles. The
+ easiest place to view and compare the styles is at
+ http://ojw.dev.openstreetmap.org/StaticMap/?mode=Style&
+
+ Tiles can be retreived from a number of servers. The supplied map
+ definitions will download tiles from:
+ http://tile.openstreetmap.org/
+ http://tah.openstreetmap.org/Tiles/tile/
+ http://tiles.openpistemap.org/tiles/contours/
+ http://andy.sandbox.cloudmade.com/tiles/cycle/
+
+ The CloudMade tiles are also available, but a user account and a key
+ are required. Register at http://www.cloudmade.com/ and then create
+ new OSM map definition files (GEO) by copying an existing file and
+ changing the URL variable. The CloudMade tile URLs have this form:
+
+ http://tile.cloudmade.com/<key>/<style#>/256/
+
+
+ Map Cache
+ ---------
+ Static maps are cached with other bitmap map images in the
+ ~/.xastir/map_cache/ directory.
+
+ Tiles are cached separately to make it possible to share them
+ with other applications. By default tiles are cached in
+ ~/.xastir/map_cache/OSMtiles/, but that location can be changed on a
+ by-style basis. The tiles are organized directories by style, zoom
+ level, and longitude:
+
+ ~/.xastir/map_cache/OSMtiles/
+ + <style1>/
+ | + <zoom>/
+ | <longitude>/
+ | + [0 ... (2^zoom - 1)].png
+ + <style2>/
+ ...
+
+ Note that 'longitude' is a tile number between 0 and (2^zoom -1).
+
+ Xastir downloads tiles as needed. If Xastir is compiled with
+ libcurl support, then it will check for updates to tiles that have
+ been cached for 7 days or more.
+ See http://wiki.openstreetmap.org/wiki/Tile_usage_policy
+
+ If a tile can not be downloaded for any reason or if the downloaded
+ file is not usable image, then the downloaded file (if any) will be
+ deleted and a red area will be shown in it's place on the display.
+
+ NOTE: Run Xastir at debug level 512 (-v 512) for more information
+ on download issues. At debug level 512, corrupt tile files
+ will not be deleted. Examining the contents of the corrupt
+ files can be informative.
+
+ If Xastir is compiled with libcurl support, then debug level
+ 8192 will enable verbose output from libcurl.
+
+ WARNING: Corrupt tile files will not be deleted when running at
+ debug level 512. If you do not delete them manually before
+ restarting Xastir, then the first time Xastir displays the
+ tile it will be shown in red and then deleted from the
+ cache.
+
+
+ Sharing Tiles
+ -------------
+ The directory structure used to cache tiles is common to other
+ programs, though the style names are typically different. An
+ example of a program that can share tiles with Xastir is TangoGPS
+ (http://www.tangogps.org).
+
+ Here are some examples of how you can share tiles with TangoGPS
+ (the setup for other programs would be similar):
+
+ 1) Setup a symlink at the style level of the caches
+ $ cd ~/.xastir/OSMmaps/
+ $ ln ~/Maps/<tangoStyleName>/ <xastirStyleName>
+
+ 2) Change the Xastir map definition file to specify the TangoGPS
+ cache by changing the following variables (see the next
+ section for more information):
+ OSM_TILED_MAP-<tangoStyleName>
+ TILE_DIR /home/<user>/Maps
+
+ 3) Share all styles and tiles by creating a symlink at the top
+ level of the cache. This also requires changing the Xastir
+ map definition files to specify the style names used by
+ TangoGPS:
+ $ cd ~/.xastir
+ $ rm -rf OSMmaps/
+ $ ln -s ../Maps OSMmaps
+
+
+ Map Definition Files
+ --------------------
+ OSM map type, style, server, cache directory, and function keys are
+ specified in Xastir GEO files. By default the files are located in
+ the /usr/local/share/xastir/maps/Online/ directory. The supplied
+ definition files have filenames of this form:
+
+ OSM_<name>.geo - static maps
+ OSM_tiled_<name>.geo - tiled maps
+
+ Where <name> is replaced with the style name. Note that <name> could
+ be any unique string and is not required to be the style.
+
+ Read the comments in the supplied definition files for more
+ information.
+
+
+ Copyrights and Licenses
+ -----------------------
+ Maps and tiles from the OpenStreetMap project are
+ Copyright OpenStreetMap and contributors, CC-BY-SA
+
+ http://www.openstreetmap.org/
+ http://creativecommons.org/licenses/by-sa/2.0/
+
+ in addition, tiles from CloudMade are
+ Copyright CloudMade, CC-BY-SA
+
+ http://www.cloudmade.com/
+ http://cloudmade.com/about/api-terms-and-conditions
+ http://cloudmade.com/terms_conditions
+
+ TopOSM tiles are a composite of CC-BY-SA and public domain data,
+ including MassGIS data. See
+ http://wiki.openstreetmap.org/wiki/TopOSM for more information.
+
+ Changing the Displayed Attribution
+ ----------------------------------
+
+ The licenses from OpenStreetMap and CloudMade require attribution
+ that is met, in part, by a label shown at the top left corner of the
+ map. Two label images have been provided, one shows icons and the
+ other shows black text on a white background.
+
+ You can change between the two label styles by changing a symlink:
+
+ $ cd /usr/local/share/xastir/maps/ # your installing may differ!
+ $ rm CC_OpenStreetMap.png
+ $ ln -s CC_OpenStreetMap_txt.png CC_OpenStreetMap.png
+ or
+ $ ln -S CC_OpenStreetMap_logo.png CC_OpenStreetMap.png
+
+
+ ------------------------------------------------------------------------
diff --git a/README.win32 b/README.win32
new file mode 100644
index 0000000..a2ad5d5
--- /dev/null
+++ b/README.win32
@@ -0,0 +1,1357 @@
+
+$Id: README.win32,v 1.151 2012/11/01 18:57:18 we7u Exp $
+
+---------------------------------------------------------------------
+Note that there are other options to get Xastir running on Win32.
+The method described below in this document is for getting Xastir
+running under Cygwin which can be problematic. Other methods exist
+on the Xastir Wiki pages which are typically easier and more robust:
+
+ http://www.xastir.org/wiki/index.php/Installation_Notes
+---------------------------------------------------------------------
+
+ Two companies have created simpler installs of Cygwin/Xastir than
+ described in this document. Contact one of these folks for more
+ info. Remember to replace the "at" below with the "@" symbol to
+ arrive at the correct e-mail addresses. We have to do that to
+ prevent large amounts of spam from going to addresses harvested
+ from web pages:
+
+
+ Lintronix:
+ Internet install of Xastir available for free, CD-ROM available
+ for a nominal fee. Everything needed to install Cygwin/Xastir
+ online (Internet install) or off-line (CD-ROM). Walks you
+ through an automated install:
+
+ http://www.lintronix.com/winxastir/
+ E-mail: winxastir at lintronix.com
+
+
+ Inuit Nunaani Wireless Inc:
+ CD-ROM available for a nominal fee. Everything needed to
+ install Cygwin/Xastir off-line. Walks you through an
+ automated install. This install is verified to work on WinXP
+ and Win98 (known _not_ to work on Win95/WinME). Contact:
+
+ E-mail: Tom Tessier <ttessier at trtdigital.ca>
+
+
+
+------------------------------------
+Installing Xastir on Windows/Cygwin:
+------------------------------------
+
+Please Note: It's beneficial to actually log in to your Windows
+computer rather than skipping that step of the Windows login process
+(Don't hit escape just to get rid of the dialog!). If you log into
+Windows properly, Cygwin will be able to figure out where to put your
+home directory. If you don't do this, you'll be referred to as
+"unknown" and you won't have a home directory in Cygwin. This means
+there won't be a good place to put your Xastir startup files. Of
+course, log in as the same user each time in order for Cygwin to use
+the proper home directory for you.
+
+CAN'T REPLACE FILES: Every once in a while Windows will refuse to
+allow you to delete/rename one of the files. The only way I've
+found to get around this problem is to reboot. Also, Windows
+typically won't allow you to replace a file that Windows currently
+has open. If you're going to be recompiling/reinstalling Xastir, or
+updating Cygwin, make sure that these applications are shut down
+before doing so. You can get VERY strange results if only some
+files get updated.
+
+SPACES IN USERNAMES: Cygwin specifically, and Unix boxes in
+general, don't much like spaces in filenames, directories, or login
+names. Any of these may cause you headaches while playing with
+Cygwin. Create a new login that doesn't have spaces and log in as
+that user before installing Cygwin, and whenever you intend to run
+Cygwin/Xastir. It's very likely that Xastir won't work for you if
+you use a login that has spaces embedded in it. For additional
+info, see this link:
+
+ http://cygwin.com/faq/faq_2.html#SEC17
+
+Explanation of this login box for those that don't see it: If you
+have the option of running networking, you'll have a login box show
+up when you first start up Windows. It'll ask for you user name and
+password, then let you in. If you escape out of that dialog, Windows
+may start right up but networking will be disabled.
+
+If you don't see that box, there are two options that I know about,
+either you or someone else set it up to auto-login with your user/
+password combo, or you don't have networking installed at all.
+
+The following steps direct you through installing Cygwin, Xastir, and
+a few optional map libraries that Xastir can use. Note that in most
+of the places below where the directions state to type commands, this
+must be done from within a Cygwin BASH shell, not a DOS window.
+Where you are asked to edit files, it's best to use Wordpad instead
+of Notepad, as Notepad doesn't do nice things to Unix-format files.
+
+Cygwin now allows you to have Xwindows apps and Windows apps all on
+the screen and visible at the same time! The instructions here set
+it up in that manner, so you can have Xastir as just another app on
+your Windows desktop.
+
+Please subscribe to the "xastir" mailing list at
+"http://www.xastir.org". There are lots of helpful people there
+that can aid you in installing/running Xastir. You must be subscribed
+in order to post messages there.
+
+
+[ ] Step 1) Install Cygwin, a free download.
+
+
+[ ] Step 1a) Go to http://www.cygwin.com with your web browser.
+Look for the black and green Cygwin icon, then click on "Install
+now!".
+
+This will load the Cygwin network installer program onto your
+computer. Remember where you decide to put this program. I put
+mine in "c:\<login>\cygwin\setup.exe", (for instance
+"c:\hacker\cygwin\setup.exe"). This program will allow you to do a
+network install of Cygwin. After you install Cygwin (see the steps
+below for details) you'll have a package directory (in my case
+"c:\hacker\cygwin\") and a Cygwin directory (in my case
+"c:\cygwin"). The un-installed packages go into the package
+directory as they are downloaded from the 'net.
+
+It will be beneficial to re-run the Cygwin network installer from
+time to time in order to keep Cygwin up to date. Each time you run
+it you'll update any packages that have been changed since you last
+ran it.
+
+[ ] Step 1b) Find the "setup.exe" program and execute it either by:
+
+ a) Clicking on it with File Explorer, or
+ b) Start->Run->path to executable, or
+ c) Opening a DOS window and typing the name.
+
+This will start installing Cygwin over the network. Answers to
+provide to the program:
+
+ Install from Internet (*)
+ "C:\cygwin"
+ Install For All Users
+ Default Text File Type Unix (*)
+ Local Package Directory "C:\hacker\cygwin"
+ Select Your Internet Connection (choose one)
+ Choose A Download Site (choose one nearby if you can determine that)
+
+Note: Responses above listed with a "(*)" are required. Others are
+up to the individual user to answer as they wish. You'll get to a
+"Progress" page where "setup.bz2" is downloaded from the 'net. If
+it hangs at this step, you may wish to "Cancel" and try another
+server until you obtain this file and are presented with a list of
+packages to install.
+
+
+[ ] Step 1c) Select Packages: Leave the packages selected that
+were selected by default, plus select the additional packages listed
+below. Note that enabling some of these packages causes others to
+be selected as well, that's OK and necessary.
+
+[ ] Press the "View" button until it says "Full" next to it. All
+packages are now in alphanumeric sorted order.
+
+Selecting a package involves clicking on the little circle symbol
+until the option you want is displayed. You can choose older
+versions of a package, choose to keep the package you have installed
+already, or choose to remove or install a package in this manner.
+If you're running Cygwin install again and see "Keep" as an option,
+that means you've already installed that package. We're only
+concerned with the "bin" packages here (stands for "binary") and not
+the "src" packages (source code).
+
+It's suggested that you keep whatever was selected by default, and
+just add the below packages to the selection. As you select
+packages, other packages may be selected for you that are also
+required:
+
+[ ] autoconf
+[ ] automake
+[ ] binutils
+[ ] bzip2
+[ ] curl
+[ ] curl-devel
+[ ] cvs
+[ ] db4.2
+[ ] diffutils
+[ ] gcc
+[ ] gv
+[ ] gzip
+[ ] ImageMagick (See notes under "Adding ImageMagick" below
+ --- there are problems with the Cygwin package)
+[ ] lcms
+[ ] less
+[ ] lesstif
+[ ] libdb4.2
+[ ] libdb4.2-devel
+[ ] libgeotiff
+[ ] libgeotiff-devel
+[ ] libgeotiff1
+[ ] libMagick-devel
+[ ] libMagick6
+[ ] libproj-devel
+[ ] libproj0
+[ ] libtool
+[ ] libxml2-devel
+[ ] m4
+[ ] make
+[ ] nano (a windows-style text editor, optional)
+[ ] patch
+[ ] pcre
+[ ] pcre-devel
+[ ] perl
+[ ] proj
+[ ] python
+[ ] rcs
+[ ] tcltk
+[ ] tiff (install sources for this one too? TBD)
+[ ] unzip
+[ ] vim (a Unix-style text editor, optional)
+[ ] wget (Optional: Can use libcurl instead)
+[ ] X-start-menu-icons
+[ ] X-startup-scripts
+[ ] xfree86-lib-compat
+[ ] xorg-x11-bin
+[ ] xorg-x11-devel: Headers
+[ ] xorg-x11-f100: 100 dpi fonts
+[ ] zip
+
+Clicking on the small circle with the two arrows will run you
+through the various select/de-select options for each package.
+
+Note regarding Perl: On some Windows systems, Perl 5.8 can cause
+page faults when compiling Xastir. If this happens to you, start up
+the Cygwin install program again and install Perl 5.6.1 instead.
+Retry the compile. If this works for you, every time you update
+Cygwin you'll have to check the Perl version to make sure that it
+doesn't update you to 5.8.
+
+Note regarding KDE: One user reported that the KDE package on
+Cygwin messes up XmStrings in Lesstif. It caused a bunch of
+headaches. You've been warned. Note that KDE is not one of the
+packages listed above (I didn't load it).
+
+
+[ ] Step 1d) Click Next and the packages will get downloaded and
+installed. Repeat the above if you have network difficulties, until
+the install succeeds completely.
+
+Some servers fail to download some files and require the user to
+press enter between downloads when it fails on these files. If this
+happens, back up and select another server.
+
+
+[ ] Step 1e) At the end of the install it'll ask you if you wish to
+create desktop icons and menu entries. Definitely select these! It
+doesn't mean that Cygwin will start automatically each time you
+reboot your computer or login (it doesn't start automatically). It
+_does_ mean that you'll have an icon to click on manually to get
+things going.
+
+This will create a Black/Green Cygwin icon on the desktop and a menu
+entry so that you can start Cygwin through the menu system as well.
+
+[ ] Step 1f) Click "Finish". Cygwin is now installed. One more
+pop-up informs you Cygwin has been installed. Sometimes this last
+dialog gets hidden behind other windows, and it does seem to need OK
+clicked to complete the installation. Click the OK button on that
+last dialog to _really_ complete the installation.
+
+The Black/Green Cygwin icon will start up a BASH window, without
+starting up Xwindows. Think of it as being similar to a DOS window,
+but with a lot more power. It understands Unix commands though, not
+DOS commands.
+
+[ ] Note: I've had the Cygwin network install fail before during
+the downloading stage without informing me in any recognizable
+manner. You might which to re-do step 1 to make sure nothing
+further gets downloaded/installed. Once you get to that point, Step
+1 is complete.
+
+
+[ ] Step 2) Create shortcut for starting X:
+
+Create a shortcut to C:\cygwin\usr\X11r6\bin\startxwin.bat from your
+desktop. This shortcut is the method you'll use to start up
+Xwindows. The usual method is to use File Explorer to find the
+file, the right click and drag it to your desktop, at which point
+you let go of the right mouse button and you'll be presented with a
+small menu. Select "Create Shortcut(s) Here". You can then rename
+the shortcut if you wish. I named mine "Xwindows".
+
+Change the properties on the shortcut so that it runs it from your
+home directory on Cygwin, something like "c:\cygwin\home\<user>\".
+Right-click on the new shortcut, then go to the Properties menu to
+change this. You may need to create the home and the user directory
+before you can change the properties on the shortcut.
+
+
+[ ] Step 3) Test Cygwin and create startup shortcuts:
+
+Note: With Win2000, I had to do a reboot before I could proceed
+further.
+
+Double-click on the shortcut you just made. You should get a shell
+window that looks very much like a DOS window. It's a BASH shell
+window and understands Unix commands instead of DOS commands.
+
+When running this shortcut for the first time from WinXP, several
+errors may occur. Repeat as necessary until the BASH window appears
+without incident.
+
+Type "exit" and then press <Enter> to make the BASH window
+disappear.
+
+You should still see an 'X' in your system tray. That's the
+X-server running. You can right-click on that and then select the
+menu entry to cause it to exit.
+
+Once you've gotten to this stage, you now have Cygwin and Xwindows
+installed and operational. Next we go after Xastir itself.
+
+[ ] Edit or create your .profile file in your home directory.
+
+NOTE: Your "home" directory would be at "C:\cygwin\<user>\" if you
+installed Cygwin in the default location. From inside a BASH shell
+you can get to your home directory just by typing "cd" and then
+pressing <Enter>. When you see things like "~/.profile" it is
+really referring to the file ".profile" in your home directory (~).
+This is a different file than the ".bash_profile" file.
+
+It appears that Cygwin uses the PATH variable to look for both
+binaries and libraries. Add this line to the file (create the
+"~/.profile" file if the file doesn't exist):
+
+ export PATH=$PATH:/lib:/usr/lib:/usr/X11R6/lib:/usr/local/lib:/bin:/usr/local/bin:.
+
+If the line already exists in your .profile, add any missing pieces
+to it from the line above. Directories should be separated by a ':'
+character. Edit it with "nano" or "vim" (again, the more
+user-friendly editor is "nano").
+
+Once you have saved the file, execute the following commands to copy
+file to where it will be automatically executed when you open a
+shell and then read it for this session so you don't have to close
+and then reopen the shell.
+
+ cp .profile .bashrc
+ source .bashrc
+
+[ ] Step 4) Create a file at C:\cygwin\home\<user>\ called
+".cvsrc", where the "<user>" part is your Windows login name. Don't
+forget the leading period in the filename as it's important. For
+instance, I created a file: "C:\cygwin\home\hacker\.cvsrc". The
+file should contain the following lines:
+
+ ##cvs -z3
+ update -P -d
+ status -v
+ diff -u
+
+The '#' marks comment out the first line. "cvs -z3" invokes
+compression, and the SourceForge site isn't performing compression
+currently.
+
+PLEASE NOTE: this file must be created in Unix format, not DOS
+format. DO NOT USE Notepad or other Windows tools to create the
+file, as CVS will not recognize the contents. Thanks to Kirk
+Mefford <kc2elo at softhome.net> for noticing this. The editor "nano"
+can be invoked from a Cygwin window to create this file, or for
+those of you who know "vi" or have Windows editors available that
+can save in Unix format, use those. If you don't, the "cvs update"
+commands won't work for you, at least until you recreate the file in
+Unix format. You've been warned!
+
+The "." in ".cvsrc" makes it a Unix hidden file, and it won't appear
+in most Unix listings. Unix files don't need a file extension, so
+don't create a file that has one (or else rename it to ".cvsrc" when
+done).
+
+Another option is to create the file using a Windows editor, then
+run a dos2unix program on it to convert it to the proper format.
+
+
+[ ] Step 5) Download Xastir sources. Start up Xwindows using your
+shortcut. Type the six lines below into the shell exactly as shown.
+Hit <ENTER> when asked for a password after typing line four (the
+"login" command):
+
+ cd ~
+ touch .cvspass
+ mkdir src
+ cd src
+ cvs -d:pserver:anonymous at xastir.cvs.sourceforge.net:/cvsroot/xastir login
+ cvs -d:pserver:anonymous at xastir.cvs.sourceforge.net:/cvsroot/xastir co xastir
+
+NOTE: The "login" command must complete without errors in order to
+create a dummy blank password in your .cvspass file. Without this
+password you'll have trouble with later CVS commands. If you see
+"EOF", "connection reset by peer", "connection refused", or "timed
+out", it means that the anonymous CVS server at SourceForge is
+overloaded (too many users). Keep trying the failed commands until
+they succeed! Notice that up-arrow (on the keyboard) and then
+<ENTER> will repeat the last command, saving you some typing.
+
+The end result when it succeeds will be a new directory
+"C:\cygwin\home\<user>\src\xastir\" which contains all of the Xastir
+source code. You can type "ls xastir" (that's lower-case LS) to see
+the file listing.
+
+Side Note: Here's the coolest thing about CVS: Once you've done
+this initial source-code download, you'll never have to do the whole
+Xastir download again. You'll just go into the "src/xastir"
+directory and type "cvs update", which will snag just the _changes_
+to the files since you last updated, and is very fast. Compile and
+install at that point and you'll be running the latest developer's
+version in just a few minutes! It's very easy to keep up with the
+developers this way.
+
+
+[ ] Step 6) Configure/compile/install Xastir. Type these commands
+into the BASH shell, waiting until each one completes before typing
+the next command:
+
+ cd ~/src/xastir
+ ./bootstrap.sh
+ ./configure
+ make
+ make install
+
+NOTE: You'll probably want to run the configure step from an xterm
+window with the X11 server running of course. If you do this from a
+non-X11 window then the configure test for "gv" will fail, as "gv"
+requires an X11 server even when asking it for it's version number.
+Without "gv" support you won't be able to print from Xastir.
+
+NOTE: The "make" step can be extremely memory hungry. If you don't
+have much free memory, that step might take a long time to run. One
+Win2k machine with only 20MB of free RAM (128MB total RAM) couldn't
+complete this step, but adding another 128MB of RAM to that machine
+caused it to succeed. Another machine running Win2k with 64MB free
+(128MB total RAM) took six hours (but keep reading!). Free up
+memory if you're having trouble completing that step. This behavior
+is only seen on Windows/Cygwin, not on the Unix-based systems. On a
+typical Linux box that step takes under two seconds. Hopefully
+Cygwin linking will improve over time to alleviate this issue.
+We've added a new link-stage parameter to reduce the memory usage
+for that step, but it doesn't totally resolve the problem. The
+machine that took six hours originally now takes 60 seconds to
+complete that step.
+
+Ignore the "PACKAGE_* redefined" warnings. They won't break
+anything and are just an annoyance.
+
+Once you get through the above commands, Xastir is compiled and
+installed on your system, with minimal map support. Later sections
+of this document detail adding additional map libraries in order to
+give you access to the full mapping capability of Xastir.
+
+NOTE: If you get the below errors during the compile it means that
+Cygwin has changed one of their packages to be incompatible with the
+rest (and needs to change a lot more of their packages to
+correspond):
+---------------------------------------------------------------------
+/usr/include/Xm/Print.h:28:34: X11/extensions/Print.h: No such file or directory
+In file included from /usr/include/Xm/XmAll.h:79,
+ from alert.c:308:
+/usr/include/Xm/Print.h:40: error: parse error before "XPContext"
+/usr/include/Xm/Print.h:43: error: parse error before '}' token
+/usr/include/Xm/Print.h:61: error: parse error before "XPFinishProc"
+make[3]: *** [alert.o] Error 1
+---------------------------------------------------------------------
+A temporary fix for the above errors (until Cygwin gets their act
+together) is to do the following:
+---------------------------------------------------------------------
+ Launch the Cygwin setup program
+ When you get to the list of packages change the list to FULL mode
+ Uncheck "Hide Obsolete Packages"
+ Scroll down the list until you find xorg-x11-devel
+ Click on the word "keep" until it changes to a 6.x version of the file
+ Click Next and finish the setup
+ Unfortunately you'll have to perform the same fix each time you
+ use the Cygwin setup program or it will "upgrade" to the
+ broken package again.
+---------------------------------------------------------------------
+
+[ ] Step 7) Create a link to the Xastir executable. Type the
+following commands into the BASH shell:
+
+ cd ~
+ ln -s /usr/local/bin/xastir xastir
+
+That will create a symbolic link from your home directory to the
+Xastir executable, to make it easier to run Xastir without typing
+the long path each time.
+
+
+[ ] Step 8) Actually run the darn thing:
+
+Let's start from scratch to make sure it all works. Close any
+Cygwin/BASH windows you may have.
+
+Click on the shortcut you created to start Xwindows.
+
+From the resulting BASH window, type "xastir &". Xastir should
+start up shortly.
+
+Note: Xastir has support for PocketAPRS, DosAPRS, WinAPRS, MacAPRS
+and GNIS maps by default. For additional types of maps, you'll need
+to install some libraries, then recompile Xastir so that it knows to
+use them. See the instructions below.
+
+The README.MAPS file has instructions for where to get maps and where
+to put them under the Xastir hierarchy.
+
+If you have any WinAPRS, DosAPRS, or PocketAPRS maps, now is a good
+time to place them in the /cygwin/usr/local/share/xastir/maps folder
+(or a subdirectory of it). You can also use "*.geo" files and the
+associated image files with Xastir. You may place them in this
+directory (or a subdirectory of it) as well, though most of the .geo
+files won't work for you until you install the ImageMagick library.
+
+What Xastir paths look like from within Windows (in case you're
+moving maps around with Explorer): Just prefix them all with
+"cygwin/". For instance, maps go into
+/cygwin/usr/local/share/xastir/maps instead of
+/usr/local/share/xastir/maps. Xastir will continue to see them as
+"/usr/local/share/xastir/maps" though from inside Cygwin. It kind
+of looks like a miniature Unix box from inside Cygwin.
+
+Run Windows in 15-bit color or better (32768 colors or more) or
+you'll get lots of warnings about Xastir not being able to allocate
+colors when it starts up, and the display will be rather stark
+looking.
+
+To set a new language or change the language current choice, use
+this command line instead from inside an Xterm:
+
+ xastir -l <language>
+
+Current choices are:
+
+ Dutch English French German Italian Portuguese Spanish
+ ElmerFudd MuppetsChef OldeEnglish PigLatin PirateEnglish
+
+This option will be stored in the users config file for the next
+time Xastir is run. On new installs Xastir will default to English
+until you use this command line option once.
+
+Another difference with Cygwin as opposed to Unix-like operating
+systems: You can't do the make install portion if Xastir is up and
+running. You have to kill Xastir first before you do "make install"
+or "make install-strip". Otherwise the newly compiled Xastir won't
+replace the old one.
+
+Note that one user running Cygwin on XP had it crash every time his
+screen-saver kicked in. Disabling the screen-server fixed that
+problem.
+
+Another interesting "feature" of Cygwin/Xwindows is that some of the
+modifier keys like ScrollLock/CapsLock/NumLock must be pressed while
+that X-window is the active foreground window. If not, the event
+can be missed, and Xwindows can get out of sync with the actual
+state of the key. This doesn't appear to be an Xastir-specific
+problem, but a Cygwin/Xwindow problem. With just a BASH shell under
+Cygwin (not involving Xwindows), the problem doesn't appear to
+happen. Just inside Xwindows on Cygwin.
+
+Some users have experienced problems with their Windows box running
+the NTFS "convert.exe" program instead of the ImageMagick
+"convert.exe" program, usually when enabling snapshots in Xastir.
+If you experience this, check your path settings and make sure that
+ImageMagick's path is first.
+
+When specifying serial ports to use with Xastir,
+
+ "COM1" is called "/dev/ttyS0" in Cygwin (and Linux)
+ "COM2" is called "/dev/ttyS1" in Cygwin (and Linux)
+
+Note the capital 'S'.
+
+
+[ ] Step 9) Document & Back Up the Configuration
+
+One user had a problem where after Cygwin/Xastir was installed, he
+installed another program, in this case Java, and it wiped out some
+of the environment variables that Cygwin set. $HOME was one
+variable that got changed.
+
+To guard against such changes, go to My Computer and right-click on
+properties. Write down the Advanced System Variables and keep the
+note in a safe place.
+
+
+Optional
+
+To shorten the Xastir sequence or to automate the startup process of
+Xastir in Windows environment, the following may prove useful.
+
+ 1. Locate startwin.bat, it will be located at: Cygwin install
+ drive, eg; C:\cygwin\usr\X11r6\bin\ Please make a backup copy
+ in case something goes wrong! Save it as a new name such as
+ startwin.bak or startwin.orig.
+
+ 2. Open startwin.bat with notepad or another ASCII text editor.
+
+ 3. Find the line:
+
+ run xterm -sl 1000 -sb -rightbar -ms red -fg yellow -bg black -e /usr/bin/bash
+
+ 4. Copy and paste the line into the startwin.bat file directly
+ under the line you just copied.
+
+ 5. Cut /usr/bin/bash -l from the end of the line then enter
+ /usr/local/bin/xastir where you just cut. You will end up with
+ entries such as this:
+
+ run xterm -sl 1000 -sb -rightbar -ms red -fg yellow -bg black -e /usr/bin/bash -l
+ run xterm -sl 1000 -sb -rightbar -ms red -fg yellow -bg black -e /usr/local/bin/xastir
+
+ 6. Save startwin.bat
+
+Now when you click the XWindow shortcut, Xastir will start without
+the need to wait for the BASH shell and typing Xastir &. In
+addition, a BASH shell window will open to allow you to monitor any
+error messages or other information generated by Xastir put out to
+STDERR and shown in the shell.
+
+In addition, you can add a shortcut to the startup directory to
+automatically start Xastir when you start Windows..
+
+
+
+Please see the INSTALL file and the Help menu in Xastir itself
+for additional information not mentioned in this document.
+
+Additional info can be found on the cygwin web-site:
+
+ http://www.cygwin.com
+
+or the Cygwin/XFree86 web-site:
+
+ http://cygwin.com/xfree/
+
+
+[ ] Step 10) Keeping up-to-date:
+
+Once a week or once a month, run the Cygwin network installer
+program (step 1b above). After it finishes, open a Cygwin window
+and type these commands to update the Xastir source code:
+
+ cd ~/src/xastir
+ cvs update
+
+If you see "EOF" or "connection reset by peer" it means that the
+anonymous CVS server at SourceForge is overloaded (too many users).
+Keep trying the failed commands until they succeed! Notice that
+up-arrow (on the keyboard) and then <ENTER> will repeat the last
+command, saving you some typing.
+
+Every once in a while Windows will refuse to allow you to
+delete/rename one of the files. The only way I've found to get
+around this problem is to reboot. I sometimes see this when trying
+to do a CVS update, and Windows won't allow one or more files to get
+updated.
+
+Repeat step 6) above to recompile/reinstall the latest Xastir.
+
+A very good option is to read the SUDO instructions in the
+README.CVS file, setting up the /etc/sudoers file and creating an
+update-xastir script as shown. Then you can type "./update-xastir"
+at any time to snag down the latest Xastir changes, compile, and
+install it. We've just included an update-xastir script with
+Xastir, so you don't have to create it anymore. You may however
+need to remove the "sudo" keyword from each line for it to work
+properly on Cygwin.
+
+
+-----
+Notes from Henk de Groot:
+
+1) On Windows ME I had to configure the shortcut to start Xwindows,
+it ran out of environment memory. Selecting an "Initial Environment"
+of 4096 bytes in tab "Memory" (I hope that is correct, I have a
+Dutch language version...) fixed it.
+
+2) My keyboard layout was a mess in the xterm, I had to add
+"setxkbmap us" to c:\cygwin\usr\X11R6\bin\startxwin.bat (just below
+"run XWin....").
+
+
+-------------------------------------------
+OPTIONAL: ADDING ADDITIONAL MAP LIBRARIES:
+-------------------------------------------
+
+These additional Xastir libraries have been tested on Cygwin:
+
+ ImageMagick
+ Shapelib
+ libtiff
+ libproj
+ libgeotiff
+ Festival
+ GDAL/OGR
+
+Anyone testing additional libraries is encouraged to share their
+findings on the Xastir mailing lists (you must be subscribed in
+order to post messages there). The libraries which have _not_ been
+made to work yet on Cygwin are:
+
+ AX25
+ GPSMan/gpsmanshp
+
+The AX25 libraries will probably never work, as they are for Linux
+only. GPSMan/gpsmanshp may work on Cygwin at some point if enough
+work is done to figure out and document the process.
+
+
+RECOMMENDED: Adding Shapelib (tested with shapelib-1.2.10):
+------------------------------------------------------------
+
+*******************************NOTE**************************************
+As of 10 November 2006, xastir's source tree contains a copy of shapelib
+1.2.10, and automatically builds shapelib if you don't have it installed.
+At this point, the only reason to follow the "Adding Shapelib" instructions
+below is if you need the shapelib shared libraries to work in other cygwin
+software. So unless you do, just skip this section and xastir's build process
+will automatically build and use its own "internal" shapelib support. Since
+the instructions below contain some "gotchas" that you have to work around,
+just using internal support is far easier if you don't need shapelib for
+other projects.
+************************************************************************
+
+Allows using many sources of online polygon, polyline, and point
+maps, including ones from NOAA. This is the only format used for
+weather alert maps.
+
+NOTE: A private copy of the Shapelib library is now included with
+Xastir. If you need Shapelib only for use with the Xastir program
+you can rely on this private copy to be installed and statically
+linked with Xastir. If you need Shapelib for any other program,
+it's recommended that you install it as shown below instead, so that
+Xastir and the other programs will use a shared library.
+
+[ ] From a BASH shell, type:
+
+ cd ~/src
+ mkdir shapelib
+
+[ ] Fetch "shapelib-1.2.10.tar.gz" from one of these sites:
+
+ http://shapelib.maptools.org/
+or http://wetnet.net/~we7u/xastir/shapelib/
+
+[ ] Put it in the C:\cygwin\home\<user>\src\shapelib directory.
+
+[ ] Untar it from the BASH shell:
+
+ cd ~/src/shapelib
+ tar xzvf shapelib-1.2.10.tar.gz
+
+[ ] Essential: Edit Shapelib's Makefile to remove the space after the "-h" on
+the line that looks like this:
+
+ /usr/bin/ld -G -h libshp.so.1 -o .libs/libshp.so.$(LIBSHP_VERSION) shpopen.lo shptree.lo dbfopen.lo -lc
+
+Change it to this (one space missing and 'c' changed to "cygwin"):
+
+ /usr/bin/ld -G -hlibshp.so.1 -o .libs/libshp.so.$(LIBSHP_VERSION) shpopen.lo shptree.lo dbfopen.lo -lcygwin
+
+I've had another report that says having the space is OK now. The
+"-lcygwin" is important to bypass the "__getreent" bug below.
+
+Here are the commands to bring up an editor on the file:
+
+ cd ~/src/shapelib/shapelib-1.2.10
+ nano Makefile
+
+
+[ ] Save the edited file, then type:
+
+ make lib
+
+[ ] You may get the "undefined reference impure_ptr" messages. If
+so, edit the file /usr/include/sys/reent.h to remove the word
+"extern" from this line:
+
+ extern struct _reent *_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
+
+then try "make lib" again.
+
+[ ] Type:
+
+ make lib_install
+
+If you get "cp: cannot stat `.libs/libshp.la': No such file or
+directory", then you forgot to edit the Makefile. BZZZT! Please
+start again at step 1) above. Thank you for playing!
+
+If you get something like: "Makefile:121: *** Missing separator.
+Stop.", then it's likely that while editing the Makefile you ended
+up with line-wrap on a line (one line broken into two or more lines
+because the editor thought it was too long). Combine the line into
+one line again and retry. Make sure not to delete any spaces that
+are there between items on the line, else you'll get different
+errors.
+
+[ ] Now you should be ready to configure and compile Xastir with
+Shapelib support. Type these commands:
+
+ cd ~/src/xastir
+ ./configure
+ make
+ make install
+
+The installed copy of Xastir should now have Shapelib support. You
+can download NOAA weather alert maps and many other sorts of maps,
+and Xastir will recognize and use them. Note that weather alert
+shapefiles must go into the /usr/local/share/xastir/Counties
+directory. All other shapefiles must go into the
+/cygwin/user/local/share/xastir/maps directory (and subdirectories
+below that of your choosing).
+
+See the README.MAPS file for where to get the maps, and a script to
+automate the download/install for you.
+
+
+Note from Gale Wilkinson, kc4pl:
+> >
+> > How do you get shapelib to "make" properly under cygwin? I
+> > have installed the latest cygwin (packages per the win32
+> > install notes) and then downloaded and unpacked the latest
+> > shapelib source package for compiling. But when trying to do
+> > the "make lib" it errors out part way through the process.
+> > The error seems to be:
+> >
+> > dbfopen.lo: In function 'DBFReadAttribute':
+> > /home/gwilkinson/src/shapelib-1.2.10/dbfopen.c:724:undefined
+> > reference to '__getreent'
+> > /home/gwilkinson/src/shapelib-1.2.10/dbfopen.c:716:undefined
+> > reference to '__getreent'
+> > make: *** [lib] Error 1
+
+Dan Brown, n8ysz, responded:
+>
+> I wrote this to get/make shapelib:
+>
+> http://brauhaus.org/xastir/get_shapelib.sh
+> or
+> http://brauhaus.org/xastir/get_shapelib.sh.txt
+
+This script is now also in the Xastir sources as
+"xastir/scripts/get_shapelib.sh".
+
+
+
+OPTIONAL: Adding ImageMagick:
+--------------------------------------------------------------
+Note: Recent Cygwin installations include ImageMagick 6.0.4.
+Unfortunately, this install is linked against some X11 DLLs that no
+longer get installed by the most recent X11 package. See
+ http://comments.gmane.org/gmane.os.cygwin.xfree/16493 for a
+work-around. NOTE: It appears this problem may have been fixed in the
+latest-latest (as of 13 November 2006) ImageMagick/Cygwin package.
+
+The ideal solution to the problem mentioned above is to rebuild
+ImageMagick from source code instead of using the (now-unmaintained)
+Cygwin ImageMagick package. The instructions below walk you through a
+build of a much older version of ImageMagick, and should still be
+fairly accurate for a more recent vintage (as of this writing,
+ImageMagick versions are up over 6.2, meaning that both the version in
+Cygwin and the version mentione below are very old).
+
+Allows using more than 68 different graphics format files as maps,
+by creating an associated .geo file for each with tie-points. This
+support also allows use of online Tiger and Terraserver maps with
+Xastir, and NOAA weather radar images. Other people are working on
+integrating even more online mapping sources. This will also allow
+you to use any GIF/JPG/XPM/BMP/... image as an Xastir map.
+
+Note: The much older Cygwin binary for ImageMagick-5.5.5 has a problem
+in it's Magick-config script which makes it impossible to use for our
+purposes. Don't try to use that version. Some people reported a
+similar problem with 5.5.7.
+
+Note that Xastir's "./configure" stage may fail trying to compile in
+ImageMagick support. If this happens, make sure you have the
+ImageMagick development package installed if using RPM packages, or
+have installed the ImageMagick header files. If it still fails,
+check the "config.log" file _very_ carefully. Often ImageMagick
+tests fail due to some other library that ImageMagick depends upon
+being absent, such as liblcms, libbz2, or others.
+
+Until the RPM packagers for ImageMagick include all of the dependent
+libraries in their RPM dependency list, the best way to assure that
+ImageMagick is installed properly is to install it from sources.
+
+
+ImageMagick:
+ http://www.imagemagick.org/
+
+ cd ~/src
+ mkdir imagemagick
+
+[ ] Download the ImageMagick cygwin binary from www.imagemagick.org
+or one of it's mirrors. If you can't find the version you need, try
+here:
+
+ http://wetnet.net/~we7u/xastir/ImageMagick/cygwin/
+
+[ ] Put it in the ~/src/imagemagick directory.
+
+[ ] Extract the files:
+
+ cd ~/src/imagemagick
+ tar xzvf filename
+
+[ ] Copy the files/directories into the /usr tree:
+
+ cd ImageMagick-5.5.3
+ cp -R * /usr
+
+[ ] Reconfigure Xastir to use this library:
+
+ cd ~/src/xastir
+ ./configure
+
+[ ] If "configure" did not find ImageMagick properly, edit the
+resulting config.h file and change this line:
+
+ /* #undef HAVE_IMAGEMAGICK */
+
+to this:
+
+ #define HAVE_IMAGEMAGICK 1
+
+
+[ ] Finish the Xastir build and install:
+
+ make
+ make install
+
+[ ] Add this to your ~/.profile file (note this is a different file
+than the .bash_profile file):
+
+ export MAGICK_HOME=/usr
+
+Now on-line Tigermaps should work for you. Unfortunately it looks
+like the ".profile" file doesn't automatically get run if you start
+up the X-server from a windows shortcut. If you don't set the
+MAGICK_HOME variable in your shell that you start Xastir from, then
+ImageMagick will fail to display images and you'll get messages like
+"No decode delegate for this image format" in the xterm you started
+Xastir from. If that happens, you can close Xastir, type
+
+ . ./.profile
+
+and then type "xastir &" again to make it work. Another option is
+to start X from within a standard Cygwin window. After starting X
+you can close the original Cygwin window. Yet another option is to
+create a script for starting Xastir so that you can set the
+MAGICK_HOME variable just before you start it. It could look
+something like this:
+
+ #!/bin/sh
+ export MAGICK_HOME=/usr
+ xastir &
+
+Perhaps name it "aprs". Issue this command to turn it into an
+executable file:
+
+ chmod 755 aprs
+
+
+Start it by typing "./aprs".
+
+--------------------------------------------------------------------
+Note from Kirk Mefford, KC2ELO:
+
+Also one more way to work around the "MAGICK_HOME" issues with
+running from the startxwin.bat file is to add "SET MAGICK_HOME=/usr"
+to the bat file before it gets to loading things. [remember DOS? ;)
+]
+
+I have Xastir loading directly from "startxwin.bat" with "run
+/usr/local/bin/xastir" and ImageMagick works fine with "SET
+MAGICK_HOME=/usr" at the top of the bat file.
+--------------------------------------------------------------------
+
+
+HIGHLY RECOMMENDED: If you create a file called "terraserver.geo"
+in the /usr/local/share/xastir/maps directory, containing the single line
+"TERRASERVER-SATELLITE", and select it with the Map Chooser, you should
+see satellite images on the map screen. This is assuming that you have
+an Internet connection up and running of course. It fetches the
+images from the Microsoft Terraserver.
+
+Also create a "terraserver-topo.geo" file in the same area somewhere.
+Inside that file put the keyword "TERRASERVER-TOPO". Selecting this map
+will fetch topo maps from the Microsoft Terraserver. More interesting
+keywords that can be used in other files are "TERRASERVER-REFLECTIVITY"
+and "TERRASERVER-URBAN". There should be files for all four Terraserver
+options installed in your /usr/local/share/xastir/maps/Online directory
+once you install Xastir.
+
+This means if you're online, you can have access to street maps
+(Tigermap server), satellite images (Terraserver), and topo maps
+(again Terraserver)!
+
+
+
+OPTIONAL: Install GeoTIFF support:
+-----------------------------------
+Note: Recent Cygwin installations include GeoTIFF support, and if you
+installed everything in the list in step 1, you already have it.. You
+only need to manually install libgeotiff if you did not have the 3
+libgeotiff choices, the 2 libproj choices, and the proj choice
+available when installing cygwin, or if Xastir doesn't find libgeotiff.
+
+Allows using USGS DRG topo maps or other types of GeoTIFF
+maps/images and has the ability to tile smaller maps into a larger
+contiguous map of an area:
+
+[NOTE: when checked on 30 Oct 2004, it is now possible to install
+libproj and libgeotiff directly from cygwin setup. Since at least one
+user has had considerable trouble installing xastir with geotiff using
+the instructions below, it is recommended that these libraries be
+installed through cygwin setup instead. Be sure to install the
+"-devel" versions that will include headers and libraries needed to
+compile xastir.]
+
+For GeoTIFF support (such as USGS DRG topo maps) you need one each
+of libproj, proj-nad27, and libgeotiff:
+
+
+ libproj (tested with proj-4.4.7):
+ ---------------------------------
+ http://www.remotesensing.org/proj/
+or http://wetnet.net/~we7u/xastir/libproj/
+
+
+ Datum translations (tested with proj-nad27-1.1):
+ ------------------------------------------------
+ ftp://ftp.remotesensing.org/pub/proj/
+or http://wetnet.net/~we7u/xastir/libproj/
+
+
+ libgeotiff (tested with libgeotiff-1.2.0):
+ ------------------------------------------
+ http://www.remotesensing.org/geotiff/geotiff.html
+or ftp://ftp.remotesensing.org/pub/geotiff/libgeotiff/
+or http://wetnet.net/~we7u/xastir/libgeotiff/
+
+
+Please note that the order of installation for these libraries is
+critical. If not installing from cygwin setup, please be sure to
+follow the instructions below carefully.
+
+
+Adding libproj to Cygwin (tested with proj-4.4.7):
+--------------------------------------------------
+
+Again, if you installed everything suggested in step 1, you already
+have this and building libproj from source is unnecessary.
+
+NOTE: You must install libproj BEFORE compiling libgeotiff, because
+libgeotiff uses libproj to do the datum translations. If you install
+libgeotiff first, datum translations won't work.
+
+[ ] Type:
+
+ cd ~/src
+ mkdir libproj
+
+[ ] Download the libproj and proj-nad27 files and place them in the
+~/src/libproj directory.
+
+The proj-nad27-1.1.tar.gz must be decompressed in the nad
+subdirectory of the proj distribution directory before you run
+configure.
+
+[ ] Type:
+
+ cd ~/src/libproj
+ tar xzvf proj-4.4.7.tar.gz
+ cd proj-4.4.7/nad
+ tar xzvf ../../proj-nad27-1.1.tar.gz
+ cd ..
+ ./configure
+ make
+ make install
+
+
+[ ] These next few commands are required for now, but once
+libgeotiff is fixed so that it finds libproj properly on Cygwin,
+they'll be removed from the libproj instructions:
+
+ cd /usr/lib
+ ln -s /usr/local/lib/libproj.a
+ ln -s /usr/local/lib/libproj.la
+
+
+
+Adding libgeotiff (tested with libgeotiff-1.2.0):
+-------------------------------------------------
+
+[ ] Type:
+
+ cd ~/src
+ mkdir libgeotiff
+
+[ ] Download libgeotiff-1.2.0 and place it in the libgeotiff
+subdirectory.
+
+ cd ~/src/libgeotiff
+ tar xzvf libgeotiff-1.2.0.tar.gz
+ cd libgeotiff-1.2.0
+ ./configure
+ make
+ make install
+
+If you must re-run "configure" for any of these libraries, remember
+to delete "config.status" and "config.cache" files first.
+
+[ ] You may get the "undefined reference impure_ptr" messages (just
+like with Shapelib above). If so, edit the file
+/usr/include/sys/reent.h to remove the word "extern" from this line:
+
+ extern struct _reent *_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
+
+then try "make" and "make install" again.
+
+I've had it compile all the way through, but I've also had it bomb
+out when it gets to the "ld -shared" step. At that point it writes
+a lot of "undefined reference" messages. The line at which the
+compile might fail:
+
+
+ ld -shared xtiff.o geo_free.o geo_get.o geo_names.o geo_new.o
+ geo_print.o geo_set.o geo_tiffp.o geo_write.o geo_trans.o
+ geo_normalize.o geotiff_proj4.o geo_extra.o cpl_serv.o cpl_csv.o -lproj
+ -ltiff -ljpeg -lz -lm -L/usr/local/lib -o libgeotiff.so.1.1.5
+
+
+To fix this, edit the Makefile to add "-lc" to the end of the LIBS
+line and run "make" again, then "make install".
+
+
+[ ] TEMPORARY: It looks like we need to switch to a newer version
+of the libtiff DLL in order to work with libgeotiff. Some Cygwin
+installations end up with this "cygtiff3.dll.new" file installed in
+/bin, some do not. If the images appear to load but always come up
+black, you need to get a different cygtiff3.dll file that works on
+your system. Below are the instructions for fixing this problem if
+that file is already present:
+
+ cd /bin
+ mv cygtiff3.dll cygtiff3.dll.old
+ cp cygtiff3.dll.new cygtiff3.dll
+
+
+[ ] Set up Xastir to use the new geotiff libraries:
+
+ cd ~/src/xastir
+ ./configure
+ make
+ make install
+
+It should find libtiff/libproj/libgeotiff at the configure stage and
+compile in support for geotiff maps. You should now be able to use
+USGS GeoTIFF topo maps, and see them tiled together in the map
+window into a continuous map.
+
+
+
+OPTIONAL: Install Festival support:
+------------------------------------
+Allows using a synthesized voice from within Xastir for alerts,
+reading messages to you, and other cool things. Tom Russo did the
+initial work on this, Henk de Groot optimized it:
+
+1) Start BASH shell in Cygwin
+
+2) Make ~/festival download directory and
+ /usr/local/festival installation directory
+
+3) Download festival components from festvox.org into ~/festival, in
+ the Windows environment the corresponding path is:
+
+ C:\Cygwin\home\%USERNAME%\festival
+
+ get the following files:
+
+ speech_tools-1.2.95-beta.tar.gz
+ festival-1.95-beta.tar.gz
+ festlex-CMU.tar.gz
+ festlex-POSLEX.tar.gz
+ festvox-kallpc16k.tar.gz
+
+4) Build festival and company:
+
+ cd /usr/local/festival
+ tar xzf ~/festival/speech_tools-1.2.95-beta.tar.gz
+ tar xzf ~/festival/festival-1.95-beta.tar.gz
+ tar xzf ~/festival/festlex_CMU.tar.gz
+ tar xzf ~/festival/festlex_POSLEX.tar.gz
+ tar xzf ~/festival/festvox_kallpc16k.tar.gz
+
+ cd speech_tools
+ ./configure && make
+ cd ../festival
+ ./configure && make
+
+ These packages are build and used where they are compiled.
+
+5) Test festival:
+
+ cd /usr/local/festival/festival/examples
+ sh saytime
+
+ Festival should say the time if everything went fine
+
+6) Add /festival/festival/bin to PATH in .profile and .bashrc. For
+ me both files look like this:
+
+ .profile and .bashrc:
+ -------------------
+ export PATH=$PATH:/lib:/usr/lib:/usr/X11R6/lib:/usr/local/lib:/usr/local/bin:/usr/local/festival/festival/bin:~/bin:.
+
+ -------------------
+
+7) Configure and build xastir. Configure should report that
+ festival is found.
+
+8) Start the festival server:
+
+ festival --server &
+
+ To do this automatically I added the following lines to my
+ .bash_profile:
+
+ -------------------
+ if [ `ps -ef | grep festival | wc -l` -eq 0 ]
+ then
+ festival --server &
+ sleep 1
+ fi
+ -------------------
+
+9) Run xastir, do File->Configure->Speech, add things to say, and
+ listen.
+
+
+
+How to make Sound Alerts work under Cygwin
+------------------------------------------
+(from Kirk Mefford, kc2elo)
+"I figured I'd share exactly what I did to make the sound alerts work in
+xastir under Cygwin. Sound support seems to be just one of the many quirks
+of trying to use *nix native software under Microsoft OS's. Hope this helps
+someone else.
+
+FYI: This was tested under Win2000
+
+Sound alert support under Cygwin using Network Audio Server (NAS)
+
+I downloaded http://nas.intra-links.net/files/nas-1.6-win-binary.zip and
+decompressed the archive with winzip (any zip utility should work fine) into
+a temporary folder.
+
+I deleted the "cygwin1.dll" and "README.txt" files that came in the package
+since they aren't needed and the extra cygwin1.dll can cause problems.
+
+
+ Note from James Cour, K1ZC:
+ ---------------------------
+ "The procedure he (Kirk) outlines there works fine EXCEPT that
+ there is a valuable piece of information in that Readme.txt file...
+ The user must have a folder named /DEV under the Cygwin folder in
+ order for NASD to work. NASD will not create it automatically, and
+ NASD will not run without it. The default set-up instructions for
+ Xastir and Cygwin do not create this folder, so the user needs to
+ manually create the folder from Windows."
+
+
+ Note from Tim Baggett, AA5DF:
+ -----------------------------
+ "I recommend running the script (create_devices.sh) found attached
+ to the email located at the URL below to create the /dev directory,
+ and all supported devices under Cygwin."
+
+ "http://cygwin.com/ml/cygwin-xfree/2004-01/msg00353.html"
+
+
+Then copy the remaining files from the package into the /bin directory under
+cygwin.
+
+All that is needed to make nas available to xastir is to load the server
+before running xastir.
+
+To load NAS for xastir to use simply type "nasd -local -b" from cygwin. This
+command will load the NAS server in the background and will only allow local
+users to access it. For more command options type "nasd -help" from within
+cygwin. Some people have trouble with the "-local" option, so try
+it without that option as well ("nasd -b").
+
+After NAS is loaded you can load xastir as you normally would.
+
+Once xastir is running, to play sound alerts you need to change the default
+configuration to use "auplay"
+
+From within xastir click on File>Configure>Audio Alarms.
+The "Audio Play Command" box should be changed to "auplay"
+Then ensure the audio files listed to play are located in
+"/usr/local/share/xastir/sounds" directory.
+
+Click OK to accept the changes and be sure to save your config before
+exiting xastir or sound will not work the next time it is loaded.
+
+Turn up the volume on your PC speakers and enjoy the noise xastir makes."
+
+
+OPTIONAL: Install GDAL/OGR support:
+------------------------------------
+One user has been successful in compiling GDAL/OGR support into
+Xastir. One thing he mentioned:
+
+"Now the word of warning. If you try to compile GDAL under Cygwin
+and the compile blows up, you are better rm -rvf'ing the entire
+directory and re-untaring the source again than trying to recompile
+in that blown directory. Make Clean doesn't do a thing and the old
+settings and mistakes stick around no matter what you try."
+
+Make sure you've got Shapelib installed on your system else Xastir
+won't find GDAL (the private Xastir copy of Shapelib is fine). Both
+are needed.
+
+Download "gdal-1.2.0b.tar.gz". In a cygwin window, type the
+following:
+
+
+ tar xzvf gdal-1.2.0b.tar.gz
+ cd gdal-1.2.0b
+ ./configure --with-jpeg=internal --with-libtiff=internal
+ make
+ make install
+
+
+The GDAL/OGR library should now be installed on your system. Return
+to the xastir directory and start with the ./configure command. It
+should pick up the fact that GDAL/OGR has been installed and compile
+support for it into Xastir. Follow with the rest of the commands to
+make/install Xastir.
+
+One user required the below GDAL configure line as otherwise it
+complained about not finding libproj:
+
+ ./configure --with-jpeg=internal --with-libtiff=internal --with-static-proj4
+
+
+APRS(tm) is a Trademark of Bob Bruninga
+
+Copyright (C) 2003-2012 The Xastir Group
+
diff --git a/TXRadar.geo b/TXRadar.geo
new file mode 100644
index 0000000..d795090
--- /dev/null
+++ b/TXRadar.geo
@@ -0,0 +1,23 @@
+#
+# $Id: TXRadar.geo,v 1.1 2004/10/05 15:54:25 we7u Exp $
+#
+#US Composite Radar image (Unidata/LDM/Gempak) n5jxs 2003 08 25
+URL http://mesonet.tamu.edu/gemdata/images/radar/01_mesonet.png
+# X Y Long Lat
+TIEPOINT 200 200 -104.80000 35.50000
+TIEPOINT 1130 1090 -95.50000 26.60000
+# Image extents: Lat: 24.6N to 37.5N, Lon: 93.5W to 106.8W (-93.5 to -106.8) # Image size extents: X: 1330 pixels, Y: 1290 pixels (.01 deg/pixel)
+IMAGESIZE 1330 1290
+#
+# REFRESH tells your program just how often to retrieve the radar
+# image. Images are recreated on the server every 6 minutes (720 sec).
+REFRESH 720
+# Transparent tells the program and image handling software what color
+#is to be considered transparent. In this case, it's white and valid
+# for a 24-bit color map.
+#TRANSPARENT 0xffffff
+# The following should work for a 16-bit color map.
+#TRANSPARENT 0x0ffff
+# The following should work for all color maps, now.
+TRANSPARENT 0x0ffffffff
+
diff --git a/UPGRADE b/UPGRADE
new file mode 100644
index 0000000..814f431
--- /dev/null
+++ b/UPGRADE
@@ -0,0 +1,95 @@
+
+$Id: UPGRADE,v 1.18 2012/11/01 18:57:18 we7u Exp $
+
+
+Previous Install Notes:
+-----------------------
+ Backup all previous installed data!
+
+ Xastir 0.1.0 users (if there are any of you still around!):
+
+ For Xastir version 0.1.0 and below there are new file locations:
+ All map data, TNC config data, and support files now go under the
+ /usr/local/xastir directory. All personal config data, logs, etc are
+ user the (user home dir)/.xastir directory (which will be created after
+ xastir starts). You can copy (after your first xastir startup) your
+ xastir.cnf file to your (user home dir)/.xastir/config directory. MAKE
+ SURE YOU DELETE all lines referencing Files! Xastir may not run properly
+ if you don't!
+
+ If you have Xastir version 0.1.1 then your files are in the right place,
+ just follow the typical build instructions.
+
+ Xastir 0.2.0 users:
+
+ Xastir 0.2.0 and newer have new device controls so you will need to
+ setup your devices again with 0.2.0.
+ Look at File->Configure->Interfaces and File->Configure->Defaults
+
+ Xastir 0.3.x, 0.9.x, 1.0.x, 1.1.0:
+
+ Versions above 1.1 drop privileges if they are run as root. If any of the
+ Xastir files are owned by root, on only readable by root, they will cause
+ problems. Fix these files by "chmod 644 filename" where filename is the
+ problem file.
+
+ Xastir 1.2.1 or later CVS:
+
+ On or about July 3rd, 2003, the locations of the Xastir system directories
+ were changed. Existing users must go through this procedure in order to
+ convert to the new directory structure. Note that if you've installed
+ Xastir from RPM's or other packages, the migration scripts
+ (xastir-migrate.sh and xastir-fixcfg.sh) may not work properly for you.
+ These scripts are designed to move Xastir's system directories only from
+ /usr/local/xastir to the new locations. If your Xastir files are
+ installed elsewhere (/usr/share/xastir, /usr/lib/xastir, /usr/bin), you
+ may need to perform the alternate procedure listed below under ALTERNATE.
+
+ cd src/xastir
+ cvs update
+ ./bootstrap.sh
+ ./configure
+ make
+ Shut down any running Xastir instances
+ cd scripts
+ su
+ ./xastir-migrate.sh (this will move the Xastir system directories)
+ make install (or make install-strip)
+ chmod 4555 /usr/local/bin/xastir (only if required)
+ exit (from root)
+ ./xastir-fixcfg.sh (run this for each user that has ever run Xastir)
+
+
+ ALTERNATE PROCEDURE (see note above):
+
+ Remove the installed Xastir using the system tools for doing so (apt,
+ rpm, etc). You'll probably wish to keep your maps directories and
+ your ~/.xastir/config/xastir.cnf files. Make sure to delete any
+ "callpass" or "xastir" binaries as well.
+
+ Remove your ~/.xastir directory, subdirectories, and all contents
+ (remember to save your xastir.cnf file if some of the settings are
+ important to you).
+
+ Move your maps directory to "/usr/local/share/xastir/maps"
+
+ Configure/compile/install the new Xastir.
+
+ When you start up the new Xastir, it will create a new xastir.cnf file
+ with the proper directory paths defined in order to find the maps.
+
+ After you start the new Xastir, you'll need to re-index all maps. The
+ Xastir binary should be in /usr/local/bin/xastir if you installed from
+ sources. Xastir files are now installed in:
+
+ /usr/local/bin/
+ /usr/local/lib/xastir/
+ /usr/local/man/
+ /usr/local/share/xastir/*
+
+
+
+ ------------------------------------------------------------------------
+Copyright (C) 1999 Frank Giannandrea
+Copyright (C) 2000-2012 The Xastir Group
+
diff --git a/USRadar.geo b/USRadar.geo
new file mode 100644
index 0000000..523e927
--- /dev/null
+++ b/USRadar.geo
@@ -0,0 +1,37 @@
+#
+# $Id: USRadar.geo,v 1.5 2006/12/01 21:47:11 we7u Exp $
+#
+#US Composite Radar image (Unidata/LDM/Gempak) n5jxs 2003 08 25
+# Modified for accuracy, comments: n5jxs 2004 03 15 1400UTC
+#
+# If you want to get a different image-type, change the selection
+# below by removing the '#' from the front of the URL, and placing
+# a '#' before all URLs for image-types you don't want.
+# I don't know what will happen if you have multiple URLs selected.
+URL http://mesonet.tamu.edu/gemdata/images/radar/01_USrad.png
+#URL http://mesonet.tamu.edu/gemdata/images/radar/01_USrad.gif
+#URL http://mesonet.tamu.edu/gemdata/images/radar/01_USrad.jpg
+#URL http://mesonet.tamu.edu/gemdata/images/radar/01_USrad.tif
+#
+#
+# X Y Long Lat
+TIEPOINT 200 200 -123.00000 48.00000
+TIEPOINT 5999 2499 -65.00000 23.00000
+# Image extents: Lat: 23.0N to 50.0N, Lon: 65.0W to 125.0W (-65.0 to -125.0)
+# Image size extents: X: 6000 pixels, Y: 2650 pixels (.01 deg/pixel)
+IMAGESIZE 6000 2500
+#
+# REFRESH tells your program just how often to retrieve the radar
+# image. Images are recreated on the server every 6 minutes (720
+# sec).
+REFRESH 720
+# Transparent tells the program and image handling software what
+# color is to be considered transparent. In this case, it's white
+# and valid for a 24-bit color map.
+#TRANSPARENT 0xffffff
+# The following should work for a 16-bit color map.
+#TRANSPARENT 0x0ffff
+# The following should work for all color maps, now.
+#TRANSPARENT 0x0ffffffff
+TRANSPARENT 0x000000000
+
diff --git a/WMSRadar.geo b/WMSRadar.geo
new file mode 100644
index 0000000..05f7def
--- /dev/null
+++ b/WMSRadar.geo
@@ -0,0 +1,17 @@
+WMSSERVER
+#URL http://mesonet.tamu.edu/cgi-bin/CONUSradar?SERVICE=WMS&LAYERS=radar,nwscounties
+URL http://mesonet.tamu.edu/cgi-bin/CONUSradar?SERVICE=WMS&LAYERS=radar&FORMAT=image/png&TRANSPARENT=TRUE&CRS=CRS:84&BGCOLOR=0x000000&VERSION=1.1.0
+#
+#
+# REFRESH tells your program just how often to retrieve the radar
+# image. Images are recreated on the server every 6 minutes (720
+# sec).
+REFRESH 720
+#
+#
+# Black
+TRANSPARENT 0x010101
+TRANSPARENT 0x000000
+# White
+TRANSPARENT 0xffffff
+
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 0000000..6e8a31d
--- /dev/null
+++ b/acinclude.m4
@@ -0,0 +1,1106 @@
+# acinclude.m4 for Xastir
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# $Id: acinclude.m4,v 1.88 2012/11/01 18:57:18 we7u Exp $
+
+# test for devices. Avoid the tests on Cygwin as they hang on some
+# WinXP boxes.
+#
+AC_DEFUN([XASTIR_DETECT_DEVICES],
+[
+AC_MSG_CHECKING([for devices])
+if test -d /proc/registry ; then
+ac_tnc_port=/dev/ttyS0
+ac_gps_port=/dev/ttyS1
+elif test -c /dev/cuaa0 ; then
+ac_tnc_port=/dev/cuaa0
+ac_gps_port=/dev/cuaa1
+elif test -c /dev/ttyS0 ; then
+ac_tnc_port=/dev/ttyS0
+ac_gps_port=/dev/ttyS1
+elif test -c /dev/cua/a ; then
+ac_tnc_port=/dev/cua/a
+ac_gps_port=/dev/cua/b
+else
+ac_tnc_port=none
+ac_gps_port=none
+fi
+
+AC_DEFINE_UNQUOTED([TNC_PORT], "$ac_tnc_port", [Default TNC port.])
+AC_DEFINE_UNQUOTED([GPS_PORT], "$ac_gps_port", [Default GPS port.])
+AC_MSG_RESULT(found $ac_tnc_port and $ac_gps_port)
+])
+
+# add search paths
+AC_DEFUN([XASTIR_ADD_SEARCH_PATHS],
+[
+AC_MSG_CHECKING([for search paths])
+
+test -d /usr/local/include && CPPFLAGS="-I/usr/local/include $CPPFLAGS"
+test -d /usr/local/lib && LDFLAGS="-L/usr/local/lib $LDFLAGS"
+
+for d in /sw /opt /opt/local /usr/dt/share /usr/sfw /opt/sfw; do
+test -d $d/include && CPPFLAGS="$CPPFLAGS -I$d/include"
+test -d $d/lib && LDFLAGS="$LDFLAGS -L$d/lib"
+done
+
+AC_MSG_RESULT([done])
+])
+
+# add compiler flags
+AC_DEFUN([XASTIR_COMPILER_FLAGS],
+[
+# notes -- gcc only! HPUX doesn't work for this so no "-Ae +O2"
+
+
+# everybody likes "-g -O2", right?
+# TVR: Not only does "everybody" not like "-g -O2", but the code below
+# is unnecessary for GCC, which does like "-g -O2". The autoconf macros that
+# probe for the C compiler will put "-g -O2" into CFLAGS if the compiler is
+# GCC and the user has not specified any CFLAGS, and leaves CFLAGS alone
+# if the user has set it him/herself. The "##" commented code
+# below forces -g -O2 into CFLAGS even if the user has specified something
+# else.
+##for f in -g -O2; do
+## eventually write a test for these
+## gcc already checks for -g earlier!
+##echo $CFLAGS | grep -- $f > /dev/null || CFLAGS="$CFLAGS $f"
+##done
+
+# brutal!
+# check for sed maybe?
+if test "$ac_cv_prog_ac_ct_CC" = "gcc"; then
+gcc --help | sed -e "/^[^ ]/d" -e "/^ [^ ]/d" -e "/^ [^-]/d" -e "s/ //" -e "s/ .*//" > gccflags
+
+# I need a test for -Wno-return-type and -DFUNCPROTO=15
+# before adding them
+
+for f in -no-cpp-precomp -pipe; do
+grep -- $f gccflags > /dev/null && CFLAGS="$CFLAGS $f"
+done
+
+# delete temporary file
+rm -f gccflags
+
+# add any other flags that aren't added earlier
+# Can't add "-Wno-unused-parameter" as older compilers don't like
+# it.
+#
+for f in -W -Wall -Wpointer-arith -Wstrict-prototypes; do
+echo $CFLAGS | grep -- $f > /dev/null || CFLAGS="$CFLAGS $f"
+done
+
+# Now check whether to use -Wno-unused-parameter (gcc 3) or -Wno-unused
+AC_MSG_CHECKING([whether compiler accepts -Wno-unused-parameter])
+save_CFLAGS=$CFLAGS
+CFLAGS="$CFLAGS -Wno-unused-parameter"
+AC_TRY_COMPILE([] ,[int i;],[AC_MSG_RESULT([yes])] ,
+[AC_MSG_RESULT([no, using -Wno-unused]); CFLAGS="$save_CFLAGS -Wno-unused"])
+
+# end gcc-specific checks
+fi
+
+# add any pthread flags now
+CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+AC_MSG_CHECKING([for compiler flags])
+AC_MSG_RESULT(using $CFLAGS)
+])
+
+# set XASTIR_SYSTEM
+# JMT - is this really necessary?
+AC_DEFUN([XASTIR_SET_SYSTEM],
+[
+AC_MSG_CHECKING([for system])
+
+case "$host_os" in
+cygwin*)
+ system=Cygnus
+;;
+darwin*)
+ system=Darwin
+ LDFLAGS="-L/sw/lib -L/opt/local/lib $LDFLAGS"
+ CPPFLAGS="-I/sw/include -I/opt/local/include $CPPFLAGS"
+ EXTRA_BIN_PATH=":/opt/local/bin:/sw/bin"
+;;
+freebsd*)
+ system=FreeBSD
+;;
+hpux*)
+ system=HP/UX
+;;
+linux*)
+ system=Linux
+#
+#
+# Useful for testing MacOSX paths on a Linux development box:
+# EXTRA_BIN_PATH=":/opt/local/bin:/sw/bin"
+#
+#
+;;
+netbsd*)
+ system=NetBSD
+;;
+openbsd*)
+ system=OpenBSD
+;;
+solaris*)
+ system=Solaris
+;;
+*)
+ system=unknown
+;;
+esac
+
+AC_DEFINE_UNQUOTED([XASTIR_SYSTEM], "$system", [Define system type.])
+AC_MSG_RESULT($system)
+])
+
+AC_DEFUN([XASTIR_DETECT_BINARIES],
+[
+BINPATH=$PATH
+
+for d in / /usr /usr/local /usr/X11 /usr/X11R6 /usr/sfw /opt/sfw /opt/local /sw; do
+test -d $d/bin && echo $BINPATH | grep -- $d/bin > /dev/null || BINPATH="$BINPATH:$d/bin"
+done
+
+# it would be much nicer to do this in a for loop
+
+if test "$use_lsb" = "yes"; then
+ AC_DEFINE_UNQUOTED(HAVE_CONVERT, 1, [Define if you have gm or convert])
+ AC_DEFINE_UNQUOTED(CONVERT_PATH, "/opt/Xastir/bin/gm convert", [Path to gm or convert])
+else
+ AC_PATH_PROG(gm, [gm version], no, $BINPATH)
+ AC_CHECK_FILE(/usr/bin/gm.exe, gm="/usr/bin/gm")
+ if test "$gm" != "no"; then
+ AC_DEFINE_UNQUOTED(HAVE_CONVERT, 1, [Define if you have gm or convert])
+ AC_DEFINE_UNQUOTED(CONVERT_PATH, "${gm} convert", [Path to gm or convert])
+ else
+ AC_PATH_PROG(convert, [convert --version], no, $BINPATH)
+ AC_CHECK_FILE(/usr/bin/convert.exe, convert="/usr/bin/convert")
+ if test "$convert" != "no"; then
+ AC_DEFINE_UNQUOTED(HAVE_CONVERT, 1, [Define if you have convert])
+ AC_DEFINE_UNQUOTED(CONVERT_PATH, "${convert}", [Path to convert])
+ fi
+ fi
+fi
+
+AC_PATH_PROG(lpr, [lpr /dev/null], no, $BINPATH)
+if test "$lpr" != "no"; then
+ AC_DEFINE_UNQUOTED(HAVE_LPR, 1, [Define if you have lpr])
+ AC_DEFINE_UNQUOTED(LPR_PATH, "${lpr}", [Path to lpr])
+fi
+
+#Find gv executable
+AC_PATH_PROG(gv, [gv], no, $BINPATH)
+
+if test "$gv" != "no"; then
+ # Test gv version
+ AC_MSG_CHECKING([gv version])
+ gv_new="no";
+ gv_version=`gv --version 2>&1`
+ gv_test=`echo $gv_version | cut -d ' ' -f 1`
+ if test "$gv_test" != "gv"; then
+ gv_version=`gv -v 2>&1`
+ fi
+ gv_test=`echo $gv_version | cut -d ' ' -f 1`
+ if test "$gv_test" != "gv"; then
+ # No gv found. Put an AC_PATH_PROG here so the "then" clause has
+ # something to do and so that we get proper output to the user.
+ AC_MSG_RESULT([gv version test likely exited with error, this is what it said: $gv_version])
+ else
+ gv_short_version=`echo $gv_version | cut -d ' ' -f 2`
+ gv_major=`echo $gv_short_version | cut -d '.' -f 1`
+ gv_minor=`echo $gv_short_version | cut -d '.' -f 2`
+ gv_tiny=`echo $gv_short_version | cut -d '.' -f 3`
+ if test "$gv_major" -gt 3; then
+ gv_new="yes";
+ elif test "$gv_major" -ge 3 -a "$gv_minor" -gt 6; then
+ gv_new="yes";
+ elif test "$gv_major" -ge 3 -a "$gv_minor" -ge 6 -a "$gv_tiny" -ge 1; then
+ gv_new="yes";
+ fi
+ if test "$gv_new" != "no"; then
+ AC_MSG_RESULT([new, >= 3.6.1])
+ AC_DEFINE_UNQUOTED(HAVE_GV, 1, [Define if you have gv])
+ AC_DEFINE_UNQUOTED(HAVE_NEW_GV, 1, [Define if you have old gv])
+ AC_DEFINE_UNQUOTED(GV_PATH, "${gv}", [Path to gv])
+ else
+ AC_MSG_RESULT([old, pre 3.6.1])
+ AC_DEFINE_UNQUOTED(HAVE_GV, 1, [Define if you have gv])
+ AC_DEFINE_UNQUOTED(HAVE_OLD_GV, 1, [Define if you have old gv])
+ AC_DEFINE_UNQUOTED(GV_PATH, "${gv}", [Path to gv])
+ fi
+ fi
+fi
+
+if test "$use_festival" != "no"; then
+ AC_PATH_PROG(festival, [festival], no, $BINPATH)
+ if test "$festival" != "no"; then
+ AC_DEFINE_UNQUOTED(HAVE_FESTIVAL, 1, [Define if you have festival])
+ fi
+fi
+
+if test "$use_gpsman" != "no"; then
+ AC_PATH_PROG(gpsman, [gpsman haslib gpsmanshp], no, $BINPATH)
+ if test "$gpsman" != "no"; then
+ AC_DEFINE_UNQUOTED(HAVE_GPSMAN, 1, [Define if you have gpsman])
+ AC_DEFINE_UNQUOTED(GPSMAN_PATH, "${gpsman}", [Path to gpsman])
+ fi
+fi
+
+if test "$use_err_popups" != "no"; then
+ AC_DEFINE_UNQUOTED(HAVE_ERROR_POPUPS, 1, [Define if you have error popups enabled])
+fi
+
+if test "$use_lsb" != "no"; then
+ AC_DEFINE_UNQUOTED(__LSB__, 1, [Define if you're compiling for Linux Standard Base])
+fi
+
+
+
+])
+
+
+
+
+
+# TVR - I don't think this is quite as evil as Jack thinks CHECK_IMAGEMAGICK is
+# It assumes that gdal-config is in the user's path, and doesn't try to
+# explore alternate paths.
+AC_DEFUN([XASTIR_CHECK_GDAL],
+[
+use_gdal=no
+#
+# Important: DO NOT use "use_gdal" as the variable here, because AC_CHECK_PROG
+# will do nothing if the variable is already set!
+#
+AC_CHECK_PROG(found_gdal_config, [gdal-config], yes, no)
+if test "${found_gdal_config}" = "yes"; then
+ save_cppflags="$CPPFLAGS"
+ save_libs="$LIBS"
+ save_ldflags="$LDFLAGS"
+
+ GDAL_BIN="gdal-config"
+ CPPFLAGS="$CPPFLAGS `${GDAL_BIN} --cflags`"
+#
+# This is an annoyance: gdal-config --libs outputs both LDFLAGS and LIBS
+# stuff. AC_CHECK_LIB puts the -l in if it works, and we only want the LDFLAGS
+# LIBS="$LIBS `${GDAL_BIN} --libs`"
+# Remove the -lgdal from what gdal-config --libs returns, because AC_CHECK_LIB
+# will put it into LIBS for us.
+#
+ LDFLAGS="$LDFLAGS `${GDAL_BIN} --libs | sed -e 's/-lgdal[^ ]*//'`"
+ AC_CHECK_HEADERS(gdal.h, [AC_CHECK_LIB(gdal, GDALAllRegister,
+ [use_gdal="yes"
+ LIBS="$LIBS -lgdal"
+ AC_DEFINE(HAVE_LIBGDAL, ,
+ [Define to 1 if you have the `gdal' library (-lgdal).])],
+ [CPPFLAGS=${save_cppflags}
+ LDFLAGS=${save_ldflags}
+ LIBS=${save_libs}])])
+else
+ AC_MSG_WARN([*** Cannot find gdal-config: Checking standard locations ***])
+ AC_CHECK_HEADERS(gdal.h, [AC_CHECK_LIB(gdal, GDALAllRegister,
+ [use_gdal="yes"
+ LIBS="$LIBS -lgdal"
+ AC_DEFINE(HAVE_LIBGDAL, ,
+ [Define to 1 if you have the `gdal' library (-lgdal).])],)])
+fi
+]
+)
+
+
+
+AC_DEFUN([XASTIR_CHECK_POSTGIS],
+[
+BINPATH="${PATH}${EXTRA_BIN_PATH}"
+# test for postgresql
+if test "${with_postgis+set}" = set; then
+ PG_CONFIG="pg_config"
+ if test "$with_postgis" != "yes"; then
+ # get path if provided
+ pg_path="$with_postgis"
+ PG_CONFIG_PATH="${pg_path}/bin"
+ BINPATH="${BINPATH}:${PG_CONFIG_PATH}"
+ POSTGIS_LIB_DIR="-L${pg_path}/lib"
+ AC_PATH_PROG(PG_CONFIG, [pg_config], no, $PG_CONFIG_PATH)
+ else
+ AC_PATH_PROG(PG_CONFIG, [pg_config], no)
+ fi
+ if test "$PG_CONFIG" != "no"; then
+ # Check for postgis spatial extensions.
+ # Look for lwpostgis.sql script in default location.
+ # If found, is likely a postgis installation.
+ # Need more definitive test for postgis, as this may fail to detect postgres
+ # installations where this script was removed, and will incorrectly
+ # detect postgres without postgis where this script has been installed but not run.
+ AC_PATH_PROG(LWPOSTGIS, [lwpostgis.sql], no, "${pg_path}/share")
+ if test "LWPOSTGIS" != "no"; then
+ #postgres with postgis enabled
+ use_postgis=yes
+ use_spatial_db=yes
+ save_cppflags="$CPPFLAGS"
+ save_cxxflags="$CXXFLAGS"
+ save_libs="$LIBS"
+ save_ldflags="$LDFLAGS"
+ CPPFLAGS="$CPPFLAGS -I`${PG_CONFIG} --includedir` `${PG_CONFIG} --cppflags`"
+ CXXFLAGS="$CXXFLAGS `${PG_CONFIG} --cflags`"
+ LDFLAGS="$LDFLAGS `${PG_CONFIG} --ldflags`"
+ LIBS="${POSTGIS_LIB_DIR} `${PG_CONFIG} --libs` -lpq $LIBS"
+ AC_DEFINE(HAVE_POSTGIS, 1, Postgresql with postgis is present. )
+ else
+ AC_MSG_WARN(*** Cannot find lwpostgis.sql: Building w/o Postgresql/Postgis support. ***)
+ AC_MSG_WARN(*** Postgresql was found, but does not appear to have Postgis added. ***)
+ AC_MSG_WARN(*** Install and enable postgis and leave the lwpostgis.sql script in ***)
+ AC_MSG_WARN(*** ${pg_path}/share ***)
+ fi
+ else
+ use_postgis=no
+ AC_MSG_WARN(*** Cannot find pg_config: Building w/o Postgresql/Postgis support. ***)
+ AC_MSG_WARN(*** Specify the path to the posgresql installation directory ***)
+ AC_MSG_WARN(*** For example: --with-postgis=/usr/local/pgsql ***)
+ fi
+fi
+
+])
+
+AC_DEFUN([XASTIR_CHECK_MYSQL],
+[
+BINPATH="${PATH}${EXTRA_BIN_PATH}"
+
+# test for MySQL
+if test "${with_mysql+set}" = set; then
+ MYSQL_CONFIG="mysql_config"
+ if test "$with_mysql" != "yes"; then
+ # get path to mysql_config if provided
+ mysql_path="$with_mysql"
+ BINPATH="${BINPATH}:${mysql_path}"
+ AC_PATH_PROG(MYSQL_CONFIG, [mysql_config], no, $mysql_path)
+ else
+ AC_PATH_PROG(MYSQL_CONFIG, [mysql_config], no)
+ fi
+ use_mysql_spatial=no
+ use_mysql_any=no
+ if test "$MYSQL_CONFIG" != "no"; then
+
+ # check for mysql version with spatial support
+ # look for mysql 4.1.2 or greater for spatial support
+ # and standardized prepared statements
+ # 4.1.0 and 4.1.1 have spatial support, but only early versions
+ # of prepared statement functions that changed in 4.1.2
+ AC_MSG_CHECKING([mysql version >= 4.1.2])
+ mysqlversion=`$MYSQL_CONFIG --version`
+ mysqlversionmajor=`echo ${mysqlversion} | cut -d '.' -f 1`
+ mysqlversionminor=`echo ${mysqlversion} | cut -d '.' -f 2`
+ mysqlversiontiny=`echo ${mysqlversion} | cut -d '.' -f 3`
+ if test "$mysqlversionmajor" -gt 4 ; then
+ mysql_has_spatial="yes"
+ elif test "$mysqlversionmajor" -ge 4 -a "$mysqlversionminor" -gt 1 ; then
+ mysql_has_spatial="yes"
+ elif test "$mysqlversionmajor" -ge 4 -a "$mysqlversionminor" -ge 1 -a "$mysqlversiontiny" -ge 2 ; then
+ mysql_has_spatial="yes"
+ else
+ mysql_has_spatial="no"
+ fi
+ AC_MSG_RESULT($mysql_has_spatial)
+ # if mysql version < 4.1, mysql present but no spatial support
+ if test "$mysql_has_spatial" = "yes"; then
+ # mysql with spatial support
+ use_mysql_spatial=yes
+ use_spatial_db=yes
+ AC_DEFINE(HAVE_MYSQL_SPATIAL, 1, MySQL with spatial support is present.)
+ else
+ AC_MSG_WARN(*** MySQL version $mysqlversion detected is < 4.1.2 ***)
+ AC_MSG_WARN(*** Spatial support enabled only for MySQL 4.1.2 and higher ***)
+ AC_MSG_WARN(*** MySQL support for Lat/Long fields is available but ***)
+ AC_MSG_WARN(*** not for Points Polygons or other spatial objects. ***)
+ fi
+ save_cppflags="$CPPFLAGS"
+ save_cxxflags="$CXXFLAGS"
+ save_libs="$LIBS"
+ CPPFLAGS="$CPPFLAGS `${MYSQL_CONFIG} --cflags`"
+ CXXFLAGS="$CXXFLAGS `${MYSQL_CONFIG} --cflags`"
+ LIBS=" `${MYSQL_CONFIG} --libs` $LIBS"
+ use_mysql_any=yes
+ AC_DEFINE(HAVE_MYSQL, 1, MySQL is present.)
+ else
+ AC_MSG_WARN(*** Cannot find mysql_config: Building w/o MySQL support. ***)
+ AC_MSG_WARN(*** Specify the path to mysql_config ***)
+ AC_MSG_WARN(*** For example: --with-mysql=/var/lib/mysql ***)
+ fi
+
+fi
+#AC_MSG_RESULT($use_mysql_spatial)
+])
+
+
+
+AC_DEFUN([XASTIR_CHECK_IMAGEMAGICK],
+[
+BINPATH="${PATH}${EXTRA_BIN_PATH}"
+
+# Check for ImageMagick
+#
+# First look for the needed Magick-config script, which tells us all
+# of the build options we need.
+#
+# Important: DO NOT use "use_imagemagick" as the variable here,
+# because AC_CHECK_PROG will do nothing if the variable is already set!
+#
+use_imagemagick=no
+AC_PATH_PROG(MAGIC_BIN, [Magick-config], no, $BINPATH)
+if test "$MAGIC_BIN" != "no"; then
+ use_imagemagick=yes
+#else
+# AC_MSG_WARN(*** Cannot find Magick-config: Building w/o ImageMagick support. ***)
+fi
+
+if test "${use_imagemagick}" = "yes"; then
+# #
+# # Compute the ImageMagick revision number
+# #
+# magickversion=`${MAGIC_BIN} --version`
+# magickmajor=`echo $magickversion | cut -d '.' -f 1`
+# magickminor=`echo $magickversion | cut -d '.' -f 2`
+# magicktiny=`echo $magickversion | cut -d '.' -f 3`
+# if test "$magickmajor" -lt 5; then
+# magickold="yes";
+# elif test "$magickmajor" -eq 5 -a "$magickminor" -lt 4; then
+# magickold="yes";
+# elif test "$magickmajor" -eq 5 -a "$magickminor" -eq 4 -a "$magicktiny" -lt 9; then
+# magickold="yes";
+# fi
+ #
+ save_cppflags="$CPPFLAGS"
+ save_cxxflags="$CXXFLAGS"
+ save_libs="$LIBS"
+ save_ldflags="$LDFLAGS"
+ #
+ # Figure out the build options using the Magick-config script
+ #
+ CPPFLAGS="$CPPFLAGS `${MAGIC_BIN} --cppflags`"
+ CXXFLAGS="$CXXFLAGS `${MAGIC_BIN} --cflags`"
+ LDFLAGS="$LDFLAGS `${MAGIC_BIN} --ldflags`"
+ LIBS="${MAGIC_LIB_DIR} `${MAGIC_BIN} --libs` $LIBS"
+ #
+ AC_CHECK_HEADER(magick/api.h, use_imagemagick="yes", use_imagemagick="no")
+ if test "${use_imagemagick}" = "no"; then
+ AC_MSG_WARN(*** Cannot find ImageMagick include files: Building w/o ImageMagick support. ***)
+ else
+ AC_SEARCH_LIBS([WriteImage],[Magick MagickCore], AC_DEFINE(HAVE_IMAGEMAGICK, 1, [Imagemagick image library]), use_imagemagick="no")
+ if test "${use_imagemagick}" = "no"; then
+ AC_MSG_WARN(*** Cannot find ImageMagick library files: Building w/o ImageMagick support. ***)
+ fi
+ fi
+ #
+ if test "${use_imagemagick}" = "no"; then
+ #
+ # No ImageMagick found. Restore variables.
+ #
+ CPPFLAGS=$save_cppflags
+ CXXFLAGS=$save_cxxflags
+ LIBS=$save_libs
+ LDFLAGS=$save_ldflags
+ fi
+#
+# if test "${magickold}" = "yes"; then
+# This used to be important, as some versions didn't support the
+# Tigermap intensity slider.
+# AC_MSG_WARN(*********************************************************)
+# AC_MSG_WARN(*** Old ImageMagick version ($magickversion) found. ***)
+# AC_MSG_WARN(*** Upgrade to 5.4.9 or newer for full functionality. ***)
+# AC_MSG_WARN(*********************************************************)
+# fi
+fi
+# End of ImageMagick checks
+
+])
+
+
+
+
+
+AC_DEFUN([XASTIR_CHECK_GRAPHICSMAGICK],
+[
+BINPATH="${PATH}${EXTRA_BIN_PATH}"
+
+# Check for GraphicsMagick
+#
+# First look for the needed GraphicsMagick-config script, which tells us all
+# of the build options we need.
+#
+# Important: DO NOT use "use_graphicsmagick" as the variable here,
+# because AC_CHECK_PROG will do nothing if the variable is already set!
+#
+use_graphicsmagick=no
+AC_PATH_PROG(GMAGIC_BIN, [GraphicsMagick-config], no, $BINPATH)
+if test "$GMAGIC_BIN" != "no"; then
+ use_graphicsmagick=yes
+#else
+# AC_MSG_WARN(*** Cannot find GraphicsMagick-config: Building w/o GraphicsMagick support. ***)
+fi
+#
+if test "${use_graphicsmagick}" = "yes"; then
+ save_cppflags="$CPPFLAGS"
+ save_cxxflags="$CXXFLAGS"
+ save_libs="$LIBS"
+ save_ldflags="$LDFLAGS"
+ #
+ # Figure out the build options using the GraphicsMagick-config script
+ #
+ CPPFLAGS="`${GMAGIC_BIN} --cppflags` $CPPFLAGS"
+ CXXFLAGS="`${GMAGIC_BIN} --cflags` $CXXFLAGS"
+ LDFLAGS="`${GMAGIC_BIN} --ldflags` $LDFLAGS"
+ LIBS="${MAGIC_LIB_DIR} `${GMAGIC_BIN} --libs` $LIBS"
+ #
+ AC_CHECK_HEADER(GraphicsMagick/magick/api.h, use_graphicsmagick="yes", use_graphicsmagick="no")
+ if test "${use_graphicsmagick}" = "no"; then
+ AC_MSG_WARN(*** Cannot find GraphicsMagick include files: Building w/o GraphicsMagick support. ***)
+ else
+ AC_CHECK_LIB([GraphicsMagick], [WriteImage], AC_DEFINE(HAVE_GRAPHICSMAGICK, 1, [GraphicsMagick image library]), use_graphicsmagick="no")
+ if test "${use_graphicsmagick}" = "no"; then
+ AC_MSG_WARN(*** Cannot find GraphicsMagick library files: Building w/o GraphicsMagick support. ***)
+ fi
+ fi
+ #
+ if test "${use_graphicsmagick}" = "no"; then
+ #
+ # No GraphicsMagick found. Restore variables.
+ #
+ CPPFLAGS=$save_cppflags
+ CXXFLAGS=$save_cxxflags
+ LIBS=$save_libs
+ LDFLAGS=$save_ldflags
+ fi
+fi
+#
+# End of GraphicsMagick checks
+
+])
+
+
+
+
+
+# things grabbed elsewhere
+
+# this is from Squeak-3.2-4's acinclude.m4
+AC_DEFUN([AC_CHECK_GMTOFF],
+[AC_CACHE_CHECK([for gmtoff in struct tm], ac_cv_tm_gmtoff,
+ AC_TRY_COMPILE([#include <time.h>],[struct tm tm; tm.tm_gmtoff;],
+ ac_cv_tm_gmtoff="yes", ac_cv_tm_gmtoff="no"))
+test "$ac_cv_tm_gmtoff" != "no" && AC_DEFINE(HAVE_TM_GMTOFF,,X)])
+
+dnl Available from the GNU Autoconf Macro Archive at:
+dnl http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html
+dnl
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+ AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test x"$acx_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+
+case "${host_cpu}-${host_os}" in
+ *solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthread or
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+
+ acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
+ ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+ case $flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $flag])
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$flag])
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ AC_TRY_LINK([#include <pthread.h>],
+ [pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+ [acx_pthread_ok=yes])
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test "x$acx_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: threads are created detached by default
+ # and the JOINABLE attribute has a nonstandard name (UNDETACHED).
+ AC_MSG_CHECKING([for joinable pthread attribute])
+ AC_TRY_LINK([#include <pthread.h>],
+ [int attr=PTHREAD_CREATE_JOINABLE;],
+ ok=PTHREAD_CREATE_JOINABLE, ok=unknown)
+ if test x"$ok" = xunknown; then
+ AC_TRY_LINK([#include <pthread.h>],
+ [int attr=PTHREAD_CREATE_UNDETACHED;],
+ ok=PTHREAD_CREATE_UNDETACHED, ok=unknown)
+ fi
+ if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then
+ AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok,
+ [Define to the necessary symbol if this constant
+ uses a non-standard name on your system.])
+ fi
+ AC_MSG_RESULT(${ok})
+ if test x"$ok" = xunknown; then
+ AC_MSG_WARN([we do not know how to create joinable pthreads])
+ fi
+
+ AC_MSG_CHECKING([if more special flags are required for pthreads])
+ flag=no
+ case "${host_cpu}-${host_os}" in
+ *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";;
+ *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+ esac
+ AC_MSG_RESULT(${flag})
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: must compile with cc_r
+ AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
+else
+ PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+ ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+ :
+else
+ acx_pthread_ok=no
+ $2
+fi
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD
+
+
+#
+AC_DEFUN([XASTIR_PATH_MOTIF], [
+# New stuff to check for Motif/Lesstif. Shamelessly borrowed from
+# the opendx project. Opendx in turn snarfed their test from AC_PATH_X.
+
+# Allow "--with-motif-includes" and "--with-motif-libs" so user can
+# force a specific set of includes.
+AC_ARG_WITH(motif-includes, [ --with-motif-includes Set path for motif includes (default none)],[with_motif_includes=$withval], [with_motif_includes=])
+if test "$with_motif_includes" != "yes" && test -z "$with_motif_includes"
+then
+ with_motif_includes=
+fi
+
+AC_ARG_WITH(motif-libs, [ --with-motif-libs Set path for motif libraries (default none)],[with_motif_libs=$withval], [with_motif_libs=])
+if test "$with_motif_libs" != "yes" && test -z "$with_motif_libs"
+then
+ with_motif_libs=
+fi
+
+ # Guess where to find include files, by looking for this one Xm .h file.
+ test -z "$xm_direct_test_include" && xm_direct_test_include=Xm/Xm.h
+
+ # First, try using that file with no special directory specified.
+AC_MSG_CHECKING([for Motif headers])
+AC_PREPROC_IFELSE(
+ [AC_LANG_SOURCE([[#include <$xm_direct_test_include>]])],
+ [
+ # We can compile using X headers with no special include directory.
+ xm_includes=
+ AC_MSG_RESULT([in default path])
+ ],[
+# that test didn't work, we need to hunt a little
+# Look for the header file in a standard set of common directories.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+ for ac_dir in \
+ /usr/X11/include \
+ /usr/X11R6/include \
+ /usr/X11R5/include \
+ /usr/X11R4/include \
+ \
+ /usr/include/X11 \
+ /usr/include/X11R6 \
+ /usr/include/X11R5 \
+ /usr/include/X11R4 \
+ \
+ /usr/local/X11/include \
+ /usr/local/X11R6/include \
+ /usr/local/X11R5/include \
+ /usr/local/X11R4/include \
+ \
+ /usr/local/include/X11 \
+ /usr/local/include/X11R6 \
+ /usr/local/include/X11R5 \
+ /usr/local/include/X11R4 \
+ \
+ /usr/X386/include \
+ /usr/x386/include \
+ /usr/XFree86/include/X11 \
+ \
+ /usr/include \
+ /usr/local/include \
+ /usr/unsupported/include \
+ /usr/athena/include \
+ /usr/local/x11r5/include \
+ /usr/lpp/Xamples/include \
+ \
+ /usr/openwin/include \
+ /usr/openwin/share/include \
+ "$with_motif_includes" \
+ ; \
+ do
+ if test -r "$ac_dir/$xm_direct_test_include"; then
+ xm_includes=$ac_dir
+ AC_MSG_RESULT([in $xm_includes])
+ break
+ fi
+ done
+ if test "x$xm_includes" = "x"; then
+ AC_MSG_ERROR([**** NO MOTIF HEADERS FOUND **** install Motif development headers or use --with-motif-includes to specify location of Xm/Xm.h ])
+ fi
+])
+ # Check for the libraries.
+
+ AC_MSG_CHECKING([for Motif libraries])
+ test -z "$xm_direct_test_library" && xm_direct_test_library=Xm
+ test -z "$xm_direct_test_function" && xm_direct_test_function=XmGetDestination
+
+ # See if we find them without any special options.
+ # Don't add to $LIBS permanently.
+ ac_save_LIBS="$LIBS"
+ LIBS="-l$xm_direct_test_library $LIBS"
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[${xm_direct_test_function}()]])],
+ [
+ LIBS="$ac_save_LIBS"
+ # We can link Motif programs with no special library path.
+ xm_libraries=
+ AC_MSG_RESULT([in default path])
+ ],[
+ LIBS="$ac_save_LIBS"
+# First see if replacing the include by lib works.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+for ac_dir in `echo "$xm_includes" | sed s/include/lib/` \
+ /usr/X11/lib \
+ /usr/X11R6/lib \
+ /usr/X11R5/lib \
+ /usr/X11R4/lib \
+ \
+ /usr/lib/X11 \
+ /usr/lib/X11R6 \
+ /usr/lib/X11R5 \
+ /usr/lib/X11R4 \
+ \
+ /usr/local/X11/lib \
+ /usr/local/X11R6/lib \
+ /usr/local/X11R5/lib \
+ /usr/local/X11R4/lib \
+ \
+ /usr/local/lib/X11 \
+ /usr/local/lib/X11R6 \
+ /usr/local/lib/X11R5 \
+ /usr/local/lib/X11R4 \
+ \
+ /usr/X386/lib \
+ /usr/x386/lib \
+ /usr/XFree86/lib/X11 \
+ \
+ /usr/lib \
+ /usr/local/lib \
+ /usr/unsupported/lib \
+ /usr/athena/lib \
+ /usr/local/x11r5/lib \
+ /usr/lpp/Xamples/lib \
+ /lib/usr/lib/X11 \
+ \
+ /usr/openwin/lib \
+ /usr/openwin/share/lib \
+ "$with_motif_libs" \
+ ; \
+do
+dnl Don't even attempt the hair of trying to link an X program!
+ for ac_extension in a so sl; do
+ if test -r $ac_dir/lib${xm_direct_test_library}.$ac_extension; then
+ xm_libraries=$ac_dir
+ AC_MSG_RESULT([in $xm_libraries])
+ break 2
+ fi
+ done
+done
+if test "x$xm_libraries" = "x"; then
+ AC_MSG_ERROR([**** MOTIF LIBRARIES NOT FOUND **** Install Motif development headers/libraries or use --with-motif-libraries to specify path to libXm.a ])
+fi
+])
+])
+
+# From Cyrus imap distribution (KB3EGH)
+
+dnl These are the Cyrus Berkeley DB macros. In an ideal world these would be
+dnl identical to the above.
+
+dnl They are here so that they can be shared between Cyrus IMAPd
+dnl and Cyrus SASL with relative ease.
+
+dnl The big difference between this and the ones above is that we don't assume
+dnl that we know the name of the library, and we try a lot of permutations
+dnl instead. We also assume that DB4 is acceptable.
+
+dnl When we're done, there will be a BDB_LIBADD and a BDB_INCADD which should
+dnl be used when necessary. We should probably be smarter about our RPATH
+dnl handling.
+
+dnl Call these with XASTIR_BERKELEY_DB_CHK.
+
+dnl We will also set $dblib to "berkeley" if we are successful, "no" otherwise.
+
+dnl this is unbelievably painful due to confusion over what db-3 should be
+dnl named and where the db-3 header file is located. arg.
+AC_DEFUN([XASTIR_BERKELEY_DB_CHK_LIB],
+[
+
+
+# We need to add the following algorithm here:
+#
+# Find the db.h file, grep for DB_VERSION_MAJOR and
+# DB_VERSION_MINOR. In my case I get this:
+#
+# #define DB_VERSION_MAJOR 4
+# #define DB_VERSION_MINOR 1
+#
+# Find the libdb.so file that Xastir would link to. Find the
+# version via the target of the symlink? In my case I have
+# this:
+#
+# > ls -al libdb.so
+# lrwxrwxrwx 1 root root 12 2004-01-07 11:29 libdb.so -> libdb-4.
+#
+# Compare the major/minor numbers. If they match, we're good to
+# go. If not, don't compile in libdb support. Perhaps we could
+# just run ldd on the test code to get the version number of the
+# linked library instead?
+#
+# Another possible way to do it would be to create test code and
+# compile/run it which would open/write/read/close/delete a
+# database. That should help to prove that Xastir would run ok if
+# the library were used.
+
+
+
+ BDB_SAVE_LDFLAGS=$LDFLAGS
+
+ if test -d $with_bdb_lib; then
+ LDFLAGS="-L$with_bdb_lib $LDFLAGS"
+ BDB_LIBADD="-L$with_bdb_lib $BDB_LIBADD"
+ else
+ BDB_LIBADD=""
+ fi
+
+ saved_LIBS=$LIBS
+# Removed db-3.3 db3.3 db33 db-3.2 db3.2 db32 db-3.1 db3.1 db31 db-3 db30 db3
+# from the probe. The map_cache.c code explicitly bombs if it doesn't have
+# version 4 or above, so why probe for version 3?
+
+# it would be nice if this could be done with AC_SEARCH_LIBS but that doesn't
+# work as it appears that there is some C++-type name mangling going on,
+# and just probing for a library that contains "db_create" fails. One needs
+# to specify the function call with the full prototype for it to be found.
+ BDB_LIB_FOUND="none"
+ AC_MSG_CHECKING([for a library containing db_create])
+ for dbname in db-4.9 db4.9 db49 db-4.8 db4.8 db48 db-4.7 db4.7 db47 db-4.6 db4.6 db46 db-4.5 db4.5 db45 db-4.4 db4.4 db44 db-4.3 db4.3 db43 db-4.2 db4.2 db42 db-4.1 db4.1 db41 db-4.0 db4.0 db-4 db40 db4 db
+ do
+ LIBS="$saved_LIBS -l$dbname"
+ AC_TRY_LINK(
+ [#include <db.h>],
+ [db_create(NULL, NULL, 0);],
+ [BDB_LIBADD="$BDB_LIBADD -l$dbname"; dblib="berkeley";
+ BDB_LIB_FOUND="-l$dbname"],
+ dblib="no")
+# STOP if we find one. Otherwise we'll keep stepping through the
+# list and resetting dblib to "no" over and over.
+ if test $dblib = "berkeley" ; then
+ break;
+ fi
+ done
+ AC_MSG_RESULT([$BDB_LIB_FOUND])
+
+# Commented out because the map_cache code is not actually set up to use
+# db_open instead of db_create. Probing in this way could actually be
+# dangerous.
+# if test "$dblib" = "no"; then
+# LIBS="$saved_LIBS -ldb"
+# AC_TRY_LINK([#include <db.h>],
+# [db_open(NULL, 0, 0, 0, NULL, NULL, NULL);],
+# BDB_LIBADD="$BDB_LIBADD -ldb"; dblib="berkeley"; dbname=db,
+# dblib="no")
+# fi
+ LIBS=$saved_LIBS
+
+ LDFLAGS=$BDB_SAVE_LDFLAGS
+])
+
+AC_DEFUN([XASTIR_BERKELEY_DB_OPTS],
+[
+AC_ARG_WITH(bdb-libdir,
+ [ --with-bdb-libdir=DIR Berkeley DB lib files are in DIR],
+ with_bdb_lib=$withval,
+ [ test "${with_bdb_lib+set}" = set || with_bdb_lib=none])
+AC_ARG_WITH(bdb-incdir,
+ [ --with-bdb-incdir=DIR Berkeley DB include files are in DIR],
+ with_bdb_inc=$withval,
+ [ test "${with_bdb_inc+set}" = set || with_bdb_inc=none ])
+])
+
+AC_DEFUN([XASTIR_BERKELEY_DB_CHK],
+[
+ AC_REQUIRE([XASTIR_BERKELEY_DB_OPTS])
+
+ xastir_save_CPPFLAGS=$CPPFLAGS
+
+ if test -d $with_bdb_inc; then
+ CPPFLAGS="$CPPFLAGS -I$with_bdb_inc"
+ BDB_INCADD="-I$with_bdb_inc"
+ else
+ BDB_INCADD=""
+ fi
+
+ dnl Note that FreeBSD puts it in a weird place
+ dnl (/usr/local/include/db42)
+ dnl (but they should use with-bdb-incdir)
+# Commented out because it doesn't distinguish between versions of db.h
+# that can work with xastir and versions that can't. It is possible to
+# have multiple versions of db installed in different places, pick up the
+# header for one and the library for another. Bleah.
+# AC_CHECK_HEADER(db.h,
+# [XASTIR_BERKELEY_DB_CHK_LIB()],
+# dblib="no")
+#
+# Do this instead --- check to see if the db.h we find first in the search
+# path will actually pass the test we do in map_cache.c. Don't even bother
+# looking for a library if not.
+ AC_MSG_CHECKING([if db.h is exists and is usable])
+ AC_TRY_COMPILE([#include <db.h>],
+ [#if (DB_VERSION_MAJOR < 4 )
+ #error DB_VERSION_MAJOR < 4
+ #endif],
+ [AC_MSG_RESULT([yes])
+ XASTIR_BERKELEY_DB_CHK_LIB()],
+ [AC_MSG_RESULT([no]); dblib="no"])
+ CPPFLAGS=$xastir_save_CPPFLAGS
+
+ use_map_cache="no"
+ if test "${dblib}" = "berkeley"; then
+ LIBS="$BDB_LIBADD $LIBS"
+ CPPFLAGS="$CPPFLAGS $BDB_INCADD"
+ AC_DEFINE(USE_MAP_CACHE, 1, [Berkeley DB Map Caching])
+ use_map_cache="yes"
+ fi
+
+])
+
+
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..bf5bfb0
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,964 @@
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],,
+[m4_warning([this file was generated for autoconf 2.68.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.11'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.11.1], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.11.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 10
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
+ [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], UPC, [depcc="$UPC" am_compiler_list=],
+ [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ am__universal=false
+ m4_case([$1], [CC],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac],
+ [CXX],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac])
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 5
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+ # Autoconf 2.62 quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS.
+AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 16
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.62])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES(OBJC)],
+ [define([AC_PROG_OBJC],
+ defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
+dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
+dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
+dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+ [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+])
+
+dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 6
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+ [[\\/$]]* | ?:[[\\/]]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[[\\\"\#\$\&\'\`$am_lf]]*)
+ AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+ *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
+ AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([acinclude.m4])
diff --git a/bootstrap.sh b/bootstrap.sh
new file mode 100755
index 0000000..0e9066d
--- /dev/null
+++ b/bootstrap.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+#
+# $Id: bootstrap.sh,v 1.23 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+#
+# This simple routine will run autostuff in the appropriate
+# order to generate the needed configure/makefiles
+#
+
+echo " 7) Removing autom4te.cache directory..."
+rm -rf autom4te.cache
+
+echo " 6) Running aclocal..."
+aclocal
+
+echo " 5) Running autoheader..."
+autoheader
+
+echo " 4) Running autoconf..."
+autoconf
+
+# Cygwin needs these parameters to be separate.
+echo " 3) Running automake..."
+automake -a -c
+
+# Automake-1.9 on SuSE 10 doesn't copy over "mkinstalldirs" if
+# missing. Check whether it is missing and copy it over ourselves
+# if so.
+if test -x "mkinstalldirs"
+then
+ echo " 2) Checking for 'mkinstalldirs'... Found!"
+else
+ echo " 2) Checking for 'mkinstalldirs'... Not Found"
+ echo " Attempting to copy it from system directories'"
+ (cp /usr/local/share/automake*/mkinstalldirs . 2>/dev/null)
+ # Did we succeed?
+ if [ $? ]
+ then
+ # Failed the copy above, try in another directory.
+ (cp /usr/share/automake*/mkinstalldirs . 2>/dev/null)
+ fi
+ # Check whether we have the file now in our current directory and
+ # that it is executable.
+ if test -x "mkinstalldirs"
+ then
+ echo " Checking for 'mkinstalldirs'... Found!"
+ else
+ echo "***ERROR: Couldn't copy the file***"
+ fi
+fi
+
+# Generate derived language files
+echo -n " 1) Generating derived language files"
+(cd config; ../scripts/langPigLatin.pl -split <language-English.sys >language-PigLatin.sys)
+echo -n "."
+(cd config; ../scripts/langElmerFudd.pl -split <language-English.sys >language-ElmerFudd.sys)
+echo -n "."
+(cd config; ../scripts/langMuppetsChef.pl -split <language-English.sys >language-MuppetsChef.sys)
+echo -n "."
+(cd config; ../scripts/langOldeEnglish.pl -split <language-English.sys >language-OldeEnglish.sys)
+echo -n "."
+(cd config; ../scripts/langPirateEnglish.pl -split <language-English.sys >language-PirateEnglish.sys)
+echo "."
+
+echo "Bootstrap complete."
+
+
diff --git a/callpass.1 b/callpass.1
new file mode 100644
index 0000000..8ff63d1
--- /dev/null
+++ b/callpass.1
@@ -0,0 +1,29 @@
+.TH callpass 1 2009-12-22 "The Xastir Group"
+
+.SH NAME
+callpass \- generate Pass-code associated with your callsign for authentication via xastir to APRS(tm) network.
+
+.SH SYNOPSIS
+.B callpass
+.I <callsign>
+
+.SH DESCRIPTION
+Generate passcode for use in xastir authentication to APRS network for traffic delivery to cooperating systems.
+.SH EXAMPLES
+
+callpass nocall
+ outputs 'Passcode for nocall is 12960'
+
+.SH NOTES
+There is no error or consistency check for callsign. This utility will generate a passcode for any string.
+.SH SEE ALSO
+xastir help file
+.br
+.PP
+.B APRS[tm]
+is a Trademark of Bob Bruninga, his home page is at "http://www.aprs.org/aprs.html"
+
+.SH COPYING
+Copyright (C) 1999,2000 Frank Giannandrea KC2GJS
+.br
+Copyright (C) 2000-2012 The Xastir Group
diff --git a/callpass/Makefile.am b/callpass/Makefile.am
new file mode 100644
index 0000000..ae87f02
--- /dev/null
+++ b/callpass/Makefile.am
@@ -0,0 +1,13 @@
+# $Id: Makefile.am,v 1.10 2012/11/01 18:57:18 we7u Exp $
+
+# Copyright (C) 2000-2012 The Xastir Group
+
+
+MAINTAINERCLEANFILES=Makefile.in
+
+bin_PROGRAMS = callpass
+
+callpass_SOURCES = callpass.c
+
+callpass_LINK=$(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+
diff --git a/callpass/Makefile.in b/callpass/Makefile.in
new file mode 100644
index 0000000..4ce5f94
--- /dev/null
+++ b/callpass/Makefile.in
@@ -0,0 +1,501 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+# $Id: Makefile.am,v 1.10 2012/11/01 18:57:18 we7u Exp $
+
+# Copyright (C) 2000-2012 The Xastir Group
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = callpass$(EXEEXT)
+subdir = callpass
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+am_callpass_OBJECTS = callpass.$(OBJEXT)
+callpass_OBJECTS = $(am_callpass_OBJECTS)
+callpass_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(callpass_SOURCES)
+DIST_SOURCES = $(callpass_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTSHP = @CONTSHP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GMAGIC_BIN = @GMAGIC_BIN@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBCOMPAT = @LIBCOMPAT@
+LIBOBJS = @LIBOBJS@
+LIBRTREE = @LIBRTREE@
+LIBS = @LIBS@
+LIBSHP = @LIBSHP@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LWPOSTGIS = @LWPOSTGIS@
+MAGIC_BIN = @MAGIC_BIN@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PG_CONFIG = @PG_CONFIG@
+POW_LIB = @POW_LIB@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUBRTREE = @SUBRTREE@
+SUBSHP = @SUBSHP@
+VERSION = @VERSION@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+convert = @convert@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+festival = @festival@
+found_gdal_config = @found_gdal_config@
+gm = @gm@
+gpsman = @gpsman@
+gv = @gv@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lpr = @lpr@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+mv = @mv@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sed = @sed@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+wget = @wget@
+xfontsel = @xfontsel@
+MAINTAINERCLEANFILES = Makefile.in
+callpass_SOURCES = callpass.c
+callpass_LINK = $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu callpass/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu callpass/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+callpass$(EXEEXT): $(callpass_OBJECTS) $(callpass_DEPENDENCIES)
+ @rm -f callpass$(EXEEXT)
+ $(callpass_LINK) $(callpass_OBJECTS) $(callpass_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/callpass.Po at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic ctags distclean distclean-compile \
+ distclean-generic distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-binPROGRAMS \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-binPROGRAMS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/callpass/callpass.c b/callpass/callpass.c
new file mode 100644
index 0000000..1517821
--- /dev/null
+++ b/callpass/callpass.c
@@ -0,0 +1,81 @@
+/*
+ * $Id: callpass.c,v 1.11 2012/11/01 18:57:18 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#define kKey 0x73e2 // This is the seed for the key
+#define true 1
+
+
+
+static short doHash(char *theCall) {
+ char rootCall[10]; // need to copy call to remove ssid from parse
+ char *p1 = rootCall;
+ short hash;
+ short i,len;
+ char *ptr = rootCall;
+
+ while ((*theCall != '-') && (*theCall != '\0')) *p1++ = toupper((int)(*theCall++));
+ *p1 = '\0';
+
+ hash = kKey; // Initialize with the key value
+ i = 0;
+ len = (short)strlen(rootCall);
+
+ while (i<len) {// Loop through the string two bytes at a time
+ hash ^= (unsigned char)(*ptr++)<<8; // xor high byte with accumulated hash
+ hash ^= (*ptr++); // xor low byte with accumulated hash
+ i += 2;
+ }
+ return (short)(hash & 0x7fff); // mask off the high bit so number is always positive
+}
+
+
+
+short checkHash(char *theCall, short theHash) {
+ return (short)(doHash(theCall) == theHash);
+}
+
+
+
+int main(int argc, char *argv[]) {
+ char temp[100];
+
+ if (argc>1) {
+
+ strncpy(temp,argv[1],100);
+
+ temp[99] = '\0'; // Forced termination
+
+ if (strlen(temp)>0)
+ printf("Passcode for %s is %d\n",temp,doHash(temp));
+
+ } else
+ printf("Usage:callpass <callsign>\n");
+
+ return(0);
+}
+
diff --git a/config.guess b/config.guess
new file mode 100755
index 0000000..666c5ad
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,1511 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+# Free Software Foundation, Inc.
+
+timestamp='2009-11-20'
+
+# This file 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.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner. Please send patches (context
+# diff format) to <config-patches at gnu.org> and include a ChangeLog
+# entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi at noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "${UNAME_MACHINE}" in
+ i?86)
+ test -z "$VENDOR" && VENDOR=pc
+ ;;
+ *)
+ test -z "$VENDOR" && VENDOR=unknown
+ ;;
+esac
+test -f /etc/SuSE-release -o -f /.buildenv && VENDOR=suse
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ELF__
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-${VENDOR}-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-${VENDOR}-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-${VENDOR}-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-${VENDOR}-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee at wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ s390x:SunOS:*:*)
+ echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ echo i386-pc-auroraux${UNAME_RELEASE}
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ eval $set_cc_for_build
+ SUN_ARCH="i386"
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH="x86_64"
+ fi
+ fi
+ echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-${VENDOR}-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[456])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-${VENDOR}-osf1mk
+ else
+ echo ${UNAME_MACHINE}-${VENDOR}-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-${VENDOR}-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ case ${UNAME_MACHINE} in
+ pc98)
+ echo i386-${VENDOR}-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ amd64)
+ echo x86_64-${VENDOR}-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_MACHINE}-${VENDOR}-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ authenticamd | genuineintel | EM64T)
+ echo x86_64-${VENDOR}-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-${VENDOR}-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ 8664:Windows_NT:*)
+ echo x86_64-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-${VENDOR}-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-${VENDOR}-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-${VENDOR}-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-${VENDOR}-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-${VENDOR}-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu${LIBC}
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu
+ else
+ echo ${UNAME_MACHINE}-${VENDOR}-linux-gnueabi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-${VENDOR}-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ LIBC=gnu
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+ echo "${UNAME_MACHINE}-${VENDOR}-linux-${LIBC}"
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu
+ exit ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef ${UNAME_MACHINE}
+ #undef ${UNAME_MACHINE}el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=${UNAME_MACHINE}el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=${UNAME_MACHINE}
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+ test x"${CPU}" != x && { echo "${CPU}-${VENDOR}-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-${VENDOR}-linux-gnu
+ exit ;;
+ padre:Linux:*:*)
+ echo sparc-${VENDOR}-linux-gnu
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-${VENDOR}-linux-gnu
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-${VENDOR}-linux-gnu ;;
+ PA8*) echo hppa2.0-${VENDOR}-linux-gnu ;;
+ *) echo hppa-${VENDOR}-linux-gnu ;;
+ esac
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-${VENDOR}-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-${VENDOR}-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-${VENDOR}-linux-gnu
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu
+ exit ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-${VENDOR}-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+ echo i386-${VENDOR}-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-${VENDOR}-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configury will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-${VENDOR}-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-${VENDOR}-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-${VENDOR}-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-${VENDOR}-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+ echo powerpc-${VENDOR}-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel at ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes at openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf at swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green at stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green at stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-${VENDOR}-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ i386)
+ eval $set_cc_for_build
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ UNAME_PROCESSOR="x86_64"
+ fi
+ fi ;;
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-${VENDOR}-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-${VENDOR}-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-${VENDOR}-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-${VENDOR}-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-${VENDOR}-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR}-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+ i*86:AROS:*:*)
+ echo ${UNAME_MACHINE}-pc-aros
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches at gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..7dc7cd5
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,661 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
+/* Path to convert */
+#undef CONVERT_PATH
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+ systems. This function is required for `alloca.c' support on those systems.
+ */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to 1 if the `getpgrp' function requires zero arguments. */
+#undef GETPGRP_VOID
+
+/* Path to gpsman */
+#undef GPSMAN_PATH
+
+/* Default GPS port. */
+#undef GPS_PORT
+
+/* Path to gv */
+#undef GV_PATH
+
+/* Define to 1 if you have the `alarm' function. */
+#undef HAVE_ALARM
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+ */
+#undef HAVE_ALLOCA_H
+
+/* Define to 1 if you have the <argz.h> header file. */
+#undef HAVE_ARGZ_H
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define if you have convert */
+#undef HAVE_CONVERT
+
+/* Database support available */
+#undef HAVE_DB
+
+/* Define to 1 if your `shp' library has DBFGetFieldIndex. */
+#undef HAVE_DBFGETFIELDINDEX
+
+/* Define to 1 if you have the `dcgettext' function. */
+#undef HAVE_DCGETTEXT
+
+/* Define to 1 if you have the declaration of `tzname', and to 0 if you don't.
+ */
+#undef HAVE_DECL_TZNAME
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_DIRENT_H
+
+/* Define if you have error popups enabled */
+#undef HAVE_ERROR_POPUPS
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define if you have festival */
+#undef HAVE_FESTIVAL
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the <gc.h> header file. */
+#undef HAVE_GC_H
+
+/* Define to 1 if you have the <gdal.h> header file. */
+#undef HAVE_GDAL_H
+
+/* Define to 1 if you have the `getcwd' function. */
+#undef HAVE_GETCWD
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#undef HAVE_GETHOSTBYNAME
+
+/* Define to 1 if you have the `gethostname' function. */
+#undef HAVE_GETHOSTNAME
+
+/* Define to 1 if you have the `getpagesize' function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define to 1 if you have the `getpgrp' function. */
+#undef HAVE_GETPGRP
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the `getwd' function. */
+#undef HAVE_GETWD
+
+/* Define if you have gpsman */
+#undef HAVE_GPSMAN
+
+/* GraphicsMagick image library */
+#undef HAVE_GRAPHICSMAGICK
+
+/* Define if you have gv */
+#undef HAVE_GV
+
+/* Imagemagick image library */
+#undef HAVE_IMAGEMAGICK
+
+/* Define to 1 if you have the `inet_ntoa' function. */
+#undef HAVE_INET_NTOA
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `ax25' library (-lax25). */
+#undef HAVE_LIBAX25
+
+/* Define to 1 if your `curl' library has curl_global_init. */
+#undef HAVE_LIBCURL
+
+/* Define to 1 if you have the `gc' library (-lgc). */
+#undef HAVE_LIBGC
+
+/* Define to 1 if you have the `gdal' library (-lgdaal). */
+#undef HAVE_LIBGDAL
+
+/* Define to 1 if you have the `geotiff' library (-lgeotiff). */
+#undef HAVE_LIBGEOTIFF
+
+/* Define to 1 if you have the <libintl.h> header file. */
+#undef HAVE_LIBINTL_H
+
+/* Define to 1 if you have the `pcre' library (-lpcre). */
+#undef HAVE_LIBPCRE
+
+/* Define to 1 if you have the `shp' library (-lshp). */
+#undef HAVE_LIBSHP
+
+/* Define to 1 if you have the <libshp/shapefil.h> header file. */
+#undef HAVE_LIBSHP_SHAPEFIL_H
+
+/* Define to 1 if you have the `Xext' library (-lXext). */
+#undef HAVE_LIBXEXT
+
+/* Define to 1 if you have the `Xm' library (-lXm). */
+#undef HAVE_LIBXM
+
+/* Define to 1 if you have the `Xp' library (-lXp). */
+#undef HAVE_LIBXP
+
+/* Define to 1 if you have the `Xpm' library (-lXpm). */
+#undef HAVE_LIBXPM
+
+/* Define to 1 if the `Xm' library (-lXm) is used for Xpm. */
+#undef HAVE_LIBXPM_IN_XM
+
+/* Define to 1 if you have the `Xt' library (-lXt). */
+#undef HAVE_LIBXT
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define if you have lpr */
+#undef HAVE_LPR
+
+/* GraphicsMagick or ImageMagick library */
+#undef HAVE_MAGICK
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+ to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the <math.h> header file. */
+#undef HAVE_MATH_H
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mempcpy' function. */
+#undef HAVE_MEMPCPY
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the `mkdir' function. */
+#undef HAVE_MKDIR
+
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the `munmap' function. */
+#undef HAVE_MUNMAP
+
+/* Define if you have mv */
+#undef HAVE_MV
+
+/* MySQL is present. */
+#undef HAVE_MYSQL
+
+/* MySQL with spatial support is present. */
+#undef HAVE_MYSQL_SPATIAL
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the <netax25/ax25.h> header file. */
+#undef HAVE_NETAX25_AX25_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define if you have old gv */
+#undef HAVE_NEW_GV
+
+/* Define to 1 if you have the <nl_types.h> header file. */
+#undef HAVE_NL_TYPES_H
+
+/* Define if you have old gv */
+#undef HAVE_OLD_GV
+
+/* Define to 1 if you have the <pcre.h> header file. */
+#undef HAVE_PCRE_H
+
+/* Define to 1 if you have the <pcre/pcre.h> header file. */
+#undef HAVE_PCRE_PCRE_H
+
+/* Postgresql with postgis is present. */
+#undef HAVE_POSTGIS
+
+/* Define to 1 if you have the `pow' function. */
+#undef HAVE_POW
+
+/* Define to 1 if you have the `libproj' library (-lproj). */
+#undef HAVE_PROJ
+
+/* Define if you have POSIX threads libraries and header files. */
+#undef HAVE_PTHREAD
+
+/* Define to 1 if you have the `pthread_mutexattr_setkind_np' function. */
+#undef HAVE_PTHREAD_MUTEXATTR_SETKIND_NP
+
+/* Define to 1 if you have the `pthread_mutexattr_settype' function. */
+#undef HAVE_PTHREAD_MUTEXATTR_SETTYPE
+
+/* Define to 1 if you have the `putenv' function. */
+#undef HAVE_PUTENV
+
+/* Define to 1 if you have the `roundf' function. */
+#undef HAVE_ROUNDF
+
+/* Define if you have sed */
+#undef HAVE_SED
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the `setenv' function. */
+#undef HAVE_SETENV
+
+/* Define to 1 if you have the `setlocale' function. */
+#undef HAVE_SETLOCALE
+
+/* Define to 1 if you have the `settimeofday' function. */
+#undef HAVE_SETTIMEOFDAY
+
+/* Define to 1 if you have the `shapefil.h' header. */
+#undef HAVE_SHAPEFIL_H
+
+/* Define to 1 if the system has the type `sighandler_t'. */
+#undef HAVE_SIGHANDLER_T
+
+/* Define to 1 if you have the `sigignore' function. */
+#undef HAVE_SIGIGNORE
+
+/* Define to 1 if the system has the type `sigjmp_buf'. */
+#undef HAVE_SIGJMP_BUF
+
+/* Define to 1 if you have the `signal' function. */
+#undef HAVE_SIGNAL
+
+/* Define to 1 if you have the <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* Define to 1 if the system has the type `sig_t'. */
+#undef HAVE_SIG_T
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* Define to 1 if the system has the type `socklen_t'. */
+#undef HAVE_SOCKLEN_T
+
+/* Spatial database support available */
+#undef HAVE_SPATIAL_DB
+
+/* Define to 1 if you have the `sqrt' function. */
+#undef HAVE_SQRT
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+ zero-length file name argument. */
+#undef HAVE_STAT_EMPTY_STRING_BUG
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `stpcpy' function. */
+#undef HAVE_STPCPY
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the `strftime' function. */
+#undef HAVE_STRFTIME
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#undef HAVE_STRNCASECMP
+
+/* Define to 1 if you have the `strndup' function. */
+#undef HAVE_STRNDUP
+
+/* Define to 1 if you have the `strpbrk' function. */
+#undef HAVE_STRPBRK
+
+/* Define to 1 if you have the `strptime' function. */
+#undef HAVE_STRPTIME
+
+/* Define to 1 if you have the `strrchr' function. */
+#undef HAVE_STRRCHR
+
+/* Define to 1 if you have the `strstr' function. */
+#undef HAVE_STRSTR
+
+/* Define to 1 if you have the `strtof' function. */
+#undef HAVE_STRTOF
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if you have the `strtoul' function. */
+#undef HAVE_STRTOUL
+
+/* Define to 1 if `tm_zone' is a member of `struct tm'. */
+#undef HAVE_STRUCT_TM_TM_ZONE
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define to 1 if you have the 'tiff' library (-ltiff) */
+#undef HAVE_TIFF
+
+/* X */
+#undef HAVE_TM_GMTOFF
+
+/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use
+ `HAVE_STRUCT_TM_TM_ZONE' instead. */
+#undef HAVE_TM_ZONE
+
+/* Define to 1 if you don't have `tm_zone' but do have the external array
+ `tzname'. */
+#undef HAVE_TZNAME
+
+/* Define to 1 if you have the `tzset' function. */
+#undef HAVE_TZSET
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Define if you have wget */
+#undef HAVE_WGET
+
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* Define to 1 if you have 'X11/xpm.h' */
+#undef HAVE_X11_XPM_H
+
+/* Define if you have xfontsel */
+#undef HAVE_XFONTSEL
+
+/* Define to 1 if you have the <Xm/XpmI.h> header file. */
+#undef HAVE_XM_XPMI_H
+
+/* Define to 1 if you have the `__argz_count' function. */
+#undef HAVE___ARGZ_COUNT
+
+/* Define to 1 if you have the `__argz_next' function. */
+#undef HAVE___ARGZ_NEXT
+
+/* Define to 1 if you have the `__argz_stringify' function. */
+#undef HAVE___ARGZ_STRINGIFY
+
+/* Path to lpr */
+#undef LPR_PATH
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+ slash. */
+#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
+
+/* Path to mv */
+#undef MV_PATH
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to the necessary symbol if this constant uses a non-standard name on
+ your system. */
+#undef PTHREAD_CREATE_JOINABLE
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Path to sed */
+#undef SED_PATH
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at runtime.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Legacy stuff, use crowbar and lets keep going */
+#undef STIPPLE
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#undef TM_IN_SYS_TIME
+
+/* Default TNC port. */
+#undef TNC_PORT
+
+/* Berkeley DB Map Caching */
+#undef USE_MAP_CACHE
+
+/* RTree spatial indexing */
+#undef USE_RTREE
+
+/* Enable extensions on AIX 3, Interix. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Version number of package */
+#undef VERSION
+
+/* Path to wget */
+#undef WGET_PATH
+
+/* Define to 1 to use dbfawk features. */
+#undef WITH_DBFAWK
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+# undef WORDS_BIGENDIAN
+# endif
+#endif
+
+/* Path to installed Xastir binaries. */
+#undef XASTIR_BIN_PATH
+
+/* Defines the installed libs */
+#undef XASTIR_INSTALLED_LIBS
+
+/* Path to installed Xastir files. */
+#undef XASTIR_PATH
+
+/* Define system type. */
+#undef XASTIR_SYSTEM
+
+/* Defines the version tocall */
+#undef XASTIR_TOCALL
+
+/* Define if you need to work with the broken Xorg server 1.7.5 */
+#undef XASTIR_XORG_SERVER_175_BUG
+
+/* Path to xfontsel */
+#undef XFONTSEL_PATH
+
+/* Define to 1 if the X Window System is missing or not being used. */
+#undef X_DISPLAY_MISSING
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+ this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
+
+/* Define if you're compiling for Linux Standard Base */
+#undef __LSB__
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
+
+#ifndef HAVE_SOCKLEN_T
+#define socklen_t int
+#endif
diff --git a/config.sub b/config.sub
new file mode 100755
index 0000000..2a55a50
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,1705 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+# Free Software Foundation, Inc.
+
+timestamp='2009-11-20'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file 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.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches at gnu.org>. Submit a context
+# diff and a properly formatted GNU ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ kopensolaris*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray | -microblaze)
+ os=
+ basic_machine=$1
+ ;;
+ -bluegene*)
+ os=-cnk
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fido | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | mcore | mep | metag \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nios | nios2 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | ubicom32 \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k | z80)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | picochip)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64octeon-* | mips64octeonel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64r5900-* | mips64r5900el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nios-* | nios2-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
+ | tron-* \
+ | ubicom32-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-* | z80-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ os=-aros
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ bluegene*)
+ basic_machine=powerpc-ibm
+ os=-cnk
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=-cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ os=-dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ microblaze)
+ basic_machine=microblaze-xilinx
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tile*)
+ basic_machine=tile-unknown
+ os=-linux-gnu
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ z80-*-coff)
+ basic_machine=z80-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -auroraux)
+ os=-auroraux
+ ;;
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+ | -sym* | -kopensolaris* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* | -aros* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* | -cegcc* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -dicos*)
+ os=-dicos
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -cnk*|-aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config/24kgrid.dbfawk b/config/24kgrid.dbfawk
new file mode 100644
index 0000000..05a411d
--- /dev/null
+++ b/config/24kgrid.dbfawk
@@ -0,0 +1,42 @@
+# $Id: 24kgrid.dbfawk,v 1.9 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map USGS 24k grid shapefiles, which contains bounding
+# rectangles for USGS 1:24000 quadrangles.
+# The shapefile itself can be had from
+# http://data.geocomm.com/quadindex/
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="NAME:STATE:LAT:LONG:MRC";
+# dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="NAME:STATE";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=8; fill_color=11; name=""; filled=0; pattern=0; display_level=65535; label_level=512; label_color=2; font_size=1; symbol=""}
+
+# per-field rules are applied to the dbffields that are read from each record.
+/^NAME=(.*)$/ {name="$1; next}
+/^STATE=(.*)$/ {name="$(name),$1; next}
diff --git a/config/Makefile.am b/config/Makefile.am
new file mode 100644
index 0000000..5b29af0
--- /dev/null
+++ b/config/Makefile.am
@@ -0,0 +1,130 @@
+# $Id: Makefile.am,v 1.52 2012/12/04 19:29:25 tvrusso Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+
+configdir = ${pkgdatadir}/config
+
+EXTRA_DIST = \
+ language-Dutch.sys \
+ language-English.sys \
+ language-French.sys \
+ language-German.sys \
+ language-Italian.sys \
+ language-Portuguese.sys \
+ language-Spanish.sys \
+ language-ElmerFudd.sys \
+ language-MuppetsChef.sys \
+ language-OldeEnglish.sys \
+ language-PigLatin.sys \
+ language-PirateEnglish.sys \
+ xastir.rgb \
+ gps_wpt.dbfawk \
+ 24kgrid.dbfawk \
+ stored_track.dbfawk \
+ tgr2shp.dbfawk \
+ tgr2shppoly.dbfawk \
+ tgr2shppoly_2006.dbfawk \
+ tgrcty.dbfawk \
+ tgrkgl.dbfawk \
+ tgrlk.dbfawk \
+ tgrlpt.dbfawk \
+ tgrlpy.dbfawk \
+ tgrplc00.dbfawk \
+ tgrwat.dbfawk \
+ nwsc_ddmmyy.dbfawk \
+ nwsc_ddmmyy_09.dbfawk \
+ nwsc_ddmmyy_09b.dbfawk \
+ nwsc_ddmmyy_10.dbfawk \
+ nwsc_ddmmyy_10a.dbfawk \
+ nwsmzddmmyy.dbfawk \
+ nwsmzddmmyy_09.dbfawk \
+ nwsmzddmmyy_11.dbfawk \
+ nwsmzoddmmyy.dbfawk \
+ nwsozddmmyy.dbfawk \
+ nwsozddmmyy_09.dbfawk \
+ nwsozddap12.dbfawk \
+ nwsw_ddmmyy.dbfawk \
+ nwsw_ddmmyy_09.dbfawk \
+ nwsw_ddmmyy_10.dbfawk \
+ nwsw_ddjn12.dbfawk \
+ nwsz_ddmmyy.dbfawk \
+ nwsz_ddmmyy_09.dbfawk \
+ nwsz_ddmmyy_10.dbfawk \
+ nwsz_ddmmyy_10b.dbfawk \
+ nwsz_ddmmyy_10c.dbfawk \
+ nwsz_ddmmyy_11.dbfawk \
+ nwsz1ddmmyy.dbfawk \
+ nwszoddmmyy.dbfawk \
+ nwshzddmmyy.dbfawk \
+ OSM_Cloudmade_administrative.dbfawk \
+ OSM_Cloudmade_highway.dbfawk \
+ OSM_Cloudmade_natural.dbfawk \
+ OSM_Cloudmade_poi.dbfawk \
+ OSM_Cloudmade_water_and_coastline.dbfawk \
+ predefined_EVENT.sys \
+ predefined_SAR.sys \
+ tl_2009_aiannh.dbfawk \
+ tl_2009_aits.dbfawk \
+ tl_2009_arealm.dbfawk \
+ tl_2009_areawater.dbfawk \
+ tl_2009_county.dbfawk \
+ tl_2009_cousub.dbfawk \
+ tl_2009_edges.dbfawk \
+ tl_2009_mil.dbfawk \
+ tl_2009_nn_county.dbfawk \
+ tl_2009_pointlm.dbfawk \
+ tl_2009_zcta5.dbfawk \
+ tnc-startup.aea \
+ tnc-startup.d700 \
+ tnc-startup.d72_d710 \
+ tnc-startup.kam \
+ tnc-startup.kpc2 \
+ tnc-startup.kpc3 \
+ tnc-startup.null \
+ tnc-startup.paccomm \
+ tnc-startup.pico \
+ tnc-startup.sys \
+ tnc-startup.thd7 \
+ tnc-startup.tnc2 \
+ tnc-startup.tnc2-ui \
+ tnc-stop.d700 \
+ tnc-stop.d72_d710 \
+ tnc-stop.sys \
+ tnc-stop.thd7 \
+ tnc-stop.tnc2-ui \
+ areawater.dbfawk \
+ arealm.dbfawk \
+ tabblock.dbfawk \
+ cousub.dbfawk \
+ cousub00.dbfawk \
+ edge.dbfawk \
+ featnames.dbfawk \
+ pointlm.dbfawk \
+ gfe_public_weather.dbfawk \
+ gfe_metro_areas.dbfawk \
+ gfe_fire_weather.dbfawk \
+ gfe_coastal_waters_warnings.dbfawk \
+ gfe_coastal_waters.dbfawk
+
+
+config_DATA = ${EXTRA_DIST}
+
+install-exec-hook:
+ -rm -f $(DESTDIR)$(configdir)/nwsfz_ddmmyy.dbfawk
+
+language-ElmerFudd.sys: language-English.sys
+ $(top_srcdir)/scripts/langElmerFudd.pl -split >$@ <$(srcdir)/language-English.sys
+
+language-MuppetsChef.sys: language-English.sys
+ $(top_srcdir)/scripts/langMuppetsChef.pl -split >$@ <$(srcdir)/language-English.sys
+
+language-OldeEnglish.sys: language-English.sys
+ $(top_srcdir)/scripts/langOldeEnglish.pl -split >$@ <$(srcdir)/language-English.sys
+
+language-PigLatin.sys: language-English.sys
+ $(top_srcdir)/scripts/langPigLatin.pl -split >$@ <$(srcdir)/language-English.sys
+
+language-PirateEnglish.sys: language-English.sys
+ $(top_srcdir)/scripts/langPirateEnglish.pl -split >$@ <$(srcdir)/language-English.sys
+
diff --git a/config/Makefile.in b/config/Makefile.in
new file mode 100644
index 0000000..e7c9803
--- /dev/null
+++ b/config/Makefile.in
@@ -0,0 +1,534 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+# $Id: Makefile.am,v 1.52 2012/12/04 19:29:25 tvrusso Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = config
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(configdir)"
+DATA = $(config_DATA)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTSHP = @CONTSHP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GMAGIC_BIN = @GMAGIC_BIN@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBCOMPAT = @LIBCOMPAT@
+LIBOBJS = @LIBOBJS@
+LIBRTREE = @LIBRTREE@
+LIBS = @LIBS@
+LIBSHP = @LIBSHP@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LWPOSTGIS = @LWPOSTGIS@
+MAGIC_BIN = @MAGIC_BIN@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PG_CONFIG = @PG_CONFIG@
+POW_LIB = @POW_LIB@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUBRTREE = @SUBRTREE@
+SUBSHP = @SUBSHP@
+VERSION = @VERSION@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+convert = @convert@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+festival = @festival@
+found_gdal_config = @found_gdal_config@
+gm = @gm@
+gpsman = @gpsman@
+gv = @gv@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lpr = @lpr@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+mv = @mv@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sed = @sed@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+wget = @wget@
+xfontsel = @xfontsel@
+configdir = ${pkgdatadir}/config
+EXTRA_DIST = \
+ language-Dutch.sys \
+ language-English.sys \
+ language-French.sys \
+ language-German.sys \
+ language-Italian.sys \
+ language-Portuguese.sys \
+ language-Spanish.sys \
+ language-ElmerFudd.sys \
+ language-MuppetsChef.sys \
+ language-OldeEnglish.sys \
+ language-PigLatin.sys \
+ language-PirateEnglish.sys \
+ xastir.rgb \
+ gps_wpt.dbfawk \
+ 24kgrid.dbfawk \
+ stored_track.dbfawk \
+ tgr2shp.dbfawk \
+ tgr2shppoly.dbfawk \
+ tgr2shppoly_2006.dbfawk \
+ tgrcty.dbfawk \
+ tgrkgl.dbfawk \
+ tgrlk.dbfawk \
+ tgrlpt.dbfawk \
+ tgrlpy.dbfawk \
+ tgrplc00.dbfawk \
+ tgrwat.dbfawk \
+ nwsc_ddmmyy.dbfawk \
+ nwsc_ddmmyy_09.dbfawk \
+ nwsc_ddmmyy_09b.dbfawk \
+ nwsc_ddmmyy_10.dbfawk \
+ nwsc_ddmmyy_10a.dbfawk \
+ nwsmzddmmyy.dbfawk \
+ nwsmzddmmyy_09.dbfawk \
+ nwsmzddmmyy_11.dbfawk \
+ nwsmzoddmmyy.dbfawk \
+ nwsozddmmyy.dbfawk \
+ nwsozddmmyy_09.dbfawk \
+ nwsozddap12.dbfawk \
+ nwsw_ddmmyy.dbfawk \
+ nwsw_ddmmyy_09.dbfawk \
+ nwsw_ddmmyy_10.dbfawk \
+ nwsw_ddjn12.dbfawk \
+ nwsz_ddmmyy.dbfawk \
+ nwsz_ddmmyy_09.dbfawk \
+ nwsz_ddmmyy_10.dbfawk \
+ nwsz_ddmmyy_10b.dbfawk \
+ nwsz_ddmmyy_10c.dbfawk \
+ nwsz_ddmmyy_11.dbfawk \
+ nwsz1ddmmyy.dbfawk \
+ nwszoddmmyy.dbfawk \
+ nwshzddmmyy.dbfawk \
+ OSM_Cloudmade_administrative.dbfawk \
+ OSM_Cloudmade_highway.dbfawk \
+ OSM_Cloudmade_natural.dbfawk \
+ OSM_Cloudmade_poi.dbfawk \
+ OSM_Cloudmade_water_and_coastline.dbfawk \
+ predefined_EVENT.sys \
+ predefined_SAR.sys \
+ tl_2009_aiannh.dbfawk \
+ tl_2009_aits.dbfawk \
+ tl_2009_arealm.dbfawk \
+ tl_2009_areawater.dbfawk \
+ tl_2009_county.dbfawk \
+ tl_2009_cousub.dbfawk \
+ tl_2009_edges.dbfawk \
+ tl_2009_mil.dbfawk \
+ tl_2009_nn_county.dbfawk \
+ tl_2009_pointlm.dbfawk \
+ tl_2009_zcta5.dbfawk \
+ tnc-startup.aea \
+ tnc-startup.d700 \
+ tnc-startup.d72_d710 \
+ tnc-startup.kam \
+ tnc-startup.kpc2 \
+ tnc-startup.kpc3 \
+ tnc-startup.null \
+ tnc-startup.paccomm \
+ tnc-startup.pico \
+ tnc-startup.sys \
+ tnc-startup.thd7 \
+ tnc-startup.tnc2 \
+ tnc-startup.tnc2-ui \
+ tnc-stop.d700 \
+ tnc-stop.d72_d710 \
+ tnc-stop.sys \
+ tnc-stop.thd7 \
+ tnc-stop.tnc2-ui \
+ areawater.dbfawk \
+ arealm.dbfawk \
+ tabblock.dbfawk \
+ cousub.dbfawk \
+ cousub00.dbfawk \
+ edge.dbfawk \
+ featnames.dbfawk \
+ pointlm.dbfawk \
+ gfe_public_weather.dbfawk \
+ gfe_metro_areas.dbfawk \
+ gfe_fire_weather.dbfawk \
+ gfe_coastal_waters_warnings.dbfawk \
+ gfe_coastal_waters.dbfawk
+
+config_DATA = ${EXTRA_DIST}
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu config/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-configDATA: $(config_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(configdir)" || $(MKDIR_P) "$(DESTDIR)$(configdir)"
+ @list='$(config_DATA)'; test -n "$(configdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(configdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(configdir)" || exit $$?; \
+ done
+
+uninstall-configDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(config_DATA)'; test -n "$(configdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(configdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(configdir)" && rm -f $$files
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(configdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-configDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-configDATA
+
+.MAKE: install-am install-exec-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic distclean \
+ distclean-generic distdir dvi dvi-am html html-am info info-am \
+ install install-am install-configDATA install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-exec-hook install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am uninstall uninstall-am uninstall-configDATA
+
+
+install-exec-hook:
+ -rm -f $(DESTDIR)$(configdir)/nwsfz_ddmmyy.dbfawk
+
+language-ElmerFudd.sys: language-English.sys
+ $(top_srcdir)/scripts/langElmerFudd.pl -split >$@ <$(srcdir)/language-English.sys
+
+language-MuppetsChef.sys: language-English.sys
+ $(top_srcdir)/scripts/langMuppetsChef.pl -split >$@ <$(srcdir)/language-English.sys
+
+language-OldeEnglish.sys: language-English.sys
+ $(top_srcdir)/scripts/langOldeEnglish.pl -split >$@ <$(srcdir)/language-English.sys
+
+language-PigLatin.sys: language-English.sys
+ $(top_srcdir)/scripts/langPigLatin.pl -split >$@ <$(srcdir)/language-English.sys
+
+language-PirateEnglish.sys: language-English.sys
+ $(top_srcdir)/scripts/langPirateEnglish.pl -split >$@ <$(srcdir)/language-English.sys
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/config/OSM_Cloudmade_administrative.dbfawk b/config/OSM_Cloudmade_administrative.dbfawk
new file mode 100644
index 0000000..ee8d887
--- /dev/null
+++ b/config/OSM_Cloudmade_administrative.dbfawk
@@ -0,0 +1,59 @@
+# $Id: OSM_Cloudmade_administrative.dbfawk,v 1.2 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that
+# accompanies a shapefile into Xastir canonical values of:
+#
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near
+# awk compatible.
+#
+# This file is used to map OSM shapefiles by "Cloudmade" which are
+# named "*_administrative.dbf".
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column
+# names in order. dbfinfo should match the dbf file that we say this
+# dbfawk file goes with.
+dbfinfo="NAME:ADMIN_LEVE";
+
+# dbffields is which of the above fields we actually want to look
+# at. No point reading dbffields that are not looked at further.
+dbffields="NAME:ADMIN_LEVE";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple
+# fields. Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=105; fill_color=11; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=8; font_size=0; symbol=""; fill_style=0;}
+
+# per-field rules are applied to the dbffields that are read from
+# each record.
+
+# select the name given in the record
+/^NAME=(.+)$/ {name="$1";next}
+
+/^ADMIN_LEVE=2/ {lanes=4; color=105; label_level=65536; font_size=1; next}
+/^ADMIN_LEVE=4/ {lanes=3; color=105; display_level=64; label_level=512; font_size=1; next}
+/^ADMIN_LEVE=6/ {lanes=2; color=105; display_level=64; label_level=512; font_size=1; next}
+/^ADMIN_LEVE=8/ {lanes=1; color=105; display_level=64; label_level=512; font_size=1; next}
+
+# key: set the search key to be the Tiger/Line ID. Not currently
+# used.
+#/^TLID=(.*)$/ {key=$1; next}
+
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
diff --git a/config/OSM_Cloudmade_highway.dbfawk b/config/OSM_Cloudmade_highway.dbfawk
new file mode 100644
index 0000000..85b4899
--- /dev/null
+++ b/config/OSM_Cloudmade_highway.dbfawk
@@ -0,0 +1,106 @@
+# $Id: OSM_Cloudmade_highway.dbfawk,v 1.2 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that
+# accompanies a shapefile into Xastir canonical values of:
+#
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near
+# awk compatible.
+#
+# This file is used to map OSM shapefiles by "Cloudmade" which are
+# named "*_highway.dbf".
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column
+# names in order. dbfinfo should match the dbf file that we say this
+# dbfawk file goes with.
+dbfinfo="TYPE:NAME:ONEWAY:LANES";
+
+# dbffields is which of the above fields we actually want to look
+# at. No point reading dbffields that are not looked at further.
+dbffields="TYPE:NAME:ONEWAY:LANES";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple
+# fields. Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=8; fill_color=11; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=8; font_size=0; symbol=""; fill_style=0;}
+
+# per-field rules are applied to the dbffields that are read from
+# each record.
+
+# select the name given in the record
+/^NAME=United States Highway (.*)$/ {name="$(name)US $1"; next}
+/^NAME=State Highway (.*)$/ {name="$(name)Hwy $1"; next}
+/^NAME=State Route (.*)$/ {name="$(name)SR-$1"; next}
+/^NAME=United States Highway (.*)$/ {name="$(name)US $1"; next}
+/^NAME=United States Highway (.*)$/ {name="$(name)US $1"; next}
+/^NAME=Interstate (.*) Northbound$/ {name="$(name)I-$1 N"; next}
+/^NAME=Interstate (.*) Southbound$/ {name="$(name)I-$1 S"; next}
+/^NAME=Interstate (.*) Eastbound$/ {name="$(name)I-$1 E"; next}
+/^NAME=Interstate (.*) Westbound$/ {name="$(name)I-$1 W"; next}
+/^NAME=Interstate (.*)$/ {name="$(name)I-$1"; next}
+/^NAME=Washington Highway (.*)$/ {name="$(name)Hwy $1"; next}
+/^NAME=(.+)$/ {name="$1";next}
+
+#/^LANES=(.+)$/ {lanes="$1";}
+
+# TYPE:
+/^TYPE=abandoned/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=bridleway/ {lanes=1; color=66; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=construction/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=crossing/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=cycleway/ {lanes=1; color=66; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=driveway/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=footway/ {lanes=1; color=66; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=ford/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=living_street/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+# Note: No display_level or label_level
+/^TYPE=motorway/ {lanes=4; color=4; label_level=65536; font_size=3; next}
+# Note: No display_level
+/^TYPE=motorway_link/ {lanes=3; color=2; label_level=16; font_size=1; next}
+/^TYPE=path/ {lanes=1; color=66; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=pedestrian/ {lanes=1; color=66; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=platform/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=primary/ {lanes=2; color=8; display_level=512; label_level=128; font_size=1; next}
+/^TYPE=primary_link/ {lanes=2; color=8; display_level=512; label_level=128; font_size=1; next}
+/^TYPE=raceway/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=ramp/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=residential/ {lanes=1; color=44; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=road/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=secondary/ {lanes=2; color=8; display_level=256; label_level=64; font_size=1; next}
+/^TYPE=secondary_link/ {lanes=1; color=8; display_level=256; label_level=64; font_size=1; next}
+/^TYPE=service/ {lanes=1; color=8; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=service; residential/ {lanes=7; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=steps/ {lanes=1; color=66; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=tertiary/ {lanes=1; color=8; display_level=256; label_level=64; font_size=1; next}
+/^TYPE=tertiary_link/ {lanes=1; color=8; display_level=256; label_level=64; font_size=1; next}
+/^TYPE=t/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=track/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=trail/ {lanes=1; color=66; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=tr/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=trunk/ {lanes=3; color=8; display_level=128; label_level=16; font_size=3; next}
+/^TYPE=trunk_link/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=unclassified/ {lanes=1; color=4; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=unsurfaced/ {lanes=1; color=105; display_level=64; label_level=16; font_size=1; next}
+
+# key: set the search key to be the Tiger/Line ID. Not currently
+# used.
+#/^TLID=(.*)$/ {key=$1; next}
+
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
diff --git a/config/OSM_Cloudmade_natural.dbfawk b/config/OSM_Cloudmade_natural.dbfawk
new file mode 100644
index 0000000..cf462d4
--- /dev/null
+++ b/config/OSM_Cloudmade_natural.dbfawk
@@ -0,0 +1,58 @@
+# $Id: OSM_Cloudmade_natural.dbfawk,v 1.2 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that
+# accompanies a shapefile into Xastir canonical values of:
+#
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near
+# awk compatible.
+#
+# This file is used to map OSM shapefiles by "Cloudmade" which are
+# named "*_natural.dbf".
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column
+# names in order. dbfinfo should match the dbf file that we say this
+# dbfawk file goes with.
+dbfinfo="NAME:TYPE";
+
+# dbffields is which of the above fields we actually want to look
+# at. No point reading dbffields that are not looked at further.
+dbffields="NAME:TYPE:";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple
+# fields. Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=4; fill_color=11; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=8; font_size=0; symbol=""; fill_style=0;}
+
+# per-field rules are applied to the dbffields that are read from
+# each record.
+
+# select the name given in the record
+/^NAME=(.+)$/ {name="$1";next}
+
+# TYPE:
+/^TYPE=water/ {lanes=1; color=9; display_level=64; label_level=16; font_size=1; next}
+/^TYPE=forest/ {lanes=1; color=10; fill-color=10; display_level=64; label_level=16; font_size=1; next}
+
+# key: set the search key to be the Tiger/Line ID. Not currently
+# used.
+#/^TLID=(.*)$/ {key=$1; next}
+
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
diff --git a/config/OSM_Cloudmade_poi.dbfawk b/config/OSM_Cloudmade_poi.dbfawk
new file mode 100644
index 0000000..9ef2758
--- /dev/null
+++ b/config/OSM_Cloudmade_poi.dbfawk
@@ -0,0 +1,62 @@
+# $Id: OSM_Cloudmade_poi.dbfawk,v 1.2 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that
+# accompanies a shapefile into Xastir canonical values of:
+#
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near
+# awk compatible.
+#
+# This file is used to map OSM shapefiles by "Cloudmade" which are
+# named "*_poi.dbf".
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column
+# names in order. dbfinfo should match the dbf file that we say this
+# dbfawk file goes with.
+dbfinfo="CATEGORY:NAME";
+
+# dbffields is which of the above fields we actually want to look
+# at. No point reading dbffields that are not looked at further.
+dbffields="CATEGORY:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple
+# fields. Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=8; fill_color=11; name=""; filled=0; pattern=0; display_level=16; label_level=16; label_color=8; font_size=0; symbol=""; fill_style=0;}
+
+# per-field rules are applied to the dbffields that are read from
+# each record.
+
+/^NAME=(.+)$/ {name="$1";next}
+/^CATEGORY=Automotive/ {color=4; font_size=1; next}
+/^CATEGORY=Eating&Drinking/ {color=4; font_size=1; next}
+/^CATEGORY=Government and Public Services/ {color=4; font_size=1; next}
+/^CATEGORY=Health care/ {color=4; font_size=1; next}
+/^CATEGORY=Leisure/ {color=4; font_size=1; next}
+/^CATEGORY=Lodging/ {color=4; font_size=1; next}
+/^CATEGORY=Night Life and Business/ {color=4; font_size=1; next}
+/^CATEGORY=Sports/ {color=4; font_size=1; next}
+/^CATEGORY=Tourism/ {color=4; font_size=1; next}
+
+# key: set the search key to be the Tiger/Line ID. Not currently
+# used.
+#/^TLID=(.*)$/ {key=$1; next}
+
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
diff --git a/config/OSM_Cloudmade_water_and_coastline.dbfawk b/config/OSM_Cloudmade_water_and_coastline.dbfawk
new file mode 100644
index 0000000..133a1b6
--- /dev/null
+++ b/config/OSM_Cloudmade_water_and_coastline.dbfawk
@@ -0,0 +1,59 @@
+# $Id: OSM_Cloudmade_water_and_coastline.dbfawk,v 1.2 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that
+# accompanies a shapefile into Xastir canonical values of:
+#
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near
+# awk compatible.
+#
+# This file is used to map OSM shapefiles by "Cloudmade" which are
+# named "*_water.dbf" and "*_coastline.dbf". Unfortunately both
+# DBF files have the same signature, so we need to have this dbfawk
+# file match both of them.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column
+# names in order. dbfinfo should match the dbf file that we say this
+# dbfawk file goes with.
+dbfinfo="NATURAL:NAME";
+
+# dbffields is which of the above fields we actually want to look
+# at. No point reading dbffields that are not looked at further.
+dbffields="NATURAL:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple
+# fields. Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=34; fill_color=26; name=""; filled=1; pattern=0; display_level=8192; label_level=32; label_color=15; font_size=0; symbol=""; fill_style=0;}
+
+# per-field rules are applied to the dbffields that are read from
+# each record.
+
+/^NAME=(.+)$/ {name="$1";next}
+/^NATURAL=shoreline/ {lanes=1; display_level=65536; label_level=1; font_size=1; next}
+/^NATURAL=water/ {lanes=1; display_level=65536; label_level=16; font_size=1; next}
+
+# key: set the search key to be the Tiger/Line ID. Not currently
+# used.
+#/^TLID=(.*)$/ {key=$1; next}
+
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
+
+
diff --git a/config/arealm.dbfawk b/config/arealm.dbfawk
new file mode 100644
index 0000000..2a53c7a
--- /dev/null
+++ b/config/arealm.dbfawk
@@ -0,0 +1,53 @@
+# $Id: arealm.dbfawk,v 1.4 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# Census.gov 2008 TigerMaps for AREALM
+# Richard Polivka, N6NKO - April, 2008
+# Craig Anderson, N6YXK - May, 2008
+# Dale Seaburg, KG5LT - March 2009
+#
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line Shapefiles as available at:
+# http://www.census.gov/geo/www/tiger/tgrshp2008/tgrshp2008.html
+#
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="STATEFP:COUNTYFP:ANSICODE:AREAID:FULLNAME:MTFCC";
+#dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="FULLNAME:MTFCC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=6; fill_color=11; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=8; font_size=0; symbol=""; fill_style=0 }
+
+/^FULLNAME=(.*)$/ {name="$1";next}
+# buildings
+/^MTFCC=K/ {display_level=256; filled=1 color=2; fill_color=2; label_level=128; next}
+# PLCC
+/^MTFCC=L/ {display_level=0; next}
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
+
diff --git a/config/areawater.dbfawk b/config/areawater.dbfawk
new file mode 100644
index 0000000..6629f92
--- /dev/null
+++ b/config/areawater.dbfawk
@@ -0,0 +1,52 @@
+# $Id: areawater.dbfawk,v 1.4 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# Census.gov 2008 TigerMaps for AREAWATER
+# Richard Polivka, N6NKO - April, 2008
+# Craig Anderson, N6YXK - May, 2008
+# Dale Seaburg, KG5LT - March, 2009
+#
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line Shapefiles as available at:
+# http://www.census.gov/geo/www/tiger/tgrshp2008/tgrshp2008.html
+#
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="STATEFP:COUNTYFP:ANSICODE:HYDROID:FULLNAME:MTFCC";
+#dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="FULLNAME:MTFCC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=26; fill_color=26; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=26; font_size=0; symbol=""; fill_style=0 }
+
+/^FULLNAME=(.*)$/ {name="$1";next}
+# water
+/^MTFCC=H20/ {filled=1; color=97; fill_color=97; label_color=26; display_level=1024;next}
+/^MTFCC=H30/ {filled=1; color=97; fill_color=97; label_color=26; display_level=1024;skip}
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
+
diff --git a/config/cousub.dbfawk b/config/cousub.dbfawk
new file mode 100644
index 0000000..2c2c90f
--- /dev/null
+++ b/config/cousub.dbfawk
@@ -0,0 +1,52 @@
+# $Id: cousub.dbfawk,v 1.4 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# Census.gov 2008 TigerMaps for COUSUB
+# Richard Polivka, N6NKO - April, 2008
+# Craig Anderson, N6YXK - May, 2008
+# Dale Seaburg, KG5LT - March, 2009
+#
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line Shapefiles as available at:
+# http://www.census.gov/geo/www/tiger/tgrshp2008/tgrshp2008.html
+#
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+# 2007FE = dbfinfo="STATEFP:COUNTYFP:COUSUBFP:COUSUBNS:COSBIDFP:NAME:NAMELSAD:LSAD:CLASSFP:MTFCC:UR:FUNCSTAT";
+dbfinfo ="STATEFP:COUNTYFP:COUSUBFP:COUSUBNS:COSBIDFP:NAME:NAMELSAD:LSAD:CLASSFP:MTFCC:CNECTAFP:NECTAFP:NCTADVFP:FUNCSTAT";
+#dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="NAME:MTFCC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=6; fill_color=11; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=8; font_size=0; symbol=""; fill_style=0 }
+
+/^NAME=(.*)$/ {name="$1";next}
+# item locations
+/^MTFCC=G/ {display_level=512;color=11; next}
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
+
diff --git a/config/cousub00.dbfawk b/config/cousub00.dbfawk
new file mode 100644
index 0000000..ecd7f10
--- /dev/null
+++ b/config/cousub00.dbfawk
@@ -0,0 +1,51 @@
+# $Id: cousub00.dbfawk,v 1.4 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# Census.gov 2008 TigerMaps for COUSUB00
+# Richard Polivka, N6NKO - April, 2008
+# Craig Anderson, N6YXK - May, 2008
+# Dale Seaburg, KG5LT - March, 2009
+#
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line Shapefiles as available at:
+# http://www.census.gov/geo/www/tiger/tgrshp2008/tgrshp2008.html
+#
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="STATEFP00:COUNTYFP00:COUSUBFP00:COSBIDFP00:NAME00:NAMELSAD00:LSAD00:CLASSFP00:MTFCC00:UR00:FUNCSTAT00";
+#dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="NAME00:MTFCC00";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=6; fill_color=11; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=8; font_size=0; symbol=""; fill_style=0 }
+
+/^NAME00=(.*)$/ {name="$1";next}
+# item locations
+/^MTFCC00=G/ {display_level=512;color=11; next}
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
+
diff --git a/config/edge.dbfawk b/config/edge.dbfawk
new file mode 100644
index 0000000..b466f42
--- /dev/null
+++ b/config/edge.dbfawk
@@ -0,0 +1,87 @@
+# $Id: edge.dbfawk,v 1.4 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# Census.gov 2008 TigerMaps for EDGES
+# Richard Polivka, N6NKO - April, 2008
+# Craig Anderson, N6YXK - May, 2008
+# Dale Seaburg, KG5LT - March, 2009
+#
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line Shapefiles as available at:
+# http://www.census.gov/geo/www/tiger/tgrshp2008/tgrshp2008.html
+#
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+# dbfinfo="STATEFP:COUNTYFP:COUNTYNS:TLID:TFIDL:TFIDR:MTFCC:FULLNAME:SMID:LFROMADD:LTOADD:RFROMADD:RTOADD:ZIPL:ZIPR:FEATCAT:HYDROFLG:RAILFLG:ROADFLG:OLFFLG:PASSFLG:DIVROAD:EXTTYP:TTYP:DECKEDROAD:ARTPATH";
+dbfinfo="STATEFP:COUNTYFP:TLID:TFIDL:TFIDR:MTFCC:FULLNAME:SMID:LFROMADD:LTOADD:RFROMADD:RTOADD:ZIPL:ZIPR:FEATCAT:HYDROFLG:RAILFLG:ROADFLG:OLFFLG:PASSFLG:DIVROAD:EXTTYP:TTYP:DECKEDROAD:ARTPATH:PERSIST:GCSEFLG:OFFSETL:OFFSETR:TNIDF:TNIDT";
+#dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="MTFCC:FULLNAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=6; fill_color=11; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=8; font_size=0; symbol=""; fill_style=0 }
+
+/^FULLNAME=(.*)$/ {name="$1";next}
+# item locations
+/^MTFCC=C3/ {display_level=0; next}
+# water
+/^MTFCC=H20/ {filled=1; fill_style=2; fill_stipple=2; color=117; fill_color=117; label_color=26; display_level=1024;next}
+/^MTFCC=H30/ {filled=1; fill_style=2; fill_stipple=2; color=117; fill_color=117; label_color=26; display_level=1024;next}
+# buildings
+/^MTFCC=K/ {display_level=128; next}
+# PLCC
+/^MTFCC=L/ {display_level=1024; next}
+# legal / statistical boundary
+/^MTFCC=P0001/ {display_level=0; next}
+# water shoreline
+/^MTFCC=P0002/ {display_level=1240; color=9; fill_color=9; next}
+# water intermittent shoreline
+/^MTFCC=P0003/ {display_level=1240; color=9; fill_color=9; next}
+# non-visible boundary
+/^MTFCC=P0004/ {display_level=0; next}
+# railroad
+/^MTFCC=R/ {lanes=2; color=8; pattern=1; display_level=128; next}
+# Limited access road
+/^MTFCC=S11/ {lanes=4; color=11; display_level=1024; label_level=512; font_size=3; next}
+# secondary road
+/^MTFCC=S12/ {display_level=512; lanes=3; color=8; label_level=256; font_size=2; next}
+# local road
+/^MTFCC=S14/ {display_level=128; label_level=16; color=48; lanes=1; next}
+# 4WD off-road trail
+/^MTFCC=S15/ {lanes=1; color=4; display_level=64; font_size=1; next}
+# Freeway access / service drive
+/^MTFCC=S16/ {color=11; display_level=64; next}
+# walkway / stairway
+/^MTFCC=S17[12]/ {lanes=1; color=12; pattern=2; display_level=64; next}
+# alley / private road
+/^MTFCC=S17[34]/ {lanes=1; color=40; pattern=2; display_level=64; next}
+# bike / bridle path
+/^MTFCC=S18/ {lanes=1; color=40; pattern=2; display_level=64; next}
+# road median
+/^MTFCC=S20/ {lanes=1; color=40; pattern=2; display_level=64; next}
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
+
diff --git a/config/featnames.dbfawk b/config/featnames.dbfawk
new file mode 100644
index 0000000..7890b62
--- /dev/null
+++ b/config/featnames.dbfawk
@@ -0,0 +1,87 @@
+# $Id: featnames.dbfawk,v 1.4 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# Census.gov 2008 TigerMaps for FEATNAMES
+# Richard Polivka, N6NKO - April, 2008
+# Craig Anderson, N6YXK - May, 2008
+# Dale Seaburg, KG5LT - March, 2009
+#
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line Shapefiles as available at:
+# http://www.census.gov/geo/www/tiger/tgrshp2008/tgrshp2008.html
+#
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+# 2007FE = dbfinfo="TLID:FULLNAME:NAME:PREDIRABRV:PRETYPABRV:PREQUALABR:SUFDIRABRV:SUFTYPABRV:SUFQUALABR:PREDIR:PRETYP:PREQUAL:SUFDIR:SUFTYP:SUFQUAL:LINEARID:MTFCC:PAFLAG";
+dbfinfo="TLID:FULLNAME:NAME:PREDIRABRV:PRETYPABRV:PREQUALABR:SUFDIRABRV:SUFTYPABRV:SUFQUALABR:PREDIR:PRETYP:PREQUAL:SUFDIR:SUFTYP:SUFQUAL:LINEARID:MTFCC:PAFLAG";
+#dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="FULLNAME:MTFCC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=26; fill_color=26; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=26; font_size=0; symbol=""; fill_style=0 }
+
+/^FULLNAME=(.*)$/ {name="$1";next}
+# item locations
+#/^MTFCC=C3/ {display_level=0; next}
+# water
+/^MTFCC=H20/ {filled=1; fill_style=2; fill_stipple=2; color=117; fill_color=117; label_color=26; display_level=1024;next}
+/^MTFCC=H30/ {filled=1; fill_style=2; fill_stipple=2; color=117; fill_color=117; label_color=26; display_level=1024;next}
+# buildings
+#/^MTFCC=K/ {display_level=256; color=25; next}
+# PLCC
+/^MTFCC=L/ {display_level=0; next}
+# legal / statistical boundary
+/^MTFCC=P0001/ {display_level=0; next}
+# water shoreline
+/^MTFCC=P0002/ {display_level=1240; color=9; fill_color=9; next}
+# water intermittent shoreline
+/^MTFCC=P0003/ {display_level=1240; color=9; fill_color=9; next}
+# non-visible boundary
+/^MTFCC=P0004/ {display_level=0; next}
+# railroad
+/^MTFCC=R/ {lanes=2; color=8; pattern=1; display_level=128; next}
+# Limited access road
+/^MTFCC=S11/ {display_level=2048; lanes=4; color=11; label_level=512; font_size=3; next}
+# secondary road
+/^MTFCC=S12/ {display_level=128; lanes=3; color=8; label_level=128; font_size=2; next}
+# local road
+/^MTFCC=S14/ {display_level=128; label_level=16; color=20; lanes=1; next}
+# 4WD off-road trail
+/^MTFCC=S15/ {lanes=1; color=69; display_level=64; font_size=1; next}
+# Freeway access / service drive
+/^MTFCC=S16/ {color=11; display_level=64; next}
+# walkway / stairway
+/^MTFCC=S17[12]/ {lanes=1; color=12; pattern=2; display_level=64; next}
+# alley / private road
+/^MTFCC=S17[34]/ {lanes=1; color=40; pattern=2; display_level=64; next}
+# bike / bridle path
+/^MTFCC=S18/ {lanes=1; color=40; pattern=2; display_level=64; next}
+# road median
+/^MTFCC=S20/ {lanes=1; color=40; pattern=2; display_level=64; next}
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
+
diff --git a/config/gfe_coastal_waters.dbfawk b/config/gfe_coastal_waters.dbfawk
new file mode 100644
index 0000000..8e60de5
--- /dev/null
+++ b/config/gfe_coastal_waters.dbfawk
@@ -0,0 +1,42 @@
+# $Id: gfe_coastal_waters.dbfawk,v 1.1 2012/03/02 20:26:50 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canonical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS state zone area polygon shapefiles
+# which are named z_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the STATE_ZONE code,
+# reformatted to match alert->title (e.g. KS033 is KS_Z033).
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="OFFICE:DIST_NAME:STATE_CODE:STATE_NAME:TIME_ZONE:AAC:DIST_NO:PT_1_NAME:PT_2_NAME:PART_STATE:DISP_ORDER:AREA_TYPE:NARR_FLAG:LEVEL:AAC_PARENT:RPT_SEAS:RPT_SWELL:ELEVATION";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="DIST_NAME:AAC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^AAC=(.*)$/ {key="$1"; next}
+/^DIST_NAME=(.*)$/ {name="$1"; next}
diff --git a/config/gfe_coastal_waters_warnings.dbfawk b/config/gfe_coastal_waters_warnings.dbfawk
new file mode 100644
index 0000000..1cf4f1c
--- /dev/null
+++ b/config/gfe_coastal_waters_warnings.dbfawk
@@ -0,0 +1,42 @@
+# $Id: gfe_coastal_waters_warnings.dbfawk,v 1.1 2012/03/02 20:26:50 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS state zone area polygon shapefiles
+# which are named z_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the STATE_ZONE code,
+# reformatted to match alert->title (e.g. KS033 is KS_Z033).
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="OFFICE:DIST_NAME:STATE_CODE:STATE_NAME:TIME_ZONE:AAC:SEG:AAC_MW:PT_1_NAME:PT_2_NAME:PART_STATE:DISP_ORDER:AREA_TYPE:NARR_FLAG:LEVEL:AAC_PARENT:RPT_SEAS:RPT_SWELL:DESC_TEXT";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="DIST_NAME:AAC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^AAC=(.*)$/ {key="$1"; next}
+/^DIST_NAME=(.*)$/ {name="$1"; next}
diff --git a/config/gfe_fire_weather.dbfawk b/config/gfe_fire_weather.dbfawk
new file mode 100644
index 0000000..58e8e91
--- /dev/null
+++ b/config/gfe_fire_weather.dbfawk
@@ -0,0 +1,42 @@
+# $Id: gfe_fire_weather.dbfawk,v 1.1 2012/03/02 20:26:50 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS state zone area polygon shapefiles
+# which are named z_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the STATE_ZONE code,
+# reformatted to match alert->title (e.g. KS033 is KS_Z033).
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="OFFICE:DIST_NO:DIST_NAME:STATE_CODE:STATE_NAME:TIME_ZONE:AAC:SOURCE:FIREBAN_TH:BAN_FLAG:DISP_ORDER:NARR_FLAG:LEVEL:USE_GFDR:USE_FFDR:USE_SFDR:USE_HI_FDR:PW_AACS";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="DIST_NAME:AAC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^AAC=(.*)$/ {key="$1"; next}
+/^DIST_NAME=(.*)$/ {name="$1"; next}
diff --git a/config/gfe_metro_areas.dbfawk b/config/gfe_metro_areas.dbfawk
new file mode 100644
index 0000000..d10afa0
--- /dev/null
+++ b/config/gfe_metro_areas.dbfawk
@@ -0,0 +1,42 @@
+# $Id: gfe_metro_areas.dbfawk,v 1.1 2012/03/02 20:26:50 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS state zone area polygon shapefiles
+# which are named z_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the STATE_ZONE code,
+# reformatted to match alert->title (e.g. KS033 is KS_Z033).
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="OFFICE:DIST_NO:DIST_NAME:STATE_CODE:STATE_NAME:TIME_ZONE:AAC:DISP_ORDER:NARR_FLAG:AAC_PARENT:SUB_FLAG:DESCRIPTN:SURF_FLAG:ROAD_FLAG";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="DIST_NAME:AAC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^AAC=(.*)$/ {key="$1"; next}
+/^DIST_NAME=(.*)$/ {name="$1"; next}
diff --git a/config/gfe_public_weather.dbfawk b/config/gfe_public_weather.dbfawk
new file mode 100644
index 0000000..4b85f77
--- /dev/null
+++ b/config/gfe_public_weather.dbfawk
@@ -0,0 +1,42 @@
+# $Id: gfe_public_weather.dbfawk,v 1.1 2012/03/02 20:26:50 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS state zone area polygon shapefiles
+# which are named z_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the STATE_ZONE code,
+# reformatted to match alert->title (e.g. KS033 is KS_Z033).
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="OFFICE:DIST_NO:DIST_NAME:STATE_CODE:STATE_NAME:TIME_ZONE:AAC:DISP_ORDER:NARR_FLAG:LEVEL:USE_GFDR:USE_FFDR:USE_SFDR:USE_HI_FDR:ALP_FLAG:SURF_FLAG:MW_AACS";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="DIST_NAME:AAC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^AAC=(.*)$/ {key="$1"; next}
+/^DIST_NAME=(.*)$/ {name="$1"; next}
diff --git a/config/gps_wpt.dbfawk b/config/gps_wpt.dbfawk
new file mode 100644
index 0000000..e72cf5f
--- /dev/null
+++ b/config/gps_wpt.dbfawk
@@ -0,0 +1,20 @@
+# $Id: gps_wpt.dbfawk,v 1.8 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map dbf data that accompanies a shapefile created
+# by the "Fetch GPS Waypoints" option of Xastir.
+#
+# It simply attaches the name of the waypoint to the displayed waypoint.
+#
+BEGIN{
+# identifies the signature we want to recognize
+ dbfinfo="name:commt:date";
+# and the fields we actually care about
+ dbffields="name";
+}
+# Executed at beginning of each record, reset defaults
+BEGIN_RECORD {key=""; lanes=1; color=3; name=""; filled=0; pattern=0; display_level=256; label_level=128; label_color=8; symbol="/. "}
+# Find the name, make sure it gets displayed along with the data.
+/^name=(.*)$/ {name="$1";}
+
diff --git a/config/language-Dutch.sys b/config/language-Dutch.sys
new file mode 100644
index 0000000..ecf1740
--- /dev/null
+++ b/config/language-Dutch.sys
@@ -0,0 +1,1372 @@
+# $Id: language-Dutch.sys,v 1.240 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# This is the Dutch Language file used for all the prompts in xastir
+#
+# Creator : Henk de Groot <pe1dnn at amsat.org >
+# Maintained by : The Xastir Group <xastir at xastir.org>
+# Last Modified : Apr 28 2001, Henk de Groot <pe1dnn at amsat.org>
+# Modified 1.0.3 : Oct 19 2001, Han Sytsma <h.l.sytsma at hetnet.nl>
+# Modified 1.0.4 : Nov 22 2001, Henk de Groot <pe1dnn at amsat.org>
+# Modified 1.0.4 : Nov 25 2001, Henk de Groot <pe1dnn at amsat.org>
+# Modified 1.0.6 : Dec 16 2001, Henk de Groot <pe1dnn at amsat.org>
+# Modified 1.0.7 : Aug 27 2002, Han Sytsma <h.l.sytsma at hetnet.nl>
+# Modified 1.1.4 : Apr 15 2003, Han Sytsma <h.l.sytsma at hetnet.nl>
+# Modified 1.1.4 : May 20 2003, Han Sytsma <h.l.sytsma at hetnet.nl>
+# Modified 1.3.2 : Jun 08 2004, Han Sytsma <h.l.sytsma at hetnet.nl>
+# Modified 1.3.x : Sept 1 2004, Han Sytsma <h.l.sytsma at hetnet.nl> / # Henk de Groot <pe1dnn at amsat.org>
+# Modified 1.4.2 : Feb 14 2005, Han Sytsma <h.l.sytsma at hetnet.nl>
+# Modified 1.7.0 : Oct 15 2005, Han Sytsma <h.l.sytsma at hetnet.nl>
+# Modified 1.8.0 : Jan 9 2006, Han Sytsma <h.l.sytsma at hetnet.nl>
+#
+# comment lines with pound signs in front are ignored
+# File format as follows:
+# Id (10 chars alpha numeric)|(String associated with id)|QuickKeys|#comment
+#
+# WARNING:
+# Some strings contain formatting commands like %s and %d, you should not
+# change these. Wrong format strings could produce a segfault!
+#
+# Main Menu
+MENUTB0001|Bestand|B|
+MENUTB0002|Schermen|S|
+MENUTB0004|Kaarten|K|
+MENUTB0005|Beeld|l|
+MENUTB0006|Berichten|r|
+MENUTB0010|Interfaces|f|
+MENUTB0009|Help|H|
+#
+# Menu "File"
+PULDNFI001|Instelling|I|
+PULDNFI002|Open Log Bestand|O|
+PULDNFI003|Test||
+PULDNFI004|Sluiten|S|
+PULDNFI007|Verander Debug Level|D|
+PULDNFI010|TNC Loggen|T|
+PULDNFI011|Net Loggen|N|
+PULDNFI012|IGate Loggen|G|
+PULDNFI013|WX Loggen|W|
+PULDNFI014|Activeer PNG Snapshots|A|
+PULDNFI015|Kaart Afdrukken|K|
+PULDNFI016|KML Snapshots||
+#
+# Menu "View"
+PULDNVI001|Bulletins|B|
+PULDNVI002|Ontvangen Packets|P|
+PULDNVI003|Mobiele Stations|M|
+PULDNVI004|Alle Stations|A|
+PULDNVI009|Lokale Stations|S|
+PULDNVI012|Laatste Stations|L|
+PULDNVI005|Weerstations|W|
+PULDNVI008|Eigen Weer Gegevens|E|
+PULDNVI007|Weer Waarschuwingen|W|
+PULDNVI011|Berichten Verkeer|V|
+PULDNVI013|Tijdsduur Aktief|U|
+PULDNVI014|Tijdsduur Programma Beschikbaar||
+PULDNVI015|GPS Status||
+PULDNVI016|ALOHA Statistieken||
+#
+# Menu "Configure"
+PULDNCF004|Station|t|
+PULDNCF001|Standaard|S|
+PULDNCF003|Tijdsinstelling|m|
+PULDNCF002|Coordinaten Aanduiding|C|
+PULDNCF006|Audio Alarm|A|
+PULDNCF007|Spraak|p|
+PULDNCF008|Instellingen nu bewaren!|I|
+# (Units see PULDNDP006)
+#
+# Menu "Maps"
+PULDNMP001|Kaart Kiezer|K|
+PULDNMP012|Ga naar Lokatie|G|
+PULDNMP014|Lokaliseer Kaart Functie|L|
+PULDNMP016|Disable Fast Zoom/Pan/Home||
+PULDNMP013|Zet alle kaarten uit|Z|
+PULDNMP002|Automatische Kaart Keuze|A|
+PULDNMP003|Kaart Graadlijnen|G|
+PULDNMP004|Kaart Niveaus||
+PULDNMP010|Kaartlabels||
+PULDNMP009|Kleur Gevulde Gebieden|K|
+PULDNMP007|Kaart WX Waarschuwing|W|
+PULDNMP005|Achtergrond Kleur|c|
+PULDNMP006|Station Tekst Stijl|S|
+PULDNMP026|Icon Omranding Stijl|O|
+PULDNMP011|Muis Menu|M|
+PULDNMP008|Kaart Intensiteit|I|
+PULDNMP020|Configureren Tigermap||
+PULDNMP021|Automatische Kaartkeuze - Zet Raster Kaarten Uit||
+PULDNMP022|Indexeer Kaarten bij het Starten||
+PULDNMP023|Index: Voeg nieuwe kaarten toe|n|
+PULDNMP024|Index: Herindexeer ALLE kaarten|H|
+PULDNMP025|Fonts||
+PULDNMP015|Xfont selectie||
+PULDNMP027|Download Kaarten opnieuw (niet uit cache)||
+PULDNMP028|Leeg de gehele kaarten cache!||
+PULDNMP029|Zoek Adres||
+PULDNMP030|Configureer USGS DRG||
+PULDNMP031|Zet kaart begrenzing aan||
+#
+#
+# PopUp "Configure Tigermap"
+MPUPTGR001|Raster|
+MPUPTGR002|Provincies||
+MPUPTGR003|Stads Labels||
+MPUPTGR004|Bevolkte Gebieden||
+MPUPTGR005|Grote wegen||
+MPUPTGR006|Straten||
+MPUPTGR007|Spoorwegen||
+MPUPTGR008|Staat Labels||
+MPUPTGR009|Snelwegen Labels||
+MPUPTGR010|VS Hoofdwegen Labels||
+MPUPTGR011|Hoofd wegen Labels||
+MPUPTGR012|Selecteer weer te geven items:||
+MPUPTGR013|Rivieren||
+MPUPTGR014|Meren||
+MPUPTGR015|Vliegvelden, Parken, enz||
+MPUPTGR016|Kaart Intensiteit||
+MPUPTGR017|Internet Kaarten Timeout (sec)||
+MPUPTGR018|Zet Tiger Kaarten aan||
+#
+# PopUp "Configureer USGS DRG"
+MPUPDRG001|Selecteer weer te geven items:||
+MPUPDRG002|Kleur onderliggende kaart (XOR)||
+MPUPDRG003|Zwart||
+MPUPDRG004|Wit||
+MPUPDRG005|Blauw||
+MPUPDRG006|Rood||
+MPUPDRG007|Bruin||
+MPUPDRG008|Groen||
+MPUPDRG009|Paars||
+MPUPDRG010|Geel||
+MPUPDRG011|Licht Blauw||
+MPUPDRG012|Licht Rood||
+MPUPDRG013|Licht Paars||
+MPUPDRG014|Licht Grijs||
+MPUPDRG015|Licht Bruin||
+#
+# PopUp "Kaart kiezer"
+WPUPMCP001|Kaart Kiezer||
+PULDNMMC01|Wis|N|
+PULDNMMC02|Vector|V|
+PULDNMMC03|250k Topogr.|2|
+PULDNMMC04|100k Topogr.|1|
+PULDNMMC05|24k Topogr.|4|
+PULDNMMC06|Vouw Dirs Uit|||
+PULDNMMC07|Dirs/Kaarten Geselecteerd:||
+PULDNMMC08|Maak Directories leeg|C|
+PULDNMMC09|Selecteer Alles|S|
+#
+# PullDown "Map Background Color"
+PULDNMBC01|Grijs||
+PULDNMBC02|Mistig Roze||
+PULDNMBC03|Marine Blauw||
+PULDNMBC04|Staal Blauw||
+PULDNMBC05|Zee Groen||
+PULDNMBC06|Pastel Groen||
+PULDNMBC07|Pastel Geel||
+PULDNMBC08|Goud Geel||
+PULDNMBC09|Roze Bruin||
+PULDNMBC10|Vuur Rood||
+PULDNMBC11|Wit||
+PULDNMBC12|Zwart||
+#
+# PullDown "Station text Style"
+PULDNMSL01|Zwarte Rand||
+PULDNMSL02|Zwarte Schaduw en gevulde achtergrond||
+PULDNMSL03|Tekst op Zwarte achtergond|T|
+#
+# PullDown "Icon Outline Style"
+PULDNMIO01|Geen Omranding|G|
+PULDNMIO02|Zwarte Omranding|Z|
+PULDNMIO03|Grijze Omranding|G|
+PULDNMIO04|Witte Omranding|W|
+#
+# Switches
+PULDNOT001|Aan||
+PULDNOT002|Uit||
+PULDNOT003|Kort||
+#
+# Menu "Display"
+PULDNDP014|Zoek station|Z|
+PULDNDP001|Volg station|V|
+PULDNDP022|Spoor downloaden|p|
+PULDNDP032|Filter gegevens||
+PULDNDP040|Deselecteer alles||
+PULDNDP041|Selecteer mijn||
+PULDNDP042|Selecteer TNC||
+PULDNDP027|- Selecteer directe stations||
+PULDNDP043|- Selecteer via digi||
+PULDNDP034|Selecteer net||
+PULDNDP019|Geef verlopen gegevens weer||
+PULDNDP044|Selecteer stations||
+PULDNDP028|- Selecteer vaste stations||
+PULDNDP029|- Selecteer bewegende stations||
+PULDNDP030|- Selecteer weer stations||
+PULDNDP053|- Selecteer CWOP WX stations||
+PULDNDP045|Selecteer Objecten/Items||
+PULDNDP026|- Selecteer weer Objecten/Items||
+PULDNDP039|- Selecteer water Hoogte Objecten/Items||
+PULDNDP031|- Selecteer andere Objecten/Items||
+PULDNDP033|Filter weergave||
+PULDNDP010|Roepnaam|R|
+PULDNDP012|Symbolen|y|
+PULDNDP011|- Draai symbolen|D|
+PULDNDP007|Station spoor|t|
+PULDNDP003|Koers|K|
+PULDNDP004|Snelheid|S|
+PULDNDP017|- Geef snelheid kort traject weer||
+PULDNDP002|Hoogte|H|
+PULDNDP009|Weer informatie|W|
+PULDNDP046|- Weer tekst||
+PULDNDP018|-- Geef alleen temperatuur weer||
+PULDNDP047|- Wind indicator||
+PULDNDP054|Geef Aloha cirkels weer||
+PULDNDP013|Zet stations nadering aan||
+PULDNDP008|Stations Vermogen/Winst|V|
+PULDNDP021|- Activeer standaard vermogen/winst||
+PULDNDP020|- Activeer mobiel vermogen/winst||
+PULDNDP023|Geef DF cirkels weer||
+PULDNDP123|Display DF Beamwidth||
+PULDNDP223|Display DF Bearing||
+PULDNDP035|Activeer berekening op geschatte waarden||
+PULDNDP036|- Geef boogsegment weer||
+PULDNDP037|- Geef richting weer||
+PULDNDP038|- Geef symbool weer||
+PULDNDP005|Afst/koers|A|
+PULDNDP024|Geeft tijd laatste rapport||
+PULDNDP015|Wis alle stations|W|
+PULDNDP016|Wis Alle sporen|S|
+PULDNDP025|Wis Object/Item geschiedenis||
+PULDNDP048|Herlaad Object/Item geschiedenis||
+PULDNDP049|Wis alle gemarkeerde bijnamen||
+PULDNDP050|Wis gemarkeerde bijnamen geschiedenis||
+PULDNDP051|Selecteer alleen gemarkeerde bijnamen||
+PULDNDP052|- Label route punten||
+PULDNDP055|Export all|E|
+PULDNDP056|Export to KML File||
+#
+# Units
+PULDNUT001|Engels||
+PULDNUT002|Metrisch||
+#
+# Menu "Messages"
+PULDNMG001|Zend Bericht Naar|Z|
+PULDNMG002|Open Groeps Bericht|O|
+PULDNMG003|Wis alle uitgaande berichten|W|
+PULDQUS001|Algemene Stations Aanvraag|G|
+PULDQUS002|IGate Stations Aanvraag|I|
+PULDQUS003|WX Stations Aanvraag|t|
+PULDNMG004|Automatisch Antwoord Bericht|A|
+PULDNMG005|Automatisch Beantwoorden|B|
+PULDNMG006|Sateliet Bevestigings Mode|M|
+PULDNMG007|Show Pending Messages|P|
+#
+# Menu "Interfaces"
+PULDNTNT04|Interface besturing||
+PULDNTNT03|Zet verzenden van alle data uit||
+PULDNTNT05|Zet verzenden positie uit||
+PULDNTNT06|Zet verzenden van objecten uit||
+PULDNTNT11|Zet server poort aan||
+PULDNTNT01|Zend nu!|Z|
+PULDNTNT07|Volg GPS spoor|F|
+PULDNTNT08|Volg GPS routes|R|
+PULDNTNT09|Volg GPS routepunten|W|
+PULDNTNT10|Laad Garmin RINO routepunten|G|
+#
+# Menu "Help"
+PULDNHEL01|Informatie|A|
+PULDNHEL02|Help Onderwerpen|I|
+PULDNHEL03|NOOD BAKEN BAKEN MODUS INSCHAKELEN|E|
+PULDNHEL04|!!! NOOD BAKEN MODUS !!!||
+PULDNHEL05|Over Xastir||
+#
+# Mouse Menu Popup
+POPUPMA001|Opties||
+POPUPMA00c|Centreer|C|
+POPUPMA015|Stations informatie|S|
+POPUPMA002|Zoom in|i|
+POPUPMA003|Zoom uit|u|
+POPUPMA004|Zoom niveau|n|
+POPUPMA005|Niveau 1|1|
+POPUPMA006|Niveau 16|6|
+POPUPMA007|Niveau 64|4|
+POPUPMA008|Niveau 256|2|
+POPUPMA009|Niveau 1024|0|
+POPUPMA010|Niveau 8192|8|
+POPUPMA017|Hele Wereld|H|
+POPUPMA016|Vorige pos/zoom|p|
+POPUPMA018|Plaats een Object|O|
+POPUPMA019|Verander een Object|V|
+POPUPMA025|Verplaats mijn station naar dit punt|H|
+POPUPMA011|Schuif Omhoog|c|
+POPUPMA012|Schuif Omlaag|h|
+POPUPMA013|Schuif naar Links|l|
+POPUPMA014|Schuif naar Rechts|r|
+POPUPMA020|Afstand meten||
+POPUPMA021|Verplaatsen||
+POPUPMA022|Volg me||
+POPUPMA023|Functie toetsen actief!||
+POPUPMA024|Schakel CapsLock/NumLock/ScrollLock/andere Toetsen UIT||
+POPUPMA026|Centreer & zoom||
+POPUPMA027|Breedtegraden||
+POPUPMA028| Lengtegraden||
+POPUPMA029|Teken CAD objecten||
+POPUPMA030|Draw||
+POPUPMA031|Sluit polygoon||
+POPUPMA032|Wis CAD polygonen||
+POPUPMA033|**NIET GEBRUIKT**||
+POPUPMA034|Handmatig Zoom Niveau||
+POPUPMA035|10% uit||
+POPUPMA036|10% in||
+POPUPMA037|Gebied||
+POPUPMA038|Vierkant||
+POPUPMA039|Vierkante voet||
+POPUPMA040|Vierkante meters||
+POPUPMA041|Richting||
+POPUPMA042|Graden||
+POPUPMA043|Pas meerduidige positie aan||# origineel ambigious mag ook meervoudige zijn?
+POPUPMA044|Positie meerduidigheid is aan, uw nieuwe positie kan verspringen.||# idem
+POPUPMA045|Voor gedefinierde objecten||
+POPUPMA046|CAD polygonen||
+POPUPMA047|Zet CAD objecten aan||
+POPUPMA048|Zet CAD labels aan||
+POPUPMA049|Zet CAD opemerkingen aan||
+POPUPMA050|Zet CAD waarschijnlijkheid aan||
+POPUPMA051|Zet CAD omgevingsgrootte aan||
+POPUPMA052|sq||
+POPUPMA053|ft||
+POPUPMA054|meters||
+POPUPMA055|mi|
+#
+# Status line labels
+BBARZM0001|Zoom %s||
+BBARZM0002|Zoom %s Tr||
+BBARSTH001|%d/%d Stations||
+BBARSTA000|%-9s Nieuw Object!||
+BBARSTA001|%-9s Nieuw station!||
+BBARSTA002|%-9s||# Nieuwe Gegevens (geeft alleen roepnaam weer)
+BBARSTA003|Kaarten Laden||
+BBARSTA004|Kaarten Geladen||
+BBARSTA005|Kaart Graadlijnen Aan||
+BBARSTA006|Kaart Graadlijnen Uit||
+BBARSTA007|Auto. Kaartkeuze is nu AAN||
+BBARSTA008|Auto. Kaartkeuze is nu UIT||
+BBARSTA009|Auto. Niveaukeuze is nu AAN||
+BBARSTA010|Auto. Niveaukeuze is nu UIT||
+BBARSTA011|Auto. Beantwoorden is UIT!||
+BBARSTA012|Bestand Gereed||
+BBARSTA013|GPS Poort Openen||
+BBARSTA014|GPS Poort Sluiten||
+BBARSTA015|Kreeg GPS RMC tekst||
+BBARSTA016|Kreeg GPS GGA tekst||
+BBARSTA017|Net verbinding naar host verbroken||
+BBARSTA018|Verbindingstijd netwerk verstreken!||
+BBARSTA019|Zoeken naar host %s||
+BBARSTA020|Verbonden met %s||
+BBARSTA021|Net verbinding mislukt!||
+BBARSTA022|Kon socket niet binden!||
+BBARSTA023|Geen IP voor host!||
+BBARSTA024|Geen host gespecificeerd||
+BBARSTA025|Host gevonden, Verbinding maken met %d||
+BBARSTA026|Wachten op GPS gegevens via HSP..||
+BBARSTA027|HSP vrijmaken, TNC gegevens ophalen..||
+BBARSTA028|%s wordt geladen||
+BBARSTA029|WX poort openen||
+BBARSTA030|WX poort sluiten||
+BBARSTA031|Zoeken naar hostnaam %d||
+BBARSTA032|WX gegevens gedecodeerd||
+BBARSTA033|Echo van de digipeater||
+BBARSTA034|Weer waarschuwings kaarten laden||
+BBARSTA035|Wachten op GPS gegevens via AUX..||
+BBARSTA036|HSP vrijmaken, TNC gegevens ophalen..||
+BBARSTA037|GPS tekst gedecodeerd||
+BBARSTA038|Positie verandering bij mijn station||
+BBARSTA039|Bezig met indexeren van: %s||
+BBARSTA040|Amateur APRS(tm) station %s||
+BBARSTA041|Wacht op GPS gegevens..||
+BBARSTA042|Uitzenden van objecten/items||
+BBARSTA043|Log bijwerken||
+BBARSTA044|ALOHA afstand is %d%s||
+BBARSTA045|Symbolen laden...||
+BBARSTA046|Opnieuw laden van symbolen...||
+BBARSTA047|Initialiseer mijn station...||
+BBARSTA048|Start interfaces...||
+BBARSTA049|Reading tiles...||
+BBARSTA050|Downloading tiles...||
+BBARSTA051|Downloading tile %li of %li||
+#
+# PopUp "View - Incoming Packet Data"
+WPUPDPD001|Ontvangen packets bekijken||
+WPUPDPD002|Alleen TNC gegevens||
+WPUPDPD003|Alleen Net gegevens||
+WPUPDPD004|TNC en Net gegevens||
+WPUPDPD005|TNC||
+WPUPDPD006|NET||
+WPUPDPD007|Station Capabilities||
+WPUPDPD008|Mine Only||
+#
+# PopUp "View - Find Station"
+WPUPLSP001|Lokaliseer station||
+WPUPLSP002|Lokaliseer roepnaam||
+WPUPLSP003|Hoofdlettergevoelig||
+WPUPLSP004|Zoek exact||
+WPUPLSP005|Lokaliseer nu!||
+WPUPLSP006|Spoed lokaliseren!||
+WPUPLSP007|FCC/RAC lokalisatie||
+#
+# PopUp "Configure - Defaults"
+WPUPCFD001|Standaardinstellingen aanpassen||
+WPUPCFD002|Na hoeveel tijd moet een station als oud beschouwd worden?||
+WPUPCFD003|15 Minuten||
+WPUPCFD004|30 Minuten||
+WPUPCFD005|45 Minuten||
+WPUPCFD006|1 Uur||
+WPUPCFD007|90 Minuten||
+WPUPCFD008|2 Uur||
+WPUPCFD009|Na hoeveel tijd moet een station van het scherm verwijderd worden?||
+WPUPCFD010|6 Uur||
+WPUPCFD011|12 Uur||
+WPUPCFD012|1 Dag||
+WPUPCFD013|2 Dagen||
+WPUPCFD014|1 Week||
+WPUPCFD015|Station Zend Opties||
+WPUPCFD016|Vast Station||
+WPUPCFD017|Mobiel Station m/lokale tijd||
+WPUPCFD018|Mobiel Station m/Zulu datum-tijd||
+WPUPCFD019|Mobiel Station m/Zulu tijd-secondes||
+WPUPCFD021|Stations Positie m/weer||
+WPUPCFD022|Stations Positie, Zulu datum-tijd en weer||
+WPUPCFD023|Verzend ruwe WX gegevens?||
+WPUPCFD024|Comprimeer Object/Item gegevens bij uitzenden?||
+WPUPCFD025|Activeer alternatief net?||
+WPUPCFD026|Met welk interval positie gegevens verzenden?||
+WPUPCFD027|Nieuwe berichten weergeven||
+WPUPCFD028|Waarschuw als speciale functie toetsen aanstaan||
+WPUPCFD029|Geef bulletins zonder afstand weer||
+WPUPCFD030|Zet positie duplicaat controle uit||
+WPUPCFD031|Laad voor gedefinierde objecten uit bestand||
+WPUPCFD032|My trails in one color||
+WPUPCFD033|ALTNET:||
+#
+# PopUp "Configure - Timing"
+WPUPCFTM01|Configureer tijdsinstelling|||
+WPUPCFTM02|Interval verzenden positie (min)||
+WPUPCFTM03|Tijd tot vervagen station (min)||
+WPUPCFTM04|Max interval verzenden Object/Item (min)||
+WPUPCFTM05|Tijd tot verdwijnen van kaart (uren)||
+WPUPCFTM06|GPS status controle interval (sec)||
+WPUPCFTM07|Tijd tot wissen station (dagen)||
+WPUPCFTM08|Timeout berekening geschatte waarden (min)||
+WPUPCFTM09|Seriele Inter-Char vertraging (ms)||
+WPUPCFTM10|Nieuwe volg tijd (min)||
+WPUPCFTM11|Nieuw volg Interval (graden)||
+WPUPCFTM12|RINO -> Objecten Interval (min), 0 = Uitgeschakeld||
+WPUPCFTM13|Snapshot Interval (min)||
+#
+# PopUp "Configure Coordinate System"
+WPUPCFC001|Configureer coordinaten stelsel||
+WPUPCFC002|Selecteer coordinaten weergave||
+WPUPCFC003|dd.dddddd|d|
+WPUPCFC004|dd mm.mmm|m|
+WPUPCFC005|dd mm ss.s|s|
+WPUPCFC006|UTM|U|
+WPUPCFC007|USNG/MGRS2||
+WPUPCFC008|UTM w/speciale zones||
+#
+# PopUp "Configure GPS"
+WPUPCFG001|GPS Instelling||
+WPUPCFG003|Eigen GPS poort||
+WPUPCFG002|Gebruik GPS positie?||
+WPUPCFG004|GPS opties||
+WPUPCFG005|Losse GPS||
+WPUPCFG006|Via TNC verbonden GPS (HSP Kabel)||
+WPUPCFG007|Via TNC verbonden GPS met gebruik van CTL-E||
+WPUPCFG008|GPS tijd (Lees elke)||
+WPUPCFG009|5 sec||
+WPUPCFG010|15 sec||
+WPUPCFG011|30 sec||
+WPUPCFG012|1 minuut||
+WPUPCFG013|2 minuten||
+WPUPCFG014|5 minuten||
+WPUPCFG015|10 minuten||
+WPUPCFG016|Via netwerk verbonden GPS||
+WPUPCFG017|GPSD Host||
+WPUPCFG018|GPSD Poort||
+WPUPCFG019|Netwerk GPS via GPSD||
+WPUPCFG020|Opnieuw verbinden na een fout?||
+WPUPCFG021|Via netwerk verbonden WX||
+WPUPCFG022|WX Host||
+WPUPCFG023|WX Poort||
+#
+# Configure TNC (baud/style are also for WX)
+WPUPCFT001|TNC instelling||
+WPUPCFT002|Gebruik TNC?||
+WPUPCFT003|TNC poort||
+WPUPCFT004|Poort instelling||
+WPUPCFT005|300 bps||
+WPUPCFT006|1200 bps||
+WPUPCFT007|2400 bps||
+WPUPCFT008|4800 bps||
+WPUPCFT009|9600 bps||
+WPUPCFT010|19200 bps||
+WPUPCFT011|UnProto paden||
+WPUPCFT012|Pad 1: %s via ||
+WPUPCFT013|Pad 2: %s via ||
+WPUPCFT014|Pad 3: %s via ||
+WPUPCFT015|Poort stijl||
+WPUPCFT016|8,N,1||
+WPUPCFT017|7,E,1||
+WPUPCFT018|7,O,1||
+WPUPCFT019|38400 bps||
+WPUPCFT020|57600 bps||
+WPUPCFT021|115200 bps||
+WPUPCFT022|230400 bps||
+WPUPCFT023|TNC instelling m/HSP GPS||
+WPUPCFT024|Data type||
+WPUPCFT025|Auto detectie||
+WPUPCFT026|Binair type||
+WPUPCFT027|ASCII type||
+WPUPCFT028|TNC instelling m/HSP GPS||
+WPUPCFT029|TNC instelling m/AUX GPS||
+WPUPCFT030|Configureer KISS TNC||
+WPUPCFT031|TNC configuratie bestanden||
+WPUPCFT032|Bestandsnaam activeren TNC||
+WPUPCFT033|Bestandsnaam deactiveren TNC||
+WPUPCFT034|KISS parameters||
+WPUPCFT035|TXDelay (10 ms stappen)||
+WPUPCFT036|Persistence (0 tot 255)||
+WPUPCFT037|SlotTime (10 ms stappen)||
+WPUPCFT038|TxTail (10 ms stappen)||
+WPUPCFT039|Vol Duplex||
+WPUPCFT040|Configureer Multi-Port KISS TNC||
+WPUPCFT041|Radio poort||
+WPUPCFT042|Twijfelachtige UNPROTO route!||
+WPUPCFT043|Gebruik liever een kortere route zoals WIDE2-2 of WIDE1-1,WIDE2-2||
+WPUPCFT044|Twijfelachtige IGATE route!||
+WPUPCFT045|Uitzenden met twijfelachtige UNPROTO route!||
+WPUPCFT046|Uitzenden met twijfelachtige IGATE route!||
+WPUPCFT047|Initialisser KISS-modus bij opstarten||
+#
+# PopUp "Configure WX Port"
+WPUPCFWX01|WX Poort instelling||
+WPUPCFWX02|Weerstation apparaat||
+WPUPCFWX03|Regenmeter correctie (globale instelling)||
+WPUPCFWX04|.1 inch/2.5mm||
+WPUPCFWX05|.01 inch/.25mm||
+WPUPCFWX06|.1mm||
+WPUPCFWX07|Geen correctie||
+#
+# PopUp "Configure - Station"
+WPUPCFS001|Stations Instelling||
+WPUPCFS002|Roepnaam||
+WPUPCFS003|Breedte graden||
+WPUPCFS004|gra||
+WPUPCFS005|min||
+WPUPCFS006|(N/S)||
+WPUPCFS007|Lengte graden||
+WPUPCFS008|(E/W)||
+WPUPCFS009|Station Symbool||
+WPUPCFS010|Groep/overlay||
+WPUPCFS011|Symbool||
+WPUPCFS028|Selecteer||
+WPUPCFS012|Vermogenswinst||
+WPUPCFS013|PHG uitschakelen||
+WPUPCFS014|Antenne winst||
+WPUPCFS015|Antenne versterking||
+WPUPCFS016|Omni||
+WPUPCFS017|Commentaar:||
+WPUPCFS018|Positie onzekerheid||
+WPUPCFS019|Geen||
+WPUPCFS020|.11 mijl omtrek||
+WPUPCFS021|1.15 mijl omtrek||
+WPUPCFS022|11.51 mijl omtrek||
+WPUPCFS023|69.09 mijl omtrek||
+WPUPCFS024|.18 kilometer omtrek||
+WPUPCFS025|1.85 kilometer omtrek||
+WPUPCFS026|18.53 kilometer omtrek||
+WPUPCFS027|111.19 kilometer omtrek||
+WPUPCFS029|Verstuur gecomprimeerde positie|C|
+#
+# PopUp "Object/Item"
+POPUPOB001|Object/Item||
+POPUPOB002|Naam||
+POPUPOB003|Plaats object||
+POPUPOB004|Verwijder object||
+POPUPOB005|Verander object||
+POPUPOB006|Maak een nieuw object||
+POPUPOB007|Oppervlakte object||
+POPUPOB008|Activeer oppervlakte object||
+POPUPOB009|Heldere kleur||
+POPUPOB010|Kleur-Vulling||
+POPUPOB011|Cirkel||
+POPUPOB012|Rechtse lijn '/'||
+POPUPOB013|Linkse lijn '\'||
+POPUPOB014|Driehoek||
+POPUPOB015|Rechthoek||
+POPUPOB016|Zwart||
+POPUPOB017|Blauw||
+POPUPOB018|Groen||
+POPUPOB019|Cyaan||
+POPUPOB020|Rood||
+POPUPOB021|Violet||
+POPUPOB022|Geel||
+POPUPOB023|Grijs||
+POPUPOB024|Offset omhoog:||
+POPUPOB025|Offset links (behalve '/'):||
+POPUPOB026|Doorgang:||
+POPUPOB027|Algemene Opties||
+POPUPOB028|Lokatie||
+POPUPOB029|Activeer markering||
+POPUPOB030|Gegevens:||
+POPUPOB031|Gemarkeerd object||
+POPUPOB032|Activeer compressie||
+POPUPOB033|Verwijder item||
+POPUPOB034|Wijzig item||
+POPUPOB035|Hoogte (voet):||
+POPUPOB036|Snelheid (knopen):||
+POPUPOB037|Richting:||
+POPUPOB038|DF object||
+POPUPOB039|Signaal - Hoogte(HAAT) - Versterking - Richting||
+POPUPOB040|Straal breedte - Richting||
+POPUPOB041|Rondstraler||
+POPUPOB042|Richtantenne||
+POPUPOB043|Onbruikbaar||
+POPUPOB044|Neem object over||
+POPUPOB045|Neem item over||
+POPUPOB046|DF richting:||
+POPUPOB047|Waarschijnlijkheids ringen||
+POPUPOB048|Kaartbeeld Object||
+POPUPOB049|Min (mi):||
+POPUPOB050|Max (mi):||
+#
+# PopUp "Configure Internet"
+WPUPCFI001|Internet Instelling||
+WPUPCFI002|Host ||
+WPUPCFI003|Poort ||
+WPUPCFI004|(Alternatieve hosts)||
+WPUPCFI005|Host1||
+WPUPCFI006|Poort1||
+WPUPCFI007|Host2||
+WPUPCFI008|Poort2||
+WPUPCFI009|Wachtwoord||
+WPUPCFI010|(Bij Geen Blanco Laten)||
+WPUPCFI011|Verbinding herstellen bij NET fout?||
+WPUPCFI012|Laten Werken als I-Gate?||
+WPUPCFI013|Bij I-Gate berichten verspreiden via TNC?||
+WPUPCFI014|I-Gate transacties loggen?|||
+WPUPCFI015|Filter parameters||
+#
+# PopUp "Configure Database"
+WPUPCFID01|Database Instelling (TBD)||
+WPUPCFID02|Host ||
+WPUPCFID03|Poort ||
+WPUPCFID04|(Alternatieve hosts)||
+WPUPCFID05|Host1||
+WPUPCFID06|Poort1||
+WPUPCFID07|Host2||
+WPUPCFID08|Poort2||
+WPUPCFID09|Wachtwoord||
+WPUPCFID10|(Bij Geen Blanco Laten)||
+WPUPCFID11|Verbinding herstellen bij NET fout?||
+WPUPCFID12|Laten werken als I-Gate?||
+WPUPCFID13|Bij I-Gate berichten verspreiden via TNC?||
+WPUPCFID14|I-Gate transacties loggen?|||
+WPUPCFID15|Filter parameters||
+#
+# PopUp "Configure AGWPE"
+WPUPCFIA01|Configureer AGWPE||
+WPUPCFIA02|Host ||
+WPUPCFIA03|Poort ||
+WPUPCFIA04|(Alternatieve hosts)||
+WPUPCFIA05|Host1||
+WPUPCFIA06|Poort1||
+WPUPCFIA07|Host2||
+WPUPCFIA08|Poort2||
+WPUPCFIA09|Wachtwoord||
+WPUPCFIA10|(Bij geen blanco laten)||
+WPUPCFIA11|Verbinding herstellen bij NET fout?||
+WPUPCFIA12|Laten werken als I-Gate?||
+WPUPCFIA13|Bij I-Gate berichten verspreiden via TNC?||
+WPUPCFIA14|I-Gate transacties loggen?||
+WPUPCFIA15|Zend op radio poort||
+#
+# PopUp "Configure Audio Alarms"
+WPUPCFA001|Audio alarm instellen||
+WPUPCFA002|Audio afspeel commando||
+WPUPCFA003|Alarm bij||
+WPUPCFA004|Audio bestand om af te spelen||
+WPUPCFA005|Nieuw Station||
+WPUPCFA006|Nieuw Bericht||
+WPUPCFA007|Nadering||
+WPUPCFA008|Band opening||
+WPUPCFA009|Minimale afstand||
+WPUPCFA010|Maximale afstand||
+WPUPCFA011|Weer waarschuwing||
+#
+# PopUp "Configure Speech"
+WPUPCFSP01|Spraak instellen||
+WPUPCFSP02|Uitvoer spraak bij:||
+WPUPCFSP03|Nieuw station||
+WPUPCFSP04|Waarschuwing nieuw bericht||
+WPUPCFSP05|Nieuwe bericht inhoud||
+WPUPCFSP06|Naderings waarschuwing||
+WPUPCFSP07|Band opening||
+WPUPCFSP08|Nieuwe weer waarschuwing||
+WPUPCFSP09|Naderings waarschuwing van gevolgd station||
+#
+# PopUp "Track Station"
+WPUPTSP001|Volg station||
+WPUPTSP002|Volg roepnaam||
+WPUPTSP003|Hoofdlettergevoelig||
+WPUPTSP004|Exact dit station||
+WPUPTSP005|Volg nu!||
+WPUPTSP006|Stop met volgen||
+WPUPTSP007|Download spoor||
+WPUPTSP008|Roepnaam||
+WPUPTSP009|Begin volgen (uren geleden)||
+WPUPTSP010|Volgduur (uren)||
+#
+# PopUp "Messages"
+WPUPMSB001|Stuur bericht, venster %d||
+WPUPMSB002|Stuur groeps bericht, venster %d||
+WPUPMSB003|Stations roepnaam:||
+WPUPMSB004|Groeps roepnaam:||
+WPUPMSB005|Nieuwe/Refresh roepnaam||
+WPUPMSB006|Nieuwe groep||
+WPUPMSB007|Wis bericht geschiedenis||
+WPUPMSB008|Bericht:||
+WPUPMSB009|Stuur nu!||
+WPUPMSB010|Pad:||
+WPUPMSB011|Breek alle openstaande berichten af||
+WPUPMSB012|Kick Timer||
+WPUPMSB013|seq||
+WPUPMSB014|type||
+WPUPMSB015|Zend uit||
+WPUPMSB016|*TIMEOUT*||
+WPUPMSB017|*AFGEBROKEN*||
+WPUPMSB018|*REJECTED*||
+WPUPMSB019|Change Path||
+WPUPMSB020|Use Default Path(s)||
+WPUPMSB021|Direct (No path)||
+WPUPMSB022|Reverse Path (Hint):||
+#
+# PopUp "Auto Reply"
+WPUPARM001|Automatich antwoord bericht||
+WPUPARM002|Antwoord:||
+#
+# PopUp "Help Index"
+WPUPHPI001|Help inhoud||
+WPUPHPI002|Bekijken||
+#
+# PopUp "Station Info"
+WPUPSTI000|Object van: %s||
+WPUPSTI001|Stations informatie||
+WPUPSTI002|Stuur bericht||
+WPUPSTI003|Doorzoek FCC databank||
+WPUPSTI004|Doorzoek RAC databank||
+WPUPSTI005|Packets ontvangen: %d Laatst Gehoord: ||
+WPUPSTI006|Gehoord via de TNC aan device %d, ||
+WPUPSTI007|Gehoord ||
+WPUPSTI008|laatste via lokaal||
+WPUPSTI009|laatste via TNC op device %d||
+WPUPSTI010|laatste via internet op device %d||
+WPUPSTI011|laatste via bestand||
+WPUPSTI012|laatste via onbekend||
+WPUPSTI013|, en is van positie veranderd||
+WPUPSTI014|Huidig Vermogen en Winst:||
+WPUPSTI016|Hoogte: %.0f%s ||
+WPUPSTI017|Richting: %s� ||
+WPUPSTI018|Snelheid: %.1fkm/h||
+WPUPSTI019|Snelheid: %.1fmph||
+WPUPSTI020|%0.1f Mijl||
+WPUPSTI021|%0.1f km||
+WPUPSTI022|Afstand vanaf mijn station %s, Koers vanaf mijn station %s||
+WPUPSTI023|Laatste positie ||
+WPUPSTI024|Weer Gegevens %c:%s||
+WPUPSTI025|Wind Richting: %s Snelheid: %03d km/h||
+WPUPSTI026|Wind Richting: %s Snelheid: %s mph||
+WPUPSTI027| Piek: %03d km/h||
+WPUPSTI028| Piek: %s mph||
+WPUPSTI029|Temperatuur: %02.1f�C ||
+WPUPSTI030|Temperatuur: %s�F ||
+WPUPSTI031|Vochigheid: %s%% ||
+WPUPSTI032|Gevoels temperatuur: %02.1f�C ||
+WPUPSTI033|Baro: %s hPa||
+WPUPSTI034|Sneeuw: %0.1f (cm/24h)||
+WPUPSTI035|Sneeuw: %0.0f (inch/24h)||
+WPUPSTI036|Regen: ||
+WPUPSTI037|%0.2f (mm/h) ||
+WPUPSTI038|%0.2f (inch/h) ||
+WPUPSTI039|%0.2f (mm/dag) ||
+WPUPSTI040|%0.2f (inch/dag) ||
+WPUPSTI041|%0.2f (mm/sinds middernacht)||
+WPUPSTI042|%0.2f (inch/sinds middernacht)||
+WPUPSTI043|Data pad: %s||
+WPUPSTI044|Commentaar %02d/%02d %02d:%02d : %s||
+WPUPSTI045|Wis spoor||
+WPUPSTI046|Totaal regen: ||
+WPUPSTI047|%0.2f (mm)||
+WPUPSTI048|%0.2f (inch)||
+WPUPSTI049|Vraag trace||
+WPUPSTI050|Vraag uitstaande berichten||
+WPUPSTI051|Vraag direkte stations||
+WPUPSTI052|Vraag versie||
+WPUPSTI053|Verander object||
+WPUPSTI054|Sla spoor op||
+WPUPSTI055|Echo vanaf:||
+WPUPSTI056|Zet automatisch bijwerken aan||
+WPUPSTI057|Omni-DF: %s||
+WPUPSTI058|DF richting: %s||
+WPUPSTI059|Status %02d/%02d %02d:%02d : %s||
+WPUPSTI060|Ontbrandings temp: %02.1f�C ||
+WPUPSTI061|Ontbrandings temp: %s�F ||
+WPUPSTI062|Vochtigheids gehalte in brandstof: %s%% ||
+WPUPSTI063|Baro: %0.2f in Hg||
+WPUPSTI064|Vraag NWS waarschuwing||
+WPUPSTI065|Gemarkeerde bijnaam: %s||
+WPUPSTI066|Geef station een bijnaam||
+WPUPSTI067|Huidig bereik: %d miles||
+WPUPSTI068|geen||
+WPUPSTI069|default||
+WPUPSTI070|HAAT||
+WPUPSTI071|omni||
+WPUPSTI072|bereik||
+WPUPSTI073|SLECHTE PHG||
+WPUPSTI074|SLECHTE SHG||
+WPUPSTI075|DF bereik||
+WPUPSTI076|Geen signaal gedetecteerd||
+WPUPSTI077|Detecteerbaar signaal (Wellicht)||
+WPUPSTI078|Detecteerbaar signaal maar niet bruikbaar)||
+WPUPSTI079|Zwak signaal, nauwelijks leesbaar||
+WPUPSTI080|Verruist maar bruikbaar signaal||
+WPUPSTI081|Enige ruis, goed bruikbaar signaal||
+WPUPSTI082|Goed signaal met enig waarneembare ruis||
+WPUPSTI083|Bijna ruisvrij siganal||
+WPUPSTI084|Volledig ruisvrij signaal||
+WPUPSTI085|Extreem sterk & volledig ruisvrij signaal||
+WPUPSTI086|VERKEERDE RICHTING||
+WPUPSTI087|SLECHTE NRQ||
+WPUPSTI088|DF openingshoek||
+WPUPSTI089|DF Lengte||
+WPUPSTI090|Ongeldig||
+WPUPSTI091|Verander volgspoor kleur||
+WPUPSTI092|Clear DF Bearing||
+#
+#
+# PopUp "ALOHA Statistics"
+WPUPALO001|ALOHA omtrek: %d %s||
+WPUPALO002|Stations binnen ALOHA omtrek: %d||
+WPUPALO003| Digis: %d||
+WPUPALO004| Mobiel (bewegend): %d||
+WPUPALO005| Mobiel (anders): %d||
+WPUPALO006| WX stations: %d||
+WPUPALO007| Vaste stations: %d||
+WPUPALO008|Laatst berekening %d %s %d %s geleden.||
+WPUPALO666|ALOHA omtrek nog niet berekend||
+#
+#
+# FCC-RAC Call Look up
+STIFCC0001|FCC databank doorzoeken||
+STIFCC0002|RAC databank doorzoeken||
+STIFCC0003|Naam:||
+STIFCC0004|Straat:||
+STIFCC0005|Plaats:||
+STIFCC0006|Staat:||
+STIFCC0007|Postcode:||
+STIFCC0008|Basis ||
+STIFCC0009|Geavanceerd ||
+STIFCC0010|5 wpm ||
+STIFCC0011|12 wpm ||
+#
+#
+# FCC-RAC Call Look up
+STIFCC0100|FCC index is oud, bezig met herindexeren||
+STIFCC0101|Zoeken roepnaam||
+STIFCC0102|Roepnaam niet gevonden!||
+STIFCC0103|RAC index is oud, bezig met herindexeren||
+#
+#
+# Band open message
+UMBNDO0001|op een afstand van||
+#
+# Universal Options
+UNIOP00001|OK||
+UNIOP00002|Annuleren||
+UNIOP00003|Sluiten||
+UNIOP00004|Mijlen||
+UNIOP00005|Km||
+UNIOP00006|Device||
+UNIOP00007|Toevoegen||
+UNIOP00008|Wissen||
+UNIOP00009|Eigenschappen||
+UNIOP00010|Uitzenden toestaan?||
+UNIOP00011|Activeren bij opstarten?||
+UNIOP00012|km/h||
+UNIOP00013|mph||
+UNIOP00014|C||
+UNIOP00015|F||
+UNIOP00016|mm||
+UNIOP00017|inch||
+UNIOP00018|mm/dag||
+UNIOP00019|inch/dag||
+UNIOP00020|mm/uur||
+UNIOP00021|inch/uur||
+UNIOP00022|mm/mid||
+UNIOP00023|inch/mid||
+UNIOP00024|graden||
+UNIOP00025|hPa||
+UNIOP00026|%||
+UNIOP00027|in Hg||
+UNIOP00028|mm Hg||
+UNIOP00029|Stel de systeem klok in vanuit GPS?||
+UNIOP00030|Digipeat?||
+UNIOP00031|m||
+UNIOP00032|Toepassen|||
+UNIOP00033|Reset||
+UNIOP00034|min||
+UNIOP00035|hr||
+UNIOP00036|day||
+UNIOP00037|Send Control-E to get GPS data?||
+UNIOP00038|Add Delay||
+#
+# PopUp "Station Chooser"
+STCHO00001|Station Kiezer||
+#
+# DISPLAY WX ALERT
+WPUPWXA001|Wx Waarschuwing||
+WPUPWXA002|Wx Waarschuwingen lijst||
+#
+# PopUp "Configure - Interfaces"
+WPUPCIF001|Geinstalleerde interfaces||
+WPUPCIF002|Kies interface type||
+#
+# PopUp "Configure AX.25 TNC"
+WPUPCAX001|Configureer AX.25 TNC||
+WPUPCAX002|AX.25 device naam||
+#
+# Interface device names
+IFDNL00000|Geen||
+IFDNL00001|Serieele TNC||
+IFDNL00002|Serieele TNC met GPS op een HSP kabel||
+IFDNL00003|Serieele GPS||
+IFDNL00004|Serieele WX||
+IFDNL00005|Internet server||
+IFDNL00006|AX25 TNC||
+IFDNL00007|Netwerk GPS (via gpsd)||
+IFDNL00008|Netwerk WX||
+IFDNL00009|Serieele TNC met GPS op een AUX kabel||
+IFDNL00010|Serieele KISS TNC||
+IFDNL00011|Database via netwerk (nog niet geimplementeerd)||
+IFDNL00012|AGWPE via Netwerk||
+IFDNL00013|Serieele Multi-Port KISS TNC||
+IFDNL00014|SQL Database (Experimental)||
+#
+# Interface device info
+IFDIN00000|%s %2d %s via serieel device %s %s||
+IFDIN00001|%s %2d %s verbonden met %s:%d %s||
+IFDIN00002|%s %2d %s gebruikt device genaamd %s %s||
+IFDIN00003|%s %2d %s %s %s %s||
+IFDIN00004|%s %2d %s %s %s:%d %s||
+IFDIN00005|%s %2d %s %s %s %s||
+IFDIN00006|INACTIEF ||
+IFDIN00007| ACTIEF ||
+IFDIN00008| FOUT ||
+IFDIN00009|ONBEKENDE||
+#
+# PopUp "Interface control"
+IFPUPCT000|Interface Besturing||
+IFPUPCT001|Start||
+IFPUPCT002|Stop||
+IFPUPCT003|Start Alle||
+IFPUPCT004|Stop Alle||
+#
+# IGate control
+IGPUPCF000|IGate Opties||
+IGPUPCF001|Schakel al het IGate verkeer uit||
+IGPUPCF002|Sta ALLEEN RF naar Inet verkeer toe||
+IGPUPCF003|Sta RF->Inet en Inet->RF verkeer toe||
+IGPUPCF004|IGate -> RF Path ||
+#
+# WX Station
+WXPUPSI000|WX station||
+WXPUPSI001|WX station type||
+WXPUPSI002|Huidige gegevens||
+WXPUPSI003|Wind koers||
+WXPUPSI004|Wind snelheid||
+WXPUPSI005|Wind piek||
+WXPUPSI006|Temp||
+WXPUPSI007|Regen totaal||
+WXPUPSI008|Regen dag totaal||
+WXPUPSI009|Baro||
+WXPUPSI010|Vochtigheid||
+WXPUPSI011|Peet Bros ULTIMETER 2000 Type (in gegevens logmode)||
+WXPUPSI012|Peet Bros ULTIMETER II Type||
+WXPUPSI013|Peet Bros ULTIMETER 2000 Type (in packet mode)||
+WXPUPSI014|Regen huidig uur tot.||
+WXPUPSI015|Regen laatste 24uur tot.||
+WXPUPSI016|Qualimetrics Q-Net||
+WXPUPSI017|Peet Bros ULTIMETER 2000 Type (complete mode)||
+WXPUPSI018|Dauw punt||
+WXPUPSI019|Wind piek||
+WXPUPSI020|Wind koude gevoel||
+WXPUPSI021|Warmte index||
+WXPUPSI022|3-Uur Baro||
+WXPUPSI023|Max Temp.||
+WXPUPSI024|Min Temp.||
+WXPUPSI025|Radio Shack WX-200/Oregon Scientific WM-918||
+WXPUPSI026|Davis Weather Monitor II/Wizard III/Vantage Pro||
+WXPUPSI027|LaCrosse WX-23xx||
+WXPUPSI028|Davis APRS Data Logger||
+#
+# Station Lists
+LHPUPNI000|Alle stations||
+LHPUPNI001|Mobiele stations||
+LHPUPNI002|Weer stations||
+LHPUPNI003|Lokale stations (via TNC)||
+LHPUPNI004|Laatste stations||
+LHPUPNI005|Objecten & Items||
+LHPUPNI006|Eigen Objecten & Items||
+LHPUPNI010|#||
+LHPUPNI011|Roepnaam||
+LHPUPNI012|#Comprimeer||
+LHPUPNI013|Pos Tijd||
+LHPUPNI014|Pad||
+LHPUPNI015|PHG||
+LHPUPNI016|Commentaar||
+LHPUPNI100|CSE||
+LHPUPNI101|SPD||
+LHPUPNI102|ALT.||
+LHPUPNI103|Breedte gr||
+LHPUPNI104|Lengte gr||
+LHPUPNI105|#Comprimeer||
+LHPUPNI106|LSV||
+LHPUPNI107|CFMS||
+LHPUPNI108|DFMS||
+LHPUPNI200|CSE||
+LHPUPNI201|SPD||
+LHPUPNI202|GST||
+LHPUPNI203|Temp||
+LHPUPNI204|Hum||
+LHPUPNI205|Baro||
+LHPUPNI206|RN-H||
+LHPUPNI207|RNSM||
+LHPUPNI208|RN24||
+LHPUPNI209|Breedte/Lengte of UTM||
+#
+# Maps WX Alert styles
+PULDNMAT01|Waarschuwings kaarten boven de andere||
+PULDNMAT02|Waarschuwings kaarten onder de andere||
+#
+# Error/popup messages
+POPEM00001|Lokaliseer fout!||
+POPEM00002|Station %s is niet gevonden!||
+POPEM00003|Spoor-volg fout!||
+POPEM00004|Interface fout!||
+POPEM00005|Ongeldige AX.25 poort naam %s||
+POPEM00006|Ongeldige AX.25 poort naam %s||
+POPEM00007|Ongeldige roepnaam %s||
+POPEM00008|Ongeldige AX.25 doeladres roepnaam of digipeater||
+POPEM00009|Kan AX.25 socket niet openen, %s||
+POPEM00010|Kan AX.25 socket niet binden, %s||
+POPEM00011|Kan geen verbinding met AX.25 roepnaam maken, %s||
+POPEM00012|AX.25 fout bij uitvoer van UI||
+POPEM00013|AX.25 probleem met axports bestand||
+POPEM00014|AX.25 ongeldige poort naam %s||
+POPEM00015|Fout bij het openen van interface %d hardware Fout||
+POPEM00016|Fout bij het openen interface %d Time Out||
+POPEM00017|Geen interfaces meer beschikbaar!||
+POPEM00018|Gegevens Aanvraag - Enkele Bericht Regel||
+POPEM00019|Verzenden is uit voor poort %d||
+POPEM00020|Database Fout!||
+POPEM00021|AX.25 ondersteunig is niet mee gecompileerd in deze Xastir Versie!||
+POPEM00022|Invoer Fout!||
+POPEM00023|Geen lokatie naam gegeven!||
+POPEM00024|Gegeven lokatie naam is in gebruik!||
+POPEM00025|Niet gevonden!||
+POPEM00026|Volgen begint op het moment van verschijnen||
+POPEM00027|Incorrecte gegevens. Zijn er velden leeg?||
+POPEM00028|Kan bestand niet openen||
+POPEM00029|Gevonden!||
+POPEM00030|Weer station symbool||
+POPEM00031|Veranderd in WX symbool '/_', andere opties: '\_' '/W' and '\W'||
+POPEM00032|Waarschuwing: gebruik nationaal weer service symbool!||
+POPEM00033|Geen GPS gegevens!||
+POPEM00034|Zet Mijn Positie TX uit totdat geldige GPS gegevens beschikbaar zijn!||
+POPEM00035|Waarschuwing||
+POPEM00036|Let op||
+POPEM00037|HSP interface aanwezig: GPS timing is verhoogd||
+POPEM00038|Naam komt overeen met bestaand Object/Item/Station||
+POPEM00039|Niet toegestane tekens gevonden, deze worden door punten vervangen||
+POPEM00040|Handmatig ingestelde uitgaande route is verloren gegaan||
+POPEM00041|Bezig met een ander bestand te bewerken. Wacht even en probeer opnieuw||
+POPEM00042|Niet een eigen object! Probeer het object eerst over te nemen.||
+POPEM00043|Geen Object/Item!||
+POPEM00044|Opzoeken in Findu database: Mislukt||
+POPEM00045|Opzoeken in Findu database: Gereed||
+POPEM00046|Berkeley DB headers en gedeelde bibliotheek komen niet overeen! Kaart cache uitgeschakeld.||
+POPEM00047|Global transmit is DISABLED. Emergency beacons are NOT going out!||
+POPEM00048|Emergency Beacon Mode!||
+POPEM00049|EMERGENCY BEACON MODE, transmitting every 60 seconds!||
+POPEM00050|Interfaces or posits/transmits DISABLED. Emergency beacons are NOT going out!||
+POPEM00051|Altnet is enabled (Configure->Defaults dialog)||
+POPEM00052|Callsign is EMPTY!||
+POPEM00053|Message is EMPTY!||
+POPEM00054|We're trying to talk to ourselves!||
+#
+# Jump Location
+JMLPO00001|Kaart lokatie||
+JMLPO00002|GA!||
+JMLPO00003|Nieuwe lokatie naam:||
+#
+# Bulletins
+BULMW00001|Bulletins||
+BULMW00002|Beperk reikwijdte tot (0, is geen limiet)||
+BULMW00003|Verander reikwijdte||
+#
+# All Message Traffic
+AMTMW00001|Alle berichten verkeer||
+AMTMW00002|Beperk reikwijdte tot (0, is geen limiet)||
+#
+# Speech Strings
+SPCHSTR001|kilometers||
+SPCHSTR002|meters||
+SPCHSTR003|mijl||
+SPCHSTR004|yards||
+SPCHSTR005|%s, afstand is %d %s.||
+SPCHSTR006|%s, afstand is %.1f %s.||
+SPCHSTR007|%s, afstand is %d %s %s %s.||
+SPCHSTR008|%s, afstand is %.1f %s %s %s.||
+SPCHSTR009|Nieuwe weer waarschuwing||
+SPCHSTR010|Nieuwe roepnaam||
+SPCHSTR011|Gehoord, D X, %s, op een afstand van %.1f %s||
+#
+#
+SPCHDIRN00|ten noorden van||
+SPCHDIRS00|ten zuiden van||
+SPCHDIRE00|ten oosten van||
+SPCHDIRW00|ten westen van||
+SPCHDIRNE0|ten noordoosten van||
+SPCHDIRNW0|ten noordwesten van||
+SPCHDIRSE0|ten zuidoosten van||
+SPCHDIRSW0|ten zuidwesten van||
+#
+# Symbol Selection Dialog
+SYMSEL0001|Selecteer symbool||
+SYMSEL0002|Primaire symbolen Databank||
+SYMSEL0003|Secondaire symbolen Databank||
+#
+# Print Properties Dialog
+PRINT0001|Print eigenschappen||
+PRINT0002|Papier formaat||
+PRINT0003|Draai beeld automatisch||
+PRINT0004|Draai beeld 90. CCW||
+PRINT0005|Pas schaal beeld automatisch aan||
+PRINT0006|Schaal:||
+PRINT0007|Forceer standaard witte achtergrondkleur||
+PRINT0008|Print in Zwart/Wit||
+PRINT0016|Inverteer kleuren||
+PRINT0009|Postscript resolutie:||
+PRINT0010|Voorbeeld||
+PRINT0011|Print naar bestand||
+PRINT0012|Bezig met printen naar bestand...||
+PRINT0013|Converteren naar postscript...||
+PRINT0014|Gereed met aanmaken print bestand||
+PRINT0015|Printer status||
+#
+# Print Properties Dialog
+PRINT1001|Direct to:||
+PRINT1002|Via Previewer:||
+#
+# Locate Feature Dialog
+FEATURE001|Naam:||
+FEATURE002|Provincie:||
+FEATURE003|Land:||
+FEATURE004|Kaart quadrant:||
+FEATURE005|Type:||
+FEATURE006|GNIS Bestand:||
+FEATURE007|Adres:||
+FEATURE008|City:||
+FEATURE009|Mark Destination||
+FEATURE010|Zip Code:||
+FEATURE011|Geocoding Bestand||
+#
+# Coordinate Calculator Dialog
+COORD001|Coordinaten berekening||
+COORD002|Bereken||
+COORD003|Bereken||
+COORD004|Wis||
+COORD005|UTM||
+COORD006|Breedtegraden of||
+COORD007|Lengtegraden of||
+COORD008|Zone||
+COORD009|UTM Oostelijk||
+COORD010|UTM Noordelijk||
+COORD011| Decimale graden: ||
+COORD012| Graden/Decimale minuten: ||
+COORD013| Graden/Minuten/Dec. seconden: ||
+COORD014| Universal Transverse Mercator: ||
+COORD015| Militair Referentie raster: ||
+COORD016| Maidenhead lokatie raster: ||
+COORD017| ** Sorry, uw invoer is niet herkend! **||
+COORD018| ** Gebruik een van onderstaande invoer formaten: **||
+#
+#
+# Smart Beaconing Dialog
+SMARTB001|Smart Beaconing||
+SMARTB002|Hoge Waarde (secs):||
+SMARTB003|Hoge Snelheid (mph):||
+SMARTB004|Hoge Snelheid (kph):||
+SMARTB005|Lage Waarde (mins):||
+SMARTB006|Lage Snelheid (mph):||
+SMARTB007|Lage Snelheid (kph):||
+SMARTB008|Minimale Draaiing (deg):||
+SMARTB009|Draai Hoek:||
+SMARTB010|Wacht Tijd (secs):||
+SMARTB011|Schakel SmartBeaconing in(tm)||
+#
+#
+#
+# Gamma Adjust Dialog
+GAMMA001|Stel Gamma Correctie bij||
+GAMMA002|Gamma Correctie||
+#
+#
+#
+# Map labels font Dialog
+MAPFONT001|Change Fonts||
+MAPFONT002|Fonts||
+MAPFONT003|Map Font Miniem||
+MAPFONT004|Map Font Klein||
+MAPFONT005|Map Font Gemiddeld||
+MAPFONT006|Map Font Groot||
+MAPFONT007|Map Font Enorm||
+MAPFONT008|Map Font Border||
+MAPFONT009|Menu Font||
+MAPFONT010|Station Font||
+MAPFONT011|ATV Font ID||
+#
+#
+#
+# Distance/Bearing on status line
+PULDNDB001|Afst/Richting Status||
+#
+#
+# GPS Transfer Operations
+GPS001|GPS overdracht||
+GPS002|Bestandsnaam||
+GPS003|Selecteer kleur||
+GPS004|Rood||
+GPS005|Groen||
+GPS006|Zwart||
+GPS007|Wit||
+GPS008|Oranje||
+GPS009|Blauw||
+GPS010|Geel||
+GPS011|Violet||
+#
+#
+# Map Properties Dialog
+MAPP001|Kaart eigenschappen||
+MAPP002|Max Min Kaart Teken USGS Auto||
+MAPP003|Zoom Zoom Laag Vulling DRG Kaart Path/Bestandsnaam||
+MAPP004|Verander Laag->||
+MAPP005|Vulling->||
+MAPP006|Ja||
+MAPP007|Nee||
+MAPP008|AutoKaart->||
+MAPP009|Max Zoom->||
+MAPP010|Min Zoom->||
+MAPP011|Auto||
+MAPP012|USGS DRG->||
+#
+#
+# Time Strings
+TIME001|Dag||
+TIME002|Dagen||
+TIME003|Uur||
+TIME004|Uren||
+TIME005|Minuut||
+TIME006|Minuten||
+TIME007|Seconde||
+TIME008|Secondes||
+#
+#
+# Map Caching
+CACHE001|Kaart in cache||
+CACHE002|Kaart uit cache laden||
+CACHE003|Kaart niet in cache gevonden...||
+#
+#
+# Map Screen Misc
+RANGE001|BEREIK SCHAAL||
+#
+#
+# GPS Status
+GPSS001|WAAS of PPS||
+GPSS002|DGPS||
+GPSS003|Geldig SPS||
+GPSS004|Ongeldig||
+GPSS005|Sats/beeld||
+GPSS006|Repareer||
+GPSS007|!GPS data is ouder dan 30 seconden!||
+GPSS008|Simulatie||
+GPSS009|Handmatig||
+GPSS010|Ingeschat op||
+GPSS011|Float RTK||
+GPSS012|RTK||
+#
+#
+# Popup cad_dialog to obtain CAD object data
+CADPUD001|Area Object||
+CADPUD002|Area Label:||
+CADPUD003|Opmerking:||
+CADPUD004|Waarschijnlijkheid (%):||
+CADPUD005|OK||
+CADPUD006|CAD Dialog||
+CADPUD007|Toon/Bewerk details||
+CADPUD008|Afbreken||
+CADPUD009|Wis CAD objecten?||
+CADPUD010|Wis alles||
+CADPUD011|Wis selectie||
+CADPUD012|Solid||
+CADPUD013|Dashed||
+CADPUD014|Double Dash||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA001|XASTIR Map of %s (upper left) to %s (lower right). UTM %d m grid, %s datum. ||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA002|XASTIR Map of %s (upper left) to %s %s (lower right). Lat/Long grid, %s datum.||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA003|XASTIR Map of %s (upper left) to %s (lower right). UTM zones, %s datum.||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST001|MySQL (lat/long)||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST002|Postgreql with Postgis||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST003|MySQL (spatial)||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA01|Xastir Simple Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA02|Xastir CAD Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA03|Xastir full Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA04|APRSWorld Schema||
diff --git a/config/language-ElmerFudd.sys b/config/language-ElmerFudd.sys
new file mode 100644
index 0000000..33470db
--- /dev/null
+++ b/config/language-ElmerFudd.sys
@@ -0,0 +1,1143 @@
+# language-ElmerFudd.sys, translated from language-English.sys
+# Please do not edit this derived file.
+MENUTB0001|Fiwe|F|
+MENUTB0002|View|V|
+MENUTB0004|Map|M|
+MENUTB0005|Station|S|
+MENUTB0006|Message|e|
+MENUTB0010|Intewface|I|
+MENUTB0009|Hewp|H|
+PULDNFI001|Configuwe|C|
+PULDNFI002|Open Wog Fiwe|O|
+PULDNFI003|Test|T|
+PULDNFI004|Exit|x|
+PULDNFI007|Change Debug Wevew|D|
+PULDNFI010|TNC Wogging||
+PULDNFI011|Net Wogging||
+PULDNFI012|IGate Wogging||
+PULDNFI013|WX Wogging||
+PULDNFI014|PNG Snapshots||
+PULDNFI015|Pwint|P|
+PULDNFI016|KMW Snapshots||
+PULDNVI001|Buwwetins|B|
+PULDNVI002|Incoming Data|I|
+PULDNVI003|Mobiwe Stations|M|
+PULDNVI004|Aww Stations|A|
+PULDNVI009|Wocaw Stations|S|
+PULDNVI012|Wast Stations|L|
+PULDNVI005|Weadew Stations|W|
+PULDNVI008|Own Weadew Data|D|
+PULDNVI007|Weadew Awewts|e|
+PULDNVI011|Message Twaffic|T|
+PULDNVI013|Uptime|U|
+PULDNVI014|Pwogwam Uptime||
+PULDNVI015|GPS Status||
+PULDNVI016|AWOHA Statistics||
+PULDNCF004|Station|S|
+PULDNCF001|Defauwts|D|
+PULDNCF003|Timing|T|
+PULDNCF002|Coowdinate System|o|
+PULDNCF006|Audio Awawms|A|
+PULDNCF007|Speech|p|
+PULDNCF008|Save Config Now!|C|
+PULDNMP001|Map Choosew|M|
+PULDNMP012|Map Dispway Bookmawks|B|
+PULDNMP014|Wocate Map Featuwe|F|
+PULDNMP016|Disabwe Fast Zoom/Pan/Home||
+PULDNMP013|Disabwe Aww Maps||
+PULDNMP002|Enabwe Auto Maps||
+PULDNMP003|Enabwe Map Gwid||
+PULDNMP004|Enabwe Map Wevews||
+PULDNMP010|Enabwe Map Wabews||
+PULDNMP009|Enabwe Awea Cowow Fiwws||
+PULDNMP007|Enabwe Weadew Awewts||
+PULDNMP005|Backgwound Cowow|C|
+PULDNMP006|Station Text Stywe|T|
+PULDNMP026|Icon Outwine Stywe|O|
+PULDNMP011|Mouse Pointew Menu|P|
+PULDNMP008|Map Intensity|I|
+PULDNMP020|Configuwe Tigewmap||
+PULDNMP021|Auto Map - Disabwe Wastew Maps||
+PULDNMP022|Index New Maps on Stawtup||
+PULDNMP023|Index: Add New Maps|N|
+PULDNMP024|Index: Weindex AWW Maps!|R|
+PULDNMP025|Fonts||
+PULDNMP015|Xfontsew||
+PULDNMP027|We-downwoad Maps (Not fwom cache)||
+PULDNMP028|Fwush Entiwe Map Cache!||
+PULDNMP029|Find Addwess||
+PULDNMP030|Configuwe USGS DWG||
+PULDNMP031|Enabwe Map Bowdew||
+MPUPTGR001|Gwid||
+MPUPTGR002|Counties||
+MPUPTGR003|City Wabews||
+MPUPTGR004|Uwban Aweas||
+MPUPTGR005|Majow Woads||
+MPUPTGR006|Stweets||
+MPUPTGR007|Waiwwoads||
+MPUPTGR008|State Wabews||
+MPUPTGR009|Intewstate Wabews||
+MPUPTGR010|US Hwy Wabews||
+MPUPTGR011|State Hwy Wabews||
+MPUPTGR012|Sewect items to be dispwayed:||
+MPUPTGR013|Wivews||
+MPUPTGR014|Wakes||
+MPUPTGR015|Aiwpowts, Pawks, etc||
+MPUPTGR016|Map Intensity||
+MPUPTGR017|Intewnet Map Timeout (sec)||
+MPUPTGR018|Enabwe Tigew Maps||
+MPUPDRG001|Sewect items to be dispwayed:||
+MPUPDRG002|Tint Undewwying Map (XOW)||
+MPUPDRG003|Bwack||
+MPUPDRG004|White||
+MPUPDRG005|Bwue||
+MPUPDRG006|Wed||
+MPUPDRG007|Bwown||
+MPUPDRG008|Gween||
+MPUPDRG009|Puwpwe||
+MPUPDRG010|Yewwow||
+MPUPDRG011|Wight Bwue||
+MPUPDRG012|Wight Wed||
+MPUPDRG013|Wight Puwpwe||
+MPUPDRG014|Wight Gway||
+MPUPDRG015|Wight Bwown||
+WPUPMCP001|Map Choosew||
+PULDNMMC01|Cweaw|C|
+PULDNMMC02|Vectow|V|
+PULDNMMC03|250k Topo|2|
+PULDNMMC04|100k Topo|1|
+PULDNMMC05|24k Topo|4|
+PULDNMMC06|Expand Diws||
+PULDNMMC07|Diws/Maps Sewected:||
+PULDNMMC08|Cweaw Diws|C
+PULDNMMC09|Sewect Aww|S|
+PULDNMBC01|Gway||
+PULDNMBC02|Misty Wose||
+PULDNMBC03|Navy Bwue||
+PULDNMBC04|Steew Bwue||
+PULDNMBC05|Med. Sea Gween||
+PULDNMBC06|Pawe Gween||
+PULDNMBC07|Pawe Gowdenwod||
+PULDNMBC08|Gowdenwod Yewwow||
+PULDNMBC09|Wosy Bwown||
+PULDNMBC10|Fiwe bwick Wed||
+PULDNMBC11|White||
+PULDNMBC12|Bwack||
+PULDNMSL01|Bwack Bowdew|B|
+PULDNMSL02|Bwack Shadow|S|
+PULDNMSL03|Text on Bwack|T|
+PULDNMIO01|No Outwine|N|
+PULDNMIO02|Bwack Outwine|B|
+PULDNMIO03|Gwey Outwine|G|
+PULDNMIO04|White Outwine|W|
+PULDNOT001|On||
+PULDNOT002|Off||
+PULDNOT003|Showt||
+PULDNDP014|Find Station|F|
+PULDNDP001|Twack Station|T|
+PULDNDP022|Fetch Findu Twaiw|u|
+PULDNDP032|Fiwtew Data||
+PULDNDP040|Sewect None||
+PULDNDP041|Sewect Mine||
+PULDNDP042|Sewect TNC||
+PULDNDP027|- Sewect Diwect||
+PULDNDP043|- Sewect Via Digi||
+PULDNDP034|Sewect Net||
+PULDNDP019|Incwude Expiwed Data||
+PULDNDP044|Sewect Stations||
+PULDNDP028|- Sewect Fixed Stations||
+PULDNDP029|- Sewect Moving Stations||
+PULDNDP030|- Sewect WX Stations||
+PULDNDP053| - Sewect CWOP WX Stations||
+PULDNDP045|Sewect Objects/Items||
+PULDNDP026|- Sewect WX Objects/Items||
+PULDNDP039|- Sewect Watew Gauge Objects/Items||
+PULDNDP031|- Sewect Odew Objects/Items||
+PULDNDP033|Fiwtew Dispway||
+PULDNDP010|Dispway Cawwsign||
+PULDNDP012|Dispway Symbow||
+PULDNDP011|- Wotate Symbow||
+PULDNDP007|Dispway Twaiw||
+PULDNDP003|Dispway Couwse||
+PULDNDP004|Dispway Speed|S|
+PULDNDP017|- Dispway Showt Speed||
+PULDNDP002|Dispway Awtitude||
+PULDNDP009|Dispway Weadew Info||
+PULDNDP046|- Dispway Weadew Text||
+PULDNDP018|-- Tempewatuwe Onwy||
+PULDNDP047|- Dispway Wind Bawb||
+PULDNDP054|Dispway Awoha Ciwcwe||
+PULDNDP013|Dispway Position Ambiguity||
+PULDNDP008|Dispway Powew/Gain||
+PULDNDP021|- Use Defauwt Powew/Gain||
+PULDNDP020|- Dispway Mobiwe Powew/Gain||
+PULDNDP023|Dispway DF Attwibutes||
+PULDNDP123|Dispway DF Beamwidf||
+PULDNDP223|Dispway DF Beawing||
+PULDNDP035|Enabwe Dead-Weckoning||
+PULDNDP036|- Dispway Awc||
+PULDNDP037|- Dispway Couwse||
+PULDNDP038|- Dispway Symbow||
+PULDNDP005|Dispway Dist/Beawing||
+PULDNDP024|Dispway Wast Wepowt Age||
+PULDNDP015|Cweaw Aww Stations!!!|A|
+PULDNDP016|Cweaw Aww Twaiws!!!|C|
+PULDNDP025|Cweaw Object/Item Histowy||
+PULDNDP048|Wewoad Object/Item Histowy||
+PULDNDP049|Cweaw Aww Tacticaw Cawws||
+PULDNDP050|Cweaw Tacticaw Caww Histowy||
+PULDNDP051|Sewect Tacticaw Cawws Onwy||
+PULDNDP052|- Wabew Twaiwpoints||
+PULDNDP055|Expowt aww|E|
+PULDNDP056|Expowt to KMW Fiwe||
+PULDNUT001|Enabwe Engwish Units|E|
+PULDNUT002|Metwic|M|
+PULDNMG001|Send Message To|S|
+PULDNMG002|Open Gwoup Messages|O|
+PULDNMG003|Cweaw Aww Outgoing Messages|C|
+PULDQUS001|Genewaw Stations Qwewy|G|
+PULDQUS002|IGate Stations Qwewy|I|
+PULDQUS003|WX Stations Qwewy|W|
+PULDNMG004|Modify Auto Wepwy Message|A|
+PULDNMG005|Enabwe Auto Wepwy Message||
+PULDNMG006|Satewwite Ack Mode|M|
+PULDNMG007|Show Pending Messages|P|
+PULDNTNT04|Intewface Contwow|C|
+PULDNTNT03|Disabwe Twansmit: AWW||
+PULDNTNT05|Disabwe Twansmit: My Position||
+PULDNTNT06|Disabwe Twansmit: Objects/Items||
+PULDNTNT11|Enabwe Sewvew Powts|P|
+PULDNTNT01|Twansmit Now!|T|
+PULDNTNT07|Fetch GPS Twack|F|
+PULDNTNT08|Fetch GPS Woutes|R|
+PULDNTNT09|Fetch GPS Waypoints|W|
+PULDNTNT10|Fetch Gawmin WINO Waypoints|G|
+PULDNHEL01|About|A|
+PULDNHEL02|Hewp Index|I|
+PULDNHEL03|EMEWGENCY BEACON MODE ENABWE|E|
+PULDNHEL04|!!! EMEWGENCY BEACON MODE !!!||
+PULDNHEL05|About Xastiw||
+POPUPMA001|Options||
+POPUPMA00c|Centew|C|
+POPUPMA015|Station Info|S|
+POPUPMA002|In|I|
+POPUPMA003|Out|O|
+POPUPMA004|Zoom Wevew|L|
+POPUPMA005|Wevew 1|1|
+POPUPMA006|Wevew 16|6|
+POPUPMA007|Wevew 64|4|
+POPUPMA008|Wevew 256|2|
+POPUPMA009|Wevew 1024|0|
+POPUPMA010|Wevew 8192|8|
+POPUPMA017|Entiwe Wowwd|E|
+POPUPMA016|Wast Map Pos/Zoom|P|
+POPUPMA018|Object/Item->Cweate|b|
+POPUPMA019|Object/Item->Modify|M|
+POPUPMA025|Move My Station Hewe|H|
+POPUPMA011|Pan up|u|
+POPUPMA012|Pan down|d|
+POPUPMA013|Pan weft|l|
+POPUPMA014|Pan wight|r|
+POPUPMA020|Measuwe||
+POPUPMA021|Move||
+POPUPMA022|TwackMe||
+POPUPMA023|Modifiews Found!||
+POPUPMA024|Pwease tuwn OFF CapsWock/NumWock/ScwowwWock/odew modifiews||
+POPUPMA026|Centew & Zoom||
+POPUPMA027| Watitude||
+POPUPMA028| Wongitude||
+POPUPMA029|Dwaw CAD Objects||
+POPUPMA030|Dwaw||
+POPUPMA031|Cwose Powygon||
+POPUPMA032|Ewase CAD Powygons||
+POPUPMA033|**NOT USED**||
+POPUPMA034|Custom Zoom Wevew||
+POPUPMA035|10% out||
+POPUPMA036|10% in||
+POPUPMA037|Awea||
+POPUPMA038|sqwawe||
+POPUPMA039|sqwawe feet||
+POPUPMA040|sqwawe metews||
+POPUPMA041|Beawing||
+POPUPMA042|degwees||
+POPUPMA043|Modify ambiguous position||
+POPUPMA044|Position ambiguity is on, youw new position may appeaw to jump.||
+POPUPMA045|Pwedefined Objects||
+POPUPMA046|CAD Powygons||
+POPUPMA047|Enabwe CAD objects||
+POPUPMA048|Enabwe CAD wabews||
+POPUPMA049|Enabwe CAD comments||
+POPUPMA050|Enabwe CAD pwobabiwity||
+POPUPMA051|Enabwe CAD awea size||
+POPUPMA052|sq||
+POPUPMA053|ft||
+POPUPMA054|metews||
+POPUPMA055|mi|
+BBARZM0001|Zoom %s||
+BBARZM0002|Zoom %s Tw||
+BBARSTH001|%d/%d Stations||
+BBARSTA000|%-9s New object!||
+BBARSTA001|%-9s New station!||
+BBARSTA002|%-9s||# new data (only display the call)
+BBARSTA003|Woading Maps...||
+BBARSTA004|Maps Woaded||
+BBARSTA005|Map Wat/Wong Gwid On|O|
+BBARSTA006|Map Wat/Wong Gwid Off|f|
+BBARSTA007|De use of Auto Maps, is now ON||
+BBARSTA008|De use of Auto Maps, is now OFF||
+BBARSTA009|De use of Map Wevews is now ON||
+BBARSTA010|De use of Map Wevews is now OFF||
+BBARSTA011|Auto Wepwy Message OFF!||
+BBARSTA012|Fiwe done..||
+BBARSTA013|Opening GPS Powt||
+BBARSTA014|Cwosing GPS Powt||
+BBARSTA015|Got GPS WMC Stwing||
+BBARSTA016|Got GPS GGA Stwing||
+BBARSTA017|Net disconnected fwom host||
+BBARSTA018|Net connection timed out!||
+BBARSTA019|Wooking up host %s||
+BBARSTA020|Connected to %s||
+BBARSTA021|Net Connection Faiwed!||
+BBARSTA022|Couwd not bind socket!||
+BBARSTA023|No IP fow Host!||
+BBARSTA024|No Host Specified||
+BBARSTA025|Host found, Connecting %d||
+BBARSTA026|Waiting fow GPS data via HSP..||
+BBARSTA027|Cweawing HSP getting TNC data..||
+BBARSTA028|Woading %s||
+BBARSTA029|Opening WX Powt||
+BBARSTA030|Cwosing WX Powt||
+BBARSTA031|Wooking up hostname %d||
+BBARSTA032|Decoded WX Data||
+BBARSTA033|Echo fwom digipeatew||
+BBARSTA034|Woading Weadew Awewt Maps||
+BBARSTA035|Waiting fow GPS data via AUX..||
+BBARSTA036|Cweawing AUX getting TNC data..||
+BBARSTA037|GPS Data Compwete||
+BBARSTA038|Position change on my station||
+BBARSTA039|Indexing %s||
+BBARSTA040|Amateuw APWS(tm) Station %s||
+BBARSTA041|Waiting fow GPS data..||
+BBARSTA042|Twansmitting objects/items||
+BBARSTA043|Wogging||
+BBARSTA044|AWOHA distance is %d%s||
+BBARSTA045|Woading symbows...||
+BBARSTA046|Wewoading symbows...||
+BBARSTA047|Initiawize my station, uh-hah-hah-hah...||
+BBARSTA048|Stawt intewfaces...||
+BBARSTA049|Weading tiwes...||
+BBARSTA050|Downwoading tiwes...||
+BBARSTA051|Downwoading tiwe %wi of %wi||
+WPUPDPD001|Dispway Packet Data||
+WPUPDPD002|TNC Data onwy|T|
+WPUPDPD003|Net Data onwy|N|
+WPUPDPD004|TNC and Net Data|a|
+WPUPDPD005|TNC||
+WPUPDPD006|NET||
+WPUPDPD007|Station Capabiwities||
+WPUPDPD008|Mine Onwy||
+WPUPLSP001|Wocate Station||
+WPUPLSP002|Wocate Cawwsign||
+WPUPLSP003|Match Case|C|
+WPUPLSP004|Match Exact|E|
+WPUPLSP005|Wocate Now!|N|
+WPUPLSP006|Emewgency Wocate!||
+WPUPLSP007|FCC/WAC Wookup||
+WPUPCFD001|Configuwe Defauwts||
+WPUPCFD002|Aftew what intewvaw of time wiww a station be considewed owd?||
+WPUPCFD003|15 min|1|
+WPUPCFD004|30 min|3|
+WPUPCFD005|45 min|4|
+WPUPCFD006|1 hw|H|
+WPUPCFD007|90 min|9|
+WPUPCFD008|2 hws|2|
+WPUPCFD009|Aftew what intewvaw of time wiww a station not be dispwayed?||
+WPUPCFD010|6 hws|6|
+WPUPCFD011|12 hws|o|
+WPUPCFD012|1 Day|D|
+WPUPCFD013|2 Days|y|
+WPUPCFD014|1 Week|W|
+WPUPCFD015|Twansmit Station Option||
+WPUPCFD016|Fixed Station|F|
+WPUPCFD017|Mobiwe Station w/wocaw time|l|
+WPUPCFD018|Mobiwe Station w/Zuwu date-time|Z|
+WPUPCFD019|Mobiwe Station w/Zuwu time-seconds|u|
+WPUPCFD021|Station Position w/weadew|S|
+WPUPCFD022|Station Position, Zuwu date-time, and weadew|t|
+WPUPCFD023|Twansmit Waw WX data?|R|
+WPUPCFD024|Twansmit compwessed objects/items?|C|
+WPUPCFD025|Activate Awtewnate net?|A|
+WPUPCFD026|Send position wepowts at what intewvaws?||
+WPUPCFD027|Pop up new buwwetins||
+WPUPCFD028|Wawn if Modifiew Keys||
+WPUPCFD029|View zewo-distance buwwetins||
+WPUPCFD030|Disabwe Posit Dupe-Checks||
+WPUPCFD031|Woad pwedefined objects fwom fiwe||
+WPUPCFD032|My twaiws in one cowow||
+WPUPCFD033|AWTNET:||
+WPUPCFTM01|Configuwe Timing||
+WPUPCFTM02|Posit TX Intewvaw (min)||
+WPUPCFTM03|Station Ghosting Time (min)||
+WPUPCFTM04|Object/Item Max TX Intewvaw (min)||
+WPUPCFTM05|Station Cweaw Time (houws)||
+WPUPCFTM06|GPS Check Intewvaw (sec)||
+WPUPCFTM07|Station Dewete Time (days)||
+WPUPCFTM08|Dead-Weckoning Timeout (min)||
+WPUPCFTM09|Sewiaw Intew-Chaw Deway (ms)||
+WPUPCFTM10|New Twack Time (min)||
+WPUPCFTM11|New Twack Intewvaw (degwees)||
+WPUPCFTM12|WINO -> Objects Intewvaw (min), 0 = Disabwed||
+WPUPCFTM13|Snapshot Intewvaw (min)||
+WPUPCFC001|Configuwe Coowdinate System||
+WPUPCFC002|Sewect Coowdinate System||
+WPUPCFC003|dd.ddddd|d|
+WPUPCFC004|dd mm.mmm|m|
+WPUPCFC005|dd mm ss.s|s|
+WPUPCFC006|UTM|U|
+WPUPCFC007|USNG/MGWS2||
+WPUPCFC008|UTM w/speciaw zones||
+WPUPCFG001|Configuwe GPS||
+WPUPCFG003|Stand awone GPS powt||
+WPUPCFG002|Use GPS Position?||
+WPUPCFG004|GPS Options||
+WPUPCFG005|Stand-awone GPS||
+WPUPCFG006|TNC Connected GPS (HSP Cabwe)||
+WPUPCFG007|TNC Connected GPS using CTW-E||
+WPUPCFG008|GPS Time (Sampwe evewy)||
+WPUPCFG009|5 sec||
+WPUPCFG010|15 sec||
+WPUPCFG011|30 sec||
+WPUPCFG012|1 min||
+WPUPCFG013|2 min||
+WPUPCFG014|5 min||
+WPUPCFG015|10 min||
+WPUPCFG016|Netwowk Connected GPS||
+WPUPCFG017|GPSD Host||
+WPUPCFG018|GPSD Powt||
+WPUPCFG019|Netwowk GPS via GPSD||
+WPUPCFG020|Weconnect on faiwuwe?||
+WPUPCFG021|Netwowk Connected WX||
+WPUPCFG022|WX Host||
+WPUPCFG023|WX Powt||
+WPUPCFT001|Configuwe TNC||
+WPUPCFT002|Use TNC?||
+WPUPCFT003|TNC Powt||
+WPUPCFT004|Powt Settings||
+WPUPCFT005|300 bps||
+WPUPCFT006|1200 bps||
+WPUPCFT007|2400 bps||
+WPUPCFT008|4800 bps||
+WPUPCFT009|9600 bps||
+WPUPCFT010|19200 bps||
+WPUPCFT011|UnPwoto Pads||
+WPUPCFT012|Paf 1: %s via ||
+WPUPCFT013|Paf 2: %s via ||
+WPUPCFT014|Paf 3: %s via ||
+WPUPCFT015|Powt Stywe||
+WPUPCFT016|8,N,1||
+WPUPCFT017|7,E,1||
+WPUPCFT018|7,O,1||
+WPUPCFT019|38400 bps||
+WPUPCFT020|57600 bps||
+WPUPCFT021|115200 bps||
+WPUPCFT022|230400 bps||
+WPUPCFT023|Configuwe TNC w/HSP GPS||
+WPUPCFT024|Data Type||
+WPUPCFT025|Auto detect||
+WPUPCFT026|Binawy Type||
+WPUPCFT027|ASCII Type||
+WPUPCFT028|Configuwe TNC w/AUX GPS||
+WPUPCFT029|Configuwe TNC w/INVAWID ENUM||
+WPUPCFT030|Configuwe KISS TNC||
+WPUPCFT031|TNC Configuwation Fiwes||
+WPUPCFT032|TNC Setup Fiwename||
+WPUPCFT033|TNC Shutdown Fiwename||
+WPUPCFT034|KISS Pawametews||
+WPUPCFT035|TXDeway (10 ms units)||
+WPUPCFT036|Pewsistence (0 to 255)||
+WPUPCFT037|SwotTime (10 ms units)||
+WPUPCFT038|TxTaiw (10 ms units)||
+WPUPCFT039|Fuww Dupwex||
+WPUPCFT040|Configuwe Muwti-Powt KISS TNC||
+WPUPCFT041|Wadio Powt||
+WPUPCFT042|Intewface Pwopewties: Dubious UNPWOTO Paf!||
+WPUPCFT043|Pwease considew a showtew paf such as WIDE2-2 ow WIDE1-1,WIDE2-2||
+WPUPCFT044|Intewface Pwopewties: Dubious IGATE Paf!||
+WPUPCFT045|Twansmitting w/Dubious UNPWOTO Paf!||
+WPUPCFT046|Twansmitting w/Dubious IGATE Paf!||
+WPUPCFT047|Init KISS-mode on stawtup||
+WPUPCFWX01|Configuwe WX Powt||
+WPUPCFWX02|Weadew Station device||
+WPUPCFWX03|Wain Gauge Cowwection (Gwobaw Setting)||
+WPUPCFWX04|.1 inch/2.5mm||
+WPUPCFWX05|.01 inch/.25mm||
+WPUPCFWX06|.1mm||
+WPUPCFWX07|No Cowwection||
+WPUPCFS001|Configuwe Station||
+WPUPCFS002|Cawwsign||
+WPUPCFS003|WAT||
+WPUPCFS004|deg||
+WPUPCFS005|min||
+WPUPCFS006|(N/S)||
+WPUPCFS007|WONG||
+WPUPCFS008|(E/W)||
+WPUPCFS009|Station Symbow||
+WPUPCFS010|Gwoup/ovewway||
+WPUPCFS011|Symbow||
+WPUPCFS028|Sewect||
+WPUPCFS012|Powew - Height (HAAT) - Gain - Diwectivity||
+WPUPCFS013|Disabwe PHG||
+WPUPCFS014|Antenna Height||
+WPUPCFS015|Antenna Gain||
+WPUPCFS016|Omni||
+WPUPCFS017|Comment:||
+WPUPCFS018|Position Ambiguity||
+WPUPCFS019|None||
+WPUPCFS020|.11 miwes||
+WPUPCFS021|1.15 miwes||
+WPUPCFS022|11.51 miwes||
+WPUPCFS023|69.09 miwes||
+WPUPCFS024|.18 kiwometwes||
+WPUPCFS025|1.85 kiwometwes||
+WPUPCFS026|18.53 kiwometwes||
+WPUPCFS027|111.19 kiwometwes||
+WPUPCFS029|Send compwessed posits|C|
+POPUPOB001|Object/Item||
+POPUPOB002|Name:||
+POPUPOB003|Cweate New Object||
+POPUPOB004|Dewete Object||
+POPUPOB005|Modify Object||
+POPUPOB006|Cweate New Item||
+POPUPOB007|Awea Object||
+POPUPOB008|Awea Object||
+POPUPOB009|Bwight Cowow||
+POPUPOB010|Cowow-Fiww||
+POPUPOB011|Ciwcwe||
+POPUPOB012|Wine-Wight '/'||
+POPUPOB013|Wine-Weft '\'||
+POPUPOB014|Twiangwe||
+POPUPOB015|Wectangwe||
+POPUPOB016|Bwack||
+POPUPOB017|Bwue||
+POPUPOB018|Gween||
+POPUPOB019|Cyan||
+POPUPOB020|Wed||
+POPUPOB021|Viowet||
+POPUPOB022|Yewwow||
+POPUPOB023|Gwey||
+POPUPOB024|Offset Up:||
+POPUPOB025|Offset Weft (Except '/'):||
+POPUPOB026|Cowwidow:||
+POPUPOB027|Genewic Options||
+POPUPOB028|Wocation||
+POPUPOB029|Signpost||
+POPUPOB030|Signpost Text||
+POPUPOB031|Signpost Object||
+POPUPOB032|Enabwe Compwession||
+POPUPOB033|Dewete Item||
+POPUPOB034|Modify Item||
+POPUPOB035|Awtitude (ft):||
+POPUPOB036|Speed (knots):||
+POPUPOB037|Couwse:||
+POPUPOB038|DF Object||
+POPUPOB039|Signaw - Height(HAAT) - Gain - Diwectivity||
+POPUPOB040|Beam Widf - Beawing||
+POPUPOB041|Omni Antenna||
+POPUPOB042|Beam Antenna||
+POPUPOB043|Usewess||
+POPUPOB044|Adopt Object||
+POPUPOB045|Adopt Item||
+POPUPOB046|DF Beawing:||
+POPUPOB047|Pwobabiwity Ciwcwes||
+POPUPOB048|Map View Object||
+POPUPOB049|Min (mi):||
+POPUPOB050|Max (mi):||
+WPUPCFI001|Configuwe Intewnet||
+WPUPCFI002|Host ||
+WPUPCFI003|Powt ||
+WPUPCFI004|(Secondawy hosts)||
+WPUPCFI005|Host1||
+WPUPCFI006|Powt1||
+WPUPCFI007|Host2||
+WPUPCFI008|Powt2||
+WPUPCFI009|Pass-code||
+WPUPCFI010|(Weave Bwank if None)||
+WPUPCFI011|Weconnect on NET faiwuwe?||
+WPUPCFI012|Wun as an I-Gate?||
+WPUPCFI013|Bwoadcast messages via TNC when an I-Gate?||
+WPUPCFI014|Wog I-Gate Twansactions?||
+WPUPCFI015|Fiwtew Pawametews||
+WPUPCFID01|Configuwe Database (TBD)||
+WPUPCFID02|Host ||
+WPUPCFID03|Powt ||
+WPUPCFID04|(Secondawy hosts)||
+WPUPCFID05|Host1||
+WPUPCFID06|Powt1||
+WPUPCFID07|Host2||
+WPUPCFID08|Powt2||
+WPUPCFID09|Pass-code||
+WPUPCFID10|(Weave Bwank if None)||
+WPUPCFID11|Weconnect on NET faiwuwe?||
+WPUPCFID12|Wun as an I-Gate?||
+WPUPCFID13|Bwoadcast messages via TNC when an I-Gate?||
+WPUPCFID14|Wog I-Gate Twansactions?||
+WPUPCFID15|Fiwtew Pawametews||
+WPUPCFIA01|Configuwe AGWPE||
+WPUPCFIA02|Host ||
+WPUPCFIA03|Powt ||
+WPUPCFIA04|(Secondawy hosts)||
+WPUPCFIA05|Host1||
+WPUPCFIA06|Powt1||
+WPUPCFIA07|Host2||
+WPUPCFIA08|Powt2||
+WPUPCFIA09|Pass-code||
+WPUPCFIA10|(Weave Bwank if None)||
+WPUPCFIA11|Weconnect on NET faiwuwe?||
+WPUPCFIA12|Wun as an I-Gate?||
+WPUPCFIA13|Bwoadcast messages via TNC when an I-Gate?||
+WPUPCFIA14|Wog I-Gate Twansactions?||
+WPUPCFIA15|Twansmit WadioPowt||
+WPUPCFA001|Configuwe Audio Awawms||
+WPUPCFA002|Audio Pway Command||
+WPUPCFA003|Awawm on||
+WPUPCFA004|Audio fiwe to Pway||
+WPUPCFA005|New Station||
+WPUPCFA006|New Message||
+WPUPCFA007|Pwoximity||
+WPUPCFA008|Band Opening||
+WPUPCFA009|Minimum Distance||
+WPUPCFA010|Maximum Distance||
+WPUPCFA011|Weadew Awewt||
+WPUPCFSP01|Configuwe Speech||
+WPUPCFSP02|Speech Output on:||
+WPUPCFSP03|New Station||
+WPUPCFSP04|New Message Awewt||
+WPUPCFSP05|New Message Body||
+WPUPCFSP06|Pwoximity Awewt||
+WPUPCFSP07|Band Opening||
+WPUPCFSP08|New Weadew Awewt||
+WPUPCFSP09|Twacked Station Pwoximity Awewt||
+WPUPTSP001|Twack Station||
+WPUPTSP002|Twack Cawwsign||
+WPUPTSP003|Match Case||
+WPUPTSP004|Match Exact||
+WPUPTSP005|Twack Now!||
+WPUPTSP006|Cweaw Twacking||
+WPUPTSP007|Downwoad Twaiw||
+WPUPTSP008|Cawwsign||
+WPUPTSP009|Stawt Twaiw (hws ago)||
+WPUPTSP010|Twaiw Wengf (hws)||
+WPUPMSB001|Send Message Box %d||
+WPUPMSB002|Send Gwoup Message Box %d||
+WPUPMSB003|Station's Caww:||
+WPUPMSB004|Gwoup's Caww:||
+WPUPMSB005|New/Wefwesh Caww||
+WPUPMSB006|New Gwoup||
+WPUPMSB007|Cweaw Msg Histowy||
+WPUPMSB008|Message:||
+WPUPMSB009|Send Now!||
+WPUPMSB010|Paf:||
+WPUPMSB011|Cancew Pending Msgs||
+WPUPMSB012|Kick Timew||
+WPUPMSB013|seq||
+WPUPMSB014|type||
+WPUPMSB015|Bwoadcast||
+WPUPMSB016|*TIMEOUT*||
+WPUPMSB017|*CANCEWWED*||
+WPUPMSB018|*WEJECTED*||
+WPUPMSB019|Change Paf||
+WPUPMSB020|Use Defauwt Paf(s)||
+WPUPMSB021|Diwect (No paf)||
+WPUPMSB022|Wevewse Paf (Hint):||
+WPUPARM001|Change Auto Wepwy||
+WPUPARM002|Wepwy:||
+WPUPHPI001|Hewp Index||
+WPUPHPI002|View||
+WPUPSTI000|Object fwom: %s||
+WPUPSTI001|Station Info||
+WPUPSTI002|Send Message||
+WPUPSTI003|Seawch FCC Database||
+WPUPSTI004|Seawch WAC Database||
+WPUPSTI005|Packets weceived: %d Wast Heawd: ||
+WPUPSTI006|Heawd via de TNC on device %d, ||
+WPUPSTI007|Heawd ||
+WPUPSTI008|wast via Wocaw||
+WPUPSTI009|wast via TNC on device %d||
+WPUPSTI010|wast via Intewnet on device %d||
+WPUPSTI011|wast via Fiwe||
+WPUPSTI012|wast via Unknown||
+WPUPSTI013|, and has moved||
+WPUPSTI014|Cuwwent Powew Gain:||
+WPUPSTI016|Awtitude: %.0f%s ||
+WPUPSTI017|Couwse: %s� ||
+WPUPSTI018|Speed: %.1f km/h||
+WPUPSTI019|Speed: %.1f mph||
+WPUPSTI020|%0.1f miwes||
+WPUPSTI021|%0.1f km||
+WPUPSTI022|Distance fwom my station: %s Beawing fwom my station: %s||
+WPUPSTI023|Wast Position: ||
+WPUPSTI024|Weadew Data %c:%s||
+WPUPSTI025|Wind Couwse: %s� Speed: %03d km/h||
+WPUPSTI026|Wind Couwse: %s� Speed: %s mph||
+WPUPSTI027| Gust: %03d km/h||
+WPUPSTI028| Gust: %s mph||
+WPUPSTI029|Tempewatuwe: %02.1f�C ||
+WPUPSTI030|Tempewatuwe: %s�F ||
+WPUPSTI031|Humidity: %s%% ||
+WPUPSTI032| Humidex: %02.1f�C ||
+WPUPSTI033|Bawo: %s hPa||
+WPUPSTI034|Snow: %0.1f (cm/24h)||
+WPUPSTI035|Snow: %0.0f (inch/24h)||
+WPUPSTI036|Wain: ||
+WPUPSTI037|%0.2f (mm/h) ||
+WPUPSTI038|%0.2f (inch/h) ||
+WPUPSTI039|%0.2f (mm/day) ||
+WPUPSTI040|%0.2f (inch/day) ||
+WPUPSTI041|%0.2f (mm/since midnight)||
+WPUPSTI042|%0.2f (inch/since midnight)||
+WPUPSTI043|Data paf: %s||
+WPUPSTI044|Comment %02d/%02d %02d:%02d : %s||
+WPUPSTI045|Cweaw Twack||
+WPUPSTI046|Totaw Wain: ||
+WPUPSTI047|%0.2f (mm)||
+WPUPSTI048|%0.2f (inch)||
+WPUPSTI049|Twace Qwewy||
+WPUPSTI050|Un-Acked Messages Qwewy||
+WPUPSTI051|Diwect Stations Qwewy||
+WPUPSTI052|Station Vewsion Qwewy||
+WPUPSTI053|Modify Object/Item||
+WPUPSTI054|Stowe Twack||
+WPUPSTI055|Echoed fwom:||
+WPUPSTI056|Enabwe Automatic Updates||
+WPUPSTI057|Omni-DF: %s||
+WPUPSTI058|DF Beawing: %s||
+WPUPSTI059|Status %02d/%02d %02d:%02d : %s||
+WPUPSTI060|Fuew Temp: %02.1f�C ||
+WPUPSTI061|Fuew Temp: %s�F ||
+WPUPSTI062|Fuew Moistuwe: %s%% ||
+WPUPSTI063|Bawo: %0.2f in Hg||
+WPUPSTI064|Fetch NWS Awewt||
+WPUPSTI065|Tacticaw Caww: %s||
+WPUPSTI066|Assign Tacticaw Caww||
+WPUPSTI067|Cuwwent Wange: %d miwes||
+WPUPSTI068|none||
+WPUPSTI069|defauwt||
+WPUPSTI070|HAAT||
+WPUPSTI071|omni||
+WPUPSTI072|wange||
+WPUPSTI073|BAD PHG||
+WPUPSTI074|BAD SHG||
+WPUPSTI075|DF Wange||
+WPUPSTI076|No signaw detected||
+WPUPSTI077|Detectibwe signaw (Maybe)||
+WPUPSTI078|Detectibwe signaw but not copyabwe)||
+WPUPSTI079|Weak signaw, mawginawwy weadabwe||
+WPUPSTI080|Noisy but copyabwe signaw||
+WPUPSTI081|Some noise, easy to copy signaw||
+WPUPSTI082|Good signaw w/detectibwe noise||
+WPUPSTI083|Neaw fuww-qwieting signaw||
+WPUPSTI084|Fuww-qwieting signaw||
+WPUPSTI085|Extwemewy stwong & fuww-qwieting signaw||
+WPUPSTI086|BAD BEAWING||
+WPUPSTI087|BAD NWQ||
+WPUPSTI088|DF Beamwidf||
+WPUPSTI089|DF Wengf||
+WPUPSTI090|Not Vawid||
+WPUPSTI091|Change Twaiw Cowow||
+WPUPSTI092|Cweaw DF Beawing||
+WPUPALO001|AWOHA wadius: %d %s||
+WPUPALO002|Stations inside AWOHA ciwcwe: %d||
+WPUPALO003| Digis: %d||
+WPUPALO004| Mobiwes (in motion): %d||
+WPUPALO005| Mobiwes (odew): %d||
+WPUPALO006| WX stations: %d||
+WPUPALO007| Home stations: %d||
+WPUPALO008|Wast cawcuwated %d %s %d %s ago.||
+WPUPALO666|AWOHA wadius not cawcuwated yet||
+STIFCC0001|FCC Database Wookup||
+STIFCC0002|WAC Database Wookup||
+STIFCC0003|Name:||
+STIFCC0004|Stweet:||
+STIFCC0005|City:||
+STIFCC0006|State:||
+STIFCC0007|Zip:||
+STIFCC0008|Basic ||
+STIFCC0009|Advanced ||
+STIFCC0010|5 wpm ||
+STIFCC0011|12 wpm ||
+STIFCC0100|FCC index owd, webuiwding||
+STIFCC0101|Cawwsign Seawch||
+STIFCC0102|Cawwsign Not Found!||
+STIFCC0103|WAC index owd, webuiwding||
+UMBNDO0001|at distance of||
+UNIOP00001|OK||
+UNIOP00002|Cancew||
+UNIOP00003|Cwose||
+UNIOP00004|miwes||
+UNIOP00005|km||
+UNIOP00006|Device||
+UNIOP00007|Add||
+UNIOP00008|Dewete||
+UNIOP00009|Pwopewties||
+UNIOP00010|Awwow Twansmitting?||
+UNIOP00011|Activate on Stawtup?||
+UNIOP00012|km/h||
+UNIOP00013|mph||
+UNIOP00014|�C||
+UNIOP00015|�F||
+UNIOP00016|mm||
+UNIOP00017|inch||
+UNIOP00018|mm/day||
+UNIOP00019|inch/day||
+UNIOP00020|mm/hw||
+UNIOP00021|inch/hw||
+UNIOP00022|mm/mid||
+UNIOP00023|inch/mid||
+UNIOP00024|deg||
+UNIOP00025|hPa||
+UNIOP00026|%||
+UNIOP00027|in Hg||
+UNIOP00028|mm Hg||
+UNIOP00029|Set System Cwock fwom GPS Data?||
+UNIOP00030|Digipeat?||
+UNIOP00031|m||
+UNIOP00032|Appwy||
+UNIOP00033|Weset||
+UNIOP00034|min||
+UNIOP00035|hw||
+UNIOP00036|day||
+UNIOP00037|Send Contwow-E to get GPS data?||
+UNIOP00038|Add Deway||
+STCHO00001|Station Choosew||
+WPUPWXA001|Wx Awewts||
+WPUPWXA002|Wx Awewt Wist||
+WPUPCIF001|Instawwed Intewfaces||
+WPUPCIF002|Choose Intewface Type||
+WPUPCAX001|Configuwe AX.25 TNC||
+WPUPCAX002|AX.25 Device name||
+IFDNL00000|None||
+IFDNL00001|Sewiaw TNC||
+IFDNL00002|Sewiaw TNC w/GPS on a HSP cabwe||
+IFDNL00003|Sewiaw GPS||
+IFDNL00004|Sewiaw WX||
+IFDNL00005|Intewnet Sewvew||
+IFDNL00006|AX25 TNC||
+IFDNL00007|Netwowked GPS (via gpsd)||
+IFDNL00008|Netwowked WX||
+IFDNL00009|Sewiaw TNC w/GPS on AUX powt||
+IFDNL00010|Sewiaw KISS TNC||
+IFDNL00011|Netwowked Database (Not Impwemented Yet)||
+IFDNL00012|Netwowked AGWPE||
+IFDNL00013|Sewiaw Muwti-Powt KISS TNC||
+IFDNL00014|SQW Database (Expewimentaw)||
+IFDIN00000|%s %2d %s %s %s||
+IFDIN00001|%s %2d %s %s:%d %s||
+IFDIN00002|%s %2d %s device %s %s||
+IFDIN00003|%s %2d %s %s %s %s||
+IFDIN00004|%s %2d %s %s %s:%d %s||
+IFDIN00005|%s %2d %s %s %s %s||
+IFDIN00006| DOWN ||
+IFDIN00007| UP ||
+IFDIN00008|EWWOW ||
+IFDIN00009|UNKNWN||
+IFPUPCT000|Intewface Contwow||
+IFPUPCT001|Stawt||
+IFPUPCT002|Stop||
+IFPUPCT003|Stawt Aww||
+IFPUPCT004|Stop Aww||
+IGPUPCF000|IGate Options||
+IGPUPCF001|Disabwe aww IGate twaffic||
+IGPUPCF002|Awwow WF to Inet twaffic ONWY||
+IGPUPCF003|Awwow WF->Inet and Inet->WF twaffic||
+IGPUPCF004|Igate -> WF Paf ||
+WXPUPSI000|WX Station||
+WXPUPSI001|WX Station Type||
+WXPUPSI002|Cuwwent Data||
+WXPUPSI003|Wind Couwse||
+WXPUPSI004|Wind Speed||
+WXPUPSI005|Wind Gust||
+WXPUPSI006|Temp||
+WXPUPSI007|Totaw Wain||
+WXPUPSI008|Today's Wain Totaw||
+WXPUPSI009|Bawo||
+WXPUPSI010|Humidity||
+WXPUPSI011|Peet Bwos UWTIMETEW 2000 Type (Data Wogging Mode)||
+WXPUPSI012|Peet Bwos UWTIMETEW II Type||
+WXPUPSI013|Peet Bwos UWTIMETEW 2000 Type (Packet Mode)||
+WXPUPSI014|Cuwwent HW Wain Tot.||
+WXPUPSI015|Wast 24 Wain Totaw||
+WXPUPSI016|Qwawimetwics Q-Net||
+WXPUPSI017|Peet Bwos UWTIMETEW 2000 Type (Compwete Mode)||
+WXPUPSI018|Dew Point||
+WXPUPSI019|High Wind||
+WXPUPSI020|Wind Chiww||
+WXPUPSI021|Heat Index||
+WXPUPSI022|3-Hw Bawo||
+WXPUPSI023|High Temp.||
+WXPUPSI024|Wow Temp.||
+WXPUPSI025|Wadio Shack WX-200/Owegon Scientific WM-918||
+WXPUPSI026|Davis Weadew Monitow II/Wizawd III/Vantage Pwo||
+WXPUPSI027|WaCwosse WX-23xx||
+WXPUPSI028|Davis APWS Data Woggew||
+LHPUPNI000|Aww Stations||
+LHPUPNI001|Mobiwe Stations||
+LHPUPNI002|Weadew Stations||
+LHPUPNI003|Wocaw Stations (via TNC)||
+LHPUPNI004|Wast Stations||
+LHPUPNI005|Objects & Items||
+LHPUPNI006|Own Objects & Items||
+LHPUPNI010|#||
+LHPUPNI011|Caww Sign||
+LHPUPNI012|#Pack||
+LHPUPNI013|Pos Time||
+LHPUPNI014|Paf||
+LHPUPNI015|PHG||
+LHPUPNI016|Comments||
+LHPUPNI100|CSE||
+LHPUPNI101|SPD||
+LHPUPNI102|AWT.||
+LHPUPNI103|Wat||
+LHPUPNI104|Wong||
+LHPUPNI105|#Pack||
+LHPUPNI106|WSV||
+LHPUPNI107|CFMS||
+LHPUPNI108|DFMS||
+LHPUPNI200|CSE||
+LHPUPNI201|SPD||
+LHPUPNI202|GST||
+LHPUPNI203|Temp||
+LHPUPNI204|Hum||
+LHPUPNI205|Bawo||
+LHPUPNI206|WN-H||
+LHPUPNI207|WNSM||
+LHPUPNI208|WN24||
+LHPUPNI209|Wat/Won ow UTM||
+PULDNMAT01|Show Awewt maps above odew maps||
+PULDNMAT02|Show Awewt maps undew odew maps||
+POPEM00001|Wocate Ewwow!||
+POPEM00002|Station %s was not found!||
+POPEM00003|Twacking Ewwow!||
+POPEM00004|Intewface Ewwow!||
+POPEM00005|Invawid AX.25 powt name %s||
+POPEM00006|Invawid AX.25 powt name %s||
+POPEM00007|Invawid cawwsign %s||
+POPEM00008|Invawid AX.25 destination cawwsign ow digipeatew||
+POPEM00009|Cannot open AX.25 socket, %s||
+POPEM00010|Cannot bind AX.25 socket, %s||
+POPEM00011|Cannot connect to AX.25 cawwsign, %s||
+POPEM00012|AX.25 ewwow on output of UI||
+POPEM00013|AX.25 pwobwem wif axpowts fiwe||
+POPEM00014|AX.25 invawid powt name %s||
+POPEM00015|Ewwow opening intewface %d Hawd Faiw||
+POPEM00016|Ewwow opening intewface %d Time Out||
+POPEM00017|No mowe intewfaces Avaiwabwe!||
+POPEM00018|Data Qwewy - Singwe Message Wine||
+POPEM00019|Powt twansmitting is off fow powt %d||
+POPEM00020|Database Ewwow!||
+POPEM00021|AX.25 suppowt not compiwed into Xastiw!||
+POPEM00022|Input Ewwow!||
+POPEM00023|No wocation name specified!||
+POPEM00024|Wocation name specified is in use!||
+POPEM00025|Not Found!||
+POPEM00026|Twacking wiww commence when it appeaws||
+POPEM00027|Impwopew info. Some fiewds empty?||
+POPEM00028|Can't open fiwe||
+POPEM00029|Found It!||
+POPEM00030|Weadew Station Symbow||
+POPEM00031|Changed to WX symbow '/_', odew options: '\_' '/W' and '\W'||
+POPEM00032|Wawning: Using Nationaw Weadew Sewvice Symbow!||
+POPEM00033|No GPS Data!||
+POPEM00034|Disabwing My Position TX Untiw Vawid GPS Data!||
+POPEM00035|Wawning||
+POPEM00036|Notice||
+POPEM00037|HSP intewface pwesent: GPS timing has been incweased||
+POPEM00038|Name Confwicts Wif Existing Object/Item/Station||
+POPEM00039|Iwwegaw chawactews found, substituting pewiods in deiw pwace||
+POPEM00040|Custom outgoing paf was wost||
+POPEM00041|Pwocessing anodew fiwe. Wait a bit, den twy again||
+POPEM00042|Object not owned by me! Twy adopting de object fiwst.||
+POPEM00043|Not an Object/Item!||
+POPEM00044|Fetch Findu Twaiw: Faiwed||
+POPEM00045|Fetch Findu Twaiw: Compwete||
+POPEM00046|Bewkewey DB headew/shawed wibwawy do NOT match! Disabwing map cache.||
+POPEM00047|Gwobaw twansmit is DISABWED. Emewgency beacons awe NOT going out!||
+POPEM00048|Emewgency Beacon Mode!||
+POPEM00049|EMEWGENCY BEACON MODE, twansmitting evewy 60 seconds!||
+POPEM00050|Intewfaces ow posits/twansmits DISABWED. Emewgency beacons awe NOT going out!||
+POPEM00051|Awtnet is enabwed (Configuwe->Defauwts diawog)||
+POPEM00052|Cawwsign is EMPTY!||
+POPEM00053|Message is EMPTY!||
+POPEM00054|We'we twying to tawk to ouwsewves!||
+JMLPO00001|Map Dispway Bookmawks||
+JMLPO00002|Activate!||
+JMLPO00003|New Name:||
+BULMW00001|Buwwetins||
+BULMW00002|Wimit Wange to (0, is no wimit)||
+BULMW00003|Change Wange||
+AMTMW00001|Aww Message Twaffic||
+AMTMW00002|Wimit Wange to (0, is no wimit)||
+SPCHSTR001|kiwometews||
+SPCHSTR002|metews||
+SPCHSTR003|miwes||
+SPCHSTR004|yawds||
+SPCHSTR005|%s, distance is %d %s.||
+SPCHSTR006|%s, distance is %.1f %s.||
+SPCHSTR007|%s, distance is %d %s %s %s.||
+SPCHSTR008|%s, distance is %.1f %s %s %s.||
+SPCHSTR009|New Weadew Awewt||
+SPCHSTR010|New Station||
+SPCHSTR011|Heawd, D X, %s, at distance of %.1f %s||
+SPCHDIRN00|nowf of||
+SPCHDIRS00|souf of||
+SPCHDIRE00|east of||
+SPCHDIRW00|west of||
+SPCHDIRNE0|nowdeast of||
+SPCHDIRNW0|nowdwest of||
+SPCHDIRSE0|soudeast of||
+SPCHDIRSW0|soudwest of||
+SYMSEL0001|Sewect Symbow||
+SYMSEL0002|Pwimawy Symbow Tabwe||
+SYMSEL0003|Secondawy Symbow Tabwe||
+PRINT0001|Pwint Pwopewties||
+PRINT0002|Papew Size||
+PRINT0003|Auto-Wotate Image||
+PRINT0004|Wotate Image 90� CCW||
+PRINT0005|Auto-Scawe Image||
+PRINT0006|Scawe:||
+PRINT0007|Fowce defauwt backgwound cowow to white||
+PRINT0008|Pwint in Bwack and White||
+PRINT0016|Wevewse Cowows||
+PRINT0009|Postscwipt Wesowution:||
+PRINT0010|Pweview||
+PRINT0011|Pwint to Fiwe||
+PRINT0012|Dumping image to fiwe...||
+PRINT0013|Convewting to Postscwipt...||
+PRINT0014|Finished cweating pwint fiwe||
+PRINT0015|Pwint Status||
+PRINT1001|Diwect to:||
+PRINT1002|Via Pweviewew:||
+FEATURE001|Name:||
+FEATURE002|State/Pwovince:||
+FEATURE003|County:||
+FEATURE004|Map Qwad:||
+FEATURE005|Type:||
+FEATURE006|GNIS Fiwe:||
+FEATURE007|Addwess:||
+FEATURE008|City:||
+FEATURE009|Mawk Destination||
+FEATURE010|Zip Code:||
+FEATURE011|Geocoding Fiwe||
+COORD001|Coowdinate Cawcuwatow||
+COORD002|Cawc||
+COORD003|Cawcuwate||
+COORD004|Cweaw||
+COORD005|UTM||
+COORD006|Watitude ow||
+COORD007|Wongitude ow||
+COORD008|Zone||
+COORD009|UTM Easting||
+COORD010|UTM Nowding||
+COORD011| Decimaw Degwees: ||
+COORD012| Degwees/Decimaw Minutes: ||
+COORD013| Degwees/Minutes/Dec. Seconds: ||
+COORD014| Univewsaw Twansvewse Mewcatow: ||
+COORD015|Miwitawy Gwid Wefewence System: ||
+COORD016| Maidenhead Gwid Wocatow: ||
+COORD017| ** Sowwy, youw input was not wecognized! **||
+COORD018| ** Pwease use one of de fowwowing input fowmats: **||
+SMARTB001|Smawt Beaconing||
+SMARTB002|High Wate (secs):||
+SMARTB003|High Speed (mph):||
+SMARTB004|High Speed (kph):||
+SMARTB005|Wow Wate (mins):||
+SMARTB006|Wow Speed (mph):||
+SMARTB007|Wow Speed (kph):||
+SMARTB008|Minimum Tuwn (deg):||
+SMARTB009|Tuwn Swope:||
+SMARTB010|Wait Time (secs):||
+SMARTB011|Enabwe SmawtBeaconing(tm)||
+GAMMA001|Adjust Gamma Cowwection||
+GAMMA002|Gamma Cowwection||
+MAPFONT001|Change Fonts||
+MAPFONT002|Fonts||
+MAPFONT003|Map Font Tiny||
+MAPFONT004|Map Font Smaww||
+MAPFONT005|Map Font Medium||
+MAPFONT006|Map Font Wawge||
+MAPFONT007|Map Font Huge||
+MAPFONT008|Map Font Bowdew||
+MAPFONT009|Menu Font||
+MAPFONT010|Station Font||
+MAPFONT011|ATV ID Font||
+PULDNDB001|Dist/Beawing Status||
+GPS001|GPS Twansfew||
+GPS002|Fiwename||
+GPS003|Sewect Cowow||
+GPS004|Wed||
+GPS005|Gween||
+GPS006|Bwack||
+GPS007|White||
+GPS008|Owange||
+GPS009|Bwue||
+GPS010|Yewwow||
+GPS011|Viowet||
+MAPP001|Map Pwopewties||
+MAPP002|Max Min Map USGS Auto||
+MAPP003|Zoom Zoom Wayew Fiww DWG Map Paf/Fiwename||
+MAPP004|Change Wayew->||
+MAPP005|Fiwwed->||
+MAPP006|Yes||
+MAPP007|No||
+MAPP008|Automaps->||
+MAPP009|Max Zoom->||
+MAPP010|Min Zoom->||
+MAPP011|Auto||
+MAPP012|USGS DWG->||
+TIME001|Day||
+TIME002|Days||
+TIME003|Houw||
+TIME004|Houws||
+TIME005|Minute||
+TIME006|Minutes||
+TIME007|Second||
+TIME008|Seconds||
+CACHE001|Map now cached||
+CACHE002|Woading Cached Map||
+CACHE003|Map not found in cache...||
+RANGE001|WANGE SCAWE||
+GPSS001|WAAS ow PPS||
+GPSS002|DGPS||
+GPSS003|Vawid SPS||
+GPSS004|Invawid||
+GPSS005|Sats/View||
+GPSS006|Fix||
+GPSS007|!GPS data is owdew dan 30 seconds!||
+GPSS008|Simuwation||
+GPSS009|Manuaw||
+GPSS010|Estimated||
+GPSS011|Fwoat WTK||
+GPSS012|WTK||
+CADPUD001|Awea Object||
+CADPUD002|Awea Wabew:||
+CADPUD003|Comment:||
+CADPUD004|Pwobabiwity (%):||
+CADPUD005|OK||
+CADPUD006|CAD Diawog||
+CADPUD007|Show/Edit Detaiws||
+CADPUD008|Cancew||
+CADPUD009|Dewete CAD objects?||
+CADPUD010|Dewete Aww||
+CADPUD011|Dewete Sewected||
+CADPUD012|Sowid||
+CADPUD013|Dashed||
+CADPUD014|Doubwe Dash||
+MDATA001|XASTIW Map of %s (uppew weft) to %s (wowew wight). UTM %d m gwid, %s datum. ||
+MDATA002|XASTIW Map of %s (uppew weft) to %s %s (wowew wight). Wat/Wong gwid, %s datum.||
+MDATA003|XASTIW Map of %s (uppew weft) to %s (wowew wight). UTM zones, %s datum.||
+XADBMST001|MySQW (wat/wong)||
+XADBMST002|Postgweqw wif Postgis||
+XADBMST003|MySQW (spatiaw)||
+XASCHEMA01|Xastiw Simpwe Schema||
+XASCHEMA02|Xastiw CAD Schema||
+XASCHEMA03|Xastiw fuww Schema||
+XASCHEMA04|APWSWowwd Schema||
diff --git a/config/language-English.sys b/config/language-English.sys
new file mode 100644
index 0000000..b7b3d5c
--- /dev/null
+++ b/config/language-English.sys
@@ -0,0 +1,1352 @@
+# $Id: language-English.sys,v 1.228 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# This is the English Language file used for all the prompts in xastir
+#
+# Creator : Frank Giannandrea <fgiannan at eazy.net >
+# Maintained by : The Xastir Group <xastir at xastir.org>
+#
+# comment lines with pound signs in front are ignored
+# File format as follows:
+# ID (10 chars alpha+numeric)|(String associated with id)|QuickKeys|#comment
+# The ID is a unique uppercase char string for each block followed by a nummer
+#
+# WARNING:
+# Some strings contain formatting commands like %s and %d, you should not
+# change these. Wrong format strings could produce a segfault!
+#
+# Main Menu
+MENUTB0001|File|F|
+MENUTB0002|View|V|
+MENUTB0004|Map|M|
+MENUTB0005|Station|S|
+MENUTB0006|Message|e|
+MENUTB0010|Interface|I|
+MENUTB0009|Help|H|
+#
+# Menu "File"
+PULDNFI001|Configure|C|
+PULDNFI002|Open Log File|O|
+PULDNFI003|Test|T|
+PULDNFI004|Exit|x|
+PULDNFI007|Change Debug Level|D|
+PULDNFI010|TNC Logging||
+PULDNFI011|Net Logging||
+PULDNFI012|IGate Logging||
+PULDNFI013|WX Logging||
+PULDNFI014|PNG Snapshots||
+PULDNFI015|Print|P|
+PULDNFI016|KML Snapshots||
+#
+# Menu "View"
+PULDNVI001|Bulletins|B|
+PULDNVI002|Incoming Data|I|
+PULDNVI003|Mobile Stations|M|
+PULDNVI004|All Stations|A|
+PULDNVI009|Local Stations|S|
+PULDNVI012|Last Stations|L|
+PULDNVI005|Weather Stations|W|
+PULDNVI008|Own Weather Data|D|
+PULDNVI007|Weather Alerts|e|
+PULDNVI011|Message Traffic|T|
+PULDNVI013|Uptime|U|
+PULDNVI014|Program Uptime||
+PULDNVI015|GPS Status||
+PULDNVI016|ALOHA Statistics||
+#
+# Menu "Configure"
+PULDNCF004|Station|S|
+PULDNCF001|Defaults|D|
+PULDNCF003|Timing|T|
+PULDNCF002|Coordinate System|o|
+PULDNCF006|Audio Alarms|A|
+PULDNCF007|Speech|p|
+PULDNCF008|Save Config Now!|C|
+# (Units see PULDNDP006)
+#
+# Menu "Maps"
+PULDNMP001|Map Chooser|M|
+PULDNMP012|Map Display Bookmarks|B|
+PULDNMP014|Locate Map Feature|F|
+PULDNMP016|Disable Fast Zoom/Pan/Home||
+PULDNMP013|Disable All Maps||
+PULDNMP002|Enable Auto Maps||
+PULDNMP003|Enable Map Grid||
+PULDNMP004|Enable Map Levels||
+PULDNMP010|Enable Map Labels||
+PULDNMP009|Enable Area Color Fills||
+PULDNMP007|Enable Weather Alerts||
+PULDNMP005|Background Color|C|
+PULDNMP006|Station Text Style|T|
+PULDNMP026|Icon Outline Style|O|
+PULDNMP011|Mouse Pointer Menu|P|
+PULDNMP008|Map Intensity|I|
+PULDNMP020|Configure Tigermap||
+PULDNMP021|Auto Map - Disable Raster Maps||
+PULDNMP022|Index New Maps on Startup||
+PULDNMP023|Index: Add New Maps|N|
+PULDNMP024|Index: Reindex ALL Maps!|R|
+PULDNMP025|Fonts||
+PULDNMP015|Xfontsel||
+PULDNMP027|Re-download Maps (Not from cache)||
+PULDNMP028|Flush Entire Map Cache!||
+PULDNMP029|Find Address||
+PULDNMP030|Configure USGS DRG||
+PULDNMP031|Enable Map Border||
+#
+# PopUp "Configure Tigermap"
+MPUPTGR001|Grid||
+MPUPTGR002|Counties||
+MPUPTGR003|City Labels||
+MPUPTGR004|Urban Areas||
+MPUPTGR005|Major Roads||
+MPUPTGR006|Streets||
+MPUPTGR007|Railroads||
+MPUPTGR008|State Labels||
+MPUPTGR009|Interstate Labels||
+MPUPTGR010|US Hwy Labels||
+MPUPTGR011|State Hwy Labels||
+MPUPTGR012|Select items to be displayed:||
+MPUPTGR013|Rivers||
+MPUPTGR014|Lakes||
+MPUPTGR015|Airports, Parks, etc||
+MPUPTGR016|Map Intensity||
+MPUPTGR017|Internet Map Timeout (sec)||
+MPUPTGR018|Enable Tiger Maps||
+#
+# PopUp "Configure USGS DRG"
+MPUPDRG001|Select items to be displayed:||
+MPUPDRG002|Tint Underlying Map (XOR)||
+MPUPDRG003|Black||
+MPUPDRG004|White||
+MPUPDRG005|Blue||
+MPUPDRG006|Red||
+MPUPDRG007|Brown||
+MPUPDRG008|Green||
+MPUPDRG009|Purple||
+MPUPDRG010|Yellow||
+MPUPDRG011|Light Blue||
+MPUPDRG012|Light Red||
+MPUPDRG013|Light Purple||
+MPUPDRG014|Light Gray||
+MPUPDRG015|Light Brown||
+#
+# PopUp "Map Chooser"
+WPUPMCP001|Map Chooser||
+PULDNMMC01|Clear|C|
+PULDNMMC02|Vector|V|
+PULDNMMC03|250k Topo|2|
+PULDNMMC04|100k Topo|1|
+PULDNMMC05|24k Topo|4|
+PULDNMMC06|Expand Dirs||
+PULDNMMC07|Dirs/Maps Selected:||
+PULDNMMC08|Clear Dirs|C
+PULDNMMC09|Select All|S|
+#
+# PullDown "Map Background Color"
+PULDNMBC01|Gray||
+PULDNMBC02|Misty Rose||
+PULDNMBC03|Navy Blue||
+PULDNMBC04|Steel Blue||
+PULDNMBC05|Med. Sea Green||
+PULDNMBC06|Pale Green||
+PULDNMBC07|Pale Goldenrod||
+PULDNMBC08|Goldenrod Yellow||
+PULDNMBC09|Rosy Brown||
+PULDNMBC10|Fire brick Red||
+PULDNMBC11|White||
+PULDNMBC12|Black||
+#
+# PullDown "Station text Style"
+PULDNMSL01|Black Border|B|
+PULDNMSL02|Black Shadow|S|
+PULDNMSL03|Text on Black|T|
+#
+# PullDown "Icon Outline Style"
+PULDNMIO01|No Outline|N|
+PULDNMIO02|Black Outline|B|
+PULDNMIO03|Grey Outline|G|
+PULDNMIO04|White Outline|W|
+#
+# Switches
+PULDNOT001|On||
+PULDNOT002|Off||
+PULDNOT003|Short||
+#
+# Menu "Stations"
+PULDNDP014|Find Station|F|
+PULDNDP001|Track Station|T|
+PULDNDP022|Fetch Findu Trail|u|
+PULDNDP032|Filter Data||
+PULDNDP040|Select None||
+PULDNDP041|Select Mine||
+PULDNDP042|Select TNC||
+PULDNDP027|- Select Direct||
+PULDNDP043|- Select Via Digi||
+PULDNDP034|Select Net||
+PULDNDP019|Include Expired Data||
+PULDNDP044|Select Stations||
+PULDNDP028|- Select Fixed Stations||
+PULDNDP029|- Select Moving Stations||
+PULDNDP030|- Select WX Stations||
+PULDNDP053| - Select CWOP WX Stations||
+PULDNDP045|Select Objects/Items||
+PULDNDP026|- Select WX Objects/Items||
+PULDNDP039|- Select Water Gauge Objects/Items||
+PULDNDP031|- Select Other Objects/Items||
+PULDNDP033|Filter Display||
+PULDNDP010|Display Callsign||
+PULDNDP012|Display Symbol||
+PULDNDP011|- Rotate Symbol||
+PULDNDP007|Display Trail||
+PULDNDP003|Display Course||
+PULDNDP004|Display Speed|S|
+PULDNDP017|- Display Short Speed||
+PULDNDP002|Display Altitude||
+PULDNDP009|Display Weather Info||
+PULDNDP046|- Display Weather Text||
+PULDNDP018|-- Temperature Only||
+PULDNDP047|- Display Wind Barb||
+PULDNDP054|Display Aloha Circle||
+PULDNDP013|Display Position Ambiguity||
+PULDNDP008|Display Power/Gain||
+PULDNDP021|- Use Default Power/Gain||
+PULDNDP020|- Display Mobile Power/Gain||
+PULDNDP023|Display DF Attributes||
+PULDNDP123|Display DF Beamwidth||
+PULDNDP223|Display DF Bearing||
+PULDNDP035|Enable Dead-Reckoning||
+PULDNDP036|- Display Arc||
+PULDNDP037|- Display Course||
+PULDNDP038|- Display Symbol||
+PULDNDP005|Display Dist/Bearing||
+PULDNDP024|Display Last Report Age||
+PULDNDP015|Clear All Stations!!!|A|
+PULDNDP016|Clear All Trails!!!|C|
+PULDNDP025|Clear Object/Item History||
+PULDNDP048|Reload Object/Item History||
+PULDNDP049|Clear All Tactical Calls||
+PULDNDP050|Clear Tactical Call History||
+PULDNDP051|Select Tactical Calls Only||
+PULDNDP052|- Label Trailpoints||
+PULDNDP055|Export all|E|
+PULDNDP056|Export to KML File||
+#
+# Units
+PULDNUT001|Enable English Units|E|
+PULDNUT002|Metric|M|
+#
+# Menu "Messages"
+PULDNMG001|Send Message To|S|
+PULDNMG002|Open Group Messages|O|
+PULDNMG003|Clear All Outgoing Messages|C|
+PULDQUS001|General Stations Query|G|
+PULDQUS002|IGate Stations Query|I|
+PULDQUS003|WX Stations Query|W|
+PULDNMG004|Modify Auto Reply Message|A|
+PULDNMG005|Enable Auto Reply Message||
+PULDNMG006|Satellite Ack Mode|M|
+PULDNMG007|Show Pending Messages|P|
+#
+# Menu "Interfaces"
+PULDNTNT04|Interface Control|C|
+PULDNTNT03|Disable Transmit: ALL||
+PULDNTNT05|Disable Transmit: My Position||
+PULDNTNT06|Disable Transmit: Objects/Items||
+PULDNTNT11|Enable Server Ports|P|
+PULDNTNT01|Transmit Now!|T|
+PULDNTNT07|Fetch GPS Track|F|
+PULDNTNT08|Fetch GPS Routes|R|
+PULDNTNT09|Fetch GPS Waypoints|W|
+PULDNTNT10|Fetch Garmin RINO Waypoints|G|
+#
+# Menu "Help"
+PULDNHEL01|About|A|
+PULDNHEL02|Help Index|I|
+PULDNHEL03|EMERGENCY BEACON MODE ENABLE|E|
+PULDNHEL04|!!! EMERGENCY BEACON MODE !!!||
+PULDNHEL05|About Xastir||
+#
+#
+# Mouse Menu Popup
+POPUPMA001|Options||
+POPUPMA00c|Center|C|
+POPUPMA015|Station Info|S|
+POPUPMA002|In|I|
+POPUPMA003|Out|O|
+POPUPMA004|Zoom Level|L|
+POPUPMA005|Level 1|1|
+POPUPMA006|Level 16|6|
+POPUPMA007|Level 64|4|
+POPUPMA008|Level 256|2|
+POPUPMA009|Level 1024|0|
+POPUPMA010|Level 8192|8|
+POPUPMA017|Entire World|E|
+POPUPMA016|Last Map Pos/Zoom|P|
+POPUPMA018|Object/Item->Create|b|
+POPUPMA019|Object/Item->Modify|M|
+POPUPMA025|Move My Station Here|H|
+POPUPMA011|Pan up|u|
+POPUPMA012|Pan down|d|
+POPUPMA013|Pan left|l|
+POPUPMA014|Pan right|r|
+POPUPMA020|Measure||
+POPUPMA021|Move||
+POPUPMA022|TrackMe||
+POPUPMA023|Modifiers Found!||
+POPUPMA024|Please turn OFF CapsLock/NumLock/ScrollLock/other modifiers||
+POPUPMA026|Center & Zoom||
+POPUPMA027| Latitude||
+POPUPMA028| Longitude||
+POPUPMA029|Draw CAD Objects||
+POPUPMA030|Draw||
+POPUPMA031|Close Polygon||
+POPUPMA032|Erase CAD Polygons||
+POPUPMA033|**NOT USED**||
+POPUPMA034|Custom Zoom Level||
+POPUPMA035|10% out||
+POPUPMA036|10% in||
+POPUPMA037|Area||
+POPUPMA038|square||
+POPUPMA039|square feet||
+POPUPMA040|square meters||
+POPUPMA041|Bearing||
+POPUPMA042|degrees||
+POPUPMA043|Modify ambiguous position||
+POPUPMA044|Position ambiguity is on, your new position may appear to jump.||
+POPUPMA045|Predefined Objects||
+POPUPMA046|CAD Polygons||
+POPUPMA047|Enable CAD objects||
+POPUPMA048|Enable CAD labels||
+POPUPMA049|Enable CAD comments||
+POPUPMA050|Enable CAD probability||
+POPUPMA051|Enable CAD area size||
+POPUPMA052|sq||
+POPUPMA053|ft||
+POPUPMA054|meters||
+POPUPMA055|mi|
+#
+#
+# Status line labels
+BBARZM0001|Zoom %s||
+BBARZM0002|Zoom %s Tr||
+BBARSTH001|%d/%d Stations||
+BBARSTA000|%-9s New object!||
+BBARSTA001|%-9s New station!||
+BBARSTA002|%-9s||# new data (only display the call)
+BBARSTA003|Loading Maps...||
+BBARSTA004|Maps Loaded||
+BBARSTA005|Map Lat/Long Grid On|O|
+BBARSTA006|Map Lat/Long Grid Off|f|
+BBARSTA007|The use of Auto Maps, is now ON||
+BBARSTA008|The use of Auto Maps, is now OFF||
+BBARSTA009|The use of Map Levels is now ON||
+BBARSTA010|The use of Map Levels is now OFF||
+BBARSTA011|Auto Reply Message OFF!||
+BBARSTA012|File done..||
+BBARSTA013|Opening GPS Port||
+BBARSTA014|Closing GPS Port||
+BBARSTA015|Got GPS RMC String||
+BBARSTA016|Got GPS GGA String||
+BBARSTA017|Net disconnected from host||
+BBARSTA018|Net connection timed out!||
+BBARSTA019|Looking up host %s||
+BBARSTA020|Connected to %s||
+BBARSTA021|Net Connection Failed!||
+BBARSTA022|Could not bind socket!||
+BBARSTA023|No IP for Host!||
+BBARSTA024|No Host Specified||
+BBARSTA025|Host found, Connecting %d||
+BBARSTA026|Waiting for GPS data via HSP..||
+BBARSTA027|Clearing HSP getting TNC data..||
+BBARSTA028|Loading %s||
+BBARSTA029|Opening WX Port||
+BBARSTA030|Closing WX Port||
+BBARSTA031|Looking up hostname %d||
+BBARSTA032|Decoded WX Data||
+BBARSTA033|Echo from digipeater||
+BBARSTA034|Loading Weather Alert Maps||
+BBARSTA035|Waiting for GPS data via AUX..||
+BBARSTA036|Clearing AUX getting TNC data..||
+BBARSTA037|GPS Data Complete||
+BBARSTA038|Position change on my station||
+BBARSTA039|Indexing %s||
+BBARSTA040|Amateur APRS(tm) Station %s||
+BBARSTA041|Waiting for GPS data..||
+BBARSTA042|Transmitting objects/items||
+BBARSTA043|Logging||
+BBARSTA044|ALOHA distance is %d%s||
+BBARSTA045|Loading symbols...||
+BBARSTA046|Reloading symbols...||
+BBARSTA047|Initialize my station...||
+BBARSTA048|Start interfaces...||
+BBARSTA049|Reading tiles...||
+BBARSTA050|Downloading tiles...||
+BBARSTA051|Downloading tile %li of %li||
+#
+#
+# PopUp "View - Incoming Packet Data"
+WPUPDPD001|Display Packet Data||
+WPUPDPD002|TNC Data only|T|
+WPUPDPD003|Net Data only|N|
+WPUPDPD004|TNC and Net Data|a|
+WPUPDPD005|TNC||
+WPUPDPD006|NET||
+WPUPDPD007|Station Capabilities||
+WPUPDPD008|Mine Only||
+#
+# PopUp "View - Find Station"
+WPUPLSP001|Locate Station||
+WPUPLSP002|Locate Callsign||
+WPUPLSP003|Match Case|C|
+WPUPLSP004|Match Exact|E|
+WPUPLSP005|Locate Now!|N|
+WPUPLSP006|Emergency Locate!||
+WPUPLSP007|FCC/RAC Lookup||
+#
+# PopUp "Configure - Defaults"
+WPUPCFD001|Configure Defaults||
+WPUPCFD002|After what interval of time will a station be considered old?||
+WPUPCFD003|15 min|1|
+WPUPCFD004|30 min|3|
+WPUPCFD005|45 min|4|
+WPUPCFD006|1 hr|H|
+WPUPCFD007|90 min|9|
+WPUPCFD008|2 hrs|2|
+WPUPCFD009|After what interval of time will a station not be displayed?||
+WPUPCFD010|6 hrs|6|
+WPUPCFD011|12 hrs|o|
+WPUPCFD012|1 Day|D|
+WPUPCFD013|2 Days|y|
+WPUPCFD014|1 Week|W|
+WPUPCFD015|Transmit Station Option||
+WPUPCFD016|Fixed Station|F|
+WPUPCFD017|Mobile Station w/local time|l|
+WPUPCFD018|Mobile Station w/Zulu date-time|Z|
+WPUPCFD019|Mobile Station w/Zulu time-seconds|u|
+WPUPCFD021|Station Position w/weather|S|
+WPUPCFD022|Station Position, Zulu date-time, and weather|t|
+WPUPCFD023|Transmit Raw WX data?|R|
+WPUPCFD024|Transmit compressed objects/items?|C|
+WPUPCFD025|Activate Alternate net?|A|
+WPUPCFD026|Send position reports at what intervals?||
+WPUPCFD027|Pop up new bulletins||
+WPUPCFD028|Warn if Modifier Keys||
+WPUPCFD029|View zero-distance bulletins||
+WPUPCFD030|Disable Posit Dupe-Checks||
+WPUPCFD031|Load predefined objects from file||
+WPUPCFD032|My trails in one color||
+WPUPCFD033|ALTNET:||
+#
+# PopUp "Configure - Timing"
+WPUPCFTM01|Configure Timing||
+WPUPCFTM02|Posit TX Interval (min)||
+WPUPCFTM03|Station Ghosting Time (min)||
+WPUPCFTM04|Object/Item Max TX Interval (min)||
+WPUPCFTM05|Station Clear Time (hours)||
+WPUPCFTM06|GPS Check Interval (sec)||
+WPUPCFTM07|Station Delete Time (days)||
+WPUPCFTM08|Dead-Reckoning Timeout (min)||
+WPUPCFTM09|Serial Inter-Char Delay (ms)||
+WPUPCFTM10|New Track Time (min)||
+WPUPCFTM11|New Track Interval (degrees)||
+WPUPCFTM12|RINO -> Objects Interval (min), 0 = Disabled||
+WPUPCFTM13|Snapshot Interval (min)||
+#
+# PopUp "Configure Coordinate System"
+WPUPCFC001|Configure Coordinate System||
+WPUPCFC002|Select Coordinate System||
+WPUPCFC003|dd.ddddd|d|
+WPUPCFC004|dd mm.mmm|m|
+WPUPCFC005|dd mm ss.s|s|
+WPUPCFC006|UTM|U|
+WPUPCFC007|USNG/MGRS2||
+WPUPCFC008|UTM w/special zones||
+#
+# PopUp "Configure GPS"
+WPUPCFG001|Configure GPS||
+WPUPCFG003|Stand alone GPS port||
+WPUPCFG002|Use GPS Position?||
+WPUPCFG004|GPS Options||
+WPUPCFG005|Stand-alone GPS||
+WPUPCFG006|TNC Connected GPS (HSP Cable)||
+WPUPCFG007|TNC Connected GPS using CTL-E||
+WPUPCFG008|GPS Time (Sample every)||
+WPUPCFG009|5 sec||
+WPUPCFG010|15 sec||
+WPUPCFG011|30 sec||
+WPUPCFG012|1 min||
+WPUPCFG013|2 min||
+WPUPCFG014|5 min||
+WPUPCFG015|10 min||
+WPUPCFG016|Network Connected GPS||
+WPUPCFG017|GPSD Host||
+WPUPCFG018|GPSD Port||
+WPUPCFG019|Network GPS via GPSD||
+WPUPCFG020|Reconnect on failure?||
+WPUPCFG021|Network Connected WX||
+WPUPCFG022|WX Host||
+WPUPCFG023|WX Port||
+#
+# Configure TNC (baud/style are also for WX)
+WPUPCFT001|Configure TNC||
+WPUPCFT002|Use TNC?||
+WPUPCFT003|TNC Port||
+WPUPCFT004|Port Settings||
+WPUPCFT005|300 bps||
+WPUPCFT006|1200 bps||
+WPUPCFT007|2400 bps||
+WPUPCFT008|4800 bps||
+WPUPCFT009|9600 bps||
+WPUPCFT010|19200 bps||
+WPUPCFT011|UnProto Paths||
+WPUPCFT012|Path 1: %s via ||
+WPUPCFT013|Path 2: %s via ||
+WPUPCFT014|Path 3: %s via ||
+WPUPCFT015|Port Style||
+WPUPCFT016|8,N,1||
+WPUPCFT017|7,E,1||
+WPUPCFT018|7,O,1||
+WPUPCFT019|38400 bps||
+WPUPCFT020|57600 bps||
+WPUPCFT021|115200 bps||
+WPUPCFT022|230400 bps||
+WPUPCFT023|Configure TNC w/HSP GPS||
+WPUPCFT024|Data Type||
+WPUPCFT025|Auto detect||
+WPUPCFT026|Binary Type||
+WPUPCFT027|ASCII Type||
+WPUPCFT028|Configure TNC w/AUX GPS||
+WPUPCFT029|Configure TNC w/INVALID ENUM||
+WPUPCFT030|Configure KISS TNC||
+WPUPCFT031|TNC Configuration Files||
+WPUPCFT032|TNC Setup Filename||
+WPUPCFT033|TNC Shutdown Filename||
+WPUPCFT034|KISS Parameters||
+WPUPCFT035|TXDelay (10 ms units)||
+WPUPCFT036|Persistence (0 to 255)||
+WPUPCFT037|SlotTime (10 ms units)||
+WPUPCFT038|TxTail (10 ms units)||
+WPUPCFT039|Full Duplex||
+WPUPCFT040|Configure Multi-Port KISS TNC||
+WPUPCFT041|Radio Port||
+WPUPCFT042|Interface Properties: Dubious UNPROTO Path!||
+WPUPCFT043|Please consider a shorter path such as WIDE2-2 or WIDE1-1,WIDE2-2||
+WPUPCFT044|Interface Properties: Dubious IGATE Path!||
+WPUPCFT045|Transmitting w/Dubious UNPROTO Path!||
+WPUPCFT046|Transmitting w/Dubious IGATE Path!||
+WPUPCFT047|Init KISS-mode on startup||
+#
+#
+# PopUp "Configure WX Port"
+WPUPCFWX01|Configure WX Port||
+WPUPCFWX02|Weather Station device||
+WPUPCFWX03|Rain Gauge Correction (Global Setting)||
+WPUPCFWX04|.1 inch/2.5mm||
+WPUPCFWX05|.01 inch/.25mm||
+WPUPCFWX06|.1mm||
+WPUPCFWX07|No Correction||
+#
+# PopUp "Configure - Station"
+WPUPCFS001|Configure Station||
+WPUPCFS002|Callsign||
+WPUPCFS003|LAT||
+WPUPCFS004|deg||
+WPUPCFS005|min||
+WPUPCFS006|(N/S)||
+WPUPCFS007|LONG||
+WPUPCFS008|(E/W)||
+WPUPCFS009|Station Symbol||
+WPUPCFS010|Group/overlay||
+WPUPCFS011|Symbol||
+WPUPCFS028|Select||
+WPUPCFS012|Power - Height (HAAT) - Gain - Directivity||
+WPUPCFS013|Disable PHG||
+WPUPCFS014|Antenna Height||
+WPUPCFS015|Antenna Gain||
+WPUPCFS016|Omni||
+WPUPCFS017|Comment:||
+WPUPCFS018|Position Ambiguity||
+WPUPCFS019|None||
+WPUPCFS020|.11 miles||
+WPUPCFS021|1.15 miles||
+WPUPCFS022|11.51 miles||
+WPUPCFS023|69.09 miles||
+WPUPCFS024|.18 kilometres||
+WPUPCFS025|1.85 kilometres||
+WPUPCFS026|18.53 kilometres||
+WPUPCFS027|111.19 kilometres||
+WPUPCFS029|Send compressed posits|C|
+#
+# PopUp "Object/Item"
+POPUPOB001|Object/Item||
+POPUPOB002|Name:||
+POPUPOB003|Create New Object||
+POPUPOB004|Delete Object||
+POPUPOB005|Modify Object||
+POPUPOB006|Create New Item||
+POPUPOB007|Area Object||
+POPUPOB008|Area Object||
+POPUPOB009|Bright Color||
+POPUPOB010|Color-Fill||
+POPUPOB011|Circle||
+POPUPOB012|Line-Right '/'||
+POPUPOB013|Line-Left '\'||
+POPUPOB014|Triangle||
+POPUPOB015|Rectangle||
+POPUPOB016|Black||
+POPUPOB017|Blue||
+POPUPOB018|Green||
+POPUPOB019|Cyan||
+POPUPOB020|Red||
+POPUPOB021|Violet||
+POPUPOB022|Yellow||
+POPUPOB023|Grey||
+POPUPOB024|Offset Up:||
+POPUPOB025|Offset Left (Except '/'):||
+POPUPOB026|Corridor:||
+POPUPOB027|Generic Options||
+POPUPOB028|Location||
+POPUPOB029|Signpost||
+POPUPOB030|Signpost Text||
+POPUPOB031|Signpost Object||
+POPUPOB032|Enable Compression||
+POPUPOB033|Delete Item||
+POPUPOB034|Modify Item||
+POPUPOB035|Altitude (ft):||
+POPUPOB036|Speed (knots):||
+POPUPOB037|Course:||
+POPUPOB038|DF Object||
+POPUPOB039|Signal - Height(HAAT) - Gain - Directivity||
+POPUPOB040|Beam Width - Bearing||
+POPUPOB041|Omni Antenna||
+POPUPOB042|Beam Antenna||
+POPUPOB043|Useless||
+POPUPOB044|Adopt Object||
+POPUPOB045|Adopt Item||
+POPUPOB046|DF Bearing:||
+POPUPOB047|Probability Circles||
+POPUPOB048|Map View Object||
+POPUPOB049|Min (mi):||
+POPUPOB050|Max (mi):||
+#
+# PopUp "Configure Internet"
+WPUPCFI001|Configure Internet||
+WPUPCFI002|Host ||
+WPUPCFI003|Port ||
+WPUPCFI004|(Secondary hosts)||
+WPUPCFI005|Host1||
+WPUPCFI006|Port1||
+WPUPCFI007|Host2||
+WPUPCFI008|Port2||
+WPUPCFI009|Pass-code||
+WPUPCFI010|(Leave Blank if None)||
+WPUPCFI011|Reconnect on NET failure?||
+WPUPCFI012|Run as an I-Gate?||
+WPUPCFI013|Broadcast messages via TNC when an I-Gate?||
+WPUPCFI014|Log I-Gate Transactions?||
+WPUPCFI015|Filter Parameters||
+#
+# PopUp "Configure Database"
+WPUPCFID01|Configure Database (TBD)||
+WPUPCFID02|Host ||
+WPUPCFID03|Port ||
+WPUPCFID04|(Secondary hosts)||
+WPUPCFID05|Host1||
+WPUPCFID06|Port1||
+WPUPCFID07|Host2||
+WPUPCFID08|Port2||
+WPUPCFID09|Pass-code||
+WPUPCFID10|(Leave Blank if None)||
+WPUPCFID11|Reconnect on NET failure?||
+WPUPCFID12|Run as an I-Gate?||
+WPUPCFID13|Broadcast messages via TNC when an I-Gate?||
+WPUPCFID14|Log I-Gate Transactions?||
+WPUPCFID15|Filter Parameters||
+#
+# PopUp "Configure AGWPE"
+WPUPCFIA01|Configure AGWPE||
+WPUPCFIA02|Host ||
+WPUPCFIA03|Port ||
+WPUPCFIA04|(Secondary hosts)||
+WPUPCFIA05|Host1||
+WPUPCFIA06|Port1||
+WPUPCFIA07|Host2||
+WPUPCFIA08|Port2||
+WPUPCFIA09|Pass-code||
+WPUPCFIA10|(Leave Blank if None)||
+WPUPCFIA11|Reconnect on NET failure?||
+WPUPCFIA12|Run as an I-Gate?||
+WPUPCFIA13|Broadcast messages via TNC when an I-Gate?||
+WPUPCFIA14|Log I-Gate Transactions?||
+WPUPCFIA15|Transmit RadioPort||
+#
+# PopUp "Configure Audio Alarms"
+WPUPCFA001|Configure Audio Alarms||
+WPUPCFA002|Audio Play Command||
+WPUPCFA003|Alarm on||
+WPUPCFA004|Audio file to Play||
+WPUPCFA005|New Station||
+WPUPCFA006|New Message||
+WPUPCFA007|Proximity||
+WPUPCFA008|Band Opening||
+WPUPCFA009|Minimum Distance||
+WPUPCFA010|Maximum Distance||
+WPUPCFA011|Weather Alert||
+#
+# PopUp "Configure Speech"
+WPUPCFSP01|Configure Speech||
+WPUPCFSP02|Speech Output on:||
+WPUPCFSP03|New Station||
+WPUPCFSP04|New Message Alert||
+WPUPCFSP05|New Message Body||
+WPUPCFSP06|Proximity Alert||
+WPUPCFSP07|Band Opening||
+WPUPCFSP08|New Weather Alert||
+WPUPCFSP09|Tracked Station Proximity Alert||
+#
+# PopUp "Track Station"
+WPUPTSP001|Track Station||
+WPUPTSP002|Track Callsign||
+WPUPTSP003|Match Case||
+WPUPTSP004|Match Exact||
+WPUPTSP005|Track Now!||
+WPUPTSP006|Clear Tracking||
+WPUPTSP007|Download Trail||
+WPUPTSP008|Callsign||
+WPUPTSP009|Start Trail (hrs ago)||
+WPUPTSP010|Trail Length (hrs)||
+#
+# PopUp "Messages..."
+WPUPMSB001|Send Message Box %d||
+WPUPMSB002|Send Group Message Box %d||
+WPUPMSB003|Station's Call:||
+WPUPMSB004|Group's Call:||
+WPUPMSB005|New/Refresh Call||
+WPUPMSB006|New Group||
+WPUPMSB007|Clear Msg History||
+WPUPMSB008|Message:||
+WPUPMSB009|Send Now!||
+WPUPMSB010|Path:||
+WPUPMSB011|Cancel Pending Msgs||
+WPUPMSB012|Kick Timer||
+WPUPMSB013|seq||
+WPUPMSB014|type||
+WPUPMSB015|Broadcast||
+WPUPMSB016|*TIMEOUT*||
+WPUPMSB017|*CANCELLED*||
+WPUPMSB018|*REJECTED*||
+WPUPMSB019|Change Path||
+WPUPMSB020|Use Default Path(s)||
+WPUPMSB021|Direct (No path)||
+WPUPMSB022|Reverse Path (Hint):||
+#
+# PopUp "Auto Reply"
+WPUPARM001|Change Auto Reply||
+WPUPARM002|Reply:||
+#
+# PopUp "Help Index"
+WPUPHPI001|Help Index||
+WPUPHPI002|View||
+#
+# PopUp "Station Info"
+WPUPSTI000|Object from: %s||
+WPUPSTI001|Station Info||
+WPUPSTI002|Send Message||
+WPUPSTI003|Search FCC Database||
+WPUPSTI004|Search RAC Database||
+WPUPSTI005|Packets received: %d Last Heard: ||
+WPUPSTI006|Heard via the TNC on device %d, ||
+WPUPSTI007|Heard ||
+WPUPSTI008|last via Local||
+WPUPSTI009|last via TNC on device %d||
+WPUPSTI010|last via Internet on device %d||
+WPUPSTI011|last via File||
+WPUPSTI012|last via Unknown||
+WPUPSTI013|, and has moved||
+WPUPSTI014|Current Power Gain:||
+WPUPSTI016|Altitude: %.0f%s ||
+WPUPSTI017|Course: %s� ||
+WPUPSTI018|Speed: %.1f km/h||
+WPUPSTI019|Speed: %.1f mph||
+WPUPSTI020|%0.1f miles||
+WPUPSTI021|%0.1f km||
+WPUPSTI022|Distance from my station: %s Bearing from my station: %s||
+WPUPSTI023|Last Position: ||
+WPUPSTI024|Weather Data %c:%s||
+WPUPSTI025|Wind Course: %s� Speed: %03d km/h||
+WPUPSTI026|Wind Course: %s� Speed: %s mph||
+WPUPSTI027| Gust: %03d km/h||
+WPUPSTI028| Gust: %s mph||
+WPUPSTI029|Temperature: %02.1f�C ||
+WPUPSTI030|Temperature: %s�F ||
+WPUPSTI031|Humidity: %s%% ||
+WPUPSTI032| Humidex: %02.1f�C ||
+WPUPSTI033|Baro: %s hPa||
+WPUPSTI034|Snow: %0.1f (cm/24h)||
+WPUPSTI035|Snow: %0.0f (inch/24h)||
+WPUPSTI036|Rain: ||
+WPUPSTI037|%0.2f (mm/h) ||
+WPUPSTI038|%0.2f (inch/h) ||
+WPUPSTI039|%0.2f (mm/day) ||
+WPUPSTI040|%0.2f (inch/day) ||
+WPUPSTI041|%0.2f (mm/since midnight)||
+WPUPSTI042|%0.2f (inch/since midnight)||
+WPUPSTI043|Data path: %s||
+WPUPSTI044|Comment %02d/%02d %02d:%02d : %s||
+WPUPSTI045|Clear Track||
+WPUPSTI046|Total Rain: ||
+WPUPSTI047|%0.2f (mm)||
+WPUPSTI048|%0.2f (inch)||
+WPUPSTI049|Trace Query||
+WPUPSTI050|Un-Acked Messages Query||
+WPUPSTI051|Direct Stations Query||
+WPUPSTI052|Station Version Query||
+WPUPSTI053|Modify Object/Item||
+WPUPSTI054|Store Track||
+WPUPSTI055|Echoed from:||
+WPUPSTI056|Enable Automatic Updates||
+WPUPSTI057|Omni-DF: %s||
+WPUPSTI058|DF Bearing: %s||
+WPUPSTI059|Status %02d/%02d %02d:%02d : %s||
+WPUPSTI060|Fuel Temp: %02.1f�C ||
+WPUPSTI061|Fuel Temp: %s�F ||
+WPUPSTI062|Fuel Moisture: %s%% ||
+WPUPSTI063|Baro: %0.2f in Hg||
+WPUPSTI064|Fetch NWS Alert||
+WPUPSTI065|Tactical Call: %s||
+WPUPSTI066|Assign Tactical Call||
+WPUPSTI067|Current Range: %d miles||
+WPUPSTI068|none||
+WPUPSTI069|default||
+WPUPSTI070|HAAT||
+WPUPSTI071|omni||
+WPUPSTI072|range||
+WPUPSTI073|BAD PHG||
+WPUPSTI074|BAD SHG||
+WPUPSTI075|DF Range||
+WPUPSTI076|No signal detected||
+WPUPSTI077|Detectible signal (Maybe)||
+WPUPSTI078|Detectible signal but not copyable)||
+WPUPSTI079|Weak signal, marginally readable||
+WPUPSTI080|Noisy but copyable signal||
+WPUPSTI081|Some noise, easy to copy signal||
+WPUPSTI082|Good signal w/detectible noise||
+WPUPSTI083|Near full-quieting signal||
+WPUPSTI084|Full-quieting signal||
+WPUPSTI085|Extremely strong & full-quieting signal||
+WPUPSTI086|BAD BEARING||
+WPUPSTI087|BAD NRQ||
+WPUPSTI088|DF Beamwidth||
+WPUPSTI089|DF Length||
+WPUPSTI090|Not Valid||
+WPUPSTI091|Change Trail Color||
+WPUPSTI092|Clear DF Bearing||
+#
+#
+# PopUp "ALOHA Statistics"
+WPUPALO001|ALOHA radius: %d %s||
+WPUPALO002|Stations inside ALOHA circle: %d||
+WPUPALO003| Digis: %d||
+WPUPALO004| Mobiles (in motion): %d||
+WPUPALO005| Mobiles (other): %d||
+WPUPALO006| WX stations: %d||
+WPUPALO007| Home stations: %d||
+WPUPALO008|Last calculated %d %s %d %s ago.||
+WPUPALO666|ALOHA radius not calculated yet||
+#
+#
+# FCC-RAC Call Look up
+STIFCC0001|FCC Database Lookup||
+STIFCC0002|RAC Database Lookup||
+STIFCC0003|Name:||
+STIFCC0004|Street:||
+STIFCC0005|City:||
+STIFCC0006|State:||
+STIFCC0007|Zip:||
+STIFCC0008|Basic ||
+STIFCC0009|Advanced ||
+STIFCC0010|5 wpm ||
+STIFCC0011|12 wpm ||
+#
+#
+# FCC-RAC indexing/searching
+STIFCC0100|FCC index old, rebuilding||
+STIFCC0101|Callsign Search||
+STIFCC0102|Callsign Not Found!||
+STIFCC0103|RAC index old, rebuilding||
+#
+#
+# Band open message
+UMBNDO0001|at distance of||
+#
+#
+# Universal Options
+UNIOP00001|OK||
+UNIOP00002|Cancel||
+UNIOP00003|Close||
+UNIOP00004|miles||
+UNIOP00005|km||
+UNIOP00006|Device||
+UNIOP00007|Add||
+UNIOP00008|Delete||
+UNIOP00009|Properties||
+UNIOP00010|Allow Transmitting?||
+UNIOP00011|Activate on Startup?||
+UNIOP00012|km/h||
+UNIOP00013|mph||
+UNIOP00014|�C||
+UNIOP00015|�F||
+UNIOP00016|mm||
+UNIOP00017|inch||
+UNIOP00018|mm/day||
+UNIOP00019|inch/day||
+UNIOP00020|mm/hr||
+UNIOP00021|inch/hr||
+UNIOP00022|mm/mid||
+UNIOP00023|inch/mid||
+UNIOP00024|deg||
+UNIOP00025|hPa||
+UNIOP00026|%||
+UNIOP00027|in Hg||
+UNIOP00028|mm Hg||
+UNIOP00029|Set System Clock from GPS Data?||
+UNIOP00030|Digipeat?||
+UNIOP00031|m||
+UNIOP00032|Apply||
+UNIOP00033|Reset||
+UNIOP00034|min||
+UNIOP00035|hr||
+UNIOP00036|day||
+UNIOP00037|Send Control-E to get GPS data?||
+UNIOP00038|Add Delay||
+#
+# PopUp "Station Chooser"
+STCHO00001|Station Chooser||
+#
+# DISPLAY WX ALERT
+WPUPWXA001|Wx Alerts||
+WPUPWXA002|Wx Alert List||
+#
+# PopUp "Configure - Interfaces"
+WPUPCIF001|Installed Interfaces||
+WPUPCIF002|Choose Interface Type||
+#
+# PopUp "Configure AX.25 TNC"
+WPUPCAX001|Configure AX.25 TNC||
+WPUPCAX002|AX.25 Device name||
+#
+# Interface device names
+IFDNL00000|None||
+IFDNL00001|Serial TNC||
+IFDNL00002|Serial TNC w/GPS on a HSP cable||
+IFDNL00003|Serial GPS||
+IFDNL00004|Serial WX||
+IFDNL00005|Internet Server||
+IFDNL00006|AX25 TNC||
+IFDNL00007|Networked GPS (via gpsd)||
+IFDNL00008|Networked WX||
+IFDNL00009|Serial TNC w/GPS on AUX port||
+IFDNL00010|Serial KISS TNC||
+IFDNL00011|Networked Database (Not Implemented Yet)||
+IFDNL00012|Networked AGWPE||
+IFDNL00013|Serial Multi-Port KISS TNC||
+IFDNL00014|SQL Database (Experimental)||
+#
+# Interface device info
+IFDIN00000|%s %2d %s %s %s||
+IFDIN00001|%s %2d %s %s:%d %s||
+IFDIN00002|%s %2d %s device %s %s||
+IFDIN00003|%s %2d %s %s %s %s||
+IFDIN00004|%s %2d %s %s %s:%d %s||
+IFDIN00005|%s %2d %s %s %s %s||
+IFDIN00006| DOWN ||
+IFDIN00007| UP ||
+IFDIN00008|ERROR ||
+IFDIN00009|UNKNWN||
+#
+# PopUp "Interface control"
+IFPUPCT000|Interface Control||
+IFPUPCT001|Start||
+IFPUPCT002|Stop||
+IFPUPCT003|Start All||
+IFPUPCT004|Stop All||
+#
+# IGate control
+IGPUPCF000|IGate Options||
+IGPUPCF001|Disable all IGate traffic||
+IGPUPCF002|Allow RF to Inet traffic ONLY||
+IGPUPCF003|Allow RF->Inet and Inet->RF traffic||
+IGPUPCF004|Igate -> RF Path ||
+#
+# WX Station
+WXPUPSI000|WX Station||
+WXPUPSI001|WX Station Type||
+WXPUPSI002|Current Data||
+WXPUPSI003|Wind Course||
+WXPUPSI004|Wind Speed||
+WXPUPSI005|Wind Gust||
+WXPUPSI006|Temp||
+WXPUPSI007|Total Rain||
+WXPUPSI008|Today's Rain Total||
+WXPUPSI009|Baro||
+WXPUPSI010|Humidity||
+WXPUPSI011|Peet Bros ULTIMETER 2000 Type (Data Logging Mode)||
+WXPUPSI012|Peet Bros ULTIMETER II Type||
+WXPUPSI013|Peet Bros ULTIMETER 2000 Type (Packet Mode)||
+WXPUPSI014|Current HR Rain Tot.||
+WXPUPSI015|Last 24 Rain Total||
+WXPUPSI016|Qualimetrics Q-Net||
+WXPUPSI017|Peet Bros ULTIMETER 2000 Type (Complete Mode)||
+WXPUPSI018|Dew Point||
+WXPUPSI019|High Wind||
+WXPUPSI020|Wind Chill||
+WXPUPSI021|Heat Index||
+WXPUPSI022|3-Hr Baro||
+WXPUPSI023|High Temp.||
+WXPUPSI024|Low Temp.||
+WXPUPSI025|Radio Shack WX-200/Oregon Scientific WM-918||
+WXPUPSI026|Davis Weather Monitor II/Wizard III/Vantage Pro||
+WXPUPSI027|LaCrosse WX-23xx||
+WXPUPSI028|Davis APRS Data Logger||
+#
+# Station Lists
+LHPUPNI000|All Stations||
+LHPUPNI001|Mobile Stations||
+LHPUPNI002|Weather Stations||
+LHPUPNI003|Local Stations (via TNC)||
+LHPUPNI004|Last Stations||
+LHPUPNI005|Objects & Items||
+LHPUPNI006|Own Objects & Items||
+LHPUPNI010|#||
+LHPUPNI011|Call Sign||
+LHPUPNI012|#Pack||
+LHPUPNI013|Pos Time||
+LHPUPNI014|Path||
+LHPUPNI015|PHG||
+LHPUPNI016|Comments||
+LHPUPNI100|CSE||
+LHPUPNI101|SPD||
+LHPUPNI102|ALT.||
+LHPUPNI103|Lat||
+LHPUPNI104|Long||
+LHPUPNI105|#Pack||
+LHPUPNI106|LSV||
+LHPUPNI107|CFMS||
+LHPUPNI108|DFMS||
+LHPUPNI200|CSE||
+LHPUPNI201|SPD||
+LHPUPNI202|GST||
+LHPUPNI203|Temp||
+LHPUPNI204|Hum||
+LHPUPNI205|Baro||
+LHPUPNI206|RN-H||
+LHPUPNI207|RNSM||
+LHPUPNI208|RN24||
+LHPUPNI209|Lat/Lon or UTM||
+#
+# Maps WX Alert styles
+PULDNMAT01|Show Alert maps above other maps||
+PULDNMAT02|Show Alert maps under other maps||
+#
+# Error/popup messages
+POPEM00001|Locate Error!||
+POPEM00002|Station %s was not found!||
+POPEM00003|Tracking Error!||
+POPEM00004|Interface Error!||
+POPEM00005|Invalid AX.25 port name %s||
+POPEM00006|Invalid AX.25 port name %s||
+POPEM00007|Invalid callsign %s||
+POPEM00008|Invalid AX.25 destination callsign or digipeater||
+POPEM00009|Cannot open AX.25 socket, %s||
+POPEM00010|Cannot bind AX.25 socket, %s||
+POPEM00011|Cannot connect to AX.25 callsign, %s||
+POPEM00012|AX.25 error on output of UI||
+POPEM00013|AX.25 problem with axports file||
+POPEM00014|AX.25 invalid port name %s||
+POPEM00015|Error opening interface %d Hard Fail||
+POPEM00016|Error opening interface %d Time Out||
+POPEM00017|No more interfaces Available!||
+POPEM00018|Data Query - Single Message Line||
+POPEM00019|Port transmitting is off for port %d||
+POPEM00020|Database Error!||
+POPEM00021|AX.25 support not compiled into Xastir!||
+POPEM00022|Input Error!||
+POPEM00023|No location name specified!||
+POPEM00024|Location name specified is in use!||
+POPEM00025|Not Found!||
+POPEM00026|Tracking will commence when it appears||
+POPEM00027|Improper info. Some fields empty?||
+POPEM00028|Can't open file||
+POPEM00029|Found It!||
+POPEM00030|Weather Station Symbol||
+POPEM00031|Changed to WX symbol '/_', other options: '\_' '/W' and '\W'||
+POPEM00032|Warning: Using National Weather Service Symbol!||
+POPEM00033|No GPS Data!||
+POPEM00034|Disabling My Position TX Until Valid GPS Data!||
+POPEM00035|Warning||
+POPEM00036|Notice||
+POPEM00037|HSP interface present: GPS timing has been increased||
+POPEM00038|Name Conflicts With Existing Object/Item/Station||
+POPEM00039|Illegal characters found, substituting periods in their place||
+POPEM00040|Custom outgoing path was lost||
+POPEM00041|Processing another file. Wait a bit, then try again||
+POPEM00042|Object not owned by me! Try adopting the object first.||
+POPEM00043|Not an Object/Item!||
+POPEM00044|Fetch Findu Trail: Failed||
+POPEM00045|Fetch Findu Trail: Complete||
+POPEM00046|Berkeley DB header/shared library do NOT match! Disabling map cache.||
+POPEM00047|Global transmit is DISABLED. Emergency beacons are NOT going out!||
+POPEM00048|Emergency Beacon Mode!||
+POPEM00049|EMERGENCY BEACON MODE, transmitting every 60 seconds!||
+POPEM00050|Interfaces or posits/transmits DISABLED. Emergency beacons are NOT going out!||
+POPEM00051|Altnet is enabled (Configure->Defaults dialog)||
+POPEM00052|Callsign is EMPTY!||
+POPEM00053|Message is EMPTY!||
+POPEM00054|We're trying to talk to ourselves!||
+#
+# Jump Location
+JMLPO00001|Map Display Bookmarks||
+JMLPO00002|Activate!||
+JMLPO00003|New Name:||
+#
+# Bulletins
+BULMW00001|Bulletins||
+BULMW00002|Limit Range to (0, is no limit)||
+BULMW00003|Change Range||
+#
+# All Message Traffic
+AMTMW00001|All Message Traffic||
+AMTMW00002|Limit Range to (0, is no limit)||
+#
+# Speech Strings
+SPCHSTR001|kilometers||
+SPCHSTR002|meters||
+SPCHSTR003|miles||
+SPCHSTR004|yards||
+SPCHSTR005|%s, distance is %d %s.||
+SPCHSTR006|%s, distance is %.1f %s.||
+SPCHSTR007|%s, distance is %d %s %s %s.||
+SPCHSTR008|%s, distance is %.1f %s %s %s.||
+SPCHSTR009|New Weather Alert||
+SPCHSTR010|New Station||
+SPCHSTR011|Heard, D X, %s, at distance of %.1f %s||
+#
+#
+SPCHDIRN00|north of||
+SPCHDIRS00|south of||
+SPCHDIRE00|east of||
+SPCHDIRW00|west of||
+SPCHDIRNE0|northeast of||
+SPCHDIRNW0|northwest of||
+SPCHDIRSE0|southeast of||
+SPCHDIRSW0|southwest of||
+#
+# Symbol Selection Dialog
+SYMSEL0001|Select Symbol||
+SYMSEL0002|Primary Symbol Table||
+SYMSEL0003|Secondary Symbol Table||
+#
+# Print Properties Dialog
+PRINT0001|Print Properties||
+PRINT0002|Paper Size||
+PRINT0003|Auto-Rotate Image||
+PRINT0004|Rotate Image 90� CCW||
+PRINT0005|Auto-Scale Image||
+PRINT0006|Scale:||
+PRINT0007|Force default background color to white||
+PRINT0008|Print in Black and White||
+PRINT0016|Reverse Colors||
+PRINT0009|Postscript Resolution:||
+PRINT0010|Preview||
+PRINT0011|Print to File||
+PRINT0012|Dumping image to file...||
+PRINT0013|Converting to Postscript...||
+PRINT0014|Finished creating print file||
+PRINT0015|Print Status||
+#
+# Print Dialog
+PRINT1001|Direct to:||
+PRINT1002|Via Previewer:||
+#
+# Locate Feature and Find Address Dialogs
+FEATURE001|Name:||
+FEATURE002|State/Province:||
+FEATURE003|County:||
+FEATURE004|Map Quad:||
+FEATURE005|Type:||
+FEATURE006|GNIS File:||
+FEATURE007|Address:||
+FEATURE008|City:||
+FEATURE009|Mark Destination||
+FEATURE010|Zip Code:||
+FEATURE011|Geocoding File||
+#
+# Coordinate Calculator Dialog
+COORD001|Coordinate Calculator||
+COORD002|Calc||
+COORD003|Calculate||
+COORD004|Clear||
+COORD005|UTM||
+COORD006|Latitude or||
+COORD007|Longitude or||
+COORD008|Zone||
+COORD009|UTM Easting||
+COORD010|UTM Northing||
+COORD011| Decimal Degrees: ||
+COORD012| Degrees/Decimal Minutes: ||
+COORD013| Degrees/Minutes/Dec. Seconds: ||
+COORD014| Universal Transverse Mercator: ||
+COORD015|Military Grid Reference System: ||
+COORD016| Maidenhead Grid Locator: ||
+COORD017| ** Sorry, your input was not recognized! **||
+COORD018| ** Please use one of the following input formats: **||
+#
+#
+# Smart Beaconing Dialog
+SMARTB001|Smart Beaconing||
+SMARTB002|High Rate (secs):||
+SMARTB003|High Speed (mph):||
+SMARTB004|High Speed (kph):||
+SMARTB005|Low Rate (mins):||
+SMARTB006|Low Speed (mph):||
+SMARTB007|Low Speed (kph):||
+SMARTB008|Minimum Turn (deg):||
+SMARTB009|Turn Slope:||
+SMARTB010|Wait Time (secs):||
+SMARTB011|Enable SmartBeaconing(tm)||
+#
+#
+#
+# Gamma Adjust Dialog
+GAMMA001|Adjust Gamma Correction||
+GAMMA002|Gamma Correction||
+#
+#
+#
+# Map labels font Dialog
+MAPFONT001|Change Fonts||
+MAPFONT002|Fonts||
+MAPFONT003|Map Font Tiny||
+MAPFONT004|Map Font Small||
+MAPFONT005|Map Font Medium||
+MAPFONT006|Map Font Large||
+MAPFONT007|Map Font Huge||
+MAPFONT008|Map Font Border||
+MAPFONT009|Menu Font||
+MAPFONT010|Station Font||
+MAPFONT011|ATV ID Font||
+#
+#
+#
+# Distance/Bearing on status line
+PULDNDB001|Dist/Bearing Status||
+#
+#
+# GPS Transfer Operations
+GPS001|GPS Transfer||
+GPS002|Filename||
+GPS003|Select Color||
+GPS004|Red||
+GPS005|Green||
+GPS006|Black||
+GPS007|White||
+GPS008|Orange||
+GPS009|Blue||
+GPS010|Yellow||
+GPS011|Violet||
+#
+#
+# Map Properties Dialog
+MAPP001|Map Properties||
+MAPP002|Max Min Map USGS Auto||
+MAPP003|Zoom Zoom Layer Fill DRG Map Path/Filename||
+MAPP004|Change Layer->||
+MAPP005|Filled->||
+MAPP006|Yes||
+MAPP007|No||
+MAPP008|Automaps->||
+MAPP009|Max Zoom->||
+MAPP010|Min Zoom->||
+MAPP011|Auto||
+MAPP012|USGS DRG->||
+#
+#
+# Time Strings
+TIME001|Day||
+TIME002|Days||
+TIME003|Hour||
+TIME004|Hours||
+TIME005|Minute||
+TIME006|Minutes||
+TIME007|Second||
+TIME008|Seconds||
+#
+#
+# Map Caching
+CACHE001|Map now cached||
+CACHE002|Loading Cached Map||
+CACHE003|Map not found in cache...||
+#
+#
+# Map Screen Misc
+RANGE001|RANGE SCALE||
+#
+#
+# GPS Status
+GPSS001|WAAS or PPS||
+GPSS002|DGPS||
+GPSS003|Valid SPS||
+GPSS004|Invalid||
+GPSS005|Sats/View||
+GPSS006|Fix||
+GPSS007|!GPS data is older than 30 seconds!||
+GPSS008|Simulation||
+GPSS009|Manual||
+GPSS010|Estimated||
+GPSS011|Float RTK||
+GPSS012|RTK||
+#
+#
+# Popup cad_dialog to obtain CAD object data and other CAD dialogs
+CADPUD001|Area Object||
+CADPUD002|Area Label:||
+CADPUD003|Comment:||
+CADPUD004|Probability (%):||
+CADPUD005|OK||
+CADPUD006|CAD Dialog||
+CADPUD007|Show/Edit Details||
+CADPUD008|Cancel||
+CADPUD009|Delete CAD objects?||
+CADPUD010|Delete All||
+CADPUD011|Delete Selected||
+CADPUD012|Solid||
+CADPUD013|Dashed||
+CADPUD014|Double Dash||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA001|XASTIR Map of %s (upper left) to %s (lower right). UTM %d m grid, %s datum. ||
+#"XASTIR Map of <lat/long> (upper left) to <lat/long> (lower right). Lat/Long grid, <wgs84> datum. ",
+MDATA002|XASTIR Map of %s (upper left) to %s %s (lower right). Lat/Long grid, %s datum.||
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM zones, <wgs84> datum. ",
+MDATA003|XASTIR Map of %s (upper left) to %s (lower right). UTM zones, %s datum.||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST001|MySQL (lat/long)||
+# DB_POSTGIS
+XADBMST002|Postgreql with Postgis||
+# DB_MYSQL_SPATIAL
+XADBMST003|MySQL (spatial)||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA01|Xastir Simple Schema||
+#XASTIR_SCHEMA_CAD
+XASCHEMA02|Xastir CAD Schema||
+#XASTIR_SCHEMA_COMPLEX
+XASCHEMA03|Xastir full Schema||
+#XASTIR_SCHEMA_APRSWORLD
+XASCHEMA04|APRSWorld Schema||
diff --git a/config/language-French.sys b/config/language-French.sys
new file mode 100644
index 0000000..96f2a8f
--- /dev/null
+++ b/config/language-French.sys
@@ -0,0 +1,1366 @@
+# $Id: language-French.sys,v 1.231 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# This is the French Language file used for all the prompts in xastir
+#
+# Creator : Richard VE2DJE ve2dje at amsat.org
+# Maintained by : The Xastir Group <xastir at xastir.org>
+# Merci � : Jacques Chion, F6CWO, qui a contribu� une grande part des
+# traductions r�centes. (N7TAP)
+#
+# comment lines with pound signs in front are ignored
+# File format as follows:
+# ID (10 chars alpha+numeric)|(String associated with id)|QuickKeys|#comment
+# The ID is a unique uppercase char string for each block followed by a nummer
+#
+# WARNING:
+# Some strings contain formatting commands like %s and %d, you should not
+# change these. Wrong format strings could produce a segfault!
+#
+# Main Menu
+MENUTB0001|Fichier|F|
+MENUTB0002|Examiner|E|
+MENUTB0004|Cartes|a|
+MENUTB0005|Stations|S|
+MENUTB0006|Messages|M|
+MENUTB0010|Interfaces|I|
+MENUTB0009|Aide|A|
+#
+# Menu "File"
+PULDNFI001|Configurer|C|
+PULDNFI002|Ouvrir le journal|O|
+PULDNFI003|Test|e|
+PULDNFI004|Quitter|Q|
+PULDNFI007|Changer niveau de d�bogage|d|
+PULDNFI010|Activer archivage TNC|T|
+PULDNFI011|Activer archivage r�seau|r|
+PULDNFI012|Activer archivage IGate|I|
+PULDNFI013|Activer archivage m�t�o|m|
+PULDNFI014|Activer copie d'�cran PNG||
+PULDNFI015|Imprimer carte|p|
+PULDNFI016|Instantan� KML||
+#
+# Menu "View"
+PULDNVI001|Bulletins|B|
+PULDNVI002|Donn�es entrantes|D|
+PULDNVI003|Stations mobiles|m|
+PULDNVI004|Toutes stations|T|
+PULDNVI009|Stations locales|l|
+PULDNVI012|Stations r�centes|r|
+PULDNVI005|Stations m�t�o|m|
+PULDNVI008|Mes donn�es m�t�o|o|
+PULDNVI007|Alertes m�t�o|A|
+PULDNVI011|Trafic des messages|i|
+PULDNVI013|Dur�e de fonctionnement|f|
+PULDNVI014|Dur�e de fonctionnement du logiciel||
+PULDNVI015|Etat du GPS||
+PULDNVI016|Statistiques ALOHA||
+#
+# Menu "Configure"
+PULDNCF004|Station|S|
+PULDNCF001|D�fauts|D|
+PULDNCF003|Temporisations|T|
+PULDNCF002|Syst�me des coordonn�es|C|
+PULDNCF006|Alertes sonores|A|
+PULDNCF007|Parole|P|
+PULDNCF008|Sauvegarder la configuration maintenant !|a|
+# (Units see PULDNDP006)
+#
+# Menu "Maps"
+PULDNMP001|Choix des cartes|C|
+PULDNMP012|Aller �|l|
+PULDNMP014|Localiser �l�ment cartographique|F|
+PULDNMP016|D�sactiver Zoom/Pan/Accueil rapide||
+PULDNMP013|D�sactiver toutes cartes|D|
+PULDNMP002|Activer cartographie automatique|A|
+PULDNMP003|Activer quadrillage|q|
+PULDNMP004|Activer niveaux de cartes|n|
+PULDNMP010|Activer annotation des cartes|n|
+PULDNMP009|Activer remplissage de zones|r|
+PULDNMP007|Activer alertes m�t�o|M|
+PULDNMP005|Couleur de fond|f|
+PULDNMP006|Style du texte de station|S|
+PULDNMP026|Style du contour d'ic�ne|O|
+PULDNMP011|Menu souris|e|
+PULDNMP008|Intensit� des cartes|I|
+PULDNMP020|Configurer Tigermap||
+PULDNMP021|Cartographie automatique - d�sactiver cartes tram�es||
+PULDNMP022|Indexer nouvelles cartes au d�marrage||
+PULDNMP023|Index: Ajouter nouvelles cartes|R|
+PULDNMP024|Index: Re-indexer toutes cartes|A|
+PULDNMP025|Fonts||
+PULDNMP015|Xfontsel||
+PULDNMP027|Re-t�l�charger les cartes (pas � partir du cache)||
+PULDNMP028|Vider le cache des cartes||
+PULDNMP029|Trouver l'adresse||
+PULDNMP030|Configurer USGS DRG||
+PULDNMP031|Activer bordure des cartes||
+#
+# PopUp "Configure Tigermap"
+MPUPTGR001|Quadrillage||
+MPUPTGR002|Comt�s||
+MPUPTGR003|Nom des villes||
+MPUPTGR004|R�gions urbaines||
+MPUPTGR005|Routes principales||
+MPUPTGR006|Rues||
+MPUPTGR007|Voies ferr�es||
+MPUPTGR008|Nom des �tats||
+MPUPTGR009|Nom des autoroutes||
+MPUPTGR010|Nom des routes US||
+MPUPTGR011|Nom des routes d'�tats||
+MPUPTGR012|Choisir les articles � afficher:||
+MPUPTGR013|Rivi�res||
+MPUPTGR014|Lacs||
+MPUPTGR015|A�roports, parcs, etc||
+MPUPTGR016|Intensit� de la carte||
+MPUPTGR017|Temporisation de carte Internet (sec)||
+MPUPTGR018|Activer cartes Tiger||
+#
+# PopUp "Configure USGS DRG"
+MPUPDRG001|S�lectionner ce qui doit �tre affich� :||
+MPUPDRG002|Colorer la carte sous-ja�ante (XOR)||
+MPUPDRG003|Noir||
+MPUPDRG004|Blanc||
+MPUPDRG005|Bleu||
+MPUPDRG006|Rouge||
+MPUPDRG007|Marron||
+MPUPDRG008|Vert||
+MPUPDRG009|Pourpre||
+MPUPDRG010|Jaune||
+MPUPDRG011|Bleu clair||
+MPUPDRG012|Rouge clair||
+MPUPDRG013|Pourpre clair||
+MPUPDRG014|Gris clair||
+MPUPDRG015|Marron clair||
+#
+# PopUp "Map Chooser"
+WPUPMCP001|Choix de cartes||
+PULDNMMC01|Effacer|A|
+PULDNMMC02|Vectorielles|V|
+PULDNMMC03|Topogr. 250k|2|
+PULDNMMC04|Topogr. 100k|1|
+PULDNMMC05|Topogr. 24k|4|
+PULDNMMC06|Agrandir r�pertoires|||
+PULDNMMC07|R�ps/cartes choisies:||
+PULDNMMC08|D�selct. r�ps|C|
+PULDNMMC09|Choisir tout|S|
+#
+# PullDown "Map Background Color"
+PULDNMBC01|Gris||
+PULDNMBC02|Rose||
+PULDNMBC03|Bleu marine||
+PULDNMBC04|Bleu acier ||
+PULDNMBC05|Vert moyen||
+PULDNMBC06|Vert p�le||
+PULDNMBC07|Jaune p�le||
+PULDNMBC08|Blanc cr�me||
+PULDNMBC09|Brun ros�||
+PULDNMBC10|Rouge brique||
+PULDNMBC11|Blanc||
+PULDNMBC12|Noir||
+#
+# PullDown "Station text Style"
+PULDNMSL01|Bordure noire|n|
+PULDNMSL02|Ombr� avec toile de fond|O|
+PULDNMSL03|Blanc sur noir|B|
+#
+# PullDown "Icon Outline Style"
+PULDNMIO01|Pas de contour|N|
+PULDNMIO02|Contour noir|B|
+PULDNMIO03|Contour gris|G|
+PULDNMIO04|Contour blanc|W|
+#
+# Switches
+PULDNOT001|Ouvrir||
+PULDNOT002|Fermer||
+PULDNOT003|Court||
+#
+# Menu "Stations"
+PULDNDP014|Localiser une station|L|
+PULDNDP001|Suivre une station|S|
+PULDNDP022|R�cup�rer piste Findu||
+PULDNDP032|Filtrer donn�es||
+PULDNDP040|Ne rien afficher||
+PULDNDP041|Ma station||
+PULDNDP042|Choisir TNC||
+PULDNDP027|- Stations en direct||
+PULDNDP043|- Stations via digi||
+PULDNDP034|Stations via le net||
+PULDNDP019|Inclure donn�es p�rim�es||
+PULDNDP044|Afficher les stations||
+PULDNDP028|- Stations fixes||
+PULDNDP029|- Stations mobiles||
+PULDNDP030|- Stations m�t�o||
+PULDNDP053| - Stations m�t�o CWOP||
+PULDNDP045|Objets/articles||
+PULDNDP026|- Objets/articles m�t�o||
+PULDNDP039|- Objets/articles indicateurs d'eau||#'
+PULDNDP031|- Autres objets/articles||
+PULDNDP033|Filtrer affichage||
+PULDNDP010|Afficher indicatif|n|
+PULDNDP012|Afficher symbole|c|
+PULDNDP011|- Pivoter symbole|o|
+PULDNDP007|Afficher piste|p|
+PULDNDP003|Afficher cap|r|
+PULDNDP004|Afficher vitesse|v|
+PULDNDP017|- Afficher vitesse abr�g�e||
+PULDNDP002|Afficher altitude|A|
+PULDNDP009|Afficher info m�t�o|I|
+PULDNDP046|- Afficher texte m�t�o||
+PULDNDP018|-- Seulement la temp�rature||
+PULDNDP047|- Indicateur de vent||
+PULDNDP054|Afficher cercle Aloha||
+PULDNDP013|Afficher ambigu�t� de position|b|
+PULDNDP008|Afficher puissance/gain|g|
+PULDNDP021|- Activer puissance/gain d�faut||
+PULDNDP020|- Activer puissance/gain mobile||
+PULDNDP023|Afficher attributs DF||
+PULDNDP123|Afficher largeur faiseau recherche auto (DF)||
+PULDNDP223|Afficher relev� recherche auto (DF)||
+PULDNDP035|Activer point estim�||
+PULDNDP036|- Afficher arc||
+PULDNDP037|- Afficher cap||
+PULDNDP038|- Afficher symbole||
+PULDNDP005|Afficher distance/rel�vement|d|
+PULDNDP024|Afficher �ge du dernier rapport||
+PULDNDP015|Effacer toutes stations !!!|E|
+PULDNDP016|Effacer toutes pistes !!!|f|
+PULDNDP025|Effacer histoire des objets/articles||
+PULDNDP048|Recharger histoire des objets/articles||
+PULDNDP049|Effacer indicatifs tactiques||
+PULDNDP050|Effacer historique des indicatifs tactiques||
+PULDNDP051|Choisir seulement les indicatifs tactiques||
+PULDNDP052|- Annoter les points de piste||
+PULDNDP055|Exporter tout|E|
+PULDNDP056|Exporter vers fichier KML||
+#
+# Units
+PULDNUT001|Activer mesures anglaises||
+PULDNUT002|M�tres||
+#
+# Menu "Messages"
+PULDNMG001|Composer un message �|C|
+PULDNMG002|Ouvrir les messages de groupe|g|
+PULDNMG003|Effacer tout message � exp�dier|E|
+PULDQUS001|Int�rroger toutes les stations|I|
+PULDQUS002|Int�rroger les stations IGate|n|
+PULDQUS003|Int�rroger les stations m�t�o|m|
+PULDNMG004|Configurer la r�ponse automatique|o|
+PULDNMG005|Activer la r�ponse automatique|R|
+PULDNMG006|Mode "Satellite Ack"|M|
+PULDNMG007|Voir les messages en attente|V|
+#
+# Menu "Interfaces"
+PULDNTNT04|Contr�le de l'interface|C|
+PULDNTNT03|D�sactiver transmission: Tout||
+PULDNTNT05|D�sactiver transmission: Ma position||
+PULDNTNT06|D�sactiver transmission: Objets/Articles||
+PULDNTNT11|Activer serveur sur port 2023||
+PULDNTNT01|Transmettre maintenant !|T|
+PULDNTNT07|Extraire piste GPS|F|
+PULDNTNT08|Extraire routes GPS|R|
+PULDNTNT09|Extraire points de cheminement GPS|W|
+PULDNTNT10|Extraire points de cheminement Garmin RINO|G|
+#
+# Menu "Help"
+PULDNHEL01|Information|I|
+PULDNHEL02|Index de l'Aide|A|#'
+PULDNHEL03|ACTIVER MODE BALISE DE DETRESSE|E|
+PULDNHEL04|!!! MODE BALISE DE DETRESSE !!!||
+PULDNHEL05|� propos de Xastir||
+#
+#
+# Mouse Menu Popup
+POPUPMA001|Options|O|
+POPUPMA00c|Centrer|C|
+POPUPMA015|Information sur la station||
+POPUPMA002|Zoom +|s|
+POPUPMA003|Zoom -|i|
+POPUPMA004|Niveau de zoom|N|
+POPUPMA005|Niveau 1|1|
+POPUPMA006|Niveau 16|6|
+POPUPMA007|Niveau 64|4|
+POPUPMA008|Niveau 256|2|
+POPUPMA009|Niveau 1024|0|
+POPUPMA010|Niveau 8192|8|
+POPUPMA017|Monde entier|M|
+POPUPMA016|Pos/zoom pr�c�dent||
+POPUPMA018|Objet/Article->Cr�er||
+POPUPMA019|Objet/Article->Modifier||
+POPUPMA025|D�placer ma station ici|H|
+POPUPMA011|Nord||
+POPUPMA012|Sud||
+POPUPMA013|Ouest||
+POPUPMA014|Est||
+POPUPMA020|Mesurer||
+POPUPMA021|D�placer||
+POPUPMA022|Me suivre||
+POPUPMA023|Modificateurs trouv�s !||
+POPUPMA024|SVP d�sactiver CapsLock/NumLock/ScrollLock/autres||
+POPUPMA026|Centre & zoom||
+POPUPMA027| Latitude||
+POPUPMA028| Longitude||
+POPUPMA029|Dessiner objets CAD||
+POPUPMA030|Dessiner||
+POPUPMA031|Fermer polygone||
+POPUPMA032|Effacer polygones CAD||
+POPUPMA033|**NOT USED**||
+POPUPMA034|Changer niveau de zoom||
+POPUPMA035|10% arri�re||
+POPUPMA036|10% avant||
+POPUPMA037|Aire||
+POPUPMA038|carr�||
+POPUPMA039|pieds carr�s||
+POPUPMA040|m�tres carr�s||
+POPUPMA041|Rel�vement||
+POPUPMA042|degr�s||
+POPUPMA043|Modifier ambigu�t� de position||
+POPUPMA044|Ambigu�t� de position est active, votre nouvelle position pourra sauter.||
+POPUPMA045|Objets pr�d�finis||
+POPUPMA046|Polygones CAD||
+POPUPMA047|Activer les objets CAD||
+POPUPMA048|Activer les �tiquettes CAD||
+POPUPMA049|Activer les commentaires CAD||
+POPUPMA050|Activer la probabilit� CAD||
+POPUPMA051|Activer la taille de la surface CAD||
+POPUPMA052|sq||
+POPUPMA053|ft||
+POPUPMA054|m�tres||
+POPUPMA055|mi|
+#
+#
+# Status line labels
+BBARZM0001|Zoom %s||
+BBARZM0002|Zoom %s Sv||
+BBARSTH001|%d/%d stations||
+BBARSTA000|%-9s Nouvel objet !||
+BBARSTA001|%-9s Nouvelle station !||
+BBARSTA002|%-9s||
+BBARSTA003|Chargement de cartes...||
+BBARSTA004|Cartes charg�es||
+BBARSTA005|Quadrillage de carte Lat/Long activ�||
+BBARSTA006|Quadrillage de carte Lat/Long d�sactiv�||
+BBARSTA007|Carte automatique activ�e||
+BBARSTA008|Carte automatique d�sactiv�e||
+BBARSTA009|Niveau de cartes activ�||
+BBARSTA010|Niveau de cartes d�sactiv�||
+BBARSTA011|R�ponse automatique d�sactiv�e||
+BBARSTA012|Fichier termin�...||
+BBARSTA013|Ouverture du port GPS||
+BBARSTA014|Fermeture du port GPS||
+BBARSTA015|R�ception de message GPS RMC||
+BBARSTA016|R�ception de message GPS GGA||
+BBARSTA017|R�seau d�connect� de l'h�te||
+BBARSTA018|Connexion r�seau d�passement de temps !||
+BBARSTA019|Recherche de l'h�te %s||#'
+BBARSTA020|Connect� � %s||
+BBARSTA021|�chec de la connexion !||
+BBARSTA022|Incapable de relier le socket !||
+BBARSTA023|H�te inconnu !||
+BBARSTA024|Serveur non sp�cifi�||#'
+BBARSTA025|H�te trouv�, connexion en cours %d||
+BBARSTA026|Attente de donn�es du GPS par HSP||
+BBARSTA027|Fermeture port HSP r�ception donn�e TNC..||
+BBARSTA028|Chargement de %s||
+BBARSTA029|Ouverture port m�t�o||
+BBARSTA030|Fermeture port m�t�o||
+BBARSTA031|Recherche d'h�te %d||#'
+BBARSTA032|Donn�es m�t�o d�cod�es||
+BBARSTA033|�cho de digipeater||
+BBARSTA034|Chargement de cartes alertes m�t�o||
+BBARSTA035|Attente de don�es du GPS par AUX||
+BBARSTA036|Fermeture port GPS r�ception donn�e TNC..||
+BBARSTA037|GPS m�t�o d�cod�es||
+BBARSTA038|Placez le changement sur ma station||
+BBARSTA039|Cr�ation de l'index de %s||
+BBARSTA040|Station d'amateur APRS(tm) %s||#'
+BBARSTA041|Attente de donn�es GPS..||
+BBARSTA042|Transmission objets/articles||
+BBARSTA043|Journalisation||
+BBARSTA044|Le rayon ALOHA est de %d%s||
+BBARSTA045|Chargement de symboles...||
+BBARSTA046|Rechargement des symboles...||
+BBARSTA047|Initialisation de ma station...||
+BBARSTA048|D�marrer interfaces...||
+BBARSTA049|Lit les dalles...||
+BBARSTA050|T�l�charge les dalles...||
+BBARSTA051|T�l�charge dalle %li de %li||
+#
+#
+# PopUp "View - Incoming Packet Data"
+WPUPDPD001|Affichage de donn�es paquet||
+WPUPDPD002|Donn�es du TNC seulement||
+WPUPDPD003|Donn�es du r�seau seulement||
+WPUPDPD004|Donn�es du TNC et du r�seau||
+WPUPDPD005|TNC||
+WPUPDPD006|R�seau||
+WPUPDPD007|Capacit� Station||
+WPUPDPD008|Seulement les miens||
+#
+# PopUp "View - Find Station"
+WPUPLSP001|Localiser une station||
+WPUPLSP002|Localiser l'indicatif||#'
+WPUPLSP003|Casse exacte|C|
+WPUPLSP004|Correspondance exacte|E|
+WPUPLSP005|Localiser maintenant !|L|
+WPUPLSP006|Localiser d�tresse !||
+WPUPLSP007|Recherche indicatif FCC/RAC||
+#
+# PopUp "Configure - Defaults"
+WPUPCFD001|Configurer d�fauts||
+WPUPCFD002|Au bout de combien de temps une station sera-t-elle consid�r�e �g�e ?||
+WPUPCFD003|15 min|1|
+WPUPCFD004|30 min|3|
+WPUPCFD005|45 min|4|
+WPUPCFD006|1 heure|h|
+WPUPCFD007|90 min|9|
+WPUPCFD008|2 heures|2|
+WPUPCFD009|Au bout de combien de temps une station ne sera-t-elle plus affich�e ?||
+WPUPCFD010|6 heures|6|
+WPUPCFD011|12 heures|e|
+WPUPCFD012|1 jour|j|
+WPUPCFD013|2 jours|o|
+WPUPCFD014|1 semaine|s|
+WPUPCFD015|Option de transmission||
+WPUPCFD016|Station fixe||
+WPUPCFD017|Station mobile + heure locale||
+WPUPCFD018|Station mobile + date/heure Zulu||
+WPUPCFD019|Station mobile + heure/secondes Zulu||
+WPUPCFD021|Position de station + m�t�o||
+WPUPCFD022|Position de station + date/heure Zulu + m�t�o||
+WPUPCFD023|Transmettre les donn�es m�t�o non trait�es ?||
+WPUPCFD024|Transmettre les objets/articles sous forme compr�ss�s ?||
+WPUPCFD025|Activer r�seau alterne ?|A|
+WPUPCFD026|Transmettre position � quel intervalle ?||
+WPUPCFD027|Afficher bulletins nouveaux||
+WPUPCFD028|Alerter si cl�s modificatrices (Verr.Num.)||
+WPUPCFD029|Voir bulletins avec distance z�ro||
+WPUPCFD030|D�sactiver identif. de duplic. posit.||
+WPUPCFD031|Charger des objets pr�d�finis � partir d'un fichier||
+WPUPCFD032|Mon parcour en une seule couleur||
+WPUPCFD033|ALTNET:||
+#
+# PopUp "Configure - Timing"
+WPUPCFTM01|Configurer temporisation||
+WPUPCFTM02|Intervalle transmission de position (min)||
+WPUPCFTM03|D�lai d'affichage faible d'une station (min)||
+WPUPCFTM04|Intervalle maximum de transmission des objets/articles (min)||#'
+WPUPCFTM05|D�lai de suppression d'affichage d'une station (heures)||
+WPUPCFTM06|Intervalle de lecture GPS (sec)||
+WPUPCFTM07|D�lai de suppression d'une station (jours)||
+WPUPCFTM08|Expiration de point estim� (min)||
+WPUPCFTM09|D�lai inter-char port s�rie (ms)||
+WPUPCFTM10|D�lai nouvelle piste (min)||
+WPUPCFTM11|Espace nouvelle piste (degr�s)||
+WPUPCFTM12|RINO -> Intervalle d'objets (min), 0 = D�sactiv�||
+WPUPCFTM13|Intervalle de capture instantan� (min)||
+#
+# PopUp "Configure Coordinate System"
+WPUPCFC001|Configurer syst�me de coordonn�es||
+WPUPCFC002|Choisir syst�me de coordonn�es||
+WPUPCFC003|dd.ddddd|d|
+WPUPCFC004|dd mm.mmm|m|
+WPUPCFC005|dd mm ss.s|s|
+WPUPCFC006|UTM|U|
+WPUPCFC007|USNG/MGRS2||
+WPUPCFC008|UTM avec zones sp�ciales||
+#
+# PopUp "Configure GPS"
+WPUPCFG001|Configurer GPS||
+WPUPCFG003|Port GPS seulement||
+WPUPCFG002|Utiliser la position GPS ?||
+WPUPCFG004|Options du GPS||
+WPUPCFG005|GPS seul||
+WPUPCFG006|TNC branch� au GPS (C�ble HSP)||
+WPUPCFG007|TNC branch� au GPS avec CTL-E||
+WPUPCFG008|Intervalle de temps GPS||
+WPUPCFG009|5 sec||
+WPUPCFG010|15 sec||
+WPUPCFG011|30 sec||
+WPUPCFG012|1 min||
+WPUPCFG013|2 min||
+WPUPCFG014|5 min||
+WPUPCFG015|10 min||
+WPUPCFG016|GPS branch� r�seau||
+WPUPCFG017|H�te GPSD||
+WPUPCFG018|Port GPSD||
+WPUPCFG019|GPS r�seau via GPSD||
+WPUPCFG020|Reconnexion sur �chec ?||
+WPUPCFG021|Connexion m�t�o r�seau||
+WPUPCFG022|H�te m�t�o||
+WPUPCFG023|Port m�t�o||
+#
+# Configure TNC (baud/style are also for WX)
+WPUPCFT001|Configurer le TNC||
+WPUPCFT002|Utiliser le TNC ?||
+WPUPCFT003|Port TNC||
+WPUPCFT004|Configuration du port||
+WPUPCFT005|300 bps||
+WPUPCFT006|1200 bps||
+WPUPCFT007|2400 bps||
+WPUPCFT008|4800 bps||
+WPUPCFT009|9600 bps||
+WPUPCFT010|19200 bps||
+WPUPCFT011|Voies UnProto||
+WPUPCFT012|Voie 1: %s via ||
+WPUPCFT013|Voie 2: %s via ||
+WPUPCFT014|Voie 3: %s via ||
+WPUPCFT015|Type de port||
+WPUPCFT016|8,N,1||
+WPUPCFT017|7,E,1||
+WPUPCFT018|7,O,1||
+WPUPCFT019|38400 bps||
+WPUPCFT020|57600 bps||
+WPUPCFT021|115200 bps||
+WPUPCFT022|230400 bps||
+WPUPCFT023|Configurer TNC +HSP GPS||
+WPUPCFT024|Type de donn�es||
+WPUPCFT025|Auto detection||
+WPUPCFT026|Type binaire||
+WPUPCFT027|Type ASCII||
+WPUPCFT028|Configurer TNC +AUX GPS||
+WPUPCFT029|COnfigurer TNC +INVALID ENUM||
+WPUPCFT030|Configurer TNC KISS||
+WPUPCFT031|Fichiers de configuration du TNC||
+WPUPCFT032|Nom du fichier de d�marrage du TNC||
+WPUPCFT033|Nom du fichier d'arr�t du TNC||#'
+WPUPCFT034|Param�tres KISS||
+WPUPCFT035|TXDelay (unit� 10 ms)||
+WPUPCFT036|Persistance (0 � 255)||
+WPUPCFT037|SlotTime (unit� 10 ms)||
+WPUPCFT038|TxTail (unit� 10 ms)||
+WPUPCFT039|Full duplex||
+WPUPCFT040|Configurer TNC Multi-Port KISS||
+WPUPCFT041|Port radio||
+WPUPCFT042|Propri�t�s d'interface: Chemin UNPROTO douteux !||
+WPUPCFT043|SVP choisissez un chemin plus court tel que WIDE2-2 or WIDE1-1,WIDE2-2||
+WPUPCFT044|Propri�t�s d'interface: Chemin IGATE douteux !||
+WPUPCFT045|Transmission avec chemin UNPROTO douteux !||
+WPUPCFT046|Transmission avec chemin IGATE douteux !||
+WPUPCFT047|Initialiser mode KISS au d�marrage||
+#
+#
+# PopUp "Configure WX Port"
+WPUPCFWX01|Configurer port m�t�o||
+WPUPCFWX02|Port m�t�o||
+WPUPCFWX03|Correction globale de pluviom�tre||
+WPUPCFWX04|.1 pouce/2.5mm||
+WPUPCFWX05|.01 pouce/.25mm||
+WPUPCFWX06|.1mm||
+WPUPCFWX07|Pas de correction||
+#
+# PopUp "Configure - Station"
+WPUPCFS001|Configurer la station||
+WPUPCFS002|Indicatif||
+WPUPCFS003|LAT||
+WPUPCFS004|deg||
+WPUPCFS005|min||
+WPUPCFS006|(N/S)||
+WPUPCFS007|LONG||
+WPUPCFS008|(E/O)||
+WPUPCFS009|Symbole de station||
+WPUPCFS010|Groupe/superposition||
+WPUPCFS011|Symbole||
+WPUPCFS028|Choisir||
+WPUPCFS012|Puissance - Hauteur (HAAT) - Gain - Directivit�||
+WPUPCFS013|D�sactiver PHG||
+WPUPCFS014|Hauteur de l'antenne||#'
+WPUPCFS015|Gain de l'antenne||#'
+WPUPCFS016|Omni||
+WPUPCFS017|Commentaire:||
+WPUPCFS018|Ambigu�t� de position||
+WPUPCFS019|Rien||
+WPUPCFS020|.11 milles||
+WPUPCFS021|1.15 milles||
+WPUPCFS022|11.51 milles||
+WPUPCFS023|69.09 milles||
+WPUPCFS024|.18 kilom�tres||
+WPUPCFS025|1.85 kilom�tres||
+WPUPCFS026|18.53 kilom�tres||
+WPUPCFS027|111.19 kilom�tres||
+WPUPCFS029|Transmettre positions compress�es|C|
+#
+# PopUp "Object/Item"
+POPUPOB001|Objet/Article||
+POPUPOB002|Nom||
+POPUPOB003|Cr�er nouvel objet||
+POPUPOB004|Supprimer objet||
+POPUPOB005|Modifier objet||
+POPUPOB006|Cr�er nouvel article||
+POPUPOB007|Objet polygonal||
+POPUPOB008|Objet polygonal||
+POPUPOB009|Couleur vive||
+POPUPOB010|Remplis de couleur||
+POPUPOB011|Cercle||
+POPUPOB012|Ligne-droite '/'||
+POPUPOB013|Ligne-gauche '\'||#'
+POPUPOB014|Triangle||
+POPUPOB015|Rectangle||
+POPUPOB016|Noir||
+POPUPOB017|Bleu||
+POPUPOB018|Vert||
+POPUPOB019|Cyan||
+POPUPOB020|Rouge||
+POPUPOB021|Violet||
+POPUPOB022|Jaune||
+POPUPOB023|Gris||
+POPUPOB024|D�calage haut:||
+POPUPOB025|D�calage gauche (sauf '/'):||
+POPUPOB026|Couloir:||
+POPUPOB027|Options g�n�riques||
+POPUPOB028|Placement||
+POPUPOB029|Activer panneau||
+POPUPOB030|Texte sur le panneau||#'
+POPUPOB031|Panneau||
+POPUPOB032|Activer compression||
+POPUPOB033|Supprimer article||
+POPUPOB034|Modifier article||
+POPUPOB035|Altitude (pieds):||
+POPUPOB036|Vitesse (noeuds):||
+POPUPOB037|Cap:||
+POPUPOB038|Objet DF||
+POPUPOB039|Signal - Hauteur (HAAT) - Gain - Directivit�||
+POPUPOB040|Largeur de faisceau - Rel�vement||
+POPUPOB041|Antenne omni||
+POPUPOB042|Antenne dirig�e||
+POPUPOB043|Inutile||
+POPUPOB044|Adopter objet||
+POPUPOB045|Adopter article||
+POPUPOB046|Rel�vement DF:||
+POPUPOB047|Cercles de probabilit�||
+POPUPOB048|Objet Map View||
+POPUPOB049|Min (mi):||
+POPUPOB050|Max (mi):||
+#
+# PopUp "Configure Internet"
+WPUPCFI001|Configurer Internet||
+WPUPCFI002|H�te ||
+WPUPCFI003|Port ||
+WPUPCFI004|(H�te secondaire)||
+WPUPCFI005|H�te1||
+WPUPCFI006|Port1||
+WPUPCFI007|H�te2||
+WPUPCFI008|Port2||
+WPUPCFI009|Code d'acc�s||#'
+WPUPCFI010|(Laisser vide si nul)||
+WPUPCFI011|Reconnexion sur erreur r�seau ?||
+WPUPCFI012|Fonction IGate ?||
+WPUPCFI013|Diffusion de messages par le TNC lorsqu'en IGate ?||#'
+WPUPCFI014|Archivage des transactions IGate ?|||
+WPUPCFI015|Param�tres du filtre||
+#
+# PopUp "Configure Database"
+WPUPCFID01|Configurer base de donn�es (TBD)||
+WPUPCFID02|H�te ||
+WPUPCFID03|Port ||
+WPUPCFID04|(H�te secondaire)||
+WPUPCFID05|H�te1||
+WPUPCFID06|Port1||
+WPUPCFID07|H�te2||
+WPUPCFID08|Port2||
+WPUPCFID09|Code d'acc�s||#'
+WPUPCFID10|(Laisser vide si nul)||
+WPUPCFID11|Reconnexion sur erreur r�seau ?||
+WPUPCFID12|Fonction IGate ?||
+WPUPCFID13|Diffusion de messages par le TNC lorsqu'en IGate ?||#'
+WPUPCFID14|Archivage des transactions IGate ?|||
+WPUPCFID15|Param�tres du filtre||
+#
+# PopUp "Configure AGWPE"
+WPUPCFIA01|Configurer AGWPE||
+WPUPCFIA02|H�te ||
+WPUPCFIA03|Port ||
+WPUPCFIA04|(H�te secondaire)||
+WPUPCFIA05|H�te1||
+WPUPCFIA06|Port1||
+WPUPCFIA07|H�te2||
+WPUPCFIA08|Port2||
+WPUPCFIA09|Code d'acc�s||#'
+WPUPCFIA10|(Laisser vide si nul)||
+WPUPCFIA11|Reconnexion sur erreur r�seau ?||
+WPUPCFIA12|Fonction IGate ?||
+WPUPCFIA13|Diffusion de messages par le TNC lorsqu'en IGate ?||#'
+WPUPCFIA14|Archivage des transactions IGate ?|||
+WPUPCFIA15|RadioPort de transmission||
+#
+# PopUp "Configure Audio Alarms"
+WPUPCFA001|Configurer alarmes sonores||
+WPUPCFA002|Commande audio � utiliser||
+WPUPCFA003|Alarme pour:||
+WPUPCFA004|Fichier sonore||
+WPUPCFA005|Nouvelle station||
+WPUPCFA006|Nouveau message||
+WPUPCFA007|Proximit�||
+WPUPCFA008|Ouverture de bande||
+WPUPCFA009|Distance minimum||
+WPUPCFA010|Distance maximum||
+WPUPCFA011|Alerte m�t�o||
+#
+# PopUp "Configure Speech"
+WPUPCFSP01|Configurer parole||
+WPUPCFSP02|Parole pour:||
+WPUPCFSP03|Nouvelle station||
+WPUPCFSP04|Alerte nouveau message||
+WPUPCFSP05|Texte nouveau message||
+WPUPCFSP06|Proximit�||
+WPUPCFSP07|Ouverture de bande||
+WPUPCFSP08|Alerte m�t�o||
+WPUPCFSP09|Station suivie � proximit�||#'
+#
+# PopUp "Track Station"
+WPUPTSP001|Suivre station||
+WPUPTSP002|Suivre l'indicatif||#'
+WPUPTSP003|Casse exacte||
+WPUPTSP004|Correspondance exacte||
+WPUPTSP005|Suivre maintenant !||
+WPUPTSP006|Annuler suivi||
+WPUPTSP007|T�l�charger piste||
+WPUPTSP008|Indicatif||
+WPUPTSP009|D�but de piste (depuis .. heures)||
+WPUPTSP010|Longueur de piste (heures)||
+#
+# PopUp "Messages..."
+WPUPMSB001|Boite d'envoi %d||#'
+WPUPMSB002|Boite d'envoi au groupe %d||#'
+WPUPMSB003|Indicatif de station:||
+WPUPMSB004|Ident. du groupe:||
+WPUPMSB005|Nouvel/Refresh indicatif||
+WPUPMSB006|Nouveau groupe||
+WPUPMSB007|Effacer histoire de messages||
+WPUPMSB008|Message:||
+WPUPMSB009|Transmettre maintenant !||
+WPUPMSB010|Voie:||
+WPUPMSB011|Annuler messages en suspens||
+WPUPMSB012|RAZ minuterie Temporisateur||
+WPUPMSB013|seq||
+WPUPMSB014|type||
+WPUPMSB015|Broadcast||
+WPUPMSB016|*EXPIRATION*||
+WPUPMSB017|*ANNULE*||
+WPUPMSB018|*REJETE*||
+WPUPMSB019|Changer chemin||
+WPUPMSB020|Utiliser chemin(s) par d�faut||
+WPUPMSB021|Direct (pas de chemin)||
+WPUPMSB022|Chemin inverse (pour info):||
+#
+# PopUp "Auto Reply"
+WPUPARM001|Modifier r�ponse automatique||
+WPUPARM002|R�ponse:||
+#
+# PopUp "Help Index"
+WPUPHPI001|Index d'Aide||#'
+WPUPHPI002|Lire||
+#
+# PopUp "Station Info"
+WPUPSTI000|Objet de: %s||
+WPUPSTI001|Information de station||
+WPUPSTI002|Composer un message||
+WPUPSTI003|Chercher dans la base FCC||
+WPUPSTI004|Chercher dans la base RAC||
+WPUPSTI005|Paquets recu: %d Derni�re transmission: ||
+WPUPSTI006|Entendu sur le TNC %d, ||
+WPUPSTI007|Entendu ||
+WPUPSTI008|derni�rement sur port local||
+WPUPSTI009|derni�rement sur TNC %d||
+WPUPSTI010|derni�rement sur Internet %d||
+WPUPSTI011|derni�rement dans fichier||
+WPUPSTI012|derni�rement sur inconnu||
+WPUPSTI013|, et a boug�||
+WPUPSTI014|Puissance/gain/etc.:||
+WPUPSTI016|Altitude: %.0f%s ||
+WPUPSTI017|Cap: %s� ||
+WPUPSTI018|Vitesse: %.1f km/h||
+WPUPSTI019|Vitesse: %.1f milles/h||
+WPUPSTI020|%0.1f milles||
+WPUPSTI021|%0.1f km||
+WPUPSTI022|Distance de ma station: %s Rel�vement de ma station: %s||
+WPUPSTI023|Derni�re position : ||
+WPUPSTI024|Donn�es m�t�o %c:%s||
+WPUPSTI025|Cap des vents: %s� Vitesse: %03d km/h||
+WPUPSTI026|Cap des vents: %s� Vitesse: %s milles/h||
+WPUPSTI027| Rafales: %03d km/h||
+WPUPSTI028| Rafales: %s milles/h||
+WPUPSTI029|Temp�rature: %02.1f�C ||
+WPUPSTI030|Temp�rature: %s�F ||
+WPUPSTI031|Humidit�: %s%% ||
+WPUPSTI032| Humidex: %02.1f�C ||
+WPUPSTI033|Baro: %s hPa||
+WPUPSTI034|Neige: %0.1f (cm/24h||
+WPUPSTI035|Neige: %0.0f (pouces/24h)||
+WPUPSTI036|Pluie: ||
+WPUPSTI037|%0.2f (mm/h) ||
+WPUPSTI038|%0.2f (pouces/h) ||
+WPUPSTI039|%0.2f (mm/jour) ||
+WPUPSTI040|%0.2f (pouces/jour) ||
+WPUPSTI041|%0.2f (mm/depuis minuit)||
+WPUPSTI042|%0.2f (pouces/depuis minuit)||
+WPUPSTI043|Route des donn�es: %s||
+WPUPSTI044|Commentaire %02d/%02d %02d:%02d : %s||
+WPUPSTI045|Effacer la piste||
+WPUPSTI046|Pluie Totale: ||
+WPUPSTI047|%0.2f (mm)||
+WPUPSTI048|%0.2f (pouces)||
+WPUPSTI049|Informations suivi||
+WPUPSTI050|Messages non confirm�s||
+WPUPSTI051|Info station en direct||
+WPUPSTI052|Info station version||
+WPUPSTI053|Modifier objet/article||
+WPUPSTI054|Sauver piste||
+WPUPSTI055|Echo de:||
+WPUPSTI056|Activer actualisation automatique||
+WPUPSTI057|Omni-DF: %s||
+WPUPSTI058|Rel�vement DF: %s||
+WPUPSTI059|Etat %02d/%02d %02d:%02d : %s||
+WPUPSTI060|Temp combustible: %02.1f�C ||
+WPUPSTI061|Temp combustible: %s�F ||
+WPUPSTI062|Humidit� combustible: %s%% ||
+WPUPSTI063|Baro: %0.2f in Hg||
+WPUPSTI064|Chercher alerte NWS||
+WPUPSTI065|Indicatif tactique: %s||
+WPUPSTI066|Assigner un indicatif tactique||
+WPUPSTI067|Port�e actuelle : %d milles||
+WPUPSTI068|nul||
+WPUPSTI069|d�faut||
+WPUPSTI070|HAAT||
+WPUPSTI071|omni||
+WPUPSTI072|port�e||
+WPUPSTI073|Mauvais PHG||
+WPUPSTI074|Mauvais SHG||
+WPUPSTI075|Port�e DF||
+WPUPSTI076|Pas de signal d�tect�||
+WPUPSTI077|Signal d�tect� (peut-�tre))||
+WPUPSTI078|Signal d�tect� non d�codable||
+WPUPSTI079|Signal faible, parfois d�codable||
+WPUPSTI080|Signal brouill� mais copiable||
+WPUPSTI081|Un peu de bruit, avec un signal facilement d�codable||
+WPUPSTI082|Bon signal avec un peu de bruit||
+WPUPSTI083|Signal presque sans bruit||
+WPUPSTI084|Signal sans bruit||
+WPUPSTI085|Signal tr�s fort sans bruit||
+WPUPSTI086|MAUVAIS RELEVEMENT||
+WPUPSTI087|MAUVAIS NRQ||
+WPUPSTI088|Largeur de faisceau DF||
+WPUPSTI089|Longueur DF||
+WPUPSTI090|Invalide||
+WPUPSTI091|Changer la couleur de la piste||
+WPUPSTI092|Effacer rel�vements DF||
+#
+#
+# PopUp "ALOHA Statistics"
+WPUPALO001|Rayon ALOHA: %d %s||
+WPUPALO002|Stations dans le cercle ALOHA: %d||
+WPUPALO003| Digis: %d||
+WPUPALO004| Mobiles (en mouvement): %d||
+WPUPALO005| Mobiles (autres): %d||
+WPUPALO006| Stations m�t�o: %d||
+WPUPALO007| Stations fixes: %d||
+WPUPALO008|Dernier calcul il y a %d %s %d %s.||
+WPUPALO666|Rayon ALOHA pas encore calcul�||
+#
+#
+# FCC-RAC Call Look up
+STIFCC0001|Recherche base de donn�es FCC||
+STIFCC0002|Recherche base de donn�es RAC||
+STIFCC0003|Nom:||
+STIFCC0004|Adresse:||
+STIFCC0005|Ville:||
+STIFCC0006|Etat:||
+STIFCC0007|Code postal:||
+STIFCC0008|License de base ||
+STIFCC0009|License avanc�e ||
+STIFCC0010|5 mots/min ||
+STIFCC0011|12 mots/min ||
+#
+#
+# FCC-RAC Call Look up
+STIFCC0100|Index FCC ancien, restauration||
+STIFCC0101|Recherche d'indicatif||
+STIFCC0102|Indicatif non trouv� !||
+STIFCC0103|Index RAC ancien, restauration||
+#
+#
+# Band open message
+UMBNDO0001|� une distance de||
+#
+#
+# Universal Options
+UNIOP00001|OK||
+UNIOP00002|Annuler||
+UNIOP00003|Fermer||
+UNIOP00004|milles||
+UNIOP00005|km||
+UNIOP00006|P�riph�rique||
+UNIOP00007|Ajouter||
+UNIOP00008|Supprimer||
+UNIOP00009|Propri�t�s||
+UNIOP00010|Permettre transmission ?||
+UNIOP00011|Activer au d�marrage ?||
+UNIOP00012|km/h||
+UNIOP00013|milles/h||
+UNIOP00014|�C||
+UNIOP00015|�F||
+UNIOP00016|mm||
+UNIOP00017|pouces||
+UNIOP00018|mm/jour||
+UNIOP00019|pouces/jour||
+UNIOP00020|mm/h||
+UNIOP00021|pouces/h||
+UNIOP00022|mm/minuit||
+UNIOP00023|pouces/minuit||
+UNIOP00024|deg||
+UNIOP00025|hPa||
+UNIOP00026|%||
+UNIOP00027|pouces Hg||
+UNIOP00028|mm Hg||
+UNIOP00029|R�gler l'horloge syst�me sur celle du GPS ?||
+UNIOP00030|R�p�teur digi ?||
+UNIOP00031|m||
+UNIOP00032|Appliquer|||
+UNIOP00033|Annuler||
+UNIOP00034|min||
+UNIOP00035|hr||
+UNIOP00036|jour||
+UNIOP00037|Send Control-E to get GPS data?||
+UNIOP00038|Add Delay||
+#
+# PopUp "Station Chooser"
+STCHO00001|Choix de station||
+#
+# DISPLAY WX ALERT
+WPUPWXA001|Alerte m�t�o||
+WPUPWXA002|Liste d'alertes m�t�o||
+#
+# PopUp "Configure - Interfaces"
+WPUPCIF001|Interfaces install�es||
+WPUPCIF002|Choix du type d'interface||
+#
+# PopUp "Configure AX.25 TNC"
+WPUPCAX001|Configurer TNC AX.25||
+WPUPCAX002|Nom de l'interface AX.25||#'
+#
+# Interface device names
+IFDNL00000|Aucune||
+IFDNL00001|TNC port s�rie||
+IFDNL00002|TNC s�rie + GPS sur c�ble HSP||
+IFDNL00003|GPS port s�rie||
+IFDNL00004|M�t�o port s�rie||
+IFDNL00005|Serveur Internet||
+IFDNL00006|TNC AX25||
+IFDNL00007|GPS r�seau (par gpsd)||
+IFDNL00008|M�t�o par r�seau||
+IFDNL00009|TNC s�rie + GPS sur c�ble AUX||
+IFDNL00010|TNC KISS s�rie||
+IFDNL00011|Base de donn�es par r�seau (pas encore impl�ment�)||
+IFDNL00012|AGWPE par r�seau||
+IFDNL00013|TNC Multi-Port KISS s�rie||
+IFDNL00014|Base de donn�es SQL (Experimental)||
+#
+# Interface device info
+IFDIN00000|%s %2d %s sur port s�rie %s %s||
+IFDIN00001|%s %2d %s connect� � %s:%d %s||
+IFDIN00002|%s %2d %s avec interface nomm�e %s %s||
+IFDIN00003|%s %2d %s %s %s %s||
+IFDIN00004|%s %2d %s %s %s:%d %s||
+IFDIN00005|%s %2d %s %s %s %s||
+IFDIN00006|INACTIF||
+IFDIN00007| ACTIF ||
+IFDIN00008|ERREUR ||
+IFDIN00009|INCONNU||
+#
+# PopUp "Interface control"
+IFPUPCT000|Contr�le d'interface||#'
+IFPUPCT001|D�marrer||
+IFPUPCT002|Arr�ter||
+IFPUPCT003|D�marrer toutes||
+IFPUPCT004|Arr�ter toutes||
+#
+# IGate control
+IGPUPCF000|Options IGate||
+IGPUPCF001|Arr�ter traffic Internet||
+IGPUPCF002|Autoriser RF vers Internet seulement||
+IGPUPCF003|Autoriser RF->Inet et Inet->RF||
+IGPUPCF004|Voie Igate -> RF ||
+#
+# WX Station
+WXPUPSI000|Station m�t�o||
+WXPUPSI001|Type de station m�t�o||
+WXPUPSI002|Donn�es courantes||
+WXPUPSI003|Cap des vents||
+WXPUPSI004|Vitesse des vents||
+WXPUPSI005|Rafales||
+WXPUPSI006|Temp�rature||
+WXPUPSI007|Pr�cipitation totale||
+WXPUPSI008|Pr�cipitation totale journali�re||
+WXPUPSI009|Barom�tre||
+WXPUPSI010|Humidit�||
+WXPUPSI011|Peet Bros ULTIMETER 2000 (mode acquisition de donn�es)||
+WXPUPSI012|Peet Bros ULTIMETER II||
+WXPUPSI013|Peet Bros ULTIMETER 2000 (mode paquet)||
+WXPUPSI014|Pr�cipitation horaire totale||
+WXPUPSI015|Total pr�cipitation 24 hrs||
+WXPUPSI016|Qualimetrics Q-Net||
+WXPUPSI017|Peet Bros ULTIMETER 2000 (mode complet)||
+WXPUPSI018|Point de ros�e||
+WXPUPSI019|Vents max.||
+WXPUPSI020|Facteur �olien||
+WXPUPSI021|Facteur humidex||
+WXPUPSI022|Baro 3 heures||
+WXPUPSI023|Temp�rature max.||
+WXPUPSI024|Temp�rature min.||
+WXPUPSI025|Radio Shack WX-200/Oregon Scientific WM-918||
+WXPUPSI026|Davis Weather Monitor II/Wizard III/Vantage Pro||
+WXPUPSI027|LaCrosse WX-23xx||
+WXPUPSI028|Davis APRS Data Logger||
+#
+# Station Lists
+LHPUPNI000|Toutes stations||
+LHPUPNI001|Stations mobiles||
+LHPUPNI002|Stations m�t�o||
+LHPUPNI003|Stations locales (via TNC)||
+LHPUPNI004|Derni�res stations||
+LHPUPNI005|Objets et articles||
+LHPUPNI006|Mes objets et articles||
+LHPUPNI010|No.||
+LHPUPNI011|Indicatif||
+LHPUPNI012|#Paq||
+LHPUPNI013|Heure derni�re pos.||
+LHPUPNI014|Chemin||
+LHPUPNI015|PHG||
+LHPUPNI016|Commentaires||
+LHPUPNI100|Cap||
+LHPUPNI101|Vit.||
+LHPUPNI102|Alt.||
+LHPUPNI103|Lat||
+LHPUPNI104|Long||
+LHPUPNI105|#Paq||
+LHPUPNI106|LSV||
+LHPUPNI107|CFMS||
+LHPUPNI108|DFMS||
+LHPUPNI200|Cap||
+LHPUPNI201|Vit||
+LHPUPNI202|GST||
+LHPUPNI203|Temp||
+LHPUPNI204|Hum||
+LHPUPNI205|Baro||
+LHPUPNI206|RN-H||
+LHPUPNI207|RNSM||
+LHPUPNI208|RN24||
+LHPUPNI209|Lat/Lon ou UTM||
+#
+# Maps WX Alert styles
+PULDNMAT01|Voir cartes alertes au dessus des autres cartes||
+PULDNMAT02|Voir cartes alertes en desous des autres cartes||
+#
+# Error/popup messages
+POPEM00001|Erreur localisation !||
+POPEM00002|Station %s non trouv�e !||
+POPEM00003|Erreur de suivi !||
+POPEM00004|Erreur d'interface !||#'
+POPEM00005|Nom de port AX.25 invalide %s||
+POPEM00006|Nom de port AX.25 invalide %s||
+POPEM00007|Indicatif invalide %s||
+POPEM00008|Destination AX25 indicatif ou relais digi invalide||
+POPEM00009|Erreur ouverture socket AX.25, %s||
+POPEM00010|Erreur liaison socket AX.25, %s||
+POPEM00011|Pas de connection � l'indicatif AX.25 %s||#'
+POPEM00012|Erreur AX.25 sur sortie UI||
+POPEM00013|Probl�me avec fichier axports||
+POPEM00014|Nom de port AX.25 invalide %s||
+POPEM00015|Erreur ouverture d'interface %d Erreur majeure||#'
+POPEM00016|Erreur ouverture d'interface %d D�passement de temps||#'
+POPEM00017|Plus d'interfaces disponible !||#'
+POPEM00018|Demande de donn�e - Message � une ligne||
+POPEM00019|Transmission hors service port %d||
+POPEM00020|Erreur base de donn�es !||
+POPEM00021|Support AX.25 non compil� dans Xastir !||#'
+POPEM00022|Erreur d'entr�e !||#'
+POPEM00023|Aucun nom de lieu sp�cifi� !||
+POPEM00024|Le nom de lieu sp�cifi� est en cours d'utilisation !||#'
+POPEM00025|Pas trouv� !||
+POPEM00026|Suivi commencera quand elle appara�tra||
+POPEM00027|Mauvaise info. Certains champs vides ?||
+POPEM00028|Ne peut ouvrir fichier||
+POPEM00029|Trouv� !||
+POPEM00030|Symbole de station m�t�o||
+POPEM00031|Chang� en symbole m�t�o '/_', autres possibilit�s: '\_' '/W' et '\W'||
+POPEM00032|Attention: utilise symbole du "National Weather Service" !||
+POPEM00033|Pas de donn�es GPS !||
+POPEM00034|TX de ma position d�sactiv� jusqu'a r�ception de bonnes donn�es GPS !||#'
+POPEM00035|Avertissement||
+POPEM00036|Avis||
+POPEM00037|Interface HSP pr�sente: temporisation GPS augment�e||
+POPEM00038|Conflit de nom avec un Objet/Item/Station d�j� existant||
+POPEM00039|Caract�re ill�gal, remplac� par un point||
+POPEM00040|Le chemin de sortie personnalis� a �t� perdu||
+POPEM00041|Traitement d'un autre fichier en cours. Attendez, puis r�essayez||
+POPEM00042|L'object ne m'appartient pas ! Essayez d'adopter l'objet d'abord.||
+POPEM00043|Ce n'est pas un objet ou article !||
+POPEM00044|R�cup�ration de piste Findu : �chec||
+POPEM00045|R�cup�ration de piste Findu : Termin�||
+POPEM00046|La biblioth�que Berkeley DB ne correspond pas ! D�sactivation du cache des cartes.||
+POPEM00047|Toutes les transmissions sont DESACTIVEES. Les balises d'urgences ne seront PAS envoy�es!||
+POPEM00048|Mode balise d'URGENCE!||
+POPEM00049|MODE BALISE D'URGENCE, transmission toutes les 60 secondes!||
+POPEM00050|Interfaces ou trans.position DESACTIVEES. Les balises d'urgences ne seront PAS envoy�es!||
+POPEM00051|R�seau alternatif (ALTNET) activ� (Menu Fichier->Configurer->Defauts)||
+POPEM00052|Indicatif est VIDE!||
+POPEM00053|Message est VIDE!||
+POPEM00054|Vous essayez de communiquer avec vous m�me!||
+#
+# Jump Location
+JMLPO00001|Afficher Cartes Favorites||
+JMLPO00002|Aller !||
+JMLPO00003|Nouveau nom de lieu:||
+#
+# Bulletins
+BULMW00001|Bulletins||
+BULMW00002|Limiter la port�e � (0, aucune limite)||
+BULMW00003|Changer port�e||
+#
+# All Message Traffic
+AMTMW00001|Tout trafic des messages||
+AMTMW00002|Limiter la port�e � (0, aucune limite)||
+#
+# Speech Strings
+SPCHSTR001|kilom�tres||
+SPCHSTR002|m�tres||
+SPCHSTR003|milles||
+SPCHSTR004|yards||
+SPCHSTR005|%s, distance est %d %s.||
+SPCHSTR006|%s, distance est %.1f %s.||
+SPCHSTR007|%s, distance est %d %s %s %s.||
+SPCHSTR008|%s, distance est %.1f %s %s %s.||
+SPCHSTR009|Nouvelle alerte m�t�o||
+SPCHSTR010|Nouvel indicatif||
+SPCHSTR011|Re�u, D X, %s, � une distance de %.1f %s||
+#
+#
+SPCHDIRN00|au nord de||
+SPCHDIRS00|au sud de||
+SPCHDIRE00|� l'est de||
+SPCHDIRW00|� l'ouest de||
+SPCHDIRNE0|au nord-est de||
+SPCHDIRNW0|au nord-ouest de||
+SPCHDIRSE0|au sud-est de||
+SPCHDIRSW0|au sud-ouest de||
+#
+# Symbol Selection Dialog
+SYMSEL0001|Choisir symbole||
+SYMSEL0002|Table de symboles primaire||
+SYMSEL0003|Table de symboles secondaire||
+#
+# Print Properties Dialog
+PRINT0001|Propri�t�s d'impression||
+PRINT0002|Taille du papier||
+PRINT0003|Rotation automatique d'image||
+PRINT0004|Tourner image 90� � gauche||
+PRINT0005|Proportion automatique d'image||
+PRINT0006|�chelle:||
+PRINT0007|Forcer le fond � �tre blanc||
+PRINT0008|Imprimer en noir et blanc||
+PRINT0016|Inverser couleurs||
+PRINT0009|R�solution Postscript:||
+PRINT0010|Pr�visualiser||
+PRINT0011|Imprimer dans un fichier||
+PRINT0012|Sauvegarde de l'image dans un fichier...||
+PRINT0013|Conversion Postscript...||
+PRINT0014|Cr�ation du fichier d'impression finie||
+PRINT0015|Etat d'impression||
+#
+# Print Properties Dialog
+PRINT1001|Directement �:||
+PRINT1002|Via Previewer:||
+#
+# Locate Feature Dialog
+FEATURE001|Nom:||
+FEATURE002|Etat/Province:||
+FEATURE003|Comt�:||
+FEATURE004|Quadrant de carte:||
+FEATURE005|Type :||
+FEATURE006|Fichier GNIS :||
+FEATURE007|Adresse :||
+FEATURE008|Ville :||
+FEATURE009|Marquer la destination||
+FEATURE010|Code postal :||
+FEATURE011|Fichier Geocoding||
+#
+# Coordinate Calculator Dialog
+COORD001|Calculatrice de coordon�es||
+COORD002|Calc||
+COORD003|Calculer||
+COORD004|Effacer||
+COORD005|UTM||
+COORD006|Latitude ou||
+COORD007|Longitude ou||
+COORD008|Zone||
+COORD009|UTM vers l'est||
+COORD010|UTM vers le nord||
+COORD011| Degr�s d�cimaux: ||
+COORD012| Degr�s/Minutes d�cimales: ||
+COORD013| Degr�s/Minutes/secondes d�c.: ||
+COORD014| Universal Transverse Mercator: ||
+COORD015|Syst. de r�f. grille militaire: ||
+COORD016| Grille Locator Maidenhead: ||
+COORD017| ** D�sol�, entr�e non reconnue ! **||
+COORD018| ** SVP utilisez l'un de ces formats d'entr�e: **||
+#
+#
+# Smart Beaconing Dialog
+SMARTB001|Balise intelligente (Smart Beaconing)||
+SMARTB002|Intervalle maximal (secs):||
+SMARTB003|Vitesse haute (m/h):||
+SMARTB004|Vitesse haute (k/h):||
+SMARTB005|Intervalle minimal (mins):||
+SMARTB006|Vitesse basse (m/h):||
+SMARTB007|Vitesse basse (k/h):||
+SMARTB008|Virage minimum (deg):||
+SMARTB009|Pente de virage:||
+SMARTB010|Temps d'attente (secs):||#'
+SMARTB011|Activer SmartBeaconing(tm)||
+#
+#
+#
+# Gamma Adjust Dialog
+GAMMA001|Ajuster correction de gamma||
+GAMMA002|Correction de gamma||
+#
+#
+#
+# Map labels font Dialog
+MAPFONT001|Changer police de carat�res||
+MAPFONT002|Police de carat�res||
+MAPFONT003|Police de carat�re des cartes Minusc||
+MAPFONT004|Police de carat�re des cartes Petite||
+MAPFONT005|Police de carat�re des cartes Moyenne||
+MAPFONT006|Police de carat�re des cartes Large||
+MAPFONT007|Police de carat�re des cartes Enorme||
+MAPFONT008|Police de carat�re des cartes Border||
+MAPFONT009|Police de carat�re des menus||
+MAPFONT010|Police de carat�re des Stations||
+MAPFONT011|Police de carat�re de l'ID ATV||
+#
+#
+#
+# Distance/Bearing on status line
+PULDNDB001|Etat dist/rel�vement||
+#
+#
+# GPS Transfer Operations
+GPS001|Transfert GPS||
+GPS002|Nom de fichier||
+GPS003|Choisir couleur||
+GPS004|Rouge||
+GPS005|Vert||
+GPS006|Noir||
+GPS007|Blanc||
+GPS008|Orange||
+GPS009|Bleu||
+GPS010|Jaune||
+GPS011|Violet||
+#
+#
+# Map Properties Dialog
+MAPP001|Caract�ristiques des cartes||
+MAPP002|Max Min Carte Afficher USGS Auto||
+MAPP003|Zoom Zoom Couche Remplie DRG Cartes Voie/Fichier||
+MAPP004|Modifier Couche->||
+MAPP005|Remplie->||
+MAPP006|Oui||
+MAPP007|Non||
+MAPP008|AutoCartes->||
+MAPP009|Max Zoom->||
+MAPP010|Min Zoom->||
+MAPP011|Auto||
+MAPP012|USGS DRG->||
+#
+#
+# Time Strings
+TIME001|jour||
+TIME002|jours||
+TIME003|heure||
+TIME004|heures||
+TIME005|minute||
+TIME006|minutes||
+TIME007|seconde||
+TIME008|secondes||
+#
+#
+# Map Caching
+CACHE001|La carte se trouve dans le cache||
+CACHE002|Chargement de la carte en m�moire||
+CACHE003|Carte non trouv�e dans le cache...||
+#
+#
+# Map Screen Misc
+RANGE001|�CHELLE||
+#
+#
+# GPS Status
+GPSS001|WAAS ou PPS||
+GPSS002|DGPS||
+GPSS003|SPS valide||
+GPSS004|Invalide||
+GPSS005|Sats/vue||
+GPSS006|Rep�re||
+GPSS007|! Les donn�es GPS ont plus de 30 secondes !||
+GPSS008|Simulation||
+GPSS009|Manuel||
+GPSS010|Estim�||
+GPSS011|RTK flottant||
+GPSS012|RTK||
+#
+#
+# Popup cad_dialog to obtain CAD object data
+CADPUD001|Object surface||
+CADPUD002|Etiquette surface:||
+CADPUD003|Commentaire:||
+CADPUD004|Probabilit� (%):||
+CADPUD005|OK||
+CADPUD006|Dialogue CAD||
+CADPUD007|Montrer/�diter les d�tails||
+CADPUD008|Annulerl||
+CADPUD009|Effacer les objets CAD ?||
+CADPUD010|Tout effacer||
+CADPUD011|Effacer la s�lection||
+CADPUD012|Continue||
+CADPUD013|pointilli�s||
+CADPUD014|Double pointilli�s||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA001|Carte XASTIR de %s (haut gauche) � %s (bas droit). UTM %d m grid, %s datum. ||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA002|carte XASTIR de %s (haut gauche) � %s %s (bas droit). Lat/Long grid, %s datum.||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA003|Carte XASTIR Map de %s (haut gauche) � %s (bas droit). UTM zones, %s datum.||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST001|MySQL (lat/long)||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST002|Postgreql avec Postgis||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST003|MySQL (spatial)||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA01|Sch�ma simple Xastir||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA02|Sch�ma CAD Xastir||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA03|Sch�ma complet Xastir||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA04|Sch�ma APRSWorld||
diff --git a/config/language-German.sys b/config/language-German.sys
new file mode 100644
index 0000000..5ae4ef2
--- /dev/null
+++ b/config/language-German.sys
@@ -0,0 +1,1363 @@
+# $Id: language-German.sys,v 1.240 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# This is the German Language file used for all the prompts in xastir
+# Dies ist die deutsche Sprachdatei f�r Menus und Textausgaben in Xastir
+#
+# Creator : Kai Altenfelder, DL3LBA <ka at suse.de>
+# Maintained by : The Xastir Group <xastir at xastir.org>
+# Modified by : 08.04.2007, Rolf Bleher, DK7IN <xastir at dk7in.de>
+#
+# comment lines with pound signs in front are ignored
+# File format as follows:
+# ID (10 chars alpha+numeric)|(String associated with id)|QuickKeys|#comment
+# The ID is a unique uppercase char string for each block followed by a nummer
+#
+# WARNING:
+# Some strings contain formatting commands like %s and %d, you should not
+# change these. Wrong format strings could produce a segfault!
+#
+# Warnung:
+# Einige Texte enthalten Formatierungsbefehle wie %s oder %d, diese sollten
+# beibehalten werden. Falsche Formatbefehle k�nnen zu einem Programmabsturz
+# f�hren.
+#
+# Hauptmenu
+MENUTB0001|Datei|D|
+MENUTB0002|Zeige|Z|
+MENUTB0004|Karten|K|
+MENUTB0005|Stationen|S|
+MENUTB0006|Nachrichten|N|
+MENUTB0010|Schnittstellen|i|
+MENUTB0009|Hilfe|H|
+#
+# Menu "Datei"
+PULDNFI001|Einstellungen|E|
+PULDNFI002|Protokolldatei laden|P|
+PULDNFI003|Test|T|
+PULDNFI004|Beenden|B|
+PULDNFI007|Debug Level �ndern|D|
+PULDNFI010|TNC protokollieren||
+PULDNFI011|Netz protokollieren||
+PULDNFI012|IGate protokollieren||
+PULDNFI013|Wetter protokollieren||
+PULDNFI014|PNG-Schnapsch�sse||
+PULDNFI015|Karte drucken|d|
+PULDNFI016|KML Snapshots||
+#
+# Menu "Zeige"
+PULDNVI001|Bekanntmachungen|B|
+PULDNVI002|Packet Radio|P|
+PULDNVI003|Mobilstationen|M|
+PULDNVI004|Alle Stationen|A|
+PULDNVI009|Lokale Stationen|L|
+PULDNVI012|Letzte Stationen|S|
+PULDNVI005|Wetterstationen|W|
+PULDNVI008|Eigene Wetterdaten|d|
+PULDNVI007|Wetterwarnung|e|
+PULDNVI011|Nachrichten|N|
+PULDNVI013|Laufzeit|z|
+PULDNVI014|Programmlaufzeit||
+PULDNVI015|GPS Status||
+PULDNVI016|ALOHA Statistiken||
+#
+# Menu "Einstellungen"
+PULDNCF004|Meine Stationsdaten|M|
+PULDNCF001|Grundeinstellungen|G|
+PULDNCF003|Zeitverhalten|Z|
+PULDNCF002|Koordinatensystem|K|
+PULDNCF006|Audio Alarm|A|
+PULDNCF007|Sprachausgabe|S|
+PULDNCF008|Einstellungen sichern|E|
+# (Einheiten siehe PULDNDP006)
+#
+# Menu "Karten"
+PULDNMP001|Kartenauswahl|K|
+PULDNMP012|Ausschnitte|A|
+PULDNMP014|Objekt in Karte suchen|O|
+PULDNMP016|Disable Fast Zoom/Pan/Home||
+PULDNMP013|Alle Karten verbergen||
+PULDNMP002|Automatische Karten||
+PULDNMP003|Gitter||
+PULDNMP004|Ebenen||
+PULDNMP010|Kartenbeschriftung||
+PULDNMP009|Fl�chen einf�rben||
+PULDNMP007|Wetterwarnung||
+PULDNMP005|Hintergrundfarbe|H|
+PULDNMP006|Textdarstellung|T|
+PULDNMP026|Symbol Umrandung|U|
+PULDNMP011|Mauszeiger-Men�|M|
+PULDNMP008|Intensit�t|I|
+PULDNMP020|Einstellungen Tigermaps||
+PULDNMP021|Autom. Karten - PixelKarten aus||
+PULDNMP022|Neue Karten beim Start indizieren||
+PULDNMP023|Index: Neue Karten hinzuf�gen|N|
+PULDNMP024|Index: ALLE Karten reindizieren|r|
+PULDNMP025|Fonts||
+PULDNMP015|Xfontsel||
+PULDNMP027|Karten neu laden (nicht vom Cache)||
+PULDNMP028|L�sche gesamten Karten-Cache!||
+PULDNMP029|Finde Adresse||
+PULDNMP030|Konfiguration USGS DRG||
+PULDNMP031|Kartenrand ein||
+#
+#
+# PopUp "Einstellungen Tigermaps"
+MPUPTGR001|Gitter||
+MPUPTGR002|Counties||
+MPUPTGR003|Orts-Beschr.||
+MPUPTGR004|Urbane Bereiche||
+MPUPTGR005|Hauptstrassen||
+MPUPTGR006|Strassen||
+MPUPTGR007|Eisenbahn||
+MPUPTGR008|State Beschr.||
+MPUPTGR009|Interstate Beschr||
+MPUPTGR010|US Hwy Beschr.||
+MPUPTGR011|State Hwy Beschr.||
+MPUPTGR012|Anzeigen von:||
+MPUPTGR013|Fl�sse||
+MPUPTGR014|Seen||
+MPUPTGR015|Flugh�fen, Parks, etc||
+MPUPTGR016|Karten Intensit�t||
+MPUPTGR017|Internet-Karten Timeout [Sek]||
+MPUPTGR018|Tiger Maps erlauben||
+#
+# PopUp "Configure USGS DRG"
+MPUPDRG001|W�hle darzustellende Objekte:||
+MPUPDRG002|f�rbe Hintergrundkarten (XOR)||
+MPUPDRG003|Schwarz||
+MPUPDRG004|Wei�||
+MPUPDRG005|Blau||
+MPUPDRG006|Rot||
+MPUPDRG007|Braun||
+MPUPDRG008|Gr�n||
+MPUPDRG009|Violett||
+MPUPDRG010|Gelb||
+MPUPDRG011|Hellblau||
+MPUPDRG012|Rosa||
+MPUPDRG013|Violett (hell)||
+MPUPDRG014|Hellgrau||
+MPUPDRG015|Hellbraun||
+#
+#
+# PopUp "Kartenauswahl"
+WPUPMCP001|Kartenauswahl||
+PULDNMMC01|Keine|K|
+PULDNMMC02|Vektor|V|
+PULDNMMC03|250k Topo|2|
+PULDNMMC04|100k Topo|1|
+PULDNMMC05|24k Topo|4|
+PULDNMMC06|Verz. expandieren|e|
+PULDNMMC07|Verz/Karten gew�hlt:||
+PULDNMMC08|Verz. l�schen|l|
+PULDNMMC09|Alles w�hlen|A|
+#
+# Karten - Hintergrundfarbe
+PULDNMBC01|Grau||
+PULDNMBC02|Helles Grau||
+PULDNMBC03|Dunkelblau||
+PULDNMBC04|Hellblau||
+PULDNMBC05|Gr�n||
+PULDNMBC06|Hellgr�n||
+PULDNMBC07|Gelb||
+PULDNMBC08|Zartes Gelb||
+PULDNMBC09|R�tliches Braun||
+PULDNMBC10|Rot||
+PULDNMBC11|Wei�||
+PULDNMBC12|Schwarz||
+#
+# Karten - Stil der Stationstexte
+PULDNMSL01|Schwarze Umrandung|U|
+PULDNMSL02|Schatten|S|
+PULDNMSL03|Schwarzer Hintergrund|H|
+#
+# PullDown "Symbol Umrandung"
+PULDNMIO01|Keine Umrandung|K|
+PULDNMIO02|Schwarze Umrandung|S|
+PULDNMIO03|Graue Umrandung|G|
+PULDNMIO04|Wei�e Umrandung|W|
+#
+# Schalter
+PULDNOT001|An||
+PULDNOT002|Aus||
+PULDNOT003|Kurz||
+#
+# Menu "Stationen"
+PULDNDP014|Station finden|f|
+PULDNDP001|Verfolge Station|V|
+PULDNDP022|Spur von findu holen|h|
+PULDNDP032|Daten filtern||
+PULDNDP040|Nichts||
+PULDNDP041|Meine Daten||
+PULDNDP042|TNC||
+PULDNDP027|- Direkt||
+PULDNDP043|- �ber Digi||
+PULDNDP034|Netzwerk||
+PULDNDP019|Alte Daten einbeziehen||
+PULDNDP044|Stationen||
+PULDNDP028|- Feste Stationen||
+PULDNDP029|- Bewegte Stationen||
+PULDNDP030|- Wetterstationen||
+PULDNDP053| - CWOP-Stationen||
+PULDNDP045|Objekte||
+PULDNDP026|- Wetter Objekte||
+PULDNDP039|- Regenmengen Objekte||
+PULDNDP031|- Andere Objekte||
+PULDNDP033|Anzeige filtern||
+PULDNDP010|Rufzeichen||
+PULDNDP012|Symbol||
+PULDNDP011|- Symbol drehen||
+PULDNDP007|Spur||
+PULDNDP003|Kurs||
+PULDNDP004|Geschwindigkeit||
+PULDNDP017|- kurz||
+PULDNDP002|H�he||
+PULDNDP009|Wetterdaten||
+PULDNDP046|- Wetter Text||
+PULDNDP018|-- nur Temperatur||
+PULDNDP047|- Windfahne||
+PULDNDP054|ALOHA Kreis anzeigen||
+PULDNDP013|Positionsverschleierung||
+PULDNDP008|Leistung/Gewinn||
+PULDNDP021|- mit Standardwert||
+PULDNDP020|- bei Mobilstationen||
+PULDNDP023|DF Kreise zeigen||
+PULDNDP123|Display DF Beamwidth||
+PULDNDP223|Display DF Bearing||
+PULDNDP035|Positionsvoraussage||
+PULDNDP036|- Kreis zeigen||
+PULDNDP037|- Kurs zeigen||
+PULDNDP038|- Symbol zeigen||
+PULDNDP005|Entfernung/Richtung||
+PULDNDP024|Alter des letzten Empfangs||
+PULDNDP015|Stationen l�schen|l|
+PULDNDP016|Spuren l�schen|S|
+PULDNDP025|ObjektHistorie l�schen||
+PULDNDP048|ObjektHistorie erneut laden||
+PULDNDP049|L�schen aller taktischen Calls||
+PULDNDP050|L�schen Verlauf taktische Calls||
+PULDNDP051|Nur taktische Calls w�hlen||
+PULDNDP052|- Wegpunkte bezeichnen||
+PULDNDP055|Exportieren|E|
+PULDNDP056|Export in KML-Datei||
+#
+# Ma�einheiten
+PULDNUT001|Englische Ma�e||
+PULDNUT002|Metrisch||
+#
+# Menu "Nachrichten"
+PULDNMG001|Schicke Nachricht an|N|
+PULDNMG002|�ffne Gruppen Nachricht|G|
+PULDNMG003|L�sche alle ausgehenden Nachrichten|L|
+PULDQUS001|Abfrage Stationen allgemein|S|
+PULDQUS002|Abfrage Internet-Gateways|I|
+PULDQUS003|Abfrage Wetterstationen|W|
+PULDNMG004|Setze automatische Antwort|t|
+PULDNMG005|Automatische Antwort|A|
+PULDNMG006|Satelliten ACK Modus|M|
+PULDNMG007|Unerledigte Nachrichten zeigen|U|
+#
+# Menu "Schnittstellen"
+PULDNTNT04|Schnittstellensteuerung||
+PULDNTNT03|Nicht senden: ALLES||
+PULDNTNT05|Nicht senden: Meine Position||
+PULDNTNT06|Nicht senden: Objekte||
+PULDNTNT11|aktiviere Server-Port||
+PULDNTNT01|Sende jetzt!|S|
+PULDNTNT07|Lade GPS Track|T|
+PULDNTNT08|Lade GPS Route|R|
+PULDNTNT09|Lade GPS Wegpunkte|W|
+PULDNTNT10|Garmin RINO Wegpunkte holen|G|
+#
+# Menu "Hilfe"
+PULDNHEL01|Version|V|
+PULDNHEL02|Hilfe Index|I|
+PULDNHEL03|NOTFALL BAKEN MODUS EINSCHALTEN|E|
+PULDNHEL04|!!! NOTFALL BAKEN MODUS !!!||
+PULDNHEL05|�ber Xastir||
+#
+# Mauszeiger PopUp Menu
+POPUPMA001|Mauszeiger-Menu||
+POPUPMA00c|Zentrieren||
+POPUPMA015|Stations-Info||
+POPUPMA002|Zoome hinein||
+POPUPMA003|Zoome heraus||
+POPUPMA004|Zoomebenen||
+POPUPMA005|Ebene 1||
+POPUPMA006|Ebene 16||
+POPUPMA007|Ebene 64||
+POPUPMA008|Ebene 256||
+POPUPMA009|Ebene 1024||
+POPUPMA010|Ebene 8192||
+POPUPMA017|Ganze Welt||
+POPUPMA016|Letzte Ansicht||
+POPUPMA018|Objekt Neu||
+POPUPMA019|Objekt �ndern||
+POPUPMA025|Meine Station hierhin!|h|
+POPUPMA011|nach oben||
+POPUPMA012|nach unten||
+POPUPMA013|nach links||
+POPUPMA014|nach rechts||
+POPUPMA020|Messen||
+POPUPMA021|Bewegen||
+POPUPMA022|Verfolge mich||
+POPUPMA023|Modifikationstasten aktiv!||
+POPUPMA024|Bitte Umschalt/Num/Rollen/andere Modifikationstasten ausschalten||
+POPUPMA026|Zentrieren & Zoom||
+POPUPMA027| Breite||
+POPUPMA028| L�nge||
+POPUPMA029|CAD-Objekte zeichnen||
+POPUPMA030|Zeichnen||
+POPUPMA031|Polygon abschlie�en||
+POPUPMA032|CAD-Polygone l�schen||
+POPUPMA033|**NICHT BENUTZT**||
+POPUPMA034|Selbstdefinierter Zoom||
+POPUPMA035|10% verkleinern||
+POPUPMA036|10% vergr��ern||
+POPUPMA037|Bereich||
+POPUPMA038|Quadrat||
+POPUPMA039|Quadratfuss||
+POPUPMA040|Quadratmeter||
+POPUPMA041|Peilung||
+POPUPMA042|Grad||
+POPUPMA043|Bearbeite mehrdeutige Position||
+POPUPMA044|Mehrdeutige Position, Ihre Position kann sich sprunghaft ver�ndern.||
+POPUPMA045|Vordefinierte Objekte||
+POPUPMA046|CAD-Polygone||
+POPUPMA047|CAD-Objekte ein||
+POPUPMA048|CAD-Label ein||
+POPUPMA049|CAD-Kommentare ein||
+POPUPMA050|CAD-Wahrscheinlichkeit ein||
+POPUPMA051|CAD-Fl�chenma� ein||
+POPUPMA052|sq||
+POPUPMA053|Fu�||
+POPUPMA054|Meter||
+POPUPMA055|Meilen|
+#
+# Texte in Statuszeile
+BBARZM0001|Zoom %s||
+BBARZM0002|Zoom %s Tr||
+BBARSTH001|%d/%d Stationen||
+BBARSTA000|%-9s Neues Objekt!||
+BBARSTA001|%-9s Neue Station!||
+BBARSTA002|%-9s||# neue Daten (nur Call angezeigt)
+BBARSTA003|Lade Karten...||
+BBARSTA004|Karten geladen||
+BBARSTA005|Kartengitter An||
+BBARSTA006|Kartengitter Aus||
+BBARSTA007|Automatische Karte ist AN||
+BBARSTA008|Automatische Karte ist AUS||
+BBARSTA009|Kartenebenen sind AN||
+BBARSTA010|Kartenebenen sind AUS||
+BBARSTA011|Automatische Antwort AUS!||
+BBARSTA012|Datei beendet..||
+BBARSTA013|�ffne GPS Port||
+BBARSTA014|Schlie�e GPS Port||
+BBARSTA015|GPS RMC String empfangen||
+BBARSTA016|GPS GGA String empfangen||
+BBARSTA017|Netz vom Host getrennt||
+BBARSTA018|Timeout beim Verbindungsaufbau!||
+BBARSTA019|Suche Host %s||
+BBARSTA020|Verbunden mit %s||
+BBARSTA021|Netzverbindung fehlgeschlagen!||
+BBARSTA022|Konnte keinen Socket erstellen!||
+BBARSTA023|Keine IP f�r Host!||
+BBARSTA024|Kein Host angegeben||
+BBARSTA025|Host gefunden, verbinde %d||
+BBARSTA026|Warte auf GPS Daten via HSP..||
+BBARSTA027|Setze HSP auf TNC Daten..||
+BBARSTA028|Laden von %s||
+BBARSTA029|�ffne WX Port||
+BBARSTA030|Schlie�e WX Port||
+BBARSTA031|Pr�fe Hostname %d||
+BBARSTA032|Dekodiere Wetterdaten||
+BBARSTA033|Echo vom Digipeater||
+BBARSTA034|Lade Wetterwarnungs-Karten||
+BBARSTA035|Warte auf GPS Daten via AUX..||
+BBARSTA036|Setze AUX auf TNC Daten..||
+BBARSTA037|Dekodiere GPS Daten||
+BBARSTA038|eigene Position ge�ndert||
+BBARSTA039|Indizieren %s||
+BBARSTA040|APRS(tm) Station %s||
+BBARSTA041|Warten auf GPS Daten..||
+BBARSTA042|Senden von Objekten||
+BBARSTA043|Protokoll||
+BBARSTA044|ALOHA Entfernung betr�gt %d%s||
+BBARSTA045|Lade Symbole...||
+BBARSTA046|Lade Symbole neu...||
+BBARSTA047|Initialisiere meine Station...||
+BBARSTA048|Starte Schnittstellen...||
+BBARSTA049|Lesen der Kacheln...||
+BBARSTA050|Laden der Kacheln...||
+BBARSTA051|Laden Kachel %li von %li||
+#
+# PopUp "Zeige - Packet Radio"
+WPUPDPD001|Packet Radio Daten||
+WPUPDPD002|Nur TNC Daten||
+WPUPDPD003|Nur Internet Daten||
+WPUPDPD004|TNC und Internet Daten||
+WPUPDPD005|TNC||
+WPUPDPD006|NET||
+WPUPDPD007|Stations-Resourcen||
+WPUPDPD008|Nur meine||
+#
+# PopUp "Station - Station finden"
+WPUPLSP001|Finde Station||
+WPUPLSP002|Rufzeichen||
+WPUPLSP003|Gro�/Klein||# ???
+WPUPLSP004|Exakt||# ???
+WPUPLSP005|Finde jetzt!||
+WPUPLSP006|Notfall-Suche!||
+WPUPLSP007|FCC/RAC Suche||
+#
+# PopUp "Einstellungen - Grundeinstellungen"
+WPUPCFD001|Grundeinstellungen||
+WPUPCFD002|Nach welcher Zeit gilt eine Station als alt?||
+WPUPCFD003|15 Minuten||
+WPUPCFD004|30 Minuten||
+WPUPCFD005|45 Minuten||
+WPUPCFD006|1 Stunde||
+WPUPCFD007|90 Minuten||
+WPUPCFD008|2 Stunden||
+WPUPCFD009|Nach welcher Zeit wird eine Station nicht mehr angezeigt?||
+WPUPCFD010|6 Stunden||
+WPUPCFD011|12 Stunden||
+WPUPCFD012|1 Tag||
+WPUPCFD013|2 Tage||
+WPUPCFD014|1 Woche||
+WPUPCFD015|Sendeformat der Station||
+WPUPCFD016|Feste Station||
+WPUPCFD017|Mobile Station mit lokaler Zeit||
+WPUPCFD018|Mobile Station mit UTC Tag/Zeit||
+WPUPCFD019|Mobile Station mit UTC Zeit/Sekunden||
+WPUPCFD021|Station mit Position und Wetter||
+WPUPCFD022|Station mit UTC Zeit, Position und Wetter||
+WPUPCFD023|Sende Wetter Rohdaten?||
+WPUPCFD024|Komprimiertes Format beim Senden von Objekten?||
+WPUPCFD025|Alternatives Netz?||
+WPUPCFD026|Sende Positionsmeldung in folgenden Intervallen||
+WPUPCFD027|PopUp-Fenster f�r neue Bekanntmachungen||
+WPUPCFD028|Warnung bei Modifikationstasten||
+WPUPCFD029|Anzeige bei Entfernung Null||
+WPUPCFD030|Position Dubletten-Pr�fung aus||
+WPUPCFD031|Vordefinierte Objekte aus Datei laden||
+WPUPCFD032|Meine Spuren in einer Farbe||
+WPUPCFD033|ALTNET:||
+#
+# PopUp "Zeitverhalten"
+WPUPCFTM01|Einstellung des Zeitverhaltens|||
+WPUPCFTM02|SendeIntervall Position [Min]||
+WPUPCFTM03|Station schemenhaft nach [Min]||
+WPUPCFTM04|Max SendeIntervall Objekt [Min]||
+WPUPCFTM05|Alte Station anzeigen f�r [Std]||
+WPUPCFTM06|GPS Abfrage alle [Sek]||
+WPUPCFTM07|Station l�schen nach [Tage]||
+WPUPCFTM08|Timeout Pos-Voraussage [Min]||
+WPUPCFTM09|Abstand zw. seriellen Zeichen (ms)||
+WPUPCFTM10|Neue Spur Zeit (Min)||
+WPUPCFTM11|Neue Spur Intervall (Grad)||
+WPUPCFTM12|RINO -> Objekt Intervall (min), 0 = Aus||
+WPUPCFTM13|Schnapschu�-Intervall (min)||
+#
+# PopUp "Koordinatensystem"
+WPUPCFC001|Koordinatensystem||
+WPUPCFC002|Koordinatensystem w�hlen||
+WPUPCFC003|dd.ddddd|d|
+WPUPCFC004|dd mm.mmm|m|
+WPUPCFC005|dd mm ss.s|s|
+WPUPCFC006|UTM|U|
+WPUPCFC007|USNG/MGRS2||
+WPUPCFC008|UTM mit Spezialzonen||
+#
+# PopUp "GPS Einstellungen"
+WPUPCFG001|GPS Einstellungen||
+WPUPCFG003|GPS Port||
+WPUPCFG002|GPS Position benutzen?||
+WPUPCFG004|GPS Optionen||
+WPUPCFG005|Eigenst�ndiger GPS||
+WPUPCFG006|TNC mit GPS verbunden (HSP Kabel)||
+WPUPCFG007|TNC mit GPS verbunden �ber Ctrl-E||
+WPUPCFG008|GPS-Abfrage alle||
+WPUPCFG009|5 Sek||
+WPUPCFG010|15 Sek||
+WPUPCFG011|30 Sek||
+WPUPCFG012|1 Minute||
+WPUPCFG013|2 Minuten||
+WPUPCFG014|5 Minuten||
+WPUPCFG015|10 Minuten||
+WPUPCFG016|GPS �ber Netzwerk verbunden||
+WPUPCFG017|gpsd Host||
+WPUPCFG018|gpsd Port||
+WPUPCFG019|GPS �ber Netz via gpsd||
+WPUPCFG020|Wiederverbinden nach Fehler?||
+WPUPCFG021|Wetter �ber Netzwerk||
+WPUPCFG022|Wetterstation Host||
+WPUPCFG023|Wetterstation Port||
+#
+# TNC Einstellungen
+WPUPCFT001|TNC Einstellungen||
+WPUPCFT002|TNC benutzen?||
+WPUPCFT003|TNC Port||
+WPUPCFT004|Port Geschwindigkeit||
+WPUPCFT005|300 bps||
+WPUPCFT006|1200 bps||
+WPUPCFT007|2400 bps||
+WPUPCFT008|4800 bps||
+WPUPCFT009|9600 bps||
+WPUPCFT010|19200 bps||
+WPUPCFT011|UnProto Pfade||
+WPUPCFT012|Pfad 1: %s via ||
+WPUPCFT013|Pfad 2: %s via ||
+WPUPCFT014|Pfad 3: %s via ||
+WPUPCFT015|Port Datenbits||
+WPUPCFT016|8,N,1||
+WPUPCFT017|7,E,1||
+WPUPCFT018|7,O,1||
+WPUPCFT019|38400 bps||
+WPUPCFT020|57600 bps||
+WPUPCFT021|115200 bps||
+WPUPCFT022|230400 bps||
+WPUPCFT023|Einstellungen f�r TNC mit GPS �ber HSP-Kabel||
+WPUPCFT024|Datenart||
+WPUPCFT025|Automatisch||
+WPUPCFT026|Bin�r||
+WPUPCFT027|ASCII||
+WPUPCFT028|Einstellungen f�r TNC mit GPS �ber AUX-Kabel||
+WPUPCFT029|Einstellungen f�r TNC mit GPS �ber INVALID ENUM||
+WPUPCFT030|KISS TNC konfigurieren||
+WPUPCFT031|TNC Konfigurationsdateien||
+WPUPCFT032|Datei f�r TNC-Setup||
+WPUPCFT033|Datei f�r TNC-Shutdown||
+WPUPCFT034|KISS Parameter||
+WPUPCFT035|TXDelay (in 10 ms Einheiten)||
+WPUPCFT036|Persistence (0 to 255)||
+WPUPCFT037|SlotTime (in 10 ms Einheiten)||
+WPUPCFT038|TxTail (in 10 ms Einheiten)||
+WPUPCFT039|Voll-Duplex||
+WPUPCFT040|Multi-Port KISS TNC konfigurieren||
+WPUPCFT041|Funkger�t Port||
+WPUPCFT042|Unklarer UNPROTO Pfad!||
+WPUPCFT043|Bitte kuerzeren Pfad eingeben, z.B. WIDE2-2 oder RELAY,WIDE2-2||
+WPUPCFT044|Unklarer IGATE Pfad!||
+WPUPCFT045|Senden eines unklaren/fehlerhaften UNPROTO-Pfades!||
+WPUPCFT046|Senden eines unklaren/fehlerhaften IGATE-Pfades!||
+WPUPCFT047|KISS-Modus beim Start aktivieren||
+#
+# PopUp "Einstellungen Wetterstation"
+WPUPCFWX01|Einstellungen Wetterstation||
+WPUPCFWX02|Device f�r Wetterstation||
+WPUPCFWX03|Regenmesser-Korrektur (globale Einstellung)||
+WPUPCFWX04|.1 inch/2.5mm||
+WPUPCFWX05|.01 inch/.25mm||
+WPUPCFWX06|.1mm||
+WPUPCFWX07|keine Korrektur||
+#
+# PopUp "Einstellungen - Stationsdaten"
+WPUPCFS001|Stationsdaten||
+WPUPCFS002|Rufzeichen||
+WPUPCFS003|Breite||
+WPUPCFS004|Grad||
+WPUPCFS005|Min||
+WPUPCFS006|(N/S)||
+WPUPCFS007|L�nge||
+WPUPCFS008|(E/W)||
+WPUPCFS009|Stations-Symbol||
+WPUPCFS010|Gruppe/Overlay||
+WPUPCFS011|Symbol||
+WPUPCFS028|Auswahl||
+WPUPCFS012|Leistung - H�he - Gewinn - Richtung||
+WPUPCFS013|Kein PHG||
+WPUPCFS014|Antennen H�he||
+WPUPCFS015|Antennen Gewinn||
+WPUPCFS016|Rundstrahler||
+WPUPCFS017|Kommentar:||
+WPUPCFS018|Positionsverschleierung||
+WPUPCFS019|Keine||
+WPUPCFS020|.11 Meilen Kreis||
+WPUPCFS021|1.15 Meilen Kreis||
+WPUPCFS022|11.51 Meilen Kreis||
+WPUPCFS023|69.09 Meilen Kreis||
+WPUPCFS024|.18 Kilometer Kreis||
+WPUPCFS025|1.85 Kilometer Kreis||
+WPUPCFS026|18.53 Kilometer Kreis||
+WPUPCFS027|111.19 Kilometer Kreis||
+WPUPCFS029|Position in komprimiertem Format senden|k|
+#
+# PopUp "Objekt/Item"
+POPUPOB001|Objekt/Item||
+POPUPOB002|Name||
+POPUPOB003|Objekt setzen||
+POPUPOB004|Objekt l�schen||
+POPUPOB005|Objekt �ndern||
+POPUPOB006|Item setzen||
+POPUPOB007|Fl�chenobjekt||
+POPUPOB008|als Fl�chenobjekt||
+POPUPOB009|Helle Farben||
+POPUPOB010|Fl�chen f�llen||
+POPUPOB011|Kreis||
+POPUPOB012|Linie-Rechts '/'||
+POPUPOB013|Linie-Links '\'||
+POPUPOB014|Dreieck||
+POPUPOB015|Rechteck||
+POPUPOB016|Schwarz||
+POPUPOB017|Blau||
+POPUPOB018|Gr�n||
+POPUPOB019|Cyan||
+POPUPOB020|Rot||
+POPUPOB021|Violett||
+POPUPOB022|Gelb||
+POPUPOB023|Grau||
+POPUPOB024|nach oben:||
+POPUPOB025|nach links (au�er '/'):||
+POPUPOB026|Korridor:||
+POPUPOB027|Allgemeine Optionen||
+POPUPOB028|Position||
+POPUPOB029|als Signpost-Objekt||
+POPUPOB030|Signpost-Text||
+POPUPOB031|Signpost Objekt||
+POPUPOB032|Komprimierung einschalten||
+POPUPOB033|Item l�schen||
+POPUPOB034|Item �ndern||
+POPUPOB035|H�he [ft]:||
+POPUPOB036|Geschwindigkeit [Knoten]:||
+POPUPOB037|Kurs:||
+POPUPOB038|als Peil-Objekt||
+POPUPOB039|Leistung - H�he - Gewinn - Richtung||
+POPUPOB040|�ffnungswinkel - Richtung||
+POPUPOB041|Rundstrahlantenne||
+POPUPOB042|Richtantenne||
+POPUPOB043|unbekannt||
+POPUPOB044|Objekt �bernehmen||
+POPUPOB045|Item �bernehmen||
+POPUPOB046|DF Peilung:||
+POPUPOB047|Wahrscheinlichkeitskreise||
+POPUPOB048|Map View Objekt||
+POPUPOB049|Min (mi):||
+POPUPOB050|Max (mi):||
+#
+# PopUp "Internet Einstellungen"
+WPUPCFI001|Internet Einstellungen||
+WPUPCFI002|Host ||
+WPUPCFI003|Port ||
+WPUPCFI004|(Weitere Hosts)||
+WPUPCFI005|Host1||
+WPUPCFI006|Port1||
+WPUPCFI007|Host2||
+WPUPCFI008|Port2||
+WPUPCFI009|Zugangs-Code||
+WPUPCFI010|(freilassen falls keiner)||
+WPUPCFI011|Wiederverbinden bei NET Fehler?||
+WPUPCFI012|Als I-Gate verwenden?||
+WPUPCFI013|Nachrichten aus Internet via TNC aussenden wenn I-Gate?||
+WPUPCFI014|I-Gate Transaktionen protokollieren?|||
+WPUPCFI015|Filter-Parameter||
+#
+# PopUp "Datenbank Einstellungen"
+WPUPCFID01|Datenbank Einstellungen (TBD)||
+WPUPCFID02|Host ||
+WPUPCFID03|Port ||
+WPUPCFID04|(Weitere Hosts)||
+WPUPCFID05|Host1||
+WPUPCFID06|Port1||
+WPUPCFID07|Host2||
+WPUPCFID08|Port2||
+WPUPCFID09|Zugangs-Code||
+WPUPCFID10|(Freilassen falls keines)||
+WPUPCFID11|Wiederverbinden bei NET Fehler?||
+WPUPCFID12|Als I-Gate verwenden?||
+WPUPCFID13|Nachrichten aus Internet via TNC aussenden wenn I-Gate?||
+WPUPCFID14|I-Gate Transaktionen protokollieren?|||
+WPUPCFID15|Filter-Parameter||
+#
+# PopUp "Configure AGWPE"
+WPUPCFIA01|AGWPE konfigurieren||
+WPUPCFIA02|Host ||
+WPUPCFIA03|Port ||
+WPUPCFIA04|(Weitere Hosts)||
+WPUPCFIA05|Host1||
+WPUPCFIA06|Port1||
+WPUPCFIA07|Host2||
+WPUPCFIA08|Port2||
+WPUPCFIA09|Zugangs-Code||
+WPUPCFIA10|Freilassen falls keines)||
+WPUPCFIA11|Wiederverbinden bei NET Fehler?||
+WPUPCFIA12|Als I-Gate verwenden?||
+WPUPCFIA13|Nachrichten aus Internet via TNC aussenden wenn I-Gate?||
+WPUPCFIA14|I-Gate Transaktionen protokollieren?|||
+WPUPCFIA15|FunkPort Senden||
+#
+# PopUp "Einstellungen f�r Audio Alarm"
+WPUPCFA001|Einstellungen f�r Audio Alarm||
+WPUPCFA002|Audio Abspielkommando||
+WPUPCFA003|Alarm an||
+WPUPCFA004|abzuspielende Audio Datei||
+WPUPCFA005|Neue Station||
+WPUPCFA006|Neue Nachricht||
+WPUPCFA007|Ann�herung||
+WPUPCFA008|Band�ffnung||
+WPUPCFA009|Minimum Entfernung||
+WPUPCFA010|Maximum Entfernung||
+WPUPCFA011|Wetter Warnung||
+#
+# PopUp "Sprachausgabe"
+WPUPCFSP01|Sprachausgabe||
+WPUPCFSP02|Sprachausgabe bei:||
+WPUPCFSP03|Neuer Station||
+WPUPCFSP04|Neuer Nachricht||
+WPUPCFSP05|Neuer Text in Nachricht||
+WPUPCFSP06|Ann�herungswarnung||
+WPUPCFSP07|Band�ffnung||
+WPUPCFSP08|Neuer Wetterwarnung||
+WPUPCFSP09|Ann�herung verfolgter Station||
+#
+# PopUp "Verfolge Station"
+WPUPTSP001|Verfolge Station||
+WPUPTSP002|Rufzeichen||
+WPUPTSP003|Gro�/Klein||
+WPUPTSP004|Exakt||
+WPUPTSP005|Verfolge jetzt!||
+WPUPTSP006|Verfolgung aufheben||
+WPUPTSP007|Spur aus dem Internet||
+WPUPTSP008|Rufzeichen||
+WPUPTSP009|Start der Spur (vor ... Std)||
+WPUPTSP010|L�nge der Spur (Std)||
+#
+# PopUp "Nachrichten..."
+WPUPMSB001|Nachricht Fenster %d||
+WPUPMSB002|Gruppennachricht Fenster %d||
+WPUPMSB003|Stationsrufzeichen:||
+WPUPMSB004|Gruppenrufzeichen:||
+WPUPMSB005|Neues/Refresh Rufzeichen||
+WPUPMSB006|Neue Gruppe||
+WPUPMSB007|L�sche alte Nachrichten||
+WPUPMSB008|Nachricht:||
+WPUPMSB009|Sende jetzt!||
+WPUPMSB010|Pfad:||
+WPUPMSB011|Wartende Nachrichten zur�cknehmen||
+WPUPMSB012|Kick Timer||
+WPUPMSB013|Seq||
+WPUPMSB014|Typ||
+WPUPMSB015|Rundmeldung||
+WPUPMSB016|*TIMEOUT*||
+WPUPMSB017|*ABBRUCH*||
+WPUPMSB018|*ZUR�CKGEWIESEN*||
+WPUPMSB019|Pfad �ndern||
+WPUPMSB020|Standard-Pfad(e) benutzen||
+WPUPMSB021|Direkt (kein Pfad)||
+WPUPMSB022|Umgekehrter Pfad (Hinweis):||
+#
+# PopUp "Automatische Antwort"
+WPUPARM001|Automatische Antwort �ndern||
+WPUPARM002|Antwort:||
+#
+# PopUp "Hilfe Index"
+WPUPHPI001|Hilfe Index||
+WPUPHPI002|Anzeigen||
+#
+# PopUp "Stations-Info"
+WPUPSTI000|Objekt von: %s||
+WPUPSTI001|Stations-Info||
+WPUPSTI002|Sende Nachricht||
+WPUPSTI003|Suche in FCC Datenbank||
+WPUPSTI004|Suche in RAC Datenbank||
+WPUPSTI005|Pakete empfangen: %d Zuletzt geh�rt: ||
+WPUPSTI006|Geh�rt �ber TNC auf Device %d, ||
+WPUPSTI007|Geh�rt ||
+WPUPSTI008|zuletzt �ber Lokal||
+WPUPSTI009|zuletzt �ber TNC auf Device %d||
+WPUPSTI010|zuletzt �ber Internet auf Device %d||
+WPUPSTI011|zuletzt �ber Datei||
+WPUPSTI012|zuletzt �ber Unbekannt||
+WPUPSTI013|, und hat die Position ge�ndert||
+WPUPSTI014|Momentane Leistung/Gewinn:||
+WPUPSTI016|H�he: %.0f %s ||
+WPUPSTI017|Kurs: %s� ||
+WPUPSTI018|Geschwindigkeit: %.1fkm/h||
+WPUPSTI019|Geschwindigkeit: %.1fmph||
+WPUPSTI020|%0.1f Meilen||
+WPUPSTI021|%0.1f km||
+WPUPSTI022|Entfernung von meiner Station %s, Richtung von meiner Station %s||
+WPUPSTI023|Letzte Position: ||
+WPUPSTI024|Wetter Daten %c:%s||
+WPUPSTI025|Wind Richtung: %s Geschwindigkeit: %03d km/h||
+WPUPSTI026|Wind Richtung: %s Geschwindigkeit: %s mph||
+WPUPSTI027| B�e: %03d km/h||
+WPUPSTI028| B�e: %s mph||
+WPUPSTI029|Temperatur: %02.1f�C ||
+WPUPSTI030|Temperatur: %s�F ||
+WPUPSTI031|Feuchte: %s%% ||
+WPUPSTI032|rel.Feuchte: %02.1f�C ||
+WPUPSTI033|Luftdruck: %s hPa||
+WPUPSTI034|Schnee: %0.1f cm/24h||
+WPUPSTI035|Schnee: %0.0f Inch/24h||
+WPUPSTI036|Regen: ||
+WPUPSTI037|%0.2f mm/h ||
+WPUPSTI038|%0.2f Inch/h ||
+WPUPSTI039|%0.2f mm/Tag ||
+WPUPSTI040|%0.2f Inch/Tag ||
+WPUPSTI041|%0.2f mm/seit 0:00||
+WPUPSTI042|%0.2f Inch/seit 0:00||
+WPUPSTI043|Datenpfad: %s||
+WPUPSTI044|Kommentar %02d/%02d %02d:%02d : %s||
+WPUPSTI045|L�sche Spur||
+WPUPSTI046|Regen gesamt: ||
+WPUPSTI047|%0.2f mm||
+WPUPSTI048|%0.2f Inch||
+WPUPSTI049|Trace Anfrage||
+WPUPSTI050|Unbest. Nachrichten||
+WPUPSTI051|Stationsanfrage||
+WPUPSTI052|Stationsversion||
+WPUPSTI053|Objekt/Item �ndern||
+WPUPSTI054|Spur speichern||
+WPUPSTI055|Echo geh�rt von:||
+WPUPSTI056|Automatische Aktualisierung||
+WPUPSTI057|Omni-DF: %s||
+WPUPSTI058|Peil-Richtung: %s||
+WPUPSTI059|Status %02d/%02d %02d:%02d : %s||
+WPUPSTI060|Brennstofftemp.: %02.1f�C ||
+WPUPSTI061|Brennstofftemp.: %s�F ||
+WPUPSTI062|Brennstofffeuchte: %s%% ||
+WPUPSTI063|Baro: %0.2f in Hg||
+WPUPSTI064|NWS Wetterwarnung holen||
+WPUPSTI065|Taktisches Rufzeichen: %s||
+WPUPSTI066|Taktischen Rufzeichen zuweisen||
+WPUPSTI067|Aktuelle Reichweite: %d Meilen||
+WPUPSTI068|keine||
+WPUPSTI069|Standard||
+WPUPSTI070|HAAT||
+WPUPSTI071|omni||
+WPUPSTI072|Reichweite||
+WPUPSTI073|PHG fehlerhaft||
+WPUPSTI074|SHG fehlerhaft||
+WPUPSTI075|DF Bereich||
+WPUPSTI076|Kein Signal erkannt||
+WPUPSTI077|m�gliches Signal||
+WPUPSTI078|Signal erkannt, nicht lesbar||
+WPUPSTI079|Schwaches Signal, schlecht lesbar||
+WPUPSTI080|Verrauschtes Signal aber lesbar||
+WPUPSTI081|Signal lesbar, etwas Rauschen||
+WPUPSTI082|Gutes Signal mit Restrauschen||
+WPUPSTI083|Sehr gutes Signal||
+WPUPSTI084|Hervorragendes Signal||
+WPUPSTI085|Au�erordentlich starkes Signal||
+WPUPSTI086|SCHLECHTE PEILUNG||
+WPUPSTI087|NRQ fehlerhaft||
+WPUPSTI088|DF �ffnungswinkel||
+WPUPSTI089|DF L�nge||
+WPUPSTI090|ung�ltig||
+WPUPSTI091|Wegfarbe �ndern||
+WPUPSTI092|Clear DF Bearing||
+#
+#
+# PopUp "ALOHA Statistics"
+WPUPALO001|ALOHA Radius: %d %s||
+WPUPALO002|Stationen innerhalb des ALOHA Kreises: %d||
+WPUPALO003| Digis : %d||
+WPUPALO004| Mobilstationen (in Bew.) : %d||
+WPUPALO005| Mobilstationen (sonstige): %d||
+WPUPALO006| Wetterstationen : %d||
+WPUPALO007| Feststationen : %d||
+WPUPALO008|zuletzt berechnet vor %d %s %d %s.||
+WPUPALO666|ALOHA Radius noch nicht berechnet||
+#
+# FCC-RAC Call Look up
+STIFCC0001|FCC Datenbank Abfrage||
+STIFCC0002|RAC Datenbank Abfrage||
+STIFCC0003|Name:||
+STIFCC0004|Stra�e:||
+STIFCC0005|Stadt:||
+STIFCC0006|Staat:||
+STIFCC0007|PLZ:||
+STIFCC0008|Grundeinstellung ||
+STIFCC0009|Erweitert ||
+STIFCC0010|5 wpm ||
+STIFCC0011|12 wpm ||
+#
+# FCC-RAC Call Look up
+STIFCC0100|FCC-Index zu alt, erstelle neu...||
+STIFCC0101|Rufzeichensuche||
+STIFCC0102|Rufzeichen nicht gefunden!||
+STIFCC0103|RAC-Index zu alt, erstelle neu...||
+#
+#
+# Band open message
+UMBNDO0001|in Entfernung von||
+#
+#
+# Allgemeine Optionen
+UNIOP00001|Ok||
+UNIOP00002|Abbrechen||
+UNIOP00003|Schlie�en||
+UNIOP00004|Meilen||
+UNIOP00005|km||
+UNIOP00006|Geraet||
+UNIOP00007|Hinzuf�gen||
+UNIOP00008|L�schen||
+UNIOP00009|Eigenschaften||
+UNIOP00010|Senden erlaubt?||
+UNIOP00011|Beim Start aktivieren?||
+UNIOP00012|km/h||
+UNIOP00013|mph||
+UNIOP00014|�C||
+UNIOP00015|�F||
+UNIOP00016|mm||
+UNIOP00017|Inch||
+UNIOP00018|mm/Tag||
+UNIOP00019|Inch/Tag||
+UNIOP00020|mm/h||
+UNIOP00021|Inch/h||
+UNIOP00022|mm ab 0:00||
+UNIOP00023|Inch ab 0:00||
+UNIOP00024|�||
+UNIOP00025|hPa||
+UNIOP00026|%||
+UNIOP00027|Inch Hg||
+UNIOP00028|mm Hg||
+UNIOP00029|Systemzeit durch GPS einstellen||
+UNIOP00030|Digipeater?||
+UNIOP00031|m||
+UNIOP00032|Anwenden|||
+UNIOP00033|Reset||
+UNIOP00034|min||
+UNIOP00035|hr||
+UNIOP00036|Tag||
+UNIOP00037|Send Control-E to get GPS data?||
+UNIOP00038|Add Delay||
+#
+# popUp "Stationsauswahl"
+STCHO00001|Stationsauswahl||
+#
+# "Zeige - Wetterwarnungen"
+WPUPWXA001|Wetterwarnung||
+WPUPWXA002|Liste der Wetterwarnungen||
+#
+# PopUp "Einstellungen - Schnittstellen"
+WPUPCIF001|Installierte Schnittstellen||
+WPUPCIF002|W�hle Schnittstellentyp||
+#
+# PopUp "Einstellungen AX.25 TNC"
+WPUPCAX001|Einstellungen AX.25 TNC||
+WPUPCAX002|AX.25 Ger�tename||
+#
+# Interface device names
+IFDNL00000|Kein||
+IFDNL00001|Serieller TNC||
+IFDNL00002|Serieller TNC + GPS mit HSP-Kabel||
+IFDNL00003|Serieller GPS||
+IFDNL00004|Serielle Wetterstation||
+IFDNL00005|Internet Server||
+IFDNL00006|AX.25 TNC||
+IFDNL00007|GPS �ber Netzwerk (via gpsd)||
+IFDNL00008|Wetter �ber Netzwerk||
+IFDNL00009|Serieller TNC + GPS mit AUX-Kabel||
+IFDNL00010|Serieller KISS TNC||
+IFDNL00011|Datenbank �ber Netz (Noch nicht implementiert)||
+IFDNL00012|AGWPE �ber Netz||
+IFDNL00013|Serieller Multi-Port KISS TNC||
+IFDNL00014|SQL Datenbank (experimentell)||
+#
+# Interface device info
+IFDIN00000|%s %2d %s an ser. Schnittstelle %s %s||
+IFDIN00001|%s %2d %s verbunden mit %s:%d %s||
+IFDIN00002|%s %2d %s �ber Geraet namens %s %s||
+IFDIN00003|%s %2d %s %s %s %s||
+IFDIN00004|%s %2d %s %s %s:%d %s||
+IFDIN00005|%s %2d %s %s %s %s||
+IFDIN00006| INAKTIV ||
+IFDIN00007| AKTIV ||
+IFDIN00008| FEHLER ||
+IFDIN00009| UNBEKANNT ||
+#
+# PopUp "Schnittstellen-Steuerung"
+IFPUPCT000|Schnittstellen-Steuerung||
+IFPUPCT001|Start||
+IFPUPCT002|Stop||
+IFPUPCT003|Alle starten||
+IFPUPCT004|Alle stoppen||
+#
+# Internet Gateway Steuerung
+IGPUPCF000|Internet Gateway||
+IGPUPCF001|Alle Weiterleitungen verhindern||
+IGPUPCF002|Weiterleitung NUR von HF nach Internet||
+IGPUPCF003|Weiterleitung HF->Internet UND Internet->HF||
+IGPUPCF004|Igate -> HF Pfad ||
+#
+# Wetterstation
+WXPUPSI000|Wetterstation||
+WXPUPSI001|Wetterstation Typ||
+WXPUPSI002|Aktuelle Werte||
+WXPUPSI003|Windrichtung||
+WXPUPSI004|Windgeschwindigkeit||
+WXPUPSI005|Wind B�en||
+WXPUPSI006|Temperatur||
+WXPUPSI007|Regenmenge||
+WXPUPSI008|Regenmenge heute||
+WXPUPSI009|Druck|
+WXPUPSI010|Luftfeuchtigkeit||
+WXPUPSI011|Peet Bros ULTIMETER 2000 Type (Data Logging Mode)||
+WXPUPSI012|Peet Bros ULTIMETER II Type||
+WXPUPSI013|Peet Bros ULTIMETER 2000 Type (Packet Mode)||
+WXPUPSI014|Regenmenge aktuelle Std.||
+WXPUPSI015|Regenmenge letze 24 Std.||
+WXPUPSI016|Qualimetrics Q-Net||
+WXPUPSI017|Peet Bros ULTIMETER 2000 Type (Complete Mode)||
+WXPUPSI018|Taupunkt||
+WXPUPSI019|Wind Spitze||
+WXPUPSI020|Windauskuehlungsfaktor (Windchill)||
+WXPUPSI021|Gef�hlte Temp.||
+WXPUPSI022|3 Std. Druck||
+WXPUPSI023|H�chsttemp.||
+WXPUPSI024|Tiefsttemp.||
+WXPUPSI025|Radio Shack WX-200/Oregon Scientific WM-918||
+WXPUPSI026|Davis Weather Monitor II/Wizard III/Vantage Pro||
+WXPUPSI027|LaCrosse WX-23xx||
+WXPUPSI028|Davis APRS Data Logger||
+#
+# Stationslisten
+LHPUPNI000|Stationsliste||
+LHPUPNI001|Mobile Stationen||
+LHPUPNI002|Wetterstationen||
+LHPUPNI003|Lokale Stationen (�ber TNC)||
+LHPUPNI004|Letzte Stationen||
+LHPUPNI005|Objekte & Punkte||
+LHPUPNI006|Eigene Objekte & Punkte||
+LHPUPNI010|#||
+LHPUPNI011|Rufzeichen||
+LHPUPNI012|Pakete||
+LHPUPNI013|Pos Zeit||
+LHPUPNI014|Pfad||
+LHPUPNI015|PHG||
+LHPUPNI016|Kommentar||
+LHPUPNI100|CSE||
+LHPUPNI101|SPD||
+LHPUPNI102|H�he||
+LHPUPNI103|Breite||
+LHPUPNI104|L�nge||
+LHPUPNI105|Pakete||
+LHPUPNI106|LSV||
+LHPUPNI107|CFMS||
+LHPUPNI108|DFMS||
+LHPUPNI200|CSE||
+LHPUPNI201|SPD||
+LHPUPNI202|B�en||
+LHPUPNI203|Temp||
+LHPUPNI204|Feucht||
+LHPUPNI205|Druck||
+LHPUPNI206|Rn-h||
+LHPUPNI207|Rn-0||
+LHPUPNI208|Rn24||
+LHPUPNI209|Breite/L�nge oder UTM||
+#
+# Stil der Wetterwarnungskarten
+PULDNMAT01|Zeige Warnungen �ber Karten||
+PULDNMAT02|Zeige Warnungen unter Karten||
+#
+# Fehlermeldungen
+POPEM00001|Suchfehler!||
+POPEM00002|Station %s wurde nicht gefunden!||
+POPEM00003|Tracking Fehler!||
+POPEM00004|Schnittstellenfehler!||
+POPEM00005|Ung�ltiger AX.25 Port Name %s||
+POPEM00006|Ung�ltiger AX.25 Port Name %s||
+POPEM00007|Ung�ltiges Rufzeichen %s||
+POPEM00008|AX.25 Ziel-Rufzeichen oder Digipeater ung�ltig||
+POPEM00009|Kann AX.25-Socket nicht �ffnen, %s||
+POPEM00010|Kann AX.25-Socket nicht binden, %s||
+POPEM00011|Kann AX.25-Rufzeichen nicht konnektieren, %s||
+POPEM00012|AX.25-Fehler auf Ausgang des UI||
+POPEM00013|AX.25-Problem mit axports Datei||
+POPEM00014|AX.25 ung�ltiger Port-Name %s||
+POPEM00015|Fehler beim �ffnen des Interface %d Hard Fail||
+POPEM00016|Fehler beim �ffnen des Interface %d Time Out||
+POPEM00017|Keine weiteren Schnittstellen verf�gbar!||
+POPEM00018|Datenanfrage - Single Message Line||
+POPEM00019|Senden abgeschaltet bei Port %d||
+POPEM00020|Datenbankfehler!||
+POPEM00021|AX.25-Unterst�tzung nicht in Xastir kompiliert!||
+POPEM00022|Eingabefehler!||
+POPEM00023|Es wurde kein Name angegeben!||
+POPEM00024|Der angegebene Name ist nicht mehr frei!||
+POPEM00025|Nicht gefunden!||
+POPEM00026|Verfolgung wird bei Erscheinen der Station aufgenommen||
+POPEM00027|Falsche Eingabe. Einige Felder leer?||
+POPEM00028|Kann Datei nicht �ffnen||
+POPEM00029|Gefunden!||
+POPEM00030|Symbol f�r Wetterstation||
+POPEM00031|Ge�ndert auf Wettersymbol '/_', auch m�glich: '\_' '/W' und '\W'||
+POPEM00032|Warnung: Symbol des National Weather Service wird benutzt!||
+POPEM00033|Keine GPS Daten!||
+POPEM00034|Position wird nicht gesendet bis g�ltige GPS-Daten!||
+POPEM00035|Warnung||
+POPEM00036|Hinweis||
+POPEM00037|HSP Interface vorhanden: GPS-Abfrageintervalle gr��er||
+POPEM00038|Der Name steht im Konflikt mit einem bereits existierenden Objekt, einer Markierung oder Station||
+POPEM00039|Nicht zul�ssige Zeichen gefunden||
+POPEM00040|Der nutzerspezifische Pfad ging verloren||
+POPEM00041|Erstelle andere Datei. Bitte etwas warten und danach neu versuchen||
+POPEM00042|Kein eigenes Objekt! Versuchen Sie erst das Obkekt zu �bernehmen.||
+POPEM00043|Kein Objekt/Item!||
+POPEM00044|Findu-Wegdaten: fehlgeschlagen||
+POPEM00045|Findu-Wegdaten: fertig||
+POPEM00046|Berkeley DB header/shared library passen nicht! Map-Cache aus.||
+POPEM00047|Senden ist global GESPERRT. Notfall-Baken werden NICHT gesendet!||
+POPEM00048|Notfall-Baken-Modus!||
+POPEM00049|NOTFALL-BAKEN-MODUS, senden alle 60 Sekunden!||
+POPEM00050|Schnittstellen oder Positionen/Senden GESPERRT. Notfall-Baken werden NICHT gesendet!||
+POPEM00051|Altnet ist aktiv (Menu Einstellungen->Grundeinstellungen)||
+POPEM00052|Rufzeichen ist LEER!||
+POPEM00053|Nachricht ist LEER!||
+POPEM00054|Wir versuchen mit uns selbst zu reden!||
+#
+# Karten - Ausschnitt
+JMLPO00001|Gespeicherte Kartenausschnitte||
+JMLPO00002|Aktivieren!|A|
+JMLPO00003|Neuer Name:||
+#
+# "Zeige - Bekanntmachungen"
+BULMW00001|Bekanntmachungen||
+BULMW00002|Bereich einschr�nken auf (0: unbegrenzt)||
+BULMW00003|neuen Bereich setzen||
+#
+# "Zeige - Nachrichten"
+AMTMW00001|Nachrichtenverkehr||
+AMTMW00002|Bereich einschr�nken auf (0: unbegrenzt)||
+#
+# Texte f�r Sprachsynthese
+SPCHSTR001|kilometer||
+SPCHSTR002|meter||
+SPCHSTR003|meilen||
+SPCHSTR004|yards||
+SPCHSTR005|%s, entfernung ist %d %s.||
+SPCHSTR006|%s, entfernung ist %.1f %s.||
+SPCHSTR007|%s, entfernung ist %d %s %s %s.||
+SPCHSTR008|%s, entfernung ist %.1f %s %s %s.||
+SPCHSTR009|neue wetterwarnung||
+SPCHSTR010|neues rufzeichen||
+SPCHSTR011|D X geh�rt, %s, in einer entfernung von %.1f %s||
+#
+SPCHDIRN00|n�rdlich von||
+SPCHDIRS00|s�dlich von||
+SPCHDIRE00|�stlich von||
+SPCHDIRW00|westlich von||
+SPCHDIRNE0|nord�stlich von||
+SPCHDIRNW0|nordwestlich von||
+SPCHDIRSE0|s�d�stlich von||
+SPCHDIRSW0|s�dwestlich von||
+#
+# Symbolauswahl Dialog
+SYMSEL0001|Symbol-Auswahl||
+SYMSEL0002|Prim�re Symbol-Tabelle||
+SYMSEL0003|Sekund�re Symbol-Tabelle||
+#
+# Druckereinstellungen Dialog
+PRINT0001|Druck Eigenschaften||
+PRINT0002|Papiergr��e||
+PRINT0003|Automatisch drehen
+PRINT0004|90� im Gegenuhrzeigersinn drehen||
+PRINT0005|Automatisch skalieren||
+PRINT0006|Skalierung:||
+PRINT0007|Standardhintergrund durch Wei� ersetzen||
+PRINT0008|Schwarz/Wei�-Druck||
+PRINT0016|Farben invertieren||
+PRINT0009|Postscript Aufl�sung:||
+PRINT0010|Vorschau||
+PRINT0011|In Datei drucken||
+PRINT0012|Gebe Bild auf Datei aus...||
+PRINT0013|Konvertiere in Postscript...||
+PRINT0014|Erstellen der Druckdatei beendet||
+PRINT0015|Druckerstatus||
+#
+# Druckereinstellungen Dialog
+PRINT1001|Direkt an:||
+PRINT1002|�ber Vorschau:||
+#
+# Locate Feature Dialog
+FEATURE001|Name:||
+FEATURE002|Bundesland/Provinz:||
+FEATURE003|County:||
+FEATURE004|Map Quad:||
+FEATURE005|Typ:||
+FEATURE006|GNIS-Datei:||
+FEATURE007|Adresse:||
+FEATURE008|Stadt:||
+FEATURE009|Zielmarkierung:||
+FEATURE010|PLZ:||
+FEATURE011|Geocoding Datei||
+#
+# Koordinatenrechner Dialog
+COORD001|Koordinatenumrechnung||
+COORD002|Umrechnen||
+COORD003|Umrechnen||
+COORD004|L�schen||
+COORD005|UTM||
+COORD006|Breitengrad oder||
+COORD007|L�ngengrad oder||
+COORD008|Zone||
+COORD009|UTM �stlich||
+COORD010|UTM n�rdlich||
+COORD011| Dezimal Grad: ||
+COORD012| Grad/Dezimal Minuten: ||
+COORD013| Grad/Minuten/Dezimal Sekunden: ||
+COORD014| Universal Transverse Mercator: ||
+COORD015|Milit�risches Koordinatensystem: ||
+COORD016| Maidenhead Grid Locator: ||
+COORD017| ** Ihre Eingabe war fehlerhaft ! **||
+COORD018| ** Bitte nutzen Sie eines der folgenden Eingabeformate: **||
+#
+#
+# Smart Beaconing Dialog
+SMARTB001|Smart Beaconing||
+SMARTB002|Hohe Rate [Sek] ||
+SMARTB003|Hohe Geschwindigkeit [mph] ||
+SMARTB004|Hohe Geschwindigkeit [km/h] ||
+SMARTB005|Niedrige Rate [Min] ||
+SMARTB006|Niedrige Geschwindigkeit [mph] ||
+SMARTB007|Niedrige Geschwindigkeit [km/h]||
+SMARTB008|Kurvenschwellwert [Grad] ||
+SMARTB009|Kurvenparameter (Turn Slope) ||
+SMARTB010|Wartezeit [Sek] ||
+SMARTB011|SmartBeaconing(tm) einschalten||
+#
+#
+#
+# Gamma Adjust Dialog
+GAMMA001|Gammakorrektur einstellen||
+GAMMA002|Gammakorrektur||
+#
+#
+# Map labels font Dialog
+MAPFONT001|Change Fonts||
+MAPFONT002|Fonts||
+MAPFONT003|Map Font Winzig||
+MAPFONT004|Map Font Klein||
+MAPFONT005|Map Font Mittel||
+MAPFONT006|Map Font Gro�||
+MAPFONT007|Map Font Riesig||
+MAPFONT008|Map Font Border||
+MAPFONT009|Menu Font||
+MAPFONT010|Station Font||
+MAPFONT011|ATV ID Font||
+#
+# Entfernung/Richtung auf der Statuszeile
+PULDNDB001|Entf./Richtung in Status||
+#
+#
+# GPS Transfer Operations
+GPS001|GPS-�bertragung||
+GPS002|Dateiname||
+GPS003|Farbe w�hlen||
+GPS004|Rot||
+GPS005|Gr�n||
+GPS006|Schwarz||
+GPS007|Wei�||
+GPS008|Orange||
+GPS009|Blau||
+GPS010|Gelb||
+GPS011|Violett||
+#
+#
+# Karten-Eigenschaften Dialog
+MAPP001|Karten-Eigenschaften||
+MAPP002|Max Min Karten gef�llt USGS automat.||
+MAPP003|Zoom Zoom Ebene zeichnen DRG Karte Pfad/Dateiname||
+MAPP004|Ebene �ndern->||
+MAPP005|gef�llt->||
+MAPP006|Ja ||
+MAPP007|Nein||
+MAPP008|aut.Karte->||
+MAPP009|Max Zoom->||
+MAPP010|Min Zoom->||
+MAPP011|Auto||
+MAPP012|USGS DRG->||
+#
+#
+# Zeit Texte
+TIME001|Tag||
+TIME002|Tage||
+TIME003|Stunde||
+TIME004|Stunden||
+TIME005|Minute||
+TIME006|Minuten||
+TIME007|Sekunde||
+TIME008|Sekunden||
+#
+#
+# Map Caching
+CACHE001|Karte im Cache gespeichert||
+CACHE002|Lade Karte aus dem Cache||
+CACHE003|Karte nicht im Cache gefunden...||
+#
+#
+# Map Screen Misc
+RANGE001|ENTFERNUNGS-SKALIERUNG||
+#
+#
+# GPS Status
+GPSS001|WAAS oder PPS||
+GPSS002|DGPS||
+GPSS003|g�ltig SPS||
+GPSS004|ung�ltig||
+GPSS005|Sats/Anzeige||
+GPSS006|Fix||
+GPSS007|!GPS-Daten sind �lter als 30 Sekunden!||
+GPSS008|Simulation||
+GPSS009|Manuell||
+GPSS010|Sch�tzung||
+GPSS011|FRTK||
+GPSS012|RTK||
+#
+#
+# Popup cad_dialog to obtain CAD object data
+CADPUD001|Fl�chenobjekt||
+CADPUD002|Fl�chen-Label:||
+CADPUD003|Kommentar:||
+CADPUD004|Wahrscheinlichkeit (%):||
+CADPUD005|OK||
+CADPUD006|CAD-Dialog||
+CADPUD007|Details zeigen/�ndern||
+CADPUD008|Abbrechen||
+CADPUD009|CAD-Objekte l�schen?||
+CADPUD010|Alle l�schen||
+CADPUD011|Ausgew�hlte l�schen||
+CADPUD012|durchgezogen||
+CADPUD013|gestrichelt||
+CADPUD014|doppelt gestrichelt||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA001|XASTIR Karte von %s (oben links) to %s (unten rechts). UTM %d m Gitter, %s Datum. ||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA002|XASTIR Karte von %s (oben links) to %s %s (unten rechts). Breite/L�nge Gitter, %s Datum.||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA003|XASTIR Karte von %s (oben links) to %s (unten rechts). UTM Zonen, %s Datum.||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST001|MySQL (lat/long)||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST002|Postgreql with Postgis||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST003|MySQL (spatial)||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA01|Xastir Simple Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA02|Xastir CAD Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA03|Xastir full Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA04|APRSWorld Schema||
diff --git a/config/language-Italian.sys b/config/language-Italian.sys
new file mode 100644
index 0000000..c500443
--- /dev/null
+++ b/config/language-Italian.sys
@@ -0,0 +1,1354 @@
+# $Id: language-Italian.sys,v 1.230 2012/11/01 18:57:18 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# Xastir Version : 1.0.0
+# Creator : Alessandro Frigeri, IK0YUP <ik0yup at myrealbox.com>
+# Maintained by : The Xastir Group <xastir at xastir.org>
+# Last Modified : Tue 31 Aug 11:00:00 CEST 2004 by IK0YUP
+#
+# comment lines with pound signs in front are ignored
+# Il formato del file � il seguente:
+# ID (10 caratteri alfanum)|(Stringa associata all'ID)|TastiDiSceltaRapida|#commento
+# WARNING:
+# Some strings contain formatting commands like %s and %d, you should not
+# change these. Wrong format strings could produce a segfault!
+#
+#
+# Men� Principale
+MENUTB0001|Dati|D|
+MENUTB0002|Liste|L|
+MENUTB0004|Mappe|M|
+MENUTB0005|Visualizza|V|
+MENUTB0006|Messaggi|e|
+MENUTB0010|Interfacce|I|
+MENUTB0009|Guida|G|
+#
+# Men� Dati
+PULDNFI001|Configura|C|
+PULDNFI002|Apri file di registro|A|
+PULDNFI003|Test||
+PULDNFI004|Esci|x|
+PULDNFI007|Cambia il livello di Debug|D|
+PULDNFI010|Registro TNC|T|
+PULDNFI011|Registro Rete|e|
+PULDNFI012|Accesso al Gateway Internet|G|
+PULDNFI013|Registro dati meteo|G|
+PULDNFI014|Cattura schermo in PNG||
+PULDNFI015|Stampa|P|
+PULDNFI016|KML Snapshots||
+#
+# Men� Visualizza
+PULDNVI001|Bollettini|B|
+PULDNVI002|Dati Packet in arrivo|P|
+PULDNVI003|Stazioni Mobili|M|
+PULDNVI004|Stazioni|S|
+PULDNVI009|Stazioni Locali|o|
+PULDNVI012|Ultime Stazioni|L|
+PULDNVI005|Stazioni Meteo|W|
+PULDNVI008|Stazioni Meteo|t|
+PULDNVI007|Allarmi Meteo|A|
+PULDNVI011|Traffico Messaggi|T|
+PULDNVI013|Tempo trascorso dall'avvio|d|
+PULDNVI014|Uptime del programma||
+PULDNVI015|Stato GPS||
+PULDNVI016|ALOHA Statistics||
+#
+# Menu' di Configurazione
+PULDNCF004|Dati Stazione|S|
+PULDNCF001|Configurazioni originali|D|
+PULDNCF003|Temporizzazione|T|
+PULDNCF002|Sistema di Coordinate|C|
+PULDNCF006|Allarmi Audio|A|
+PULDNCF007|Annunci Vocali|p|
+PULDNCF008|Salva la Configurazione Ora!|C|
+# (per unit� vedere PULDNDP006)
+#
+# Men� Mappe
+PULDNMP001|Scegli mappa|C|
+PULDNMP012|Vai alla posizione...|J|#NUOVA funzione dalla v. 0.3.2
+PULDNMP014|Localizza Elemento Mappa|E|
+PULDNMP016|Disable Fast Zoom/Pan/Home||
+PULDNMP013|Disattiva tutte le mappe|D|
+PULDNMP002|Mappe automatiche|A|
+PULDNMP003|Reticolato|G|
+PULDNMP004|Livelli delle Mappe|L|
+PULDNMP010|Abilita etichette delle mappe|F|
+PULDNMP009|Colora le aree chiuse|F|
+PULDNMP007|Mappe Allarme Meteo|W|
+PULDNMP005|Colore dello sfondo della mappa|B|
+PULDNMP006|Etichette Stazione|S|
+PULDNMP026|Stile Bordo Icone|O|
+PULDNMP011|Men� sul puntatore del mouse|M|
+PULDNMP008|Intensit� Mappa|I|
+PULDNMP020|Configura Tigermap||
+PULDNMP021|Mappe Automatche - Disabilita Mappe Raster||
+PULDNMP022|Indicizza Mappe all' Avvio||
+PULDNMP023|Indice: Aggiungi Nuove Mappe|N|
+PULDNMP024|Indice: Riordina Tutte le Mappe|R|
+PULDNMP025|Fonts||
+PULDNMP015|Xfontsel||
+PULDNMP027|Re-download Maps (Not from cache)||
+PULDNMP028|Flush Entire Map Cache!||
+PULDNMP029|Find Address||
+PULDNMP030|Configure USGS DRG||
+PULDNMP031|Enable Map Border||
+#
+#
+# PopUp "Configure Tigermap"
+MPUPTGR001|Griglia||
+MPUPTGR002|Contee||
+MPUPTGR003|Etichette Citt�||
+MPUPTGR004|Aree Urbane||
+MPUPTGR005|Strade Principali||
+MPUPTGR006|Strade||
+MPUPTGR007|Ferrovie||
+MPUPTGR008|Etichette Stato||
+MPUPTGR009|Etichette Strade Statali||
+MPUPTGR010|Etichette Autostrade USA||
+MPUPTGR011|Etichette Autostrade Nazionali||
+MPUPTGR012|Seleziona oggetti da visualizzare:||
+MPUPTGR013|Fiumi||
+MPUPTGR014|Laghi||
+MPUPTGR015|Aereoporti, Parchi, ecc||
+MPUPTGR016|Intensit� Mappa||
+MPUPTGR017|Internet Map Timeout (sec)||
+MPUPTGR018|Abilita Mappe Tiger||
+#
+# PopUp "Configure USGS DRG"
+MPUPDRG001|Select items to be displayed:||
+MPUPDRG002|Tint Underlying Map (XOR)||
+MPUPDRG003|Black||
+MPUPDRG004|White||
+MPUPDRG005|Blue||
+MPUPDRG006|Red||
+MPUPDRG007|Brown||
+MPUPDRG008|Green||
+MPUPDRG009|Purple||
+MPUPDRG010|Yellow||
+MPUPDRG011|Light Blue||
+MPUPDRG012|Light Red||
+MPUPDRG013|Light Purple||
+MPUPDRG014|Light Gray||
+MPUPDRG015|Light Brown||
+#
+#
+# Finestra di dialogo mappe
+WPUPMCP001|Scegli mappa||
+PULDNMMC01|Cancella|N|
+PULDNMMC02|Vettoriali|V|
+PULDNMMC03|Topografiche 250k|2|
+PULDNMMC04|Topografiche 100k|1|
+PULDNMMC05|Topografiche 24k|4|
+PULDNMMC06|Espandi Cartella|||
+PULDNMMC07|Cartella/Mappa Selezionata:||
+PULDNMMC08|Clear Dirs|C|
+PULDNMMC09|Select All|S|
+#
+# Men� Colori dello sfondo delle mappe.
+PULDNMBC01|Grigio||
+PULDNMBC02|Rosa||
+PULDNMBC03|Blu mare||
+PULDNMBC04|Blu acciaio||
+PULDNMBC05|Verde acqua||
+PULDNMBC06|Verde chiaro||
+PULDNMBC07|Oro forte||
+PULDNMBC08|Oro chiaro||
+PULDNMBC09|Marrone||
+PULDNMBC10|Rosso fuoco||
+PULDNMBC11|Bianco||
+PULDNMBC12|Nero||
+#
+# Stili delle etichette delle stazioni
+PULDNMSL01|Bordo nero||
+PULDNMSL02|Ombra nera e sfondo uniforme||
+PULDNMSL03|Testo su sfondo nero|T|
+#
+# PullDown "Stile Bordo Icone"
+PULDNMIO01|Nessun Bordo|N|
+PULDNMIO02|Bordo Nero|B|
+PULDNMIO03|Bordo Grigio|G|
+PULDNMIO04|Bordo Bianco|W|
+#
+# ATTIVO/DISATTIVO
+PULDNOT001|Attiva||
+PULDNOT002|Disattiva||
+PULDNOT003|Breve||
+#
+# Man� Stazioni
+PULDNDP014|Localizza Stazione|L|
+PULDNDP001|Segui Stazione|T|
+PULDNDP022|Scarica il percorso da Findu||
+PULDNDP032|Filtra Dati||
+PULDNDP040|Seleziona Nessuno||
+PULDNDP041|Seleziona Miei||
+PULDNDP042|Seleziona TNC||
+PULDNDP027|- Seleziona Diretta||
+PULDNDP043|- Seleziona Via Digi||
+PULDNDP034|Seleziona Rete||
+PULDNDP019|Visualizza dati scaduti||
+PULDNDP044|Seleziona Stazioni||
+PULDNDP028|- Seleziona Stazioni Fisse||
+PULDNDP029|- Seleziona Stazioni Mobili||
+PULDNDP030|- Seleziona Stazioni Meteo||
+PULDNDP053| - Seleziona stazioni Meteo CWOP||
+PULDNDP045|- Seleziona Oggetti/Dettagli||
+PULDNDP026|- Seleziona Oggetti/Dettagli Meteo||
+PULDNDP039|- Seleziona Oggetti/Dettagli Misura Acqua||
+PULDNDP031|- Seleziona Altri Oggetti/Dettagli||
+PULDNDP033|Visualizza Filtro||
+PULDNDP010|Nominativo|l|
+PULDNDP012|Simboli|Y|
+PULDNDP011|- Ruota Simboli|R|
+PULDNDP007|Percorsi delle stazioni|i|
+PULDNDP003|Direzione|C|
+PULDNDP004|Velocit�|S|
+PULDNDP017|- Visualizza basse velocit�||
+PULDNDP002|Altitudine||A
+PULDNDP009|Informazioni Meteo|W|
+PULDNDP046|- Visualizza Testo Meteo||
+PULDNDP018|-- Visualizza solo Temperatura||
+PULDNDP047|- Visualizza Vento||
+PULDNDP054|Display Aloha Circle||
+PULDNDP013|Ambiguit� di posizione|
+PULDNDP008|Potenza/Guadagno|P|
+PULDNDP021|- Potenza/Guadagno - default||
+PULDNDP020|- Potenza/Guadagno - stazioni mobili||
+PULDNDP023|Visualizza i cerchi DF||
+PULDNDP123|Display DF Beamwidth||
+PULDNDP223|Display DF Bearing||
+PULDNDP035|Abilita Conteggio||
+PULDNDP036|- Visualizza Arc||
+PULDNDP037|- Visualizza Rotta||
+PULDNDP038|- Visualizza Simbolo||
+PULDNDP005|Distanza/Direzione|D|
+PULDNDP024|Visualizza Et� Ultimo Rapporto||
+PULDNDP015|Elimina tutte le stazioni|C|
+PULDNDP016|Elimina tutti i percorsi|T|
+PULDNDP025|Cancella Storico Oggetti/Dettagli||
+PULDNDP048|Ricarica Storico Oggetti/Dettagli||
+PULDNDP049|Cancella tutte le chiamate tattiche||
+PULDNDP050|Cancella lo storico delle chiamate tattiche||
+PULDNDP051|Seleziona solo chiamate tattiche||
+PULDNDP052|- Etichetta i punti percorso||
+PULDNDP055|Export all|E|
+PULDNDP056|Export to KML File||
+#
+# Sistema di misura
+PULDNUT001|Sistema inglese||
+PULDNUT002|Metrico||
+#
+# Messaggi
+PULDNMG001|Invia messaggio a...|S|
+PULDNMG002|Apri gruppo di messaggi|g|
+PULDNMG003|Elimina tutti i messaggi in uscita|C|
+PULDQUS001|Cerca tutte le stazioni|e|
+PULDQUS002|Cerca le stazioni Gateway|I|
+PULDQUS003|Cerca le stazioni meteo|W|
+PULDNMG004|Imposta risposta automatica ai messaggi in arrivo|S|
+PULDNMG005|Risposta automatica ai messaggi in arrivo|R|
+PULDNMG006|Modalit� Satellite Ack|M|
+PULDNMG007|Show Pending Messages|P|
+#
+# Menu "Interfaces"
+PULDNTNT04|Interface Control||
+PULDNTNT03|Disabilita Trasmissioni: TUTTE||
+PULDNTNT05|Disabilita Trasmissioni: Mia Posizione||
+PULDNTNT06|Disabilita Trasmissioni: Oggetti/Entit�||
+PULDNTNT11|Abilita la porta del Server||
+PULDNTNT01|Trasmetti Ora!|T|
+PULDNTNT07|Carica tracciato GPS|F|
+PULDNTNT08|Carica rotte GPS|R|
+PULDNTNT09|Carica punti GPS|W|
+PULDNTNT10|Ricevi Waypoints Garmin RINO|G|
+#
+# Men� Aiuto
+PULDNHEL01|Versione di Xastir|A|
+PULDNHEL02|Indice Guida|I|
+PULDNHEL03|EMERGENCY BEACON MODE ENABLE|E|
+PULDNHEL04|!!! EMERGENCY BEACON MODE !!!||
+PULDNHEL05|About Xastir||
+#
+#Mouse Menu Popup
+POPUPMA001|Opzioni||
+POPUPMA00c|Centra la mappa||
+POPUPMA015|Informazioni stazione||
+POPUPMA002|Zoom avanti||
+POPUPMA003|Zoom indietro||
+POPUPMA004|Livello di Zoom||
+POPUPMA005|Livello 1||
+POPUPMA006|Livello 16||
+POPUPMA007|Livello 64||
+POPUPMA008|Livello 256||
+POPUPMA009|Livello 1024||
+POPUPMA010|Livello 8192||
+POPUPMA017|Tutto il mondo||
+POPUPMA016|Ultima posizione e zoom||
+POPUPMA018|Oggetto/Entit�->Crea||
+POPUPMA019|Oggetto/Entit�->Modifica||
+POPUPMA025|Muovi La mia Stazione Qu�|H|
+POPUPMA011|Sposta in alto||
+POPUPMA012|Sposta in basso||
+POPUPMA013|Sposta a sinistra||
+POPUPMA014|Sposta a destra||
+POPUPMA020|Misurazione distanze|D|
+POPUPMA021|Muovi||
+POPUPMA022|RintracciaMi||
+POPUPMA023|Trovato Blocco Tastiera!||
+POPUPMA024|Per Favore disabilita Blocco Maiuscole/BlocNum/Scorrimento/||
+POPUPMA026|Center & Zoom||
+POPUPMA027| Latitudine||
+POPUPMA028| Longitudine||
+POPUPMA029|Disegna oggetti CAD||
+POPUPMA030|Draw||
+POPUPMA031|Chiudi il poligono||
+POPUPMA032|Erase CAD Polygons||
+POPUPMA033|**NOT USED**||
+POPUPMA034|Custom Zoom Level||
+POPUPMA035|10% out||
+POPUPMA036|10% in||
+POPUPMA037|Area||
+POPUPMA038|square||
+POPUPMA039|square feet||
+POPUPMA040|square meters||
+POPUPMA041|Bearing||
+POPUPMA042|degrees||
+POPUPMA043|Modify ambiguous position||
+POPUPMA044|Position abiguity is on, your new position may appear to jump.||
+POPUPMA045|Predefined Objects||
+POPUPMA046|CAD Polygons||
+POPUPMA047|Enable CAD objects||
+POPUPMA048|Enable CAD labels||
+POPUPMA049|Enable CAD comments||
+POPUPMA050|Enable CAD probability||
+POPUPMA051|Enable CAD area size||
+POPUPMA052|sq||
+POPUPMA053|ft||
+POPUPMA054|meters||
+POPUPMA055|mi|
+#
+#Etichette barra di stato
+BBARZM0001|Zoom %s||
+BBARZM0002|Zoom %s Tr||
+BBARSTH001|%d/%d Stazioni||
+BBARSTA000|%-9s Nuovo Oggetto!||
+BBARSTA001|Nuova statione! %-9s||
+BBARSTA002|Nuovi dati da %-9s||
+BBARSTA003|Caricamento mappe...||
+BBARSTA004|Mappe caricate||
+BBARSTA005|Reticolato Lat/Long Attivo||
+BBARSTA006|Reticolato Lat/Long Non Attivo||
+BBARSTA007|Caricamento automatico delle mappe attivo||
+BBARSTA008|Caricamento automatico delle mappe non attivo||
+BBARSTA009|Livello mappe automatico attivato||
+BBARSTA010|Livello automatico mappe disattivato||
+BBARSTA011|Risposta automatica ai messaggi in arrivo disattivata!||
+BBARSTA012|File caricato..||
+BBARSTA013|Attivazione porta GPS||
+BBARSTA014|Disattivazione porta GPS||
+BBARSTA015|Ricezione stringa RMC dal GPS||
+BBARSTA016|Ricezione stringa GGA dal GPS||
+BBARSTA017|Disconnessione dall'host in rete||
+BBARSTA018|Connessione con l'host perduta (Time-out)!||
+BBARSTA019|Sto cercando l'host %s||
+BBARSTA020|Connesso a %s||
+BBARSTA021|Connessione fallita!||
+BBARSTA022|Non posso utilizzare la porta di rete!||
+BBARSTA023|Risoluzione IP host fallita!||
+BBARSTA024|Non � stato specificato nessun host||
+BBARSTA025|Host trovato, connessione a %d||
+BBARSTA026|Sto attendendo dati dal GPS via HSP..||
+BBARSTA027|Libero HSP, ricezione dati da TNC..||
+BBARSTA028|Caricamento %s|| #
+BBARSTA029|Apertura porta meteo||#
+BBARSTA030|Chiusura porta meteo||#
+BBARSTA031|Ricerca di %d in corso||#KEEP the %d
+BBARSTA032|Dati meteo rilevati||#
+BBARSTA033|Eco da digipeater||
+BBARSTA034|Caricamento Mappe Allerta Meteo||
+BBARSTA035|Sto attendendo dati del GPS via AUX..||
+BBARSTA036|Libero AUX, ricezione dati da TNC..||
+BBARSTA037|Dati GPS rilevati||
+BBARSTA038|Posizionare il cambiamento sulla mia stazione||
+BBARSTA039|Indicizzazione %s||
+BBARSTA040|Stazione APRS(tm) %s||
+BBARSTA041|Attendo dati GPS..||
+BBARSTA042|Transmetto oggetti/dettagli||
+BBARSTA043|Registro||
+BBARSTA044|ALOHA distance is %d%s||
+BBARSTA045|Loading symbols...||
+BBARSTA046|Reloading symbols...||
+BBARSTA047|Initialize my station...||
+BBARSTA048|Start interfaces...||
+BBARSTA049|Reading tiles...||
+BBARSTA050|Downloading tiles...||
+BBARSTA051|Downloading tile %li of %li||
+#
+#Visualizzazione dati packet
+WPUPDPD001|Visualizzazione dati packet||
+WPUPDPD002|Solo dati da TNC||
+WPUPDPD003|Solo dati dalla Rete||
+WPUPDPD004|Dati da TNC e Rete||
+WPUPDPD005|TNC||
+WPUPDPD006|RETE||
+WPUPDPD007|Station Capabilities||
+WPUPDPD008|Mine Only||
+#
+#Menu' localizza stazione
+WPUPLSP001|Localizza Stazione||
+WPUPLSP002|Localizza Nominativo||
+WPUPLSP003|Non rispetta Maius/Minus||
+WPUPLSP004|Rispetta Maius/minus ||
+WPUPLSP005|Localizza!||
+WPUPLSP006|Localizzazione di Emergenza!||
+WPUPLSP007|Ricerca su FCC/RAC||
+#
+# Configure defaults popup
+WPUPCFD001|Parametri originali||
+WPUPCFD002|Dopo quanto tempo una stazione � da considerarsi vecchia?||
+WPUPCFD003|15 Minuti||
+WPUPCFD004|30 Minuti||
+WPUPCFD005|45 Minuti||
+WPUPCFD006|1 Ora||
+WPUPCFD007|90 Minuti||
+WPUPCFD008|2 Ore||
+WPUPCFD009|Dopo quanto tempo una stazione verr� cancellata?||
+WPUPCFD010|6 Ore||
+WPUPCFD011|12 Ore||
+WPUPCFD012|1 Giorno||
+WPUPCFD013|2 Giorni||
+WPUPCFD014|1 Settimana||
+WPUPCFD015|Opzione trasmissione dati stazione||
+WPUPCFD016|Stazione fissa||
+WPUPCFD017|Stazione mobile con ora locale||
+WPUPCFD018|Stazione mobile con ora e data UTC||
+WPUPCFD019|Stazione mobile con ora UTC (con secondi)||
+WPUPCFD021|Posizione della Stazione con dati meteo||
+WPUPCFD022|Posizione stazione, Data e ora UTC, dati meteo||
+WPUPCFD023|Devo trasmettere i dati Meteo?||
+WPUPCFD024|Comprimo i dati oggetti/dettagli quando trasmetto?||
+WPUPCFD025|Attivare rete alternativa?|A|
+WPUPCFD026|Intervallo per invio rapporti posizione||
+WPUPCFD027|Apparizione nuovi bollettini||
+WPUPCFD028|Avvisa per utilizzo tasti inadatti||
+WPUPCFD029|Vedi bollettini a distanza zero||
+WPUPCFD030|Disattiva Posit Dupe-Checks||
+WPUPCFD031|Load predefined objects from file||
+WPUPCFD032|My trails in one color||
+WPUPCFD033|ALTNET:||
+#
+# PopUp "Configure - Timing"
+WPUPCFTM01|Configura Temporizzazioni||
+WPUPCFTM02|Intervallo TX posizione (min)||
+WPUPCFTM03|Tempo di Ghosting della stazione (min)||
+WPUPCFTM04|Max Intervallo TX Oggetto/Entit� (min)||
+WPUPCFTM05|Clear Time della stazione (ore)||
+WPUPCFTM06|Intervallo controllo GPS (sec)||
+WPUPCFTM07|Tempo eliminazione stazione (giorni)||
+WPUPCFTM08|Fuori tempo Ricalcolo Assoluto (min)||
+WPUPCFTM09|Serial Inter-Char Delay (ms)||
+WPUPCFTM10|Nuovo tempo della traccia (min)||
+WPUPCFTM11|Nuovo intervallo della traccia (gradi)||
+WPUPCFTM12|RINO -> Intervallo oggetto (min), 0 = Non attivo||
+WPUPCFTM13|Snapshot Interval (min)||
+#
+# PopUp "Configure Coordinate System"
+WPUPCFC001|Configura Sistema Coordinate||
+WPUPCFC002|Seleziona Sistema Coordinate||
+WPUPCFC003|gg.ggggg|d|
+WPUPCFC004|gg mm.mmm|m|
+WPUPCFC005|gg mm ss.s|s|
+WPUPCFC006|UTM|U|
+WPUPCFC007|USNG/MGRS2||
+WPUPCFC008|UTM con zone speciali||
+#
+# Configurazione GPS
+WPUPCFG001|Configura GPS||
+WPUPCFG003|GPS collegato ad una porta autonoma||
+WPUPCFG002|Usare la posizione data dal GPS?||
+WPUPCFG004|Opzioni GPS||
+WPUPCFG005|GPS Autonomo||
+WPUPCFG006|GPS Collegato al TNC(con cavo HSP)||
+WPUPCFG007|GPS Collegato al TNC usando CTL-E||
+WPUPCFG008|Ora dal GPS (Rileva ogni)||
+WPUPCFG009|5 sec||
+WPUPCFG010|15 sec||
+WPUPCFG011|30 sec||
+WPUPCFG012|1 minuto||
+WPUPCFG013|2 Minuti||
+WPUPCFG014|5 Minuti||
+WPUPCFG015|10 Minuti||
+WPUPCFG016|GPS collegato ad una rete (gpsd)||
+WPUPCFG017|Host GPSD||
+WPUPCFG018|Porta GPSD||
+WPUPCFG019|GPS in rete con GPSD||
+WPUPCFG020|Riconnetti in caso di errore?||
+WPUPCFG021|Dati Meteo rilevati dalla rete||
+WPUPCFG022|Host Meteo||
+WPUPCFG023|Porta Meteo||
+#
+#Configure TNC (baud/style are also for Meteo)
+WPUPCFT001|Configura TNC||
+WPUPCFT002|Usare TNC?||
+WPUPCFT003|porta TNC||
+WPUPCFT004|Impostazioni porta||
+WPUPCFT005|300 bps||
+WPUPCFT006|1200 bps||
+WPUPCFT007|2400 bps||
+WPUPCFT008|4800 bps||
+WPUPCFT009|9600 bps||
+WPUPCFT010|19200 bps||
+WPUPCFT011|Percorsi UnProto||
+WPUPCFT012|Percorso 1: %s via ||
+WPUPCFT013|Percorso 2: %s via ||
+WPUPCFT014|Percorso 3: %s via ||
+WPUPCFT015|Stile porta||
+WPUPCFT016|8,N,1||
+WPUPCFT017|7,E,1||
+WPUPCFT018|7,O,1||
+WPUPCFT019|38400 bps||
+WPUPCFT020|57600 bps||
+WPUPCFT021|115200 bps||
+WPUPCFT022|230400 bps||
+WPUPCFT023|Configura TNC con cavo HSP per GPS||
+WPUPCFT024|Tipi di dati||
+WPUPCFT025|Riconoscimento automatico||
+WPUPCFT026|Dati binari||
+WPUPCFT027|Dati ASCII||
+WPUPCFT028|Configura TNC con cavo AUX per GPS||
+WPUPCFT029|Configura TNC con INVALID ENUM||
+WPUPCFT030|Configura TNC KISS||
+WPUPCFT031|File di configurazione del TNC||
+WPUPCFT032|Nome File configurazione TNC||
+WPUPCFT033|Nome File dello Shutdown TNC||
+WPUPCFT034|Parametri KISS||
+WPUPCFT035|Ritardo TX (unit� di 10 ms)||
+WPUPCFT036|Persistenza (0 to 255)||
+WPUPCFT037|SlotTime (unit� di 10 ms)||
+WPUPCFT038|Coda Tx (unit� di 10 ms)||
+WPUPCFT039|Full Duplex||
+WPUPCFT040|Configura TNC Multi-Port KISS||
+WPUPCFT041|Porta Radio||
+WPUPCFT042|Dubious UNPROTO Path!||
+WPUPCFT043|Please consider a shorter path such as WIDE2-2 or WIDE1-1,WIDE2-2||
+WPUPCFT044|Dubious IGATE Path!||
+WPUPCFT045|Transmitting w/Dubious UNPROTO Path!||
+WPUPCFT046|Transmitting w/Dubious IGATE Path!||
+WPUPCFT047|Init KISS-Mode||
+#
+#Configura Porta Meteo
+WPUPCFWX01|Configura Porta Meteo||
+WPUPCFWX02|Periferica della stazione||
+WPUPCFWX03|Correzione Portata pioggia (Settaggio Globale)||
+WPUPCFWX04|.1 inch/2.5mm||
+WPUPCFWX05|.01 inch/.25mm||
+WPUPCFWX06|.1mm||
+WPUPCFWX07|Nessuna Correzione||
+#
+#Configure Stazione
+WPUPCFS001|Configura Dati Stazione||
+WPUPCFS002|Nominativo||
+WPUPCFS003|LAT||
+WPUPCFS004|grad||
+WPUPCFS005|min||
+WPUPCFS006|(N/S)||
+WPUPCFS007|LONG||
+WPUPCFS008|(E/W)||
+WPUPCFS009|Simbolo della Stazione||
+WPUPCFS010|Raggruppa/Sovrapponi||
+WPUPCFS011|Simbolo||
+WPUPCFS028|Seleziona||
+WPUPCFS012|Potenza-guadagno||
+WPUPCFS013|Disattiva PHG||
+WPUPCFS014|Altezza antenna||
+WPUPCFS015|Guadagno antenna||
+WPUPCFS016|Omni||
+WPUPCFS017|Commenti:||
+WPUPCFS018|Ambiguit� posizione||
+WPUPCFS019|Nessuna||
+WPUPCFS020|cerchio di.11 miglia||
+WPUPCFS021|cerchio di1.15 miglia||
+WPUPCFS022|cerchio di11.51 miglia||
+WPUPCFS023|cerchio di69.09 miglia||
+WPUPCFS024|cerchio di.18 chilometri||
+WPUPCFS025|cerchio di1.85 chilometri||
+WPUPCFS026|cerchio di18.53 chilometri||
+WPUPCFS027|cerchio di 111.19 chilometri||
+WPUPCFS029|Invia posizioni compresse|C|
+#
+# PopUp "Oggetto/Entit�"
+POPUPOB001|Oggetto/Entit�||
+POPUPOB002|Nome||
+POPUPOB003|Imposta Oggetto||
+POPUPOB004|Elimina Oggetto||
+POPUPOB005|Modifica Oggetto||
+POPUPOB006|Crea Nuova Entit�||
+POPUPOB007|Oggetto Area||
+POPUPOB008|Abilita Oggetto Area||
+POPUPOB009|Colore Brillante||
+POPUPOB010|Riempimento||
+POPUPOB011|Cerchio||
+POPUPOB012|Linea a destra '/'||
+POPUPOB013|Linea a sinistra '\'||
+POPUPOB014|Triangolo||
+POPUPOB015|Rettangolo||
+POPUPOB016|Nero||
+POPUPOB017|Blu||
+POPUPOB018|Verde||
+POPUPOB019|Azzurro||
+POPUPOB020|Rosso||
+POPUPOB021|Viola||
+POPUPOB022|Giallo||
+POPUPOB023|Grigio||
+POPUPOB024|Spostamento lungo lat.:||
+POPUPOB025|Spostamento lungo long.:||
+POPUPOB026|Corridoio:||
+POPUPOB027|Opzioni Generiche||
+POPUPOB028|Posizione||
+POPUPOB029|Abilita simbolo postazione||
+POPUPOB030|Dati:||
+POPUPOB031|Simbolo postazione||
+POPUPOB032|Abilita compressione||
+POPUPOB033|Elimina Entit�||
+POPUPOB034|Modifica Entit�||
+POPUPOB035|Altitudine (piedi):||
+POPUPOB036|Velocit� (nodi):||
+POPUPOB037|Direzione:||
+POPUPOB038|Oggetto DF||
+POPUPOB039|Segnale - Altezza(HAAT) - Guadagno - Direttivit�||
+POPUPOB040|Larghezza fascio - Puntamento||
+POPUPOB041|Antenna Omni||
+POPUPOB042|Antenna Direzionale||
+POPUPOB043|Sconosciuta||
+POPUPOB044|Adotta l'Oggetto||
+POPUPOB045|Adotte l'Item||
+POPUPOB046|DF Bearing:||
+POPUPOB047|Probability Circles||
+POPUPOB048|Map View Object||
+POPUPOB049|Min (mi):||
+POPUPOB050|Max (mi):||
+#
+#Configure Internet
+WPUPCFI001|Configura Rete||
+WPUPCFI002|Host ||
+WPUPCFI003|Porta ||
+WPUPCFI004|(host secondari)||
+WPUPCFI005|Host1||
+WPUPCFI006|Porta 1||
+WPUPCFI007|Host2||
+WPUPCFI008|Porta 2||
+WPUPCFI009|codice||
+WPUPCFI010|(Lascia vuoto se non necessario)||
+WPUPCFI011|Riconnettersi in caso di sconnessione?||
+WPUPCFI012|Funzionare da Gateway?||
+WPUPCFI013|Trasmetto i dati al TNC quando sono collegato ad Internet?||
+WPUPCFI014|Scrivo nel log le trasmissioni dalla Rete al TNC?|||
+WPUPCFI015|Parametri Filtro||
+#
+#Configure Database
+WPUPCFID01|Configura Database (TBD)||
+WPUPCFID02|Host ||
+WPUPCFID03|Porta ||
+WPUPCFID04|(host secondari)||
+WPUPCFID05|Host1||
+WPUPCFID06|Porta 1||
+WPUPCFID07|Host2||
+WPUPCFID08|Porta 2||
+WPUPCFID09|codice||
+WPUPCFID10|(Lascia vuoto se non necessario)||
+WPUPCFID11|Riconnettersi in caso di sconnessione?||
+WPUPCFID12|Funzionare da Gateway?||
+WPUPCFID13|Trasmetto i dati al TNC quando sono collegato ad Internet?||
+WPUPCFID14|Scrivo nel log le trasmissioni dalla Rete al TNC?|||
+WPUPCFID15|Parametri Filtro||
+#
+# PopUp "Configure AGWPE"
+WPUPCFIA01|Configura AGWPE||
+WPUPCFIA02|Host ||
+WPUPCFIA03|Porta ||
+WPUPCFIA04|(Host secondari)||
+WPUPCFIA05|Host1||
+WPUPCFIA06|Porta1||
+WPUPCFIA07|Host2||
+WPUPCFIA08|Porta2||
+WPUPCFIA09|Codice segreto||
+WPUPCFIA10|((Lascia in Bianco se Nessuno)||
+WPUPCFIA11|Riconnetti su errore NET?||
+WPUPCFIA12|Opera come I-Gate?||
+WPUPCFIA13|Manda messaggi Broadcast via TNC durante operazione I-Gate?||
+WPUPCFIA14|Registra su Log I-Gate Transactions?||
+WPUPCFIA15|Porta radio di trasmissione||
+#
+#Configure Audio Alarms
+WPUPCFA001|Configura Suoni||
+WPUPCFA002|Comando esecuzione audio||
+WPUPCFA003|Allarme attivo||
+WPUPCFA004|File audio da eseguire||
+WPUPCFA005|Nuova stazione||
+WPUPCFA006|Nuovo messaggio||
+WPUPCFA007|Vicinanza||
+WPUPCFA008|Apertura banda||
+WPUPCFA009|Distanza minima||
+WPUPCFA010|Distanza massima||
+WPUPCFA011|Allarme meteo||
+#
+# PopUp "Configure Speech"
+WPUPCFSP01|Configura Annuncio||
+WPUPCFSP02|Annuncio su:||
+WPUPCFSP03|Nuova stazione||
+WPUPCFSP04|Nuovo Messaggio||
+WPUPCFSP05|Nuovo corpo del messaggio||
+WPUPCFSP06|Allarme di vicinanza||
+WPUPCFSP07|Apertura di banda||
+WPUPCFSP08|Allarme Meteo||
+WPUPCFSP09|Avviso Prossimit� Stazione Tracciata||
+#
+# Track Stazione
+WPUPTSP001|Segui Stazione||
+WPUPTSP002|Segui Nominativo||
+WPUPTSP003|Corrispondenza a caso||
+WPUPTSP004|Corrispondenza Esatta||
+WPUPTSP005|Segui ora!||
+WPUPTSP006|Annulla operazione||
+WPUPTSP007|Scarica tracciato||
+WPUPTSP008|Nominativo||
+WPUPTSP009|Percorso iniziato (ore fa)||
+WPUPTSP010|Durata percorso (ore)||
+#
+#Messages
+WPUPMSB001|Casella messaggi %d||
+WPUPMSB002|Casella messaggi a gruppo %d||
+WPUPMSB003|Nominativi stazioni:||
+WPUPMSB004|Nominativo gruppo:||
+WPUPMSB005|Nuovo/Refresh nominativo||
+WPUPMSB006|Nuovo gruppo||
+WPUPMSB007|Cancella storico Msg||
+WPUPMSB008|Messaggio:||
+WPUPMSB009|Invia ora!||
+WPUPMSB010|Percorso:||
+WPUPMSB011|Cancella Msg in attesa||
+WPUPMSB012|Kick Timer||
+WPUPMSB013|seq||
+WPUPMSB014|type||
+WPUPMSB015|Broadcast||
+WPUPMSB016|*TIMEOUT*||
+WPUPMSB017|*CANCELLED*||
+WPUPMSB018|*REJECTED*||
+WPUPMSB019|Change Path||
+WPUPMSB020|Use Default Path(s)||
+WPUPMSB021|Direct (No path)||
+WPUPMSB022|Reverse Path (Hint):||
+#
+#Auto Reply
+WPUPARM001|Cambia risposta automatica||
+WPUPARM002|Risposta:||
+#
+#Help Index
+WPUPHPI001|Indice guida||
+WPUPHPI002|Visualizza||
+#
+#Stazione Info popup
+WPUPSTI000|Oggetto Inserito da: %s||
+WPUPSTI001|Informazioni stazione||
+WPUPSTI002|Invia messaggio||
+WPUPSTI003|Cerca nel Database FCC||
+WPUPSTI004|Cerca nel Database RFC||
+WPUPSTI005|Pacchetti recevuti: %d Ultima stazione ascoltata: ||
+WPUPSTI006|Ascoltata dal TNC sulla periferica %d, ||
+WPUPSTI007|Ascoltata ||
+WPUPSTI008|Ascoltata l'ultima volta in locale||
+WPUPSTI009|Ascoltata l'ultima volta dal TNC, periferica %d||
+WPUPSTI010|Ascoltata l'ultima volta da Internet sulla periferica %d||
+WPUPSTI011|ultima via File||
+WPUPSTI012|Ascoltata l'ultima volta via Unknown||
+WPUPSTI013|, e ha cambiato posizione||
+WPUPSTI014|Potenza attuale:||
+WPUPSTI016|Altitudine: %.0f%s||
+WPUPSTI017| Direzione: %s� ||
+WPUPSTI018| Velocit�: %.1f km/ora||
+WPUPSTI019| Velocit�: %.1f miglia/ora||
+WPUPSTI020|%0.1f Miglia||
+WPUPSTI021|%0.1f chilometri||
+WPUPSTI022|Distanza dalla mia Stazione: %s, direzione rispetto alla mia stazione: %s||
+WPUPSTI023|Ultima posizione: ||
+WPUPSTI024|Dati meteorologici %c:%s||
+WPUPSTI025|Direzione del vento: %s�, Velocit�: %03d km/ora||
+WPUPSTI026|Direzione del vento: %s�, Velocit�: %s miglia/ora||
+WPUPSTI027| Picco: %03d km/ora||
+WPUPSTI028| Picco: %s MPH||
+WPUPSTI029|Temperatura: %02.1f�C ||
+WPUPSTI030|Temperatura: %s�F ||
+WPUPSTI031|Umidit�: %s%% ||
+WPUPSTI032|Humidex: %02.1f�C ||
+WPUPSTI033|Pressione: %s mb ||
+WPUPSTI034|Neve: %0.1f (cm/24ora) ||
+WPUPSTI035|Neve: %0.0f (inch/24ora) ||
+WPUPSTI036|Pioggia: ||
+WPUPSTI037|%0.2f (mm/ora) ||
+WPUPSTI038|%0.2f (pollici/ora) ||
+WPUPSTI039|%0.2f (mm/Giorno) ||
+WPUPSTI040|%0.2f (pollici/Giorno) ||
+WPUPSTI041|%0.2f (mm/da mezzanotte)||
+WPUPSTI042|%0.2f (pollici/da mezzanotte)||
+WPUPSTI043|Percorso dei dati: %s||
+WPUPSTI044|Commenti %02d/%02d %02d:%02d : %s||
+WPUPSTI045|Elimina traccia||
+WPUPSTI046|Pioggia totale: ||
+WPUPSTI047|%0.2f (mm)||
+WPUPSTI048|%0.2f (pollici)||
+WPUPSTI049|Richiesta traccia||
+WPUPSTI050|Richiesta Messaggi non Riconosciuti||
+WPUPSTI051|Richiesta Stazioni Dirette||
+WPUPSTI052|Richiesta Versione Stazione||
+WPUPSTI053|Modifica Oggetto/Entit�||
+WPUPSTI054|Registra Tracciato||
+WPUPSTI055|Ripetuto da:||
+WPUPSTI056|Abilita Aggiornamento Automatico||
+WPUPSTI057|Omni-DF: %s||
+WPUPSTI058|Puntamento DF: %s||
+WPUPSTI059|Stato %02d/%02d %02d:%02d : %s||
+WPUPSTI060|Temp Carburante: %02.1f�C ||
+WPUPSTI061|Temp Carburante: %s�F ||
+WPUPSTI062|Umidit� Carburante: %s%% ||
+WPUPSTI063|Pressione: %0.2f in Hg||
+WPUPSTI064|Ricevi avvisi NWS||
+WPUPSTI065|Chiamata tattica: %s||
+WPUPSTI066|Assign Tactical Call||
+WPUPSTI067|Current Range: %d miles||
+WPUPSTI068|none||
+WPUPSTI069|default||
+WPUPSTI070|HAAT||
+WPUPSTI071|omni||
+WPUPSTI072|range||
+WPUPSTI073|BAD PHG||
+WPUPSTI074|BAD SHG||
+WPUPSTI075|DF Range||
+WPUPSTI076|No signal detected||
+WPUPSTI077|Detectible signal (Maybe)||
+WPUPSTI078|Detectible signal but not copyable)||
+WPUPSTI079|Weak signal, marginally readable||
+WPUPSTI080|Noisy but copyable signal||
+WPUPSTI081|Some noise, easy to copy signal||
+WPUPSTI082|Good signal w/detectible noise||
+WPUPSTI083|Near full-quieting signal||
+WPUPSTI084|Full-quieting signal||
+WPUPSTI085|Extremely strong & full-quieting signal||
+WPUPSTI086|BAD BEARING||
+WPUPSTI087|BAD NRQ||
+WPUPSTI088|DF Beamwidth||
+WPUPSTI089|DF Length||
+WPUPSTI090|Not Valid||
+WPUPSTI091|Change Trail Color||
+WPUPSTI092|Clear DF Bearing||
+#
+#
+# PopUp "ALOHA Statistics"
+WPUPALO001|ALOHA radius: %d %s||
+WPUPALO002|Stations inside ALOHA circle: %d||
+WPUPALO003| Digis: %d||
+WPUPALO004| Mobiles (in motion): %d||
+WPUPALO005| Mobiles (other): %d||
+WPUPALO006| WX stations: %d||
+WPUPALO007| Home stations: %d||
+WPUPALO008|Last calculated %d %s %d %s ago.||
+WPUPALO666|ALOHA radius not calculated yet||
+#
+# FCC-RAC Call Look up
+STIFCC0001|Ricerca nel database FCC||
+STIFCC0002|Ricerca nel database RAC||
+STIFCC0003|Nome:||
+STIFCC0004|Indirizzo:||
+STIFCC0005|Citt�:||
+STIFCC0006|Stato:||
+STIFCC0007|Codice Postale:||
+STIFCC0008|Informazioni base||
+STIFCC0009|Informazioni avanzate ||
+STIFCC0010|5 wpm ||
+STIFCC0011|12 wpm ||
+#
+# FCC-RAC Call Look up
+STIFCC0100|FCC index old, rebuilding||
+STIFCC0101|Callsign Search||
+STIFCC0102|Callsign Not Found!||
+STIFCC0103|RAC index old, rebuilding||
+#
+#
+#Band open message
+UMBNDO0001|ad una distanza di||
+#
+#Universal Options
+UNIOP00001|OK||
+UNIOP00002|Annulla||
+UNIOP00003|Chiudi||
+UNIOP00004|Miglia||
+UNIOP00005|Chilometri||
+UNIOP00006|Periferica||
+UNIOP00007|Aggiungi||
+UNIOP00008|Cancella||
+UNIOP00009|Propriet�||
+UNIOP00010|Consenti la trasmissione?||
+UNIOP00011|Attiva all'avvio?||
+UNIOP00012|km/ora||
+UNIOP00013|miglia/ora||
+UNIOP00014|C||
+UNIOP00015|F||
+UNIOP00016|mm||
+UNIOP00017|pollici||
+UNIOP00018|mm/Giorno||
+UNIOP00019|pollici/Giorno||
+UNIOP00020|mm/ora||
+UNIOP00021|pollici/ora||
+UNIOP00022|mm da mezzanotte||
+UNIOP00023|pollici da mezzanotte||
+UNIOP00024|gradi||
+UNIOP00025|hPa||
+UNIOP00026|%||
+UNIOP00027|in Hg||
+UNIOP00028|mm Hg||
+UNIOP00029|Regolare il tempo del sistema dal GPS||
+UNIOP00030|Ripeti?||
+UNIOP00031|m||
+UNIOP00032|Apply|||
+UNIOP00033|Reset||
+UNIOP00034|min||
+UNIOP00035|hr||
+UNIOP00036|day||
+UNIOP00037|Send Control-E to get GPS data?||
+UNIOP00038|Add Delay||
+#
+# PopUp "Station Chooser"
+STCHO00001|Scelta Stazione||
+#
+#DISPLAY Meteo ALERT
+WPUPWXA001|Allarmi Meteo||
+WPUPWXA002|Lista allarmi meteo||
+#
+# Configure Interfaces
+WPUPCIF001|Interfacce installate||
+WPUPCIF002|Scelta tipo di interfaccia||
+#
+#Configure AX.25
+WPUPCAX001|Configura TNC AX.25||
+WPUPCAX002|Periferica TNC AX.25||
+#
+#Interface device names
+IFDNL00000|Nessuna||
+IFDNL00001|TNC Seriale||
+IFDNL00002|TNC Seriale con GPS connesso con cavo HSP||
+IFDNL00003|GPS Seriale||
+IFDNL00004|Meteo Seriale||
+IFDNL00005|Server Internet||
+IFDNL00006|TNC AX.25||
+IFDNL00007|GPS in rete (via gpsd)||
+IFDNL00008|Meteo in rete||
+IFDNL00009|TNC Seriale con GPS connesso con cavo AUX||
+IFDNL00010|TNC Seriale in KISS||
+IFDNL00011|Database su Rete (Non ancora Implementato)||
+IFDNL00012|AGWPE Via Rete||
+IFDNL00013|TNC Seriale in Multi-Port KISS||
+IFDNL00014|SQL Database (Experimental)||
+#
+#Interface device info
+IFDIN00000|%s %2d %s sulla seriale %s %s||
+IFDIN00001|%s %2d %s connettendo %s:%d %s||
+IFDIN00002|%s %2d %s usa la porta %s %s||
+IFDIN00003|%s %2d %s %s %s %s||
+IFDIN00004|%s %2d %s %s %s:%d %s||
+IFDIN00005|%s %2d %s %s %s %s||
+IFDIN00006| Disattiva ||
+IFDIN00007| Attiva ||
+IFDIN00008| ERRORE ||
+IFDIN00009|SCONOSCIUTO||
+#
+#Interface control
+IFPUPCT000|Controllo interfaccia||
+IFPUPCT001|Avvia||
+IFPUPCT002|Ferma||
+IFPUPCT003|Avvia Tutte||
+IFPUPCT004|Ferma Tutte||
+#
+#IGate control
+IGPUPCF000|Opzioni Gateway||
+IGPUPCF001|Disabilita tutto il traffico per il gateway||
+IGPUPCF002|Permetti solo il traffico verso il Gateway||
+IGPUPCF003|Permetti il traffico Radio->Rete e Rete->Radio||
+IGPUPCF004|Igate -> RF Path ||
+#
+#Stazione Meteo
+WXPUPSI000|Stazione Meteo||
+WXPUPSI001|Tipo di Stazione meteo||
+WXPUPSI002|Dati correnti||
+WXPUPSI003|Direzione del vento||
+WXPUPSI004|Velocit� del vento||
+WXPUPSI005|Raffiche||
+WXPUPSI006|Temperatura||
+WXPUPSI007|Pioggia totale||
+WXPUPSI008|Pioggia totale odierna||
+WXPUPSI009|Pressione||
+WXPUPSI010|Umidit�||
+WXPUPSI011|Peet Bros ULTIMETER 2000 (Modalit� Data Logging)||
+WXPUPSI012|Peet Bros ULTIMETER II ||
+WXPUPSI013|Peet Bros ULTIMETER 2000 (Modalit� Packet)||
+WXPUPSI014|Pioggia (ultima ora)||
+WXPUPSI015|Pioggia (24 ore)||
+WXPUPSI016|Qualimetrics Q-Net||
+WXPUPSI017|Peet Bros ULTIMETER 2000 Type (Complete Mode)||
+WXPUPSI018|Temp.rugiada||
+WXPUPSI019|Velocit� massima vento||
+WXPUPSI020|Vento Freddo||
+WXPUPSI021|Indice Termico||
+WXPUPSI022|Pressione ultime 3 Ore||
+WXPUPSI023|Temp. Massima||
+WXPUPSI024|Temp. Minima||
+WXPUPSI025|Radio Shack Meteo-200/Oregon Scientific WM-918||
+WXPUPSI026|Davis Weather Monitor II/Wizard III/Vantage Pro||
+WXPUPSI027|LaCrosse WX-23xx||
+WXPUPSI028|Davis APRS Data Logger||
+#
+# Stn Lists
+LHPUPNI000|Lista stazioni||
+LHPUPNI001|Lista stazioni mobili||
+LHPUPNI002|Lista stazioni meteo||
+LHPUPNI003|Lista stazioni locali||
+LHPUPNI004|Lista ultime stazioni||
+LHPUPNI005|Oggetti e Dettagli||
+LHPUPNI006|Oggetti e Dettagli personali||
+LHPUPNI010|#||
+LHPUPNI011|Sigla||
+LHPUPNI012|#Pack||
+LHPUPNI013|Data e Ora||
+LHPUPNI014|Percorso||
+LHPUPNI015|PHG||
+LHPUPNI016|Commenti||
+LHPUPNI100|CSE||
+LHPUPNI101|SPD||
+LHPUPNI102|ALT.||
+LHPUPNI103|Latitudine||
+LHPUPNI104|Longitudine||
+LHPUPNI105|#Pack||
+LHPUPNI106|LSV||
+LHPUPNI107|CFMS||
+LHPUPNI108|DFMS||
+LHPUPNI200|CSE||
+LHPUPNI201|SPD||
+LHPUPNI202|GST||
+LHPUPNI203|Temperatura||
+LHPUPNI204|Umidit�||
+LHPUPNI205|Pressione||
+LHPUPNI206|RN-H||
+LHPUPNI207|RNSM||
+LHPUPNI208|RN24||
+LHPUPNI209|Lat/Lon or UTM||
+#
+# Maps Meteo Alert styles
+PULDNMAT01|Mostra allarmi sopra altre mappe||
+PULDNMAT02|Mostra allarmi sotto altre mappe||
+#
+# Error/popup messages
+POPEM00001|Localizza errore!||
+POPEM00002|Stazione %s non trovata!||
+POPEM00003|Errore nell'inseguimento!||
+POPEM00004|Errore dell'interfaccia!||
+POPEM00005|Nome della porta %s non valido||
+POPEM00006|Nome della porta AX.25 %s non valido||
+POPEM00007|Nominativo %s non valido||
+POPEM00008|Destinazione AX.25, Nominativo o digipeater errati||
+POPEM00009|Impossibile aprire la porta AX.25, %s||
+POPEM00010|Non posso collegare la porta AX.25, %s||
+POPEM00011|Connessione al nominativo AX.25 non riuscita, %s||
+POPEM00012|AX.25 errore sull'uscita di UI||
+POPEM00013|AX.25: problema nel file axports||
+POPEM00014|AX.25: %s||
+POPEM00015|Errore nell'apertura dell'interfaccia %d (Fallito)||
+POPEM00016|Errore nell'apertura dell'interfaccia %d (Tempo scaduto)||
+POPEM00017|Non sono disponibili altre interfacce!||
+POPEM00018|Richiesta dati - Messaggio su linea singola|
+POPEM00019|La trasmissione dalla porta %d � disattivata|
+POPEM00020|Errore del Database!|
+POPEM00021|Supporto AX.25 non compilato in Xastir!||
+POPEM00022|Errore di input!|
+POPEM00023|Non e' stato specificato alcun nome per questo punto!|
+POPEM00024|Il nome assegnato al punto � gi� in uso!|
+POPEM00025|Non trovato!||
+POPEM00026|Il tracciamento verr� visualizzato quando appare||
+POPEM00027|Informazione non completa. Campi vuoti?||
+POPEM00028|Non � possibile aprire il file||
+POPEM00029|Trovato!||
+POPEM00030|Simbolo Stazione Meteo||
+POPEM00031|Cambiato al simbolo Meteo '/_', altre opzioni: '\_' '/W' e '\W'||
+POPEM00032|Attenzione: Stai usando il simbolo Meteo del Servizio Nazionale!||
+POPEM00033|Nessun dato GPS!||
+POPEM00034|Disabilito TX Mia Posizione fino all'arrivo dei dati GPS!||
+POPEM00035|Attenzione||
+POPEM00036|Nota||
+POPEM00037|presente interfaccia HSP: l'intervallo di lettura del GPS viene aumentato||
+POPEM00038|Name Conflicts With Existing Object/Item/Station||
+POPEM00039|Illegal characters found, substituting periods in their place||
+POPEM00040|Custom outgoing path was lost||
+POPEM00041|Processing another file. Wait a bit, then try again||
+POPEM00042|Object not owned by me! Try adopting the object first.||
+POPEM00043|Not an Object/Item!||
+POPEM00044|Fetch Findu Trail: Failed||
+POPEM00045|Fetch Findu Trail: Complete||
+POPEM00046|Berkeley DB header/shared library do NOT match! Disabling map cache.||
+POPEM00047|Global transmit is DISABLED. Emergency beacons are NOT going out!||
+POPEM00048|Emergency Beacon Mode!||
+POPEM00049|EMERGENCY BEACON MODE, transmitting every 60 seconds!||
+POPEM00050|Interfaces or posits/transmits DISABLED. Emergency beacons are NOT going out!||
+POPEM00051|Altnet is enabled (Configure->Defaults dialog)||
+POPEM00052|Callsign is EMPTY!||
+POPEM00053|Message is EMPTY!||
+POPEM00054|We're trying to talk to ourselves!||
+#
+# Jump Location
+JMLPO00001|Posizione Mappa||
+JMLPO00002|Vai!||
+JMLPO00003|Nome del nuovo punto:||
+#
+# Bollettini
+BULMW00001|Bollettini||
+BULMW00002|Raggio (0, senza limite)||
+BULMW00003|Cambia raggio||
+#
+# All Message Traffic
+AMTMW00001|Traffico di tutti i messaggi||
+AMTMW00002|Raggio (0, senza limite)||
+#
+# Speech Strings
+SPCHSTR001|chilometri||
+SPCHSTR002|metri||
+SPCHSTR003|miglia||
+SPCHSTR004|yards||
+SPCHSTR005|%s, distanza � %d %s.||
+SPCHSTR006|%s, distanza � %.1f %s.||
+SPCHSTR007|%s, distanza � %d %s %s %s.||
+SPCHSTR008|%s, distanza � %.1f %s %s %s.||
+SPCHSTR009|Nuovo Allarme Meteo||
+SPCHSTR010|Nuovo Nominativo||
+SPCHSTR011|Ascoltato, D X, %s, alla distanza di %.1f %s||
+#
+SPCHDIRN00|nord di||
+SPCHDIRS00|sud di||
+SPCHDIRE00|est di||
+SPCHDIRW00|ovest di||
+SPCHDIRNE0|nordest di||
+SPCHDIRNW0|nordovest di||
+SPCHDIRSE0|sudest di||
+SPCHDIRSW0|sudovest di||
+#
+# Symbol Selection Dialog
+SYMSEL0001|Selezione simbolo||
+SYMSEL0002|Tabella Primaria||
+SYMSEL0003|Tabella Secondaria||
+#
+# Finestra di dialogo proprieta di stampa
+PRINT0001|Propriet� di Stampa||
+PRINT0002|Formato Carta||
+PRINT0003|Ruota Immagine automaticamente
+PRINT0004|Ruota Immagine di 90� in senso antiorario||
+PRINT0005|Ridimensiona immagine||
+PRINT0006|Scala:||
+PRINT0007|Sfondo bianco||
+PRINT0008|Stampa in bianco e nero||
+PRINT0016|Inverti i colori||
+PRINT0009|Risoluzione del file Postscript:||
+PRINT0010|Anteprima||
+PRINT0011|Stampa su file||
+PRINT0012|Elaborazione immagine su file...||
+PRINT0013|Conversione in Postscript...||
+PRINT0014|Fine elaborazione file.||
+PRINT0015|Stato del processo di stampa||
+#
+# Finestra di dialogo proprieta di stampa
+PRINT1001|Direct to:||
+PRINT1002|Via Previewer:||
+#
+# Finestra di dialogo localizza elemento mappa
+FEATURE001|Nome:||
+FEATURE002|Stato/Provincia:||
+FEATURE003|Contea:||
+FEATURE004|Quadrante:||
+FEATURE005|Tipo:||
+FEATURE006|File GNIS:||
+FEATURE007|Address:||
+FEATURE008|City:||
+FEATURE009|Mark Destination||
+FEATURE010|Zip Code:||
+FEATURE011|Geocoding File||
+#
+# Coordinate Calculator Dialog
+COORD001|Calcolo Coordinate||
+COORD002|Calc||
+COORD003|Calcola||
+COORD004|Cancella||
+COORD005|UTM||
+COORD006|Latitudine o||
+COORD007|Longitudine o||
+COORD008|Zona||
+COORD009|UTM Est||
+COORD010|UTM Nord||
+COORD011| Decimal Degrees: ||
+COORD012| Degrees/Decimal Minutes: ||
+COORD013| Degrees/Minutes/Dec. Seconds: ||
+COORD014| Universal Transverse Mercator: ||
+COORD015|Military Grid Reference System: ||
+COORD016| Maidenhead Grid Locator: ||
+COORD017| ** Sorry, your input was not recognized! **||
+COORD018| ** Please use one of the following input formats: **||
+#
+#
+# Smart Beaconing Dialog
+SMARTB001|SmartBeaconing||
+SMARTB002|Tasso Alto (secs):||
+SMARTB003|Alta Velocit� (mph):||
+SMARTB004|Alta Velocit� (kmh):||
+SMARTB005|Tasso Basso (mins):||
+SMARTB006|Bassa Velocit� (mph):||
+SMARTB007|Bassa Velocit� (kmh):||
+SMARTB008|Giro Minimo (gradi):||
+SMARTB009|Inclinazione Giro:||
+SMARTB010|Tempo di Attesa (secondi):||
+SMARTB011|Abilita SmartBeaconing(tm)||
+#
+#
+#
+# Gamma Adjust Dialog
+GAMMA001|Impostazione Correzione Gamma||
+GAMMA002|Correzione Gamma||
+#
+#
+# Map labels font Dialog
+MAPFONT001|Change Fonts||
+MAPFONT002|Fonts||
+MAPFONT003|Map Font Minuscolo||
+MAPFONT004|Map Font Piccolo||
+MAPFONT005|Map Font Medio||
+MAPFONT006|Map Font Grande||
+MAPFONT007|Map Font Enorme||
+MAPFONT008|Map Font Border||
+MAPFONT009|Menu Font||
+MAPFONT010|Station Font||
+MAPFONT011|ATV ID Font||
+#
+# Distance/Bearing on status line
+PULDNDB001|Stato Distanza/Puntamento||
+#
+#
+# GPS Transfer Operations
+GPS001|Trasferimento GPS||
+GPS002|Nome File||
+GPS003|Seleziona Colore||
+GPS004|Rosso||
+GPS005|Verde||
+GPS006|Nero||
+GPS007|Bianco||
+GPS008|Arancione||
+GPS009|Blu||
+GPS010|Giallo||
+GPS011|Viola||
+#
+#
+# Map Properties Dialog
+MAPP001|Propriet� Mappa||
+MAPP002|Max Min Disegna Mappa USGS Auto||
+MAPP003|Zoom Zoom Livello Riempi DRG Map Percorso/Nome File||
+MAPP004|Cambia Livello->||
+MAPP005|Riempito->||
+MAPP006|Si||
+MAPP007|No||
+MAPP008|Automappe->||
+MAPP009|Max Zoom->||
+MAPP010|Min Zoom->||
+MAPP011|Auto||
+MAPP012|USGS DRG->||
+#
+#
+# Time Strings
+TIME001|Giorno||
+TIME002|Giorni||
+TIME003|Ora||
+TIME004|Ore||
+TIME005|Minuto||
+TIME006|Minuti||
+TIME007|Secondo||
+TIME008|Secondi||
+#
+#
+# Map Caching
+CACHE001|Map now cached||
+CACHE002|Loading Cached Map||
+CACHE003|Map not found in cache...||
+#
+#
+# Map Screen Misc
+RANGE001|RANGE SCALE||
+#
+#
+# GPS Status
+GPSS001|WAAS or PPS||
+GPSS002|DGPS||
+GPSS003|Valid SPS||
+GPSS004|Invalid||
+GPSS005|Sats/View||
+GPSS006|Fix||
+GPSS007|!GPS data is older than 30 seconds!||
+GPSS008|Simulation||
+GPSS009|Manual||
+GPSS010|Estimated||
+GPSS011|Float RTK||
+GPSS012|RTK||
+#
+#
+# Popup cad_dialog to obtain CAD object data
+CADPUD001|Area Object||
+CADPUD002|Area Label:||
+CADPUD003|Comment:||
+CADPUD004|Probability (%):||
+CADPUD005|OK||
+CADPUD006|CAD Dialog||
+CADPUD007|Show/Edit Details||
+CADPUD008|Cancel||
+CADPUD009|Delete CAD objects?||
+CADPUD010|Delete All||
+CADPUD011|Delete Selected||
+CADPUD012|Solid||
+CADPUD013|Dashed||
+CADPUD014|Double Dash||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA001|XASTIR Map of %s (upper left) to %s (lower right). UTM %d m grid, %s datum. ||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA002|XASTIR Map of %s (upper left) to %s %s (lower right). Lat/Long grid, %s datum.||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA003|XASTIR Map of %s (upper left) to %s (lower right). UTM zones, %s datum.||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST001|MySQL (lat/long)||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST002|Postgreql with Postgis||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST003|MySQL (spatial)||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA01|Xastir Simple Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA02|Xastir CAD Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA03|Xastir full Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA04|APRSWorld Schema||
diff --git a/config/language-MuppetsChef.sys b/config/language-MuppetsChef.sys
new file mode 100644
index 0000000..64e34a3
--- /dev/null
+++ b/config/language-MuppetsChef.sys
@@ -0,0 +1,1143 @@
+# language-MuppetsChef.sys, translated from language-English.sys
+# Please do not edit this derived file.
+MENUTB0001|Feele|F|
+MENUTB0002|Feeuo|V|
+MENUTB0004|Mep|M|
+MENUTB0005|Steteeun|S|
+MENUTB0006|Messege|e|
+MENUTB0010|Interffece|I|
+MENUTB0009|Help|H|
+PULDNFI001|Cunffeeguore|C|
+PULDNFI002|Oupee-a Lug Feele|O|
+PULDNFI003|Test|T|
+PULDNFI004|Ixeet|x|
+PULDNFI007|Chuonge-a Debuog Leffel|D|
+PULDNFI010|TNC Luggeeng||
+PULDNFI011|Net Luggeeng||
+PULDNFI012|IGete-a Luggeeng||
+PULDNFI013|VX Luggeeng||
+PULDNFI014|PNG Snepshuts||
+PULDNFI015|Preent|P|
+PULDNFI016|KML Snepshuts||
+PULDNVI001|Buolleteens|B|
+PULDNVI002|Incumeeng Dete|I|
+PULDNVI003|Mubeele-a Steteeuns|M|
+PULDNVI004|Ell Steteeuns|A|
+PULDNVI009|Lucel Steteeuns|S|
+PULDNVI012|Lest Steteeuns|L|
+PULDNVI005|Veezeer Steteeuns|W|
+PULDNVI008|Ouon Veezeer Dete|D|
+PULDNVI007|Veezeer Ilerts|e|
+PULDNVI011|Messege-a Treffeec|T|
+PULDNVI013|Oupteeme|U|
+PULDNVI014|Prugrem Ouopteeme||
+PULDNVI015|GPS Stetuos||
+PULDNVI016|ELOHE Steteestics||
+PULDNCF004|Steteeun|S|
+PULDNCF001|Deffuolts|D|
+PULDNCF003|Teemeeng|T|
+PULDNCF002|Cuordeenete-a System|o|
+PULDNCF006|Ouodeeu Ilerms|A|
+PULDNCF007|Speech|p|
+PULDNCF008|Seffe-a Cunffeeg Nuo!|C|
+PULDNMP001|Mep Chuoser|M|
+PULDNMP012|Mep DEEspley Buokmerks|B|
+PULDNMP014|Lucete-a Mep Feetuore|F|
+PULDNMP016|DEEseble-a Fest Zuom/Puon/Hume||
+PULDNMP013|DEEseble-a Ill Meps||
+PULDNMP002|Ineble-a Ououtu Meps||
+PULDNMP003|Ineble-a Mep Greed||
+PULDNMP004|Ineble-a Mep Leffels||
+PULDNMP010|Ineble-a Mep Lebels||
+PULDNMP009|Ineble-a Iree-a Culur Feells||
+PULDNMP007|Ineble-a Veezeer Ilerts||
+PULDNMP005|Beckgruound Culur|C|
+PULDNMP006|Stetiun Text Style|T|
+PULDNMP026|Icun Ououotleene-a Style|O|
+PULDNMP011|Muouse-a Puinter Menuo|P|
+PULDNMP008|Mep Intenseety|I|
+PULDNMP020|Cunffeeguore-a Teegermep||
+PULDNMP021|Ouotu Mep - DEEseble-a Rester Meps||
+PULDNMP022|Index Nuo Meps ouon Stertuop||
+PULDNMP023|Index: Idd Nuo Meps|N|
+PULDNMP024|Index: Reendex ILL Meps!|R|
+PULDNMP025|Funts||
+PULDNMP015|Xffuntsel||
+PULDNMP027|Re-a-duonlued Meps (Nut ffrum ceche-a)||
+PULDNMP028|Fluosh Inture-a Mep Ceche-a!||
+PULDNMP029|FEEnd Iddress||
+PULDNMP030|Cunffeeguore-a OuoSGS DRG||
+PULDNMP031|Ineble-a Mep Burder||
+MPUPTGR001|Greed||
+MPUPTGR002|Cuountees||
+MPUPTGR003|CEEty Lebels||
+MPUPTGR004|Ourbuon Irees||
+MPUPTGR005|Mejur Rueds||
+MPUPTGR006|Streets||
+MPUPTGR007|Reelrueds||
+MPUPTGR008|Stete-a Lebels||
+MPUPTGR009|Interstete-a Lebels||
+MPUPTGR010|OuS Hvy Lebels||
+MPUPTGR011|Stete-a Hvy Lebels||
+MPUPTGR012|Select items tu be-a deespleyed:||
+MPUPTGR013|Reeffers||
+MPUPTGR014|Lekes||
+MPUPTGR015|Eurpurts, Perks, ietc||
+MPUPTGR016|Mep Intenseety||
+MPUPTGR017|Internet Mep Timeuout (sec)||
+MPUPTGR018|Ineble-a Tiger Meps||
+MPUPDRG001|Select items tu be-a deespleyed:||
+MPUPDRG002|Tint Ouonderlying Mep (XOR)||
+MPUPDRG003|Bleck||
+MPUPDRG004|Vheete||
+MPUPDRG005|Bluoe||
+MPUPDRG006|Red||
+MPUPDRG007|Bruon||
+MPUPDRG008|Gree||
+MPUPDRG009|Puorple||
+MPUPDRG010|Yelluo||
+MPUPDRG011|LEEght Bluoe||
+MPUPDRG012|LEEght Red||
+MPUPDRG013|LEEght Puorple||
+MPUPDRG014|LEEght Grey||
+MPUPDRG015|LEEght Bruon||
+WPUPMCP001|Mep Chuoser||
+PULDNMMC01|Cleer|C|
+PULDNMMC02|Fectur|V|
+PULDNMMC03|250k Tupu|2|
+PULDNMMC04|100k Tupu|1|
+PULDNMMC05|24k Tupu|4|
+PULDNMMC06|Ixpuond Deers||
+PULDNMMC07|Durs/Meps Selected:||
+PULDNMMC08|Cleer Deers|C
+PULDNMMC09|Select Ill|S|
+PULDNMBC01|Grey||
+PULDNMBC02|MEEsty Ruse||
+PULDNMBC03|Neffy Bluoe||
+PULDNMBC04|Steel Bluoe||
+PULDNMBC05|Med.. Burk Burk Burk! See-a Gree||
+PULDNMBC06|Pele-a Gree||
+PULDNMBC07|Pele-a Guldenrud||
+PULDNMBC08|Guldenrud Yelluo||
+PULDNMBC09|Rusy Bruon||
+PULDNMBC10|Fure-a brick Red||
+PULDNMBC11|Vheete||
+PULDNMBC12|Bleck||
+PULDNMSL01|Bleck Burder|B|
+PULDNMSL02|Bleck Sheduo|S|
+PULDNMSL03|Text ouon Bleck|T|
+PULDNMIO01|Nu Ououotleene|N|
+PULDNMIO02|Bleck Ououotleene|B|
+PULDNMIO03|Grey Ououotleene|G|
+PULDNMIO04|Vheete-a Ououotleene|W|
+PULDNOT001|Oun||
+PULDNOT002|Ouff||
+PULDNOT003|Shurt||
+PULDNDP014|FEEnd Steteeun|F|
+PULDNDP001|Treck Steteeun|T|
+PULDNDP022|Fetch FEEnduo Treel|u|
+PULDNDP032|FEElter Dete||
+PULDNDP040|Select Nune||
+PULDNDP041|Select Meene||
+PULDNDP042|Select TNC||
+PULDNDP027|- Select Deerect||
+PULDNDP043|- Select FEEe-a Deegee||
+PULDNDP034|Select Net||
+PULDNDP019|Incluode-a Ixpured Dete||
+PULDNDP044|Select Steteeuns||
+PULDNDP028|- Select FEExed Steteeuns||
+PULDNDP029|- Select Muffeeng Steteeuns||
+PULDNDP030|- Select VX Steteeuns||
+PULDNDP053| - Select CVOP VX Steteeuns||
+PULDNDP045|Select Ouobjects/Items||
+PULDNDP026|- Select VX Ouobjects/Items||
+PULDNDP039|- Select Veter Guoge-a Ouobjects/Items||
+PULDNDP031|- Select Ouozeer Ouobjects/Items||
+PULDNDP033|FEElter Deespley||
+PULDNDP010|DEEspley Cellseegn||
+PULDNDP012|DEEspley Symbul||
+PULDNDP011|- Rutete-a Symbul||
+PULDNDP007|DEEspley Treel||
+PULDNDP003|DEEspley Cuourse||
+PULDNDP004|DEEspley Speed|S|
+PULDNDP017|- DEEspley Shurt Speed||
+PULDNDP002|DEEspley Ilteetuode||
+PULDNDP009|DEEspley Veezeer Inffu||
+PULDNDP046|- DEEspley Veezeer Text||
+PULDNDP018|-- Temperetuore-a Ouonly||
+PULDNDP047|- DEEspley Vind Berb||
+PULDNDP054|DEEspley Iluhe-a Ceercle||
+PULDNDP013|DEEspley Pusitiun Imbeeguoity||
+PULDNDP008|DEEspley Puoer/Geen||
+PULDNDP021|- Ouose-a Deffuolt Puoer/Geen||
+PULDNDP020|- DEEspley Mubeele-a Puoer/Geen||
+PULDNDP023|DEEspley DF Ittreebuotes||
+PULDNDP123|DEEspley DF Beemveedt||
+PULDNDP223|DEEspley DF Beereeng||
+PULDNDP035|Ineble-a Deed-Reckuneeng||
+PULDNDP036|- DEEspley Irc||
+PULDNDP037|- DEEspley Cuourse||
+PULDNDP038|- DEEspley Symbul||
+PULDNDP005|DEEspley DEEst/Beereeng||
+PULDNDP024|DEEspley Lest Repurt Ige||
+PULDNDP015|Cleer Ill Stetiuns!!!|A|
+PULDNDP016|Cleer Ill Treels!!!|C|
+PULDNDP025|Cleer Ouobject/Item Heestury||
+PULDNDP048|Relued Ouobject/Item Heestury||
+PULDNDP049|Cleer Ill Tecticel Cells||
+PULDNDP050|Cleer Tecticel Cell Heestury||
+PULDNDP051|Select Tecticel Cells Ouonly||
+PULDNDP052|- Lebel Treelpuints||
+PULDNDP055|Ixpurt ill|E|
+PULDNDP056|Ixpurt tu KML Feele||
+PULDNUT001|Ineble-a Ingleesh Ouoneets|E|
+PULDNUT002|Metreec|M|
+PULDNMG001|Send Messege-a Tu|S|
+PULDNMG002|Oupee-a Gruoup Messeges|O|
+PULDNMG003|Cleer Ill Ououotguing Messeges|C|
+PULDQUS001|Generel Stetiuns Quoery|G|
+PULDQUS002|IGete-a Stetiuns Quoery|I|
+PULDQUS003|VX Stetiuns Quoery|W|
+PULDNMG004|Mudeeffy Ououtu Reply Messege|A|
+PULDNMG005|Ineble-a Ououtu Reply Messege||
+PULDNMG006|Setelleete-a Ick Mude|M|
+PULDNMG007|Shuo Pendeeng Messeges|P|
+PULDNTNT04|Interffece-a Cuntrul|C|
+PULDNTNT03|DEEseble-a Truonsmeet: ILL||
+PULDNTNT05|DEEseble-a Truonsmeet: My Puseetiun||
+PULDNTNT06|DEEseble-a Truonsmeet: Ouobjects/Items||
+PULDNTNT11|Ineble-a Serffer Purts|P|
+PULDNTNT01|Truonsmeet Nuo!|T|
+PULDNTNT07|Fetch GPS Treck|F|
+PULDNTNT08|Fetch GPS Ruoutes|R|
+PULDNTNT09|Fetch GPS Veypueents|W|
+PULDNTNT10|Fetch Germeen RINO Veypueents|G|
+PULDNHEL01|Ebuout|A|
+PULDNHEL02|Help Index|I|
+PULDNHEL03|IMERGENCY BEECON MODE INEBLE|E|
+PULDNHEL04|!!! IMERGENCY BEECON MODE !!!||
+PULDNHEL05|Ebuout Xesteer||
+POPUPMA001|Oupteeuns||
+POPUPMA00c|Center|C|
+POPUPMA015|Stetiun Inffu|S|
+POPUPMA002|In|I|
+POPUPMA003|Ouout|O|
+POPUPMA004|Zuom Leffel|L|
+POPUPMA005|Leffel 1|1|
+POPUPMA006|Leffel 16|6|
+POPUPMA007|Leffel 64|4|
+POPUPMA008|Leffel 256|2|
+POPUPMA009|Leffel 1024|0|
+POPUPMA010|Leffel 8192|8|
+POPUPMA017|Inture-a Vurld|E|
+POPUPMA016|Lest Mep Pus/Zuom|P|
+POPUPMA018|Oubject/Item->Creete|b|
+POPUPMA019|Oubject/Item->Mudeeffy|M|
+POPUPMA025|Muffe-a My Stetiun Here|H|
+POPUPMA011|Puon ouop|u|
+POPUPMA012|Puon duon|d|
+POPUPMA013|Puon lefft|l|
+POPUPMA014|Puon reeght|r|
+POPUPMA020|Meesuore||
+POPUPMA021|Muffe||
+POPUPMA022|TreckMe||
+POPUPMA023|Mudeeffeers Fuound!||
+POPUPMA024|Pleese-a tuorn OuoFF CepsLuck/NuomLuck/ScrullLuck/ouozeer mudeeffeers||
+POPUPMA026|Center & Zuom||
+POPUPMA027| Leteetuode||
+POPUPMA028| Lungeetuode||
+POPUPMA029|Drev CED Ouobjects||
+POPUPMA030|Drev||
+POPUPMA031|Cluse-a Pulygun||
+POPUPMA032|Irese-a CED Pulyguns||
+POPUPMA033|**NOT OuoSED**||
+POPUPMA034|Cuostum Zuom Leffel||
+POPUPMA035|10% ououot||
+POPUPMA036|10% ien||
+POPUPMA037|Eree||
+POPUPMA038|squoere||
+POPUPMA039|squoere-a ffeet||
+POPUPMA040|squoere-a meters||
+POPUPMA041|Beereeng||
+POPUPMA042|degrees||
+POPUPMA043|Mudeeffy imbeeguouous puseetiun||
+POPUPMA044|Pusitiun imbeeguoity is ouon, yuour nuo pusitiun mey ippeer tu juomp.. Burk Burk Burk!||
+POPUPMA045|Predeffeened Ouobjects||
+POPUPMA046|CED Pulyguns||
+POPUPMA047|Ineble-a CED ouobjects||
+POPUPMA048|Ineble-a CED lebels||
+POPUPMA049|Ineble-a CED cumments||
+POPUPMA050|Ineble-a CED prubebeeleety||
+POPUPMA051|Ineble-a CED iree-a seeze||
+POPUPMA052|sq||
+POPUPMA053|fft||
+POPUPMA054|meters||
+POPUPMA055|mee|
+BBARZM0001|Zuom %s||
+BBARZM0002|Zuom %s Tr||
+BBARSTH001|%d/%d Steteeuns||
+BBARSTA000|%-9s Nuo ouobject!||
+BBARSTA001|%-9s Nuo stetiun!||
+BBARSTA002|%-9s||# new data (only display the call)
+BBARSTA003|Luedeeng Meps.. Burk Burk Burk!..||
+BBARSTA004|Meps Lueded||
+BBARSTA005|Mep Let/Lung Grid Ouon|O|
+BBARSTA006|Mep Let/Lung Grid Ouoff|f|
+BBARSTA007|Zee-a ouose-a ouoff Ououtu Meps, is nuo OuoN||
+BBARSTA008|Zee-a ouose-a ouoff Ououtu Meps, is nuo OuoFF||
+BBARSTA009|Zee-a ouose-a ouoff Mep Leffels is nuo OuoN||
+BBARSTA010|Zee-a ouose-a ouoff Mep Leffels is nuo OuoFF||
+BBARSTA011|Ouotu Reply Messege-a OuoFF!||
+BBARSTA012|FEEle-a dune-a.. Burk Burk Burk!.||
+BBARSTA013|Oupening GPS Purt||
+BBARSTA014|Clusing GPS Purt||
+BBARSTA015|Gut GPS RMC Streeng||
+BBARSTA016|Gut GPS GGE Streeng||
+BBARSTA017|Net deescunnected ffrum hust||
+BBARSTA018|Net cunnectiun timed ououot!||
+BBARSTA019|Luokeeng ouop hust %s||
+BBARSTA020|Cunnected tu %s||
+BBARSTA021|Net Cunnectiun Feeled!||
+BBARSTA022|Cuould nut beend sucket!||
+BBARSTA023|Nu IP ffur Hust!||
+BBARSTA024|Nu Hust Speceeffeed||
+BBARSTA025|Hust ffuound, Cunnecting %d||
+BBARSTA026|Veeting ffur GPS dete-a fee-a HSP..||
+BBARSTA027|Cleering HSP getting TNC dete-a.. Burk Burk Burk!.||
+BBARSTA028|Luedeeng %s||
+BBARSTA029|Oupening VX Purt||
+BBARSTA030|Clusing VX Purt||
+BBARSTA031|Luokeeng ouop hustneme-a %d||
+BBARSTA032|Decuded VX Dete||
+BBARSTA033|Ichu ffrum deegeepeeter||
+BBARSTA034|Luedeeng Veezeer Ilert Meps||
+BBARSTA035|Veeting ffur GPS dete-a fee-a IOuX..||
+BBARSTA036|Cleering IOuX getting TNC dete-a.. Burk Burk Burk!.||
+BBARSTA037|GPS Dete-a Cumplete||
+BBARSTA038|Pusitiun chuonge-a ouon my steteeun||
+BBARSTA039|Indexing %s||
+BBARSTA040|Emeteuor IPRS(tm) Stetiun %s||
+BBARSTA041|Veeting ffur GPS dete-a.. Burk Burk Burk!.||
+BBARSTA042|Truonsmeetting ouobjects/ietems||
+BBARSTA043|Luggeeng||
+BBARSTA044|ELOHE deestuonce-a is %d%s||
+BBARSTA045|Luedeeng symbuls.. Burk Burk Burk!..||
+BBARSTA046|Reluedeeng symbuls.. Burk Burk Burk!..||
+BBARSTA047|Initieleeze-a my stetiun.. Burk Burk Burk!..||
+BBARSTA048|Stert interffeces.. Burk Burk Burk!..||
+BBARSTA049|Reedeeng tiles.. Burk Burk Burk!..||
+BBARSTA050|Duonluedeeng tiles.. Burk Burk Burk!..||
+BBARSTA051|Duonluedeeng tile-a %lee ouoff %lee||
+WPUPDPD001|DEEspley Pecket Dete||
+WPUPDPD002|TNC Dete-a ouonly|T|
+WPUPDPD003|Net Dete-a ouonly|N|
+WPUPDPD004|TNC ouond Net Dete|a|
+WPUPDPD005|TNC||
+WPUPDPD006|NET||
+WPUPDPD007|Stetiun Cepebeeleeties||
+WPUPDPD008|MEEne-a Ouonly||
+WPUPLSP001|Lucete-a Steteeun||
+WPUPLSP002|Lucete-a Cellseegn||
+WPUPLSP003|Metch Cese|C|
+WPUPLSP004|Metch Ixect|E|
+WPUPLSP005|Lucete-a Nuo!|N|
+WPUPLSP006|Imergency Lucete-a!||
+WPUPLSP007|FCC/REC Luokuop||
+WPUPCFD001|Cunffeeguore-a Deffuolts||
+WPUPCFD002|Effter vhet interffel ouoff time-a vill i-a stetiun be-a cunsidered ouold?||
+WPUPCFD003|15 meen|1|
+WPUPCFD004|30 meen|3|
+WPUPCFD005|45 meen|4|
+WPUPCFD006|1 hr|H|
+WPUPCFD007|90 meen|9|
+WPUPCFD008|2 hrs|2|
+WPUPCFD009|Effter vhet interffel ouoff time-a vill i-a stetiun nut be-a deespleyed?||
+WPUPCFD010|6 hrs|6|
+WPUPCFD011|12 hrs|o|
+WPUPCFD012|1 Dey|D|
+WPUPCFD013|2 Deys|y|
+WPUPCFD014|1 Veek|W|
+WPUPCFD015|Truonsmeet Stetiun Ouopteeun||
+WPUPCFD016|FEExed Steteeun|F|
+WPUPCFD017|Mubeele-a Stetiun v/lucel teeme|l|
+WPUPCFD018|Mubeele-a Stetiun v/Zuoluo dete-a-teeme|Z|
+WPUPCFD019|Mubeele-a Stetiun v/Zuoluo time-a-secunds|u|
+WPUPCFD021|Stetiun Pusitiun v/veezeer|S|
+WPUPCFD022|Stetiun Pusitiun, Zuoluo dete-a-time-a, ouond veezeer|t|
+WPUPCFD023|Truonsmeet Rev VX dete-a?|R|
+WPUPCFD024|Truonsmeet cumpressed ouobjects/items?|C|
+WPUPCFD025|Ectiffete-a Ilternete-a net?|A|
+WPUPCFD026|Send pusitiun repurts it vhet interffels?||
+WPUPCFD027|Pup ouop nuo buolleteens||
+WPUPCFD028|Vern iff Mudeeffeer Keys||
+WPUPCFD029|FEEuo zeru-deestuonce-a buolleteens||
+WPUPCFD030|DEEseble-a Pusit Duope-a-Checks||
+WPUPCFD031|Lued predeffeened ouobjects ffrum ffeele||
+WPUPCFD032|My treels in ouone-a culur||
+WPUPCFD033|ELTNET:||
+WPUPCFTM01|Cunffeeguore-a Teemeeng||
+WPUPCFTM02|Pusit TX Interffel (meen)||
+WPUPCFTM03|Stetiun Ghusting Time-a (meen)||
+WPUPCFTM04|Oubject/Item Mex TX Interffel (meen)||
+WPUPCFTM05|Stetiun Cleer Time-a (huours)||
+WPUPCFTM06|GPS Check Interffel (sec)||
+WPUPCFTM07|Stetiun Delete-a Time-a (deys)||
+WPUPCFTM08|Deed-Reckuning Timeuout (meen)||
+WPUPCFTM09|Seriel Inter-Cher Deley (ms)||
+WPUPCFTM10|Nuo Treck Time-a (meen)||
+WPUPCFTM11|Nuo Treck Interffel (degrees)||
+WPUPCFTM12|RINO -> Ouobjects Interffel (meen), 0 = Deesebled||
+WPUPCFTM13|Snepshut Interffel (meen)||
+WPUPCFC001|Cunffeeguore-a Cuordeenete-a System||
+WPUPCFC002|Select Cuordeenete-a System||
+WPUPCFC003|dd.. Burk Burk Burk!ddddd|d|
+WPUPCFC004|dd mm.. Burk Burk Burk!mmm|m|
+WPUPCFC005|dd mm ss.. Burk Burk Burk!s|s|
+WPUPCFC006|OuTM|U|
+WPUPCFC007|OuSNG/MGRS2||
+WPUPCFC008|OuTM v/speceel zunes||
+WPUPCFG001|Cunffeeguore-a GPS||
+WPUPCFG003|Stuond ilune-a GPS purt||
+WPUPCFG002|Ouse-a GPS Pusitiun?||
+WPUPCFG004|GPS Ouopteeuns||
+WPUPCFG005|Stuond-ilune-a GPS||
+WPUPCFG006|TNC Cunnected GPS (HSP Ceble-a)||
+WPUPCFG007|TNC Cunnected GPS ouosing CTL-I||
+WPUPCFG008|GPS Time-a (Semple-a iffery)||
+WPUPCFG009|5 sec||
+WPUPCFG010|15 sec||
+WPUPCFG011|30 sec||
+WPUPCFG012|1 meen||
+WPUPCFG013|2 meen||
+WPUPCFG014|5 meen||
+WPUPCFG015|10 meen||
+WPUPCFG016|Netvurk Cunnected GPS||
+WPUPCFG017|GPSD Hust||
+WPUPCFG018|GPSD Purt||
+WPUPCFG019|Netvurk GPS fee-a GPSD||
+WPUPCFG020|Recunnect ouon ffeeluore-a?||
+WPUPCFG021|Netvurk Cunnected VX||
+WPUPCFG022|VX Hust||
+WPUPCFG023|VX Purt||
+WPUPCFT001|Cunffeeguore-a TNC||
+WPUPCFT002|Ouse-a TNC?||
+WPUPCFT003|TNC Purt||
+WPUPCFT004|Purt Setteengs||
+WPUPCFT005|300 bps||
+WPUPCFT006|1200 bps||
+WPUPCFT007|2400 bps||
+WPUPCFT008|4800 bps||
+WPUPCFT009|9600 bps||
+WPUPCFT010|19200 bps||
+WPUPCFT011|OunPrutu Peths||
+WPUPCFT012|Pet 1: %s fee-a ||
+WPUPCFT013|Pet 2: %s fee-a ||
+WPUPCFT014|Pet 3: %s fee-a ||
+WPUPCFT015|Purt Style||
+WPUPCFT016|8,N,1||
+WPUPCFT017|7,I,1||
+WPUPCFT018|7,Ouo,1||
+WPUPCFT019|38400 bps||
+WPUPCFT020|57600 bps||
+WPUPCFT021|115200 bps||
+WPUPCFT022|230400 bps||
+WPUPCFT023|Cunffeeguore-a TNC v/HSP GPS||
+WPUPCFT024|Dete-a Type||
+WPUPCFT025|Ouotu detect||
+WPUPCFT026|BEEnery Type||
+WPUPCFT027|ESCII Type||
+WPUPCFT028|Cunffeeguore-a TNC v/IOuX GPS||
+WPUPCFT029|Cunffeeguore-a TNC v/INFELID INOuM||
+WPUPCFT030|Cunffeeguore-a KISS TNC||
+WPUPCFT031|TNC Cunffeeguoretiun Feeles||
+WPUPCFT032|TNC Setuop Feeleneme||
+WPUPCFT033|TNC Shuotduon Feeleneme||
+WPUPCFT034|KISS Peremeters||
+WPUPCFT035|TXDeley (10 ms ouonits)||
+WPUPCFT036|Persistence-a (0 tu 255)||
+WPUPCFT037|SlutTime-a (10 ms ouonits)||
+WPUPCFT038|TxTeel (10 ms ouonits)||
+WPUPCFT039|Fuoll Duoplex||
+WPUPCFT040|Cunffeeguore-a Muolti-Purt KISS TNC||
+WPUPCFT041|Redeeu Purt||
+WPUPCFT042|Interffece-a Pruperties: Duobeeuous OuoNPROTO Pet!||
+WPUPCFT043|Pleese-a cunsider i-a shurter pet suoch is VIDE2-2 ouor VIDE1-1,VIDE2-2||
+WPUPCFT044|Interffece-a Pruperties: Duobeeuous IGETE Pet!||
+WPUPCFT045|Truonsmeetting v/Duobeeuous OuoNPROTO Pet!||
+WPUPCFT046|Truonsmeetting v/Duobeeuous IGETE Pet!||
+WPUPCFT047|Init KISS-mude-a ouon stertuop||
+WPUPCFWX01|Cunffeeguore-a VX Purt||
+WPUPCFWX02|Veezeer Stetiun deffeece||
+WPUPCFWX03|Reen Guoge-a Currectiun (Glubel Setting)||
+WPUPCFWX04|.1 inch/2.5mm||
+WPUPCFWX05|.01 inch/.25mm||
+WPUPCFWX06|.1mm||
+WPUPCFWX07|Nu Currecteeun||
+WPUPCFS001|Cunffeeguore-a Steteeun||
+WPUPCFS002|Cellseegn||
+WPUPCFS003|LET||
+WPUPCFS004|deg||
+WPUPCFS005|meen||
+WPUPCFS006|(N/S)||
+WPUPCFS007|LONG||
+WPUPCFS008|(I/V)||
+WPUPCFS009|Stetiun Symbul||
+WPUPCFS010|Gruoup/ouofferley||
+WPUPCFS011|Symbul||
+WPUPCFS028|Select||
+WPUPCFS012|Puoer - Heeght (HEAT) - Geen - Deerectiffeety||
+WPUPCFS013|DEEseble-a PHG||
+WPUPCFS014|Ountenne-a Heeght||
+WPUPCFS015|Ountenne-a Geen||
+WPUPCFS016|Oumnee||
+WPUPCFS017|Cumment:||
+WPUPCFS018|Pusitiun Imbeeguoity||
+WPUPCFS019|Nune||
+WPUPCFS020|.11 meeles||
+WPUPCFS021|1.15 meeles||
+WPUPCFS022|11.51 meeles||
+WPUPCFS023|69.09 meeles||
+WPUPCFS024|.18 keelumetres||
+WPUPCFS025|1.85 keelumetres||
+WPUPCFS026|18.53 keelumetres||
+WPUPCFS027|111.19 keelumetres||
+WPUPCFS029|Send cumpressed puseets|C|
+POPUPOB001|Oubject/Item||
+POPUPOB002|Neme-a:||
+POPUPOB003|Creete-a Nuo Ouobject||
+POPUPOB004|Delete-a Ouobject||
+POPUPOB005|Mudeeffy Ouobject||
+POPUPOB006|Creete-a Nuo Item||
+POPUPOB007|Eree-a Ouobject||
+POPUPOB008|Eree-a Ouobject||
+POPUPOB009|Bright Culur||
+POPUPOB010|Culur-Feell||
+POPUPOB011|Ceercle||
+POPUPOB012|LEEne-a-Right '/'||
+POPUPOB013|LEEne-a-Lefft '\'||
+POPUPOB014|Treeuongle||
+POPUPOB015|Rectuongle||
+POPUPOB016|Bleck||
+POPUPOB017|Bluoe||
+POPUPOB018|Gree||
+POPUPOB019|Cyuon||
+POPUPOB020|Red||
+POPUPOB021|Feeulet||
+POPUPOB022|Yelluo||
+POPUPOB023|Grey||
+POPUPOB024|Ouffset Ouop:||
+POPUPOB025|Ouffset Lefft (Ixcept '/'):||
+POPUPOB026|Curridur:||
+POPUPOB027|Generic Ouopteeuns||
+POPUPOB028|Luceteeun||
+POPUPOB029|Seegnpust||
+POPUPOB030|Signpust Text||
+POPUPOB031|Signpust Ouobject||
+POPUPOB032|Ineble-a Cumpresseeun||
+POPUPOB033|Delete-a Item||
+POPUPOB034|Mudeeffy Item||
+POPUPOB035|Eltituode-a (fft):||
+POPUPOB036|Speed (knuts):||
+POPUPOB037|Cuourse-a:||
+POPUPOB038|DF Ouobject||
+POPUPOB039|Signel - Heeght(HEAT) - Geen - Deerectiffeety||
+POPUPOB040|Beem Vidt - Beereeng||
+POPUPOB041|Oumni Ouontenne||
+POPUPOB042|Beem Ouontenne||
+POPUPOB043|Ouseless||
+POPUPOB044|Edupt Ouobject||
+POPUPOB045|Edupt Item||
+POPUPOB046|DF Beering:||
+POPUPOB047|Prubebeeleety Ceercles||
+POPUPOB048|Mep FEEuo Ouobject||
+POPUPOB049|MEEn (mee):||
+POPUPOB050|Mex (mee):||
+WPUPCFI001|Cunffeeguore-a Internet||
+WPUPCFI002|Hust ||
+WPUPCFI003|Purt ||
+WPUPCFI004|(Secundery husts)||
+WPUPCFI005|Hust1||
+WPUPCFI006|Purt1||
+WPUPCFI007|Hust2||
+WPUPCFI008|Purt2||
+WPUPCFI009|Pess-cude||
+WPUPCFI010|(Leeffe-a Bluonk iff Nune-a)||
+WPUPCFI011|Recunnect ouon NET ffeeluore-a?||
+WPUPCFI012|Ruon is ouon I-Gete-a?||
+WPUPCFI013|Bruedcest messeges fee-a TNC vhee-a ouon I-Gete-a?||
+WPUPCFI014|Lug I-Gete-a Truonsectiuns?||
+WPUPCFI015|FEElter Peremeters||
+WPUPCFID01|Cunffeeguore-a Detebese-a (TBD)||
+WPUPCFID02|Hust ||
+WPUPCFID03|Purt ||
+WPUPCFID04|(Secundery husts)||
+WPUPCFID05|Hust1||
+WPUPCFID06|Purt1||
+WPUPCFID07|Hust2||
+WPUPCFID08|Purt2||
+WPUPCFID09|Pess-cude||
+WPUPCFID10|(Leeffe-a Bluonk iff Nune-a)||
+WPUPCFID11|Recunnect ouon NET ffeeluore-a?||
+WPUPCFID12|Ruon is ouon I-Gete-a?||
+WPUPCFID13|Bruedcest messeges fee-a TNC vhee-a ouon I-Gete-a?||
+WPUPCFID14|Lug I-Gete-a Truonsectiuns?||
+WPUPCFID15|FEElter Peremeters||
+WPUPCFIA01|Cunffeeguore-a IGVPE||
+WPUPCFIA02|Hust ||
+WPUPCFIA03|Purt ||
+WPUPCFIA04|(Secundery husts)||
+WPUPCFIA05|Hust1||
+WPUPCFIA06|Purt1||
+WPUPCFIA07|Hust2||
+WPUPCFIA08|Purt2||
+WPUPCFIA09|Pess-cude||
+WPUPCFIA10|(Leeffe-a Bluonk iff Nune-a)||
+WPUPCFIA11|Recunnect ouon NET ffeeluore-a?||
+WPUPCFIA12|Ruon is ouon I-Gete-a?||
+WPUPCFIA13|Bruedcest messeges fee-a TNC vhee-a ouon I-Gete-a?||
+WPUPCFIA14|Lug I-Gete-a Truonsectiuns?||
+WPUPCFIA15|Truonsmeet RedeeuPurt||
+WPUPCFA001|Cunffeeguore-a Ououdeeu Ilerms||
+WPUPCFA002|Ouodeeu Pley Cummuond||
+WPUPCFA003|Elerm ouon||
+WPUPCFA004|Ouodeeu ffeele-a tu Pley||
+WPUPCFA005|Nuo Steteeun||
+WPUPCFA006|Nuo Messege||
+WPUPCFA007|Pruxeemeety||
+WPUPCFA008|Buond Ouopeneeng||
+WPUPCFA009|MEEnimuom Deestuonce||
+WPUPCFA010|Meximuom Deestuonce||
+WPUPCFA011|Veezeer Ilert||
+WPUPCFSP01|Cunffeeguore-a Speech||
+WPUPCFSP02|Speech Ououotpuot ouon:||
+WPUPCFSP03|Nuo Steteeun||
+WPUPCFSP04|Nuo Messege-a Ilert||
+WPUPCFSP05|Nuo Messege-a Budy||
+WPUPCFSP06|Pruximeety Ilert||
+WPUPCFSP07|Buond Ouopeneeng||
+WPUPCFSP08|Nuo Veezeer Ilert||
+WPUPCFSP09|Trecked Stetiun Pruximeety Ilert||
+WPUPTSP001|Treck Steteeun||
+WPUPTSP002|Treck Cellseegn||
+WPUPTSP003|Metch Cese||
+WPUPTSP004|Metch Ixect||
+WPUPTSP005|Treck Nuo!||
+WPUPTSP006|Cleer Treckeeng||
+WPUPTSP007|Duonlued Treel||
+WPUPTSP008|Cellseegn||
+WPUPTSP009|Stert Treel (hrs igu)||
+WPUPTSP010|Treel Lengt (hrs)||
+WPUPMSB001|Send Messege-a Bux %d||
+WPUPMSB002|Send Gruoup Messege-a Bux %d||
+WPUPMSB003|Stetiun's Cell:||
+WPUPMSB004|Gruoup's Cell:||
+WPUPMSB005|Nuo/Reffresh Cell||
+WPUPMSB006|Nuo Gruoup||
+WPUPMSB007|Cleer Msg Heestury||
+WPUPMSB008|Messege-a:||
+WPUPMSB009|Send Nuo!||
+WPUPMSB010|Pet:||
+WPUPMSB011|Cuoncel Pendeeng Msgs||
+WPUPMSB012|KEEck Teemer||
+WPUPMSB013|seq||
+WPUPMSB014|type||
+WPUPMSB015|Bruedcest||
+WPUPMSB016|*TIMEOOuT*||
+WPUPMSB017|*CENCELLED*||
+WPUPMSB018|*REJECTED*||
+WPUPMSB019|Chuonge-a Pet||
+WPUPMSB020|Ouse-a Deffuolt Pet(s)||
+WPUPMSB021|Durect (Nu pet)||
+WPUPMSB022|Refferse-a Pet (HEEnt):||
+WPUPARM001|Chuonge-a Ououtu Reply||
+WPUPARM002|Reply:||
+WPUPHPI001|Help Index||
+WPUPHPI002|Feeuo||
+WPUPSTI000|Oubject ffrum: %s||
+WPUPSTI001|Stetiun Inffu||
+WPUPSTI002|Send Messege||
+WPUPSTI003|Seerch FCC Detebese||
+WPUPSTI004|Seerch REC Detebese||
+WPUPSTI005|Peckets receeffed: %d Lest Heerd: ||
+WPUPSTI006|Heerd fee-a zee-a TNC ouon deffeece-a %d, ||
+WPUPSTI007|Heerd ||
+WPUPSTI008|lest fee-a Lucel||
+WPUPSTI009|lest fee-a TNC ouon deffeece-a %d||
+WPUPSTI010|lest fee-a Internet ouon deffeece-a %d||
+WPUPSTI011|lest fee-a Feele||
+WPUPSTI012|lest fee-a Ouonknuon||
+WPUPSTI013|, ouond hes muffed||
+WPUPSTI014|Cuorrent Puoer Geen:||
+WPUPSTI016|Eltituode-a: %.0ff%s ||
+WPUPSTI017|Cuourse-a: %s� ||
+WPUPSTI018|Speed: %.1ff km/h||
+WPUPSTI019|Speed: %.1ff mph||
+WPUPSTI020|%0.1ff meeles||
+WPUPSTI021|%0.1ff km||
+WPUPSTI022|DEEstuonce-a ffrum my stetiun: %s Beering ffrum my stetiun: %s||
+WPUPSTI023|Lest Pusitiun: ||
+WPUPSTI024|Veezeer Dete-a %c:%s||
+WPUPSTI025|Vind Cuourse-a: %s� Speed: %03d km/h||
+WPUPSTI026|Vind Cuourse-a: %s� Speed: %s mph||
+WPUPSTI027| Guost: %03d km/h||
+WPUPSTI028| Guost: %s mph||
+WPUPSTI029|Temperetuore-a: %02.1ff�C ||
+WPUPSTI030|Temperetuore-a: %s�F ||
+WPUPSTI031|Huomeedeety: %s%% ||
+WPUPSTI032| Huomeedex: %02.1ff�C ||
+WPUPSTI033|Beru: %s hPe||
+WPUPSTI034|Snuo: %0.1ff (cm/24h)||
+WPUPSTI035|Snuo: %0.0ff (inch/24h)||
+WPUPSTI036|Reen: ||
+WPUPSTI037|%0.2ff (mm/h) ||
+WPUPSTI038|%0.2ff (inch/h) ||
+WPUPSTI039|%0.2ff (mm/dey) ||
+WPUPSTI040|%0.2ff (inch/dey) ||
+WPUPSTI041|%0.2ff (mm/since-a meednight)||
+WPUPSTI042|%0.2ff (inch/since-a meednight)||
+WPUPSTI043|Dete-a pet: %s||
+WPUPSTI044|Cumment %02d/%02d %02d:%02d : %s||
+WPUPSTI045|Cleer Treck||
+WPUPSTI046|Tutel Reen: ||
+WPUPSTI047|%0.2ff (mm)||
+WPUPSTI048|%0.2ff (inch)||
+WPUPSTI049|Trece-a Quoery||
+WPUPSTI050|Oun-Icked Messeges Quoery||
+WPUPSTI051|Durect Stetiuns Quoery||
+WPUPSTI052|Stetiun Fersiun Quoery||
+WPUPSTI053|Mudeeffy Ouobject/Item||
+WPUPSTI054|Sture-a Treck||
+WPUPSTI055|Ichued ffrum:||
+WPUPSTI056|Ineble-a Ououtumetic Ouopdetes||
+WPUPSTI057|Oumni-DF: %s||
+WPUPSTI058|DF Beering: %s||
+WPUPSTI059|Stetuos %02d/%02d %02d:%02d : %s||
+WPUPSTI060|Fuoel Temp: %02.1ff�C ||
+WPUPSTI061|Fuoel Temp: %s�F ||
+WPUPSTI062|Fuoel Muistuore-a: %s%% ||
+WPUPSTI063|Beru: %0.2ff in Hg||
+WPUPSTI064|Fetch NVS Ilert||
+WPUPSTI065|Tecticel Cell: %s||
+WPUPSTI066|Essign Tecticel Cell||
+WPUPSTI067|Cuorrent Ruonge-a: %d meeles||
+WPUPSTI068|nune||
+WPUPSTI069|deffuolt||
+WPUPSTI070|HEAT||
+WPUPSTI071|oumnee||
+WPUPSTI072|ruonge||
+WPUPSTI073|BED PHG||
+WPUPSTI074|BED SHG||
+WPUPSTI075|DF Ruonge||
+WPUPSTI076|Nu signel detected||
+WPUPSTI077|Detectible-a signel (Meybe-a)||
+WPUPSTI078|Detectible-a signel buot nut cupyeble-a)||
+WPUPSTI079|Veek signel, mergeenelly reedeble||
+WPUPSTI080|Nuisy buot cupyeble-a seegnel||
+WPUPSTI081|Sume-a nuise-a, iesy tu cupy seegnel||
+WPUPSTI082|Guod signel v/detectible-a nueese||
+WPUPSTI083|Neer ffuoll-quoieting seegnel||
+WPUPSTI084|Fuoll-quoieting seegnel||
+WPUPSTI085|Ixtremely strung & ffuoll-quoieting seegnel||
+WPUPSTI086|BED BEERING||
+WPUPSTI087|BED NRQ||
+WPUPSTI088|DF Beemveedt||
+WPUPSTI089|DF Lengt||
+WPUPSTI090|Nut Feleed||
+WPUPSTI091|Chuonge-a Treel Culur||
+WPUPSTI092|Cleer DF Beereeng||
+WPUPALO001|ELOHE redeeuos: %d %s||
+WPUPALO002|Stetiuns inside-a ILOHE curcle-a: %d||
+WPUPALO003| DEEgees: %d||
+WPUPALO004| Mubeeles (in mutiun): %d||
+WPUPALO005| Mubeeles (ouozeer): %d||
+WPUPALO006| VX stetiuns: %d||
+WPUPALO007| Hume-a stetiuns: %d||
+WPUPALO008|Lest celcuoleted %d %s %d %s igu.. Burk Burk Burk!||
+WPUPALO666|ELOHE redeeuos nut celcuoleted yet||
+STIFCC0001|FCC Detebese-a Luokuop||
+STIFCC0002|REC Detebese-a Luokuop||
+STIFCC0003|Neme-a:||
+STIFCC0004|Street:||
+STIFCC0005|CEEty:||
+STIFCC0006|Stete-a:||
+STIFCC0007|Zip:||
+STIFCC0008|Besic ||
+STIFCC0009|Edffuonced ||
+STIFCC0010|5 vpm ||
+STIFCC0011|12 vpm ||
+STIFCC0100|FCC index ouold, rebuoeeldeeng||
+STIFCC0101|Cellsign Seerch||
+STIFCC0102|Cellsign Nut Fuound!||
+STIFCC0103|REC index ouold, rebuoeeldeeng||
+UMBNDO0001|et deestuonce-a ouoff||
+UNIOP00001|OuK||
+UNIOP00002|Cuoncel||
+UNIOP00003|Cluse||
+UNIOP00004|meeles||
+UNIOP00005|km||
+UNIOP00006|Deffeece||
+UNIOP00007|Edd||
+UNIOP00008|Delete||
+UNIOP00009|Prupertees||
+UNIOP00010|Elluo Truonsmeetting?||
+UNIOP00011|Ectiffete-a ouon Stertuop?||
+UNIOP00012|km/h||
+UNIOP00013|mph||
+UNIOP00014|�C||
+UNIOP00015|�F||
+UNIOP00016|mm||
+UNIOP00017|eench||
+UNIOP00018|mm/dey||
+UNIOP00019|inch/dey||
+UNIOP00020|mm/hr||
+UNIOP00021|inch/hr||
+UNIOP00022|mm/meed||
+UNIOP00023|inch/meed||
+UNIOP00024|deg||
+UNIOP00025|hPe||
+UNIOP00026|%||
+UNIOP00027|in Hg||
+UNIOP00028|mm Hg||
+UNIOP00029|Set System Cluck ffrum GPS Dete-a?||
+UNIOP00030|DEEgeepeet?||
+UNIOP00031|m||
+UNIOP00032|Epply||
+UNIOP00033|Reset||
+UNIOP00034|meen||
+UNIOP00035|hr||
+UNIOP00036|dey||
+UNIOP00037|Send Cuntrul-I tu get GPS dete-a?||
+UNIOP00038|Edd Deley||
+STCHO00001|Stetiun Chuoser||
+WPUPWXA001|Vx Ilerts||
+WPUPWXA002|Vx Ilert Leest||
+WPUPCIF001|Instelled Interffeces||
+WPUPCIF002|Chuose-a Interffece-a Type||
+WPUPCAX001|Cunffeeguore-a IX.25 TNC||
+WPUPCAX002|EX.25 Deffeece-a neme||
+IFDNL00000|Nune||
+IFDNL00001|Seriel TNC||
+IFDNL00002|Seriel TNC v/GPS ouon i-a HSP ceble||
+IFDNL00003|Seriel GPS||
+IFDNL00004|Seriel VX||
+IFDNL00005|Internet Serffer||
+IFDNL00006|EX25 TNC||
+IFDNL00007|Netvurked GPS (fee-a gpsd)||
+IFDNL00008|Netvurked VX||
+IFDNL00009|Seriel TNC v/GPS ouon IOuX purt||
+IFDNL00010|Seriel KISS TNC||
+IFDNL00011|Netvurked Detebese-a (Nut Implemented Yet)||
+IFDNL00012|Netvurked IGVPE||
+IFDNL00013|Seriel Muolti-Purt KISS TNC||
+IFDNL00014|SQL Detebese-a (Ixperimentel)||
+IFDIN00000|%s %2d %s %s %s||
+IFDIN00001|%s %2d %s %s:%d %s||
+IFDIN00002|%s %2d %s deffeece-a %s %s||
+IFDIN00003|%s %2d %s %s %s %s||
+IFDIN00004|%s %2d %s %s %s:%d %s||
+IFDIN00005|%s %2d %s %s %s %s||
+IFDIN00006| DOVN ||
+IFDIN00007| OuoP ||
+IFDIN00008|IRROR ||
+IFDIN00009|OuNKNVN||
+IFPUPCT000|Interffece-a Cuntrul||
+IFPUPCT001|Stert||
+IFPUPCT002|Stup||
+IFPUPCT003|Stert Ill||
+IFPUPCT004|Stup Ill||
+IGPUPCF000|IGete-a Ouopteeuns||
+IGPUPCF001|DEEseble-a ill IGete-a treffeec||
+IGPUPCF002|Elluo RF tu Inet treffeec OuoNLY||
+IGPUPCF003|Elluo RF->Inet ouond Inet->RF treffeec||
+IGPUPCF004|Igete-a -> RF Pet ||
+WXPUPSI000|VX Steteeun||
+WXPUPSI001|VX Stetiun Type||
+WXPUPSI002|Cuorrent Dete||
+WXPUPSI003|Vind Cuourse||
+WXPUPSI004|Vind Speed||
+WXPUPSI005|Vind Guost||
+WXPUPSI006|Temp||
+WXPUPSI007|Tutel Reen||
+WXPUPSI008|Tudey's Reen Tutel||
+WXPUPSI009|Beru||
+WXPUPSI010|Huomeedeety||
+WXPUPSI011|Peet Brus OuoLTIMETER 2000 Type-a (Dete-a Luggeeng Mude-a)||
+WXPUPSI012|Peet Brus OuoLTIMETER II Type||
+WXPUPSI013|Peet Brus OuoLTIMETER 2000 Type-a (Pecket Mude-a)||
+WXPUPSI014|Cuorrent HR Reen Tut.. Burk Burk Burk!||
+WXPUPSI015|Lest 24 Reen Tutel||
+WXPUPSI016|Quoeleemetrics Q-Net||
+WXPUPSI017|Peet Brus OuoLTIMETER 2000 Type-a (Cumplete-a Mude-a)||
+WXPUPSI018|Duo Pueent||
+WXPUPSI019|HEEgh Veend||
+WXPUPSI020|Vind Cheell||
+WXPUPSI021|Heet Index||
+WXPUPSI022|3-Hr Beru||
+WXPUPSI023|HEEgh Temp.. Burk Burk Burk!||
+WXPUPSI024|Luo Temp.. Burk Burk Burk!||
+WXPUPSI025|Redeeu Sheck VX-200/Ouoregun Sceentiffeec VM-918||
+WXPUPSI026|Deffees Veezeer Munitur II/Vizerd III/Fuontege-a Pru||
+WXPUPSI027|LeCrusse-a VX-23xx||
+WXPUPSI028|Deffees IPRS Dete-a Lugger||
+LHPUPNI000|Ell Steteeuns||
+LHPUPNI001|Mubeele-a Steteeuns||
+LHPUPNI002|Veezeer Steteeuns||
+LHPUPNI003|Lucel Stetiuns (fee-a TNC)||
+LHPUPNI004|Lest Steteeuns||
+LHPUPNI005|Oubjects & Items||
+LHPUPNI006|Ouon Ouobjects & Items||
+LHPUPNI010|#||
+LHPUPNI011|Cell Seegn||
+LHPUPNI012|#Peck||
+LHPUPNI013|Pus Teeme||
+LHPUPNI014|Pet||
+LHPUPNI015|PHG||
+LHPUPNI016|Cumments||
+LHPUPNI100|CSE||
+LHPUPNI101|SPD||
+LHPUPNI102|ELT.||
+LHPUPNI103|Let||
+LHPUPNI104|Lung||
+LHPUPNI105|#Peck||
+LHPUPNI106|LSF||
+LHPUPNI107|CFMS||
+LHPUPNI108|DFMS||
+LHPUPNI200|CSE||
+LHPUPNI201|SPD||
+LHPUPNI202|GST||
+LHPUPNI203|Temp||
+LHPUPNI204|Huom||
+LHPUPNI205|Beru||
+LHPUPNI206|RN-H||
+LHPUPNI207|RNSM||
+LHPUPNI208|RN24||
+LHPUPNI209|Let/Lun ouor OuoTM||
+PULDNMAT01|Shuo Ilert meps ibuffe-a ouozeer meps||
+PULDNMAT02|Shuo Ilert meps ouonder ouozeer meps||
+POPEM00001|Lucete-a Irrur!||
+POPEM00002|Stetiun %s ves nut ffuound!||
+POPEM00003|Treckeeng Irrur!||
+POPEM00004|Interffece-a Irrur!||
+POPEM00005|Inffeleed IX.25 purt neme-a %s||
+POPEM00006|Inffeleed IX.25 purt neme-a %s||
+POPEM00007|Inffeleed cellsign %s||
+POPEM00008|Inffeleed IX.25 destinetiun cellsign ouor deegeepeeter||
+POPEM00009|Cuonnut ouopee-a IX.25 sucket, %s||
+POPEM00010|Cuonnut beend IX.25 sucket, %s||
+POPEM00011|Cuonnut cunnect tu IX.25 cellsign, %s||
+POPEM00012|EX.25 ouorrur ouon ououotpuot ouoff OuoI||
+POPEM00013|EX.25 prublem vit ixpurts ffeele||
+POPEM00014|EX.25 inffeleed purt neme-a %s||
+POPEM00015|Irrur ouopening interffece-a %d Herd Feel||
+POPEM00016|Irrur ouopening interffece-a %d Time-a Ououot||
+POPEM00017|Nu mure-a interffeces Iffeeleble-a!||
+POPEM00018|Dete-a Quoery - Single-a Messege-a Leene||
+POPEM00019|Purt truonsmeetting is ouoff ffur purt %d||
+POPEM00020|Detebese-a Irrur!||
+POPEM00021|EX.25 suoppurt nut cumpiled intu Xestur!||
+POPEM00022|Inpuot Irrur!||
+POPEM00023|Nu lucetiun neme-a speceeffeed!||
+POPEM00024|Lucetiun neme-a speceeffeed is in ouose-a!||
+POPEM00025|Nut Fuound!||
+POPEM00026|Treckeeng vill cummence-a vhee-a it ippeers||
+POPEM00027|Impruper inffu.. Burk Burk Burk! Sume-a ffeelds impty?||
+POPEM00028|Cuon't ouopee-a ffeele||
+POPEM00029|Fuound It!||
+POPEM00030|Veezeer Stetiun Symbul||
+POPEM00031|Chuonged tu VX symbul '/_', ouozeer ouoptiuns: '\_' '/V' ouond '\V'||
+POPEM00032|Verning: Ouosing Netiunel Veezeer Serffeece-a Symbul!||
+POPEM00033|Nu GPS Dete-a!||
+POPEM00034|DEEsebleeng My Pusitiun TX Ouontil Feleed GPS Dete-a!||
+POPEM00035|Verneeng||
+POPEM00036|Nuteece||
+POPEM00037|HSP interffece-a present: GPS timeeng hes bee-a iencreesed||
+POPEM00038|Neme-a Cunffleects Vit Ixisting Ouobject/Item/Steteeun||
+POPEM00039|Illegel cherecters ffuound, suobstituoting periuds in zeeur plece||
+POPEM00040|Cuostum ououotguing pet ves lust||
+POPEM00041|Prucessing ouonuzeer ffeele-a.. Burk Burk Burk! Veet i-a beet, zee-a try igeen||
+POPEM00042|Oubject nut ououned by me-a! Try idupting zee-a ouobject ffurst.. Burk Burk Burk!||
+POPEM00043|Nut ouon Ouobject/Item!||
+POPEM00044|Fetch FEEnduo Treel: Feeled||
+POPEM00045|Fetch FEEnduo Treel: Cumplete||
+POPEM00046|Berkeley DB heeder/shered leebrery du NOT metch! DEEsebleeng mep ceche-a.. Burk Burk Burk!||
+POPEM00047|Glubel truonsmeet is DISEBLED. Imergency beecuns ire-a NOT guing ououot!||
+POPEM00048|Imergency Beecun Mude-a!||
+POPEM00049|IMERGENCY BEECON MODE, truonsmeetting iffery 60 secunds!||
+POPEM00050|Interffeces ouor pusits/truonsmeets DISEBLED. Imergency beecuns ire-a NOT guing ououot!||
+POPEM00051|Eltnet is inebled (Cunffeeguore-a->Deffuolts deelug)||
+POPEM00052|Cellsign is IMPTY!||
+POPEM00053|Messege-a is IMPTY!||
+POPEM00054|Ve-a're-a trying tu telk tu ououorselffes!||
+JMLPO00001|Mep DEEspley Buokmerks||
+JMLPO00002|Ectiffete-a!||
+JMLPO00003|Nuo Neme-a:||
+BULMW00001|Buolleteens||
+BULMW00002|LEEmeet Ruonge-a tu (0, is nu leemeet)||
+BULMW00003|Chuonge-a Ruonge||
+AMTMW00001|Ell Messege-a Treffeec||
+AMTMW00002|LEEmeet Ruonge-a tu (0, is nu leemeet)||
+SPCHSTR001|keelumeters||
+SPCHSTR002|meters||
+SPCHSTR003|meeles||
+SPCHSTR004|yerds||
+SPCHSTR005|%s, deestuonce-a is %d %s.. Burk Burk Burk!||
+SPCHSTR006|%s, deestuonce-a is %.1ff %s.. Burk Burk Burk!||
+SPCHSTR007|%s, deestuonce-a is %d %s %s %s.. Burk Burk Burk!||
+SPCHSTR008|%s, deestuonce-a is %.1ff %s %s %s.. Burk Burk Burk!||
+SPCHSTR009|Nuo Veezeer Ilert||
+SPCHSTR010|Nuo Steteeun||
+SPCHSTR011|Heerd, D X, %s, it deestuonce-a ouoff %.1ff %s||
+SPCHDIRN00|nurt ouoff||
+SPCHDIRS00|suout ouoff||
+SPCHDIRE00|iest ouoff||
+SPCHDIRW00|vest ouoff||
+SPCHDIRNE0|nurzeest ouoff||
+SPCHDIRNW0|nurthvest ouoff||
+SPCHDIRSE0|suouzeest ouoff||
+SPCHDIRSW0|suouthvest ouoff||
+SYMSEL0001|Select Symbul||
+SYMSEL0002|Primery Symbul Teble||
+SYMSEL0003|Secundery Symbul Teble||
+PRINT0001|Print Prupertees||
+PRINT0002|Peper Seeze||
+PRINT0003|Ouotu-Rutete-a Imege||
+PRINT0004|Rutete-a Imege-a 90� CCV||
+PRINT0005|Ouotu-Scele-a Imege||
+PRINT0006|Scele-a:||
+PRINT0007|Furce-a deffuolt beckgruound culur tu vheete||
+PRINT0008|Print in Bleck ouond Vheete||
+PRINT0016|Refferse-a Culurs||
+PRINT0009|Pustscript Resuluotiun:||
+PRINT0010|Preffeeuo||
+PRINT0011|Print tu Feele||
+PRINT0012|Duomping imege-a tu ffeele-a.. Burk Burk Burk!..||
+PRINT0013|Cunfferting tu Pustscript.. Burk Burk Burk!..||
+PRINT0014|FEEnished creeting print ffeele||
+PRINT0015|Print Stetuos||
+PRINT1001|Durect tu:||
+PRINT1002|FEEe-a Preffeeuoer:||
+FEATURE001|Neme-a:||
+FEATURE002|Stete-a/Pruffeence-a:||
+FEATURE003|Cuounty:||
+FEATURE004|Mep Quoed:||
+FEATURE005|Type-a:||
+FEATURE006|GNIS FEEle-a:||
+FEATURE007|Eddress:||
+FEATURE008|CEEty:||
+FEATURE009|Merk Desteenetiun||
+FEATURE010|Zip Cude-a:||
+FEATURE011|Geucudeeng Feele||
+COORD001|Cuordeenete-a Celcuoletur||
+COORD002|Celc||
+COORD003|Celcuolete||
+COORD004|Cleer||
+COORD005|OuTM||
+COORD006|Letituode-a ouor||
+COORD007|Lungeetuode-a ouor||
+COORD008|Zune||
+COORD009|OuTM Iesteeng||
+COORD010|OuTM Nurzeeng||
+COORD011| Deceemel Degrees: ||
+COORD012| Degrees/Deceemel MEEnuotes: ||
+COORD013| Degrees/MEEnuotes/Dec.. Burk Burk Burk! Secunds: ||
+COORD014| Ouoniffersel Truonsfferse-a Mercetur: ||
+COORD015|MEEleetery Grid Refference-a System: ||
+COORD016| Meedenheed Grid Lucetur: ||
+COORD017| ** Surry, yuour inpuot ves nut recugnized! **||
+COORD018| ** Pleese-a ouose-a ouone-a ouoff zee-a ffulluoing inpuot ffurmets: **||
+SMARTB001|Smert Beecuneeng||
+SMARTB002|HEEgh Rete-a (secs):||
+SMARTB003|HEEgh Speed (mph):||
+SMARTB004|HEEgh Speed (kph):||
+SMARTB005|Luo Rete-a (meens):||
+SMARTB006|Luo Speed (mph):||
+SMARTB007|Luo Speed (kph):||
+SMARTB008|MEEnimuom Tuorn (deg):||
+SMARTB009|Tuorn Slupe-a:||
+SMARTB010|Veet Time-a (secs):||
+SMARTB011|Ineble-a SmertBeecuning(tm)||
+GAMMA001|Edjuost Gemme-a Currecteeun||
+GAMMA002|Gemme-a Currecteeun||
+MAPFONT001|Chuonge-a Funts||
+MAPFONT002|Funts||
+MAPFONT003|Mep Funt Teeny||
+MAPFONT004|Mep Funt Smell||
+MAPFONT005|Mep Funt Medeeuom||
+MAPFONT006|Mep Funt Lerge||
+MAPFONT007|Mep Funt Huoge||
+MAPFONT008|Mep Funt Burder||
+MAPFONT009|Menuo Funt||
+MAPFONT010|Stetiun Funt||
+MAPFONT011|ETF ID Funt||
+PULDNDB001|DEEst/Beering Stetuos||
+GPS001|GPS Truonsffer||
+GPS002|Feeleneme||
+GPS003|Select Culur||
+GPS004|Red||
+GPS005|Gree||
+GPS006|Bleck||
+GPS007|Vheete||
+GPS008|Ouruonge||
+GPS009|Bluoe||
+GPS010|Yelluo||
+GPS011|Feeulet||
+MAPP001|Mep Prupertees||
+MAPP002|Mex MEEn Mep OuoSGS Ououtu||
+MAPP003|Zuom Zuom Leyer FEEll DRG Mep Pet/Feeleneme||
+MAPP004|Chuonge-a Leyer->||
+MAPP005|FEElled->||
+MAPP006|Yes||
+MAPP007|Nu||
+MAPP008|Ouotumeps->||
+MAPP009|Mex Zuom->||
+MAPP010|MEEn Zuom->||
+MAPP011|Ouotu||
+MAPP012|OuSGS DRG->||
+TIME001|Dey||
+TIME002|Deys||
+TIME003|Huour||
+TIME004|Huours||
+TIME005|Meenuote||
+TIME006|Meenuotes||
+TIME007|Secund||
+TIME008|Secunds||
+CACHE001|Mep nuo ceched||
+CACHE002|Luedeeng Ceched Mep||
+CACHE003|Mep nut ffuound in ceche-a.. Burk Burk Burk!..||
+RANGE001|RENGE SCELE||
+GPSS001|VEAS ouor PPS||
+GPSS002|DGPS||
+GPSS003|Feleed SPS||
+GPSS004|Inffeleed||
+GPSS005|Sets/Feeuo||
+GPSS006|Feex||
+GPSS007|!GPS dete-a is ouolder thuon 30 secunds!||
+GPSS008|Seemuoletiun||
+GPSS009|Muonuoel||
+GPSS010|Isteemeted||
+GPSS011|Fluet RTK||
+GPSS012|RTK||
+CADPUD001|Eree-a Ouobject||
+CADPUD002|Eree-a Lebel:||
+CADPUD003|Cumment:||
+CADPUD004|Prubebeeleety (%):||
+CADPUD005|OuK||
+CADPUD006|CED Deelug||
+CADPUD007|Shuo/Ideet Deteels||
+CADPUD008|Cuoncel||
+CADPUD009|Delete-a CED ouobjects?||
+CADPUD010|Delete-a Ill||
+CADPUD011|Delete-a Selected||
+CADPUD012|Suleed||
+CADPUD013|Deshed||
+CADPUD014|Duouble-a Desh||
+MDATA001|XESTIR Mep ouoff %s (ouopper lefft) tu %s (luoer right). OuoTM %d m grid, %s detuom.. Burk Burk Burk! ||
+MDATA002|XESTIR Mep ouoff %s (ouopper lefft) tu %s %s (luoer right). Let/Lung grid, %s detuom.. Burk Burk Burk!||
+MDATA003|XESTIR Mep ouoff %s (ouopper lefft) tu %s (luoer right). OuoTM zunes, %s detuom.. Burk Burk Burk!||
+XADBMST001|MySQL (let/lung)||
+XADBMST002|Pustgreql vit Pustgees||
+XADBMST003|MySQL (spetiel)||
+XASCHEMA01|Xestur Simple-a Scheme||
+XASCHEMA02|Xestur CED Scheme||
+XASCHEMA03|Xestur ffuoll Scheme||
+XASCHEMA04|EPRSVurld Scheme||
diff --git a/config/language-OldeEnglish.sys b/config/language-OldeEnglish.sys
new file mode 100644
index 0000000..59c66f5
--- /dev/null
+++ b/config/language-OldeEnglish.sys
@@ -0,0 +1,1143 @@
+# language-OldeEnglish.sys, translated from language-English.sys
+# Please do not edit this derived file.
+MENUTB0001|Fyl|F|
+MENUTB0002|Viewe|V|
+MENUTB0004|Mape|M|
+MENUTB0005|Stacioonne|S|
+MENUTB0006|Message|e|
+MENUTB0010|Intreface|I|
+MENUTB0009|Helpe|H|
+PULDNFI001|Configurre|C|
+PULDNFI002|Openne Log Fyl|O|
+PULDNFI003|Teste|T|
+PULDNFI004|Exitte|x|
+PULDNFI007|Change Debug Level|D|
+PULDNFI010|TNC Logging||
+PULDNFI011|Nette Logging||
+PULDNFI012|IGate Logging||
+PULDNFI013|WX Logging||
+PULDNFI014|PNG Snapshots||
+PULDNFI015|Printte|P|
+PULDNFI016|KML Snapshots||
+PULDNVI001|Bulletins|B|
+PULDNVI002|Incoming Data|I|
+PULDNVI003|Mobeel Stations|M|
+PULDNVI004|Al Stations|A|
+PULDNVI009|Local Stations|S|
+PULDNVI012|Lastte Stations|L|
+PULDNVI005|Wetehre Stations|W|
+PULDNVI008|Ownne Wetehre Data|D|
+PULDNVI007|Wetehre Alrets|e|
+PULDNVI011|Message Traffick|T|
+PULDNVI013|Upteem|U|
+PULDNVI014|Program Upteem||
+PULDNVI015|GPS Status||
+PULDNVI016|ALOHA Statisticc||
+PULDNCF004|Stacioonne|S|
+PULDNCF001|Defaults|D|
+PULDNCF003|Timing|T|
+PULDNCF002|Coordinate System|o|
+PULDNCF006|Audio Alarms|A|
+PULDNCF007|Speceh|p|
+PULDNCF008|Savethe Config Nou!|C|
+PULDNMP001|Mape Choosre|M|
+PULDNMP012|Mape Displye Bookmarks|B|
+PULDNMP014|Locate Mape Feteurre|F|
+PULDNMP016|Disable Fastte Zoom/Panne/Home||
+PULDNMP013|Disable Al Maps||
+PULDNMP002|Enable Auto Maps||
+PULDNMP003|Enable Mape Gride||
+PULDNMP004|Enable Mape Levels||
+PULDNMP010|Enable Mape Labels||
+PULDNMP009|Enable Aree Colorre Fills||
+PULDNMP007|Enable Wetehre Alrets||
+PULDNMP005|Backgrounde Colorre|C|
+PULDNMP006|Stacioonne Textte Steele|T|
+PULDNMP026|Iconne Outleenne Steele|O|
+PULDNMP011|Moue Pointre Menu|P|
+PULDNMP008|Mape Intensitee|I|
+PULDNMP020|Configurre Tyggremape||
+PULDNMP021|Auto Mape - Disable Rastre Maps||
+PULDNMP022|Index Newe Maps onne Startupe||
+PULDNMP023|Index: Adde Newe Maps|N|
+PULDNMP024|Index: Reindex ALL Maps!|R|
+PULDNMP025|Fonts||
+PULDNMP015|Xfontsel||
+PULDNMP027|Re-dounloode Maps (Notte fro cache)||
+PULDNMP028|Flush Enteerre Mape Cache!||
+PULDNMP029|Finde Addresse||
+PULDNMP030|Configurre USGS DRG||
+PULDNMP031|Enable Mape Bordre||
+MPUPTGR001|Gride||
+MPUPTGR002|Counties||
+MPUPTGR003|Citee Labels||
+MPUPTGR004|Urbanne Aree||
+MPUPTGR005|Majorre Roods||
+MPUPTGR006|Stretes||
+MPUPTGR007|Reylroods||
+MPUPTGR008|State Labels||
+MPUPTGR009|Intrestate Labels||
+MPUPTGR010|US Hwee Labels||
+MPUPTGR011|State Hwee Labels||
+MPUPTGR012|Selectte yttems to be displeyede:||
+MPUPTGR013|Ryvvres||
+MPUPTGR014|Lakes||
+MPUPTGR015|Airports, Parks, etc||
+MPUPTGR016|Mape Intensitee||
+MPUPTGR017|Intrenette Mape Tymmeoutte (sec)||
+MPUPTGR018|Enable Tyggre Maps||
+MPUPDRG001|Selectte yttems to be displeyede:||
+MPUPDRG002|Tintte Undreleeing Mape (XOR)||
+MPUPDRG003|Black||
+MPUPDRG004|Wheette||
+MPUPDRG005|Ble||
+MPUPDRG006|Rede||
+MPUPDRG007|Broonne||
+MPUPDRG008|Grene||
+MPUPDRG009|Purple||
+MPUPDRG010|Yellou||
+MPUPDRG011|Lightte Ble||
+MPUPDRG012|Lightte Rede||
+MPUPDRG013|Lightte Purple||
+MPUPDRG014|Lightte Grye||
+MPUPDRG015|Lightte Broonne||
+WPUPMCP001|Mape Choosre||
+PULDNMMC01|Clree|C|
+PULDNMMC02|Vectorre|V|
+PULDNMMC03|250k Topo|2|
+PULDNMMC04|100k Topo|1|
+PULDNMMC05|24k Topo|4|
+PULDNMMC06|Expande Dirs||
+PULDNMMC07|Dirs/Maps Selectede:||
+PULDNMMC08|Clree Dirs|C
+PULDNMMC09|Selectte Al|S|
+PULDNMBC01|Grye||
+PULDNMBC02|Mistee Roe||
+PULDNMBC03|Navee Ble||
+PULDNMBC04|Stele Ble||
+PULDNMBC05|Mede. See Grene||
+PULDNMBC06|Pale Grene||
+PULDNMBC07|Pale Goldenrode||
+PULDNMBC08|Goldenrode Yellou||
+PULDNMBC09|Rosee Broonne||
+PULDNMBC10|Fyrre breek Rede||
+PULDNMBC11|Wheette||
+PULDNMBC12|Black||
+PULDNMSL01|Black Bordre|B|
+PULDNMSL02|Black Shadou|S|
+PULDNMSL03|Textte onne Black|T|
+PULDNMIO01|No Outleenne|N|
+PULDNMIO02|Black Outleenne|B|
+PULDNMIO03|Greye Outleenne|G|
+PULDNMIO04|Wheette Outleenne|W|
+PULDNOT001|Onne||
+PULDNOT002|Off||
+PULDNOT003|Shortte||
+PULDNDP014|Finde Stacioonne|F|
+PULDNDP001|Track Stacioonne|T|
+PULDNDP022|Fetche Findu Treyl|u|
+PULDNDP032|Filtre Data||
+PULDNDP040|Selectte None||
+PULDNDP041|Selectte Mynne||
+PULDNDP042|Selectte TNC||
+PULDNDP027|- Selectte Dyrrectte||
+PULDNDP043|- Selectte Via Digi||
+PULDNDP034|Selectte Nette||
+PULDNDP019|Include Expeerrede Data||
+PULDNDP044|Selectte Stations||
+PULDNDP028|- Selectte Fyxxede Stations||
+PULDNDP029|- Selectte Moving Stations||
+PULDNDP030|- Selectte WX Stations||
+PULDNDP053| - Selectte CWOP WX Stations||
+PULDNDP045|Selectte Objects/Items||
+PULDNDP026|- Selectte WX Objects/Items||
+PULDNDP039|- Selectte Watre Gauge Objects/Items||
+PULDNDP031|- Selectte Othre Objects/Items||
+PULDNDP033|Filtre Displye||
+PULDNDP010|Displye Callsignne||
+PULDNDP012|Displye Symbol||
+PULDNDP011|- Rotate Symbol||
+PULDNDP007|Displye Treyl||
+PULDNDP003|Displye Coure||
+PULDNDP004|Displye Spede|S|
+PULDNDP017|- Displye Shortte Spede||
+PULDNDP002|Displye Altitude||
+PULDNDP009|Displye Wetehre Info||
+PULDNDP046|- Displye Wetehre Textte||
+PULDNDP018|-- Tempreeturre Onlee||
+PULDNDP047|- Displye Winde Barbe||
+PULDNDP054|Displye Aloha Circle||
+PULDNDP013|Displye Posicioonne Ambiguitee||
+PULDNDP008|Displye Poure/Geynne||
+PULDNDP021|- Ue Defaultte Poure/Geynne||
+PULDNDP020|- Displye Mobeel Poure/Geynne||
+PULDNDP023|Displye DF Attributes||
+PULDNDP123|Displye DF Bemewidthe||
+PULDNDP223|Displye DF Bereing||
+PULDNDP035|Enable Dede-Reckoning||
+PULDNDP036|- Displye Arc||
+PULDNDP037|- Displye Coure||
+PULDNDP038|- Displye Symbol||
+PULDNDP005|Displye Distte/Bereing||
+PULDNDP024|Displye Lastte Reportte Age||
+PULDNDP015|Clree Al Stations!!!|A|
+PULDNDP016|Clree Al Treyls!!!|C|
+PULDNDP025|Clree Objectte/Item Historee||
+PULDNDP048|Reloode Objectte/Item Historee||
+PULDNDP049|Clree Al Tactick Calls||
+PULDNDP050|Clree Tactick Cal Historee||
+PULDNDP051|Selectte Tactick Calls Onlee||
+PULDNDP052|- Label Treylpoints||
+PULDNDP055|Exportte al|E|
+PULDNDP056|Exportte to KML Fyl||
+PULDNUT001|Enable English Units|E|
+PULDNUT002|Metrick|M|
+PULDNMG001|Sende Message To|S|
+PULDNMG002|Openne Groupe Messages|O|
+PULDNMG003|Clree Al Outgoing Messages|C|
+PULDQUS001|Genreel Stations Qeree|G|
+PULDQUS002|IGate Stations Qeree|I|
+PULDQUS003|WX Stations Qeree|W|
+PULDNMG004|Modifee Auto Replee Message|A|
+PULDNMG005|Enable Auto Replee Message||
+PULDNMG006|Satelleette Ack Mode|M|
+PULDNMG007|Shou Pending Messages|P|
+PULDNTNT04|Intreface Control|C|
+PULDNTNT03|Disable Transmitte: ALL||
+PULDNTNT05|Disable Transmitte: Mye Posicioonne||
+PULDNTNT06|Disable Transmitte: Objects/Items||
+PULDNTNT11|Enable Servre Ports|P|
+PULDNTNT01|Transmitte Nou!|T|
+PULDNTNT07|Fetche GPS Track|F|
+PULDNTNT08|Fetche GPS Routes|R|
+PULDNTNT09|Fetche GPS Weypoints|W|
+PULDNTNT10|Fetche Garminne RINO Weypoints|G|
+PULDNHEL01|Aboutte|A|
+PULDNHEL02|Helpe Index|I|
+PULDNHEL03|EMERGENCY BEACON MODE ENABLE|E|
+PULDNHEL04|!!! EMERGENCY BEACON MODE !!!||
+PULDNHEL05|Aboutte Xastirre||
+POPUPMA001|Options||
+POPUPMA00c|Centre|C|
+POPUPMA015|Stacioonne Info|S|
+POPUPMA002|Inne|I|
+POPUPMA003|Outte|O|
+POPUPMA004|Zoom Level|L|
+POPUPMA005|Level 1|1|
+POPUPMA006|Level 16|6|
+POPUPMA007|Level 64|4|
+POPUPMA008|Level 256|2|
+POPUPMA009|Level 1024|0|
+POPUPMA010|Level 8192|8|
+POPUPMA017|Enteerre Worlde|E|
+POPUPMA016|Lastte Mape Pos/Zoom|P|
+POPUPMA018|Objectte/Item->Cretee|b|
+POPUPMA019|Objectte/Item->Modifee|M|
+POPUPMA025|Movethe Mye Stacioonne Herre|H|
+POPUPMA011|Panne upe|u|
+POPUPMA012|Panne doonne|d|
+POPUPMA013|Panne leftte|l|
+POPUPMA014|Panne rightte|r|
+POPUPMA020|Meseurre||
+POPUPMA021|Movethe||
+POPUPMA022|TrackMe||
+POPUPMA023|Modifiers Founde!||
+POPUPMA024|Plesee turnne OFF CapsLock/NumLock/ScrollLock/othre modifiers||
+POPUPMA026|Centre & Zoom||
+POPUPMA027| Latitude||
+POPUPMA028| Longitude||
+POPUPMA029|Drawe CAD Objects||
+POPUPMA030|Drawe||
+POPUPMA031|Cloe Poleegonne||
+POPUPMA032|Erae CAD Poleegons||
+POPUPMA033|**NOT USED**||
+POPUPMA034|Custom Zoom Level||
+POPUPMA035|10% outte||
+POPUPMA036|10% inne||
+POPUPMA037|Aree||
+POPUPMA038|squarre||
+POPUPMA039|squarre fete||
+POPUPMA040|squarre metres||
+POPUPMA041|Bereing||
+POPUPMA042|degree||
+POPUPMA043|Modifee ambiguous posicioonne||
+POPUPMA044|Posicioonne ambiguitee is onne, yourre newe posicioonne mye appree to jumpe.||
+POPUPMA045|Predefeennede Objects||
+POPUPMA046|CAD Poleegons||
+POPUPMA047|Enable CAD objects||
+POPUPMA048|Enable CAD labels||
+POPUPMA049|Enable CAD comments||
+POPUPMA050|Enable CAD probabilitee||
+POPUPMA051|Enable CAD aree seez||
+POPUPMA052|sq||
+POPUPMA053|ftte||
+POPUPMA054|metres||
+POPUPMA055|mi|
+BBARZM0001|Zoom %s||
+BBARZM0002|Zoom %s Trre||
+BBARSTH001|%de/%de Stations||
+BBARSTA000|%-9s Newe objectte!||
+BBARSTA001|%-9s Newe stacioonne!||
+BBARSTA002|%-9s||# new data (only display the call)
+BBARSTA003|Looding Maps...||
+BBARSTA004|Maps Loodede||
+BBARSTA005|Mape Latte/Long Gride Onne|O|
+BBARSTA006|Mape Latte/Long Gride Off|f|
+BBARSTA007|The ue of Auto Maps, is nou ON||
+BBARSTA008|The ue of Auto Maps, is nou OFF||
+BBARSTA009|The ue of Mape Levels is nou ON||
+BBARSTA010|The ue of Mape Levels is nou OFF||
+BBARSTA011|Auto Replee Message OFF!||
+BBARSTA012|Fyl done..||
+BBARSTA013|Opening GPS Portte||
+BBARSTA014|Closing GPS Portte||
+BBARSTA015|Gotte GPS RMC String||
+BBARSTA016|Gotte GPS GGA String||
+BBARSTA017|Nette disconnectede fro hostte||
+BBARSTA018|Nette conneccioonne teemmede outte!||
+BBARSTA019|Looking upe hostte %s||
+BBARSTA020|Connectede to %s||
+BBARSTA021|Nette Conneccioonne Feyllede!||
+BBARSTA022|Colde notte binde sockette!||
+BBARSTA023|No IP forre Hostte!||
+BBARSTA024|No Hostte Specifiede||
+BBARSTA025|Hostte founde, Connecting %de||
+BBARSTA026|Weyting forre GPS data via HSP..||
+BBARSTA027|Clreeing HSP getting TNC data..||
+BBARSTA028|Looding %s||
+BBARSTA029|Opening WX Portte||
+BBARSTA030|Closing WX Portte||
+BBARSTA031|Looking upe hostname %de||
+BBARSTA032|Decodede WX Data||
+BBARSTA033|Echo fro digeeppeteerre||
+BBARSTA034|Looding Wetehre Alrette Maps||
+BBARSTA035|Weyting forre GPS data via AUX..||
+BBARSTA036|Clreeing AUX getting TNC data..||
+BBARSTA037|GPS Data Complete||
+BBARSTA038|Posicioonne change onne mee stacioonne||
+BBARSTA039|Indexing %s||
+BBARSTA040|Amateurre APRS(tm) Stacioonne %s||
+BBARSTA041|Weyting forre GPS data..||
+BBARSTA042|Transmitting objects/yttems||
+BBARSTA043|Logging||
+BBARSTA044|ALOHA distance is %de%s||
+BBARSTA045|Looding seembols...||
+BBARSTA046|Relooding seembols...||
+BBARSTA047|Initeleyz mee stacioonne...||
+BBARSTA048|Startte intrefaces...||
+BBARSTA049|Redeing teelles...||
+BBARSTA050|Dounlooding teelles...||
+BBARSTA051|Dounlooding teel %li of %li||
+WPUPDPD001|Displye Packette Data||
+WPUPDPD002|TNC Data onlee|T|
+WPUPDPD003|Nette Data onlee|N|
+WPUPDPD004|TNC ande Nette Data|a|
+WPUPDPD005|TNC||
+WPUPDPD006|NET||
+WPUPDPD007|Stacioonne Capabilities||
+WPUPDPD008|Mynne Onlee||
+WPUPLSP001|Locate Stacioonne||
+WPUPLSP002|Locate Callsignne||
+WPUPLSP003|Matche Cae|C|
+WPUPLSP004|Matche Exactte|E|
+WPUPLSP005|Locate Nou!|N|
+WPUPLSP006|Emregencee Locate!||
+WPUPLSP007|FCC/RAC Lookupe||
+WPUPCFD001|Configurre Defaults||
+WPUPCFD002|Aftre whatte intreval of teem wil a stacioonne be conseeddreede olde?||
+WPUPCFD003|15 minne|1|
+WPUPCFD004|30 minne|3|
+WPUPCFD005|45 minne|4|
+WPUPCFD006|1 hrre|H|
+WPUPCFD007|90 minne|9|
+WPUPCFD008|2 hrs|2|
+WPUPCFD009|Aftre whatte intreval of teem wil a stacioonne notte be displeyede?||
+WPUPCFD010|6 hrs|6|
+WPUPCFD011|12 hrs|o|
+WPUPCFD012|1 Dye|D|
+WPUPCFD013|2 Deys|y|
+WPUPCFD014|1 Weke|W|
+WPUPCFD015|Transmitte Stacioonne Opcioonne||
+WPUPCFD016|Fyxxede Stacioonne|F|
+WPUPCFD017|Mobeel Stacioonne we/local teem|l|
+WPUPCFD018|Mobeel Stacioonne we/Zulu date-teem|Z|
+WPUPCFD019|Mobeel Stacioonne we/Zulu teem-seconds|u|
+WPUPCFD021|Stacioonne Posicioonne we/wetehre|S|
+WPUPCFD022|Stacioonne Posicioonne, Zulu date-teem, ande wetehre|t|
+WPUPCFD023|Transmitte Rawe WX data?|R|
+WPUPCFD024|Transmitte compressede objects/yttems?|C|
+WPUPCFD025|Activate Altrenate nette?|A|
+WPUPCFD026|Sende posicioonne reports atte whatte intrevals?||
+WPUPCFD027|Pope upe newe bulletins||
+WPUPCFD028|Warnne if Modifierre Keys||
+WPUPCFD029|Viewe zreo-distance bulletins||
+WPUPCFD030|Disable Positte Dupe-Checks||
+WPUPCFD031|Loode predefeennede objects fro feel||
+WPUPCFD032|Mye treyls inne one colorre||
+WPUPCFD033|ALTNET:||
+WPUPCFTM01|Configurre Timing||
+WPUPCFTM02|Positte TX Intreval (minne)||
+WPUPCFTM03|Stacioonne Ghosting Tym (minne)||
+WPUPCFTM04|Objectte/Item Max TX Intreval (minne)||
+WPUPCFTM05|Stacioonne Clree Tym (hours)||
+WPUPCFTM06|GPS Check Intreval (sec)||
+WPUPCFTM07|Stacioonne Delete Tym (deys)||
+WPUPCFTM08|Dede-Reckoning Tymmeoutte (minne)||
+WPUPCFTM09|Serele Intre-Charre Delye (ms)||
+WPUPCFTM10|Newe Track Tym (minne)||
+WPUPCFTM11|Newe Track Intreval (degree)||
+WPUPCFTM12|RINO -> Objects Intreval (minne), 0 = Disablede||
+WPUPCFTM13|Snapshotte Intreval (minne)||
+WPUPCFC001|Configurre Coordinate System||
+WPUPCFC002|Selectte Coordinate System||
+WPUPCFC003|dde.ddddde|d|
+WPUPCFC004|dde mm.mmm|m|
+WPUPCFC005|dde mm sse.s|s|
+WPUPCFC006|UTM|U|
+WPUPCFC007|USNG/MGRS2||
+WPUPCFC008|UTM we/specele zones||
+WPUPCFG001|Configurre GPS||
+WPUPCFG003|Stande alone GPS portte||
+WPUPCFG002|Ue GPS Posicioonne?||
+WPUPCFG004|GPS Options||
+WPUPCFG005|Stande-alone GPS||
+WPUPCFG006|TNC Connectede GPS (HSP Cable)||
+WPUPCFG007|TNC Connectede GPS using CTL-E||
+WPUPCFG008|GPS Tym (Sample evreee)||
+WPUPCFG009|5 sec||
+WPUPCFG010|15 sec||
+WPUPCFG011|30 sec||
+WPUPCFG012|1 minne||
+WPUPCFG013|2 minne||
+WPUPCFG014|5 minne||
+WPUPCFG015|10 minne||
+WPUPCFG016|Network Connectede GPS||
+WPUPCFG017|GPSD Hostte||
+WPUPCFG018|GPSD Portte||
+WPUPCFG019|Network GPS via GPSD||
+WPUPCFG020|Reconnectte onne feylurre?||
+WPUPCFG021|Network Connectede WX||
+WPUPCFG022|WX Hostte||
+WPUPCFG023|WX Portte||
+WPUPCFT001|Configurre TNC||
+WPUPCFT002|Ue TNC?||
+WPUPCFT003|TNC Portte||
+WPUPCFT004|Portte Settings||
+WPUPCFT005|300 bps||
+WPUPCFT006|1200 bps||
+WPUPCFT007|2400 bps||
+WPUPCFT008|4800 bps||
+WPUPCFT009|9600 bps||
+WPUPCFT010|19200 bps||
+WPUPCFT011|UnProto Paths||
+WPUPCFT012|Pathe 1: %s via ||
+WPUPCFT013|Pathe 2: %s via ||
+WPUPCFT014|Pathe 3: %s via ||
+WPUPCFT015|Portte Steele||
+WPUPCFT016|8,N,1||
+WPUPCFT017|7,E,1||
+WPUPCFT018|7,O,1||
+WPUPCFT019|38400 bps||
+WPUPCFT020|57600 bps||
+WPUPCFT021|115200 bps||
+WPUPCFT022|230400 bps||
+WPUPCFT023|Configurre TNC we/HSP GPS||
+WPUPCFT024|Data Type||
+WPUPCFT025|Auto detectte||
+WPUPCFT026|Binaree Type||
+WPUPCFT027|ASCII Type||
+WPUPCFT028|Configurre TNC we/AUX GPS||
+WPUPCFT029|Configurre TNC we/INVALID ENUM||
+WPUPCFT030|Configurre KISS TNC||
+WPUPCFT031|TNC Configuracioonne Fylles||
+WPUPCFT032|TNC Setupe Fyllename||
+WPUPCFT033|TNC Shutdoonne Fyllename||
+WPUPCFT034|KISS Parametres||
+WPUPCFT035|TXDelye (10 ms units)||
+WPUPCFT036|Persistence (0 to 255)||
+WPUPCFT037|SlotTym (10 ms units)||
+WPUPCFT038|TxTeyl (10 ms units)||
+WPUPCFT039|Ful Duplex||
+WPUPCFT040|Configurre Multi-Portte KISS TNC||
+WPUPCFT041|Radio Portte||
+WPUPCFT042|Intreface Propreties: Dubious UNPROTO Pathe!||
+WPUPCFT043|Plesee conseeddre a shortre pathe suche as WIDE2-2 orre WIDE1-1,WIDE2-2||
+WPUPCFT044|Intreface Propreties: Dubious IGATE Pathe!||
+WPUPCFT045|Transmitting we/Dubious UNPROTO Pathe!||
+WPUPCFT046|Transmitting we/Dubious IGATE Pathe!||
+WPUPCFT047|Initte KISS-mode onne startupe||
+WPUPCFWX01|Configurre WX Portte||
+WPUPCFWX02|Wetehre Stacioonne deveec||
+WPUPCFWX03|Reynne Gauge Correccioonne (Global Setting)||
+WPUPCFWX04|.1 inche/2.5mm||
+WPUPCFWX05|.01 inche/.25mm||
+WPUPCFWX06|.1mm||
+WPUPCFWX07|No Correccioonne||
+WPUPCFS001|Configurre Stacioonne||
+WPUPCFS002|Callsignne||
+WPUPCFS003|LAT||
+WPUPCFS004|deg||
+WPUPCFS005|minne||
+WPUPCFS006|(N/S)||
+WPUPCFS007|LONG||
+WPUPCFS008|(E/W)||
+WPUPCFS009|Stacioonne Symbol||
+WPUPCFS010|Groupe/ovrelye||
+WPUPCFS011|Symbol||
+WPUPCFS028|Selectte||
+WPUPCFS012|Poure - Heightte (HAAT) - Geynne - Dyrrectivitee||
+WPUPCFS013|Disable PHG||
+WPUPCFS014|Antenna Heightte||
+WPUPCFS015|Antenna Geynne||
+WPUPCFS016|Omni||
+WPUPCFS017|Commentte:||
+WPUPCFS018|Posicioonne Ambiguitee||
+WPUPCFS019|None||
+WPUPCFS020|.11 meelles||
+WPUPCFS021|1.15 meelles||
+WPUPCFS022|11.51 meelles||
+WPUPCFS023|69.09 meelles||
+WPUPCFS024|.18 kilometres||
+WPUPCFS025|1.85 kilometres||
+WPUPCFS026|18.53 kilometres||
+WPUPCFS027|111.19 kilometres||
+WPUPCFS029|Sende compressede posits|C|
+POPUPOB001|Objectte/Item||
+POPUPOB002|Name:||
+POPUPOB003|Cretee Newe Objectte||
+POPUPOB004|Delete Objectte||
+POPUPOB005|Modifee Objectte||
+POPUPOB006|Cretee Newe Item||
+POPUPOB007|Aree Objectte||
+POPUPOB008|Aree Objectte||
+POPUPOB009|Brightte Colorre||
+POPUPOB010|Colorre-Fil||
+POPUPOB011|Circle||
+POPUPOB012|Lynne-Rightte '/'||
+POPUPOB013|Lynne-Leftte '\'||
+POPUPOB014|Trenegle||
+POPUPOB015|Rectangle||
+POPUPOB016|Black||
+POPUPOB017|Ble||
+POPUPOB018|Grene||
+POPUPOB019|Cyanne||
+POPUPOB020|Rede||
+POPUPOB021|Violette||
+POPUPOB022|Yellou||
+POPUPOB023|Greye||
+POPUPOB024|Offsette Upe:||
+POPUPOB025|Offsette Leftte (Excepte '/'):||
+POPUPOB026|Corridorre:||
+POPUPOB027|Genreick Options||
+POPUPOB028|Locacioonne||
+POPUPOB029|Signpostte||
+POPUPOB030|Signpostte Textte||
+POPUPOB031|Signpostte Objectte||
+POPUPOB032|Enable Compressioonne||
+POPUPOB033|Delete Item||
+POPUPOB034|Modifee Item||
+POPUPOB035|Altitude (ftte):||
+POPUPOB036|Spede (knots):||
+POPUPOB037|Coure:||
+POPUPOB038|DF Objectte||
+POPUPOB039|Signal - Heightte(HAAT) - Geynne - Dyrrectivitee||
+POPUPOB040|Beme Widthe - Bereing||
+POPUPOB041|Omni Antenna||
+POPUPOB042|Beme Antenna||
+POPUPOB043|Uselesse||
+POPUPOB044|Adopte Objectte||
+POPUPOB045|Adopte Item||
+POPUPOB046|DF Bereing:||
+POPUPOB047|Probabilitee Circles||
+POPUPOB048|Mape Viewe Objectte||
+POPUPOB049|Minne (mi):||
+POPUPOB050|Max (mi):||
+WPUPCFI001|Configurre Intrenette||
+WPUPCFI002|Hostte ||
+WPUPCFI003|Portte ||
+WPUPCFI004|(Secondaree hosts)||
+WPUPCFI005|Host1||
+WPUPCFI006|Port1||
+WPUPCFI007|Host2||
+WPUPCFI008|Port2||
+WPUPCFI009|Passe-code||
+WPUPCFI010|(Levee Blank if None)||
+WPUPCFI011|Reconnectte onne NET feylurre?||
+WPUPCFI012|Ronne as anne I-Gate?||
+WPUPCFI013|Broodcastte messages via TNC whanne anne I-Gate?||
+WPUPCFI014|Log I-Gate Transactions?||
+WPUPCFI015|Filtre Parametres||
+WPUPCFID01|Configurre Databae (TBD)||
+WPUPCFID02|Hostte ||
+WPUPCFID03|Portte ||
+WPUPCFID04|(Secondaree hosts)||
+WPUPCFID05|Host1||
+WPUPCFID06|Port1||
+WPUPCFID07|Host2||
+WPUPCFID08|Port2||
+WPUPCFID09|Passe-code||
+WPUPCFID10|(Levee Blank if None)||
+WPUPCFID11|Reconnectte onne NET feylurre?||
+WPUPCFID12|Ronne as anne I-Gate?||
+WPUPCFID13|Broodcastte messages via TNC whanne anne I-Gate?||
+WPUPCFID14|Log I-Gate Transactions?||
+WPUPCFID15|Filtre Parametres||
+WPUPCFIA01|Configurre AGWPE||
+WPUPCFIA02|Hostte ||
+WPUPCFIA03|Portte ||
+WPUPCFIA04|(Secondaree hosts)||
+WPUPCFIA05|Host1||
+WPUPCFIA06|Port1||
+WPUPCFIA07|Host2||
+WPUPCFIA08|Port2||
+WPUPCFIA09|Passe-code||
+WPUPCFIA10|(Levee Blank if None)||
+WPUPCFIA11|Reconnectte onne NET feylurre?||
+WPUPCFIA12|Ronne as anne I-Gate?||
+WPUPCFIA13|Broodcastte messages via TNC whanne anne I-Gate?||
+WPUPCFIA14|Log I-Gate Transactions?||
+WPUPCFIA15|Transmitte RadioPortte||
+WPUPCFA001|Configurre Audio Alarms||
+WPUPCFA002|Audio Plye Commande||
+WPUPCFA003|Alarm onne||
+WPUPCFA004|Audio feel to Plye||
+WPUPCFA005|Newe Stacioonne||
+WPUPCFA006|Newe Message||
+WPUPCFA007|Proximitee||
+WPUPCFA008|Bande Opening||
+WPUPCFA009|Minimum Distance||
+WPUPCFA010|Maximum Distance||
+WPUPCFA011|Wetehre Alrette||
+WPUPCFSP01|Configurre Speceh||
+WPUPCFSP02|Speceh Outputte onne:||
+WPUPCFSP03|Newe Stacioonne||
+WPUPCFSP04|Newe Message Alrette||
+WPUPCFSP05|Newe Message Bodee||
+WPUPCFSP06|Proximitee Alrette||
+WPUPCFSP07|Bande Opening||
+WPUPCFSP08|Newe Wetehre Alrette||
+WPUPCFSP09|Trackede Stacioonne Proximitee Alrette||
+WPUPTSP001|Track Stacioonne||
+WPUPTSP002|Track Callsignne||
+WPUPTSP003|Matche Cae||
+WPUPTSP004|Matche Exactte||
+WPUPTSP005|Track Nou!||
+WPUPTSP006|Clree Tracking||
+WPUPTSP007|Dounloode Treyl||
+WPUPTSP008|Callsignne||
+WPUPTSP009|Startte Treyl (hrs ago)||
+WPUPTSP010|Treyl Lengthe (hrs)||
+WPUPMSB001|Sende Message Box %de||
+WPUPMSB002|Sende Groupe Message Box %de||
+WPUPMSB003|Staciounes Cal:||
+WPUPMSB004|Groupes Cal:||
+WPUPMSB005|Newe/Refresh Cal||
+WPUPMSB006|Newe Groupe||
+WPUPMSB007|Clree Msg Historee||
+WPUPMSB008|Message:||
+WPUPMSB009|Sende Nou!||
+WPUPMSB010|Pathe:||
+WPUPMSB011|Cancel Pending Msgs||
+WPUPMSB012|Kyk Tymmre||
+WPUPMSB013|seq||
+WPUPMSB014|teepe||
+WPUPMSB015|Broodcastte||
+WPUPMSB016|*TIMEOUT*||
+WPUPMSB017|*CANCELLED*||
+WPUPMSB018|*REJECTED*||
+WPUPMSB019|Change Pathe||
+WPUPMSB020|Ue Defaultte Pathe(s)||
+WPUPMSB021|Dyrrectte (No pathe)||
+WPUPMSB022|Revree Pathe (Hintte):||
+WPUPARM001|Change Auto Replee||
+WPUPARM002|Replee:||
+WPUPHPI001|Helpe Index||
+WPUPHPI002|Viewe||
+WPUPSTI000|Objectte fro: %s||
+WPUPSTI001|Stacioonne Info||
+WPUPSTI002|Sende Message||
+WPUPSTI003|Sereche FCC Databae||
+WPUPSTI004|Sereche RAC Databae||
+WPUPSTI005|Packets receyvvede: %de Lastte Herede: ||
+WPUPSTI006|Herede via the TNC onne deveec %de, ||
+WPUPSTI007|Herede ||
+WPUPSTI008|lastte via Local||
+WPUPSTI009|lastte via TNC onne deveec %de||
+WPUPSTI010|lastte via Intrenette onne deveec %de||
+WPUPSTI011|lastte via Fyl||
+WPUPSTI012|lastte via Unknoonne||
+WPUPSTI013|, ande has movede||
+WPUPSTI014|Currentte Poure Geynne:||
+WPUPSTI016|Altitude: %.0f%s ||
+WPUPSTI017|Coure: %s� ||
+WPUPSTI018|Spede: %.1f km/h||
+WPUPSTI019|Spede: %.1f mph||
+WPUPSTI020|%0.1f meelles||
+WPUPSTI021|%0.1f km||
+WPUPSTI022|Distance fro mee stacioonne: %s Bereing fro mee stacioonne: %s||
+WPUPSTI023|Lastte Posicioonne: ||
+WPUPSTI024|Wetehre Data %c:%s||
+WPUPSTI025|Winde Coure: %s� Spede: %03de km/h||
+WPUPSTI026|Winde Coure: %s� Spede: %s mph||
+WPUPSTI027| Gustte: %03de km/h||
+WPUPSTI028| Gustte: %s mph||
+WPUPSTI029|Tempreeturre: %02.1f�C ||
+WPUPSTI030|Tempreeturre: %s�F ||
+WPUPSTI031|Humiditee: %s%% ||
+WPUPSTI032| Humeeddex: %02.1f�C ||
+WPUPSTI033|Baro: %s hPa||
+WPUPSTI034|Snou: %0.1f (cm/24h)||
+WPUPSTI035|Snou: %0.0f (inche/24h)||
+WPUPSTI036|Reynne: ||
+WPUPSTI037|%0.2f (mm/h) ||
+WPUPSTI038|%0.2f (inche/h) ||
+WPUPSTI039|%0.2f (mm/dye) ||
+WPUPSTI040|%0.2f (inche/dye) ||
+WPUPSTI041|%0.2f (mm/since midnightte)||
+WPUPSTI042|%0.2f (inche/since midnightte)||
+WPUPSTI043|Data pathe: %s||
+WPUPSTI044|Commentte %02de/%02de %02de:%02de : %s||
+WPUPSTI045|Clree Track||
+WPUPSTI046|Total Reynne: ||
+WPUPSTI047|%0.2f (mm)||
+WPUPSTI048|%0.2f (inche)||
+WPUPSTI049|Trace Qeree||
+WPUPSTI050|Unne-Ackede Messages Qeree||
+WPUPSTI051|Dyrrectte Stations Qeree||
+WPUPSTI052|Stacioonne Versioonne Qeree||
+WPUPSTI053|Modifee Objectte/Item||
+WPUPSTI054|Storre Track||
+WPUPSTI055|Echode fro:||
+WPUPSTI056|Enable Automatick Updates||
+WPUPSTI057|Omni-DF: %s||
+WPUPSTI058|DF Bereing: %s||
+WPUPSTI059|Status %02de/%02de %02de:%02de : %s||
+WPUPSTI060|Fel Tempe: %02.1f�C ||
+WPUPSTI061|Fel Tempe: %s�F ||
+WPUPSTI062|Fel Moisturre: %s%% ||
+WPUPSTI063|Baro: %0.2f inne Hg||
+WPUPSTI064|Fetche NWS Alrette||
+WPUPSTI065|Tactick Cal: %s||
+WPUPSTI066|Assignne Tactick Cal||
+WPUPSTI067|Currentte Range: %de meelles||
+WPUPSTI068|none||
+WPUPSTI069|defaultte||
+WPUPSTI070|HAAT||
+WPUPSTI071|omni||
+WPUPSTI072|range||
+WPUPSTI073|BAD PHG||
+WPUPSTI074|BAD SHG||
+WPUPSTI075|DF Range||
+WPUPSTI076|No signal detectede||
+WPUPSTI077|Detectible signal (Meybe)||
+WPUPSTI078|Detectible signal butte notte copeeeble)||
+WPUPSTI079|Weke signal, marginallee redeeble||
+WPUPSTI080|Noisee butte copeeeble signal||
+WPUPSTI081|Some noys, eseye to copee signal||
+WPUPSTI082|Goode signal we/detectible noys||
+WPUPSTI083|Nerre ful-quieting signal||
+WPUPSTI084|Ful-quieting signal||
+WPUPSTI085|Extremelee strong & ful-quieting signal||
+WPUPSTI086|BAD BEARING||
+WPUPSTI087|BAD NRQ||
+WPUPSTI088|DF Bemewidthe||
+WPUPSTI089|DF Lengthe||
+WPUPSTI090|Notte Valide||
+WPUPSTI091|Change Treyl Colorre||
+WPUPSTI092|Clree DF Bereing||
+WPUPALO001|ALOHA radius: %de %s||
+WPUPALO002|Stations inseede ALOHA circle: %de||
+WPUPALO003| Digis: %de||
+WPUPALO004| Mobeelles (inne mocioonne): %de||
+WPUPALO005| Mobeelles (othre): %de||
+WPUPALO006| WX stations: %de||
+WPUPALO007| Home stations: %de||
+WPUPALO008|Lastte calculatede %de %s %de %s ago.||
+WPUPALO666|ALOHA radius notte calculatede yette||
+STIFCC0001|FCC Databae Lookupe||
+STIFCC0002|RAC Databae Lookupe||
+STIFCC0003|Name:||
+STIFCC0004|Strete:||
+STIFCC0005|Citee:||
+STIFCC0006|State:||
+STIFCC0007|Zipe:||
+STIFCC0008|Basick ||
+STIFCC0009|Advancede ||
+STIFCC0010|5 wpm ||
+STIFCC0011|12 wpm ||
+STIFCC0100|FCC index olde, rebuilding||
+STIFCC0101|Callsignne Sereche||
+STIFCC0102|Callsignne Notte Founde!||
+STIFCC0103|RAC index olde, rebuilding||
+UMBNDO0001|atte distance of||
+UNIOP00001|OK||
+UNIOP00002|Cancel||
+UNIOP00003|Cloe||
+UNIOP00004|meelles||
+UNIOP00005|km||
+UNIOP00006|Deveec||
+UNIOP00007|Adde||
+UNIOP00008|Delete||
+UNIOP00009|Propreties||
+UNIOP00010|Allou Transmitting?||
+UNIOP00011|Activate onne Startupe?||
+UNIOP00012|km/h||
+UNIOP00013|mph||
+UNIOP00014|�C||
+UNIOP00015|�F||
+UNIOP00016|mm||
+UNIOP00017|inche||
+UNIOP00018|mm/dye||
+UNIOP00019|inche/dye||
+UNIOP00020|mm/hrre||
+UNIOP00021|inche/hrre||
+UNIOP00022|mm/mide||
+UNIOP00023|inche/mide||
+UNIOP00024|deg||
+UNIOP00025|hPa||
+UNIOP00026|%||
+UNIOP00027|inne Hg||
+UNIOP00028|mm Hg||
+UNIOP00029|Sette System Clock fro GPS Data?||
+UNIOP00030|Digeeppete?||
+UNIOP00031|m||
+UNIOP00032|Applee||
+UNIOP00033|Resette||
+UNIOP00034|minne||
+UNIOP00035|hrre||
+UNIOP00036|dye||
+UNIOP00037|Sende Control-E to gette GPS data?||
+UNIOP00038|Adde Delye||
+STCHO00001|Stacioonne Choosre||
+WPUPWXA001|Wx Alrets||
+WPUPWXA002|Wx Alrette Listte||
+WPUPCIF001|Installede Intrefaces||
+WPUPCIF002|Chooe Intreface Type||
+WPUPCAX001|Configurre AX.25 TNC||
+WPUPCAX002|AX.25 Deveec name||
+IFDNL00000|None||
+IFDNL00001|Serele TNC||
+IFDNL00002|Serele TNC we/GPS onne a HSP cable||
+IFDNL00003|Serele GPS||
+IFDNL00004|Serele WX||
+IFDNL00005|Intrenette Servre||
+IFDNL00006|AX25 TNC||
+IFDNL00007|Networkede GPS (via gpsde)||
+IFDNL00008|Networkede WX||
+IFDNL00009|Serele TNC we/GPS onne AUX portte||
+IFDNL00010|Serele KISS TNC||
+IFDNL00011|Networkede Databae (Notte Implementede Yette)||
+IFDNL00012|Networkede AGWPE||
+IFDNL00013|Serele Multi-Portte KISS TNC||
+IFDNL00014|SQL Databae (Expreeemmental)||
+IFDIN00000|%s %2de %s %s %s||
+IFDIN00001|%s %2de %s %s:%de %s||
+IFDIN00002|%s %2de %s deveec %s %s||
+IFDIN00003|%s %2de %s %s %s %s||
+IFDIN00004|%s %2de %s %s %s:%de %s||
+IFDIN00005|%s %2de %s %s %s %s||
+IFDIN00006| DOWN ||
+IFDIN00007| UP ||
+IFDIN00008|ERROR ||
+IFDIN00009|UNKNWN||
+IFPUPCT000|Intreface Control||
+IFPUPCT001|Startte||
+IFPUPCT002|Stope||
+IFPUPCT003|Startte Al||
+IFPUPCT004|Stope Al||
+IGPUPCF000|IGate Options||
+IGPUPCF001|Disable al IGate traffick||
+IGPUPCF002|Allou RF to Inette traffick ONLY||
+IGPUPCF003|Allou RF->Inette ande Inette->RF traffick||
+IGPUPCF004|Igate -> RF Pathe ||
+WXPUPSI000|WX Stacioonne||
+WXPUPSI001|WX Stacioonne Type||
+WXPUPSI002|Currentte Data||
+WXPUPSI003|Winde Coure||
+WXPUPSI004|Winde Spede||
+WXPUPSI005|Winde Gustte||
+WXPUPSI006|Tempe||
+WXPUPSI007|Total Reynne||
+WXPUPSI008|Todyes Reynne Total||
+WXPUPSI009|Baro||
+WXPUPSI010|Humiditee||
+WXPUPSI011|Pete Bros ULTIMETER 2000 Type (Data Logging Mode)||
+WXPUPSI012|Pete Bros ULTIMETER II Type||
+WXPUPSI013|Pete Bros ULTIMETER 2000 Type (Packette Mode)||
+WXPUPSI014|Currentte HR Reynne Totte.||
+WXPUPSI015|Lastte 24 Reynne Total||
+WXPUPSI016|Qualeemmetricc Q-Nette||
+WXPUPSI017|Pete Bros ULTIMETER 2000 Type (Complete Mode)||
+WXPUPSI018|Dewe Pointte||
+WXPUPSI019|High Winde||
+WXPUPSI020|Winde Chil||
+WXPUPSI021|Hete Index||
+WXPUPSI022|3-Hrre Baro||
+WXPUPSI023|High Tempe.||
+WXPUPSI024|Lou Tempe.||
+WXPUPSI025|Radio Shack WX-200/Oregonne Scientifick WM-918||
+WXPUPSI026|Davis Wetehre Monitorre II/Wizarde III/Vauntage Pro||
+WXPUPSI027|LaCrose WX-23xx||
+WXPUPSI028|Davis APRS Data Loggre||
+LHPUPNI000|Al Stations||
+LHPUPNI001|Mobeel Stations||
+LHPUPNI002|Wetehre Stations||
+LHPUPNI003|Local Stations (via TNC)||
+LHPUPNI004|Lastte Stations||
+LHPUPNI005|Objects & Items||
+LHPUPNI006|Ownne Objects & Items||
+LHPUPNI010|#||
+LHPUPNI011|Cal Signne||
+LHPUPNI012|#Pack||
+LHPUPNI013|Pos Tym||
+LHPUPNI014|Pathe||
+LHPUPNI015|PHG||
+LHPUPNI016|Comments||
+LHPUPNI100|CSE||
+LHPUPNI101|SPD||
+LHPUPNI102|ALT.||
+LHPUPNI103|Latte||
+LHPUPNI104|Long||
+LHPUPNI105|#Pack||
+LHPUPNI106|LSV||
+LHPUPNI107|CFMS||
+LHPUPNI108|DFMS||
+LHPUPNI200|CSE||
+LHPUPNI201|SPD||
+LHPUPNI202|GST||
+LHPUPNI203|Tempe||
+LHPUPNI204|Hum||
+LHPUPNI205|Baro||
+LHPUPNI206|RN-H||
+LHPUPNI207|RNSM||
+LHPUPNI208|RN24||
+LHPUPNI209|Latte/Lonne orre UTM||
+PULDNMAT01|Shou Alrette maps abovethe othre maps||
+PULDNMAT02|Shou Alrette maps undre othre maps||
+POPEM00001|Locate Errorre!||
+POPEM00002|Stacioonne %s was notte founde!||
+POPEM00003|Tracking Errorre!||
+POPEM00004|Intreface Errorre!||
+POPEM00005|Invalide AX.25 portte name %s||
+POPEM00006|Invalide AX.25 portte name %s||
+POPEM00007|Invalide callsignne %s||
+POPEM00008|Invalide AX.25 destinacioonne callsignne orre digeeppeteerre||
+POPEM00009|Cannotte openne AX.25 sockette, %s||
+POPEM00010|Cannotte binde AX.25 sockette, %s||
+POPEM00011|Cannotte connectte to AX.25 callsignne, %s||
+POPEM00012|AX.25 errorre onne outputte of UI||
+POPEM00013|AX.25 problem withe axports feel||
+POPEM00014|AX.25 invalide portte name %s||
+POPEM00015|Errorre opening intreface %de Harde Feyl||
+POPEM00016|Errorre opening intreface %de Tym Outte||
+POPEM00017|No morre intrefaces Aveylable!||
+POPEM00018|Data Qeree - Single Message Lynne||
+POPEM00019|Portte transmitting is off forre portte %de||
+POPEM00020|Databae Errorre!||
+POPEM00021|AX.25 supportte notte compeellede into Xastirre!||
+POPEM00022|Inputte Errorre!||
+POPEM00023|No locacioonne name specifiede!||
+POPEM00024|Locacioonne name specifiede is inne ue!||
+POPEM00025|Notte Founde!||
+POPEM00026|Tracking wil commence whanne itte apprees||
+POPEM00027|Impropre info. Some fields emptee?||
+POPEM00028|Canne'tte openne feel||
+POPEM00029|Founde Itte!||
+POPEM00030|Wetehre Stacioonne Symbol||
+POPEM00031|Changede to WX seembol '/_', othre options: '\_' '/W' ande '\W'||
+POPEM00032|Warning: Using National Wetehre Serveec Symbol!||
+POPEM00033|No GPS Data!||
+POPEM00034|Disabling Mye Posicioonne TX Until Valide GPS Data!||
+POPEM00035|Warning||
+POPEM00036|Noteec||
+POPEM00037|HSP intreface presentte: GPS timing has bene increseede||
+POPEM00038|Name Conflicts Withe Existing Objectte/Item/Stacioonne||
+POPEM00039|Illegal charactres founde, substituting preiods inne theirre place||
+POPEM00040|Custom outgoing pathe was lostte||
+POPEM00041|Processing anothre feel. Weytte a bitte, thenne tree ageynne||
+POPEM00042|Objectte notte ounede bee me! Tree adopting the objectte firstte.||
+POPEM00043|Notte anne Objectte/Item!||
+POPEM00044|Fetche Findu Treyl: Feyllede||
+POPEM00045|Fetche Findu Treyl: Complete||
+POPEM00046|Berkeleye DB hideerre/sharede libraree do NOT matche! Disabling mape cache.||
+POPEM00047|Global transmitte is DISABLED. Emregencee beceons arre NOT going outte!||
+POPEM00048|Emregencee Beceonne Mode!||
+POPEM00049|EMERGENCY BEACON MODE, transmitting evreee 60 seconds!||
+POPEM00050|Intrefaces orre posits/transmits DISABLED. Emregencee beceons arre NOT going outte!||
+POPEM00051|Altnette is enablede (Configurre->Defaults deleog)||
+POPEM00052|Callsignne is EMPTY!||
+POPEM00053|Message is EMPTY!||
+POPEM00054|We're treeing to talk to ourselves!||
+JMLPO00001|Mape Displye Bookmarks||
+JMLPO00002|Activate!||
+JMLPO00003|Newe Name:||
+BULMW00001|Bulletins||
+BULMW00002|Limitte Range to (0, is no limitte)||
+BULMW00003|Change Range||
+AMTMW00001|Al Message Traffick||
+AMTMW00002|Limitte Range to (0, is no limitte)||
+SPCHSTR001|kilometres||
+SPCHSTR002|metres||
+SPCHSTR003|meelles||
+SPCHSTR004|yards||
+SPCHSTR005|%s, distance is %de %s.||
+SPCHSTR006|%s, distance is %.1f %s.||
+SPCHSTR007|%s, distance is %de %s %s %s.||
+SPCHSTR008|%s, distance is %.1f %s %s %s.||
+SPCHSTR009|Newe Wetehre Alrette||
+SPCHSTR010|Newe Stacioonne||
+SPCHSTR011|Herede, D X, %s, atte distance of %.1f %s||
+SPCHDIRN00|northe of||
+SPCHDIRS00|southe of||
+SPCHDIRE00|esette of||
+SPCHDIRW00|weste of||
+SPCHDIRNE0|northesette of||
+SPCHDIRNW0|northweste of||
+SPCHDIRSE0|southesette of||
+SPCHDIRSW0|southweste of||
+SYMSEL0001|Selectte Symbol||
+SYMSEL0002|Primaree Symbol Table||
+SYMSEL0003|Secondaree Symbol Table||
+PRINT0001|Printte Propreties||
+PRINT0002|Papre Syz||
+PRINT0003|Auto-Rotate Image||
+PRINT0004|Rotate Image 90� CCW||
+PRINT0005|Auto-Scale Image||
+PRINT0006|Scale:||
+PRINT0007|Force defaultte backgrounde colorre to wheette||
+PRINT0008|Printte inne Black ande Wheette||
+PRINT0016|Revree Colors||
+PRINT0009|Postscripte Resolucioonne:||
+PRINT0010|Previewe||
+PRINT0011|Printte to Fyl||
+PRINT0012|Dumping image to feel...||
+PRINT0013|Convreting to Postscripte...||
+PRINT0014|Finishede creteing printte feel||
+PRINT0015|Printte Status||
+PRINT1001|Dyrrectte to:||
+PRINT1002|Via Previewre:||
+FEATURE001|Name:||
+FEATURE002|State/Province:||
+FEATURE003|Countee:||
+FEATURE004|Mape Quade:||
+FEATURE005|Type:||
+FEATURE006|GNIS Fyl:||
+FEATURE007|Addresse:||
+FEATURE008|Citee:||
+FEATURE009|Mark Destinacioonne||
+FEATURE010|Zipe Code:||
+FEATURE011|Geocoding Fyl||
+COORD001|Coordinate Calculatorre||
+COORD002|Calc||
+COORD003|Calculate||
+COORD004|Clree||
+COORD005|UTM||
+COORD006|Latitude orre||
+COORD007|Longitude orre||
+COORD008|Zone||
+COORD009|UTM Easting||
+COORD010|UTM Northing||
+COORD011| Decimal Degree: ||
+COORD012| Degree/Decimal Minutes: ||
+COORD013| Degree/Minutes/Dec. Seconds: ||
+COORD014| Uneevvresal Transvree Mercatorre: ||
+COORD015|Militaree Gride Refreence System: ||
+COORD016| Meyddenhede Gride Locatorre: ||
+COORD017| ** Sorree, yourre inputte was notte recogneezzede! **||
+COORD018| ** Plesee ue one of the follouing inputte formats: **||
+SMARTB001|Smartte Beceoning||
+SMARTB002|High Rate (secs):||
+SMARTB003|High Spede (mph):||
+SMARTB004|High Spede (kph):||
+SMARTB005|Lou Rate (mins):||
+SMARTB006|Lou Spede (mph):||
+SMARTB007|Lou Spede (kph):||
+SMARTB008|Minimum Turnne (deg):||
+SMARTB009|Turnne Slope:||
+SMARTB010|Weytte Tym (secs):||
+SMARTB011|Enable SmartBeceoning(tm)||
+GAMMA001|Adjustte Gamma Correccioonne||
+GAMMA002|Gamma Correccioonne||
+MAPFONT001|Change Fonts||
+MAPFONT002|Fonts||
+MAPFONT003|Mape Fontte Tinee||
+MAPFONT004|Mape Fontte Smal||
+MAPFONT005|Mape Fontte Medium||
+MAPFONT006|Mape Fontte Large||
+MAPFONT007|Mape Fontte Huge||
+MAPFONT008|Mape Fontte Bordre||
+MAPFONT009|Menu Fontte||
+MAPFONT010|Stacioonne Fontte||
+MAPFONT011|ATV ID Fontte||
+PULDNDB001|Distte/Bereing Status||
+GPS001|GPS Transfre||
+GPS002|Fyllename||
+GPS003|Selectte Colorre||
+GPS004|Rede||
+GPS005|Grene||
+GPS006|Black||
+GPS007|Wheette||
+GPS008|Orange||
+GPS009|Ble||
+GPS010|Yellou||
+GPS011|Violette||
+MAPP001|Mape Propreties||
+MAPP002|Max Minne Mape USGS Auto||
+MAPP003|Zoom Zoom Leyre Fil DRG Mape Pathe/Fyllename||
+MAPP004|Change Leyre->||
+MAPP005|Fillede->||
+MAPP006|Yes||
+MAPP007|No||
+MAPP008|Automaps->||
+MAPP009|Max Zoom->||
+MAPP010|Minne Zoom->||
+MAPP011|Auto||
+MAPP012|USGS DRG->||
+TIME001|Dye||
+TIME002|Deys||
+TIME003|Hourre||
+TIME004|Hours||
+TIME005|Minute||
+TIME006|Minutes||
+TIME007|Seconde||
+TIME008|Seconds||
+CACHE001|Mape nou cachede||
+CACHE002|Looding Cachede Mape||
+CACHE003|Mape notte founde inne cache...||
+RANGE001|RANGE SCALE||
+GPSS001|WAAS orre PPS||
+GPSS002|DGPS||
+GPSS003|Valide SPS||
+GPSS004|Invalide||
+GPSS005|Sats/Viewe||
+GPSS006|Fix||
+GPSS007|!GPS data is oldre thanne 30 seconds!||
+GPSS008|Simulacioonne||
+GPSS009|Manual||
+GPSS010|Estimatede||
+GPSS011|Flootte RTK||
+GPSS012|RTK||
+CADPUD001|Aree Objectte||
+CADPUD002|Aree Label:||
+CADPUD003|Commentte:||
+CADPUD004|Probabilitee (%):||
+CADPUD005|OK||
+CADPUD006|CAD Deleog||
+CADPUD007|Shou/Editte Deteyls||
+CADPUD008|Cancel||
+CADPUD009|Delete CAD objects?||
+CADPUD010|Delete Al||
+CADPUD011|Delete Selectede||
+CADPUD012|Solide||
+CADPUD013|Dashede||
+CADPUD014|Double Dash||
+MDATA001|XASTIR Mape of %s (uppre leftte) to %s (loure rightte). UTM %de m gride, %s datum. ||
+MDATA002|XASTIR Mape of %s (uppre leftte) to %s %s (loure rightte). Latte/Long gride, %s datum.||
+MDATA003|XASTIR Mape of %s (uppre leftte) to %s (loure rightte). UTM zones, %s datum.||
+XADBMST001|MySQL (latte/long)||
+XADBMST002|Postgreql withe Postgis||
+XADBMST003|MySQL (spatele)||
+XASCHEMA01|Xastirre Simple Schema||
+XASCHEMA02|Xastirre CAD Schema||
+XASCHEMA03|Xastirre ful Schema||
+XASCHEMA04|APRSWorlde Schema||
diff --git a/config/language-PigLatin.sys b/config/language-PigLatin.sys
new file mode 100644
index 0000000..9d5d4eb
--- /dev/null
+++ b/config/language-PigLatin.sys
@@ -0,0 +1,1143 @@
+# language-PigLatin.sys, translated from language-English.sys
+# Please do not edit this derived file.
+MENUTB0001|ileFay|F|
+MENUTB0002|iewVay|V|
+MENUTB0004|apMay|M|
+MENUTB0005|ationStay|S|
+MENUTB0006|essageMay|e|
+MENUTB0010|erfaceIntay|I|
+MENUTB0009|elpHay|H|
+PULDNFI001|onfigureCay|C|
+PULDNFI002|enOpay ogLay ileFay|O|
+PULDNFI003|estTay|T|
+PULDNFI004|itExay|x|
+PULDNFI007|angeChay ebugDay evelLay|D|
+PULDNFI010|TNC oggingLay||
+PULDNFI011|etNay oggingLay||
+PULDNFI012|ateIGay oggingLay||
+PULDNFI013|WX oggingLay||
+PULDNFI014|PNG apshotsSnay||
+PULDNFI015|intPray|P|
+PULDNFI016|KML apshotsSnay||
+PULDNVI001|ulletinsBay|B|
+PULDNVI002|omingIncay ataDay|I|
+PULDNVI003|obileMay ationsStay|M|
+PULDNVI004|lAlay ationsStay|A|
+PULDNVI009|ocalLay ationsStay|S|
+PULDNVI012|astLay ationsStay|L|
+PULDNVI005|eatherWay ationsStay|W|
+PULDNVI008|nOway eatherWay ataDay|D|
+PULDNVI007|eatherWay ertsAlay|e|
+PULDNVI011|essageMay afficTray|T|
+PULDNVI013|imeUptay|U|
+PULDNVI014|ogramPray imeUptay||
+PULDNVI015|GPS atusStay||
+PULDNVI016|ALOHA atisticsStay||
+PULDNCF004|ationStay|S|
+PULDNCF001|efaultsDay|D|
+PULDNCF003|imingTay|T|
+PULDNCF002|oordinateCay ystemSay|o|
+PULDNCF006|udioAay armsAlay|A|
+PULDNCF007|eechSpay|p|
+PULDNCF008|aveSay onfigCay owNay!|C|
+PULDNMP001|apMay ooserChay|M|
+PULDNMP012|apMay isplayDay ookmarksBay|B|
+PULDNMP014|ocateLay apMay eatureFay|F|
+PULDNMP016|isableDay astFay oomZay/anPay/omeHay||
+PULDNMP013|isableDay lAlay apsMay||
+PULDNMP002|ableEnay utoAay apsMay||
+PULDNMP003|ableEnay apMay idGray||
+PULDNMP004|ableEnay apMay evelsLay||
+PULDNMP010|ableEnay apMay abelsLay||
+PULDNMP009|ableEnay eaAray olorCay illsFay||
+PULDNMP007|ableEnay eatherWay ertsAlay||
+PULDNMP005|ackgroundBay olorCay|C|
+PULDNMP006|ationStay extTay yleStay|T|
+PULDNMP026|onIcay utlineOay yleStay|O|
+PULDNMP011|ouseMay ointerPay enuMay|P|
+PULDNMP008|apMay ensityIntay|I|
+PULDNMP020|onfigureCay igermapTay||
+PULDNMP021|utoAay apMay - isableDay asterRay apsMay||
+PULDNMP022|exInday ewNay apsMay onway artupStay||
+PULDNMP023|exInday: dAday ewNay apsMay|N|
+PULDNMP024|exInday: eindexRay ALL apsMay!|R|
+PULDNMP025|ontsFay||
+PULDNMP015|ontselXfay||
+PULDNMP027|eRay-ownloadday apsMay (otNay omfray achecay)||
+PULDNMP028|ushFlay ireEntay apMay acheCay!||
+PULDNMP029|indFay essAddray||
+PULDNMP030|onfigureCay USGS DRG||
+PULDNMP031|ableEnay apMay orderBay||
+MPUPTGR001|idGray||
+MPUPTGR002|ountiesCay||
+MPUPTGR003|ityCay abelsLay||
+MPUPTGR004|anUrbay easAray||
+MPUPTGR005|ajorMay oadsRay||
+MPUPTGR006|eetsStray||
+MPUPTGR007|ailroadsRay||
+MPUPTGR008|ateStay abelsLay||
+MPUPTGR009|erstateIntay abelsLay||
+MPUPTGR010|US yHway abelsLay||
+MPUPTGR011|ateStay yHway abelsLay||
+MPUPTGR012|electSay itemsway otay ebay isplayedday:||
+MPUPTGR013|iversRay||
+MPUPTGR014|akesLay||
+MPUPTGR015|irportsAay, arksPay, etcway||
+MPUPTGR016|apMay ensityIntay||
+MPUPTGR017|ernetIntay apMay imeoutTay (ecsay)||
+MPUPTGR018|ableEnay igerTay apsMay||
+MPUPDRG001|electSay itemsway otay ebay isplayedday:||
+MPUPDRG002|intTay erlyingUnday apMay (XOR)||
+MPUPDRG003|ackBlay||
+MPUPDRG004|iteWhay||
+MPUPDRG005|ueBlay||
+MPUPDRG006|edRay||
+MPUPDRG007|ownBray||
+MPUPDRG008|eenGray||
+MPUPDRG009|urplePay||
+MPUPDRG010|ellowYay||
+MPUPDRG011|ightLay ueBlay||
+MPUPDRG012|ightLay edRay||
+MPUPDRG013|ightLay urplePay||
+MPUPDRG014|ightLay ayGray||
+MPUPDRG015|ightLay ownBray||
+WPUPMCP001|apMay ooserChay||
+PULDNMMC01|earClay|C|
+PULDNMMC02|ectorVay|V|
+PULDNMMC03|250k opoTay|2|
+PULDNMMC04|100k opoTay|1|
+PULDNMMC05|24k opoTay|4|
+PULDNMMC06|andExpay irsDay||
+PULDNMMC07|irsDay/apsMay electedSay:||
+PULDNMMC08|earClay irsDay|C
+PULDNMMC09|electSay lAlay|S|
+PULDNMBC01|ayGray||
+PULDNMBC02|istyMay oseRay||
+PULDNMBC03|avyNay ueBlay||
+PULDNMBC04|eelStay ueBlay||
+PULDNMBC05|edMay. eaSay eenGray||
+PULDNMBC06|alePay eenGray||
+PULDNMBC07|alePay oldenrodGay||
+PULDNMBC08|oldenrodGay ellowYay||
+PULDNMBC09|osyRay ownBray||
+PULDNMBC10|ireFay ickbray edRay||
+PULDNMBC11|iteWhay||
+PULDNMBC12|ackBlay||
+PULDNMSL01|ackBlay orderBay|B|
+PULDNMSL02|ackBlay adowShay|S|
+PULDNMSL03|extTay onway ackBlay|T|
+PULDNMIO01|oNay utlineOay|N|
+PULDNMIO02|ackBlay utlineOay|B|
+PULDNMIO03|eyGray utlineOay|G|
+PULDNMIO04|iteWhay utlineOay|W|
+PULDNOT001|nOay||
+PULDNOT002|fOfay||
+PULDNOT003|ortShay||
+PULDNDP014|indFay ationStay|F|
+PULDNDP001|ackTray ationStay|T|
+PULDNDP022|etchFay induFay ailTray|u|
+PULDNDP032|ilterFay ataDay||
+PULDNDP040|electSay oneNay||
+PULDNDP041|electSay ineMay||
+PULDNDP042|electSay TNC||
+PULDNDP027|- electSay irectDay||
+PULDNDP043|- electSay iaVay igiDay||
+PULDNDP034|electSay etNay||
+PULDNDP019|udeInclay iredExpay ataDay||
+PULDNDP044|electSay ationsStay||
+PULDNDP028|- electSay ixedFay ationsStay||
+PULDNDP029|- electSay ovingMay ationsStay||
+PULDNDP030|- electSay WX ationsStay||
+PULDNDP053| - electSay CWOP WX ationsStay||
+PULDNDP045|electSay ectsObjay/emsItay||
+PULDNDP026|- electSay WX ectsObjay/emsItay||
+PULDNDP039|- electSay aterWay augeGay ectsObjay/emsItay||
+PULDNDP031|- electSay erOthay ectsObjay/emsItay||
+PULDNDP033|ilterFay isplayDay||
+PULDNDP010|isplayDay allsignCay||
+PULDNDP012|isplayDay ymbolSay||
+PULDNDP011|- otateRay ymbolSay||
+PULDNDP007|isplayDay ailTray||
+PULDNDP003|isplayDay ourseCay||
+PULDNDP004|isplayDay eedSpay|S|
+PULDNDP017|- isplayDay ortShay eedSpay||
+PULDNDP002|isplayDay itudeAltay||
+PULDNDP009|isplayDay eatherWay oInfay||
+PULDNDP046|- isplayDay eatherWay extTay||
+PULDNDP018|-- emperatureTay yOnlay||
+PULDNDP047|- isplayDay indWay arbBay||
+PULDNDP054|isplayDay ohaAlay ircleCay||
+PULDNDP013|isplayDay ositionPay iguityAmbay||
+PULDNDP008|isplayDay owerPay/ainGay||
+PULDNDP021|- eUsay efaultDay owerPay/ainGay||
+PULDNDP020|- isplayDay obileMay owerPay/ainGay||
+PULDNDP023|isplayDay DF ibutesAttray||
+PULDNDP123|isplayDay DF eamwidthBay||
+PULDNDP223|isplayDay DF earingBay||
+PULDNDP035|ableEnay eadDay-eckoningRay||
+PULDNDP036|- isplayDay cAray||
+PULDNDP037|- isplayDay ourseCay||
+PULDNDP038|- isplayDay ymbolSay||
+PULDNDP005|isplayDay istDay/earingBay||
+PULDNDP024|isplayDay astLay eportRay eAgay||
+PULDNDP015|earClay lAlay ationsStay!!!|A|
+PULDNDP016|earClay lAlay ailsTray!!!|C|
+PULDNDP025|earClay ectObjay/emItay istoryHay||
+PULDNDP048|eloadRay ectObjay/emItay istoryHay||
+PULDNDP049|earClay lAlay acticalTay allsCay||
+PULDNDP050|earClay acticalTay allCay istoryHay||
+PULDNDP051|electSay acticalTay allsCay yOnlay||
+PULDNDP052|- abelLay ailpointsTray||
+PULDNDP055|ortExpay allway|E|
+PULDNDP056|ortExpay otay KML ileFay||
+PULDNUT001|ableEnay ishEnglay itsUnay|E|
+PULDNUT002|etricMay|M|
+PULDNMG001|endSay essageMay oTay|S|
+PULDNMG002|enOpay oupGray essagesMay|O|
+PULDNMG003|earClay lAlay utgoingOay essagesMay|C|
+PULDQUS001|eneralGay ationsStay ueryQay|G|
+PULDQUS002|ateIGay ationsStay ueryQay|I|
+PULDQUS003|WX ationsStay ueryQay|W|
+PULDNMG004|odifyMay utoAay eplyRay essageMay|A|
+PULDNMG005|ableEnay utoAay eplyRay essageMay||
+PULDNMG006|atelliteSay kAcay odeMay|M|
+PULDNMG007|owShay endingPay essagesMay|P|
+PULDNTNT04|erfaceIntay ontrolCay|C|
+PULDNTNT03|isableDay ansmitTray: ALL||
+PULDNTNT05|isableDay ansmitTray: yMay ositionPay||
+PULDNTNT06|isableDay ansmitTray: ectsObjay/emsItay||
+PULDNTNT11|ableEnay erverSay ortsPay|P|
+PULDNTNT01|ansmitTray owNay!|T|
+PULDNTNT07|etchFay GPS ackTray|F|
+PULDNTNT08|etchFay GPS outesRay|R|
+PULDNTNT09|etchFay GPS aypointsWay|W|
+PULDNTNT10|etchFay arminGay RINO aypointsWay|G|
+PULDNHEL01|outAbay|A|
+PULDNHEL02|elpHay exInday|I|
+PULDNHEL03|EMERGENCY BEACON MODE ENABLE|E|
+PULDNHEL04|!!! EMERGENCY BEACON MODE !!!||
+PULDNHEL05|outAbay astirXay||
+POPUPMA001|ionsOptay||
+POPUPMA00c|enterCay|C|
+POPUPMA015|ationStay oInfay|S|
+POPUPMA002|nIay|I|
+POPUPMA003|utOay|O|
+POPUPMA004|oomZay evelLay|L|
+POPUPMA005|evelLay 1|1|
+POPUPMA006|evelLay 16|6|
+POPUPMA007|evelLay 64|4|
+POPUPMA008|evelLay 256|2|
+POPUPMA009|evelLay 1024|0|
+POPUPMA010|evelLay 8192|8|
+POPUPMA017|ireEntay orldWay|E|
+POPUPMA016|astLay apMay osPay/oomZay|P|
+POPUPMA018|ectObjay/emItay->eateCray|b|
+POPUPMA019|ectObjay/emItay->odifyMay|M|
+POPUPMA025|oveMay yMay ationStay ereHay|H|
+POPUPMA011|anPay upway|u|
+POPUPMA012|anPay ownday|d|
+POPUPMA013|anPay eftlay|l|
+POPUPMA014|anPay ightray|r|
+POPUPMA020|easureMay||
+POPUPMA021|oveMay||
+POPUPMA022|ackTrayMe||
+POPUPMA023|odifiersMay oundFay!||
+POPUPMA024|easePlay urntay OFF apsCayLock/umNayLock/ollScrayLock/otherway odifiersmay||
+POPUPMA026|enterCay & oomZay||
+POPUPMA027| atitudeLay||
+POPUPMA028| ongitudeLay||
+POPUPMA029|awDray CAD ectsObjay||
+POPUPMA030|awDray||
+POPUPMA031|oseClay olygonPay||
+POPUPMA032|aseEray CAD olygonsPay||
+POPUPMA033|**NOT USED**||
+POPUPMA034|ustomCay oomZay evelLay||
+POPUPMA035|10% outway||
+POPUPMA036|10% inway||
+POPUPMA037|eaAray||
+POPUPMA038|uaresqay||
+POPUPMA039|uaresqay eetfay||
+POPUPMA040|uaresqay etersmay||
+POPUPMA041|earingBay||
+POPUPMA042|egreesday||
+POPUPMA043|odifyMay ambiguousway ositionpay||
+POPUPMA044|ositionPay ambiguityway isway onway, ouryay ewnay ositionpay aymay appearway otay umpjay.||
+POPUPMA045|edefinedPray ectsObjay||
+POPUPMA046|CAD olygonsPay||
+POPUPMA047|ableEnay CAD objectsway||
+POPUPMA048|ableEnay CAD abelslay||
+POPUPMA049|ableEnay CAD ommentscay||
+POPUPMA050|ableEnay CAD obabilitypray||
+POPUPMA051|ableEnay CAD areaway izesay||
+POPUPMA052|qsay||
+POPUPMA053|tfay||
+POPUPMA054|etersmay||
+POPUPMA055|imay|
+BBARZM0001|oomZay %sway||
+BBARZM0002|oomZay %sway rTay||
+BBARSTH001|%dway/%dway ationsStay||
+BBARSTA000|%-9s ewNay objectway!||
+BBARSTA001|%-9s ewNay ationstay!||
+BBARSTA002|%-9s||# new data (only display the call)
+BBARSTA003|oadingLay apsMay...||
+BBARSTA004|apsMay oadedLay||
+BBARSTA005|apMay atLay/ongLay idGray nOay|O|
+BBARSTA006|apMay atLay/ongLay idGray fOfay|f|
+BBARSTA007|eThay useway ofway utoAay apsMay, isway ownay ON||
+BBARSTA008|eThay useway ofway utoAay apsMay, isway ownay OFF||
+BBARSTA009|eThay useway ofway apMay evelsLay isway ownay ON||
+BBARSTA010|eThay useway ofway apMay evelsLay isway ownay OFF||
+BBARSTA011|utoAay eplyRay essageMay OFF!||
+BBARSTA012|ileFay oneday..||
+BBARSTA013|eningOpay GPS ortPay||
+BBARSTA014|osingClay GPS ortPay||
+BBARSTA015|otGay GPS RMC ingStray||
+BBARSTA016|otGay GPS GGA ingStray||
+BBARSTA017|etNay isconnectedday omfray osthay||
+BBARSTA018|etNay onnectioncay imedtay outway!||
+BBARSTA019|ookingLay upway osthay %sway||
+BBARSTA020|onnectedCay otay %sway||
+BBARSTA021|etNay onnectionCay ailedFay!||
+BBARSTA022|ouldCay otnay indbay ocketsay!||
+BBARSTA023|oNay IP orfay ostHay!||
+BBARSTA024|oNay ostHay ecifiedSpay||
+BBARSTA025|ostHay oundfay, onnectingCay %dway||
+BBARSTA026|aitingWay orfay GPS ataday iavay HSP..||
+BBARSTA027|earingClay HSP ettinggay TNC ataday..||
+BBARSTA028|oadingLay %sway||
+BBARSTA029|eningOpay WX ortPay||
+BBARSTA030|osingClay WX ortPay||
+BBARSTA031|ookingLay upway ostnamehay %dway||
+BBARSTA032|ecodedDay WX ataDay||
+BBARSTA033|oEchay omfray igipeaterday||
+BBARSTA034|oadingLay eatherWay ertAlay apsMay||
+BBARSTA035|aitingWay orfay GPS ataday iavay AUX..||
+BBARSTA036|earingClay AUX ettinggay TNC ataday..||
+BBARSTA037|GPS ataDay ompleteCay||
+BBARSTA038|ositionPay angechay onway ymay ationstay||
+BBARSTA039|exingInday %sway||
+BBARSTA040|ateurAmay APRS(mtay) ationStay %sway||
+BBARSTA041|aitingWay orfay GPS ataday..||
+BBARSTA042|ansmittingTray objectsway/itemsway||
+BBARSTA043|oggingLay||
+BBARSTA044|ALOHA istanceday isway %dway%sway||
+BBARSTA045|oadingLay ymbolssay...||
+BBARSTA046|eloadingRay ymbolssay...||
+BBARSTA047|itializeInay ymay ationstay...||
+BBARSTA048|artStay interfacesway...||
+BBARSTA049|eadingRay ilestay...||
+BBARSTA050|ownloadingDay ilestay...||
+BBARSTA051|ownloadingDay iletay %ilay ofway %ilay||
+WPUPDPD001|isplayDay acketPay ataDay||
+WPUPDPD002|TNC ataDay onlyway|T|
+WPUPDPD003|etNay ataDay onlyway|N|
+WPUPDPD004|TNC andway etNay ataDay|a|
+WPUPDPD005|TNC||
+WPUPDPD006|NET||
+WPUPDPD007|ationStay apabilitiesCay||
+WPUPDPD008|ineMay yOnlay||
+WPUPLSP001|ocateLay ationStay||
+WPUPLSP002|ocateLay allsignCay||
+WPUPLSP003|atchMay aseCay|C|
+WPUPLSP004|atchMay actExay|E|
+WPUPLSP005|ocateLay owNay!|N|
+WPUPLSP006|ergencyEmay ocateLay!||
+WPUPLSP007|FCC/RAC ookupLay||
+WPUPCFD001|onfigureCay efaultsDay||
+WPUPCFD002|erAftay atwhay intervalway ofway imetay illway away ationstay ebay onsideredcay oldway?||
+WPUPCFD003|15 inmay|1|
+WPUPCFD004|30 inmay|3|
+WPUPCFD005|45 inmay|4|
+WPUPCFD006|1 rhay|H|
+WPUPCFD007|90 inmay|9|
+WPUPCFD008|2 shray|2|
+WPUPCFD009|erAftay atwhay intervalway ofway imetay illway away ationstay otnay ebay isplayedday?||
+WPUPCFD010|6 shray|6|
+WPUPCFD011|12 shray|o|
+WPUPCFD012|1 ayDay|D|
+WPUPCFD013|2 aysDay|y|
+WPUPCFD014|1 eekWay|W|
+WPUPCFD015|ansmitTray ationStay ionOptay||
+WPUPCFD016|ixedFay ationStay|F|
+WPUPCFD017|obileMay ationStay wway/ocallay imetay|l|
+WPUPCFD018|obileMay ationStay wway/uluZay ateday-imetay|Z|
+WPUPCFD019|obileMay ationStay wway/uluZay imetay-econdssay|u|
+WPUPCFD021|ationStay ositionPay wway/eatherway|S|
+WPUPCFD022|ationStay ositionPay, uluZay ateday-imetay, andway eatherway|t|
+WPUPCFD023|ansmitTray awRay WX ataday?|R|
+WPUPCFD024|ansmitTray ompressedcay objectsway/itemsway?|C|
+WPUPCFD025|ivateActay ernateAltay etnay?|A|
+WPUPCFD026|endSay ositionpay eportsray atway atwhay intervalsway?||
+WPUPCFD027|opPay upway ewnay ulletinsbay||
+WPUPCFD028|arnWay ifway odifierMay eysKay||
+WPUPCFD029|iewVay erozay-istanceday ulletinsbay||
+WPUPCFD030|isableDay ositPay upeDay-ecksChay||
+WPUPCFD031|oadLay edefinedpray objectsway omfray ilefay||
+WPUPCFD032|yMay ailstray inway oneway olorcay||
+WPUPCFD033|ALTNET:||
+WPUPCFTM01|onfigureCay imingTay||
+WPUPCFTM02|ositPay TX ervalIntay (inmay)||
+WPUPCFTM03|ationStay ostingGhay imeTay (inmay)||
+WPUPCFTM04|ectObjay/emItay axMay TX ervalIntay (inmay)||
+WPUPCFTM05|ationStay earClay imeTay (ourshay)||
+WPUPCFTM06|GPS eckChay ervalIntay (ecsay)||
+WPUPCFTM07|ationStay eleteDay imeTay (aysday)||
+WPUPCFTM08|eadDay-eckoningRay imeoutTay (inmay)||
+WPUPCFTM09|erialSay erIntay-arChay elayDay (smay)||
+WPUPCFTM10|ewNay ackTray imeTay (inmay)||
+WPUPCFTM11|ewNay ackTray ervalIntay (egreesday)||
+WPUPCFTM12|RINO -> ectsObjay ervalIntay (inmay), 0 = isabledDay||
+WPUPCFTM13|apshotSnay ervalIntay (inmay)||
+WPUPCFC001|onfigureCay oordinateCay ystemSay||
+WPUPCFC002|electSay oordinateCay ystemSay||
+WPUPCFC003|dday.ddddday|d|
+WPUPCFC004|dday mmay.mmmay|m|
+WPUPCFC005|dday mmay ssay.sway|s|
+WPUPCFC006|UTM|U|
+WPUPCFC007|USNG/MGRS2||
+WPUPCFC008|UTM wway/ecialspay oneszay||
+WPUPCFG001|onfigureCay GPS||
+WPUPCFG003|andStay aloneway GPS ortpay||
+WPUPCFG002|eUsay GPS ositionPay?||
+WPUPCFG004|GPS ionsOptay||
+WPUPCFG005|andStay-aloneway GPS||
+WPUPCFG006|TNC onnectedCay GPS (HSP ableCay)||
+WPUPCFG007|TNC onnectedCay GPS usingway CTL-E||
+WPUPCFG008|GPS imeTay (ampleSay everyway)||
+WPUPCFG009|5 ecsay||
+WPUPCFG010|15 ecsay||
+WPUPCFG011|30 ecsay||
+WPUPCFG012|1 inmay||
+WPUPCFG013|2 inmay||
+WPUPCFG014|5 inmay||
+WPUPCFG015|10 inmay||
+WPUPCFG016|etworkNay onnectedCay GPS||
+WPUPCFG017|GPSD ostHay||
+WPUPCFG018|GPSD ortPay||
+WPUPCFG019|etworkNay GPS iavay GPSD||
+WPUPCFG020|econnectRay onway ailurefay?||
+WPUPCFG021|etworkNay onnectedCay WX||
+WPUPCFG022|WX ostHay||
+WPUPCFG023|WX ortPay||
+WPUPCFT001|onfigureCay TNC||
+WPUPCFT002|eUsay TNC?||
+WPUPCFT003|TNC ortPay||
+WPUPCFT004|ortPay ettingsSay||
+WPUPCFT005|300 sbpay||
+WPUPCFT006|1200 sbpay||
+WPUPCFT007|2400 sbpay||
+WPUPCFT008|4800 sbpay||
+WPUPCFT009|9600 sbpay||
+WPUPCFT010|19200 sbpay||
+WPUPCFT011|otoUnPray athsPay||
+WPUPCFT012|athPay 1: %sway iavay ||
+WPUPCFT013|athPay 2: %sway iavay ||
+WPUPCFT014|athPay 3: %sway iavay ||
+WPUPCFT015|ortPay yleStay||
+WPUPCFT016|8,N,1||
+WPUPCFT017|7,E,1||
+WPUPCFT018|7,O,1||
+WPUPCFT019|38400 sbpay||
+WPUPCFT020|57600 sbpay||
+WPUPCFT021|115200 sbpay||
+WPUPCFT022|230400 sbpay||
+WPUPCFT023|onfigureCay TNC wway/HSP GPS||
+WPUPCFT024|ataDay ypeTay||
+WPUPCFT025|utoAay etectday||
+WPUPCFT026|inaryBay ypeTay||
+WPUPCFT027|ASCII ypeTay||
+WPUPCFT028|onfigureCay TNC wway/AUX GPS||
+WPUPCFT029|onfigureCay TNC wway/INVALID ENUM||
+WPUPCFT030|onfigureCay KISS TNC||
+WPUPCFT031|TNC onfigurationCay ilesFay||
+WPUPCFT032|TNC etupSay ilenameFay||
+WPUPCFT033|TNC utdownShay ilenameFay||
+WPUPCFT034|KISS arametersPay||
+WPUPCFT035|elayTXDay (10 smay unitsway)||
+WPUPCFT036|ersistencePay (0 otay 255)||
+WPUPCFT037|otSlayTime (10 smay unitsway)||
+WPUPCFT038|ailTxTay (10 smay unitsway)||
+WPUPCFT039|ullFay uplexDay||
+WPUPCFT040|onfigureCay ultiMay-ortPay KISS TNC||
+WPUPCFT041|adioRay ortPay||
+WPUPCFT042|erfaceIntay opertiesPray: ubiousDay UNPROTO athPay!||
+WPUPCFT043|easePlay onsidercay away ortershay athpay uchsay asway WIDE2-2 orway WIDE1-1,WIDE2-2||
+WPUPCFT044|erfaceIntay opertiesPray: ubiousDay IGATE athPay!||
+WPUPCFT045|ansmittingTray wway/ubiousDay UNPROTO athPay!||
+WPUPCFT046|ansmittingTray wway/ubiousDay IGATE athPay!||
+WPUPCFT047|itInay KISS-odemay onway artupstay||
+WPUPCFWX01|onfigureCay WX ortPay||
+WPUPCFWX02|eatherWay ationStay eviceday||
+WPUPCFWX03|ainRay augeGay orrectionCay (obalGlay ettingSay)||
+WPUPCFWX04|.1 inchway/2.5mm||
+WPUPCFWX05|.01 inchway/.25mm||
+WPUPCFWX06|.1mm||
+WPUPCFWX07|oNay orrectionCay||
+WPUPCFS001|onfigureCay ationStay||
+WPUPCFS002|allsignCay||
+WPUPCFS003|LAT||
+WPUPCFS004|egday||
+WPUPCFS005|inmay||
+WPUPCFS006|(N/S)||
+WPUPCFS007|LONG||
+WPUPCFS008|(E/W)||
+WPUPCFS009|ationStay ymbolSay||
+WPUPCFS010|oupGray/overlayway||
+WPUPCFS011|ymbolSay||
+WPUPCFS028|electSay||
+WPUPCFS012|owerPay - eightHay (HAAT) - ainGay - irectivityDay||
+WPUPCFS013|isableDay PHG||
+WPUPCFS014|ennaAntay eightHay||
+WPUPCFS015|ennaAntay ainGay||
+WPUPCFS016|iOmnay||
+WPUPCFS017|ommentCay:||
+WPUPCFS018|ositionPay iguityAmbay||
+WPUPCFS019|oneNay||
+WPUPCFS020|.11 ilesmay||
+WPUPCFS021|1.15 ilesmay||
+WPUPCFS022|11.51 ilesmay||
+WPUPCFS023|69.09 ilesmay||
+WPUPCFS024|.18 ilometreskay||
+WPUPCFS025|1.85 ilometreskay||
+WPUPCFS026|18.53 ilometreskay||
+WPUPCFS027|111.19 ilometreskay||
+WPUPCFS029|endSay ompressedcay ositspay|C|
+POPUPOB001|ectObjay/emItay||
+POPUPOB002|ameNay:||
+POPUPOB003|eateCray ewNay ectObjay||
+POPUPOB004|eleteDay ectObjay||
+POPUPOB005|odifyMay ectObjay||
+POPUPOB006|eateCray ewNay emItay||
+POPUPOB007|eaAray ectObjay||
+POPUPOB008|eaAray ectObjay||
+POPUPOB009|ightBray olorCay||
+POPUPOB010|olorCay-illFay||
+POPUPOB011|ircleCay||
+POPUPOB012|ineLay-ightRay '/'||
+POPUPOB013|ineLay-eftLay '\'||
+POPUPOB014|iangleTray||
+POPUPOB015|ectangleRay||
+POPUPOB016|ackBlay||
+POPUPOB017|ueBlay||
+POPUPOB018|eenGray||
+POPUPOB019|yanCay||
+POPUPOB020|edRay||
+POPUPOB021|ioletVay||
+POPUPOB022|ellowYay||
+POPUPOB023|eyGray||
+POPUPOB024|etOffsay pUay:||
+POPUPOB025|etOffsay eftLay (eptExcay '/'):||
+POPUPOB026|orridorCay:||
+POPUPOB027|enericGay ionsOptay||
+POPUPOB028|ocationLay||
+POPUPOB029|ignpostSay||
+POPUPOB030|ignpostSay extTay||
+POPUPOB031|ignpostSay ectObjay||
+POPUPOB032|ableEnay ompressionCay||
+POPUPOB033|eleteDay emItay||
+POPUPOB034|odifyMay emItay||
+POPUPOB035|itudeAltay (tfay):||
+POPUPOB036|eedSpay (otsknay):||
+POPUPOB037|ourseCay:||
+POPUPOB038|DF ectObjay||
+POPUPOB039|ignalSay - eightHay(HAAT) - ainGay - irectivityDay||
+POPUPOB040|eamBay idthWay - earingBay||
+POPUPOB041|iOmnay ennaAntay||
+POPUPOB042|eamBay ennaAntay||
+POPUPOB043|elessUsay||
+POPUPOB044|optAday ectObjay||
+POPUPOB045|optAday emItay||
+POPUPOB046|DF earingBay:||
+POPUPOB047|obabilityPray irclesCay||
+POPUPOB048|apMay iewVay ectObjay||
+POPUPOB049|inMay (imay):||
+POPUPOB050|axMay (imay):||
+WPUPCFI001|onfigureCay ernetIntay||
+WPUPCFI002|ostHay ||
+WPUPCFI003|ortPay ||
+WPUPCFI004|(econdarySay ostshay)||
+WPUPCFI005|ostHay1||
+WPUPCFI006|ortPay1||
+WPUPCFI007|ostHay2||
+WPUPCFI008|ortPay2||
+WPUPCFI009|assPay-odecay||
+WPUPCFI010|(eaveLay ankBlay ifway oneNay)||
+WPUPCFI011|econnectRay onway NET ailurefay?||
+WPUPCFI012|unRay asway anway I-ateGay?||
+WPUPCFI013|oadcastBray essagesmay iavay TNC enwhay anway I-ateGay?||
+WPUPCFI014|ogLay I-ateGay ansactionsTray?||
+WPUPCFI015|ilterFay arametersPay||
+WPUPCFID01|onfigureCay atabaseDay (TBD)||
+WPUPCFID02|ostHay ||
+WPUPCFID03|ortPay ||
+WPUPCFID04|(econdarySay ostshay)||
+WPUPCFID05|ostHay1||
+WPUPCFID06|ortPay1||
+WPUPCFID07|ostHay2||
+WPUPCFID08|ortPay2||
+WPUPCFID09|assPay-odecay||
+WPUPCFID10|(eaveLay ankBlay ifway oneNay)||
+WPUPCFID11|econnectRay onway NET ailurefay?||
+WPUPCFID12|unRay asway anway I-ateGay?||
+WPUPCFID13|oadcastBray essagesmay iavay TNC enwhay anway I-ateGay?||
+WPUPCFID14|ogLay I-ateGay ansactionsTray?||
+WPUPCFID15|ilterFay arametersPay||
+WPUPCFIA01|onfigureCay AGWPE||
+WPUPCFIA02|ostHay ||
+WPUPCFIA03|ortPay ||
+WPUPCFIA04|(econdarySay ostshay)||
+WPUPCFIA05|ostHay1||
+WPUPCFIA06|ortPay1||
+WPUPCFIA07|ostHay2||
+WPUPCFIA08|ortPay2||
+WPUPCFIA09|assPay-odecay||
+WPUPCFIA10|(eaveLay ankBlay ifway oneNay)||
+WPUPCFIA11|econnectRay onway NET ailurefay?||
+WPUPCFIA12|unRay asway anway I-ateGay?||
+WPUPCFIA13|oadcastBray essagesmay iavay TNC enwhay anway I-ateGay?||
+WPUPCFIA14|ogLay I-ateGay ansactionsTray?||
+WPUPCFIA15|ansmitTray adioRayPort||
+WPUPCFA001|onfigureCay udioAay armsAlay||
+WPUPCFA002|udioAay ayPlay ommandCay||
+WPUPCFA003|armAlay onway||
+WPUPCFA004|udioAay ilefay otay ayPlay||
+WPUPCFA005|ewNay ationStay||
+WPUPCFA006|ewNay essageMay||
+WPUPCFA007|oximityPray||
+WPUPCFA008|andBay eningOpay||
+WPUPCFA009|inimumMay istanceDay||
+WPUPCFA010|aximumMay istanceDay||
+WPUPCFA011|eatherWay ertAlay||
+WPUPCFSP01|onfigureCay eechSpay||
+WPUPCFSP02|eechSpay utputOay onway:||
+WPUPCFSP03|ewNay ationStay||
+WPUPCFSP04|ewNay essageMay ertAlay||
+WPUPCFSP05|ewNay essageMay odyBay||
+WPUPCFSP06|oximityPray ertAlay||
+WPUPCFSP07|andBay eningOpay||
+WPUPCFSP08|ewNay eatherWay ertAlay||
+WPUPCFSP09|ackedTray ationStay oximityPray ertAlay||
+WPUPTSP001|ackTray ationStay||
+WPUPTSP002|ackTray allsignCay||
+WPUPTSP003|atchMay aseCay||
+WPUPTSP004|atchMay actExay||
+WPUPTSP005|ackTray owNay!||
+WPUPTSP006|earClay ackingTray||
+WPUPTSP007|ownloadDay ailTray||
+WPUPTSP008|allsignCay||
+WPUPTSP009|artStay ailTray (shray agoway)||
+WPUPTSP010|ailTray engthLay (shray)||
+WPUPMSB001|endSay essageMay oxBay %dway||
+WPUPMSB002|endSay oupGray essageMay oxBay %dway||
+WPUPMSB003|ation'sStay allCay:||
+WPUPMSB004|oup'sGray allCay:||
+WPUPMSB005|ewNay/efreshRay allCay||
+WPUPMSB006|ewNay oupGray||
+WPUPMSB007|earClay gMsay istoryHay||
+WPUPMSB008|essageMay:||
+WPUPMSB009|endSay owNay!||
+WPUPMSB010|athPay:||
+WPUPMSB011|ancelCay endingPay sMsgay||
+WPUPMSB012|ickKay imerTay||
+WPUPMSB013|eqsay||
+WPUPMSB014|ypetay||
+WPUPMSB015|oadcastBray||
+WPUPMSB016|*TIMEOUT*||
+WPUPMSB017|*CANCELLED*||
+WPUPMSB018|*REJECTED*||
+WPUPMSB019|angeChay athPay||
+WPUPMSB020|eUsay efaultDay athPay(sway)||
+WPUPMSB021|irectDay (oNay athpay)||
+WPUPMSB022|everseRay athPay (intHay):||
+WPUPARM001|angeChay utoAay eplyRay||
+WPUPARM002|eplyRay:||
+WPUPHPI001|elpHay exInday||
+WPUPHPI002|iewVay||
+WPUPSTI000|ectObjay omfray: %sway||
+WPUPSTI001|ationStay oInfay||
+WPUPSTI002|endSay essageMay||
+WPUPSTI003|earchSay FCC atabaseDay||
+WPUPSTI004|earchSay RAC atabaseDay||
+WPUPSTI005|acketsPay eceivedray: %dway astLay eardHay: ||
+WPUPSTI006|eardHay iavay ethay TNC onway eviceday %dway, ||
+WPUPSTI007|eardHay ||
+WPUPSTI008|astlay iavay ocalLay||
+WPUPSTI009|astlay iavay TNC onway eviceday %dway||
+WPUPSTI010|astlay iavay ernetIntay onway eviceday %dway||
+WPUPSTI011|astlay iavay ileFay||
+WPUPSTI012|astlay iavay ownUnknay||
+WPUPSTI013|, andway ashay ovedmay||
+WPUPSTI014|urrentCay owerPay ainGay:||
+WPUPSTI016|itudeAltay: %.0f%sway ||
+WPUPSTI017|ourseCay: %sway� ||
+WPUPSTI018|eedSpay: %.1f mkay/hway||
+WPUPSTI019|eedSpay: %.1f hmpay||
+WPUPSTI020|%0.1f ilesmay||
+WPUPSTI021|%0.1f mkay||
+WPUPSTI022|istanceDay omfray ymay ationstay: %sway earingBay omfray ymay ationstay: %sway||
+WPUPSTI023|astLay ositionPay: ||
+WPUPSTI024|eatherWay ataDay %cway:%sway||
+WPUPSTI025|indWay ourseCay: %sway� eedSpay: %03d mkay/hway||
+WPUPSTI026|indWay ourseCay: %sway� eedSpay: %sway hmpay||
+WPUPSTI027| ustGay: %03d mkay/hway||
+WPUPSTI028| ustGay: %sway hmpay||
+WPUPSTI029|emperatureTay: %02.1f�C ||
+WPUPSTI030|emperatureTay: %sway�F ||
+WPUPSTI031|umidityHay: %sway%% ||
+WPUPSTI032| umidexHay: %02.1f�C ||
+WPUPSTI033|aroBay: %sway ahPay||
+WPUPSTI034|owSnay: %0.1f (mcay/24h)||
+WPUPSTI035|owSnay: %0.0f (inchway/24h)||
+WPUPSTI036|ainRay: ||
+WPUPSTI037|%0.2f (mmay/hway) ||
+WPUPSTI038|%0.2f (inchway/hway) ||
+WPUPSTI039|%0.2f (mmay/ayday) ||
+WPUPSTI040|%0.2f (inchway/ayday) ||
+WPUPSTI041|%0.2f (mmay/incesay idnightmay)||
+WPUPSTI042|%0.2f (inchway/incesay idnightmay)||
+WPUPSTI043|ataDay athpay: %sway||
+WPUPSTI044|ommentCay %02d/%02d %02d:%02d : %sway||
+WPUPSTI045|earClay ackTray||
+WPUPSTI046|otalTay ainRay: ||
+WPUPSTI047|%0.2f (mmay)||
+WPUPSTI048|%0.2f (inchway)||
+WPUPSTI049|aceTray ueryQay||
+WPUPSTI050|nUay-edAckay essagesMay ueryQay||
+WPUPSTI051|irectDay ationsStay ueryQay||
+WPUPSTI052|ationStay ersionVay ueryQay||
+WPUPSTI053|odifyMay ectObjay/emItay||
+WPUPSTI054|oreStay ackTray||
+WPUPSTI055|oedEchay omfray:||
+WPUPSTI056|ableEnay utomaticAay atesUpday||
+WPUPSTI057|iOmnay-DF: %sway||
+WPUPSTI058|DF earingBay: %sway||
+WPUPSTI059|atusStay %02d/%02d %02d:%02d : %sway||
+WPUPSTI060|uelFay empTay: %02.1f�C ||
+WPUPSTI061|uelFay empTay: %sway�F ||
+WPUPSTI062|uelFay oistureMay: %sway%% ||
+WPUPSTI063|aroBay: %0.2f inway gHay||
+WPUPSTI064|etchFay NWS ertAlay||
+WPUPSTI065|acticalTay allCay: %sway||
+WPUPSTI066|ignAssay acticalTay allCay||
+WPUPSTI067|urrentCay angeRay: %dway ilesmay||
+WPUPSTI068|onenay||
+WPUPSTI069|efaultday||
+WPUPSTI070|HAAT||
+WPUPSTI071|omniway||
+WPUPSTI072|angeray||
+WPUPSTI073|BAD PHG||
+WPUPSTI074|BAD SHG||
+WPUPSTI075|DF angeRay||
+WPUPSTI076|oNay ignalsay etectedday||
+WPUPSTI077|etectibleDay ignalsay (aybeMay)||
+WPUPSTI078|etectibleDay ignalsay utbay otnay opyablecay)||
+WPUPSTI079|eakWay ignalsay, arginallymay eadableray||
+WPUPSTI080|oisyNay utbay opyablecay ignalsay||
+WPUPSTI081|omeSay oisenay, easyway otay opycay ignalsay||
+WPUPSTI082|oodGay ignalsay wway/etectibleday oisenay||
+WPUPSTI083|earNay ullfay-ietingquay ignalsay||
+WPUPSTI084|ullFay-ietingquay ignalsay||
+WPUPSTI085|emelyExtray ongstray & ullfay-ietingquay ignalsay||
+WPUPSTI086|BAD BEARING||
+WPUPSTI087|BAD NRQ||
+WPUPSTI088|DF eamwidthBay||
+WPUPSTI089|DF engthLay||
+WPUPSTI090|otNay alidVay||
+WPUPSTI091|angeChay ailTray olorCay||
+WPUPSTI092|earClay DF earingBay||
+WPUPALO001|ALOHA adiusray: %dway %sway||
+WPUPALO002|ationsStay insideway ALOHA irclecay: %dway||
+WPUPALO003| igisDay: %dway||
+WPUPALO004| obilesMay (inway otionmay): %dway||
+WPUPALO005| obilesMay (otherway): %dway||
+WPUPALO006| WX ationsstay: %dway||
+WPUPALO007| omeHay ationsstay: %dway||
+WPUPALO008|astLay alculatedcay %dway %sway %dway %sway agoway.||
+WPUPALO666|ALOHA adiusray otnay alculatedcay etyay||
+STIFCC0001|FCC atabaseDay ookupLay||
+STIFCC0002|RAC atabaseDay ookupLay||
+STIFCC0003|ameNay:||
+STIFCC0004|eetStray:||
+STIFCC0005|ityCay:||
+STIFCC0006|ateStay:||
+STIFCC0007|ipZay:||
+STIFCC0008|asicBay ||
+STIFCC0009|ancedAdvay ||
+STIFCC0010|5 mwpay ||
+STIFCC0011|12 mwpay ||
+STIFCC0100|FCC indexway oldway, ebuildingray||
+STIFCC0101|allsignCay earchSay||
+STIFCC0102|allsignCay otNay oundFay!||
+STIFCC0103|RAC indexway oldway, ebuildingray||
+UMBNDO0001|atway istanceday ofway||
+UNIOP00001|OK||
+UNIOP00002|ancelCay||
+UNIOP00003|oseClay||
+UNIOP00004|ilesmay||
+UNIOP00005|mkay||
+UNIOP00006|eviceDay||
+UNIOP00007|dAday||
+UNIOP00008|eleteDay||
+UNIOP00009|opertiesPray||
+UNIOP00010|owAllay ansmittingTray?||
+UNIOP00011|ivateActay onway artupStay?||
+UNIOP00012|mkay/hway||
+UNIOP00013|hmpay||
+UNIOP00014|�C||
+UNIOP00015|�F||
+UNIOP00016|mmay||
+UNIOP00017|inchway||
+UNIOP00018|mmay/ayday||
+UNIOP00019|inchway/ayday||
+UNIOP00020|mmay/rhay||
+UNIOP00021|inchway/rhay||
+UNIOP00022|mmay/idmay||
+UNIOP00023|inchway/idmay||
+UNIOP00024|egday||
+UNIOP00025|ahPay||
+UNIOP00026|%||
+UNIOP00027|inway gHay||
+UNIOP00028|mmay gHay||
+UNIOP00029|etSay ystemSay ockClay omfray GPS ataDay?||
+UNIOP00030|igipeatDay?||
+UNIOP00031|mway||
+UNIOP00032|yApplay||
+UNIOP00033|esetRay||
+UNIOP00034|inmay||
+UNIOP00035|rhay||
+UNIOP00036|ayday||
+UNIOP00037|endSay ontrolCay-E otay etgay GPS ataday?||
+UNIOP00038|dAday elayDay||
+STCHO00001|ationStay ooserChay||
+WPUPWXA001|xWay ertsAlay||
+WPUPWXA002|xWay ertAlay istLay||
+WPUPCIF001|alledInstay erfacesIntay||
+WPUPCIF002|ooseChay erfaceIntay ypeTay||
+WPUPCAX001|onfigureCay AX.25 TNC||
+WPUPCAX002|AX.25 eviceDay amenay||
+IFDNL00000|oneNay||
+IFDNL00001|erialSay TNC||
+IFDNL00002|erialSay TNC wway/GPS onway away HSP ablecay||
+IFDNL00003|erialSay GPS||
+IFDNL00004|erialSay WX||
+IFDNL00005|ernetIntay erverSay||
+IFDNL00006|AX25 TNC||
+IFDNL00007|etworkedNay GPS (iavay dgpsay)||
+IFDNL00008|etworkedNay WX||
+IFDNL00009|erialSay TNC wway/GPS onway AUX ortpay||
+IFDNL00010|erialSay KISS TNC||
+IFDNL00011|etworkedNay atabaseDay (otNay ementedImplay etYay)||
+IFDNL00012|etworkedNay AGWPE||
+IFDNL00013|erialSay ultiMay-ortPay KISS TNC||
+IFDNL00014|SQL atabaseDay (erimentalExpay)||
+IFDIN00000|%sway %2d %sway %sway %sway||
+IFDIN00001|%sway %2d %sway %sway:%dway %sway||
+IFDIN00002|%sway %2d %sway eviceday %sway %sway||
+IFDIN00003|%sway %2d %sway %sway %sway %sway||
+IFDIN00004|%sway %2d %sway %sway %sway:%dway %sway||
+IFDIN00005|%sway %2d %sway %sway %sway %sway||
+IFDIN00006| DOWN ||
+IFDIN00007| UP ||
+IFDIN00008|ERROR ||
+IFDIN00009|UNKNWN||
+IFPUPCT000|erfaceIntay ontrolCay||
+IFPUPCT001|artStay||
+IFPUPCT002|opStay||
+IFPUPCT003|artStay lAlay||
+IFPUPCT004|opStay lAlay||
+IGPUPCF000|ateIGay ionsOptay||
+IGPUPCF001|isableDay allway ateIGay affictray||
+IGPUPCF002|owAllay RF otay etInay affictray ONLY||
+IGPUPCF003|owAllay RF->etInay andway etInay->RF affictray||
+IGPUPCF004|ateIgay -> RF athPay ||
+WXPUPSI000|WX ationStay||
+WXPUPSI001|WX ationStay ypeTay||
+WXPUPSI002|urrentCay ataDay||
+WXPUPSI003|indWay ourseCay||
+WXPUPSI004|indWay eedSpay||
+WXPUPSI005|indWay ustGay||
+WXPUPSI006|empTay||
+WXPUPSI007|otalTay ainRay||
+WXPUPSI008|oday'sTay ainRay otalTay||
+WXPUPSI009|aroBay||
+WXPUPSI010|umidityHay||
+WXPUPSI011|eetPay osBray ULTIMETER 2000 ypeTay (ataDay oggingLay odeMay)||
+WXPUPSI012|eetPay osBray ULTIMETER II ypeTay||
+WXPUPSI013|eetPay osBray ULTIMETER 2000 ypeTay (acketPay odeMay)||
+WXPUPSI014|urrentCay HR ainRay otTay.||
+WXPUPSI015|astLay 24 ainRay otalTay||
+WXPUPSI016|ualimetricsQay Q-etNay||
+WXPUPSI017|eetPay osBray ULTIMETER 2000 ypeTay (ompleteCay odeMay)||
+WXPUPSI018|ewDay ointPay||
+WXPUPSI019|ighHay indWay||
+WXPUPSI020|indWay illChay||
+WXPUPSI021|eatHay exInday||
+WXPUPSI022|3-rHay aroBay||
+WXPUPSI023|ighHay empTay.||
+WXPUPSI024|owLay empTay.||
+WXPUPSI025|adioRay ackShay WX-200/egonOray ientificScay WM-918||
+WXPUPSI026|avisDay eatherWay onitorMay II/izardWay III/antageVay oPray||
+WXPUPSI027|aLayCrosse WX-23xx||
+WXPUPSI028|avisDay APRS ataDay oggerLay||
+LHPUPNI000|lAlay ationsStay||
+LHPUPNI001|obileMay ationsStay||
+LHPUPNI002|eatherWay ationsStay||
+LHPUPNI003|ocalLay ationsStay (iavay TNC)||
+LHPUPNI004|astLay ationsStay||
+LHPUPNI005|ectsObjay & emsItay||
+LHPUPNI006|nOway ectsObjay & emsItay||
+LHPUPNI010|#||
+LHPUPNI011|allCay ignSay||
+LHPUPNI012|#ackPay||
+LHPUPNI013|osPay imeTay||
+LHPUPNI014|athPay||
+LHPUPNI015|PHG||
+LHPUPNI016|ommentsCay||
+LHPUPNI100|CSE||
+LHPUPNI101|SPD||
+LHPUPNI102|ALT.||
+LHPUPNI103|atLay||
+LHPUPNI104|ongLay||
+LHPUPNI105|#ackPay||
+LHPUPNI106|LSV||
+LHPUPNI107|CFMS||
+LHPUPNI108|DFMS||
+LHPUPNI200|CSE||
+LHPUPNI201|SPD||
+LHPUPNI202|GST||
+LHPUPNI203|empTay||
+LHPUPNI204|umHay||
+LHPUPNI205|aroBay||
+LHPUPNI206|RN-H||
+LHPUPNI207|RNSM||
+LHPUPNI208|RN24||
+LHPUPNI209|atLay/onLay orway UTM||
+PULDNMAT01|owShay ertAlay apsmay aboveway otherway apsmay||
+PULDNMAT02|owShay ertAlay apsmay underway otherway apsmay||
+POPEM00001|ocateLay orErray!||
+POPEM00002|ationStay %sway asway otnay oundfay!||
+POPEM00003|ackingTray orErray!||
+POPEM00004|erfaceIntay orErray!||
+POPEM00005|alidInvay AX.25 ortpay amenay %sway||
+POPEM00006|alidInvay AX.25 ortpay amenay %sway||
+POPEM00007|alidInvay allsigncay %sway||
+POPEM00008|alidInvay AX.25 estinationday allsigncay orway igipeaterday||
+POPEM00009|annotCay openway AX.25 ocketsay, %sway||
+POPEM00010|annotCay indbay AX.25 ocketsay, %sway||
+POPEM00011|annotCay onnectcay otay AX.25 allsigncay, %sway||
+POPEM00012|AX.25 errorway onway outputway ofway UI||
+POPEM00013|AX.25 oblempray ithway axportsway ilefay||
+POPEM00014|AX.25 invalidway ortpay amenay %sway||
+POPEM00015|orErray openingway interfaceway %dway ardHay ailFay||
+POPEM00016|orErray openingway interfaceway %dway imeTay utOay||
+POPEM00017|oNay oremay interfacesway ailableAvay!||
+POPEM00018|ataDay ueryQay - ingleSay essageMay ineLay||
+POPEM00019|ortPay ansmittingtray isway offway orfay ortpay %dway||
+POPEM00020|atabaseDay orErray!||
+POPEM00021|AX.25 upportsay otnay ompiledcay intoway astirXay!||
+POPEM00022|utInpay orErray!||
+POPEM00023|oNay ocationlay amenay ecifiedspay!||
+POPEM00024|ocationLay amenay ecifiedspay isway inway useway!||
+POPEM00025|otNay oundFay!||
+POPEM00026|ackingTray illway ommencecay enwhay itway appearsway||
+POPEM00027|operImpray infoway. omeSay ieldsfay emptyway?||
+POPEM00028|an'tCay openway ilefay||
+POPEM00029|oundFay tIay!||
+POPEM00030|eatherWay ationStay ymbolSay||
+POPEM00031|angedChay otay WX ymbolsay '/'_ay, otherway optionsway: '\'_ay '/'Way andway '\'Way||
+POPEM00032|arningWay: ingUsay ationalNay eatherWay erviceSay ymbolSay!||
+POPEM00033|oNay GPS ataDay!||
+POPEM00034|isablingDay yMay ositionPay TX ilUntay alidVay GPS ataDay!||
+POPEM00035|arningWay||
+POPEM00036|oticeNay||
+POPEM00037|HSP interfaceway esentpray: GPS imingtay ashay eenbay increasedway||
+POPEM00038|ameNay onflictsCay ithWay istingExay ectObjay/emItay/ationStay||
+POPEM00039|egalIllay aracterschay oundfay, ubstitutingsay eriodspay inway eirthay aceplay||
+POPEM00040|ustomCay outgoingway athpay asway ostlay||
+POPEM00041|ocessingPray anotherway ilefay. aitWay away itbay, enthay ytray againway||
+POPEM00042|ectObjay otnay ownedway ybay emay! yTray adoptingway ethay objectway irstfay.||
+POPEM00043|otNay anway ectObjay/emItay!||
+POPEM00044|etchFay induFay ailTray: ailedFay||
+POPEM00045|etchFay induFay ailTray: ompleteCay||
+POPEM00046|erkeleyBay DB eaderhay/aredshay ibrarylay oday NOT atchmay! isablingDay apmay achecay.||
+POPEM00047|obalGlay ansmittray isway DISABLED. ergencyEmay eaconsbay areway NOT oinggay outway!||
+POPEM00048|ergencyEmay eaconBay odeMay!||
+POPEM00049|EMERGENCY BEACON MODE, ansmittingtray everyway 60 econdssay!||
+POPEM00050|erfacesIntay orway ositspay/ansmitstray DISABLED. ergencyEmay eaconsbay areway NOT oinggay outway!||
+POPEM00051|etAltnay isway enabledway (onfigureCay->efaultsDay ialogday)||
+POPEM00052|allsignCay isway EMPTY!||
+POPEM00053|essageMay isway EMPTY!||
+POPEM00054|e'reWay yingtray otay alktay otay ourselvesway!||
+JMLPO00001|apMay isplayDay ookmarksBay||
+JMLPO00002|ivateActay!||
+JMLPO00003|ewNay ameNay:||
+BULMW00001|ulletinsBay||
+BULMW00002|imitLay angeRay otay (0, isway onay imitlay)||
+BULMW00003|angeChay angeRay||
+AMTMW00001|lAlay essageMay afficTray||
+AMTMW00002|imitLay angeRay otay (0, isway onay imitlay)||
+SPCHSTR001|ilometerskay||
+SPCHSTR002|etersmay||
+SPCHSTR003|ilesmay||
+SPCHSTR004|ardsyay||
+SPCHSTR005|%sway, istanceday isway %dway %sway.||
+SPCHSTR006|%sway, istanceday isway %.1f %sway.||
+SPCHSTR007|%sway, istanceday isway %dway %sway %sway %sway.||
+SPCHSTR008|%sway, istanceday isway %.1f %sway %sway %sway.||
+SPCHSTR009|ewNay eatherWay ertAlay||
+SPCHSTR010|ewNay ationStay||
+SPCHSTR011|eardHay, D X, %sway, atway istanceday ofway %.1f %sway||
+SPCHDIRN00|orthnay ofway||
+SPCHDIRS00|outhsay ofway||
+SPCHDIRE00|eastway ofway||
+SPCHDIRW00|estway ofway||
+SPCHDIRNE0|ortheastnay ofway||
+SPCHDIRNW0|orthwestnay ofway||
+SPCHDIRSE0|outheastsay ofway||
+SPCHDIRSW0|outhwestsay ofway||
+SYMSEL0001|electSay ymbolSay||
+SYMSEL0002|imaryPray ymbolSay ableTay||
+SYMSEL0003|econdarySay ymbolSay ableTay||
+PRINT0001|intPray opertiesPray||
+PRINT0002|aperPay izeSay||
+PRINT0003|utoAay-otateRay ageImay||
+PRINT0004|otateRay ageImay 90� CCW||
+PRINT0005|utoAay-aleScay ageImay||
+PRINT0006|aleScay:||
+PRINT0007|orceFay efaultday ackgroundbay olorcay otay itewhay||
+PRINT0008|intPray inway ackBlay andway iteWhay||
+PRINT0016|everseRay olorsCay||
+PRINT0009|ostscriptPay esolutionRay:||
+PRINT0010|eviewPray||
+PRINT0011|intPray otay ileFay||
+PRINT0012|umpingDay imageway otay ilefay...||
+PRINT0013|onvertingCay otay ostscriptPay...||
+PRINT0014|inishedFay eatingcray intpray ilefay||
+PRINT0015|intPray atusStay||
+PRINT1001|irectDay otay:||
+PRINT1002|iaVay eviewerPray:||
+FEATURE001|ameNay:||
+FEATURE002|ateStay/ovincePray:||
+FEATURE003|ountyCay:||
+FEATURE004|apMay uadQay:||
+FEATURE005|ypeTay:||
+FEATURE006|GNIS ileFay:||
+FEATURE007|essAddray:||
+FEATURE008|ityCay:||
+FEATURE009|arkMay estinationDay||
+FEATURE010|ipZay odeCay:||
+FEATURE011|eocodingGay ileFay||
+COORD001|oordinateCay alculatorCay||
+COORD002|alcCay||
+COORD003|alculateCay||
+COORD004|earClay||
+COORD005|UTM||
+COORD006|atitudeLay orway||
+COORD007|ongitudeLay orway||
+COORD008|oneZay||
+COORD009|UTM astingEay||
+COORD010|UTM orthingNay||
+COORD011| ecimalDay egreesDay: ||
+COORD012| egreesDay/ecimalDay inutesMay: ||
+COORD013| egreesDay/inutesMay/ecDay. econdsSay: ||
+COORD014| iversalUnay ansverseTray ercatorMay: ||
+COORD015|ilitaryMay idGray eferenceRay ystemSay: ||
+COORD016| aidenheadMay idGray ocatorLay: ||
+COORD017| ** orrySay, ouryay inputway asway otnay ecognizedray! **||
+COORD018| ** easePlay useway oneway ofway ethay ollowingfay inputway ormatsfay: **||
+SMARTB001|artSmay eaconingBay||
+SMARTB002|ighHay ateRay (ecssay):||
+SMARTB003|ighHay eedSpay (hmpay):||
+SMARTB004|ighHay eedSpay (hkpay):||
+SMARTB005|owLay ateRay (insmay):||
+SMARTB006|owLay eedSpay (hmpay):||
+SMARTB007|owLay eedSpay (hkpay):||
+SMARTB008|inimumMay urnTay (egday):||
+SMARTB009|urnTay opeSlay:||
+SMARTB010|aitWay imeTay (ecssay):||
+SMARTB011|ableEnay artSmayBeaconing(mtay)||
+GAMMA001|ustAdjay ammaGay orrectionCay||
+GAMMA002|ammaGay orrectionCay||
+MAPFONT001|angeChay ontsFay||
+MAPFONT002|ontsFay||
+MAPFONT003|apMay ontFay inyTay||
+MAPFONT004|apMay ontFay allSmay||
+MAPFONT005|apMay ontFay ediumMay||
+MAPFONT006|apMay ontFay argeLay||
+MAPFONT007|apMay ontFay ugeHay||
+MAPFONT008|apMay ontFay orderBay||
+MAPFONT009|enuMay ontFay||
+MAPFONT010|ationStay ontFay||
+MAPFONT011|ATV ID ontFay||
+PULDNDB001|istDay/earingBay atusStay||
+GPS001|GPS ansferTray||
+GPS002|ilenameFay||
+GPS003|electSay olorCay||
+GPS004|edRay||
+GPS005|eenGray||
+GPS006|ackBlay||
+GPS007|iteWhay||
+GPS008|angeOray||
+GPS009|ueBlay||
+GPS010|ellowYay||
+GPS011|ioletVay||
+MAPP001|apMay opertiesPray||
+MAPP002|axMay inMay apMay USGS utoAay||
+MAPP003|oomZay oomZay ayerLay illFay DRG apMay athPay/ilenameFay||
+MAPP004|angeChay ayerLay->||
+MAPP005|illedFay->||
+MAPP006|esYay||
+MAPP007|oNay||
+MAPP008|utomapsAay->||
+MAPP009|axMay oomZay->||
+MAPP010|inMay oomZay->||
+MAPP011|utoAay||
+MAPP012|USGS DRG->||
+TIME001|ayDay||
+TIME002|aysDay||
+TIME003|ourHay||
+TIME004|oursHay||
+TIME005|inuteMay||
+TIME006|inutesMay||
+TIME007|econdSay||
+TIME008|econdsSay||
+CACHE001|apMay ownay achedcay||
+CACHE002|oadingLay achedCay apMay||
+CACHE003|apMay otnay oundfay inway achecay...||
+RANGE001|RANGE SCALE||
+GPSS001|WAAS orway PPS||
+GPSS002|DGPS||
+GPSS003|alidVay SPS||
+GPSS004|alidInvay||
+GPSS005|atsSay/iewVay||
+GPSS006|ixFay||
+GPSS007|!GPS ataday isway olderway anthay 30 econdssay!||
+GPSS008|imulationSay||
+GPSS009|anualMay||
+GPSS010|imatedEstay||
+GPSS011|oatFlay RTK||
+GPSS012|RTK||
+CADPUD001|eaAray ectObjay||
+CADPUD002|eaAray abelLay:||
+CADPUD003|ommentCay:||
+CADPUD004|obabilityPray (%):||
+CADPUD005|OK||
+CADPUD006|CAD ialogDay||
+CADPUD007|owShay/itEday etailsDay||
+CADPUD008|ancelCay||
+CADPUD009|eleteDay CAD objectsway?||
+CADPUD010|eleteDay lAlay||
+CADPUD011|eleteDay electedSay||
+CADPUD012|olidSay||
+CADPUD013|ashedDay||
+CADPUD014|oubleDay ashDay||
+MDATA001|XASTIR apMay ofway %sway (upperway eftlay) otay %sway (owerlay ightray). UTM %dway mway idgray, %sway atumday. ||
+MDATA002|XASTIR apMay ofway %sway (upperway eftlay) otay %sway %sway (owerlay ightray). atLay/ongLay idgray, %sway atumday.||
+MDATA003|XASTIR apMay ofway %sway (upperway eftlay) otay %sway (owerlay ightray). UTM oneszay, %sway atumday.||
+XADBMST001|yMaySQL (atlay/onglay)||
+XADBMST002|ostgreqlPay ithway ostgisPay||
+XADBMST003|yMaySQL (atialspay)||
+XASCHEMA01|astirXay impleSay emaSchay||
+XASCHEMA02|astirXay CAD emaSchay||
+XASCHEMA03|astirXay ullfay emaSchay||
+XASCHEMA04|orldAPRSWay emaSchay||
diff --git a/config/language-PirateEnglish.sys b/config/language-PirateEnglish.sys
new file mode 100644
index 0000000..994c289
--- /dev/null
+++ b/config/language-PirateEnglish.sys
@@ -0,0 +1,1143 @@
+# language-PirateEnglish.sys, translated from language-English.sys
+# Please do not edit this derived file.
+MENUTB0001|Scroll|F|
+MENUTB0002|Gander|V|
+MENUTB0004|Treasure Map|M|
+MENUTB0005|Ship|S|
+MENUTB0006|Dispatch|e|
+MENUTB0010|Grapple|I|
+MENUTB0009|Aid|H|
+PULDNFI001|Provision me' ship|C|
+PULDNFI002|Open Scribble Scroll|O|
+PULDNFI003|Test|T|
+PULDNFI004|Run Away!|x|
+PULDNFI007|Change Debug Level|D|
+PULDNFI010|TNC Scribblin'||
+PULDNFI011|Net Scribblin'||
+PULDNFI012|IGate Scribblin'||
+PULDNFI013|WX Scribblin'||
+PULDNFI014|PNG Etchin's||
+PULDNFI015|Affix t' parchment|P|
+PULDNFI016|KML Etchin's||
+PULDNVI001|Bulletins|B|
+PULDNVI002|Incomin' Data|I|
+PULDNVI003|Mobile Ships|M|
+PULDNVI004|All Ships|A|
+PULDNVI009|Local Ships|S|
+PULDNVI012|Last Ships|L|
+PULDNVI005|Weather Ships|W|
+PULDNVI008|Own Weather Data|D|
+PULDNVI007|Weather Alerts|e|
+PULDNVI011|Dispatch Traffic|T|
+PULDNVI013|Uptime|U|
+PULDNVI014|Program Uptime||
+PULDNVI015|GPS Status||
+PULDNVI016|ALOHA Statistics||
+PULDNCF004|Ship|S|
+PULDNCF001|Defaults|D|
+PULDNCF003|Timin'|T|
+PULDNCF002|Coordinate System|o|
+PULDNCF006|Racket Alarms|A|
+PULDNCF007|Parley|p|
+PULDNCF008|Save Config Now!|C|
+PULDNMP001|Treasure Map Chooser|M|
+PULDNMP012|Treasure Map Display Bookmarks|B|
+PULDNMP014|Locate Treasure Map Feature|F|
+PULDNMP016|Disable Fast Zoom/Pan/Haven||
+PULDNMP013|Disable All Treasure Map||
+PULDNMP002|Enable Auto Treasure Map||
+PULDNMP003|Enable Treasure Map Grid||
+PULDNMP004|Enable Treasure Map Levels||
+PULDNMP010|Enable Treasure Map Labels||
+PULDNMP009|Enable Area Color Fills||
+PULDNMP007|Enable Weather Alerts||
+PULDNMP005|Background Color|C|
+PULDNMP006|Ship Text Style|T|
+PULDNMP026|Icon Outline Style|O|
+PULDNMP011|Mouse Pointer Menu|P|
+PULDNMP008|Treasure Map Intensity|I|
+PULDNMP020|Provision me' ship Tigermap||
+PULDNMP021|Auto Treasure Map - Disable Raster Treasure Map||
+PULDNMP022|Index New Treasure Map on Startup||
+PULDNMP023|Index: Add New Treasure Map|N|
+PULDNMP024|Index: Reindex ALL Treasure Map!|R|
+PULDNMP025|Scribbles||
+PULDNMP015|Xfontsel||
+PULDNMP027|Re-plunder Treasure Map (Not from cache)||
+PULDNMP028|Flush Entire Treasure Map Cache!||
+PULDNMP029|Find Address||
+PULDNMP030|Provision me' ship USGS DRG||
+PULDNMP031|Enable Treasure Map Border||
+MPUPTGR001|Grid||
+MPUPTGR002|Counties||
+MPUPTGR003|City Labels||
+MPUPTGR004|Urban Areas||
+MPUPTGR005|Major Roads||
+MPUPTGR006|Streets||
+MPUPTGR007|Railroads||
+MPUPTGR008|State Labels||
+MPUPTGR009|Interstate Labels||
+MPUPTGR010|US Hwy Labels||
+MPUPTGR011|State Hwy Labels||
+MPUPTGR012|Choose 'yer Weapon! items t' be displayed:||
+MPUPTGR013|Rivers||
+MPUPTGR014|Lakes||
+MPUPTGR015|Airports, Parks, etc||
+MPUPTGR016|Treasure Map Intensity||
+MPUPTGR017|Seven Seas Treasure Map Timeout (sec)||
+MPUPTGR018|Enable Tiger Treasure Map||
+MPUPDRG001|Choose 'yer Weapon! items t' be displayed:||
+MPUPDRG002|Tint Underlyin' Treasure Map (XOR)||
+MPUPDRG003|Black||
+MPUPDRG004|White||
+MPUPDRG005|Blue||
+MPUPDRG006|Red||
+MPUPDRG007|Brown||
+MPUPDRG008|Green||
+MPUPDRG009|Purple||
+MPUPDRG010|Yellow||
+MPUPDRG011|Light Blue||
+MPUPDRG012|Light Red||
+MPUPDRG013|Light Purple||
+MPUPDRG014|Light Gray||
+MPUPDRG015|Light Brown||
+WPUPMCP001|Treasure Map Chooser||
+PULDNMMC01|Clear|C|
+PULDNMMC02|Vector|V|
+PULDNMMC03|250k Topo|2|
+PULDNMMC04|100k Topo|1|
+PULDNMMC05|24k Topo|4|
+PULDNMMC06|Expand Dirs||
+PULDNMMC07|Dirs/Treasure Map Choose 'yer Weapon!ed:||
+PULDNMMC08|Clear Dirs|C
+PULDNMMC09|Choose 'yer Weapon! All|S|
+PULDNMBC01|Gray||
+PULDNMBC02|Misty Rose||
+PULDNMBC03|Navy Blue||
+PULDNMBC04|Steel Blue||
+PULDNMBC05|Med. Sea Green||
+PULDNMBC06|Pale Green||
+PULDNMBC07|Pale Goldenrod||
+PULDNMBC08|Goldenrod Yellow||
+PULDNMBC09|Rosy Brown||
+PULDNMBC10|Fire brick Red||
+PULDNMBC11|White||
+PULDNMBC12|Black||
+PULDNMSL01|Black Border|B|
+PULDNMSL02|Black Shadow|S|
+PULDNMSL03|Text on Black|T|
+PULDNMIO01|Nay Outline|N|
+PULDNMIO02|Black Outline|B|
+PULDNMIO03|Grey Outline|G|
+PULDNMIO04|White Outline|W|
+PULDNOT001|On||
+PULDNOT002|Off||
+PULDNOT003|Short||
+PULDNDP014|Find Ship|F|
+PULDNDP001|Track Ship|T|
+PULDNDP022|Fetch Findu Trail|u|
+PULDNDP032|Filter Data||
+PULDNDP040|Choose 'yer Weapon! None||
+PULDNDP041|Choose 'yer Weapon! Mine||
+PULDNDP042|Choose 'yer Weapon! TNC||
+PULDNDP027|- Choose 'yer Weapon! Direct||
+PULDNDP043|- Choose 'yer Weapon! Via Digi||
+PULDNDP034|Choose 'yer Weapon! Net||
+PULDNDP019|Include Expired Data||
+PULDNDP044|Choose 'yer Weapon! Ships||
+PULDNDP028|- Choose 'yer Weapon! Fixed Ships||
+PULDNDP029|- Choose 'yer Weapon! Movin' Ships||
+PULDNDP030|- Choose 'yer Weapon! WX Ships||
+PULDNDP053| - Choose 'yer Weapon! CWOP WX Ships||
+PULDNDP045|Choose 'yer Weapon! Objects/Items||
+PULDNDP026|- Choose 'yer Weapon! WX Objects/Items||
+PULDNDP039|- Choose 'yer Weapon! Water Gauge Objects/Items||
+PULDNDP031|- Choose 'yer Weapon! Other Objects/Items||
+PULDNDP033|Filter Display||
+PULDNDP010|Display Callsign||
+PULDNDP012|Display Symbol||
+PULDNDP011|- Rotate Symbol||
+PULDNDP007|Display Trail||
+PULDNDP003|Display Course||
+PULDNDP004|Display Speed|S|
+PULDNDP017|- Display Short Speed||
+PULDNDP002|Display Altitude||
+PULDNDP009|Display Weather Info||
+PULDNDP046|- Display Weather Text||
+PULDNDP018|-- Temperature Only||
+PULDNDP047|- Display Wind Barb||
+PULDNDP054|Display Aloha Circle||
+PULDNDP013|Display Positin' Ambiguity||
+PULDNDP008|Display Power/Gain||
+PULDNDP021|- Use Default Power/Gain||
+PULDNDP020|- Display Mobile Power/Gain||
+PULDNDP023|Display DF Attributes||
+PULDNDP123|Display DF Beamwidth||
+PULDNDP223|Display DF Bearin'||
+PULDNDP035|Enable Dead-Reckonin'||
+PULDNDP036|- Display Arc||
+PULDNDP037|- Display Course||
+PULDNDP038|- Display Symbol||
+PULDNDP005|Display Dist/Bearin'||
+PULDNDP024|Display Last Report Age||
+PULDNDP015|Clear All Ships!!!|A|
+PULDNDP016|Clear All Trails!!!|C|
+PULDNDP025|Clear Object/Item History||
+PULDNDP048|Reload Object/Item History||
+PULDNDP049|Clear All Tactical Calls||
+PULDNDP050|Clear Tactical Call History||
+PULDNDP051|Choose 'yer Weapon! Tactical Calls Only||
+PULDNDP052|- Label Trailpoints||
+PULDNDP055|Export all|E|
+PULDNDP056|Export t' KML Scroll||
+PULDNUT001|Enable English Units|E|
+PULDNUT002|Metric|M|
+PULDNMG001|Send Dispatch To|S|
+PULDNMG002|Open Group Dispatchs|O|
+PULDNMG003|Clear All Outgoin' Dispatchs|C|
+PULDQUS001|General Ships Query|G|
+PULDQUS002|IGate Ships Query|I|
+PULDQUS003|WX Ships Query|W|
+PULDNMG004|Modify Auto Reply Dispatch|A|
+PULDNMG005|Enable Auto Reply Dispatch||
+PULDNMG006|Heavenly Body Ack Mode|M|
+PULDNMG007|Show Pendin' Dispatchs|P|
+PULDNTNT04|Grapple Control|C|
+PULDNTNT03|Disable Transmit: ALL||
+PULDNTNT05|Disable Transmit: My Positin'||
+PULDNTNT06|Disable Transmit: Objects/Items||
+PULDNTNT11|Enable Server Ports|P|
+PULDNTNT01|Transmit Now!|T|
+PULDNTNT07|Fetch GPS Track|F|
+PULDNTNT08|Fetch GPS Routes|R|
+PULDNTNT09|Fetch GPS Waypoints|W|
+PULDNTNT10|Fetch Garmin RINO Waypoints|G|
+PULDNHEL01|'bout|A|
+PULDNHEL02|Aid Index|I|
+PULDNHEL03|EMERGENCY BEACON MODE ENABLE|E|
+PULDNHEL04|!!! EMERGENCY BEACON MODE !!!||
+PULDNHEL05|'bout HMS Xastir||
+POPUPMA001|Optin's||
+POPUPMA00c|Center|C|
+POPUPMA015|Ship Info|S|
+POPUPMA002|In|I|
+POPUPMA003|Out|O|
+POPUPMA004|Zoom Level|L|
+POPUPMA005|Level 1|1|
+POPUPMA006|Level 16|6|
+POPUPMA007|Level 64|4|
+POPUPMA008|Level 256|2|
+POPUPMA009|Level 1024|0|
+POPUPMA010|Level 8192|8|
+POPUPMA017|Entire World|E|
+POPUPMA016|Last Treasure Map Pos/Zoom|P|
+POPUPMA018|Object/Item->Create|b|
+POPUPMA019|Object/Item->Modify|M|
+POPUPMA025|Move My Ship Here|H|
+POPUPMA011|Pan up|u|
+POPUPMA012|Pan down|d|
+POPUPMA013|Pan left|l|
+POPUPMA014|Pan right|r|
+POPUPMA020|Measure||
+POPUPMA021|Move||
+POPUPMA022|TrackMe||
+POPUPMA023|Modifiers Found!||
+POPUPMA024|Please turn OFF CapsLock/NumLock/ScrollLock/other modifiers||
+POPUPMA026|Center & Zoom||
+POPUPMA027| Latitude||
+POPUPMA028| Longitude||
+POPUPMA029|Draw CAD Objects||
+POPUPMA030|Draw||
+POPUPMA031|Nay Polygon||
+POPUPMA032|Erase CAD Polygons||
+POPUPMA033|**NOT USED**||
+POPUPMA034|Custom Zoom Level||
+POPUPMA035|10% out||
+POPUPMA036|10% 'n||
+POPUPMA037|Area||
+POPUPMA038|square||
+POPUPMA039|square feet||
+POPUPMA040|square meters||
+POPUPMA041|Bearin'||
+POPUPMA042|degrees||
+POPUPMA043|Modify ambiguous positin'||
+POPUPMA044|Positin' ambiguity be on, yer new positin' may appear t' jump.||
+POPUPMA045|Predefined Objects||
+POPUPMA046|CAD Polygons||
+POPUPMA047|Enable CAD objects||
+POPUPMA048|Enable CAD labels||
+POPUPMA049|Enable CAD comments||
+POPUPMA050|Enable CAD probability||
+POPUPMA051|Enable CAD area size||
+POPUPMA052|sq||
+POPUPMA053|ft||
+POPUPMA054|meters||
+POPUPMA055|mi|
+BBARZM0001|Zoom %s||
+BBARZM0002|Zoom %s Tr||
+BBARSTH001|%d/%d Ships||
+BBARSTA000|%-9s New object!||
+BBARSTA001|%-9s New ship!||
+BBARSTA002|%-9s||# new data (only display the call)
+BBARSTA003|Loadin' Treasure Map...||
+BBARSTA004|Treasure Map Loaded||
+BBARSTA005|Treasure Map Lat/Long Grid On|O|
+BBARSTA006|Treasure Map Lat/Long Grid Off|f|
+BBARSTA007|The use o' Auto Treasure Map, be now ON||
+BBARSTA008|The use o' Auto Treasure Map, be now OFF||
+BBARSTA009|The use o' Treasure Map Levels be now ON||
+BBARSTA010|The use o' Treasure Map Levels be now OFF||
+BBARSTA011|Auto Reply Dispatch OFF!||
+BBARSTA012|Scroll done..||
+BBARSTA013|Openin' GPS Port||
+BBARSTA014|Closin' GPS Port||
+BBARSTA015|Got GPS RMC Strin'||
+BBARSTA016|Got GPS GGA Strin'||
+BBARSTA017|Net disconnected from host||
+BBARSTA018|Net connectin' timed out!||
+BBARSTA019|Lookin' up host %s||
+BBARSTA020|Connected t' %s||
+BBARSTA021|Net Connectin' Failed!||
+BBARSTA022|Could not bind socket!||
+BBARSTA023|Nay IP fer Host!||
+BBARSTA024|Nay Host Specified||
+BBARSTA025|Host found, Connectin' %d||
+BBARSTA026|Waitin' fer GPS data via HSP..||
+BBARSTA027|Clearin' HSP gettin' TNC data..||
+BBARSTA028|Loadin' %s||
+BBARSTA029|Openin' WX Port||
+BBARSTA030|Closin' WX Port||
+BBARSTA031|Lookin' up hostname %d||
+BBARSTA032|Decoded WX Data||
+BBARSTA033|Echo from digipeater||
+BBARSTA034|Loadin' Weather Alert Treasure Map||
+BBARSTA035|Waitin' fer GPS data via AUX..||
+BBARSTA036|Clearin' AUX gettin' TNC data..||
+BBARSTA037|GPS Data Complete||
+BBARSTA038|Positin' change on me ship||
+BBARSTA039|Indexin' %s||
+BBARSTA040|Amateur APRS(tm) Ship %s||
+BBARSTA041|Waitin' fer GPS data..||
+BBARSTA042|Transmittin' objects/items||
+BBARSTA043|Scribblin'||
+BBARSTA044|ALOHA distance be %d%s||
+BBARSTA045|Loadin' symbols...||
+BBARSTA046|Reloadin' symbols...||
+BBARSTA047|Initialize me ship...||
+BBARSTA048|Start grapples...||
+BBARSTA049|Readin' tiles...||
+BBARSTA050|Downloadin' tiles...||
+BBARSTA051|Downloadin' tile %li o' %li||
+WPUPDPD001|Display Packet Data||
+WPUPDPD002|TNC Data only|T|
+WPUPDPD003|Net Data only|N|
+WPUPDPD004|TNC an' Net Data|a|
+WPUPDPD005|TNC||
+WPUPDPD006|NET||
+WPUPDPD007|Ship Capabilities||
+WPUPDPD008|Mine Only||
+WPUPLSP001|Locate Ship||
+WPUPLSP002|Locate Callsign||
+WPUPLSP003|Match Case|C|
+WPUPLSP004|Match Exact|E|
+WPUPLSP005|Locate Now!|N|
+WPUPLSP006|Emergency Locate!||
+WPUPLSP007|FCC/RAC Lookup||
+WPUPCFD001|Provision me' ship Defaults||
+WPUPCFD002|After what interval o' time will a ship be considered auld?||
+WPUPCFD003|15 min|1|
+WPUPCFD004|30 min|3|
+WPUPCFD005|45 min|4|
+WPUPCFD006|1 hr|H|
+WPUPCFD007|90 min|9|
+WPUPCFD008|2 hrs|2|
+WPUPCFD009|After what interval o' time will a ship not be displayed?||
+WPUPCFD010|6 hrs|6|
+WPUPCFD011|12 hrs|o|
+WPUPCFD012|1 Day|D|
+WPUPCFD013|2 Days|y|
+WPUPCFD014|1 Week|W|
+WPUPCFD015|Transmit Ship Optin'||
+WPUPCFD016|Fixed Ship|F|
+WPUPCFD017|Mobile Ship w/local time|l|
+WPUPCFD018|Mobile Ship w/Zulu date-time|Z|
+WPUPCFD019|Mobile Ship w/Zulu time-seconds|u|
+WPUPCFD021|Ship Positin' w/weather|S|
+WPUPCFD022|Ship Positin', Zulu date-time, an' weather|t|
+WPUPCFD023|Transmit Raw WX data?|R|
+WPUPCFD024|Transmit scrawny objects/items?|C|
+WPUPCFD025|Activate Alternate net?|A|
+WPUPCFD026|Send positin' reports at what intervals?||
+WPUPCFD027|Pop up new bulletins||
+WPUPCFD028|Warn if Modifier Keys||
+WPUPCFD029|Gander zero-distance bulletins||
+WPUPCFD030|Disable Posit Dupe-Checks||
+WPUPCFD031|Load predefined objects from scroll||
+WPUPCFD032|My trails 'n one color||
+WPUPCFD033|ALTNET:||
+WPUPCFTM01|Provision me' ship Timin'||
+WPUPCFTM02|Posit TX Interval (min)||
+WPUPCFTM03|Ship Ghostin' Time (min)||
+WPUPCFTM04|Object/Item Max TX Interval (min)||
+WPUPCFTM05|Ship Clear Time (hours)||
+WPUPCFTM06|GPS Check Interval (sec)||
+WPUPCFTM07|Ship Delete Time (days)||
+WPUPCFTM08|Dead-Reckonin' Timeout (min)||
+WPUPCFTM09|Serial Inter-Char Delay (ms)||
+WPUPCFTM10|New Track Time (min)||
+WPUPCFTM11|New Track Interval (degrees)||
+WPUPCFTM12|RINO -> Objects Interval (min), 0 = Disabled||
+WPUPCFTM13|Etchin' Interval (min)||
+WPUPCFC001|Provision me' ship Coordinate System||
+WPUPCFC002|Choose 'yer Weapon! Coordinate System||
+WPUPCFC003|dd.ddddd|d|
+WPUPCFC004|dd mm.mmm|m|
+WPUPCFC005|dd mm ss.s|s|
+WPUPCFC006|UTM|U|
+WPUPCFC007|USNG/MGRS2||
+WPUPCFC008|UTM w/special zones||
+WPUPCFG001|Provision me' ship GPS||
+WPUPCFG003|Stand alone GPS port||
+WPUPCFG002|Use GPS Positin'?||
+WPUPCFG004|GPS Optin's||
+WPUPCFG005|Stand-alone GPS||
+WPUPCFG006|TNC Connected GPS (HSP Cable)||
+WPUPCFG007|TNC Connected GPS usin' CTL-E||
+WPUPCFG008|GPS Time (Sample every)||
+WPUPCFG009|5 sec||
+WPUPCFG010|15 sec||
+WPUPCFG011|30 sec||
+WPUPCFG012|1 min||
+WPUPCFG013|2 min||
+WPUPCFG014|5 min||
+WPUPCFG015|10 min||
+WPUPCFG016|Network Connected GPS||
+WPUPCFG017|GPSD Host||
+WPUPCFG018|GPSD Port||
+WPUPCFG019|Network GPS via GPSD||
+WPUPCFG020|Reconnect on failure?||
+WPUPCFG021|Network Connected WX||
+WPUPCFG022|WX Host||
+WPUPCFG023|WX Port||
+WPUPCFT001|Provision me' ship TNC||
+WPUPCFT002|Use TNC?||
+WPUPCFT003|TNC Port||
+WPUPCFT004|Port Settin's||
+WPUPCFT005|300 bps||
+WPUPCFT006|1200 bps||
+WPUPCFT007|2400 bps||
+WPUPCFT008|4800 bps||
+WPUPCFT009|9600 bps||
+WPUPCFT010|19200 bps||
+WPUPCFT011|UnProto Paths||
+WPUPCFT012|Path 1: %s via ||
+WPUPCFT013|Path 2: %s via ||
+WPUPCFT014|Path 3: %s via ||
+WPUPCFT015|Port Style||
+WPUPCFT016|8,N,1||
+WPUPCFT017|7,E,1||
+WPUPCFT018|7,O,1||
+WPUPCFT019|38400 bps||
+WPUPCFT020|57600 bps||
+WPUPCFT021|115200 bps||
+WPUPCFT022|230400 bps||
+WPUPCFT023|Provision me' ship TNC w/HSP GPS||
+WPUPCFT024|Data Type||
+WPUPCFT025|Auto detect||
+WPUPCFT026|Binary Type||
+WPUPCFT027|ASCII Type||
+WPUPCFT028|Provision me' ship TNC w/AUX GPS||
+WPUPCFT029|Provision me' ship TNC w/INVALID ENUM||
+WPUPCFT030|Provision me' ship KISS TNC||
+WPUPCFT031|TNC Configuratin' Scrolls||
+WPUPCFT032|TNC Setup Scrollname||
+WPUPCFT033|TNC Shutdown Scrollname||
+WPUPCFT034|KISS Parameters||
+WPUPCFT035|TXDelay (10 ms units)||
+WPUPCFT036|Persistence (0 t' 255)||
+WPUPCFT037|SlotTime (10 ms units)||
+WPUPCFT038|TxTail (10 ms units)||
+WPUPCFT039|Full Duplex||
+WPUPCFT040|Provision me' ship Multi-Port KISS TNC||
+WPUPCFT041|Radio Port||
+WPUPCFT042|Grapple Properties: Dubious UNPROTO Path!||
+WPUPCFT043|Please consider a shorter path such as WIDE2-2 or WIDE1-1,WIDE2-2||
+WPUPCFT044|Grapple Properties: Dubious IGATE Path!||
+WPUPCFT045|Transmittin' w/Dubious UNPROTO Path!||
+WPUPCFT046|Transmittin' w/Dubious IGATE Path!||
+WPUPCFT047|Init KISS-mode on startup||
+WPUPCFWX01|Provision me' ship WX Port||
+WPUPCFWX02|Weather Ship device||
+WPUPCFWX03|Rain Gauge Correctin' (Global Settin')||
+WPUPCFWX04|.1 inch/2.5mm||
+WPUPCFWX05|.01 inch/.25mm||
+WPUPCFWX06|.1mm||
+WPUPCFWX07|Nay Correctin'||
+WPUPCFS001|Provision me' ship Ship||
+WPUPCFS002|Callsign||
+WPUPCFS003|LAT||
+WPUPCFS004|deg||
+WPUPCFS005|min||
+WPUPCFS006|(N/S)||
+WPUPCFS007|LONG||
+WPUPCFS008|(E/W)||
+WPUPCFS009|Ship Symbol||
+WPUPCFS010|Group/overlay||
+WPUPCFS011|Symbol||
+WPUPCFS028|Choose 'yer Weapon!||
+WPUPCFS012|Power - Height (HAAT) - Gain - Directivity||
+WPUPCFS013|Disable PHG||
+WPUPCFS014|Antenna Height||
+WPUPCFS015|Antenna Gain||
+WPUPCFS016|Omni||
+WPUPCFS017|Comment:||
+WPUPCFS018|Positin' Ambiguity||
+WPUPCFS019|None||
+WPUPCFS020|.11 miles||
+WPUPCFS021|1.15 miles||
+WPUPCFS022|11.51 miles||
+WPUPCFS023|69.09 miles||
+WPUPCFS024|.18 kilometres||
+WPUPCFS025|1.85 kilometres||
+WPUPCFS026|18.53 kilometres||
+WPUPCFS027|111.19 kilometres||
+WPUPCFS029|Send scrawny posits|C|
+POPUPOB001|Object/Item||
+POPUPOB002|Name:||
+POPUPOB003|Create New Object||
+POPUPOB004|Delete Object||
+POPUPOB005|Modify Object||
+POPUPOB006|Create New Item||
+POPUPOB007|Area Object||
+POPUPOB008|Area Object||
+POPUPOB009|Bright Color||
+POPUPOB010|Color-Fill||
+POPUPOB011|Circle||
+POPUPOB012|Line-Right '/'||
+POPUPOB013|Line-Left '\'||
+POPUPOB014|Triangle||
+POPUPOB015|Rectangle||
+POPUPOB016|Black||
+POPUPOB017|Blue||
+POPUPOB018|Green||
+POPUPOB019|Cyan||
+POPUPOB020|Red||
+POPUPOB021|Violet||
+POPUPOB022|Yellow||
+POPUPOB023|Grey||
+POPUPOB024|Offset Up:||
+POPUPOB025|Offset Left (Except '/'):||
+POPUPOB026|Corridor:||
+POPUPOB027|Generic Optin's||
+POPUPOB028|Locatin'||
+POPUPOB029|Signpost||
+POPUPOB030|Signpost Text||
+POPUPOB031|Signpost Object||
+POPUPOB032|Enable Compression||
+POPUPOB033|Delete Item||
+POPUPOB034|Modify Item||
+POPUPOB035|Altitude (ft):||
+POPUPOB036|Speed (knots):||
+POPUPOB037|Course:||
+POPUPOB038|DF Object||
+POPUPOB039|Signal - Height(HAAT) - Gain - Directivity||
+POPUPOB040|Beam Width - Bearin'||
+POPUPOB041|Omni Antenna||
+POPUPOB042|Beam Antenna||
+POPUPOB043|Useless||
+POPUPOB044|Adopt Object||
+POPUPOB045|Adopt Item||
+POPUPOB046|DF Bearin':||
+POPUPOB047|Probability Circles||
+POPUPOB048|Treasure Map Gander Object||
+POPUPOB049|Min (mi):||
+POPUPOB050|Max (mi):||
+WPUPCFI001|Provision me' ship Seven Seas||
+WPUPCFI002|Host ||
+WPUPCFI003|Port ||
+WPUPCFI004|(Secondary hosts)||
+WPUPCFI005|Host1||
+WPUPCFI006|Port1||
+WPUPCFI007|Host2||
+WPUPCFI008|Port2||
+WPUPCFI009|Pass-code||
+WPUPCFI010|(Leave Blank if None)||
+WPUPCFI011|Reconnect on NET failure?||
+WPUPCFI012|Run as an I-Gate?||
+WPUPCFI013|Broadcast dispatchs via TNC when an I-Gate?||
+WPUPCFI014|Scribble I-Gate Transactin's?||
+WPUPCFI015|Filter Parameters||
+WPUPCFID01|Provision me' ship Database (TBD)||
+WPUPCFID02|Host ||
+WPUPCFID03|Port ||
+WPUPCFID04|(Secondary hosts)||
+WPUPCFID05|Host1||
+WPUPCFID06|Port1||
+WPUPCFID07|Host2||
+WPUPCFID08|Port2||
+WPUPCFID09|Pass-code||
+WPUPCFID10|(Leave Blank if None)||
+WPUPCFID11|Reconnect on NET failure?||
+WPUPCFID12|Run as an I-Gate?||
+WPUPCFID13|Broadcast dispatchs via TNC when an I-Gate?||
+WPUPCFID14|Scribble I-Gate Transactin's?||
+WPUPCFID15|Filter Parameters||
+WPUPCFIA01|Provision me' ship AGWPE||
+WPUPCFIA02|Host ||
+WPUPCFIA03|Port ||
+WPUPCFIA04|(Secondary hosts)||
+WPUPCFIA05|Host1||
+WPUPCFIA06|Port1||
+WPUPCFIA07|Host2||
+WPUPCFIA08|Port2||
+WPUPCFIA09|Pass-code||
+WPUPCFIA10|(Leave Blank if None)||
+WPUPCFIA11|Reconnect on NET failure?||
+WPUPCFIA12|Run as an I-Gate?||
+WPUPCFIA13|Broadcast dispatchs via TNC when an I-Gate?||
+WPUPCFIA14|Scribble I-Gate Transactin's?||
+WPUPCFIA15|Transmit RadioPort||
+WPUPCFA001|Provision me' ship Racket Alarms||
+WPUPCFA002|Racket Play Command||
+WPUPCFA003|Alarm on||
+WPUPCFA004|Racket scroll t' Play||
+WPUPCFA005|New Ship||
+WPUPCFA006|New Dispatch||
+WPUPCFA007|Proximity||
+WPUPCFA008|Band Openin'||
+WPUPCFA009|Minimum Distance||
+WPUPCFA010|Maximum Distance||
+WPUPCFA011|Weather Alert||
+WPUPCFSP01|Provision me' ship Parley||
+WPUPCFSP02|Parley Output on:||
+WPUPCFSP03|New Ship||
+WPUPCFSP04|New Dispatch Alert||
+WPUPCFSP05|New Dispatch Body||
+WPUPCFSP06|Proximity Alert||
+WPUPCFSP07|Band Openin'||
+WPUPCFSP08|New Weather Alert||
+WPUPCFSP09|Tracked Ship Proximity Alert||
+WPUPTSP001|Track Ship||
+WPUPTSP002|Track Callsign||
+WPUPTSP003|Match Case||
+WPUPTSP004|Match Exact||
+WPUPTSP005|Track Now!||
+WPUPTSP006|Clear Trackin'||
+WPUPTSP007|Plunder Trail||
+WPUPTSP008|Callsign||
+WPUPTSP009|Start Trail (hrs ago)||
+WPUPTSP010|Trail Length (hrs)||
+WPUPMSB001|Send Dispatch Box %d||
+WPUPMSB002|Send Group Dispatch Box %d||
+WPUPMSB003|Ship's Call:||
+WPUPMSB004|Group's Call:||
+WPUPMSB005|New/Refresh Call||
+WPUPMSB006|New Group||
+WPUPMSB007|Clear Msg History||
+WPUPMSB008|Dispatch:||
+WPUPMSB009|Send Now!||
+WPUPMSB010|Path:||
+WPUPMSB011|Nay Pendin' Msgs||
+WPUPMSB012|Kick Timer||
+WPUPMSB013|seq||
+WPUPMSB014|type||
+WPUPMSB015|Broadcast||
+WPUPMSB016|*TIMEOUT*||
+WPUPMSB017|*CANCELLED*||
+WPUPMSB018|*REJECTED*||
+WPUPMSB019|Change Path||
+WPUPMSB020|Use Default Path(s)||
+WPUPMSB021|Direct (Nay path)||
+WPUPMSB022|Reverse Path (Hint):||
+WPUPARM001|Change Auto Reply||
+WPUPARM002|Reply:||
+WPUPHPI001|Aid Index||
+WPUPHPI002|Gander||
+WPUPSTI000|Object from: %s||
+WPUPSTI001|Ship Info||
+WPUPSTI002|Send Dispatch||
+WPUPSTI003|Scour FCC Database||
+WPUPSTI004|Scour RAC Database||
+WPUPSTI005|Packets received: %d Last Heard: ||
+WPUPSTI006|Heard via th' TNC on device %d, ||
+WPUPSTI007|Heard ||
+WPUPSTI008|last via Local||
+WPUPSTI009|last via TNC on device %d||
+WPUPSTI010|last via Seven Seas on device %d||
+WPUPSTI011|last via Scroll||
+WPUPSTI012|last via Unknown||
+WPUPSTI013|, an' has moved||
+WPUPSTI014|Current Power Gain:||
+WPUPSTI016|Altitude: %.0f%s ||
+WPUPSTI017|Course: %s� ||
+WPUPSTI018|Speed: %.1f km/h||
+WPUPSTI019|Speed: %.1f mph||
+WPUPSTI020|%0.1f miles||
+WPUPSTI021|%0.1f km||
+WPUPSTI022|Distance from me ship: %s Bearin' from me ship: %s||
+WPUPSTI023|Last Positin': ||
+WPUPSTI024|Weather Data %c:%s||
+WPUPSTI025|Wind Course: %s� Speed: %03d km/h||
+WPUPSTI026|Wind Course: %s� Speed: %s mph||
+WPUPSTI027| Gust: %03d km/h||
+WPUPSTI028| Gust: %s mph||
+WPUPSTI029|Temperature: %02.1f�C ||
+WPUPSTI030|Temperature: %s�F ||
+WPUPSTI031|Humidity: %s%% ||
+WPUPSTI032| Humidex: %02.1f�C ||
+WPUPSTI033|Baro: %s hPa||
+WPUPSTI034|Snow: %0.1f (cm/24h)||
+WPUPSTI035|Snow: %0.0f (inch/24h)||
+WPUPSTI036|Rain: ||
+WPUPSTI037|%0.2f (mm/h) ||
+WPUPSTI038|%0.2f (inch/h) ||
+WPUPSTI039|%0.2f (mm/day) ||
+WPUPSTI040|%0.2f (inch/day) ||
+WPUPSTI041|%0.2f (mm/since midnight)||
+WPUPSTI042|%0.2f (inch/since midnight)||
+WPUPSTI043|Data path: %s||
+WPUPSTI044|Comment %02d/%02d %02d:%02d : %s||
+WPUPSTI045|Clear Track||
+WPUPSTI046|Total Rain: ||
+WPUPSTI047|%0.2f (mm)||
+WPUPSTI048|%0.2f (inch)||
+WPUPSTI049|Trace Query||
+WPUPSTI050|Un-Acked Dispatchs Query||
+WPUPSTI051|Direct Ships Query||
+WPUPSTI052|Ship Version Query||
+WPUPSTI053|Modify Object/Item||
+WPUPSTI054|Store Track||
+WPUPSTI055|Echoed from:||
+WPUPSTI056|Enable Automatic Updates||
+WPUPSTI057|Omni-DF: %s||
+WPUPSTI058|DF Bearin': %s||
+WPUPSTI059|Status %02d/%02d %02d:%02d : %s||
+WPUPSTI060|Fuel Temp: %02.1f�C ||
+WPUPSTI061|Fuel Temp: %s�F ||
+WPUPSTI062|Fuel Moisture: %s%% ||
+WPUPSTI063|Baro: %0.2f 'n Hg||
+WPUPSTI064|Fetch NWS Alert||
+WPUPSTI065|Tactical Call: %s||
+WPUPSTI066|Assign Tactical Call||
+WPUPSTI067|Current Range: %d miles||
+WPUPSTI068|none||
+WPUPSTI069|default||
+WPUPSTI070|HAAT||
+WPUPSTI071|omni||
+WPUPSTI072|range||
+WPUPSTI073|BAD PHG||
+WPUPSTI074|BAD SHG||
+WPUPSTI075|DF Range||
+WPUPSTI076|Nay signal detected||
+WPUPSTI077|Detectible signal (Maybe)||
+WPUPSTI078|Detectible signal but not copyable)||
+WPUPSTI079|Weak signal, marginally readable||
+WPUPSTI080|Noisy but copyable signal||
+WPUPSTI081|Some noise, easy t' copy signal||
+WPUPSTI082|Good signal w/detectible noise||
+WPUPSTI083|Near full-quietin' signal||
+WPUPSTI084|Full-quietin' signal||
+WPUPSTI085|Extremely strong & full-quietin' signal||
+WPUPSTI086|BAD BEARING||
+WPUPSTI087|BAD NRQ||
+WPUPSTI088|DF Beamwidth||
+WPUPSTI089|DF Length||
+WPUPSTI090|Not Valid||
+WPUPSTI091|Change Trail Color||
+WPUPSTI092|Clear DF Bearin'||
+WPUPALO001|ALOHA radius: %d %s||
+WPUPALO002|Ships inside ALOHA circle: %d||
+WPUPALO003| Digis: %d||
+WPUPALO004| Mobiles ('n motin'): %d||
+WPUPALO005| Mobiles (other): %d||
+WPUPALO006| WX ships: %d||
+WPUPALO007| Haven ships: %d||
+WPUPALO008|Last calculated %d %s %d %s ago.||
+WPUPALO666|ALOHA radius not calculated yet||
+STIFCC0001|FCC Database Lookup||
+STIFCC0002|RAC Database Lookup||
+STIFCC0003|Name:||
+STIFCC0004|Street:||
+STIFCC0005|City:||
+STIFCC0006|State:||
+STIFCC0007|Zip:||
+STIFCC0008|Basic ||
+STIFCC0009|Advanced ||
+STIFCC0010|5 wpm ||
+STIFCC0011|12 wpm ||
+STIFCC0100|FCC index auld, rebuildin'||
+STIFCC0101|Callsign Scour||
+STIFCC0102|Callsign Not Found!||
+STIFCC0103|RAC index auld, rebuildin'||
+UMBNDO0001|at distance o'||
+UNIOP00001|Aye||
+UNIOP00002|Nay||
+UNIOP00003|Nay||
+UNIOP00004|miles||
+UNIOP00005|km||
+UNIOP00006|Device||
+UNIOP00007|Add||
+UNIOP00008|Delete||
+UNIOP00009|Properties||
+UNIOP00010|Allow Transmittin'?||
+UNIOP00011|Activate on Startup?||
+UNIOP00012|km/h||
+UNIOP00013|mph||
+UNIOP00014|�C||
+UNIOP00015|�F||
+UNIOP00016|mm||
+UNIOP00017|inch||
+UNIOP00018|mm/day||
+UNIOP00019|inch/day||
+UNIOP00020|mm/hr||
+UNIOP00021|inch/hr||
+UNIOP00022|mm/mid||
+UNIOP00023|inch/mid||
+UNIOP00024|deg||
+UNIOP00025|hPa||
+UNIOP00026|%||
+UNIOP00027|'n Hg||
+UNIOP00028|mm Hg||
+UNIOP00029|Set System Clock from GPS Data?||
+UNIOP00030|Digipeat?||
+UNIOP00031|m||
+UNIOP00032|Apply||
+UNIOP00033|Reset||
+UNIOP00034|min||
+UNIOP00035|hr||
+UNIOP00036|day||
+UNIOP00037|Send Control-E t' get GPS data?||
+UNIOP00038|Add Delay||
+STCHO00001|Ship Chooser||
+WPUPWXA001|Wx Alerts||
+WPUPWXA002|Wx Alert List||
+WPUPCIF001|Installed Grapples||
+WPUPCIF002|Choose Grapple Type||
+WPUPCAX001|Provision me' ship AX.25 TNC||
+WPUPCAX002|AX.25 Device name||
+IFDNL00000|None||
+IFDNL00001|Serial TNC||
+IFDNL00002|Serial TNC w/GPS on a HSP cable||
+IFDNL00003|Serial GPS||
+IFDNL00004|Serial WX||
+IFDNL00005|Seven Seas Server||
+IFDNL00006|AX25 TNC||
+IFDNL00007|Networked GPS (via gpsd)||
+IFDNL00008|Networked WX||
+IFDNL00009|Serial TNC w/GPS on AUX port||
+IFDNL00010|Serial KISS TNC||
+IFDNL00011|Networked Database (Not Implemented Yet)||
+IFDNL00012|Networked AGWPE||
+IFDNL00013|Serial Multi-Port KISS TNC||
+IFDNL00014|SQL Database (Experimental)||
+IFDIN00000|%s %2d %s %s %s||
+IFDIN00001|%s %2d %s %s:%d %s||
+IFDIN00002|%s %2d %s device %s %s||
+IFDIN00003|%s %2d %s %s %s %s||
+IFDIN00004|%s %2d %s %s %s:%d %s||
+IFDIN00005|%s %2d %s %s %s %s||
+IFDIN00006| DOWN ||
+IFDIN00007| UP ||
+IFDIN00008|ERROR ||
+IFDIN00009|UNKNWN||
+IFPUPCT000|Grapple Control||
+IFPUPCT001|Start||
+IFPUPCT002|Stop||
+IFPUPCT003|Start All||
+IFPUPCT004|Stop All||
+IGPUPCF000|IGate Optin's||
+IGPUPCF001|Disable all IGate traffic||
+IGPUPCF002|Allow RF t' Inet traffic ONLY||
+IGPUPCF003|Allow RF->Inet an' Inet->RF traffic||
+IGPUPCF004|Igate -> RF Path ||
+WXPUPSI000|WX Ship||
+WXPUPSI001|WX Ship Type||
+WXPUPSI002|Current Data||
+WXPUPSI003|Wind Course||
+WXPUPSI004|Wind Speed||
+WXPUPSI005|Wind Gust||
+WXPUPSI006|Temp||
+WXPUPSI007|Total Rain||
+WXPUPSI008|Today's Rain Total||
+WXPUPSI009|Baro||
+WXPUPSI010|Humidity||
+WXPUPSI011|Peet Bros ULTIMETER 2000 Type (Data Scribblin' Mode)||
+WXPUPSI012|Peet Bros ULTIMETER II Type||
+WXPUPSI013|Peet Bros ULTIMETER 2000 Type (Packet Mode)||
+WXPUPSI014|Current HR Rain Tot.||
+WXPUPSI015|Last 24 Rain Total||
+WXPUPSI016|Qualimetrics Q-Net||
+WXPUPSI017|Peet Bros ULTIMETER 2000 Type (Complete Mode)||
+WXPUPSI018|Dew Point||
+WXPUPSI019|High Wind||
+WXPUPSI020|Wind Chill||
+WXPUPSI021|Heat Index||
+WXPUPSI022|3-Hr Baro||
+WXPUPSI023|High Temp.||
+WXPUPSI024|Low Temp.||
+WXPUPSI025|Radio Shack WX-200/Oregon Scientific WM-918||
+WXPUPSI026|Davis Weather Monitor II/Wizard III/Vantage Pro||
+WXPUPSI027|LaCrosse WX-23xx||
+WXPUPSI028|Davis APRS Data Scribbleger||
+LHPUPNI000|All Ships||
+LHPUPNI001|Mobile Ships||
+LHPUPNI002|Weather Ships||
+LHPUPNI003|Local Ships (via TNC)||
+LHPUPNI004|Last Ships||
+LHPUPNI005|Objects & Items||
+LHPUPNI006|Own Objects & Items||
+LHPUPNI010|#||
+LHPUPNI011|Call Sign||
+LHPUPNI012|#Pack||
+LHPUPNI013|Pos Time||
+LHPUPNI014|Path||
+LHPUPNI015|PHG||
+LHPUPNI016|Comments||
+LHPUPNI100|CSE||
+LHPUPNI101|SPD||
+LHPUPNI102|ALT.||
+LHPUPNI103|Lat||
+LHPUPNI104|Long||
+LHPUPNI105|#Pack||
+LHPUPNI106|LSV||
+LHPUPNI107|CFMS||
+LHPUPNI108|DFMS||
+LHPUPNI200|CSE||
+LHPUPNI201|SPD||
+LHPUPNI202|GST||
+LHPUPNI203|Temp||
+LHPUPNI204|Hum||
+LHPUPNI205|Baro||
+LHPUPNI206|RN-H||
+LHPUPNI207|RNSM||
+LHPUPNI208|RN24||
+LHPUPNI209|Lat/Lon or UTM||
+PULDNMAT01|Show Alert Treasure Map above other Treasure Map||
+PULDNMAT02|Show Alert Treasure Map under other Treasure Map||
+POPEM00001|Locate Error!||
+POPEM00002|Ship %s were bein' not found!||
+POPEM00003|Trackin' Error!||
+POPEM00004|Grapple Error!||
+POPEM00005|Invalid AX.25 port name %s||
+POPEM00006|Invalid AX.25 port name %s||
+POPEM00007|Invalid callsign %s||
+POPEM00008|Invalid AX.25 destinatin' callsign or digipeater||
+POPEM00009|Cannot open AX.25 socket, %s||
+POPEM00010|Cannot bind AX.25 socket, %s||
+POPEM00011|Cannot connect t' AX.25 callsign, %s||
+POPEM00012|AX.25 error on output o' UI||
+POPEM00013|AX.25 problem with axports scroll||
+POPEM00014|AX.25 invalid port name %s||
+POPEM00015|Error openin' grapple %d Hard Fail||
+POPEM00016|Error openin' grapple %d Time Out||
+POPEM00017|Nay more grapples Available!||
+POPEM00018|Data Query - Single Dispatch Line||
+POPEM00019|Port transmittin' be off fer port %d||
+POPEM00020|Database Error!||
+POPEM00021|AX.25 support not compiled into HMS Xastir!||
+POPEM00022|Input Error!||
+POPEM00023|Nay locatin' name specified!||
+POPEM00024|Locatin' name specified be 'n use!||
+POPEM00025|Not Found!||
+POPEM00026|Trackin' will commence when it appears||
+POPEM00027|Improper info. Some fields empty?||
+POPEM00028|Can't open scroll||
+POPEM00029|Found It!||
+POPEM00030|Weather Ship Symbol||
+POPEM00031|Changed t' WX symbol '/_', other optin's: '\_' '/W' an' '\W'||
+POPEM00032|Warnin': Usin' National Weather Service Symbol!||
+POPEM00033|Nay GPS Data!||
+POPEM00034|Disablin' My Positin' TX Until Valid GPS Data!||
+POPEM00035|Warnin'||
+POPEM00036|Notice||
+POPEM00037|HSP grapple present: GPS timin' has been increased||
+POPEM00038|Name Conflicts With Existin' Object/Item/Ship||
+POPEM00039|Illegal characters found, substitutin' periods 'n their place||
+POPEM00040|Custom outgoin' path were bein' lost||
+POPEM00041|Processin' another scroll. Wait a bit, then try again||
+POPEM00042|Object not owned by me! Try adoptin' th' object first.||
+POPEM00043|Not an Object/Item!||
+POPEM00044|Fetch Findu Trail: Failed||
+POPEM00045|Fetch Findu Trail: Complete||
+POPEM00046|Berkeley DB header/shared library do NOT match! Disablin' Treasure Map cache.||
+POPEM00047|Global transmit be DISABLED. Emergency beacons be NOT goin' out!||
+POPEM00048|Emergency Beacon Mode!||
+POPEM00049|EMERGENCY BEACON MODE, transmittin' every 60 seconds!||
+POPEM00050|Grapples or posits/transmits DISABLED. Emergency beacons be NOT goin' out!||
+POPEM00051|Altnet be enabled (Provision me' ship->Defaults dialog)||
+POPEM00052|Callsign be EMPTY!||
+POPEM00053|Dispatch be EMPTY!||
+POPEM00054|We're tryin' t' talk t' ourselves!||
+JMLPO00001|Treasure Map Display Bookmarks||
+JMLPO00002|Activate!||
+JMLPO00003|New Name:||
+BULMW00001|Bulletins||
+BULMW00002|Limit Range t' (0, be nay limit)||
+BULMW00003|Change Range||
+AMTMW00001|All Dispatch Traffic||
+AMTMW00002|Limit Range t' (0, be nay limit)||
+SPCHSTR001|kilometers||
+SPCHSTR002|meters||
+SPCHSTR003|miles||
+SPCHSTR004|yards||
+SPCHSTR005|%s, distance be %d %s.||
+SPCHSTR006|%s, distance be %.1f %s.||
+SPCHSTR007|%s, distance be %d %s %s %s.||
+SPCHSTR008|%s, distance be %.1f %s %s %s.||
+SPCHSTR009|New Weather Alert||
+SPCHSTR010|New Ship||
+SPCHSTR011|Heard, D X, %s, at distance o' %.1f %s||
+SPCHDIRN00|north o'||
+SPCHDIRS00|south o'||
+SPCHDIRE00|east o'||
+SPCHDIRW00|west o'||
+SPCHDIRNE0|northeast o'||
+SPCHDIRNW0|northwest o'||
+SPCHDIRSE0|southeast o'||
+SPCHDIRSW0|southwest o'||
+SYMSEL0001|Choose 'yer Weapon! Symbol||
+SYMSEL0002|Primary Symbol Table||
+SYMSEL0003|Secondary Symbol Table||
+PRINT0001|Affix t' parchment Properties||
+PRINT0002|Paper Size||
+PRINT0003|Auto-Rotate Image||
+PRINT0004|Rotate Image 90� CCW||
+PRINT0005|Auto-Scale Image||
+PRINT0006|Scale:||
+PRINT0007|Force default background color t' white||
+PRINT0008|Affix t' parchment 'n Black an' White||
+PRINT0016|Reverse Colors||
+PRINT0009|Postscript Resolutin':||
+PRINT0010|Preview||
+PRINT0011|Affix t' parchment t' Scroll||
+PRINT0012|Dumpin' image t' scroll...||
+PRINT0013|Convertin' t' Postscript...||
+PRINT0014|Finished creatin' affix t' parchment scroll||
+PRINT0015|Affix t' parchment Status||
+PRINT1001|Direct t':||
+PRINT1002|Via Previewer:||
+FEATURE001|Name:||
+FEATURE002|State/Province:||
+FEATURE003|County:||
+FEATURE004|Treasure Map Quad:||
+FEATURE005|Type:||
+FEATURE006|GNIS Scroll:||
+FEATURE007|Address:||
+FEATURE008|City:||
+FEATURE009|Mark Destinatin'||
+FEATURE010|Zip Code:||
+FEATURE011|Geocodin' Scroll||
+COORD001|Coordinate Calculator||
+COORD002|Calc||
+COORD003|Calculate||
+COORD004|Clear||
+COORD005|UTM||
+COORD006|Latitude or||
+COORD007|Longitude or||
+COORD008|Zone||
+COORD009|UTM Eastin'||
+COORD010|UTM Northin'||
+COORD011| Decimal Degrees: ||
+COORD012| Degrees/Decimal Minutes: ||
+COORD013| Degrees/Minutes/Dec. Seconds: ||
+COORD014| Universal Transverse Mercator: ||
+COORD015|Military Grid Reference System: ||
+COORD016| Maidenhead Grid Locator: ||
+COORD017| ** Sorry, yer input were bein' not recognized! **||
+COORD018| ** Please use one o' th' followin' input formats: **||
+SMARTB001|Smart Beaconin'||
+SMARTB002|High Rate (secs):||
+SMARTB003|High Speed (mph):||
+SMARTB004|High Speed (kph):||
+SMARTB005|Low Rate (mins):||
+SMARTB006|Low Speed (mph):||
+SMARTB007|Low Speed (kph):||
+SMARTB008|Minimum Turn (deg):||
+SMARTB009|Turn Slope:||
+SMARTB010|Wait Time (secs):||
+SMARTB011|Enable SmartBeaconin'(tm)||
+GAMMA001|Adjust Gamma Correctin'||
+GAMMA002|Gamma Correctin'||
+MAPFONT001|Change Scribbles||
+MAPFONT002|Scribbles||
+MAPFONT003|Treasure Map Scribble Tiny||
+MAPFONT004|Treasure Map Scribble Small||
+MAPFONT005|Treasure Map Scribble Medium||
+MAPFONT006|Treasure Map Scribble Large||
+MAPFONT007|Treasure Map Scribble Huge||
+MAPFONT008|Treasure Map Scribble Border||
+MAPFONT009|Menu Scribble||
+MAPFONT010|Ship Scribble||
+MAPFONT011|ATV ID Scribble||
+PULDNDB001|Dist/Bearin' Status||
+GPS001|GPS Transfer||
+GPS002|Scrollname||
+GPS003|Choose 'yer Weapon! Color||
+GPS004|Red||
+GPS005|Green||
+GPS006|Black||
+GPS007|White||
+GPS008|Orange||
+GPS009|Blue||
+GPS010|Yellow||
+GPS011|Violet||
+MAPP001|Treasure Map Properties||
+MAPP002|Max Min Treasure Map USGS Auto||
+MAPP003|Zoom Zoom Layer Fill DRG Treasure Map Path/Scrollname||
+MAPP004|Change Layer->||
+MAPP005|Filled->||
+MAPP006|Aye||
+MAPP007|Nay||
+MAPP008|Automaps->||
+MAPP009|Max Zoom->||
+MAPP010|Min Zoom->||
+MAPP011|Auto||
+MAPP012|USGS DRG->||
+TIME001|Day||
+TIME002|Days||
+TIME003|Hour||
+TIME004|Hours||
+TIME005|Minute||
+TIME006|Minutes||
+TIME007|Second||
+TIME008|Seconds||
+CACHE001|Treasure Map now cached||
+CACHE002|Loadin' Cached Treasure Map||
+CACHE003|Treasure Map not found 'n cache...||
+RANGE001|RANGE SCALE||
+GPSS001|WAAS or PPS||
+GPSS002|DGPS||
+GPSS003|Valid SPS||
+GPSS004|Invalid||
+GPSS005|Sats/Gander||
+GPSS006|Fix||
+GPSS007|!GPS data be older than 30 seconds!||
+GPSS008|Simulatin'||
+GPSS009|Manual||
+GPSS010|Estimated||
+GPSS011|Float RTK||
+GPSS012|RTK||
+CADPUD001|Area Object||
+CADPUD002|Area Label:||
+CADPUD003|Comment:||
+CADPUD004|Probability (%):||
+CADPUD005|Aye||
+CADPUD006|CAD Dialog||
+CADPUD007|Show/Edit Details||
+CADPUD008|Nay||
+CADPUD009|Delete CAD objects?||
+CADPUD010|Delete All||
+CADPUD011|Delete Choose 'yer Weapon!ed||
+CADPUD012|Solid||
+CADPUD013|Dashed||
+CADPUD014|Double Dash||
+MDATA001|HMS XASTIR Treasure Map o' %s (upper left) t' %s (lower right). UTM %d m grid, %s datum. ||
+MDATA002|HMS XASTIR Treasure Map o' %s (upper left) t' %s %s (lower right). Lat/Long grid, %s datum.||
+MDATA003|HMS XASTIR Treasure Map o' %s (upper left) t' %s (lower right). UTM zones, %s datum.||
+XADBMST001|MySQL (lat/long)||
+XADBMST002|Postgreql with Postgis||
+XADBMST003|MySQL (spatial)||
+XASCHEMA01|HMS Xastir Simple Schema||
+XASCHEMA02|HMS Xastir CAD Schema||
+XASCHEMA03|HMS Xastir full Schema||
+XASCHEMA04|APRSWorld Schema||
diff --git a/config/language-Portuguese.sys b/config/language-Portuguese.sys
new file mode 100644
index 0000000..063a0c0
--- /dev/null
+++ b/config/language-Portuguese.sys
@@ -0,0 +1,1353 @@
+# $Id: language-Portuguese.sys,v 1.227 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# Este e o ficheiro da lingua Portuguesa, sem pontuacao, usado para todas as consultas
+# no Xastir.
+#
+# Criador : por CT1DRB, David Quental
+#
+# Linhas de comentarios com o simbolo de cardinal a frente sao ignorados
+# O formato do ficheiro e como segue:
+# Id (10 caracteres alfa numerico)|(Cadeia associada com id)|TeclaRapida|#comentario
+#
+# AVISO:
+# Algumas cadeias de letras conteem comandos de formato como %s e %d, voce nao
+# deve mudar isso. Cadeias de formatos errados poderao produzir um segfault!
+#
+# Menu principal
+MENUTB0001|Ficheiro|F|
+MENUTB0002|Visualizar|V|
+MENUTB0004|Mapas|M|
+MENUTB0005|Estacoes|s|
+MENUTB0006|Mensagens|g|
+MENUTB0010|Interfaces|I|
+MENUTB0009|Ajuda|j|
+#
+# Menu de ficheiro
+PULDNFI001|Configurar|C|
+PULDNFI002|Abrir o log|B|
+PULDNFI003|Testar|P|
+PULDNFI004|Sair|S|
+PULDNFI007|Muda nivel de debug|D|
+PULDNFI010|Abre o log do TNC|T|
+PULDNFI011|Abre o log da internet|I|
+PULDNFI012|Abre o log da I-Gate|G|
+PULDNFI013|Abre o log do tempo|W|
+PULDNFI014|Activa PNG instantanea||
+PULDNFI015|Imprimir mapa|P|
+PULDNFI016|KML Snapshots||
+#
+# Menu visor
+PULDNVI001|Boletins|B|
+PULDNVI002|Trafego recebido|D|
+PULDNVI003|Estacoes moveis|m|
+PULDNVI004|Todas as estacoes|e|
+PULDNVI009|Estacoes locais|t|
+PULDNVI012|Ultimas estacoes|U|
+PULDNVI005|Estacoes meteorologicas|t|
+PULDNVI008|A sua estacao meteorologica|s|
+PULDNVI007|Alerta de tempo|A|
+PULDNVI011|Trafego de mensagens|f|
+PULDNVI013|Aviso|v|
+PULDNVI014|Programar aviso|r|
+PULDNVI015|GPS Status||
+PULDNVI016|ALOHA Statistics||
+#
+# Menu de configuracao
+PULDNCF004|Esta��o|E|
+PULDNCF001|Pre-definidos|P|
+PULDNCF003|Momento certo|T|
+PULDNCF002|Sistema de coordenadas|S|
+PULDNCF006|Audio dos alarmes|A|
+PULDNCF007|Sintetizador de voz|S|
+PULDNCF008|Guardar configuracao!|G|
+# (Unidades ver PULDNDP006)
+#
+# Menu de mapas
+PULDNMP001|Seleccionar mapas|M|
+PULDNMP012|Saltar para um local do mapa|S|
+PULDNMP014|Localizar faixa no mapa|L|
+PULDNMP016|Disable Fast Zoom/Pan/Home||
+PULDNMP013|Desactivar todos os mapas||
+PULDNMP002|Activar auto mapas||
+PULDNMP003|Activar as coordenadas do mapa||
+PULDNMP004|Niveis dos mapas||
+PULDNMP010|Etiquetas dos mapas||
+PULDNMP009|Activar areas coloridas||
+PULDNMP007|Activar os alertas de WX||
+PULDNMP005|Cor de fundo|C|
+PULDNMP006|Estilo de texto da estacao|E|
+PULDNMP026|Estilo da linha de fora do icon|O|
+PULDNMP011|Menu indicador do rato|r|
+PULDNMP008|Intensidade do mapa|I|
+PULDNMP020|Configurar tigermap||
+PULDNMP021|Auto Map - desactivar raster mapas||
+PULDNMP022|Indexar mapas no comeco||
+PULDNMP023|Index: Acrescentar mapas novos|A|
+PULDNMP024|Index: Reindexar os mapas TODOS|R|
+PULDNMP025|Fonts||
+PULDNMP015|Seleccionar a fonte do X||
+PULDNMP027|Re-download Maps (Not from cache)||
+PULDNMP028|Flush Entire Map Cache!||
+PULDNMP029|Find Address||
+PULDNMP030|Configure USGS DRG||
+PULDNMP031|Enable Map Border||
+#
+# PopUp "Configurar tigermap"
+MPUPTGR001|Grelha||
+MPUPTGR002|Freguesias||
+MPUPTGR003|Etiquetas citadinas||
+MPUPTGR004|Areas urbanas||
+MPUPTGR005|Vias principais||
+MPUPTGR006|Ruas||
+MPUPTGR007|Estradas||
+MPUPTGR008|Etiquetas de provincia||
+MPUPTGR009|Etiquetas inter-provincias||
+MPUPTGR010|Etiquetas Hwy de Portugal||
+MPUPTGR011|Etiquetas Hwy de provincia||
+MPUPTGR012|Seleccionar itens para mostrar:||
+MPUPTGR013|Rios||
+MPUPTGR014|Lagos||
+MPUPTGR015|Aeroportos, parques, etc||
+MPUPTGR016|Intensidade do mapa||
+MPUPTGR017|Internet Map Timeout (sec)||
+MPUPTGR018|Activar Tiger Maps||
+#
+# PopUp "Configure USGS DRG"
+MPUPDRG001|Select items to be displayed:||
+MPUPDRG002|Tint Underlying Map (XOR)||
+MPUPDRG003|Black||
+MPUPDRG004|White||
+MPUPDRG005|Blue||
+MPUPDRG006|Red||
+MPUPDRG007|Brown||
+MPUPDRG008|Green||
+MPUPDRG009|Purple||
+MPUPDRG010|Yellow||
+MPUPDRG011|Light Blue||
+MPUPDRG012|Light Red||
+MPUPDRG013|Light Purple||
+MPUPDRG014|Light Gray||
+MPUPDRG015|Light Brown||
+#
+#
+# Selecao de mapas
+WPUPMCP001|Escolher mapa||
+PULDNMMC01|Limpar|N|
+PULDNMMC02|Vectores|V|
+PULDNMMC03|250k Topo|2|
+PULDNMMC04|100k Topo|1|
+PULDNMMC05|24k Topo|4|
+PULDNMMC06|Direccoes expandidas|||
+PULDNMMC07|Selecionados dirs/mapas:||
+PULDNMMC08|Limpar dirs|C|
+PULDNMMC09|Seleccionar tudo|S|
+#
+# Cores de fundo do mapa
+PULDNMBC01|Cinzento||
+PULDNMBC02|Rosado mistico||
+PULDNMBC03|Azul marinho||
+PULDNMBC04|Azul escuro||
+PULDNMBC05|Med. verde mar||
+PULDNMBC06|Verde palido||
+PULDNMBC07|Dourado palido||
+PULDNMBC08|Dourado amarelado||
+PULDNMBC09|Castanho rosado||
+PULDNMBC10|Vermelho escuro||
+PULDNMBC11|Branco||
+PULDNMBC12|Preto||
+#
+# Mapas de estacoes e estilos das etiquetas
+PULDNMSL01|Fundo negro||
+PULDNMSL02|Fundo cinzento||
+PULDNMSL03|Texto em negro|T|
+#
+# PullDown "Estilo da linha de fora do icon"
+PULDNMIO01|Nao ha limite|N|
+PULDNMIO02|Limite preto|B|
+PULDNMIO03|Limite cinzento|G|
+PULDNMIO04|Limite brando|W|
+#
+# Switches ON/OFF/Curto
+PULDNOT001|On||
+PULDNOT002|Off||
+PULDNOT003|Curto||
+#
+# Menu de mostragem de estacoes
+PULDNDP014|Localizar estacao|L|
+PULDNDP001|Rastrear estacao|R|
+PULDNDP022|Tirar o rasto de Findu|F|
+PULDNDP032|Filtrar dados||
+PULDNDP040|Escolher nada||
+PULDNDP041|Escolher meu||
+PULDNDP042|Escolher TNC||
+PULDNDP027|- Mostrar estacoes direct||
+PULDNDP043|- Escolher via digi||
+PULDNDP034|Mostrar estacoes net||
+PULDNDP019|Mostrar infos expiradas||
+PULDNDP044|Mostrar estacoes||
+PULDNDP028|- Mostrar estacoes fixas||
+PULDNDP029|- Mostrar estacoes moveis||
+PULDNDP030|- Mostrar estacoes de tempo||
+PULDNDP053| - Seleccionar estacoes CWOP WX||
+PULDNDP045|Mostrar objectos/items||
+PULDNDP026|- Mostrar objectos/items metereologicos||
+PULDNDP039|- Mostrar objectos de medida de agua/Items||
+PULDNDP031|- Mostrar outros objectos/Items||
+PULDNDP033|Filtrar monitor||
+PULDNDP010|Mostrar indicativo|i|
+PULDNDP012|Mostrar simbolos|D|
+PULDNDP011|- Simbolos rodados|S|
+PULDNDP007|Rastos de estacoes|R|
+PULDNDP003|Mostrar curso|c|
+PULDNDP004|Mostrar velocidade|v|
+PULDNDP017|- Mostrar velocidade baixa||
+PULDNDP002|Mostrar altura|a|
+PULDNDP009|Mostrar info do tempo|t|
+PULDNDP046|- Mostrar texto do tempo||
+PULDNDP018|-- Mostrar so a temperatura||
+PULDNDP047|- Mostrar intensidade do vento||
+PULDNDP054|Display Aloha Circle||
+PULDNDP013|Ambiguidade de posicao||
+PULDNDP008|Estacao potencia/ganho|p|
+PULDNDP021|- Activar por defeito pot/ganho||
+PULDNDP020|- Activar movel pot/ganho||
+PULDNDP023|Mostrar circulos DF||
+PULDNDP123|Display DF Beamwidth||
+PULDNDP223|Display DF Bearing||
+PULDNDP035|Activar Dead-Reckoning||
+PULDNDP036|- Activar arco Dead-Reckoning||
+PULDNDP037|- Activar curso Dead-Reckoning||
+PULDNDP038|- Activar simbolo Dead-Reckoning||
+PULDNDP005|Mostrar dist/curso|d|
+PULDNDP024|Mostrar o ultimo reporte horario||
+PULDNDP015|Anular todas as estacoes|A|
+PULDNDP016|Limpar rastos|L|
+PULDNDP025|Limpar historia de objecto/item||
+PULDNDP048|Recarregar objecto/historia de item||
+PULDNDP049|Limpar todos os indicativos tacticos||
+PULDNDP050|Limpar a historia dos indicativos tacticos||
+PULDNDP051|Seleccionar unicamente indicativos tacticos||
+PULDNDP052|- Etiquetas de pontos de pista||
+PULDNDP055|Export all|E|
+PULDNDP056|Export to KML File||
+#
+# Inglesa/metrica
+PULDNUT001|Activar unidades Inglesas||
+PULDNUT002|Metrica||
+#
+# Menu de mensagens
+PULDNMG001|Enviar mensagem a|E|
+PULDNMG002|Abrir mensagens de grupos|g|
+PULDNMG003|Anular todas as mensagens a enviar|A|
+PULDQUS001|Pergunta geral a estacoes|r|
+PULDQUS002|Pergunta a estacoes I-Gate|I|
+PULDQUS003|Pergunta a estacoes WX|W|
+PULDNMG004|Modificar mensagem de resposta automatica|f|
+PULDNMG005|Activar mensagem de resposta automatica|A|
+PULDNMG006|Modo de reconhecimento por satelite|M|
+PULDNMG007|Show Pending Messages|P|
+#
+# Menu de interfaces
+PULDNTNT04|Interface Control||
+PULDNTNT03|Desactivar transmitir: TODOS||
+PULDNTNT05|Desactivar transmitir: A minha posicao||
+PULDNTNT06|Desactivar transmitir: Objectos/Artigos||
+PULDNTNT11|Activar porta de server||
+PULDNTNT01|Transmitir agora..!|T|
+PULDNTNT07|Buscar rastro de GPS|F|
+PULDNTNT08|Buscar rotas de GPS|R|
+PULDNTNT09|Buscar waypoints de GPS|W|
+PULDNTNT10|Buscar pontos da Garmin RINO|G|
+#
+# Menu de ajuda
+PULDNHEL01|Acerca de|A|
+PULDNHEL02|Index de ajuda|I|
+PULDNHEL03|EMERGENCY BEACON MODE ENABLE|E|
+PULDNHEL04|!!! EMERGENCY BEACON MODE !!!||
+PULDNHEL05|About Xastir||
+#
+# Menu do rato
+POPUPMA001|Opcoes||
+POPUPMA00c|Centro||
+POPUPMA015|Info da estacao||
+POPUPMA002|Aproximar|A|
+POPUPMA003|Afastar|f|
+POPUPMA004|Nivel de focagem|N|
+POPUPMA005|Nivel 1|1|
+POPUPMA006|Nivel 16|6|
+POPUPMA007|Nivel 64|4|
+POPUPMA008|Nivel 256|2|
+POPUPMA009|Nivel 1024|0|
+POPUPMA010|Nivel 8192|8|
+POPUPMA017|O mundo inteiro|E|
+POPUPMA016|Ultima pos/focagem do mapa|P|
+POPUPMA018|Criar objecto/artigo|C|
+POPUPMA019|Modificar objecto/artigo|M|
+POPUPMA025|Mover aqui a minha estacao|H|
+POPUPMA011|Ir para cima|u|
+POPUPMA012|Ir para baixo|d|
+POPUPMA013|Ir para a esquerda|l|
+POPUPMA014|Ir para a direita|r|
+POPUPMA020|Medida||
+POPUPMA021|Movimento||
+POPUPMA022|Siga-me||
+POPUPMA023|Modificadores encontrados!||
+POPUPMA024|Por favor desligue as teclas CapsLock/NumLock/ScrollLock/outros||
+POPUPMA026|Centro e Zoom||
+POPUPMA027| Latitude||
+POPUPMA028| Longitude||
+POPUPMA029|Desenhar objectos CAD||
+POPUPMA030|Draw||
+POPUPMA031|Fechar poligono||
+POPUPMA032|Erase CAD Polygons||
+POPUPMA033|**NOT USED**||
+POPUPMA034|Custom Zoom Level||
+POPUPMA035|10% out||
+POPUPMA036|10% in||
+POPUPMA037|Area||
+POPUPMA038|square||
+POPUPMA039|square feet||
+POPUPMA040|square meters||
+POPUPMA041|Bearing||
+POPUPMA042|degrees||
+POPUPMA043|Modify ambiguous position||
+POPUPMA044|Position abiguity is on, your new position may appear to jump.||
+POPUPMA045|Predefined Objects||
+POPUPMA046|CAD Polygons||
+POPUPMA047|Enable CAD objects||
+POPUPMA048|Enable CAD labels||
+POPUPMA049|Enable CAD comments||
+POPUPMA050|Enable CAD probability||
+POPUPMA051|Enable CAD area size||
+POPUPMA052|sq||
+POPUPMA053|ft||
+POPUPMA054|meters||
+POPUPMA055|mi|
+#
+# Menu dos estados das linhas de etiquetas
+BBARZM0001|Foco %s||
+BBARZM0002|Foco %s Tr||
+BBARSTH001|%d/%d estacoes||
+BBARSTA000|%-9s novo objecto!||
+BBARSTA001|%-9s nova estacao!||
+BBARSTA002|%s||
+BBARSTA003|Carregando mapas...||
+BBARSTA004|Mapas carregados...||
+BBARSTA005|Graduacao lat/long esta ON||
+BBARSTA006|Graduacao lat/long esta OFF||
+BBARSTA007|O uso dos auto mapas, esta ON||
+BBARSTA008|O uso dos auto mapas, esta OFF||
+BBARSTA009|Os niveis do mapa estao ON||
+BBARSTA010|Os niveis do mapa estao OFF||
+BBARSTA011|A mensagem de resposta automatica esta OFF!||
+BBARSTA012|Ficheiro criado..||
+BBARSTA013|Abrindo porta GPS||
+BBARSTA014|Fechando porta GPS||
+BBARSTA015|Obtendo a string do GPS RMC||
+BBARSTA016|Obtendo a string do GPS GGA||
+BBARSTA017|Rede desligada do servidor||
+BBARSTA018|Ligacao fechada por excesso de tempo!||
+BBARSTA019|A procurar servidor %s||
+BBARSTA020|Ligado a %s||
+BBARSTA021|Falha na ligacao � rede!||
+BBARSTA022|Pode nao ligar ao socket!||
+BBARSTA023|Nao ha IP para o servidor!||
+BBARSTA024|Nao ha servidor especificado||
+BBARSTA025|Servidor encontrado, a ligar %d||
+BBARSTA026|Esperando por infos do GPS via HSP..||
+BBARSTA027|Limpando as infos de HSP obtidos do TNC..||
+BBARSTA028|Carregando %s||
+BBARSTA029|Abrindo porta WX||
+BBARSTA030|A fechar porta WX||
+BBARSTA031|A procura o servidor %d||
+BBARSTA032|Infos de WX descodificados||
+BBARSTA033|Eco desde o digipeater||
+BBARSTA034|Carregando mapas de alerta WX||
+BBARSTA035|Esperando por dados do GPS via AUX..||
+BBARSTA036|Limpando AUX para obter dados do TNC..||
+BBARSTA037|Dados do GPS completos||
+BBARSTA038|Posicao alterada na minha estacao||
+BBARSTA039|Indexando %s||
+BBARSTA040|Estacao de radioamador de APRS(tm) %s||
+BBARSTA041|Esperando pela data do GPS..||
+BBARSTA042|Transmitindo objectos/items||
+BBARSTA043|Registando||
+BBARSTA044|ALOHA distance is %d%s||
+BBARSTA045|Loading symbols...||
+BBARSTA046|Reloading symbols...||
+BBARSTA047|Initialize my station...||
+BBARSTA048|Start interfaces...||
+BBARSTA049|Reading tiles...||
+BBARSTA050|Downloading tiles...||
+BBARSTA051|Downloading tile %li of %li||
+#
+# Visualiza��o do trafego de packet
+WPUPDPD001|Visualizacao do trafego||
+WPUPDPD002|So dados do TNC||
+WPUPDPD003|So dados da rede||
+WPUPDPD004|Dados do TNC e da rede||
+WPUPDPD005|TNC||
+WPUPDPD006|REDE||
+WPUPDPD007|Station Capabilities||
+WPUPDPD008|Mine Only||
+#
+# Localizar estacao
+WPUPLSP001|Localizar estacao||
+WPUPLSP002|Localizar indicativo||
+WPUPLSP003|Maiscula/minuscula|M|
+WPUPLSP004|Exacta|E|
+WPUPLSP005|Localizar agora!|A|
+WPUPLSP006|Localizar emergencia!||
+WPUPLSP007|FCC/RAC Lookup||
+#
+# Configurar predefinidos
+WPUPCFD001|Configurar valores pre-definidos||
+WPUPCFD002|desde que intervalo de tempo sera considerada uma estacao antiga?||
+WPUPCFD003|15 minutos|1|
+WPUPCFD004|30 minutos|3|
+WPUPCFD005|45 minutos|4|
+WPUPCFD006|1 hora|H|
+WPUPCFD007|90 minutos|9|
+WPUPCFD008|2 horas|2|
+WPUPCFD009|desde que intervalo de tempo a estacao nao sera mostrada?||
+WPUPCFD010|6 horas|6|
+WPUPCFD011|12 horas|o|
+WPUPCFD012|1 Dia|D|
+WPUPCFD013|2 Dias|s|
+WPUPCFD014|1 semana|n|
+WPUPCFD015|Opcao modo de transmissao da estacao||
+WPUPCFD016|Estacao fixa|F|
+WPUPCFD017|Estacao movel c/hora local|l|
+WPUPCFD018|Estacao movel c/data-hora zulu|z|
+WPUPCFD019|Estacao movel c/horas-segundos zulu|u|
+WPUPCFD021|Posicao da estacao c/tempo|t|
+WPUPCFD022|Posicao da estacao, data-hora zulu e tempo|d|
+WPUPCFD023|Transmitir infos WX em Raw?||
+WPUPCFD024|Comprimir objecto/item durante a transmissao?||
+WPUPCFD025|Activar rede alternativa?|A|
+WPUPCFD026|Enviar reportes de posicao em que intervalos?||
+WPUPCFD027|Pop up de novos boletins||
+WPUPCFD028|Avisar se teclas foram modificadas||
+WPUPCFD029|Ver boletins de distancia zero||
+WPUPCFD030|Desactivar dupe-checks de posit||
+WPUPCFD031|Load predefined objects from file||
+WPUPCFD032|My trails in one color||
+WPUPCFD033|ALTNET:||
+#
+# PopUp "Configurar - momento certo"
+WPUPCFTM01|Configurar momento certo|||
+WPUPCFTM02|Intervalo Posit TX (min)||
+WPUPCFTM03|Tempo de estacao fantasma (min)||
+WPUPCFTM04|Max Intervalo TX objecto/item (min)||
+WPUPCFTM05|Tempo para limpar estacao (horas)||
+WPUPCFTM06|Intervalo para verificar GPS (seg)||
+WPUPCFTM07|Tempo para apagar estacao (dias)||
+WPUPCFTM08|Tempo limite para dead-reckoning (min)||
+WPUPCFTM09|Serie de atraso de inter-char (ms)||
+WPUPCFTM10|Novo tempo de pista (min)||
+WPUPCFTM11|Novo intervado de pista (degrees)||
+WPUPCFTM12|RINO -> Intervalo de objectos (min), 0 = Desactivado||
+WPUPCFTM13|Snapshot Interval (min)||
+#
+# PopUp "Sistema de configuracao de coordenadas"
+WPUPCFC001|Sistema de configuracao de coordenadas||
+WPUPCFC002|Sistema de selecao de coordenadas||
+WPUPCFC003|dd.ddddd|d|
+WPUPCFC004|dd mm.mmm|m|
+WPUPCFC005|dd mm ss.s|s|
+WPUPCFC006|UTM|U|
+WPUPCFC007|USNG/MGRS2||
+WPUPCFC008|UTM com zonas especiais||
+#
+# Configurar GPS
+WPUPCFG001|Configurar GPS||
+WPUPCFG003|Porta exclusiva de GPS||
+WPUPCFG002|Usar posicao GPS?||
+WPUPCFG004|opcoes do GPS||
+WPUPCFG005|GPS exclusivo||
+WPUPCFG006|TNC ligado a GPS (cabo HSP)||
+WPUPCFG007|TNC ligado a GPS usando CTL-E||
+WPUPCFG008|GPS tempo (a mostrar cada)||
+WPUPCFG009|5 sec||
+WPUPCFG010|15 sec||
+WPUPCFG011|30 sec||
+WPUPCFG012|1 minuto||
+WPUPCFG013|2 minutos||
+WPUPCFG014|5 minutos||
+WPUPCFG015|10 minutos||
+WPUPCFG016|Rede ligada ao GPS||
+WPUPCFG017|Servidor GPSD||
+WPUPCFG018|Porta GPSD||
+WPUPCFG019|Rede GPS via GPSD||
+WPUPCFG020|Voltar a ligar quando falhar?||
+WPUPCFG021|Rede ligada a WX||
+WPUPCFG022|Servidor WX||
+WPUPCFG023|Porta WX||
+#
+# Configurar TNC (bauds tambem sao para WX)
+WPUPCFT001|Configurar TNC||
+WPUPCFT002|Usar TNC?||
+WPUPCFT003|Porta TNC||
+WPUPCFT004|Velocidade da porta||
+WPUPCFT005|300 bps||
+WPUPCFT006|1200 bps||
+WPUPCFT007|2400 bps||
+WPUPCFT008|4800 bps||
+WPUPCFT009|9600 bps||
+WPUPCFT010|19200 bps||
+WPUPCFT011|Rota do UnProto||
+WPUPCFT012|Rota 1: %s via ||
+WPUPCFT013|Rota 2: %s via ||
+WPUPCFT014|Rota 3: %s via ||
+WPUPCFT015|Modo da porta||
+WPUPCFT016|8,N,1||
+WPUPCFT017|7,E,1||
+WPUPCFT018|7,O,1||
+WPUPCFT019|38400 bps||
+WPUPCFT020|57600 bps||
+WPUPCFT021|115200 bps||
+WPUPCFT022|230400 bps||
+WPUPCFT023|Configurar o TNC c/HSP GPS||
+WPUPCFT024|Tipo de data||
+WPUPCFT025|Auto deteccao||
+WPUPCFT026|Tipo Binario||
+WPUPCFT027|Tipo ASCII||
+WPUPCFT028|Configurar TNC com GPS AUX||
+WPUPCFT029|Configurar TNC com ENUM INVALIDO||
+WPUPCFT030|Configurar o TNC em KISS||
+WPUPCFT031|Ficheiros de configuracao do TNC||
+WPUPCFT032|Nome do ficheiro de definicoes do TNC||
+WPUPCFT033|Nome do ficheiro de fecho do TNC||
+WPUPCFT034|Parametros do KISS||
+WPUPCFT035|TXDelay (10 unidades de ms)||
+WPUPCFT036|Persistencia (0 a 255)||
+WPUPCFT037|SlotTime (10 unidades de ms)||
+WPUPCFT038|TxTail (10 unidades de ms)||
+WPUPCFT039|Duplex completo (Full Duplex)||
+WPUPCFT040|Configurar o TNC em Multi-Port KISS||
+WPUPCFT041|Porta radio||
+WPUPCFT042|Dubious UNPROTO Path!||
+WPUPCFT043|Please consider a shorter path such as WIDE2-2 or WIDE1-1,WIDE2-2||
+WPUPCFT044|Dubious IGATE Path!||
+WPUPCFT045|Transmitting w/Dubious UNPROTO Path!||
+WPUPCFT046|Transmitting w/Dubious IGATE Path!||
+WPUPCFT047|Init KISS-mode on startup||
+#
+# Configurar a porta da estacao meteorologica
+WPUPCFWX01|Configurar a porta da estacao meteorologica||
+WPUPCFWX02|Dispositivo da estacao meteorologica||
+WPUPCFWX03|Correccao da medida de chuva (Definicoes globais)||
+WPUPCFWX04|.1 polegadas/2.5mm||
+WPUPCFWX05|.01 polegadas/.25mm||
+WPUPCFWX06|.1mm||
+WPUPCFWX07|Nao corrigido||
+#
+# Configurar a estacao
+WPUPCFS001|Configurar a estacao||
+WPUPCFS002|Indicativo||
+WPUPCFS003|Latitude||
+WPUPCFS004|grd||
+WPUPCFS005|min||
+WPUPCFS006|(N/S)||
+WPUPCFS007|Longitude||
+WPUPCFS008|(E/W)||
+WPUPCFS009|Simbolo da estacao||
+WPUPCFS010|Grupo/sobreposto||
+WPUPCFS011|Simbolo||
+WPUPCFS028|Seleccione||
+WPUPCFS012|Potencia - Altura (HAAT) - Ganho e direccao||
+WPUPCFS013|Desactive PHG||
+WPUPCFS014|Altura da antena||
+WPUPCFS015|Ganho da antena||
+WPUPCFS016|Omni||
+WPUPCFS017|Comentarios:||
+WPUPCFS018|Posicao ambigua||
+WPUPCFS019|Nenhuma||
+WPUPCFS020|.11 milha||
+WPUPCFS021|1.15 milhas||
+WPUPCFS022|11.51 milhas||
+WPUPCFS023|69.09 milhas||
+WPUPCFS024|.18 quilometro||
+WPUPCFS025|1.85 quilometros||
+WPUPCFS026|18.53 quilometros||
+WPUPCFS027|111.19 quilometros||
+WPUPCFS029|Enviar posits comprimidas|C|
+#
+# Dialogo de Objeto/Artigo
+POPUPOB001|Objecto/artigo||
+POPUPOB002|Nome:||
+POPUPOB003|Criar novo objecto||
+POPUPOB004|Apagar objeto||
+POPUPOB005|Modificar objecto||
+POPUPOB006|Criar novo artigo||
+POPUPOB007|Area do objeto||
+POPUPOB008|Activar area do objecto||
+POPUPOB009|Cor luminosa||
+POPUPOB010|Area colorida||
+POPUPOB011|Circulo||
+POPUPOB012|Linha-direita '/'||
+POPUPOB013|Linha-esquerda '\'||
+POPUPOB014|Triangulo||
+POPUPOB015|Rectangulo||
+POPUPOB016|Negro||
+POPUPOB017|Azul||
+POPUPOB018|Verde||
+POPUPOB019|Cinzento||
+POPUPOB020|Vermelho||
+POPUPOB021|Violeta||
+POPUPOB022|Amarelo||
+POPUPOB023|Cinzento||
+POPUPOB024|Compensar em cima:||
+POPUPOB025|Compensar a esq.(Excepto '/'):||
+POPUPOB026|Corredor:||
+POPUPOB027|Opcoes gerais||
+POPUPOB028|Situacao||
+POPUPOB029|Activar letreiro||
+POPUPOB030|Data:||
+POPUPOB031|Letreiro objecto||
+POPUPOB032|Activar compressao||
+POPUPOB033|Apagar artigo||
+POPUPOB034|Modificar artigo||
+POPUPOB035|Altitude (Pes):||
+POPUPOB036|Velocidade (nos):||
+POPUPOB037|Curso:||
+POPUPOB038|DF objecto||
+POPUPOB039|Sinal - Altura(HAAT) - Ganho - Direccao||
+POPUPOB040|Dirigindo - Amplitude da direccao||
+POPUPOB041|Antena omni-direcional||
+POPUPOB042|Antena direcional||
+POPUPOB043|Inutil||
+POPUPOB044|Adoptar objecto||
+POPUPOB045|Adoptar item||
+POPUPOB046|DF Bearing:||
+POPUPOB047|Probability Circles||
+POPUPOB048|Map View Object||
+POPUPOB049|Min (mi):||
+POPUPOB050|Max (mi):||
+#
+# Configurar Internet
+WPUPCFI001|Configurar internet||
+WPUPCFI002|Servidor||
+WPUPCFI003|Porta||
+WPUPCFI004|(Servidores secundarios)||
+WPUPCFI005|Servidor1||
+WPUPCFI006|Porta1||
+WPUPCFI007|Servidor2||
+WPUPCFI008|Porta2||
+WPUPCFI009|Senha||
+WPUPCFI010|(Deixar em branco se nao houver nada)||
+WPUPCFI011|Voltar a ligar em caso de falha de rede?||
+WPUPCFI012|Correr como num I-Gate?||
+WPUPCFI013|Difundir mensagens via TNC quando houver um I-Gate?||
+WPUPCFI014|Registo de transacoes do I-Gate?|||
+WPUPCFI015|Parametros filtrados||
+#
+# Configurar Database
+WPUPCFID01|Configurar Database (TBD)||
+WPUPCFID02|Servidor||
+WPUPCFID03|Porta||
+WPUPCFID04|(Servidores secundarios)||
+WPUPCFID05|Servidor1||
+WPUPCFID06|Porta1||
+WPUPCFID07|Servidor2||
+WPUPCFID08|Porta2||
+WPUPCFID09|Senha||
+WPUPCFID10|(Deixar em branco se nao houver nada)||
+WPUPCFID11|Voltar a ligar em caso de falha de rede?||
+WPUPCFID12|Correr como num I-Gate?||
+WPUPCFID13|Difundir mensagens via TNC quando houver um I-Gate?||
+WPUPCFID14|Log de transacoes do I-Gate?|||
+WPUPCFID15|Parametros filtrados||
+#
+# PopUp "Configurar AGWPE"
+WPUPCFIA01|Configurar AGWPE||
+WPUPCFIA02|Host ||
+WPUPCFIA03|Porta ||
+WPUPCFIA04|(Hosts secundarios)||
+WPUPCFIA05|Host1||
+WPUPCFIA06|Porta1||
+WPUPCFIA07|Host2||
+WPUPCFIA08|Porta2||
+WPUPCFIA09|Codigo de passagem||
+WPUPCFIA10|(Deixar em branco se nao ha nada)||
+WPUPCFIA11|Voltar a ligar se houver uma falha da NET?||
+WPUPCFIA12|Funcionar como uma I-Gate?||
+WPUPCFIA13|Divulgar mensagens via TNC quando estiver na I-Gate?||
+WPUPCFIA14|Registo das transacoes I-Gate?||
+WPUPCFIA15|Transmitir RadioPort||
+#
+# Configurar Alarmas de Audio
+WPUPCFA001|Configurar alarme de audio||
+WPUPCFA002|Aplicacao audio||
+WPUPCFA003|Alarme ON||
+WPUPCFA004|Ficheiros de audio||
+WPUPCFA005|Nova estacao||
+WPUPCFA006|Nova mensagem||
+WPUPCFA007|Proximidade||
+WPUPCFA008|Banda aberta||
+WPUPCFA009|Minima distancia||
+WPUPCFA010|Maxima distancia||
+WPUPCFA011|Alerta de tempo||
+#
+# Configurar o festival, o sintetizador de voz
+WPUPCFSP01|Configurar o festival como sintetizador de voz||
+WPUPCFSP02|Fixar em 'ON' as opcoes do sintetizador de voz||
+WPUPCFSP03|<- Anuncia nova estacao||
+WPUPCFSP04|<- Anuncia alerta de nova mensagem||
+WPUPCFSP05|<- Anuncia corpo de nova mensagem||
+WPUPCFSP06|<- Anuncia a proximidade de estacoes||
+WPUPCFSP07|<- Anuncia DX condi��o de banda aberta||
+WPUPCFSP08|<- Anuncia alerta sobre condicoes do tempo||
+WPUPCFSP09|Alerta de proximidade da estacao rastreada||
+#
+# Rastreo da estacao
+WPUPTSP001|Rastrear estacao||
+WPUPTSP002|Rastrear indicativo||
+WPUPTSP003|Maiscula/minuscula||
+WPUPTSP004|Exacto||
+WPUPTSP005|Rastrear agora!||
+WPUPTSP006|Limpar rastro||
+WPUPTSP007|Receber caminho||
+WPUPTSP008|Indicativo||
+WPUPTSP009|Comecar rasto (horas atras)||
+WPUPTSP010|Tamanho do rasto (horas)||
+#
+# Menu de mensagens
+WPUPMSB001|Enviar mensagem %d||
+WPUPMSB002|Enviar mensagem ao grupo %d||
+WPUPMSB003|Indicativo de estacao:||
+WPUPMSB004|Indicativos de grupos:||
+WPUPMSB005|Novo/Refresh indicativo||
+WPUPMSB006|Novo grupo||
+WPUPMSB007|Limpar hist�ria da mensagem||
+WPUPMSB008|Mensagem:||
+WPUPMSB009|Enviar agora!||
+WPUPMSB010|Encaminhamento:||
+WPUPMSB011|Cancelar mensagens pendentes||
+WPUPMSB012|Kick Timer||
+WPUPMSB013|seq||
+WPUPMSB014|type||
+WPUPMSB015|Broadcast||
+WPUPMSB016|*TIMEOUT*||
+WPUPMSB017|*CANCELLED*||
+WPUPMSB018|*REJECTED*||
+WPUPMSB019|Change Path||
+WPUPMSB020|Use Default Path(s)||
+WPUPMSB021|Direct (No path)||
+WPUPMSB022|Reverse Path (Hint):||
+#
+# Auto resposta
+WPUPARM001|Mudar resposta automatica||
+WPUPARM002|Reenviar:||
+#
+# Auuda / Indice
+WPUPHPI001|Indice de ajuda|I|
+WPUPHPI002|Visualizar|V|
+#
+# Informacao da estacao
+WPUPSTI000|Objecto criado desde: %s||
+WPUPSTI001|Info estacao||
+WPUPSTI002|Enviar mensagem||
+WPUPSTI003|Procurar infos FCC||
+WPUPSTI004|Procurar infos RAC||
+WPUPSTI005|%d: pacotes recebidos, ultimo recebido na data: ||
+WPUPSTI006|Ouvido via TNC no dispositivo: %d, ||
+WPUPSTI007|Ouvido ||
+WPUPSTI008|Ultima vez via local||
+WPUPSTI009|U�ltima vez via TNC no dispositivo: %d||
+WPUPSTI010|Ultima vez via internet no dispositivo: %d||
+WPUPSTI011|Ultima vez via ficheiro||
+WPUPSTI012|Ultima vez via desconhecida||
+WPUPSTI013|, e mudou de posicao||
+WPUPSTI014|Actual potencia/ganho:||
+WPUPSTI016|Altitude: %.1f%s ||
+WPUPSTI017|Curso: %s� ||
+WPUPSTI018|Velocidade: %.1f km/h||
+WPUPSTI019|Velocidade: %.1f mph||
+WPUPSTI020|%0.1f milhas||
+WPUPSTI021|%0.1f km||
+WPUPSTI022|Distancia desde a minha estaca�o %s, curso desde a minha estacao %s||
+WPUPSTI023|Ultima posicao: ||
+WPUPSTI024|Dados da estacao meteorologica %c:%s||
+WPUPSTI025|Curso do vento: %s� Velocidade: %03d km/h||
+WPUPSTI026|Curso do vento: %s� Velocidade: %s mph||
+WPUPSTI027| Rajada: %03d Km/h||
+WPUPSTI028| Rajada: %s mph||
+WPUPSTI029|Temperatura: %02.1f�C ||
+WPUPSTI030|Temperatura: %s�F ||
+WPUPSTI031|Humidade: %s%% ||
+WPUPSTI032|Indice da humidade: %02.1f�C ||
+WPUPSTI033|Pressao barometrica: %s mb||
+WPUPSTI034|Neve: %0.1f (cm/24h)||
+WPUPSTI035|Neve: %0.0f (plg/24h)||
+WPUPSTI036|Chuva: ||
+WPUPSTI037|%0.2f (mm/h) ||
+WPUPSTI038|%0.2f (plg/h) ||
+WPUPSTI039|%0.2f (mm/dia) ||
+WPUPSTI040|%0.2f (plg/dia) ||
+WPUPSTI041|%0.2f (mm/desde a meia noite)||
+WPUPSTI042|%0.2f (mm/desde a meia noite)||
+WPUPSTI043|Rota de dados: %s||
+WPUPSTI044|Comentarios %02d/%02d %02d:%02d : %s||
+WPUPSTI045|Limpar rastro||
+WPUPSTI046|Total de chuva: ||
+WPUPSTI047|%0.2f (mm)||
+WPUPSTI048|%0.2f (plg)||
+WPUPSTI049|Perguntar rastro||
+WPUPSTI050|Perguntar por mensagens nao-confirmadas||
+WPUPSTI051|Pergunta directa a estacao||
+WPUPSTI052|Pergunta versao a estacao||
+WPUPSTI053|Modificar objeto/artigo||
+WPUPSTI054|Armazenar rastro||
+WPUPSTI055|Repetido desde:||
+WPUPSTI056|Activar actualizacao automatica||
+WPUPSTI057|Omni-DF: %s||
+WPUPSTI058|DF dirigido: %s||
+WPUPSTI059|Estados %02d/%02d %02d:%02d : %s||
+WPUPSTI060|Temp do combustivel: %02.1f�C ||
+WPUPSTI061|Temp do combustivel: %s�F ||
+WPUPSTI062|Mistura do combustevel: %s%% ||
+WPUPSTI063|Baro: %0.2f em Hg||
+WPUPSTI064|Procurar alerta de NWS||
+WPUPSTI065|Indicativo tactico: %s||
+WPUPSTI066|Assign Tactical Call||
+WPUPSTI067|Current Range: %d miles||
+WPUPSTI068|none||
+WPUPSTI069|default||
+WPUPSTI070|HAAT||
+WPUPSTI071|omni||
+WPUPSTI072|range||
+WPUPSTI073|BAD PHG||
+WPUPSTI074|BAD SHG||
+WPUPSTI075|DF Range||
+WPUPSTI076|No signal detected||
+WPUPSTI077|Detectible signal (Maybe)||
+WPUPSTI078|Detectible signal but not copyable)||
+WPUPSTI079|Weak signal, marginally readable||
+WPUPSTI080|Noisy but copyable signal||
+WPUPSTI081|Some noise, easy to copy signal||
+WPUPSTI082|Good signal w/detectible noise||
+WPUPSTI083|Near full-quieting signal||
+WPUPSTI084|Full-quieting signal||
+WPUPSTI085|Extremely strong & full-quieting signal||
+WPUPSTI086|BAD BEARING||
+WPUPSTI087|BAD NRQ||
+WPUPSTI088|DF Beamwidth||
+WPUPSTI089|DF Length||
+WPUPSTI090|Not Valid||
+WPUPSTI091|Change Trail Color||
+WPUPSTI092|Clear DF Bearing||
+#
+#
+# PopUp "ALOHA Statistics"
+WPUPALO001|ALOHA radius: %d %s||
+WPUPALO002|Stations inside ALOHA circle: %d||
+WPUPALO003| Digis: %d||
+WPUPALO004| Mobiles (in motion): %d||
+WPUPALO005| Mobiles (other): %d||
+WPUPALO006| WX stations: %d||
+WPUPALO007| Home stations: %d||
+WPUPALO008|Last calculated %d %s %d %s ago.||
+WPUPALO666|ALOHA radius not calculated yet||
+#
+# FCC-RAC procurar indicativo
+STIFCC0001|Procurar FCC banco de datos||
+STIFCC0002|Procurar RAC banco de datos||
+STIFCC0003|Nome:||
+STIFCC0004|Rua/Av�:||
+STIFCC0005|Cidade:||
+STIFCC0006|Estado:||
+STIFCC0007|Codigo postal:||
+STIFCC0008|Basica ||
+STIFCC0009|Avancada ||
+STIFCC0010|5 wpm ||
+STIFCC0011|12 wpm ||
+#
+# FCC-RAC procurar indicativo
+STIFCC0100|FCC index old, rebuilding||
+STIFCC0101|Callsign Search||
+STIFCC0102|Callsign Not Found!||
+STIFCC0103|RAC index old, rebuilding||
+#
+#
+# Mensagem de banda aberta
+UMBNDO0001|a cerca de||
+#
+# Opcoes universais
+UNIOP00001|Aceitar||
+UNIOP00002|Cancelar||
+UNIOP00003|Fechar||
+UNIOP00004|milhas||
+UNIOP00005|km||
+UNIOP00006|Dispositivo||
+UNIOP00007|Acrescentar||
+UNIOP00008|Anular||
+UNIOP00009|Propriedades||
+UNIOP00010|Permitir transmissao?||
+UNIOP00011|Activar no inicio?||
+UNIOP00012|km/h||
+UNIOP00013|mph||
+UNIOP00014|C||
+UNIOP00015|F||
+UNIOP00016|mm||
+UNIOP00017|plg||
+UNIOP00018|mm/dia||
+UNIOP00019|plg/dia||
+UNIOP00020|mm/hora||
+UNIOP00021|plg/hora||
+UNIOP00022|mm/med||
+UNIOP00023|plg/med||
+UNIOP00024|grd||
+UNIOP00025|mb||
+UNIOP00026|%||
+UNIOP00027|inHg||
+UNIOP00028|mm Hg||
+UNIOP00029|Definir o relogio do sistema desde o GPS?||
+UNIOP00030|Digipeater?||
+UNIOP00031|m||
+UNIOP00032|Aplicar|||
+UNIOP00033|Reset||
+UNIOP00034|min||
+UNIOP00035|hr||
+UNIOP00036|day||
+UNIOP00037|Send Control-E to get GPS data?||
+UNIOP00038|Add Delay||
+#
+# Seleccionar estacao
+STCHO00001|Seleccionar estacao||
+#
+# Desligar alarme de WX
+WPUPWXA001|Alerta do tempo||
+WPUPWXA002|Lista de alerta do tempo||
+#
+# Configurar interfaces
+WPUPCIF001|Interfaces instalados||
+WPUPCIF002|Escolher tipo de interface||
+#
+# Configurar AX.25 TNC
+WPUPCAX001|Configurar AX.25 TNC||
+WPUPCAX002|AX.25 nome da porta||
+#
+# Nomes dos dispositivos do interface
+IFDNL00000|Nada||
+IFDNL00001|TNC via a porta serie||
+IFDNL00002|Serial TNC c/GPS mais (cabo HSP)||
+IFDNL00003|GPS via porta serie||
+IFDNL00004|Est. meteorologica via porta serie||
+IFDNL00005|Ligacao a um servidor na internet||
+IFDNL00006|AX.25 TNC||
+IFDNL00007|GPS ligado via o servidor gpsd||
+IFDNL00008|Est. meteorologica ligada a uma REDE||
+IFDNL00009|TNC com GPS na porta AUX||
+IFDNL00010|KISS TNC da porta serie||
+IFDNL00011|Base de dados de rede (Nao implementado ainda)||
+IFDNL00012|AGWPE em rede||
+IFDNL00013|Multi-Port KISS TNC da porta serie||
+IFDNL00014|SQL Database (Experimental)||
+#
+# Info dispositivo interface
+IFDIN00000|%s %2d %s sobre serie %s %s||
+IFDIN00001|%s %2d %s ligado a %s:%d %s||
+IFDIN00002|%s %2d %s usando dispositivo nomeado %s %s||
+IFDIN00003|%s %2d %s %s %s %s||
+IFDIN00004|%s %2d %s %s %s:%d %s||
+IFDIN00005|%s %2d %s %s %s %s||
+IFDIN00006| desligado ||
+IFDIN00007| ligado ||
+IFDIN00008| ERRO ||
+IFDIN00009|DESCONHECIDO||
+#
+# Controle da interface
+IFPUPCT000|Controle do interface||
+IFPUPCT001|Iniciar||
+IFPUPCT002|Parar||
+IFPUPCT003|Iniciar todos||
+IFPUPCT004|Parar todos||
+#
+# Control de I-Gate
+IGPUPCF000|Opcoes I-Gate||
+IGPUPCF001|Desactiva todo o trafego da IGate||
+IGPUPCF002|So permite trafego de RF para Inet||
+IGPUPCF003|Permite trafego de RF->Inet e Inet->RF||
+IGPUPCF004|Caminho Igate -> RF ||
+#
+# Esta��o meteorologica
+WXPUPSI000|Estacao meteorologica||
+WXPUPSI001|Tipo de estacao meteorologica||
+WXPUPSI002|Datos actuais||
+WXPUPSI003|Curso do vento||
+WXPUPSI004|Velocidade do vento||
+WXPUPSI005|Rajada do vento||
+WXPUPSI006|Temperatura||
+WXPUPSI007|Total de chuva||
+WXPUPSI008|Total de chuva hoje||
+WXPUPSI009|Pressao barometrica||
+WXPUPSI010|Humidade relativa||
+WXPUPSI011|Peet Bros ULTIMETER 2000 Tipo (Modo dados log)||
+WXPUPSI012|Peet Bros ULTIMETER II Tipo||
+WXPUPSI013|Peet Bros ULTIMETER 2000 Tipo (Modo paquete)||
+WXPUPSI014|Horas totais de chuva||
+WXPUPSI015|Ultimas 24 tot. de chuvas||
+WXPUPSI016|Qualimetricos Q-Net||
+WXPUPSI017|Tipo Peet Bros ULTIMETER 2000 (Modo Completo)||
+WXPUPSI018|Ponto de Rocio||
+WXPUPSI019|Vento alto||
+WXPUPSI020|Vento frio||
+WXPUPSI021|Indice calorifico||
+WXPUPSI022|3-Hr Baro||
+WXPUPSI023|Alta temperat.||
+WXPUPSI024|Baixa temperat.||
+WXPUPSI025|Radio Shack WX-200/Oregon Scientific WM-918||
+WXPUPSI026|Davis Weather Monitor II/Wizard III/Vantage Pro||
+WXPUPSI027|LaCrosse WX-23xx||
+WXPUPSI028|Davis APRS Data Logger||
+#
+# Listas das estacoes
+LHPUPNI000|Todas as estacoes||
+LHPUPNI001|Estacoes moveis||
+LHPUPNI002|Estacaos meteorologicas||
+LHPUPNI003|Estacoes locais (via TNC)||
+LHPUPNI004|Ultimas estacoes||
+LHPUPNI005|Objectos e items||
+LHPUPNI006|Objectos e items proprios||
+LHPUPNI010| #||
+LHPUPNI011|Indicativo||
+LHPUPNI012|#Pack||
+LHPUPNI013|Ult. posicao||
+LHPUPNI014|Rota||
+LHPUPNI015|PHG||
+LHPUPNI016|Comentarios||
+LHPUPNI100|CSE||
+LHPUPNI101|SPD||
+LHPUPNI102|ALT.||
+LHPUPNI103|Lat||
+LHPUPNI104|Long||
+LHPUPNI105|#Pack||
+LHPUPNI106|LSV||
+LHPUPNI107|CFMS||
+LHPUPNI108|DFMS||
+LHPUPNI200|CSE||
+LHPUPNI201|SPD||
+LHPUPNI202|GST||
+LHPUPNI203|Temp||
+LHPUPNI204|Hum||
+LHPUPNI205|Baro||
+LHPUPNI206|RN-H||
+LHPUPNI207|RNSM||
+LHPUPNI208|RN24||
+LHPUPNI209|Lat/Lon ou UTM||
+#
+# Tracar alertas WX sobre mapas
+PULDNMAT01|Mostra mapa de alarmes sobre outros mapas||
+PULDNMAT02|Mostra mapa de alarmes debaixo de outros mapas||
+#
+# Error/popup mensagens
+POPEM00001|Localiza erro!||
+POPEM00002|A estacao %s nao foi encontrada!||
+POPEM00003|Rastrear erro!||
+POPEM00004|Erro do interface!||
+POPEM00005|Nome invalido da porta AX.25 %s||
+POPEM00006|Nome invalido da porta AX.25 %s||
+POPEM00007|Indicativo invalido %s||
+POPEM00008|Indicativo invalido AX.25 destinado ao digipeater||
+POPEM00009|Nao posso abrir o interface AX.25, %s||
+POPEM00010|Nao posso ligar o interface AX.25, %s||
+POPEM00011|Nao posso ligar ao indicativo AX.25, %s||
+POPEM00012|AX.25 erro na saida de UI||
+POPEM00013|AX.25 problema com o ficheiro /etc/ax25/axports||
+POPEM00014|AX.25 nome invalido da porta %s||
+POPEM00015|Erro abrindo o interface %d, falha grave||
+POPEM00016|Erro abrindo o interface %d tempo esgotado||
+POPEM00017|Nao ha mais interfaces disponiveis!||
+POPEM00018|Dado requerido - Simples linha de mensagem|
+POPEM00019|A porta de transmissao esta "off" para a porta %d|
+POPEM00020|Erro no banco de dados!|
+POPEM00021|AX.25 nao foi compilado no Xastir!||
+POPEM00022|Erro de entrada!|
+POPEM00023|Nome de localizacao nao especificada!|
+POPEM00024|Nome de localizacao especificada em uso!|
+POPEM00025|Nao encontrado!||
+POPEM00026|O rastreamento come�ara quando ele aparecer||
+POPEM00027|Info impropia. Alguns campos vazios?||
+POPEM00028|Nao se pode abrir o ficheiro||
+POPEM00029|Encontrado!||
+POPEM00030|Simbolo da estacao meteorologica||
+POPEM00031|Alterado para simbolo de WX '/_', outras opcoes: '\_' '/W' e '\W'||
+POPEM00032|Atencao: usando simbolos do servico nacional meteorologico!||
+POPEM00033|Nao ha dados GPS!||
+POPEM00034|Desactivando a TX da minha posicao ate ter dados validos do GPS!||
+POPEM00035|Atencao||
+POPEM00036|Aviso||
+POPEM00037|Interface HSP presente: tempo de GPS foi aumentado||
+POPEM00038|Name Conflicts With Existing Object/Item/Station||
+POPEM00039|Illegal characters found, substituting periods in their place||
+POPEM00040|Custom outgoing path was lost||
+POPEM00041|Processing another file. Wait a bit, then try again||
+POPEM00042|Object not owned by me! Try adopting the object first.||
+POPEM00043|Not an Object/Item!||
+POPEM00044|Fetch Findu Trail: Failed||
+POPEM00045|Fetch Findu Trail: Complete||
+POPEM00046|Berkeley DB header/shared library do NOT match! Disabling map cache.||
+POPEM00047|Global transmit is DISABLED. Emergency beacons are NOT going out!||
+POPEM00048|Emergency Beacon Mode!||
+POPEM00049|EMERGENCY BEACON MODE, transmitting every 60 seconds!||
+POPEM00050|Interfaces or posits/transmits DISABLED. Emergency beacons are NOT going out!||
+POPEM00051|Altnet is enabled (Configure->Defaults dialog)||
+POPEM00052|Callsign is EMPTY!||
+POPEM00053|Message is EMPTY!||
+POPEM00054|We're trying to talk to ourselves!||
+#
+# Salto de localizacao
+JMLPO00001|Localizacao de mapa||
+JMLPO00002|IR!||
+JMLPO00003|Nome da nova localizacao:||
+#
+# Boletins
+BULMW00001|Boletins||
+BULMW00002|Limite de alcance a (0, nao ha limite)||
+BULMW00003|Mudanca de alcance||
+#
+# Trafego de todas as mensagens
+AMTMW00001|Trafego de todas as mensagens||
+AMTMW00002|Limite de alcance a (0, nao ha limite)||
+#
+# Cadeias do sintetizador
+SPCHSTR001|Quilometros||
+SPCHSTR002|metros||
+SPCHSTR003|milhas||
+SPCHSTR004|jardas||
+SPCHSTR005|%s, distancia e %d %s.||
+SPCHSTR006|%s, distancia e %.1f %s.||
+SPCHSTR007|%s, distancia e %d %s %s %s.||
+SPCHSTR008|%s, distancia e %.1f %s %s %s.||
+SPCHSTR009|Novo alerta de tempo||
+SPCHSTR010|Indicativo novo||
+SPCHSTR011|Ouvido, D X, %s, na distancia de %.1f %s||
+#
+SPCHDIRN00|norte of||
+SPCHDIRS00|sul of||
+SPCHDIRE00|este of||
+SPCHDIRW00|oeste of||
+SPCHDIRNE0|nordeste of||
+SPCHDIRNW0|nordoeste of||
+SPCHDIRSE0|sudeste of||
+SPCHDIRSW0|sudoeste of||
+#
+# Dialogo da sele��o do simbolo
+SYMSEL0001|Selecionar simbolo||
+SYMSEL0002|Tabela de simbolo primario||
+SYMSEL0003|Tabela de simbolo secundario||
+#
+# Dialogo das propriedades da impressora
+PRINT0001|Propriedades da impressora||
+PRINT0002|Largura do papel||
+PRINT0003|Auto-rodar imagem
+PRINT0004|Rodar imagem 90� CCW||
+PRINT0005|Auto-balancear imagem||
+PRINT0006|Balanca:||
+PRINT0007|Forcar a pre-definida cor de fundo a branco||
+PRINT0008|Imprimir em branco e preto||
+PRINT0016|Cores invertidas||
+PRINT0009|Resolucao do postscript:||
+PRINT0010|Prevista||
+PRINT0011|Imprimir o ficheiro||
+PRINT0012|Guardar imagem num ficheiro...||
+PRINT0013|Convertendo para postscript...||
+PRINT0014|Criando arquivo de impressao finalizado||
+PRINT0015|Estado da impressora||
+#
+# Dialogo das propriedades da impressora
+PRINT1001|Direct to:||
+PRINT1002|Via Previewer:||
+#
+# Dialogo de localizar forma
+FEATURE001|Nome:||
+FEATURE002|Estado/provincia:||
+FEATURE003|Pas:||
+FEATURE004|Mapa quad:||
+FEATURE005|Tipo:||
+FEATURE006|GNIS arquivo:||
+FEATURE007|Address:||
+FEATURE008|City:||
+FEATURE009|Mark Destination||
+FEATURE010|Zip Code:||
+FEATURE011|Geocoding File||
+#
+# Dialogo do calculo de coordenadas
+COORD001|Calcular coordenadas||
+COORD002|Calc||
+COORD003|Calcular||
+COORD004|Limpar||
+COORD005|UTM||
+COORD006|Latitude ou||
+COORD007|Longitude ou||
+COORD008|Zona||
+COORD009|UTM indo para este||
+COORD010|UTM indo para norte||
+COORD011| Decimal Degrees: ||
+COORD012| Degrees/Decimal Minutes: ||
+COORD013| Degrees/Minutes/Dec. Seconds: ||
+COORD014| Universal Transverse Mercator: ||
+COORD015|Military Grid Reference System: ||
+COORD016| Maidenhead Grid Locator: ||
+COORD017| ** Sorry, your input was not recognized! **||
+COORD018| ** Please use one of the following input formats: **||
+#
+#
+# Dialogo do smart beaconing
+SMARTB001|Beaconing esperto||
+SMARTB002|Racio alto (secs):||
+SMARTB003|Velocidade alta (mph):||
+SMARTB004|Velocidade alta (kph):||
+SMARTB005|Racio baixo (mins):||
+SMARTB006|Velocidade baixa (mph):||
+SMARTB007|Velocidade baixa (kph):||
+SMARTB008|Voltar ao minimo (deg):||
+SMARTB009|Virar encosta:||
+SMARTB010|Tempo de espera (secs):||
+SMARTB011|Activar SmartBeaconing(tm)||
+#
+#
+#
+# Dialogo do gamma adjust
+GAMMA001|Correccao do ajuste gamma||
+GAMMA002|Correccao gamma||
+#
+#
+# Dialogo das fontes de etiquetas dos mapas
+MAPFONT001|Change Fonts||
+MAPFONT002|Fonts||
+MAPFONT003|Map Muito pequeno Font||
+MAPFONT004|Map Font Pequeno||
+MAPFONT005|Map Font Medio||
+MAPFONT006|Map Font Grande||
+MAPFONT007|Map Font Enorme||
+MAPFONT008|Map Font Border||
+MAPFONT009|Menu Font||
+MAPFONT010|Station Font||
+MAPFONT011|ATV ID Font||
+#
+# Distancia/rumo na linha de estados
+PULDNDB001|Estado dist/rumo||
+#
+#
+# Operacoes transferencias de GPS
+GPS001|Transferir GPS||
+GPS002|Ficheiro||
+GPS003|Escolher cor||
+GPS004|Vermelho||
+GPS005|Verde||
+GPS006|Preto||
+GPS007|Branco||
+GPS008|Laranja||
+GPS009|Azul||
+GPS010|Amarelo||
+GPS011|Violeta||
+#
+#
+# Dialogo de propriedades dos mapas
+MAPP001|Propriedades dos mapas||
+MAPP002| Max Min Desenhar mapas USGS||
+MAPP003| Zoom Zoom Camada Preenchido DRG AutoMapa Caminho/Ficheiro||
+MAPP004|Mudar camada->||
+MAPP005|Preenchido->||
+MAPP006|Sim||
+MAPP007|Nao||
+MAPP008|Automapas->||
+MAPP009|Max Zoom->||
+MAPP010|Min Zoom->||
+MAPP011|Auto||
+MAPP012|USGS DRG->||
+#
+#
+# Marcas do tempo
+TIME001|Dia||
+TIME002|Dias||
+TIME003|Hora||
+TIME004|Horas||
+TIME005|Minuto||
+TIME006|Minutos||
+TIME007|Segundo||
+TIME008|Segundos||
+#
+#
+# Map Caching
+CACHE001|Map now cached||
+CACHE002|Loading Cached Map||
+CACHE003|Map not found in cache...||
+#
+#
+# Map Screen Misc
+RANGE001|RANGE SCALE||
+#
+#
+# GPS Status
+GPSS001|WAAS or PPS||
+GPSS002|DGPS||
+GPSS003|Valid SPS||
+GPSS004|Invalid||
+GPSS005|Sats/View||
+GPSS006|Fix||
+GPSS007|!GPS data is older than 30 seconds!||
+GPSS008|Simulation||
+GPSS009|Manual||
+GPSS010|Estimated||
+GPSS011|Float RTK||
+GPSS012|RTK||
+#
+#
+# Popup cad_dialog to obtain CAD object data
+CADPUD001|Area Object||
+CADPUD002|Area Label:||
+CADPUD003|Comment:||
+CADPUD004|Probability (%):||
+CADPUD005|OK||
+CADPUD006|CAD Dialog||
+CADPUD007|Show/Edit Details||
+CADPUD008|Cancel||
+CADPUD009|Delete CAD objects?||
+CADPUD010|Delete All||
+CADPUD011|Delete Selected||
+CADPUD012|Solid||
+CADPUD013|Dashed||
+CADPUD014|Double Dash||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA001|XASTIR Map of %s (upper left) to %s (lower right). UTM %d m grid, %s datum. ||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA002|XASTIR Map of %s (upper left) to %s %s (lower right). Lat/Long grid, %s datum.||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA003|XASTIR Map of %s (upper left) to %s (lower right). UTM zones, %s datum.||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST001|MySQL (lat/long)||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST002|Postgreql with Postgis||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST003|MySQL (spatial)||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA01|Xastir Simple Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA02|Xastir CAD Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA03|Xastir full Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA04|APRSWorld Schema||
diff --git a/config/language-Spanish.sys b/config/language-Spanish.sys
new file mode 100644
index 0000000..9a986ca
--- /dev/null
+++ b/config/language-Spanish.sys
@@ -0,0 +1,1345 @@
+# $Id: language-Spanish.sys,v 1.237 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# Este es el archivo del Lenguaje Espa�ol usado para todas, consultas en Xastir.
+#
+# Creador : por Jose R. Marte A. <hi8gn at amsat.org>
+# Mantenido por : El Xastir Grupo <xastir at xastir.org>
+# Ult. Revisi�n : 05/20/2003, Por Jose R. Marte A. <hi8gn at amsat.org>
+#
+# L�neas de comentarios con un signo de libra en frente son ignorado
+# El formato del archivo es como sigue:
+# Id (10 caract�res alfa num�rico)|(Cadena asociada con id)|TeclaR�pida|#comentario
+#
+# AVISO:
+# Algunas cadenas de letras contienen comando de formato como %s y %d, usted no
+# deber�a cambiar eso. Cadena de formatos errados podr�an producir un segfault!
+#
+# Men� Principal
+MENUTB0001|Archivo|A|
+MENUTB0002|Visualizar|V|
+MENUTB0004|Mapas|M|
+MENUTB0005|Estaciones|S|
+MENUTB0006|Mensajes|e|
+MENUTB0010|Interfaces|I|
+MENUTB0009|Ayuda|y|
+#
+# Men� archivo
+PULDNFI001|Configurar|C|
+PULDNFI002|Abrir Bit�cora|B|
+PULDNFI003|Prueba|P|
+PULDNFI004|Salir|S|
+PULDNFI007|Cambia nivel Depuraci�n|D|
+PULDNFI010|Bit�cora del TNC|T|
+PULDNFI011|Bit�cora de Internet|I|
+PULDNFI012|Bit�cora del I-Gate|G|
+PULDNFI013|Bit�cora del WX|W|
+PULDNFI014|Activa PNG Instant�nea||
+PULDNFI015|Imprimir Mapa|P|
+PULDNFI016|KML Snapshots||
+#
+# Men� visor
+PULDNVI001|Boletines|B|
+PULDNVI002|Datos entrantes|D|
+PULDNVI003|Estaciones M�viles|M|
+PULDNVI004|Todas las Estaciones|T|
+PULDNVI009|Estaciones Locales|L|
+PULDNVI012|�ltimas Estaciones|U|
+PULDNVI005|Estaciones Meteorol�gicas|E|
+PULDNVI008|Su Estaci�n Meteorol�gica|S|
+PULDNVI007|Alerta del tiempo|A|
+PULDNVI011|Tr�ficos de Mensajes|f|
+PULDNVI013|Tiempo de Inicio|I|
+PULDNVI014|Tiempo Transcurrido||
+PULDNVI015|GPS Status||
+PULDNVI016|ALOHA Statistics||
+#
+# Men� de Configuraci�n
+PULDNCF004|Estaci�n|E|
+PULDNCF001|Predefinidos|P|
+PULDNCF003|Cron�metro|t|
+PULDNCF002|Sistema de Coordenada|C|
+PULDNCF006|Alarmas de Audio|A|
+PULDNCF007|Sintetizador de Voz|S|
+PULDNCF008|Guardar Configuraci�n!|G|
+#
+# Men� de Mapas
+PULDNMP001|Seleccionar Mapas|M|
+PULDNMP012|Saltar a una Locaci�n|S|
+PULDNMP014|Localice rasgo del Mapa|L|
+PULDNMP016|Disable Fast Zoom/Pan/Home||
+PULDNMP013|Desactive todos los Mapas||
+PULDNMP002|Activar Auto Mapas||
+PULDNMP003|Rejillas sobre Mapa||
+PULDNMP004|Niveles de Mapas||
+PULDNMP010|Etiquetas de Mapas||
+PULDNMP009|Activar Areas Coloridas||
+PULDNMP007|Alerta Mapa WX||
+PULDNMP005|Color de fondo|C|
+PULDNMP006|Etiquetas de estiones|E|
+PULDNMP026|Icon Outline Style|O|
+PULDNMP011|Men� Indicador del Rat�n|R|
+PULDNMP008|Intensidad del Mapa|I|
+PULDNMP020|Configurar Tigermapa||
+PULDNMP021|Auto Mapa - Desactivar Mapas de Trama||
+PULDNMP022|Indezar Mapas en Inicio||
+PULDNMP023|Indice: Agregar Nuevos Mapas|A|
+PULDNMP024|Indice: Reindezar TODOS los Mapas|T|
+PULDNMP025|Fonts||
+PULDNMP015|Xfontsel||
+PULDNMP027|Re-download Maps (Not from cache)||
+PULDNMP028|Flush Entire Map Cache!||
+PULDNMP029|Find Address||
+PULDNMP030|Configure USGS DRG||
+PULDNMP031|Enable Map Border||
+#
+# Men� "Configurar Tigermapa"
+MPUPTGR001|Rejilla||
+MPUPTGR002|Condados||
+MPUPTGR003|Etiquetas de Ciudades||
+MPUPTGR004|Areas Urbanas||
+MPUPTGR005|Caminos Principales||
+MPUPTGR006|Calles||
+MPUPTGR007|Ferrocarriles||
+MPUPTGR008|Etiquetas de Estados||
+MPUPTGR009|Etiquetas de Inter-estatar||
+MPUPTGR010|Etiquetas de Carretera||
+MPUPTGR011|Etiquetas de Carretera en Estados||
+MPUPTGR012|Seleccionar art�culos a ser desplegado:||
+MPUPTGR013|Rios||
+MPUPTGR014|Lagos||
+MPUPTGR015|Aereopuertos, Parqueos, etc||
+MPUPTGR016|Intensidad de Mapa||
+MPUPTGR017|Internet Map Timeout (segundo)||
+MPUPTGR018|Activar Tiger Mapas||
+#
+# PopUp "Configure USGS DRG"
+MPUPDRG001|Select items to be displayed:||
+MPUPDRG002|Tint Underlying Map (XOR)||
+MPUPDRG003|Black||
+MPUPDRG004|White||
+MPUPDRG005|Blue||
+MPUPDRG006|Red||
+MPUPDRG007|Brown||
+MPUPDRG008|Green||
+MPUPDRG009|Purple||
+MPUPDRG010|Yellow||
+MPUPDRG011|Light Blue||
+MPUPDRG012|Light Red||
+MPUPDRG013|Light Purple||
+MPUPDRG014|Light Gray||
+MPUPDRG015|Light Brown||
+#
+# Seleccion de Mapas
+WPUPMCP001|Selecci�n de Mapa||
+PULDNMMC01|Limpiar|N|
+PULDNMMC02|Vectores|V|
+PULDNMMC03|250k Topo|2|
+PULDNMMC04|100k Topo|1|
+PULDNMMC05|24k Topo|4|
+PULDNMMC06|Expandir Dirs|||
+PULDNMMC07|Dirs/Mapas Seleccionado:||
+PULDNMMC08|Clear Dirs|C|
+PULDNMMC09|Select All|S|
+#
+# Colores de fondo del mapa
+PULDNMBC01|Gris||
+PULDNMBC02|Rosado M�stico||
+PULDNMBC03|Azul Marino||
+PULDNMBC04|Azul acerado||
+PULDNMBC05|Med. Verde mar||
+PULDNMBC06|Verde P�lido||
+PULDNMBC07|Dorado P�lido||
+PULDNMBC08|Dorado Amarillo||
+PULDNMBC09|Marr�n Rosado||
+PULDNMBC10|Rojo ladrillo||
+PULDNMBC11|Blanco||
+PULDNMBC12|Negro||
+#
+# Mapas Estaciones estilos de etiquetas
+PULDNMSL01|Fondo Negro||
+PULDNMSL02|Fondo Gris||
+PULDNMSL03|Texto en Negro|T|
+#
+# PullDown "Icon Outline Style"
+PULDNMIO01|No Outline|N|
+PULDNMIO02|Black Outline|B|
+PULDNMIO03|Grey Outline|G|
+PULDNMIO04|White Outline|W|
+#
+# Switches ON/OFF/Corto
+PULDNOT001|On||
+PULDNOT002|Off||
+PULDNOT003|Corto||
+#
+# Men� de Despliegue de Estaciones
+PULDNDP014|Localizar Estaci�n|L|
+PULDNDP001|Rastreo de Estaci�n|E|
+PULDNDP022|Sacar Rastro de Findu|F|
+PULDNDP032|Filtrar Datos||
+PULDNDP040|- Seleccionar Nada||
+PULDNDP041|- Seleccionar M�o||
+PULDNDP042|- Seleccionar TNC||
+PULDNDP027|- Seleccionar Directo||
+PULDNDP043|- Seleccionar V�a Digi||
+PULDNDP034|- Seleccionar Red||
+PULDNDP019|Incluir Datos Expirados||
+PULDNDP044|- Seleccionar Estaciones||
+PULDNDP028|- Seleccionar Estaciones Fijas||
+PULDNDP029|- Seleccionar Estaciones M�viles||
+PULDNDP030|- Seleccionar Estaciones de WX||
+PULDNDP053| - Select CWOP WX Stations||
+PULDNDP045|- Seleccionar Objetos/Art�culos||
+PULDNDP026|- Seleccionar Objetos/Art�culos de WX||
+PULDNDP039|- Seleccionar Objetos/Art�culos Medidores de Agua||
+PULDNDP031|- Seleccionar Otros Objetos/Art�culos||
+PULDNDP033|Filtrar Visualizaci�n||
+PULDNDP010|Mostrar Indicativo|I|
+PULDNDP012|Mostrar S�mbolo|D|
+PULDNDP011|- S�mbolo Rotado|S|
+PULDNDP007|Mostrar Rastros|R|
+PULDNDP003|Mostrar Curso|C|
+PULDNDP004|Mostrar Velocidad|V|
+PULDNDP017|- Mostrar Velocidad Corta||
+PULDNDP002|Mostrar Altura|A|
+PULDNDP009|Mostrar Informe del Tiempo|T|
+PULDNDP046|- Mostrar Texto||
+PULDNDP018|- S�lo la Temperatura||
+PULDNDP047|- Mostrar Indicaci�n de Viento||
+PULDNDP054|Display Aloha Circle||
+PULDNDP013|Mostrar Ambig�edad de Posici�n||
+PULDNDP008|Mostrar Potencia/Ganancia|P|
+PULDNDP021|- Usar Pot/Ganancia por Defecto||
+PULDNDP020|- Mostrar Pot/Ganancia M�viles||
+PULDNDP023|Mostrar atributos DF||
+PULDNDP123|Display DF Beamwidth||
+PULDNDP223|Display DF Bearing||
+PULDNDP035|Activar Conteo-Muerto||
+PULDNDP036|- Mostrar Arco||
+PULDNDP037|- Mostrar Curso||
+PULDNDP038|- Mostrar S�mbolo||
+PULDNDP005|Mostrar Orientaci�n/Distancia|D|
+PULDNDP024|Mostrar Tiempo del Ultimo Informe||
+PULDNDP015|Anular Todas las Estaciones|A|
+PULDNDP016|Limpiar Rastros|n|
+PULDNDP025|Limpiar Historia de Objeto/Art�culo||
+PULDNDP048|Recargar Historia de Objeto/Art�culo||
+PULDNDP049|Clear All Tactical Calls||
+PULDNDP050|Clear Tactical Call History||
+PULDNDP051|Select Tactical Calls Only||
+PULDNDP052|- Label Trailpoints||
+PULDNDP055|Export all|E|
+PULDNDP056|Export to KML File||
+#
+# Inglesa/M�trica
+PULDNUT001|Activar Unidades Inglesa||
+PULDNUT002|M�trica||
+#
+# Men� de Mensajes
+PULDNMG001|Enviar Mensaje A|E|
+PULDNMG002|Abrir Mensajes Grupos|G|
+PULDNMG003|Anular todos mensajes saliente|B|
+PULDQUS001|Pregunta General a Estaciones|P|
+PULDQUS002|Pregunta a Estaciones I-Gate|I|
+PULDQUS003|Pregunta a Estaciones WX|W|
+PULDNMG004|Fijar Mensaje en Contestaci�n Autom�tica|F|
+PULDNMG005|Activar Auto contestaci�n de Mensaje|A|
+PULDNMG006|Sat�lite Modo de Reconocimiento|M|
+PULDNMG007|Show Pending Messages|P|
+#
+# Men� de Interfaces
+PULDNTNT04|Interface Control||
+PULDNTNT03|Desactivar Transmitir: TODOS||
+PULDNTNT05|Desactivar Transmitir: Mi Posici�n||
+PULDNTNT06|Desactivar Transmitir: Objetos/Art�culos||
+PULDNTNT11|Enable Server Port||
+PULDNTNT01|Transmitir Ahora..!|T|
+PULDNTNT07|Coger Huella de GPS|F|
+PULDNTNT08|Coger Rutas de GPS|R|
+PULDNTNT09|Coger V�aPuntos de GPS|W|
+PULDNTNT10|Fetch Garmin RINO Waypoints|G|
+#
+# Men� de Ayuda
+PULDNHEL01|Acerca de|A|
+PULDNHEL02|Indice de Ayuda|I|
+PULDNHEL03|EMERGENCY BEACON MODE ENABLE|E|
+PULDNHEL04|!!! EMERGENCY BEACON MODE !!!||
+PULDNHEL05|About Xastir||
+#
+# Men� de Rat�n
+POPUPMA001|Opciones||
+POPUPMA00c|Centro||
+POPUPMA015|Info de estaci�n||
+POPUPMA002|Acercar|A|
+POPUPMA003|Alejar|l|
+POPUPMA004|Nivel de Enfoque|N|
+POPUPMA005|Nivel 1|1|
+POPUPMA006|Nivel 16|6|
+POPUPMA007|Nivel 64|4|
+POPUPMA008|Nivel 256|2|
+POPUPMA009|Nivel 1024|0|
+POPUPMA010|Nivel 8192|8|
+POPUPMA017|El Mundo Entero|E|
+POPUPMA016|Ultima Pos/Enfoque del Mapa|P|
+POPUPMA018|Crear Objeto/Art�culo|C|
+POPUPMA019|Modificar Objeto/Art�culo|M|
+POPUPMA025||Mover Mi Estaci�n Aqu�|A|
+POPUPMA011|Paneo arriba|u|
+POPUPMA012|Paneo abajo|d|
+POPUPMA013|Paneo izquierda|l|
+POPUPMA014|Paneo derecha|r|
+POPUPMA020|Medida||
+POPUPMA021|Movimiento||
+POPUPMA022|Rastr�eMe||
+POPUPMA023|Modificadores Encontrado!||
+POPUPMA024|Por favor apague OFF CapsLock/NumLock/ScrollLock/otro modificadores||
+POPUPMA026|Centre & Enfoque||
+POPUPMA027| Latitud||
+POPUPMA028| Longitud||
+POPUPMA029|Dibuje Objetos CAD||
+POPUPMA030|Draw||
+POPUPMA031|Cierre el Pol�gono||
+POPUPMA032|Erase CAD Polygons||
+POPUPMA033|**NOT USED**||
+POPUPMA034|Custom Zoom Level||
+POPUPMA035|10% out||
+POPUPMA036|10% in||
+POPUPMA037|Area||
+POPUPMA038|square||
+POPUPMA039|square feet||
+POPUPMA040|square meters||
+POPUPMA041|Bearing||
+POPUPMA042|degrees||
+POPUPMA043|Modify ambiguous position||
+POPUPMA044|Position abiguity is on, your new position may appear to jump.||
+POPUPMA045|Predefined Objects||
+POPUPMA046|CAD Polygons||
+POPUPMA047|Enable CAD objects||
+POPUPMA048|Enable CAD labels||
+POPUPMA049|Enable CAD comments||
+POPUPMA050|Enable CAD probability||
+POPUPMA051|Enable CAD area size||
+POPUPMA052|sq||
+POPUPMA053|ft||
+POPUPMA054|meters||
+POPUPMA055|mi|
+#
+# Men� de Estados de la l�neas de Etiquetas
+BBARZM0001|Foco %s||
+BBARZM0002|Foco %s Tr||
+BBARSTH001|%d/%d Estaciones||
+BBARSTA000|%-9s Nuevo objeto!||
+BBARSTA001|%-9s Nueva estaci�n!||
+BBARSTA002|%s||
+BBARSTA003|Cargando mapas...||
+BBARSTA004|Mapas cargados...||
+BBARSTA005|Mapa Lat/Long Rejilla es ON||
+BBARSTA006|Mapa Lat/Long Rejilla es OFF||
+BBARSTA007|El uso de Auto Mapas, es ON||
+BBARSTA008|El uso de Auto Mapas, es OFF||
+BBARSTA009|Los Niveles del Mapa est�n ON||
+BBARSTA010|Los Niveles del Mapa est�n OFF||
+BBARSTA011|Auto contestaci�n de Mensaje es OFF!||
+BBARSTA012|Achivo creado..||
+BBARSTA013|Abriendo Puerto GPS||
+BBARSTA014|Cerrando Puerto GPS||
+BBARSTA015|Obtenido GPS RMC Cord�n||
+BBARSTA016|Obtenido GPS GGA Cord�n||
+BBARSTA017|Red desconectada del Servidor||
+BBARSTA018|Conexi�n a Red tiempo vencido!||
+BBARSTA019|Buscando Servidor %s||
+BBARSTA020|Conectado al %s||
+BBARSTA021|Fracaso en conexi�n de la Red!||
+BBARSTA022|Podr�a no atar el s�calo!||
+BBARSTA023|No IP para el Servidor!||
+BBARSTA024|No Servidor Especificado||
+BBARSTA025|Servidor encontrado, Conectando %d||
+BBARSTA026|Esperando por datos del GPS v�a HSP..||
+BBARSTA027|Limpiando el HSP datos obtenido del TNC..||
+BBARSTA028|Cargando %s||
+BBARSTA029|Abriendo Puerto WX||
+BBARSTA030|Cerrando Puerto WX||
+BBARSTA031|Buscando el Servidor %d||
+BBARSTA032|Datos de WX Decodificado||
+BBARSTA033|Eco desde digipeater||
+BBARSTA034|Cargando Mapas de alerta WX||
+BBARSTA035|Esperando por datos del GPS v�a AUX..||
+BBARSTA036|Limpiando el AUX datos obtenido del TNC..||
+BBARSTA037|Datos de GPS Decondificado||
+BBARSTA038|Coloque el cambio en mi estaci�n||
+BBARSTA039|Indezando %s||
+BBARSTA040|Estaci�n de Aficionado APRS(tm) %s||
+BBARSTA041|Esperando por GPS data..||
+BBARSTA042|Transmitiendo objetos/articulos||
+BBARSTA043|Anotando||
+BBARSTA044|ALOHA distance is %d%s||
+BBARSTA045|Loading symbols...||
+BBARSTA046|Reloading symbols...||
+BBARSTA047|Initialize my station...||
+BBARSTA048|Start interfaces...||
+BBARSTA049|Reading tiles...||
+BBARSTA050|Downloading tiles...||
+BBARSTA051|Downloading tile %li of %li||
+#
+# Despliegue Paquete de Datos
+WPUPDPD001|Despligue de Datos||
+WPUPDPD002|s�lo datos del TNC||
+WPUPDPD003|s�lo datos de la Red||
+WPUPDPD004|Datos del TNC y la Red||
+WPUPDPD005|TNC||
+WPUPDPD006|RED||
+WPUPDPD007|Station Capabilities||
+WPUPDPD008|Mine Only||
+#
+# Localizar Estaci�n
+WPUPLSP001|Localizar estaci�n||
+WPUPLSP002|Localizar Indicativo||
+WPUPLSP003|Macheo Sensible|S|
+WPUPLSP004|Macheo Exacto|E|
+WPUPLSP005|Localizar ahora!|A|
+WPUPLSP006|Localizar Emergencia!||
+WPUPLSP007|FCC/RAC Lookup||
+#
+# Configurar predefinidos
+WPUPCFD001|Configurar valores predefinidos||
+WPUPCFD002|desde qu� int�rvalo de tiempo ser� considerada una estaci�n vieja?||
+WPUPCFD003|15 minutos|1|
+WPUPCFD004|30 minutos|3|
+WPUPCFD005|45 minutos|4|
+WPUPCFD006|1 hora|H|
+WPUPCFD007|90 minutos|9|
+WPUPCFD008|2 horas|2|
+WPUPCFD009|desde qu� int�rvalo de tiempo la estaci�n no ser� desplegada?||
+WPUPCFD010|6 horas|6|
+WPUPCFD011|12 horas|o|
+WPUPCFD012|1 D�a|D|
+WPUPCFD013|2 D�as|s|
+WPUPCFD014|1 semana|n|
+WPUPCFD015|Opci�n modo de Transmisi�n de la estaci�n||
+WPUPCFD016|Estaci�n Fija|F|
+WPUPCFD017|Estaci�n M�vil c/Hora local|l|
+WPUPCFD018|Estaci�n M�vil c/Fecha-hora Z�lu|Z|
+WPUPCFD019|Estaci�n M�vil c/Horas-segundos Z�lu|u|
+WPUPCFD021|Posici�n de la estaci�n c/Tiempo|T|
+WPUPCFD022|Posici�n de la estaci�n, fecha-hora Zulu, y Tiempo|f|
+WPUPCFD023|Transmitir datos WX en Raw?||
+WPUPCFD024|Comprimir datos objeto/art�culo cuando transmita?||
+WPUPCFD025|Activar Red Alternada?|A|
+WPUPCFD026|Enviar reportes de posici�n en qu� int�rvalos?||
+WPUPCFD027|Mostrar bulletines Nuevo||
+WPUPCFD028|Avisar si hay teclas Modificadora||
+WPUPCFD029|Ver boletines de zero-distancia||
+WPUPCFD030|Disable Posit Dupe-Checks||
+WPUPCFD031|Load predefined objects from file||
+WPUPCFD032|My trails in one color||
+WPUPCFD033|ALTNET:||
+#
+# Menu "Configurar - Cron�metro"
+WPUPCFTM01|Configurar Cron�metro||
+WPUPCFTM02|TX Posici�n Int�rvalo (minutos)||
+WPUPCFTM03|Desvanecimiento de la Estaci�n (minutos)||
+WPUPCFTM04|Objeto/Art�culo TX Max Int�rvalo (minutos)||
+WPUPCFTM05|Limpiar Tiempo de la Estaci�n (horas)||
+WPUPCFTM06|Chequeo Int�rvalo del GPS (segundos)||
+WPUPCFTM07|Borrar Tiempo de la Estaci�n (d�as)||
+WPUPCFTM08|Descanso Conteo-Muerto (minutos)||
+WPUPCFTM09|Serial Inter-Char Delay (ms)||
+WPUPCFTM10|Nuevo Tiempo Rastro (min)||
+WPUPCFTM11|Nuevo Interval Rastro (grados)||
+WPUPCFTM12|RINO -> Objects Interval (min), 0 = Disabled||
+WPUPCFTM13|Snapshot Interval (min)||
+#
+# Configurar Sistema de Coordenada"
+WPUPCFC001|Configurar Sistema de Coordenada||
+WPUPCFC002|Seleccione Sistema de Coordenada||
+WPUPCFC003|dd.ddddd|d|
+WPUPCFC004|dd mm.mmm|m|
+WPUPCFC005|dd mm ss.s|s|
+WPUPCFC006|UTM|U|
+WPUPCFC007|USNG/MGRS2||
+WPUPCFC008|UTM con zonas especiales||
+#
+# Configurar GPS
+WPUPCFG001|Configurar GPS||
+WPUPCFG003|Puerto exclusivo de GPS||
+WPUPCFG002|Usar Posici�n GPS?||
+WPUPCFG004|opciones del GPS||
+WPUPCFG005|GPS Exclusivo||
+WPUPCFG006|TNC conectado a GPS (Cable HSP)||
+WPUPCFG007|TNC conectado a GPS usando CTL-E||
+WPUPCFG008|GPS tiempo (Muestreo cada)||
+WPUPCFG009|5 sec||
+WPUPCFG010|15 sec||
+WPUPCFG011|30 sec||
+WPUPCFG012|1 minuto||
+WPUPCFG013|2 minutos||
+WPUPCFG014|5 minutos||
+WPUPCFG015|10 minutos||
+WPUPCFG016|Red conectada al GPS||
+WPUPCFG017|Servidor GPSD||
+WPUPCFG018|Puerto GPSD||
+WPUPCFG019|Red GPS v�a GPSD||
+WPUPCFG020|Reconectar en fallo?||
+WPUPCFG021|Red Conectada a WX||
+WPUPCFG022|Servidor WX||
+WPUPCFG023|Puerto WX||
+#
+# Configurar TNC (baudio tambi�n son para WX)
+WPUPCFT001|Configurar TNC||
+WPUPCFT002|Usar TNC?||
+WPUPCFT003|Puerto TNC||
+WPUPCFT004|Velocidad del Puerto||
+WPUPCFT005|300 bps||
+WPUPCFT006|1200 bps||
+WPUPCFT007|2400 bps||
+WPUPCFT008|4800 bps||
+WPUPCFT009|9600 bps||
+WPUPCFT010|19200 bps||
+WPUPCFT011|Rutas del UnProto||
+WPUPCFT012|Ruta 1: %s v�a ||
+WPUPCFT013|Ruta 2: %s v�a ||
+WPUPCFT014|Ruta 3: %s v�a ||
+WPUPCFT015|Modo del Puerto||
+WPUPCFT016|8,N,1||
+WPUPCFT017|7,E,1||
+WPUPCFT018|7,O,1||
+WPUPCFT019|38400 bps||
+WPUPCFT020|57600 bps||
+WPUPCFT021|115200 bps||
+WPUPCFT022|230400 bps||
+WPUPCFT023|Configurar el TNC c/HSP GPS||
+WPUPCFT024|Tipo de Data||
+WPUPCFT025|Auto detecci�n||
+WPUPCFT026|Tipo Binario||
+WPUPCFT027|Tipo ASCII||
+WPUPCFT028|Configurar el TNC c/AUX GPS||
+WPUPCFT029|Configurar el TNC c/MAL ENUM||
+WPUPCFT030|Configurar un KISS TNC||
+WPUPCFT031|Archivos de Configuraci�n del TNC||
+WPUPCFT032|Arreglar Archivo del TNC||
+WPUPCFT033|Archivo de apagar TNC||
+WPUPCFT034|Par�metros TNC KISS modo||
+WPUPCFT035|TXDelay (10 ms unidades)||
+WPUPCFT036|Persistence (0 to 255)||
+WPUPCFT037|SlotTime (10 ms unidades)||
+WPUPCFT038|TxTail (10 ms unidades)||
+WPUPCFT039|Full Duplex||
+WPUPCFT040|Configurar un Multi-Port KISS TNC||
+WPUPCFT041|Radio Port||
+WPUPCFT042|Dubious UNPROTO Path!||
+WPUPCFT043|Please consider a shorter path such as WIDE2-2 or WIDE1-1,WIDE2-2||
+WPUPCFT044|Dubious IGATE Path!||
+WPUPCFT045|Transmitting w/Dubious UNPROTO Path!||
+WPUPCFT046|Transmitting w/Dubious IGATE Path!||
+WPUPCFT047|Init KISS-mode on startup||
+#
+# Configurar el Puerto de la Estaci�n Meteorol�gica
+WPUPCFWX01|Configurar el Puerto de la Estaci�n Meteorol�gica||
+WPUPCFWX02|Dispositivo de la Estaci�n Meteorol�gica||
+WPUPCFWX03|Tipo Medida de lluvia (Configuraci�n Global)||
+WPUPCFWX04|0.1 pg / 2.5 mm||
+WPUPCFWX05|0.01 pg / 0.25 mm||
+WPUPCFWX06|0.1 mm||
+WPUPCFWX07|No Correcci�n||
+#
+# Configurar la Estaci�n
+WPUPCFS001|Configurar la estaci�n||
+WPUPCFS002|Indicativo||
+WPUPCFS003|Latitud||
+WPUPCFS004|grd||
+WPUPCFS005|min||
+WPUPCFS006|(N/S)||
+WPUPCFS007|Longitud||
+WPUPCFS008|(E/W)||
+WPUPCFS009|S�mbolo de la estaci�n||
+WPUPCFS010|Grupo/sobrepuesto||
+WPUPCFS011|S�mbolo||
+WPUPCFS028|Seleccione||
+WPUPCFS012|Potencia - Altura (HAAT) - Ganancia y Direcci�n||
+WPUPCFS013|Desactive PHG||
+WPUPCFS014|Altura de la Antena||
+WPUPCFS015|Ganancia de la Antena||
+WPUPCFS016|Omni||
+WPUPCFS017|Comentarios:||
+WPUPCFS018|Posici�n ambig�a||
+WPUPCFS019|Ninguna||
+WPUPCFS020|.11 milla||
+WPUPCFS021|1.15 millas||
+WPUPCFS022|11.51 millas||
+WPUPCFS023|69.09 millas||
+WPUPCFS024|.18 kil�metro||
+WPUPCFS025|1.85 kil�metros||
+WPUPCFS026|18.53 kil�metros||
+WPUPCFS027|111.19 kil�metros||
+WPUPCFS029|Env�o de posici�n comprimida|C|
+#
+# Di�logo de Objeto/Art�culo
+POPUPOB001|Objeto/Ar�culo||
+POPUPOB002|Nombre:||
+POPUPOB003|Crear Nuevo Objeto||
+POPUPOB004|Borrar Objeto||
+POPUPOB005|Modificar Objeto||
+POPUPOB006|Crear Nuevo Art�culo||
+POPUPOB007|Area de Objeto||
+POPUPOB008|Activar Area de Objeto||
+POPUPOB009|Color Luminoso||
+POPUPOB010|Area Colorida||
+POPUPOB011|C�rculo||
+POPUPOB012|L�nea-Derecha '/'||
+POPUPOB013|L�nea-Izquierda '\'||
+POPUPOB014|Tri�ngulo||
+POPUPOB015|Rect�ngulo||
+POPUPOB016|Negro||
+POPUPOB017|Azul||
+POPUPOB018|Verde||
+POPUPOB019|Cian||
+POPUPOB020|Rojo||
+POPUPOB021|Violeta||
+POPUPOB022|Amarillo||
+POPUPOB023|Gris||
+POPUPOB024|Compense Arriba:||
+POPUPOB025|Compense Izq.(Excepto '/'):||
+POPUPOB026|Corridor:||
+POPUPOB027|Opciones Gen�ricas||
+POPUPOB028|Situaci�n||
+POPUPOB029|Activar Letrero||
+POPUPOB030|Data:||
+POPUPOB031|Letrero Objeto||
+POPUPOB032|Activar Compresi�n||
+POPUPOB033|Borrar Art�culo||
+POPUPOB034|Modificar Art�culo||
+POPUPOB035|Altitud (Pies):||
+POPUPOB036|Velocidad (Nudos):||
+POPUPOB037|Curso:||
+POPUPOB038|DF Objeto||
+POPUPOB039|Se�al - Altura(HAAT) - Ganancia - Direcci�n||
+POPUPOB040|Dirigiendo - Ancho de la orientaci�n||
+POPUPOB041|Antena Omni-direccional||
+POPUPOB042|Antena Direccional||
+POPUPOB043|In�til||
+POPUPOB044|Adopt Object||
+POPUPOB045|Adopt Item||
+POPUPOB046|DF Bearing:||
+POPUPOB047|Probability Circles||
+POPUPOB048|Map View Object||
+POPUPOB049|Min (mi):||
+POPUPOB050|Max (mi):||
+#
+# Configurar Internet
+WPUPCFI001|Configurar Internet||
+WPUPCFI002|Servidor||
+WPUPCFI003|Puerto||
+WPUPCFI004|(Servidores Secundarios)||
+WPUPCFI005|Servidor1||
+WPUPCFI006|Puerto1||
+WPUPCFI007|Servidor2||
+WPUPCFI008|Puerto2||
+WPUPCFI009|Palabra de Paso||
+WPUPCFI010|Dejar en blanco si nada||
+WPUPCFI011|Reconectar en fallo de la RED?||
+WPUPCFI012|Correr como un I-Gate?||
+WPUPCFI013|Difundir mensajes v�a TNC cuando un I-Gate?||
+WPUPCFI014|Bit�cora de Transacciones del I-Gate?|||
+WPUPCFI015|Parametros de Filtrado||
+#
+# Configurar Base de datos
+WPUPCFID01|Configurar Base de datos(TBD)||
+WPUPCFID02|Servidor||
+WPUPCFID03|Puerto||
+WPUPCFID04|(Servidores Secundarios)||
+WPUPCFID05|Servidor1||
+WPUPCFID06|Puerto1||
+WPUPCFID07|Servidor2||
+WPUPCFID08|Puerto2||
+WPUPCFID09|Palabra de Paso||
+WPUPCFID10|Dejar en blanco si nada||
+WPUPCFID11|Reconectar en fallo de la RED?||
+WPUPCFID12|Correr como un I-Gate?||
+WPUPCFID13|Difundir mensajes v�a TNC cuando un I-Gate?||
+WPUPCFID14|Bit�cora de Transacciones del I-Gate?|||
+WPUPCFID15|Parametros de Filtrado||
+#
+# Menu "Configurar AGWPE"
+WPUPCFIA01|Configurar AGWPE||
+WPUPCFIA02|Servidor ||
+WPUPCFIA03|Puerto ||
+WPUPCFIA04|(Servidores Secundario)||
+WPUPCFIA05|Servidor1||
+WPUPCFIA06|Puerto1||
+WPUPCFIA07|Servidor2||
+WPUPCFIA08|Puerto2||
+WPUPCFIA09|Codigo de Paso||
+WPUPCFIA10|(dejar en blanco si Nada)||
+WPUPCFIA11|Reconectar en fallo de RED?||
+WPUPCFIA12|Correr como un I-Gate?||
+WPUPCFIA13|Difundir mensajes via TNC cuando un I-Gate?||
+WPUPCFIA14|Bit�cora de Transacciones I-Gate?||
+WPUPCFIA15|Transmitir RadioPuerto||
+#
+# Configurar Alarmas de Audio
+WPUPCFA001|Configurar Alarma de Audio||
+WPUPCFA002|Aplicaci�n Audio||
+WPUPCFA003|Alarma ON||
+WPUPCFA004|Archivos de Audio||
+WPUPCFA005|Nueva estaci�n||
+WPUPCFA006|Nuevo mensaje||
+WPUPCFA007|Proximidad||
+WPUPCFA008|Banda abierta||
+WPUPCFA009|M�nima distancia||
+WPUPCFA010|M�xima distancia||
+WPUPCFA011|Alerta del Tiempo||
+#
+# Configurar a Festival el sintetizador de Voz
+WPUPCFSP01|Configurar a Festival el Sintetizador de Voz||
+WPUPCFSP02|Fijar en 'ON' la opciones del Sintetizador de Voz||
+WPUPCFSP03|<- Anunciar Nueva Estaci�n||
+WPUPCFSP04|<- Anunciar Alerta de Nuevo Mensaje||
+WPUPCFSP05|<- Anunciar Cuerpo de Nuevo Mensaje||
+WPUPCFSP06|<- Anunciar la Proximidad de estaciones||
+WPUPCFSP07|<- Anunciar DX condici�n de Banda Abierta||
+WPUPCFSP08|<- Anunciar Alerta sobre condiciones del Tiempo||
+WPUPCFSP09|<- Estaci�n Rastreada Alerta de Proximidad||
+#
+# Rastreo de Estaci�n
+WPUPTSP001|Rastreo estaci�n||
+WPUPTSP002|Rastreo Indicativo||
+WPUPTSP003|Macheo Sensible||
+WPUPTSP004|Macheo Exacto||
+WPUPTSP005|Rastrear Ahora!||
+WPUPTSP006|Limpiar Rastro||
+WPUPTSP007|Abajar Rastro||
+WPUPTSP008|Indicativo||
+WPUPTSP009|Inicio Del Rastro (hace horas)||
+WPUPTSP010|Longitud del Rastro (horas)||
+#
+# Men� de Mensajes
+WPUPMSB001|Enviar mensaje %d||
+WPUPMSB002|Enviar Mensaje a grupo %d||
+WPUPMSB003|Indicativo de Estaci�n:||
+WPUPMSB004|Indicativos de Grupos:||
+WPUPMSB005|Nuevo/Refresh Indicativo||
+WPUPMSB006|Nuevo grupo||
+WPUPMSB007|Clear Msg History||
+WPUPMSB008|Mensaje:||
+WPUPMSB009|Enviar ahora!||
+WPUPMSB010|Ruta:||
+WPUPMSB011|Cancel Pending Msgs||
+WPUPMSB012|Kick Timer||
+WPUPMSB013|seq||
+WPUPMSB014|type||
+WPUPMSB015|Broadcast||
+WPUPMSB016|*TIMEOUT*||
+WPUPMSB017|*CANCELLED*||
+WPUPMSB018|*REJECTED*||
+WPUPMSB019|Change Path||
+WPUPMSB020|Use Default Path(s)||
+WPUPMSB021|Direct (No path)||
+WPUPMSB022|Reverse Path (Hint):||
+#
+# Auto Contestaci�n
+WPUPARM001|Cambiar auto Contestaci�n||
+WPUPARM002|Reenviar:||
+#
+# Ayuda / Indice
+WPUPHPI001|Indice de Ayuda|I|
+WPUPHPI002|Visualizar|V|
+#
+# Informaci�n de la Estaci�n
+WPUPSTI000|Objeto creado desde: %s||
+WPUPSTI001|Info Estaci�n||
+WPUPSTI002|Enviar mensaje||
+WPUPSTI003|Buscar datos FCC||
+WPUPSTI004|Buscar datos RAC||
+WPUPSTI005|%d: Paquetes recibidos, �ltimo recibido en fecha: ||
+WPUPSTI006|O�do v�a TNC en dispositivo: %d, ||
+WPUPSTI007|O�do ||
+WPUPSTI008|Ultima vez v�a Local||
+WPUPSTI009|Ultima vez v�a TNC en dispositivo: %d||
+WPUPSTI010|Ultima vez v�a Internet en dispositivo: %d||
+WPUPSTI011|Ultima vez v�a Archivo||
+WPUPSTI012|Ultima vez v�a Desconocida||
+WPUPSTI013|, y ha cambiado posici�n||
+WPUPSTI014|Actual Potencia/Ganancia:||
+WPUPSTI016|Altitud: %.1f%s ||
+WPUPSTI017|Curso: %s� ||
+WPUPSTI018|Velocidad: %.1f km/h||
+WPUPSTI019|Velocidad: %.1f mph||
+WPUPSTI020|%0.1f millas||
+WPUPSTI021|%0.1f km||
+WPUPSTI022|Distancia desde mi estaci�n %s, Curso desde mi estaci�n %s||
+WPUPSTI023|Ultima posici�n: ||
+WPUPSTI024|Datos de la estaci�n Meteorol�gica %c:%s||
+WPUPSTI025|Curso del viento: %s� Velocidad: %03d km/h||
+WPUPSTI026|Curso del viento: %s� Velocidad: %s mph||
+WPUPSTI027| R�faga: %03d Km/h||
+WPUPSTI028| R�faga: %s mph||
+WPUPSTI029|Temperatura: %02.1f�C ||
+WPUPSTI030|Temperatura: %s�F ||
+WPUPSTI031| Humedad: %s%% ||
+WPUPSTI032|Indice de Humedad: %02.1f�C ||
+WPUPSTI033| Presi�n Barom�trica: %s mb||
+WPUPSTI034|Nieve: %0.1f (cm/24h)||
+WPUPSTI035|Nieve: %0.0f (plg/24h)||
+WPUPSTI036|Lluvia: ||
+WPUPSTI037|%0.2f (mm/h) ||
+WPUPSTI038|%0.2f (plg/h) ||
+WPUPSTI039|%0.2f (mm/d�a) ||
+WPUPSTI040|%0.2f (plg/d�a) ||
+WPUPSTI041|%0.2f (mm/desde medianoche)||
+WPUPSTI042|%0.2f (mm/desde medianoche)||
+WPUPSTI043|Ruta de Datos: %s||
+WPUPSTI044|Comentarios %02d/%02d %02d:%02d : %s||
+WPUPSTI045|Limpiar Rastro||
+WPUPSTI046|Total lluvia: ||
+WPUPSTI047|%0.2f (mm)||
+WPUPSTI048|%0.2f (plg)||
+WPUPSTI049|Preguntar rastro||
+WPUPSTI050|Pregunta no-conocido Mensaje||
+WPUPSTI051|Pregunta directa a estaci�n||
+WPUPSTI052|Pregunta versi�n a estaci�n||
+WPUPSTI053|Modificar Objeto/Art�culo||
+WPUPSTI054|Almacenar Rastro||
+WPUPSTI055|Repetido desde:||
+WPUPSTI056|Activar Actualizaciones Autom�tica||
+WPUPSTI057|Omni-DF: %s||
+WPUPSTI058|Orientando DF: %s||
+WPUPSTI059|Estados %02d/%02d %02d:%02d : %s||
+WPUPSTI060|Incendio Temp: %02.1f�C ||
+WPUPSTI061|Incendio Temp: %s�F ||
+WPUPSTI062|Humedad de Incendio: %s%% ||
+WPUPSTI063|Baro: %0.2f en Hg||
+WPUPSTI064|Fetch NWS Alert||
+WPUPSTI065|Tactical Call: %s||
+WPUPSTI066|Assign Tactical Call||
+WPUPSTI067|Current Range: %d miles||
+WPUPSTI068|none||
+WPUPSTI069|default||
+WPUPSTI070|HAAT||
+WPUPSTI071|omni||
+WPUPSTI072|range||
+WPUPSTI073|BAD PHG||
+WPUPSTI074|BAD SHG||
+WPUPSTI075|DF Range||
+WPUPSTI076|No signal detected||
+WPUPSTI077|Detectible signal (Maybe)||
+WPUPSTI078|Detectible signal but not copyable)||
+WPUPSTI079|Weak signal, marginally readable||
+WPUPSTI080|Noisy but copyable signal||
+WPUPSTI081|Some noise, easy to copy signal||
+WPUPSTI082|Good signal w/detectible noise||
+WPUPSTI083|Near full-quieting signal||
+WPUPSTI084|Full-quieting signal||
+WPUPSTI085|Extremely strong & full-quieting signal||
+WPUPSTI086|BAD BEARING||
+WPUPSTI087|BAD NRQ||
+WPUPSTI088|DF Beamwidth||
+WPUPSTI089|DF Length||
+WPUPSTI090|Not Valid||
+WPUPSTI091|Change Trail Color||
+WPUPSTI092|Clear DF Bearing||
+#
+#
+# PopUp "ALOHA Statistics"
+WPUPALO001|ALOHA radius: %d %s||
+WPUPALO002|Stations inside ALOHA circle: %d||
+WPUPALO003| Digis: %d||
+WPUPALO004| Mobiles (in motion): %d||
+WPUPALO005| Mobiles (other): %d||
+WPUPALO006| WX stations: %d||
+WPUPALO007| Home stations: %d||
+WPUPALO008|Last calculated %d %s %d %s ago.||
+WPUPALO666|ALOHA radius not calculated yet||
+#
+# FCC-RAC buscar Indicativo
+STIFCC0001|Buscar en Base de datos FCC||
+STIFCC0002|Buscar en Base de datos RAC||
+STIFCC0003|Nombre:||
+STIFCC0004|Calle:||
+STIFCC0005|Ciudad:||
+STIFCC0006|Estado:||
+STIFCC0007|Zona Postal:||
+STIFCC0008|B�sica ||
+STIFCC0009|Advanzada ||
+STIFCC0010|5 wpm ||
+STIFCC0011|12 wpm ||
+#
+# FCC-RAC buscar Indicativo
+STIFCC0100|FCC index old, rebuilding||
+STIFCC0101|Callsign Search||
+STIFCC0102|Callsign Not Found!||
+STIFCC0103|RAC index old, rebuilding||
+#
+#
+# Mensaje de Banda abierta
+UMBNDO0001|en distancia de||
+#
+# Opciones Universales
+UNIOP00001|Aceptar||
+UNIOP00002|Cancelar||
+UNIOP00003|Cerrar||
+UNIOP00004|millas||
+UNIOP00005|km||
+UNIOP00006|Dispositivo||
+UNIOP00007|Agregar||
+UNIOP00008|Anular||
+UNIOP00009|Propiedades||
+UNIOP00010|Permitir Transmisi�n?||
+UNIOP00011|Activar en Inicio?||
+UNIOP00012|km/h||
+UNIOP00013|mph||
+UNIOP00014|C||
+UNIOP00015|F||
+UNIOP00016|mm||
+UNIOP00017|pg||
+UNIOP00018|mm/d�a||
+UNIOP00019|pg/d�a||
+UNIOP00020|mm/hora||
+UNIOP00021|pg/hora||
+UNIOP00022|mm/med||
+UNIOP00023|pg/med||
+UNIOP00024|grd||
+UNIOP00025|mb||
+UNIOP00026|%||
+UNIOP00027|pg Hg||
+UNIOP00028|mm Hg||
+UNIOP00029|Fije el tiempo del sistema del GPS||
+UNIOP00030|Digipeat?||
+UNIOP00031|m||
+UNIOP00032|Apply|||
+UNIOP00033|Reset||
+UNIOP00034|min||
+UNIOP00035|hr||
+UNIOP00036|day||
+UNIOP00037|Send Control-E to get GPS data?||
+UNIOP00038|Add Delay||
+#
+# Seleccionar Estaci�n
+STCHO00001|Seleccionar Estaci�n||
+#
+# DESPLIEGUE ALARMA WX
+WPUPWXA001|Alerta del Tiempo||
+WPUPWXA002|Lista de alerta del Tiempo||
+#
+# Configurar Interfaces
+WPUPCIF001|Interfaces Instalados||
+WPUPCIF002|Elegir Tipo de interf�z||
+#
+# Configurar AX.25 TNC
+WPUPCAX001|Configurar AX.25 TNC||
+WPUPCAX002|AX.25 nombre de puerto||
+#
+# Nombres de dispositivos de la Interf�z
+IFDNL00000|Nada||
+IFDNL00001|TNC v�a el Puerto Serial||
+IFDNL00002|Serial TNC c/GPS m�s (cable HSP)||
+IFDNL00003|GPS v�a Puerto Serial||
+IFDNL00004|Est. Meteorol�gica v�a Puerto Serial||
+IFDNL00005|Conexi�n a un Servidor en Internet||
+IFDNL00006|AX.25 TNC||
+IFDNL00007|GPS Enlazado v�a el Servidor gpsd||
+IFDNL00008|Est. Meteorol�gica Enlazada a una RED||
+IFDNL00009|Serial TNC c/GPS m�s (cable AUX)||
+IFDNL00010|Serial KISS TNC||
+IFDNL00011|Red Base de Datos (Aun No Implementada)||
+IFDNL00012|Red AGWPE||
+IFDNL00013|Serial Multi-Port KISS TNC||
+IFDNL00014|SQL Database (Experimental)||
+#
+# Info dispositivo Interf�z
+IFDIN00000|%s %2d %s sobre serial %s %s||
+IFDIN00001|%s %2d %s conectado a %s:%d %s||
+IFDIN00002|%s %2d %s usando dispositivo nombrado %s %s||
+IFDIN00003|%s %2d %s %s %s %s||
+IFDIN00004|%s %2d %s %s %s:%d %s||
+IFDIN00005|%s %2d %s %s %s %s||
+IFDIN00006| ABAJO ||
+IFDIN00007| ARRIBA ||
+IFDIN00008| ERROR ||
+IFDIN00009|DESCONOCIDO||
+#
+# Control de la interf�z
+IFPUPCT000|Control de Interf�z||
+IFPUPCT001|Iniciar||
+IFPUPCT002|Detener||
+IFPUPCT003|Iniciar todos||
+IFPUPCT004|Detener todos||
+#
+# Control de I-Gate
+IGPUPCF000|I-Gate Opciones||
+IGPUPCF001|Desactiva todo el IGate tr�fico||
+IGPUPCF002|S�lo Permite tr�fico de RF->Inet||
+IGPUPCF003|Permite ambos tr�ficos RF<->Inet||
+IGPUPCF004|Igate -> RF Ruta ||
+#
+# Estaci�n Meteorol�gica
+WXPUPSI000|Estaci�n meteorol�gica||
+WXPUPSI001|Tipo de estaci�n Meteorol�gica||
+WXPUPSI002|Datos Actuales||
+WXPUPSI003|Curso del viento||
+WXPUPSI004|Velocidad del viento||
+WXPUPSI005|R�faga del viento||
+WXPUPSI006|Temperatura||
+WXPUPSI007|Total lluvia||
+WXPUPSI008|Hoy Total lluvia||
+WXPUPSI009|Presi�n Barom�trica||
+WXPUPSI010|Humedad Relativa||
+WXPUPSI011|Peet Bros ULTIMETER 2000 Tipo (Modo Datos Log)||
+WXPUPSI012|Peet Bros ULTIMETER II Tipo||
+WXPUPSI013|Peet Bros ULTIMETER 2000 Tipo (Modo Paquete)||
+WXPUPSI014|Actual Tot. hora lluvia||
+WXPUPSI015|Ultimas 24 Tot. lluvias||
+WXPUPSI016|Cualim�tricos Q-Net||
+WXPUPSI017|Tipo Peet Bros ULTIMETER 2000 (Modo Completo)||
+WXPUPSI018|Punto de Roc�o||
+WXPUPSI019|Viento Alto||
+WXPUPSI020|Viento Fr�o||
+WXPUPSI021|Indice Caluroso||
+WXPUPSI022|3-Hr Baro||
+WXPUPSI023|Alta Temperat.||
+WXPUPSI024|Baja Temperat.||
+WXPUPSI025|Radio Shack WX-200/Oregon Scientific WM-918||
+WXPUPSI026|Davis Weather Monitor II/Wizard III/Vantage Pro||
+WXPUPSI027|LaCrosse WX-23xx||
+WXPUPSI028|Davis APRS Data Logger||
+#
+# Listas de Estaciones
+LHPUPNI000|Todas las estaciones||
+LHPUPNI001|Estaciones m�viles||
+LHPUPNI002|Estaciones Meteorol�gicas||
+LHPUPNI003|Estaciones locales (v�a TNC)||
+LHPUPNI004|Ultimas Estaciones||
+LHPUPNI005|Objetos y Art�culos||
+LHPUPNI006|Objetos y Art�culos Propio||
+LHPUPNI010| #||
+LHPUPNI011|Indicativo||
+LHPUPNI012|#Pack||
+LHPUPNI013|Ult.Posici�n||
+LHPUPNI014|Ruta||
+LHPUPNI015|PHG||
+LHPUPNI016|Comentarios||
+LHPUPNI100|CSE||
+LHPUPNI101|SPD||
+LHPUPNI102|ALT.||
+LHPUPNI103|Lat||
+LHPUPNI104|Long||
+LHPUPNI105|#Pack||
+LHPUPNI106|LSV||
+LHPUPNI107|CFMS||
+LHPUPNI108|DFMS||
+LHPUPNI200|CSE||
+LHPUPNI201|SPD||
+LHPUPNI202|GST||
+LHPUPNI203|Temp||
+LHPUPNI204|Hum||
+LHPUPNI205|Baro||
+LHPUPNI206|RN-H||
+LHPUPNI207|RNSM||
+LHPUPNI208|RN24||
+LHPUPNI209|Lat/Lon o UTM||
+#
+# Traza Alertas WX sobre mapas
+PULDNMAT01|Muestra mapa de alarma sobre otros mapas||
+PULDNMAT02|Muestra mapa de alarma bajo otros mapas||
+#
+# Error/popup mensajes
+POPEM00001|Localiza Error!||
+POPEM00002|La estaci�n %s no fue encontrada!||
+POPEM00003|Rastreo Error!||
+POPEM00004|Interf�z Error!||
+POPEM00005|Inv�lido nombre de puerto AX.25 %s||
+POPEM00006|Inv�lido nombre de puerto AX.25 %s||
+POPEM00007|Inv�lido Indicativo %s||
+POPEM00008|Inv�lido Indicativo AX.25 destinaci�n o digipeater||
+POPEM00009|No puedo abrir el s�calo AX.25, %s||
+POPEM00010|No puedo atar el s�calo AX.25, %s||
+POPEM00011|No puedo conectar al Indicativo AX.25, %s||
+POPEM00012|AX.25 error en la salida de UI||
+POPEM00013|AX.25 problema con el archivo axports||
+POPEM00014|AX.25 inv�lido nombre de puerto %s||
+POPEM00015|Error abriendo la interf�z %d, duro fallo||
+POPEM00016|Error abriendo la interf�z %d Tiempo agotado||
+POPEM00017|No hay mas interf�z disponible!||
+POPEM00018|Dato requerido - Simple L�nea de Mensaje|
+POPEM00019|El Puerto de transmisi�n est� "off" para puerto %d|
+POPEM00020|Error banco de Datos!|
+POPEM00021|El soporte de AX.25 no est� compilado en Xastir!||
+POPEM00022|Error de entrada!|
+POPEM00023|Nombre de locaci�n no especificada!|
+POPEM00024|Nombre de Locaci�n especificada en uso!|
+POPEM00025|No Encontrado!||
+POPEM00026|El Rastreo empezar� cuando el aparezca||
+POPEM00027|Info Impropia. Algunos campos vac�o?||
+POPEM00028|No se puede abrir el archivo||
+POPEM00029|Encontrado!||
+POPEM00030|S�mbolo de Estaci�n Meteorol�gica||
+POPEM00031|Cambiado a s�mbolo WX '/_', otras opciones: '\_' '/W' y '\W'||
+POPEM00032|Aviso: Usando S�mbolo del National Weather Service!||
+POPEM00033|No GPS Data!||
+POPEM00034|Disactivando TX de Mi Posici�n Hasta ver Data de GPS V�lido!||
+POPEM00035|Warning||
+POPEM00036|Notice||
+POPEM00037|HSP interface present: GPS timing has been increased||
+POPEM00038|Name Conflicts With Existing Object/Item/Station||
+POPEM00039|Illegal characters found, substituting periods in their place||
+POPEM00040|Custom outgoing path was lost||
+POPEM00041|Processing another file. Wait a bit, then try again||
+POPEM00042|Object not owned by me! Try adopting the object first.||
+POPEM00043|Not an Object/Item!||
+POPEM00044|Fetch Findu Trail: Failed||
+POPEM00045|Fetch Findu Trail: Complete||
+POPEM00046|Berkeley DB header/shared library do NOT match! Disabling map cache.||
+POPEM00047|Global transmit is DISABLED. Emergency beacons are NOT going out!||
+POPEM00048|Emergency Beacon Mode!||
+POPEM00049|EMERGENCY BEACON MODE, transmitting every 60 seconds!||
+POPEM00050|Interfaces or posits/transmits DISABLED. Emergency beacons are NOT going out!||
+POPEM00051|Altnet is enabled (Configure->Defaults dialog)||
+POPEM00052|Callsign is EMPTY!||
+POPEM00053|Message is EMPTY!||
+POPEM00054|We're trying to talk to ourselves!||
+#
+# Salto de Locaci�n
+JMLPO00001|Localizaci�n de Mapa||
+JMLPO00002|IR!||
+JMLPO00003|Nombre de Nueva Localizaci�n:||
+#
+# Boletines
+BULMW00001|Boletines||
+BULMW00002|L�mite de Rango a (0, no hay l�mite)||
+BULMW00003|Cambio de Rango||
+#
+# Tr�fico de todo los mensajes
+AMTMW00001|Tr�fico de todos los mensajes||
+AMTMW00002|L�mite de Rango a (0, no hay l�mite)||
+#
+# Cadenas del Sintetizador
+SPCHSTR001|kil�metros||
+SPCHSTR002|metros||
+SPCHSTR003|millas||
+SPCHSTR004|yardas||
+SPCHSTR005|%s, distancia es %d %s.||
+SPCHSTR006|%s, distancia es %.1f %s.||
+SPCHSTR007|%s, distancia es %d %s %s %s.||
+SPCHSTR008|%s, distancia es %.1f %s %s %s.||
+SPCHSTR009|Nueva Alerta de WX||
+SPCHSTR010|Nueva LLamada||
+SPCHSTR011|O�do, D X, %s, en distancia de %.1f %s||
+#
+SPCHDIRN00|norte de||
+SPCHDIRS00|sur de||
+SPCHDIRE00|este de||
+SPCHDIRW00|oeste de||
+SPCHDIRNE0|noreste de||
+SPCHDIRNW0|noroeste de||
+SPCHDIRSE0|sureste de||
+SPCHDIRSW0|suroeste de||
+#
+# Di�logo de seleci�n de S�mbolo
+SYMSEL0001|Seleccione S�mbolo||
+SYMSEL0002|Tabla de S�mbolo primario||
+SYMSEL0003|Tabla de S�mbolo Secundario||
+#
+# Di�logo de la Propiedades de Impresora
+PRINT0001|Propiedades de Impresora||
+PRINT0002|Ancho del Paper||
+PRINT0003|Auto-Rotar Imagen
+PRINT0004|Rotar Imagen 90� CCW||
+PRINT0005|Auto-Balancear Imagen||
+PRINT0006|Balanza:||
+PRINT0007|Forza el predefinido color de fondo a blanco||
+PRINT0008|Imprime en Blanco y Negro||
+PRINT0016|Colores Revertidos||
+PRINT0009|Resoluci�n de Postscript:||
+PRINT0010|Prevista||
+PRINT0011|Imprimir al archivo||
+PRINT0012|Guardar imagen a un archivo...||
+PRINT0013|Convirtiendo a Postscript...||
+PRINT0014|Creando archivo de impresi�n Finalizado||
+PRINT0015|Estado de Impresora||
+#
+# Di�logo de la Propiedades de Impresora
+PRINT1001|Direct to:||
+PRINT1002|Via Previewer:||
+#
+# Di�logo de localizar forma
+FEATURE001|Nombre:||
+FEATURE002|Estado/Provincia:||
+FEATURE003|Pais:||
+FEATURE004|Cuadratura del Mapa:||
+FEATURE005|Tipo:||
+FEATURE006|GNIS Archivo:||
+FEATURE007|Address:||
+FEATURE008|City:||
+FEATURE009|Mark Destination||
+FEATURE010|Zip Code:||
+FEATURE011|Geocoding File||
+#
+# Di�logo de Calcular Coordenada
+COORD001|Calcula Coordenada||
+COORD002|Calc||
+COORD003|Calcular||
+COORD004|Limpiar||
+COORD005|UTM||
+COORD006|Latitud o||
+COORD007|Longitud o||
+COORD008|Zona||
+COORD009|UTM Hacia Este||
+COORD010|UTM Hacia Norte||
+COORD011| Decimal Degrees: ||
+COORD012| Degrees/Decimal Minutes: ||
+COORD013| Degrees/Minutes/Dec. Seconds: ||
+COORD014| Universal Transverse Mercator: ||
+COORD015|Military Grid Reference System: ||
+COORD016| Maidenhead Grid Locator: ||
+COORD017| ** Sorry, your input was not recognized! **||
+COORD018| ** Please use one of the following input formats: **||
+#
+# Di�logo Baliza Inteligente
+SMARTB001|Baliza Inteligente||
+SMARTB002|Alta Proporci�n (secs):||
+SMARTB003|Alta Velocidad (mph):||
+SMARTB004|Alta Velocidad (kph):||
+SMARTB005|Baja Proporci�n (mins):||
+SMARTB006|Baja Velocidad (mph):||
+SMARTB007|Baja Velocidad (kph):||
+SMARTB008|M�nima Vuelta (grados):||
+SMARTB009|Vuelta de declive:||
+SMARTB010|Tiempo de Espera (secs):||
+SMARTB011|Activar Baliza Inteligente(tm)||
+#
+# Di�logo Ajuste de Gamma
+GAMMA001|Ajuste Correcci�n de Gamma||
+GAMMA002|Correcci�n Gamma||
+#
+# Map labels font Dialog
+MAPFONT001|Change Fonts||
+MAPFONT002|Fonts||
+MAPFONT003|Map Font Min�sculo||
+MAPFONT004|Map Font Peque�o||
+MAPFONT005|Map Font Medio||
+MAPFONT006|Map Font Grande||
+MAPFONT007|Map Font Enorme||
+MAPFONT008|Map Font Border||
+MAPFONT009|Menu Font||
+MAPFONT010|Station Font||
+MAPFONT011|ATV ID Font||
+#
+# Distancia/Orientaci�n en l�nea de estado
+PULDNDB001|Estado de Distancia/Orientaci�n||
+#
+# Transferir Operaciones de GPS
+GPS001|Transferir GPS||
+GPS002|Nombre de Archivo||
+GPS003|Seleccionar Color||
+GPS004|Rojo||
+GPS005|Verde||
+GPS006|Negro||
+GPS007|Blanco||
+GPS008|Naranja||
+GPS009|Azul||
+GPS010|Amarillo||
+GPS011|Violeta||
+#
+# Di�logo de Propiedades de Mapa
+MAPP001|Propiedades de Mapa||
+MAPP002|Max Min Dibuja Mapa USGS Auto||
+MAPP003|Zoom Zoom Capa Llenado DRG Mapa Sendero/NombreArchivo||
+MAPP004|Cambie Capa->||
+MAPP005|Llenado->||
+MAPP006|S�||
+MAPP007|No||
+MAPP008|Automapas->||
+MAPP009|Max Zoom->||
+MAPP010|Min Zoom->||
+MAPP011|Auto||
+MAPP012|USGS DRG->||
+#
+# Cadenas del Tiempo
+TIME001|D�a||
+TIME002|D�as||
+TIME003|Hora||
+TIME004|Horas||
+TIME005|Minuto||
+TIME006|Minutos||
+TIME007|Segundo||
+TIME008|Segundos||
+#
+#
+# Map Caching
+CACHE001|Map now cached||
+CACHE002|Loading Cached Map||
+CACHE003|Map not found in cache...||
+#
+#
+# Map Screen Misc
+RANGE001|RANGE SCALE||
+#
+#
+# GPS Status
+GPSS001|WAAS or PPS||
+GPSS002|DGPS||
+GPSS003|Valid SPS||
+GPSS004|Invalid||
+GPSS005|Sats/View||
+GPSS006|Fix||
+GPSS007|!GPS data is older than 30 seconds!||
+GPSS008|Simulation||
+GPSS009|Manual||
+GPSS010|Estimated||
+GPSS011|Float RTK||
+GPSS012|RTK||
+#
+#
+# Popup cad_dialog to obtain CAD object data
+CADPUD001|Area Object||
+CADPUD002|Area Label:||
+CADPUD003|Comment:||
+CADPUD004|Probability (%):||
+CADPUD005|OK||
+CADPUD006|CAD Dialog||
+CADPUD007|Show/Edit Details||
+CADPUD008|Cancel||
+CADPUD009|Delete CAD objects?||
+CADPUD010|Delete All||
+CADPUD011|Delete Selected||
+CADPUD012|Solid||
+CADPUD013|Dashed||
+CADPUD014|Double Dash||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA001|XASTIR Map of %s (upper left) to %s (lower right). UTM %d m grid, %s datum. ||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA002|XASTIR Map of %s (upper left) to %s %s (lower right). Lat/Long grid, %s datum.||
+#
+#
+# Format strings for map metadata in top border
+#"XASTIR Map of <utm_coord> (upper left) to <utm_coord> (lower right). UTM <grid_size> m grid, <wgs84> datum. ",
+MDATA003|XASTIR Map of %s (upper left) to %s (lower right). UTM zones, %s datum.||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST001|MySQL (lat/long)||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST002|Postgreql with Postgis||
+#
+# Text interpretation of integer values of database type and schema type
+# used for sql database configuration in interface_gui.c
+# DB_MYSQL
+XADBMST003|MySQL (spatial)||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA01|Xastir Simple Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA02|Xastir CAD Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA03|Xastir full Schema||
+# XASTIR_SCHEMA_SIMPLE]
+XASCHEMA04|APRSWorld Schema||
diff --git a/config/nwsc_ddmmyy.dbfawk b/config/nwsc_ddmmyy.dbfawk
new file mode 100644
index 0000000..a03b8f9
--- /dev/null
+++ b/config/nwsc_ddmmyy.dbfawk
@@ -0,0 +1,55 @@
+# $Id: nwsc_ddmmyy.dbfawk,v 1.23 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# label_color - color for label
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS county polygon shapefiles
+# which are named c_ddmmyy.dbf. These are used for WX alerts but can also
+# be used as a map of all US counties. For the WX alert feature, the
+# key is set to the concatentation of the STATE and FIPS county code
+# in the same format as the alert->title (e.g. WI_C037).
+#
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="STATE:CWA:COUNTYNAME:FIPS:TIME_ZONE:FE_AREA:LON:LAT";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="COUNTYNAME:STATE:FIPS";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=1; fill_color=7; color=8; name=""; filled=1; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+# name: name is just the county name.
+/^COUNTYNAME=(.*)$/ {name="$1"; font_size=4; next}
+# also append "County" to the name except for Louisiana, use Parish
+# (is this the only state that calls them something other than county?):
+# XXX check this whole LA thing. I think they call them parishes.
+/^STATE=(LA)$/ {name="$name Parish"; key="$1"; next}
+/^STATE=(..)$/ {name="$name County"; key="$1"; next}
+/^FIPS=..(...)$/ {key="$(key)_C$1"; next}
+
+# don't need special end case handling...
+#END_RECORD {name="$name ($key)";}
+#END {}
diff --git a/config/nwsc_ddmmyy_09.dbfawk b/config/nwsc_ddmmyy_09.dbfawk
new file mode 100644
index 0000000..b48f6cb
--- /dev/null
+++ b/config/nwsc_ddmmyy_09.dbfawk
@@ -0,0 +1,59 @@
+# $Id: nwsc_ddmmyy_09.dbfawk,v 1.4 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# label_color - color for label
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS county polygon shapefiles
+# which are named c_ddmmyy.dbf. These are used for WX alerts but can also
+# be used as a map of all US counties. For the WX alert feature, the
+# key is set to the concatentation of the STATE and FIPS county code
+# in the same format as the alert->title (e.g. WI_C037).
+#
+# This DBFAWK file matches the set of county shapefiles that was published
+# by NOAA in 2009, and differs from the earlier format. Shapefiles from 2008
+# are matched by the file "nwsc_ddmmyy.dbfawk" instead.
+#
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="OBJECTID:SHAPE_LENG:SHAPE_AREA:STATE:CWA:COUNTYNAME:FIPS:TIME_ZONE:FE_AREA:LON:LAT";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="COUNTYNAME:STATE:FIPS";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=1; fill_color=7; color=8; name=""; filled=1; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+# name: name is just the county name.
+/^COUNTYNAME=(.*)$/ {name="$1"; font_size=4; next}
+# also append "County" to the name except for Louisiana, use Parish
+# (is this the only state that calls them something other than county?):
+# XXX check this whole LA thing. I think they call them parishes.
+/^STATE=(LA)$/ {name="$name Parish"; key="$1"; next}
+/^STATE=(..)$/ {name="$name County"; key="$1"; next}
+/^FIPS=..(...)$/ {key="$(key)_C$1"; next}
+
+# don't need special end case handling...
+#END_RECORD {name="$name ($key)";}
+#END {}
diff --git a/config/nwsc_ddmmyy_09b.dbfawk b/config/nwsc_ddmmyy_09b.dbfawk
new file mode 100644
index 0000000..c9f8d68
--- /dev/null
+++ b/config/nwsc_ddmmyy_09b.dbfawk
@@ -0,0 +1,59 @@
+# $Id: nwsc_ddmmyy_09b.dbfawk,v 1.3 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# label_color - color for label
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS county polygon shapefiles
+# which are named c_ddmmyy.dbf. These are used for WX alerts but can also
+# be used as a map of all US counties. For the WX alert feature, the
+# key is set to the concatentation of the STATE and FIPS county code
+# in the same format as the alert->title (e.g. WI_C037).
+#
+# This DBFAWK file matches the set of county shapefiles that was published
+# by NOAA in 2009, and differs from the earlier format. Shapefiles from 2008
+# are matched by the file "nwsc_ddmmyy.dbfawk" instead.
+#
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="OBJECTID_1:OBJECTID:STATE:CWA:COUNTYNAME:FIPS:TIME_ZONE:FE_AREA:LON:LAT";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="COUNTYNAME:STATE:FIPS";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=1; fill_color=7; color=8; name=""; filled=1; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+# name: name is just the county name.
+/^COUNTYNAME=(.*)$/ {name="$1"; font_size=4; next}
+# also append "County" to the name except for Louisiana, use Parish
+# (is this the only state that calls them something other than county?):
+# XXX check this whole LA thing. I think they call them parishes.
+/^STATE=(LA)$/ {name="$name Parish"; key="$1"; next}
+/^STATE=(..)$/ {name="$name County"; key="$1"; next}
+/^FIPS=..(...)$/ {key="$(key)_C$1"; next}
+
+# don't need special end case handling...
+#END_RECORD {name="$name ($key)";}
+#END {}
diff --git a/config/nwsc_ddmmyy_10.dbfawk b/config/nwsc_ddmmyy_10.dbfawk
new file mode 100644
index 0000000..072b3b1
--- /dev/null
+++ b/config/nwsc_ddmmyy_10.dbfawk
@@ -0,0 +1,59 @@
+# $Id: nwsc_ddmmyy_10.dbfawk,v 1.2 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# label_color - color for label
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS county polygon shapefiles
+# which are named c_ddmmyy.dbf. These are used for WX alerts but can also
+# be used as a map of all US counties. For the WX alert feature, the
+# key is set to the concatentation of the STATE and FIPS county code
+# in the same format as the alert->title (e.g. WI_C037).
+#
+# This DBFAWK file matches the set of county shapefiles that was published
+# by NOAA in 2009, and differs from the earlier format. Shapefiles from 2008
+# are matched by the file "nwsc_ddmmyy.dbfawk" instead.
+#
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="OBJECTID_1:OBJECTID_2:OBJECTID:STATE:ZONE:CWA:NAME:STATE_ZONE:TIME_ZONE:FE_AREA:LON:LAT:SHAPE_LENG:SHAPE_LE_1:Shape_Le_2:Shape_Area";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="STATE";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=1; fill_color=7; color=8; name=""; filled=1; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+# name: name is just the county name.
+#/^COUNTYNAME=(.*)$/ {name="$1"; font_size=4; next}
+# also append "County" to the name except for Louisiana, use Parish
+# (is this the only state that calls them something other than county?):
+# XXX check this whole LA thing. I think they call them parishes.
+#/^STATE=(LA)$/ {name="$name Parish"; key="$1"; next}
+#/^STATE=(..)$/ {name="$name County"; key="$1"; next}
+#/^FIPS=..(...)$/ {key="$(key)_C$1"; next}
+
+# don't need special end case handling...
+#END_RECORD {name="$name ($key)";}
+#END {}
diff --git a/config/nwsc_ddmmyy_10a.dbfawk b/config/nwsc_ddmmyy_10a.dbfawk
new file mode 100644
index 0000000..c1e0950
--- /dev/null
+++ b/config/nwsc_ddmmyy_10a.dbfawk
@@ -0,0 +1,59 @@
+# $Id$
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# label_color - color for label
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS county polygon shapefiles
+# which are named c_ddmmyy.dbf. These are used for WX alerts but can also
+# be used as a map of all US counties. For the WX alert feature, the
+# key is set to the concatentation of the STATE and FIPS county code
+# in the same format as the alert->title (e.g. WI_C037).
+#
+# This DBFAWK file matches the set of county shapefiles that was published
+# by NOAA in 2009, and differs from the earlier format. Shapefiles from 2008
+# are matched by the file "nwsc_ddmmyy.dbfawk" instead.
+#
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="OBJECTID:ID:WFO:GL_WFO:SHAPE_LENG:SHAPE_AREA:MZ:AJOIN0:AJOIN1:STATE:CWA:COUNTYNAME:FIPS:TIME_ZONE:FE_AREA:LON:LAT";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="STATE";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=1; fill_color=7; color=8; name=""; filled=1; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+# name: name is just the county name.
+#/^COUNTYNAME=(.*)$/ {name="$1"; font_size=4; next}
+# also append "County" to the name except for Louisiana, use Parish
+# (is this the only state that calls them something other than county?):
+# XXX check this whole LA thing. I think they call them parishes.
+#/^STATE=(LA)$/ {name="$name Parish"; key="$1"; next}
+#/^STATE=(..)$/ {name="$name County"; key="$1"; next}
+#/^FIPS=..(...)$/ {key="$(key)_C$1"; next}
+
+# don't need special end case handling...
+#END_RECORD {name="$name ($key)";}
+#END {}
diff --git a/config/nwshzddmmyy.dbfawk b/config/nwshzddmmyy.dbfawk
new file mode 100644
index 0000000..de4b393
--- /dev/null
+++ b/config/nwshzddmmyy.dbfawk
@@ -0,0 +1,42 @@
+# $Id: nwshzddmmyy.dbfawk,v 1.2 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS offshore marine zone area polygon shapefiles
+# which are named ozddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the ID code reformated
+# to match the alert->title. For example AN_Z081.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="WFO:NAME:LAT:LON";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+#/^ID=(..)(.*)$/ {key="$1_$2"; next}
+#/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwsmzddmmyy.dbfawk b/config/nwsmzddmmyy.dbfawk
new file mode 100644
index 0000000..73d7989
--- /dev/null
+++ b/config/nwsmzddmmyy.dbfawk
@@ -0,0 +1,41 @@
+# $Id: nwsmzddmmyy.dbfawk,v 1.21 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS offshore marine zone area polygon shapefiles
+# which are named ozddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the ID code.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="ID:WFO:NAME:GL_WFO:LON:LAT";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="ID:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^ID=(..)(.*)$/ {key="$1_$2"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwsmzddmmyy_09.dbfawk b/config/nwsmzddmmyy_09.dbfawk
new file mode 100644
index 0000000..71ce7ac
--- /dev/null
+++ b/config/nwsmzddmmyy_09.dbfawk
@@ -0,0 +1,41 @@
+# $Id: nwsmzddmmyy_09.dbfawk,v 1.3 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS offshore marine zone area polygon shapefiles
+# which are named ozddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the ID code.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="OBJECTID:ID:WFO:NAME:GL_WFO:LON:LAT:Shape_Leng:Shape_Area";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="ID:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^ID=(..)(.*)$/ {key="$1_$2"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwsmzddmmyy_11.dbfawk b/config/nwsmzddmmyy_11.dbfawk
new file mode 100644
index 0000000..6583fb3
--- /dev/null
+++ b/config/nwsmzddmmyy_11.dbfawk
@@ -0,0 +1,41 @@
+# $Id$
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS offshore marine zone area polygon shapefiles
+# which are named ozddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the ID code.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="ID:WFO:GL_WFO:NAME:AJOIN0:AJOIN1:LON:LAT";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="ID:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^ID=(..)(.*)$/ {key="$1_$2"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwsmzoddmmyy.dbfawk b/config/nwsmzoddmmyy.dbfawk
new file mode 100644
index 0000000..8e57938
--- /dev/null
+++ b/config/nwsmzoddmmyy.dbfawk
@@ -0,0 +1,41 @@
+# $Id$
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS offshore marine zone area polygon shapefiles
+# which are named ozddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the ID code.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="ID:WFO:NAME:WFO_AREA:LON:LAT";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="ID:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^ID=(.*)$/ {key="$1"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwsozddap12.dbfawk b/config/nwsozddap12.dbfawk
new file mode 100644
index 0000000..44c1ea9
--- /dev/null
+++ b/config/nwsozddap12.dbfawk
@@ -0,0 +1,42 @@
+# $Id: nwsozddap12.dbfawk,v 1.2 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS offshore marine zone area polygon shapefiles
+# which are named ozddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the ID code reformated
+# to match the alert->title. For example AN_Z081.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="ID:WFO:LON:LAT:Location:Name";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="ID:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^ID=(..)(.*)$/ {key="$1_$2"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwsozddmmyy.dbfawk b/config/nwsozddmmyy.dbfawk
new file mode 100644
index 0000000..9a0b147
--- /dev/null
+++ b/config/nwsozddmmyy.dbfawk
@@ -0,0 +1,42 @@
+# $Id: nwsozddmmyy.dbfawk,v 1.19 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS offshore marine zone area polygon shapefiles
+# which are named ozddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the ID code reformated
+# to match the alert->title. For example AN_Z081.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="ID:WFO:NAME:LON:LAT";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="ID:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^ID=(..)(.*)$/ {key="$1_$2"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwsozddmmyy_09.dbfawk b/config/nwsozddmmyy_09.dbfawk
new file mode 100644
index 0000000..9dcd349
--- /dev/null
+++ b/config/nwsozddmmyy_09.dbfawk
@@ -0,0 +1,42 @@
+# $Id: nwsozddmmyy_09.dbfawk,v 1.3 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS offshore marine zone area polygon shapefiles
+# which are named ozddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the ID code reformated
+# to match the alert->title. For example AN_Z081.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="ID:WFO:LON:LAT:NAME";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="ID:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^ID=(..)(.*)$/ {key="$1_$2"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwsw_ddjn12.dbfawk b/config/nwsw_ddjn12.dbfawk
new file mode 100644
index 0000000..aecede2
--- /dev/null
+++ b/config/nwsw_ddjn12.dbfawk
@@ -0,0 +1,41 @@
+# $Id: nwsw_ddjn12.dbfawk,v 1.2 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS county warning area polygon shapefiles
+# which are named w_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the CWA code
+# reformated to match alert->title. For example: CW_ATAE for CWA TAE.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="CWA:WFO:Lon:Lat";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="WFO";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^WFO=(.*)$/ {name="$1"; key="CW_A$1"; next}
diff --git a/config/nwsw_ddmmyy.dbfawk b/config/nwsw_ddmmyy.dbfawk
new file mode 100644
index 0000000..cfbf462
--- /dev/null
+++ b/config/nwsw_ddmmyy.dbfawk
@@ -0,0 +1,41 @@
+# $Id: nwsw_ddmmyy.dbfawk,v 1.19 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS county warning area polygon shapefiles
+# which are named w_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the CWA code
+# reformated to match alert->title. For example: CW_ATAE for CWA TAE.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="WFO:CWA:LON:LAT";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="WFO";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^WFO=(.*)$/ {name="$1"; key="CW_A$1"; next}
diff --git a/config/nwsw_ddmmyy_09.dbfawk b/config/nwsw_ddmmyy_09.dbfawk
new file mode 100644
index 0000000..82a41af
--- /dev/null
+++ b/config/nwsw_ddmmyy_09.dbfawk
@@ -0,0 +1,41 @@
+# $Id: nwsw_ddmmyy_09.dbfawk,v 1.3 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS county warning area polygon shapefiles
+# which are named w_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the CWA code
+# reformated to match alert->title. For example: CW_ATAE for CWA TAE.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="WFO:CWA:AREA:LON:LAT";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="WFO";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^WFO=(.*)$/ {name="$1"; key="CW_A$1"; next}
diff --git a/config/nwsw_ddmmyy_10.dbfawk b/config/nwsw_ddmmyy_10.dbfawk
new file mode 100644
index 0000000..f6b19fb
--- /dev/null
+++ b/config/nwsw_ddmmyy_10.dbfawk
@@ -0,0 +1,41 @@
+# $Id$
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS county warning area polygon shapefiles
+# which are named w_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the CWA code
+# reformated to match alert->title. For example: CW_ATAE for CWA TAE.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="AJOIN0:AJOIN1:WFO:CWA:LON:LAT";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="WFO";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^WFO=(.*)$/ {name="$1"; key="CW_A$1"; next}
diff --git a/config/nwsz1ddmmyy.dbfawk b/config/nwsz1ddmmyy.dbfawk
new file mode 100644
index 0000000..82b2ca6
--- /dev/null
+++ b/config/nwsz1ddmmyy.dbfawk
@@ -0,0 +1,42 @@
+# $Id$
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS state zone area polygon shapefiles
+# which are named z_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the STATE_ZONE code,
+# reformatted to match alert->title (e.g. KS033 is KS_Z033).
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="STATE:ZONE:CWA:NAME:STATE_ZONE:TIME_ZONE:FE_AREA:LON:LAT";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="STATE_ZONE:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^STATE_ZONE=(..)(.*)$/ {key="$1_Z$2"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwsz_ddmmyy.dbfawk b/config/nwsz_ddmmyy.dbfawk
new file mode 100644
index 0000000..58ee742
--- /dev/null
+++ b/config/nwsz_ddmmyy.dbfawk
@@ -0,0 +1,42 @@
+# $Id: nwsz_ddmmyy.dbfawk,v 1.25 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS state zone area polygon shapefiles
+# which are named z_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the STATE_ZONE code,
+# reformatted to match alert->title (e.g. KS033 is KS_Z033).
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="STATE:ZONE:CWA:NAME:STATE_ZONE:TIME_ZONE:FE_AREA:CEN_LAT:CEN_LON:LON:LAT:SHORTNAME";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="STATE_ZONE:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^STATE_ZONE=(..)(.*)$/ {key="$1_Z$2"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwsz_ddmmyy_09.dbfawk b/config/nwsz_ddmmyy_09.dbfawk
new file mode 100644
index 0000000..fe3bbb4
--- /dev/null
+++ b/config/nwsz_ddmmyy_09.dbfawk
@@ -0,0 +1,42 @@
+# $Id: nwsz_ddmmyy_09.dbfawk,v 1.3 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS state zone area polygon shapefiles
+# which are named z_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the STATE_ZONE code,
+# reformatted to match alert->title (e.g. KS033 is KS_Z033).
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="OBJECTID:STATE:ZONE:CWA:NAME:STATE_ZONE:TIME_ZONE:FE_AREA:CEN_LAT:CEN_LON:SHAPE_LENG:SHAPE_AREA:LON:LAT:SHORTNAME";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="STATE_ZONE:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^STATE_ZONE=(..)(.*)$/ {key="$1_Z$2"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwsz_ddmmyy_10.dbfawk b/config/nwsz_ddmmyy_10.dbfawk
new file mode 100644
index 0000000..e81b380
--- /dev/null
+++ b/config/nwsz_ddmmyy_10.dbfawk
@@ -0,0 +1,42 @@
+# $Id$
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS state zone area polygon shapefiles
+# which are named z_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the STATE_ZONE code,
+# reformatted to match alert->title (e.g. KS033 is KS_Z033).
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="OBJECTID:STATE:ZONE:CWA:NAME:STATE_ZONE:TIME_ZONE:FE_AREA:SHAPE_LENG:SHAPE_AREA:FI:LON:LAT:SHORTNAME";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="STATE_ZONE:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^STATE_ZONE=(..)(.*)$/ {key="$1_Z$2"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwsz_ddmmyy_10b.dbfawk b/config/nwsz_ddmmyy_10b.dbfawk
new file mode 100644
index 0000000..e271c91
--- /dev/null
+++ b/config/nwsz_ddmmyy_10b.dbfawk
@@ -0,0 +1,42 @@
+# $Id: nwsz_ddmmyy_10b.dbfawk,v 1.2 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS state zone area polygon shapefiles
+# which are named z_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the STATE_ZONE code,
+# reformatted to match alert->title (e.g. KS033 is KS_Z033).
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="OBJECTID:STATE:CWA:TIME_ZONE:FE_AREA:ZONE:NAME:STATE_ZONE:AJOIN0:AJOIN1:LON:LAT:SHORTNAME";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="STATE_ZONE:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^STATE_ZONE=(..)(.*)$/ {key="$1_Z$2"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwsz_ddmmyy_10c.dbfawk b/config/nwsz_ddmmyy_10c.dbfawk
new file mode 100644
index 0000000..3fd30e2
--- /dev/null
+++ b/config/nwsz_ddmmyy_10c.dbfawk
@@ -0,0 +1,42 @@
+# $Id$
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS state zone area polygon shapefiles
+# which are named z_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the STATE_ZONE code,
+# reformatted to match alert->title (e.g. KS033 is KS_Z033).
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="STATE:CWA:TIME_ZONE:FE_AREA:ZONE:NAME:STATE_ZONE:LON:LAT:SHORTNAME";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="STATE_ZONE:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^STATE_ZONE=(..)(.*)$/ {key="$1_Z$2"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwsz_ddmmyy_11.dbfawk b/config/nwsz_ddmmyy_11.dbfawk
new file mode 100644
index 0000000..2e0e9e2
--- /dev/null
+++ b/config/nwsz_ddmmyy_11.dbfawk
@@ -0,0 +1,43 @@
+# $Id: nwsz_ddmmyy_11.dbfawk,v 1.2 2012/03/02 20:10:35 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS state zone area polygon shapefiles
+# which are named z_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the STATE_ZONE code,
+# reformatted to match alert->title (e.g. KS033 is KS_Z033).
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+#dbfinfo="OBJECTID:STATE:CWA:TIME_ZONE:FE_AREA:ZONE:NAME:STATE_ZONE:LON:LAT:SHORTNAME:Shape_Leng:Shape_Area";
+dbfinfo="OBJECTID:STATE:CWA:TIME_ZONE:FE_AREA:ZONE:NAME:STATE_ZONE:LON:LAT:SHORTNAME";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="STATE_ZONE:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^STATE_ZONE=(..)(.*)$/ {key="$1_Z$2"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/nwszoddmmyy.dbfawk b/config/nwszoddmmyy.dbfawk
new file mode 100644
index 0000000..54b0ff4
--- /dev/null
+++ b/config/nwszoddmmyy.dbfawk
@@ -0,0 +1,42 @@
+# $Id$
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map NWS state zone area polygon shapefiles
+# which are named z_ddmmyy.dbf. These are used for WX alerts.
+# For the WX alert feature, the key is set to the STATE_ZONE code,
+# reformatted to match alert->title (e.g. KS033 is KS_Z033).
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="STATE:ZONE:CWA:NAME:STATE_ZONE:TIME_ZONE:FE_AREA:LON:LAT:SHORTNAME";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="STATE_ZONE:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key="BOGUS"; lanes=2; fill_color=7; color=8; name=""; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=512; label_color=20; font_size=2; symbol=""}
+
+/^STATE_ZONE=(..)(.*)$/ {key="$1_Z$2"; next}
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/pointlm.dbfawk b/config/pointlm.dbfawk
new file mode 100644
index 0000000..c7a299e
--- /dev/null
+++ b/config/pointlm.dbfawk
@@ -0,0 +1,63 @@
+# $Id: pointlm.dbfawk,v 1.4 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# Census.gov 2008 TigerMaps for POINTLM
+# Richard Polivka, N6NKO - April, 2008
+# Craig Anderson, N6YXK - May, 2008
+# Dale Seaburg, KG5LT - March, 2009
+#
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line Shapefiles as available at:
+# http://www.census.gov/geo/www/tiger/tgrshp2008/tgrshp2008.html
+#
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+# 2007FE = dbfinfo="STATEFP:COUNTYFP:COUNTYNS:POINTID:FULLNAME:MTFCC";
+dbfinfo="STATEFP:COUNTYFP:ANSICODE:POINTID:FULLNAME:MTFCC";
+#dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="FULLNAME:MTFCC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=6; fill_color=11; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=8; font_size=0; symbol=""; fill_style=0 }
+
+/^FULLNAME=(.*)$/ {name="$1";next}
+# item locations
+/^MTFCC=C3/ {display_level=512;color=50; next}
+# Hospitals
+/^MTFCC=K12/ {filled=1; fill_color=12; label_color=12; display_level=256; label_level=128; font_size=12; next}
+# Schools
+/^MTFCC=K25/ {filled=1; fill_color=5; label_color=5; display_level=256; label_level=64; font_size=10; next}
+# Airports
+/^MTFCC=K24/ {filled=1; fill_color=13; label_color=13; display_level=256; label_level=128; font_size=12; next}
+# buildings
+/^MTFCC=K/ {filled=1; fill_color=2; label_color=2; display_level=256; next}
+# PLCC
+/^MTFCC=L/ {display_level=0; next}
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
+
+
diff --git a/config/predefined_EVENT.sys b/config/predefined_EVENT.sys
new file mode 100644
index 0000000..aac68ec
--- /dev/null
+++ b/config/predefined_EVENT.sys
@@ -0,0 +1,109 @@
+#
+# $Id: predefined_EVENT.sys,v 1.7 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2005-2012 The Xastir Group
+#
+# This file contains definitions for the Create SAR objects menu
+#
+# The objects defined here are typical Public Service Event objects.
+#
+# The objects defined here are ones that might be used in a public
+# service event such as a 5k race. Customize this file to fit your
+# needs.
+#
+# Typical modifications include internationalizing the names and menu text
+# and adding your own custom objects.
+#
+# To select this file as the source of custom objects in the Create SAR
+# objects menu, use the Load SAR objects menu options in the Configure
+# defaults dialog (File/Configure/Defaults).
+#
+# Lines begining with # are comments and will be ignored.
+#
+# Each line contains a tab separated variable and value pair.
+# Each set of lines defines an object as specified on the prepared
+# objects menu. Each set of lines must have variables defined in the
+# following order:
+#
+# NAME The name of the object.
+# Maximum length = MAX_CALLSIGN - 1 or - 2, to allow for Name1, Name2
+# incrementing numbers with multiple objects.
+# If name ends with a - then the first object will be called Name-1,
+# the second Name-2, and so on. If name does not end with a - then
+# The first object will be called Name, the second Name2.
+# PAGE The APRS symbol code page, / or \
+# Maximum length = 1 character.
+# SYMBOL The APRS symbol specifier.
+ Maximum length = 1 character.
+# DATA Additional data (such as probability circles) to follow the symbol in
+# the APRS string for the object
+# Use DATA NULL if there is no additional data, or omit the DATA line.
+# Maximum length = PREDEFINED_OBJECT_DATA_LENGTH = 44
+# MENU The text to appear on the prepared objects menu for this object.
+# Maximum length = 25 characters.
+# HIDDENCHILD NO for entries that appear on the menu. YES for a second
+# object to be created at the same time as the one above it.
+# This is a workaround to create an IPP and an IPP_ with different
+# probability circles in the same place at the same time.
+# YES is case sensitive.
+# HIDDENCHILD must be the last line in each object.
+#
+# NAME, PAGE, SYMBOL, MENU, and HIDDENCHILD are required for each object.
+#
+# Each set of lines specifying an object should be separated by a blank line
+# for clarity. Blank lines are ignored.
+#
+# The maximum number of objects that can be shown on the predefined object
+# menu is defined by the constant MAX_NUMBER_OF_PREDEFINED_OBJECTS.
+
+NAME ICP
+PAGE /
+SYMBOL c
+DATA NULL
+MENU ICP: Command Post
+HIDDENCHILD NO
+
+NAME Water
+PAGE /
+SYMBOL w
+DATA NULL
+MENU Water
+HIDDENCHILD NO
+
+# FirstAid post
+# "FirstAid" as name will only alow FirstAid1 to FirstAid9
+# due to the default length constraint on object names.
+NAME Aid
+#NAME FirstAid
+#NAME Aid-
+PAGE /
+# A is blue field with white cross, + is red cross
+SYMBOL A
+#SYMBOL +
+DATA NULL
+MENU Aid: First Aid
+#MENU First Aid
+#MENU Aid-n: First Aid
+HIDDENCHILD NO
+
+NAME Staging
+PAGE S
+SYMBOL 0
+DATA NULL
+MENU Staging
+HIDDENCHILD NO
+
+NAME Waypt-
+PAGE \
+SYMBOL m
+DATA NULL
+MENU Waypt-n: Waypoint
+HIDDENCHILD NO
+
+NAME Toilets
+PAGE \
+SYMBOL r
+DATA NULL
+MENU Toilets
+HIDDENCHILD NO
+
diff --git a/config/predefined_SAR.sys b/config/predefined_SAR.sys
new file mode 100644
index 0000000..f565a81
--- /dev/null
+++ b/config/predefined_SAR.sys
@@ -0,0 +1,135 @@
+#
+# $Id: predefined_SAR.sys,v 1.8 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2005-2012 The Xastir Group
+#
+# This file contains definitions for the Create SAR objects menu
+#
+# The objects defined here are typical Search and Rescue and ICS objects.
+#
+# You may modify this file to produce a custom set of prepared objects.
+# Typical modification would be changing probability circles from
+# miles to kilometers, placing probability circles around the PLS
+# instead of the IPP, internationalizing the names and menu text,
+# and adding your own standard objects.
+#
+# To select this file as the source of custom objects in the Create SAR
+# objects menu, use the Load SAR objects menu options in the Configure
+# defaults dialog (File/Configure/Defaults).
+#
+# Lines begining with # are comments and will be ignored.
+#
+# Each line contains a tab separated variable and value pair.
+# Each set of lines defines an object as specified on the prepared
+# objects menu. Each set of lines must have variables defined in the
+# following order:
+#
+# NAME The name of the object.
+# Maximum length = MAX_CALLSIGN - 1 or - 2, to allow for Name1, Name2
+# incrementing numbers with multiple objects.
+# If name ends with a - then the first object will be called Name-1,
+# the second Name-2, and so on. If name does not end with a - then
+# The first object will be called Name, the second Name2.
+# PAGE The APRS symbol code page, / or \
+# Maximum length = 1 character.
+# SYMBOL The APRS symbol specifier.
+ Maximum length = 1 character.
+# DATA Additional data (such as probability circles) to follow the symbol in
+# the APRS string for the object
+# Use DATA NULL if there is no additional data, or omit the DATA line.
+# Maximum length = PREDEFINED_OBJECT_DATA_LENGTH = 44
+# MENU The text to appear on the prepared objects menu for this object.
+# Maximum length = 25 characters.
+# HIDDENCHILD NO for entries that appear on the menu. YES for a second
+# object to be created at the same time as the one above it.
+# This is a workaround to create an IPP and an IPP_ with different
+# probability circles in the same place at the same time.
+# YES is case sensitive.
+# HIDDENCHILD must be the last line in each object.
+#
+# NAME, PAGE, SYMBOL, MENU, and HIDDENCHILD are required for each object.
+#
+# Each set of lines specifying an object should be separated by a blank line
+# for clarity. Blank lines are ignored.
+#
+# The maximum number of objects that can be shown on the predefined object
+# menu is defined by the constant MAX_NUMBER_OF_PREDEFINED_OBJECTS.
+
+NAME ICP
+PAGE /
+SYMBOL c
+DATA NULL
+MENU ICP: Command Post
+HIDDENCHILD NO
+
+NAME Staging
+PAGE S
+SYMBOL 0
+DATA NULL
+MENU Staging
+HIDDENCHILD NO
+
+NAME IPP
+PAGE /
+SYMBOL /
+#circles at .75 and 1 miles
+DATA Pmin0.75,Pmax1.0
+#circles at 2 and 3 kilometers
+#DATA Pmin1.24,Pmax1.86
+MENU IPP: InitialPlanningPoint
+HIDDENCHILD NO
+
+NAME IPP_
+PAGE /
+SYMBOL /
+# circles at .25 and .5 miles
+DATA Pmin0.25,Pmax0.5
+# circles at .5 and 1 kilometers
+#DATA Pmin0.31,Pmax0.62
+MENU [not shown]
+HIDDENCHILD YES
+
+NAME PLS
+PAGE /
+SYMBOL /
+DATA NULL
+MENU PLS: Point Last Seen
+HIDDENCHILD NO
+
+NAME LKP
+PAGE /
+SYMBOL .
+DATA NULL
+MENU LKP: Last Known Point
+HIDDENCHILD NO
+
+NAME Base
+PAGE B
+SYMBOL 0
+DATA NULL
+MENU Base
+HIDDENCHILD NO
+
+NAME Helibase
+PAGE H
+SYMBOL 0
+DATA NULL
+MENU Helibase
+HIDDENCHILD NO
+
+# Using Heli- will produce an object named Heli-1
+# with subsequent objects Heli-2, Heli-3, etc.
+NAME Heli-
+PAGE /
+SYMBOL /
+DATA NULL
+MENU Heli-n Helispot
+HIDDENCHILD NO
+
+NAME Camp
+PAGE C
+SYMBOL 0
+DATA NULL
+MENU Camp
+HIDDENCHILD NO
+
diff --git a/config/stored_track.dbfawk b/config/stored_track.dbfawk
new file mode 100644
index 0000000..779f39e
--- /dev/null
+++ b/config/stored_track.dbfawk
@@ -0,0 +1,15 @@
+# $Id: stored_track.dbfawk,v 1.3 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2009-2012 The Xastir Group
+#
+
+
+BEGIN {
+dbfinfo="Credits:DateTime:Label;
+dbffields="Label:DateTime";
+}
+
+BEGIN_RECORD {key=""; lanes=3; color=12; name=""; filled=0; pattern=0; display_level=65536; label_level=256; label_color=12; symbol=""}
+
+/^Label=(.*)$/ {name="$1";}
+/^DateTime=(.*)$/ {name="$name ($1)";}
diff --git a/config/tabblock.dbfawk b/config/tabblock.dbfawk
new file mode 100644
index 0000000..31acf9f
--- /dev/null
+++ b/config/tabblock.dbfawk
@@ -0,0 +1,53 @@
+# $Id: tabblock.dbfawk,v 1.4 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# Census.gov 2008 TigerMaps for TABBLOCK
+# Richard Polivka, N6NKO - April, 2008
+# Craig Anderson, N6YXK - May, 2008
+# Dale Seaburg, KG5LT - March, 2009
+#
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line Shapefiles as available at:
+# http://www.census.gov/geo/www/tiger/tgrshp2008/tgrshp2008.html
+#
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+# 2007FE = dbfinfo="STATEFP:COUNTYFP:COUNTYNS:STATEFP00:COUNTYFP00:TRACTCE00:BLOCKCE00:SUFFIX1CE:BLKIDFP:NAME:MTFCC:UR00:UACE00:FUNCSTAT";
+dbfinfo="STATEFP:COUNTYFP:COUNTYNS:STATEFP00:COUNTYFP00:TRACTCE00:BLOCKCE00:SUFFIX1CE:BLKIDFP:NAME:MTFCC:UR:UACE:FUNCSTAT";
+#dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="UR:NAME:MTFCC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=11; fill_color=26; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=26; font_size=0; symbol=""; fill_style=0 }
+
+#/^NAME=(.*)$/ {name="$1";next}
+# item locations
+/^MTFCC=G5/ {next}
+/^UR=U/ {display_level=2048;filled=1;color=99;fill_color=99; skip}
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
+
diff --git a/config/tgr2shp.dbfawk b/config/tgr2shp.dbfawk
new file mode 100644
index 0000000..93ae223
--- /dev/null
+++ b/config/tgr2shp.dbfawk
@@ -0,0 +1,263 @@
+# $Id: tgr2shp.dbfawk,v 1.11 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line shapefiles which are
+# converted to shapefiles using the command:
+# ogr2ogr -f "ESRI Shapefile" -t_srs "EPSG:4326" out_directory in_directory
+#
+# THis file is identical to the file "tgrlk" except for the "dbfinfo" variable
+# that is used to recognize the signature of the shapefiles.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="MODULE:TLID:SIDE1:SOURCE:FEDIRP:FENAME:FETYPE:FEDIRS:CFCC:FRADDL:TOADDL:FRADDR:TOADDR:FRIADDL:TOIADDL:FRIADDR:TOIADDR:ZIPL:ZIPR:AIANHHFPL:AIANHHFPR:AIHHTLIL:AIHHTLIR:CENSUS1:CENSUS2:STATEL:STATER:COUNTYL:COUNTYR:COUSUBL:COUSUBR:SUBMCDL:SUBMCDR:PLACEL:PLACER:TRACTL:TRACTR:BLOCKL:BLOCKR";
+#dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="TLID:FEDIRP:FENAME:FETYPE:FEDIRS:CFCC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=8; fill_color=11; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=8; font_size=0; symbol=""; fill_style=0 }
+
+# per-field rules are applied to the dbffields that are read from each record.
+# key: set the search key to be the Tiger/Line ID. Not currently used.
+/^TLID=(.*)$/ {key=$1; next}
+# name: concatenate FEDIRP (direction prefix), FENAME (name),
+# FETYPE (type: Rd, Ln, Pky, etc.) and FEDIRS (direction suffix).
+# also abbreviate United States Highway to US, etc.
+/^FEDIRP=(.+)$/ {name="$1 ";next}
+/^FENAME=United States Highway (.*)$/ {name="$(name)US $1"; next}
+/^FENAME=State Highway (.*)$/ {name="$(name)State $1";next}
+/^FENAME=State Route (.*)$/ {name="$(name)SR $1";next}
+/^FENAME=(.*)$/ {name="$(name)$1"; next}
+/^FETYPE=(.+)$/ {name="$(name) $1"; next}
+/^FEDIRS=(.+)$/ {name="$(name) $1"; next}
+# Census Feature Class Codes are used to set lanes, color, display_level, etc.
+# CFCC A..: roads
+# A11 - primary limited access road or interstate highway, unseparated
+# A12 - primary limited access road or interstate highway, unseparated in tunnel
+# A13 - primary limited access road or interstate highway, unseparated, underpassing
+# A14 - primary limited access road or interstate highway, unseparated, with rail line in center
+# A15 - primary limited access road or interstate highway, separated
+# A16 - primary limited access road or interstate highway, separated, in tunnel
+# A17 - primary limited access road or interstate highway, separated, underpassing
+# A18 - primary limited access road or interstate highway, separated, with rail line in center
+# A21 - primary road without limit access, US highways, unseparated
+# A22 -primary road without limit access, US highways, unseparated, in tunnel
+# A23 - primary road without limit access, US highways, underpassing
+# A24 - primary road without limit access, US highways, unseparated, with rail line in center
+# A25 - primary road without limit access, US highways, separated
+# A26 - primary road without limit access, US highways, separated, in tunnel
+# A27 - primary road without limit access, US highways, separated, underpassing
+# A28 - primary road without limit access, US highways, separated, with rail line in center
+# A31 - secondary and connection road, state highways, unseperated
+# A32 - " in tunnel
+# A33 - " underpassing
+# A34 - " with rail line in center
+# A35 - secondary and connection road, state highways, seperated
+# A36 - " in tunnel
+# A37 - " underpassing
+# A38 - " with rail line in center
+# A41 - local, neighborhood and rural road, city street, unseparated
+# A42 - " in tunnel
+# A43 - " underpassing
+# A44 - " with rail line in center
+# A45 - local, neighborhood and rural road, city street, separated
+# A46 - " in tunnel
+# A47 - " underpassing
+# A48 - " with rail line in center
+# A51 - vehicular trail, unseparated
+# A52 - " in tunnel
+# A53 - " underpassing
+# A61 - cul-de-sac
+# A62 - traffic circle
+# A63 - access ramp
+# A64 - service drive
+# A65 - ferry crossing
+# A71 - walkway or trail
+# A72 - stairway
+# A73 - alley
+# A74 - driveway
+# "P" types denote "Provisional" streets that had not been field checked
+# or verified through aerial photography as of the date of preparation of
+# the TIGER/Line data. They are otherwise equivalent to "A" types, and
+# we'll just display them the same way.
+/^CFCC=[AP]1/ {lanes=4; color=4; label_level=512; font_size=3; next}
+/^CFCC=[AP]2/ {lanes=3; color=8; label_level=256; font_size=2; next}
+/^CFCC=[AP]3/ {lanes=2; color=8; label_level=128; font_size=1; next}
+/^CFCC=[AP]3[1-6]/ {display_level=256; next}
+/^CFCC=[AP]3[7-8]/ {display_level=128; next}
+/^CFCC=[AP]4/ {display_level=96; label_level=16; color=40; lanes=1; next}
+/^CFCC=[AP]5/ {lanes=2; color=40; display_level=64; font_size=1; next}
+/^CFCC=[AP]65/ {lanes=2; color=8; pattern=2; font_size=1; next}
+/^CFCC=[AP]6[^5]/ {color=40; display_level=64; next}
+/^CFCC=[AP]7[12]/ {lanes=1; color=12; pattern=2; display_level=64; next}
+/^CFCC=[AP]7[03-9]/ {lanes=1; color=40; pattern=2; display_level=64; next}
+# need to implement these:
+# B: railroads
+# B01 - railroad track
+# B02 - " in tunnel
+# B03 - " underpassing
+# B11 - railroad main line
+# B12 - " in tunnel
+# B13 - " underpassing
+# B21 - railroad spur
+# B22 - " in tunnel
+# B23 - " underpassing
+# B31 - railroad yard track
+# B32 - " in tunnel
+# B33 - " underpassing
+# B40 - railroad ferry crossing
+# B50 - other rail line
+# B51 - carline (streetcars, etc.)
+# B52 - cog railroad, incline railway or logging tram
+/^CFCC=B/ {lanes=1; color=8; pattern=1; display_level=128; next}
+# C: transmission lines
+# C00 - misc ground transportation
+# C10 - pipeline
+# C20 - power transmission line
+# C30 - other ground transportation
+# C31 - aerial tramway
+/^CFCC=C/ {display_level=0; next}
+# D: landmarks
+# D00 - unknown
+# D10 - military installation
+# D20 - multihousehold or transient quarters
+# D21 - apartment building or complex
+# D22 - rooming or boarding house
+# D23 - trailer cour or mobile home park
+# D24 - marina
+# D25 - crew-of-vessel area
+# D26 - housing facility for workers
+# D27 - hotel, motel, resort, spa, YMCA, YWCA
+# D28 - campground
+# D29 - shelter or mission
+# D30 - custodial facility
+# D31 - hospital
+# D32 - halfway house
+# D33 - nursing home
+# D34 - county home or poor farm
+# D35 - orphanage
+# D36 - jail
+# D37 - federal penetentiary, state prison, or prison farm
+# D40 - unknown educational or religious
+# D41 - sorority or fraternity
+# D42 - convent or monastery
+# D43 - educational institution
+# D44 - religious institution
+# D50 - transportation terminal
+# D51 - airport
+# D52 - train station
+# D53 - bus terminal
+# D54 - marine terminal
+# D55 - seaplane anchorage
+# D70 - tower
+# D71 - lookout tower
+# D80 - open space
+# D81 - golf course
+# D82 - cemetery
+# D83 - national park
+# D84 - national forest
+# D85 - state or local park or forest
+# D90 - special purpose landmark
+# D91 - post office box-only ZIP Code location
+# D92 - urbanizacion (Puerto Rico)
+# E: physical featuers
+# E00 - unknown physical feature
+# E10 - fence line
+# E20 - topgraphic feature
+# E21 - ridge line
+# E22 - mountain peak
+# E23 - island
+# F: legal boundaries
+# F00 - nonvisible boundary
+# F10 - jurisdictional boundary
+# F11 - offset boundary
+# F12 - corridor boundary
+# F13 - interpolate boundary across water
+# F14 - superseded boundary
+# F15 - superseded boundary, corrected
+# F20 - data base topology
+# F21 - automated feature extension to lenghten physical feature
+# F22 - irregular feature extension, determined manually
+# F23 - closure extension
+# F24 - separation line
+# F25 - centerline
+# F30 - point-to-point line
+# F40 - property line
+# F50 - Zip Code boundary
+# F60 - map edge
+# F70 - statistical boundardy
+# F71 - 1980 "
+# F72 - 1990 "
+# F73 - internal use
+# F74 - 1990 " ...
+# F80 - other tabulation boundary
+# F81 - internal use
+# F82 - internal use
+/^CFCC=F10$/{color=255; fill_color=255; label_level=32; display_level=512; pattern=0; next}
+/^CFCC=F/{display_level=0; next}
+# (G not used by census; tig2aprs uses for special maps)
+# H: hydrography
+# H00 - water feature
+# H01 - shoreline of perennial water feature
+# H02 - shoreline of intermittent "
+# H10 - stream
+# H11 - perennial stream
+# H12 - intermittent stream
+# H13 - braided stream or river
+# H20 - canal, ditch or aqueduct
+# H21 - perennial "
+# H22 - intermittent "
+# H30 - lake or pond
+# H31 - perennial "
+# H32 - intermittent "
+# H40 - reservoir
+# H41 - perennial "
+# H42 - intermittent "
+# H50 - bay, estuary, gulf, sound, sea, ocean
+# H51 - bay, estuary, gulf or sound
+# H52 - sea or ocean
+# H60 - gravel pit or quarry filled with water
+# H70 - nonvisibile....
+# H80 - special water features
+# H81 - glacier
+# Don't display hydrology unless zoomed all the way in --- adjust to taste,
+# in NM anything more than this looks absurd coz every intermittent wash
+# would show up as a blue line, which is just wrong.
+/^CFCC=H/ {lanes=0; color=26; fill_color=26; label_color=26; display_level=1;}
+/^CFCC=H01/ {pattern=0; display_level=512; lanes=1; next}
+/^CFCC=H02/ {pattern=2; display_level=1; next}
+/^CFCC=H[124]2/ {lanes=1; pattern=2; display_level=128; next}
+# These filled patterns don't actually work: the tiger shapefiles produced
+# by ogr2ogr do not have the polygon features readily accessible!
+/^CFCC=H[34][01]/ {lanes=1; pattern=0; filled=1; fill_style=0; display_level=512; next}
+/^CFCC=H32/ {lanes=1; pattern=1; filled=1; fill_style=1; display_level=512; next}
+/^CFCC=H[1-6][013-9]/ {lanes=1; display_level=512; next}
+/^CFCC=H7/ {display_level=0; label_level=0; next}
+/^CFCC=H8/ {lanes=1; display_level=1}
+/^CFCC=H81/ {color=15; fill_color=15; display_level=256; next}
+# X00 - feature not yet classified
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
diff --git a/config/tgr2shppoly.dbfawk b/config/tgr2shppoly.dbfawk
new file mode 100644
index 0000000..221dc92
--- /dev/null
+++ b/config/tgr2shppoly.dbfawk
@@ -0,0 +1,262 @@
+# $Id: tgr2shppoly.dbfawk,v 1.15 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line shapefiles which are
+# converted to shapefiles using the Xastir_tigerpoly.py utility
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+dbfinfo="MODULE:FILE:CENID:POLYID:STATECU:COUNTYCU:TRACT:BLOCK:BLOCKSUFCU:RS_A1:AIANHHFPCU:AIANHHCU:AIHHTLICU:ANRCCU:AITSCECU:AITSCU:CONCITCU:COUSUBCU:SUBMCDCU:PLACECU:SDELMCU:SDSECCU:SDUNICU:RS_A20:RS_A21:RS_A22:CDCU:ZCTA5CU:ZCTA3CU:RS_A4:RS_A5:RS_A6:RS_A7:RS_A8:RS_A9:CBSACU:CSACU:NECTACU:CNECTACU:METDIVCU:NECTADIVCU:RS_A14:RS_A15:RS_A16:RS_A17:RS_A18:RS_A19:STATE:COUNTY:BLKGRP:AIANHHFP:AIANHH:AIHHTLI:ANRC:AITSCE:AITS:CONCIT:COUSUB:SUBMCD:PLACE:SDELM:SDSEC:SDUNI:MSACMSA:PMSA:NECMA:CD106 [...]
+#dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="WATER:CFCC:LANAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=8; fill_color=11; name=""; filled=0; pattern=0; display_level=0; label_level=32; label_color=8; font_size=0; symbol=""; fill_style=0; fill_stipple=0 }
+
+# Name -- only features that have landmark records get names
+/^LANAME=None$/ {next}
+/^LANAME=(.*)$/ {name="$1"; next}
+
+#We need this just in case there is no CFCC code to tell us we're a water
+# feature
+#Perennial water
+/^WATER=1$/ {filled=1; fill_style=2; fill_stipple=2; color=117; fill_color=117; label_color=26; display_level=1024;}
+#intermittent water
+/^WATER=2$/ {filled=1; fill_style=2; fill_stipple=0; color=117; fill_color=117; label_color=26; display_level=512;pattern=1;}
+
+# These are *all* the allowed feature classes, even those that aren't
+# polygon types. We won't actually bother testing for anything other
+# than the ones we expect to find, lest we spend too much time filtering.
+
+# Census Feature Class Codes are used to set lanes, color, display_level, etc.
+# CFCC A..: roads
+# A11 - primary limited access road or interstate highway, unseparated
+# A12 - primary limited access road or interstate highway, unseparated in tunnel
+# A13 - primary limited access road or interstate highway, unseparated, underpassing
+# A14 - primary limited access road or interstate highway, unseparated, with rail line in center
+# A15 - primary limited access road or interstate highway, separated
+# A16 - primary limited access road or interstate highway, separated, in tunnel
+# A17 - primary limited access road or interstate highway, separated, underpassing
+# A18 - primary limited access road or interstate highway, separated, with rail line in center
+# A21 - primary road without limit access, US highways, unseparated
+# A22 -primary road without limit access, US highways, unseparated, in tunnel
+# A23 - primary road without limit access, US highways, underpassing
+# A24 - primary road without limit access, US highways, unseparated, with rail line in center
+# A25 - primary road without limit access, US highways, separated
+# A26 - primary road without limit access, US highways, separated, in tunnel
+# A27 - primary road without limit access, US highways, separated, underpassing
+# A28 - primary road without limit access, US highways, separated, with rail line in center
+# A31 - secondary and connection road, state highways, unseperated
+# A32 - " in tunnel
+# A33 - " underpassing
+# A34 - " with rail line in center
+# A35 - secondary and connection road, state highways, seperated
+# A36 - " in tunnel
+# A37 - " underpassing
+# A38 - " with rail line in center
+# A41 - local, neighborhood and rural road, city street, unseparated
+# A42 - " in tunnel
+# A43 - " underpassing
+# A44 - " with rail line in center
+# A45 - local, neighborhood and rural road, city street, separated
+# A46 - " in tunnel
+# A47 - " underpassing
+# A48 - " with rail line in center
+# A51 - vehicular trail, unseparated
+# A52 - " in tunnel
+# A53 - " underpassing
+# A61 - cul-de-sac
+# A62 - traffic circle
+# A63 - access ramp
+# A64 - service drive
+# A65 - ferry crossing
+# A71 - walkway or trail
+# A72 - stairway
+# A73 - alley
+# A74 - driveway
+
+#Roads are not going to be polygons, don't even check
+
+# need to implement these:
+# B: railroads
+# B01 - railroad track
+# B02 - " in tunnel
+# B03 - " underpassing
+# B11 - railroad main line
+# B12 - " in tunnel
+# B13 - " underpassing
+# B21 - railroad spur
+# B22 - " in tunnel
+# B23 - " underpassing
+# B31 - railroad yard track
+# B32 - " in tunnel
+# B33 - " underpassing
+# B40 - railroad ferry crossing
+# B50 - other rail line
+# B51 - carline (streetcars, etc.)
+# B52 - cog railroad, incline railway or logging tram
+# /^CFCC=B/ {lanes=1; color=8; pattern=1; display_level=128; next}
+
+# C: transmission lines
+# C00 - misc ground transportation
+# C10 - pipeline
+# C20 - power transmission line
+# C30 - other ground transportation
+# C31 - aerial tramway
+# /^CFCC=C/ {display_level=0; next}
+# D: landmarks
+# D00 - unknown
+# D10 - military installation
+# color is RosyBrown2
+/^CFCC=D1/ { filled=1; color=112; fill_color=112; fill_style=2; fill_stipple=0; display_level=1024; font_size=1; next}
+# D20 - multihousehold or transient quarters
+# D21 - apartment building or complex
+# D22 - rooming or boarding house
+# D23 - trailer cour or mobile home park
+# D24 - marina
+# D25 - crew-of-vessel area
+# D26 - housing facility for workers
+# D27 - hotel, motel, resort, spa, YMCA, YWCA
+# D28 - campground
+# D29 - shelter or mission
+/^CFCC=D2/ {filled=1; color=14; fill_color=14; fill_style=2; fill_stipple=0; display_level=128; font_size=1; next}
+# D30 - custodial facility
+# D31 - hospital
+# D32 - halfway house
+# D33 - nursing home
+# D34 - county home or poor farm
+# D35 - orphanage
+# D36 - jail
+# D37 - federal penetentiary, state prison, or prison farm
+/^CFCC=D3/ {filled=1; color=13; fill_color=13; fill_style=2; fill_stipple=0; display_level=128; font_size=1; next}
+# D40 - unknown educational or religious
+# D41 - sorority or fraternity
+# D42 - convent or monastery
+# D43 - educational institution
+# D44 - religious institution
+/^CFCC=D4/ { filled=1; color=20; fill_color=20; fill_style=2; fill_stipple=0; display_level=64; font_size=1; next}
+# D50 - transportation terminal
+# D51 - airport
+# D52 - train station
+# D53 - bus terminal
+# D54 - marine terminal
+# D55 - seaplane anchorage
+# D57 - Airport
+# color is "gray81"
+/^CFCC=D5/ {filled=1; color=113; fill_color=113; fill_style=2; fill_stipple=1; display_level=512; font_size=1; next}
+# D60 - Employment center
+# D61 - Shopping center
+# D62 - Industrial Building or Ind. park
+# D63 - Office Building or office park
+# D64 - Amusement Center
+# D65 - Government Center
+# D66 - Other emplyoment center
+/^CFCC=D6/ {filled=1; color=113; fill_color=113; fill_style=2; fill_stipple=0; display_level=256; font_size=1; next}
+# D70 - tower
+# D71 - lookout tower
+/^CFCC=D7/ {filled=1; color=113; fill_color=113; fill_style=2; fill_stipple=0; display_level=128; font_size=1; next}
+# D80 - open space
+# D81 - golf course
+# D82 - cemetery
+# Color is "tgr_park_1"
+/^CFCC=D8[01]/ {filled=1; color=114; fill_color=114; fill_style=2; fill_stipple=0; display_level=512; font_size=1; next}
+# D83 - national park
+# D84 - national forest
+# D85 - state or local park or forest
+# color is "tgr_forest_1"
+/^CFCC=D8[3-5]/ {filled=1; color=116; fill_color=116; fill_style=2; fill_stipple=0; display_level=1024; font_size=1; next}
+# D90 - special purpose landmark
+# D91 - post office box-only ZIP Code location
+# D92 - urbanizacion (Puerto Rico)
+/^CFCC=D9/ {filled=1; color=101; fill_color=101; fill_style=2; fill_stipple=0; display_level=256; font_size=1; next}
+
+# E: physical featuers
+# E00 - unknown physical feature
+# E10 - fence line
+# E20 - topgraphic feature
+# E21 - ridge line
+# E22 - mountain peak
+# E23 - island
+# Don't display the E's
+# F: legal boundaries
+# F00 - nonvisible boundary
+# F10 - jurisdictional boundary
+# F11 - offset boundary
+# F12 - corridor boundary
+# F13 - interpolate boundary across water
+# F14 - superseded boundary
+# F15 - superseded boundary, corrected
+# F20 - data base topology
+# F21 - automated feature extension to lenghten physical feature
+# F22 - irregular feature extension, determined manually
+# F23 - closure extension
+# F24 - separation line
+# F25 - centerline
+# F30 - point-to-point line
+# F40 - property line
+# F50 - Zip Code boundary
+# F60 - map edge
+# F70 - statistical boundardy
+# F71 - 1980 "
+# F72 - 1990 "
+# F73 - internal use
+# F74 - 1990 " ...
+# F80 - other tabulation boundary
+# F81 - internal use
+# F82 - internal use
+/^CFCC=F/{filled=1; color=115; fill_color=115; fill_style=0; label_level=32; display_level=512; pattern=0; next}
+#/^CFCC=F/{display_level=0; next}
+# Don't bother with the F's either for now
+# (G not used by census; tig2aprs uses for special maps)
+# H: hydrography
+# Color is "tgr_water_1"
+/^CFCC=H/ {filled=1; color=117; fill_color=3; label_color=26; display_level=512;}
+# H00 - water feature
+# H01 - shoreline of perennial water feature
+# H02 - shoreline of intermittent "
+/^CFCC=H0/ {filled=1; fill_style=2; fill_stipple=2; display_level=4096; label_level=16; lanes=1}
+/^CFCC=H02/ {filled=1; fill_stipple=0; pattern=1; next}
+# H10 - stream
+# H11 - perennial stream
+# H12 - intermittent stream
+# H13 - braided stream or river
+# H20 - canal, ditch or aqueduct
+# H21 - perennial "
+# H22 - intermittent "
+# H30 - lake or pond
+# H31 - perennial "
+# H32 - intermittent "
+# H40 - reservoir
+# H41 - perennial "
+# H42 - intermittent "
+# H50 - bay, estuary, gulf, sound, sea, ocean
+# H51 - bay, estuary, gulf or sound
+# H52 - sea or ocean
+/^CFCC=H[1-5]/ {filled=1; fill_style=2; fill_stipple=2;display_level=256; label_level=16; lanes=1}
+/^CFCC=H[1-4]2/ {filled=1; fill_stipple=0; pattern=1; next}
+# H60 - gravel pit or quarry filled with water
+/^CFCC=H6/ {filled=1; fill_style=2; fill_stipple=2;display_level=256; label_level=16; lanes=1}
+# H70 - nonvisibile....
+# H80 - special water features
+# H81 - glacier
+/^CFCC=H81/ {filled=1; color=15; fill_color=15; fill_style=2; fill_stipple=2;display_level=256; label_level=16; lanes=1}
diff --git a/config/tgr2shppoly_2006.dbfawk b/config/tgr2shppoly_2006.dbfawk
new file mode 100644
index 0000000..917c6aa
--- /dev/null
+++ b/config/tgr2shppoly_2006.dbfawk
@@ -0,0 +1,265 @@
+# $Id: tgr2shppoly_2006.dbfawk,v 1.5 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line shapefiles which are
+# converted to shapefiles using the Xastir_tigerpoly.py utility
+#
+# It differs from the "tgr2shppoly.dbfawk" file only in the DBF signature,
+# which changed between the 2004 and 2006 TIGER/Line releases.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+dbfinfo="MODULE:FILE:CENID:POLYID:STATECU:COUNTYCU:TRACT:BLOCK:BLOCKSUFCU:RS_A1:AIANHHFPCU:AIANHHCU:AIHHTLICU:ANRCCU:AITSCECU:AITSCU:CONCITCU:COUSUBCU:SUBMCDCU:PLACECU:SDELMCU:SDSECCU:SDUNICU:RS_A20:RS_A21:RS_A22:CDCU:ZCTA5CU:ZCTA3CU:RS_A4:RS_A5:RS_A6:RS_A7:RS_A8:RS_A9:CBSACU:CSACU:NECTACU:CNECTACU:METDIVCU:NECTADIVCU:RS_A14:UACU:URCU:RS_A17:RS_A18:RS_A19:STATE:COUNTY:BLKGRP:AIANHHFP:AIANHH:AIHHTLI:ANRC:AITSCE:AITS:CONCIT:COUSUB:SUBMCD:PLACE:SDELM:SDSEC:SDUNI:MSACMSA:PMSA:NECMA:CD106:CD1 [...]
+#dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="WATER:CFCC:LANAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=8; fill_color=11; name=""; filled=0; pattern=0; display_level=0; label_level=32; label_color=8; font_size=0; symbol=""; fill_style=0; fill_stipple=0 }
+
+# Name -- only features that have landmark records get names
+/^LANAME=None$/ {next}
+/^LANAME=(.*)$/ {name="$1"; next}
+
+#We need this just in case there is no CFCC code to tell us we're a water
+# feature
+#Perennial water
+/^WATER=1$/ {filled=1; fill_style=2; fill_stipple=2; color=117; fill_color=117; label_color=26; display_level=1024;}
+#intermittent water
+/^WATER=2$/ {filled=1; fill_style=2; fill_stipple=0; color=117; fill_color=117; label_color=26; display_level=512;pattern=1;}
+
+# These are *all* the allowed feature classes, even those that aren't
+# polygon types. We won't actually bother testing for anything other
+# than the ones we expect to find, lest we spend too much time filtering.
+
+# Census Feature Class Codes are used to set lanes, color, display_level, etc.
+# CFCC A..: roads
+# A11 - primary limited access road or interstate highway, unseparated
+# A12 - primary limited access road or interstate highway, unseparated in tunnel
+# A13 - primary limited access road or interstate highway, unseparated, underpassing
+# A14 - primary limited access road or interstate highway, unseparated, with rail line in center
+# A15 - primary limited access road or interstate highway, separated
+# A16 - primary limited access road or interstate highway, separated, in tunnel
+# A17 - primary limited access road or interstate highway, separated, underpassing
+# A18 - primary limited access road or interstate highway, separated, with rail line in center
+# A21 - primary road without limit access, US highways, unseparated
+# A22 -primary road without limit access, US highways, unseparated, in tunnel
+# A23 - primary road without limit access, US highways, underpassing
+# A24 - primary road without limit access, US highways, unseparated, with rail line in center
+# A25 - primary road without limit access, US highways, separated
+# A26 - primary road without limit access, US highways, separated, in tunnel
+# A27 - primary road without limit access, US highways, separated, underpassing
+# A28 - primary road without limit access, US highways, separated, with rail line in center
+# A31 - secondary and connection road, state highways, unseperated
+# A32 - " in tunnel
+# A33 - " underpassing
+# A34 - " with rail line in center
+# A35 - secondary and connection road, state highways, seperated
+# A36 - " in tunnel
+# A37 - " underpassing
+# A38 - " with rail line in center
+# A41 - local, neighborhood and rural road, city street, unseparated
+# A42 - " in tunnel
+# A43 - " underpassing
+# A44 - " with rail line in center
+# A45 - local, neighborhood and rural road, city street, separated
+# A46 - " in tunnel
+# A47 - " underpassing
+# A48 - " with rail line in center
+# A51 - vehicular trail, unseparated
+# A52 - " in tunnel
+# A53 - " underpassing
+# A61 - cul-de-sac
+# A62 - traffic circle
+# A63 - access ramp
+# A64 - service drive
+# A65 - ferry crossing
+# A71 - walkway or trail
+# A72 - stairway
+# A73 - alley
+# A74 - driveway
+
+#Roads are not going to be polygons, don't even check
+
+# need to implement these:
+# B: railroads
+# B01 - railroad track
+# B02 - " in tunnel
+# B03 - " underpassing
+# B11 - railroad main line
+# B12 - " in tunnel
+# B13 - " underpassing
+# B21 - railroad spur
+# B22 - " in tunnel
+# B23 - " underpassing
+# B31 - railroad yard track
+# B32 - " in tunnel
+# B33 - " underpassing
+# B40 - railroad ferry crossing
+# B50 - other rail line
+# B51 - carline (streetcars, etc.)
+# B52 - cog railroad, incline railway or logging tram
+# /^CFCC=B/ {lanes=1; color=8; pattern=1; display_level=128; next}
+
+# C: transmission lines
+# C00 - misc ground transportation
+# C10 - pipeline
+# C20 - power transmission line
+# C30 - other ground transportation
+# C31 - aerial tramway
+# /^CFCC=C/ {display_level=0; next}
+# D: landmarks
+# D00 - unknown
+# D10 - military installation
+# color is RosyBrown2
+/^CFCC=D1/ { filled=1; color=112; fill_color=112; fill_style=2; fill_stipple=0; display_level=1024; font_size=1; next}
+# D20 - multihousehold or transient quarters
+# D21 - apartment building or complex
+# D22 - rooming or boarding house
+# D23 - trailer cour or mobile home park
+# D24 - marina
+# D25 - crew-of-vessel area
+# D26 - housing facility for workers
+# D27 - hotel, motel, resort, spa, YMCA, YWCA
+# D28 - campground
+# D29 - shelter or mission
+/^CFCC=D2/ {filled=1; color=14; fill_color=14; fill_style=2; fill_stipple=0; display_level=128; font_size=1; next}
+# D30 - custodial facility
+# D31 - hospital
+# D32 - halfway house
+# D33 - nursing home
+# D34 - county home or poor farm
+# D35 - orphanage
+# D36 - jail
+# D37 - federal penetentiary, state prison, or prison farm
+/^CFCC=D3/ {filled=1; color=13; fill_color=13; fill_style=2; fill_stipple=0; display_level=128; font_size=1; next}
+# D40 - unknown educational or religious
+# D41 - sorority or fraternity
+# D42 - convent or monastery
+# D43 - educational institution
+# D44 - religious institution
+/^CFCC=D4/ { filled=1; color=20; fill_color=20; fill_style=2; fill_stipple=0; display_level=64; font_size=1; next}
+# D50 - transportation terminal
+# D51 - airport
+# D52 - train station
+# D53 - bus terminal
+# D54 - marine terminal
+# D55 - seaplane anchorage
+# D57 - Airport
+# color is "gray81"
+/^CFCC=D5/ {filled=1; color=113; fill_color=113; fill_style=2; fill_stipple=1; display_level=512; font_size=1; next}
+# D60 - Employment center
+# D61 - Shopping center
+# D62 - Industrial Building or Ind. park
+# D63 - Office Building or office park
+# D64 - Amusement Center
+# D65 - Government Center
+# D66 - Other emplyoment center
+/^CFCC=D6/ {filled=1; color=113; fill_color=113; fill_style=2; fill_stipple=0; display_level=256; font_size=1; next}
+# D70 - tower
+# D71 - lookout tower
+/^CFCC=D7/ {filled=1; color=113; fill_color=113; fill_style=2; fill_stipple=0; display_level=128; font_size=1; next}
+# D80 - open space
+# D81 - golf course
+# D82 - cemetery
+# Color is "tgr_park_1"
+/^CFCC=D8[01]/ {filled=1; color=114; fill_color=114; fill_style=2; fill_stipple=0; display_level=512; font_size=1; next}
+# D83 - national park
+# D84 - national forest
+# D85 - state or local park or forest
+# color is "tgr_forest_1"
+/^CFCC=D8[3-5]/ {filled=1; color=116; fill_color=116; fill_style=2; fill_stipple=0; display_level=1024; font_size=1; next}
+# D90 - special purpose landmark
+# D91 - post office box-only ZIP Code location
+# D92 - urbanizacion (Puerto Rico)
+/^CFCC=D9/ {filled=1; color=101; fill_color=101; fill_style=2; fill_stipple=0; display_level=256; font_size=1; next}
+
+# E: physical featuers
+# E00 - unknown physical feature
+# E10 - fence line
+# E20 - topgraphic feature
+# E21 - ridge line
+# E22 - mountain peak
+# E23 - island
+# Don't display the E's
+# F: legal boundaries
+# F00 - nonvisible boundary
+# F10 - jurisdictional boundary
+# F11 - offset boundary
+# F12 - corridor boundary
+# F13 - interpolate boundary across water
+# F14 - superseded boundary
+# F15 - superseded boundary, corrected
+# F20 - data base topology
+# F21 - automated feature extension to lenghten physical feature
+# F22 - irregular feature extension, determined manually
+# F23 - closure extension
+# F24 - separation line
+# F25 - centerline
+# F30 - point-to-point line
+# F40 - property line
+# F50 - Zip Code boundary
+# F60 - map edge
+# F70 - statistical boundardy
+# F71 - 1980 "
+# F72 - 1990 "
+# F73 - internal use
+# F74 - 1990 " ...
+# F80 - other tabulation boundary
+# F81 - internal use
+# F82 - internal use
+/^CFCC=F/{filled=1; color=115; fill_color=115; fill_style=0; label_level=32; display_level=512; pattern=0; next}
+#/^CFCC=F/{display_level=0; next}
+# Don't bother with the F's either for now
+# (G not used by census; tig2aprs uses for special maps)
+# H: hydrography
+# Color is "tgr_water_1"
+/^CFCC=H/ {filled=1; color=117; fill_color=3; label_color=26; display_level=512;}
+# H00 - water feature
+# H01 - shoreline of perennial water feature
+# H02 - shoreline of intermittent "
+/^CFCC=H0/ {filled=1; fill_style=2; fill_stipple=2; display_level=4096; label_level=16; lanes=1}
+/^CFCC=H02/ {filled=1; fill_stipple=0; pattern=1; next}
+# H10 - stream
+# H11 - perennial stream
+# H12 - intermittent stream
+# H13 - braided stream or river
+# H20 - canal, ditch or aqueduct
+# H21 - perennial "
+# H22 - intermittent "
+# H30 - lake or pond
+# H31 - perennial "
+# H32 - intermittent "
+# H40 - reservoir
+# H41 - perennial "
+# H42 - intermittent "
+# H50 - bay, estuary, gulf, sound, sea, ocean
+# H51 - bay, estuary, gulf or sound
+# H52 - sea or ocean
+/^CFCC=H[1-5]/ {filled=1; fill_style=2; fill_stipple=2;display_level=256; label_level=16; lanes=1}
+/^CFCC=H[1-4]2/ {filled=1; fill_stipple=0; pattern=1; next}
+# H60 - gravel pit or quarry filled with water
+/^CFCC=H6/ {filled=1; fill_style=2; fill_stipple=2;display_level=256; label_level=16; lanes=1}
+# H70 - nonvisibile....
+# H80 - special water features
+# H81 - glacier
+/^CFCC=H81/ {filled=1; color=15; fill_color=15; fill_style=2; fill_stipple=2;display_level=256; label_level=16; lanes=1}
diff --git a/config/tgrcty.dbfawk b/config/tgrcty.dbfawk
new file mode 100644
index 0000000..a222d39
--- /dev/null
+++ b/config/tgrcty.dbfawk
@@ -0,0 +1,48 @@
+# $Id: tgrcty.dbfawk,v 1.15 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line "cty" polygon shapefiles
+# which are named tgrSSCCCcty00.dbf, where SSCCC are the FIPS state and
+# county codes.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="ID:FIPSSTCO:STATE:COUNTY";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="COUNTY:FIPSSTCO";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key=""; lanes=1; fill_color=11; color=8; name=""; filled=0; pattern=0; display_level=8192; label_level=512; label_color=20; font_size=4; symbol=""}
+
+# name: name is just the county name.
+/^COUNTY=(.*)$/ {name="$1"; next}
+# key: set the search key to be the FIPS code. Not currently used.
+# also append County to the name except for Louisiana, use Parish:
+/^FIPSSTCO=(22.*)$/ {name="$name Parish"; key=$1; next}
+/^FIPSSTCO=(.*)$/ {name="$name County"; key=$1; next}
+# don't need special end case handling...
+#END_RECORD {name="$name ($key)";}
+#END {}
diff --git a/config/tgrkgl.dbfawk b/config/tgrkgl.dbfawk
new file mode 100644
index 0000000..c36e0cb
--- /dev/null
+++ b/config/tgrkgl.dbfawk
@@ -0,0 +1,66 @@
+# $Id: tgrkgl.dbfawk,v 1.14 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line "kgl" (Key Geographic
+# Location) shapefiles which are named tgrSSCCCkgl.dbf, where SSCCC
+# are the FIPS state and county codes.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="ID:POLYID:COUNTY:CFCC:KGLNAME";
+# dbffields is which of the above fields we actually want to look at.
+dbffields="KGLNAME:CFCC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key=""; lanes=1; fill_color=255; color=8; name=""; filled=1; pattern=0;
+display_level=0; label_level=0; label_color=8; font_size=2; symbol="/. "}
+
+# name and key are both the KGL name
+/^KGLNAME=(.*)$/ {name=$1; key=$1; next}
+# CFCC=D.. for landmarks. Use the same code here and for tgrlk.
+#D2: residence?
+#D23: trailer park
+#D28: campground
+/^CFCC=D2/ {symbol="/- "; display_level=64; label_level=32}
+/^CFCC=D23$/ {symbol="/R "; next}
+/^CFCC=D28$/ {symbol="/; "; next}
+/^CFCC=D2/ {next}
+#D31: hospital
+/^CFCC=D31$/ {color=9; symbol="/h "; display_level=128; label_level=64; next}
+#D40: unknown educational or religious
+#D41: sorority or fraternity
+#D42: convent or monastery
+#D43: educational institution
+#D44: religious institution
+/^CFCC=D4/ {color=8; symbol="/K "; display_level=64; label_level=32}
+/^CFCC=D4[03]$/ {color=14; next}
+#D51: airport
+#D54: harbor
+/^CFCC=D51$/ {symbol="/' "; display_level=128; label_level=32; next}
+/^CFCC=D54$/ {symbol="\\s "; display_level=128; label_level=32; next }
+#DB: state forests, etc.
+/^CFCC=D8/ {color=73; display_level=64; label_level=32; next}
+# don't need special end case handling...
+#END_RECORD {}
+#END {}
diff --git a/config/tgrlk.dbfawk b/config/tgrlk.dbfawk
new file mode 100644
index 0000000..cd1c37b
--- /dev/null
+++ b/config/tgrlk.dbfawk
@@ -0,0 +1,247 @@
+# $Id: tgrlk.dbfawk,v 1.16 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line "lk" shapefiles which are
+# named tgrSSCCClk[A-H].dbf, where SSCCC are the FIPS state and county codes.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="TLID:FNODE:TNODE:LENGTH:FEDIRP:FENAME:FETYPE:FEDIRS:CFCC:FRADDL:TOADDL:FRADDR:TOADDR:ZIPL:ZIPR:CENSUS1:CENSUS2:CFCC1:CFCC2:SOURCE";
+# dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="TLID:FEDIRP:FENAME:FETYPE:FEDIRS:CFCC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=8; fill_color=11; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=8; font_size=0; symbol=""}
+
+# per-field rules are applied to the dbffields that are read from each record.
+# key: set the search key to be the Tiger/Line ID. Not currently used.
+/^TLID=(.*)$/ {key=$1; next}
+# name: concatenate FEDIRP (direction prefix), FENAME (name),
+# FETYPE (type: Rd, Ln, Pky, etc.) and FEDIRS (direction suffix).
+# also abbreviate United States Highway to US, etc.
+/^FEDIRP=(.+)$/ {name="$1 ";next}
+/^FENAME=United States Highway (.*)$/ {name="$(name)US $1"; next}
+/^FENAME=State Highway (.*)$/ {name="$(name)State $1";next}
+/^FENAME=State Route (.*)$/ {name="$(name)SR $1";next}
+/^FENAME=(.*)$/ {name="$(name)$1; next}
+/^FETYPE=(.+)$/ {name="$(name) $1"; next}
+/^FEDIRS=(.+)$/ {name="$(name) $1"; next}
+# Census Feature Class Codes are used to set lanes, color, display_level, etc.
+# CFCC A..: roads
+# A11 - primary limited access road or interstate highway, unseparated
+# A12 - primary limited access road or interstate highway, unseparated in tunnel
+# A13 - primary limited access road or interstate highway, unseparated, underpassing
+# A14 - primary limited access road or interstate highway, unseparated, with rail line in center
+# A15 - primary limited access road or interstate highway, separated
+# A16 - primary limited access road or interstate highway, separated, in tunnel
+# A17 - primary limited access road or interstate highway, separated, underpassing
+# A18 - primary limited access road or interstate highway, separated, with rail line in center
+# A21 - primary road without limit access, US highways, unseparated
+# A22 -primary road without limit access, US highways, unseparated, in tunnel
+# A23 - primary road without limit access, US highways, underpassing
+# A24 - primary road without limit access, US highways, unseparated, with rail line in center
+# A25 - primary road without limit access, US highways, separated
+# A26 - primary road without limit access, US highways, separated, in tunnel
+# A27 - primary road without limit access, US highways, separated, underpassing
+# A28 - primary road without limit access, US highways, separated, with rail line in center
+# A31 - secondary and connection road, state highways, unseperated
+# A32 - " in tunnel
+# A33 - " underpassing
+# A34 - " with rail line in center
+# A35 - secondary and connection road, state highways, seperated
+# A36 - " in tunnel
+# A37 - " underpassing
+# A38 - " with rail line in center
+# A41 - local, neighborhood and rural road, city street, unseparated
+# A42 - " in tunnel
+# A43 - " underpassing
+# A44 - " with rail line in center
+# A45 - local, neighborhood and rural road, city street, separated
+# A46 - " in tunnel
+# A47 - " underpassing
+# A48 - " with rail line in center
+# A51 - vehicular trail, unseparated
+# A52 - " in tunnel
+# A53 - " underpassing
+# A61 - cul-de-sac
+# A62 - traffic circle
+# A63 - access ramp
+# A64 - service drive
+# A65 - ferry crossing
+# A71 - walkway or trail
+# A72 - stairway
+# A73 - alley
+# A74 - driveway
+/^CFCC=A1/ {lanes=4; color=4; label_level=512; font_size=3; next}
+/^CFCC=A2/ {lanes=3; color=8; label_level=256; font_size=2; next}
+/^CFCC=A3/ {lanes=2; color=8; label_level=128; font_size=1; next}
+/^CFCC=A3[1-6]/ {display_level=256; next}
+/^CFCC=A3[7-8]/ {display_level=128; next}
+/^CFCC=A4/ {display_level=96; label_level=16; color=40; lanes=1; next}
+/^CFCC=A5/ {lanes=2; color=40; display_level=64; font_size=1; next}
+/^CFCC=A65/ {lanes=2; color=8; pattern=2; font_size=1; next}
+/^CFCC=A6[^5]/ {color=40; display_level=64; next}
+/^CFCC=A7[12]/ {lanes=1; color=12; pattern=2; display_level=64; next}
+/^CFCC=A7[03-9]/ {lanes=1; color=40; pattern=2; display_level=64; next}
+# need to implement these:
+# B: railroads
+# B01 - railroad track
+# B02 - " in tunnel
+# B03 - " underpassing
+# B11 - railroad main line
+# B12 - " in tunnel
+# B13 - " underpassing
+# B21 - railroad spur
+# B22 - " in tunnel
+# B23 - " underpassing
+# B31 - railroad yard track
+# B32 - " in tunnel
+# B33 - " underpassing
+# B40 - railroad ferry crossing
+# B50 - other rail line
+# B51 - carline (streetcars, etc.)
+# B52 - cog railroad, incline railway or logging tram
+/^CFCC=B/ {lanes=1; color=8; pattern=1; display_level=128; next}
+# C: transmission lines
+# C00 - misc ground transportation
+# C10 - pipeline
+# C20 - power transmission line
+# C30 - other ground transportation
+# C31 - aerial tramway
+/^CFCC=C/ {display_level=0; next}
+# D: landmarks
+# D00 - unknown
+# D10 - military installation
+# D20 - multihousehold or transient quarters
+# D21 - apartment building or complex
+# D22 - rooming or boarding house
+# D23 - trailer cour or mobile home park
+# D24 - marina
+# D25 - crew-of-vessel area
+# D26 - housing facility for workers
+# D27 - hotel, motel, resort, spa, YMCA, YWCA
+# D28 - campground
+# D29 - shelter or mission
+# D30 - custodial facility
+# D31 - hospital
+# D32 - halfway house
+# D33 - nursing home
+# D34 - county home or poor farm
+# D35 - orphanage
+# D36 - jail
+# D37 - federal penetentiary, state prison, or prison farm
+# D40 - unknown educational or religious
+# D41 - sorority or fraternity
+# D42 - convent or monastery
+# D43 - educational institution
+# D44 - religious institution
+# D50 - transportation terminal
+# D51 - airport
+# D52 - train station
+# D53 - bus terminal
+# D54 - marine terminal
+# D55 - seaplane anchorage
+# D70 - tower
+# D71 - lookout tower
+# D80 - open space
+# D81 - golf course
+# D82 - cemetery
+# D83 - national park
+# D84 - national forest
+# D85 - state or local park or forest
+# D90 - special purpose landmark
+# D91 - post office box-only ZIP Code location
+# D92 - urbanizacion (Puerto Rico)
+# E: physical featuers
+# E00 - unknown physical feature
+# E10 - fence line
+# E20 - topgraphic feature
+# E21 - ridge line
+# E22 - mountain peak
+# E23 - island
+# F: legal boundaries
+# F00 - nonvisible boundary
+# F10 - jurisdictional boundary
+# F11 - offset boundary
+# F12 - corridor boundary
+# F13 - interpolate boundary across water
+# F14 - superseded boundary
+# F15 - superseded boundary, corrected
+# F20 - data base topology
+# F21 - automated feature extension to lenghten physical feature
+# F22 - irregular feature extension, determined manually
+# F23 - closure extension
+# F24 - separation line
+# F25 - centerline
+# F30 - point-to-point line
+# F40 - property line
+# F50 - Zip Code boundary
+# F60 - map edge
+# F70 - statistical boundardy
+# F71 - 1980 "
+# F72 - 1990 "
+# F73 - internal use
+# F74 - 1990 " ...
+# F80 - other tabulation boundary
+# F81 - internal use
+# F82 - internal use
+/^CFCC=F10$/{color=255; fill_color=255; label_level=32; display_level=512; pattern=0; next}
+/^CFCC=F/{display_level=0; next}
+# (G not used by census; tig2aprs uses for special maps)
+# H: hydrography
+# H00 - water feature
+# H01 - shoreline of perennial water feature
+# H02 - shoreline of intermittent "
+# H10 - stream
+# H11 - perennial stream
+# H12 - intermittent stream
+# H13 - braided stream or river
+# H20 - canal, ditch or aqueduct
+# H21 - perennial "
+# H22 - intermittent "
+# H30 - lake or pond
+# H31 - perennial "
+# H32 - intermittent "
+# H40 - reservoir
+# H41 - perennial "
+# H42 - intermittent "
+# H50 - bay, estuary, gulf, sound, sea, ocean
+# H51 - bay, estuary, gulf or sound
+# H52 - sea or ocean
+# H60 - gravel pit or quarry filled with water
+# H70 - nonvisibile....
+# H80 - special water features
+# H81 - glacier
+/^CFCC=H/ {lanes=0; color=26; fill_color=26; label_color=26}
+/^CFCC=H02/ {pattern=2; next}
+/^CFCC=H[1-6]2/ {lanes=1; pattern=2; next}
+/^CFCC=H[1-6][013-9]/ {lanes=1; next}
+/^CFCC=H7/ {display_level=0; label_level=0; next}
+/^CFCC=H8/ {lanes=1}
+/^CFCC=H81/ {color=15; fill_color=15; next}
+# X00 - feature not yet classified
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
diff --git a/config/tgrlpt.dbfawk b/config/tgrlpt.dbfawk
new file mode 100644
index 0000000..7ec623b
--- /dev/null
+++ b/config/tgrlpt.dbfawk
@@ -0,0 +1,106 @@
+# $Id: tgrlpt.dbfawk,v 1.15 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line "lpt" landmark point shapefiles which are
+# named tgrSSCCClpt.dbf, where SSCCC are the FIPS state and county codes.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="ID:CFCC:NAME";
+# dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="CFCC:NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=11; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=8; font_size=2; symbol=""}
+
+# per-field rules are applied to the dbffields that are read from each record.
+# key: set the search key to be the Tiger/Line ID. Not currently used.
+/^NAME=(.*)$/ {name="$1"; next}
+# Census Feature Class Codes are used to set lanes, color, display_level, etc.
+# D: landmarks
+# D00 - unknown
+# D10 - military installation
+# D20 - multihousehold or transient quarters
+# D21 - apartment building or complex
+# D22 - rooming or boarding house
+# D23 - trailer cour or mobile home park
+# D24 - marina
+# D25 - crew-of-vessel area
+# D26 - housing facility for workers
+# D27 - hotel, motel, resort, spa, YMCA, YWCA
+# D28 - campground
+# D29 - shelter or mission
+# D30 - custodial facility
+# D31 - hospital
+# D32 - halfway house
+# D33 - nursing home
+# D34 - county home or poor farm
+# D35 - orphanage
+# D36 - jail
+# D37 - federal penetentiary, state prison, or prison farm
+# D40 - unknown educational or religious
+# D41 - sorority or fraternity
+# D42 - convent or monastery
+# D43 - educational institution
+# D44 - religious institution
+# D50 - transportation terminal
+# D51 - airport
+# D52 - train station
+# D53 - bus terminal
+# D54 - marine terminal
+# D55 - seaplane anchorage
+# D70 - tower
+# D71 - lookout tower
+# D80 - open space
+# D81 - golf course
+# D82 - cemetery
+# D83 - national park
+# D84 - national forest
+# D85 - state or local park or forest
+# D90 - special purpose landmark
+# D91 - post office box-only ZIP Code location
+# D92 - urbanizacion (Puerto Rico)
+
+/^CFCC=D28/ {color=10; symbol="/] "; next}
+/^CFCC=D28/ {color=10; symbol="/\; "; next}
+/^CFCC=D31/ {color=9; symbol="/h "; next}
+/^CFCC=D40/ {color=5; next}
+/^CFCC=D41/ {color=2; next}
+/^CFCC=D42/ {color=1; next}
+/^CFCC=D43/ {color=2; symbol="/K "; next}
+/^CFCC=D44/ {color=1; next}
+/^CFCC=D51/ {color=14; symbol="/' "; next}
+/^CFCC=D52/ {color=14; symbol="/= "; next}
+/^CFCC=D53/ {color=14; symbol="/U "; next}
+/^CFCC=D54/ {color=1; symbol="/s "; next}
+/^CFCC=D70/ {color=1; symbol="/r "; next}
+/^CFCC=D8/ {color=2; next}
+
+# X<t><s><o> - APRS extension to get all the various APRS symbols.
+# Useful for home made maps. Perhaps I shouldn't overload tiger/line
+# stuff with this and just define a new .dbfawk....
+# <t><s><o> are table, symbol, and overlay,
+
+/^CFCC=X(.*)$/ {symbol="$1"; next}
+
diff --git a/config/tgrlpy.dbfawk b/config/tgrlpy.dbfawk
new file mode 100644
index 0000000..c63d33c
--- /dev/null
+++ b/config/tgrlpy.dbfawk
@@ -0,0 +1,48 @@
+# $Id: tgrlpy.dbfawk,v 1.13 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line "lpy" landmark polygon shapefiles which are
+# named tgrSSCCClklpy.dbf, where SSCCC are the FIPS state and county codes.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="ID:POLYID:CENID:COUNTY:CFCC:LANDNAME:LANDPOLY";
+# dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="CFCC:LANDNAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; fill_color=11; color=8; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=8; font_size=2; symbol=""}
+
+# per-field rules are applied to the dbffields that are read from each record.
+# key: set the search key to be the Tiger/Line ID. Not currently used.
+/^NAME=(.*)$/ {name="$1"; next}
+/^CFCC=H/ {lanes=0; color=26; fill_color=26}
+/^CFCC=H02/ {pattern=2; next}
+/^CFCC=H[1-6]2/ {lanes=1; pattern=2; next}
+/^CFCC=H[1-6][013-9]/ {lanes=1; next}
+/^CFCC=H7/ {display_level=0; label_level=0; next}
+/^CFCC=H8/ {lanes=1}
+/^CFCC=H81/ {color=15; fill_color=15; next}
+
diff --git a/config/tgrplc00.dbfawk b/config/tgrplc00.dbfawk
new file mode 100644
index 0000000..ca8e496
--- /dev/null
+++ b/config/tgrplc00.dbfawk
@@ -0,0 +1,38 @@
+# $Id: tgrplc00.dbfawk,v 1.13 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line "plc" shapefiles which are
+# named tgrSSCCCplc00.dbf, where SSCCC are the FIPS state and county codes.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="ID:COUNTY:PLACE:NAME";
+# dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="NAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=3; color=4; fill_color=103; name=""; filled=1; pattern=0; display_level=8192; label_level=256; label_color=8; font_size=2; symbol=""}
+
+/^NAME=(.*)$/ {name="$1"; next}
diff --git a/config/tgrwat.dbfawk b/config/tgrwat.dbfawk
new file mode 100644
index 0000000..a4b9e89
--- /dev/null
+++ b/config/tgrwat.dbfawk
@@ -0,0 +1,49 @@
+# $Id: tgrwat.dbfawk,v 1.15 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc.
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+#
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line "wat" polygon shapefiles
+# which are named tgrSSCCCwat.dbf, where SSCCC are the FIPS state and
+# county codes.
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="ID:COUNTY:CFCC:LANDNAME:LANDPOLY";
+# dbffields is which of the above fields we actually want to look at.
+# Note that the order we list these is important since we are appending the
+# word County or Parish depending on what state the county is in.
+dbffields="CFCC:LANDNAME";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+BEGIN_RECORD {key=""; lanes=1; color=26; fill_color=26; name=""; filled=1; pattern=0; display_level=8192; label_level=512; label_color=8; font_size=2; symbol=""}
+
+# name: name is just the county name.
+/^COUNTY=(.*)$/ {name="$1"; next}
+# key: set the search key to be the FIPS code. Not currently used.
+# also append County to the name except for Louisiana, use Parish:
+# XXX - find out what the FIPS code is for Louisiana and replace 99 with it:
+/^FIPSSTCO=(99.*)$/ {name="$name Parish"; key=$1; next}
+/^FIPSSTCO=(.*)$/ {name="$name County"; key=$1; next}
+# don't need special end case handling...
+#END_RECORD {name="$name ($key)";}
+#END {}
diff --git a/config/tl_2009_aiannh.dbfawk b/config/tl_2009_aiannh.dbfawk
new file mode 100644
index 0000000..869dc89
--- /dev/null
+++ b/config/tl_2009_aiannh.dbfawk
@@ -0,0 +1,52 @@
+# Written for the Tiger/Line 2009 dataset
+# NB: Colors have been chosen with a black background in mind.
+#
+# $Id: tl_2009_aiannh.dbfawk,v 1.2 2010/07/02 07:17:29 we7u Exp $
+#
+# Copyright (C) 2010 Peter Gamache, KC0TFB
+#
+# 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
+#
+# see file COPYING for details
+#
+# color,label_color,fill_color sets object colors
+# lanes sets width of lines drawn (in pixels)
+# name sets the text that will be used as the label for the feature
+# symbol "XYZ", where X=group (/ or \), Y=symbol and Z=overlay
+# fill_style 0=solid, 1=tiled, 2=stippled, 3=Opaque Stippled
+# fill_stipple 0 is a 13 percent stipple, 1 is 25%, 2 is 50%.
+# pattern line pattern: 0=solid, 1=dashed, 2=double dash
+# display_level maximum zoom level for object display
+# label_level maximum zoom level for label display
+# font_size 0="Tiny", 4="Huge"
+
+BEGIN {
+# dbfinfo extracted from tl_2009_27_aiannh.dbf:
+dbfinfo="AIANNHCE:AIANNHNS:AIANNHID:NAME:NAMELSAD:LSAD:CLASSFP:COMPTYP:AIANNHR:MTFCC:FUNCSTAT:ALAND:AWATER:INTPTLAT:INTPTLON:STATEFP:AIANNHFP:PARTFLG";
+dbffields="NAMELSAD:MTFCC";
+}
+/^NAMELSAD=(.*)$/ {name="$1";next}
+
+/^MTFCC=G21/ {
+display_level=128; color=65;
+label_level=96; label_color=6;
+next;
+}
+
+#END_RECORD {}
+#END {}
diff --git a/config/tl_2009_aits.dbfawk b/config/tl_2009_aits.dbfawk
new file mode 100644
index 0000000..100c079
--- /dev/null
+++ b/config/tl_2009_aits.dbfawk
@@ -0,0 +1,52 @@
+# Written for the Tiger/Line 2009 dataset
+# NB: Colors have been chosen with a black background in mind.
+#
+# $Id: tl_2009_aits.dbfawk,v 1.1 2010/07/02 07:12:20 we7u Exp $
+#
+# Copyright (C) 2010 Peter Gamache, KC0TFB
+#
+# 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
+#
+# see file COPYING for details
+#
+# color,label_color,fill_color sets object colors
+# lanes sets width of lines drawn (in pixels)
+# name sets the text that will be used as the label for the feature
+# symbol "XYZ", where X=group (/ or \), Y=symbol and Z=overlay
+# fill_style 0=solid, 1=tiled, 2=stippled, 3=Opaque Stippled
+# fill_stipple 0 is a 13 percent stipple, 1 is 25%, 2 is 50%.
+# pattern line pattern: 0=solid, 1=dashed, 2=double dash
+# display_level maximum zoom level for object display
+# label_level maximum zoom level for label display
+# font_size 0="Tiny", 4="Huge"
+
+BEGIN {
+# dbfinfo extracted from tl_2009_27_aits.dbf:
+dbfinfo="AIANNHCE:TRSUBCE:TRSUBNS:TRSUBID:NAME:NAMELSAD:LSAD:CLASSFP:MTFCC:FUNCSTAT:ALAND:AWATER:INTPTLAT:INTPTLON:STATEFP:TRSUBFP:PARTFLG";
+dbffields="NAMELSAD:MTFCC";
+}
+/^NAMELSAD=(.*)$/ {name="$1";next}
+
+/^MTFCC=G23/ {
+display_level=128; color=65;
+label_level=96; label_color=6;
+next;
+}
+
+#END_RECORD {}
+#END {}
diff --git a/config/tl_2009_arealm.dbfawk b/config/tl_2009_arealm.dbfawk
new file mode 100644
index 0000000..95acc5d
--- /dev/null
+++ b/config/tl_2009_arealm.dbfawk
@@ -0,0 +1,104 @@
+# Written for the Tiger/Line 2009 dataset
+# NB: Colors have been chosen with a black background in mind.
+#
+# $Id: tl_2009_arealm.dbfawk,v 1.1 2010/07/02 07:12:20 we7u Exp $
+#
+# Copyright (C) 2010 Peter Gamache, KC0TFB
+#
+# 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
+#
+# see file COPYING for details
+#
+# color,label_color,fill_color sets object colors
+# lanes sets width of lines drawn (in pixels)
+# name sets the text that will be used as the label for the feature
+# symbol "XYZ", where X=group (/ or \), Y=symbol and Z=overlay
+# fill_style (w/ filled=1) 0=solid, 1=tiled, 2=stippled, 3=Opaque Stippled
+# fill_stipple 0 is a 13 percent stipple, 1 is 25%, 2 is 50%.
+# pattern line pattern: 0=solid, 1=dashed, 2=double dash
+# display_level maximum zoom level for object display
+# label_level maximum zoom level for label display
+# font_size 0="Tiny", 4="Huge"
+
+BEGIN {
+dbfinfo="STATEFP:COUNTYFP:ANSICODE:AREAID:FULLNAME:MTFCC:ALAND:AWATER:INTPTLAT:INTPTLON";
+dbffields="FULLNAME:MTFCC";
+}
+
+BEGIN_RECORD {
+ color=11; # color 11 used on things we missed.
+ # Set defaults for other values:
+ name=""; filled=0; pattern=0; key=""; lanes=1; fill_color=40; label_color=48; fill_style=0;
+ display_level=128; label_level=96; font_size=0; symbol=""; fill_stipple=0;
+}
+
+/^FULLNAME=(.*)$/ {name="$1";next}
+
+/^MTFCC=C3023/ { # Island
+color=40; label_color=48; font_size=1; display_level=256; label_level=128; next; }
+/^MTFCC=C3/ { # Other "C3" features not drawn - less than 20 in the whole dataset.
+display_level=0; next; }
+
+# Dwelling areas:
+
+/^MTFCC=K1121/ { # Apartment complex
+display_level=32; label_level=24; next; }
+/^MTFCC=K1228/ { # Campground
+display_level=64; label_level=48; filled=1; color=114 fill_color=114; fill_style=2; fill_stipple=2; label_color=0; font_size=1; next; }
+/^MTFCC=K122/ { # Trailer court, dormitory, hotel/resort, shelter/mission
+display_level=32; label_level=24; next; }
+/^MTFCC=K1231/ { # Hospital/hospice/urgent care facility
+display_level=64; label_level=48; filled=1; fill_color=112; fill_style=2; label_color=12; font_size=1; next; }
+/^MTFCC=K123[349]/ { # Nursing/retirement home, County home/poor farm, religious quarters
+display_level=32; label_level=24; next; }
+/^MTFCC=K123[567]/ { Juvenile Institution/Local Jail or Detention Center/Federal Penitentiary, State Prison
+display_level=32; label_level=24; filled=1; fill_style=2; fill_stipple=1; label_color=67; font_size=1; next; }
+
+# Government facilities:
+
+/^MTFCC=21[046]/ { # Governmental/Community Center/Government Center
+display_level=64; label_level=48; filled=1; fill_color=67; fill_style=2; fill_stipple=2; label_color=15; font_size=1; next; }
+/^MTFCC=K218/ { # Park/NPS land/Nat'l forest or other federal land/State, regional, county or city park
+display_level=64; label_level=32; filled=1; color=114 fill_color=114; fill_style=2; label_color=0; font_size=1; next; }
+
+# Commercial facilities
+
+/^MTFCC=K23/ { # We don't draw "K23" features
+display_level=0; next; }
+
+# Transit
+
+/^MTFCC=K24/ { # Marina/Airport/Train Station/Bus Terminal/Marine Terminal/Seaplane Anchorage/etc
+display_level=128; label_level=64; filled=1; color=115 fill_color=115; fill_style=2; label_color=0; font_size=1; next; }
+
+# Education/recreation/misc
+
+/^MTFCC=K254[03]/ { # University/College/School/Academy
+display_level=64; label_level=48; filled=1; fill_color=103; fill_style=2; font_size=0; next; }
+/^MTFCC=K2561/ { # Golf course
+display_level=64; label_level=48; filled=1; color=114 fill_color=100; fill_style=2; label_color=10; font_size=1; next; }
+/^MTFCC=K2582/ { # Cemetary (don't display - overlap w/ pointlm database)
+display_level=0; next; }
+/^MTFCC=K3544/ { # Place of worship (don't display - overlap w/ pointlm database)
+display_level=0; next; }
+/^MTFCC=K25/ { # All others (Amusement Center, Zoo)
+display_level=128; label_level=64; next; }
+
+#END_RECORD {}
+#END {}
+
diff --git a/config/tl_2009_areawater.dbfawk b/config/tl_2009_areawater.dbfawk
new file mode 100644
index 0000000..f4c63c6
--- /dev/null
+++ b/config/tl_2009_areawater.dbfawk
@@ -0,0 +1,74 @@
+# Written for the Tiger/Line 2009 dataset
+# NB: Colors have been chosen with a black background in mind.
+#
+# $Id: tl_2009_areawater.dbfawk,v 1.1 2010/07/02 07:12:20 we7u Exp $
+#
+# Copyright (C) 2010 Peter Gamache, KC0TFB
+#
+# 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
+#
+# see file COPYING for details
+#
+# color,label_color,fill_color sets object colors
+# lanes sets width of lines drawn (in pixels)
+# name sets the text that will be used as the label for the feature
+# symbol "XYZ", where X=group (/ or \), Y=symbol and Z=overlay
+# fill_style (w/ filled=1) 0=solid, 1=tiled, 2=stippled, 3=Opaque Stippled
+# fill_stipple 0 is a 13 percent stipple, 1 is 25%, 2 is 50%.
+# pattern line pattern: 0=solid, 1=dashed, 2=double dash
+# display_level maximum zoom level for object display
+# label_level maximum zoom level for label display
+# font_size 0="Tiny", 4="Huge"
+
+BEGIN {
+dbfinfo="STATEFP:COUNTYFP:ANSICODE:HYDROID:FULLNAME:MTFCC:ALAND:AWATER:INTPTLAT:INTPTLON";
+dbffields="FULLNAME:MTFCC";
+}
+
+BEGIN_RECORD {
+ color=11; # color 11 used on things we missed.
+ # defaults for items below
+ name=""; filled=1; pattern=0; key=""; lanes=1;
+ fill_color=42; label_color=3; fill_style=0;
+ display_level=128; label_level=32; font_size=0; symbol="";
+}
+
+/^FULLNAME=(.*)$/ {name="$1";next}
+
+/^MTFCC=H2025/ { # Swamp/marsh
+color=42; fill_style=2; display_level=64; fill_stipple=0; next}
+/^MTFCC=H2030/ { # Lake/Pond, Reservoir, Bay/Estuary/Gulf/Sound, Ocean/Sea
+color=42; fill_style=0; next}
+/^MTFCC=H2040/ { # Reservoir
+color=42; fill_style=2; fill_stipple=2; display_level=64; next}
+/^MTFCC=H20[48]1/ { # Treatment Pond, Glacier
+color=42; fill_style=2; fill_stipple=1; display_level=64; next}
+/^MTFCC=H205/ { # Bay/Estuary/Gulf/Sound, Ocean/Sea
+color=42; fill_style=0; display_level=256; next}
+/^MTFCC=H2060/ { # Quarry filled w/ water
+color=42; fill_style=2; fill_stipple=2; display_level=64; name="$name (Quarry/Pit)"; next}
+/^MTFCC=H3010/ { # Stream/river
+color=42; next}
+/^MTFCC=H3013/ { # Braided stream
+color=42; display_level=64; next}
+/^MTFCC=H302/ { # Canal/ditch/aqueduct
+color=42; display_level=32; next}
+
+#END_RECORD {}
+#END {}
+
diff --git a/config/tl_2009_county.dbfawk b/config/tl_2009_county.dbfawk
new file mode 100644
index 0000000..28a64ca
--- /dev/null
+++ b/config/tl_2009_county.dbfawk
@@ -0,0 +1,55 @@
+# Written for the Tiger/Line 2009 dataset
+# NB: Colors have been chosen with a black background in mind.
+#
+# $Id: tl_2009_county.dbfawk,v 1.1 2010/07/02 07:12:20 we7u Exp $
+#
+# Copyright (C) 2010 Peter Gamache, KC0TFB
+#
+# 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
+#
+# see file COPYING for details
+#
+# color,label_color,fill_color sets object colors
+# lanes sets width of lines drawn (in pixels)
+# name sets the text that will be used as the label for the feature
+# symbol "XYZ", where X=group (/ or \), Y=symbol and Z=overlay
+# fill_style (w/ filled=1) 0=solid, 1=tiled, 2=stippled, 3=Opaque Stippled
+# fill_stipple 0 is a 13 percent stipple, 1 is 25%, 2 is 50%.
+# pattern line pattern: 0=solid, 1=dashed, 2=double dash
+# display_level maximum zoom level for object display
+# label_level maximum zoom level for label display
+# font_size 0="Tiny", 4="Huge"
+
+BEGIN {
+dbfinfo="STATEFP:COUNTYFP:COUNTYNS:CNTYIDFP:NAME:NAMELSAD:LSAD:CLASSFP:MTFCC:CSAFP:CBSAFP:METDIVFP:FUNCSTAT:ALAND:AWATER:INTPTLAT:INTPTLON";
+dbffields="NAMELSAD:MTFCC";
+}
+
+BEGIN_RECORD {
+ color=11; # color 11 used on things we missed.
+ # Set defaults for other values:
+ name=""; filled=0; pattern=0; key=""; lanes=1; fill_color=20; label_color=20; fill_style=0;
+ display_level=64; label_level=32; font_size=0; symbol=""; fill_stipple=0;
+}
+
+/^NAMELSAD=(.*)$/ {name="$1"}
+/^MTFCC=G/ { # Counties/Parishes
+display_level=5000; color=254; label_level=2048; label_color=254; next}
+
+#END_RECORD {}
+#END {}
diff --git a/config/tl_2009_cousub.dbfawk b/config/tl_2009_cousub.dbfawk
new file mode 100644
index 0000000..13af2fb
--- /dev/null
+++ b/config/tl_2009_cousub.dbfawk
@@ -0,0 +1,55 @@
+# Written for the Tiger/Line 2009 dataset
+# NB: Colors have been chosen with a black background in mind.
+#
+# $Id: tl_2009_cousub.dbfawk,v 1.1 2010/07/02 07:12:20 we7u Exp $
+#
+# Copyright (C) 2010 Peter Gamache, KC0TFB
+#
+# 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
+#
+# see file COPYING for details
+#
+# color,label_color,fill_color sets object colors
+# lanes sets width of lines drawn (in pixels)
+# name sets the text that will be used as the label for the feature
+# symbol "XYZ", where X=group (/ or \), Y=symbol and Z=overlay
+# fill_style (w/ filled=1) 0=solid, 1=tiled, 2=stippled, 3=Opaque Stippled
+# fill_stipple 0 is a 13 percent stipple, 1 is 25%, 2 is 50%.
+# pattern line pattern: 0=solid, 1=dashed, 2=double dash
+# display_level maximum zoom level for object display
+# label_level maximum zoom level for label display
+# font_size 0="Tiny", 4="Huge"
+
+BEGIN {
+dbfinfo ="STATEFP:COUNTYFP:COUSUBFP:COUSUBNS:COSBIDFP:NAME:NAMELSAD:LSAD:CLASSFP:MTFCC:CNECTAFP:NECTAFP:NCTADVFP:FUNCSTAT:ALAND:AWATER:INTPTLAT:INTPTLON";
+dbffields="NAMELSAD:MTFCC";
+}
+
+BEGIN_RECORD {
+ color=11; # color 11 used on things we missed.
+ # Set defaults for other values:
+ name=""; filled=0; pattern=0; key=""; lanes=1; fill_color=20; label_color=20; fill_style=0;
+ display_level=64; label_level=32; font_size=0; symbol=""; fill_stipple=0;
+}
+
+/^NAMELSAD=(.*)$/ {name="$1";next; }
+/^MTFCC=G/ { # "County Subdivisions" - better known as cities, towns and townships.
+display_level=128; label_level=96; color=115; label_color=115; next}
+
+#END_RECORD {}
+#END {}
diff --git a/config/tl_2009_edges.dbfawk b/config/tl_2009_edges.dbfawk
new file mode 100644
index 0000000..82d456f
--- /dev/null
+++ b/config/tl_2009_edges.dbfawk
@@ -0,0 +1,100 @@
+# Written for the Tiger/Line 2009 dataset
+# NB: Colors have been chosen with a black background in mind.
+#
+# $Id: tl_2009_edges.dbfawk,v 1.1 2010/07/02 07:12:20 we7u Exp $
+#
+# Copyright (C) 2010 Peter Gamache, KC0TFB
+#
+# 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
+#
+# see file COPYING for details
+#
+# color,label_color,fill_color sets object colors
+# lanes sets width of lines drawn (in pixels)
+# name sets the text that will be used as the label for the feature
+# symbol "XYZ", where X=group (/ or \), Y=symbol and Z=overlay
+# fill_style (w/ filled=1) 0=solid, 1=tiled, 2=stippled, 3=Opaque Stippled
+# fill_stipple 0 is a 13 percent stipple, 1 is 25%, 2 is 50%.
+# pattern line pattern: 0=solid, 1=dashed, 2=double dash
+# display_level maximum zoom level for object display
+# label_level maximum zoom level for label display
+# font_size 0="Tiny", 4="Huge"
+
+BEGIN {
+dbfinfo="STATEFP:COUNTYFP:TLID:TFIDL:TFIDR:MTFCC:FULLNAME:SMID:LFROMADD:LTOADD:RFROMADD:RTOADD:ZIPL:ZIPR:FEATCAT:HYDROFLG:RAILFLG:ROADFLG:OLFFLG:PASSFLG:DIVROAD:EXTTYP:TTYP:DECKEDROAD:ARTPATH:PERSIST:GCSEFLG:OFFSETL:OFFSETR:TNIDF:TNIDT";
+dbffields="MTFCC:FULLNAME";
+# level presets
+l_metro=256; l_county=80; l_city=32; l_town=16; l_hood=8;
+}
+
+BEGIN_RECORD {
+ color=11; # color 11 used on things we missed.
+ # Set defaults for other values:
+ name=""; filled=0; pattern=0; key=""; lanes=1; fill_color=20; label_color=20; fill_style=0;
+ display_level=64; label_level=32; font_size=0; symbol=""; fill_stipple=0;
+}
+
+/^FULLNAME=(.*)$/ {name="$1";next; }
+
+# Non-road items:
+
+/^MTFCC=L4031/ { # Ski Lift or Arial Tramway
+display_level=l_city; color=12; pattern=2; name="$name (Ski Lift/Tramway)"; next; }
+/^MTFCC=L4165/ { # Ferry crossing
+lanes=3; pattern=2; color=72; label_color=72; display_level=l_metro; label_level=l_county; next; }
+/^MTFCC=[CHKLP]/ { # Don't draw other non-road items
+display_level=0; next; }
+/^MTFCC=R101/ { # Freight Rail (heavy/freight)
+color=80; label_color=48; pattern=1; lanes=2; display_level=128; label_level=64; next; }
+/^MTFCC=R105/ { # Passenger Rail (light/mass transit/cog rail)
+color=67; label_color=67; pattern=2; display_level=128; label_level=64; next; }
+
+# Public Roadways
+
+/^MTFCC=S11/ { # Freeways/major highways
+lanes=4; color=102; label_color=102; display_level=1024; label_level=256; font_size=2; next; }
+/^MTFCC=S12/ { # Secondary roads
+display_level=256; lanes=3; color=36; label_color=36; label_level=128; font_size=2; next; }
+/^MTFCC=S14/ { # Local roads, ramps and service drives/frontage roads
+display_level=40; color=44; label_color=44; label_level=16; color=48; lanes=1; next; }
+/^MTFCC=S15/ { # 4WD off-road trail
+color=99; label_color=99; display_level=64; font_size=1; name="$name (OHV/4WD trail)"; next; }
+/^MTFCC=S16/ { # ramps and service roads for Freeways/major highways
+color=102; label_color=102; display_level=32; next; }
+/^MTFCC=S20/ { # road median
+color=44; label_color=44; pattern=1; display_level=16; next; }
+/^MTFCC=S173/ { # alley
+color=44; label_color=44; pattern=1; display_level=32; name="$name (alley)"; next; }
+
+# Non-public roads (and public non-roads)
+
+/^MTFCC=S171/ { # walkway / pedestrian trail
+lanes=1; color=65; label_color=65; pattern=1; display_level=64; label_level=32; name="$name (walkway)"; next; }
+/^MTFCC=S172/ { # stairway
+lanes=1; color=12; label_color=12; pattern=2; display_level=32; label_level=20; name="$name (stairs)"; next; }
+/^MTFCC=S174/ { # private road
+lanes=1; color=23; label_color=23; pattern=2; display_level=32; label_level=20; name="$name (private road)"; next; }
+/^MTFCC=S17/ { # business park / townhome road / parking lane / "internal census use only"
+lanes=1; color=23; label_color=23; pattern=1; display_level=32; label_level=20; name="$name (parking/private)"; next; }
+/^MTFCC=S182/ { # bike path
+lanes=1; color=65; label_color=65; pattern=1; display_level=64; label_level=32; name="$name (bikeway)"; next; }
+/^MTFCC=S183/ { # bridle path
+lanes=1; color=65; label_color=65; pattern=2; display_level=64; label_level=32; name="$name (bridle path)"; next; }
+
+#END_RECORD {}
+#END {}
diff --git a/config/tl_2009_mil.dbfawk b/config/tl_2009_mil.dbfawk
new file mode 100644
index 0000000..71aa4ec
--- /dev/null
+++ b/config/tl_2009_mil.dbfawk
@@ -0,0 +1,47 @@
+# Written for the Tiger/Line 2009 dataset
+# NB: Colors have been chosen with a black background in mind.
+#
+# $Id: tl_2009_mil.dbfawk,v 1.1 2010/07/02 07:12:20 we7u Exp $
+#
+# Copyright (C) 2010 Peter Gamache, KC0TFB
+#
+# 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
+#
+# see file COPYING for details
+#
+# color,label_color,fill_color sets object colors
+# lanes sets width of lines drawn (in pixels)
+# name sets the text that will be used as the label for the feature
+# symbol "XYZ", where X=group (/ or \), Y=symbol and Z=overlay
+# fill_style 0=solid, 1=tiled, 2=stippled, 3=Opaque Stippled
+# fill_stipple 0 is a 13 percent stipple, 1 is 25%, 2 is 50%.
+# pattern line pattern: 0=solid, 1=dashed, 2=double dash
+# display_level maximum zoom level for object display
+# label_level maximum zoom level for label display
+# font_size 0="Tiny", 4="Huge"
+
+BEGIN {
+dbfinfo="ANSICODE:AREAID:FULLNAME:MTFCC:ALAND:AWATER:INTPTLAT:INTPTLON:PARTFLG";
+dbffields="FULLNAME:MTFCC";
+}
+/^FULLNAME=(.*)$/ {name="$1"; next; }
+/^MTFCC=K21/ { # Military installation
+display_level=128; color=116; label_level=64; label_color=116; fill_style=2; fill_stipple=0; fill_color=116; filled=1; next; }
+
+#END_RECORD {}
+#END {}
diff --git a/config/tl_2009_nn_county.dbfawk b/config/tl_2009_nn_county.dbfawk
new file mode 100644
index 0000000..3bec460
--- /dev/null
+++ b/config/tl_2009_nn_county.dbfawk
@@ -0,0 +1,56 @@
+# tl_2009_nn_county.dbfawk
+#
+# $Id: tl_2009_nn_county.dbfawk,v 1.2 2012/11/01 18:57:19 we7u Exp $
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# Census.gov 2009 TigerMaps for state counties or equivalent areas.
+#
+# Based on work by:
+# Richard Polivka, N6NKO - April, 2008
+# Craig Anderson, N6YXK - May, 2008
+# Dale Seaburg, KG5LT - March 2009
+# Edited for 2009 data by:
+# Peter Gamache, KC0TFB - June, 2010
+#
+# This dbfawk file is used to map arbitrary dbf data that accompanies
+# a shapefile into Xastir canoncical values of:
+# key - search key
+# lanes - width of feature (usually a road but applies to rivers, etc. too)
+# color - color to draw the road
+# name - name of the road for labels
+# filled - whether a polygon is drawn filled or not
+# fill_color - color to fill polygon with
+# pattern - line pattern for road, river, etc. (0 - solid; 1 - dash; 2 - double dash)
+# display_level - highest zoom level at which to display the feature
+# label_level - highest zoom level at which to display the label
+# symbol - 3 char 'TIO': table, ID, overlay
+# NOTE: This file format is modeled after awk but is nowhere near awk
+# compatible.
+#
+# This file is used to map US Census Tiger/Line 2009 Shapefiles.
+#
+
+# BEGIN is called once per dbf file which contains multiple records.
+BEGIN {
+# dbfinfo is the "signature" of the dbf file listing the column names in order.
+# dbfinfo should match the dbf file that we say this dbfawk file goes with.
+dbfinfo="STATEFP:COUNTYFP:COUNTYNS:CNTYIDFP:NAME:NAMELSAD:LSAD:CLASSFP:MTFCC:CSAFP:CBSAFP:METDIVFP:FUNCSTAT:ALAND:AWATER:INTPTLAT:INTPTLON";
+
+
+#dbffields is which of the above fields we actually want to look at.
+# No point reading dbffields that are not looked at further.
+dbffields="NAMELSAD:MTFCC";
+}
+
+# BEGIN_RECORD is called once per dbf record which contains multiple fields.
+# Use this rule to re-initialize variables between records.
+# use color 11 to highlight stuff that isn't properly mapped.
+BEGIN_RECORD {key=""; lanes=1; color=6; fill_color=11; name=""; filled=0; pattern=0; display_level=8192; label_level=32; label_color=8; font_size=0; symbol=""; fill_style=0 }
+
+/^NAMELSAD=(.*)$/ {name="$1"}
+# counties
+/^MTFCC=G/ {display_level=6000; filled=0; color=45; label_level=2048; label_color=37; next}
+
+# just a demo of the END_RECORD and END rules:
+#END_RECORD {name="$name ($key)";}
+#END {}
diff --git a/config/tl_2009_pointlm.dbfawk b/config/tl_2009_pointlm.dbfawk
new file mode 100644
index 0000000..9313186
--- /dev/null
+++ b/config/tl_2009_pointlm.dbfawk
@@ -0,0 +1,135 @@
+# Written for the Tiger/Line 2009 dataset
+# NB: Colors have been chosen with a black background in mind.
+#
+# $Id: tl_2009_pointlm.dbfawk,v 1.1 2010/07/02 07:12:20 we7u Exp $
+#
+# Copyright (C) 2010 Peter Gamache, KC0TFB
+#
+# 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
+#
+# see file COPYING for details
+#
+# color,label_color,fill_color sets object colors
+# lanes sets width of lines drawn (in pixels)
+# name sets the text that will be used as the label for the feature
+# symbol "XYZ", where X=group (/ or \), Y=symbol and Z=overlay
+# fill_style (w/ filled=1) 0=solid, 1=tiled, 2=stippled, 3=Opaque Stippled
+# fill_stipple 0 is a 13 percent stipple, 1 is 25%, 2 is 50%.
+# pattern line pattern: 0=solid, 1=dashed, 2=double dash
+# display_level maximum zoom level for object display
+# label_level maximum zoom level for label display
+# font_size 0="Tiny", 4="Huge"
+
+BEGIN {
+dbfinfo="STATEFP:COUNTYFP:ANSICODE:POINTID:FULLNAME:MTFCC";
+dbffields="FULLNAME:MTFCC";
+# level presets
+l_metro=128; l_county=64; l_city=32; l_town=16; l_hood=8;
+}
+
+BEGIN_RECORD { # Defaults
+key=""; lanes=1; color=70; fill_color=70; name=""; filled=0; pattern=0; display_level=48; label_level=32; label_color=70; font_size=0; symbol=""; fill_style=0;
+}
+
+/^FULLNAME=(.*)$/ {name="$1"; next; }
+
+# Geography
+
+/^MTFCC=3022/ { # Mountain Peak or Summit
+display_level=l_county; next; }
+/^MTFCC=3022/ { # Islands should be in edges.dbf, not here.
+display_level=0; next; }
+/^MTFCC=3026/ { # Quarry
+next; }
+/^MTFCC=3027/ { # Dam should be in areawater, not here.
+display_level=0; next; }
+
+# Road features
+
+/^MTFCC=C306/ { # ignore cul-de-sacs, roundabouts, gates and toll booths
+display_level=0; next; }
+
+# Towers
+
+/^MTFCC=C307[014]/ { # Towers (beacon/observation/lighthouse, antenna and water)
+display_level=l_city; color=50; label_color=50; symbol="\L"; next; }
+/^MTFCC=C3072/ { display_level=l_city; color=50; label_color=50; name="$name (antenna tower)"; symbol="/r"; next; }
+/^MTFCC=C3073/ { display_level=l_city; color=50; label_color=50; name="$name (water tower)"; symbol="/r"; next; }
+/^MTFCC=C307/ { # ignore other towers (tanks, windmills and monuments)
+display_level=0; next; }
+
+# Locality points
+
+/^MTFCC=C308/ { # city names; redundant with cousub.dbf
+display_level=0; next}
+
+# Potential housing (for disaster relief)
+
+/^MTFCC=K1231/ { # Hospitals
+label_color=12; display_level=l_county; symbol="/h"; next}
+/^MTFCC=K12/ { # Don't display other types
+display_level=0; next}
+
+# other gov't items
+
+/^MTFCC=K2110/ { # Military; redundant with mil.dbf
+display_level=0; next; }
+/^MTFCC=K2146/ { # Community center
+display_level=l_city; symbol="/?"; next}
+/^MTFCC=K2165/ { # Gov't center
+display_level=l_city; symbol="/?"; next}
+/^MTFCC=K218/ { # Parks not shown; redundant with arealm.dbf
+display_level=0; next}
+/^MTFCC=K2193/ { # fire dept
+label_color=12; display_level=l_county; symbol="/d"; next}
+/^MTFCC=K2194/ { # police/sheriff station
+label_color=9; display_level=l_county; symbol="/!"; next}
+/^MTFCC=K2196/ { # City hall
+display_level=l_city; symbol="/?"; next}
+/^MTFCC=K219/ { # other buildings not shown
+display_level=0; next}
+
+# Transportation
+
+/^MTFCC=K2400/ { # Transportation terminal?
+display_level=l_city; symbol="/U?"; next}
+/^MTFCC=K245[156]/ { # Airport/airfield, seaplane terminal
+display_level=l_county; symbol="\^@"; next; }
+/^MTFCC=K2452/ { # train/trolley/light rail station
+display_level=l_city; symbol="/=@"; next}
+/^MTFCC=K2453/ { # bus terminal
+display_level=l_city; symbol="/U@"; next}
+/^MTFCC=K2454/ { # marine terminal
+display_level=l_county; symbol="\s@"; next}
+
+# Education/entertainment/misc
+
+/^MTFCC=K254[03]/ { # University/school
+display_level=l_town; symbol="/K"; next}
+/^MTFCC=K2561/ { # golf course; redundant w/ arealm
+display_level=0; next; }
+/^MTFCC=K2582/ { # cemetaries
+display_level=0; next}
+/^MTFCC=K3544/ { # religious
+display_level=0; next}
+
+# catch-all rule:
+/^MTFCC=K/ {display_level=16; label_level=16; next}
+
+#END_RECORD {}
+#END {}
diff --git a/config/tl_2009_zcta5.dbfawk b/config/tl_2009_zcta5.dbfawk
new file mode 100644
index 0000000..0b0a286
--- /dev/null
+++ b/config/tl_2009_zcta5.dbfawk
@@ -0,0 +1,47 @@
+# Written for the Tiger/Line 2009 dataset
+# NB: Colors have been chosen with a black background in mind.
+#
+# $Id: tl_2009_zcta5.dbfawk,v 1.1 2010/07/02 07:12:20 we7u Exp $
+#
+# Copyright (C) 2010 Peter Gamache, KC0TFB
+#
+# 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
+#
+# see file COPYING for details
+#
+# color,label_color,fill_color sets object colors
+# lanes sets width of lines drawn (in pixels)
+# name sets the text that will be used as the label for the feature
+# symbol "XYZ", where X=group (/ or \), Y=symbol and Z=overlay
+# fill_style 0=solid, 1=tiled, 2=stippled, 3=Opaque Stippled
+# fill_stipple 0 is a 13 percent stipple, 1 is 25%, 2 is 50%.
+# pattern line pattern: 0=solid, 1=dashed, 2=double dash
+# display_level maximum zoom level for object display
+# label_level maximum zoom level for label display
+# font_size 0="Tiny", 4="Huge"
+
+BEGIN {
+dbfinfo="ZCTA5CE:CLASSFP:MTFCC:FUNCSTAT:ALAND:AWATER:INTPTLAT:INTPTLON";
+dbffields="ZCTA5CE:MTFCC";
+}
+/^ZCTA5CE=(.*)$/ {name="$1";next}
+/^MTFCC=G6350/ { # Zip code tabulation area, 5-digit
+display_level=128; color=103; label_level=64; label_color=103; font_size=1; next; }
+
+#END_RECORD {}
+#END {}
diff --git a/config/tnc-startup.aea b/config/tnc-startup.aea
new file mode 100644
index 0000000..9098ae7
--- /dev/null
+++ b/config/tnc-startup.aea
@@ -0,0 +1,47 @@
+# $Id: tnc-startup.aea,v 1.19 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# This is the TNC Startup file for AEA TNC's.
+# lines that begin with a pound sign are comments.
+#
+# This has not been tweaked yet to be specific to AEA's.
+# Please modify it and send the patches to the mailing lists.
+# Thanks.
+#
+HID on
+#CWID off
+EXP on
+ECHO off
+#
+# Important! Only uncomment if really needed as a fill-in digi:
+#MYAlias WIDE1-1
+#
+B E 0
+DIGI on
+FLow off
+FUll off
+HEA off
+#LFadd off
+#LFSup ON
+#AUTOLF off
+#MCOM off
+MFILTER 0
+MON ON
+#
+# Important! Only monitor PID 0xf0 packets:
+MPROTO OFF
+#
+#MResp OFF
+MRPt on
+MSTamp off
+MXMit off
+NEWmode off
+#PACLen 128
+PASSALL off
+#SCR 0
+# B E 0 must be set to 0 or both APRS and your TNC will send BCNS
+# Which will alternate in everyones L and A lists and fill up
+# their logs. Do NOT set B E to anything other than 0 while APRS
+# is running.
+
diff --git a/config/tnc-startup.d700 b/config/tnc-startup.d700
new file mode 100644
index 0000000..8b28c6b
--- /dev/null
+++ b/config/tnc-startup.d700
@@ -0,0 +1,69 @@
+# $Id: tnc-startup.d700,v 1.14 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2004-2012 The Xastir Group
+#
+# TNC Init file for KENWOOD D700. Also reported to work with the
+# Alinco DR-135TP radio (with the EJ-41U TNC which also uses a Tasco
+# TNC just like the Kenwoods). Perhaps works with the Alinco DR-635
+# radio (with the EJ-50U TNC) too.
+#
+# NOTE: TXD on a D700A is fixed at 500ms (1/2 second) in "APRS"
+# mode. In "packet" mode we can change the txd to other values.
+#
+#
+#Don't send CONTROL-C before this line
+##META <no-ctrl-c>
+TC 1
+##Pause for one second
+##META <delay>
+##META <delay>
+#Put the TNC in packet mode since this is where we want to end up
+# Change the 1 to 0 to go to normal radio mode
+##META <no-ctrl-c>
+TNC 2
+# Pause for two seconds
+##META <delay>
+##META <delay>
+##META <delay>
+##META <delay>
+# Enable 4800 baud GPS
+# Change to 2 for 9600 baud GPS
+# Disable both the META line and the GU line for no change
+##META <no-ctrl-c>
+GU 1
+# Pause for two seconds
+##META <delay>
+##META <delay>
+##META <delay>
+##META <delay>
+#Turn off Terminal Control
+##META <no-ctrl-c>
+TC 0
+# Pause for two seconds just in case
+##META <delay>
+##META <delay>
+##META <delay>
+##META <delay>
+HID off
+#CWID off
+AWlen 8
+BBSMsgs ON
+B E 0
+LOC E 0
+Echo off
+FLow off
+AUTOLF off
+MCOM off
+MON ON
+MRPt on
+PACLen 128
+PASSALL off
+HBAUD 1200
+TXDELAY 25
+HEADERLN off
+# Delete following lines if without GPS
+GBAUD 4800
+GPSTEXT $GPRMC
+LTMH OFF
+LTM 10
+#
diff --git a/config/tnc-startup.d72_d710 b/config/tnc-startup.d72_d710
new file mode 100644
index 0000000..1b93267
--- /dev/null
+++ b/config/tnc-startup.d72_d710
@@ -0,0 +1,47 @@
+# $Id: tnc-startup.d72_d710,v 1.2 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2011-2012 The Xastir Group
+#
+# TNC Init file for KENWOOD TM-D710 or TH-D72 radios.
+# Contributed by Kai Günter, LA3QMA.
+#
+# If using a GPS you must change GBAUD, GPSTEXT, LTMH.
+#
+#
+#Don't send CONTROL-C before this line
+##META <no-ctrl-c>
+#TC 1
+##Pause for one second
+##META <delay>
+##META <delay>
+#Put the TNC in packet mode since this is where we want to end up
+# Change the 1 to 0 to go to normal radio mode
+##META <no-ctrl-c>
+TN 2,0
+# Pause for two seconds
+##META <delay>
+##META <delay>
+##META <delay>
+##META <delay>
+HID off
+AWlen 8
+BBSMsgs ON
+B E 0
+LOC E 0
+Echo off
+FLow off
+AUTOLF off
+MCOM off
+MON ON
+MRPt on
+PACLen 128
+PASSALL off
+HBAUD 1200
+TXDELAY 25
+HEADERLN off
+# Delete following lines if without GPS
+#GBAUD 4800
+#GPSTEXT $GPRMC
+#LTMH OFF
+#
+#
diff --git a/config/tnc-startup.kam b/config/tnc-startup.kam
new file mode 100644
index 0000000..f60d417
--- /dev/null
+++ b/config/tnc-startup.kam
@@ -0,0 +1,43 @@
+# $Id: tnc-startup.kam,v 1.19 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# This is the TNC Startup file for a Kantronics KAM TNC.
+# lines that begin with a pound sign are comments.
+# Edit this file for your tnc!
+#
+# Important! Only uncomment if really needed as a fill-in digi:
+#myalias WIDE1-1
+#
+INTF TERM
+#One KAM user reports this command does not exist on his KAM
+#txu on
+xflow off
+MONITOR ON
+MSTAMP OFF
+HEADERLN OFF
+#One KAM user reports this command does not exist on his KAM
+#SCREENLN 0
+AUTOLF OFF
+LFADD OFF
+CD SOFT
+MCOM OFF/OFF
+MCON OFF
+FILT OFF
+AUTOCR 0
+BEACON EVERY 0
+BT %
+BUDL OFF/OFF
+CMS DISC
+CONL OFF
+CT APRS Network no connected messages supported!
+ECHO OFF
+FLOW OFF
+HID OFF/OFF
+#CWID EVERY 0
+MSTAMP OFF
+PASSALL OFF
+#
+# Important! Monitor only PID 0xf0 packets:
+PID OFF
+
diff --git a/config/tnc-startup.kpc2 b/config/tnc-startup.kpc2
new file mode 100644
index 0000000..c666e18
--- /dev/null
+++ b/config/tnc-startup.kpc2
@@ -0,0 +1,30 @@
+# $Id: tnc-startup.kpc2,v 1.13 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2004-2012 The Xastir Group
+#
+# This is the TNC Startup file for Kantronics TNC.
+# lines that begin with a pound sign are comments.
+#
+#
+HID off
+#CWID every 0
+B E 0
+DIGI on
+ECho off
+FLow off
+FUll off
+HEA off
+LFadd off
+AUTOLF off
+MCOM off
+MON ON
+MResp OFF
+MRPt on
+MSTamp off
+#
+# Important! Only uncomment if really needed as a fill-in digi:
+#MYAlias WIDE1-1
+#
+NEWmode off
+SCR 0
+#
diff --git a/config/tnc-startup.kpc3 b/config/tnc-startup.kpc3
new file mode 100644
index 0000000..2672cae
--- /dev/null
+++ b/config/tnc-startup.kpc3
@@ -0,0 +1,76 @@
+# $Id: tnc-startup.kpc3,v 1.22 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# This is the TNC Startup file for Kantronics TNC.
+# lines that begin with a pound sign are comments.
+#
+# This configuration sets up Control-E mode for a KPC-3+ (GPS
+# connected to the 2nd serial port). When Xastir is actively
+# getting GPS fixes, the TNC beacons only what Xastir sends to it.
+# When Xastir stops getting GPS data from the TNC, the TNC will
+# revert to dumb-tracker mode and start sending NMEA strings out all
+# by itself at a 20-minute rate. If the GPS get disconnected or
+# turned off, the dumb-tracker mode will cease to send out beacons.
+# This last function is done by the "CLEAR" parameter for the BLT
+# commands.
+#
+# Some people prefer to turn off the GPS but still have the TNC
+# beacon their last good GPS position when in dumb-tracker mode.
+# To do this, remove the "CLEAR" parameters from the BLT command
+# lines.
+#
+
+int terminal
+
+# Clear out the LT buffers so we don't have old data in there:
+LT 1
+LT 2
+LT 3
+LT 4
+# Clear out the buffer regularly to prevent stale data:
+BLT 1 00:20:00 CLEAR
+BLT 2 00:20:00 CLEAR
+BLT 3 00:00:00
+BLT 4 00:00:00
+# Set up the NMEA strings to capture:
+GPSHEAD 1 $GPRMC
+GPSHEAD 2 $GPGGA
+#
+GPSPORT 4800 NORMAL CHECKSUM
+LGETCHAR $05
+#
+HID off
+#CWID every 0
+#
+# Important! Only uncomment if really needed as a fill-in digi:
+#MYAlias WIDE1-1
+#
+B E 0
+DIGI on
+ECho off
+FILT off
+FLow off
+FUll off
+HEA off
+LFadd off
+LFSup ON
+AUTOLF off
+MCOM off
+MON ON
+MResp OFF
+MRPt on
+MSTamp off
+MXMit off
+NEWmode off
+#PACLen 128
+PASSALL off
+#
+# Important! Monitor only PID 0xf0 packets:
+PID off
+#
+SCR 0
+# B E 0 must be set to 0 or both APRS and your TNC will send BCNS
+# Which will alternate in everyones L and A lists and fill up
+# their logs. Do NOT set B E to anything other than 0 while APRS
+# is running.
diff --git a/config/tnc-startup.null b/config/tnc-startup.null
new file mode 100644
index 0000000..e69de29
diff --git a/config/tnc-startup.paccomm b/config/tnc-startup.paccomm
new file mode 100644
index 0000000..4758b00
--- /dev/null
+++ b/config/tnc-startup.paccomm
@@ -0,0 +1,50 @@
+# $Id: tnc-startup.paccomm,v 1.18 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# This is the TNC Startup file for a Pac-Comm TNC with v5.x firmware.
+# Adapted from Kantronics startup file by Kurt Freiberger, WB5BBW
+
+# lines that begin with a pound sign are comments.
+
+HID off
+#CWID every 0
+MON 0
+ECHO off
+#MYCall WB5BBW
+#
+# Important! Only uncomment if really needed as a fill-in digi:
+#MYAlias WIDE1-1
+#
+#
+#
+#MY1Alias LOCAL
+#MY2Alias REGION
+#MY3Alias WORLD
+#
+# B E 0 must be set to 0 or both APRS and your TNC will send BCNS
+# Which will alternate in everyones L and A lists and fill up
+# their logs. Do NOT set B E to anything other than 0 while APRS
+# is running.
+B E 0
+# This enables DIGI On and DIGI-SWAP,DIGI-NOT-OWN, DIGI-ONCE enabled.
+DIGI 7
+FLow off
+FUll off
+HEA off
+LFadd off
+AUTOLF off
+MCOM off
+MFILT $00
+MRPt on
+MSTamp off
+NEWmode off
+PASSALL off
+SCR 0
+MON 1
+#
+# Important! Monitor only PID 0xf0 packets:
+PIDCHECK on
+#
+# End of tnc-startup.pac
+#
diff --git a/config/tnc-startup.pico b/config/tnc-startup.pico
new file mode 100644
index 0000000..364b85c
--- /dev/null
+++ b/config/tnc-startup.pico
@@ -0,0 +1,86 @@
+# $Id: tnc-startup.pico,v 1.22 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# This is the TNC Startup file for a dual-port Paccomm PicoPacket TNC.
+# lines that begin with a pound sign are comments.
+
+ECHO off
+AUTOLF on
+BEACON EVERY 0
+#
+# Clear the GPS buffers
+LTEXT %
+L1TEXT %
+L2TEXT %
+L3TEXT %
+#
+# Set up the NMEA strings we wish to capture:
+#GPSTEXT %
+GPSTEXT $GPRMC
+#
+#LG1TEXT %
+LG1TEXT $GPGGA
+#
+LG2TEXT %
+#LG2TEXT $GPVTG
+#
+LG3TEXT %
+#LG3TEXT $PGRME
+#
+# Digipeat,callsign substitution,
+# no digi of own packets, and digi-once
+DIGIPEAT 7
+ELOC 0
+FLOW off
+FULLDUP off
+GPS off
+HEADERLI off
+HID off
+#CWID every 0
+INTERVAL 0
+LFADD off
+LGETCHAR $05
+LOC E 0
+#
+MALL ON
+MCOM off
+MCON on
+MFILTER 0
+MONITOR 3
+MRPT on
+MSTAMP off
+#
+# Important! Only uncomment if really needed as a fill-in digi:
+#MYALIAS WIDE1-1
+#
+#MY1ALIAS SAR
+#MY2ALIAS ESAR
+#MY3ALIAS ESAR2
+NEWMODE off
+NOMODE on
+#PACLEN 128
+#
+# Only used in KISS mode?
+PERSIST 128
+#
+PASSALL off
+#
+# Important! Monitor only PID 0xf0 packets:
+PIDCHECK on
+#
+PMS off
+SCREENLN 0
+#
+# Only used in KISS mode?
+SLOTTIME 15
+#
+TXDELAY 30
+XFLOW off
+#
+#
+# BEACON EVERY 0 must be set to 0 or both Xastir and your TNC will send
+# beacons which will alternate in everyones lists and fill up their
+# logs. Do NOT set BEACON EVERY to anything other than 0 while Xastir
+# is running.
+
diff --git a/config/tnc-startup.sys b/config/tnc-startup.sys
new file mode 100644
index 0000000..1ecef8a
--- /dev/null
+++ b/config/tnc-startup.sys
@@ -0,0 +1,56 @@
+# $Id: tnc-startup.sys,v 1.20 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# This is the TNC Startup file for Kantronics TNC.
+# lines that begin with a pound sign are comments.
+
+int terminal
+
+ECHO off
+HID off
+#CWID off
+#CWID every 0
+#
+# Important! Only uncomment if really needed as a fill-in digi:
+#MYAlias WIDE1-1
+#
+B E 0
+DIGI on
+EXP on
+Filt off
+FLow off
+FUll off
+HEA off
+LFadd off
+LFSup on
+AUTOLF off
+MCOM off
+MFILT off
+MON on
+MResp off
+MRPt on
+MSTamp off
+MXMit off
+NEWmode off
+#PACLen 128
+PASSALL off
+#
+#
+# Important! Monitor only PID 0xf0 packets:
+# *Kantronics*
+PID off
+# *TAPR2*
+MNOAX25 off
+# *Paccomm*
+PIDCHECK on
+# *AEA*
+MPROTO OFF
+# End of monitor only PID 0xf0 packets section
+#
+#
+SCR 0
+# B E 0 must be set to 0 or both APRS and your TNC will send BCNS
+# Which will alternate in everyones L and A lists and fill up
+# their logs. Do NOT set B E to anything other than 0 while APRS
+# is running.
diff --git a/config/tnc-startup.thd7 b/config/tnc-startup.thd7
new file mode 100644
index 0000000..1ae2808
--- /dev/null
+++ b/config/tnc-startup.thd7
@@ -0,0 +1,79 @@
+# $Id: tnc-startup.thd7,v 1.17 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# TNC Init file for KENWOOD TH-D7
+#
+#--------------------------------------------------
+# Note: Terminal Control commands are send without
+# CONTROL-C before the lines.
+#--------------------------------------------------
+#
+#--------------------------------------------------
+# Turn on Terminal Control
+#
+# This will make the TH-D7 drop out of Packet mode.
+# Once out of Packet mode, the TH-D7 will forget
+# all old TNC settings and even KISS mode, so we
+# can start from a clean situation.
+#--------------------------------------------------
+#
+##META <no-ctrl-c>
+TC 1
+# Pause one second
+##META <delay>
+##META <delay>
+#
+#--------------------------------------------------
+# Turn off Terminal Control
+#
+# This will make the TH-D7 switch to Packet mode.
+#--------------------------------------------------
+#
+##META <no-ctrl-c>
+TC 0
+# Pause for two seconds just in case
+##META <delay>
+##META <delay>
+##META <delay>
+##META <delay>
+#
+#--------------------------------------------------
+# Initialize the TNC
+#
+# This will setup the TH-D7 TNC for use with APRS.
+#--------------------------------------------------
+#
+HID off
+#CWID off
+AWlen 8
+BBSMsgs ON
+B E 0
+LOC E 0
+Echo off
+FLow off
+AUTOLF off
+MCOM off
+MON ON
+MRPt on
+PACLen 128
+PASSALL off
+#
+# Enable this line ONLY if you're running 9600 baud packet. It
+# changes the on-the-air speed from the default 1200 baud.
+#HBAUD 9600
+#
+TXDELAY 25
+#
+#--------------------------------------------------
+# Initialize the GPS
+#
+# Enable the commands if running with GPS.
+# If running without GPS, leave them disabled.
+#--------------------------------------------------
+#
+#GBAUD 4800
+#GPSTEXT $GPRMC
+#LTMH OFF
+#LTM 10
+#
diff --git a/config/tnc-startup.tnc2 b/config/tnc-startup.tnc2
new file mode 100644
index 0000000..0f275db
--- /dev/null
+++ b/config/tnc-startup.tnc2
@@ -0,0 +1,48 @@
+# $Id: tnc-startup.tnc2,v 1.7 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2005-2012 The Xastir Group
+#
+# This is the TNC Startup file for a TAPR TNC2 style of TNC. This
+# includes many TNC's from TAPR, Paccomm, MFJ, AEA, etc that were
+# based on the original TAPR-2 design.
+
+# lines that begin with a pound sign are comments.
+
+HID off
+#CWID every 0
+MON 0
+ECHO off
+#MYCall WB5BBW
+#
+# Important! Only uncomment if really needed as a fill-in digi:
+#MYAlias WIDE1-1
+#
+#MY1Alias WIDE
+#MY2Alias REGION
+#MY3Alias WORLD
+# B E 0 must be set to 0 or both APRS and your TNC will send BCNS
+# Which will alternate in everyones L and A lists and fill up
+# their logs. Do NOT set B E to anything other than 0 while APRS
+# is running.
+B E 0
+# This enables DIGI On and DIGI-SWAP,DIGI-NOT-OWN, DIGI-ONCE enabled.
+DIGI 7
+FLow off
+FUll off
+HEA off
+LFadd off
+AUTOLF off
+MCOM off
+MFILT $00
+MRPt on
+MSTamp off
+NEWmode off
+PASSALL off
+SCR 0
+MON 1
+#
+# Important! Monitor only PID 0xf0 packets:
+PIDCHECK on
+#
+# End of tnc-startup.tnc2
+#
diff --git a/config/tnc-startup.tnc2-ui b/config/tnc-startup.tnc2-ui
new file mode 100644
index 0000000..ad77a03
--- /dev/null
+++ b/config/tnc-startup.tnc2-ui
@@ -0,0 +1,19 @@
+# $Id: tnc-startup.tnc2-ui,v 1.11 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2004-2012 The Xastir Group
+#
+# This is the TNC Startup file for the TNC2-UI TNC.
+# lines that begin with a pound sign are comments.
+
+HID off
+#CWID off
+MONITOR OFF
+ECHO OFF
+LF OFF
+BEACON 0
+LTIME 0
+HEADER OFF
+MCOM OFF
+AXLF OFF
+MONITOR ON
+
diff --git a/config/tnc-stop.d700 b/config/tnc-stop.d700
new file mode 100644
index 0000000..c1a1589
--- /dev/null
+++ b/config/tnc-stop.d700
@@ -0,0 +1,48 @@
+# $Id: tnc-stop.d700,v 1.8 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2004-2012 The Xastir Group
+#
+#TNC STOP FILE
+# Undo any settings make in tnc-startup.sys
+# Edit this file for your tnc!
+UNPROTO CQ
+AUTOLF ON
+ECHO ON
+#Don't send CONTROL-C before this line
+##META <no-ctrl-c>
+TC 1
+##Pause for one second
+##META <delay>
+##META <delay>
+# Turn off AUX port
+##META <no-ctrl-c>
+GU 0
+##META <delay>
+#Put the TNC in internal mode since this is where we want to end up
+# Change the 1 to 0 to go to normal radio mode
+##META <no-ctrl-c>
+TNC 1
+# Pause for two seconds
+##META <delay>
+##META <delay>
+##META <delay>
+##META <delay>
+# Enable 4800 baud GPS
+# Change to 2 for 9600 baud GPS
+# Disable both the META line and the GU line for no change
+##META <no-ctrl-c>
+GU 1
+# Pause for two seconds
+##META <delay>
+##META <delay>
+##META <delay>
+##META <delay>
+#Turn off Terminal Control
+##META <no-ctrl-c>
+TC 0
+# Pause for two seconds just in case
+##META <delay>
+##META <delay>
+##META <delay>
+##META <delay>
+#
diff --git a/config/tnc-stop.d72_d710 b/config/tnc-stop.d72_d710
new file mode 100644
index 0000000..752855f
--- /dev/null
+++ b/config/tnc-stop.d72_d710
@@ -0,0 +1,39 @@
+# $Id: tnc-stop.d72_d710,v 1.2 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2011-2012 The Xastir Group
+#
+# TNC STOP FILE for Kenwood TM-D710 or TH-D72 radios.
+# Contributed by Kai Günter, LA3QMA.
+#
+# Undo any settings make in tnc-startup.sys
+# Edit this file for your tnc!
+#
+#
+UNPROTO CQ
+AUTOLF ON
+ECHO ON
+#Don't send CONTROL-C before this line
+##META <no-ctrl-c>
+TC 1
+##Pause for one second
+##META <delay>
+##META <delay>
+##META <delay>
+#Put the TNC in internal mode since this is where we want to end up
+# Change the 1 to 0 to go to normal radio mode
+##META <no-ctrl-c>
+TN 0,0
+# Pause for two seconds
+##META <delay>
+##META <delay>
+##META <delay>
+##META <delay>
+#Turn off Terminal Control
+##META <no-ctrl-c>
+TC 0
+# Pause for two seconds just in case
+##META <delay>
+##META <delay>
+##META <delay>
+##META <delay>
+#
diff --git a/config/tnc-stop.sys b/config/tnc-stop.sys
new file mode 100644
index 0000000..d0cc71b
--- /dev/null
+++ b/config/tnc-stop.sys
@@ -0,0 +1,9 @@
+# $Id: tnc-stop.sys,v 1.9 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+#TNC STOP FILE
+# Undo any settings make in tnc-startup.sys
+# Edit this file for your tnc!
+UNPROTO CQ
+AUTOLF ON
diff --git a/config/tnc-stop.thd7 b/config/tnc-stop.thd7
new file mode 100644
index 0000000..c6c7173
--- /dev/null
+++ b/config/tnc-stop.thd7
@@ -0,0 +1,39 @@
+# $Id: tnc-stop.thd7,v 1.8 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2004-2012 The Xastir Group
+#
+# TNC Stop file for KENWOOD TH-D7
+#
+#--------------------------------------------------
+# Note: Terminal Control commands are send without
+# CONTROL-C before the lines.
+#--------------------------------------------------
+#
+#--------------------------------------------------
+# Turn on Terminal Control
+#
+# This will make the TH-D7 drop out of Packet mode.
+# Once out of Packet mode, the TH-D7 will forget
+# all TNC settings. No need to restore anything.
+#--------------------------------------------------
+#
+##META <no-ctrl-c>
+TC 1
+# Pause one second
+##META <delay>
+##META <delay>
+#
+#--------------------------------------------------
+# Resume standalone APRS use.
+#
+# GPS en Beacon settings are not changed. Once back
+# in APRS mode, the GPS and Beacon are resumed as
+# they were.
+#--------------------------------------------------
+#
+##META <no-ctrl-c>
+TNC 1
+# Pause one second
+##META <delay>
+##META <delay>
+#
diff --git a/config/tnc-stop.tnc2-ui b/config/tnc-stop.tnc2-ui
new file mode 100644
index 0000000..b1a4738
--- /dev/null
+++ b/config/tnc-stop.tnc2-ui
@@ -0,0 +1,12 @@
+# $Id: tnc-stop.tnc2-ui,v 1.8 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2004-2012 The Xastir Group
+#
+# This is the TNC Startup file for the TNC2-UI TNC.
+# lines that begin with a pound sign are comments.
+
+MONITOR OFF
+LF ON
+ECHO ON
+MONITOR ON
+
diff --git a/config/xastir.rgb b/config/xastir.rgb
new file mode 100644
index 0000000..ae14a83
--- /dev/null
+++ b/config/xastir.rgb
@@ -0,0 +1,92 @@
+000 000 000 black
+069 069 069 gray27
+047 079 079 DarkSlateGray
+089 089 089 gray35
+135 135 135 gray53
+169 169 169 darkgray
+186 186 186 gray73
+204 204 204 gray80
+207 207 207 gray81
+211 211 211 lightgray
+219 219 219 gray86
+255 255 255 white
+
+000 000 255 blue
+000 000 238 blue2
+000 000 205 blue3
+000 000 139 blue4
+173 216 230 lightblue
+030 144 255 DodgerBlue
+065 105 225 RoyalBlue
+070 130 180 SteelBlue
+000 191 255 DeepSkyBlue
+000 000 205 MediumBlue
+000 000 128 NavyBlue
+
+000 255 000 green
+000 238 000 green2
+000 205 000 green3
+000 139 000 green4
+152 251 152 PaleGreen
+050 205 050 LimeGreen
+060 179 113 MediumSeaGreen
+034 139 034 ForestGreen
+000 100 000 DarkGreen
+
+000 255 255 cyan
+000 238 238 cyan2
+000 205 205 cyan3
+000 139 139 cyan4
+224 255 255 LightCyan
+
+255 000 000 red
+238 000 000 red2
+205 000 000 red3
+139 000 000 red4
+
+255 000 255 magenta
+238 000 238 magenta2
+205 000 205 magenta3
+139 000 139 magenta4
+
+255 255 000 yellow
+238 238 000 yellow2
+238 238 150 yellow3
+139 139 000 yellow4
+250 250 210 LightGoldenrodYellow
+238 232 170 PaleGoldenrod
+255 248 220 cornsilk
+
+255 165 000 orange
+238 154 000 orange2
+205 133 000 orange3
+205 102 000 DarkOrange3
+255 069 000 OrangeRed
+
+178 034 034 firebrick
+188 143 143 RosyBrown
+255 180 180 RosyBrown2
+
+165 042 042 brown
+255 064 064 brown1
+205 051 051 brown3
+255 130 071 sienna1
+
+064 224 208 turquoise
+186 085 211 mediumorchid
+153 050 204 DarkOrchid
+160 032 240 purple
+127 255 000 chartreuse
+230 230 250 lavender
+221 160 221 plum
+238 174 238 plum2
+250 128 114 salmon
+255 192 203 pink
+255 228 225 MistyRose
+255 174 185 LightPink1
+255 105 180 HotPink
+
+127 255 127 tgr_park_1
+255 247 159 tgr_city_1
+175 215 127 tgr_forest_1
+0 159 255 tgr_water_1
diff --git a/configure b/configure
new file mode 100755
index 0000000..02fb440
--- /dev/null
+++ b/configure
@@ -0,0 +1,14320 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.68 for xastir 2.0.4.
+#
+# Report bugs to <xastir at xastir.org>.
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ # We cannot yet assume a decent shell, so we have to provide a
+ # neutralization value for shells without unset; and this also
+ # works around shells that cannot unset nonexistent variables.
+ # Preserve -v and -x to the replacement shell.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+ esac
+ exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf at gnu.org and xastir at xastir.org
+$0: about your system, including any error possibly output
+$0: before this message. Then install a modern shell, or
+$0: manually run the script under such a shell if you do
+$0: have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='xastir'
+PACKAGE_TARNAME='xastir'
+PACKAGE_VERSION='2.0.4'
+PACKAGE_STRING='xastir 2.0.4'
+PACKAGE_BUGREPORT='xastir at xastir.org'
+PACKAGE_URL=''
+
+ac_unique_file="src/xastir.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_header_list=
+ac_func_list=
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+MAGIC_BIN
+GMAGIC_BIN
+DAVIS_FALSE
+DAVIS_TRUE
+LIBRTREE
+SUBRTREE
+found_gdal_config
+MYSQL_CONFIG
+LWPOSTGIS
+PG_CONFIG
+LIBSHP
+CONTSHP
+SUBSHP
+POW_LIB
+LIBOBJS
+ALLOCA
+LIBCOMPAT
+wget
+xfontsel
+mv
+sed
+X_EXTRA_LIBS
+X_LIBS
+X_PRE_LIBS
+X_CFLAGS
+XMKMF
+gpsman
+festival
+gv
+lpr
+convert
+gm
+PTHREAD_CFLAGS
+PTHREAD_LIBS
+PTHREAD_CC
+RANLIB
+LN_S
+EGREP
+GREP
+CPP
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_dependency_tracking
+with_festival
+with_gpsman
+with_errorpopups
+with_lsb
+with_xorg_175_workaround
+with_x
+with_libcurl
+with_motif_includes
+with_motif_libs
+with_libproj
+with_internal_shapelib
+with_shapelib
+with_pcre
+with_geotiff
+with_postgis
+with_mysql
+with_ax25
+with_dbfawk
+with_gdal
+with_rtree
+enable_davis
+with_libgc
+with_profiling
+with_map_cache
+with_bdb_libdir
+with_bdb_incdir
+with_graphicsmagick
+with_imagemagick
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+XMKMF'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used" >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures xastir 2.0.4 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/xastir]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+X features:
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of xastir 2.0.4:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors
+ --enable-davis Turn on Davis support
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --without-festival Disable festival features.
+ --without-gpsman Disable gpsman features.
+ --with-errorpopups Send error popups to stderr.
+ --with-lsb Enable Linux Standard Base.
+ --with-xorg_175_workaround
+ Employ workaround for broken Xorg 1.7.5 server
+ --with-x use the X Window System
+ --without-libcurl Disable libcurl features.
+ --with-motif-includes Set path for motif includes (default none)
+ --with-motif-libs Set path for motif libraries (default none)
+ --without-libproj Disable libproj features.
+ --with-internal-shapelib Force use of internal shapelib library.
+ --without-shapelib Disable shapelib features.
+ --without-pcre Disable pcre features.
+ --without-geotiff Disable geotiff features.
+ --with-postgis Enable Postgresql with PostGIS.
+ --with-mysql Enable MySQL, with spatial support if available.
+ --without-ax25 Disable ax25 features.
+ --without-dbfawk Disable dbfawk features.
+ --without-gdal Disable gdal features.
+ --without-rtree Disable spatial indexing of shapefiles.
+ --with-libgc Enable libgc features.
+ --with-profiling Enable profiling features.
+ --without-map-cache Disable Map Caching.
+ --with-bdb-libdir=DIR Berkeley DB lib files are in DIR
+ --with-bdb-incdir=DIR Berkeley DB include files are in DIR
+ --without-graphicsmagick Disable graphicsmagick features.
+ --without-imagemagick Disable imagemagick features.
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+ XMKMF Path to xmkmf, Makefile generator for X Window System
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <xastir at xastir.org>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+xastir configure 2.0.4
+generated by GNU Autoconf 2.68
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## -------------------------------- ##
+## Report this to xastir at xastir.org ##
+## -------------------------------- ##"
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_test_x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ----------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_c_check_member ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_member
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ as_decl_name=`echo $2|sed 's/ *(.*//'`
+ as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+ (void) $as_decl_use;
+#else
+ (void) $as_decl_name;
+#endif
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_decl
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by xastir $as_me 2.0.4, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+as_fn_append ac_header_list " sys/time.h"
+as_fn_append ac_header_list " unistd.h"
+as_fn_append ac_func_list " alarm"
+as_fn_append ac_header_list " stdlib.h"
+as_fn_append ac_header_list " sys/param.h"
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+am__api_version='1.11'
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[\\\"\#\$\&\'\`$am_lf]*)
+ as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+ *[\\\"\#\$\&\'\`$am_lf\ \ ]*)
+ as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ as_fn_error $? "ls -t appears to fail. Make sure there is not a broken
+alias in your environment" "$LINENO" 5
+ fi
+
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+ if ${ac_cv_path_mkdir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in mkdir gmkdir; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+ case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+ 'mkdir (GNU coreutils) '* | \
+ 'mkdir (coreutils) '* | \
+ 'mkdir (fileutils) '4.1*)
+ ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+ break 3;;
+ esac
+ done
+ done
+ done
+IFS=$as_save_IFS
+
+fi
+
+ test -d ./--version && rmdir ./--version
+ if test "${ac_cv_path_mkdir+set}" = set; then
+ MKDIR_P="$ac_cv_path_mkdir -p"
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for MKDIR_P within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ MKDIR_P="$ac_install_sh -d"
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+ [\\/$]* | ?:[\\/]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AWK="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ am__isrc=' -I$(srcdir)'
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='xastir'
+ VERSION='2.0.4'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+#########################################################################
+
+
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+echo ""
+echo "Configuring xastir 2.0.4"
+echo ""
+
+# Take out the dots in order to create the TOCALL
+
+cat >>confdefs.h <<_ACEOF
+#define XASTIR_TOCALL "`echo 2.0.4 | sed -e 's/^/APX/' -e 's/\.//g'`"
+_ACEOF
+
+
+# Check for host type
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+# Define _GNU_SOURCE if appropriate
+# doesn't work with older (heh) autoconfs
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CC" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+ ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default"
+if test "x$ac_cv_header_minix_config_h" = xyes; then :
+ MINIX=yes
+else
+ MINIX=
+fi
+
+
+ if test "$MINIX" = yes; then
+
+$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h
+
+
+$as_echo "#define _MINIX 1" >>confdefs.h
+
+ fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
+$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; }
+if ${ac_cv_safe_to_define___extensions__+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+# define __EXTENSIONS__ 1
+ $ac_includes_default
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_safe_to_define___extensions__=yes
+else
+ ac_cv_safe_to_define___extensions__=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
+$as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
+ test $ac_cv_safe_to_define___extensions__ = yes &&
+ $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h
+
+ $as_echo "#define _ALL_SOURCE 1" >>confdefs.h
+
+ $as_echo "#define _GNU_SOURCE 1" >>confdefs.h
+
+ $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+ $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h
+
+
+
+
+# Checks for programs.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CC" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AWK="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+#AC_PROG_YACC
+
+# test for devices
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for devices" >&5
+$as_echo_n "checking for devices... " >&6; }
+if test -d /proc/registry ; then
+ac_tnc_port=/dev/ttyS0
+ac_gps_port=/dev/ttyS1
+elif test -c /dev/cuaa0 ; then
+ac_tnc_port=/dev/cuaa0
+ac_gps_port=/dev/cuaa1
+elif test -c /dev/ttyS0 ; then
+ac_tnc_port=/dev/ttyS0
+ac_gps_port=/dev/ttyS1
+elif test -c /dev/cua/a ; then
+ac_tnc_port=/dev/cua/a
+ac_gps_port=/dev/cua/b
+else
+ac_tnc_port=none
+ac_gps_port=none
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define TNC_PORT "$ac_tnc_port"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define GPS_PORT "$ac_gps_port"
+_ACEOF
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: found $ac_tnc_port and $ac_gps_port" >&5
+$as_echo "found $ac_tnc_port and $ac_gps_port" >&6; }
+
+
+# add includes and libs
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for search paths" >&5
+$as_echo_n "checking for search paths... " >&6; }
+
+test -d /usr/local/include && CPPFLAGS="-I/usr/local/include $CPPFLAGS"
+test -d /usr/local/lib && LDFLAGS="-L/usr/local/lib $LDFLAGS"
+
+for d in /sw /opt /opt/local /usr/dt/share /usr/sfw /opt/sfw; do
+test -d $d/include && CPPFLAGS="$CPPFLAGS -I$d/include"
+test -d $d/lib && LDFLAGS="$LDFLAGS -L$d/lib"
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
+$as_echo "done" >&6; }
+
+
+# check for pthread first
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5
+$as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_join ();
+int
+main ()
+{
+return pthread_join ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ acx_pthread_ok=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5
+$as_echo "$acx_pthread_ok" >&6; }
+ if test x"$acx_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+
+case "${host_cpu}-${host_os}" in
+ *solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthread or
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+
+ acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
+ ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+ case $flag in
+ none)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5
+$as_echo_n "checking whether pthreads work without any flags... " >&6; }
+ ;;
+
+ -*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5
+$as_echo_n "checking whether pthreads work with $flag... " >&6; }
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5
+$as_echo_n "checking for the pthreads library -l$flag... " >&6; }
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <pthread.h>
+int
+main ()
+{
+pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ acx_pthread_ok=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5
+$as_echo "$acx_pthread_ok" >&6; }
+ if test "x$acx_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: threads are created detached by default
+ # and the JOINABLE attribute has a nonstandard name (UNDETACHED).
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5
+$as_echo_n "checking for joinable pthread attribute... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <pthread.h>
+int
+main ()
+{
+int attr=PTHREAD_CREATE_JOINABLE;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ok=PTHREAD_CREATE_JOINABLE
+else
+ ok=unknown
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ if test x"$ok" = xunknown; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <pthread.h>
+int
+main ()
+{
+int attr=PTHREAD_CREATE_UNDETACHED;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ok=PTHREAD_CREATE_UNDETACHED
+else
+ ok=unknown
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ fi
+ if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then
+
+$as_echo "#define PTHREAD_CREATE_JOINABLE \$ok" >>confdefs.h
+
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ok}" >&5
+$as_echo "${ok}" >&6; }
+ if test x"$ok" = xunknown; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: we do not know how to create joinable pthreads" >&5
+$as_echo "$as_me: WARNING: we do not know how to create joinable pthreads" >&2;}
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5
+$as_echo_n "checking if more special flags are required for pthreads... " >&6; }
+ flag=no
+ case "${host_cpu}-${host_os}" in
+ *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";;
+ *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5
+$as_echo "${flag}" >&6; }
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: must compile with cc_r
+ # Extract the first word of "cc_r", so it can be a program name with args.
+set dummy cc_r; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_PTHREAD_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$PTHREAD_CC"; then
+ ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_PTHREAD_CC="cc_r"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_PTHREAD_CC" && ac_cv_prog_PTHREAD_CC="${CC}"
+fi
+fi
+PTHREAD_CC=$ac_cv_prog_PTHREAD_CC
+if test -n "$PTHREAD_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5
+$as_echo "$PTHREAD_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+else
+ PTHREAD_CC="$CC"
+fi
+
+
+
+
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+
+$as_echo "#define HAVE_PTHREAD 1" >>confdefs.h
+
+ :
+else
+ acx_pthread_ok=no
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+# add compiler flags
+
+# notes -- gcc only! HPUX doesn't work for this so no "-Ae +O2"
+
+
+# everybody likes "-g -O2", right?
+# TVR: Not only does "everybody" not like "-g -O2", but the code below
+# is unnecessary for GCC, which does like "-g -O2". The autoconf macros that
+# probe for the C compiler will put "-g -O2" into CFLAGS if the compiler is
+# GCC and the user has not specified any CFLAGS, and leaves CFLAGS alone
+# if the user has set it him/herself. The "##" commented code
+# below forces -g -O2 into CFLAGS even if the user has specified something
+# else.
+##for f in -g -O2; do
+## eventually write a test for these
+## gcc already checks for -g earlier!
+##echo $CFLAGS | grep -- $f > /dev/null || CFLAGS="$CFLAGS $f"
+##done
+
+# brutal!
+# check for sed maybe?
+if test "$ac_cv_prog_ac_ct_CC" = "gcc"; then
+gcc --help | sed -e "/^^ /d" -e "/^ ^ /d" -e "/^ ^-/d" -e "s/ //" -e "s/ .*//" > gccflags
+
+# I need a test for -Wno-return-type and -DFUNCPROTO=15
+# before adding them
+
+for f in -no-cpp-precomp -pipe; do
+grep -- $f gccflags > /dev/null && CFLAGS="$CFLAGS $f"
+done
+
+# delete temporary file
+rm -f gccflags
+
+# add any other flags that aren't added earlier
+# Can't add "-Wno-unused-parameter" as older compilers don't like
+# it.
+#
+for f in -W -Wall -Wpointer-arith -Wstrict-prototypes; do
+echo $CFLAGS | grep -- $f > /dev/null || CFLAGS="$CFLAGS $f"
+done
+
+# Now check whether to use -Wno-unused-parameter (gcc 3) or -Wno-unused
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler accepts -Wno-unused-parameter" >&5
+$as_echo_n "checking whether compiler accepts -Wno-unused-parameter... " >&6; }
+save_CFLAGS=$CFLAGS
+CFLAGS="$CFLAGS -Wno-unused-parameter"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+int i;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using -Wno-unused" >&5
+$as_echo "no, using -Wno-unused" >&6; }; CFLAGS="$save_CFLAGS -Wno-unused"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# end gcc-specific checks
+fi
+
+# add any pthread flags now
+CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler flags" >&5
+$as_echo_n "checking for compiler flags... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: using $CFLAGS" >&5
+$as_echo "using $CFLAGS" >&6; }
+
+
+# set XASTIR_SYSTEM
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for system" >&5
+$as_echo_n "checking for system... " >&6; }
+
+case "$host_os" in
+cygwin*)
+ system=Cygnus
+;;
+darwin*)
+ system=Darwin
+ LDFLAGS="-L/sw/lib -L/opt/local/lib $LDFLAGS"
+ CPPFLAGS="-I/sw/include -I/opt/local/include $CPPFLAGS"
+ EXTRA_BIN_PATH=":/opt/local/bin:/sw/bin"
+;;
+freebsd*)
+ system=FreeBSD
+;;
+hpux*)
+ system=HP/UX
+;;
+linux*)
+ system=Linux
+#
+#
+# Useful for testing MacOSX paths on a Linux development box:
+# EXTRA_BIN_PATH=":/opt/local/bin:/sw/bin"
+#
+#
+;;
+netbsd*)
+ system=NetBSD
+;;
+openbsd*)
+ system=OpenBSD
+;;
+solaris*)
+ system=Solaris
+;;
+*)
+ system=unknown
+;;
+esac
+
+
+cat >>confdefs.h <<_ACEOF
+#define XASTIR_SYSTEM "$system"
+_ACEOF
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $system" >&5
+$as_echo "$system" >&6; }
+
+
+# Check for binaries
+use_festival=yes
+use_gpsman=yes
+use_err_popups=no
+use_lsb=no
+use_spatial_db=no
+use_postgis=no
+use_mysql_spatial=no
+
+# Check whether --with-festival was given.
+if test "${with_festival+set}" = set; then :
+ withval=$with_festival; use_festival=$withval
+fi
+
+
+
+# Check whether --with-gpsman was given.
+if test "${with_gpsman+set}" = set; then :
+ withval=$with_gpsman; use_gpsman=$withval
+fi
+
+
+
+# Check whether --with-errorpopups was given.
+if test "${with_errorpopups+set}" = set; then :
+ withval=$with_errorpopups; use_err_popups=$withval
+fi
+
+
+
+# Check whether --with-lsb was given.
+if test "${with_lsb+set}" = set; then :
+ withval=$with_lsb; use_lsb=$withval
+fi
+
+
+
+# Check whether --with-xorg_175_workaround was given.
+if test "${with_xorg_175_workaround+set}" = set; then :
+ withval=$with_xorg_175_workaround;
+else
+ with_xorg_175_workaround=no
+fi
+
+if test "x$with_xorg_175_workaround" != xno; then :
+
+$as_echo "#define XASTIR_XORG_SERVER_175_BUG 1" >>confdefs.h
+
+fi
+
+# Now that all the various "use_" variables are set, probe for binaries.
+
+BINPATH=$PATH
+
+for d in / /usr /usr/local /usr/X11 /usr/X11R6 /usr/sfw /opt/sfw /opt/local /sw; do
+test -d $d/bin && echo $BINPATH | grep -- $d/bin > /dev/null || BINPATH="$BINPATH:$d/bin"
+done
+
+# it would be much nicer to do this in a for loop
+
+if test "$use_lsb" = "yes"; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_CONVERT 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define CONVERT_PATH "/opt/Xastir/bin/gm convert"
+_ACEOF
+
+else
+ # Extract the first word of "gm version", so it can be a program name with args.
+set dummy gm version; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_gm+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $gm in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gm="$gm" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $BINPATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_gm="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_gm" && ac_cv_path_gm="no"
+ ;;
+esac
+fi
+gm=$ac_cv_path_gm
+if test -n "$gm"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gm" >&5
+$as_echo "$gm" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /usr/bin/gm.exe" >&5
+$as_echo_n "checking for /usr/bin/gm.exe... " >&6; }
+if ${ac_cv_file__usr_bin_gm_exe+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ test "$cross_compiling" = yes &&
+ as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
+if test -r "/usr/bin/gm.exe"; then
+ ac_cv_file__usr_bin_gm_exe=yes
+else
+ ac_cv_file__usr_bin_gm_exe=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file__usr_bin_gm_exe" >&5
+$as_echo "$ac_cv_file__usr_bin_gm_exe" >&6; }
+if test "x$ac_cv_file__usr_bin_gm_exe" = xyes; then :
+ gm="/usr/bin/gm"
+fi
+
+ if test "$gm" != "no"; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_CONVERT 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define CONVERT_PATH "${gm} convert"
+_ACEOF
+
+ else
+ # Extract the first word of "convert --version", so it can be a program name with args.
+set dummy convert --version; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_convert+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $convert in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_convert="$convert" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $BINPATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_convert="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_convert" && ac_cv_path_convert="no"
+ ;;
+esac
+fi
+convert=$ac_cv_path_convert
+if test -n "$convert"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $convert" >&5
+$as_echo "$convert" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /usr/bin/convert.exe" >&5
+$as_echo_n "checking for /usr/bin/convert.exe... " >&6; }
+if ${ac_cv_file__usr_bin_convert_exe+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ test "$cross_compiling" = yes &&
+ as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
+if test -r "/usr/bin/convert.exe"; then
+ ac_cv_file__usr_bin_convert_exe=yes
+else
+ ac_cv_file__usr_bin_convert_exe=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file__usr_bin_convert_exe" >&5
+$as_echo "$ac_cv_file__usr_bin_convert_exe" >&6; }
+if test "x$ac_cv_file__usr_bin_convert_exe" = xyes; then :
+ convert="/usr/bin/convert"
+fi
+
+ if test "$convert" != "no"; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_CONVERT 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define CONVERT_PATH "${convert}"
+_ACEOF
+
+ fi
+ fi
+fi
+
+# Extract the first word of "lpr /dev/null", so it can be a program name with args.
+set dummy lpr /dev/null; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_lpr+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $lpr in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_lpr="$lpr" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $BINPATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_lpr="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_lpr" && ac_cv_path_lpr="no"
+ ;;
+esac
+fi
+lpr=$ac_cv_path_lpr
+if test -n "$lpr"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lpr" >&5
+$as_echo "$lpr" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test "$lpr" != "no"; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LPR 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define LPR_PATH "${lpr}"
+_ACEOF
+
+fi
+
+#Find gv executable
+# Extract the first word of "gv", so it can be a program name with args.
+set dummy gv; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_gv+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $gv in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gv="$gv" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $BINPATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_gv="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_gv" && ac_cv_path_gv="no"
+ ;;
+esac
+fi
+gv=$ac_cv_path_gv
+if test -n "$gv"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gv" >&5
+$as_echo "$gv" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+if test "$gv" != "no"; then
+ # Test gv version
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking gv version" >&5
+$as_echo_n "checking gv version... " >&6; }
+ gv_new="no";
+ gv_version=`gv --version 2>&1`
+ gv_test=`echo $gv_version | cut -d ' ' -f 1`
+ if test "$gv_test" != "gv"; then
+ gv_version=`gv -v 2>&1`
+ fi
+ gv_test=`echo $gv_version | cut -d ' ' -f 1`
+ if test "$gv_test" != "gv"; then
+ # No gv found. Put an AC_PATH_PROG here so the "then" clause has
+ # something to do and so that we get proper output to the user.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: gv version test likely exited with error, this is what it said: $gv_version" >&5
+$as_echo "gv version test likely exited with error, this is what it said: $gv_version" >&6; }
+ else
+ gv_short_version=`echo $gv_version | cut -d ' ' -f 2`
+ gv_major=`echo $gv_short_version | cut -d '.' -f 1`
+ gv_minor=`echo $gv_short_version | cut -d '.' -f 2`
+ gv_tiny=`echo $gv_short_version | cut -d '.' -f 3`
+ if test "$gv_major" -gt 3; then
+ gv_new="yes";
+ elif test "$gv_major" -ge 3 -a "$gv_minor" -gt 6; then
+ gv_new="yes";
+ elif test "$gv_major" -ge 3 -a "$gv_minor" -ge 6 -a "$gv_tiny" -ge 1; then
+ gv_new="yes";
+ fi
+ if test "$gv_new" != "no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: new, >= 3.6.1" >&5
+$as_echo "new, >= 3.6.1" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GV 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_NEW_GV 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define GV_PATH "${gv}"
+_ACEOF
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: old, pre 3.6.1" >&5
+$as_echo "old, pre 3.6.1" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GV 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_OLD_GV 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define GV_PATH "${gv}"
+_ACEOF
+
+ fi
+ fi
+fi
+
+if test "$use_festival" != "no"; then
+ # Extract the first word of "festival", so it can be a program name with args.
+set dummy festival; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_festival+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $festival in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_festival="$festival" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $BINPATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_festival="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_festival" && ac_cv_path_festival="no"
+ ;;
+esac
+fi
+festival=$ac_cv_path_festival
+if test -n "$festival"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $festival" >&5
+$as_echo "$festival" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "$festival" != "no"; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_FESTIVAL 1
+_ACEOF
+
+ fi
+fi
+
+if test "$use_gpsman" != "no"; then
+ # Extract the first word of "gpsman haslib gpsmanshp", so it can be a program name with args.
+set dummy gpsman haslib gpsmanshp; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_gpsman+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $gpsman in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gpsman="$gpsman" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $BINPATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_gpsman="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_gpsman" && ac_cv_path_gpsman="no"
+ ;;
+esac
+fi
+gpsman=$ac_cv_path_gpsman
+if test -n "$gpsman"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gpsman" >&5
+$as_echo "$gpsman" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "$gpsman" != "no"; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GPSMAN 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define GPSMAN_PATH "${gpsman}"
+_ACEOF
+
+ fi
+fi
+
+if test "$use_err_popups" != "no"; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ERROR_POPUPS 1
+_ACEOF
+
+fi
+
+if test "$use_lsb" != "no"; then
+
+cat >>confdefs.h <<_ACEOF
+#define __LSB__ 1
+_ACEOF
+
+fi
+
+
+
+
+
+# if the probes failed, then make sure the "use_" variables are set to no,
+# even if we requested them.
+if test "x${festival}" = "xno"; then
+ use_festival=no
+fi
+if test "x${gpsman}" = "xno"; then
+ use_gpsman=no
+fi
+
+
+# JMT - XXX - what is this and why is it relevant?
+#AC_DEFINE(_REENTRANT, 1, [Use reentrant code if available.])
+
+cat >>confdefs.h <<_ACEOF
+#define STIPPLE 1
+_ACEOF
+
+
+# Checks for libraries.
+#
+#
+# Find the X11 include and library directories.
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5
+$as_echo_n "checking for X... " >&6; }
+
+
+# Check whether --with-x was given.
+if test "${with_x+set}" = set; then :
+ withval=$with_x;
+fi
+
+# $have_x is `yes', `no', `disabled', or empty when we do not yet know.
+if test "x$with_x" = xno; then
+ # The user explicitly disabled X.
+ have_x=disabled
+else
+ case $x_includes,$x_libraries in #(
+ *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #(
+ *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # One or both of the vars are not set, and there is no cached value.
+ac_x_includes=no ac_x_libraries=no
+rm -f -r conftest.dir
+if mkdir conftest.dir; then
+ cd conftest.dir
+ cat >Imakefile <<'_ACEOF'
+incroot:
+ @echo incroot='${INCROOT}'
+usrlibdir:
+ @echo usrlibdir='${USRLIBDIR}'
+libdir:
+ @echo libdir='${LIBDIR}'
+_ACEOF
+ if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then
+ # GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+ for ac_var in incroot usrlibdir libdir; do
+ eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`"
+ done
+ # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
+ for ac_extension in a so sl dylib la dll; do
+ if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" &&
+ test -f "$ac_im_libdir/libX11.$ac_extension"; then
+ ac_im_usrlibdir=$ac_im_libdir; break
+ fi
+ done
+ # Screen out bogus values from the imake configuration. They are
+ # bogus both because they are the default anyway, and because
+ # using them would break gcc on systems where it needs fixed includes.
+ case $ac_im_incroot in
+ /usr/include) ac_x_includes= ;;
+ *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;;
+ esac
+ case $ac_im_usrlibdir in
+ /usr/lib | /usr/lib64 | /lib | /lib64) ;;
+ *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;;
+ esac
+ fi
+ cd ..
+ rm -f -r conftest.dir
+fi
+
+# Standard set of common directories for X headers.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+ac_x_header_dirs='
+/usr/X11/include
+/usr/X11R7/include
+/usr/X11R6/include
+/usr/X11R5/include
+/usr/X11R4/include
+
+/usr/include/X11
+/usr/include/X11R7
+/usr/include/X11R6
+/usr/include/X11R5
+/usr/include/X11R4
+
+/usr/local/X11/include
+/usr/local/X11R7/include
+/usr/local/X11R6/include
+/usr/local/X11R5/include
+/usr/local/X11R4/include
+
+/usr/local/include/X11
+/usr/local/include/X11R7
+/usr/local/include/X11R6
+/usr/local/include/X11R5
+/usr/local/include/X11R4
+
+/usr/X386/include
+/usr/x386/include
+/usr/XFree86/include/X11
+
+/usr/include
+/usr/local/include
+/usr/unsupported/include
+/usr/athena/include
+/usr/local/x11r5/include
+/usr/lpp/Xamples/include
+
+/usr/openwin/include
+/usr/openwin/share/include'
+
+if test "$ac_x_includes" = no; then
+ # Guess where to find include files, by looking for Xlib.h.
+ # First, try using that file with no special directory specified.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <X11/Xlib.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # We can compile using X headers with no special include directory.
+ac_x_includes=
+else
+ for ac_dir in $ac_x_header_dirs; do
+ if test -r "$ac_dir/X11/Xlib.h"; then
+ ac_x_includes=$ac_dir
+ break
+ fi
+done
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+fi # $ac_x_includes = no
+
+if test "$ac_x_libraries" = no; then
+ # Check for the libraries.
+ # See if we find them without any special options.
+ # Don't add to $LIBS permanently.
+ ac_save_LIBS=$LIBS
+ LIBS="-lX11 $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <X11/Xlib.h>
+int
+main ()
+{
+XrmInitialize ()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ LIBS=$ac_save_LIBS
+# We can link X programs with no special library path.
+ac_x_libraries=
+else
+ LIBS=$ac_save_LIBS
+for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g`
+do
+ # Don't even attempt the hair of trying to link an X program!
+ for ac_extension in a so sl dylib la dll; do
+ if test -r "$ac_dir/libX11.$ac_extension"; then
+ ac_x_libraries=$ac_dir
+ break 2
+ fi
+ done
+done
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi # $ac_x_libraries = no
+
+case $ac_x_includes,$ac_x_libraries in #(
+ no,* | *,no | *\'*)
+ # Didn't find X, or a directory has "'" in its name.
+ ac_cv_have_x="have_x=no";; #(
+ *)
+ # Record where we found X for the cache.
+ ac_cv_have_x="have_x=yes\
+ ac_x_includes='$ac_x_includes'\
+ ac_x_libraries='$ac_x_libraries'"
+esac
+fi
+;; #(
+ *) have_x=yes;;
+ esac
+ eval "$ac_cv_have_x"
+fi # $with_x != no
+
+if test "$have_x" != yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5
+$as_echo "$have_x" >&6; }
+ no_x=yes
+else
+ # If each of the values was on the command line, it overrides each guess.
+ test "x$x_includes" = xNONE && x_includes=$ac_x_includes
+ test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
+ # Update the cache value to reflect the command line values.
+ ac_cv_have_x="have_x=yes\
+ ac_x_includes='$x_includes'\
+ ac_x_libraries='$x_libraries'"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5
+$as_echo "libraries $x_libraries, headers $x_includes" >&6; }
+fi
+
+if test "$no_x" = yes; then
+ # Not all programs may use this symbol, but it does not hurt to define it.
+
+$as_echo "#define X_DISPLAY_MISSING 1" >>confdefs.h
+
+ X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS=
+else
+ if test -n "$x_includes"; then
+ X_CFLAGS="$X_CFLAGS -I$x_includes"
+ fi
+
+ # It would also be nice to do this for all -L options, not just this one.
+ if test -n "$x_libraries"; then
+ X_LIBS="$X_LIBS -L$x_libraries"
+ # For Solaris; some versions of Sun CC require a space after -R and
+ # others require no space. Words are not sufficient . . . .
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -R must be followed by a space" >&5
+$as_echo_n "checking whether -R must be followed by a space... " >&6; }
+ ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries"
+ ac_xsave_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ X_LIBS="$X_LIBS -R$x_libraries"
+else
+ LIBS="$ac_xsave_LIBS -R $x_libraries"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ X_LIBS="$X_LIBS -R $x_libraries"
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: neither works" >&5
+$as_echo "neither works" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_c_werror_flag=$ac_xsave_c_werror_flag
+ LIBS=$ac_xsave_LIBS
+ fi
+
+ # Check for system-dependent libraries X programs must link with.
+ # Do this before checking for the system-independent R6 libraries
+ # (-lICE), since we may need -lsocket or whatever for X linking.
+
+ if test "$ISC" = yes; then
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet"
+ else
+ # Martyn Johnson says this is needed for Ultrix, if the X
+ # libraries were built with DECnet support. And Karl Berry says
+ # the Alpha needs dnet_stub (dnet does not exist).
+ ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XOpenDisplay ();
+int
+main ()
+{
+return XOpenDisplay ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5
+$as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; }
+if ${ac_cv_lib_dnet_dnet_ntoa+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldnet $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dnet_ntoa ();
+int
+main ()
+{
+return dnet_ntoa ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dnet_dnet_ntoa=yes
+else
+ ac_cv_lib_dnet_dnet_ntoa=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5
+$as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; }
+if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes; then :
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet"
+fi
+
+ if test $ac_cv_lib_dnet_dnet_ntoa = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5
+$as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; }
+if ${ac_cv_lib_dnet_stub_dnet_ntoa+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldnet_stub $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dnet_ntoa ();
+int
+main ()
+{
+return dnet_ntoa ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dnet_stub_dnet_ntoa=yes
+else
+ ac_cv_lib_dnet_stub_dnet_ntoa=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5
+$as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; }
+if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes; then :
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub"
+fi
+
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$ac_xsave_LIBS"
+
+ # msh at cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT,
+ # to get the SysV transport functions.
+ # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4)
+ # needs -lnsl.
+ # The nsl library prevents programs from opening the X display
+ # on Irix 5.2, according to T.E. Dickey.
+ # The functions gethostbyname, getservbyname, and inet_addr are
+ # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking.
+ ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
+if test "x$ac_cv_func_gethostbyname" = xyes; then :
+
+fi
+
+ if test $ac_cv_func_gethostbyname = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5
+$as_echo_n "checking for gethostbyname in -lnsl... " >&6; }
+if ${ac_cv_lib_nsl_gethostbyname+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_nsl_gethostbyname=yes
+else
+ ac_cv_lib_nsl_gethostbyname=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5
+$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; }
+if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then :
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl"
+fi
+
+ if test $ac_cv_lib_nsl_gethostbyname = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5
+$as_echo_n "checking for gethostbyname in -lbsd... " >&6; }
+if ${ac_cv_lib_bsd_gethostbyname+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lbsd $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_bsd_gethostbyname=yes
+else
+ ac_cv_lib_bsd_gethostbyname=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5
+$as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; }
+if test "x$ac_cv_lib_bsd_gethostbyname" = xyes; then :
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd"
+fi
+
+ fi
+ fi
+
+ # lieder at skyler.mavd.honeywell.com says without -lsocket,
+ # socket/setsockopt and other routines are undefined under SCO ODT
+ # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary
+ # on later versions), says Simon Leinen: it contains gethostby*
+ # variants that don't use the name server (or something). -lsocket
+ # must be given before -lnsl if both are needed. We assume that
+ # if connect needs -lnsl, so does gethostbyname.
+ ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect"
+if test "x$ac_cv_func_connect" = xyes; then :
+
+fi
+
+ if test $ac_cv_func_connect = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5
+$as_echo_n "checking for connect in -lsocket... " >&6; }
+if ${ac_cv_lib_socket_connect+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket $X_EXTRA_LIBS $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char connect ();
+int
+main ()
+{
+return connect ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_socket_connect=yes
+else
+ ac_cv_lib_socket_connect=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5
+$as_echo "$ac_cv_lib_socket_connect" >&6; }
+if test "x$ac_cv_lib_socket_connect" = xyes; then :
+ X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS"
+fi
+
+ fi
+
+ # Guillermo Gomez says -lposix is necessary on A/UX.
+ ac_fn_c_check_func "$LINENO" "remove" "ac_cv_func_remove"
+if test "x$ac_cv_func_remove" = xyes; then :
+
+fi
+
+ if test $ac_cv_func_remove = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5
+$as_echo_n "checking for remove in -lposix... " >&6; }
+if ${ac_cv_lib_posix_remove+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lposix $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char remove ();
+int
+main ()
+{
+return remove ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_posix_remove=yes
+else
+ ac_cv_lib_posix_remove=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5
+$as_echo "$ac_cv_lib_posix_remove" >&6; }
+if test "x$ac_cv_lib_posix_remove" = xyes; then :
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix"
+fi
+
+ fi
+
+ # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay.
+ ac_fn_c_check_func "$LINENO" "shmat" "ac_cv_func_shmat"
+if test "x$ac_cv_func_shmat" = xyes; then :
+
+fi
+
+ if test $ac_cv_func_shmat = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5
+$as_echo_n "checking for shmat in -lipc... " >&6; }
+if ${ac_cv_lib_ipc_shmat+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lipc $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shmat ();
+int
+main ()
+{
+return shmat ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_ipc_shmat=yes
+else
+ ac_cv_lib_ipc_shmat=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5
+$as_echo "$ac_cv_lib_ipc_shmat" >&6; }
+if test "x$ac_cv_lib_ipc_shmat" = xyes; then :
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc"
+fi
+
+ fi
+ fi
+
+ # Check for libraries that X11R6 Xt/Xaw programs need.
+ ac_save_LDFLAGS=$LDFLAGS
+ test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries"
+ # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to
+ # check for ICE first), but we must link in the order -lSM -lICE or
+ # we get undefined symbols. So assume we have SM if we have ICE.
+ # These have to be linked with before -lX11, unlike the other
+ # libraries we check for below, so use a different variable.
+ # John Interrante, Karl Berry
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5
+$as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; }
+if ${ac_cv_lib_ICE_IceConnectionNumber+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lICE $X_EXTRA_LIBS $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char IceConnectionNumber ();
+int
+main ()
+{
+return IceConnectionNumber ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_ICE_IceConnectionNumber=yes
+else
+ ac_cv_lib_ICE_IceConnectionNumber=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5
+$as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; }
+if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes; then :
+ X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE"
+fi
+
+ LDFLAGS=$ac_save_LDFLAGS
+
+fi
+
+if test "$no_x" = "yes"; then
+ as_fn_error $? "*** No X11! Install X-Windows development headers/libraries! ***" "$LINENO" 5
+fi
+
+CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+LDFLAGS="$LDFLAGS $X_LIBS"
+LIBS="$LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing tan" >&5
+$as_echo_n "checking for library containing tan... " >&6; }
+if ${ac_cv_search_tan+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char tan ();
+int
+main ()
+{
+return tan ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' math m; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_tan=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_tan+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_tan+:} false; then :
+
+else
+ ac_cv_search_tan=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_tan" >&5
+$as_echo "$ac_cv_search_tan" >&6; }
+ac_res=$ac_cv_search_tan
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XextAddDisplay in -lXext" >&5
+$as_echo_n "checking for XextAddDisplay in -lXext... " >&6; }
+if ${ac_cv_lib_Xext_XextAddDisplay+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXext $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XextAddDisplay ();
+int
+main ()
+{
+return XextAddDisplay ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_Xext_XextAddDisplay=yes
+else
+ ac_cv_lib_Xext_XextAddDisplay=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xext_XextAddDisplay" >&5
+$as_echo "$ac_cv_lib_Xext_XextAddDisplay" >&6; }
+if test "x$ac_cv_lib_Xext_XextAddDisplay" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBXEXT 1
+_ACEOF
+
+ LIBS="-lXext $LIBS"
+
+fi
+
+# It appears that XpGetDocumentData is not used
+# *anywhere* in Xastir, and the fact that this is being probed for has
+# confused at least one user into thinking he needed to install the X Printing
+# Extension development headers when it was completely unnecessary. But
+# apparently at least one linux system has a motif library that requires
+# libXp and doesn't link it in dynamically --- so this needs to be enabled?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XpGetDocumentData in -lXp" >&5
+$as_echo_n "checking for XpGetDocumentData in -lXp... " >&6; }
+if ${ac_cv_lib_Xp_XpGetDocumentData+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXp $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XpGetDocumentData ();
+int
+main ()
+{
+return XpGetDocumentData ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_Xp_XpGetDocumentData=yes
+else
+ ac_cv_lib_Xp_XpGetDocumentData=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xp_XpGetDocumentData" >&5
+$as_echo "$ac_cv_lib_Xp_XpGetDocumentData" >&6; }
+if test "x$ac_cv_lib_Xp_XpGetDocumentData" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBXP 1
+_ACEOF
+
+ LIBS="-lXp $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XtDisplay in -lXt" >&5
+$as_echo_n "checking for XtDisplay in -lXt... " >&6; }
+if ${ac_cv_lib_Xt_XtDisplay+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXt $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XtDisplay ();
+int
+main ()
+{
+return XtDisplay ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_Xt_XtDisplay=yes
+else
+ ac_cv_lib_Xt_XtDisplay=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xt_XtDisplay" >&5
+$as_echo "$ac_cv_lib_Xt_XtDisplay" >&6; }
+if test "x$ac_cv_lib_Xt_XtDisplay" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBXT 1
+_ACEOF
+
+ LIBS="-lXt $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XmTextFindString in -lXm" >&5
+$as_echo_n "checking for XmTextFindString in -lXm... " >&6; }
+if ${ac_cv_lib_Xm_XmTextFindString+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXm $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XmTextFindString ();
+int
+main ()
+{
+return XmTextFindString ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_Xm_XmTextFindString=yes
+else
+ ac_cv_lib_Xm_XmTextFindString=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xm_XmTextFindString" >&5
+$as_echo "$ac_cv_lib_Xm_XmTextFindString" >&6; }
+if test "x$ac_cv_lib_Xm_XmTextFindString" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBXM 1
+_ACEOF
+
+ LIBS="-lXm $LIBS"
+
+fi
+
+
+
+
+#use_html2text=no
+#AC_PATH_PROG(html2text, [html2text --version], no, $BINPATH)
+#if test "$html2text" != "no"; then
+# AC_DEFINE_UNQUOTED(HAVE_HTML2TEXT, 1, [Define if you have html2text])
+# AC_DEFINE_UNQUOTED(HTML2TEXT_PATH, "${html2text}", [Path to html2text])
+# use_html2text=yes
+#fi
+
+
+
+use_sed=no
+# Extract the first word of "sed --version", so it can be a program name with args.
+set dummy sed --version; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_sed+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $sed in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_sed="$sed" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $BINPATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_sed="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_sed" && ac_cv_path_sed="no"
+ ;;
+esac
+fi
+sed=$ac_cv_path_sed
+if test -n "$sed"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sed" >&5
+$as_echo "$sed" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test "$sed" != "no"; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_SED 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define SED_PATH "${sed}"
+_ACEOF
+
+ use_sed=yes
+fi
+
+
+
+use_mv=no
+# Extract the first word of "mv --version", so it can be a program name with args.
+set dummy mv --version; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_mv+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $mv in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_mv="$mv" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $BINPATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_mv="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_mv" && ac_cv_path_mv="no"
+ ;;
+esac
+fi
+mv=$ac_cv_path_mv
+if test -n "$mv"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $mv" >&5
+$as_echo "$mv" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test "$mv" != "no"; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_MV 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define MV_PATH "${mv}"
+_ACEOF
+
+ use_mv=yes
+fi
+
+
+
+use_xfontsel=no
+# Extract the first word of "xfontsel", so it can be a program name with args.
+set dummy xfontsel; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_xfontsel+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $xfontsel in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_xfontsel="$xfontsel" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $BINPATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_xfontsel="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_xfontsel" && ac_cv_path_xfontsel="no"
+ ;;
+esac
+fi
+xfontsel=$ac_cv_path_xfontsel
+if test -n "$xfontsel"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xfontsel" >&5
+$as_echo "$xfontsel" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test "$xfontsel" != "no"; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_XFONTSEL 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define XFONTSEL_PATH "${xfontsel}"
+_ACEOF
+
+ use_xfontsel=yes
+fi
+
+
+
+use_curl=no
+curl_desired=yes
+# Note: Had to move AC_CHECK_HEADER here instead of inside the first
+# "if" statement: It corrupted later tests, don't know why. The
+# only downside is that we check for the libcurl headers even if
+# --without-libcurl was specified on the command-line.
+ac_fn_c_check_header_mongrel "$LINENO" "curl/curl.h" "ac_cv_header_curl_curl_h" "$ac_includes_default"
+if test "x$ac_cv_header_curl_curl_h" = xyes; then :
+ CURL_INC="yes"
+else
+ CURL_INC="no"
+fi
+
+
+
+# Check whether --with-libcurl was given.
+if test "${with_libcurl+set}" = set; then :
+ withval=$with_libcurl; curl_desired=$withval
+fi
+
+if test "${curl_desired}" = "yes"; then
+ if test "${CURL_INC}" = "yes"; then
+ if test "${use_lsb}" = "no"; then
+ # Important: when using the three-argument version of AC_CHECK_LIB, you
+ # must do all of what is normally the default behavior in the third argument,
+ # not just the extra stuff you want to accomplish:
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl_global_init in -lcurl" >&5
+$as_echo_n "checking for curl_global_init in -lcurl... " >&6; }
+if ${ac_cv_lib_curl_curl_global_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcurl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char curl_global_init ();
+int
+main ()
+{
+return curl_global_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_curl_curl_global_init=yes
+else
+ ac_cv_lib_curl_curl_global_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curl_curl_global_init" >&5
+$as_echo "$ac_cv_lib_curl_curl_global_init" >&6; }
+if test "x$ac_cv_lib_curl_curl_global_init" = xyes; then :
+ use_curl="yes"
+ LIBS="${LIBS} -lcurl"
+
+$as_echo "#define HAVE_LIBCURL /**/" >>confdefs.h
+
+
+fi
+
+ else
+
+$as_echo "#define HAVE_LIBCURL /**/" >>confdefs.h
+
+ LIBS="${LIBS} -lcurl"
+ use_curl=yes
+ fi
+ fi
+fi
+# Test for wget only if above libcurl tests fail
+use_wget=no
+if test "${use_curl}" = "no"; then
+ # Extract the first word of "wget --version", so it can be a program name with args.
+set dummy wget --version; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_wget+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $wget in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_wget="$wget" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $BINPATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_wget="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_wget" && ac_cv_path_wget="no"
+ ;;
+esac
+fi
+wget=$ac_cv_path_wget
+if test -n "$wget"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $wget" >&5
+$as_echo "$wget" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "$wget" != "no"; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_WGET 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define WGET_PATH "${wget}"
+_ACEOF
+
+ use_wget=yes
+ fi
+fi
+
+
+
+use_retrieval=no
+if test "${use_curl}" = "yes"; then
+ use_retrieval="yes (libcurl)"
+else
+ if test "${use_wget}" = "yes"; then
+ use_retrieval="yes (wget)"
+ fi
+fi
+
+
+
+# Test for libgps, used for accessing GPSD daemon
+#use_libgps=no
+#AC_CHECK_HEADER(gps.h, GPS_INC="yes", GPS_INC="no")
+#if test "${GPS_INC}" = "yes"; then
+# AC_CHECK_LIB([gps], [gps_open],
+# [use_libgps="yes"
+# LIBS="${LIBS} -lgps"
+# AC_DEFINE(HAVE_LIBGPS, ,
+# [Define to 1 if your `libgps' library has gps_open.])
+# ])
+#fi
+
+
+
+# JMT - XXX - why is this here?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lcompat" >&5
+$as_echo_n "checking for main in -lcompat... " >&6; }
+if ${ac_cv_lib_compat_main+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcompat $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_compat_main=yes
+else
+ ac_cv_lib_compat_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_compat_main" >&5
+$as_echo "$ac_cv_lib_compat_main" >&6; }
+if test "x$ac_cv_lib_compat_main" = xyes; then :
+ LIBCOMPAT="-lcompat"
+
+fi
+
+
+# Check for sched_yield in librt (Needed for Solaris)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sched_yield in -lrt" >&5
+$as_echo_n "checking for sched_yield in -lrt... " >&6; }
+if ${ac_cv_lib_rt_sched_yield+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sched_yield ();
+int
+main ()
+{
+return sched_yield ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_rt_sched_yield=yes
+else
+ ac_cv_lib_rt_sched_yield=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_sched_yield" >&5
+$as_echo "$ac_cv_lib_rt_sched_yield" >&6; }
+if test "x$ac_cv_lib_rt_sched_yield" = xyes; then :
+ LIBS="-lrt $LIBS"
+fi
+
+
+# Check for endian
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_bigendian=unknown
+ # See if we're dealing with a universal compiler.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __APPLE_CC__
+ not a universal capable compiler
+ #endif
+ typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ # Check for potential -arch flags. It is not universal unless
+ # there are at least two -arch flags with different values.
+ ac_arch=
+ ac_prev=
+ for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+ if test -n "$ac_prev"; then
+ case $ac_word in
+ i?86 | x86_64 | ppc | ppc64)
+ if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+ ac_arch=$ac_word
+ else
+ ac_cv_c_bigendian=universal
+ break
+ fi
+ ;;
+ esac
+ ac_prev=
+ elif test "x$ac_word" = "x-arch"; then
+ ac_prev=arch
+ fi
+ done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if sys/param.h defines the BYTE_ORDER macro.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+ && LITTLE_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to _BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # Compile a test program.
+ if test "$cross_compiling" = yes; then :
+ # Try to guess by grepping values from an object file.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+short int ascii_mm[] =
+ { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+ short int ascii_ii[] =
+ { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+ int use_ascii (int i) {
+ return ascii_mm[i] + ascii_ii[i];
+ }
+ short int ebcdic_ii[] =
+ { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+ short int ebcdic_mm[] =
+ { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+ int use_ebcdic (int i) {
+ return ebcdic_mm[i] + ebcdic_ii[i];
+ }
+ extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+ ac_cv_c_bigendian=yes
+ fi
+ if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_c_bigendian=no
+else
+ ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+ yes)
+ $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+ no)
+ ;; #(
+ universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+ ;; #(
+ *)
+ as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+
+
+
+# Our old stuff. Doesn't work in all cases.
+# Checks for header files.
+#AC_CHECK_HEADERS([Xm/Xm.h],MOTIF_INC="yes", AC_MSG_ERROR(*** Cannot find Motif include files: Please install one of Motif/OpenMotif/Lesstif development packages. ***))
+
+
+# New stuff to check for Motif/Lesstif. Shamelessly borrowed from
+# the opendx project. Opendx in turn snarfed their test from AC_PATH_X.
+
+# Allow "--with-motif-includes" and "--with-motif-libs" so user can
+# force a specific set of includes.
+
+# Check whether --with-motif-includes was given.
+if test "${with_motif_includes+set}" = set; then :
+ withval=$with_motif_includes; with_motif_includes=$withval
+else
+ with_motif_includes=
+fi
+
+if test "$with_motif_includes" != "yes" && test -z "$with_motif_includes"
+then
+ with_motif_includes=
+fi
+
+
+# Check whether --with-motif-libs was given.
+if test "${with_motif_libs+set}" = set; then :
+ withval=$with_motif_libs; with_motif_libs=$withval
+else
+ with_motif_libs=
+fi
+
+if test "$with_motif_libs" != "yes" && test -z "$with_motif_libs"
+then
+ with_motif_libs=
+fi
+
+ # Guess where to find include files, by looking for this one Xm .h file.
+ test -z "$xm_direct_test_include" && xm_direct_test_include=Xm/Xm.h
+
+ # First, try using that file with no special directory specified.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Motif headers" >&5
+$as_echo_n "checking for Motif headers... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$xm_direct_test_include>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+ # We can compile using X headers with no special include directory.
+ xm_includes=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: in default path" >&5
+$as_echo "in default path" >&6; }
+
+else
+
+# that test didn't work, we need to hunt a little
+# Look for the header file in a standard set of common directories.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+ for ac_dir in \
+ /usr/X11/include \
+ /usr/X11R6/include \
+ /usr/X11R5/include \
+ /usr/X11R4/include \
+ \
+ /usr/include/X11 \
+ /usr/include/X11R6 \
+ /usr/include/X11R5 \
+ /usr/include/X11R4 \
+ \
+ /usr/local/X11/include \
+ /usr/local/X11R6/include \
+ /usr/local/X11R5/include \
+ /usr/local/X11R4/include \
+ \
+ /usr/local/include/X11 \
+ /usr/local/include/X11R6 \
+ /usr/local/include/X11R5 \
+ /usr/local/include/X11R4 \
+ \
+ /usr/X386/include \
+ /usr/x386/include \
+ /usr/XFree86/include/X11 \
+ \
+ /usr/include \
+ /usr/local/include \
+ /usr/unsupported/include \
+ /usr/athena/include \
+ /usr/local/x11r5/include \
+ /usr/lpp/Xamples/include \
+ \
+ /usr/openwin/include \
+ /usr/openwin/share/include \
+ "$with_motif_includes" \
+ ; \
+ do
+ if test -r "$ac_dir/$xm_direct_test_include"; then
+ xm_includes=$ac_dir
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: in $xm_includes" >&5
+$as_echo "in $xm_includes" >&6; }
+ break
+ fi
+ done
+ if test "x$xm_includes" = "x"; then
+ as_fn_error $? "**** NO MOTIF HEADERS FOUND **** install Motif development headers or use --with-motif-includes to specify location of Xm/Xm.h " "$LINENO" 5
+ fi
+
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+ # Check for the libraries.
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Motif libraries" >&5
+$as_echo_n "checking for Motif libraries... " >&6; }
+ test -z "$xm_direct_test_library" && xm_direct_test_library=Xm
+ test -z "$xm_direct_test_function" && xm_direct_test_function=XmGetDestination
+
+ # See if we find them without any special options.
+ # Don't add to $LIBS permanently.
+ ac_save_LIBS="$LIBS"
+ LIBS="-l$xm_direct_test_library $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+${xm_direct_test_function}()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ LIBS="$ac_save_LIBS"
+ # We can link Motif programs with no special library path.
+ xm_libraries=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: in default path" >&5
+$as_echo "in default path" >&6; }
+
+else
+
+ LIBS="$ac_save_LIBS"
+# First see if replacing the include by lib works.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+for ac_dir in `echo "$xm_includes" | sed s/include/lib/` \
+ /usr/X11/lib \
+ /usr/X11R6/lib \
+ /usr/X11R5/lib \
+ /usr/X11R4/lib \
+ \
+ /usr/lib/X11 \
+ /usr/lib/X11R6 \
+ /usr/lib/X11R5 \
+ /usr/lib/X11R4 \
+ \
+ /usr/local/X11/lib \
+ /usr/local/X11R6/lib \
+ /usr/local/X11R5/lib \
+ /usr/local/X11R4/lib \
+ \
+ /usr/local/lib/X11 \
+ /usr/local/lib/X11R6 \
+ /usr/local/lib/X11R5 \
+ /usr/local/lib/X11R4 \
+ \
+ /usr/X386/lib \
+ /usr/x386/lib \
+ /usr/XFree86/lib/X11 \
+ \
+ /usr/lib \
+ /usr/local/lib \
+ /usr/unsupported/lib \
+ /usr/athena/lib \
+ /usr/local/x11r5/lib \
+ /usr/lpp/Xamples/lib \
+ /lib/usr/lib/X11 \
+ \
+ /usr/openwin/lib \
+ /usr/openwin/share/lib \
+ "$with_motif_libs" \
+ ; \
+do
+ for ac_extension in a so sl; do
+ if test -r $ac_dir/lib${xm_direct_test_library}.$ac_extension; then
+ xm_libraries=$ac_dir
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: in $xm_libraries" >&5
+$as_echo "in $xm_libraries" >&6; }
+ break 2
+ fi
+ done
+done
+if test "x$xm_libraries" = "x"; then
+ as_fn_error $? "**** MOTIF LIBRARIES NOT FOUND **** Install Motif development headers/libraries or use --with-motif-libraries to specify path to libXm.a " "$LINENO" 5
+fi
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+if test "x$xm_includes" != "x" ; then
+ CFLAGS="$CFLAGS -I$xm_includes"
+ CPPFLAGS="$CPPFLAGS -I$xm_includes"
+fi
+if test "x$xm_libraries" != "x" ; then
+ LDFLAGS="-L$xm_libraries $LDFLAGS"
+fi
+
+
+
+
+
+#
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5
+$as_echo_n "checking for working alloca.h... " >&6; }
+if ${ac_cv_working_alloca_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <alloca.h>
+int
+main ()
+{
+char *p = (char *) alloca (2 * sizeof (int));
+ if (p) return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_working_alloca_h=yes
+else
+ ac_cv_working_alloca_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5
+$as_echo "$ac_cv_working_alloca_h" >&6; }
+if test $ac_cv_working_alloca_h = yes; then
+
+$as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5
+$as_echo_n "checking for alloca... " >&6; }
+if ${ac_cv_func_alloca_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+void *alloca (size_t);
+# endif
+# endif
+# endif
+# endif
+#endif
+
+int
+main ()
+{
+char *p = (char *) alloca (1);
+ if (p) return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_func_alloca_works=yes
+else
+ ac_cv_func_alloca_works=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5
+$as_echo "$ac_cv_func_alloca_works" >&6; }
+
+if test $ac_cv_func_alloca_works = yes; then
+
+$as_echo "#define HAVE_ALLOCA 1" >>confdefs.h
+
+else
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+# that cause trouble. Some versions do not even contain alloca or
+# contain a buggy version. If you still want to use their alloca,
+# use ar to extract alloca.o from them instead of compiling alloca.c.
+
+ALLOCA=\${LIBOBJDIR}alloca.$ac_objext
+
+$as_echo "#define C_ALLOCA 1" >>confdefs.h
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5
+$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; }
+if ${ac_cv_os_cray+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#if defined CRAY && ! defined CRAY2
+webecray
+#else
+wenotbecray
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "webecray" >/dev/null 2>&1; then :
+ ac_cv_os_cray=yes
+else
+ ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5
+$as_echo "$ac_cv_os_cray" >&6; }
+if test $ac_cv_os_cray = yes; then
+ for ac_func in _getb67 GETB67 getb67; do
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+
+cat >>confdefs.h <<_ACEOF
+#define CRAY_STACKSEG_END $ac_func
+_ACEOF
+
+ break
+fi
+
+ done
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5
+$as_echo_n "checking stack direction for C alloca... " >&6; }
+if ${ac_cv_c_stack_direction+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_c_stack_direction=0
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+}
+
+int
+main ()
+{
+ return find_stack_direction () < 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_c_stack_direction=1
+else
+ ac_cv_c_stack_direction=-1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5
+$as_echo "$ac_cv_c_stack_direction" >&6; }
+cat >>confdefs.h <<_ACEOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+_ACEOF
+
+
+fi
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+ as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5
+$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; }
+if eval \${$as_ac_Header+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main ()
+{
+if ((DIR *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$as_ac_Header=yes"
+else
+ eval "$as_ac_Header=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$as_ac_Header
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
+$as_echo_n "checking for library containing opendir... " >&6; }
+if ${ac_cv_search_opendir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char opendir ();
+int
+main ()
+{
+return opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' dir; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_opendir=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_opendir+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_opendir+:} false; then :
+
+else
+ ac_cv_search_opendir=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
+$as_echo "$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
+$as_echo_n "checking for library containing opendir... " >&6; }
+if ${ac_cv_search_opendir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char opendir ();
+int
+main ()
+{
+return opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' x; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_opendir=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_opendir+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_opendir+:} false; then :
+
+else
+ ac_cv_search_opendir=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
+$as_echo "$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5
+$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; }
+if ${ac_cv_header_sys_wait_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+
+int
+main ()
+{
+ int s;
+ wait (&s);
+ s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_sys_wait_h=yes
+else
+ ac_cv_header_sys_wait_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5
+$as_echo "$ac_cv_header_sys_wait_h" >&6; }
+if test $ac_cv_header_sys_wait_h = yes; then
+
+$as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
+
+fi
+
+for ac_header in argz.h arpa/inet.h fcntl.h libintl.h limits.h locale.h malloc.h math.h netdb.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in netinet/in.h nl_types.h stdarg.h stddef.h stdlib.h string.h strings.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in sys/file.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h signal.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in termios.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Checks for typedefs, structures, and compiler characteristics.
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
+$as_echo_n "checking for an ANSI C-conforming const... " >&6; }
+if ${ac_cv_c_const+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this. */
+ typedef int charset[2];
+ const charset cs;
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *pcpcc;
+ char **ppc;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ pcpcc = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++pcpcc;
+ ppc = (char**) pcpcc;
+ pcpcc = (char const *const *) ppc;
+ { /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ if (s) return 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ if (!foo) return 0;
+ }
+ return !cs[0] && !zero.x;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_const=yes
+else
+ ac_cv_c_const=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5
+$as_echo "$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+$as_echo "#define const /**/" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5
+$as_echo_n "checking for uid_t in sys/types.h... " >&6; }
+if ${ac_cv_type_uid_t+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "uid_t" >/dev/null 2>&1; then :
+ ac_cv_type_uid_t=yes
+else
+ ac_cv_type_uid_t=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5
+$as_echo "$ac_cv_type_uid_t" >&6; }
+if test $ac_cv_type_uid_t = no; then
+
+$as_echo "#define uid_t int" >>confdefs.h
+
+
+$as_echo "#define gid_t int" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if ${ac_cv_c_inline+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
+if test "x$ac_cv_type_pid_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5
+$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; }
+if ${ac_cv_header_time+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_time=yes
+else
+ ac_cv_header_time=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5
+$as_echo "$ac_cv_header_time" >&6; }
+if test $ac_cv_header_time = yes; then
+
+$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h
+
+fi
+
+#AC_STRUCT_TM
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5
+$as_echo_n "checking return type of signal handlers... " >&6; }
+if ${ac_cv_type_signal+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <signal.h>
+
+int
+main ()
+{
+return *(signal (0, 0)) (0) == 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_type_signal=int
+else
+ ac_cv_type_signal=void
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5
+$as_echo "$ac_cv_type_signal" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5
+$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
+if ${ac_cv_struct_tm+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm tm;
+ int *p = &tm.tm_sec;
+ return !p;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_struct_tm=time.h
+else
+ ac_cv_struct_tm=sys/time.h
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5
+$as_echo "$ac_cv_struct_tm" >&6; }
+if test $ac_cv_struct_tm = sys/time.h; then
+
+$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct tm" "tm_zone" "ac_cv_member_struct_tm_tm_zone" "#include <sys/types.h>
+#include <$ac_cv_struct_tm>
+
+"
+if test "x$ac_cv_member_struct_tm_tm_zone" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_TM_TM_ZONE 1
+_ACEOF
+
+
+fi
+
+if test "$ac_cv_member_struct_tm_tm_zone" = yes; then
+
+$as_echo "#define HAVE_TM_ZONE 1" >>confdefs.h
+
+else
+ ac_fn_c_check_decl "$LINENO" "tzname" "ac_cv_have_decl_tzname" "#include <time.h>
+"
+if test "x$ac_cv_have_decl_tzname" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_TZNAME $ac_have_decl
+_ACEOF
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tzname" >&5
+$as_echo_n "checking for tzname... " >&6; }
+if ${ac_cv_var_tzname+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <time.h>
+#if !HAVE_DECL_TZNAME
+extern char *tzname[];
+#endif
+
+int
+main ()
+{
+return tzname[0][0];
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_var_tzname=yes
+else
+ ac_cv_var_tzname=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_var_tzname" >&5
+$as_echo "$ac_cv_var_tzname" >&6; }
+ if test $ac_cv_var_tzname = yes; then
+
+$as_echo "#define HAVE_TZNAME 1" >>confdefs.h
+
+ fi
+fi
+
+
+#Some (Mac?) systems don't define this where it should be, so we kludge
+ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include <sys/types.h>
+#include <sys/socket.h>
+"
+if test "x$ac_cv_type_socklen_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_SOCKLEN_T 1
+_ACEOF
+
+
+fi
+
+
+# some BSD systems do not define sighandler_t, but rather sig_t
+ac_fn_c_check_type "$LINENO" "sighandler_t" "ac_cv_type_sighandler_t" "#include <signal.h>
+"
+if test "x$ac_cv_type_sighandler_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_SIGHANDLER_T 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_type "$LINENO" "sig_t" "ac_cv_type_sig_t" "#include <signal.h>
+"
+if test "x$ac_cv_type_sig_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_SIG_T 1
+_ACEOF
+
+
+fi
+
+
+# some BSD systems do not define sighandler_t, but rather sig_t
+ac_fn_c_check_type "$LINENO" "sigjmp_buf" "ac_cv_type_sigjmp_buf" "#include <setjmp.h>
+"
+if test "x$ac_cv_type_sigjmp_buf" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_SIGJMP_BUF 1
+_ACEOF
+
+
+fi
+
+
+#Force this into config.h.in
+
+
+
+# Check for tm_gmtoff in tm
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gmtoff in struct tm" >&5
+$as_echo_n "checking for gmtoff in struct tm... " >&6; }
+if ${ac_cv_tm_gmtoff+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <time.h>
+int
+main ()
+{
+struct tm tm; tm.tm_gmtoff;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_tm_gmtoff="yes"
+else
+ ac_cv_tm_gmtoff="no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_tm_gmtoff" >&5
+$as_echo "$ac_cv_tm_gmtoff" >&6; }
+test "$ac_cv_tm_gmtoff" != "no" &&
+$as_echo "#define HAVE_TM_GMTOFF /**/" >>confdefs.h
+
+
+# Checks for library functions.
+#
+for ac_header in vfork.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default"
+if test "x$ac_cv_header_vfork_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_VFORK_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_func in fork vfork
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test "x$ac_cv_func_fork" = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5
+$as_echo_n "checking for working fork... " >&6; }
+if ${ac_cv_func_fork_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_fork_works=cross
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* By Ruediger Kuhlmann. */
+ return fork () < 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_fork_works=yes
+else
+ ac_cv_func_fork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5
+$as_echo "$ac_cv_func_fork_works" >&6; }
+
+else
+ ac_cv_func_fork_works=$ac_cv_func_fork
+fi
+if test "x$ac_cv_func_fork_works" = xcross; then
+ case $host in
+ *-*-amigaos* | *-*-msdosdjgpp*)
+ # Override, as these systems have only a dummy fork() stub
+ ac_cv_func_fork_works=no
+ ;;
+ *)
+ ac_cv_func_fork_works=yes
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;}
+fi
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+if test "x$ac_cv_func_vfork" = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5
+$as_echo_n "checking for working vfork... " >&6; }
+if ${ac_cv_func_vfork_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_vfork_works=cross
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Thanks to Paul Eggert for this test. */
+$ac_includes_default
+#include <sys/wait.h>
+#ifdef HAVE_VFORK_H
+# include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+ argument registers are propagated back to the parent. The compiler
+ is told about this with #include <vfork.h>, but some compilers
+ (e.g. gcc -O) don't grok <vfork.h>. Test for this by using a
+ static variable whose address is put into a register that is
+ clobbered by the vfork. */
+static void
+#ifdef __cplusplus
+sparc_address_test (int arg)
+# else
+sparc_address_test (arg) int arg;
+#endif
+{
+ static pid_t child;
+ if (!child) {
+ child = vfork ();
+ if (child < 0) {
+ perror ("vfork");
+ _exit(2);
+ }
+ if (!child) {
+ arg = getpid();
+ write(-1, "", 0);
+ _exit (arg);
+ }
+ }
+}
+
+int
+main ()
+{
+ pid_t parent = getpid ();
+ pid_t child;
+
+ sparc_address_test (0);
+
+ child = vfork ();
+
+ if (child == 0) {
+ /* Here is another test for sparc vfork register problems. This
+ test uses lots of local variables, at least as many local
+ variables as main has allocated so far including compiler
+ temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris
+ 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should
+ reuse the register of parent for one of the local variables,
+ since it will think that parent can't possibly be used any more
+ in this routine. Assigning to the local variable will thus
+ munge parent in the parent process. */
+ pid_t
+ p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+ p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+ /* Convince the compiler that p..p7 are live; otherwise, it might
+ use the same hardware register for all 8 local variables. */
+ if (p != p1 || p != p2 || p != p3 || p != p4
+ || p != p5 || p != p6 || p != p7)
+ _exit(1);
+
+ /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent
+ from child file descriptors. If the child closes a descriptor
+ before it execs or exits, this munges the parent's descriptor
+ as well. Test for this by closing stdout in the child. */
+ _exit(close(fileno(stdout)) != 0);
+ } else {
+ int status;
+ struct stat st;
+
+ while (wait(&status) != child)
+ ;
+ return (
+ /* Was there some problem with vforking? */
+ child < 0
+
+ /* Did the child fail? (This shouldn't happen.) */
+ || status
+
+ /* Did the vfork/compiler bug occur? */
+ || parent != getpid()
+
+ /* Did the file descriptor bug occur? */
+ || fstat(fileno(stdout), &st) != 0
+ );
+ }
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_vfork_works=yes
+else
+ ac_cv_func_vfork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5
+$as_echo "$ac_cv_func_vfork_works" >&6; }
+
+fi;
+if test "x$ac_cv_func_fork_works" = xcross; then
+ ac_cv_func_vfork_works=$ac_cv_func_vfork
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;}
+fi
+
+if test "x$ac_cv_func_vfork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h
+
+else
+
+$as_echo "#define vfork fork" >>confdefs.h
+
+fi
+if test "x$ac_cv_func_fork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h
+
+fi
+
+if test $ac_cv_c_compiler_gnu = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5
+$as_echo_n "checking whether $CC needs -traditional... " >&6; }
+if ${ac_cv_prog_gcc_traditional+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_pattern="Autoconf.*'x'"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then :
+ ac_cv_prog_gcc_traditional=yes
+else
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then :
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5
+$as_echo "$ac_cv_prog_gcc_traditional" >&6; }
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether getpgrp requires zero arguments" >&5
+$as_echo_n "checking whether getpgrp requires zero arguments... " >&6; }
+if ${ac_cv_func_getpgrp_void+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Use it with a single arg.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+getpgrp (0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_func_getpgrp_void=no
+else
+ ac_cv_func_getpgrp_void=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getpgrp_void" >&5
+$as_echo "$ac_cv_func_getpgrp_void" >&6; }
+if test $ac_cv_func_getpgrp_void = yes; then
+
+$as_echo "#define GETPGRP_VOID 1" >>confdefs.h
+
+fi
+
+for ac_header in stdlib.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_stdlib_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_STDLIB_H 1
+_ACEOF
+
+fi
+
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5
+$as_echo_n "checking for GNU libc compatible malloc... " >&6; }
+if ${ac_cv_func_malloc_0_nonnull+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_malloc_0_nonnull=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#if defined STDC_HEADERS || defined HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *malloc ();
+#endif
+
+int
+main ()
+{
+return ! malloc (0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_malloc_0_nonnull=yes
+else
+ ac_cv_func_malloc_0_nonnull=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5
+$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; }
+if test $ac_cv_func_malloc_0_nonnull = yes; then :
+
+$as_echo "#define HAVE_MALLOC 1" >>confdefs.h
+
+else
+ $as_echo "#define HAVE_MALLOC 0" >>confdefs.h
+
+ case " $LIBOBJS " in
+ *" malloc.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS malloc.$ac_objext"
+ ;;
+esac
+
+
+$as_echo "#define malloc rpl_malloc" >>confdefs.h
+
+fi
+
+
+
+
+
+ for ac_header in $ac_header_list
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+
+
+ for ac_func in $ac_func_list
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working mktime" >&5
+$as_echo_n "checking for working mktime... " >&6; }
+if ${ac_cv_func_working_mktime+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_working_mktime=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Test program from Paul Eggert and Tony Leneis. */
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include <limits.h>
+#include <stdlib.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifndef HAVE_ALARM
+# define alarm(X) /* empty */
+#endif
+
+/* Work around redefinition to rpl_putenv by other config tests. */
+#undef putenv
+
+static time_t time_t_max;
+static time_t time_t_min;
+
+/* Values we'll use to set the TZ environment variable. */
+static const char *tz_strings[] = {
+ (const char *) 0, "TZ=GMT0", "TZ=JST-9",
+ "TZ=EST+3EDT+2,M10.1.0/00:00:00,M2.3.0/00:00:00"
+};
+#define N_STRINGS (sizeof (tz_strings) / sizeof (tz_strings[0]))
+
+/* Return 0 if mktime fails to convert a date in the spring-forward gap.
+ Based on a problem report from Andreas Jaeger. */
+static int
+spring_forward_gap ()
+{
+ /* glibc (up to about 1998-10-07) failed this test. */
+ struct tm tm;
+
+ /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0"
+ instead of "TZ=America/Vancouver" in order to detect the bug even
+ on systems that don't support the Olson extension, or don't have the
+ full zoneinfo tables installed. */
+ putenv ((char*) "TZ=PST8PDT,M4.1.0,M10.5.0");
+
+ tm.tm_year = 98;
+ tm.tm_mon = 3;
+ tm.tm_mday = 5;
+ tm.tm_hour = 2;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ tm.tm_isdst = -1;
+ return mktime (&tm) != (time_t) -1;
+}
+
+static int
+mktime_test1 (time_t now)
+{
+ struct tm *lt;
+ return ! (lt = localtime (&now)) || mktime (lt) == now;
+}
+
+static int
+mktime_test (time_t now)
+{
+ return (mktime_test1 (now)
+ && mktime_test1 ((time_t) (time_t_max - now))
+ && mktime_test1 ((time_t) (time_t_min + now)));
+}
+
+static int
+irix_6_4_bug ()
+{
+ /* Based on code from Ariel Faigon. */
+ struct tm tm;
+ tm.tm_year = 96;
+ tm.tm_mon = 3;
+ tm.tm_mday = 0;
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ tm.tm_isdst = -1;
+ mktime (&tm);
+ return tm.tm_mon == 2 && tm.tm_mday == 31;
+}
+
+static int
+bigtime_test (int j)
+{
+ struct tm tm;
+ time_t now;
+ tm.tm_year = tm.tm_mon = tm.tm_mday = tm.tm_hour = tm.tm_min = tm.tm_sec = j;
+ now = mktime (&tm);
+ if (now != (time_t) -1)
+ {
+ struct tm *lt = localtime (&now);
+ if (! (lt
+ && lt->tm_year == tm.tm_year
+ && lt->tm_mon == tm.tm_mon
+ && lt->tm_mday == tm.tm_mday
+ && lt->tm_hour == tm.tm_hour
+ && lt->tm_min == tm.tm_min
+ && lt->tm_sec == tm.tm_sec
+ && lt->tm_yday == tm.tm_yday
+ && lt->tm_wday == tm.tm_wday
+ && ((lt->tm_isdst < 0 ? -1 : 0 < lt->tm_isdst)
+ == (tm.tm_isdst < 0 ? -1 : 0 < tm.tm_isdst))))
+ return 0;
+ }
+ return 1;
+}
+
+static int
+year_2050_test ()
+{
+ /* The correct answer for 2050-02-01 00:00:00 in Pacific time,
+ ignoring leap seconds. */
+ unsigned long int answer = 2527315200UL;
+
+ struct tm tm;
+ time_t t;
+ tm.tm_year = 2050 - 1900;
+ tm.tm_mon = 2 - 1;
+ tm.tm_mday = 1;
+ tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
+ tm.tm_isdst = -1;
+
+ /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0"
+ instead of "TZ=America/Vancouver" in order to detect the bug even
+ on systems that don't support the Olson extension, or don't have the
+ full zoneinfo tables installed. */
+ putenv ((char*) "TZ=PST8PDT,M4.1.0,M10.5.0");
+
+ t = mktime (&tm);
+
+ /* Check that the result is either a failure, or close enough
+ to the correct answer that we can assume the discrepancy is
+ due to leap seconds. */
+ return (t == (time_t) -1
+ || (0 < t && answer - 120 <= t && t <= answer + 120));
+}
+
+int
+main ()
+{
+ time_t t, delta;
+ int i, j;
+
+ /* This test makes some buggy mktime implementations loop.
+ Give up after 60 seconds; a mktime slower than that
+ isn't worth using anyway. */
+ alarm (60);
+
+ for (;;)
+ {
+ t = (time_t_max << 1) + 1;
+ if (t <= time_t_max)
+ break;
+ time_t_max = t;
+ }
+ time_t_min = - ((time_t) ~ (time_t) 0 == (time_t) -1) - time_t_max;
+
+ delta = time_t_max / 997; /* a suitable prime number */
+ for (i = 0; i < N_STRINGS; i++)
+ {
+ if (tz_strings[i])
+ putenv ((char*) tz_strings[i]);
+
+ for (t = 0; t <= time_t_max - delta; t += delta)
+ if (! mktime_test (t))
+ return 1;
+ if (! (mktime_test ((time_t) 1)
+ && mktime_test ((time_t) (60 * 60))
+ && mktime_test ((time_t) (60 * 60 * 24))))
+ return 1;
+
+ for (j = 1; ; j <<= 1)
+ if (! bigtime_test (j))
+ return 1;
+ else if (INT_MAX / 2 < j)
+ break;
+ if (! bigtime_test (INT_MAX))
+ return 1;
+ }
+ return ! (irix_6_4_bug () && spring_forward_gap () && year_2050_test ());
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_working_mktime=yes
+else
+ ac_cv_func_working_mktime=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_working_mktime" >&5
+$as_echo "$ac_cv_func_working_mktime" >&6; }
+if test $ac_cv_func_working_mktime = no; then
+ case " $LIBOBJS " in
+ *" mktime.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS mktime.$ac_objext"
+ ;;
+esac
+
+fi
+
+
+
+
+
+
+for ac_func in getpagesize
+do :
+ ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize"
+if test "x$ac_cv_func_getpagesize" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GETPAGESIZE 1
+_ACEOF
+
+fi
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working mmap" >&5
+$as_echo_n "checking for working mmap... " >&6; }
+if ${ac_cv_func_mmap_fixed_mapped+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_mmap_fixed_mapped=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+/* malloc might have been renamed as rpl_malloc. */
+#undef malloc
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+ Here is a matrix of mmap possibilities:
+ mmap private not fixed
+ mmap private fixed at somewhere currently unmapped
+ mmap private fixed at somewhere already mapped
+ mmap shared not fixed
+ mmap shared fixed at somewhere currently unmapped
+ mmap shared fixed at somewhere already mapped
+ For private mappings, we should verify that changes cannot be read()
+ back from the file, nor mmap's back from the file at a different
+ address. (There have been systems where private was not correctly
+ implemented like the infamous i386 svr4.0, and systems where the
+ VM page cache was not coherent with the file system buffer cache
+ like early versions of FreeBSD and possibly contemporary NetBSD.)
+ For shared mappings, we should conversely verify that changes get
+ propagated back to all the places they're supposed to be.
+
+ Grep wants private fixed already mapped.
+ The main things grep needs to know about mmap are:
+ * does it exist and is it safe to write into the mmap'd area
+ * how to use it (BSD variants) */
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#if !defined STDC_HEADERS && !defined HAVE_STDLIB_H
+char *malloc ();
+#endif
+
+/* This mess was copied from the GNU getpagesize.h. */
+#ifndef HAVE_GETPAGESIZE
+# ifdef _SC_PAGESIZE
+# define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+# ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else /* no EXEC_PAGESIZE */
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif /* no CLSIZE */
+# else /* no NBPG */
+# ifdef NBPC
+# define getpagesize() NBPC
+# else /* no NBPC */
+# ifdef PAGESIZE
+# define getpagesize() PAGESIZE
+# endif /* PAGESIZE */
+# endif /* no NBPC */
+# endif /* no NBPG */
+# endif /* no EXEC_PAGESIZE */
+# else /* no HAVE_SYS_PARAM_H */
+# define getpagesize() 8192 /* punt totally */
+# endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+int
+main ()
+{
+ char *data, *data2, *data3;
+ const char *cdata2;
+ int i, pagesize;
+ int fd, fd2;
+
+ pagesize = getpagesize ();
+
+ /* First, make a file with some known garbage in it. */
+ data = (char *) malloc (pagesize);
+ if (!data)
+ return 1;
+ for (i = 0; i < pagesize; ++i)
+ *(data + i) = rand ();
+ umask (0);
+ fd = creat ("conftest.mmap", 0600);
+ if (fd < 0)
+ return 2;
+ if (write (fd, data, pagesize) != pagesize)
+ return 3;
+ close (fd);
+
+ /* Next, check that the tail of a page is zero-filled. File must have
+ non-zero length, otherwise we risk SIGBUS for entire page. */
+ fd2 = open ("conftest.txt", O_RDWR | O_CREAT | O_TRUNC, 0600);
+ if (fd2 < 0)
+ return 4;
+ cdata2 = "";
+ if (write (fd2, cdata2, 1) != 1)
+ return 5;
+ data2 = (char *) mmap (0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0L);
+ if (data2 == MAP_FAILED)
+ return 6;
+ for (i = 0; i < pagesize; ++i)
+ if (*(data2 + i))
+ return 7;
+ close (fd2);
+ if (munmap (data2, pagesize))
+ return 8;
+
+ /* Next, try to mmap the file at a fixed address which already has
+ something else allocated at it. If we can, also make sure that
+ we see the same garbage. */
+ fd = open ("conftest.mmap", O_RDWR);
+ if (fd < 0)
+ return 9;
+ if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED, fd, 0L))
+ return 10;
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data2 + i))
+ return 11;
+
+ /* Finally, make sure that changes to the mapped area do not
+ percolate back to the file as seen by read(). (This is a bug on
+ some variants of i386 svr4.0.) */
+ for (i = 0; i < pagesize; ++i)
+ *(data2 + i) = *(data2 + i) + 1;
+ data3 = (char *) malloc (pagesize);
+ if (!data3)
+ return 12;
+ if (read (fd, data3, pagesize) != pagesize)
+ return 13;
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data3 + i))
+ return 14;
+ close (fd);
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_mmap_fixed_mapped=yes
+else
+ ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_fixed_mapped" >&5
+$as_echo "$ac_cv_func_mmap_fixed_mapped" >&6; }
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+
+$as_echo "#define HAVE_MMAP 1" >>confdefs.h
+
+fi
+rm -f conftest.mmap conftest.txt
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lstat correctly handles trailing slash" >&5
+$as_echo_n "checking whether lstat correctly handles trailing slash... " >&6; }
+if ${ac_cv_func_lstat_dereferences_slashed_symlink+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ rm -f conftest.sym conftest.file
+echo >conftest.file
+if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_lstat_dereferences_slashed_symlink=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+ /* Linux will dereference the symlink and fail, as required by POSIX.
+ That is better in the sense that it means we will not
+ have to compile and use the lstat wrapper. */
+ return lstat ("conftest.sym/", &sbuf) == 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_lstat_dereferences_slashed_symlink=yes
+else
+ ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+else
+ # If the `ln -s' command failed, then we probably don't even
+ # have an lstat function.
+ ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f conftest.sym conftest.file
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5
+$as_echo "$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; }
+
+test $ac_cv_func_lstat_dereferences_slashed_symlink = yes &&
+
+cat >>confdefs.h <<_ACEOF
+#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+_ACEOF
+
+
+if test "x$ac_cv_func_lstat_dereferences_slashed_symlink" = xno; then
+ case " $LIBOBJS " in
+ *" lstat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS lstat.$ac_objext"
+ ;;
+esac
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat accepts an empty string" >&5
+$as_echo_n "checking whether stat accepts an empty string... " >&6; }
+if ${ac_cv_func_stat_empty_string_bug+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_stat_empty_string_bug=yes
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+ return stat ("", &sbuf) == 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_stat_empty_string_bug=no
+else
+ ac_cv_func_stat_empty_string_bug=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_stat_empty_string_bug" >&5
+$as_echo "$ac_cv_func_stat_empty_string_bug" >&6; }
+if test $ac_cv_func_stat_empty_string_bug = yes; then
+ case " $LIBOBJS " in
+ *" stat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS stat.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STAT_EMPTY_STRING_BUG 1
+_ACEOF
+
+fi
+
+for ac_func in strftime
+do :
+ ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime"
+if test "x$ac_cv_func_strftime" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_STRFTIME 1
+_ACEOF
+
+else
+ # strftime is in -lintl on SCO UNIX.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5
+$as_echo_n "checking for strftime in -lintl... " >&6; }
+if ${ac_cv_lib_intl_strftime+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lintl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char strftime ();
+int
+main ()
+{
+return strftime ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_intl_strftime=yes
+else
+ ac_cv_lib_intl_strftime=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5
+$as_echo "$ac_cv_lib_intl_strftime" >&6; }
+if test "x$ac_cv_lib_intl_strftime" = xyes; then :
+ $as_echo "#define HAVE_STRFTIME 1" >>confdefs.h
+
+LIBS="-lintl $LIBS"
+fi
+
+fi
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working strtod" >&5
+$as_echo_n "checking for working strtod... " >&6; }
+if ${ac_cv_func_strtod+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_strtod=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+$ac_includes_default
+#ifndef strtod
+double strtod ();
+#endif
+int
+main()
+{
+ {
+ /* Some versions of Linux strtod mis-parse strings with leading '+'. */
+ char *string = " +69";
+ char *term;
+ double value;
+ value = strtod (string, &term);
+ if (value != 69 || term != (string + 4))
+ return 1;
+ }
+
+ {
+ /* Under Solaris 2.4, strtod returns the wrong value for the
+ terminating character under some conditions. */
+ char *string = "NaN";
+ char *term;
+ strtod (string, &term);
+ if (term != string && *(term - 1) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_strtod=yes
+else
+ ac_cv_func_strtod=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strtod" >&5
+$as_echo "$ac_cv_func_strtod" >&6; }
+if test $ac_cv_func_strtod = no; then
+ case " $LIBOBJS " in
+ *" strtod.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strtod.$ac_objext"
+ ;;
+esac
+
+ac_fn_c_check_func "$LINENO" "pow" "ac_cv_func_pow"
+if test "x$ac_cv_func_pow" = xyes; then :
+
+fi
+
+if test $ac_cv_func_pow = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pow in -lm" >&5
+$as_echo_n "checking for pow in -lm... " >&6; }
+if ${ac_cv_lib_m_pow+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pow ();
+int
+main ()
+{
+return pow ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_m_pow=yes
+else
+ ac_cv_lib_m_pow=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_pow" >&5
+$as_echo "$ac_cv_lib_m_pow" >&6; }
+if test "x$ac_cv_lib_m_pow" = xyes; then :
+ POW_LIB=-lm
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot find library containing definition of pow" >&5
+$as_echo "$as_me: WARNING: cannot find library containing definition of pow" >&2;}
+fi
+
+fi
+
+fi
+
+for ac_func in __argz_count __argz_next __argz_stringify alarm dcgettext
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+for ac_func in getcwd getpgrp gethostbyname gethostname gettimeofday
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+for ac_func in getwd inet_ntoa memmove mempcpy memset mkdir munmap pow
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+for ac_func in putenv select setenv setlocale settimeofday signal sigignore
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+for ac_func in snprintf socket sqrt stpcpy strcasecmp strchr strdup
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+for ac_func in strerror strncasecmp strpbrk strptime strrchr strstr
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+for ac_func in strtof strtol strtoul tzset vsnprintf
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+# Check for deprecated/current pthread functions
+for ac_func in pthread_mutexattr_setkind_np pthread_mutexattr_settype
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+# this is a GNU extension and not present on all systems.
+for ac_func in strndup
+do :
+ ac_fn_c_check_func "$LINENO" "strndup" "ac_cv_func_strndup"
+if test "x$ac_cv_func_strndup" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_STRNDUP 1
+_ACEOF
+
+fi
+done
+
+
+#this is also a recent extension that should not be counted on
+for ac_func in roundf
+do :
+ ac_fn_c_check_func "$LINENO" "roundf" "ac_cv_func_roundf"
+if test "x$ac_cv_func_roundf" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_ROUNDF 1
+_ACEOF
+
+fi
+done
+
+
+# Check for intl library (Needed for Cygwin)
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gettext in -lintl" >&5
+$as_echo_n "checking for gettext in -lintl... " >&6; }
+if ${ac_cv_lib_intl_gettext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lintl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gettext ();
+int
+main ()
+{
+return gettext ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_intl_gettext=yes
+else
+ ac_cv_lib_intl_gettext=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_gettext" >&5
+$as_echo "$ac_cv_lib_intl_gettext" >&6; }
+if test "x$ac_cv_lib_intl_gettext" = xyes; then :
+ LIBS="-lintl ${LIBS}"
+fi
+
+
+# Check for libproj (need to do this before test for shapelib, because
+# the shapelib test asks about "use_proj"
+use_proj=yes
+
+# Check whether --with-libproj was given.
+if test "${with_libproj+set}" = set; then :
+ withval=$with_libproj; use_proj=$withval
+fi
+
+if test "${use_proj}" = "yes"; then
+ use_proj=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pj_init in -lproj" >&5
+$as_echo_n "checking for pj_init in -lproj... " >&6; }
+if ${ac_cv_lib_proj_pj_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lproj $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pj_init ();
+int
+main ()
+{
+return pj_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_proj_pj_init=yes
+else
+ ac_cv_lib_proj_pj_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_proj_pj_init" >&5
+$as_echo "$ac_cv_lib_proj_pj_init" >&6; }
+if test "x$ac_cv_lib_proj_pj_init" = xyes; then :
+ use_proj=yes LIBS="$LIBS -lproj"
+
+$as_echo "#define HAVE_PROJ /**/" >>confdefs.h
+
+
+fi
+
+fi
+
+
+# Check for Shapelib
+use_shapelib=yes
+force_internal_shapelib=no
+shapelib_desired=yes
+LIBSHP=""
+SUBSHP=""
+# This symbol will be blank if the proj library hasn't been found, and will
+# have the three programs that need proj if it has
+CONTSHP=""
+
+# Check whether --with-internal-shapelib was given.
+if test "${with_internal_shapelib+set}" = set; then :
+ withval=$with_internal_shapelib; force_internal_shapelib=$withval
+fi
+
+
+# Check whether --with-shapelib was given.
+if test "${with_shapelib+set}" = set; then :
+ withval=$with_shapelib; shapelib_desired=$withval
+fi
+
+if test "${shapelib_desired}" = "no"; then
+ use_shapelib=no
+ force_internal_shapelib=no
+fi
+if test "${force_internal_shapelib}" = "yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ***************************************************************** " >&5
+$as_echo "$as_me: WARNING: ***************************************************************** " >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Internal Shapelib library has been forced. " >&5
+$as_echo "$as_me: WARNING: Internal Shapelib library has been forced. " >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ***************************************************************** " >&5
+$as_echo "$as_me: WARNING: ***************************************************************** " >&2;}
+ # Temporary setting to get into if block below
+ use_shapelib=no
+fi
+if test "${shapelib_desired}" = "yes" -a "${force_internal_shapelib}" = "no"; then
+ use_shapelib=no
+ for ac_header in shapefil.h libshp/shapefil.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DBFOpen in -lshp" >&5
+$as_echo_n "checking for DBFOpen in -lshp... " >&6; }
+if ${ac_cv_lib_shp_DBFOpen+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lshp $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char DBFOpen ();
+int
+main ()
+{
+return DBFOpen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_shp_DBFOpen=yes
+else
+ ac_cv_lib_shp_DBFOpen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_shp_DBFOpen" >&5
+$as_echo "$ac_cv_lib_shp_DBFOpen" >&6; }
+if test "x$ac_cv_lib_shp_DBFOpen" = xyes; then :
+ use_shapelib=yes
+ LIBS="$LIBS -lshp"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DBFGetFieldIndex in -lshp" >&5
+$as_echo_n "checking for DBFGetFieldIndex in -lshp... " >&6; }
+if ${ac_cv_lib_shp_DBFGetFieldIndex+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lshp $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char DBFGetFieldIndex ();
+int
+main ()
+{
+return DBFGetFieldIndex ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_shp_DBFGetFieldIndex=yes
+else
+ ac_cv_lib_shp_DBFGetFieldIndex=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_shp_DBFGetFieldIndex" >&5
+$as_echo "$ac_cv_lib_shp_DBFGetFieldIndex" >&6; }
+if test "x$ac_cv_lib_shp_DBFGetFieldIndex" = xyes; then :
+
+$as_echo "#define HAVE_DBFGETFIELDINDEX /**/" >>confdefs.h
+
+fi
+
+
+$as_echo "#define HAVE_LIBSHP /**/" >>confdefs.h
+
+ break
+fi
+
+fi
+
+done
+
+fi
+if test "${shapelib_desired}" = "yes" -a "${use_shapelib}" = "no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: **************************************************************** " >&5
+$as_echo "$as_me: WARNING: **************************************************************** " >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Your system does not have shapelib installed. Using an internal " >&5
+$as_echo "$as_me: WARNING: Your system does not have shapelib installed. Using an internal " >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: version. This may lead to a larger filesize for the executable. " >&5
+$as_echo "$as_me: WARNING: version. This may lead to a larger filesize for the executable. " >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Install shapelib on your system to eliminate this warning. " >&5
+$as_echo "$as_me: WARNING: Install shapelib on your system to eliminate this warning. " >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: **************************************************************** " >&5
+$as_echo "$as_me: WARNING: **************************************************************** " >&2;}
+ LIBSHP="-Lshapelib -lshape"
+ CPPFLAGS="-I\$(top_srcdir)/src/shapelib $CPPFLAGS"
+ SUBSHP="shapelib"
+ use_shapelib=yes
+ force_internal_shapelib=yes
+
+$as_echo "#define HAVE_DBFGETFIELDINDEX /**/" >>confdefs.h
+
+
+$as_echo "#define HAVE_LIBSHP /**/" >>confdefs.h
+
+
+$as_echo "#define HAVE_SHAPEFIL_H /**/" >>confdefs.h
+
+
+ if test $use_proj = "yes"
+ then
+ CONTSHP="shpcentrd shpproj shpdata shpwkb"
+ fi
+fi
+
+
+
+
+
+# Check for pcre
+use_pcre=yes
+
+# Check whether --with-pcre was given.
+if test "${with_pcre+set}" = set; then :
+ withval=$with_pcre; use_pcre=$withval
+fi
+
+if test "${use_pcre}" = "yes"; then
+ use_pcre=no
+ for ac_header in pcre.h pcre/pcre.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre_compile in -lpcre" >&5
+$as_echo_n "checking for pcre_compile in -lpcre... " >&6; }
+if ${ac_cv_lib_pcre_pcre_compile+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpcre $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pcre_compile ();
+int
+main ()
+{
+return pcre_compile ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pcre_pcre_compile=yes
+else
+ ac_cv_lib_pcre_pcre_compile=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcre_pcre_compile" >&5
+$as_echo "$ac_cv_lib_pcre_pcre_compile" >&6; }
+if test "x$ac_cv_lib_pcre_pcre_compile" = xyes; then :
+ use_pcre=yes
+ LIBS="$LIBS -lpcre"
+
+$as_echo "#define HAVE_LIBPCRE /**/" >>confdefs.h
+
+ break
+fi
+
+fi
+
+done
+
+fi
+
+
+# Check for XPM
+if test "${use_lsb}" = "no"; then
+ for ac_header in X11/xpm.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "X11/xpm.h" "ac_cv_header_X11_xpm_h" "$ac_includes_default"
+if test "x$ac_cv_header_X11_xpm_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_X11_XPM_H 1
+_ACEOF
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing XpmWriteFileFromPixmap" >&5
+$as_echo_n "checking for library containing XpmWriteFileFromPixmap... " >&6; }
+if ${ac_cv_search_XpmWriteFileFromPixmap+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XpmWriteFileFromPixmap ();
+int
+main ()
+{
+return XpmWriteFileFromPixmap ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' Xpm; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_XpmWriteFileFromPixmap=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_XpmWriteFileFromPixmap+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_XpmWriteFileFromPixmap+:} false; then :
+
+else
+ ac_cv_search_XpmWriteFileFromPixmap=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_XpmWriteFileFromPixmap" >&5
+$as_echo "$ac_cv_search_XpmWriteFileFromPixmap" >&6; }
+ac_res=$ac_cv_search_XpmWriteFileFromPixmap
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_LIBXPM /**/" >>confdefs.h
+
+fi
+
+fi
+
+done
+
+ for ac_header in Xm/XpmI.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "Xm/XpmI.h" "ac_cv_header_Xm_XpmI_h" "$ac_includes_default"
+if test "x$ac_cv_header_Xm_XpmI_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_XM_XPMI_H 1
+_ACEOF
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing XmeXpmWriteFileFromPixmap" >&5
+$as_echo_n "checking for library containing XmeXpmWriteFileFromPixmap... " >&6; }
+if ${ac_cv_search_XmeXpmWriteFileFromPixmap+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XmeXpmWriteFileFromPixmap ();
+int
+main ()
+{
+return XmeXpmWriteFileFromPixmap ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' Xm; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_XmeXpmWriteFileFromPixmap=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_XmeXpmWriteFileFromPixmap+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_XmeXpmWriteFileFromPixmap+:} false; then :
+
+else
+ ac_cv_search_XmeXpmWriteFileFromPixmap=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_XmeXpmWriteFileFromPixmap" >&5
+$as_echo "$ac_cv_search_XmeXpmWriteFileFromPixmap" >&6; }
+ac_res=$ac_cv_search_XmeXpmWriteFileFromPixmap
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_LIBXPM_IN_XM /**/" >>confdefs.h
+
+fi
+
+fi
+
+done
+
+else
+
+$as_echo "#define HAVE_LIBXPM /**/" >>confdefs.h
+
+
+$as_echo "#define HAVE_LIBXPM_IN_XM /**/" >>confdefs.h
+
+
+$as_echo "#define HAVE_X11_XPM_H /**/" >>confdefs.h
+
+fi
+
+
+#check for libtiff, libgeotiff
+# libjpeg.a and libz.a need to be compiled under LSB
+
+
+use_geotiff=yes
+
+# Check whether --with-geotiff was given.
+if test "${with_geotiff+set}" = set; then :
+ withval=$with_geotiff; use_geotiff=$withval
+fi
+
+if test "${use_geotiff}" = "yes"; then
+ if test "${use_proj}" = "yes" ; then
+ if test "${use_lsb}" = "yes" ; then
+ use_tiff=yes
+ use_geotiff=yes
+ LIBS="$LIBS -lgeotiff -ltiff -ljpeg -lz -lproj"
+
+$as_echo "#define HAVE_TIFF /**/" >>confdefs.h
+
+
+$as_echo "#define HAVE_LIBGEOTIFF /**/" >>confdefs.h
+
+ else
+ ac_fn_c_check_header_mongrel "$LINENO" "xtiffio.h" "ac_cv_header_xtiffio_h" "$ac_includes_default"
+if test "x$ac_cv_header_xtiffio_h" = xyes; then :
+
+else
+ use_geotiff="no"
+fi
+
+
+ if test "${use_geotiff}" = "yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TIFFClose in -ltiff" >&5
+$as_echo_n "checking for TIFFClose in -ltiff... " >&6; }
+if ${ac_cv_lib_tiff_TIFFClose+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ltiff $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char TIFFClose ();
+int
+main ()
+{
+return TIFFClose ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_tiff_TIFFClose=yes
+else
+ ac_cv_lib_tiff_TIFFClose=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tiff_TIFFClose" >&5
+$as_echo "$ac_cv_lib_tiff_TIFFClose" >&6; }
+if test "x$ac_cv_lib_tiff_TIFFClose" = xyes; then :
+ use_tiff=yes
+ LIBS="$LIBS -ltiff"
+
+$as_echo "#define HAVE_TIFF /**/" >>confdefs.h
+
+fi
+
+ if test "${use_tiff}" = "yes"; then
+ use_geotiff=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTIFNew in -lgeotiff" >&5
+$as_echo_n "checking for GTIFNew in -lgeotiff... " >&6; }
+if ${ac_cv_lib_geotiff_GTIFNew+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgeotiff $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char GTIFNew ();
+int
+main ()
+{
+return GTIFNew ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_geotiff_GTIFNew=yes
+else
+ ac_cv_lib_geotiff_GTIFNew=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_geotiff_GTIFNew" >&5
+$as_echo "$ac_cv_lib_geotiff_GTIFNew" >&6; }
+if test "x$ac_cv_lib_geotiff_GTIFNew" = xyes; then :
+ use_geotiff=yes
+ LIBS="$LIBS -lgeotiff"
+
+$as_echo "#define HAVE_LIBGEOTIFF /**/" >>confdefs.h
+
+fi
+
+ else
+ echo "*** Warning: geotiff requires libtiff."
+ use_geotiff=no
+ fi
+ else
+ echo "*** Warning: geotiff include files not found."
+ fi
+ fi
+ else
+ echo "*** Warning: geotiff requires libproj."
+ use_geotiff=no
+ fi
+fi
+
+# Check for spatial database support
+use_postgis=no
+
+# Check whether --with-postgis was given.
+if test "${with_postgis+set}" = set; then :
+ withval=$with_postgis; use_postgis=$withval
+fi
+
+if test "${use_postgis}" != "no"; then
+
+BINPATH="${PATH}${EXTRA_BIN_PATH}"
+# test for postgresql
+if test "${with_postgis+set}" = set; then
+ PG_CONFIG="pg_config"
+ if test "$with_postgis" != "yes"; then
+ # get path if provided
+ pg_path="$with_postgis"
+ PG_CONFIG_PATH="${pg_path}/bin"
+ BINPATH="${BINPATH}:${PG_CONFIG_PATH}"
+ POSTGIS_LIB_DIR="-L${pg_path}/lib"
+ # Extract the first word of "pg_config", so it can be a program name with args.
+set dummy pg_config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PG_CONFIG="$PG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PG_CONFIG_PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_PG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_PG_CONFIG" && ac_cv_path_PG_CONFIG="no"
+ ;;
+esac
+fi
+PG_CONFIG=$ac_cv_path_PG_CONFIG
+if test -n "$PG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PG_CONFIG" >&5
+$as_echo "$PG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ else
+ # Extract the first word of "pg_config", so it can be a program name with args.
+set dummy pg_config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PG_CONFIG="$PG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_PG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_PG_CONFIG" && ac_cv_path_PG_CONFIG="no"
+ ;;
+esac
+fi
+PG_CONFIG=$ac_cv_path_PG_CONFIG
+if test -n "$PG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PG_CONFIG" >&5
+$as_echo "$PG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+ if test "$PG_CONFIG" != "no"; then
+ # Check for postgis spatial extensions.
+ # Look for lwpostgis.sql script in default location.
+ # If found, is likely a postgis installation.
+ # Need more definitive test for postgis, as this may fail to detect postgres
+ # installations where this script was removed, and will incorrectly
+ # detect postgres without postgis where this script has been installed but not run.
+ # Extract the first word of "lwpostgis.sql", so it can be a program name with args.
+set dummy lwpostgis.sql; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_LWPOSTGIS+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $LWPOSTGIS in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_LWPOSTGIS="$LWPOSTGIS" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in "${pg_path}/share"
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_LWPOSTGIS="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_LWPOSTGIS" && ac_cv_path_LWPOSTGIS="no"
+ ;;
+esac
+fi
+LWPOSTGIS=$ac_cv_path_LWPOSTGIS
+if test -n "$LWPOSTGIS"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LWPOSTGIS" >&5
+$as_echo "$LWPOSTGIS" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "LWPOSTGIS" != "no"; then
+ #postgres with postgis enabled
+ use_postgis=yes
+ use_spatial_db=yes
+ save_cppflags="$CPPFLAGS"
+ save_cxxflags="$CXXFLAGS"
+ save_libs="$LIBS"
+ save_ldflags="$LDFLAGS"
+ CPPFLAGS="$CPPFLAGS -I`${PG_CONFIG} --includedir` `${PG_CONFIG} --cppflags`"
+ CXXFLAGS="$CXXFLAGS `${PG_CONFIG} --cflags`"
+ LDFLAGS="$LDFLAGS `${PG_CONFIG} --ldflags`"
+ LIBS="${POSTGIS_LIB_DIR} `${PG_CONFIG} --libs` -lpq $LIBS"
+
+$as_echo "#define HAVE_POSTGIS 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Cannot find lwpostgis.sql: Building w/o Postgresql/Postgis support. ***" >&5
+$as_echo "$as_me: WARNING: *** Cannot find lwpostgis.sql: Building w/o Postgresql/Postgis support. ***" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Postgresql was found" >&5
+$as_echo "$as_me: WARNING: *** Postgresql was found" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Install and enable postgis and leave the lwpostgis.sql script in ***" >&5
+$as_echo "$as_me: WARNING: *** Install and enable postgis and leave the lwpostgis.sql script in ***" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** ${pg_path}/share ***" >&5
+$as_echo "$as_me: WARNING: *** ${pg_path}/share ***" >&2;}
+ fi
+ else
+ use_postgis=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Cannot find pg_config: Building w/o Postgresql/Postgis support. ***" >&5
+$as_echo "$as_me: WARNING: *** Cannot find pg_config: Building w/o Postgresql/Postgis support. ***" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Specify the path to the posgresql installation directory ***" >&5
+$as_echo "$as_me: WARNING: *** Specify the path to the posgresql installation directory ***" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** For example: --with-postgis=/usr/local/pgsql ***" >&5
+$as_echo "$as_me: WARNING: *** For example: --with-postgis=/usr/local/pgsql ***" >&2;}
+ fi
+fi
+
+
+fi
+use_mysql=no
+
+# Check whether --with-mysql was given.
+if test "${with_mysql+set}" = set; then :
+ withval=$with_mysql; use_mysql=$withval
+fi
+
+if test "${use_mysql}" != "no"; then
+
+BINPATH="${PATH}${EXTRA_BIN_PATH}"
+
+# test for MySQL
+if test "${with_mysql+set}" = set; then
+ MYSQL_CONFIG="mysql_config"
+ if test "$with_mysql" != "yes"; then
+ # get path to mysql_config if provided
+ mysql_path="$with_mysql"
+ BINPATH="${BINPATH}:${mysql_path}"
+ # Extract the first word of "mysql_config", so it can be a program name with args.
+set dummy mysql_config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MYSQL_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $MYSQL_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_MYSQL_CONFIG="$MYSQL_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $mysql_path
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_MYSQL_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_MYSQL_CONFIG" && ac_cv_path_MYSQL_CONFIG="no"
+ ;;
+esac
+fi
+MYSQL_CONFIG=$ac_cv_path_MYSQL_CONFIG
+if test -n "$MYSQL_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MYSQL_CONFIG" >&5
+$as_echo "$MYSQL_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ else
+ # Extract the first word of "mysql_config", so it can be a program name with args.
+set dummy mysql_config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MYSQL_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $MYSQL_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_MYSQL_CONFIG="$MYSQL_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_MYSQL_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_MYSQL_CONFIG" && ac_cv_path_MYSQL_CONFIG="no"
+ ;;
+esac
+fi
+MYSQL_CONFIG=$ac_cv_path_MYSQL_CONFIG
+if test -n "$MYSQL_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MYSQL_CONFIG" >&5
+$as_echo "$MYSQL_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+ use_mysql_spatial=no
+ use_mysql_any=no
+ if test "$MYSQL_CONFIG" != "no"; then
+
+ # check for mysql version with spatial support
+ # look for mysql 4.1.2 or greater for spatial support
+ # and standardized prepared statements
+ # 4.1.0 and 4.1.1 have spatial support, but only early versions
+ # of prepared statement functions that changed in 4.1.2
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking mysql version >= 4.1.2" >&5
+$as_echo_n "checking mysql version >= 4.1.2... " >&6; }
+ mysqlversion=`$MYSQL_CONFIG --version`
+ mysqlversionmajor=`echo ${mysqlversion} | cut -d '.' -f 1`
+ mysqlversionminor=`echo ${mysqlversion} | cut -d '.' -f 2`
+ mysqlversiontiny=`echo ${mysqlversion} | cut -d '.' -f 3`
+ if test "$mysqlversionmajor" -gt 4 ; then
+ mysql_has_spatial="yes"
+ elif test "$mysqlversionmajor" -ge 4 -a "$mysqlversionminor" -gt 1 ; then
+ mysql_has_spatial="yes"
+ elif test "$mysqlversionmajor" -ge 4 -a "$mysqlversionminor" -ge 1 -a "$mysqlversiontiny" -ge 2 ; then
+ mysql_has_spatial="yes"
+ else
+ mysql_has_spatial="no"
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $mysql_has_spatial" >&5
+$as_echo "$mysql_has_spatial" >&6; }
+ # if mysql version < 4.1, mysql present but no spatial support
+ if test "$mysql_has_spatial" = "yes"; then
+ # mysql with spatial support
+ use_mysql_spatial=yes
+ use_spatial_db=yes
+
+$as_echo "#define HAVE_MYSQL_SPATIAL 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** MySQL version $mysqlversion detected is < 4.1.2 ***" >&5
+$as_echo "$as_me: WARNING: *** MySQL version $mysqlversion detected is < 4.1.2 ***" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Spatial support enabled only for MySQL 4.1.2 and higher ***" >&5
+$as_echo "$as_me: WARNING: *** Spatial support enabled only for MySQL 4.1.2 and higher ***" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** MySQL support for Lat/Long fields is available but ***" >&5
+$as_echo "$as_me: WARNING: *** MySQL support for Lat/Long fields is available but ***" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** not for Points Polygons or other spatial objects. ***" >&5
+$as_echo "$as_me: WARNING: *** not for Points Polygons or other spatial objects. ***" >&2;}
+ fi
+ save_cppflags="$CPPFLAGS"
+ save_cxxflags="$CXXFLAGS"
+ save_libs="$LIBS"
+ CPPFLAGS="$CPPFLAGS `${MYSQL_CONFIG} --cflags`"
+ CXXFLAGS="$CXXFLAGS `${MYSQL_CONFIG} --cflags`"
+ LIBS=" `${MYSQL_CONFIG} --libs` $LIBS"
+ use_mysql_any=yes
+
+$as_echo "#define HAVE_MYSQL 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Cannot find mysql_config: Building w/o MySQL support. ***" >&5
+$as_echo "$as_me: WARNING: *** Cannot find mysql_config: Building w/o MySQL support. ***" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Specify the path to mysql_config ***" >&5
+$as_echo "$as_me: WARNING: *** Specify the path to mysql_config ***" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** For example: --with-mysql=/var/lib/mysql ***" >&5
+$as_echo "$as_me: WARNING: *** For example: --with-mysql=/var/lib/mysql ***" >&2;}
+ fi
+
+fi
+#AC_MSG_RESULT($use_mysql_spatial)
+
+fi
+
+if test "${use_postgis}" = "yes"; then
+ use_spatial_db=yes
+
+$as_echo "#define HAVE_SPATIAL_DB 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_DB 1" >>confdefs.h
+
+fi
+if test "${use_mysql_spatial}" = "yes"; then
+ use_spatial_db=yes
+
+$as_echo "#define HAVE_DB 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_SPATIAL_DB 1" >>confdefs.h
+
+elif test use_mysql_any = "yes"; then
+
+$as_echo "#define HAVE_DB 1" >>confdefs.h
+
+fi
+
+# Check for AX.25 library
+use_ax25=yes
+
+# Check whether --with-ax25 was given.
+if test "${with_ax25+set}" = set; then :
+ withval=$with_ax25; use_ax25=$withval
+fi
+
+if test "${use_ax25}" = "yes"; then
+ use_ax25=no
+ for ac_header in netax25/ax25.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "netax25/ax25.h" "ac_cv_header_netax25_ax25_h" "$ac_includes_default"
+if test "x$ac_cv_header_netax25_ax25_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_NETAX25_AX25_H 1
+_ACEOF
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ax25_config_load_ports in -lax25" >&5
+$as_echo_n "checking for ax25_config_load_ports in -lax25... " >&6; }
+if ${ac_cv_lib_ax25_ax25_config_load_ports+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lax25 $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ax25_config_load_ports ();
+int
+main ()
+{
+return ax25_config_load_ports ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_ax25_ax25_config_load_ports=yes
+else
+ ac_cv_lib_ax25_ax25_config_load_ports=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ax25_ax25_config_load_ports" >&5
+$as_echo "$ac_cv_lib_ax25_ax25_config_load_ports" >&6; }
+if test "x$ac_cv_lib_ax25_ax25_config_load_ports" = xyes; then :
+ use_ax25=yes
+ LIBS="$LIBS -lax25"
+
+$as_echo "#define HAVE_LIBAX25 /**/" >>confdefs.h
+
+ break
+fi
+
+fi
+
+done
+
+fi
+
+
+# use dbfawk
+use_dbfawk=yes
+
+# Check whether --with-dbfawk was given.
+if test "${with_dbfawk+set}" = set; then :
+ withval=$with_dbfawk; use_dbfawk=$withval
+fi
+
+# dbfawk requires shapelib and pcre. Make sure:
+if test "${use_dbfawk}" = "yes"; then
+ if test "${use_pcre}" = "yes" -a "${use_shapelib}" = "yes"; then
+
+$as_echo "#define WITH_DBFAWK /**/" >>confdefs.h
+
+ else
+ echo "*** Warning: dbfawk requires both pcre and shapelib."
+ use_dbfawk=no
+ fi
+fi
+
+
+# Check for GDAL. Make sure that the GDAL check is towards the
+# last, as it can mess up shapelib and libgeotiff currently.
+use_gdal=yes
+
+# Check whether --with-gdal was given.
+if test "${with_gdal+set}" = set; then :
+ withval=$with_gdal; use_gdal=$withval
+fi
+
+if test "${use_gdal}" = "yes"; then
+ if test "${use_lsb}" = "no"; then
+
+use_gdal=no
+#
+# Important: DO NOT use "use_gdal" as the variable here, because AC_CHECK_PROG
+# will do nothing if the variable is already set!
+#
+# Extract the first word of "gdal-config", so it can be a program name with args.
+set dummy gdal-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_found_gdal_config+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$found_gdal_config"; then
+ ac_cv_prog_found_gdal_config="$found_gdal_config" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_found_gdal_config="yes"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_found_gdal_config" && ac_cv_prog_found_gdal_config="no"
+fi
+fi
+found_gdal_config=$ac_cv_prog_found_gdal_config
+if test -n "$found_gdal_config"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $found_gdal_config" >&5
+$as_echo "$found_gdal_config" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test "${found_gdal_config}" = "yes"; then
+ save_cppflags="$CPPFLAGS"
+ save_libs="$LIBS"
+ save_ldflags="$LDFLAGS"
+
+ GDAL_BIN="gdal-config"
+ CPPFLAGS="$CPPFLAGS `${GDAL_BIN} --cflags`"
+#
+# This is an annoyance: gdal-config --libs outputs both LDFLAGS and LIBS
+# stuff. AC_CHECK_LIB puts the -l in if it works, and we only want the LDFLAGS
+# LIBS="$LIBS `${GDAL_BIN} --libs`"
+# Remove the -lgdal from what gdal-config --libs returns, because AC_CHECK_LIB
+# will put it into LIBS for us.
+#
+ LDFLAGS="$LDFLAGS `${GDAL_BIN} --libs | sed -e 's/-lgdal^ *//'`"
+ for ac_header in gdal.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "gdal.h" "ac_cv_header_gdal_h" "$ac_includes_default"
+if test "x$ac_cv_header_gdal_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GDAL_H 1
+_ACEOF
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GDALAllRegister in -lgdal" >&5
+$as_echo_n "checking for GDALAllRegister in -lgdal... " >&6; }
+if ${ac_cv_lib_gdal_GDALAllRegister+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgdal $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char GDALAllRegister ();
+int
+main ()
+{
+return GDALAllRegister ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_gdal_GDALAllRegister=yes
+else
+ ac_cv_lib_gdal_GDALAllRegister=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gdal_GDALAllRegister" >&5
+$as_echo "$ac_cv_lib_gdal_GDALAllRegister" >&6; }
+if test "x$ac_cv_lib_gdal_GDALAllRegister" = xyes; then :
+ use_gdal="yes"
+ LIBS="$LIBS -lgdal"
+
+$as_echo "#define HAVE_LIBGDAL /**/" >>confdefs.h
+
+else
+ CPPFLAGS=${save_cppflags}
+ LDFLAGS=${save_ldflags}
+ LIBS=${save_libs}
+fi
+
+fi
+
+done
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Cannot find gdal-config: Checking standard locations ***" >&5
+$as_echo "$as_me: WARNING: *** Cannot find gdal-config: Checking standard locations ***" >&2;}
+ for ac_header in gdal.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "gdal.h" "ac_cv_header_gdal_h" "$ac_includes_default"
+if test "x$ac_cv_header_gdal_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GDAL_H 1
+_ACEOF
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GDALAllRegister in -lgdal" >&5
+$as_echo_n "checking for GDALAllRegister in -lgdal... " >&6; }
+if ${ac_cv_lib_gdal_GDALAllRegister+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgdal $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char GDALAllRegister ();
+int
+main ()
+{
+return GDALAllRegister ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_gdal_GDALAllRegister=yes
+else
+ ac_cv_lib_gdal_GDALAllRegister=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gdal_GDALAllRegister" >&5
+$as_echo "$ac_cv_lib_gdal_GDALAllRegister" >&6; }
+if test "x$ac_cv_lib_gdal_GDALAllRegister" = xyes; then :
+ use_gdal="yes"
+ LIBS="$LIBS -lgdal"
+
+$as_echo "#define HAVE_LIBGDAL /**/" >>confdefs.h
+
+fi
+
+fi
+
+done
+
+fi
+
+
+ else
+ CPPFLAGS="$CPPFLAGS -I/opt/lsb-tmp/include"
+ LDFLAGS="$LDFLAGS -L/opt/lsb-tmp/lib -lgdal"
+ LIBS="$LIBS -lgdal"
+
+$as_echo "#define HAVE_LIBGDAL /**/" >>confdefs.h
+
+ fi
+fi
+
+use_rtree=yes
+LIBRTREE=""
+SUBRTREE=""
+
+# Check whether --with-rtree was given.
+if test "${with_rtree+set}" = set; then :
+ withval=$with_rtree; use_rtree=$withval
+fi
+
+if test "${use_rtree}" = "yes" ; then
+ if test "${use_shapelib}" = "yes"; then
+
+$as_echo "#define USE_RTREE 1" >>confdefs.h
+
+ LIBRTREE="-Lrtree -lrtree"
+ SUBRTREE="rtree"
+ else
+ echo "*** Warning: rtree requires shapelib."
+ use_rtree=no
+ fi
+fi
+
+
+
+
+
+
+# Check whether --enable-davis was given.
+if test "${enable_davis+set}" = set; then :
+ enableval=$enable_davis; case "${enableval}" in
+ yes) davis=true ;;
+ no) davis=false ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-davis" "$LINENO" 5 ;;
+ esac
+else
+ davis=false
+fi
+
+ if test x$davis = xtrue; then
+ DAVIS_TRUE=
+ DAVIS_FALSE='#'
+else
+ DAVIS_TRUE='#'
+ DAVIS_FALSE=
+fi
+
+if test "${davis}" = "true"; then
+ davis=yes
+else
+ davis=no
+fi
+
+
+
+
+
+# Check for LIBGC, a Garbage Collection library. If found, allow
+# linking it with Xastir, but require the "--with-libgc" flag to
+# enable it.
+use_libgc=no
+
+# Check whether --with-libgc was given.
+if test "${with_libgc+set}" = set; then :
+ withval=$with_libgc; use_libgc=$withval
+fi
+
+if test "${use_libgc}" = "yes"; then
+ for ac_header in gc.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "gc.h" "ac_cv_header_gc_h" "$ac_includes_default"
+if test "x$ac_cv_header_gc_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GC_H 1
+_ACEOF
+ LIBGC_INC="yes"
+else
+ use_libgc=no
+fi
+
+done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GC_init in -lgc" >&5
+$as_echo_n "checking for GC_init in -lgc... " >&6; }
+if ${ac_cv_lib_gc_GC_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgc $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char GC_init ();
+int
+main ()
+{
+return GC_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_gc_GC_init=yes
+else
+ ac_cv_lib_gc_GC_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gc_GC_init" >&5
+$as_echo "$ac_cv_lib_gc_GC_init" >&6; }
+if test "x$ac_cv_lib_gc_GC_init" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBGC 1
+_ACEOF
+
+ LIBS="-lgc $LIBS"
+
+else
+ use_libgc=no
+fi
+
+fi
+
+
+
+
+
+# Check whether profiling was requested. If so, add the "-pg" flag
+# to CFLAGS. Require "--with-profiling" flag to enable it.
+use_profiling=no
+
+# Check whether --with-profiling was given.
+if test "${with_profiling+set}" = set; then :
+ withval=$with_profiling; use_profiling=$withval
+fi
+
+if test "${use_profiling}" = "yes"; then
+ CFLAGS="$CFLAGS -pg"
+fi
+
+
+
+
+
+# Check for Berkeley DB.
+use_map_cache=yes
+
+# Check whether --with-map_cache was given.
+if test "${with_map_cache+set}" = set; then :
+ withval=$with_map_cache; use_map_cache=$withval
+fi
+
+if test "${use_map_cache}" = "yes"; then
+
+
+# Check whether --with-bdb-libdir was given.
+if test "${with_bdb_libdir+set}" = set; then :
+ withval=$with_bdb_libdir; with_bdb_lib=$withval
+else
+ test "${with_bdb_lib+set}" = set || with_bdb_lib=none
+fi
+
+
+# Check whether --with-bdb-incdir was given.
+if test "${with_bdb_incdir+set}" = set; then :
+ withval=$with_bdb_incdir; with_bdb_inc=$withval
+else
+ test "${with_bdb_inc+set}" = set || with_bdb_inc=none
+fi
+
+
+
+
+
+ xastir_save_CPPFLAGS=$CPPFLAGS
+
+ if test -d $with_bdb_inc; then
+ CPPFLAGS="$CPPFLAGS -I$with_bdb_inc"
+ BDB_INCADD="-I$with_bdb_inc"
+ else
+ BDB_INCADD=""
+ fi
+
+ # Commented out because it doesn't distinguish between versions of db.h
+# that can work with xastir and versions that can't. It is possible to
+# have multiple versions of db installed in different places, pick up the
+# header for one and the library for another. Bleah.
+# AC_CHECK_HEADER(db.h,
+# [XASTIR_BERKELEY_DB_CHK_LIB()],
+# dblib="no")
+#
+# Do this instead --- check to see if the db.h we find first in the search
+# path will actually pass the test we do in map_cache.c. Don't even bother
+# looking for a library if not.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if db.h is exists and is usable" >&5
+$as_echo_n "checking if db.h is exists and is usable... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <db.h>
+int
+main ()
+{
+#if (DB_VERSION_MAJOR < 4 )
+ #error DB_VERSION_MAJOR < 4
+ #endif
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+
+
+# We need to add the following algorithm here:
+#
+# Find the db.h file, grep for DB_VERSION_MAJOR and
+# DB_VERSION_MINOR. In my case I get this:
+#
+# #define DB_VERSION_MAJOR 4
+# #define DB_VERSION_MINOR 1
+#
+# Find the libdb.so file that Xastir would link to. Find the
+# version via the target of the symlink? In my case I have
+# this:
+#
+# > ls -al libdb.so
+# lrwxrwxrwx 1 root root 12 2004-01-07 11:29 libdb.so -> libdb-4.
+#
+# Compare the major/minor numbers. If they match, we're good to
+# go. If not, don't compile in libdb support. Perhaps we could
+# just run ldd on the test code to get the version number of the
+# linked library instead?
+#
+# Another possible way to do it would be to create test code and
+# compile/run it which would open/write/read/close/delete a
+# database. That should help to prove that Xastir would run ok if
+# the library were used.
+
+
+
+ BDB_SAVE_LDFLAGS=$LDFLAGS
+
+ if test -d $with_bdb_lib; then
+ LDFLAGS="-L$with_bdb_lib $LDFLAGS"
+ BDB_LIBADD="-L$with_bdb_lib $BDB_LIBADD"
+ else
+ BDB_LIBADD=""
+ fi
+
+ saved_LIBS=$LIBS
+# Removed db-3.3 db3.3 db33 db-3.2 db3.2 db32 db-3.1 db3.1 db31 db-3 db30 db3
+# from the probe. The map_cache.c code explicitly bombs if it doesn't have
+# version 4 or above, so why probe for version 3?
+
+# it would be nice if this could be done with AC_SEARCH_LIBS but that doesn't
+# work as it appears that there is some C++-type name mangling going on,
+# and just probing for a library that contains "db_create" fails. One needs
+# to specify the function call with the full prototype for it to be found.
+ BDB_LIB_FOUND="none"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a library containing db_create" >&5
+$as_echo_n "checking for a library containing db_create... " >&6; }
+ for dbname in db-4.9 db4.9 db49 db-4.8 db4.8 db48 db-4.7 db4.7 db47 db-4.6 db4.6 db46 db-4.5 db4.5 db45 db-4.4 db4.4 db44 db-4.3 db4.3 db43 db-4.2 db4.2 db42 db-4.1 db4.1 db41 db-4.0 db4.0 db-4 db40 db4 db
+ do
+ LIBS="$saved_LIBS -l$dbname"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <db.h>
+int
+main ()
+{
+db_create(NULL, NULL, 0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ BDB_LIBADD="$BDB_LIBADD -l$dbname"; dblib="berkeley";
+ BDB_LIB_FOUND="-l$dbname"
+else
+ dblib="no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+# STOP if we find one. Otherwise we'll keep stepping through the
+# list and resetting dblib to "no" over and over.
+ if test $dblib = "berkeley" ; then
+ break;
+ fi
+ done
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BDB_LIB_FOUND" >&5
+$as_echo "$BDB_LIB_FOUND" >&6; }
+
+# Commented out because the map_cache code is not actually set up to use
+# db_open instead of db_create. Probing in this way could actually be
+# dangerous.
+# if test "$dblib" = "no"; then
+# LIBS="$saved_LIBS -ldb"
+# AC_TRY_LINK([#include <db.h>],
+# [db_open(NULL, 0, 0, 0, NULL, NULL, NULL);],
+# BDB_LIBADD="$BDB_LIBADD -ldb"; dblib="berkeley"; dbname=db,
+# dblib="no")
+# fi
+ LIBS=$saved_LIBS
+
+ LDFLAGS=$BDB_SAVE_LDFLAGS
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }; dblib="no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CPPFLAGS=$xastir_save_CPPFLAGS
+
+ use_map_cache="no"
+ if test "${dblib}" = "berkeley"; then
+ LIBS="$BDB_LIBADD $LIBS"
+ CPPFLAGS="$CPPFLAGS $BDB_INCADD"
+
+$as_echo "#define USE_MAP_CACHE 1" >>confdefs.h
+
+ use_map_cache="yes"
+ fi
+
+
+fi
+
+
+
+
+
+# Check for GraphicsMagick. If not available/desired then check for
+# ImageMagick. These checks are VERY important to have as the last,
+# as they mess up previous checks if they fail.
+#
+use_graphicsmagick=yes
+use_imagemagick=no
+
+# Check whether --with-graphicsmagick was given.
+if test "${with_graphicsmagick+set}" = set; then :
+ withval=$with_graphicsmagick; use_graphicsmagick=$withval
+fi
+
+if test "${use_graphicsmagick}" = "yes"; then
+ if test "${use_lsb}" = "no"; then
+
+BINPATH="${PATH}${EXTRA_BIN_PATH}"
+
+# Check for GraphicsMagick
+#
+# First look for the needed GraphicsMagick-config script, which tells us all
+# of the build options we need.
+#
+# Important: DO NOT use "use_graphicsmagick" as the variable here,
+# because AC_CHECK_PROG will do nothing if the variable is already set!
+#
+use_graphicsmagick=no
+# Extract the first word of "GraphicsMagick-config", so it can be a program name with args.
+set dummy GraphicsMagick-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_GMAGIC_BIN+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $GMAGIC_BIN in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_GMAGIC_BIN="$GMAGIC_BIN" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $BINPATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_GMAGIC_BIN="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_GMAGIC_BIN" && ac_cv_path_GMAGIC_BIN="no"
+ ;;
+esac
+fi
+GMAGIC_BIN=$ac_cv_path_GMAGIC_BIN
+if test -n "$GMAGIC_BIN"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMAGIC_BIN" >&5
+$as_echo "$GMAGIC_BIN" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test "$GMAGIC_BIN" != "no"; then
+ use_graphicsmagick=yes
+#else
+# AC_MSG_WARN(*** Cannot find GraphicsMagick-config: Building w/o GraphicsMagick support. ***)
+fi
+#
+if test "${use_graphicsmagick}" = "yes"; then
+ save_cppflags="$CPPFLAGS"
+ save_cxxflags="$CXXFLAGS"
+ save_libs="$LIBS"
+ save_ldflags="$LDFLAGS"
+ #
+ # Figure out the build options using the GraphicsMagick-config script
+ #
+ CPPFLAGS="`${GMAGIC_BIN} --cppflags` $CPPFLAGS"
+ CXXFLAGS="`${GMAGIC_BIN} --cflags` $CXXFLAGS"
+ LDFLAGS="`${GMAGIC_BIN} --ldflags` $LDFLAGS"
+ LIBS="${MAGIC_LIB_DIR} `${GMAGIC_BIN} --libs` $LIBS"
+ #
+ ac_fn_c_check_header_mongrel "$LINENO" "GraphicsMagick/magick/api.h" "ac_cv_header_GraphicsMagick_magick_api_h" "$ac_includes_default"
+if test "x$ac_cv_header_GraphicsMagick_magick_api_h" = xyes; then :
+ use_graphicsmagick="yes"
+else
+ use_graphicsmagick="no"
+fi
+
+
+ if test "${use_graphicsmagick}" = "no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Cannot find GraphicsMagick include files: Building w/o GraphicsMagick support. ***" >&5
+$as_echo "$as_me: WARNING: *** Cannot find GraphicsMagick include files: Building w/o GraphicsMagick support. ***" >&2;}
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for WriteImage in -lGraphicsMagick" >&5
+$as_echo_n "checking for WriteImage in -lGraphicsMagick... " >&6; }
+if ${ac_cv_lib_GraphicsMagick_WriteImage+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lGraphicsMagick $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char WriteImage ();
+int
+main ()
+{
+return WriteImage ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_GraphicsMagick_WriteImage=yes
+else
+ ac_cv_lib_GraphicsMagick_WriteImage=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GraphicsMagick_WriteImage" >&5
+$as_echo "$ac_cv_lib_GraphicsMagick_WriteImage" >&6; }
+if test "x$ac_cv_lib_GraphicsMagick_WriteImage" = xyes; then :
+
+$as_echo "#define HAVE_GRAPHICSMAGICK 1" >>confdefs.h
+
+else
+ use_graphicsmagick="no"
+fi
+
+ if test "${use_graphicsmagick}" = "no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Cannot find GraphicsMagick library files: Building w/o GraphicsMagick support. ***" >&5
+$as_echo "$as_me: WARNING: *** Cannot find GraphicsMagick library files: Building w/o GraphicsMagick support. ***" >&2;}
+ fi
+ fi
+ #
+ if test "${use_graphicsmagick}" = "no"; then
+ #
+ # No GraphicsMagick found. Restore variables.
+ #
+ CPPFLAGS=$save_cppflags
+ CXXFLAGS=$save_cxxflags
+ LIBS=$save_libs
+ LDFLAGS=$save_ldflags
+ fi
+fi
+#
+# End of GraphicsMagick checks
+
+
+ else
+ MAGIC_BIN="/opt/lsb-tmp/bin/GraphicsMagick-config"
+ CPPFLAGS="$CPPFLAGS `${MAGIC_BIN} --cppflags`"
+ CXXFLAGS="$CXXFLAGS `${MAGIC_BIN} --cflags`"
+ LDFLAGS="$LDFLAGS `${MAGIC_BIN} --ldflags`"
+ LIBS="${MAGIC_LIB_DIR} `${MAGIC_BIN} --libs` $LIBS"
+
+$as_echo "#define HAVE_GRAPHICSMAGICK 1" >>confdefs.h
+
+ fi
+fi
+#
+# Note: This must be a separate "if" as the use_graphicsmagick
+# variable gets set to "no" if GM is not available above.
+#
+if test "${use_graphicsmagick}" = "no"; then
+ use_imagemagick=yes
+
+# Check whether --with-imagemagick was given.
+if test "${with_imagemagick+set}" = set; then :
+ withval=$with_imagemagick; use_imagemagick=$withval
+fi
+
+ if test "${use_imagemagick}" = "yes"; then
+
+BINPATH="${PATH}${EXTRA_BIN_PATH}"
+
+# Check for ImageMagick
+#
+# First look for the needed Magick-config script, which tells us all
+# of the build options we need.
+#
+# Important: DO NOT use "use_imagemagick" as the variable here,
+# because AC_CHECK_PROG will do nothing if the variable is already set!
+#
+use_imagemagick=no
+# Extract the first word of "Magick-config", so it can be a program name with args.
+set dummy Magick-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MAGIC_BIN+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $MAGIC_BIN in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_MAGIC_BIN="$MAGIC_BIN" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $BINPATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_MAGIC_BIN="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_MAGIC_BIN" && ac_cv_path_MAGIC_BIN="no"
+ ;;
+esac
+fi
+MAGIC_BIN=$ac_cv_path_MAGIC_BIN
+if test -n "$MAGIC_BIN"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_BIN" >&5
+$as_echo "$MAGIC_BIN" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test "$MAGIC_BIN" != "no"; then
+ use_imagemagick=yes
+#else
+# AC_MSG_WARN(*** Cannot find Magick-config: Building w/o ImageMagick support. ***)
+fi
+
+if test "${use_imagemagick}" = "yes"; then
+# #
+# # Compute the ImageMagick revision number
+# #
+# magickversion=`${MAGIC_BIN} --version`
+# magickmajor=`echo $magickversion | cut -d '.' -f 1`
+# magickminor=`echo $magickversion | cut -d '.' -f 2`
+# magicktiny=`echo $magickversion | cut -d '.' -f 3`
+# if test "$magickmajor" -lt 5; then
+# magickold="yes";
+# elif test "$magickmajor" -eq 5 -a "$magickminor" -lt 4; then
+# magickold="yes";
+# elif test "$magickmajor" -eq 5 -a "$magickminor" -eq 4 -a "$magicktiny" -lt 9; then
+# magickold="yes";
+# fi
+ #
+ save_cppflags="$CPPFLAGS"
+ save_cxxflags="$CXXFLAGS"
+ save_libs="$LIBS"
+ save_ldflags="$LDFLAGS"
+ #
+ # Figure out the build options using the Magick-config script
+ #
+ CPPFLAGS="$CPPFLAGS `${MAGIC_BIN} --cppflags`"
+ CXXFLAGS="$CXXFLAGS `${MAGIC_BIN} --cflags`"
+ LDFLAGS="$LDFLAGS `${MAGIC_BIN} --ldflags`"
+ LIBS="${MAGIC_LIB_DIR} `${MAGIC_BIN} --libs` $LIBS"
+ #
+ ac_fn_c_check_header_mongrel "$LINENO" "magick/api.h" "ac_cv_header_magick_api_h" "$ac_includes_default"
+if test "x$ac_cv_header_magick_api_h" = xyes; then :
+ use_imagemagick="yes"
+else
+ use_imagemagick="no"
+fi
+
+
+ if test "${use_imagemagick}" = "no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Cannot find ImageMagick include files: Building w/o ImageMagick support. ***" >&5
+$as_echo "$as_me: WARNING: *** Cannot find ImageMagick include files: Building w/o ImageMagick support. ***" >&2;}
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing WriteImage" >&5
+$as_echo_n "checking for library containing WriteImage... " >&6; }
+if ${ac_cv_search_WriteImage+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char WriteImage ();
+int
+main ()
+{
+return WriteImage ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' Magick MagickCore; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_WriteImage=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_WriteImage+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_WriteImage+:} false; then :
+
+else
+ ac_cv_search_WriteImage=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_WriteImage" >&5
+$as_echo "$ac_cv_search_WriteImage" >&6; }
+ac_res=$ac_cv_search_WriteImage
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_IMAGEMAGICK 1" >>confdefs.h
+
+else
+ use_imagemagick="no"
+fi
+
+ if test "${use_imagemagick}" = "no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Cannot find ImageMagick library files: Building w/o ImageMagick support. ***" >&5
+$as_echo "$as_me: WARNING: *** Cannot find ImageMagick library files: Building w/o ImageMagick support. ***" >&2;}
+ fi
+ fi
+ #
+ if test "${use_imagemagick}" = "no"; then
+ #
+ # No ImageMagick found. Restore variables.
+ #
+ CPPFLAGS=$save_cppflags
+ CXXFLAGS=$save_cxxflags
+ LIBS=$save_libs
+ LDFLAGS=$save_ldflags
+ fi
+#
+# if test "${magickold}" = "yes"; then
+# This used to be important, as some versions didn't support the
+# Tigermap intensity slider.
+# AC_MSG_WARN(*********************************************************)
+# AC_MSG_WARN(*** Old ImageMagick version ($magickversion) found. ***)
+# AC_MSG_WARN(*** Upgrade to 5.4.9 or newer for full functionality. ***)
+# AC_MSG_WARN(*********************************************************)
+# fi
+fi
+# End of ImageMagick checks
+
+
+ fi
+fi
+#
+#
+#
+if test "${use_imagemagick}" = "yes" -o "${use_graphicsmagick}" = "yes"; then
+
+$as_echo "#define HAVE_MAGICK 1" >>confdefs.h
+
+fi
+
+
+
+
+
+# Set XASTIR_DATA_BASE in CPPFLAGS due to Gnu coding standard that requires
+# datadir expansion to be deferred until make time.
+if test "x${datadir}" = "x"; then
+ CPPFLAGS="$CPPFLAGS -DXASTIR_DATA_BASE=\\\"${ac_default_prefix}/share/xastir\\\""
+else
+ CPPFLAGS="$CPPFLAGS -DXASTIR_DATA_BASE=\\\"${datadir}/xastir\\\""
+fi
+
+
+
+# Add a special option that makes Cygwin link much faster (from
+# Henk de Groot)
+save_LDFLAGS="$LDFLAGS"
+LDFLAGS="-Wl,--no-keep-memory $LDFLAGS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+int
+main ()
+{
+/* Stupid useless test for linker flags */
+ exit(0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ xa_cv_no_keep_memory=yes
+else
+ xa_cv_no_keep_memory=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test "${xa_cv_no_keep_memory}" = "no"; then
+ LDFLAGS="$save_LDFLAGS"
+fi
+
+#
+# Assure we have this order for these LIBS: "-lXm -lXt -lX11" by
+# adding them to the beginning. Add spaces around them for the
+# following steps. Here I'm adding them to the beginning so the
+# dupe-check portion will take out the later ones that might be in
+# the wrong order. If they're in the wrong order, we can get
+# "Error: Shell widget xastir has zero width and/or height" when
+# Xastir is started up. Can also get "Error: attempt to add
+# non-widget child "DropSiteManager" to parent", but that can also
+# be caused by other problems with libraries.
+#
+LIBS=" -lXm -lXt -lX11 $LIBS"
+
+#
+# Remove duplicate entries. Thanks to Paul Lutt, ke7xt, for this!
+#
+# Don't get rid of dupes on the LIBS line. We may need the same
+# "-Llibdir" called out several times, immediately prior to each
+# "-llibrary" that needs it.
+#
+
+CFLAGS=`echo "$CFLAGS" | awk '{for(i=1;i<=NF;++i) {if (arg[$i]++ == 0) s = s " " $i} print s}'`
+CPPFLAGS=`echo "$CPPFLAGS" | awk '{for(i=1;i<=NF;++i) {if (arg[$i]++ == 0) s = s " " $i} print s}'`
+LDFLAGS=`echo "$LDFLAGS" | awk '{for(i=1;i<=NF;++i) {if (arg[$i]++ == 0) s = s " " $i} print s}'`
+#LIBS=`echo "$LIBS" | awk '{for(i=1;i<=NF;++i) {if (arg[$i]++ == 0) s = s " " $i} print s}'`
+
+
+
+#
+# Remove "-g" CFLAGS/CPPFLAGS entries. Note: This is a _bad_ idea
+# as debuggers won't have a symbol table to work from!
+#
+#changequote(,)
+#CFLAGS=`echo "$CFLAGS" | awk '{for(i=1;i<=NF;++i) {if ($i != "-g") s = s " " $i} print s}'`
+#CPPFLAGS=`echo "$CPPFLAGS" | awk '{for(i=1;i<=NF;++i) {if ($i != "-g") s = s " " $i} print s}'`
+#changequote([,])
+
+
+#
+# Change the compiler optimization if using Windows/Cygwin in order
+# to reduce memory usage and speed up the compile. Here we change
+# "-O2" to "-O1" or " " in CFLAGS/CPPFLAGS to reduce the level of
+# optimization.
+# We also wish to remove "-no-undefined" from LDFLAGS on Cygwin, as
+# we use GCC for our linking instead of libtool, and GCC doesn't
+# like that flag at the link stage.
+#
+case "$host_os" in
+cygwin*)
+
+ CFLAGS=`echo "$CFLAGS" | awk '{for(i=1;i<=NF;++i) {if ($i != "-O2") s = s " " $i} print s}'`
+ CPPFLAGS=`echo "$CPPFLAGS" | awk '{for(i=1;i<=NF;++i) {if ($i != "-O2") s = s " " $i} print s}'`
+ LDFLAGS=`echo "$LDFLAGS" | awk '{for(i=1;i<=NF;++i) {if ($i != "-no-undefined") s = s " " $i} print s}'`
+
+;;
+esac
+
+
+# Create the ILIBS defined variable. We add spaces here in the else
+# clauses in order to make the REGRESSION_TESTS format nicely. We
+# take them back out before we define the variable that Xastir uses
+# for it's Help->About dialog.
+#
+if test "${use_ax25}" = "yes"; then
+ ILIBS="AX25"
+else
+ ILIBS=" "
+fi
+if test "${use_festival}" = "yes"; then
+ ILIBS="$ILIBS Festival"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_gpsman}" = "yes"; then
+ ILIBS="$ILIBS GPSMan"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_graphicsmagick}" = "yes"; then
+ ILIBS="$ILIBS GraphicsMagick"
+else
+ if test "${use_imagemagick}" = "yes"; then
+ ILIBS="$ILIBS ImageMagick "
+ else
+ ILIBS="$ILIBS "
+ fi
+fi
+if test "${use_proj}" = "yes"; then
+ ILIBS="$ILIBS libProj"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_geotiff}" = "yes"; then
+ ILIBS="$ILIBS GeoTiff"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_gdal}" = "yes"; then
+ ILIBS="$ILIBS GDAL/OGR"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_shapelib}" = "yes"; then
+ ILIBS="$ILIBS ShapeLib"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_pcre}" = "yes"; then
+ ILIBS="$ILIBS PCRE"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_dbfawk}" = "yes"; then
+ ILIBS="$ILIBS Dbfawk"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_map_cache}" = "yes"; then
+ ILIBS="$ILIBS map_caching"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_err_popups}" = "yes"; then
+ ILIBS="$ILIBS error_popups"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_libgc}" = "yes"; then
+ ILIBS="$ILIBS libgc"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_profiling}" = "yes"; then
+ ILIBS="$ILIBS profiling"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_rtree}" = "yes"; then
+ ILIBS="$ILIBS rtree"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_lsb}" = "yes"; then
+ ILIBS="$ILIBS LSB"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_curl}" = "yes"; then
+ ILIBS="$ILIBS libcurl"
+else
+ if test "${use_wget}" = "yes"; then
+ ILIBS="$ILIBS wget "
+ else
+ ILIBS="$ILIBS "
+ fi
+fi
+
+# Write out the library information to "summary.log". Here we want
+# the spaces for the undefined pieces, so REGRESSION_TESTS formats
+# nicely.
+echo "$ILIBS" >summary.log
+
+
+#
+# Remove extraneous spaces from output variables (asthetic)
+#
+ILIBS=`echo $ILIBS | sed -e 's/ */ /g'`
+X_CFLAGS=`echo $X_CFLAGS | sed -e 's/ */ /g'`
+X_PRE_LIBS=`echo $X_PRE_LIBS | sed -e 's/ */ /g'`
+X_LIBS=`echo $X_LIBS | sed -e 's/ */ /g'`
+X_EXTRA_LIBS=`echo $X_EXTRA_LIBS | sed -e 's/ */ /g'`
+
+CC=`echo $CC | sed -e 's/ */ /g'`
+CFLAGS=`echo $CFLAGS | sed -e 's/ */ /g'`
+CPPFLAGS=`echo $CPPFLAGS | sed -e 's/ */ /g'`
+CXXFLAGS=`echo $CXXFLAGS | sed -e 's/ */ /g'`
+LDFLAGS=`echo $LDFLAGS | sed -e 's/ */ /g'`
+TESTED_LIBS=`echo $LIBS | sed -e 's/ */ /g'`
+MAGICK_DEP_LIBS=`echo $MAGICK_DEP_LIBS | sed -e 's/ */ /g'`
+LIBS=`echo $LIBS | sed -e 's/ */ /g'`
+
+
+# Change the output text for Shapelib if we're using the internal
+# library. The below will be used for the configure summary and for
+# the Help->About text in Xastir.
+if test "${force_internal_shapelib}" = "yes"; then
+ ILIBS=`echo $ILIBS | sed -e 's/ShapeLib/ShapeLib(internal)/g'`
+ use_shapelib="yes (internal)"
+fi
+
+
+
+tmp_path="$ac_default_prefix"
+tmp_bin_path="$ac_default_prefix"
+if test "x$prefix" != xNONE; then
+ tmp_path="$prefix"
+ tmp_bin_path="$prefix"
+fi
+if test "x$exec_prefix" != xNONE; then
+ tmp_bin_path="$exec_prefix"
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define XASTIR_PATH "`echo $tmp_path`"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define XASTIR_BIN_PATH "`echo $tmp_bin_path`"
+_ACEOF
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define XASTIR_INSTALLED_LIBS "`echo $ILIBS`"
+_ACEOF
+
+
+
+
+
+#AC_SUBST(CPPFLAGS)
+
+#AC_SUBST(LDFLAGS)
+#AC_SUBST(X_PRE_LIBS)
+#AC_SUBST(X_LIBS)
+#AC_SUBST(X_EXTRA_LIBS)
+
+ac_config_files="$ac_config_files Makefile callpass/Makefile config/Makefile help/Makefile m4/Makefile scripts/Makefile scripts/values scripts/values.pl src/Makefile src/rtree/Makefile src/shapelib/Makefile src/shapelib/contrib/Makefile symbols/Makefile xastir.spec xastir-min.spec xastir-lsb.spec"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+ if test -n "$EXEEXT"; then
+ am__EXEEXT_TRUE=
+ am__EXEEXT_FALSE='#'
+else
+ am__EXEEXT_TRUE='#'
+ am__EXEEXT_FALSE=
+fi
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+if test -z "${DAVIS_TRUE}" && test -z "${DAVIS_FALSE}"; then
+ as_fn_error $? "conditional \"DAVIS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by xastir $as_me 2.0.4, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <xastir at xastir.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+xastir config.status 2.0.4
+configured by $0, generated by GNU Autoconf 2.68,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "callpass/Makefile") CONFIG_FILES="$CONFIG_FILES callpass/Makefile" ;;
+ "config/Makefile") CONFIG_FILES="$CONFIG_FILES config/Makefile" ;;
+ "help/Makefile") CONFIG_FILES="$CONFIG_FILES help/Makefile" ;;
+ "m4/Makefile") CONFIG_FILES="$CONFIG_FILES m4/Makefile" ;;
+ "scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
+ "scripts/values") CONFIG_FILES="$CONFIG_FILES scripts/values" ;;
+ "scripts/values.pl") CONFIG_FILES="$CONFIG_FILES scripts/values.pl" ;;
+ "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+ "src/rtree/Makefile") CONFIG_FILES="$CONFIG_FILES src/rtree/Makefile" ;;
+ "src/shapelib/Makefile") CONFIG_FILES="$CONFIG_FILES src/shapelib/Makefile" ;;
+ "src/shapelib/contrib/Makefile") CONFIG_FILES="$CONFIG_FILES src/shapelib/contrib/Makefile" ;;
+ "symbols/Makefile") CONFIG_FILES="$CONFIG_FILES symbols/Makefile" ;;
+ "xastir.spec") CONFIG_FILES="$CONFIG_FILES xastir.spec" ;;
+ "xastir-min.spec") CONFIG_FILES="$CONFIG_FILES xastir-min.spec" ;;
+ "xastir-lsb.spec") CONFIG_FILES="$CONFIG_FILES xastir-lsb.spec" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$_am_arg" : 'X\(//\)[^/]' \| \
+ X"$_am_arg" : 'X\(//\)$' \| \
+ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+ :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+ # Autoconf 2.62 quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir=$dirpart/$fdir; as_fn_mkdir_p
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+ ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
+# Please leave these in as they're very useful for debug when we
+# port to new platforms! Leave them commented out unless doing
+# debugging on the configure scripts.
+#
+#echo ""
+#echo " LIBS: $LIBS"
+#echo " LDFLAGS: $LDFLAGS"
+#echo " CFLAGS: $CFLAGS"
+#echo " CPPFLAGS: $CPPFLAGS"
+#echo " X_LIBS: $X_LIBS"
+#echo " X_PRE_LIBS: $X_PRE_LIBS"
+#echo "X_EXTRA_LIBS: $X_EXTRA_LIBS"
+
+
+# Write a short summary of the configure tests/results to
+# "summary.log"
+egrep -e "checking |result:|gcc version" config.log >> summary.log
+
+
+echo ===========================================
+echo
+echo xastir 2.0.4 has been configured to use the following
+echo options and external libraries:
+echo
+echo MINIMUM OPTIONS:
+echo " ShapeLib (Vector maps) ................. : $use_shapelib"
+echo
+echo RECOMMENDED OPTIONS:
+
+echo -n " GraphicsMagick/ImageMagick (Raster maps) : "
+if test "${use_graphicsmagick}" = "yes"; then
+ echo "yes (GraphicsMagick)"
+else
+ if test "${use_imagemagick}" = "yes"; then
+ echo "yes (ImageMagick)"
+ else
+ echo "no"
+ fi
+fi
+echo " pcre (Shapefile customization) ......... : $use_pcre"
+echo " dbfawk (Shapefile customization) ....... : $use_dbfawk"
+echo " rtree indexing (Shapefile speedups) .... : $use_rtree"
+echo " map caching (Raster map speedups) ...... : $use_map_cache"
+echo " internet map retrieval ................. : $use_retrieval"
+echo
+echo FOR THE ADVENTUROUS:
+echo " AX25 (Linux Kernel I/O Drivers) ........ : $use_ax25"
+echo " libproj (USGS Topos & Aerial Photos) ... : $use_proj"
+echo " GeoTiff (USGS Topos & Aerial Photos) ... : $use_geotiff"
+echo " Festival (Text-to-speech) .............. : $use_festival"
+echo " GDAL/OGR (Obtuse map formats) .......... : $use_gdal"
+echo " GPSMan/gpsmanshp (GPS downloads) ....... : $use_gpsman"
+#echo " GPSD Client (libgps) ................... : $use_libgps"
+
+if test "${use_err_popups}" = "yes" -o "${use_libgc}" = "yes" -o "${use_profiling}" = "yes" -o "${use_lsb}" = "yes" -o "${use_spatial_db}" = "yes" -o "$use_mysql_any" = "yes"; then
+ echo
+ echo DEVELOPER OPTIONS:
+ echo " ErrorPopups (Old Method) ............... : $use_err_popups"
+ echo " libgc (Debug memory usage) ............. : $use_libgc"
+ echo " profiling (Debug code efficiency) ...... : $use_profiling"
+ echo " Linux Standard Base (LSB) .............. : $use_lsb"
+ echo " Spatial database support ............... : $use_spatial_db"
+ echo " Spatial database Postgresql/Postgis .... : $use_postgis"
+ echo " MySQL .................................. : $use_mysql_any"
+ echo " MySQL Spatial database support ......... : $use_mysql_spatial"
+fi
+
+#echo Davis/MySQL............................. : $davis
+echo
+echo xastir will be installed in $prefix/bin.
+if test "x$xastirpath" != "x" ; then
+ echo Warning: You have an old copy of Xastir at $xastirpath.
+fi
+echo "Type 'make' to build Xastir (Use 'gmake' instead on some systems)."
+
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..898f304
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,1003 @@
+# Process this file with autoconf to produce a configure script.
+
+# $Id: configure.ac,v 1.226 2012/12/04 23:35:35 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+
+
+#########################################################################
+# SET VERSION HERE!
+#
+# Note that the most standard OSS method of doing numbering is:
+# Major.Minor.PatchLevel
+#
+# If we are only doing patches, change the PATCHLEVEL number.
+# If we add new features, change the MINOR number.
+# If we feel we've added enough new features or rewritten enough
+# code to warrant it, change the MAJOR number.
+#
+# Also: We adopted the convention of using odd numbers for development
+# or development releases, even numbers for STABLE releases.
+#
+#
+# AC_INIT():
+# It should look something like this: (xastir, 2.0.2, xastir at xastir.org)
+# The revision number must contain at least one '.' and two digits.
+# AM_INIT_AUTOMAKE():
+# It should look something like this: (xastir, 2.0.2)
+# The revision number must contain at least one '.' and two digits.
+#
+AC_INIT([xastir], [2.0.4], [xastir at xastir.org])
+AM_INIT_AUTOMAKE
+#########################################################################
+
+
+AC_PREREQ(2.53)
+
+AC_CONFIG_SRCDIR([src/xastir.h])
+AM_CONFIG_HEADER(config.h)
+
+echo ""
+echo "Configuring AC_PACKAGE_NAME AC_PACKAGE_VERSION"
+echo ""
+
+# Take out the dots in order to create the TOCALL
+AC_DEFINE_UNQUOTED(XASTIR_TOCALL, "`echo AC_PACKAGE_VERSION | sed -e 's/^/APX/' -e 's/\.//g'`", [Defines the version tocall])
+
+# Check for host type
+AC_CANONICAL_HOST
+
+# Define _GNU_SOURCE if appropriate
+# doesn't work with older (heh) autoconfs
+AC_GNU_SOURCE
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_AWK
+AC_PROG_RANLIB
+#AC_PROG_YACC
+
+# test for devices
+XASTIR_DETECT_DEVICES
+
+# add includes and libs
+XASTIR_ADD_SEARCH_PATHS
+
+# check for pthread first
+ACX_PTHREAD
+
+# add compiler flags
+XASTIR_COMPILER_FLAGS
+
+# set XASTIR_SYSTEM
+XASTIR_SET_SYSTEM
+
+# Check for binaries
+use_festival=yes
+use_gpsman=yes
+use_err_popups=no
+use_lsb=no
+use_spatial_db=no
+use_postgis=no
+use_mysql_spatial=no
+AC_ARG_WITH(festival,[ --without-festival Disable festival features.],use_festival=$withval)
+
+AC_ARG_WITH(gpsman,[ --without-gpsman Disable gpsman features.],use_gpsman=$withval)
+
+AC_ARG_WITH(errorpopups,[ --with-errorpopups Send error popups to stderr.],use_err_popups=$withval)
+
+AC_ARG_WITH(lsb,[ --with-lsb Enable Linux Standard Base.],use_lsb=$withval)
+
+AC_ARG_WITH([xorg_175_workaround],
+ [AS_HELP_STRING([--with-xorg_175_workaround],[Employ workaround for broken Xorg 1.7.5 server])],
+ [],
+ [with_xorg_175_workaround=no])
+AS_IF([test "x$with_xorg_175_workaround" != xno],
+ [AC_DEFINE([XASTIR_XORG_SERVER_175_BUG], [1],
+ [Define if you need to work with the broken Xorg server 1.7.5])])
+
+# Now that all the various "use_" variables are set, probe for binaries.
+XASTIR_DETECT_BINARIES
+
+# if the probes failed, then make sure the "use_" variables are set to no,
+# even if we requested them.
+if test "x${festival}" = "xno"; then
+ use_festival=no
+fi
+if test "x${gpsman}" = "xno"; then
+ use_gpsman=no
+fi
+
+
+# JMT - XXX - what is this and why is it relevant?
+#AC_DEFINE(_REENTRANT, 1, [Use reentrant code if available.])
+AC_DEFINE_UNQUOTED(STIPPLE, 1, [Legacy stuff, use crowbar and lets keep going])
+
+# Checks for libraries.
+#
+#
+# Find the X11 include and library directories.
+#
+AC_PATH_XTRA
+if test "$no_x" = "yes"; then
+ AC_MSG_ERROR(*** No X11! Install X-Windows development headers/libraries! ***)
+fi
+
+CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+LDFLAGS="$LDFLAGS $X_LIBS"
+LIBS="$LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
+
+AC_SEARCH_LIBS(tan,math m)
+AC_CHECK_LIB([Xext], [XextAddDisplay])
+# It appears that XpGetDocumentData is not used
+# *anywhere* in Xastir, and the fact that this is being probed for has
+# confused at least one user into thinking he needed to install the X Printing
+# Extension development headers when it was completely unnecessary. But
+# apparently at least one linux system has a motif library that requires
+# libXp and doesn't link it in dynamically --- so this needs to be enabled?
+AC_CHECK_LIB([Xp], [XpGetDocumentData])
+AC_CHECK_LIB([Xt], [XtDisplay])
+AC_CHECK_LIB([Xm], [XmTextFindString])
+
+
+
+#use_html2text=no
+#AC_PATH_PROG(html2text, [html2text --version], no, $BINPATH)
+#if test "$html2text" != "no"; then
+# AC_DEFINE_UNQUOTED(HAVE_HTML2TEXT, 1, [Define if you have html2text])
+# AC_DEFINE_UNQUOTED(HTML2TEXT_PATH, "${html2text}", [Path to html2text])
+# use_html2text=yes
+#fi
+
+
+
+use_sed=no
+AC_PATH_PROG(sed, [sed --version], no, $BINPATH)
+if test "$sed" != "no"; then
+ AC_DEFINE_UNQUOTED(HAVE_SED, 1, [Define if you have sed])
+ AC_DEFINE_UNQUOTED(SED_PATH, "${sed}", [Path to sed])
+ use_sed=yes
+fi
+
+
+
+use_mv=no
+AC_PATH_PROG(mv, [mv --version], no, $BINPATH)
+if test "$mv" != "no"; then
+ AC_DEFINE_UNQUOTED(HAVE_MV, 1, [Define if you have mv])
+ AC_DEFINE_UNQUOTED(MV_PATH, "${mv}", [Path to mv])
+ use_mv=yes
+fi
+
+
+
+use_xfontsel=no
+AC_PATH_PROG(xfontsel, xfontsel, no, $BINPATH)
+if test "$xfontsel" != "no"; then
+ AC_DEFINE_UNQUOTED(HAVE_XFONTSEL, 1, [Define if you have xfontsel])
+ AC_DEFINE_UNQUOTED(XFONTSEL_PATH, "${xfontsel}", [Path to xfontsel])
+ use_xfontsel=yes
+fi
+
+
+
+use_curl=no
+curl_desired=yes
+# Note: Had to move AC_CHECK_HEADER here instead of inside the first
+# "if" statement: It corrupted later tests, don't know why. The
+# only downside is that we check for the libcurl headers even if
+# --without-libcurl was specified on the command-line.
+AC_CHECK_HEADER(curl/curl.h, CURL_INC="yes", CURL_INC="no")
+AC_ARG_WITH(libcurl,[ --without-libcurl Disable libcurl features.],curl_desired=$withval)
+if test "${curl_desired}" = "yes"; then
+ if test "${CURL_INC}" = "yes"; then
+ if test "${use_lsb}" = "no"; then
+ # Important: when using the three-argument version of AC_CHECK_LIB, you
+ # must do all of what is normally the default behavior in the third argument,
+ # not just the extra stuff you want to accomplish:
+ AC_CHECK_LIB([curl], [curl_global_init],
+ [use_curl="yes"
+ LIBS="${LIBS} -lcurl"
+ AC_DEFINE(HAVE_LIBCURL, ,
+ [Define to 1 if your `curl' library has curl_global_init.])
+ ])
+ else
+ AC_DEFINE(HAVE_LIBCURL, , [Define to 1 if your `curl' library has curl_global_init.] )
+ LIBS="${LIBS} -lcurl"
+ use_curl=yes
+ fi
+ fi
+fi
+# Test for wget only if above libcurl tests fail
+use_wget=no
+if test "${use_curl}" = "no"; then
+ AC_PATH_PROG(wget, [wget --version], no, $BINPATH)
+ if test "$wget" != "no"; then
+ AC_DEFINE_UNQUOTED(HAVE_WGET, 1, [Define if you have wget])
+ AC_DEFINE_UNQUOTED(WGET_PATH, "${wget}", [Path to wget])
+ use_wget=yes
+ fi
+fi
+
+
+
+use_retrieval=no
+if test "${use_curl}" = "yes"; then
+ use_retrieval="yes (libcurl)"
+else
+ if test "${use_wget}" = "yes"; then
+ use_retrieval="yes (wget)"
+ fi
+fi
+
+
+
+# Test for libgps, used for accessing GPSD daemon
+#use_libgps=no
+#AC_CHECK_HEADER(gps.h, GPS_INC="yes", GPS_INC="no")
+#if test "${GPS_INC}" = "yes"; then
+# AC_CHECK_LIB([gps], [gps_open],
+# [use_libgps="yes"
+# LIBS="${LIBS} -lgps"
+# AC_DEFINE(HAVE_LIBGPS, ,
+# [Define to 1 if your `libgps' library has gps_open.])
+# ])
+#fi
+
+
+
+# JMT - XXX - why is this here?
+AC_CHECK_LIB(compat, main,
+ [LIBCOMPAT="-lcompat"
+ AC_SUBST(LIBCOMPAT)])
+
+# Check for sched_yield in librt (Needed for Solaris)
+AC_CHECK_LIB(rt, sched_yield, LIBS="-lrt $LIBS")
+
+# Check for endian
+AC_C_BIGENDIAN
+
+
+
+# Our old stuff. Doesn't work in all cases.
+# Checks for header files.
+#AC_CHECK_HEADERS([Xm/Xm.h],MOTIF_INC="yes", AC_MSG_ERROR(*** Cannot find Motif include files: Please install one of Motif/OpenMotif/Lesstif development packages. ***))
+
+XASTIR_PATH_MOTIF
+if test "x$xm_includes" != "x" ; then
+ CFLAGS="$CFLAGS -I$xm_includes"
+ CPPFLAGS="$CPPFLAGS -I$xm_includes"
+fi
+if test "x$xm_libraries" != "x" ; then
+ LDFLAGS="-L$xm_libraries $LDFLAGS"
+fi
+
+AC_SUBST(LDFLAGS)
+AC_SUBST(LIBS)
+
+
+#
+AC_FUNC_ALLOCA
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS([argz.h arpa/inet.h fcntl.h libintl.h limits.h locale.h malloc.h math.h netdb.h])
+AC_CHECK_HEADERS([netinet/in.h nl_types.h stdarg.h stddef.h stdlib.h string.h strings.h])
+AC_CHECK_HEADERS([sys/file.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h signal.h])
+AC_CHECK_HEADERS([termios.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+#
+AC_C_CONST
+AC_TYPE_UID_T
+AC_C_INLINE
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_HEADER_TIME
+#AC_STRUCT_TM
+AC_TYPE_SIGNAL
+AC_STRUCT_TIMEZONE
+
+#Some (Mac?) systems don't define this where it should be, so we kludge
+AC_CHECK_TYPES(socklen_t,,,[#include <sys/types.h>
+#include <sys/socket.h>])
+
+# some BSD systems do not define sighandler_t, but rather sig_t
+AC_CHECK_TYPES(sighandler_t,,,[#include <signal.h>])
+AC_CHECK_TYPES(sig_t,,,[#include <signal.h>])
+
+# some BSD systems do not define sighandler_t, but rather sig_t
+AC_CHECK_TYPES(sigjmp_buf,,,[#include <setjmp.h>])
+
+#Force this into config.h.in
+AH_BOTTOM([#ifndef HAVE_SOCKLEN_T
+#define socklen_t int
+#endif])
+
+
+# Check for tm_gmtoff in tm
+AC_CHECK_GMTOFF
+
+# Checks for library functions.
+#
+AC_FUNC_FORK
+AC_PROG_GCC_TRADITIONAL
+AC_FUNC_GETPGRP
+AC_FUNC_MALLOC
+AC_FUNC_MKTIME
+AC_FUNC_MMAP
+AC_FUNC_STAT
+AC_FUNC_STRFTIME
+AC_FUNC_STRTOD
+AC_CHECK_FUNCS([__argz_count __argz_next __argz_stringify alarm dcgettext])
+AC_CHECK_FUNCS([getcwd getpgrp gethostbyname gethostname gettimeofday])
+AC_CHECK_FUNCS([getwd inet_ntoa memmove mempcpy memset mkdir munmap pow])
+AC_CHECK_FUNCS([putenv select setenv setlocale settimeofday signal sigignore])
+AC_CHECK_FUNCS([snprintf socket sqrt stpcpy strcasecmp strchr strdup])
+AC_CHECK_FUNCS([strerror strncasecmp strpbrk strptime strrchr strstr])
+AC_CHECK_FUNCS([strtof strtol strtoul tzset vsnprintf])
+
+# Check for deprecated/current pthread functions
+AC_CHECK_FUNCS([pthread_mutexattr_setkind_np pthread_mutexattr_settype])
+
+# this is a GNU extension and not present on all systems.
+AC_CHECK_FUNCS([strndup])
+
+#this is also a recent extension that should not be counted on
+AC_CHECK_FUNCS([roundf])
+
+# Check for intl library (Needed for Cygwin)
+#
+AC_CHECK_LIB(intl, gettext, LIBS="-lintl ${LIBS}")
+
+# Check for libproj (need to do this before test for shapelib, because
+# the shapelib test asks about "use_proj"
+use_proj=yes
+AC_ARG_WITH(libproj,[ --without-libproj Disable libproj features.],use_proj=$withval)
+if test "${use_proj}" = "yes"; then
+ use_proj=no
+ AC_CHECK_LIB(proj, pj_init, use_proj=yes LIBS="$LIBS -lproj"
+ AC_DEFINE(HAVE_PROJ, , Define to 1 if you have the `libproj' library (-lproj). )
+ )
+fi
+
+
+# Check for Shapelib
+use_shapelib=yes
+force_internal_shapelib=no
+shapelib_desired=yes
+LIBSHP=""
+SUBSHP=""
+# This symbol will be blank if the proj library hasn't been found, and will
+# have the three programs that need proj if it has
+CONTSHP=""
+AC_ARG_WITH(internal-shapelib,[ --with-internal-shapelib Force use of internal shapelib library.],force_internal_shapelib=$withval)
+AC_ARG_WITH(shapelib,[ --without-shapelib Disable shapelib features.],shapelib_desired=$withval)
+if test "${shapelib_desired}" = "no"; then
+ use_shapelib=no
+ force_internal_shapelib=no
+fi
+if test "${force_internal_shapelib}" = "yes"; then
+ AC_MSG_WARN([***************************************************************** ])
+ AC_MSG_WARN([Internal Shapelib library has been forced. ])
+ AC_MSG_WARN([***************************************************************** ])
+ # Temporary setting to get into if block below
+ use_shapelib=no
+fi
+if test "${shapelib_desired}" = "yes" -a "${force_internal_shapelib}" = "no"; then
+ use_shapelib=no
+ AC_CHECK_HEADERS(shapefil.h libshp/shapefil.h, [AC_CHECK_LIB(shp, DBFOpen, use_shapelib=yes
+ LIBS="$LIBS -lshp"
+ AC_CHECK_LIB(shp,DBFGetFieldIndex,
+ AC_DEFINE(HAVE_DBFGETFIELDINDEX, , Define to 1 if your `shp' library has DBFGetFieldIndex. ) )
+ AC_DEFINE(HAVE_LIBSHP, , Define to 1 if you have the `shp' library (-lshp). )
+ break)])
+fi
+if test "${shapelib_desired}" = "yes" -a "${use_shapelib}" = "no"; then
+ AC_MSG_WARN([**************************************************************** ])
+ AC_MSG_WARN([Your system does not have shapelib installed. Using an internal ])
+ AC_MSG_WARN([version. This may lead to a larger filesize for the executable. ])
+ AC_MSG_WARN([Install shapelib on your system to eliminate this warning. ])
+ AC_MSG_WARN([**************************************************************** ])
+ LIBSHP="-Lshapelib -lshape"
+ CPPFLAGS="-I\$(top_srcdir)/src/shapelib $CPPFLAGS"
+ SUBSHP="shapelib"
+ use_shapelib=yes
+ force_internal_shapelib=yes
+ AC_DEFINE(HAVE_DBFGETFIELDINDEX, , Define to 1 if your `shp' library has DBFGetFieldIndex. )
+ AC_DEFINE(HAVE_LIBSHP, , Define to 1 if you have the `shp' library (-lshp). )
+ AC_DEFINE(HAVE_SHAPEFIL_H, , Define to 1 if you have the `shapefil.h' header. )
+
+ if test $use_proj = "yes"
+ then
+ CONTSHP="shpcentrd shpproj shpdata shpwkb"
+ fi
+fi
+AC_SUBST(SUBSHP)
+AC_SUBST(CONTSHP)
+AC_SUBST(LIBSHP)
+
+
+# Check for pcre
+use_pcre=yes
+AC_ARG_WITH(pcre,[ --without-pcre Disable pcre features.],use_pcre=$withval)
+if test "${use_pcre}" = "yes"; then
+ use_pcre=no
+ AC_CHECK_HEADERS(pcre.h pcre/pcre.h, [AC_CHECK_LIB(pcre, pcre_compile, use_pcre=yes
+ LIBS="$LIBS -lpcre"
+ AC_DEFINE(HAVE_LIBPCRE, , Define to 1 if you have the `pcre' library (-lpcre). )
+ break)])
+fi
+
+
+# Check for XPM
+if test "${use_lsb}" = "no"; then
+ AC_CHECK_HEADERS(X11/xpm.h, AC_SEARCH_LIBS(XpmWriteFileFromPixmap, Xpm, AC_DEFINE(HAVE_LIBXPM, , Define to 1 if you have the `Xpm' library (-lXpm). )))
+ AC_CHECK_HEADERS(Xm/XpmI.h, AC_SEARCH_LIBS(XmeXpmWriteFileFromPixmap, Xm, AC_DEFINE(HAVE_LIBXPM_IN_XM, , Define to 1 if the `Xm' library (-lXm) is used for Xpm. )))
+else
+ AC_DEFINE(HAVE_LIBXPM, , Define to 1 if you have the `Xpm' library (-lXpm). )
+ AC_DEFINE(HAVE_LIBXPM_IN_XM, , Define to 1 if the `Xm' library (-lXm) is used for Xpm. )
+ AC_DEFINE(HAVE_X11_XPM_H, , Define to 1 if you have 'X11/xpm.h' )
+fi
+
+
+#check for libtiff, libgeotiff
+# libjpeg.a and libz.a need to be compiled under LSB
+
+
+use_geotiff=yes
+AC_ARG_WITH(geotiff, [ --without-geotiff Disable geotiff features.], use_geotiff=$withval)
+if test "${use_geotiff}" = "yes"; then
+ if test "${use_proj}" = "yes" ; then
+ if test "${use_lsb}" = "yes" ; then
+ use_tiff=yes
+ use_geotiff=yes
+ LIBS="$LIBS -lgeotiff -ltiff -ljpeg -lz -lproj"
+ AC_DEFINE(HAVE_TIFF, ,Define to 1 if you have the 'tiff' library (-ltiff))
+ AC_DEFINE(HAVE_LIBGEOTIFF, ,Define to 1 if you have the `geotiff' library (-lgeotiff).)
+ else
+ AC_CHECK_HEADER(xtiffio.h, , use_geotiff="no")
+ if test "${use_geotiff}" = "yes"; then
+ AC_CHECK_LIB(tiff, TIFFClose, use_tiff=yes
+ LIBS="$LIBS -ltiff"
+ AC_DEFINE(HAVE_TIFF, ,Define to 1 if you have the 'tiff' library (-ltiff)))
+ if test "${use_tiff}" = "yes"; then
+ use_geotiff=no
+ AC_CHECK_LIB(geotiff, GTIFNew, use_geotiff=yes
+ LIBS="$LIBS -lgeotiff"
+ AC_DEFINE(HAVE_LIBGEOTIFF, ,Define to 1 if you have the `geotiff' library (-lgeotiff).))
+ else
+ echo "*** Warning: geotiff requires libtiff."
+ use_geotiff=no
+ fi
+ else
+ echo "*** Warning: geotiff include files not found."
+ fi
+ fi
+ else
+ echo "*** Warning: geotiff requires libproj."
+ use_geotiff=no
+ fi
+fi
+
+# Check for spatial database support
+use_postgis=no
+AC_ARG_WITH(postgis, [ --with-postgis Enable Postgresql with PostGIS.],use_postgis=$withval)
+if test "${use_postgis}" != "no"; then
+ XASTIR_CHECK_POSTGIS
+fi
+use_mysql=no
+AC_ARG_WITH(mysql, [ --with-mysql Enable MySQL, with spatial support if available.],use_mysql=$withval)
+if test "${use_mysql}" != "no"; then
+ XASTIR_CHECK_MYSQL
+fi
+
+if test "${use_postgis}" = "yes"; then
+ use_spatial_db=yes
+ AC_DEFINE(HAVE_SPATIAL_DB, 1, [Spatial database support available] )
+ AC_DEFINE(HAVE_DB, 1, [Database support available] )
+fi
+if test "${use_mysql_spatial}" = "yes"; then
+ use_spatial_db=yes
+ AC_DEFINE(HAVE_DB, 1, [Database support available] )
+ AC_DEFINE(HAVE_SPATIAL_DB, 1, [Spatial database support available] )
+elif test use_mysql_any = "yes"; then
+ AC_DEFINE(HAVE_DB, 1, [Database support available] )
+fi
+
+# Check for AX.25 library
+use_ax25=yes
+AC_ARG_WITH(ax25,[ --without-ax25 Disable ax25 features.],use_ax25=$withval)
+if test "${use_ax25}" = "yes"; then
+ use_ax25=no
+ AC_CHECK_HEADERS(netax25/ax25.h, [AC_CHECK_LIB(ax25, ax25_config_load_ports, use_ax25=yes
+ LIBS="$LIBS -lax25"
+ AC_DEFINE(HAVE_LIBAX25, , Define to 1 if you have the `ax25' library (-lax25). )
+ break)])
+fi
+
+
+# use dbfawk
+use_dbfawk=yes
+AC_ARG_WITH(dbfawk,[ --without-dbfawk Disable dbfawk features.],use_dbfawk=$withval)
+# dbfawk requires shapelib and pcre. Make sure:
+if test "${use_dbfawk}" = "yes"; then
+ if test "${use_pcre}" = "yes" -a "${use_shapelib}" = "yes"; then
+ AC_DEFINE(WITH_DBFAWK, , Define to 1 to use dbfawk features. )
+ else
+ echo "*** Warning: dbfawk requires both pcre and shapelib."
+ use_dbfawk=no
+ fi
+fi
+
+
+# Check for GDAL. Make sure that the GDAL check is towards the
+# last, as it can mess up shapelib and libgeotiff currently.
+use_gdal=yes
+AC_ARG_WITH(gdal,[ --without-gdal Disable gdal features.],use_gdal=$withval)
+if test "${use_gdal}" = "yes"; then
+ if test "${use_lsb}" = "no"; then
+ XASTIR_CHECK_GDAL
+ else
+ CPPFLAGS="$CPPFLAGS -I/opt/lsb-tmp/include"
+ LDFLAGS="$LDFLAGS -L/opt/lsb-tmp/lib -lgdal"
+ LIBS="$LIBS -lgdal"
+ AC_DEFINE(HAVE_LIBGDAL, , [Define to 1 if you have the `gdal' library (-lgdaal).])
+ fi
+fi
+
+use_rtree=yes
+LIBRTREE=""
+SUBRTREE=""
+AC_ARG_WITH(rtree,[ --without-rtree Disable spatial indexing of shapefiles.],[use_rtree=$withval])
+if test "${use_rtree}" = "yes" ; then
+ if test "${use_shapelib}" = "yes"; then
+ AC_DEFINE([USE_RTREE],1,[RTree spatial indexing])
+ LIBRTREE="-Lrtree -lrtree"
+ SUBRTREE="rtree"
+ else
+ echo "*** Warning: rtree requires shapelib."
+ use_rtree=no
+ fi
+fi
+AC_SUBST(SUBRTREE)
+AC_SUBST(LIBRTREE)
+
+
+
+
+AC_ARG_ENABLE(davis, [ --enable-davis Turn on Davis support],
+ [case "${enableval}" in
+ yes) davis=true ;;
+ no) davis=false ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-davis) ;;
+ esac],[davis=false])
+AM_CONDITIONAL(DAVIS, test x$davis = xtrue)
+if test "${davis}" = "true"; then
+ davis=yes
+else
+ davis=no
+fi
+
+
+
+
+
+# Check for LIBGC, a Garbage Collection library. If found, allow
+# linking it with Xastir, but require the "--with-libgc" flag to
+# enable it.
+use_libgc=no
+AC_ARG_WITH(libgc,[ --with-libgc Enable libgc features.],use_libgc=$withval)
+if test "${use_libgc}" = "yes"; then
+ AC_CHECK_HEADERS([gc.h], LIBGC_INC="yes", use_libgc=no)
+ AC_CHECK_LIB([gc], [GC_init], , use_libgc=no)
+fi
+
+
+
+
+
+# Check whether profiling was requested. If so, add the "-pg" flag
+# to CFLAGS. Require "--with-profiling" flag to enable it.
+use_profiling=no
+AC_ARG_WITH(profiling,[ --with-profiling Enable profiling features.],use_profiling=$withval)
+if test "${use_profiling}" = "yes"; then
+ CFLAGS="$CFLAGS -pg"
+fi
+
+
+
+
+
+# Check for Berkeley DB.
+use_map_cache=yes
+AC_ARG_WITH(map_cache,[ --without-map-cache Disable Map Caching.],use_map_cache=$withval)
+if test "${use_map_cache}" = "yes"; then
+ XASTIR_BERKELEY_DB_CHK
+fi
+
+
+
+
+
+# Check for GraphicsMagick. If not available/desired then check for
+# ImageMagick. These checks are VERY important to have as the last,
+# as they mess up previous checks if they fail.
+#
+use_graphicsmagick=yes
+use_imagemagick=no
+AC_ARG_WITH(graphicsmagick,[ --without-graphicsmagick Disable graphicsmagick features.],use_graphicsmagick=$withval)
+if test "${use_graphicsmagick}" = "yes"; then
+ if test "${use_lsb}" = "no"; then
+ XASTIR_CHECK_GRAPHICSMAGICK
+ else
+ MAGIC_BIN="/opt/lsb-tmp/bin/GraphicsMagick-config"
+ CPPFLAGS="$CPPFLAGS `${MAGIC_BIN} --cppflags`"
+ CXXFLAGS="$CXXFLAGS `${MAGIC_BIN} --cflags`"
+ LDFLAGS="$LDFLAGS `${MAGIC_BIN} --ldflags`"
+ LIBS="${MAGIC_LIB_DIR} `${MAGIC_BIN} --libs` $LIBS"
+ AC_DEFINE(HAVE_GRAPHICSMAGICK, 1, [GraphicsMagick image library])
+ fi
+fi
+#
+# Note: This must be a separate "if" as the use_graphicsmagick
+# variable gets set to "no" if GM is not available above.
+#
+if test "${use_graphicsmagick}" = "no"; then
+ use_imagemagick=yes
+ AC_ARG_WITH(imagemagick,[ --without-imagemagick Disable imagemagick features.],use_imagemagick=$withval)
+ if test "${use_imagemagick}" = "yes"; then
+ XASTIR_CHECK_IMAGEMAGICK
+ fi
+fi
+#
+#
+#
+if test "${use_imagemagick}" = "yes" -o "${use_graphicsmagick}" = "yes"; then
+ AC_DEFINE(HAVE_MAGICK, 1, [GraphicsMagick or ImageMagick library])
+fi
+
+
+
+
+
+# Set XASTIR_DATA_BASE in CPPFLAGS due to Gnu coding standard that requires
+# datadir expansion to be deferred until make time.
+if test "x${datadir}" = "x"; then
+ CPPFLAGS="$CPPFLAGS -DXASTIR_DATA_BASE=\\\"${ac_default_prefix}/share/xastir\\\""
+else
+ CPPFLAGS="$CPPFLAGS -DXASTIR_DATA_BASE=\\\"${datadir}/xastir\\\""
+fi
+
+
+
+# Add a special option that makes Cygwin link much faster (from
+# Henk de Groot)
+save_LDFLAGS="$LDFLAGS"
+LDFLAGS="-Wl,--no-keep-memory $LDFLAGS"
+AC_TRY_LINK([#include <sys/types.h>],
+ [/* Stupid useless test for linker flags */
+ exit(0);],
+ xa_cv_no_keep_memory=yes,
+ xa_cv_no_keep_memory=no)
+if test "${xa_cv_no_keep_memory}" = "no"; then
+ LDFLAGS="$save_LDFLAGS"
+fi
+
+#
+# Assure we have this order for these LIBS: "-lXm -lXt -lX11" by
+# adding them to the beginning. Add spaces around them for the
+# following steps. Here I'm adding them to the beginning so the
+# dupe-check portion will take out the later ones that might be in
+# the wrong order. If they're in the wrong order, we can get
+# "Error: Shell widget xastir has zero width and/or height" when
+# Xastir is started up. Can also get "Error: attempt to add
+# non-widget child "DropSiteManager" to parent", but that can also
+# be caused by other problems with libraries.
+#
+LIBS=" -lXm -lXt -lX11 $LIBS"
+
+#
+# Remove duplicate entries. Thanks to Paul Lutt, ke7xt, for this!
+#
+# Don't get rid of dupes on the LIBS line. We may need the same
+# "-Llibdir" called out several times, immediately prior to each
+# "-llibrary" that needs it.
+#
+changequote(,)
+CFLAGS=`echo "$CFLAGS" | awk '{for(i=1;i<=NF;++i) {if (arg[$i]++ == 0) s = s " " $i} print s}'`
+CPPFLAGS=`echo "$CPPFLAGS" | awk '{for(i=1;i<=NF;++i) {if (arg[$i]++ == 0) s = s " " $i} print s}'`
+LDFLAGS=`echo "$LDFLAGS" | awk '{for(i=1;i<=NF;++i) {if (arg[$i]++ == 0) s = s " " $i} print s}'`
+#LIBS=`echo "$LIBS" | awk '{for(i=1;i<=NF;++i) {if (arg[$i]++ == 0) s = s " " $i} print s}'`
+changequote([,])
+
+
+#
+# Remove "-g" CFLAGS/CPPFLAGS entries. Note: This is a _bad_ idea
+# as debuggers won't have a symbol table to work from!
+#
+#changequote(,)
+#CFLAGS=`echo "$CFLAGS" | awk '{for(i=1;i<=NF;++i) {if ($i != "-g") s = s " " $i} print s}'`
+#CPPFLAGS=`echo "$CPPFLAGS" | awk '{for(i=1;i<=NF;++i) {if ($i != "-g") s = s " " $i} print s}'`
+#changequote([,])
+
+
+#
+# Change the compiler optimization if using Windows/Cygwin in order
+# to reduce memory usage and speed up the compile. Here we change
+# "-O2" to "-O1" or " " in CFLAGS/CPPFLAGS to reduce the level of
+# optimization.
+# We also wish to remove "-no-undefined" from LDFLAGS on Cygwin, as
+# we use GCC for our linking instead of libtool, and GCC doesn't
+# like that flag at the link stage.
+#
+case "$host_os" in
+cygwin*)
+ changequote(,)
+ CFLAGS=`echo "$CFLAGS" | awk '{for(i=1;i<=NF;++i) {if ($i != "-O2") s = s " " $i} print s}'`
+ CPPFLAGS=`echo "$CPPFLAGS" | awk '{for(i=1;i<=NF;++i) {if ($i != "-O2") s = s " " $i} print s}'`
+ LDFLAGS=`echo "$LDFLAGS" | awk '{for(i=1;i<=NF;++i) {if ($i != "-no-undefined") s = s " " $i} print s}'`
+ changequote([,])
+;;
+esac
+
+
+# Create the ILIBS defined variable. We add spaces here in the else
+# clauses in order to make the REGRESSION_TESTS format nicely. We
+# take them back out before we define the variable that Xastir uses
+# for it's Help->About dialog.
+#
+if test "${use_ax25}" = "yes"; then
+ ILIBS="AX25"
+else
+ ILIBS=" "
+fi
+if test "${use_festival}" = "yes"; then
+ ILIBS="$ILIBS Festival"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_gpsman}" = "yes"; then
+ ILIBS="$ILIBS GPSMan"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_graphicsmagick}" = "yes"; then
+ ILIBS="$ILIBS GraphicsMagick"
+else
+ if test "${use_imagemagick}" = "yes"; then
+ ILIBS="$ILIBS ImageMagick "
+ else
+ ILIBS="$ILIBS "
+ fi
+fi
+if test "${use_proj}" = "yes"; then
+ ILIBS="$ILIBS libProj"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_geotiff}" = "yes"; then
+ ILIBS="$ILIBS GeoTiff"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_gdal}" = "yes"; then
+ ILIBS="$ILIBS GDAL/OGR"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_shapelib}" = "yes"; then
+ ILIBS="$ILIBS ShapeLib"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_pcre}" = "yes"; then
+ ILIBS="$ILIBS PCRE"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_dbfawk}" = "yes"; then
+ ILIBS="$ILIBS Dbfawk"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_map_cache}" = "yes"; then
+ ILIBS="$ILIBS map_caching"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_err_popups}" = "yes"; then
+ ILIBS="$ILIBS error_popups"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_libgc}" = "yes"; then
+ ILIBS="$ILIBS libgc"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_profiling}" = "yes"; then
+ ILIBS="$ILIBS profiling"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_rtree}" = "yes"; then
+ ILIBS="$ILIBS rtree"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_lsb}" = "yes"; then
+ ILIBS="$ILIBS LSB"
+else
+ ILIBS="$ILIBS "
+fi
+if test "${use_curl}" = "yes"; then
+ ILIBS="$ILIBS libcurl"
+else
+ if test "${use_wget}" = "yes"; then
+ ILIBS="$ILIBS wget "
+ else
+ ILIBS="$ILIBS "
+ fi
+fi
+
+# Write out the library information to "summary.log". Here we want
+# the spaces for the undefined pieces, so REGRESSION_TESTS formats
+# nicely.
+echo "$ILIBS" >summary.log
+
+
+#
+# Remove extraneous spaces from output variables (asthetic)
+#
+ILIBS=`echo $ILIBS | sed -e 's/ */ /g'`
+X_CFLAGS=`echo $X_CFLAGS | sed -e 's/ */ /g'`
+X_PRE_LIBS=`echo $X_PRE_LIBS | sed -e 's/ */ /g'`
+X_LIBS=`echo $X_LIBS | sed -e 's/ */ /g'`
+X_EXTRA_LIBS=`echo $X_EXTRA_LIBS | sed -e 's/ */ /g'`
+
+CC=`echo $CC | sed -e 's/ */ /g'`
+CFLAGS=`echo $CFLAGS | sed -e 's/ */ /g'`
+CPPFLAGS=`echo $CPPFLAGS | sed -e 's/ */ /g'`
+CXXFLAGS=`echo $CXXFLAGS | sed -e 's/ */ /g'`
+LDFLAGS=`echo $LDFLAGS | sed -e 's/ */ /g'`
+TESTED_LIBS=`echo $LIBS | sed -e 's/ */ /g'`
+MAGICK_DEP_LIBS=`echo $MAGICK_DEP_LIBS | sed -e 's/ */ /g'`
+LIBS=`echo $LIBS | sed -e 's/ */ /g'`
+
+
+# Change the output text for Shapelib if we're using the internal
+# library. The below will be used for the configure summary and for
+# the Help->About text in Xastir.
+if test "${force_internal_shapelib}" = "yes"; then
+ ILIBS=`echo $ILIBS | sed -e 's/ShapeLib/ShapeLib(internal)/g'`
+ use_shapelib="yes (internal)"
+fi
+
+
+
+tmp_path="$ac_default_prefix"
+tmp_bin_path="$ac_default_prefix"
+if test "x$prefix" != xNONE; then
+ tmp_path="$prefix"
+ tmp_bin_path="$prefix"
+fi
+if test "x$exec_prefix" != xNONE; then
+ tmp_bin_path="$exec_prefix"
+fi
+AC_DEFINE_UNQUOTED(XASTIR_PATH, "`echo $tmp_path`", [Path to installed Xastir files.])
+AC_DEFINE_UNQUOTED(XASTIR_BIN_PATH, "`echo $tmp_bin_path`", [Path to installed Xastir binaries.])
+
+
+
+AC_DEFINE_UNQUOTED(XASTIR_INSTALLED_LIBS, "`echo $ILIBS`", [Defines the installed libs])
+
+
+AC_SUBST(LDFLAGS)
+AC_SUBST(LIBS)
+#AC_SUBST(CPPFLAGS)
+AC_SUBST(X_CFLAGS)
+#AC_SUBST(LDFLAGS)
+#AC_SUBST(X_PRE_LIBS)
+#AC_SUBST(X_LIBS)
+#AC_SUBST(X_EXTRA_LIBS)
+
+AC_CONFIG_FILES([Makefile \
+ callpass/Makefile \
+ config/Makefile \
+ help/Makefile \
+ m4/Makefile \
+ scripts/Makefile \
+ scripts/values \
+ scripts/values.pl \
+ src/Makefile \
+ src/rtree/Makefile \
+ src/shapelib/Makefile \
+ src/shapelib/contrib/Makefile \
+ symbols/Makefile \
+ xastir.spec \
+ xastir-min.spec \
+ xastir-lsb.spec])
+
+AC_OUTPUT
+
+# Please leave these in as they're very useful for debug when we
+# port to new platforms! Leave them commented out unless doing
+# debugging on the configure scripts.
+#
+#echo ""
+#echo " LIBS: $LIBS"
+#echo " LDFLAGS: $LDFLAGS"
+#echo " CFLAGS: $CFLAGS"
+#echo " CPPFLAGS: $CPPFLAGS"
+#echo " X_LIBS: $X_LIBS"
+#echo " X_PRE_LIBS: $X_PRE_LIBS"
+#echo "X_EXTRA_LIBS: $X_EXTRA_LIBS"
+
+
+# Write a short summary of the configure tests/results to
+# "summary.log"
+egrep -e "checking |result:|gcc version" config.log >> summary.log
+
+
+echo ===========================================
+echo
+echo AC_PACKAGE_NAME AC_PACKAGE_VERSION has been configured to use the following
+echo options and external libraries:
+echo
+echo MINIMUM OPTIONS:
+echo " ShapeLib (Vector maps) ................. : $use_shapelib"
+echo
+echo RECOMMENDED OPTIONS:
+
+echo -n " GraphicsMagick/ImageMagick (Raster maps) : "
+if test "${use_graphicsmagick}" = "yes"; then
+ echo "yes (GraphicsMagick)"
+else
+ if test "${use_imagemagick}" = "yes"; then
+ echo "yes (ImageMagick)"
+ else
+ echo "no"
+ fi
+fi
+echo " pcre (Shapefile customization) ......... : $use_pcre"
+echo " dbfawk (Shapefile customization) ....... : $use_dbfawk"
+echo " rtree indexing (Shapefile speedups) .... : $use_rtree"
+echo " map caching (Raster map speedups) ...... : $use_map_cache"
+echo " internet map retrieval ................. : $use_retrieval"
+echo
+echo FOR THE ADVENTUROUS:
+echo " AX25 (Linux Kernel I/O Drivers) ........ : $use_ax25"
+echo " libproj (USGS Topos & Aerial Photos) ... : $use_proj"
+echo " GeoTiff (USGS Topos & Aerial Photos) ... : $use_geotiff"
+echo " Festival (Text-to-speech) .............. : $use_festival"
+echo " GDAL/OGR (Obtuse map formats) .......... : $use_gdal"
+echo " GPSMan/gpsmanshp (GPS downloads) ....... : $use_gpsman"
+#echo " GPSD Client (libgps) ................... : $use_libgps"
+
+if test "${use_err_popups}" = "yes" -o "${use_libgc}" = "yes" -o "${use_profiling}" = "yes" -o "${use_lsb}" = "yes" -o "${use_spatial_db}" = "yes" -o "$use_mysql_any" = "yes"; then
+ echo
+ echo DEVELOPER OPTIONS:
+ echo " ErrorPopups (Old Method) ............... : $use_err_popups"
+ echo " libgc (Debug memory usage) ............. : $use_libgc"
+ echo " profiling (Debug code efficiency) ...... : $use_profiling"
+ echo " Linux Standard Base (LSB) .............. : $use_lsb"
+ echo " Spatial database support ............... : $use_spatial_db"
+ echo " Spatial database Postgresql/Postgis .... : $use_postgis"
+ echo " MySQL .................................. : $use_mysql_any"
+ echo " MySQL Spatial database support ......... : $use_mysql_spatial"
+fi
+
+#echo Davis/MySQL............................. : $davis
+echo
+echo AC_PACKAGE_NAME will be installed in $prefix/bin.
+if test "x$xastirpath" != "x" ; then
+ echo Warning: You have an old copy of Xastir at $xastirpath.
+fi
+echo "Type 'make' to build Xastir (Use 'gmake' instead on some systems)."
+
+
diff --git a/depcomp b/depcomp
new file mode 100755
index 0000000..df8eea7
--- /dev/null
+++ b/depcomp
@@ -0,0 +1,630 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
+# Software Foundation, Inc.
+
+# 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, 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, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva at dcc.unicamp.br>.
+
+case $1 in
+ '')
+ echo "$0: No command. Try \`$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+ depmode Dependency tracking mode.
+ source Source file read by `PROGRAMS ARGS'.
+ object Object file output by `PROGRAMS ARGS'.
+ DEPDIR directory where to store dependencies.
+ depfile Dependency file to output.
+ tmpdepfile Temporary file to use when outputing dependencies.
+ libtool Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake at gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "depcomp $scriptversion"
+ exit $?
+ ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
+ exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+ sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags. We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write. Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+ # HP compiler uses -M and no extra arg.
+ gccflag=-M
+ depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+ # This is just like msvisualcpp but w/o cygpath translation.
+ # Just convert the backslash-escaped backslashes to single forward
+ # slashes to satisfy depend.m4
+ cygpath_u="sed s,\\\\\\\\,/,g"
+ depmode=msvisualcpp
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want. Yay! Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff. Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am. Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+ for arg
+ do
+ case $arg in
+ -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+ *) set fnord "$@" "$arg" ;;
+ esac
+ shift # fnord
+ shift # $arg
+ done
+ "$@"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## There are various ways to get dependency output from gcc. Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+## up in a subdir. Having to rename by hand is ugly.
+## (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+## -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+## than renaming).
+ if test -z "$gccflag"; then
+ gccflag=-MD,
+ fi
+ "$@" -Wp,"$gccflag$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+ sed -e 's/^[^:]*: / /' \
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header). We avoid this by adding
+## dummy dependencies for each header file. Too bad gcc doesn't do
+## this for us directly.
+ tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'. On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+sgi)
+ if test "$libtool" = yes; then
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
+ else
+ "$@" -MDupdate "$tmpdepfile"
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
+ echo "$object : \\" > "$depfile"
+
+ # Clip off the initial element (the dependent). Don't try to be
+ # clever and replace this with sed code, as IRIX sed won't handle
+ # lines with more than a fixed number of characters (4096 in
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
+ # the IRIX cc adds comments like `#:fec' to the end of the
+ # dependency line.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+ tr '
+' ' ' >> "$depfile"
+ echo >> "$depfile"
+
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+aix)
+ # The C for AIX Compiler uses -M and outputs the dependencies
+ # in a .u file. In older versions, this file always lives in the
+ # current directory. Also, the AIX compiler puts `$object:' at the
+ # start of each line; $object doesn't have directory information.
+ # Version 6 uses the directory in both cases.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$base.u
+ tmpdepfile3=$dir.libs/$base.u
+ "$@" -Wc,-M
+ else
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$dir$base.u
+ tmpdepfile3=$dir$base.u
+ "$@" -M
+ fi
+ stat=$?
+
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ # Each line is of the form `foo.o: dependent.h'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+icc)
+ # Intel's C compiler understands `-MD -MF file'. However on
+ # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+ # ICC 7.0 will fill foo.d with something like
+ # foo.o: sub/foo.c
+ # foo.o: sub/foo.h
+ # which is wrong. We want:
+ # sub/foo.o: sub/foo.c
+ # sub/foo.o: sub/foo.h
+ # sub/foo.c:
+ # sub/foo.h:
+ # ICC 7.1 will output
+ # foo.o: sub/foo.c sub/foo.h
+ # and will wrap long lines using \ :
+ # foo.o: sub/foo.c ... \
+ # sub/foo.h ... \
+ # ...
+
+ "$@" -MD -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ # Each line is of the form `foo.o: dependent.h',
+ # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process this invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+ sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp2)
+ # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+ # compilers, which have integrated preprocessors. The correct option
+ # to use with these is +Maked; it writes dependencies to a file named
+ # 'foo.d', which lands next to the object file, wherever that
+ # happens to be.
+ # Much of this is similar to the tru64 case; see comments there.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir.libs/$base.d
+ "$@" -Wc,+Maked
+ else
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir$base.d
+ "$@" +Maked
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
+ # Add `dependent.h:' lines.
+ sed -ne '2,${
+ s/^ *//
+ s/ \\*$//
+ s/$/:/
+ p
+ }' "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile" "$tmpdepfile2"
+ ;;
+
+tru64)
+ # The Tru64 compiler uses -MD to generate dependencies as a side
+ # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+ # dependencies in `foo.d' instead, so we check for that too.
+ # Subdirectories are respected.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+ if test "$libtool" = yes; then
+ # With Tru64 cc, shared objects can also be used to make a
+ # static library. This mechanism is used in libtool 1.4 series to
+ # handle both shared and static libraries in a single compilation.
+ # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+ #
+ # With libtool 1.5 this exception was removed, and libtool now
+ # generates 2 separate objects for the 2 libraries. These two
+ # compilations output dependencies in $dir.libs/$base.o.d and
+ # in $dir$base.o.d. We have to check for both files, because
+ # one of the two compilations can be disabled. We should prefer
+ # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+ # automatically cleaned when .libs/ is deleted, while ignoring
+ # the former would cause a distcleancheck panic.
+ tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
+ tmpdepfile2=$dir$base.o.d # libtool 1.5
+ tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
+ tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
+ "$@" -Wc,-MD
+ else
+ tmpdepfile1=$dir$base.o.d
+ tmpdepfile2=$dir$base.d
+ tmpdepfile3=$dir$base.d
+ tmpdepfile4=$dir$base.d
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+#nosideeffect)
+ # This comment above is used by automake to tell side-effect
+ # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ test -z "$dashmflag" && dashmflag=-M
+ # Require at least two characters before searching for `:'
+ # in the target name. This is to cope with DOS-style filenames:
+ # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+ "$@" $dashmflag |
+ sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+dashXmstdout)
+ # This case only exists to satisfy depend.m4. It is never actually
+ # run, as this mode is specially recognized in the preamble.
+ exit 1
+ ;;
+
+makedepend)
+ "$@" || exit $?
+ # Remove any Libtool call
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+ # X makedepend
+ shift
+ cleared=no eat=no
+ for arg
+ do
+ case $cleared in
+ no)
+ set ""; shift
+ cleared=yes ;;
+ esac
+ if test $eat = yes; then
+ eat=no
+ continue
+ fi
+ case "$arg" in
+ -D*|-I*)
+ set fnord "$@" "$arg"; shift ;;
+ # Strip any option that makedepend may not understand. Remove
+ # the object too, otherwise makedepend will parse it as a source file.
+ -arch)
+ eat=yes ;;
+ -*|$object)
+ ;;
+ *)
+ set fnord "$@" "$arg"; shift ;;
+ esac
+ done
+ obj_suffix=`echo "$object" | sed 's/^.*\././'`
+ touch "$tmpdepfile"
+ ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
+ ;;
+
+cpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ "$@" -E |
+ sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+ sed '$ s: \\$::' > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ cat < "$tmpdepfile" >> "$depfile"
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvisualcpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ IFS=" "
+ for arg
+ do
+ case "$arg" in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+ set fnord "$@"
+ shift
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift
+ shift
+ ;;
+ esac
+ done
+ "$@" -E 2>/dev/null |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
+ echo " " >> "$depfile"
+ sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvcmsys)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/help/Makefile.am b/help/Makefile.am
new file mode 100644
index 0000000..4762083
--- /dev/null
+++ b/help/Makefile.am
@@ -0,0 +1,22 @@
+# $Id: Makefile.am,v 1.12 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+helpdir = ${pkgdatadir}/help
+EXTRA_DIST = \
+ help-Dutch.dat \
+ help-English.dat \
+ help-French.dat \
+ help-German.dat \
+ help-Italian.dat \
+ help-Portuguese.dat \
+ help-Spanish.dat
+
+help_DATA = \
+ help-Dutch.dat \
+ help-English.dat \
+ help-French.dat \
+ help-German.dat \
+ help-Italian.dat \
+ help-Portuguese.dat \
+ help-Spanish.dat
diff --git a/help/Makefile.in b/help/Makefile.in
new file mode 100644
index 0000000..8a4dbd1
--- /dev/null
+++ b/help/Makefile.in
@@ -0,0 +1,430 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = help
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(helpdir)"
+DATA = $(help_DATA)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTSHP = @CONTSHP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GMAGIC_BIN = @GMAGIC_BIN@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBCOMPAT = @LIBCOMPAT@
+LIBOBJS = @LIBOBJS@
+LIBRTREE = @LIBRTREE@
+LIBS = @LIBS@
+LIBSHP = @LIBSHP@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LWPOSTGIS = @LWPOSTGIS@
+MAGIC_BIN = @MAGIC_BIN@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PG_CONFIG = @PG_CONFIG@
+POW_LIB = @POW_LIB@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUBRTREE = @SUBRTREE@
+SUBSHP = @SUBSHP@
+VERSION = @VERSION@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+convert = @convert@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+festival = @festival@
+found_gdal_config = @found_gdal_config@
+gm = @gm@
+gpsman = @gpsman@
+gv = @gv@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lpr = @lpr@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+mv = @mv@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sed = @sed@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+wget = @wget@
+xfontsel = @xfontsel@
+
+# $Id: Makefile.am,v 1.12 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+helpdir = ${pkgdatadir}/help
+EXTRA_DIST = \
+ help-Dutch.dat \
+ help-English.dat \
+ help-French.dat \
+ help-German.dat \
+ help-Italian.dat \
+ help-Portuguese.dat \
+ help-Spanish.dat
+
+help_DATA = \
+ help-Dutch.dat \
+ help-English.dat \
+ help-French.dat \
+ help-German.dat \
+ help-Italian.dat \
+ help-Portuguese.dat \
+ help-Spanish.dat
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu help/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu help/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-helpDATA: $(help_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(helpdir)" || $(MKDIR_P) "$(DESTDIR)$(helpdir)"
+ @list='$(help_DATA)'; test -n "$(helpdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(helpdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(helpdir)" || exit $$?; \
+ done
+
+uninstall-helpDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(help_DATA)'; test -n "$(helpdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(helpdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(helpdir)" && rm -f $$files
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(helpdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-helpDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-helpDATA
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic distclean \
+ distclean-generic distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-helpDATA \
+ install-html install-html-am install-info install-info-am \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \
+ uninstall-am uninstall-helpDATA
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/help/help-Dutch.dat b/help/help-Dutch.dat
new file mode 100644
index 0000000..a858ac6
--- /dev/null
+++ b/help/help-Dutch.dat
@@ -0,0 +1,3099 @@
+HELP-INDEX>READ ME FIRST - License
+
+ READ ME FIRST - License
+
+For the most current information please read the README file in the Xastir
+directory. Also see the LICENSE and COPYING files for additional information.
+
+Remember this program is intended to be used by the HAM community, in the USA
+the FCC restricts you from transmitting over RF if you are not a licensed HAM.
+Users in countries outside the USA should seek their local government
+restrictions.
+
+LICENSE:
+
+XASTIR, Amateur Station Tracking and Information Reporting
+Copyright (C) 1999,2000 Frank Giannandrea
+Copyright (C) 2000-2012 The Xastir Group
+
+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.
+
+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.
+
+More information on the program can be found at:
+
+ http://www.xastir.org
+ http://sourceforge.net/projects/xastir/
+ http://xastir.sourceforge.net
+
+There are some mailing lists available that are Xastir-specific.
+Please subscribe to one or both of them for the latest Xastir
+information. See http://www.xastir.org to subscribe.
+
+For more information on the GNU License look at:
+http://www.gnu.org
+
+
+HELP-INDEX>Welcome! and Notes from the Authors
+
+ Welcome! and Notes from the Authors
+
+XASTIR, or X-windows Amateur Station Tracking and Information Reporting.
+
+Xastir is an APRS(tm) program that is Open Source and free to use and
+pass out to others. Currently this program is in development and should
+not be seen as a finished product! Your help will be needed to make this
+a better program. If you have programming skills and/or can write
+documentation, your help may be needed! We have a lot of ideas but very
+little time, so if you think you can add something to the effort let us
+know!
+
+
+
+APRS(tm) is a Trademark of Bob Bruninga, his home page is at
+"http://web.usna.navy.mil/~bruninga/aprs.html". A great deal of information
+on APRS(tm) can be found in the APRSdos documentation written by
+Bob Bruninga. An additional source of information is the APRS(tm)
+specification, available from http://www.tapr.org .
+
+HELP-INDEX>What's new in Xastir 2.0.1
+(Changes between 1.7 and 2.0.0 were never recorded here,this block
+describes a few of the changes from 1.9.8 to 2.0.0 that occured right
+before release of 2.0.0, but otherwise documents only changes from 2.0.0
+to 2.0.1)
+
+Added tiling for OpenStreetMaps (2.0.0).
+Added "setlocale()" calls to assure we aren't confused by user
+LANG variable settings.
+Improved speed of config file processing.
+Fixes for new One-Wire-Daemon protocol, allowing both old and
+new to work with Xastir.
+Fixed segfaults that could happen when closing list dialogs.
+Fix OSM code to support 16-bit quanta in Graphics/ImageMagick.
+Fixed broken makefile that was ignoring DESTDIR.
+Fixed broken build so internal shapelib builds correctly when
+proj.4 is not installed.
+Add dbfawk files for several generations of new NWS shapefiles.
+Update get-NWSdata to pull current NWS shapefiles.
+Add start/stop files for Kenwood D72 and D710 radios.
+Added a script to convert GeoPDF files to usable GeoTIFF files.
+Make the command to set a TNC into CONVERSE mode a run-time
+configurable option in the TNC Interface Properties dialog.
+Add support for Australian Bureau of Metrology weather alerts.
+Fixes for Davis APRS Data Logger, Davis Meteo and LaCrosse
+support so it gets rain totals correct.
+Allow "posit interval" in File->Configure->Timing to go all the
+way to zero, meaning "never send posits on a schedule."
+Add signal support so that Xastir will emit a posit when it
+receives SIGUSR2. Combined with zero "posit interval," this
+allows Xastir to emit a posit only when told to by an external
+script.
+Fixed error in logic for band-opening alerts (speech and audio
+alarms) so it does not incorrectly report third party traffic
+as a band opening.
+Add "Send Control-E to get GPS data?" to TNC interface
+properties for the "Serial TNC w/ GPS on AUX port" interface
+type. Defaults to enabled, which is correct for KPC-3+ TNCs,
+but should be turned off for any TNC that automatically
+streams GPS NMEA strings, such as Kenwood APRS radios.
+Update GPSMAN support to reflect changes in the gpsman command
+line.
+Add a small delay between sending the converse-mode command
+and sending data for transmission, because KAM TNCs don't
+work if you send the data immediately.
+Fix a bug in the OSM tile download loop that could prevent
+further downloading of tiles if any one tile download fails.
+Fixed a thread-unsafeness bug that could cause Xastir to start
+using corrupted file names when multiple logging options
+(TNC, NET, WX, IGATE, etc.) selected simultaneously.
+Fixed get-fcc-rac.pl script to reflect changes in RAC download
+site.
+
+
+
+
+HELP-INDEX>What's new in Xastir 1.7
+Added REGRESSION_TESTS in order to test interoperability of the
+configure-time flags.
+Added a replacement for malloc() for those cases where the OS
+provides a faulty one.
+Added more to the summary.log file: The tests and results from
+config.log.
+GDAL configure probe now uses gdal-config if it's in the user's
+path.
+Tweaked configure so that dependent libraries cause other library
+searches to fail, and to provide more user output.
+Added ASCII-art drawing to INSTALL showing most of the library
+dependencies.
+Updated symbols.dat to more closely correspond to the current spec.
+Implemented EMERGENCY BEACON transmit capability under the Help
+menu.
+Added decoding for "EMERGENCY" anywhere in the packet plus any of
+these in the TO: field: ALARM, ALERT, WARNING, WXALARM, EM. Any of
+these will invoke the normal emergency popup dialog.
+Waypoint symbols now have a line drawn between them and the station
+transmitting them, per the spec.
+Now using font metrics to determine size of font. We use that to
+determine size of black rectangle to draw underneath.
+Fixed the Fetch Findu Trail function so that it matches what Findu
+can provide.
+Fixed track->shapefile function so that it works on Cygwin too.
+Added reset button to Change Debug Levels dialog.
+Enable WX Alerts menu item is now grey'ed out if Shapelib isn't
+installed.
+RINO Download timing slider is now visible but grey'ed out if gpsman
+isn't installed.
+Added a custom zoom option to the right-click zoom levels menu.
+Moved the center & zoom dialog to the map menu.
+Changed a memcpy() to an xastir_snprintf() function in alert.c to
+assure that a string is terminated.
+Free'ing some malloc'ed space for cases where hash inserts fail.
+Added probe for sighandler_t definition.
+Changed includes, added leak_detector.h.
+A few small changes here and there to get rid of compiler warnings.
+Freeing some malloc'ed space for the cases where hash inserts fail.
+Fixed initializers for awk_rule[].
+Changed hash add functions so that they do a delete first instead of
+replacing hash values.
+Moved some wx-alert related code to debug level 2.
+Changed leak detect interval from 5 minutes to 60 seconds.
+Fixed a big memory leak in draw_nice_string() function.
+Changed include files around so memory leak detection stuff is in
+leak_detection.h.
+Added new compiler flags and cleaned up the code to eliminate many
+warnings created.
+Fixed Incoming Data dialog code so that packets transmitted to local
+interfaces would appear there.
+TNC/NET toggles work for those now too.
+Fixed memory leak in font metrics code.
+Simplfied get_long() and get_int() functions and callouts.
+Tweaks for sighandler_t and sigjmp_buf.
+Added a sign-on message for server connects.
+FCC/RAC lookup or Locate Now buttons don't destroy the dialog
+anymore.
+Fixing up strings.h includes.
+Added a new popup for EMERGENCY packets.
+Changed signal() with SIG_IGN to sigignore for some cases.
+Added a test for sigignore() to configure.ac.
+Changes to allow different versions of "gv" to be used.
+Moved "-lgdal" to end of link line to avoid conflict with other
+libraries.
+Added UDP server and client.
+Added more language strings for previously hard-coded values.
+Changed config file get_int and get_long functions to provide better
+output when config file entries are missing or out-of-range.
+We now allow gating to the internet and to RF for user-defined
+packets and telemetry packets.
+Changing to <CR><LF> for the TCP server signon message.
+Changing to timestamp per packet for log files, with long int
+seconds at the beginning.
+Added icon.
+Added support for -geometry command-line parameter.
+Added fast creation of standard SAR objects via mouse menu,
+including adding digits to the end of the object name if name would
+conflict with pre-existing objects.
+
+
+
+HELP-INDEX>What's new in Xastir 1.6
+Fix for DF lines having incorrect angles at times.
+Configurable display of layers for USGS topo maps.
+Better Map Feature Search: Shows up to 50 matches, user selects
+which one to center map on.
+Configurable "relay" digipeater calls: Up to 50 callsigns can be
+specified in the Xastir config file to use for relay digipeating.
+"WIDE1-1" is now the default.
+Added support for Web Map Service (WMS).
+Tweaked the GPGGA and GPRMC GPS sentence decoding.
+Added speed-ups for lat/long geotiff's.
+Added Aloha circle.
+Added new #defines in interface.h for specifying "conv" or 'k'
+command to TNC.
+Added new tnc-startup file for TAPR-2 style TNC's.
+Added transparency capability to WMS.
+Fixed digpeating code for "wide1-1,wide2-1" case.
+Fixed some compile errors that are seen on FC4 and OSX Tiger.
+Added new terraserver .geo file options.
+Changed Map Properties "fill" option to allow NO/YES/AUTO.
+Auto uses dbfawk if present, no/yes force fill to that state.
+Fixed some #ifdefs here and there so that compiles will work if
+some libraries aren't present.
+Added map caching for nearly all internet maps, plus two new toggles
+on the map menu for clearing out current-view maps or all maps from
+the cache.
+Moved Tigermap timeout slider to main timing dialog, renamed it, and
+made it function for ALL internet map fetches.
+Added timestamps to x_spider log messages.
+A fix for the emacs tempfile bug w.r.t. dbfawk files went in, but
+hasn't been verified to have fixed the problem yet.
+More bulletproofing added to the map_cache code.
+Fixed a compile problem that happens if ImageMagick isn't installed.
+Changed stipple style to solid for polygons drawn with dbfawk.
+Another fix so that linking works without map caching.
+
+
+
+HELP-INDEX>What's new in Xastir 1.5
+Optional Rtree shapefile extent caching
+Optional berkelydb-based internet map caching
+Modifier keys fix
+Improvements to the message GUI
+Tactical call support re-written, hashtable based
+Warnings on crazy paths
+Hashtable weather alert speedups
+Dead-reconing for Objects/items
+Igate of specific stations (in the nws-stations.txt)
+Fixed DF object properties
+Measure function more accurate
+Decoding for "Position with Timestamp no APRS messaging" packets.
+More thorough checking for scanf/sscanf/fscanf function calls
+Fixing 100% humidity for some weather stations, plus added more data for Davis stations
+Changed active internet connection check from 1 min to 5 minutes
+Fixed decoding of compressed DF objects
+Fixes to allow new WHO-IS server to be used from Xastir
+Got rid of extra 0x00 byts between transmitted KISS frames
+Tweak to not start an interface upon changing its properties
+Tweaks to allow use of http proxy servers for online map accesses (.netrc file)
+
+
+
+HELP-INDEX>What's new in Xastir 1.4
+Comment fields for interfaces
+split_gnis and ozi2geo scripts, need to add to section on scripts
+serial mkiss interface
+move objects without confirm
+new timing params w.r.t. trails, need to add to config|timing part
+geo-coder (already in docs)
+exponential/random back-off for almost everything
+dbfawk default, memory leaks fixed
+click+drag zoom boxes
+tactical callsign support
+numerous small memory leaks, uninitialized data uses, and similar bugs fixed.
+GPS quality info
+RINO waypoints downloading
+label trackpoints
+comment/status timestamps
+listener socket/ability to act like a limited internet server
+
+
+HELP-INDEX>Starting Xastir for the first time
+
+ Starting Xastir for the first time
+
+When first running Xastir, you should start it from a terminal window so
+that any warning or error messages can be seen. On most systems a path is
+set up to run programs in /usr/local/bin and all you need to do is type
+"xastir &" at the prompt. On systems that do not have this path installed
+type "/usr/local/bin/xastir &" to start the program. The '&' character
+will cause Xastir to start in the background, leaving the terminal window
+available for other uses.
+
+You may also set the language choice at this time. To set the language or
+change the current language choice, call Xastir with the option '-l':
+
+ xastir -lEnglish
+
+Language options are:
+ xastir -l Dutch
+ xastir -l English
+ xastir -l French
+ xastir -l German
+ xastir -l Italian
+ xastir -l Portuguese
+ xastir -l Spanish
+ xastir -l ElmerFudd
+ xastir -l MuppetsSwedishChef
+ xastir -l OldeEnglish
+ xastir -l PigLatin
+ xastir -l PirateEnglish
+
+The chosen language will be stored in your config file, so it is preserved
+for the next time you call Xastir. For new installs Xastir will default to
+English until you change the language with this command line option.
+
+The menus on the top may be accessed with the mouse or with keyboard
+shortcuts. The keyboard shortcuts may not work correctly with num-lock on.
+
+You will need to configure interfaces in order to actually use Xastir.
+Interface configuration is detailed under the "Configuring Interfaces" help
+topic and its subtopics.
+
+If you are operating in a situation where a coordinate system other than the
+default DD MM.MMMM system would be helpful, you may select your preferred
+system by going to File|Configure|Coordinate system. Any of the supported
+coordinate systems my be used as input by using the Coordinate Calculator.
+
+HELP-INDEX>Configure the Station Information
+
+ Configure the Station Information
+
+Click on File, then Configure, then Station.
+
+Fill in your Amateur Station call sign.
+
+Fill in your station position if you are not using Xastir with a GPS
+unit. You can locate your general position on the map with Xastir and
+use the position given by the cursor placement over the map. This
+position will be viewable in the box at the bottom of the Xastir screen
+2nd from the left, whenever the mouse is over the drawing area. You can also
+choose "Move My Station Here" from the right-click menu while your mouse is
+over your location. If you have a GPS you can skip this and set up the GPS
+later.
+
+"Send Compressed posits", if selected, will transmit in the newer compressed
+format. This format will reduce the amount of data on the air, thereby
+increasing the capacity of the APRS(tm) network. The maximum precision of the
+transmitted position is also higher. Some older programs, including recent
+versions of WinAPRS, do not decode this format yet. Findu.com might also have
+trouble with it. We transmit course/speed in this format but not altitude.
+In order to send course/speed AND altitude requires adding nine characters to
+the packet which negates part of the reason to use compressed posits.
+
+To select a symbol to be used for your station you need to specify
+a group and a symbol character. You can manually fill in these fields,
+or press select to graphically choose a symbol. There are two groups
+of symbols available. A text description of each symbol can be found
+in the "symbol table" help topic.
+
+For some symbols of the secondary group you can specify an overlay.
+With that a symbol will be displayed together with an additional
+overlay character, e.g. a car symbol with the number 1 overlay-ed on
+top of the symbol.
+
+For using overlays you need to select a symbol from the secondary symbol
+table and enter the overlay character to be shown in the group/overlay
+field. Only numbers and uppercase characters are allowed as overlay
+characters. According to the APRS(tm) specification not every symbol can
+be overlay-ed, Xastir doesn't enforce this, but some other programs may.
+Note that not all of the symbols have been implemented in the graphics
+chooser yet, and some of them are not per the APRS(tm) spec yet.
+
+Next, enter the data for the power/height/gain of your station. This
+is useful information but is not required; simply select "Disable PHG"
+to disable it. These choices present a granular representation of your
+stations range. Select the combination of values closest to the
+description of your station. Please use height above average
+terrain (HAAT) for the height value. Do NOT use average height
+above sea level or height above ground. All values must be
+specified if you wish to transmit PHG information.
+
+Another option would be to specify the RNG in the comment field in miles
+instead of using PHG. See the APRS(tm) spec for details.
+
+For Gain use the gain of your antenna in dBi.
+(FIXME: dBd? spec is unclear, I think it's implying dBi because it says "in
+absence of any data, stations are assumed to be running 10w to a 3dB omni at
+20ft. A typical omni is only 3dBi.....)
+
+Note: The gain setting is really intended for vertical antennas; the gain
+setting for a beam should be quite a bit below the forward gain of the beam.
+This is because with directivity set, the PHG circle is only offset by 1/3rd
+of its size toward the specified direction. Setting gain higher will enlarge
+the whole circle unrealistically, rather than increasing the directivity.
+There was talk several years ago about amending the specifications to better
+deal with beam antennas, but nothing was changed.
+
+Enter a comment, not required but it will add insight on your station.
+A common thing to enter here is your preferred e-mail address. It will
+be transmitted along with your posits.
+
+Position ambiguity will allow you control how accurately you transmit your
+position. A setting of none will allow your station to transmit the exact
+position you have entered or received from a GPS. The other choices will
+place you somewhere in the range of the choice you selected. Note that
+this may throw some non-spec compliant stations for a loop. Findu.com
+doesn't understand position ambiguity.
+
+Clicking OK will save your changes, Clicking on Cancel will keep the
+previous settings.
+
+HELP-INDEX>Configure Default Operation
+
+ Configure Default Operation
+
+Click on File, then Configure, then Defaults.
+
+This page sets up some standard defaults for the program operation.
+
+Transmit Station Option sets the type of packet your station will transmit
+its data as.
+
+IGate Options will set your station up as an Internet-RF gateway. This option
+should be used with caution; As a ham you are responsible for the data that
+comes in via the Internet and is transmitted via RF. You also will need to
+choose an IGate option on each interface in order for the IGate to function.
+If you want to have your IGate forward NWS weather alerts to RF, you must
+create a ~/.xastir/data/nws-stations.txt file listing each call or NWS station
+(like "PHISVR") that you would like to transmit via RF. This feature also
+works for gating specific callsigns to RF. Bob Bruninga, WB4APR, recommends
+gating these calls to RF: SCOUTS, SATERN, KIDS, REDCROSS, FOUR-H, YOUTH, GUARD,
+MARS, JOTA. See his link: "Generic Callsigns for National Events" off this web
+page for his current list of recommended callsigns:
+
+ http://www.ew.usna.edu/~bruninga/aprs.html
+
+"Transmit Compressed objects/items?", if selected, will transmit objects and
+items in the newer compressed format. The maximum precision of the transmitted
+position is higher, and the transmission is shorter, but some older programs do
+not decode this format yet. Currently this only compresses "standard"
+objects/items with an optional speed/course. It won't compress area, signpost,
+or DF objects/items, and won't currently represent altitude in "standard"
+objects/items.
+
+"Pop up new Bulletins", if selected, will cause Xastir to bring up the bulletin
+dialog when bulletins within the configured range are received. "View
+zero-distance bulletins" will cause bulletins with no known location not to
+be displayed or cause pop-ups.
+
+"Warn if Modifier keys" will cause Xastir to print a warning if you attempt to
+use Xastir while num-lock, scroll-lock, or caps-lock is engaged. Some users
+report the screen blanking on them and similar problems when they attempt to
+use Xastir with one of these modifier keys on.
+
+You can also select "Activate alternate net?" and choose an altnet call from
+this dialog. Altnet allows you to have a private APRS(tm) network among the
+stations that also have altnet configured, and have the same altnet call
+entered.
+
+"Disable Posit Dupe-Checks" disables the check for duplicate copies of a
+position. This should only be used when a station might return to exactly the
+same position (within 60' or so for non-compressed positions) and you wish to
+see the duplicate positions and/or tracks displayed on the map. This option
+is almost never needed in practice, but can be useful for special events like
+search and rescue operations.
+
+"My Trails in one color" shows all trails with your callsign but different
+ssids in the same color. With My trails in one color selected, mycall-1
+and mycall-2 are shown in the same color. With My trails in one color
+unchecked, mycall-1 and mycall-2 are shown in different colors.
+
+"Load predefined objects from file" and the pick list which follows it allows
+you to replace the list of Predefined objects that are accessible from the
+right click pop-up menu with your own list of objects. A set of standard
+Search and Rescue objects and a set of typical public event objects are
+supplied in the predefined_SAR.sys and predefined_EVENT.sys files. You may
+also use these files as a template to create a predefined_USER.sys file.
+See the instructions in the predefined_SAR.sys and predefined_EVENT.sys file
+for details on how to define objects for a custom predefined objects menu.
+If both "Load predefined objects from file" is selected and a file that
+exists in the xastir/config/ directory is selected, then the objects defined
+in that file will be shown on the Predefined objects menu. The unaltered
+predefined_SAR.sys file defines the same objects as the default menu.
+
+
+HELP-INDEX>Configure Timing
+
+ Configure Timing
+
+Click on File, then Configure, then Timing.
+
+Posit TX Interval specifies how often your station's position will be
+transmitted. For fixed stations a good recommendation is every 30 minutes,
+and definitely no less than 10 minutes. Mobile stations may wish to use a
+faster rate. Note that if you're using SmartBeaconing, this slider is
+ignored.
+
+Object/Item Max TX Interval is the maximum interval used for sending out
+objects and items. Try to keep these intervals reasonable, as transmitting
+to a long path every 5 minutes will really take up a lot of the air time.
+A decaying interval algorithm is triggered any time an object is created,
+modified, or killed. The transmit interval will increase until it hits the
+max interval indicated by the slider.
+
+GPS Check Interval will set the interval of time to look at the GPS for new
+data. This is available for stations using an HSP or shared cable with their
+TNC.
+
+Dead-Reckoning Timeout adjusts how long a position is assumed valid for the
+purpose of estimating its current position.
+
+New Track Time adjusts how many minutes must elapse before a new
+separate track is started. Caution: setting the new track time to 0 will turn
+off the display of all tracks.
+
+RINO -> Objects Interval adjusts how often waypoints are downloaded from an
+attached Garmin RINO radio/GPS unit. APRS(tm) Objects are created out of any
+waypoints beginning with "APRS". The "APRS" prefix is removed when creating
+the Object names.
+
+Station Ghosting Time specifies the ghosting interval. Stations that have not
+been heard in the given period will appear ghosted on screen.
+
+Station Clear Time specifies when a station will be removed from the screen.
+
+Station Delete Time specifies the number of full days before data from a
+station will be entirely removed from the Xastir database.
+
+Serial Inter-Char Delay specifies a wait time in milliseconds between each
+character sent to an attached TNC.
+
+New Track Interval (degrees) specifies distance in lat/long degrees at which
+a new track segment is started. Caution: setting new track interval to 0
+degreees will turn off the display of all tracks.
+
+Snapshot Interval (minutes) specifies how often snapshot files will be
+written if either File->PNG Snapshots or File->KML Snapshots are selected.
+
+HELP-INDEX>Configure Audio Alarms
+
+ Configure Audio Alarms
+
+Click on File, then Configure, then Audio Alarms.
+
+To use this option you must have a sound card and a program that will play
+wav files. The Audio Play Command should contain the program you want to
+execute to play the audio file (and any command line options). That of
+course doesn't work if the only sound card in the system is used for a
+soundmodem...
+
+Each type of alert has a check-box to enable it. The fields will contain the
+name of the file to play. Fields under the option will set parameters for the
+option.
+
+The current choices are:
+Play message on hearing a new station.
+Play message on receiving a new message.
+Play message on receiving data from a station within the min/max distance of
+ your proximity settings.
+Play message on receiving data from a station (via TNC) within the min/max
+ distance of your band opening settings.
+Play message on receiving and displaying a new weather alert.
+
+There is a standard set of sounds available most places where Xastir can be
+obtained, please see the file INSTALL for more information.
+
+HELP-INDEX>Configure Speech
+
+ Configure Speech Synthesis
+
+To use this option you must have a sound card and the 'festival' speech
+synthesis software installed. Install Festival and start it in 'server'
+mode prior to starting up XASTIR. The normal command for this is
+"festival_server &". If you use the "festival --server" option instead (old
+method), you may run into problems with connections getting rejected by the
+server.
+
+Once you have festival installed, Xastir will have the ability to speak using
+the following choices:
+
+New Station - Announce the call of a new station.
+New Message Alert - Announce the arrival of a new message.
+New Message Body - Speak the contents of a message.
+Proximity Alert - Announce when receiving data from a station within the
+ min.max distance of your proximity settings. This option uses the
+ proximity settings found in the Audio Alarms menu.
+Tracked station Proximity Alert - Announce when receiving data from a
+ station within the min.max distance of the tracked station. This option
+ uses the proximity settings found in the Audio Alarms menu.
+Band Opening - Announce when receiving data from a station (via TNC)
+ within the min/max distance of your band opening settings. This option
+ uses the distance settings found in the Audio Alarms menu.
+New Weather Alert - Not implemented yet.
+
+Info on Festival may be obtained from: http://www.speech.cs.cmu.edu/festival/
+
+HELP-INDEX>Configure Smart Beaconing
+
+Click File, then Configure, then Smart Beaconing.
+
+The main "Enable SmartBeaconing(tm)" Will cause Xastir to transmit positions at
+various rates and locations based on the movement of the station. It creates
+more realistic trails and makes dead-reckoning much more accurate. This option
+is only useful in a mobile station with a GPS attached.
+
+There are several options available to customize the operation of
+SmartBeaconing:
+
+High rate
+The interval (in seconds) at which beacons are sent when the speed is above the
+High speed setting. This parameter is also used to compute a beacon rate based
+on speed when traveling between the high and low speeds.
+
+High speed
+The speed threshold that will cause beacons at the rate specified above.
+
+Low rate
+The interval (in minutes) at which beacons are sent when the speed is below the
+Low speed setting. Basically consider this to be the stopped beacon rate.
+This parameter is not used at all when traveling at a rate of speed higher than
+"Low speed".
+
+Low speed
+The speed threshold that will cause beacons at the rate specified above.
+
+Minimum Turn
+The minimum degrees that corner pegging can occur at "High speed" or above.
+Lower speeds will require more degrees of turn to trigger a posit, based on
+the value of "Turn Slope" below.
+
+Turn Slope
+Fudge factor for making turns less sensitive at lower speeds. The parameter
+doesn't have any units. It ends up being non-linear over the speed range the
+way the original SmartBeaconing(tm) algorithm works.
+
+Wait Time
+The time in seconds between corner-pegging beacons, prevents multiple
+beacons in short succession.
+
+HELP-INDEX>Configure Units of Measure
+
+ Configure Units of Measure
+
+The default selection is for the Metric System: mm, cm, km/h, etc. To select
+English units, inches, feet, MPH, etc. Click on File, then Configure, then
+toggle the "Enable English Units" check-box.
+
+HELP-INDEX>Save Config Now!
+
+ Save Config Now!
+
+This button will save all of the current configuration to the config file.
+Note that when Xastir is closed, it also saves configuration to the config
+file.
+
+HELP-INDEX>Bottom Status Bar
+
+ Bottom Status Bar
+
+At the bottom of the window various status messages are available:
+
+In the first box on the left general status messages are displayed for a
+short time.
+
+The second box displays the current lat/long or UTM, and Maidenhead grid
+square position of the mouse over the map. If file|configure|Dist/Bearing
+Status is selected, this box will also contain the course and bearing of
+this position relative to your station.
+
+A third box is used to display how many stations are on screen, and how many
+are in the database.
+
+The fourth box will display the current zoom level and will display "Tr" if
+the station tracking is on. At some zoom levels the Tr is not
+displayed properly due to the size of the box.
+
+The fifth box indicates whether logging is enabled.
+
+The last area will display the device status for each interface. Each will
+display in order first to last or 0 to 9. The interface status is separated
+into three areas, top device type, center data flow, and bottom interface
+operational status.
+
+The device type will show what interfaces are configured. The color will
+show what type of device the interface is configured for. Blues are for
+the various TNC devices; Greens will show the GPS devices; Yellow for
+Internet Servers; Orange for WX interfaces.
+
+The center will show data flow in (arrow pointing left) or data flow out
+(arrow pointing right) for that interface.
+
+A green box at the bottom will show if that interface is active. A red
+box will show if the interface is active but in an error condition.
+Otherwise nothing will show if the interface is not active.
+
+HELP-INDEX>Moving the Map and the Options Menu
+
+ Moving the Map and the Options Menu
+
+Map movement is very simple, ease and quickness of movement is dependent on
+your processor speed and the amount of detail you load. Hint: You can
+disable all maps in the maps menu in order to move around quickly, then
+enable maps again.
+
+Zooming:
+Zooming can be accomplished by right clicking on the map (and holding the
+button down). This will bring up an options menu, with choices to zoom in or
+out a single level, or to change to one of the preset zoom levels.
+
+All zooming functions from the options menu will zoom in or out at the point
+on the map where you clicked the right mouse button. Zoom levels have a cascade
+menu. Levels 1-64 are for very local areas and levels 256 and above are for
+large areas. The lower number the level, the more local the area.
+
+A quicker zoom in function is to push and hold the left mouse button, drag it
+across the area of interest and let go. The map will zoom to approximately
+the size of the square you just described with the mouse drag operation. The
+"move" and "measure" toolbar check-boxes must be disabled for this feature to
+work. Clicking the middle button zooms out with a factor of 2, centering
+where you clicked as well.
+
+The map can also be zoomed with the keyboard Page-Up/Page-Down keys, or the "In"
+and "Out" buttons in the toolbar. The zooming in this case keeps the same map
+center (no centering).
+
+Panning/Centering:
+The map can be centered at a specific location by choosing center in the
+right-click options menu.
+
+Panning is also accomplished by using the options menu, or by using the arrow
+buttons on the toolbar. The map position will shift a portion of a screen.
+Enough data from the previous screen should be available to re-orient yourself.
+
+The map can also be panned with the keyboard arrow keys.
+
+More About Options Menu:
+
+Map Display Bookmarks
+See the help topic "Creating and using Map Display Bookmarks"
+
+The "Station Info" selection on the options menu will look for the station
+closest to where you right-clicked the mouse. If more than one station is
+close to that position a "Station chooser" list will appear, then you can
+choose what station's data you want to look at. If only one station is close
+to the mouse pointer then that station's data will display immediately. For
+mobile stations with a lot of track data this could need some time on slow
+computers. Note that expired stations still have their data stored in the
+Xastir database, and if one knows a station's former location, one can still
+view its info in this manner. Use the "Display Expired Data" option
+to display some data that disappears for ghosted stations, like
+speed/altitude, etc.
+
+With "Last Pos/Zoom" you can restore the previous map view by restoring the
+previous values of the map zoom and centering values.
+
+For Object and Item information, please see the help topic "Objects and Items"
+
+Draw CAD objects lets you create polygons on screen, for tactical or
+presentation use. This feature is still under construction.
+
+"Move my Station here" Allows you to move your station to a specified map
+location without editing the station configuration.
+
+HELP-INDEX>Objects and Items
+
+A station could place several different objects on the map, with their
+position transmitted to other stations. The object names are less restrictive
+than the normal station names.
+
+Objects and items are nearly the same things, but their use could differ a bit.
+Objects are generally used for moving or variable things such as thunderstorms,
+while items are generally used for more inanimate things, such as water
+stations. Because items may not be decoded by some flavors of APRS(tm)
+programs, objects are often used for inanimate things, too.
+
+Besides normal objects with a symbol at its position there are some special
+objects available. Area objects are useful for a variety of operations in
+which you want to draw or highlight an area of interest on the map. They can
+also be used to draw trails/roads/boundaries, watch boxes for severe weather,
+runways, perimeter of a search area or of a public service event, areas of
+damage, areas to stay out of, buildings that aren't on the map, checker/chess
+boards for gaming on APRS(tm). :-) Note that area objects are not
+implemented on all versions of APRS(tm) programs, and some of the details of
+how they are displayed may also be different on other programs.
+For the other three, probability circles, signposts and DF objects, see below.
+
+Objects/Items are retransmitted at a decaying rate up to the max interval
+specified in File|Configure|Timings. "killed" objects/items are also
+retransmitted in this manner until they expire from the queue (currently 20
+transmits). Objects/Items are persistent across Xastir sessions, and are
+stored in ~/.xastir/config/object.log. This file may be cleared by selecting
+"Clear Object/Item history" from the Stations menu.
+
+The Object/Item creation option in the right click menu will bring up a dialog
+with the position of your object filled in based on where you clicked the
+mouse. You may fill in the details, and add an object/item from this menu.
+
+The Object/Item modification option brings you the object modification dialog.
+It is similar to the object creation dialog, except the object's current
+information is already filled out, and the object's name and a few of the
+other options can't be changed. You could also delete the object with this
+option.
+
+Objects and items can be moved with the mouse if the "Move" check-box on the
+toolbar is enabled.
+
+The Predefined Objects option in the right click menu allows you to rapidly
+place standard Search and Rescue objects without having to go through the
+Object/Item creation dialog. These objects include standard Incident
+Command System symbols for ICP, Staging, Base, and Helibase, as well as
+SAR objects for PLS, IPP (with 4 area circles), and LKP If an object of the
+same name as an object you select off the list allready exists, a new
+object will be created with a number appended to the end. For example,
+the first time you select Staging from the Predefined objects menu, an
+object named Staging will be created. If you then create an additional
+Staging object from the Predefined objects menu, it will be named Staging2.
+Heli- (and user defined objects ending in a "-") will be created as Heli-1,
+Heli-2, Heli-3, etc. If you have recieved one of these standard objects that
+was transmitted by another station, your first object will be named with an
+appended number. You may wish to assign a tactical call to your object in
+this situation (for example, replacing ICP2 with a tactical call).
+
+The Predefined Objects menu is customizable by modifying the files
+predefined_SAR.sys, predefined_EVENT.sys, and predefined_USER.sys, and then
+selecting one these files through the File/Configuration/Defaults dialog.
+See the predefined_SAR.sys file for details.
+
+Description of the entries in the object dialogue:
+
+= Signpost =
+This makes the object a signpost object. These signs can contain one
+to three characters, and currently appear in Xastir as a blank sign.
+Station Info shows the value contained on the sign.
+
+= Area Object =
+This makes the object an area object, and enables the area object controls
+described below.
+
+= DF Object =
+This is a direction-finding report. Enabling it allows you to choose Omni or
+Beam report, and allows you to put in the specifics for each. See:
+ http://web.usna.navy.mil/~bruninga/dfing.html
+and the APRSdos documentation for details on these useful techniques.
+(FIXME: Separate section on DF'ing techniques?)
+
+= Probability Circles =
+This allows you to define the radius (in miles) of two circles centered on
+the object or item. Min is the radius (in miles) of the smaller, inner
+circle, and Max is the radius (in miles) of the larger, outer circle.
+These circles are drawn in red. They can be used to assist in planning
+Search and Rescue operations. To create more than two circles, add additional
+probability circle objects to the same location. Probability circles may not
+be displayed by other client software.
+
+= Name =
+This is the name of the object or item. It may be up to 9 characters long,
+with spaces allowed inside the name. When modifying an object, this may not
+be changed. To rename an object you must delete the original and then create
+a new object. Note that if you select Signpost/Area Object/DF Object that
+this field and perhaps others are cleared. Enter the name AFTER you've
+selected the type of object it will become.
+
+= Station Symbol =
+You may select a symbol for the object. Press select to choose graphically,
+or see the symbol table help section for descriptions of each symbol. Note
+also that area objects, signpost objects, and DF objects have special fixed
+symbols and therefore can't be selected here. Those particular symbols get
+automatically assigned when you change to that type of object.
+
+= Location =
+The location of the object is specified here. If you selected "Create
+Object/Item" from the right-click menu, the location you clicked will be filled
+in. If you moved an object with the mouse, the new location will be in these
+fields. You can also type in a location, for instance you may be placing an
+object from an over-the-air voice report.
+
+= Generic Options =
+You may specify the speed, direction, and altitude of objects here. Some object
+types cannot have a speed or direction, in which case the fields are grayed
+out.
+
+= Signpost Text =
+If the object is a signpost object, you may specify the 1 to 3 digit
+number that appears on the sign here. Note that Xastir doesn't display
+signpost objects properly yet.
+
+= Area Object =
+Area Objects are used to highlight specific parts of maps, or to draw extra
+detail onto maps. This will be done with the following entries:
+ = Bright Color =
+ Use the brighter version of the colors allowed.
+ = Color-Fill =
+ The area should be filled, not just outlined. This may be useful to
+ exclude an area from a search or other event.
+ = Object Type =
+ Choose from the geometric shapes allowed.
+ = Object Color =
+ Choose the color in which the object will display. This is also affected
+ by the "Bright Color" option above.
+ = Object Offset Up =
+ In hundredth of a degree latitude. An unfortunate detail of the spec,
+ and hard to calculate easily. Suffice it to say that you can change
+ the size of the object once you place it.
+ = Object Offset Left except / =
+ In hundredth of a degree longitude. See above.
+ = Object corridor =
+ This is the width of a line area object. Useful for runways, weather
+ watch boxes, describing an area of interest or an area of exclusion, etc.
+
+Always delete your objects and items when you are done with them!
+Don't just allow them to expire from your cache, as they may hang
+around on other peoples' screens for an extended period.
+
+
+Description of weather watch boxes:
+
+Watch boxes and "areas of maximum concern" (AOMC) generated by the WXSVR
+(http://wxsvr.net/) are colored as follows:
+
+ Yellow dashed = Severe Thunderstorm Watch (looks like crime scene tape)
+ Yellow solid = AOMC for Severe Thunderstorm Warning
+ Red dashed = Tornado Watch
+ Red solid = AOMC for Tornado Warning.
+ Green dashed = Mesoscale (larger) discussion area
+ Blue dashed = Test Watch
+ Blue solid = Test Warning
+
+HELP-INDEX>CAD Objects
+
+ CAD Objects
+
+[CAD object support has moved from the right click menu to
+Map/Draw CAD Objects].
+
+CAD object support is preliminary at this time. Features and the user
+interface are subject to change.
+
+CAD objects are arbitrary shapes that you can draw on maps in xastir, but
+can't transmit by APRS.
+
+Currently supported CAD objects are:
+Polygons: Closed areas of at least three points.
+
+To create a CAD object, first press the Draw radio button on the toolbar.
+This will change the cursor to a pencil. Begin drawing a polygon by
+clicking with the middle mouse button (or both buttons on a two button mouse,
+for which you will need to have three button mouse emulation enabled). This
+places a point on the map. Now move the cursor somewhere else (the normal
+left click/right click navigation and zoom functions still work normaly) and
+click the middle mouse button again. This draws a line between the two points
+you have selected. Middle click again to draw another line segment and keep
+repeating until you have drawn all except for the closing line segment of your
+polygon. To close the polygon, select Map/Draw
+CAD Objects/Close Polygon. This will close your polygon and bring up a dialog
+that will allow you to enter a name, comment, and probability for the polygon.
+
+When you have finished drawing CAD objects, exit the CAD drawing mode by
+deselecting the Draw radio button on the toolbar.
+
+CAD objects can be edited from the View/CAD Polygons menu and from the
+Map/Draw CAD Objects/CAD Polygons menu. CAD objects can be deleted from the
+Map/Draw CAD Objects/Erase CAD Polygons menu.
+
+HELP-INDEX>View Menu
+
+ View Menu Options
+
+The View menu presents various ways to look at data in Xastir.
+
+Bulletins
+This is the APRS(tm) bulletin board, where important announcements are posted.
+If you are connected with the internet interface, it is a good idea to set the
+range field to a few hundred miles, to ignore posts from other portions of the
+world. "0" in the range field means the entire world. Click the "Change range"
+button to make changes to this field effective. Xastir currently does not
+support sending bulletins. Incoming bulletins will open this dialog
+automatically if you select "pop up new bulletins" in the Configure|Defaults
+dialog. The "View zero-distance bulletins" button enables viewing bulletins
+for which you don't have a range yet (they haven't sent a posit yet, but you
+received a bulletin from them). If this is unchecked, you must get a position
+from a station, and the station must be within the range selected (or range
+must be set to zero), in order for the bulletin to be viewed.
+
+Incoming packet data
+This displays the incoming data on your TNC or internet interface. The radio
+buttons below select if you want to see only TNC data, only internet data, or
+both.
+
+Mobile Stations
+This is a list of stations that are moving. Stations qualify for this list if
+they have moved (more than one position received for them), the symbol of the
+station is not considered. Information shown includes course, speed, altitude,
+position, number of packets received, number of visible GPS satellites, course
+from your station, and distance from your station.
+
+All Stations
+This option displays a table of all stations sorted alphabetically. It includes
+the number of packets heard, the time the station was last heard, the path that
+the most recent packet took, the PHG, and the comment of the station.
+
+Local stations
+This option displays only stations that are heard via your TNC. It includes
+the number of packets heard, the time the station was last heard, the path that
+the most recent packet took, the PHG, and the comment of the station.
+
+Last Stations
+This option displays a table of all stations sorted from most recently heard
+to least recently heard. It includes the number of packets heard, the time
+the station was last heard, the path that the most recent packet took, the PHG,
+and the comment of the station.
+
+Objects & Items
+This option displays only objects and items. It includes the number of packets
+heard, the time the objects/item was last heard, the path that the most recent
+packet took, the PHG, and the comment of the object/item.
+
+Own Objects & Items
+This option displays only objects and items that you control (i.e.: Have sent
+the most recent update for). It includes the number of packets heard, the time
+the objects/item was last heard, the path that the most recent packet took, the
+PHG, and the comment of the object/item. A ghosted icon indicates that the
+object has been deleted.
+
+Weather Stations
+This option displays a table of all the APRS(tm) weather stations and their
+data. Data includes wind course, wind speed, wind gust speed, temperature,
+humidity, barometric pressure, rain in the past hour, rain since midnight,
+and rain in the last 24 hours.
+
+Own weather data
+Displays your weather data if you have a weather station and have configured
+Xastir to access it.
+
+Weather Alerts
+Displays weather alerts received, including the alert flags, alert source/type,
+alert destination, expiration, message, and effected location. This data
+is used for the alert highlighting. Double-clicking on an alert will request
+further information about it via finger from the online WXSVR. This only
+works if you have internet access; future versions may access this data over
+radio as well.
+
+Message Traffic
+Shows all message traffic while the window is open. It includes the source,
+destination, interface, and message. The range option can limit this display
+to nearby stations, much like the range control on bulletins. A range of 0
+causes all messages to be displayed.
+
+GPS Status
+Shows the status of your GPS unit, including the type of fix and number of
+satellites acquired.
+
+Uptime
+Shows the amount of time elapsed since Xastir was started.
+
+HELP-INDEX>Map Menu and the Map Chooser
+
+ Map Menu and the Map Chooser
+
+Map Menu:
+
+Map Chooser
+This will present you with a list of map directories and/or files in your
+map directory. Checking the "Expand Dirs" option toggles the expansion of
+directories into individual map files. The properties dialog allows more
+advanced controls, and is described below. Click on map names to highlight
+them, this will cause them to be displayed when you click the OK button. You
+may select any number of maps. Clicking "Clear" will select no maps,
+clicking "Vector" will select only vector maps. The three "topo" options will
+automatically select all GeoTIFF images of the listed size. Clicking the OK
+button will display the selected maps. Cancel will abandon any changes.
+
+ Map Chooser Properties
+ Clicking the Properties button will bring up a dialog where you can specify
+ the layer in which maps appear, and in which zoom levels they appear. Higher
+ layer numbers are displayed on top of lower numbers. The range may be
+ specified from -99999 to 99999; it is suggested that you space your layering
+ numbers widely to allow later insertion of additional map layers. From this
+ dialog you may specify whether a vector map is drawn with color fills. This
+ is a per-map setting; the global disable option on the Maps menu can override
+ this. The Filled setting is ignored for raster maps (images). A setting of
+ "auto" allows a dbfawk file to control this parameter directly (usable only
+ if dbfawk is compiled in and the map in question is a Shapefile). You can
+ also select whether a map is considered by the "Auto maps" feature here.
+ Finally, you can specify the minimum and maximum zoom levels at which a map
+ is displayed. This is useful to prevent very detailed local maps from loading
+ at very wide zoom positions, and visa-versa. A minimum zoom of 10 means a map
+ will be displayed at all zooms including and above 10. Likewise, a maximum
+ zoom of 256 means a map will be displayed at all zooms below and including
+ 256.
+
+Map Display Bookmarks
+See the help topic "Creating and using Map Display Bookmarks"
+
+Locate Map Feature
+This option brings up a search dialog where you can search through the labels
+in a GNIS file to find a specific location. It will center the map on the
+new location if it is found. The "GNIS File:" entry is saved between calls
+and between invocations of Xastir. You must put GNIS files into the
+xastir/GNIS directory in order to use this feature.
+
+Find Address
+This option brings up a search dialog where you can enter an address. It will
+center on the map if the address is found. The path to the geo-coder file is
+saved between calls.
+
+Coordinate Calc
+This option opens a simple calculator that can convert between coordinate
+systems. This is useful for converting positions to the various formats used
+by different groups of people. This same calculator can be called up by the
+Calc button on some of the other dialogs. It's useful for entering coordinates
+in other formats.
+
+Configure menu:
+ Background color
+ This option controls the color of the background behind the maps you have
+ displayed. The background color is often entirely hidden by filled maps
+ (see below).
+
+ Map Intensity
+ This controls the brightness of any graphics used as maps. This option only
+ appears if you have compiled with GeoTIFF support.
+
+ Adjust Gamma Correction
+ This allows you to apply gamma connection to all loaded map graphics. Maps
+ can be adjusted individually in their .geo files, see the section on .geos in
+ "Map files and WX Counties". This option only appears if you've compiled with
+ ImageMagick support, and does not apply to geoTIFF maps; see the above
+ option.
+
+ Map labels font
+ This allows you to set the font style and size used for map labels.
+
+ Station Text Style
+ Controls which font and style to use for station text and others.
+
+ Icon Outline Style
+ This allows you to specify an outline that surrounds station icons. This
+ helps improve visibility on various backgrounds.
+
+ Configure Tigermap
+ Turning this option on causes Xastir to download the map from the US census
+ bureau's online tiger mapping server. The dialog that comes up allows one to
+ select which layers are displayed, as well as the brightness of the resulting
+ map. This is only available if you have compiled with ImageMagick support.
+ Tigermaps are always loaded as the bottom layer; they do not have layering
+ settings in the Map Chooser.
+
+Disable All Maps
+This option disables the loading of any maps. It is most useful when doing
+rapid zooming or panning, because it saves the need to load the maps on each
+redraw. Note that this option is not saved between sessions.
+
+Enable Auto Maps
+When enabled, any map found in the map directory (or any directory under it)
+will be displayed if it falls within the current display region. You can add
+any number of directory levels under the main map directory for your maps. Auto
+maps will go through any that have Auto Maps enabled (in the Map Chooser
+Properties dialog) check them all and find what map (or part) should be
+displayed. All Maps will be merged into the viewing area. If you have a large
+quantity of maps, very detailed maps or a slower computer this can be quite
+slow. When this option is off, maps selected with the Map Chooser and/or Tiger
+Maps dialog will be displayed.
+
+Auto Maps - disable Raster maps
+This option prevents Auto Maps from loading maps which are graphics (images).
+Only vector maps will be displayed in this case.
+
+Enable Map Grid
+When enabled, this option will display a grid on the map. If the coordinate
+system is UTM a UTM grid will be displayed. If the coordinate system is
+latitude/longitude then a latitude and longitude grid will be displayed. As you
+zoom in the grid switches to a finer resolution. The spacing of the latitude
+and longitude grid may be manually adjusted with the "+" and "-" keys.
+
+Enable Map Border
+When both Enable Map Grid and Enable Map Border are enabled, a narrow white
+border is drawn around the map and the grid lines are labeled using the
+selected coordinate system (File/Configure/Coordinate System), and the selected
+border font (Map/Configure/Map Labels font/Border Font). If the UTM or MGRS
+coordinate systems are selected, the grid lines will be labeled with easting
+and northing values only at zoom levels smaller than about 2048.
+
+Enable Map Levels
+When enabled, this option will try to filter out data when the zoom level
+shows large areas. This does not work will all maps but will work with the
+maps generated from Tiger Line maps at the aprs.rutgers.edu site, and with
+ESRI Shapefile maps. This does not decrease the loading times of the maps very
+much, rather it simply reduces screen clutter.
+
+Enable Map Labels
+This option toggles the display of map labels embedded in DosAPRS, WinAPRS,
+GNIS, and ESRI Shapefile format maps.
+
+Enable Area Color Fills
+This option controls the filling of vector maps. In certain cases, you
+may want to eliminate the fill to see maps below the top maps. This is a global
+control, maps may individually have color fill toggled in the properties dialog
+of the Map Chooser.
+
+Enable Weather Alert Counties
+This toggles the display of county warning area maps for severe weather.
+These maps can be obtained and installed according to the directions in the
+README.MAPS file. They are displayed on screen when special weather alert
+messages are received, and expire after a time or can be remotely canceled.
+The weather alert text can be seen under View|Weather Alerts. The
+xastir/Counties directory must be populated with the correct files from NOAA
+and Shapelib support must be compiled into Xastir in order to enable this
+functionality.
+
+Index New Maps on Startup
+This option controls if the map index file is built on startup. Most users
+should leave this enabled. If the timestamp of the map file is newer than
+the map index file, the map will be indexed.
+
+Index: Add New Maps
+This option adds any new maps to the max index. Same rules as the above
+Index New Maps feature, but a manual method of invoking it.
+
+Index: Reindex ALL Maps
+This option starts over from scratch, indexing every map it recognizes in the
+maps directory. This is useful if the Add New Maps function is skipping some
+maps, perhaps because of old timestamps on the map files. This function may
+take quite a while to complete if you have a lot of maps.
+
+Mouse pointer menu
+This option brings up the options menu normally available by right clicking.
+
+One note on maps: Many of the currently available vector maps for the
+U.S. were created in NAD 1927 datum, while Xastir and other APRS(tm) programs
+use WGS 1984 datum. If zoomed in to a small area on the map the datum
+shift may be very noticeable. The USGS topographic maps have their datum
+corrected by Xastir as they are displayed, so positions will generally
+be more accurate with those topographic maps.
+
+HELP-INDEX>Map files and WX Counties
+
+ Map files and WX Counties
+
+Map Types
+Xastir will work with various types of map files. All DosAPRS, Windows/Mac
+APRS(tm) map files are supported, as well as PocketAPRS format maps and GNIS
+(Geographic Names Information System) label files. Xastir also can be
+compiled to use external libraries to support XPixmap (XPM) images, GeoTIFF
+topographic maps, and ESRI Shapefile maps. The graphics handling capability
+of Xastir can be greatly extended by compiling with ImageMagick support,
+enabling support for many graphic formats as maps (see
+"http://www.imagemagick.org/www/formats.html"). Xastir supports weather
+alert maps in ESRI Shapefile format, available from NOAA.
+
+Details of locations to obtain many of the above types of maps are found in
+the file README.MAPS
+
+Map Locations
+Any map file should be stored in the /usr/local/share/xastir/maps directory
+on your computer. This location may be different on some systems, depending on
+how Xastir was compiled/installed. You can create any number of directories
+under this directory to help organize and separate your data. The maps will be
+loaded in alphanumerical order unless layering is specified.
+
+Hints on installing and organizing maps are found in README.MAPS.
+Maps in a pixel graphics format actually need a combination of two files,
+a data file with a graphic pixmap (.xpm) (or other format if you compiled
+with ImageMagick), and a calibration file (.geo). The .xpm file is the
+standard graphic format, available without additional libraries. If you
+want to save storage space you can use gzip to compress those files
+("gzip map.xpm" will result in "map.xpm.gz"). Xastir detects this
+automatically during map loading. You can use XView/Gimp/ImageMagick and
+other programs to convert gif, jpg, and tif images into this format if
+you don't have support for many image types compiled in (ImageMagick). If
+you have problems with maps in xpm format, try to load and save the
+graphics with Gimp first, to convert all unknown color names into the
+binary representation.
+
+The .geo file is a text data file that will tie the image to a location
+in the world. Here is an example of a .geo file that will cover the entire
+world with the map world1.xpm:
+
+FILENAME world1.xpm
+# x y lon lat
+TIEPOINT 0 0 -180 90
+TIEPOINT 639 319 180 -90
+IMAGESIZE 640 320
+
+.geo files can have many elements:
+
+FILENAME <filename>
+This specifies the filename of a map image to be loaded from the local disk.
+
+URL <http://website>
+This specifies the URL of a map image to be loaded from a web or ftp site.
+ImageMagick only.
+
+TIEPOINT <x-pixel> <y-pixel> <longitude> <latitude>
+Two tie-points are required, and more than 2 will be ignored.
+these two lines are for connecting an x,y pixel position in the image
+to a lat and long position on the earth. The points should be as close as
+possible to the upper left corner and the lower right corner of the image for
+best accuracy. The latitude/longitude are specified in decimal degrees.
+
+IMAGESIZE <pixels horizontally> <pixels vertically>
+This specifies the size of the image in pixels. If this is not set, the image
+will be loaded each map redraw, regardless if it is on screen or not.
+IMAGESIZE is a REQUIRED OPTION if a URL is specified. For local files, it's
+an optional parameter (we use ImageMagick to query the image size for local
+files).
+
+DATUM <datum>
+This feature is not implemented.
+
+PROJECTION <projection>
+This feature is only partially implemented, default is "LatLon", other
+possibility is "TM" to specify that the map is in Transverse Mercator
+projection.
+
+# <anything>
+Any line with the first character of a '#' will be ignored.
+
+ImageMagick specific image enhancements:
+
+GAMMA
+eg: GAMMA 1.2 or GAMMA 1.2,2.0,1.2
+The first will change overall gamma for this image, the second will
+lighten green more than red or blue.
+
+CONTRAST
+eg: CONTRAST 0 or CONTRAST 1
+Doesn't seem to do that much, other values make no difference.
+
+NEGATE
+eg: NEGATE 0 or NEGATE 1
+0 will negate all colors, 1 just grayscale colors.
+
+EQUALIZE
+No argument.
+
+NORMALIZE
+No argument.
+
+LEVEL <black_point, mid_point, white_point>
+eg: LEVEL 0,1,65535
+These values seem to be the defaults.
+
+MODULATE <brightness, saturation, hue>
+eg: MODULATE 90,150,100
+These are percents, 100,100,100 is the default.
+
+REFRESH <seconds>
+eg: REFRESH 900
+This tag is used for dynamic URLs such as weather radar, where you
+wish Xastir to auto-redraw the map at a specified interval. By
+adding this tag to weather radar .geos, you can watch the weather
+move across your screen. Xastir contains only one interval counter,
+so the smallest REFRESH interval loaded takes effect for all selected
+maps.
+
+TRANSPARENT
+Color to remove from the background (make it transparent). Use a
+number, 0=black. Color-mapped images use the map value, so white is
+usually 0xffffffff (32-bits of 1s). Values must be in hexadecimal,
+and are preceeded by "0x". The value can be obtained by using debug
+level 16. The first of the four numbers after "Color allocated is"
+is the colormap index.
+
+CROP <left top right bottom>
+Removes borders (makes them transparent). Values are in pixels with
+(0,0) at the upper left. A good value for the 620x620 NWS radar
+images is "CROP 35 20 616 600"
+
+Special/nonstandard .geo files:
+
+TIGERMAP
+A file with just the word "TIGERMAP" will cause Xastir to retrieve an
+online Tiger map of the area on screen. These are not available for every
+place in the world. "tigermap.geo" is automatically installed in the maps
+directory.
+
+TERRASERVER-SATELLITE
+A file with just the word "TERRASERVER-SATELLITE" will cause Xastir to
+retrieve a Terraserver satellite photo of the area on screen. Those
+services are not available for every place in the world. Note that using
+the Terraserver maps at any zoom above 256 will probably take a long time
+to load, won't show much detail, and probably won't display correctly. This
+is a limit of Microsoft's Terraserver, not Xastir. Also note that
+crossing UTM zone boundaries is not supported by Terraserver.
+"terraserver.geo" is automatically installed in the maps directory.
+
+TERRASERVER-TOPO
+A file with just the word "TERRASERVER-TOPO" will cause Xastir to retrieve a
+topographic map of the area on screen. Those services are not available for
+every place in the world. Note that using the maps at any zoom above 256
+will probably take a long time to load, won't show much detail, and
+probably won't display correctly. This is a limit of Microsoft's
+Terraserver, not Xastir. Also note that crossing UTM zone boundaries is not
+supported by Terraserver. "terraserver-topo.geo" is automatically
+installed in the maps directory.
+
+TERRASERVER-URBAN
+Same as above but with Terraserver colored urban-area satellite
+images. "terraserver-urban.geo" is automatically installed in the
+maps directory.
+
+TERRASERVER-REFLECTIVITY
+Same as above but with Terraserver reflectivity images.
+"terraserver-reflectivity.geo" is automatically installed in the
+maps directory.
+
+TOPORAMA-250k
+Canadian 1:250k scale topo maps, downloaded from findu.com.
+"CanadaTopo250k.geo" is automatically installed in the maps
+directory.
+
+TOPORAMA-50k
+Canadian 1:50k scale topo maps, downloaded from findu.com.
+"CanadaTopo50k.geo" is automatically installed in the maps
+directory.
+
+WMSSERVER
+Allows use of Web Map Services (WMS). An example "WMSRadar.geo" is
+automatically installed in the maps directory.
+
+
+
+geoTIFF maps are a combination of two files as well: a .tif and a .fgd file.
+The .tif file is the actual map data. The .fgd file need only contain four
+lines like this (but may contain many other lines):
+
+1.5.1.1 WEST BOUNDING COORDINATE: -122.000000
+1.5.1.2 EAST BOUNDING COORDINATE: -120.000000
+1.5.1.3 NORTH BOUNDING COORDINATE: 48.000000
+1.5.1.4 SOUTH BOUNDING COORDINATE: 47.000000
+
+Xastir uses only those four lines in its calculations to determine the corner
+points of a map, to see whether the map fits in the current viewport (so it
+can decide whether to skip it). If your map data are USGS topographic maps,
+the .fgd file should be readily available to you. If it is not, the mapfgd.pl
+script can create it for you. If you don't have a .fgd file, the map will load
+fine, but the white borders won't be cropped and the size and rotation may be
+off a tad bit. An added feature in Xastir is the ability to do datum
+translations from NAD 1927 to WGS 84 datum, which makes the USGS topographic
+maps much more accurate on the Xastir screen.
+
+Xastir can use USGS geoTIFF topographic maps directly from the CD drive.
+Manually mount the disk or use auto-mounter to do it for you, and make sure
+you have a sym-link created in your maps directory that points to where you
+mounted your CD-ROM drive. That's it!
+
+
+ESRI Shapefile maps are also a combination of several files, a .shp file, a
+.dbf file, and a .shx file. You only need to select the .shp file to load the
+map, but the other(s) must be present for the map to load correctly.
+
+
+GNIS (Geographic Names Information System) data is a collection of names of
+locations, or geographic features. These labels behave like map labels in
+Dos/WinAPRS maps. As you zoom in, more labels will appear, assuming you've
+selected the GNIS file as a map and have enabled Map Labels in the Maps menu.
+If you have some of them in the xastir/GNIS directory, you can also search
+for map labels within Xastir.
+
+
+WX County Maps
+All WX County maps should be stored in the /usr/local/share/xastir/Counties
+and Xastir only supports the ESRI Shapefile standard for these. Installation
+is explained in README.MAPS. You must have Shapelib compiled in.
+
+As NWS messages are received, different areas will get tinted to designate
+areas of concern. They are color-coded to specify different types of
+alerts. The colors are: Cyan for advisory, yellow for watch, red for warning,
+orange for canceled alert, royal blue for tests, and green for undetermined
+alert levels. The coloring is done with a pixmap stipple that displays the
+type of alert, if it is able to be determined. These changes were made so that
+the underlying maps may still be seen underneath the weather alert areas, and
+so the alert type may be more easily determined, as sometimes matching the
+alerts on screen and in the weather alerts dialog is difficult. The display
+of weather alerts may be turned on/off via the Map menu.
+
+HELP-INDEX>Stations Menu
+
+ Stations Menu
+
+These options will allow you to control the data displayed around the stations
+on the map. It will also let you track and find stations, and clear stations
+and trails in the database and from the map.
+
+Find Station
+See the help topic "Locating a Station".
+
+Track Station
+See the help topic "Tracking a Station"
+
+Fetch Findu Trail
+Downloads historic trail data from findu.com. Slider bars control the starting
+point and duration of data downloaded. For an example, if you wished to see
+the track that happened two days ago, all day long, you might set the first
+slider to 48 hours (start time of two days ago) and the second slider to 24
+hours to snag exactly one day's worth of data, from the start until 24 hours
+later.
+
+
+Export all
+This sub-menu allows saving data for all stations to files [or databases]
+
+ Export to KML file
+ Saves all stations and their trails to a Keyhole Markup Language
+ file in ~/.xastir/tracklogs. The filename will be the current
+ date and time with a .kml extension, e.g. 20080125-033045.kml
+ KML files can also be written on a regular basis using KML
+ Snapshots on the file menu.
+
+ Store to open databases [Not yet implemented]
+ [Store to database interfaces is currently only implemented through
+ individual SQL database interface dialogs]
+
+ To save a png snapshot of the current map, use File->PNG Snapshots
+
+Filter Data
+This sub-menu allows filtering of the displayed symbols:
+
+ Select None
+ Determines if symbols should be drawn on the map. The other options depend
+ on this being enabled.
+
+ Select Mine
+ Determines if your own station is shown on the map.
+
+ Select via TNC
+ Global toggle for displaying data received via a TNC, but may be narrowed:
+
+ Select Direct
+ This option only displays stations heard directly (not digipeated).
+
+ Select via Digi
+ This option displays stations heard indirectly via a digipeater.
+
+ Select Net
+ This option displays stations with data received via the Internet.
+
+ Include Expired Data
+ Causes Xastir to continue to display the station data that normally goes
+ away when the symbol is ghosted. The expiration time can be adjusted in
+ the File|Configure|Defaults menu.
+
+
+ Select Stations
+ Global toggle for displaying stations, but may be narrowed:
+
+ Select Fixed Stations
+ This option displays stationary stations.
+
+ Select Moving Stations
+ This option displays stations with multiple positions or non-zero speed
+
+ Select WX Stations
+ This option displays Weather Stations.
+
+ Select CWOP WX Stations
+ This option includes the display of citizen weather (non-ham) weather
+ data.
+
+ Select Objects/Items
+ Global toggle for displaying objects/items, but may be narrowed:
+
+ Select WX Objects/Items
+ This option displays weather Objects and Items. This includes tropical
+ storms and remote weather stations.
+
+ Select Water Gauge Objects/Items
+ This option toggles the display of water gauge (/w) objects.
+
+ Select Other Objects/Items
+ This option enables or disables the display of objects other than those
+ listed above.
+
+
+Filter Display
+This sub-menu allows filtering of the displayed data:
+
+ Display Callsign
+ Determines if the callsign is displayed.
+
+ Label Trailpoints
+ This option includes callsigns along trails, to help identify which
+ points belong to which stations.
+
+ Display Symbol
+ Determines if the symbol is shown to the left of the callsign.
+
+ Rotate Symbol
+ Some symbols will change their orientation to show the direction in which
+ they are traveling.
+
+ Display Trail
+ When enabled, any moving station will trail a colored line. We now display
+ as many locations as we have in our database (old limit was 100). Long
+ trail segments (over 2 degrees latitude or 2 degrees long), or segments with
+ more than 45 minutes receive delay between the points will not be displayed.
+ Duplicate points are also eliminated from the track (SAR team returning to
+ base: Last segment may not be displayed due to the starting point appearing
+ twice in the trail list).
+
+ Display Course
+ When enabled, green text will appear below the call sign. This will display
+ the last known course (in degrees) the station was traveling.
+
+ Display Speed
+ When on, red text will appear below the call sign (or course). This will
+ display the last known speed of the station.
+
+ Display Short Speed
+ This option removes display of the measurement units for speed.
+
+ Display Altitude
+ When enabled, blue text will appear above the call sign. This will display
+ the last known altitude of the station.
+
+
+ Display Weather Info
+ Global toggle for displaying weather information, but may be narrowed:
+
+ Display Weather Text
+ When enabled, the latest weather data (temp,wind speed/course/gust,
+ humidity) is displayed. This may be adjusted with the following option:
+
+ Display Temperature Only
+ Displays only the temperature data for the station.
+
+ Display Wind Barb
+ When enabled, a wind barb showing the direction and speed of the wind is
+ drawn for all displayed stations reporting this information.
+
+
+ Display Position Ambiguity
+ When enabled, the area in which station using position ambiguity may be
+ located within is shaded, with the relevant station in the center.
+
+ Display Power/Gain
+ When on, Power/Gain Circles will be displayed. Overlapping circles indicate
+ that the stations are theoretically within simplex range of one another.
+ This is only roughly accurate, especially in areas of variable terrain.
+
+ Use Default Power/Gain
+ Enables a default power/gain setting as specified in the APRS(tm)
+ specification.
+
+ Display Mobile Power/Gain
+ Enables power/gain circles for mobile stations.
+
+
+ Display DF Attributes
+ When enabled, any DF circles/lines will be displayed on the screen.
+
+ Enable Dead-Reckoning
+ When enabled, the positions of stations are estimated based on past course
+ and speed. The recalculation rate should be reasonable, but can be adjusted
+ in the configuration file.
+
+ Display Arc
+ Displays an expanding arc of expected maximum travel distance, location and
+ course given the past course and speed. The arc slowly becomes a circle as
+ the position report gets older.
+
+ Display Course
+ Displays an expected course and distance traveled by the station, assuming
+ the course hasn't changed.
+
+ Display Symbols
+ Displays a ghosted version of the stations symbol at the expected position,
+ assuming the station has continued at its current course and speed.
+
+
+ Display Dist/Bearing
+ When enabled, two lines of text will be displayed on the left side of the
+ stations' icon. The top line will contain the distance from your station to
+ this station. The bottom line will contain the course from your station to
+ this station.
+
+ Display Last Report Age
+ Display the time since the station was last heard.
+
+Reload Object/Item History
+This will reload the ~/.xastir/config/objects.log file used for Object and Item
+persistence. This is needed if you edit the file while Xastir is running.
+
+Clear Object/Item History
+This will clear the ~/.xastir/config/objects.log file used for Object and Item
+persistence. It is recommended that you manually select and delete all Objects
+and Items that you own before doing this, otherwise they may remain on the
+screens of other APRS(tm) users.
+
+Clear All Tactical Calls
+Clears all assigned tactical calls. This will take effect the next
+redraw. Note that this will NOT clear tactical calls on other
+peoples' screens if you've published them via a message to
+"TACTICAL" (see the help text for "Send Message").
+
+Clear Tactical Call History
+This removes the tactical call history file, meaning that tactical calls
+assigned will not remain permanent between Xastir restarts. Note
+that this will NOT clear tactical calls on other peoples' screens if
+you've published them via a message to "TACTICAL" (see the help text
+for "Send Message".
+
+Clear All Trails
+This will wipe all the line tracking data from the station database and
+refresh the screen. This option is perhaps useful if you're low on memory
+or just want an uncluttered screen. You may also clear individual stations'
+trails from the Station Info dialog.
+
+Clear All Stations
+This will wipe all the data from the station database except yours. This
+option is perhaps useful if you're low on memory or just want to unclutter
+your screen.
+
+HELP-INDEX>Messages and the Messages menu
+
+ Messages and the Messages menu
+
+Send Message to and Open group messages
+
+These are very similar. "Send message to" will send your messages to one
+station and will only receive data from that station. Group messages are more
+general: you can receive any message for the group and you will send out your
+messages to that group name. Group messages code is not fully implemented yet
+and various problems still need to be worked out. The "groups" file is looked
+for in ~/.xastir/config. This is where the groups you are a member of are
+stored. As was said before the "groups" functionality may not be complete yet.
+
+At some point in the near future sending of bulletins should be added to this
+menu as well. It's not coded yet.
+
+Each of these two screens contains a message box, a call line, a message line,
+and various buttons. You must first enter the call of the group or station you
+want to contact. Once that is done any new message that has come in from that
+station to you will be displayed. If the station is sending you information
+and no message window is up it will automatically pop up a new window (up to
+10) with that station's call sign filled in for you. You can now enter a
+message on the message line. The message can be longer that the message line,
+and will max out at about 250+ characters. Once your message is entered,
+clicking on the "Send Now!" button will send your message. The "Send Now!"
+button will gray out until your message is completely ack'ed. Any message you
+receive will be sorted by the line # and be placed in the message window. If
+you are in a group mode each line will display the call sign from where the
+message was sent followed by the message itself. Currently group messages are
+sorted by call and then line #. When you are done sending messages clicking on
+the exit button will close the window. Other buttons are also available: The
+"New Call" button will allow you to look at old data a station has sent. Type
+in the call and click on this button, any old information will be displayed.
+You can also use this button to change the call of the station you're talking
+with. Enter the new call and click the button. The "Clear Msg History" button
+will clear any message displayed in the message window. "Cancel Pending Msgs"
+will cancel any messages in the transmit queue that haven't been acknowledged
+by the remote station yet. After canceling the pending messages or receiving
+and acknowledgment packet from the remote station, you may send new messages to
+the remote station. Xastir will allow you to type ahead, so you can just keep
+typing if you don't want to wait for the acknowledgments.
+
+Messages in reply to previous ones will attempt to use the path of the
+received message to avoid flooding the system with broadcast messages. You
+may adjust the path in the send message dialog, or the default path(s) set
+in the interface control will be used if you leave this blank. The path
+can be set for each message sent, but once a message is sent the path
+remains fixed for that particular message.
+
+Each outgoing message remains highlighted until it is ack'ed by the remote
+station. If it times out or if you cancel the pending messages, those
+messages will remain highlighted unless you clear the message history.
+
+To publish TACTICAL calls to other Xastir and APRS+SA stations as
+well as assign those tactical calls locally: Send a message to
+"TACTICAL" with the body of the message containing lines something
+like:
+
+ callsign-1=TAC1;callsign-2=TAC2;callsign-3=TAC3
+
+To remove these tactical calls later from local AND remote screens,
+assure that the original message(s) assigning them has timed-out or
+been cancelled, then send a message like this and let it retry until
+it times out (assigns blank tactical calls to the original
+callsigns, thereby removing the assignment):
+
+ callsign-1=;callsign-2=;callsign-3=
+
+Clear all outgoing messages
+This will clear all un-ack'ed messages you have sent.
+
+General Stations Query
+This sends an ?APRS? packet, which should cause all local stations to report
+their position and/or status. Most software ignores this query, because
+responding to it would cause massive floods of data.
+
+IGate Stations Query
+This sends an ?IGATE? packet, which should cause all local IGates to respond
+with their capabilities.
+
+WX Stations Query
+This sends an ?WX? packet, which should cause all local weather stations to
+report their position and weather.
+
+Modify Auto reply message
+This will set the message that is sent as an Auto Reply.
+
+Enable Auto Reply Msg
+This will turn on an automatic reply when an incoming message is received.
+
+Satellite Ack Mode
+This mode disables the sending of ack messages in response to received
+messages. Messages are still acknowledged using the reply-ack system. When
+operating over a satellite it is clear that your message made it, because you
+will hear it repeated. The receiving station sending an independent ack only
+adds QRM.
+
+HELP-INDEX>Interfaces Menu
+
+ Interfaces menu
+
+This menu contains interface related options.
+
+Interface Control
+This option displays a window where you can turn on and off your configured
+interfaces, as well as add, delete, or configure interfaces. See the "Configure
+Interfaces" help topic.
+
+Disable Transmit options
+These options disable the transmission of everything, one's position, or one's
+objects. These are global options and affect all interfaces. Most interfaces
+have an option to disable transmission on that specific interface in their
+configuration menus as well.
+
+Enable Server Port
+This enables/disables TCP and UDP listening sockets at port 2023. You may
+connect other APRS(tm) clients to the TCP port in order to send/receive
+APRS(tm) data. Once they authenticate, they'll be able to send data to Xastir.
+Without authentication, they'll be able to receive every bit of TNC and INET
+data that Xastir receives. Note that ANY user with the proper credentials can
+come in on the TCP or UDP ports if they are enabled. The only one of these two
+ports currently that can send to RF is the UDP Server port. The TCP
+port cannot.
+
+ "user WE7U-13 pass XXXX vers XASTIR 1.3.3"
+
+Connect another APRS(tm) client to that port and it should authenticate and be
+able to send to any server that Xastir is connected to, as well as receive
+packets from all ports/servers Xastir is hooked to.
+
+You should also have a binary called "xastir_udp_client" which can send packets
+into the UDP listening port. Invoke it like this:
+
+ xastir_udp_client localhost 2023 <callsign> <passcode> "APRS Packet Goes Here"
+
+Currently that will inject the packet into Xastir's decoding routines and send
+it to any TCP-connected clients. It will also igate it to the INET if you have
+igating enabled. It will send the packet out the RF ports as third-party
+packets only if you add the "-to_rf" flag after the passcode like this:
+
+ xastir_udp_client localhost 2023 <callsign> <passcode> -to_rf "APRS Packet"
+
+The UDP client is useful for generating and injecting APRS packets from
+external scripts. It can also be used to fetch the callsign of the remote
+xastir server by using the -identify flag:
+
+ xastir_udp_client localhost 2023 <callsign> <passcode> -identify
+
+Transmit now
+Causes all interfaces that have transmit enabled (see configure|interfaces) to
+transmit a position packet. It will be grayed out if Disable Transmit: ALL
+is selected.
+
+If you have GPSMan installed, you have these additional menu options
+displayed:
+
+Fetch GPS Track
+Download a set of trackpoints from an attached GPS.
+
+Fetch GPS Routes
+Download a set of routes from an attached GPS.
+
+Fetch GPS Waypoints
+Download a set of waypoints from an attached GPS.
+
+Fetch Garmin RINO Waypoints
+Snag waypoints from an attached Garmin RINO, create APRS(tm) Objects out of any
+waypoints which begin with "APRS".
+
+HELP-INDEX>Station info box - FCC and RAC lookup
+
+ Station info box - FCC and RAC lookup
+
+Station Info will display any data decoded by Xastir.
+
+You can assign (local only) tactical calls to stations from here, by
+clicking the "Assign Tactical Call" button. This will cause the
+station on screen to display as the tactical call instead of its
+callsign. Assigning a blank tactical call clears this feature, and
+it can also be cleared for all stations in the Stations menu. This
+feature assigns tactical calls to the local Xastir station only, but
+see below to publish them to others.
+
+To publish tactical calls across the air to other Xastir and APRS+SA
+stations (as well as assign them locally), see the "Send Message" help
+section.
+
+"Enable Automatic Updates" will cause the window to refresh frequently with the
+latest information.
+
+The information available may include: Number of packets heard, the time
+last heard, the device the packet came from, station comments,
+power/height/gain of the station, course/distance from your station,
+weather information, and current and previous positions.
+
+For moving stations a track-log follows with the most recent entries on top.
+A '+' in front indicates that a new track starts at that point (if there was
+a large gap in time or position). A star at the end of a line indicates that
+this station could be heard direct (without a digi) at that specific position.
+Positions are followed by the 6 digit Maidenhead grid square the station was
+located in at that point.
+
+For your own station, there is an "Echoed from" field, listing the
+last six digipeaters that heard you directly. This is useful for setting
+non-generic paths.
+
+Currently two rows of four buttons appear in the Station Info window. Some
+of the labels on the buttons change based on the type of station that you're
+dealing with.
+
+For objects/items:
+
+Store Modify Blank Close
+Track Object/
+ Item
+
+Station Trace Un-Acked Direct
+Version Query Messages Stations
+Query Query Query
+
+For other stations:
+
+Store Send Search Close
+Track Message FCC (RAC)
+ Database
+
+Station Trace Un-Acked Direct
+Version Query Messages Stations
+Query Query Query
+
+"Station Version Query" changes to "Clear Track" for mobile stations.
+The Clear Track button will clear any line tracking for this station that is
+currently stored or on the map display.
+
+"Store Track" will save the track of the station to a file on disk. The
+format is similar to that used by GPS receivers but its specification
+might be changed (enhanced) in future versions. There is currently no
+way to read that track data back in, but it is planned for the future.
+The goal is to also read and display GPS track-logs in a similar manner.
+These track-log files will be placed in the directory ~/.xastir/tracklogs
+with a name equal to the stations call with ".trk" as extension. "Store
+Track" will simultaneously save the station's track as a Keyhole Markup
+Language (.kml) file with a filename equal to the station's call, the
+current date and time and .kml as extension. If shapefile support has
+been included, the station's track will also be saved as a set of four
+files (.dbf,.prj,.shp,.shx). Subsequent presses of Store Track for the
+same station will write additional lines into the .trk file, and create
+new .kml (and shapefile) files (each containing all positions in the
+station's track.
+
+"Modify Object/Item" will bring up the Object Modify window.
+
+"Send message" will open up the message window and allow you to send a message
+to this station. It will fill in the call sign for you.
+
+If the FCC (U.S. Federal Communications Commission) or RAC (Radio Amateurs of
+Canada) database is installed and the callsign appears to be a Canadian or
+U.S. callsign, the "Search FCC/RAC Database" button will become active,
+otherwise this button will be inactive. The FCC and RAC files should be
+placed in the /usr/local/share/xastir/fcc directory, and case is important!
+Pressing this button adds the station's name and address into the Station
+Info box. Instructions for installing these databases are in the README.MAPS
+file.
+
+Xastir will create index files for each database file upon startup. If a newer
+callsign file is placed there while Xastir is running, it will create or
+rebuild the index on the next lookup. Special prefixes are NOT handled.
+
+HELP-INDEX>Creating a log
+ Creating a log
+
+Xastir can log data from the internet or TNC for later playback, or for
+debugging purposes. WARNING: Logging can fill up your hard drive, so be
+careful using it, or make preparations for rolling over the log files
+automatically via cron. An indication will be shown on the status bar when
+logging is enabled.
+
+All these choices are accessible via the File menu:
+
+Enable TNC Logging
+Logs all TNC data received and transmitted. These logs can be played back using
+the "Open Log File" feature.
+
+Enable Net logging
+Logs all internet data received and transmitted. These logs can be played back
+using the "Open Log File" feature. If you have no interfaces started but still
+want to log your posits and objects locally, this is the option to enable for
+that as well.
+
+Enable IGate logging
+Logs all data forwarded in both directions, and rejected forwards with reasons
+for rejection. Includes NWS messages forwarded to RF.
+
+Enable WX logging
+Logs all weather data received from your weather station.
+
+
+HELP-INDEX>Replaying a log
+
+ Replaying a log
+
+Click on "File", then "Open Log File" and a file selector window will display.
+You can use it to browse your hard drive and select any file containing raw
+TNC data like those created by the TNC and Net logging options. Your station
+will still function the same way, receiving and transmitting. If you were
+logging data, the typical place to look for those files would be
+~/.xastir/logs/
+
+NOTE: This function doesn't read the saved station tracklogs.
+
+HELP-INDEX>Locating a Station
+
+ Locating a Station
+
+Click on "Stations", then "Find Station". A window will pop up. You can now
+enter a call or part of a call. By default it will search for an exact match
+(full call, not partial) and is not case sensitive. If you are looking for a
+partial match, "Match Exact" should not be selected.
+
+For objects which could contain lower case letters you have to check
+"Match Case"! Opposite to the name, without "Match Case" the search
+text will only be converted to upper case...
+
+Clicking on the "Locate Now!" button will center the first station
+found in the center of your screen at the current zoom level.
+
+Clicking "FCC/RAC Lookup" will look up the user's information if the FCC or RAC
+database, of those databases are installed.
+
+Clicking on "Cancel" will close the window.
+
+This dialog will pop up if a station sends a Mic-e "Emergency!" packet, to
+encourage users to locate and perhaps help the listed station.
+
+HELP-INDEX>Creating and using Map Display Bookmarks
+
+ Creating and using Map Display Bookmarks
+
+Click on "Maps", then "Map Display Bookmarks" and a window will pop up.
+If this is the first time you have used this then the box will have no
+entries in it. To add a bookmark to the list: Position the main map to
+the area and zoom level you want to use. Enter a unique name in the
+"New Name" area, then click on add. Your entry will be added to the
+list (in alphabetical order). You can add as many map display bookmarks
+as you want. To use one of the bookmarks mark its name and click
+"Activate!". The main map will then show the stored area and zoom level.
+You can similarly delete a bookmark by clicking on the bookmark name and
+then the "Delete" button.
+
+"Maps->Locate Map Feature" is another method to jump to a location, if
+the name of the location is known and you have GNIS files installed.
+
+HELP-INDEX>Tracking a Station
+
+ Tracking a Station
+
+Click on "Stations", then "Track Station". Enter the callsign to track (all or
+part) then click on the "Track Now!" button. As the station moves it will
+remain viewable in the main map window. As the stations starts to get close
+to the edge of the map window the window will re-center so that the object is
+always visible. To stop tracking this station click on the "Clear Tracking"
+button. While tracking is active, a "Tr" is shown in the status bar next to
+the zoom level. If the station is not on the map yet, tracking will begin
+as soon as it shows up.
+
+HELP-INDEX>Printing
+
+ Printing the Map Screen
+
+Note: Printing has not been set up on Windows/Cygwin. These instructions
+are for Unix and Unix-like operating systems.
+
+Xastir can print the drawing area in either black & white or color. It does
+this by first dumping the image to an XPixmap file on disk, then using external
+tools to convert it to postscript, scale it, rotate it, preview it, then print
+it. You must have your system printing set up to handle postscript (usually
+this requires Ghostscript and a print filter installed, as well as lp or lpr
+print spoolers). You must also have the following tools installed for this
+capability: ImageMagick tools (specifically "convert"), "Ghostscript",
+Ghostscript fonts, and "gv". Once all of these packages are installed and
+functional, you should get a "gv" window popping up shortly after you tell
+Xastir to create a print file. From there you can view the printed image, and
+if acceptable, tell "gv" to print it. Note that sometimes changing to a white
+default background for the maps is recommended, depending on what maps you have
+viewable. This can save greatly on ink.
+
+HELP-INDEX>Creating Snapshots
+
+ Creating Automatic Snapshots
+
+Xastir has the capability to create automatic snapshots of the map screen
+on a recurring basis. The default time period is set at once per five
+minutes. Assuming that you have "convert" from the ImageMagick tools
+installed, Xastir will create an XPM format file in ~/.xastir/tmp/, then
+convert it to the PNG file ~/.xastir/tmp/snapshot.png. This file is useful for
+embedding in web pages to show a "live" image of what is on your Xastir
+screen. Enable this feature via the "File->PNG Snapshots" toggle-button.
+The rate is once every five minutes (configurable from the Configure
+Timing dialog from "File->Configure->Timing"), or every time the button is
+toggled from off to on. A .geo is created to allow you to use the snapshot
+as a map. A .kml file is also written to allow you to use the snapshot as
+a graphic overlay on terrain in applications capable of reading kml. See
+kml_snapshot_to_web.sh and kml_snapshot_feed.kml in the scripts directory
+for more information on using the snapshot.png and snapshot.kml file to
+produce a kml feed using the snapshots.
+
+ Creating Automatic KML Snapshots
+
+Xastir is capable of writing all current stations and tracks to a kml file
+on a recurring basis. Enable this feature via the "File->KML Snapshots"
+toggle button. The rate at which these snapshots are generated is the same
+as that of PNG snapshots, configured from "File->Configure->Timing" by
+setting the snapshot time interval. Each snapshot is written to a .kml
+file in ~/.xastir/tracklogs, with a filename based on the date and time
+of the snapshot, e.g. 20080206-000720.kml This behavior may change to
+make KML snapshots write to a single file like PNG snapshots.
+
+
+HELP-INDEX>Included Scripts
+
+ Included Scripts
+
+Xastir includes several Perl scripts and a shell script that may be useful:
+
+get-fcc-rac.pl
+This shell script automates retrieving and installing the FCC and the RAC
+callsign databases. Note that these databases are very large!
+
+icontable.pl
+This script generates an xpm bitmap of all Xastir's primary and secondary
+symbols from the symbols.dat file. The overlays and specials are ignored.
+Output is to STDOUT, so a typical call would be "icontable.pl > symbols.xpm".
+
+inf2geo.pl
+This script creates .geo files from UI-View .inf files. To create a map.geo
+from a map.inf, typical usage would be "inf2geo.pl map".
+
+kiss-off.pl
+This script sends the commands needed to turn off a TNC's KISS mode.
+
+mapblast2geo.pl
+This script creates .geo files for Mapblast pixel maps. It includes usage
+information.
+
+mapfgd.pl
+This script creates minimal .fgd files for GeoTIFF images lacking them, based
+on information found in the GeoTIFF file. The created files allow Xastir to
+crop the white borders and rotate/scale the map properly. Typical usage would
+be "mapfgd.pl mapdir" where mapdir is the directory containing the GeoTIFF
+images.
+
+overlay.pl
+This script creates .log format files from comma-separated overlay files. See
+the script comments for full usage information.
+
+ozi2geo.pl
+This script creates .geo files from OziExplorer .map files.
+
+permutations.pl
+This script converts between different lat/lon formats. See the script comments
+for further details.
+
+split_gnis.bash
+This will take a GNIS data-point file (typically for a whole state, 8+MB), break
+it down into smaller chunks (typically for a county, 30-200k) it will also
+throw away the trailing spaces and <CR>s at EOL.
+
+split_gnis.pl
+This is a Perl version of the above script.
+
+test_coord.pl
+Tests for the Coordinate.pm Perl module.
+
+track-get.pl
+This script downloads the track-log of a specified object from a Garmin GPS.
+It requires the GPS::Garmin module. It prompts for an object name, and writes
+the track-log to the ~/.xastir/logs directory.
+
+update_langfile.pl
+This script is targeted toward developers. It rebuilds a specified language
+file to contain all the strings of another. It is usually used to regenerate
+the non-English language files when significant changes have been made to the
+English file. When the second language file lacks a string in the main file,
+the untranslated string is inserted. Typical usage would be
+"update_langfile.pl language-German.sys" . The main language file is
+hard-coded but easily editable.
+
+waypoint-get.pl
+This similar script downloads the waypoints from a Garmin GPS, and creates a
+log in the ~/.xastir/logs directory containing the waypoints as objects. It
+also requires the GPS::Garmin module.
+
+db_gis_mysql.sql db_gis_postgis.sql
+These will create tables for storing station data in a mysql or postgresql/
+postgis database. SQL Server database support is experimental. See the
+"OPTIONAL: Experimental. Add GIS database support" section in INSTALL
+
+HELP-INDEX>Configuring Interfaces
+
+ Configuring Interfaces
+
+Click on Interfaces, then Interface Control.
+
+An "Installed Interfaces" box should appear. This box will allow you to add,
+delete, and modify the properties of various devices you may want to use with
+Xastir.
+
+Supported interface types are:
+Serial TNC
+Serial TNC w/GPS on HSP cable
+Serial GPS
+Serial WX
+Internet Server
+AX.25 TNC
+Networked GPS (via gpsd)
+Networked WX
+Serial TNC w/GPS on AUX port
+Serial KISS TNC
+Networked Database (Not Implemented Yet)
+Networked AGWPE
+Serial Multi-Port KISS TNC
+SQL Databases [MySQL,Postgis] (Experimental)
+
+To add a device, click on the add button. A "Choose Interface Type" box will
+appear. Click on the type of device you would like to add. Then click the Add
+button in the "Choose Interface Type" box. Properties for that device will
+appear. Fill out the requested information and click OK.
+
+To delete the device, click on the device you wish to delete and then click
+the delete button.
+
+To modify the properties of a device, click on the device you wish to modify,
+then click the properties button. The properties for that device will appear.
+Change the information you want and click OK.
+
+More specific help is available under the help topics of each interface type.
+
+SQL Databases will only appear as an option if you have MySQL or Postgis
+support compiled.
+
+HELP-INDEX>Configure Serial TNC Devices
+
+ Configure Serial TNC Devices
+
+This section covers adding or modifying Serial TNCs or Serial TNCs with a
+GPS on a HSP cable.
+
+If you have a HSP cable, which allows you to share the TNC port with a GPS
+unit you may choose a TNC with GPS (HSP Cable). This is a special cable and may
+not work on all computers/GPS/TNC combinations. If you use this device the TNC
+and the GPS should be set to the same communications parameters. Generally
+4800 bps, 8 data bits, no parity, and 1 stop bit.
+
+TNC Port Options:
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Allow Transmitting" will tell Xastir that any outgoing RF data can
+be sent to this device for broadcast.
+
+The TNC Port is the Unix device that the TNC (or TNC and GPS) is hooked to.
+Normally you can use /dev/ttyS0 (com1), /dev/ttyS1 (com2) etc.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Now set the bps rate under port settings, and the parameters under port
+style. Port Style setting 8N1 is used for 8 data bits, No parity and 1 stop
+bit. 7E1 is used for 7 data bits, even parity and 1 stop bit. 7O1 is used for
+7 data bits, odd parity, and 1 stop bit. These parameters must match your TNC
+and GPS.
+
+Choose the correct IGate operation for this device. You may have several TNC
+devices, and this option can be different for each device. If you are not
+running an IGate leave it at the default option of "Disable".
+
+Enter up to three UNPROTO paths. Xastir will assume the XX VIA part of the
+UNPROTO path. There are three paths allowed so that your signal will be heard
+if conditions are bad. XASTIR will cycle through each one that is filled in,
+one per transmission time. If you are local to a digi, just WIDE2-2 may be a
+good choice. If you are using low power and/or are distant from a digi then
+WIDE1-1, WIDE2-2 may work better. Or if you know the call of your closest digi you
+may use XXXCALL, WIDE2-2. Most of you will only need one path. If you are in a
+remote area and your signal is difficult to get out you may need more. Check
+with a local group and ask what path may be best for your area. If no paths are
+entered it will default to WIDE2-2.
+
+If you are IGating to RF, you may enter a specific path to use for the packets
+you send to RF. If you leave this blank, the UNPROTO paths above will be used.
+If the UNPROTO paths are blank, WIDE2-2 will be used.
+
+TNC Startup and Shutdown files. These fields specify a filename that is
+located in the /usr/local/share/xastir/config directory. Each file is a
+standard text file containing any commands you would like to send your TNC at
+the time the device is activated (startup file) or shut down.
+
+HELP-INDEX>Configure Serial TNC w/GPS on HSP cable or AUX port
+
+ Configure Serial TNC w/GPS on HSP cable or AUX port
+
+These hybrid interface types implement the options of both serial TNCs and
+GPSs. Please consult the configuration help for both serial TNCs and serial
+Gpsd for further information on the configuration of these devices.
+
+"Send Control-E to get GPS Data?"
+
+This checkbox controls whether Xastir sends a Control-E to the TNC every time
+it needs GPS data.
+
+Some TNCs that support a GPS on an auxilliary port require that Xastir
+send a Control-E to the TNC in order to get the GPS data each time it
+is needed. Devices in this class include the Kantronics KPC-3+.
+
+Some devices, like Kenwood APRS radios (D700, etc.) do NOT require
+this, and in fact the Control-E interferes with correct operation of
+these devices.
+
+Because Control-E was required by the most common TNCs that had an aux
+port for GPS at the time that this interface type was written, this is
+the default behavior of Xastir. If you have a Kenwood radio that you are
+using in this mode, you must DESELECT the "Send Control-E to get GPS data?"
+checkbox in the configuration dialog for this interface type.
+
+HELP-INDEX>Configure Serial KISS TNC
+
+ Configure Serial KISS TNC
+
+This section covers adding or modifying Serial KISS TNCs. KISS mode can be done
+by most standard TNCs too, and it eliminates the necessity to set the options
+specially in the startup files, at the expense of slightly higher processor
+usage. And of course this enables the use of purely KISS TNCs, such as the one
+described in the November 2000 issue of QST, without a separate program or
+kernel module.
+
+Options
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Allow Transmitting" will tell Xastir that any outgoing RF data can
+be sent to this device for broadcast.
+
+Selecting "RELAY Digipeat?" will tell Xastir to digipeat traffic. It will do
+this if the first unused digipeater call in the path matches your callsign or a
+callsign listed in your Xastir config file ("RELAY_DIGIPEAT_CALLS" line,
+default is "WIDE1-1"). This option is only recommended for base stations in
+regions where there are few other fill-in digipeaters in the area. Consult with
+a local group about the best setting for your region. You may hand-edit the
+Xastir config file when Xastir is not running in order to change this string to
+match your local recommendations. In the U.S., "WIDE1-1" is the recommended
+setting.
+
+The TNC Port is the Unix serial device that the TNC is hooked to.
+Normally you can use /dev/ttyS0 (com1), /dev/ttyS1 (com2) etc.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Now set the bps rate under port settings.
+
+Choose the correct IGate operation for this device. You may have several TNC
+devices, and this option can be different for each device. If you are not
+running an IGate leave it at the default option of "Disable".
+
+Enter up to three UNPROTO paths. Xastir will assume the XX VIA part of the
+UNPROTO path. There are three paths allowed so that your signal will be heard
+if conditions are bad. Xastir will cycle through each one that is filled in,
+one per transmission time. If you are local to a digi, just a WIDE2-2 may be a
+good choice. If you are using low power and/or are distant from a digi then
+WIDE1-1,WIDE2-2 may work better. Or if you know the call of your closest digi
+you may use XXXCALL,WIDE2-2. Most of you will only need one path. If you are in
+a remote area and your signal is difficult to get out you may need more. Check
+with a local group and ask what path may be best for your area. If no paths
+are entered it will default to WIDE2-2.
+
+If you are IGating to RF, you may enter a specific path to use for the packets
+you send to RF. If you leave this blank, the UNPROTO paths above will be used.
+If the UNPROTO paths are blank, WIDE2-2 will be used.
+
+Next configure the KISS parameters: TXdelay is the time (in 10ms units) needed
+between the keying of the radio and when it is ready to send data. Persistence
+and slottime are the channel access parameters: Slottime is how often the
+channel access algorithm is executed, and should usually be set to 10.
+Persistence is how aggressively your station tries to grab the channel when
+free, and should be ideally set to 255 divided by the number of stations on the
+channel. Full duplex allows the transmission to begin while there are packets
+being received on the channel, this should be disabled in most cases (set to
+"0").
+
+HELP-INDEX>Configure AX.25 TNC Devices
+
+ Configure AX.25 TNC Devices
+
+This section covers adding or modifying AX.25 TNC devices. AX.25 devices can
+be any device that uses the Linux AX.25 drivers. This is a kernel level
+driver, and device such as a Baycom or a sound modem can be used as a TNC.
+These devices must be set up and running before Xastir can use them.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Allow Transmitting" will tell Xastir that any outgoing RF data can
+be sent to this device for broadcast.
+
+Selecting "RELAY Digipeat?" will tell Xastir to digipeat traffic. It will do
+this if the first unused digipeater call in the path matches your callsign or a
+callsign listed in your Xastir config file ("RELAY_DIGIPEAT_CALLS" line,
+default is "WIDE1-1"). This option is only recommended for base stations in
+regions where there are few other fill-in digipeater stations in the area.
+Consult with a local group about the best setting for your region. This is
+only needed if you are not using any other software that performs this
+function, such as aprsdigi or DIGI_NED. You may hand-edit the Xastir config
+file when Xastir is not running in order to change this string to match your
+local recommendations. In the U.S., "WIDE1-1" is the recommended setting.
+
+Enter the AX.25 Device name you specified in the axports file for this device.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Choose the correct IGate operation for this device. You may have several TNC
+devices and this option can be different for each device. If you are not
+running an IGate leave it at the default option of "Disable".
+
+Enter in up to three UNPROTO paths. Xastir will assume the XX VIA part of the
+UNPROTO path. There are three paths allowed so that your signal will be heard
+if conditions are bad. Xastir will cycle through each one that is filled in,
+one per transmission time. If you are local to a digi, just a WIDE2-2 may be a
+good choice. If you are using low power and/or are distant from a digi then
+WIDE1-1,WIDE2-2 may work better. Or if you know the call of your closest digi
+you may use XXXCALL,WIDE2-2. Most of you will only need one path. If you are in
+a remote area and your signal is difficult to get out you may need more. Check
+with a local group and ask what path may be best for your area. If no paths
+are entered it will default to WIDE2-2.
+
+If you are IGating to RF, you may enter a specific path to use for the packets
+you send to RF. If you leave this blank, the UNPROTO paths above will be used.
+If the UNPROTO paths are blank, WIDE2-2 will be used.
+
+NOTE: To use AX.25 devices with Xastir you will need to run the program as
+"root". If you want to run Xastir as another user you may want to set the
+suid bit on the Xastir program file. Please see INSTALL file for more
+information; current Xastir drops the extra privileges but has not been audited
+for exploits. Use in this fashion in a multi-user environment at your own risk!
+
+HELP-INDEX>Configure Serial GPS Devices
+
+ Configure Serial GPS Devices
+
+Set the serial port device for your GPS unit. Common values of /dev/ttyS0
+(COM1) or /dev/ttyS1 (COM2) can be used.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Set system clock from GPS data" will tell Xastir to try setting the
+system's clock to the highly accurate time signal from the GPS receiver. This
+requires root privileges on most systems.
+
+Now set the bps rate under port settings, and the parameters under port
+style. Port Style setting 8N1 is used for 8 data bits, No parity and 1 stop
+bit. 7E1 is used for 7 data bits, even parity and 1 stop bit. 7O1 is used for
+7 data bits, odd parity, and 1 stop bit. These parameters must match your GPS.
+Most GPS units will use 4800 bps and 8,n,1.
+
+HELP-INDEX>Configure Networked GPS Devices
+
+ Configure Networked GPS Devices
+
+If you need to share the GPS data with different programs or machines, this
+option is best. Xastir will work with gpsd which will allow several
+connections to share your GPS data.
+
+Set the host name (or IP address) and the port number for the gpsd host on
+your network.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Reconnect on failure" will tell Xastir to try to reconnect when the
+data stream has failed.
+
+Selecting "Set system clock from GPS data" will tell Xastir to try setting the
+system's clock to the highly accurate time signal from the GPS receiver. This
+requires root privileges on most systems.
+
+HELP-INDEX>Configure the Internet Server
+
+ Configure the Internet Server
+
+Internet Servers allow you to send and receive data for all over the world.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+setup communications with it when the program first starts.
+
+Selecting "Allow Transmitting" will tell Xastir that any outgoing Internet
+data can be sent to this device.
+
+Enter the host name (or IP address) and the port number of the Internet
+Server you want to contact.
+
+Enter a valid pass-code to validate your connection, this will allow your
+data to be transmitted via an IGate. If you don't have a pass-code, use the
+included "callpass" program to generate one. Note that passcodes are dependent
+on callsigns. From the src directory, "make callpass" should create the
+executable if it isn't already compiled.
+
+Enter any filter parameters. This causes a special message to be sent to the
+server requesting that the data be filtered in a certain way. The exact format
+of this field is fully specified, please consult APRSSIG for more information.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Reconnect on failure" will tell Xastir to try to reconnect when the
+data stream has failed.
+
+HELP-INDEX>Configure a Serial WX Station
+
+ Configure a Serial WX Station
+
+Set the serial port device for your WX unit. Common values of /dev/ttyS0
+(COM1) or /dev/ttyS1 (COM2) can be used.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Now set the bps rate under port settings, and the parameters under port
+style. Port Style setting 8N1 is used for 8 data bits, No parity and 1 stop
+bit. 7E1 is used for 7 data bits, even parity and 1 stop bit. 7O1 is used for
+7 data bits, odd parity, and 1 stop bit. These parameters must match your WX
+unit. The Data Type option will allow you to override what type of serial data
+the program will look for. The auto-detect feature will first look for Weather
+data in a binary type as the Radio Shack WX-200 uses. If no binary data is
+found in the stream, Xastir will look for an ASCII type of WX station (like
+Peet Bros.).
+
+Now set the Rain Gauge correction factor. Xastir requires that the rain gauge
+report in .01 inch increments. If the unit reports in .1 inch or .1 millimeter
+increments, a correction must be specified to obtain accurate measurements.
+
+HELP-INDEX>Configure a Networked WX Station
+
+ Configure a Networked WX Station
+
+Xastir can use WX data servers such as wx200d. wx200d will allow several
+network connections, thus sharing the Weather data with several programs or
+computers.
+
+Enter the host name (or IP address) and the port number of the WX data server
+you want to contact.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Reconnect on failure" will tell Xastir to try to reconnect when the
+data stream has failed.
+
+As before the Data Type will override the auto detection.
+
+Now set the Rain Gauge correction factor. Xastir requires that the rain gauge
+report in .01 inch increments. If the unit reports in .1 inch or .1 millimeter
+increments, a correction must be specified to obtain accurate measurements.
+
+HELP-INDEX>Configure an AGWPE Connection
+
+ Configure an AGWPE Connection
+
+Xastir can use an AGWPE network interface running on a Windows box
+as a TNC interface. It can also use the login/password security that
+AGWPE has built-in, but you must set up the account in the AGWPE
+application with your callsign for the username, in all capital
+letters. For instance: "AB7CD".
+
+The other options are described in the sections for Serial TNC and for
+Network interfaces.
+
+HELP-INDEX>Configure a SQL Database Connection
+
+ Configure a SQL Database Connection
+ [Experimental]
+
+Xastir can experimentally store and retrieve station data from either
+a MySQL database or a Postgresql + Postgis database. See the
+"OPTIONAL: Experimental. Add GIS database support." section in the
+INSTALL file for more information. Station and object data are stored
+as spatial data, and can be retrieved from other GIS applications, for example
+Xastir can write station locations into a Postgis database from which they
+can also be viewed using QGIS. SQL database connections also allow for the
+persistence of data between Xastir sessions. All aspects of spatial database
+support, including database structures, are currently experimental and may
+change at any time. You may configure multiple SQL database connections,
+but you should only have one active at a time.
+
+Before creating a database connection in Xastir, you will need to create a
+database to connect to, create an appropriate set of tables
+(see the db_gis_xxxxx.sql scripts in the scripts directory), and add a user
+with a password and rights to access the database. For postgis databases
+you may also need to appropriately configure the user in pg_hba.conf
+
+Configuration options on the SQL database dialog include:
+Database: MySQL (lat/long) for very old MySQL databases,
+ Postgis for postgresql + postgis, and
+ MySQL (Spatial) for current MySQL databases.
+With tables for: Currently only the Xastir simple schema - a very basic
+ flat table holding minimal information about stations.
+Host: IP address or hostname for the database server, default is localhost.
+Port: Default is 3306 for MySQL and 5432 for Postgresql. The database can
+ be on a remote server, but the appropriate port will need to be
+ open in any firewalls.
+Username: Can be unique to your database, e.g. xastir_user
+Password: Unique to your database.
+Schema name: Your database name. e.g. xastir
+MySQL Socket: check my.cnf, or mysql --help | grep socket
+ Leave blank for postgis databases.
+Reconnect on Net Failure: [Not yet implemented]
+MySQL defaults and Postgis defaults provided by the buttons may
+or may not be correct for your database.
+
+Three options control the behavior of the SQL Database interface:
+Activate on Startup: Try to connect to this database and begin storing heard
+station data as soon as Xastir starts (if store incoming data is also selected).
+
+Store incoming data: Stores each station (including objects and items) report
+as a record in the database. All stations heard on all interfaces will be
+stored to the database - if you are connected to internet feeds and leave
+xastir running this can easily be a million records per day.
+
+Load data on startup: Retrieve all station data from the database
+when restaring Xastir. Currently the only way to retrieve persistent
+data from a database. Will attempt to connect to database and retrieve data
+independent of the settings of either activate on startup or store incoming
+data. Due to rounding and conversion errors, non-mobile stations may move
+slightly.
+
+The "Most Recent Error" box may or may not contain an error message to help
+identify connection problems. When Xastir fails to connect to a database,
+the interface will show ERROR on the interface list, and the most recent error
+may be shown here. Running xastir from the console and observing error
+messages there, or running xastir from the console with xastir -v1 may help
+identify the cause of connection problems, as may examination of the
+database's error logs.
+
+You will only be able to configure a SQL Database interface if you have
+compiled Xastir with support for that DBMS (--with-mysql or --with-postgis).
+
+HELP-INDEX>Symbol Table
+
+These are the symbols that you can select for your station under the "Station
+Information" configuration menu. The current list can be found in the APRS(tm)
+Reference which you could get from http://www.tapr.org
+
+ Symbol Table
+
+Symbol Group / Group \
+
+! Triangle w/! Triangle w/!
+" Rain Cloud Rain Cloud
+# Digi DIGI
+$ Phone Symbol $ Symbol
+% DX DX
+& GATE-HF GATE
+' Small Aircraft Aircraft Crash
+( Cloud Cloud
+) TBD
+* SNOW Flake SNOW Flake
++ Red Cross
+, Reverse L
+- House w/omni
+. Small x
+/ Red Dot
+0 0 in a box Circle
+1 1 in a box
+2 2 in a box
+3 3 in a box
+4 4 in a box
+5 5 in a box
+6 6 in a box
+7 7 in a box
+8 8 in a box
+9 9 in a box GAS
+: Fire ?
+; Tent Tent
+< Motorcycle Pennant
+= Train Engine
+> Car Car
+? POS Antenna ? in a box
+@ HURRICANE/STORM HURRICANE/STORM
+A First Aid Box
+B BBS Blowing Snow
+C Canoe
+D D in a circle
+E E in a circle Smoke Stack
+F F in a circle
+G Grid Square Antenna ?
+H Hotel/Bed
+I TCP/IP ?
+J J in a circle Lightening
+K School House
+L Light House Light House
+M Mac
+N NTS ?
+O Balloon
+P Police car Rx
+Q Circle with in Circles Circle with in Circles
+R RV Restaurant
+S Shuttle Satellite
+T Thunderstorm (cloud/bolt) Thunderstorm (cloud/bolt)
+U School Bus Sun
+V VOR TAC VOR TAC Symbol
+W National Weather Service NWS-Digi
+X Helicopter
+Y Sail Boat
+Z Windows
+[ Runner WC
+\ DF Triangle
+] Packet Mail Box
+^ Large Aircraft Large Aircraft
+_ Weather Station WS-Digi
+` Satellite Dish
+a Ambulance
+b Bike blowing cloud
+c DX antenna
+d Fire dept. DX Antenna
+e Horse Sleet cloud
+f Fire Truck FC Cloud
+g glider Pennant (2)
+h Hospital HAM
+i Island Island
+j Jeep Jeep
+k Truck Truck
+l Small dot Small Dot
+m MIC Mile Post
+n N Small Triangle
+o EOC Dot with in Circles
+p Puppy Dot with in Circles
+q GS Antenna GS Antenna
+r Antenna Tower Antenna Tower
+s Boat Boat
+t TS ?
+u 18 Wheel Truck
+v Van Dot with in Circles
+w H20 Flood
+x X Windows Red Dot
+y House w/Yagi House w/yagi
+z X Windows
+{ FOG FOG
+| Black Line Black Line
+} TCP TCP
+~ Sail Boat Sail Boat
+
+HELP-INDEX>What was new in Xastir 1.0
+
+Over the past year, Xastir has been under active development, and this new
+release is the culmination of those efforts. Development has been run by
+Chuck Byam, who agreed to take over for Frank Giannandrea. Many other
+individuals have contributed to this project, and are listed in the AUTHORS
+file.
+
+The Xastir package now uses GNU autoconf to build makefiles and select
+features based on the libraries and software one has installed. No more
+editing makefiles as in previous releases!
+
+Starting Xastir 1.0, one probably won't immediately notice any major
+changes. The familiar interface of previous Xastir versions has been retained
+for the most part. The great majority of the changes are improvements in
+efficiency under the hood:
+* Startup time for the program has been improved.
+* Memory usage has greatly improved, with dynamic allocation of separate
+ station, trail, and weather data on an as-needed basis. No longer will
+ memory be wasted on stationary stations for trail data, nor will non-weather
+ stations waste memory for weather information. With these modifications,
+ Xastir can even be connected to the internet link comfortably on a 16MB
+ machine.
+* Improvements have been made to avoid having to reload maps from disk at every
+ minor change; Weather alerts and changes to the display and tracking options
+ no longer cause the maps to reload, rather the trails and symbols are
+ redrawn alone.
+* Improvements have been made to various dialog boxes that re-drew often, to
+ redraw less often, to allow them to be usable on slower systems. This is
+ also true of tracking a station, with the map redrawing only if the station
+ approaches the edge of the screen.
+Thanks to these changes, Xastir is perfectly usable on slower Pentium(tm)
+machines.
+
+Native GeoTIFF support is now included, and will be compiled into one's copy
+of Xastir if they have the GeoTIFF libraries installed on their system. These
+map files are of very high quality, and are especially useful in search and
+rescue operations. Maps on this format are available from the USGS, and
+commercially on CD-ROM. Xastir understands how to convert from the NAD-27
+datum to the new WGS-84 datum, so maps of both format can be read accurately.
+New shortcut buttons have been added to the map selection dialog to enable
+one to pick all maps of a specific type.
+
+Support for the Festival Speech Synthesis System is now available to announce
+new stations and band openings. The old system of alert sounds has been
+retained as well.
+
+Xastir now supports adding and deleting objects. Finally, Xastir users are able
+to manage resources with this useful feature. Objects are helpful for
+coordinating events, directing travelers, and doing search and rescue work.
+
+The County Warning Area maps that display weather alerts are no longer painted
+onto the maps below, but are shaded onto the maps. While this does make the
+colors unpredictable, it is now possible to see the road-maps below the
+alert!
+
+A new and useful feature is the change in the orientation of a symbol based on
+the direction in which it is moving. Even without a trail, a quick glance can
+tell you a mobile station's bearing. There are several more new options in the
+display menu, enabling one to decide more precisely what is displayed and what
+isn't.
+
+Panning and control over the map has been enhanced: There are now arrow buttons
+visible at the top of the screen to pan the map. The map can also be panned
+with the arrow keys, and the zoom can be adjusted with the page up and page
+down keys. There are new option in the click menu, to center the map where you
+clicked or to place an object where you clicked. The panning options in this
+menu have been removed in favor of the new controls at the top of the screen.
+
+Support for altnet has been added, enabling one to have a private APRS(tm)
+network for special events, search and rescue, storm chasing, or whenever else
+the user doesn't want to be bothered by the hundreds of APRS(tm) stations
+around.
+
+There are numerous small changes, both visible and invisible to the user. The
+interface control dialog now has a "Start all" and "Stop all" option, to save
+the user the time of performing these actions for each interface. The station
+setup dialog now shows you your symbol, so you don't have to exit the dialog to
+see which symbol you chose. Several buffer overflows that caused unpredictable
+behavior and/or crashes have been fixed. And many minor improvements have been
+made to the source code to ensure that it compiles correctly on various
+systems.
+
+Enjoy the new Xastir!
+
+
+HELP-INDEX>What was new in Xastir 1.1
+
+ What was new in Xastir 1.1
+
+This new release, Xastir 1.1, adds significant new features and enhancements
+to the user interface. Unlike 1.0, the interface changes will take some getting
+used to, but the flexibility and versatility of the enhanced interface will
+more than make up for the troubles.
+Among the improvements to the user interface:
+* Keyboard shortcuts for menus and dialogs, menu reorganization, and mouse
+ behavior changes.
+* The ability to move objects or measure distance with the mouse, using the
+ appropriate check-boxes in the toolbar.
+* A scale has been added to allow one to judge distance on a map.
+* Map labels for windows-style APRS(tm) maps are rotated to match the marked
+ map features.
+* The user interface for dealing with objects has been entirely redesigned.
+* Station info boxes can be set to automatically update.
+* Tear-off menus. Allow you to keep a menu on the screen and play with
+ different options. Tear off a menu by clicking on the dashed-line portion.
+
+Map support has been greatly enhanced, with PocketAPRS, ESRI Shapefiles, GNIS
+labels and many graphics formats with ImageMagick. Additionally, support for
+downloading graphical maps from web-servers has been added, allowing Xastir to
+use online radar, Tiger, and Terraserver maps.
+
+Xastir 1.1 supports much more of the APRS(tm) protocol than its predecessor:
+* It can add, modify, move and view area objects, signpost objects, and items.
+ These features are invaluable for event coordination and search and rescue
+ use. Objects and items are also periodically retransmitted.
+* Support for displaying position ambiguity squares, pre-calculated radio
+ ranges, Maidenhead grid squares, and weather objects. These features aren't
+ extremely common, but do come up occasionally.
+* Support for the APRS(tm) radio direction finding features. These features
+ are useful for anything from tracking jammers to locating lost hikers. Xastir
+ supports both Omni and Beam reports.
+
+Other notable improvements:
+* Xastir can now search for a specified location or landmark using GNIS data.
+* Track logs can now be exported to file.
+* Maps can be printed if certain tools and libraries are present.
+* Support for retrieving historical track data from findu.com.
+* Xastir now compiles and runs on Mac OS X, Solaris and FreeBSD with only
+ minimal changes; see README for details.
+* Several major bugs found in 1.0 have been corrected, including the problems
+ loading DOS maps and the problems with the weather reporting. Other minor
+ bugs and memory leaks have been fixed. And several more errors have been
+ corrected in the parsing routines, so Xastir should remain stable no matter
+ what is thrown at it!
+
+
+HELP-INDEX>What was new in Xastir 1.2
+
+ What was new in Xastir 1.2
+
+The latest Xastir release adds numerous new capabilities, keeping Xastir a
+benchmark for APRS(tm) programs on any operating system.
+
+Xastir's hardware support has been enhanced, with
+* Support for Serial KISS TNCs
+* Support for Serial TNCs with GPS on the AUX port
+* Support for using AGWPE as a TNC
+* Support for Dallas One-Wire weather station
+ (see http://melhuish.info/simon/projects/oww/)
+* Support for more weather stations via the wx200d daemon (WX-200/WM-918/
+ WMR-918/WMR-968)
+* Support for the different sized rain gauges of the Peet Brothers weather
+ stations.
+
+Additionally, several bugs in the weather reporting code were corrected, and
+support for setting the system clock based on the GPS was added.
+
+There have been many additions and improvements to the Xastir user interface:
+The most notable is the addition of dead-reckoning. This means that stations
+that are moving will continue to move on your screen in the direction and at
+the speed speed that they last reported. The estimated location can be shown
+with any combination of a ghosted icon, a dashed line from the last position,
+or an arc of expected possible distance and angle.
+
+Also very notable are the improvements to the Map Chooser. Maps can now be
+selected a directory at a time, or individually. And the new map properties
+dialog allows individual control of map layering, map color filling, and
+consideration for auto-maps. Additionally, with extent caching under the hood,
+auto-maps regains much of its formal usefulness even with many maps installed!
+
+Bulletins pop up on screen, and emergency beacons cause an alert with the
+locate station dialog on hand. These changes are helpful in emergencies and
+event coordination.
+
+Xastir can now be set to use one of several coordinate systems, including UTM,
+dd.ddddd, dd mm.mmm, and dd mm ss.s. This is helpful for coordinating with
+other groups using a different system.
+
+The online Tiger maps can now be enabled from the map menu, and options can
+be adjusted to request maps with just the data you want displayed.
+
+The stations menu has been reorganized, allowing more intuitive filtering of
+stations shown and of accompanying data.
+
+Other smaller interface changes include:
+* The density of the grid-lines can be adjusted with the +, =, and - keys.
+* Objects and item lists have been added to the view menu.
+* Station maidenhead grid squares are now shown in station info and the
+ coordinate calculator.
+* There is a check-box "Track me" to enable easily tracking your own station
+* The length of trails downloaded from findu.com can now be specified.
+* Xastir can now ID via voice IDs or Screen IDs, by editing the configuration
+ file. This is intended for configurations when the Xastir screen is seen
+ remotely via fast-scan TV.
+* Timestamps are written to log files every 30 seconds of operation, to keep a
+ record of when data was heard.
+* The status bar can display the course/distance to your station when
+ enabled in the file|configure menu.
+* Range scales are now shown opposite the map scale. This is an attempt to
+ standardize various APRS(tm) client approaches to zoom levels.
+
+New additions under-the-hood:
+* Tracked proximity alarms.
+* Export waypoints within proximity boundaries. Your GPS can show
+ you the locations of APRS(tm) stations as waypoints on the GPS map
+ screen.
+* Export trail as ESRI Shapefile. New feature if you have Shapelib
+ compiled in. Station Info->Store Track button also creates a
+ Shapefile map of the station's track now.
+
+The weather reporting features have been improved, with the addition of
+optional wind barbs to weather stations and decoding of storm wind radius data.
+Weather alert shading is now done with pixmap stipples showing the type of
+alert. Further information on an alert is available over the internet from
+the WXSVR by simply double-clicking the alert in the weather alerts list.
+Weather alerts now use the newer ESRI Shapefile-format maps.
+
+Xastir's map support has been improved with enhancements to the ESRI Shapefile
+code to handle point-type ESRI Shapefiles. Additionally, speed improvements
+have been made in the ImageMagick graphical map loading, and many
+color-correction features have been added. As mentioned above, the Map Chooser
+has been greatly improved, and weather alerts use ESRI Shapefile-format maps.
+
+Under the hood, Xastir has had several major improvements:
+
+The messaging system has been largely rewritten, and the annoying timed updates
+to dialogs no longer occur. The new messaging system allows multiple messages
+to be queued, and implements reply-ack's for speed. Xastir also attempts to
+specify a reasonable path for the message based on received messages. This
+improves speed and congestion control. The messaging GUI has been largely
+untouched, and remains high on the list of future improvements.
+
+The build process has been significantly improved; Xastir is now able to be
+built on numerous operating systems with few manual interventions.
+
+Xastir now supports GPSMan/gpsmanshp, allowing the importing of waypoints,
+tracks, and routes from several types of GPS receivers. This allows you to
+create ESRI Shapefile-format maps out of GPS data.
+
+Xastir now implements SmartBeaconing(tm), which greatly improves trail quality
+and reduces unneeded channel usage. See the "Configure SmartBeaconing" help
+topic.
+
+IGating support has also improved, with the ability to configure a specific RF
+path for IGated packets, and the addition of a 29 second anti-dupe queue to
+reduce unnecessary redundancy on the RF channel.
+
+Map extents and filenames are now cached, so maps will not be loaded from disk
+unless they are on screen. This is a major improvement for map types that did
+not specify this information. Additionally, auto-maps uses this information,
+making it usable even with many maps installed.
+
+Objects controlled by Xastir are now stored in a file, so a restart of Xastir
+will not cause them to be lost. Additionally, Xastir now supports the
+compressed format for objects and items, which can help reduce RF channel
+congestion. It also gives you better location accuracy of the placed objects.
+See the help topic "Configure Default Operation".
+
+Xastir now drops root privileges when not needed if run setuid root. Please
+read the information about this in INSTALL; this change provides only
+limited protection.
+
+Xastir now supports using a private colormap with the command-line argument
+"-i". This is recommended for systems running in 8-bit color mode.
+
+Additionally, several more buffer overruns and other errors were corrected in
+Xastir's data parser, and numerous other bugs have been fixed.
+
+Enjoy the new Xastir!
+
+HELP-INDEX>What's new in Xastir 1.3
+
+ What's new in Xastir 1.3
+
+This latest Xastir release greatly improves on the efficiency and usability of
+Xastir, and adds many helpful and often-requested new features.
+
+.geo files can now have REFRESH tags, to specify how often the file is
+reloaded. This is useful for weather radars and other dynamic images. .geo
+files can also have a TRANSPARENT tag to make a certain color transparent, and
+a CROP tag to specify a specific region to display.
+
+Some Opentrac packets are now decoded and displayed. See
+http://opentrac.org/ for more details.
+
+The default main Xastir directory is now /usr/local/share/xastir; please see
+the upgrade notes in README for migration information. This more closely
+mirrors the behavior of other applications. If you're installing
+from a binary package (rpm/deb/etc), the default install location
+may be /usr/share/xastir.
+
+Xastir efficiency has been greatly improved. Changes in data structures and
+timing values have made this Xastir release the most efficient yet.
+Additionally, map redraw sequences are interruptible, so map panning speed
+has been improved.
+
+dbfawk support - Experimental support for configurable shapefile metadata, in
+an awk-like language. See README.MAPS for more details; this must be turned
+on with a specific switch to the configure command.
+
+GDAL/OGR support - Experimental support for GDAL and loading of native Tiger
+data (.RT1 files). This is automatically enabled if the GDAL library is
+found.
+
+Support for UTM w/special zones and MGRS coordinate systems.
+
+Cad drawing mode allows one to draw regions on your screen using the center
+mouse button. This feature is not yet complete, but is functional.
+
+User interface changes:
+* Several of the menus have been reorganized to have a hierarchical design.
+* Additionally, a few colors have been modified for better visibility.
+* The map label font and style are more configurable
+* The cursor changes to let one know if they're in move object or measure mode.
+* If the coordinate system is set to UTM, and "Map Grid" is selected, an UTM
+ grid is displayed.
+
+Snapshot mode now generates a .geo file, allowing the image to later be used
+as a map.
+
+Tiger maps have been moved back the chooser, as was the pre-1.2 behavior.
+This is more consistent.
+
diff --git a/help/help-English.dat b/help/help-English.dat
new file mode 100644
index 0000000..a858ac6
--- /dev/null
+++ b/help/help-English.dat
@@ -0,0 +1,3099 @@
+HELP-INDEX>READ ME FIRST - License
+
+ READ ME FIRST - License
+
+For the most current information please read the README file in the Xastir
+directory. Also see the LICENSE and COPYING files for additional information.
+
+Remember this program is intended to be used by the HAM community, in the USA
+the FCC restricts you from transmitting over RF if you are not a licensed HAM.
+Users in countries outside the USA should seek their local government
+restrictions.
+
+LICENSE:
+
+XASTIR, Amateur Station Tracking and Information Reporting
+Copyright (C) 1999,2000 Frank Giannandrea
+Copyright (C) 2000-2012 The Xastir Group
+
+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.
+
+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.
+
+More information on the program can be found at:
+
+ http://www.xastir.org
+ http://sourceforge.net/projects/xastir/
+ http://xastir.sourceforge.net
+
+There are some mailing lists available that are Xastir-specific.
+Please subscribe to one or both of them for the latest Xastir
+information. See http://www.xastir.org to subscribe.
+
+For more information on the GNU License look at:
+http://www.gnu.org
+
+
+HELP-INDEX>Welcome! and Notes from the Authors
+
+ Welcome! and Notes from the Authors
+
+XASTIR, or X-windows Amateur Station Tracking and Information Reporting.
+
+Xastir is an APRS(tm) program that is Open Source and free to use and
+pass out to others. Currently this program is in development and should
+not be seen as a finished product! Your help will be needed to make this
+a better program. If you have programming skills and/or can write
+documentation, your help may be needed! We have a lot of ideas but very
+little time, so if you think you can add something to the effort let us
+know!
+
+
+
+APRS(tm) is a Trademark of Bob Bruninga, his home page is at
+"http://web.usna.navy.mil/~bruninga/aprs.html". A great deal of information
+on APRS(tm) can be found in the APRSdos documentation written by
+Bob Bruninga. An additional source of information is the APRS(tm)
+specification, available from http://www.tapr.org .
+
+HELP-INDEX>What's new in Xastir 2.0.1
+(Changes between 1.7 and 2.0.0 were never recorded here,this block
+describes a few of the changes from 1.9.8 to 2.0.0 that occured right
+before release of 2.0.0, but otherwise documents only changes from 2.0.0
+to 2.0.1)
+
+Added tiling for OpenStreetMaps (2.0.0).
+Added "setlocale()" calls to assure we aren't confused by user
+LANG variable settings.
+Improved speed of config file processing.
+Fixes for new One-Wire-Daemon protocol, allowing both old and
+new to work with Xastir.
+Fixed segfaults that could happen when closing list dialogs.
+Fix OSM code to support 16-bit quanta in Graphics/ImageMagick.
+Fixed broken makefile that was ignoring DESTDIR.
+Fixed broken build so internal shapelib builds correctly when
+proj.4 is not installed.
+Add dbfawk files for several generations of new NWS shapefiles.
+Update get-NWSdata to pull current NWS shapefiles.
+Add start/stop files for Kenwood D72 and D710 radios.
+Added a script to convert GeoPDF files to usable GeoTIFF files.
+Make the command to set a TNC into CONVERSE mode a run-time
+configurable option in the TNC Interface Properties dialog.
+Add support for Australian Bureau of Metrology weather alerts.
+Fixes for Davis APRS Data Logger, Davis Meteo and LaCrosse
+support so it gets rain totals correct.
+Allow "posit interval" in File->Configure->Timing to go all the
+way to zero, meaning "never send posits on a schedule."
+Add signal support so that Xastir will emit a posit when it
+receives SIGUSR2. Combined with zero "posit interval," this
+allows Xastir to emit a posit only when told to by an external
+script.
+Fixed error in logic for band-opening alerts (speech and audio
+alarms) so it does not incorrectly report third party traffic
+as a band opening.
+Add "Send Control-E to get GPS data?" to TNC interface
+properties for the "Serial TNC w/ GPS on AUX port" interface
+type. Defaults to enabled, which is correct for KPC-3+ TNCs,
+but should be turned off for any TNC that automatically
+streams GPS NMEA strings, such as Kenwood APRS radios.
+Update GPSMAN support to reflect changes in the gpsman command
+line.
+Add a small delay between sending the converse-mode command
+and sending data for transmission, because KAM TNCs don't
+work if you send the data immediately.
+Fix a bug in the OSM tile download loop that could prevent
+further downloading of tiles if any one tile download fails.
+Fixed a thread-unsafeness bug that could cause Xastir to start
+using corrupted file names when multiple logging options
+(TNC, NET, WX, IGATE, etc.) selected simultaneously.
+Fixed get-fcc-rac.pl script to reflect changes in RAC download
+site.
+
+
+
+
+HELP-INDEX>What's new in Xastir 1.7
+Added REGRESSION_TESTS in order to test interoperability of the
+configure-time flags.
+Added a replacement for malloc() for those cases where the OS
+provides a faulty one.
+Added more to the summary.log file: The tests and results from
+config.log.
+GDAL configure probe now uses gdal-config if it's in the user's
+path.
+Tweaked configure so that dependent libraries cause other library
+searches to fail, and to provide more user output.
+Added ASCII-art drawing to INSTALL showing most of the library
+dependencies.
+Updated symbols.dat to more closely correspond to the current spec.
+Implemented EMERGENCY BEACON transmit capability under the Help
+menu.
+Added decoding for "EMERGENCY" anywhere in the packet plus any of
+these in the TO: field: ALARM, ALERT, WARNING, WXALARM, EM. Any of
+these will invoke the normal emergency popup dialog.
+Waypoint symbols now have a line drawn between them and the station
+transmitting them, per the spec.
+Now using font metrics to determine size of font. We use that to
+determine size of black rectangle to draw underneath.
+Fixed the Fetch Findu Trail function so that it matches what Findu
+can provide.
+Fixed track->shapefile function so that it works on Cygwin too.
+Added reset button to Change Debug Levels dialog.
+Enable WX Alerts menu item is now grey'ed out if Shapelib isn't
+installed.
+RINO Download timing slider is now visible but grey'ed out if gpsman
+isn't installed.
+Added a custom zoom option to the right-click zoom levels menu.
+Moved the center & zoom dialog to the map menu.
+Changed a memcpy() to an xastir_snprintf() function in alert.c to
+assure that a string is terminated.
+Free'ing some malloc'ed space for cases where hash inserts fail.
+Added probe for sighandler_t definition.
+Changed includes, added leak_detector.h.
+A few small changes here and there to get rid of compiler warnings.
+Freeing some malloc'ed space for the cases where hash inserts fail.
+Fixed initializers for awk_rule[].
+Changed hash add functions so that they do a delete first instead of
+replacing hash values.
+Moved some wx-alert related code to debug level 2.
+Changed leak detect interval from 5 minutes to 60 seconds.
+Fixed a big memory leak in draw_nice_string() function.
+Changed include files around so memory leak detection stuff is in
+leak_detection.h.
+Added new compiler flags and cleaned up the code to eliminate many
+warnings created.
+Fixed Incoming Data dialog code so that packets transmitted to local
+interfaces would appear there.
+TNC/NET toggles work for those now too.
+Fixed memory leak in font metrics code.
+Simplfied get_long() and get_int() functions and callouts.
+Tweaks for sighandler_t and sigjmp_buf.
+Added a sign-on message for server connects.
+FCC/RAC lookup or Locate Now buttons don't destroy the dialog
+anymore.
+Fixing up strings.h includes.
+Added a new popup for EMERGENCY packets.
+Changed signal() with SIG_IGN to sigignore for some cases.
+Added a test for sigignore() to configure.ac.
+Changes to allow different versions of "gv" to be used.
+Moved "-lgdal" to end of link line to avoid conflict with other
+libraries.
+Added UDP server and client.
+Added more language strings for previously hard-coded values.
+Changed config file get_int and get_long functions to provide better
+output when config file entries are missing or out-of-range.
+We now allow gating to the internet and to RF for user-defined
+packets and telemetry packets.
+Changing to <CR><LF> for the TCP server signon message.
+Changing to timestamp per packet for log files, with long int
+seconds at the beginning.
+Added icon.
+Added support for -geometry command-line parameter.
+Added fast creation of standard SAR objects via mouse menu,
+including adding digits to the end of the object name if name would
+conflict with pre-existing objects.
+
+
+
+HELP-INDEX>What's new in Xastir 1.6
+Fix for DF lines having incorrect angles at times.
+Configurable display of layers for USGS topo maps.
+Better Map Feature Search: Shows up to 50 matches, user selects
+which one to center map on.
+Configurable "relay" digipeater calls: Up to 50 callsigns can be
+specified in the Xastir config file to use for relay digipeating.
+"WIDE1-1" is now the default.
+Added support for Web Map Service (WMS).
+Tweaked the GPGGA and GPRMC GPS sentence decoding.
+Added speed-ups for lat/long geotiff's.
+Added Aloha circle.
+Added new #defines in interface.h for specifying "conv" or 'k'
+command to TNC.
+Added new tnc-startup file for TAPR-2 style TNC's.
+Added transparency capability to WMS.
+Fixed digpeating code for "wide1-1,wide2-1" case.
+Fixed some compile errors that are seen on FC4 and OSX Tiger.
+Added new terraserver .geo file options.
+Changed Map Properties "fill" option to allow NO/YES/AUTO.
+Auto uses dbfawk if present, no/yes force fill to that state.
+Fixed some #ifdefs here and there so that compiles will work if
+some libraries aren't present.
+Added map caching for nearly all internet maps, plus two new toggles
+on the map menu for clearing out current-view maps or all maps from
+the cache.
+Moved Tigermap timeout slider to main timing dialog, renamed it, and
+made it function for ALL internet map fetches.
+Added timestamps to x_spider log messages.
+A fix for the emacs tempfile bug w.r.t. dbfawk files went in, but
+hasn't been verified to have fixed the problem yet.
+More bulletproofing added to the map_cache code.
+Fixed a compile problem that happens if ImageMagick isn't installed.
+Changed stipple style to solid for polygons drawn with dbfawk.
+Another fix so that linking works without map caching.
+
+
+
+HELP-INDEX>What's new in Xastir 1.5
+Optional Rtree shapefile extent caching
+Optional berkelydb-based internet map caching
+Modifier keys fix
+Improvements to the message GUI
+Tactical call support re-written, hashtable based
+Warnings on crazy paths
+Hashtable weather alert speedups
+Dead-reconing for Objects/items
+Igate of specific stations (in the nws-stations.txt)
+Fixed DF object properties
+Measure function more accurate
+Decoding for "Position with Timestamp no APRS messaging" packets.
+More thorough checking for scanf/sscanf/fscanf function calls
+Fixing 100% humidity for some weather stations, plus added more data for Davis stations
+Changed active internet connection check from 1 min to 5 minutes
+Fixed decoding of compressed DF objects
+Fixes to allow new WHO-IS server to be used from Xastir
+Got rid of extra 0x00 byts between transmitted KISS frames
+Tweak to not start an interface upon changing its properties
+Tweaks to allow use of http proxy servers for online map accesses (.netrc file)
+
+
+
+HELP-INDEX>What's new in Xastir 1.4
+Comment fields for interfaces
+split_gnis and ozi2geo scripts, need to add to section on scripts
+serial mkiss interface
+move objects without confirm
+new timing params w.r.t. trails, need to add to config|timing part
+geo-coder (already in docs)
+exponential/random back-off for almost everything
+dbfawk default, memory leaks fixed
+click+drag zoom boxes
+tactical callsign support
+numerous small memory leaks, uninitialized data uses, and similar bugs fixed.
+GPS quality info
+RINO waypoints downloading
+label trackpoints
+comment/status timestamps
+listener socket/ability to act like a limited internet server
+
+
+HELP-INDEX>Starting Xastir for the first time
+
+ Starting Xastir for the first time
+
+When first running Xastir, you should start it from a terminal window so
+that any warning or error messages can be seen. On most systems a path is
+set up to run programs in /usr/local/bin and all you need to do is type
+"xastir &" at the prompt. On systems that do not have this path installed
+type "/usr/local/bin/xastir &" to start the program. The '&' character
+will cause Xastir to start in the background, leaving the terminal window
+available for other uses.
+
+You may also set the language choice at this time. To set the language or
+change the current language choice, call Xastir with the option '-l':
+
+ xastir -lEnglish
+
+Language options are:
+ xastir -l Dutch
+ xastir -l English
+ xastir -l French
+ xastir -l German
+ xastir -l Italian
+ xastir -l Portuguese
+ xastir -l Spanish
+ xastir -l ElmerFudd
+ xastir -l MuppetsSwedishChef
+ xastir -l OldeEnglish
+ xastir -l PigLatin
+ xastir -l PirateEnglish
+
+The chosen language will be stored in your config file, so it is preserved
+for the next time you call Xastir. For new installs Xastir will default to
+English until you change the language with this command line option.
+
+The menus on the top may be accessed with the mouse or with keyboard
+shortcuts. The keyboard shortcuts may not work correctly with num-lock on.
+
+You will need to configure interfaces in order to actually use Xastir.
+Interface configuration is detailed under the "Configuring Interfaces" help
+topic and its subtopics.
+
+If you are operating in a situation where a coordinate system other than the
+default DD MM.MMMM system would be helpful, you may select your preferred
+system by going to File|Configure|Coordinate system. Any of the supported
+coordinate systems my be used as input by using the Coordinate Calculator.
+
+HELP-INDEX>Configure the Station Information
+
+ Configure the Station Information
+
+Click on File, then Configure, then Station.
+
+Fill in your Amateur Station call sign.
+
+Fill in your station position if you are not using Xastir with a GPS
+unit. You can locate your general position on the map with Xastir and
+use the position given by the cursor placement over the map. This
+position will be viewable in the box at the bottom of the Xastir screen
+2nd from the left, whenever the mouse is over the drawing area. You can also
+choose "Move My Station Here" from the right-click menu while your mouse is
+over your location. If you have a GPS you can skip this and set up the GPS
+later.
+
+"Send Compressed posits", if selected, will transmit in the newer compressed
+format. This format will reduce the amount of data on the air, thereby
+increasing the capacity of the APRS(tm) network. The maximum precision of the
+transmitted position is also higher. Some older programs, including recent
+versions of WinAPRS, do not decode this format yet. Findu.com might also have
+trouble with it. We transmit course/speed in this format but not altitude.
+In order to send course/speed AND altitude requires adding nine characters to
+the packet which negates part of the reason to use compressed posits.
+
+To select a symbol to be used for your station you need to specify
+a group and a symbol character. You can manually fill in these fields,
+or press select to graphically choose a symbol. There are two groups
+of symbols available. A text description of each symbol can be found
+in the "symbol table" help topic.
+
+For some symbols of the secondary group you can specify an overlay.
+With that a symbol will be displayed together with an additional
+overlay character, e.g. a car symbol with the number 1 overlay-ed on
+top of the symbol.
+
+For using overlays you need to select a symbol from the secondary symbol
+table and enter the overlay character to be shown in the group/overlay
+field. Only numbers and uppercase characters are allowed as overlay
+characters. According to the APRS(tm) specification not every symbol can
+be overlay-ed, Xastir doesn't enforce this, but some other programs may.
+Note that not all of the symbols have been implemented in the graphics
+chooser yet, and some of them are not per the APRS(tm) spec yet.
+
+Next, enter the data for the power/height/gain of your station. This
+is useful information but is not required; simply select "Disable PHG"
+to disable it. These choices present a granular representation of your
+stations range. Select the combination of values closest to the
+description of your station. Please use height above average
+terrain (HAAT) for the height value. Do NOT use average height
+above sea level or height above ground. All values must be
+specified if you wish to transmit PHG information.
+
+Another option would be to specify the RNG in the comment field in miles
+instead of using PHG. See the APRS(tm) spec for details.
+
+For Gain use the gain of your antenna in dBi.
+(FIXME: dBd? spec is unclear, I think it's implying dBi because it says "in
+absence of any data, stations are assumed to be running 10w to a 3dB omni at
+20ft. A typical omni is only 3dBi.....)
+
+Note: The gain setting is really intended for vertical antennas; the gain
+setting for a beam should be quite a bit below the forward gain of the beam.
+This is because with directivity set, the PHG circle is only offset by 1/3rd
+of its size toward the specified direction. Setting gain higher will enlarge
+the whole circle unrealistically, rather than increasing the directivity.
+There was talk several years ago about amending the specifications to better
+deal with beam antennas, but nothing was changed.
+
+Enter a comment, not required but it will add insight on your station.
+A common thing to enter here is your preferred e-mail address. It will
+be transmitted along with your posits.
+
+Position ambiguity will allow you control how accurately you transmit your
+position. A setting of none will allow your station to transmit the exact
+position you have entered or received from a GPS. The other choices will
+place you somewhere in the range of the choice you selected. Note that
+this may throw some non-spec compliant stations for a loop. Findu.com
+doesn't understand position ambiguity.
+
+Clicking OK will save your changes, Clicking on Cancel will keep the
+previous settings.
+
+HELP-INDEX>Configure Default Operation
+
+ Configure Default Operation
+
+Click on File, then Configure, then Defaults.
+
+This page sets up some standard defaults for the program operation.
+
+Transmit Station Option sets the type of packet your station will transmit
+its data as.
+
+IGate Options will set your station up as an Internet-RF gateway. This option
+should be used with caution; As a ham you are responsible for the data that
+comes in via the Internet and is transmitted via RF. You also will need to
+choose an IGate option on each interface in order for the IGate to function.
+If you want to have your IGate forward NWS weather alerts to RF, you must
+create a ~/.xastir/data/nws-stations.txt file listing each call or NWS station
+(like "PHISVR") that you would like to transmit via RF. This feature also
+works for gating specific callsigns to RF. Bob Bruninga, WB4APR, recommends
+gating these calls to RF: SCOUTS, SATERN, KIDS, REDCROSS, FOUR-H, YOUTH, GUARD,
+MARS, JOTA. See his link: "Generic Callsigns for National Events" off this web
+page for his current list of recommended callsigns:
+
+ http://www.ew.usna.edu/~bruninga/aprs.html
+
+"Transmit Compressed objects/items?", if selected, will transmit objects and
+items in the newer compressed format. The maximum precision of the transmitted
+position is higher, and the transmission is shorter, but some older programs do
+not decode this format yet. Currently this only compresses "standard"
+objects/items with an optional speed/course. It won't compress area, signpost,
+or DF objects/items, and won't currently represent altitude in "standard"
+objects/items.
+
+"Pop up new Bulletins", if selected, will cause Xastir to bring up the bulletin
+dialog when bulletins within the configured range are received. "View
+zero-distance bulletins" will cause bulletins with no known location not to
+be displayed or cause pop-ups.
+
+"Warn if Modifier keys" will cause Xastir to print a warning if you attempt to
+use Xastir while num-lock, scroll-lock, or caps-lock is engaged. Some users
+report the screen blanking on them and similar problems when they attempt to
+use Xastir with one of these modifier keys on.
+
+You can also select "Activate alternate net?" and choose an altnet call from
+this dialog. Altnet allows you to have a private APRS(tm) network among the
+stations that also have altnet configured, and have the same altnet call
+entered.
+
+"Disable Posit Dupe-Checks" disables the check for duplicate copies of a
+position. This should only be used when a station might return to exactly the
+same position (within 60' or so for non-compressed positions) and you wish to
+see the duplicate positions and/or tracks displayed on the map. This option
+is almost never needed in practice, but can be useful for special events like
+search and rescue operations.
+
+"My Trails in one color" shows all trails with your callsign but different
+ssids in the same color. With My trails in one color selected, mycall-1
+and mycall-2 are shown in the same color. With My trails in one color
+unchecked, mycall-1 and mycall-2 are shown in different colors.
+
+"Load predefined objects from file" and the pick list which follows it allows
+you to replace the list of Predefined objects that are accessible from the
+right click pop-up menu with your own list of objects. A set of standard
+Search and Rescue objects and a set of typical public event objects are
+supplied in the predefined_SAR.sys and predefined_EVENT.sys files. You may
+also use these files as a template to create a predefined_USER.sys file.
+See the instructions in the predefined_SAR.sys and predefined_EVENT.sys file
+for details on how to define objects for a custom predefined objects menu.
+If both "Load predefined objects from file" is selected and a file that
+exists in the xastir/config/ directory is selected, then the objects defined
+in that file will be shown on the Predefined objects menu. The unaltered
+predefined_SAR.sys file defines the same objects as the default menu.
+
+
+HELP-INDEX>Configure Timing
+
+ Configure Timing
+
+Click on File, then Configure, then Timing.
+
+Posit TX Interval specifies how often your station's position will be
+transmitted. For fixed stations a good recommendation is every 30 minutes,
+and definitely no less than 10 minutes. Mobile stations may wish to use a
+faster rate. Note that if you're using SmartBeaconing, this slider is
+ignored.
+
+Object/Item Max TX Interval is the maximum interval used for sending out
+objects and items. Try to keep these intervals reasonable, as transmitting
+to a long path every 5 minutes will really take up a lot of the air time.
+A decaying interval algorithm is triggered any time an object is created,
+modified, or killed. The transmit interval will increase until it hits the
+max interval indicated by the slider.
+
+GPS Check Interval will set the interval of time to look at the GPS for new
+data. This is available for stations using an HSP or shared cable with their
+TNC.
+
+Dead-Reckoning Timeout adjusts how long a position is assumed valid for the
+purpose of estimating its current position.
+
+New Track Time adjusts how many minutes must elapse before a new
+separate track is started. Caution: setting the new track time to 0 will turn
+off the display of all tracks.
+
+RINO -> Objects Interval adjusts how often waypoints are downloaded from an
+attached Garmin RINO radio/GPS unit. APRS(tm) Objects are created out of any
+waypoints beginning with "APRS". The "APRS" prefix is removed when creating
+the Object names.
+
+Station Ghosting Time specifies the ghosting interval. Stations that have not
+been heard in the given period will appear ghosted on screen.
+
+Station Clear Time specifies when a station will be removed from the screen.
+
+Station Delete Time specifies the number of full days before data from a
+station will be entirely removed from the Xastir database.
+
+Serial Inter-Char Delay specifies a wait time in milliseconds between each
+character sent to an attached TNC.
+
+New Track Interval (degrees) specifies distance in lat/long degrees at which
+a new track segment is started. Caution: setting new track interval to 0
+degreees will turn off the display of all tracks.
+
+Snapshot Interval (minutes) specifies how often snapshot files will be
+written if either File->PNG Snapshots or File->KML Snapshots are selected.
+
+HELP-INDEX>Configure Audio Alarms
+
+ Configure Audio Alarms
+
+Click on File, then Configure, then Audio Alarms.
+
+To use this option you must have a sound card and a program that will play
+wav files. The Audio Play Command should contain the program you want to
+execute to play the audio file (and any command line options). That of
+course doesn't work if the only sound card in the system is used for a
+soundmodem...
+
+Each type of alert has a check-box to enable it. The fields will contain the
+name of the file to play. Fields under the option will set parameters for the
+option.
+
+The current choices are:
+Play message on hearing a new station.
+Play message on receiving a new message.
+Play message on receiving data from a station within the min/max distance of
+ your proximity settings.
+Play message on receiving data from a station (via TNC) within the min/max
+ distance of your band opening settings.
+Play message on receiving and displaying a new weather alert.
+
+There is a standard set of sounds available most places where Xastir can be
+obtained, please see the file INSTALL for more information.
+
+HELP-INDEX>Configure Speech
+
+ Configure Speech Synthesis
+
+To use this option you must have a sound card and the 'festival' speech
+synthesis software installed. Install Festival and start it in 'server'
+mode prior to starting up XASTIR. The normal command for this is
+"festival_server &". If you use the "festival --server" option instead (old
+method), you may run into problems with connections getting rejected by the
+server.
+
+Once you have festival installed, Xastir will have the ability to speak using
+the following choices:
+
+New Station - Announce the call of a new station.
+New Message Alert - Announce the arrival of a new message.
+New Message Body - Speak the contents of a message.
+Proximity Alert - Announce when receiving data from a station within the
+ min.max distance of your proximity settings. This option uses the
+ proximity settings found in the Audio Alarms menu.
+Tracked station Proximity Alert - Announce when receiving data from a
+ station within the min.max distance of the tracked station. This option
+ uses the proximity settings found in the Audio Alarms menu.
+Band Opening - Announce when receiving data from a station (via TNC)
+ within the min/max distance of your band opening settings. This option
+ uses the distance settings found in the Audio Alarms menu.
+New Weather Alert - Not implemented yet.
+
+Info on Festival may be obtained from: http://www.speech.cs.cmu.edu/festival/
+
+HELP-INDEX>Configure Smart Beaconing
+
+Click File, then Configure, then Smart Beaconing.
+
+The main "Enable SmartBeaconing(tm)" Will cause Xastir to transmit positions at
+various rates and locations based on the movement of the station. It creates
+more realistic trails and makes dead-reckoning much more accurate. This option
+is only useful in a mobile station with a GPS attached.
+
+There are several options available to customize the operation of
+SmartBeaconing:
+
+High rate
+The interval (in seconds) at which beacons are sent when the speed is above the
+High speed setting. This parameter is also used to compute a beacon rate based
+on speed when traveling between the high and low speeds.
+
+High speed
+The speed threshold that will cause beacons at the rate specified above.
+
+Low rate
+The interval (in minutes) at which beacons are sent when the speed is below the
+Low speed setting. Basically consider this to be the stopped beacon rate.
+This parameter is not used at all when traveling at a rate of speed higher than
+"Low speed".
+
+Low speed
+The speed threshold that will cause beacons at the rate specified above.
+
+Minimum Turn
+The minimum degrees that corner pegging can occur at "High speed" or above.
+Lower speeds will require more degrees of turn to trigger a posit, based on
+the value of "Turn Slope" below.
+
+Turn Slope
+Fudge factor for making turns less sensitive at lower speeds. The parameter
+doesn't have any units. It ends up being non-linear over the speed range the
+way the original SmartBeaconing(tm) algorithm works.
+
+Wait Time
+The time in seconds between corner-pegging beacons, prevents multiple
+beacons in short succession.
+
+HELP-INDEX>Configure Units of Measure
+
+ Configure Units of Measure
+
+The default selection is for the Metric System: mm, cm, km/h, etc. To select
+English units, inches, feet, MPH, etc. Click on File, then Configure, then
+toggle the "Enable English Units" check-box.
+
+HELP-INDEX>Save Config Now!
+
+ Save Config Now!
+
+This button will save all of the current configuration to the config file.
+Note that when Xastir is closed, it also saves configuration to the config
+file.
+
+HELP-INDEX>Bottom Status Bar
+
+ Bottom Status Bar
+
+At the bottom of the window various status messages are available:
+
+In the first box on the left general status messages are displayed for a
+short time.
+
+The second box displays the current lat/long or UTM, and Maidenhead grid
+square position of the mouse over the map. If file|configure|Dist/Bearing
+Status is selected, this box will also contain the course and bearing of
+this position relative to your station.
+
+A third box is used to display how many stations are on screen, and how many
+are in the database.
+
+The fourth box will display the current zoom level and will display "Tr" if
+the station tracking is on. At some zoom levels the Tr is not
+displayed properly due to the size of the box.
+
+The fifth box indicates whether logging is enabled.
+
+The last area will display the device status for each interface. Each will
+display in order first to last or 0 to 9. The interface status is separated
+into three areas, top device type, center data flow, and bottom interface
+operational status.
+
+The device type will show what interfaces are configured. The color will
+show what type of device the interface is configured for. Blues are for
+the various TNC devices; Greens will show the GPS devices; Yellow for
+Internet Servers; Orange for WX interfaces.
+
+The center will show data flow in (arrow pointing left) or data flow out
+(arrow pointing right) for that interface.
+
+A green box at the bottom will show if that interface is active. A red
+box will show if the interface is active but in an error condition.
+Otherwise nothing will show if the interface is not active.
+
+HELP-INDEX>Moving the Map and the Options Menu
+
+ Moving the Map and the Options Menu
+
+Map movement is very simple, ease and quickness of movement is dependent on
+your processor speed and the amount of detail you load. Hint: You can
+disable all maps in the maps menu in order to move around quickly, then
+enable maps again.
+
+Zooming:
+Zooming can be accomplished by right clicking on the map (and holding the
+button down). This will bring up an options menu, with choices to zoom in or
+out a single level, or to change to one of the preset zoom levels.
+
+All zooming functions from the options menu will zoom in or out at the point
+on the map where you clicked the right mouse button. Zoom levels have a cascade
+menu. Levels 1-64 are for very local areas and levels 256 and above are for
+large areas. The lower number the level, the more local the area.
+
+A quicker zoom in function is to push and hold the left mouse button, drag it
+across the area of interest and let go. The map will zoom to approximately
+the size of the square you just described with the mouse drag operation. The
+"move" and "measure" toolbar check-boxes must be disabled for this feature to
+work. Clicking the middle button zooms out with a factor of 2, centering
+where you clicked as well.
+
+The map can also be zoomed with the keyboard Page-Up/Page-Down keys, or the "In"
+and "Out" buttons in the toolbar. The zooming in this case keeps the same map
+center (no centering).
+
+Panning/Centering:
+The map can be centered at a specific location by choosing center in the
+right-click options menu.
+
+Panning is also accomplished by using the options menu, or by using the arrow
+buttons on the toolbar. The map position will shift a portion of a screen.
+Enough data from the previous screen should be available to re-orient yourself.
+
+The map can also be panned with the keyboard arrow keys.
+
+More About Options Menu:
+
+Map Display Bookmarks
+See the help topic "Creating and using Map Display Bookmarks"
+
+The "Station Info" selection on the options menu will look for the station
+closest to where you right-clicked the mouse. If more than one station is
+close to that position a "Station chooser" list will appear, then you can
+choose what station's data you want to look at. If only one station is close
+to the mouse pointer then that station's data will display immediately. For
+mobile stations with a lot of track data this could need some time on slow
+computers. Note that expired stations still have their data stored in the
+Xastir database, and if one knows a station's former location, one can still
+view its info in this manner. Use the "Display Expired Data" option
+to display some data that disappears for ghosted stations, like
+speed/altitude, etc.
+
+With "Last Pos/Zoom" you can restore the previous map view by restoring the
+previous values of the map zoom and centering values.
+
+For Object and Item information, please see the help topic "Objects and Items"
+
+Draw CAD objects lets you create polygons on screen, for tactical or
+presentation use. This feature is still under construction.
+
+"Move my Station here" Allows you to move your station to a specified map
+location without editing the station configuration.
+
+HELP-INDEX>Objects and Items
+
+A station could place several different objects on the map, with their
+position transmitted to other stations. The object names are less restrictive
+than the normal station names.
+
+Objects and items are nearly the same things, but their use could differ a bit.
+Objects are generally used for moving or variable things such as thunderstorms,
+while items are generally used for more inanimate things, such as water
+stations. Because items may not be decoded by some flavors of APRS(tm)
+programs, objects are often used for inanimate things, too.
+
+Besides normal objects with a symbol at its position there are some special
+objects available. Area objects are useful for a variety of operations in
+which you want to draw or highlight an area of interest on the map. They can
+also be used to draw trails/roads/boundaries, watch boxes for severe weather,
+runways, perimeter of a search area or of a public service event, areas of
+damage, areas to stay out of, buildings that aren't on the map, checker/chess
+boards for gaming on APRS(tm). :-) Note that area objects are not
+implemented on all versions of APRS(tm) programs, and some of the details of
+how they are displayed may also be different on other programs.
+For the other three, probability circles, signposts and DF objects, see below.
+
+Objects/Items are retransmitted at a decaying rate up to the max interval
+specified in File|Configure|Timings. "killed" objects/items are also
+retransmitted in this manner until they expire from the queue (currently 20
+transmits). Objects/Items are persistent across Xastir sessions, and are
+stored in ~/.xastir/config/object.log. This file may be cleared by selecting
+"Clear Object/Item history" from the Stations menu.
+
+The Object/Item creation option in the right click menu will bring up a dialog
+with the position of your object filled in based on where you clicked the
+mouse. You may fill in the details, and add an object/item from this menu.
+
+The Object/Item modification option brings you the object modification dialog.
+It is similar to the object creation dialog, except the object's current
+information is already filled out, and the object's name and a few of the
+other options can't be changed. You could also delete the object with this
+option.
+
+Objects and items can be moved with the mouse if the "Move" check-box on the
+toolbar is enabled.
+
+The Predefined Objects option in the right click menu allows you to rapidly
+place standard Search and Rescue objects without having to go through the
+Object/Item creation dialog. These objects include standard Incident
+Command System symbols for ICP, Staging, Base, and Helibase, as well as
+SAR objects for PLS, IPP (with 4 area circles), and LKP If an object of the
+same name as an object you select off the list allready exists, a new
+object will be created with a number appended to the end. For example,
+the first time you select Staging from the Predefined objects menu, an
+object named Staging will be created. If you then create an additional
+Staging object from the Predefined objects menu, it will be named Staging2.
+Heli- (and user defined objects ending in a "-") will be created as Heli-1,
+Heli-2, Heli-3, etc. If you have recieved one of these standard objects that
+was transmitted by another station, your first object will be named with an
+appended number. You may wish to assign a tactical call to your object in
+this situation (for example, replacing ICP2 with a tactical call).
+
+The Predefined Objects menu is customizable by modifying the files
+predefined_SAR.sys, predefined_EVENT.sys, and predefined_USER.sys, and then
+selecting one these files through the File/Configuration/Defaults dialog.
+See the predefined_SAR.sys file for details.
+
+Description of the entries in the object dialogue:
+
+= Signpost =
+This makes the object a signpost object. These signs can contain one
+to three characters, and currently appear in Xastir as a blank sign.
+Station Info shows the value contained on the sign.
+
+= Area Object =
+This makes the object an area object, and enables the area object controls
+described below.
+
+= DF Object =
+This is a direction-finding report. Enabling it allows you to choose Omni or
+Beam report, and allows you to put in the specifics for each. See:
+ http://web.usna.navy.mil/~bruninga/dfing.html
+and the APRSdos documentation for details on these useful techniques.
+(FIXME: Separate section on DF'ing techniques?)
+
+= Probability Circles =
+This allows you to define the radius (in miles) of two circles centered on
+the object or item. Min is the radius (in miles) of the smaller, inner
+circle, and Max is the radius (in miles) of the larger, outer circle.
+These circles are drawn in red. They can be used to assist in planning
+Search and Rescue operations. To create more than two circles, add additional
+probability circle objects to the same location. Probability circles may not
+be displayed by other client software.
+
+= Name =
+This is the name of the object or item. It may be up to 9 characters long,
+with spaces allowed inside the name. When modifying an object, this may not
+be changed. To rename an object you must delete the original and then create
+a new object. Note that if you select Signpost/Area Object/DF Object that
+this field and perhaps others are cleared. Enter the name AFTER you've
+selected the type of object it will become.
+
+= Station Symbol =
+You may select a symbol for the object. Press select to choose graphically,
+or see the symbol table help section for descriptions of each symbol. Note
+also that area objects, signpost objects, and DF objects have special fixed
+symbols and therefore can't be selected here. Those particular symbols get
+automatically assigned when you change to that type of object.
+
+= Location =
+The location of the object is specified here. If you selected "Create
+Object/Item" from the right-click menu, the location you clicked will be filled
+in. If you moved an object with the mouse, the new location will be in these
+fields. You can also type in a location, for instance you may be placing an
+object from an over-the-air voice report.
+
+= Generic Options =
+You may specify the speed, direction, and altitude of objects here. Some object
+types cannot have a speed or direction, in which case the fields are grayed
+out.
+
+= Signpost Text =
+If the object is a signpost object, you may specify the 1 to 3 digit
+number that appears on the sign here. Note that Xastir doesn't display
+signpost objects properly yet.
+
+= Area Object =
+Area Objects are used to highlight specific parts of maps, or to draw extra
+detail onto maps. This will be done with the following entries:
+ = Bright Color =
+ Use the brighter version of the colors allowed.
+ = Color-Fill =
+ The area should be filled, not just outlined. This may be useful to
+ exclude an area from a search or other event.
+ = Object Type =
+ Choose from the geometric shapes allowed.
+ = Object Color =
+ Choose the color in which the object will display. This is also affected
+ by the "Bright Color" option above.
+ = Object Offset Up =
+ In hundredth of a degree latitude. An unfortunate detail of the spec,
+ and hard to calculate easily. Suffice it to say that you can change
+ the size of the object once you place it.
+ = Object Offset Left except / =
+ In hundredth of a degree longitude. See above.
+ = Object corridor =
+ This is the width of a line area object. Useful for runways, weather
+ watch boxes, describing an area of interest or an area of exclusion, etc.
+
+Always delete your objects and items when you are done with them!
+Don't just allow them to expire from your cache, as they may hang
+around on other peoples' screens for an extended period.
+
+
+Description of weather watch boxes:
+
+Watch boxes and "areas of maximum concern" (AOMC) generated by the WXSVR
+(http://wxsvr.net/) are colored as follows:
+
+ Yellow dashed = Severe Thunderstorm Watch (looks like crime scene tape)
+ Yellow solid = AOMC for Severe Thunderstorm Warning
+ Red dashed = Tornado Watch
+ Red solid = AOMC for Tornado Warning.
+ Green dashed = Mesoscale (larger) discussion area
+ Blue dashed = Test Watch
+ Blue solid = Test Warning
+
+HELP-INDEX>CAD Objects
+
+ CAD Objects
+
+[CAD object support has moved from the right click menu to
+Map/Draw CAD Objects].
+
+CAD object support is preliminary at this time. Features and the user
+interface are subject to change.
+
+CAD objects are arbitrary shapes that you can draw on maps in xastir, but
+can't transmit by APRS.
+
+Currently supported CAD objects are:
+Polygons: Closed areas of at least three points.
+
+To create a CAD object, first press the Draw radio button on the toolbar.
+This will change the cursor to a pencil. Begin drawing a polygon by
+clicking with the middle mouse button (or both buttons on a two button mouse,
+for which you will need to have three button mouse emulation enabled). This
+places a point on the map. Now move the cursor somewhere else (the normal
+left click/right click navigation and zoom functions still work normaly) and
+click the middle mouse button again. This draws a line between the two points
+you have selected. Middle click again to draw another line segment and keep
+repeating until you have drawn all except for the closing line segment of your
+polygon. To close the polygon, select Map/Draw
+CAD Objects/Close Polygon. This will close your polygon and bring up a dialog
+that will allow you to enter a name, comment, and probability for the polygon.
+
+When you have finished drawing CAD objects, exit the CAD drawing mode by
+deselecting the Draw radio button on the toolbar.
+
+CAD objects can be edited from the View/CAD Polygons menu and from the
+Map/Draw CAD Objects/CAD Polygons menu. CAD objects can be deleted from the
+Map/Draw CAD Objects/Erase CAD Polygons menu.
+
+HELP-INDEX>View Menu
+
+ View Menu Options
+
+The View menu presents various ways to look at data in Xastir.
+
+Bulletins
+This is the APRS(tm) bulletin board, where important announcements are posted.
+If you are connected with the internet interface, it is a good idea to set the
+range field to a few hundred miles, to ignore posts from other portions of the
+world. "0" in the range field means the entire world. Click the "Change range"
+button to make changes to this field effective. Xastir currently does not
+support sending bulletins. Incoming bulletins will open this dialog
+automatically if you select "pop up new bulletins" in the Configure|Defaults
+dialog. The "View zero-distance bulletins" button enables viewing bulletins
+for which you don't have a range yet (they haven't sent a posit yet, but you
+received a bulletin from them). If this is unchecked, you must get a position
+from a station, and the station must be within the range selected (or range
+must be set to zero), in order for the bulletin to be viewed.
+
+Incoming packet data
+This displays the incoming data on your TNC or internet interface. The radio
+buttons below select if you want to see only TNC data, only internet data, or
+both.
+
+Mobile Stations
+This is a list of stations that are moving. Stations qualify for this list if
+they have moved (more than one position received for them), the symbol of the
+station is not considered. Information shown includes course, speed, altitude,
+position, number of packets received, number of visible GPS satellites, course
+from your station, and distance from your station.
+
+All Stations
+This option displays a table of all stations sorted alphabetically. It includes
+the number of packets heard, the time the station was last heard, the path that
+the most recent packet took, the PHG, and the comment of the station.
+
+Local stations
+This option displays only stations that are heard via your TNC. It includes
+the number of packets heard, the time the station was last heard, the path that
+the most recent packet took, the PHG, and the comment of the station.
+
+Last Stations
+This option displays a table of all stations sorted from most recently heard
+to least recently heard. It includes the number of packets heard, the time
+the station was last heard, the path that the most recent packet took, the PHG,
+and the comment of the station.
+
+Objects & Items
+This option displays only objects and items. It includes the number of packets
+heard, the time the objects/item was last heard, the path that the most recent
+packet took, the PHG, and the comment of the object/item.
+
+Own Objects & Items
+This option displays only objects and items that you control (i.e.: Have sent
+the most recent update for). It includes the number of packets heard, the time
+the objects/item was last heard, the path that the most recent packet took, the
+PHG, and the comment of the object/item. A ghosted icon indicates that the
+object has been deleted.
+
+Weather Stations
+This option displays a table of all the APRS(tm) weather stations and their
+data. Data includes wind course, wind speed, wind gust speed, temperature,
+humidity, barometric pressure, rain in the past hour, rain since midnight,
+and rain in the last 24 hours.
+
+Own weather data
+Displays your weather data if you have a weather station and have configured
+Xastir to access it.
+
+Weather Alerts
+Displays weather alerts received, including the alert flags, alert source/type,
+alert destination, expiration, message, and effected location. This data
+is used for the alert highlighting. Double-clicking on an alert will request
+further information about it via finger from the online WXSVR. This only
+works if you have internet access; future versions may access this data over
+radio as well.
+
+Message Traffic
+Shows all message traffic while the window is open. It includes the source,
+destination, interface, and message. The range option can limit this display
+to nearby stations, much like the range control on bulletins. A range of 0
+causes all messages to be displayed.
+
+GPS Status
+Shows the status of your GPS unit, including the type of fix and number of
+satellites acquired.
+
+Uptime
+Shows the amount of time elapsed since Xastir was started.
+
+HELP-INDEX>Map Menu and the Map Chooser
+
+ Map Menu and the Map Chooser
+
+Map Menu:
+
+Map Chooser
+This will present you with a list of map directories and/or files in your
+map directory. Checking the "Expand Dirs" option toggles the expansion of
+directories into individual map files. The properties dialog allows more
+advanced controls, and is described below. Click on map names to highlight
+them, this will cause them to be displayed when you click the OK button. You
+may select any number of maps. Clicking "Clear" will select no maps,
+clicking "Vector" will select only vector maps. The three "topo" options will
+automatically select all GeoTIFF images of the listed size. Clicking the OK
+button will display the selected maps. Cancel will abandon any changes.
+
+ Map Chooser Properties
+ Clicking the Properties button will bring up a dialog where you can specify
+ the layer in which maps appear, and in which zoom levels they appear. Higher
+ layer numbers are displayed on top of lower numbers. The range may be
+ specified from -99999 to 99999; it is suggested that you space your layering
+ numbers widely to allow later insertion of additional map layers. From this
+ dialog you may specify whether a vector map is drawn with color fills. This
+ is a per-map setting; the global disable option on the Maps menu can override
+ this. The Filled setting is ignored for raster maps (images). A setting of
+ "auto" allows a dbfawk file to control this parameter directly (usable only
+ if dbfawk is compiled in and the map in question is a Shapefile). You can
+ also select whether a map is considered by the "Auto maps" feature here.
+ Finally, you can specify the minimum and maximum zoom levels at which a map
+ is displayed. This is useful to prevent very detailed local maps from loading
+ at very wide zoom positions, and visa-versa. A minimum zoom of 10 means a map
+ will be displayed at all zooms including and above 10. Likewise, a maximum
+ zoom of 256 means a map will be displayed at all zooms below and including
+ 256.
+
+Map Display Bookmarks
+See the help topic "Creating and using Map Display Bookmarks"
+
+Locate Map Feature
+This option brings up a search dialog where you can search through the labels
+in a GNIS file to find a specific location. It will center the map on the
+new location if it is found. The "GNIS File:" entry is saved between calls
+and between invocations of Xastir. You must put GNIS files into the
+xastir/GNIS directory in order to use this feature.
+
+Find Address
+This option brings up a search dialog where you can enter an address. It will
+center on the map if the address is found. The path to the geo-coder file is
+saved between calls.
+
+Coordinate Calc
+This option opens a simple calculator that can convert between coordinate
+systems. This is useful for converting positions to the various formats used
+by different groups of people. This same calculator can be called up by the
+Calc button on some of the other dialogs. It's useful for entering coordinates
+in other formats.
+
+Configure menu:
+ Background color
+ This option controls the color of the background behind the maps you have
+ displayed. The background color is often entirely hidden by filled maps
+ (see below).
+
+ Map Intensity
+ This controls the brightness of any graphics used as maps. This option only
+ appears if you have compiled with GeoTIFF support.
+
+ Adjust Gamma Correction
+ This allows you to apply gamma connection to all loaded map graphics. Maps
+ can be adjusted individually in their .geo files, see the section on .geos in
+ "Map files and WX Counties". This option only appears if you've compiled with
+ ImageMagick support, and does not apply to geoTIFF maps; see the above
+ option.
+
+ Map labels font
+ This allows you to set the font style and size used for map labels.
+
+ Station Text Style
+ Controls which font and style to use for station text and others.
+
+ Icon Outline Style
+ This allows you to specify an outline that surrounds station icons. This
+ helps improve visibility on various backgrounds.
+
+ Configure Tigermap
+ Turning this option on causes Xastir to download the map from the US census
+ bureau's online tiger mapping server. The dialog that comes up allows one to
+ select which layers are displayed, as well as the brightness of the resulting
+ map. This is only available if you have compiled with ImageMagick support.
+ Tigermaps are always loaded as the bottom layer; they do not have layering
+ settings in the Map Chooser.
+
+Disable All Maps
+This option disables the loading of any maps. It is most useful when doing
+rapid zooming or panning, because it saves the need to load the maps on each
+redraw. Note that this option is not saved between sessions.
+
+Enable Auto Maps
+When enabled, any map found in the map directory (or any directory under it)
+will be displayed if it falls within the current display region. You can add
+any number of directory levels under the main map directory for your maps. Auto
+maps will go through any that have Auto Maps enabled (in the Map Chooser
+Properties dialog) check them all and find what map (or part) should be
+displayed. All Maps will be merged into the viewing area. If you have a large
+quantity of maps, very detailed maps or a slower computer this can be quite
+slow. When this option is off, maps selected with the Map Chooser and/or Tiger
+Maps dialog will be displayed.
+
+Auto Maps - disable Raster maps
+This option prevents Auto Maps from loading maps which are graphics (images).
+Only vector maps will be displayed in this case.
+
+Enable Map Grid
+When enabled, this option will display a grid on the map. If the coordinate
+system is UTM a UTM grid will be displayed. If the coordinate system is
+latitude/longitude then a latitude and longitude grid will be displayed. As you
+zoom in the grid switches to a finer resolution. The spacing of the latitude
+and longitude grid may be manually adjusted with the "+" and "-" keys.
+
+Enable Map Border
+When both Enable Map Grid and Enable Map Border are enabled, a narrow white
+border is drawn around the map and the grid lines are labeled using the
+selected coordinate system (File/Configure/Coordinate System), and the selected
+border font (Map/Configure/Map Labels font/Border Font). If the UTM or MGRS
+coordinate systems are selected, the grid lines will be labeled with easting
+and northing values only at zoom levels smaller than about 2048.
+
+Enable Map Levels
+When enabled, this option will try to filter out data when the zoom level
+shows large areas. This does not work will all maps but will work with the
+maps generated from Tiger Line maps at the aprs.rutgers.edu site, and with
+ESRI Shapefile maps. This does not decrease the loading times of the maps very
+much, rather it simply reduces screen clutter.
+
+Enable Map Labels
+This option toggles the display of map labels embedded in DosAPRS, WinAPRS,
+GNIS, and ESRI Shapefile format maps.
+
+Enable Area Color Fills
+This option controls the filling of vector maps. In certain cases, you
+may want to eliminate the fill to see maps below the top maps. This is a global
+control, maps may individually have color fill toggled in the properties dialog
+of the Map Chooser.
+
+Enable Weather Alert Counties
+This toggles the display of county warning area maps for severe weather.
+These maps can be obtained and installed according to the directions in the
+README.MAPS file. They are displayed on screen when special weather alert
+messages are received, and expire after a time or can be remotely canceled.
+The weather alert text can be seen under View|Weather Alerts. The
+xastir/Counties directory must be populated with the correct files from NOAA
+and Shapelib support must be compiled into Xastir in order to enable this
+functionality.
+
+Index New Maps on Startup
+This option controls if the map index file is built on startup. Most users
+should leave this enabled. If the timestamp of the map file is newer than
+the map index file, the map will be indexed.
+
+Index: Add New Maps
+This option adds any new maps to the max index. Same rules as the above
+Index New Maps feature, but a manual method of invoking it.
+
+Index: Reindex ALL Maps
+This option starts over from scratch, indexing every map it recognizes in the
+maps directory. This is useful if the Add New Maps function is skipping some
+maps, perhaps because of old timestamps on the map files. This function may
+take quite a while to complete if you have a lot of maps.
+
+Mouse pointer menu
+This option brings up the options menu normally available by right clicking.
+
+One note on maps: Many of the currently available vector maps for the
+U.S. were created in NAD 1927 datum, while Xastir and other APRS(tm) programs
+use WGS 1984 datum. If zoomed in to a small area on the map the datum
+shift may be very noticeable. The USGS topographic maps have their datum
+corrected by Xastir as they are displayed, so positions will generally
+be more accurate with those topographic maps.
+
+HELP-INDEX>Map files and WX Counties
+
+ Map files and WX Counties
+
+Map Types
+Xastir will work with various types of map files. All DosAPRS, Windows/Mac
+APRS(tm) map files are supported, as well as PocketAPRS format maps and GNIS
+(Geographic Names Information System) label files. Xastir also can be
+compiled to use external libraries to support XPixmap (XPM) images, GeoTIFF
+topographic maps, and ESRI Shapefile maps. The graphics handling capability
+of Xastir can be greatly extended by compiling with ImageMagick support,
+enabling support for many graphic formats as maps (see
+"http://www.imagemagick.org/www/formats.html"). Xastir supports weather
+alert maps in ESRI Shapefile format, available from NOAA.
+
+Details of locations to obtain many of the above types of maps are found in
+the file README.MAPS
+
+Map Locations
+Any map file should be stored in the /usr/local/share/xastir/maps directory
+on your computer. This location may be different on some systems, depending on
+how Xastir was compiled/installed. You can create any number of directories
+under this directory to help organize and separate your data. The maps will be
+loaded in alphanumerical order unless layering is specified.
+
+Hints on installing and organizing maps are found in README.MAPS.
+Maps in a pixel graphics format actually need a combination of two files,
+a data file with a graphic pixmap (.xpm) (or other format if you compiled
+with ImageMagick), and a calibration file (.geo). The .xpm file is the
+standard graphic format, available without additional libraries. If you
+want to save storage space you can use gzip to compress those files
+("gzip map.xpm" will result in "map.xpm.gz"). Xastir detects this
+automatically during map loading. You can use XView/Gimp/ImageMagick and
+other programs to convert gif, jpg, and tif images into this format if
+you don't have support for many image types compiled in (ImageMagick). If
+you have problems with maps in xpm format, try to load and save the
+graphics with Gimp first, to convert all unknown color names into the
+binary representation.
+
+The .geo file is a text data file that will tie the image to a location
+in the world. Here is an example of a .geo file that will cover the entire
+world with the map world1.xpm:
+
+FILENAME world1.xpm
+# x y lon lat
+TIEPOINT 0 0 -180 90
+TIEPOINT 639 319 180 -90
+IMAGESIZE 640 320
+
+.geo files can have many elements:
+
+FILENAME <filename>
+This specifies the filename of a map image to be loaded from the local disk.
+
+URL <http://website>
+This specifies the URL of a map image to be loaded from a web or ftp site.
+ImageMagick only.
+
+TIEPOINT <x-pixel> <y-pixel> <longitude> <latitude>
+Two tie-points are required, and more than 2 will be ignored.
+these two lines are for connecting an x,y pixel position in the image
+to a lat and long position on the earth. The points should be as close as
+possible to the upper left corner and the lower right corner of the image for
+best accuracy. The latitude/longitude are specified in decimal degrees.
+
+IMAGESIZE <pixels horizontally> <pixels vertically>
+This specifies the size of the image in pixels. If this is not set, the image
+will be loaded each map redraw, regardless if it is on screen or not.
+IMAGESIZE is a REQUIRED OPTION if a URL is specified. For local files, it's
+an optional parameter (we use ImageMagick to query the image size for local
+files).
+
+DATUM <datum>
+This feature is not implemented.
+
+PROJECTION <projection>
+This feature is only partially implemented, default is "LatLon", other
+possibility is "TM" to specify that the map is in Transverse Mercator
+projection.
+
+# <anything>
+Any line with the first character of a '#' will be ignored.
+
+ImageMagick specific image enhancements:
+
+GAMMA
+eg: GAMMA 1.2 or GAMMA 1.2,2.0,1.2
+The first will change overall gamma for this image, the second will
+lighten green more than red or blue.
+
+CONTRAST
+eg: CONTRAST 0 or CONTRAST 1
+Doesn't seem to do that much, other values make no difference.
+
+NEGATE
+eg: NEGATE 0 or NEGATE 1
+0 will negate all colors, 1 just grayscale colors.
+
+EQUALIZE
+No argument.
+
+NORMALIZE
+No argument.
+
+LEVEL <black_point, mid_point, white_point>
+eg: LEVEL 0,1,65535
+These values seem to be the defaults.
+
+MODULATE <brightness, saturation, hue>
+eg: MODULATE 90,150,100
+These are percents, 100,100,100 is the default.
+
+REFRESH <seconds>
+eg: REFRESH 900
+This tag is used for dynamic URLs such as weather radar, where you
+wish Xastir to auto-redraw the map at a specified interval. By
+adding this tag to weather radar .geos, you can watch the weather
+move across your screen. Xastir contains only one interval counter,
+so the smallest REFRESH interval loaded takes effect for all selected
+maps.
+
+TRANSPARENT
+Color to remove from the background (make it transparent). Use a
+number, 0=black. Color-mapped images use the map value, so white is
+usually 0xffffffff (32-bits of 1s). Values must be in hexadecimal,
+and are preceeded by "0x". The value can be obtained by using debug
+level 16. The first of the four numbers after "Color allocated is"
+is the colormap index.
+
+CROP <left top right bottom>
+Removes borders (makes them transparent). Values are in pixels with
+(0,0) at the upper left. A good value for the 620x620 NWS radar
+images is "CROP 35 20 616 600"
+
+Special/nonstandard .geo files:
+
+TIGERMAP
+A file with just the word "TIGERMAP" will cause Xastir to retrieve an
+online Tiger map of the area on screen. These are not available for every
+place in the world. "tigermap.geo" is automatically installed in the maps
+directory.
+
+TERRASERVER-SATELLITE
+A file with just the word "TERRASERVER-SATELLITE" will cause Xastir to
+retrieve a Terraserver satellite photo of the area on screen. Those
+services are not available for every place in the world. Note that using
+the Terraserver maps at any zoom above 256 will probably take a long time
+to load, won't show much detail, and probably won't display correctly. This
+is a limit of Microsoft's Terraserver, not Xastir. Also note that
+crossing UTM zone boundaries is not supported by Terraserver.
+"terraserver.geo" is automatically installed in the maps directory.
+
+TERRASERVER-TOPO
+A file with just the word "TERRASERVER-TOPO" will cause Xastir to retrieve a
+topographic map of the area on screen. Those services are not available for
+every place in the world. Note that using the maps at any zoom above 256
+will probably take a long time to load, won't show much detail, and
+probably won't display correctly. This is a limit of Microsoft's
+Terraserver, not Xastir. Also note that crossing UTM zone boundaries is not
+supported by Terraserver. "terraserver-topo.geo" is automatically
+installed in the maps directory.
+
+TERRASERVER-URBAN
+Same as above but with Terraserver colored urban-area satellite
+images. "terraserver-urban.geo" is automatically installed in the
+maps directory.
+
+TERRASERVER-REFLECTIVITY
+Same as above but with Terraserver reflectivity images.
+"terraserver-reflectivity.geo" is automatically installed in the
+maps directory.
+
+TOPORAMA-250k
+Canadian 1:250k scale topo maps, downloaded from findu.com.
+"CanadaTopo250k.geo" is automatically installed in the maps
+directory.
+
+TOPORAMA-50k
+Canadian 1:50k scale topo maps, downloaded from findu.com.
+"CanadaTopo50k.geo" is automatically installed in the maps
+directory.
+
+WMSSERVER
+Allows use of Web Map Services (WMS). An example "WMSRadar.geo" is
+automatically installed in the maps directory.
+
+
+
+geoTIFF maps are a combination of two files as well: a .tif and a .fgd file.
+The .tif file is the actual map data. The .fgd file need only contain four
+lines like this (but may contain many other lines):
+
+1.5.1.1 WEST BOUNDING COORDINATE: -122.000000
+1.5.1.2 EAST BOUNDING COORDINATE: -120.000000
+1.5.1.3 NORTH BOUNDING COORDINATE: 48.000000
+1.5.1.4 SOUTH BOUNDING COORDINATE: 47.000000
+
+Xastir uses only those four lines in its calculations to determine the corner
+points of a map, to see whether the map fits in the current viewport (so it
+can decide whether to skip it). If your map data are USGS topographic maps,
+the .fgd file should be readily available to you. If it is not, the mapfgd.pl
+script can create it for you. If you don't have a .fgd file, the map will load
+fine, but the white borders won't be cropped and the size and rotation may be
+off a tad bit. An added feature in Xastir is the ability to do datum
+translations from NAD 1927 to WGS 84 datum, which makes the USGS topographic
+maps much more accurate on the Xastir screen.
+
+Xastir can use USGS geoTIFF topographic maps directly from the CD drive.
+Manually mount the disk or use auto-mounter to do it for you, and make sure
+you have a sym-link created in your maps directory that points to where you
+mounted your CD-ROM drive. That's it!
+
+
+ESRI Shapefile maps are also a combination of several files, a .shp file, a
+.dbf file, and a .shx file. You only need to select the .shp file to load the
+map, but the other(s) must be present for the map to load correctly.
+
+
+GNIS (Geographic Names Information System) data is a collection of names of
+locations, or geographic features. These labels behave like map labels in
+Dos/WinAPRS maps. As you zoom in, more labels will appear, assuming you've
+selected the GNIS file as a map and have enabled Map Labels in the Maps menu.
+If you have some of them in the xastir/GNIS directory, you can also search
+for map labels within Xastir.
+
+
+WX County Maps
+All WX County maps should be stored in the /usr/local/share/xastir/Counties
+and Xastir only supports the ESRI Shapefile standard for these. Installation
+is explained in README.MAPS. You must have Shapelib compiled in.
+
+As NWS messages are received, different areas will get tinted to designate
+areas of concern. They are color-coded to specify different types of
+alerts. The colors are: Cyan for advisory, yellow for watch, red for warning,
+orange for canceled alert, royal blue for tests, and green for undetermined
+alert levels. The coloring is done with a pixmap stipple that displays the
+type of alert, if it is able to be determined. These changes were made so that
+the underlying maps may still be seen underneath the weather alert areas, and
+so the alert type may be more easily determined, as sometimes matching the
+alerts on screen and in the weather alerts dialog is difficult. The display
+of weather alerts may be turned on/off via the Map menu.
+
+HELP-INDEX>Stations Menu
+
+ Stations Menu
+
+These options will allow you to control the data displayed around the stations
+on the map. It will also let you track and find stations, and clear stations
+and trails in the database and from the map.
+
+Find Station
+See the help topic "Locating a Station".
+
+Track Station
+See the help topic "Tracking a Station"
+
+Fetch Findu Trail
+Downloads historic trail data from findu.com. Slider bars control the starting
+point and duration of data downloaded. For an example, if you wished to see
+the track that happened two days ago, all day long, you might set the first
+slider to 48 hours (start time of two days ago) and the second slider to 24
+hours to snag exactly one day's worth of data, from the start until 24 hours
+later.
+
+
+Export all
+This sub-menu allows saving data for all stations to files [or databases]
+
+ Export to KML file
+ Saves all stations and their trails to a Keyhole Markup Language
+ file in ~/.xastir/tracklogs. The filename will be the current
+ date and time with a .kml extension, e.g. 20080125-033045.kml
+ KML files can also be written on a regular basis using KML
+ Snapshots on the file menu.
+
+ Store to open databases [Not yet implemented]
+ [Store to database interfaces is currently only implemented through
+ individual SQL database interface dialogs]
+
+ To save a png snapshot of the current map, use File->PNG Snapshots
+
+Filter Data
+This sub-menu allows filtering of the displayed symbols:
+
+ Select None
+ Determines if symbols should be drawn on the map. The other options depend
+ on this being enabled.
+
+ Select Mine
+ Determines if your own station is shown on the map.
+
+ Select via TNC
+ Global toggle for displaying data received via a TNC, but may be narrowed:
+
+ Select Direct
+ This option only displays stations heard directly (not digipeated).
+
+ Select via Digi
+ This option displays stations heard indirectly via a digipeater.
+
+ Select Net
+ This option displays stations with data received via the Internet.
+
+ Include Expired Data
+ Causes Xastir to continue to display the station data that normally goes
+ away when the symbol is ghosted. The expiration time can be adjusted in
+ the File|Configure|Defaults menu.
+
+
+ Select Stations
+ Global toggle for displaying stations, but may be narrowed:
+
+ Select Fixed Stations
+ This option displays stationary stations.
+
+ Select Moving Stations
+ This option displays stations with multiple positions or non-zero speed
+
+ Select WX Stations
+ This option displays Weather Stations.
+
+ Select CWOP WX Stations
+ This option includes the display of citizen weather (non-ham) weather
+ data.
+
+ Select Objects/Items
+ Global toggle for displaying objects/items, but may be narrowed:
+
+ Select WX Objects/Items
+ This option displays weather Objects and Items. This includes tropical
+ storms and remote weather stations.
+
+ Select Water Gauge Objects/Items
+ This option toggles the display of water gauge (/w) objects.
+
+ Select Other Objects/Items
+ This option enables or disables the display of objects other than those
+ listed above.
+
+
+Filter Display
+This sub-menu allows filtering of the displayed data:
+
+ Display Callsign
+ Determines if the callsign is displayed.
+
+ Label Trailpoints
+ This option includes callsigns along trails, to help identify which
+ points belong to which stations.
+
+ Display Symbol
+ Determines if the symbol is shown to the left of the callsign.
+
+ Rotate Symbol
+ Some symbols will change their orientation to show the direction in which
+ they are traveling.
+
+ Display Trail
+ When enabled, any moving station will trail a colored line. We now display
+ as many locations as we have in our database (old limit was 100). Long
+ trail segments (over 2 degrees latitude or 2 degrees long), or segments with
+ more than 45 minutes receive delay between the points will not be displayed.
+ Duplicate points are also eliminated from the track (SAR team returning to
+ base: Last segment may not be displayed due to the starting point appearing
+ twice in the trail list).
+
+ Display Course
+ When enabled, green text will appear below the call sign. This will display
+ the last known course (in degrees) the station was traveling.
+
+ Display Speed
+ When on, red text will appear below the call sign (or course). This will
+ display the last known speed of the station.
+
+ Display Short Speed
+ This option removes display of the measurement units for speed.
+
+ Display Altitude
+ When enabled, blue text will appear above the call sign. This will display
+ the last known altitude of the station.
+
+
+ Display Weather Info
+ Global toggle for displaying weather information, but may be narrowed:
+
+ Display Weather Text
+ When enabled, the latest weather data (temp,wind speed/course/gust,
+ humidity) is displayed. This may be adjusted with the following option:
+
+ Display Temperature Only
+ Displays only the temperature data for the station.
+
+ Display Wind Barb
+ When enabled, a wind barb showing the direction and speed of the wind is
+ drawn for all displayed stations reporting this information.
+
+
+ Display Position Ambiguity
+ When enabled, the area in which station using position ambiguity may be
+ located within is shaded, with the relevant station in the center.
+
+ Display Power/Gain
+ When on, Power/Gain Circles will be displayed. Overlapping circles indicate
+ that the stations are theoretically within simplex range of one another.
+ This is only roughly accurate, especially in areas of variable terrain.
+
+ Use Default Power/Gain
+ Enables a default power/gain setting as specified in the APRS(tm)
+ specification.
+
+ Display Mobile Power/Gain
+ Enables power/gain circles for mobile stations.
+
+
+ Display DF Attributes
+ When enabled, any DF circles/lines will be displayed on the screen.
+
+ Enable Dead-Reckoning
+ When enabled, the positions of stations are estimated based on past course
+ and speed. The recalculation rate should be reasonable, but can be adjusted
+ in the configuration file.
+
+ Display Arc
+ Displays an expanding arc of expected maximum travel distance, location and
+ course given the past course and speed. The arc slowly becomes a circle as
+ the position report gets older.
+
+ Display Course
+ Displays an expected course and distance traveled by the station, assuming
+ the course hasn't changed.
+
+ Display Symbols
+ Displays a ghosted version of the stations symbol at the expected position,
+ assuming the station has continued at its current course and speed.
+
+
+ Display Dist/Bearing
+ When enabled, two lines of text will be displayed on the left side of the
+ stations' icon. The top line will contain the distance from your station to
+ this station. The bottom line will contain the course from your station to
+ this station.
+
+ Display Last Report Age
+ Display the time since the station was last heard.
+
+Reload Object/Item History
+This will reload the ~/.xastir/config/objects.log file used for Object and Item
+persistence. This is needed if you edit the file while Xastir is running.
+
+Clear Object/Item History
+This will clear the ~/.xastir/config/objects.log file used for Object and Item
+persistence. It is recommended that you manually select and delete all Objects
+and Items that you own before doing this, otherwise they may remain on the
+screens of other APRS(tm) users.
+
+Clear All Tactical Calls
+Clears all assigned tactical calls. This will take effect the next
+redraw. Note that this will NOT clear tactical calls on other
+peoples' screens if you've published them via a message to
+"TACTICAL" (see the help text for "Send Message").
+
+Clear Tactical Call History
+This removes the tactical call history file, meaning that tactical calls
+assigned will not remain permanent between Xastir restarts. Note
+that this will NOT clear tactical calls on other peoples' screens if
+you've published them via a message to "TACTICAL" (see the help text
+for "Send Message".
+
+Clear All Trails
+This will wipe all the line tracking data from the station database and
+refresh the screen. This option is perhaps useful if you're low on memory
+or just want an uncluttered screen. You may also clear individual stations'
+trails from the Station Info dialog.
+
+Clear All Stations
+This will wipe all the data from the station database except yours. This
+option is perhaps useful if you're low on memory or just want to unclutter
+your screen.
+
+HELP-INDEX>Messages and the Messages menu
+
+ Messages and the Messages menu
+
+Send Message to and Open group messages
+
+These are very similar. "Send message to" will send your messages to one
+station and will only receive data from that station. Group messages are more
+general: you can receive any message for the group and you will send out your
+messages to that group name. Group messages code is not fully implemented yet
+and various problems still need to be worked out. The "groups" file is looked
+for in ~/.xastir/config. This is where the groups you are a member of are
+stored. As was said before the "groups" functionality may not be complete yet.
+
+At some point in the near future sending of bulletins should be added to this
+menu as well. It's not coded yet.
+
+Each of these two screens contains a message box, a call line, a message line,
+and various buttons. You must first enter the call of the group or station you
+want to contact. Once that is done any new message that has come in from that
+station to you will be displayed. If the station is sending you information
+and no message window is up it will automatically pop up a new window (up to
+10) with that station's call sign filled in for you. You can now enter a
+message on the message line. The message can be longer that the message line,
+and will max out at about 250+ characters. Once your message is entered,
+clicking on the "Send Now!" button will send your message. The "Send Now!"
+button will gray out until your message is completely ack'ed. Any message you
+receive will be sorted by the line # and be placed in the message window. If
+you are in a group mode each line will display the call sign from where the
+message was sent followed by the message itself. Currently group messages are
+sorted by call and then line #. When you are done sending messages clicking on
+the exit button will close the window. Other buttons are also available: The
+"New Call" button will allow you to look at old data a station has sent. Type
+in the call and click on this button, any old information will be displayed.
+You can also use this button to change the call of the station you're talking
+with. Enter the new call and click the button. The "Clear Msg History" button
+will clear any message displayed in the message window. "Cancel Pending Msgs"
+will cancel any messages in the transmit queue that haven't been acknowledged
+by the remote station yet. After canceling the pending messages or receiving
+and acknowledgment packet from the remote station, you may send new messages to
+the remote station. Xastir will allow you to type ahead, so you can just keep
+typing if you don't want to wait for the acknowledgments.
+
+Messages in reply to previous ones will attempt to use the path of the
+received message to avoid flooding the system with broadcast messages. You
+may adjust the path in the send message dialog, or the default path(s) set
+in the interface control will be used if you leave this blank. The path
+can be set for each message sent, but once a message is sent the path
+remains fixed for that particular message.
+
+Each outgoing message remains highlighted until it is ack'ed by the remote
+station. If it times out or if you cancel the pending messages, those
+messages will remain highlighted unless you clear the message history.
+
+To publish TACTICAL calls to other Xastir and APRS+SA stations as
+well as assign those tactical calls locally: Send a message to
+"TACTICAL" with the body of the message containing lines something
+like:
+
+ callsign-1=TAC1;callsign-2=TAC2;callsign-3=TAC3
+
+To remove these tactical calls later from local AND remote screens,
+assure that the original message(s) assigning them has timed-out or
+been cancelled, then send a message like this and let it retry until
+it times out (assigns blank tactical calls to the original
+callsigns, thereby removing the assignment):
+
+ callsign-1=;callsign-2=;callsign-3=
+
+Clear all outgoing messages
+This will clear all un-ack'ed messages you have sent.
+
+General Stations Query
+This sends an ?APRS? packet, which should cause all local stations to report
+their position and/or status. Most software ignores this query, because
+responding to it would cause massive floods of data.
+
+IGate Stations Query
+This sends an ?IGATE? packet, which should cause all local IGates to respond
+with their capabilities.
+
+WX Stations Query
+This sends an ?WX? packet, which should cause all local weather stations to
+report their position and weather.
+
+Modify Auto reply message
+This will set the message that is sent as an Auto Reply.
+
+Enable Auto Reply Msg
+This will turn on an automatic reply when an incoming message is received.
+
+Satellite Ack Mode
+This mode disables the sending of ack messages in response to received
+messages. Messages are still acknowledged using the reply-ack system. When
+operating over a satellite it is clear that your message made it, because you
+will hear it repeated. The receiving station sending an independent ack only
+adds QRM.
+
+HELP-INDEX>Interfaces Menu
+
+ Interfaces menu
+
+This menu contains interface related options.
+
+Interface Control
+This option displays a window where you can turn on and off your configured
+interfaces, as well as add, delete, or configure interfaces. See the "Configure
+Interfaces" help topic.
+
+Disable Transmit options
+These options disable the transmission of everything, one's position, or one's
+objects. These are global options and affect all interfaces. Most interfaces
+have an option to disable transmission on that specific interface in their
+configuration menus as well.
+
+Enable Server Port
+This enables/disables TCP and UDP listening sockets at port 2023. You may
+connect other APRS(tm) clients to the TCP port in order to send/receive
+APRS(tm) data. Once they authenticate, they'll be able to send data to Xastir.
+Without authentication, they'll be able to receive every bit of TNC and INET
+data that Xastir receives. Note that ANY user with the proper credentials can
+come in on the TCP or UDP ports if they are enabled. The only one of these two
+ports currently that can send to RF is the UDP Server port. The TCP
+port cannot.
+
+ "user WE7U-13 pass XXXX vers XASTIR 1.3.3"
+
+Connect another APRS(tm) client to that port and it should authenticate and be
+able to send to any server that Xastir is connected to, as well as receive
+packets from all ports/servers Xastir is hooked to.
+
+You should also have a binary called "xastir_udp_client" which can send packets
+into the UDP listening port. Invoke it like this:
+
+ xastir_udp_client localhost 2023 <callsign> <passcode> "APRS Packet Goes Here"
+
+Currently that will inject the packet into Xastir's decoding routines and send
+it to any TCP-connected clients. It will also igate it to the INET if you have
+igating enabled. It will send the packet out the RF ports as third-party
+packets only if you add the "-to_rf" flag after the passcode like this:
+
+ xastir_udp_client localhost 2023 <callsign> <passcode> -to_rf "APRS Packet"
+
+The UDP client is useful for generating and injecting APRS packets from
+external scripts. It can also be used to fetch the callsign of the remote
+xastir server by using the -identify flag:
+
+ xastir_udp_client localhost 2023 <callsign> <passcode> -identify
+
+Transmit now
+Causes all interfaces that have transmit enabled (see configure|interfaces) to
+transmit a position packet. It will be grayed out if Disable Transmit: ALL
+is selected.
+
+If you have GPSMan installed, you have these additional menu options
+displayed:
+
+Fetch GPS Track
+Download a set of trackpoints from an attached GPS.
+
+Fetch GPS Routes
+Download a set of routes from an attached GPS.
+
+Fetch GPS Waypoints
+Download a set of waypoints from an attached GPS.
+
+Fetch Garmin RINO Waypoints
+Snag waypoints from an attached Garmin RINO, create APRS(tm) Objects out of any
+waypoints which begin with "APRS".
+
+HELP-INDEX>Station info box - FCC and RAC lookup
+
+ Station info box - FCC and RAC lookup
+
+Station Info will display any data decoded by Xastir.
+
+You can assign (local only) tactical calls to stations from here, by
+clicking the "Assign Tactical Call" button. This will cause the
+station on screen to display as the tactical call instead of its
+callsign. Assigning a blank tactical call clears this feature, and
+it can also be cleared for all stations in the Stations menu. This
+feature assigns tactical calls to the local Xastir station only, but
+see below to publish them to others.
+
+To publish tactical calls across the air to other Xastir and APRS+SA
+stations (as well as assign them locally), see the "Send Message" help
+section.
+
+"Enable Automatic Updates" will cause the window to refresh frequently with the
+latest information.
+
+The information available may include: Number of packets heard, the time
+last heard, the device the packet came from, station comments,
+power/height/gain of the station, course/distance from your station,
+weather information, and current and previous positions.
+
+For moving stations a track-log follows with the most recent entries on top.
+A '+' in front indicates that a new track starts at that point (if there was
+a large gap in time or position). A star at the end of a line indicates that
+this station could be heard direct (without a digi) at that specific position.
+Positions are followed by the 6 digit Maidenhead grid square the station was
+located in at that point.
+
+For your own station, there is an "Echoed from" field, listing the
+last six digipeaters that heard you directly. This is useful for setting
+non-generic paths.
+
+Currently two rows of four buttons appear in the Station Info window. Some
+of the labels on the buttons change based on the type of station that you're
+dealing with.
+
+For objects/items:
+
+Store Modify Blank Close
+Track Object/
+ Item
+
+Station Trace Un-Acked Direct
+Version Query Messages Stations
+Query Query Query
+
+For other stations:
+
+Store Send Search Close
+Track Message FCC (RAC)
+ Database
+
+Station Trace Un-Acked Direct
+Version Query Messages Stations
+Query Query Query
+
+"Station Version Query" changes to "Clear Track" for mobile stations.
+The Clear Track button will clear any line tracking for this station that is
+currently stored or on the map display.
+
+"Store Track" will save the track of the station to a file on disk. The
+format is similar to that used by GPS receivers but its specification
+might be changed (enhanced) in future versions. There is currently no
+way to read that track data back in, but it is planned for the future.
+The goal is to also read and display GPS track-logs in a similar manner.
+These track-log files will be placed in the directory ~/.xastir/tracklogs
+with a name equal to the stations call with ".trk" as extension. "Store
+Track" will simultaneously save the station's track as a Keyhole Markup
+Language (.kml) file with a filename equal to the station's call, the
+current date and time and .kml as extension. If shapefile support has
+been included, the station's track will also be saved as a set of four
+files (.dbf,.prj,.shp,.shx). Subsequent presses of Store Track for the
+same station will write additional lines into the .trk file, and create
+new .kml (and shapefile) files (each containing all positions in the
+station's track.
+
+"Modify Object/Item" will bring up the Object Modify window.
+
+"Send message" will open up the message window and allow you to send a message
+to this station. It will fill in the call sign for you.
+
+If the FCC (U.S. Federal Communications Commission) or RAC (Radio Amateurs of
+Canada) database is installed and the callsign appears to be a Canadian or
+U.S. callsign, the "Search FCC/RAC Database" button will become active,
+otherwise this button will be inactive. The FCC and RAC files should be
+placed in the /usr/local/share/xastir/fcc directory, and case is important!
+Pressing this button adds the station's name and address into the Station
+Info box. Instructions for installing these databases are in the README.MAPS
+file.
+
+Xastir will create index files for each database file upon startup. If a newer
+callsign file is placed there while Xastir is running, it will create or
+rebuild the index on the next lookup. Special prefixes are NOT handled.
+
+HELP-INDEX>Creating a log
+ Creating a log
+
+Xastir can log data from the internet or TNC for later playback, or for
+debugging purposes. WARNING: Logging can fill up your hard drive, so be
+careful using it, or make preparations for rolling over the log files
+automatically via cron. An indication will be shown on the status bar when
+logging is enabled.
+
+All these choices are accessible via the File menu:
+
+Enable TNC Logging
+Logs all TNC data received and transmitted. These logs can be played back using
+the "Open Log File" feature.
+
+Enable Net logging
+Logs all internet data received and transmitted. These logs can be played back
+using the "Open Log File" feature. If you have no interfaces started but still
+want to log your posits and objects locally, this is the option to enable for
+that as well.
+
+Enable IGate logging
+Logs all data forwarded in both directions, and rejected forwards with reasons
+for rejection. Includes NWS messages forwarded to RF.
+
+Enable WX logging
+Logs all weather data received from your weather station.
+
+
+HELP-INDEX>Replaying a log
+
+ Replaying a log
+
+Click on "File", then "Open Log File" and a file selector window will display.
+You can use it to browse your hard drive and select any file containing raw
+TNC data like those created by the TNC and Net logging options. Your station
+will still function the same way, receiving and transmitting. If you were
+logging data, the typical place to look for those files would be
+~/.xastir/logs/
+
+NOTE: This function doesn't read the saved station tracklogs.
+
+HELP-INDEX>Locating a Station
+
+ Locating a Station
+
+Click on "Stations", then "Find Station". A window will pop up. You can now
+enter a call or part of a call. By default it will search for an exact match
+(full call, not partial) and is not case sensitive. If you are looking for a
+partial match, "Match Exact" should not be selected.
+
+For objects which could contain lower case letters you have to check
+"Match Case"! Opposite to the name, without "Match Case" the search
+text will only be converted to upper case...
+
+Clicking on the "Locate Now!" button will center the first station
+found in the center of your screen at the current zoom level.
+
+Clicking "FCC/RAC Lookup" will look up the user's information if the FCC or RAC
+database, of those databases are installed.
+
+Clicking on "Cancel" will close the window.
+
+This dialog will pop up if a station sends a Mic-e "Emergency!" packet, to
+encourage users to locate and perhaps help the listed station.
+
+HELP-INDEX>Creating and using Map Display Bookmarks
+
+ Creating and using Map Display Bookmarks
+
+Click on "Maps", then "Map Display Bookmarks" and a window will pop up.
+If this is the first time you have used this then the box will have no
+entries in it. To add a bookmark to the list: Position the main map to
+the area and zoom level you want to use. Enter a unique name in the
+"New Name" area, then click on add. Your entry will be added to the
+list (in alphabetical order). You can add as many map display bookmarks
+as you want. To use one of the bookmarks mark its name and click
+"Activate!". The main map will then show the stored area and zoom level.
+You can similarly delete a bookmark by clicking on the bookmark name and
+then the "Delete" button.
+
+"Maps->Locate Map Feature" is another method to jump to a location, if
+the name of the location is known and you have GNIS files installed.
+
+HELP-INDEX>Tracking a Station
+
+ Tracking a Station
+
+Click on "Stations", then "Track Station". Enter the callsign to track (all or
+part) then click on the "Track Now!" button. As the station moves it will
+remain viewable in the main map window. As the stations starts to get close
+to the edge of the map window the window will re-center so that the object is
+always visible. To stop tracking this station click on the "Clear Tracking"
+button. While tracking is active, a "Tr" is shown in the status bar next to
+the zoom level. If the station is not on the map yet, tracking will begin
+as soon as it shows up.
+
+HELP-INDEX>Printing
+
+ Printing the Map Screen
+
+Note: Printing has not been set up on Windows/Cygwin. These instructions
+are for Unix and Unix-like operating systems.
+
+Xastir can print the drawing area in either black & white or color. It does
+this by first dumping the image to an XPixmap file on disk, then using external
+tools to convert it to postscript, scale it, rotate it, preview it, then print
+it. You must have your system printing set up to handle postscript (usually
+this requires Ghostscript and a print filter installed, as well as lp or lpr
+print spoolers). You must also have the following tools installed for this
+capability: ImageMagick tools (specifically "convert"), "Ghostscript",
+Ghostscript fonts, and "gv". Once all of these packages are installed and
+functional, you should get a "gv" window popping up shortly after you tell
+Xastir to create a print file. From there you can view the printed image, and
+if acceptable, tell "gv" to print it. Note that sometimes changing to a white
+default background for the maps is recommended, depending on what maps you have
+viewable. This can save greatly on ink.
+
+HELP-INDEX>Creating Snapshots
+
+ Creating Automatic Snapshots
+
+Xastir has the capability to create automatic snapshots of the map screen
+on a recurring basis. The default time period is set at once per five
+minutes. Assuming that you have "convert" from the ImageMagick tools
+installed, Xastir will create an XPM format file in ~/.xastir/tmp/, then
+convert it to the PNG file ~/.xastir/tmp/snapshot.png. This file is useful for
+embedding in web pages to show a "live" image of what is on your Xastir
+screen. Enable this feature via the "File->PNG Snapshots" toggle-button.
+The rate is once every five minutes (configurable from the Configure
+Timing dialog from "File->Configure->Timing"), or every time the button is
+toggled from off to on. A .geo is created to allow you to use the snapshot
+as a map. A .kml file is also written to allow you to use the snapshot as
+a graphic overlay on terrain in applications capable of reading kml. See
+kml_snapshot_to_web.sh and kml_snapshot_feed.kml in the scripts directory
+for more information on using the snapshot.png and snapshot.kml file to
+produce a kml feed using the snapshots.
+
+ Creating Automatic KML Snapshots
+
+Xastir is capable of writing all current stations and tracks to a kml file
+on a recurring basis. Enable this feature via the "File->KML Snapshots"
+toggle button. The rate at which these snapshots are generated is the same
+as that of PNG snapshots, configured from "File->Configure->Timing" by
+setting the snapshot time interval. Each snapshot is written to a .kml
+file in ~/.xastir/tracklogs, with a filename based on the date and time
+of the snapshot, e.g. 20080206-000720.kml This behavior may change to
+make KML snapshots write to a single file like PNG snapshots.
+
+
+HELP-INDEX>Included Scripts
+
+ Included Scripts
+
+Xastir includes several Perl scripts and a shell script that may be useful:
+
+get-fcc-rac.pl
+This shell script automates retrieving and installing the FCC and the RAC
+callsign databases. Note that these databases are very large!
+
+icontable.pl
+This script generates an xpm bitmap of all Xastir's primary and secondary
+symbols from the symbols.dat file. The overlays and specials are ignored.
+Output is to STDOUT, so a typical call would be "icontable.pl > symbols.xpm".
+
+inf2geo.pl
+This script creates .geo files from UI-View .inf files. To create a map.geo
+from a map.inf, typical usage would be "inf2geo.pl map".
+
+kiss-off.pl
+This script sends the commands needed to turn off a TNC's KISS mode.
+
+mapblast2geo.pl
+This script creates .geo files for Mapblast pixel maps. It includes usage
+information.
+
+mapfgd.pl
+This script creates minimal .fgd files for GeoTIFF images lacking them, based
+on information found in the GeoTIFF file. The created files allow Xastir to
+crop the white borders and rotate/scale the map properly. Typical usage would
+be "mapfgd.pl mapdir" where mapdir is the directory containing the GeoTIFF
+images.
+
+overlay.pl
+This script creates .log format files from comma-separated overlay files. See
+the script comments for full usage information.
+
+ozi2geo.pl
+This script creates .geo files from OziExplorer .map files.
+
+permutations.pl
+This script converts between different lat/lon formats. See the script comments
+for further details.
+
+split_gnis.bash
+This will take a GNIS data-point file (typically for a whole state, 8+MB), break
+it down into smaller chunks (typically for a county, 30-200k) it will also
+throw away the trailing spaces and <CR>s at EOL.
+
+split_gnis.pl
+This is a Perl version of the above script.
+
+test_coord.pl
+Tests for the Coordinate.pm Perl module.
+
+track-get.pl
+This script downloads the track-log of a specified object from a Garmin GPS.
+It requires the GPS::Garmin module. It prompts for an object name, and writes
+the track-log to the ~/.xastir/logs directory.
+
+update_langfile.pl
+This script is targeted toward developers. It rebuilds a specified language
+file to contain all the strings of another. It is usually used to regenerate
+the non-English language files when significant changes have been made to the
+English file. When the second language file lacks a string in the main file,
+the untranslated string is inserted. Typical usage would be
+"update_langfile.pl language-German.sys" . The main language file is
+hard-coded but easily editable.
+
+waypoint-get.pl
+This similar script downloads the waypoints from a Garmin GPS, and creates a
+log in the ~/.xastir/logs directory containing the waypoints as objects. It
+also requires the GPS::Garmin module.
+
+db_gis_mysql.sql db_gis_postgis.sql
+These will create tables for storing station data in a mysql or postgresql/
+postgis database. SQL Server database support is experimental. See the
+"OPTIONAL: Experimental. Add GIS database support" section in INSTALL
+
+HELP-INDEX>Configuring Interfaces
+
+ Configuring Interfaces
+
+Click on Interfaces, then Interface Control.
+
+An "Installed Interfaces" box should appear. This box will allow you to add,
+delete, and modify the properties of various devices you may want to use with
+Xastir.
+
+Supported interface types are:
+Serial TNC
+Serial TNC w/GPS on HSP cable
+Serial GPS
+Serial WX
+Internet Server
+AX.25 TNC
+Networked GPS (via gpsd)
+Networked WX
+Serial TNC w/GPS on AUX port
+Serial KISS TNC
+Networked Database (Not Implemented Yet)
+Networked AGWPE
+Serial Multi-Port KISS TNC
+SQL Databases [MySQL,Postgis] (Experimental)
+
+To add a device, click on the add button. A "Choose Interface Type" box will
+appear. Click on the type of device you would like to add. Then click the Add
+button in the "Choose Interface Type" box. Properties for that device will
+appear. Fill out the requested information and click OK.
+
+To delete the device, click on the device you wish to delete and then click
+the delete button.
+
+To modify the properties of a device, click on the device you wish to modify,
+then click the properties button. The properties for that device will appear.
+Change the information you want and click OK.
+
+More specific help is available under the help topics of each interface type.
+
+SQL Databases will only appear as an option if you have MySQL or Postgis
+support compiled.
+
+HELP-INDEX>Configure Serial TNC Devices
+
+ Configure Serial TNC Devices
+
+This section covers adding or modifying Serial TNCs or Serial TNCs with a
+GPS on a HSP cable.
+
+If you have a HSP cable, which allows you to share the TNC port with a GPS
+unit you may choose a TNC with GPS (HSP Cable). This is a special cable and may
+not work on all computers/GPS/TNC combinations. If you use this device the TNC
+and the GPS should be set to the same communications parameters. Generally
+4800 bps, 8 data bits, no parity, and 1 stop bit.
+
+TNC Port Options:
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Allow Transmitting" will tell Xastir that any outgoing RF data can
+be sent to this device for broadcast.
+
+The TNC Port is the Unix device that the TNC (or TNC and GPS) is hooked to.
+Normally you can use /dev/ttyS0 (com1), /dev/ttyS1 (com2) etc.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Now set the bps rate under port settings, and the parameters under port
+style. Port Style setting 8N1 is used for 8 data bits, No parity and 1 stop
+bit. 7E1 is used for 7 data bits, even parity and 1 stop bit. 7O1 is used for
+7 data bits, odd parity, and 1 stop bit. These parameters must match your TNC
+and GPS.
+
+Choose the correct IGate operation for this device. You may have several TNC
+devices, and this option can be different for each device. If you are not
+running an IGate leave it at the default option of "Disable".
+
+Enter up to three UNPROTO paths. Xastir will assume the XX VIA part of the
+UNPROTO path. There are three paths allowed so that your signal will be heard
+if conditions are bad. XASTIR will cycle through each one that is filled in,
+one per transmission time. If you are local to a digi, just WIDE2-2 may be a
+good choice. If you are using low power and/or are distant from a digi then
+WIDE1-1, WIDE2-2 may work better. Or if you know the call of your closest digi you
+may use XXXCALL, WIDE2-2. Most of you will only need one path. If you are in a
+remote area and your signal is difficult to get out you may need more. Check
+with a local group and ask what path may be best for your area. If no paths are
+entered it will default to WIDE2-2.
+
+If you are IGating to RF, you may enter a specific path to use for the packets
+you send to RF. If you leave this blank, the UNPROTO paths above will be used.
+If the UNPROTO paths are blank, WIDE2-2 will be used.
+
+TNC Startup and Shutdown files. These fields specify a filename that is
+located in the /usr/local/share/xastir/config directory. Each file is a
+standard text file containing any commands you would like to send your TNC at
+the time the device is activated (startup file) or shut down.
+
+HELP-INDEX>Configure Serial TNC w/GPS on HSP cable or AUX port
+
+ Configure Serial TNC w/GPS on HSP cable or AUX port
+
+These hybrid interface types implement the options of both serial TNCs and
+GPSs. Please consult the configuration help for both serial TNCs and serial
+Gpsd for further information on the configuration of these devices.
+
+"Send Control-E to get GPS Data?"
+
+This checkbox controls whether Xastir sends a Control-E to the TNC every time
+it needs GPS data.
+
+Some TNCs that support a GPS on an auxilliary port require that Xastir
+send a Control-E to the TNC in order to get the GPS data each time it
+is needed. Devices in this class include the Kantronics KPC-3+.
+
+Some devices, like Kenwood APRS radios (D700, etc.) do NOT require
+this, and in fact the Control-E interferes with correct operation of
+these devices.
+
+Because Control-E was required by the most common TNCs that had an aux
+port for GPS at the time that this interface type was written, this is
+the default behavior of Xastir. If you have a Kenwood radio that you are
+using in this mode, you must DESELECT the "Send Control-E to get GPS data?"
+checkbox in the configuration dialog for this interface type.
+
+HELP-INDEX>Configure Serial KISS TNC
+
+ Configure Serial KISS TNC
+
+This section covers adding or modifying Serial KISS TNCs. KISS mode can be done
+by most standard TNCs too, and it eliminates the necessity to set the options
+specially in the startup files, at the expense of slightly higher processor
+usage. And of course this enables the use of purely KISS TNCs, such as the one
+described in the November 2000 issue of QST, without a separate program or
+kernel module.
+
+Options
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Allow Transmitting" will tell Xastir that any outgoing RF data can
+be sent to this device for broadcast.
+
+Selecting "RELAY Digipeat?" will tell Xastir to digipeat traffic. It will do
+this if the first unused digipeater call in the path matches your callsign or a
+callsign listed in your Xastir config file ("RELAY_DIGIPEAT_CALLS" line,
+default is "WIDE1-1"). This option is only recommended for base stations in
+regions where there are few other fill-in digipeaters in the area. Consult with
+a local group about the best setting for your region. You may hand-edit the
+Xastir config file when Xastir is not running in order to change this string to
+match your local recommendations. In the U.S., "WIDE1-1" is the recommended
+setting.
+
+The TNC Port is the Unix serial device that the TNC is hooked to.
+Normally you can use /dev/ttyS0 (com1), /dev/ttyS1 (com2) etc.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Now set the bps rate under port settings.
+
+Choose the correct IGate operation for this device. You may have several TNC
+devices, and this option can be different for each device. If you are not
+running an IGate leave it at the default option of "Disable".
+
+Enter up to three UNPROTO paths. Xastir will assume the XX VIA part of the
+UNPROTO path. There are three paths allowed so that your signal will be heard
+if conditions are bad. Xastir will cycle through each one that is filled in,
+one per transmission time. If you are local to a digi, just a WIDE2-2 may be a
+good choice. If you are using low power and/or are distant from a digi then
+WIDE1-1,WIDE2-2 may work better. Or if you know the call of your closest digi
+you may use XXXCALL,WIDE2-2. Most of you will only need one path. If you are in
+a remote area and your signal is difficult to get out you may need more. Check
+with a local group and ask what path may be best for your area. If no paths
+are entered it will default to WIDE2-2.
+
+If you are IGating to RF, you may enter a specific path to use for the packets
+you send to RF. If you leave this blank, the UNPROTO paths above will be used.
+If the UNPROTO paths are blank, WIDE2-2 will be used.
+
+Next configure the KISS parameters: TXdelay is the time (in 10ms units) needed
+between the keying of the radio and when it is ready to send data. Persistence
+and slottime are the channel access parameters: Slottime is how often the
+channel access algorithm is executed, and should usually be set to 10.
+Persistence is how aggressively your station tries to grab the channel when
+free, and should be ideally set to 255 divided by the number of stations on the
+channel. Full duplex allows the transmission to begin while there are packets
+being received on the channel, this should be disabled in most cases (set to
+"0").
+
+HELP-INDEX>Configure AX.25 TNC Devices
+
+ Configure AX.25 TNC Devices
+
+This section covers adding or modifying AX.25 TNC devices. AX.25 devices can
+be any device that uses the Linux AX.25 drivers. This is a kernel level
+driver, and device such as a Baycom or a sound modem can be used as a TNC.
+These devices must be set up and running before Xastir can use them.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Allow Transmitting" will tell Xastir that any outgoing RF data can
+be sent to this device for broadcast.
+
+Selecting "RELAY Digipeat?" will tell Xastir to digipeat traffic. It will do
+this if the first unused digipeater call in the path matches your callsign or a
+callsign listed in your Xastir config file ("RELAY_DIGIPEAT_CALLS" line,
+default is "WIDE1-1"). This option is only recommended for base stations in
+regions where there are few other fill-in digipeater stations in the area.
+Consult with a local group about the best setting for your region. This is
+only needed if you are not using any other software that performs this
+function, such as aprsdigi or DIGI_NED. You may hand-edit the Xastir config
+file when Xastir is not running in order to change this string to match your
+local recommendations. In the U.S., "WIDE1-1" is the recommended setting.
+
+Enter the AX.25 Device name you specified in the axports file for this device.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Choose the correct IGate operation for this device. You may have several TNC
+devices and this option can be different for each device. If you are not
+running an IGate leave it at the default option of "Disable".
+
+Enter in up to three UNPROTO paths. Xastir will assume the XX VIA part of the
+UNPROTO path. There are three paths allowed so that your signal will be heard
+if conditions are bad. Xastir will cycle through each one that is filled in,
+one per transmission time. If you are local to a digi, just a WIDE2-2 may be a
+good choice. If you are using low power and/or are distant from a digi then
+WIDE1-1,WIDE2-2 may work better. Or if you know the call of your closest digi
+you may use XXXCALL,WIDE2-2. Most of you will only need one path. If you are in
+a remote area and your signal is difficult to get out you may need more. Check
+with a local group and ask what path may be best for your area. If no paths
+are entered it will default to WIDE2-2.
+
+If you are IGating to RF, you may enter a specific path to use for the packets
+you send to RF. If you leave this blank, the UNPROTO paths above will be used.
+If the UNPROTO paths are blank, WIDE2-2 will be used.
+
+NOTE: To use AX.25 devices with Xastir you will need to run the program as
+"root". If you want to run Xastir as another user you may want to set the
+suid bit on the Xastir program file. Please see INSTALL file for more
+information; current Xastir drops the extra privileges but has not been audited
+for exploits. Use in this fashion in a multi-user environment at your own risk!
+
+HELP-INDEX>Configure Serial GPS Devices
+
+ Configure Serial GPS Devices
+
+Set the serial port device for your GPS unit. Common values of /dev/ttyS0
+(COM1) or /dev/ttyS1 (COM2) can be used.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Set system clock from GPS data" will tell Xastir to try setting the
+system's clock to the highly accurate time signal from the GPS receiver. This
+requires root privileges on most systems.
+
+Now set the bps rate under port settings, and the parameters under port
+style. Port Style setting 8N1 is used for 8 data bits, No parity and 1 stop
+bit. 7E1 is used for 7 data bits, even parity and 1 stop bit. 7O1 is used for
+7 data bits, odd parity, and 1 stop bit. These parameters must match your GPS.
+Most GPS units will use 4800 bps and 8,n,1.
+
+HELP-INDEX>Configure Networked GPS Devices
+
+ Configure Networked GPS Devices
+
+If you need to share the GPS data with different programs or machines, this
+option is best. Xastir will work with gpsd which will allow several
+connections to share your GPS data.
+
+Set the host name (or IP address) and the port number for the gpsd host on
+your network.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Reconnect on failure" will tell Xastir to try to reconnect when the
+data stream has failed.
+
+Selecting "Set system clock from GPS data" will tell Xastir to try setting the
+system's clock to the highly accurate time signal from the GPS receiver. This
+requires root privileges on most systems.
+
+HELP-INDEX>Configure the Internet Server
+
+ Configure the Internet Server
+
+Internet Servers allow you to send and receive data for all over the world.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+setup communications with it when the program first starts.
+
+Selecting "Allow Transmitting" will tell Xastir that any outgoing Internet
+data can be sent to this device.
+
+Enter the host name (or IP address) and the port number of the Internet
+Server you want to contact.
+
+Enter a valid pass-code to validate your connection, this will allow your
+data to be transmitted via an IGate. If you don't have a pass-code, use the
+included "callpass" program to generate one. Note that passcodes are dependent
+on callsigns. From the src directory, "make callpass" should create the
+executable if it isn't already compiled.
+
+Enter any filter parameters. This causes a special message to be sent to the
+server requesting that the data be filtered in a certain way. The exact format
+of this field is fully specified, please consult APRSSIG for more information.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Reconnect on failure" will tell Xastir to try to reconnect when the
+data stream has failed.
+
+HELP-INDEX>Configure a Serial WX Station
+
+ Configure a Serial WX Station
+
+Set the serial port device for your WX unit. Common values of /dev/ttyS0
+(COM1) or /dev/ttyS1 (COM2) can be used.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Now set the bps rate under port settings, and the parameters under port
+style. Port Style setting 8N1 is used for 8 data bits, No parity and 1 stop
+bit. 7E1 is used for 7 data bits, even parity and 1 stop bit. 7O1 is used for
+7 data bits, odd parity, and 1 stop bit. These parameters must match your WX
+unit. The Data Type option will allow you to override what type of serial data
+the program will look for. The auto-detect feature will first look for Weather
+data in a binary type as the Radio Shack WX-200 uses. If no binary data is
+found in the stream, Xastir will look for an ASCII type of WX station (like
+Peet Bros.).
+
+Now set the Rain Gauge correction factor. Xastir requires that the rain gauge
+report in .01 inch increments. If the unit reports in .1 inch or .1 millimeter
+increments, a correction must be specified to obtain accurate measurements.
+
+HELP-INDEX>Configure a Networked WX Station
+
+ Configure a Networked WX Station
+
+Xastir can use WX data servers such as wx200d. wx200d will allow several
+network connections, thus sharing the Weather data with several programs or
+computers.
+
+Enter the host name (or IP address) and the port number of the WX data server
+you want to contact.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Reconnect on failure" will tell Xastir to try to reconnect when the
+data stream has failed.
+
+As before the Data Type will override the auto detection.
+
+Now set the Rain Gauge correction factor. Xastir requires that the rain gauge
+report in .01 inch increments. If the unit reports in .1 inch or .1 millimeter
+increments, a correction must be specified to obtain accurate measurements.
+
+HELP-INDEX>Configure an AGWPE Connection
+
+ Configure an AGWPE Connection
+
+Xastir can use an AGWPE network interface running on a Windows box
+as a TNC interface. It can also use the login/password security that
+AGWPE has built-in, but you must set up the account in the AGWPE
+application with your callsign for the username, in all capital
+letters. For instance: "AB7CD".
+
+The other options are described in the sections for Serial TNC and for
+Network interfaces.
+
+HELP-INDEX>Configure a SQL Database Connection
+
+ Configure a SQL Database Connection
+ [Experimental]
+
+Xastir can experimentally store and retrieve station data from either
+a MySQL database or a Postgresql + Postgis database. See the
+"OPTIONAL: Experimental. Add GIS database support." section in the
+INSTALL file for more information. Station and object data are stored
+as spatial data, and can be retrieved from other GIS applications, for example
+Xastir can write station locations into a Postgis database from which they
+can also be viewed using QGIS. SQL database connections also allow for the
+persistence of data between Xastir sessions. All aspects of spatial database
+support, including database structures, are currently experimental and may
+change at any time. You may configure multiple SQL database connections,
+but you should only have one active at a time.
+
+Before creating a database connection in Xastir, you will need to create a
+database to connect to, create an appropriate set of tables
+(see the db_gis_xxxxx.sql scripts in the scripts directory), and add a user
+with a password and rights to access the database. For postgis databases
+you may also need to appropriately configure the user in pg_hba.conf
+
+Configuration options on the SQL database dialog include:
+Database: MySQL (lat/long) for very old MySQL databases,
+ Postgis for postgresql + postgis, and
+ MySQL (Spatial) for current MySQL databases.
+With tables for: Currently only the Xastir simple schema - a very basic
+ flat table holding minimal information about stations.
+Host: IP address or hostname for the database server, default is localhost.
+Port: Default is 3306 for MySQL and 5432 for Postgresql. The database can
+ be on a remote server, but the appropriate port will need to be
+ open in any firewalls.
+Username: Can be unique to your database, e.g. xastir_user
+Password: Unique to your database.
+Schema name: Your database name. e.g. xastir
+MySQL Socket: check my.cnf, or mysql --help | grep socket
+ Leave blank for postgis databases.
+Reconnect on Net Failure: [Not yet implemented]
+MySQL defaults and Postgis defaults provided by the buttons may
+or may not be correct for your database.
+
+Three options control the behavior of the SQL Database interface:
+Activate on Startup: Try to connect to this database and begin storing heard
+station data as soon as Xastir starts (if store incoming data is also selected).
+
+Store incoming data: Stores each station (including objects and items) report
+as a record in the database. All stations heard on all interfaces will be
+stored to the database - if you are connected to internet feeds and leave
+xastir running this can easily be a million records per day.
+
+Load data on startup: Retrieve all station data from the database
+when restaring Xastir. Currently the only way to retrieve persistent
+data from a database. Will attempt to connect to database and retrieve data
+independent of the settings of either activate on startup or store incoming
+data. Due to rounding and conversion errors, non-mobile stations may move
+slightly.
+
+The "Most Recent Error" box may or may not contain an error message to help
+identify connection problems. When Xastir fails to connect to a database,
+the interface will show ERROR on the interface list, and the most recent error
+may be shown here. Running xastir from the console and observing error
+messages there, or running xastir from the console with xastir -v1 may help
+identify the cause of connection problems, as may examination of the
+database's error logs.
+
+You will only be able to configure a SQL Database interface if you have
+compiled Xastir with support for that DBMS (--with-mysql or --with-postgis).
+
+HELP-INDEX>Symbol Table
+
+These are the symbols that you can select for your station under the "Station
+Information" configuration menu. The current list can be found in the APRS(tm)
+Reference which you could get from http://www.tapr.org
+
+ Symbol Table
+
+Symbol Group / Group \
+
+! Triangle w/! Triangle w/!
+" Rain Cloud Rain Cloud
+# Digi DIGI
+$ Phone Symbol $ Symbol
+% DX DX
+& GATE-HF GATE
+' Small Aircraft Aircraft Crash
+( Cloud Cloud
+) TBD
+* SNOW Flake SNOW Flake
++ Red Cross
+, Reverse L
+- House w/omni
+. Small x
+/ Red Dot
+0 0 in a box Circle
+1 1 in a box
+2 2 in a box
+3 3 in a box
+4 4 in a box
+5 5 in a box
+6 6 in a box
+7 7 in a box
+8 8 in a box
+9 9 in a box GAS
+: Fire ?
+; Tent Tent
+< Motorcycle Pennant
+= Train Engine
+> Car Car
+? POS Antenna ? in a box
+@ HURRICANE/STORM HURRICANE/STORM
+A First Aid Box
+B BBS Blowing Snow
+C Canoe
+D D in a circle
+E E in a circle Smoke Stack
+F F in a circle
+G Grid Square Antenna ?
+H Hotel/Bed
+I TCP/IP ?
+J J in a circle Lightening
+K School House
+L Light House Light House
+M Mac
+N NTS ?
+O Balloon
+P Police car Rx
+Q Circle with in Circles Circle with in Circles
+R RV Restaurant
+S Shuttle Satellite
+T Thunderstorm (cloud/bolt) Thunderstorm (cloud/bolt)
+U School Bus Sun
+V VOR TAC VOR TAC Symbol
+W National Weather Service NWS-Digi
+X Helicopter
+Y Sail Boat
+Z Windows
+[ Runner WC
+\ DF Triangle
+] Packet Mail Box
+^ Large Aircraft Large Aircraft
+_ Weather Station WS-Digi
+` Satellite Dish
+a Ambulance
+b Bike blowing cloud
+c DX antenna
+d Fire dept. DX Antenna
+e Horse Sleet cloud
+f Fire Truck FC Cloud
+g glider Pennant (2)
+h Hospital HAM
+i Island Island
+j Jeep Jeep
+k Truck Truck
+l Small dot Small Dot
+m MIC Mile Post
+n N Small Triangle
+o EOC Dot with in Circles
+p Puppy Dot with in Circles
+q GS Antenna GS Antenna
+r Antenna Tower Antenna Tower
+s Boat Boat
+t TS ?
+u 18 Wheel Truck
+v Van Dot with in Circles
+w H20 Flood
+x X Windows Red Dot
+y House w/Yagi House w/yagi
+z X Windows
+{ FOG FOG
+| Black Line Black Line
+} TCP TCP
+~ Sail Boat Sail Boat
+
+HELP-INDEX>What was new in Xastir 1.0
+
+Over the past year, Xastir has been under active development, and this new
+release is the culmination of those efforts. Development has been run by
+Chuck Byam, who agreed to take over for Frank Giannandrea. Many other
+individuals have contributed to this project, and are listed in the AUTHORS
+file.
+
+The Xastir package now uses GNU autoconf to build makefiles and select
+features based on the libraries and software one has installed. No more
+editing makefiles as in previous releases!
+
+Starting Xastir 1.0, one probably won't immediately notice any major
+changes. The familiar interface of previous Xastir versions has been retained
+for the most part. The great majority of the changes are improvements in
+efficiency under the hood:
+* Startup time for the program has been improved.
+* Memory usage has greatly improved, with dynamic allocation of separate
+ station, trail, and weather data on an as-needed basis. No longer will
+ memory be wasted on stationary stations for trail data, nor will non-weather
+ stations waste memory for weather information. With these modifications,
+ Xastir can even be connected to the internet link comfortably on a 16MB
+ machine.
+* Improvements have been made to avoid having to reload maps from disk at every
+ minor change; Weather alerts and changes to the display and tracking options
+ no longer cause the maps to reload, rather the trails and symbols are
+ redrawn alone.
+* Improvements have been made to various dialog boxes that re-drew often, to
+ redraw less often, to allow them to be usable on slower systems. This is
+ also true of tracking a station, with the map redrawing only if the station
+ approaches the edge of the screen.
+Thanks to these changes, Xastir is perfectly usable on slower Pentium(tm)
+machines.
+
+Native GeoTIFF support is now included, and will be compiled into one's copy
+of Xastir if they have the GeoTIFF libraries installed on their system. These
+map files are of very high quality, and are especially useful in search and
+rescue operations. Maps on this format are available from the USGS, and
+commercially on CD-ROM. Xastir understands how to convert from the NAD-27
+datum to the new WGS-84 datum, so maps of both format can be read accurately.
+New shortcut buttons have been added to the map selection dialog to enable
+one to pick all maps of a specific type.
+
+Support for the Festival Speech Synthesis System is now available to announce
+new stations and band openings. The old system of alert sounds has been
+retained as well.
+
+Xastir now supports adding and deleting objects. Finally, Xastir users are able
+to manage resources with this useful feature. Objects are helpful for
+coordinating events, directing travelers, and doing search and rescue work.
+
+The County Warning Area maps that display weather alerts are no longer painted
+onto the maps below, but are shaded onto the maps. While this does make the
+colors unpredictable, it is now possible to see the road-maps below the
+alert!
+
+A new and useful feature is the change in the orientation of a symbol based on
+the direction in which it is moving. Even without a trail, a quick glance can
+tell you a mobile station's bearing. There are several more new options in the
+display menu, enabling one to decide more precisely what is displayed and what
+isn't.
+
+Panning and control over the map has been enhanced: There are now arrow buttons
+visible at the top of the screen to pan the map. The map can also be panned
+with the arrow keys, and the zoom can be adjusted with the page up and page
+down keys. There are new option in the click menu, to center the map where you
+clicked or to place an object where you clicked. The panning options in this
+menu have been removed in favor of the new controls at the top of the screen.
+
+Support for altnet has been added, enabling one to have a private APRS(tm)
+network for special events, search and rescue, storm chasing, or whenever else
+the user doesn't want to be bothered by the hundreds of APRS(tm) stations
+around.
+
+There are numerous small changes, both visible and invisible to the user. The
+interface control dialog now has a "Start all" and "Stop all" option, to save
+the user the time of performing these actions for each interface. The station
+setup dialog now shows you your symbol, so you don't have to exit the dialog to
+see which symbol you chose. Several buffer overflows that caused unpredictable
+behavior and/or crashes have been fixed. And many minor improvements have been
+made to the source code to ensure that it compiles correctly on various
+systems.
+
+Enjoy the new Xastir!
+
+
+HELP-INDEX>What was new in Xastir 1.1
+
+ What was new in Xastir 1.1
+
+This new release, Xastir 1.1, adds significant new features and enhancements
+to the user interface. Unlike 1.0, the interface changes will take some getting
+used to, but the flexibility and versatility of the enhanced interface will
+more than make up for the troubles.
+Among the improvements to the user interface:
+* Keyboard shortcuts for menus and dialogs, menu reorganization, and mouse
+ behavior changes.
+* The ability to move objects or measure distance with the mouse, using the
+ appropriate check-boxes in the toolbar.
+* A scale has been added to allow one to judge distance on a map.
+* Map labels for windows-style APRS(tm) maps are rotated to match the marked
+ map features.
+* The user interface for dealing with objects has been entirely redesigned.
+* Station info boxes can be set to automatically update.
+* Tear-off menus. Allow you to keep a menu on the screen and play with
+ different options. Tear off a menu by clicking on the dashed-line portion.
+
+Map support has been greatly enhanced, with PocketAPRS, ESRI Shapefiles, GNIS
+labels and many graphics formats with ImageMagick. Additionally, support for
+downloading graphical maps from web-servers has been added, allowing Xastir to
+use online radar, Tiger, and Terraserver maps.
+
+Xastir 1.1 supports much more of the APRS(tm) protocol than its predecessor:
+* It can add, modify, move and view area objects, signpost objects, and items.
+ These features are invaluable for event coordination and search and rescue
+ use. Objects and items are also periodically retransmitted.
+* Support for displaying position ambiguity squares, pre-calculated radio
+ ranges, Maidenhead grid squares, and weather objects. These features aren't
+ extremely common, but do come up occasionally.
+* Support for the APRS(tm) radio direction finding features. These features
+ are useful for anything from tracking jammers to locating lost hikers. Xastir
+ supports both Omni and Beam reports.
+
+Other notable improvements:
+* Xastir can now search for a specified location or landmark using GNIS data.
+* Track logs can now be exported to file.
+* Maps can be printed if certain tools and libraries are present.
+* Support for retrieving historical track data from findu.com.
+* Xastir now compiles and runs on Mac OS X, Solaris and FreeBSD with only
+ minimal changes; see README for details.
+* Several major bugs found in 1.0 have been corrected, including the problems
+ loading DOS maps and the problems with the weather reporting. Other minor
+ bugs and memory leaks have been fixed. And several more errors have been
+ corrected in the parsing routines, so Xastir should remain stable no matter
+ what is thrown at it!
+
+
+HELP-INDEX>What was new in Xastir 1.2
+
+ What was new in Xastir 1.2
+
+The latest Xastir release adds numerous new capabilities, keeping Xastir a
+benchmark for APRS(tm) programs on any operating system.
+
+Xastir's hardware support has been enhanced, with
+* Support for Serial KISS TNCs
+* Support for Serial TNCs with GPS on the AUX port
+* Support for using AGWPE as a TNC
+* Support for Dallas One-Wire weather station
+ (see http://melhuish.info/simon/projects/oww/)
+* Support for more weather stations via the wx200d daemon (WX-200/WM-918/
+ WMR-918/WMR-968)
+* Support for the different sized rain gauges of the Peet Brothers weather
+ stations.
+
+Additionally, several bugs in the weather reporting code were corrected, and
+support for setting the system clock based on the GPS was added.
+
+There have been many additions and improvements to the Xastir user interface:
+The most notable is the addition of dead-reckoning. This means that stations
+that are moving will continue to move on your screen in the direction and at
+the speed speed that they last reported. The estimated location can be shown
+with any combination of a ghosted icon, a dashed line from the last position,
+or an arc of expected possible distance and angle.
+
+Also very notable are the improvements to the Map Chooser. Maps can now be
+selected a directory at a time, or individually. And the new map properties
+dialog allows individual control of map layering, map color filling, and
+consideration for auto-maps. Additionally, with extent caching under the hood,
+auto-maps regains much of its formal usefulness even with many maps installed!
+
+Bulletins pop up on screen, and emergency beacons cause an alert with the
+locate station dialog on hand. These changes are helpful in emergencies and
+event coordination.
+
+Xastir can now be set to use one of several coordinate systems, including UTM,
+dd.ddddd, dd mm.mmm, and dd mm ss.s. This is helpful for coordinating with
+other groups using a different system.
+
+The online Tiger maps can now be enabled from the map menu, and options can
+be adjusted to request maps with just the data you want displayed.
+
+The stations menu has been reorganized, allowing more intuitive filtering of
+stations shown and of accompanying data.
+
+Other smaller interface changes include:
+* The density of the grid-lines can be adjusted with the +, =, and - keys.
+* Objects and item lists have been added to the view menu.
+* Station maidenhead grid squares are now shown in station info and the
+ coordinate calculator.
+* There is a check-box "Track me" to enable easily tracking your own station
+* The length of trails downloaded from findu.com can now be specified.
+* Xastir can now ID via voice IDs or Screen IDs, by editing the configuration
+ file. This is intended for configurations when the Xastir screen is seen
+ remotely via fast-scan TV.
+* Timestamps are written to log files every 30 seconds of operation, to keep a
+ record of when data was heard.
+* The status bar can display the course/distance to your station when
+ enabled in the file|configure menu.
+* Range scales are now shown opposite the map scale. This is an attempt to
+ standardize various APRS(tm) client approaches to zoom levels.
+
+New additions under-the-hood:
+* Tracked proximity alarms.
+* Export waypoints within proximity boundaries. Your GPS can show
+ you the locations of APRS(tm) stations as waypoints on the GPS map
+ screen.
+* Export trail as ESRI Shapefile. New feature if you have Shapelib
+ compiled in. Station Info->Store Track button also creates a
+ Shapefile map of the station's track now.
+
+The weather reporting features have been improved, with the addition of
+optional wind barbs to weather stations and decoding of storm wind radius data.
+Weather alert shading is now done with pixmap stipples showing the type of
+alert. Further information on an alert is available over the internet from
+the WXSVR by simply double-clicking the alert in the weather alerts list.
+Weather alerts now use the newer ESRI Shapefile-format maps.
+
+Xastir's map support has been improved with enhancements to the ESRI Shapefile
+code to handle point-type ESRI Shapefiles. Additionally, speed improvements
+have been made in the ImageMagick graphical map loading, and many
+color-correction features have been added. As mentioned above, the Map Chooser
+has been greatly improved, and weather alerts use ESRI Shapefile-format maps.
+
+Under the hood, Xastir has had several major improvements:
+
+The messaging system has been largely rewritten, and the annoying timed updates
+to dialogs no longer occur. The new messaging system allows multiple messages
+to be queued, and implements reply-ack's for speed. Xastir also attempts to
+specify a reasonable path for the message based on received messages. This
+improves speed and congestion control. The messaging GUI has been largely
+untouched, and remains high on the list of future improvements.
+
+The build process has been significantly improved; Xastir is now able to be
+built on numerous operating systems with few manual interventions.
+
+Xastir now supports GPSMan/gpsmanshp, allowing the importing of waypoints,
+tracks, and routes from several types of GPS receivers. This allows you to
+create ESRI Shapefile-format maps out of GPS data.
+
+Xastir now implements SmartBeaconing(tm), which greatly improves trail quality
+and reduces unneeded channel usage. See the "Configure SmartBeaconing" help
+topic.
+
+IGating support has also improved, with the ability to configure a specific RF
+path for IGated packets, and the addition of a 29 second anti-dupe queue to
+reduce unnecessary redundancy on the RF channel.
+
+Map extents and filenames are now cached, so maps will not be loaded from disk
+unless they are on screen. This is a major improvement for map types that did
+not specify this information. Additionally, auto-maps uses this information,
+making it usable even with many maps installed.
+
+Objects controlled by Xastir are now stored in a file, so a restart of Xastir
+will not cause them to be lost. Additionally, Xastir now supports the
+compressed format for objects and items, which can help reduce RF channel
+congestion. It also gives you better location accuracy of the placed objects.
+See the help topic "Configure Default Operation".
+
+Xastir now drops root privileges when not needed if run setuid root. Please
+read the information about this in INSTALL; this change provides only
+limited protection.
+
+Xastir now supports using a private colormap with the command-line argument
+"-i". This is recommended for systems running in 8-bit color mode.
+
+Additionally, several more buffer overruns and other errors were corrected in
+Xastir's data parser, and numerous other bugs have been fixed.
+
+Enjoy the new Xastir!
+
+HELP-INDEX>What's new in Xastir 1.3
+
+ What's new in Xastir 1.3
+
+This latest Xastir release greatly improves on the efficiency and usability of
+Xastir, and adds many helpful and often-requested new features.
+
+.geo files can now have REFRESH tags, to specify how often the file is
+reloaded. This is useful for weather radars and other dynamic images. .geo
+files can also have a TRANSPARENT tag to make a certain color transparent, and
+a CROP tag to specify a specific region to display.
+
+Some Opentrac packets are now decoded and displayed. See
+http://opentrac.org/ for more details.
+
+The default main Xastir directory is now /usr/local/share/xastir; please see
+the upgrade notes in README for migration information. This more closely
+mirrors the behavior of other applications. If you're installing
+from a binary package (rpm/deb/etc), the default install location
+may be /usr/share/xastir.
+
+Xastir efficiency has been greatly improved. Changes in data structures and
+timing values have made this Xastir release the most efficient yet.
+Additionally, map redraw sequences are interruptible, so map panning speed
+has been improved.
+
+dbfawk support - Experimental support for configurable shapefile metadata, in
+an awk-like language. See README.MAPS for more details; this must be turned
+on with a specific switch to the configure command.
+
+GDAL/OGR support - Experimental support for GDAL and loading of native Tiger
+data (.RT1 files). This is automatically enabled if the GDAL library is
+found.
+
+Support for UTM w/special zones and MGRS coordinate systems.
+
+Cad drawing mode allows one to draw regions on your screen using the center
+mouse button. This feature is not yet complete, but is functional.
+
+User interface changes:
+* Several of the menus have been reorganized to have a hierarchical design.
+* Additionally, a few colors have been modified for better visibility.
+* The map label font and style are more configurable
+* The cursor changes to let one know if they're in move object or measure mode.
+* If the coordinate system is set to UTM, and "Map Grid" is selected, an UTM
+ grid is displayed.
+
+Snapshot mode now generates a .geo file, allowing the image to later be used
+as a map.
+
+Tiger maps have been moved back the chooser, as was the pre-1.2 behavior.
+This is more consistent.
+
diff --git a/help/help-French.dat b/help/help-French.dat
new file mode 100644
index 0000000..4abb303
--- /dev/null
+++ b/help/help-French.dat
@@ -0,0 +1,593 @@
+HELP-INDEX>ME LIRE EN PREMIER - License
+
+ ME LIRE EN PREMIER pour XASTIR
+
+Traduction Francaise par F1SJE F1SJE at F1SJE.FRPA.FRA.EU
+Correction et derniers peaufinages F1IOL at F6KBF.FRPA.FRA.EU
+
+!!! NOTE: Ces documentations ne sont peut-�tre pas � jour ou incompl�tes
+
+Les plus r�centes informations sont dans le README.1ST dans le r�pertoire
+Xastir.
+
+Ce programme est destin� a �tre utilis� par des radio-amateurs DANS LE
+CADRE DE LEUR REGLEMENTATION NATIONALE.
+
+LICENSE :
+
+XASTIR, Amateur Station Tracking and Information Reporting
+Copyright (C) 1999 Frank Giannandrea
+Copyright (c) 2000-2012 The Xastir Group
+
+Ce programme est libre; vous pouvez le redistribuer et le modifier
+dans les conditions d�finies dans la "GNU General Public License"
+(version 2 ou sup�rieure) d�finie par la "Free Software Fondation".
+
+mais SANS AUCUNE GARANTIE. Voir la "GNU General Public License" pour
+plus de d�tails.
+
+Vous devriez avoir recu une copie de la "GNU General Public License"
+avec ce programme sinon �crivez � : the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Plus d'informations sur ce programme peuvent �tre trouv�e sur sa page Web :
+
+http://www.xastir.org
+http://sourceforge.net/projects/xastir/
+http://xastir.sourceforge.net
+
+Pour plus d'informations sur la License GNU regardez sur :
+http://www.gnu.org
+
+
+HELP-INDEX>Bienvenue! Et notes de l'auteur.
+
+ Bienvenue dans Xastir
+
+XASTIR, ou X-windows Amateur Station Tracking and Information Reporting.
+
+C'est un programme APRS(tm) dont les sources sont ouvertes et libres
+d'utilisation et de diffusion. Ce programme est en cours de d�veloppement
+et ne devrait pas �tre vu comme un produit fini. J'aurai besoin de votre
+aide pour le rendre plus fonctionnel. J'ai beaucoup d'id�es mais peu de
+temps alors si vous pensez pouvoir m'aider n'h�sitez pas et faite moi le
+savoir!
+
+73s
+Frank Giannandrea
+
+APRS[tm] est une marque d�pos�e de Bob Bruninga,
+Sa page d'accueil est "http://web.usna.navy.mil/~bruninga/aprs.html"
+
+HELP-INDEX>D�buter
+ D�buter
+
+Maintenant que Xastir fonctionne il faut le configurer !
+Le menu Configurer va vous permettre de param�trer votre station.
+La plupart de options par d�faut vous permettent d�j� de travailler.
+
+Le sous menu d�faut vous permet de s�lectionner les valeurs des
+diff�rents intervals de temps, les options de transmission et les
+fonctions du gateway internet.
+
+Le sous menu interfaces vous permet de param�trer vos p�riph�riques
+s�rie, AX25, GPS, Stations m�t�o, Connexions internet etc...
+Vous pouvez �galement modifier les param�tres de ces interfaces avec
+ce menu.
+
+Pour commencer le plus important est de configurer la station;
+indicatif, Latitude/Longitude (Si vous n'avez pas de GPS), incertitude
+quant � la position et autres informations.
+
+Alarmes sonores va configurer les sons en fonction des �v�nements.
+
+Mesure vous permettra de choisr entre syst�me m�trique ou mesures
+anglaises.
+
+NOTE : Dans les menus les options grises sont actives, quand vous
+s�lectionnez vous faites passer l'option en gris.
+
+HELP-INDEX>Configuration de la station
+
+ Configuration de la station
+
+Entrez votre indicatif/SSID.
+
+Le d�faut est NOCALL, si vous ne savez pas ce que ca veut dire peut-etre
+ne devriez vous pas utiliser ce programme.
+
+Ensuite entrez latitude et longitude en degr�s, minutes, centi�mes
+
+N pour Nord, S pour Sud, E pour Est et attention W pour Ouest (Ndt : allez
+on ne va pas modifier les sources pour ca hi ! )
+
+Maintenant entrez votre Groupe/Overlay et le symbole de votre station.
+Regardez le listing des tables pour choisir votre symbole.
+Par d�faut le symbole est x pour xwindows/Unix et le groupe est "/".
+Si vous voulez autre chose entrez la lettre ou le chiffre dans la
+fen�tre Groupe/Overlay et prenez un symbole dans le groupe "\".
+
+Ce n'est pas obligatoire mais si vous voulez entrez ensuite la puissance,
+la hauteur et le gain de votre antenne en vous aidant des tableaux ci-dessous :
+
+
+Chiffre a utiliser 0 1 2 3 4 5 6 7 8 9
+Puissance (en watts) 0 1 4 9 16 25 36 49 64 81
+
+Exemple : Entrez 6 pour 36 Watts
+
+Idem pour la hauteur, ce n'est pas la hauteur au dessus du sol
+mais la hauteur au dessus du niveau de la mer.
+
+Chiffre a utiliser 0 1 2 3 4 5 6 7 8 9
+Hauteur 10 20 40 80 160 320 640 1280 2560 5120
+
+Exemple : Entrez 7 pour 1280m
+
+Pour le gain mettez simplement le gain de votre antenne en dB.
+
+Ci dessous en degr�s par rapport au nord
+
+Chiffre a utiliser 0 1 2 3 4 5 6 7 8 9
+Direction (deg) 0 45 90 135 180 225 270 315 360 None
+
+Utilisez 0 pour une antenne omnidirectionnelle (Verticale)
+
+Entrez un commentaire, ce n'est pas exig� mais personnalisera votre station.
+
+L'incertitude quant � votre position vous permet de g�rer la pr�cision
+avec laquelle vous allez transmettre votre position.
+Avec aucune votre station transmettra la position exacte que vous avez
+entr�e ou recue par GPS sinon votre station sera vue quelque part dans
+les limites choisies.
+
+
+cliquez sur OK pour sauvegarder vos changements, cliquez sur annuler pour conserver
+les param�tres courants.
+
+HELP-INDEX>Comment utiliser mon GPS avec Xastir
+
+ Comment utiliser mon GPS avec Xastir
+
+Vous avez 3 solutions, un GPS en r�seau , un GPS sur port s�rie ou un GPS
+sur port s�rie avec TNC et c�ble HSP.
+L'int�r�t d'un GPS en r�seau est que vous pouvez le partager avec d'autres
+programmes. Xastir peut se connecter en r�seau sur un d�mon nomm� GPSD.
+Ce programme envoie des donn�es GPS standards sur le r�seau.
+Certaines versions autorisent une connexion GPS sur internet.
+Une fois install� sur votre machine (ou une autre en r�seau) vous pouvez
+y connnecter Xastir en cr�ant une interface.
+Cliquez sur Configurer/Interfaces
+Ajouter
+R�seau GPS (avec gpsd)
+Entrez le nom de la machine ou vous avez install� GPSD et le nom du port.
+Validez les 2 autres options selon ce que vous voulez.
+
+GPS s�rie :
+C'est un GPS s�rie standard connect� sur port s�rie qui doit transmettre
+ses donn�es au format NEMA. Proc�dez comme pour gpsd pour l'ajouter,
+mettez le port s�rie utilis�, en principe les param�tres par d�faut pour
+le port s�rie doivent fonctionner sinon ajustez les � l'aide de la doc de
+votre appareil.
+
+HSP TNC/GPS:
+ Regardez � "Comment utiliser mon TNC avec Xastir?"
+
+
+HELP-INDEX>Comment utiliser mon TNC avec Xastir?
+
+ Comment utiliser mon TNC avec Xastir?
+
+La encore vous avez trois solutions : Un TNC en r�seau (AX25), un TNC sur
+port s�rie et un TNC avec c�ble HSP et GPS.
+
+AX25 :
+
+C'est simplement un des ports du kernel AX25 de Linux, vous devez avoir
+les librairies AX25 d'install�es et le support AX25 dans le Kernel.
+
+TNC S�rie :
+
+TNC S�rie avec HSP et GPS :
+
+
+HELP-INDEX>Configurer les Defauts
+
+ Configurer les Defauts
+
+cliquez sur Configurer/Defaut.
+
+S�lectionnez l'intervalle de temps au del� duquel votre station sera
+consid�r�e comme vieille, 2 heures par default. Au bout de cet intervalle
+de temps l'icone de la station deviendra ombr�e ou transparente.
+
+
+Cliquez sur OK pour sauvegarder vos changements, Cliquez sur annuler pour conserver
+les param�tres courants.
+
+HELP-INDEX>Configurer le port GPS
+
+ Configurer le port GPS
+cliquez sur Configurer/Interfaces
+Ajouter
+S�rie GPS pour un GPS seul, vous utiliserez un port s�rie style ttyS1.
+
+Si vous avez un c�ble HSP qui vous permet de partager le port TNC avec
+un GPS vous devez s�lectionner S�rie TNC/GPS sur c�ble HSP.
+C'est un c�ble sp�cial qui ne fonctionne pas sur toutes combinaisons
+de machines/GPS/TNC.
+Attention aux param�tres de transmission, soyez sympas avec les autres
+utilisateurs de la fr�quence.
+Pour activer l'utilisation du GPS s�lectionner l'option autorisation de
+transmettre sinon vous transmettrez les donn�es que vous avez configur�es
+dans le sous menu station. Ces donn�es seront mises a jours automatiquement
+si vous utilisez un GPS.
+Quand vous utilisez GPS vous denenez une station mobile avec vitesse et
+direction m�me si vous ne bougez pas, les donn�es transmises changent. (Je
+changerai cela avec une option plus tard)
+Vous devrez s�lectionnez les intervalles de transmission directement
+avec le GPS, les options par defaut de votre station ne seront plus prises
+en compte. Si vous etes en fixe mettez 10 minutes, sinon choissisez les
+options selon vos besoins.
+
+Cliquez sur OK pour sauvegarder vos changements, Cliquez sur annuler pour conserver
+les param�tres courants.
+
+HELP-INDEX>Configurer le port TNC
+
+ Configurer le port TNC
+
+cliquez sur Configurer/Interface
+Ajouter
+Choisir votre TNC
+S�lectionnez activer au d�marrage et autorisation de transmettre
+selon vos besoins.
+Entrez le port et param�trez le.
+
+Entrez le chemin des UNPROTOS.
+Xastir par d�faut a d�j� le chemin VIA XX.
+Vous pouvez en ajouter 3 autres de mani�re a �tre bien entendu
+m�me dans de mauvaises conditions.
+En fonction des champs remplis Xastir commencera un cycle d'envoi vers
+ces destinations, l'une apr�s l'autre a chaque fois qu'il sera l'heure
+de transmettre.
+Si vous �tes en local sans digi mettez WIDE2-2, si vous etes QRP ou loin
+d'un digi WIDE1-1,WIDE2-2 fonctionnera mieux.
+Si vous �tes pr�s d'un digi vous pouvez mettre INDICATIF,WIDE2-2.
+La plupart d'entre vous n'avez besoin que d'un chemin mais si vous n'etes
+pas bien d�gag� mettez en plusieurs, demandez aux stations qui vous
+entourent.
+
+Cliquez sur OK pour sauvegarder vos changements, Cliquez sur annuler pour conserver
+les param�tres courants.
+
+HELP-INDEX>Configurer la connexion � Internet
+
+ Configurer la connexion � Internet
+
+Vous devez conna�tre un serveur et un n� de port, par defaut
+www.aprs.net port 10151. Un mot de passe valide autorisera votre
+station � transmettre par internet et � �tre retransmise sur l'air.
+Pour obtenir un mot de passe contacter Steve Dimse, K4HG � www.aprs.net
+en lui pr�cisant vos nom, indicatif etc etc... Apr�s v�rification il vous
+donnera votre code. Sans code par d'acc�s sur l'air mais vous �tes quand
+m�me forward� sur Internet.
+Validez reconnexion sur erreur r�seau pour une reconnexion automatique en
+cas de coupure.
+Dans Configurer/options vous avez la possiblit� de devenir un Gateway vous
+aussi. FAITES TRES ATTENTION � cette option, contactez Steve Dimse et veillez
+� rester en conformit� avec la r�glementation en vigueur.
+Dans interface/fichier journal vous avez une option pour enregistrer
+tous les �v�nements du Gateway.
+
+Cliquez sur OK pour sauvegarder vos changements, Cliquez sur annuler pour conserver
+les param�tres courants.
+
+APRS[tm] est une marque d�pos�e de Bob Bruninga,
+Sa page d'accueil est "http://web.usna.navy.mil/~bruninga/aprs.html"
+
+HELP-INDEX>Configurer alertes sonores
+
+ Configurer alertes sonores
+
+Bien �videment vous devez avoir une carte son ! il vous faudra aussi un
+programme qui joue les .wav, mettez le chemin complet dans la fen�tre
+commande audio.
+
+Choix disponibles :
+
+Nouvelle station
+
+Nouveau message
+
+Proximit�
+
+Ouverture de bande
+
+Distance Minimum
+
+Distance Maximum
+
+Alerte M�t�o
+
+HELP-INDEX>Configuration des Unit�s
+
+ Configuration des Unit�s
+
+Ceci selectionne le syst�me d'unit�s, par defaut m�trique. Sinon
+les mesures anglaises sont disponibles.
+
+HELP-INDEX>Ligne de status inf�rieure
+
+ Ligne de status inf�rieure
+
+En bas de la fen�tre vous pouvez voir diff�rents messages :
+
+1�re fenetre : messages g�n�raux.
+2�me fen�tre : Latitude/Longitude du pointeur sur la carte.
+3�me fen�tre : Nombre de stations dans la base de donn�e.
+4�me fen�tre : Niveau de Zoom et Tr si le suivi de station est actif.
+
+Les 2 derni�res fen�tres montrent le status du TNC et du r�seau.
+Un ">" pour des donn�es sortantes et un "<" pour des donn�es entrantes.
+
+
+HELP-INDEX>Mouvements de la carte (Zoom et N.S.E.W) et menu options
+
+ Mouvements de la carte (Zoom et N.S.E.W) et menu options
+
+Les mouvements de la carte sont tr�s simple, la facilit� et la rapidit�
+des mouvements d�pend de la vitesse du processeur et du niveau de d�tail
+des cartes charg�es.
+Il suffit de cliquer sur un point de carte pour voir s'ouvrir un menu
+qui permet de Zoomer sur ce point, voir + au nord, sud est ou ouest par
+rapport au centre de la carte; plus le zoom est petit plus le grossissement
+est grand.
+Le sous menu information sur la station vous donne les �l�ments de la station
+la plus proche du point ou vous avez cliqu�. S'il y a plusieurs stations non
+loin un choix vous sera propos�.
+
+HELP-INDEX>Menu Cartes et choix de cartes
+
+ Menu Cartes et choix de cartes
+
+Carte automatique Actif/Inactif
+Si actif toutes les cartes du sous r�pertoire "map" et toutes celle des
+r�pertoires dessous seront affich�es si elles correspondent � la r�gion
+sur laquelle vous travaillez. Ceci peut ralentir consid�rablement le syst�me
+si vous avez beaucoup de cartes et un ordinateur tr�s lent.
+Si inactif seules les cartes choisies dans cartes/choisir une carte seront
+affich�es.
+
+Quadrillage Actif/Inactif
+Active un quadrillage tous les 10�.
+
+Niveau Actif/Inactif
+Active le filtrage des petits d�tails quand le niveau de zoom montre une
+large surface, fonctionne seulement avec le cartes g�n�r�es avec "Tiger
+Line maps" (Site aprs.rutgers.edu).
+
+Choisir une carte
+Cliquez simplement sur les cartes que vous voulez afficher. Vous pouvez
+en prendre autant que vous voulez.
+cliquez sur OK pour afficher vos cartes, cliquez sur annuler pour conserver
+les param�tres courants.
+
+HELP-INDEX>Options Visualisation
+
+ Options Visualisation
+
+Ces options vous permettent d'afficher des donn�es autour des stations
+se trouvant sur la carte.
+
+Altitude Actif/Inactif
+Si actif une ligne bleue de donn�es aparait au dessus de l'indicatif,
+indiquant la derni�re altitude connue de la station.
+
+Route Actif/Inactif
+Si actif une ligne verte de donn�es aparait au dessous de l'indicatif,
+indiquant le dernier azimut connu de la station.
+
+Vitesse Actif/Inactif
+Si actif une ligne rouge de donn�es aparait au dessous de l'indicatif
+ou de la trajectoire indiquant la derni�re vitesse connue de la station.
+
+Distance/Orientation Actif/Inactif
+Si actif deux lignes de donn�es aparaissent � gauche de l'indicatif, la
+ligne du dessus indique la distance par rapport � votre station, celle
+du dessous l'azimut.
+
+Trajectoire des stations Actif/Inactif
+Si actif toutes les stations en mouvement traceront une ligne de couleur
+affichant les 100 derni�res positions. Quand la station devient vieille
+et que sont icones est transparente la trajectoire n'est plus en ligne
+continue.
+
+PHG Actif/Inactif
+Si actif on verra des cercles Puissance/Gain autour de la station.
+
+Suivre une station
+Ouvrira une fen�tre ou vous pourrez entrer un indicatif. cliquez sur
+suivre maintenant et l'affichage ira sur cette station et continuera
+de la suivre quand elle enverra d'autres donn�es.
+cliquez sur fin de suivi pour arr�ter.
+Cliquez sur Annuler pour quitter sans changement.
+
+Information M�t�o
+Si actif Les derni�res donn�es m�t�o seront affich�es (T�, Vitesse et
+direction du vent, rafales, humidit�)
+
+HELP-INDEX>Messages
+
+ Messages
+
+Composer un message et message de groupe
+C'est a peu pr�t la m�me chose. Composer un message enverra votre
+message � une unique station, inversement vous ne recevrez des
+messages que de cette station. Message de groupe enverra un message
+a un groupe de personnes et inversement vous recevrez tous les messages
+post�s dans ce groupe. Actuellement les messages de groupe ne
+fonctionnent pas tout � fait bien.
+Dans chacun de ces �crans il y a une fen�tre Message, une ligne Message,
+une fen�tre ident. de la station et quelques boutons.
+Entrez en premier l'indicatif de la station ou le groupe. Ceci fait vous
+recevrez d�j� tous les messages de la station ou du groupe; une fen�tre
+s'ouvrira s'il n'y en a pas d'ouverte. Vous pouvez maintenant entrer
+un message de 250 caract�res maxi sur la ligne message, cliquez sur
+transmettre maintenant pour l'envoyer. Le bouton restera gris j'usqu'a
+reception d'un accus� de r�ception. Les messages recus seront tri�s et
+s'afficheront dans la fen�tre message. En mode groupe vous verrez
+l'indicatif de l'exp�diteur suivi du message; les messages seront tri�s
+par indicatif. Quand vous avez termin� cliquez sur fermer.
+Le bouton nouvelle identit� vous permet de voir les anciens messages
+qu'une station a envoy�s; tapez son indicatif pour les afficher.
+Bien entendu ce bouton peut servir � changer la station avec qui vous
+parlez. Le bouton effacer tous les messages effacera tous les messages
+de la fen�tre en cours.
+
+Effacer tous les messages sortants
+Efface tous les messages non acquitt�s.
+
+R�ponse automatique
+Active ou d�sactive la r�ponse automatique.
+
+Message de r�ponse automatique
+Configure un message de r�ponse automatique.
+
+
+HELP-INDEX>Effacer toutes les stations
+
+ Effacer toutes les stations
+
+cliquez sur fichier/Effacer toutes les stations enlevera toutes
+les station de votre �cran et de la base de donn�es station.
+
+
+HELP-INDEX>Relire un fichier journal
+
+ Relire un fichier journal
+
+cliquez sur Fichier/ouvrir un fichier journal. Choisissez un
+fichier journal, votre station va se comporter comme si elle
+recevait en �mmettait de nouveau, simulant les �v�nements du
+fichier journal. Ca peut bien sur cr�er quelques messages d'alerte
+si par exemple vous avez eu une session message, votre station va
+renvoyer les messages � un fichier journal !
+
+HELP-INDEX>Localiser une Station
+
+ Localiser une Station
+
+Cliquer sur examiner/localiser une station, une fen�tre s'ouvre,
+entrez un indicatif ou une partie. Par d�faut Xastir cherchera
+la correspondance exacte (D'une station ou d'un objet). Case exact
+vous permettra de chercher sans prendre en compte la diff�rence
+majuscule/minuscule. Cliquez sur trouver maintenant centrera
+l'�cran sur la premi�re correspondance trouv�e.
+Cliquer sur annuler fermera la fen�tre.
+
+HELP-INDEX>Table des symboles
+
+ Table des symboles
+
+
+
+
+Symbole Groupe / Groupe \
+
+
+! Triangle w/! Triangle w/!
+" Rain Cloud Rain Cloud
+# Digi DIGI
+$ Phone Symbol $ Symbol
+% DX DX
+& GATE-HF GATE
+' Small Aircraft Aircraft Crash
+( Cloud Cloud
+) TBD
+* SNOW Flake SNOW Flake
++ Red Cross
+, Reverse L
+- House w/omni
+. Small x
+/ Red Dot
+0 0 in a box Circle
+1 1 in a box
+2 2 in a box
+3 3 in a box
+4 4 in a box
+5 5 in a box
+6 6 in a box
+7 7 in a box
+8 8 in a box
+9 9 in a box GAS
+: Fire ?
+; Tent Tent
+< Motorcycle Pennant
+= Train Engine
+> Car Car
+? POS Antenna ? in a box
+@ HURRICANE/STORM HURRICANE/STORM
+A First Aid Box
+B BBS Blowing Snow
+C Canoe
+D D in a circle
+E E in a circle Smoke Stack
+F F in a circle
+G Grid Square Antenna ?
+H Hotel/Bed
+I TCP/IP ?
+J J in a circle Lightening
+K School House
+L Light House Light House
+M Mac
+N NTS ?
+O Balloon
+P Police car Rx
+Q Circle with in Circles Circle with in Circles
+R RV Restaurant
+S Shuttle Satellite
+T Thunderstorm (cloud/bolt) Thunderstorm (cloud/bolt)
+U School Bus Sun
+V VOR TAC VOR TAC Symbol
+W National Weather Service NWS-Digi
+X Helicopter
+Y Sail Boat
+Z Windows
+[ Runner WC
+\ DF Triangle
+] Packet Mail Box
+^ Large Aircraft Large Aircraft
+_ Weather Station WS-Digi
+` Satellite Dish
+a Ambulance
+b Bike blowing cloud
+c DX antenna
+d Fire dept. DX Antenna
+e Horse Sleet cloud
+f Fire Truck FC Cloud
+g glider Pennant (2)
+h Hospital HAM
+i Island Island
+j Jeep Jeep
+k Truck Truck
+l Small dot Small Dot
+m MIC Mile Post
+n N Small Triangle
+o EOC Dot with in Circles
+p Puppy Dot with in Circles
+q GS Antenna GS Antenna
+r Antenna Tower Antenna Tower
+s Boat Boat
+t TS ?
+u 18 Wheel Truck
+v Van Dot with in Circles
+w H20 Flood
+x X Windows Red Dot
+y House w/Yagi House w/yagi
+z X Windows
+{ FOG FOG
+| Black Line Black Line
+} TCP TCP
+~ Sail Boat Sail Boat
+
diff --git a/help/help-German.dat b/help/help-German.dat
new file mode 100644
index 0000000..9e8b591
--- /dev/null
+++ b/help/help-German.dat
@@ -0,0 +1,1957 @@
+HELP-INDEX>Einf�hrende Worte / Lizenzbestimmungen
+
+ Einf�hrende Worte / Lizenzbestimmungen
+
+F�r die aktuellsten Informationen und genauere Installationshinweise
+lesen sie bitte die README Datei im Xastir Hauptverzeichnis. Beachten
+Sie auch die Dateien LICENCE und COPYING f�r weitere Informationen.
+
+Bitte denken sie daran, da� dieses Programm f�r den Einsatz im
+Amateurfunk bestimmt ist. In Deutschland mu� man im Besitz eines
+Funkzeugnises sein, um auf Amateurfunkfrequenzen senden zu d�rfen.
+Informationen zum Erwerb eines Funkzeugisses findet man beim
+Amateurfunkclub DARC http://www.darc.de. Auch in anderen L�ndern
+gelten �hnliche Bestimmungen, die zu beachten sind.
+
+Die Entwicklung der Software und die Dokumentation erfolgte zun�chst in
+Englisch, so da� im Zweifelsfall die englische Version aktueller sein
+k�nnte. Die vorliegende deutsche Hilfedatei wurde von DK7IN �bersetzt.
+Korrekturen und Anregungen bitte an xastir at dk7in.de
+
+
+LIZENZBESTIMMUNGEN f�r XASTIR:
+
+XASTIR steht unter der GNU Lizenz, im Folgenden der englische
+Wortlaut. Die Details der GNU-Lizenz finden sich in der Datei
+LICENCE.
+
+XASTIR, Amateur Station Tracking and Information Reporting
+Copyright (C) 1999,2000 Frank Giannandrea
+Copyright (C) 2000-2012 The Xastir Group
+
+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.
+
+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
+
+
+Weitere Informationen zum Programm findet man unter:
+ http://www.xastir.org
+ http://sourceforge.net/projects/xastir/
+ http://xastir.sourceforge.net
+
+Es gibt einige Mailinglisten zu XASTIR. Melden sie sich zu einer oder
+beiden unter http://www.xastir.org an, um die neuesten Diskussionen rund
+um XASTIR zu verfolgen.
+
+Weitere Informationen zur GNU Lizenz finden sich auf:
+ http://www.gnu.org
+
+Informationen �ber Freie Software in deutscher Sprache
+finden Sie bei der Free Software Foundation Europe
+ http://fsfeurope.org/index.de.html
+
+
+HELP-INDEX>Willkommen! und Anmerkungen der Autoren
+
+ Willkommen! und Anmerkungen der Autoren
+
+XASTIR (X-Window Amateur Station Tracking and Information Reporting)
+
+XASTIR ist ein APRS(tm)-Programm, das als Open Source frei benutzt und an
+andere weitergegeben werden darf. Das Programm befindet sich momentan im
+Entwicklungsstadium und sollte nicht als fertiges Produkt angesehen
+werden! Mit ihrer Mitarbeit kann dieses Programm besser werden. Wenn sie
+also Programmiererfahrung haben, oder Dokumentation schreiben k�nnen,
+k�nnen wir ihre Hilfe gebrauchen. Wir haben eine Menge Ideen aber nur
+begrenzte Zeit. Wenn sie also denken, einen Beitrag leisten zu k�nnen,
+lassen sie es uns wissen!
+
+
+APRS[tm] ist ein Warenzeichen von Bob Bruninga, seine Homepage ist
+"http://web.usna.navy.mil/~bruninga/aprs.html"
+Beachten Sie bitte, da� sehr viel Information zu APRS(tm) in
+der von Bob Bruninga geschriebenen Dokumentationen zu APRSdos
+enthalten ist. Eine weitere Informationsquelle ist die von
+http://www.tapr.org als PDF-Dokument erh�ltliche APRS Spezifikation.
+
+HELP-INDEX>Neuheiten in Xastir 1.2
+
+ Neuheiten in Xastir 1.2
+
+Die aktuellste Xastir Version hat wiederum einige neue F�higkeiten
+hinzubekommen, so da� Xastir ein Benchmark f�r APRS-Programme auf
+allen Betriebssystemen bleibt.
+
+Die Hardware-Unterst�tzung von Xastir wurde erweitert:
+ * Unterst�tzung f�r serielle KISS TNCs
+ * Unterst�tzung f�r serielle TNCs mit GPS an der AUX-Schnittstelle
+ * Unterst�tzung f�r den Einsatz von AGWPE als TNC
+ * Unterst�tzung f�r eine Dallas One-Wire Wetterstation
+ (siehe http://melhuish.info/simon/projects/oww/)
+ * Unterst�tzung f�r weitere Wetterstationen �ber den wx200d Daemon
+ (WX-200 / WM-918 / WMR-918 / WMR-968)
+ * Unterst�tzung f�r verschieden gro�e Regenmesser der Peet Brothers
+ Wetterstationen.
+
+Weiterhin wurden einige Fehler Im Kode der Wetterberichte korrigiert,
+auch l��t sich nun die Systemzeit �ber einen angeschlossenen
+GPS-Empf�nger stellen.
+
+Es gab viele Erg�nzungen und Verbesserungen in der Xastir Benutzer-
+Schnittstelle:
+Die bemerkenswerteste ist die Positionsvoraussage. Dies bedeutet, da� sich
+alle beweglichen Stationen nach dem letzten Empfang auf dem Bildschirm
+weiterbewegt werden, so als w�rden sie sich weiterhin mit der letzten
+Geschwindigkeit in die zuletzt berichtete Richtung bewegen. Die so
+vorausgesagte Position kann mit einer Kombination aus einem schemenhaften
+Symbol, einer gestrichelten Linie von der letzten gesicherten Position und
+einem Kreissegment des erwarteten Bereichs von Entfernung und Richtung
+angegeben werden.
+
+Bemerkenswert ist auch die Verbesserung der Kartenauswahl. Neben der
+individuellen Auswahl einzelner Karten k�nnen nun auch ganze
+Kartenverzeichnisse auf einmal ausgew�hlt werden. Unter "Eigenschaften"
+bei der Kartenauswahl, kann den einzelnen Karten nun eine individuelle
+Ebene zugewiesen werden, um die Reihenfolge der Darstellung zu beeinflussen.
+Ebenso wird dort festgelegt, ob Karten mit Farbe gef�llt werden sollen, oder
+ob sie bei "automatischen Karten" ber�cksichtigt werden sollen.
+Dank erweiterem Caching im Hintergrund erlangen automatische Karten wieder
+ihre Bedeutung, und das auch bei vielen installierten Karten!
+
+Bekanntmachungen erscheinen auf dem Schirm und Notfall-Baken ergeben eine
+Warnung, die gleich die Sucheingabe f�r diese Station mitbringt. Diese
+�nderungen sind hilfreich bei der Koordination von Notf�llen oder Ereignissen.
+
+Xastir kann nun f�r verschiedene Koordinatensystemen eingerichtet werden,
+darunter UTM, dd.ddddd, dd mm.mmm, und dd mm ss.s. Dies ist hilfreich bei
+der Koordination mit anderen Gruppen, die ein abweichendes System benutzen.
+
+Die online Tigermaps k�nnen nun aus dem Kartenmenu heraus eingeschaltet
+und die anzuzeigenden Daten individuell angepa�t werden.
+
+Das Stationen-Menu wurde reorganisiert, um so eine intuitive Filterung der
+darzustellenden Stationen und der dann anzuzeigenden Daten zu erlauben.
+
+Andere kleinere �nderungen beinhalten:
+ * Die Dichte der Gitterlinien kann mit den '+', '=' und '-'-Tasten
+ ge�ndert werden.
+ * Objekte und Items wurden zum Menu "Zeige" hinzugef�gt.
+ * Der Maidenhead Locator wird nun in der Stationsinfo und im
+ Koordinatenrechner angezeigt.
+ * Es gibt einen Schalter "Verfolge mich", um die eigene Station auf
+ einfache Weise immer auf dem Bildschirm zu sehen.
+ * Die L�nge und der Startzeitpunkt der von findu.com herunterzuladenden
+ Spuren k�nnen nun eingestellt werden.
+ * Xastir can now ID via voice ID's or Screen ID's, by editing the
+ configuration file. This is intended for configurations when the Xastir
+ screen is seen remotely via fast-scan TV.
+ * Zeitstempel werden alle 30 Sekunden in die Protokolldateien geschrieben,
+ um so besser informiert zu sein, wann eine Station geh�rt wurde.
+ * Die Statuszeile kann nun auch die Entfernung und Richtung zur eigenen
+ Station anzeigen, wenn dies im "Datei - Einstellungen" Menu aktiviert
+ wurde.
+ * Eine Bereichsskala erg�nzt nun die L�ngenskala. Dies ist ein Versuch,
+ den Ansatz bez�glich der Zoom-Stufen bei verschiedenen APRS-Programmen
+ zu standardisieren.
+
+Die M�glichkeiten von Wetterberichten wurden verbessert, mit dem
+Hinzuf�gen einer optionalen Windfahne bei Wetterstationen und der
+Dekodierung des Radius von Sturmwinden. Die Markierung von gebieten mit
+Wetterwarnungen wird nun mit Mustern vorgenommen, die die Art der Warnung
+zeigen. Weitere Informationen zu einer Warnung stehen �ber das Internet
+vom Wetterserver zur Verf�gung und werden durch Doppelklicken auf die
+Warnung in der Wetterwarnungsliste angezeigt. Wetterwarnungne benutzen
+nun Karten mit dem neueren ESRI Shapefile-Format.
+
+Xastir's kartenunterst�tzung wurde verbessert mit Erweiterungen des ESRI
+Shapefile Kodes um Punkt-Typ ESRI Shapefiles handhaben zu k�nnen. Zus�tzlich
+wurden Geschwindigkeitsverbesserungen beim Laden von Kartengrafiken mit
+ImageMagick erzielt und etliche Farbkorreturm�glichkeiten hinzugef�gt.
+Wie oben erw�hnt, wurde die Kartenauswahl deutlich verbessert und Wetterkarten
+benutzen Karten im ESRI Shapefile-Format.
+
+Im Hintergrund hat Xastir einige wichtige Verbesserungen erfahren:
+
+Das Nachrichtensystem wurde gr��tenteils umgeschrieben und die nervenden
+zeitgesteuerten Updates im Nachrichtenfesnter erscheinen nicht mehr.
+Das neue Nachrichtensystem erlaubt es, mehrere Nachrichten in einer
+Warteschlange zu halten und verwendet Reply-ACK's f�r mehr Geschwindigkeit.
+Xastir versucht auch einen vern�nftigen Pfad aufgrund einer empfangenen
+Nachricht vorzugeben. Dies erh�ht die Geschwindigkeit und vermeidet die
+�berflutung von Digipeatern.
+
+Der Build-Proze� wurde signifikant verbessert. Xastir kann nun auf vielen
+Betriebssystemen �bersetzt werden, wobei nur wenige manuelle Eingriffe n�tig
+sind.
+
+Xastir unterst�tzt nun GPSMan/gpsmanshp, um so Wegpunkte, Tracklogs und
+Routen von verschiedenen Arten von GPS-Empf�ngern zu importieren. Hiermit
+k�nnen auch Karten im ESRI Shapefile-Format aus GPS-Daten erzeugt werden.
+
+Xastir hat nun SmartBeaconing(tm) implementiert, das die Spurqualit�t
+deutlich erh�ht und unn�tige Kanalbelegung vermeidet. Siehe hierzu die Hilfe
+"Einstellungen - Smart Beaconing".
+
+Die Unterst�tzung f�r Internet-Gateways wurde verbessert, mit der M�glichkeit
+f�r weitergereichte Pakete einen speziellen Pfad zu definieren, sowie einer
+29 Sekunden Warteschlange zur Aussonderung von Doppeln, um so die unn�tige
+Redundanz auf dem Funkkanal zu reduzieren.
+
+Kartenbereiche und Dateinamen werden nun gecached, so da� Karten nur von der
+Festplatte geladen werden m�ssen, wenn sie auf dem Schirm darstellbar sind.
+Dies ist eine wichtige Verbesserungen f�r Karten, die diese Information nicht
+angeben. Zus�tzlich wird diese Information von "automatischen Karten"
+verwendet, wodurch dies auch bei vielen installierten Karten noch verwendbar
+ist.
+
+Von Xastir kontrollierte Objekte werden nun in einer Datei gespeichert, so
+da� sie bei einem Neustart von Xastir nicht verloren gehen. Au�erdem
+unterst�tzt Xastir nun das komprimierte Format bei Objekten und Items, was
+dabei helfen kann, die �berf�llung von Funkkan�len zu reduzieren. Dies
+f�hrt auch zu einer h�heren Genauigkeit der platzierten Objekte. Siehe
+hierzu "Datei - Einstellungen - Grundeinstellungen".
+
+Xastir gibt nun root-Privilegien auf, wenn sie nicht ben�tigt werden, wenn
+es mittels setuid gestartet wird. Bitte lesen Sie die Informationen hierzu
+in der datei INSTALL. Diese �nderung bietet einen eingeschr�nkten Schutz.
+
+Xastir unterst�tzt nun die Benutzung einer eigenen Farbtabelle mit dem
+Kommandozeilenparameter "-i". Dies wird empfohlen f�r Systeme, die im
+8-Bit Farbmodus laufen.
+
+Zudem wurden einige weitere Puffer�berl�ufe und andere Fehler im Datenparser
+von Xastir korrigiert und viele ander Fehler wurden beseitigt.
+
+Erfreuen Sie sich am neuen Xastir !
+
+
+HELP-INDEX>Der erste Aufruf von Xastir
+
+ Der erste Aufruf von Xastir
+
+Beim ersten Start von Xastir sollten sie das Programm aus einem
+Terminalfenster heraus aufrufen, um m�gliche Fehlermeldungen sehen zu
+k�nnen. Da auf den meisten Systemen der Pfad so eingerichtet ist, da�
+Programme in /usr/local/bin gefunden werden, reicht es am Prompt
+"xastir &" einzugeben. Auf anderen Systemen mu� "/usr/local/bin/xastir &"
+eingegeben werden, um das Programm zu starten. Das '&' sorgt daf�r, da�
+Xastir im Hintergrund gestartet wir, so da� das Terminalfenster noch
+anderweitig verwendet werden kann.
+
+Sie k�nnen beim Aufruf auch gleich die Sprache w�hlen. Um die Sprache zu
+�ndern, rufen sie Xastir mit der Option -l auf:
+
+ xastir -lGerman
+
+Weitere M�glichkeiten sind:
+ xastir -l Dutch
+ xastir -l English
+ xastir -l French
+ xastir -l Italian
+ xastir -l Spanish
+ xastir -l ElmerFudd
+ xastir -l MuppetsSwedishChef
+ xastir -l OldeEnglish
+ xastir -l PigLatin
+ xastir -l PirateEnglish
+
+Die so gew�hlte Sprache wird in der Konfigurationsdatei des Benutzers
+gespeichert und auch beim n�chsten Aufruf ohne diese Option verwendet.
+Bei einem neu installierten Xastir ist die Voreinstellung Englisch
+bis zu einer �nderung mit dieser Option.
+
+Die Menus am oberen Rand k�nnen auch mit Tastenk�rzeln erreicht werden.
+Diese funktionieren gegebenenfalls nicht, wenn NumLock eingeschaltet ist.
+
+Vor der Benutzung mu� Xastir und einige Schnittstellen konfiguriert
+werden. Die Schnittstellenkonfiguration ist detailliert in der Hilfe
+unter "Schnittstellen" beschrieben.
+
+HELP-INDEX>Stationsdaten
+
+ Stationsdaten
+
+Klicken sie auf Datei, Einstellungen, dann auf Meine Stationsdaten
+
+Tragen sie ihr Amateurfunk-Rufzeichen ein.
+
+Tragen sie die Position ihrer Station ein, wenn sie Xastir nicht
+zusammen mit einem GPS-Empf�nger einsetzen. Sie k�nnen ihre ungef�hre
+Position auch mit einer Karte in Xastir bestimmen indem sie die Maus
+auf der Karte plazieren und die Position in der Statuszeile ablesen.
+Wenn sie einen GPS-Empf�nger haben k�nnen sie diesen Schritt
+�berspringen und stattdessen sp�ter den GPS-Empf�nger einrichten.
+
+W�hlen sie ein Symbol f�r ihre Station, hierzu ist die Angabe der
+Gruppe und des eigentlichen Symbolzeichens erforderlich. Sie k�nnen
+dies manuell eintragen, oder nach Dr�cken auf Auswahl aus einer
+grafischen Symbol�bersicht ausw�hlen. Es stehen zwei Gruppen von
+Symbolen zur Verf�gung. Eine Beschreibung der Symbolbedeutung findet
+sich im Hilfetext "Symboltabelle".
+
+F�r einige Symbole der sekund�ren Gruppe kann auch ein Overlay
+spezifiziert werden. Hierbei wird das Symbol zusammen mit dem
+Overlay-Zeichen dargestellt, z.B. ein Autosymbol mit der Zahl 1.
+
+Um Overlays zu nutzen m�ssen sie ein Symbol der sekund�ren Gruppe w�hlen
+und das gew�nschte �berlagerungszeichen in das Feld Gruppe/Overlay
+eintragen. Nur Zahlen und Gro�buchstaben sind als Overlay zul�ssig.
+Nach den APRS-Spezifikationen kann nicht jedes Symbol �berlagert werden,
+aber Xastir erzwingt dies nicht, wie m�glicherweise andere Programme.
+Beachten sie, da� bisher auch nicht alle Symbole belegt sind und manche
+eventuell nicht ganz den APRS-Spezifikationen entsprechen.
+
+Tragen sie als n�chstes die Daten f�r Leistung, H�he, Gewinn und
+Vorzugsrichtung f�r ihre Station ein. Es ist eine sinnvolle Information
+wird aber nicht unbedingt ben�tigt. W�hlen sie einfach "Kein PHG", wenn
+sie diese Daten nicht aussenden wollen. Diese Einstellungen geben eine
+grobe Vorstellung von der Reichweite ihrer Station. W�hlen sie die Werte,
+die den ihren am n�chsten kommen.
+
+Eine andere M�glichkeit w�re es, stattdessen die Reichweite RNG in
+Meilen im Kommentar zu spezifizieren. F�r Details ziehen sie bitte
+die APRS-Spezifikationen zu Rate.
+
+Benutzen sie hier bitte die nicht die H�he �ber dem Boden oder
+Meeresh�he, sondern die H�he gegen�ber dem durchschnittlichen Gel�nde.
+Die Angabe ist in Fu�, Meter m�ssen mit 3,28 multipliziert werden.
+
+Als Gewinn tragen sie den Antennengewinn in dBi ein.
+
+Anmerkung: Die Angabe des Gewinns ist prim�r f�r Vertikalantennen
+gedacht, f�r Beams sollten kleinere Werte eingetragen werden. Die Grund
+hierf�r ist, da� bei gesetzter Vorzugsrichtung, die Ellipse f�r die
+Reichweite nur um ein Drittel in die angegebene Richtung vergr��ert wird.
+Wird der Gewinn eines Beams gr��er angegeben, so wird nur die
+Reichweitenmarkierung unrealistisch gro�, statt da� die deren
+Richtwirkung erh�ht w�rde.
+
+Bei der Angabe einer Vorzugsrichtung ihrer Antenne w�ren z.B. 90� eine
+Antenne, die nach Osten weist.
+
+Geben sie einen Kommentar ein, dies ist nicht notwendig, erlaubt aber
+die �bermittlung sinnvoller Informationen, wie z.B. den Namen und die
+E-Mail-Adresse. Es wird zusammen mit den Positionsmeldungen �bertragen.
+
+Die Positionsverschleierung erlaubt ihnen einszustellen, wie genau ihre
+Position �bermittelt wird. Bei "Keine" werden die exakten eingetragenen
+oder vom GPS empfangenen Daten ausgesendet. Die anderen M�glichkeiten
+setzen die �bermittelte Position irgendwo in den gew�hlten Bereich.
+Einige Stationen, die nicht ganz den Spezifikationen entsprechen,
+verstehen jedoch keine Positionsverschleierung, so z.B. auch findu.com.
+
+Bei einem Klick auf OK werden die �nderungen gesichert, bei Abbrechen
+bleiben die vorherigen Einstellungen erhalten.
+
+HELP-INDEX>Grundeinstellungen
+
+ Grundeinstellungen
+
+Klicken sie auf Datei, Einstellungen, dann auf Grundeinstellungen
+
+Auf dieser Seite werden einige Standardwerte f�r den Programmablauf
+eingestellt. Alte Stationen werden nach einiger Zeit schemenhaft
+dargestellt und die zugeh�rigen Spuren gestrichelt.
+
+In der ersten Zeile wird festgelegt, nach welcher Zeit eine Station nur
+noch schemenhaft angezeigt wird. In der n�chsten Zeile wird festgelegt,
+nach welcher Zeit eine Station ganz vom Bildschirm verschwindet. Nach
+dem Doppelten dieser Zeit wird die Station dann auch aus den internen
+Datenbanken gel�scht.
+
+Die dritte Zeile legt fest, in welchen Abst�nden die eigene Position
+�bermittelt wird. F�r Feststationen sind 30 Minuten ein guter Wert, es
+sollten auf alle F�lle nicht unter 10 Minuten sein. Bei Mobilstationen
+kann ein k�rzeres Intervall sinnvoll sein. Diese Einstellung wird auch
+verwendet, um Objekte und Items wiederholt zu senden. Versuchen sie hier
+eine sinnvolle Einstellung zu finden, um nicht zu viel unn�tigen Verkehr
+zu produzieren.
+
+GPS Zeit legt das Zeitintervall fest, nach dem nach neuen GPS Daten
+geschaut wird. Diese Option ist f�r Stationen mit gemeinsamen Zugriff
+auf TNC und GPS �ber ein HSP-Kabel.
+
+Mit dem Sendeformat der Station wird festgelegt, welche Art von Paketen
+die Station sendet.
+
+IGate Options erm�glicht die Errichtung einer Br�cke zwischen Internet
+und Funk. Diese Option sollte mit Vorsicht benutzt werden. Als
+Fumkamateur sind sie selbst daf�r verantwortlich, was aus dem Internet
+kommt und �ber ihre Funkanlage ausgesendet wird. Sie m�ssen au�erdem bei
+jeder Schnittstelle eine IGate-Einstellung machen, damit dies
+funktioniert. Wenn sie wollen, da� ihr IGate NWS Wetterwarnungen �ber
+Funk weitergibt, m�ssen sie eine Datei ~/.xastir/data/nws-stations.txt
+anlegen, in der alle Stationen aufgef�hrt sind (wie z.B. "PHISVR"),
+deren Daten sie �ber Funk weiterreichen wollen.
+
+Bei Aktivierung von "Sende komprimierte Position" wird die Position in
+einem neueren, komprimierten Format gesendet. Hierdurch werden die
+gesendeten Pakete k�rzer, so da� die Kapazit�t des APRS(tm) Netzwerks
+steigt. Die maximale Aufl�sung der gesendeten Position ist ebenfalls
+h�her. Allerdings k�nnen einige �ltere Programme, einschlie�lich
+k�rzlich erschienener Versionen von WinAPRS, dieses Format noch nicht
+dekodieren. Auch findu.com kann damit Probleme haben.
+
+Wenn "Sende Wetter Rohdaten" gew�hlt wurde, werden auch Pakete gesendet,
+die unverarbeitete Wetterstationsdaten enthalten. Dies ist n�tzlich f�r
+Wetterstationen mit ASCII-Daten, wie Peet Bros. Wetterstationen.
+
+Sie k�nnen au�erdem Alternatives Netz aktivieren, und dort ein eigenes
+K�rzel eintragen. Alternatives Netz erlaubt ihnen damit, ein privates
+APRS-Netzwerk aufzubauen, mit Stationen, die ebenfalls Alternatives
+Netz aktiviert haben und das gleiche Rufzeichen benutzen.
+
+HELP-INDEX>Audio Alarm
+
+ Audio Alarm
+
+Klicken sie auf Datei, Einstellungen, dann Audio Alarm.
+
+Um diese Option zu nutzen, ben�tigen sie eine Soundkarte und ein
+Programm, das Audiodateien im WAV-Format abspielt. Tragen sie als
+Kommando dieses Programm ein und eventuell ben�tigte Kommandozeilen-
+parameter. Das ganze funktioniert nat�rlich nicht, wenn die einzige
+Soundkarte im System f�r ein Soundmodem benutzt wird...
+
+F�r verschiedene Ereignisse kann eine Datei eingetragen werden, z.B. eine
+wav-Datei, die abgespielt werden soll. Bei einigen Ereignissen k�nnen
+zus�tzliche Parameter ge�ndert werden. F�r jedes Ereignis kann einzeln
+festgelegt werden, ob eine akustische Meldung erfolgen soll.
+
+Momentan steht zur Verf�gung:
+Abspielen einer Ansage beim Auftauchen einer neuen Station
+Abspielen einer Ansage bei einer neuen Nachricht
+Abspielen einer Ansage, wenn Daten von einer Station empfangen
+ werden, die sich innerhalb einer min/max Entfernung gem�� den
+ Ann�herungs-Einstellungen befindet
+Abspielen einer Ansage, wenn Daten von einer Station �ber TNC
+ empfangen werden, die sich innerhalb einer min/max Entfernung
+ gem�� den Band�ffnungs-Einstellungen befindet
+Abspielen einer Ansage bei einer Wetterwarnung
+
+
+HELP-INDEX>Sprachausgabe
+
+ Sprachausgabe
+
+Klicken sie auf Datei, Einstellungen, dann Sprachausgabe.
+
+Um diese Option zu nutzen, ben�tigen sie neben einer Soundkarte die
+'Festival' Sprachsynthese Software. Installieren sie Festival und starten
+sie es als Server bevor sie Xastir aufrufen. Das Kommando hierf�r hei�t
+�blicherweise "festival --server &".
+
+Nachdem Festival installiert ist, kann Xastir f�r folgende F�lle eine
+Sprachausgabe vornehmen:
+
+o Ansagen des Rufzeichens einer neuen Station.
+
+o Ansagen, da� eine neue Nachricht eingetroffen ist.
+
+o Den Text einer Nachricht vorlesen.
+
+o Eine Ansage, wenn Daten von einer Station empfangen wurden, die sich
+ innerhalb einer min/max Entfernung gem�� den
+ Ann�herungs-Einstellungen (siehe Audio Alarm) befindet.
+
+o Eine Ansage, wenn Daten von einer Station �ber TNC empfangen werden,
+ die sich innerhalb einer min/max Entfernung
+ gem�� den Band�ffnungs-Einstellungen (siehe Audio Alarm) befindet.
+
+o Die Ansage einer Wetterwarnung ist bisher noch nicht verf�gbar.
+
+Informationen zu Festival erhalten sie �ber:
+ http://www.speech.cs.cmu.edu/festival/
+
+HELP-INDEX>Ma�einheiten
+
+ Ma�einheiten
+
+Als Standardeinstellung wird das metrische System mit mm, cm, m, km,
+km/h, usw. verwendet. Wenn sie englische Ma�einheiten bevorzugen,
+klicken sie auf Datei, Einstellungen und aktivieren sie Englische Ma�e,
+um Zoll, Fu�, mph, usw. anzuzeigen.
+
+HELP-INDEX>Einstellungen sichern
+
+ Einstellungen sichern
+
+�ber Datei, Einstellungen, Einstellungen sichern k�nnen alle
+vorgenommenen Einstellungen sofort in der Konfigurationsdatei gespeichert
+werden. Aber auch beim Verlassen des Programms werden die Einstellungen
+gespeichert.
+
+HELP-INDEX>Statuszeile
+
+ Statuszeile
+
+Am unteren Rand des Bildschirms werden verschiedene Statusmeldungen
+dargestellt:
+
+Im ersten Feld (links) werden allgemeine Statusmeldungen angezeigt, sie
+werden nach kurzer Zeit wieder gel�scht.
+
+Das zweite Feld zeigt bei Mausbewegungen die aktuelle Position auf der
+Karte unter dem Mauszeiger an.
+
+Ein drittes Feld zeigt die Anzahl der insgesamt empfangenen Stationen in
+der Datenbank an.
+
+Das vierte Feld zeigt den aktuellen Zoomstatus an und ein "Tr", wenn eine
+Station verfolgt wird (Tracking).
+
+Das letzte Feld zeigt mit Symbolen den Status f�r jedes Ger�t an, wobei
+die Schnittstellen von links nach rechts (0 bis 9) gez�hlt werden. Der
+Status wird vertikal in drei Bereiche unterteilt. Oben Art des Ger�ts,
+in der Mitte der Datenflu� und unten der Betriebszustand.
+
+Die Art des Ger�ts kann anhand der Farbe unterschieden werden. Blau steht
+f�r die verschiedenen TNC Ger�te, gr�n sind GPS-Empf�nger, gelb Internet
+Server und orange Wetterstationen.
+
+In der Mitte zeigt ein links weisender Pfeil empfangene Daten an, ein
+rechtsweisender Pfeil steht f�r �ber dieses Ger�t gesendete Daten.
+
+Ein gr�nes Rechteck im unteren Bereich zeigt, da� diese Schnittstelle
+aktiviert ist. Ein rotes Rechteck deutet auf eine aktive Schnittstelle
+hin, bei der aber ein Fehler aufgetreten ist. Anderenfalls wird nichts
+angezeigt, wenn die Schnittstelle nicht aktiv ist.
+
+HELP-INDEX>Verschieben der Karte und Mauszeiger-Menu
+
+ Verschieben der Karte und Mauszeiger-Menu
+
+Das Verschieben der Karte ist sehr einfach, die Geschwindigkeit des
+Bildaufbaus h�ngt jedoch von der Rechnerleistung und dem Umfang der zu
+ladenden Kartendaten ab.
+
+Zoomen:
+Man kann in der Karte zoomen, indem man auf der Karte mit der rechten
+Maustaste klickt (und diese gedr�ckt h�lt). Es erscheint ein PopUp-Menu,
+mit der M�glichkeit, hinein oder heraus zu zoomen, oder auf eine der
+vordefinierten Skalierungsfaktoren zu wechseln.
+
+Die Zoom-Funktionen zentrieren die Karte gleichzeitig an dem Punkt, an
+dem die rechte Maustaste gedr�ckt wurde. Bei "Zoomebenen" erh�lt man ein
+Untermenu. Die Skalierungen 1-64 sind f�r die n�here Umgebung, w�hrend
+256 und h�her gr��ere Bereiche darstellen. Je kleiner die Zahl, umso
+lokaler wird der Kartenausschnitt.
+
+Ein schnelleres Hineinzoomen in einen Kartenausschnitt kann mit der Maus
+erreicht werden, wenn man auf mit der linken Maustaste auf eine Ecke des
+gew�nschten Ausschnitts klickt, bei gedr�ckter Maustaste zur
+gegen�berliegeden Ecke f�hrt und dort die Taste losl��t. Die Karte wird
+in der Mitte des gew�hlten Ausschnitts neu zentriert, f�r die Skalierung
+wird nur die H�he des Ausschnitts verwendet, die Breite wird der
+Bildschirmgr��e entsprechend angepa�t. Die Schaltkn�pfe "Messen" und
+"Bewegen" d�rfen hierf�r nicht aktiviert sein.
+
+Weiterhin besteht die M�glichkeit die PgUp und PgDn Tasten zum Zoomen zu
+verwenden. Hierbei bleibt das Zentrum er Karte erhalten.
+
+Verschieben/Zentrieren:
+Die Karte kann bei gleicher Aufl�sung neu zentriert werden, indem man
+mit der linken Maustaste auf das neue Zentrum klickt. Beim Klicken mit
+der mittleren Maustaste wird die Karte neu zentriert, au�erdem wird die
+Aufl�sung durch Herauszoomen auf die H�lfte reduziert.
+
+Ein Verschieben kann �ber das Mauszeiger-Menu oder durch die Pfeile am
+oberen Bildschirmrand erfolgen. Die Karte wird nur um einen Teil der
+Bildschirmgr��e verschoben, so da� gen�gend Daten bestehen bleiben, um
+sich wieder zurechtzufinden. Auch die Cursortasten verschieben die Karte.
+
+Informationen zum Mauszeiger-Menu:
+"Stationsinfo" versucht zun�chst die Station zu finden, die der Stelle,
+an der die rechte Maustaste gedr�ckt wurde, am n�chsten liegt. Befinden
+sich dort mehrere Stationen, so kommt zun�chst ein PopUp-Fenster mit
+einer Stationsliste, aus der man die gew�nschte w�hlen kann. Danach, oder
+wenn nur eine Station direkt in unmittelbarer N�he ist, �ffnet ein
+Fenster mit verschiedenen Daten zu dieser Station. Bei Mobilstationen mit
+vielen Daten kann dies auf langsamen Computern etwas Zeit ben�tigen. Um
+alte Stationen zu sehen, kann vor�bergehend "Alte Daten zeigen" im Menu
+"Ansicht" eingeschaltet werden.
+
+�ber den Menupunkt "Letzte Ansicht" kann der vorherigen Kartenausschnitt
+wieder hergestellt werden.
+
+F�r Informationen zu Objekten siehe den Hilfetext "Objekte und Items"
+
+HELP-INDEX>Objekte und Items
+
+ Objekte und Items
+
+Eine Station kann verschiedene Objekte auf der Karte setzen, deren
+Position auch �ber Funk an andere Stationen weitergegeben wird. Bei den
+Namen f�r Objekte bestehen nicht so viele Einschr�nkungen wie f�r die
+Stationsnamen.
+
+Objekte und Items sind ziemlich das gleiche, sie werden manchmal f�r
+etwas unterschiedliche Zwecke angewandt. Objekte werden oft f�r
+bewegliche oder ver�nderliche Dinge eingsetzt, wie z.B. Wirbelst�rme,
+w�hrend Items im Allgemeinen f�r unbewegliche Dinge, z.B. eine
+Wasserstation, eingesetzt werden. Da Items von einigen APRS-Programmen
+nicht dekodiert werden k�nnen, werden aber oftmals auch unbewegliche
+Objekte verwendet.
+
+�ber das Mauszeiger-Menu hat man Zugriff zu "Objekt Neu" und "Objekt
+�ndern. Ma�geblich f�r das Objekt ist dabei die Position des Mauszeigers
+bei Aufruf des Mauszeiger-Menus.
+
+Neben normalen Objekten mit einem Symbol an der Position gibt es noch
+spezielle Objekte. Fl�chenobjekte sind geeignet, wenn es darum geht einen
+gr��eren Bereich auf der Karte zu markieren. Man kann damit auch Wege,
+Stra�en oder Grenzen zeichnen, ein Suchgebiet abstecken, oder wenn es
+sein mu� auch ein Schachbrett um �ber APRS zu spielen :-) Beachten sie,
+da� Fl�chenobjekte nicht in allen APRS-Programmen implementiert sind und
+wenn, dann auch teilweise unterschiedlich dargestellt werden. Die anderen
+beiden, Signpost und Peil-Objekte werden weiter unten beschrieben.
+
+Objekte werden in den gleichen Abst�nden wie die eigenen Stationsdaten,
+die in "Datei-Einstellungen-Grundeinstellungen" festgelegt sind,
+wiederholt ausgesendet, insgesamt bis zum Doppelten der ebenfalls dort
+definierten Anzeigezeit f�r Stationen. Auch gel�schte Objekte werden
+wiederholt gesendet, bis sie in der Datenbank auslaufen.
+
+
+Bei "Objekt Neu" wird die Position, an der das Mauszeiger-Menu ge�ffnet
+wurde, als Vorgabe f�r ein neu zu erstellendes Objekt verwendet. Nach
+Eingabe eines Namens kann man ein anderes Symbol f�r das Objekt w�hlen,
+einen Kommentar eintragen und es �ber das Menu ein neues Objekt oder
+Item erstellen.
+
+Bei "Objekt �ndern" erh�lt man einen �hnlichen Dialog, bei dem allerdings
+die Daten des Objekt an der Position des Mauszeigers bereits eingetragen
+sind. Einige Daten, wie z.B. der Objektname, k�nnen nicht ge�ndert
+werden. Hier�ber ist auch das L�schen eines Objekts m�glich.
+
+Objekte und Items k�nnen auch mit der Maus auf der Karte verschoben
+werden, wenn der Schaltknopf "Bewegen" auf der oberen Leiste aktiviert
+ist.
+
+Erl�uterung der einzelnen Eintr�ge im Objekt-Dialog:
+
+= Signpost-Objekt =
+Durch Aktivieren wird aus dem Objekt ein Signpost-Objekt, auf einem
+Hinweisschild k�nnen drei Zeichen dargestellt werden, die sichtbar
+werden, wenn an der betreffenden Position hineingezoomt wird. Hinweis:
+Das funktioniert SO noch nicht...
+
+= Fl�chenobjekt =
+Hierdurch wird das Objekt als ein Fl�chenobjekt definiert, zus�tzlich
+werden die unten erl�uterten Steuerfunktionen f�r Fl�chenobjekte
+eingeschaltet.
+
+= Peil-Objekt =
+Hierbei handelt es sich um eine Peilmeldung, die mit dem DF-Symbol
+markiert wird. Sie k�nnen zwischen einer Meldung mit Rundstrahl- oder
+Richtantenne w�hlen und die spezifischen Daten eintragen. N�here Details
+�ber diese Techniken finden sich unter
+ http://web.usna.navy.mil/~bruninga/dfing.html
+und in der APRSdos Dokumentation.
+
+= Name =
+Dies ist der Name des Objekts, der aus bis zu neun Zeichen bestehen kann,
+wobei auch Leerzeichen innerhalb des Namens zul�ssig sind. Beim �ndern
+eines Objekts kann der Name nicht mehr ge�ndert werden. Falls trotzdem
+erforderlich, mu� das Objekt zun�chst gel�scht und dann mit neuem Namen
+neu erstellt werden. Wenn Sie das Objekt als Fl�chenobjekt, Signpost-
+oder Peil-Objekt definieren, wird der dann unn�tige Name gel�scht.
+
+= Stations-Symbol =
+W�hlen sie ein Symbol f�r das Objekt, hierzu ist die Angabe der
+Gruppe und des eigentlichen Symbolzeichens erforderlich. Sie k�nnen
+dies manuell eintragen, oder nach Dr�cken auf "Auswahl" aus einer
+grafischen Symbol�bersicht ausw�hlen. Es stehen zwei Gruppen von
+Symbolen zur Verf�gung. Eine Beschreibung der Symbolbedeutung findet
+sich im Hilfetext "Symboltabelle". Bei Signpost-, Fl�chen- und
+Peil-Objekten l��t sich das Symbol nicht �ndern.
+
+= Position =
+Hier wird die Position des Objekts eingegeben. Wenn Sie ein neues Objekt
+erstellen, so wurde dort bereits die Position eingetragen, an der Sie
+mit der rechten Maustaste geklickt hatten, um das Mauszeiger-Menu
+aufzurufen. Wenn Sie das Objekt verschoben haben, so steht dort die neue
+Position. Sie k�nnen die Daten aber auch manuell eintragen, z.B. wenn
+Ihnen jemand eine Position �ber Sprechfunk durchgegeben hat.
+
+= Allgemeine Optionen =
+Hier k�nnen Sie die Geschwindigkeit, die Bewegungsrichtung und die H�he
+des Objekts eintragen. Bei einigen Objekten ist die Angabe von
+Geschwindigkeit und Richtung nicht m�glich, die Felder sind dann in Grau
+dargestellt.
+
+= Signpost Text =
+Hier k�nnen Sie f�r ein Signpost-Objekt den Text (ein bis drei Zeichen)
+angeben, der auf dem Hinweisschild erscheinen soll. Beachten Sie, da�
+Xastir Signpost-Objekte momentan noch nicht richtig anzeigt.
+
+= Fl�chenobjekt =
+Fl�chenobjekte werden eingesetzt, um spezielle Teile einer Karte
+herauszuheben oder zus�tzliche Details zu zeichnen. Hierzu dienen die
+folgenden Eintr�ge:
+
+ = Helle Farben =
+ Wenn aktiviert, werden hellere, sonst dunklere Farben f�r die Fl�chen
+ verwendet.
+
+ = Fl�chen f�llen =
+ Wenn markiert, werden die Fl�chen mit Objektfarbe gef�llt, ansonsten
+ wird nur die Umrandung dargestellt.
+
+ = Objekt-Typ =
+ Verschiedene geometrische Grundformen k�nnen hier gew�hlt werden:
+ Kreis/Ellipse, Linie nach rechts, Linie nach links, Dreieck, Rechteck
+
+ = Objektfarbe =
+ Hier wird die Farbe gew�hlt in der das Objekt gezeichnet wird. Dies
+ wird auch durch das Markieren von "Helle Farben" (siehe oben)
+ beeinflu�t. Es stehen zur Verf�gung:
+ Schwarz, Blau, Gr�n, Cyan, Rot, Violett, Gelb, Grau
+
+ = nach oben =
+ Ausdehnung des Fl�chenobjekts nach oben in 1/100 Grad.
+
+ = nach links =
+ Ausdehnung des Fl�chenobjekts nach links in 1/100 Grad.
+
+ = Korridor =
+ Gibt die Breite eines Linienobjekts an und wird in Meilen
+ spezifiziert.
+
+Denken Sie daran, Ihre Objekte zu l�schen, wenn sie nicht mehr ben�tigt
+werden. Anderenfalls werden sie wiederholt gesendet und erscheinen auf
+dem Bildschirm anderer Stationen bis sie verfallen.
+
+HELP-INDEX>Listendarstellungen
+
+ Listendarstellungen
+
+�ber den Menupunkt "Zeige" k�nnen verschiedene Daten der Stationen meist
+in Form von Listen dargestellt werden.
+
+= Berichte =
+Berichte (bulletin boards) sind eine M�glichkeit, �ber APRS Nachrichten
+und wichtige Ank�ndigungen an alle zu senden. Wenn Sie mit dem Internet
+verbunden sind, ist es sinnvoll, den Einzugsbereich auf wenige 100km
+einzustellen um so Berichte aus anderen Teilen der Welt zu ignorieren.
+Der Eintrag einer '0' im Feld Bereich bedeutet keinerlei Einschr�nkungen,
+d.h. alle Berichte werden empfangen. Klicken Sie auf "neuen Bereich
+setzen" um den eingegebenen Wert zu �bernehmen.
+Xastir unterst�tzt das Senden von Berichten momentan noch nicht.
+
+= Packet Radio =
+Hier werden die �ber Packet Radio oder das Internet ankommenden Rohdaten
+dargestellt. Es kann gew�hlt werden, ob nur Daten vom TNC, nur
+Daten aus dem Internet, oder beides angezeigt werden soll.
+
+= Mobilstationen =
+Dies ist eine Liste von Stationen, die sich bewegen, typischerweise also
+Mobilstationen. Die Bedeutung des Symbols wird dabei ignoriert, es wird
+nur festgestellt, ob sich die Station bewegt. Die angezeigte Information
+umfa�t neben der letzten bekannten Position auch Geschwindigkeit,
+Bewegungsrichtung, H�he, Anzahl der empfangenen Pakete, Anzahl der
+sichtbaren Satelliten sowie Abstand und Richtung von unserer eigenen
+Station.
+
+= Alle Stationen =
+Hier wird eine Tabelle mit allen Stationen in alphabetischer Reihenfolge
+angezeigt. Es umfa�t auch die Anzahl der geh�rten Pakete, die Zeit zu der
+die Station zuletzt geh�rt wurde, den Pfad, den das letzte Paket genommen
+hatte, PHG und nat�rlich den Kommentar.
+
+= Lokale Stationen =
+Eine �hnliche Tabelle wie zuvor, allerdings werden nur Stationen
+angezeigt, die �ber den eigenen TNC geh�rt wurden.
+
+= Letzte Stationen =
+Eine Liste mit allen Stationen in der Reihenfolge, in der sie geh�rt
+wurden. Die zuletzt geh�rten Stationen stehen oben am Beginn der Liste.
+Angezeigt wird wiederum die Anzahl der geh�rten Pakete, die Zeit zu der
+die Station zuletzt geh�rt wurde, den Pfad, den das letzte Paket genommen
+hatte, PHG und der Kommentar.
+
+= Wetterstationen =
+Diese Liste umfa�t nur APRS Wetterstationen mit deren Daten. Aufgef�hrt
+werden Windgeschwindigkeit- und richtung, Geschwindigkeit von B�en, die
+Temperatur, die Luftfeuchtigkeit, den Druck, Regenmenge w�hrend der
+letzten Stunde, seit Mitternacht und w�hrend der letzten 24 Stunden.
+
+= Eigene Wetterdaten =
+Wenn eine eigene Wetterstation vorhanden ist und in Xastir konfiguriert
+wurde, so werden deren Wetterdaten hier angezeigt.
+
+= Wetterwarnung =
+Zeigt die empfangenen Wetterwarnungen des amerikanischen NWS an.
+
+= Nachrichten =
+Zeigt den Nachrichtenverkehr zwischen den verschiedenen Stationen solange
+das Fenster ge�ffnet ist. Dies beinhaltet Quelle und Ziel, �ber welche
+Schnittstelle sie lif und den Inhalt der Nachricht. �ber "Bereich" kann
+die Anzeige auf Nachrichten von Stationen in der Umgebung beschr�nkt
+werden, bei Eingabe von '0' werden alle Nachrichten angezeigt.
+
+= Laufzeit =
+Zeigt an, seit wie lange Xastir bereits l�uft.
+
+HELP-INDEX>Kartenauswahl und Einstellungen
+
+ Kartenauswahl und Einstellungen
+
+= Kartenauswahl =
+Hiermit erhalten sie eine Liste aller Dateien im Kartenverzeichnis. Wenn
+sie einen Dateinamen markieren, so wird die Karte beim Klicken auf OK
+geladen und angezeigt, wenn sie in den aktuellen Bildauschnitt f�llt.
+Sie k�nnen mehrere Karten gleichzeitig ausw�hlen. Abbruch verwirft die
+�nderungen in der Kartenauswahl. Es gibt auch Buttons um alle Karten
+gleichzeitig abzuw�hlen oder bestimmte Kartentypen zu laden.
+
+= Ausschnitte =
+Genaueres siehe im Hilfetext zu "Gespeicherte Kartenausschnitten"
+
+= Objekt in Karte suchen =
+Hiermit erhalten Sie einen Dialog zur Suche eines bestimmten Objekts in
+einer GNIS Datei. Falls gefunden wird die Karte an dieser Stelle neu
+zentriert. Die zuletzt befragte GNIS-Datei wird beim n�chsten Aufruf
+wiederum als Vorgabe gew�hlt.
+
+= Alle Karten verbergen =
+Hiermit kann das Laden aller Karten vor�bergehend verhindert werden. Dies
+ist vor allem dann vorteilhaft, wenn man die Karte oft verschiebt oder
+zoomt und der langsame Kartenaufbau dazwischen st�rend wirkt. Bei einem
+Neustart von Xastir ist diese Option immer ausgeschaltet.
+
+= Automatische Karte (An/Aus) =
+Falls eingeschaltet, wird jede Karte im Kartenverzeichnis oder einem
+Unterverzeichnis geladen, die f�r den aktuell dargestellten Ausschnitt
+g�ltig ist. Sie k�nnen beliebig viele Uterverzeichnis-Ebenen unterhalb
+des Kartenverzeichnisses anlegen, die automatisch durchsucht werden. Alle
+Karten werden im dargestellten Ausschnitt �berlagert. Die Reihenfolge
+h�ngt von der alphabetischen Sortierung ab, gegebenenfalls kann man Links
+auf andere Namen anlegen, um die Sortierung flexibler handhaben zu
+k�nnen. Wenn sie viele oder komplexe Karten haben, oder einen langsamen
+Computer, dann kann das Laden der Karten sehr lange dauern. Wenn diese
+Option ausgeschaltet ist, werden die in der Kartenauswahl markierten
+Karten geladen.
+
+= Gitter (An/Aus) =
+Wenn eingeschaltet wird ein Kartengitter mit, je nach Zoomebene, 10 Grad
+bzw. 1 Grad Abstand gezeichnet.
+
+= Ebenen (An/Aus) =
+Falls eingeschaltet, werden Details bei der Darstellung herausgefiltert
+wenn gr��ere Bereiche durch herauszoomen dargestellt werden. Dies
+funktioniert nicht mit allen Karten, es verringert auch nicht die
+Ladezeit, sondern sorgt nur daf�r, da� der Bildschirm lesbar bleibt. Ein
+Beispiel hierf�r sind Karten die aus den Tiger Line Karten von
+aprs.rutgers.edu erzeugt wurden.
+
+= Kartenbeschriftungen =
+Hiermit k�nnen Kartenbeschriftungen ein- oder ausgeschaltet werden, die
+in Karten im dosAPRS, WinAPRS, GNIS und ESRI Shapefile Format enthalten
+sind.
+
+= Fl�chen einf�rben (An/Aus) =
+Diese Option legt das Einf�rben bei Vektorkarten fest. In manchen F�llen
+ist es sinnvoll, die F�llung zu entfernen, um darunterliegende weitere
+Karten sehen zu k�nnen. Die Karten werden in alphabetischer Reihenfolge
+geladen, so da� ein Umbenennen oder ein Link eine weitere M�glichkeit in
+diesem Fall darstellt.
+
+= Wetterwarnung Counties =
+Bei Wetterwarnungen des amerikanischen NWS k�nnen einzelne Counties, f�r
+die eine Wetterwarnung vorliegt, eingef�rbt werden. Dies kann hiermit
+gesteuert werden.
+
+= Hintergrundfarbe (An/Aus) =
+Erm�glicht die Auswahl der bei transparenten Karten durchscheinenden
+Hintergrundfarbe.
+
+= Intensit�t =
+Hiermit kann die Farbs�ttigung der Karte gesteuert werden. Dieser
+Menupunkt erscheint nur, wenn Xastir mit GeoTIFF-Unterst�tzung und/oder
+ImageMagick zusammen kompiliert wurde.
+
+= Textdarstellung =
+Erm�glicht die Auswahl zwischen zwei verschiedenen Arten der
+Schriftdarstellung f�r Stationsinformationen auf der Karte.
+
+= Mauszeiger-Menu =
+�ffnet das Mauszeiger-Menu, das sonst beim Klick mit der rechten
+Maustaste erscheint.
+
+
+Eine Anmerkung zu Karten:
+Viele der zur Zeit erh�ltlichen Vektorkarten f�r die USA sind mit dem
+NAD-27 Datum erstellt worden, w�hrend Xastir und andere APRS Programme
+das aktuelle WGS-84 Datum verwenden. Wenn man sehr weit auf einen kleinen
+Kartenausschnitt herein zoomt werden die Abweichungen durch das falsche
+Kartendatum deutlich. Bei den USGS Topographischen Karten wird die
+Datumsabweichung von Xastir korrigiert, so da� Positionen hiermit im
+Allgemeinen genauer sind als mit anderen topographischen Karten.
+
+HELP-INDEX>Kartendateien und County-Daten f�r Wetterwarnungen
+
+ Kartendateien und County-Daten f�r Wetterwarnungen
+
+Kartentypen
+Xastir kann mit den verschiedensten Kartentypen arbeiten. Alle DosAPRS-,
+WinAPRS- und MacAPRS-Karten werden unterst�tzt. Zus�tzlich unterst�tzt
+Xastir von Haus aus Karten im PocketAPRS-Format, Bezeichnungen aus GNIS-
+Dateien (Geographic Names Information System) und Karten im XPixmap-
+Grafikformat. Xastir kann so kompiliert werden, da� externe Bibliotheken
+eingebunden werden k�nnen, um topographische Karten im GeoTIFF-Format und
+ESRI Shapefiles zu unterst�tzen. Die F�higkeit mit Karten in den
+verschiedensten Grafikformaten umzugehen kann durch das Kompilieren mit
+ImageMagick-Unterst�tzung stark erweitert werden (siehe
+"http://www.imagemagick.org/www/formats.html"). Xastir unterst�tzt die
+Darstellung von Bereichen von Wetterwarnungen auf Karten, hierzu k�nnen
+die Daten im klassischen dosAPRS/WinAPRS-Format vorliegen, die Einbindung
+im neuen ESRI Shapefile-Format wird in K�rze vollst�ndig sein. Einen
+Hinweis auf die Quellen von verschiedenen Kartenformaten finden Sie in
+der Datei README.1ST.
+
+Karten-Verzeichnisse
+Alle Kartendateien sollten unter /usr/local/share/xastir/maps auf Ihrm
+Computer gespeichert werden. Zur besseren Organisation und Trennung der
+Karten k�nnen sie dort auch beliebige Unterverzeichnisse anlegen. Bei der
+Kartenauswahl werden die Karten mit ihrem ralativen Pfad alphabetisch
+sortiert angezeigt. Symbolische Links k�nnen helfen, um die Reihenfolge
+gegebenenfalls zu �ndern.
+
+Hinweise zur Installation und Organisation der Karten finden sich
+ebenfalls in README.1ST.
+
+F�r Karten im Pixelgrafikformat werden immer zwei Dateien ben�tigt, zum
+einen die Grafikdatei im .xpm Format (oder andere Formate bei
+ImageMagick-Unterst�tzung) und eine Kalibrierungsdatei (.geo). Das
+Standardgrafikformat ohne zus�tzliche Bibliotheken ist .xpm, um Platz zu
+sparen k�nnen diese Dateien aber auch mit gzip gepackt werden
+("gzip map.xpm" erzeugt die komprimierte Datei "map.xpm.gz"). Dies wird
+von Xastir automatisch erkannt und beim Laden der Karte ber�cksichtigt.
+Sie k�nnen XView, Gimp, ImageMagick oder andere Programme benutzen, um
+Grafiken zu konvertieren, die als gif, jpg oder tiff-Dateien vorliegen,
+wenn Sie nicht ImageMagick hinzukompilieren wollen. Sollten Sie Probleme
+mit Karten im .xpm-Format haben, versuchen Sie zun�chst, die Grafik in
+Gimp zu laden und wieder abzuspeichern, hierdurch werden alle, evtl.
+unbekannten, Farbnamen in Bin�rdarstellung umgewandelt.
+
+Die .geo-Datei ist eine Textdatei, die Kartenposition in der Welt
+festlegt. Zur Erl�uterung hier die Datei world1.geo:
+
+FILENAME world1.xpm
+# x y lon lat
+TIEPOINT 0 0 -180 90
+TIEPOINT 640 320 180 -90
+
+Dieses einfache Beispiel besteht aus vier grundlegenden Komponenten. Die
+erste Zeile (FILENAME) legt die Grafikdatei fest, die f�r diese Karte
+benutzt werden soll. Bei einer komprimierten .xpm-Datei ist die Angabe
+der Endung ".gz" optional. Wenn kein Pfad angegeben wird, wird die
+Grafikdatei im gleichen Verzeichnis wie die .geo-Datei gesucht.
+Unter FILENAME kann auch eine URL angegeben werden, unter der Xastir die
+Kartengrafik mittels wget herunterladen kann. Dies bedeutet, da� so
+ziemlich jedes Bild, da� �ber HTTP oder FTP im Internet verf�gbar ist,
+als Karte dienen kann.
+
+Die zweite Zeile ist eine Kommenarzeile, dies wird durch ein '#' als
+erstes Zeichen einer Zeile festgelegt.
+
+Die letzten beiden Zeilen binden x-y-Positionen in der Grafikdatei an
+Koordinaten (L�ngen- und Breitengrade) in der realen Welt. Zwei solche
+Punkte werden ben�tigt und sie sollten f�r eine hohe Genauigkeit
+m�glichst weit auseinander in den Ecken der Grafikdatei liegen, z.B. oben
+links und unten rechts.
+
+Um eine solche Karte zu verwenden, w�hlen Sie in der Kartenauswahl die
+zugeh�rige .geo-Datei.
+
+Die Gr��e der Grafikdatei kann optional ebenfalls in der .geo-Datei
+angegeben werden:
+
+FILENAME Agnes_Mountain.xpm.gz
+#
+# X Y Lon Lat
+# ---- ---- ------------- -----------
+TIEPOINT 0 0 -121.00120491 48.37481943
+TIEPOINT 1337 1999 -120.87619806 48.24982052
+#
+IMAGESIZE 1338 2000
+
+Mit IMAGESIZE wird die Bildgr��e in Pixel angegeben. Xastir benutzt diese
+Information, um Karten, die nicht in den aktuell dargestellten Ausschnitt
+fallen, m�glichst schnell aussortieren zu k�nnen. Wird dies nicht
+angegeben, mu� Xastir die Grafikdatei zum Berechnen auf alle F�lle immer
+laden.
+
+Wenn Xastir mit Unterst�tzung von ImageMagick kompiliert wurde, so stehen
+au�er .xpm s�mtliche Grafikformate zur Verf�gung, die von ImageMagick
+selbst oder seinen Bibliotheken unterst�tzt werden.
+
+Es gibt verschiedene "spezielle" .geo-Dateien, die von Xastir verwendet
+werden k�nnen:
+
+o Eine Datei, die nur das Wort "TIGERMAP" enth�lt, veranla�t Xastir,
+ Tiger Karten im passenden Ausschnitt aus dem Internet zu laden und auf
+ dem Bildschirm darzustellen.
+
+o Eine Datei, die nur das Wort "TERRASERVER-SATELLITE" enth�lt, veranla�t
+ Xastir, Terraserver Satellitenfotos des gew�hlten Ausschnitts
+ darzustellen. Dies funktioniert allerdings nicht in allen Gegenden der
+ Welt. Beachten Sie, da� bei einem Zoom-Faktor gr��er als 256 Terraserver
+ Karten zum Laden vermutlich sehr lange brauchen und m�glicherweise auch
+ nicht korrekt dargestellt werden. Dies ist eine Limitierung von
+ Terraserver, nicht von Xastir.
+
+o Eine Datei mit dem Wort "FINDU" und einer weiteren Zeile
+ "CALL <callsign>" l�dt historische Spurdaten der mit dem Call
+ spezifizierten Station. Dies ist allerdings inzwischen �ber das
+ Stationsmenu einfacher zu bewerkstelligen.
+
+
+geoTIFF Karten sind ebenfalls eine Kombination aus zwei Dateien, einer
+.tif und einer .fgd Datei. Die .tif-Datei enth�lt die eigentlichen
+Kartendaten, die .fgd-Kalibrierungsdatei ben�tigt nur vier Eintr�ge wie
+im folgenden Fall, kann aber viele Andere Eintr�ge zus�tzlich enhalten:
+
+1.5.1.1 WEST BOUNDING COORDINATE: -122.000000
+1.5.1.2 EAST BOUNDING COORDINATE: -120.000000
+1.5.1.3 NORTH BOUNDING COORDINATE: 48.000000
+1.5.1.4 SOUTH BOUNDING COORDINATE: 47.000000
+
+Xastir benutzt diese vier Zeilen, um die Eckpunkte der Karte zu
+berechnen, und um festzustellen, ob die Karte in den gerade angezeigten
+Ausschnitt f�llt. Wenn es sich bei Ihren Daten um topographische
+USGS-Karten handelt, sollten auch die .fgd-Dateien vorliegen. Xastir
+ist in der Lage das Datum von NAD27 in WGS84 umzurechnen, so da� auch
+USGS-Karten unter Xastir eine h�here Genauigkeit erreichen.
+
+Wenn Sie keine .fgd-Datei haben, wird die Karte problemlos geladen,
+allerdings werden die wei�en R�nder am Kartenrand nicht beschnitten und
+die Karte k�nnte eine leicht falsche Gr��e und Rotation besitzen.
+
+Xastir kann nun USGS geoTIFF topographische Karten direkt von einer CD
+laden. Mounten Sie das CD-ROM manuell oder automatisch durch automounter,
+und achten Sie darauf, da� ein symbolischer Link im Kartenverzeichnis auf
+das gemountete Laufwerk zeigt. Das war es!
+
+
+Auch Shapefiles sind eine Kombination aus mehreren Dateien, .shp, .dbf
+und .shx. Sie m�ssen nur die .shp-Datei ausw�hlen, um die Karte zu laden.
+Die anderen Dateien m�ssen jedoch vorhanden sein, um die Karte
+ordnungsgem�� laden zu k�nnen.
+
+
+GNIS (Geographic Names Information System) Daten bestehen aus einer
+Sammlung von Namen von Orten oder geographischen Objekten mit ihren
+jeweiligen Positionen. Diese Bezeichnungen werden wie die in Dos/WinAPRS
+Karten dargestellt. Je weiter man hineinzoomt, umso mehr detailiertere
+Bezeichnungen erscheinen, unter der Annahme, da� eine GNIS-Datei als
+Karte gew�hlt wurde und die Darstellung von Bezeichnungen im Kartenmenu
+eingeschaltet wurden.
+
+
+County Karten f�r Wetterwarnungen
+Alle County-Karten sollten im Verzeichnis /usr/local/share/xastir/Counties
+gespeichert werden. Es gibt verschiedene Formate f�r diese Karten, aber
+dieses Verzeichnis wird immer Unterverzeichnisse f�r jeden Staat/Marine-
+Bereich haben (Abk�rzung aus zwei Buchstaben).
+Das alte Format benutzt <ST><COUNTYNAME>.map, w�hrend das neue Format
+<ST>Z<NWSZONECODE>.map benutzt. Die Installation wird ausf�hrlicher in
+README.1ST im Abschnitt �ber die Quelle von Karten beschrieben.
+
+Wenn eine NWS Nachricht empfangen wird, so werden die entsprechenden
+Bereiche eingef�rbt, um den Bereich der Warnung zu kennzeichnen. Die
+verschiedenen Farben beschreiben dabei die Art der Warnung.
+Urspr�nglich wurden folgende Farben verwendet:
+Cyan for advisory, yellow for watch, red for warning, orange for
+cancelled alert, royal blue for tests, and green for undetermined
+alert levels.
+Inzwischen k�nnen die Farben davon etwas abweichen, da die Fl�chen nun
+nicht mehr gef�llt werden, sondern nur noch in der Farbe ge�ndert werden,
+so da� man die darunterliegende Karte noch erkennen kann.
+Die Darstellung von Wetterwarnungen kann im Kartenmenu ein- bzw.
+ausgeschaltet werden.
+
+HELP-INDEX>Ansicht
+
+ Ansicht
+
+Die Optionen in diesem Menu erlauben ihnen festzulegen, welche Daten
+zu den Stationen auf der Karte angezeigt werden sollen. Es erlaubt
+Ihnen auch Stationen zu suchen und zu verfolgen, oder Stationen oder
+deren Spur zu l�schen.
+
+= Station finden =
+ Siehe hierzu unter "Stationen finden".
+
+= Verfolge Station =
+ Siehe hierzu unter "Verfolgen von Stationen".
+
+= Spur von Findu holen =
+ L�dt alte Spurdaten einer Station aus dem Internet von findu.com.
+ Momentan werden die Daten der letzten beiden Wochen geladen.
+
+= Symbole =
+ Hiermit kann festgelegt werden, ob Symbole auf der Karte gezeichnet
+ werden sollen. Die meisten folgenden Optionen h�ngen hiervon ebenfalls
+ ab. Bei alten Stationen wird das Symbol nur noch schememhaft in der
+ Standardausrichtung gezeichnet, die zugeh�rige Spur wird gestrichelt
+ und alle Daten au�er dem Rufzeichen verschwinden vom Bildschirm.
+
+= Symbole drehen =
+ Wenn eingeschaltet, werden einige Symbole auf der Karte gedreht, um
+ so die Richtung, in die sich Mobilstationen bewegen, anzudeuten.
+
+= Rufzeichen =
+ Zeigt das Rufzeichen der Station rechts vom Symbol an.
+
+= Geschwindigkeit =
+ Zeigt die Geschwindigkeit einer Station in roter Schrift unterhalb
+ von Rufzeichen und Richtung an, sofern eine Geschwindigkeit
+ �bermittelt wird.
+= - kurz =
+ Wenn markiert wird die Geschwindigkeit in Kurzform ohne Einheit
+ angezeigt.
+
+= H�he =
+ Zeigt die H�he oberhalb des Rufzeichens in blauer Schrift an,
+ sofern sie �bermittelt wurde.
+
+= Kurs =
+ Zeigt die Richtung, in die sich die Station bewegt, unterhalb des
+ Rufzeichens in gr�ner Schrift an, sofern die Station einen Kurs
+ �bermittelt.
+
+= Entfernung/Richtung =
+ Erm�glicht die Anzeige der Entfernung von der eigenen Station und der
+ Richtung, in der sich die Station von der eigenen Station aus befindet.
+ Diese beiden Werte werden links vom Symbol dargestellt.
+
+= Wetterdaten =
+ Wenn eingeschaltet, werden bei Wetterstationen unterhalb des Symbols
+ die letzten Wetterdaten aufgelistet (Temperatur, Wind- und B�en-
+ geschwindigkeit, Windrichtung und Feuchtigkeit.
+= - nur Temperatur =
+ Wenn markiert wird nur die Temperatur angezeigt.
+
+= Leistung/Gewinn =
+ Wenn PHG-Daten �bermittelt werden, wird ein Kreis um die Station
+ gezeichnet, dessen Radius aus Leistung, H�he und Antennengewinn
+ berechnet wird. Wenn sich zwei Kreise �berschneiden sind die
+ Stationen theoretisch in Reichweite f�r eine Simplexverbindung.
+ In der Praxis is dies aber nur eine sehr grobe N�herung, vor allem
+ in Gegenden mit sich �nderndem Gel�nde.
+= - mit Standardwert =
+ F�r Stationen, die keine PHG-Daten �bermitteln, wird stattdessen
+ ein Standardwert gen�� den APRS-Spezifikationen verwendet.
+= - bei Mobilstationen =
+ Hiermit k�nnen auch f�r Mobilstationen Entfernungskreise gezeichnet
+ werden.
+
+= Positionsverschleierung =
+ Wenn eingeschaltet, wird die Fl�che markiert, in der sich eine Station
+ mit Positionsverschleierung befinden kann. Die betreffende Station
+ wird in der Mitte dieses Bereichs positioniert.
+
+= Alte Daten zeigen =
+ Xastir zeigt Daten auch noch an, nachdem sie eigentlich bereits als
+ alt deklariert wurden. Diese Zeiten k�nnen unter Datei-Einstellungen-
+ Grundeinstellungen ge�mdert werden.
+
+= DF Kreise zeigen =
+ Wenn eingeschaltet, werden auch alle Kreise f�r Peilungen (Direction
+ Finding) angezeigt.
+
+= Spuren =
+ Wenn markiert, wird f�r Mobilstationen eine farbige Spur mit den
+ letzten maximal 100 Positionen gezeichnet. Jeder neuen Mobilstation
+ wird hierzu eine neue Farbe aus einer Tabelle zugewiesen.
+
+= Stationen l�schen =
+ Dies l�scht alle Stationsdaten au�er den eigenen. Dies ist
+ z.B. n�tzlich, wenn der Speicher knapp bemessen ist.
+
+= Spuren L�schen =
+ L�schen alle Spuren der Mobilstationen. Dies ist z.B. n�tzlich,
+ wenn der Speicher knapp bemessen ist. Die Spur einzelner Stationen
+ kann auch �ber das StationsInfo Menu gel�scht werden.
+
+HELP-INDEX>Nachrichten
+
+ Nachrichten
+
+= Schicke Nachricht an =
+ Hiermit k�nnen Nachrichten mit einer einzelnen Station ausgetauscht
+ werden. Dies ist auch �ber das Menu StationsInfo m�glich.
+
+= �ffne Gruppen Nachricht=
+ Dies funktioniert �hnlich, nur da� die Nachrichten an einen
+ Gruppennamen geschickt werden. Die Gruppen werden in der Datei
+ "groups" in ~/.xastir/config definiert. Gruppennachrichten sind noch
+ nicht voll implementiert und einige Probleme m�ssen noch beseitigt
+ werden.
+
+In Zukunft wird es auch m�glich sein, Bulletins zu verschicken, dies ist
+aber momentan noch nicht implementiert.
+
+Im Nachrichtenfenster mu� zun�chst das Rufzeichen der Station eingetragen
+werden, der man eine Nachricht schicken will. Darunter kann man dann eine
+Zeile des Nachrichtentexts (max. 250 Zeichen) eingeben und mit
+"Sende jetzt!" abschicken. Bis zu einer Best�tigung (ACK) durch die
+Gegenstation bleibt dieser Button inaktiv (grau).
+
+Es stehen maximal zehn Fenster f�r Nachrichten an verschiedene Rufzeichen
+zur Verf�gung.
+
+Beim Empfang einer an die eigene Station gerichteten Nachricht �ffnet
+sich automatisch das Nachrichtenfenster, wobei das Rufzeichen des
+Absenders bereits eingetragen ist.
+
+Im gro�en Fenster sind oben die ausgehenden und unten die eingetroffenen
+Nachrichten sortiert nach ihrer Zeilennummer aufgelistet.
+
+Mit "Beenden" wird das Nachrichtenfenster verlassen.
+Mit "Neues Rufzeichen" kann man nachschauen, welche Nachrichten eine
+Station fr�her gesendet hatte. Sie k�nnen dies auch einsetzen, um mit
+einer anderen Station Nachrichten auszutauschen.
+Mit "L�sche Nachrichten" wird die angezeigte Liste mit Nachrichten
+gel�scht.
+
+= L�sche alle ausgehenden Nachrichten =
+ Hiermit werden alle noch nicht best�tigten gesendeten Nachrichten
+ gel�scht. Anderenfalls wird mehrfach versucht, diese zuzustellen.
+
+= Stationen Allgemein =
+ Dies sendet ein ?APRS? Paket, wodurch alle lokalen Stationen mit
+ ihrer Position und/oder ihrem Status antworten sollten. Viele
+ Programme ignorieren diese Anfrage, da eine Antwort zu einer Flut
+ von Daten f�hren kann.
+
+= IGate Stationen =
+ Dies sendet ein ?IGATE? Paket, wodurch alle IGate-Stationen antworten
+ und ihre M�glichkeiten mitteilen sollten.
+
+= Wetterstationen =
+ Dies sendet ein ?WX? Paket, wodurch alle lokalen Wetterstationen ihre
+ Position und die Wetterdaten senden sollten.
+
+= Setze automatische Antwort =
+ Legt den Text fest, der als automatische Antwort gesendet wird.
+
+= Automatische Antwort =
+ Hiermit kann ein vorbereiteter Standardtext bei jeder ankommenden
+ Nachricht als Antwort versandt werden.
+
+HELP-INDEX>Schnittstellen
+
+ Schnittstellen
+
+In diesem Menu k�nnen Einstellungen zu den vershiedenen Schnittstellen
+gemacht werden.
+
+= Schnittstellen Ein/Aus =
+ Diese Option �ffnet ein Fenster, in dem Sie alle Ihre konfigurierten
+ Schnittstellen ein- oder ausschalten k�nnen.
+
+= Einstellungen =
+ Eine Liste mit den installierten Schnittstellen erscheint und erlaubt
+ Ihnen deren Einstellungen zu �nden und weitere Schnittstellen
+ hinzuzuf�gen bzw. vorhandene zu l�schen. N�heres finden Sie unter
+ "Schnittstellen Konfiguration"
+
+= Nicht senden: ALLES =
+ Wenn markiert wird �berhaupt NICHT gesendet.
+ F�r diese und die folgenden beiden Optionen gilt, da� es sich um
+ globale Einstellungen handelt, die f�r alle Schnittstellen gelten.
+ Die meisten Schnittstellen bieten auch die M�glichkeit, das Senden
+ �ber diese spezielle Schnittstelle einzeln auszuschalten.
+
+= Nicht senden: Meine Position =
+ Wenn markiert wird die eigene Position nicht gesendet.
+
+= Nicht senden: Objekte =
+ Wenn markiert wird die eigenen Objekte nicht gesendet.
+
+= Sende jetzt! =
+ F�hrt dazu, da� alle eingeschalteten Schnittstellen ein Positions-
+ Paket senden. Es ist nicht funktionsf�hig (grau), wenn das Senden
+ grunds�tzlich ausgeschaltet ist.
+
+HELP-INDEX>Stations-Info
+
+ Stations-Info
+
+Das Fenster Stations-Info zeigt alle Daten an, die von Xastir f�r diese
+Station dekodiert wurden.
+
+Es k�nnen die folgenden Informationen angezeigt werden: Die Anzahl der
+geh�rten Pakete, die Uhrzeit, zu der die Station zuletzt geh�rt wurde,
+�ber welche Schnittstelle dies erfolgte, den Kommentar, PHG (aus
+Leistung, H�he und Gewinn), Entfernung und Richtung von meiner Station,
+Wetterdaten und die letzte Position.
+Bei Stationen, die sich bewegen, folgt ein Tracklog mit den neuesten
+Daten ganz oben. Ein '+' vor einer Zeile markiert den Start eines neuen
+Tracks (wenn zuvor eine gro�e Zeit- bzw. Ortsdifferenz vorlag). Ein Stern
+am Ende einer Zeile weist darauf hin, da� die Station an der jeweiligen
+Position auf direktem Weg geh�rt werden konnte (ohne Digipeater).
+
+Nur f�r die eigene Station gibt es ein Feld "Echo von", das die letzten
+sechs Digipeater auff�hrt, die mein Paket als erste weitergegeben haben.
+
+Am unteren Rand des Fensters befinden sich zwei Reihen mit vier Aktions-
+feldern, deren Funktion abh�ngig von der Art der dargestellten Station
+ist.
+
+F�r Objekte/Items:
+
+Track speichern Objekt �ndern --leer-- Schlie�en
+? Stationsversion ? Trace ? unbest. Nachrichten Stationsanfrage
+
+
+F�r andere Stationen:
+
+Track speichern Nachricht senden FCC/RAC Datenbank Schlie�en
+? Stationsversion ? Trace ? unbest. Nachrichten Stationsanfrage
+
+Bei sich bewegenden Stationen fehlt die Anfrage nach der Stationsversion,
+stattdessen findet sich dort "Spur l�schen". Hiermit werden alle
+Bewegungsdaten dieser Station in der Datenbank und vom Bildschirm
+gel�scht.
+
+Mit "Spur speichern" wird die Position und falls vorhanden, alle
+Bewegungsdaten in einer Datei auf der Festplatte gespeichert. Das
+derzeit benutzte Format ist dem �hnlich, das bei GPS-Empf�ngern zum
+Einsatz kommt, die Spezifikationen k�nnten sich aber in zuk�nftigen
+Versionen noch �ndern. Es gibt momentan keinen Weg, diese Daten wieder
+einzulesen, dies ist aber f�r die Zukunft geplant. Das Ziel ist es auch
+GPS Tracklog-Dateien in �hnlicher Art laden und darstellen zu k�nnen.
+Diese Tracklog-Dateien werden im Verzeichnis ~/.xastir/tracklogs
+abgelegt, der Dateiname besteht aus dem jeweiligen Rufzeichen mit der
+Erweiterung ".trk".
+
+"Objekt/Item �ndern" �ffnet das Fenster zum �ndern von Objekten.
+
+"Sende Nachricht" �ffnet f�r diese Station ein Nachrichtenfenster und
+erm�glicht an diese Station eine Nachricht zu senden.
+
+Wenn die FCC (U.S. Federal Communications Commission) oder RAC (Radio
+Amateurs of Canada) Datenbank installiert ist und das Rufzeichen aus
+dem US-amerikanischen bzw. kanadischen Kontingent stammt, so ist das
+"FCC/RAC Suche"-Feld vorhanden, sonst nicht. Die FCC- und RAC-Dateien
+sollten sich im Verzeichnis /usr/local/share/xastir/fcc befinden, wobei auf
+Gro�-/Kleinschreibung zu achten ist. Wenn die Suche erfolgreich ist,
+wird Name und Adresse der Station im Stations-Info Fenster angezeigt.
+Anweisungen zur Installation dieser Datenbanken finden sich in der
+Datei README.1ST.
+
+Xastir erzeugt beim Start eine Indexdatei f�r jede dieser Datenbanken.
+Wenn eine Rufzeichendatei aktualisiert wird, w�hrend Xastir l�uft, so
+wird der Index bei der n�chsten Suche erstellt oder neu aufgebaut.
+Spezielle Pr�fixe werden NICHT ber�cksichtigt.
+
+HELP-INDEX>Erstellen von Protokolldateien
+
+ Erstellen von Protokolldateien
+
+Xastir kann empfangene Daten in Protokolldateien schreiben, so da� sie
+sp�ter wieder eingespielt werden, oder zu Debuggingzwecken analysiert
+werden k�nnen. Alle diese Einstellungen werden im Menu "Datei"
+vorgenommen.
+
+= TNC protokollieren =
+ Protokolliert alle Daten, die �ber den TNC empfangen bzw. gesendet
+ werden. Dieses Protokoll kann �ber "Protokolldatei laden" zu einem
+ sp�teren Zeitpunkt wieder eingelesen werden.
+
+= Netz protokollieren =
+ Protokolliert alle Daten, die �ber das Internet empfangen bzw. gesendet
+ werden. Dieses Protokoll kann �ber "Protokolldatei laden" zu einem
+ sp�teren Zeitpunkt wieder eingelesen werden. Wenn Sie keine
+ Schnittstelle gestartet haben und Ihre Position oder die eigenen
+ Objekte lokal protokollieren wollen, ist dies die geeignete Methode.
+
+= IGate protokollieren =
+ Protokolliert alle weitergereichten Daten in beide Richtungen, bei
+ unterdr�ckten Weiterleitungen auch den Grund hierf�r. Dies beinhaltet
+ auch NWS Nachrichten, die in Richtung Funk weitergeleitet werden
+ (gem�� ~/.xastir/data/nws-stations.txt: eine Textdatei, die alle
+ Rufzeichen bzw. NWS Station wie z.B. "SECIND" angibt, deren Daten
+ �ber Funk weitergegeben werden sollen).
+
+= Wetter protokollieren =
+ Protokolliert alle Wetterdaten, die von Ihrer Wetterstation empfangen
+ werden.
+
+HELP-INDEX>Wiedergeben einer Protokolldatei
+
+ Wiedergeben einer Protokolldatei
+
+Klicken sie auf Datei, dann auf "Protokolldatei laden". In einem
+Auswahlfenster k�nnen sie eine Datei ausw�hlen, deren Inhalt von Xastir
+geladen werden soll. Es mu� sich dabei um eine Datei mit TNC Rohdaten
+handeln, wie sie auch von Xastir als Protokolldatei geschrieben werden
+kann. Die Station funktioniert dabei weiterhin wie gewohnt, die
+eingespielten Daten werden aber nicht wieder ausgesendet. Wenn sie Daten
+protokollieren, finden sie diese Dateien �blicherweise in ~/.xastir/logs/
+
+HELP-INDEX>Finden einer Station
+
+ Finden einer Station
+
+Klicken sie auf Ansicht, dann auf "Station finden". Ein Fenster
+erscheint, in dem sie das Rufzeichen der zu suchenden Station eingeben
+k�nnen. In der Standardeinstellung wird nach �bereinstimmung mit dem
+kompletten Rufzeichen (Exact Match) gesucht.
+
+Bei Objekten, die Kleinbuchstaben enthalten, mu� "Match Case" gew�hlt
+werden! Entgegen dem Namen wird ohne "Match Case" der Suchbegriff nur in
+Gro�buchstaben umgesetzt...
+
+Mit "Finde jetzt!" wird der Suchvorgang gestarted und bei Erfolg der
+Bildausschnitt so justiert, da� die Station mit einer �bereinstimmung
+in der Mitte zu sehen ist.
+
+HELP-INDEX>Gespeicherte Kartenausschnitte
+
+ Gespeicherte Kartenausschnitte
+
+Klicken sie auf Karten, dann auf "Ausschnitte" und sie erhalten ein
+PopUp-Fenster mit fr�her gespeicherten Kartenausschnitten. Beim ersten
+Aufruf wird diese Liste noch leer sein. Sie k�nnen den aktuellen
+Kartenausschnitt unter einem Namen speichern. Geben sie diesen Namen
+unter "Neuer Name" ein und w�hlen anschlie�end "Hinzuf�gen".
+
+Nach Markieren eines Namens aus der Liste k�nnen sie den gespeicherten
+Kartenausschnitt durch "Aktivieren!" wieder herstellen.
+
+Durch Markieren und "L�schen" k�nnen Eintr�ge aus der Liste auch wieder
+entfernt werden.
+
+"Karte - Objekt in Karte suchen" ist eine weitere M�glichkeit, um einen
+Kartenausschnitt zu �ndern, indem ein bestimmtes Objekt bei installierten
+GNIS-Dateien gesucht werden kann.
+
+HELP-INDEX>Verfolgen einer Station
+
+ Verfolgen einer Station (Tracking)
+
+Klicken sie auf Ansicht, dann auf "Verfolge Station". Geben sie das
+Rufzeichen ein und dr�cken sie "Verfolge jetzt!". Die verfolgte Station
+bleibt nun immer auf dem Bildschirm sichtbar. Wenn die Station nahe an
+den Rand des Kartenausschnitts gelangt, wird die Karte nachgef�hrt. Um
+das Tracking wieder aufzuheben klicken sie auf "Verfolgung aufheben".
+
+HELP-INDEX>Schnittstellen Konfiguration
+
+ Schnittstellen Konfiguration
+
+Klicken sie auf Schnittstellen, dann auf Einstellungen
+
+Es erscheint ein Fenster "Installierte Schnittstellen", f�r die
+verschiedenen Ger�te, die sie mit Xastir zusammen benutzen wollen. Dort
+k�nnen sie Schnittstellen hinzuf�gen, l�schen und deren Eigenschaften
+�ndern.
+
+Durch Klick auf "Hinzuf�gen" k�nnen sie ein neues Ger�t anmelden,
+es erscheint ein Fenster zur Auswahl des Schnittstellentyps.
+
+Momentan sind verf�gbar:
+ Serieller TNC
+ Serieller TNC plus GPS mit HSP-Kabel
+ Serieller GPS-Empf�nger
+ Serielle Wetterstation
+ Internet Server
+ AX.25 TNC
+ GPS �ber Netzwerk (via gpsd)
+ Wetterstation �ber Netzwerk
+
+Markieren sie das gew�nschte Ger�t aus der Liste und Klicken auf
+"Hinzuf�gen", es erscheint dann ein Fenster, indem sie die verschiedene
+Eigenschaften f�r dieses Ger�t festlegen k�nnen. Tragen sie die
+ben�tigten Werte ein und best�tigen sie mit OK.
+
+Ein Ger�t kann nach Markierung mit einem Klick auf "L�schen" wieder
+entfernt werden.
+
+Mit "Einstellungen" erhalten sie f�r das markierte Ger�t aus der
+Schnittstellenliste ein Fenster, indem sie verschiedene Parameter �ndern
+k�nnen.
+
+Weiterf�rende Hilfe findet man in den Abschnitten f�r die einzelnen
+Schnittstellentypen.
+
+HELP-INDEX>Serieller TNC
+
+ Serieller TNC
+
+Dieser Abschnitt behandelt das Hinzuf�gen oder �ndern von seriellen TNCs
+und seriellen TNCs mit einem GPS �ber ein HSP-Kabel.
+
+Wenn sie ein HSP-Kabel besitzen, k�nnen sie diesen Eintrag ausw�hlen und
+dann sowohl den TNC als auch den GPS-Empf�nger �ber die gleiche serielle
+Schnittstelle anschlie�en. Es handelt sich um ein spezielles Kabel, bei
+dem die Empfangsleitung durch den Computer zwischen den beiden Ger�ten
+umgeschaltet werden kann. Es arbeitet m�glicherweise nicht mit allen
+m�glichen Kombinationen von Computer, TNC und GPS. Der TNC und der GPS
+m�ssen auf die gleichen Kommunikationsparameter eingestellt werden,
+�blicherweise also 4800 bps, 8 Datenbits, keine Parit�t und 1 Stopbit.
+
+Optionen f�r die TNC-Schnittstelle:
+Durch Markieren von "Beim Start aktivieren" wird Xastir bei jedem
+Programmstart versuchen, diese Schnittstelle einzuschalten.
+
+"Senden erlaubt" legt fest, ob �ber diese Schnittstelle �berhaupt Daten
+gesendet werden d�rfen.
+
+Als TNC Port wird das Unix Device eingetragen, mit dem der TNC (oder TNC
+und GPS) verbunden ist. Normalerweise geben sie hier /dev/ttyS0 (COM1),
+/dev/ttyS1 (COM2) etc. an.
+
+Setzen sie nun die Baudrate und die Anzahl der Datenbits. 8N1 steht f�r
+8 Datenbits, keine Parit�t und 1 Stopbit, 7E1 f�r 7 Datenbits, gerade
+Parit�t und 1 Stopbit und 7O1 arbeitet mit ungerader Parit�t. Bei
+Verwendung des HSP-Kabels m�ssen diese Einstellungen f�r TNC und GPS
+identisch sein.
+
+Mit den IGate Optionen k�nnen sie festlegen, in welche Richtung
+Internetverkehr �ber diese Schnittstelle erfolgen kann. Dies kann f�r
+jedes Ger�t getrennt eingestellt werden. Wenn sie kein IGate betreiben,
+lassen sie die Einstellungen auf "Disable".
+
+Tragen sie bis zu drei UNPROTO Pfade ein, Xastir gibt dabei das
+Zielrufzeichen vor. Falls mehrere Pfade (bis zu drei) eingetragen wurden,
+so verwendet Xastir diese abwechselnd bei jeder Aussendung, um so auch in
+schwierigen Situationen geh�rt zu werden. Wenn sie nur lokalen Verkehr
+haben, so gen�gt ein einzelnes WIDE2-2. Bei wenig Leistung oder gr��erer
+Entfernung von einem Digipeater d�rfte "WIDE1-1,WIDE2-2" besser funktionieren.
+Wenn sie das Rufzeichen eines benachbarten Digis kennen, k�nnen sie auch
+alle Pakete �ber diesen schicken, indem sie es an erster Stelle nennen,
+also z.B. "DB0XYZ,WIDE2-2". F�r die meisten Stationen wird ein Pfad gen�gen,
+in abgelegenen Gegenden oder unter schwierigen Bedingungen kann es
+sinnvoll sein, mehrere einzutragen. Am besten l��t es sich mit �rtlichen
+Funkamateuren abkl�ren, welcher Pfad geeignet ist, um einerseits gut
+geh�rt zu werden, andererseits aber die Frequenzen nicht unn�tig zu
+belasten. In Gegenden mit intelligenten Digis, die Wiederholungsschleifen
+weitgehend vermeiden, kann auch z.B. WIDE3-3 oder "WIDE1-1,WIDE3-3"
+verwendet werden.
+
+Die TNC Startup und Shutdown Dateien befinden sich im Verzeichnis
+/usr/local/share/xastir/config und werden beim Starten bzw. Stoppen der
+TNC-Verbindung zur Initialisierung ausgef�hrt. Es handelt sich um
+normale Textdateien mit Kommandos, die an den TNC gesendet werden.
+
+HELP-INDEX>AX.25 TNC Schnittstellen
+
+ AX.25 TNC Schnittstellen
+
+Als AX.25 TNC Device kann jedes Ger�t verwendet werden, da� �ber ein
+Linux AX.25 Treiber angesprochen werden kann. Hierbei handelt es sich um
+einen Kernel-Treiber, der z.B. auch das Baycom-Modem oder ein Packet
+Radio �ber die Soundkarte unterst�tzt. Diese Ger�te m�ssen vor dem Start
+von Xastir in Linux eingerichtet werden, bevor sie benutzt werden k�nnen.
+
+Durch Markieren von "Beim Start aktivieren" wird Xastir bei jedem
+Programmstart versuchen, diese Schnittstelle einzuschalten.
+
+"Senden erlaubt" legt fest, ob �ber diese Schnittstelle �berhaupt Daten
+gesendet werden d�rfen.
+
+Mit den IGate Optionen k�nnen sie festlegen, in welche Richtung
+Internetverkehr �ber diese Schnittstelle erfolgen kann. Dies kann f�r
+jedes Ger�t getrennt eingestellt werden. Wenn sie kein IGate betreiben,
+lassen sie die Einstellungen auf "Disable".
+
+Geben sie den f�r das AX.25-Ger�t festgelegten Device-Namen an, wie er
+in der Datei /etc/ax25/axports steht.
+
+Tragen sie bis zu drei UNPROTO Pfade ein, Xastir gibt dabei das
+Zielrufzeichen vor. Falls mehrere Pfade (bis zu drei) eingetragen wurden,
+so verwendet Xastir diese abwechselnd bei jeder Aussendung, um so auch in
+schwierigen Situationen geh�rt zu werden. Wenn sie nur lokalen Verkehr
+haben, so gen�gt ein einzelnes WIDE2-2. Bei wenig Leistung oder gr��erer
+Entfernung von einem Digipeater d�rfte "WIDE1-1,WIDE2-2" besser funktionieren.
+Wenn sie das Rufzeichen eines benachbarten Digis kennen, k�nnen sie auch
+alle Pakete �ber diesen schicken, indem sie es an erster Stelle nennen,
+also z.B. "DB0XYZ,WIDE2-2". F�r die meisten Stationen wird ein Pfad gen�gen,
+in abgelegenen Gegenden oder unter schwierigen Bedingungen kann es
+sinnvoll sein, mehrere einzutragen. Am besten l��t es sich mit �rtlichen
+Funkamateuren abkl�ren, welcher Pfad geeignet ist, um einerseits gut
+geh�rt zu werden, andererseits aber die Frequenzen nicht unn�tig zu
+belasten. In Gegenden mit intelligenten Digis, die Wiederholungsschleifen
+weitgehend vermeiden, kann auch z.B. WIDE3-3 oder "WIDE1-1,WIDE3-3"
+verwendet werden.
+
+Anmerkung: Um die AX.25 Treiber verwenden zu k�nnen, mu� Xastir unter
+"root"-Rechten laufen. Um Xastir als normaler Benutzer zu starten, mu�
+das suid Bit beim Xastir-Programm gesetzt werden. Hierzu dient das
+folgende Kommando (als root): "chmod a+s /usr/local/bin/xastir".
+
+Beachten sie bitte, da� jedes Programm, das auf diese Weise l�uft, als
+Sicherheitsrisiko angesehen werden kann. Es wurde nicht besonders auf
+m�gliche Sicherheitsrisiken hin getestet, benutzen sie es also in einer
+Mehrbenutzer-Umgebung mit Vorsicht und auf eigenes Riskio!
+
+HELP-INDEX>Serieller GPS
+
+ Serieller GPS
+
+Setzen sie die serielle Schnittstelle f�r den GPS Empf�nger. G�ngige
+Eintr�ge sind hier /dev/ttyS0 (COM1) oder /dev/ttyS1 (COM2).
+
+Durch Markieren von "Beim Start aktivieren" wird Xastir bei jedem
+Programmstart versuchen, diese Schnittstelle einzuschalten.
+
+Setzen sie nun die Baudrate und die Anzahl der Datenbits. 8N1 steht f�r
+acht Datenbits, keine Parit�t und 1 Stopbit, 7E1 f�r 7 Datenbits, gerade
+Parit�t und 1 Stopbit und 7O1 arbeitet mit ungerader Parit�t. Die Daten
+m�ssen mit denen des GPS-Empf�ngers �bereinstimmen, die meisten Ger�te
+verwenden im ben�tigten NMEA-Modus 4800 bps und 8N1.
+
+HELP-INDEX>GPS �ber Netzwerk
+
+ GPS �ber Netzwerk
+
+Wenn sie die GPS-Daten f�r verschiedene Programme bzw. Computer
+ben�tigen, ist diese Auswahl die geeignetste. Hierzu mu� vorher der gpsd
+eingerichtet worden sein, von dem Xastir dann, neben anderen Programmen,
+die GPS-Daten beziehen kann.
+
+Tragen sie Namen (oder IP-Adresse) und Port-Nummer f�r den gpsd Rechner
+in ihrem Netzwerk ein.
+
+Durch Markieren von "Beim Start aktivieren" wird Xastir bei jedem
+Programmstart versuchen, diese Schnittstelle einzuschalten.
+
+Durch Markieren von "Wiederverbinden nach Fehler" versucht Xastir die
+Netzwerkverbindung nach einem Fehler wieder herzustellen.
+
+HELP-INDEX>Internet Server
+
+ Internet Server
+
+Internet Server erlauben ihnen Daten aus der ganzen Welt zu empfangen und
+lokale Daten ins Internet zu senden.
+
+Durch Markieren von "Beim Start aktivieren" wird Xastir bei jedem
+Programmstart versuchen, diese Schnittstelle einzuschalten.
+
+"Senden erlaubt" legt fest, ob �ber diese Schnittstelle �berhaupt Daten
+ins Internet gesendet werden d�rfen.
+
+Tragen sie Namen (oder IP-Adresse) und Port-Nummer des Internet Servers
+ein, den sie ansprechen wollen.
+
+Geben sie einen g�ltigen Schl�ssel (Pass-Code) ein um Daten �ber ein
+IGate senden zu k�nnen. Wenn sie keinen Schl�ssel passend zu ihrem
+Rufzeichen haben, k�nnen sie einen mit dem beigef�gten Programm
+"callpass" erzeugen. Wenn es noch nicht bereits kompiliert wurde, geben
+hierzu sie im src Verzeicnis "make callpass" ein.
+
+Durch Markieren von "Wiederverbinden nach Fehler" versucht Xastir die
+Netzwerkverbindung nach einem Fehler wieder herzustellen.
+
+HELP-INDEX>Serielle Wetterstation
+
+ Serielle Wetterstation
+
+Tragen sie die serielle Schnittstelle f�r die Wetterstation ein. G�ngige
+Eintr�ge sind hier /dev/ttyS0 (COM1) oder /dev/ttyS1 (COM2).
+
+Durch Markieren von "Beim Start aktivieren" wird Xastir bei jedem
+Programmstart versuchen, diese Schnittstelle einzuschalten.
+
+Setzen sie nun die Baudrate und die Anzahl der Datenbits. 8N1 steht f�r
+acht Datenbits, keine Parit�t und 1 Stopbit, 7E1 f�r 7 Datenbits, gerade
+Parit�t und 1 Stopbit und 7O1 arbeitet mit ungerader Parit�t. Die Daten
+m�ssen mit denen ihrer Wetterstation �bereinstimmen.
+
+Durch die Angabe der "Datenart" kann festgelegt werden, welche Daten das
+Programm �ber die serielle Schnittstelle erwartet. Bei "Automatisch" wird
+zun�chst nach Wetterdaten im Bin�rformat geschaut, wie es die Radio Shack
+WX-200 Wetterstation liefert. Falls keine Bin�rdaten im Datenstrom
+gefunden werden, versucht Xastir eine Wetterstation mit ASCII-Daten zu
+finden (wie Peet Bros.).
+
+HELP-INDEX>Wetterstation �ber Netzwerk
+
+ Wetterstation �ber Netzwerk
+
+Xastir kann Wetterdaten Server wie den wx200d ansprechen. wx200d erlaubt
+mehrere Netzwerkverbindungen, so da� Wetterdaten gleichzeitig
+verschiednen Programmen oder Computern zur Verf�gung steht.
+
+Tragen sie Namen (oder IP-Adresse) und Port-Nummer des Wetterdaten
+Servers in ihrem Netzwerk ein.
+
+Durch Markieren von "Beim Start aktivieren" wird Xastir bei jedem
+Programmstart versuchen, diese Schnittstelle einzuschalten.
+
+Durch Markieren von "Wiederverbinden nach Fehler" versucht Xastir die
+Netzwerkverbindung nach einem Fehler wieder herzustellen.
+
+Wie im vorigen Abschnitt kann durch Angabe von "Datenart" die
+automatische Auswahl �berschrieben werden.
+
+HELP-INDEX>Ausdrucken des Bildschirms
+
+ Ausdrucken des Bildschirms
+
+Xastir kann den dargestellten Kartenausschnitt in Schwarz-Wei� oder in
+Farbe ausdrucken. Hierbei wird das Bild zun�chst als XPixmap-Datei
+gespeichert, dann werden externen Zusatzprogramme gestartet, um es ins
+PostScript-Format zu konvertieren, zu skalieren und rotieren, eine
+Vorschau zu erm�glichen und es schlie�lich zu drucken.
+
+Hierf�r mu� Ihr System so eingerichtet sein, da� Sie PostScript-Dateien
+drucken k�nnen, gew�hnlich wird hierf�r ghostscript, installierte
+Druckerfilter sowie ein lp oder lpr Druckerspooler ben�tigt. F�r die
+Erstellung der Ausdrucke m�ssen dann die folgenden Pakete installiert
+sein: ImageMagick (speziell "convert"), Ghostscript nebst Schriften, und
+"gv". Wenn diese Pakete funktionsf�hig sind, so sollte kurz nach dem
+Druckbefehl in Xastir ein "gv"-Fenster aufgehen, in dem man das Druckbild
+zun�chst begutachten kann. Falls das Ergebnis zufriedenstellend ist, kann
+es von gv aus ausgedruckt werden.
+
+Beachten Sie, da� es in Abh�ngigkeit von den dargestellten Karten
+sinnvoll sein kann, den Kartenhintergrund auf wei�e Farbe zu �ndern,
+hierdurch kann gegebenenfalls einiges an Tinte gespart werden.
+
+HELP-INDEX>Erstellen automatischer Schnappsch�sse
+
+ Erstellen automatischer Schnappsch�sse
+
+Xastir hat die F�higkeit, wiederholt automatische Schnappsch�sse des
+dargestellten Kartenausschnitts anzufertigen. Momentan erfolgt dies alle
+f�nf Minuten. Unter der Voraussetzung, da� "convert" aus dem ImageMagick-
+Paket installiert ist, erzeugt Xastir eine XPM-Datei in /var/tmp und
+konvertiert diese dann in die PNG-Datei /var/tmp/xastir_snap.png.
+Hiermit kann das aktuelle Geschehen z.B. auf einer regelm��ig
+aktualisierten Webpage dargestellt werden. Schnappsch�sse werden �ber
+Datei - Schnappsch�sse eingeschaltet.
+
+HELP-INDEX>Symboltabelle
+
+ Symboltabelle
+
+Dies sind die Definitionen der f�r ihre Station oder f�r Objekte
+w�hlbaren Symbole. Es stehen zwei Gruppen zur Verf�gung, mit teilweise
+unterschiedlichen Symbolen bei gleichem Symbolbuchstaben. Die Grafiken
+aus der alternative Gruppe "\" werden auch herangezogen, wenn ein Overlay
+erfolgen soll. Hierzu wird als Gruppe ein Buchstabe [A-Z] oder eine
+Zahl [0-9] eingegeben, dies erscheint dann �berlagert �ber dem Symbol.
+Die aktuelle Liste findet man in der APRS Reference, die es bei
+http://www.tapr.org gibt.
+
+
+ Symboltabelle
+
+Symbol Group / Group \
+
+! Triangle w/! Triangle w/!
+" Rain Cloud Rain Cloud
+# Digi DIGI
+$ Phone Symbol $ Symbol
+% DX DX
+& GATE-HF GATE
+' Small Aircraft Aircraft Crash
+( Cloud Cloud
+) TBD
+* SNOW Flake SNOW Flake
++ Red Cross
+, Reverse L
+- House w/omni
+. Small x
+/ Red Dot
+0 0 in a box Circle
+1 1 in a box
+2 2 in a box
+3 3 in a box
+4 4 in a box
+5 5 in a box
+6 6 in a box
+7 7 in a box
+8 8 in a box
+9 9 in a box GAS
+: Fire ?
+; Tent Tent
+< Motorcycle Pennant
+= Train Engine
+> Car Car
+? POS Antenna ? in a box
+@ HURRICANE/STORM HURRICANE/STORM
+A First Aid Box
+B BBS Blowing Snow
+C Canoe
+D D in a circle
+E E in a circle Smoke Stack
+F F in a circle
+G Grid Square Antenna ?
+H Hotel/Bed
+I TCP/IP ?
+J J in a circle Lightening
+K School House
+L Light House Light House
+M Mac
+N NTS ?
+O Balloon
+P Police car Rx
+Q Circle with in Circles Circle with in Circles
+R RV Restaurant
+S Shuttle Satellite
+T Thunderstorm (cloud/bolt) Thunderstorm (cloud/bolt)
+U School Bus Sun
+V VOR TAC VOR TAC Symbol
+W National Weather Service NWS-Digi
+X Helicopter
+Y Sail Boat
+Z Windows
+[ Runner WC
+\ DF Triangle
+] Packet Mail Box
+^ Large Aircraft Large Aircraft
+_ Weather Station WS-Digi
+` Satellite Dish
+a Ambulance
+b Bike blowing cloud
+c DX antenna
+d Fire dept. DX Antenna
+e Horse Sleet cloud
+f Fire Truck FC Cloud
+g glider Pennant (2)
+h Hospital HAM
+i Island Island
+j Jeep Jeep
+k Truck Truck
+l Small dot Small Dot
+m MIC Mile Post
+n N Small Triangle
+o EOC Dot with in Circles
+p Puppy Dot with in Circles
+q GS Antenna GS Antenna
+r Antenna Tower Antenna Tower
+s Boat Boat
+t TS ?
+u 18 Wheel Truck
+v Van Dot with in Circles
+w H20 Flood
+x X Windows Red Dot
+y House w/Yagi House w/yagi
+z X Windows
+{ FOG FOG
+| Black Line Black Line
+} TCP TCP
+~ Sail Boat Sail Boat
+
+HELP-INDEX>Was war neu in Xastir V1.0
+
+ Was war neu in Xastir V1.0
+
+W�hrend des vergangenen Jahres wurde Xastir weiterentwickelt und dieses
+Release ist das Ergebnis dieser Bem�hungen. Die Entwicklung wurde von
+Chuck Byam geleitet, der das Projekt mit dem Einverst�ndnis von Frank
+Giannandrea �bernommen hat. Viele andere haben zum Erfolg des Projects
+beigetragen, eine Auflistung findet sich in der Datei AUTHORS.
+
+Das Xastir Paket benutzt nun GNU autoconf um die Makefiles zu erstellen
+und verschiedene Eigenschaften aufgrund der installierten Bibliotheken
+und Software auszuw�hlen.
+
+Beim Start von Xastir V1.0 werden sie wom�glich nicht sofort gr��ere
+�nderungen entdecken. Die bekannte Bedienoberfl�che wurde weitgehend
+beibehalten. Der gr��te Teil der �nderungen bleibt im Verborgenen und
+dient einer Steigerungen der Effizienz:
+
+o Die Startzeit des Programms wurde verbessert
+
+o Der Speicherbedarf wurde durch dynamische Speicherzuweisung f�r
+ Stationen, Spuren und Wetterdaten stark verbessert. D.h. es wird kein
+ Speicher mehr verschwendet f�r nicht vorhandene Spurdaten bei festen
+ Stationen oder Wetterdaten bei den meisten Stationen. Mit diesen
+ �nderungen ist es m�glich, Xastir komfortabel mit dem Internet zu
+ verbinden, auch wenn nur sehr wenig Speicher vorhanden ist.
+
+o Das Laden der Karten wurde verbessert, indem nun nicht mehr bei jeder
+ kleinen �nderung die Karte neu von der Festplatte geladen werden mu�.
+ Wetterwarnungen und �nderungen an den Einstellungen f�r die Darstellung
+ und Tracking Optionen erfordern kein Neuladen der Karten, stattdessen
+ werden nur die Symbole und die Spuren neu gezeichnet.
+
+o Verschiedene Dialog-Fenster, die fr�her h�ufig neu gezeichnet wurden,
+ werden nun nur bei Bedarf aktualisiert und sind damit auch auf
+ langsameren Systemen akzeptabel. Dies gilt auch f�r das Verfolgen einer
+ Station (Tracking), wobei die Karte nun nur neu gezeichnet wird, wenn
+ die Station sich dem Rand des Bildschirms n�hert.
+
+Dank dieser �nderungen kann Xastir problemlos auch auf langsameren
+Pentium(tm) Rechnern eingesetzt werden.
+
+Unterst�tzung f�r das GeoTIFF Kartenformat ist nun vorhanden und wird
+in Xastir einkompiliert, wenn die GeoTiff Bibliotheken auf dem System
+installiert sind. Diese Karten sind von hoher Qualit�t und besonders f�r
+Such- und Rettungsoperationen zu gebrauchen. Karten in diesem Format sind
+vom USGS und kommerziell auf CD-ROM erh�ltlich. Xastir wei�, wie das
+Datum von NAD-27 in WGS-84 umzurechnen ist, so da� Karten in beiden
+Formaten ohne Genauigkeitsverlust gelesen werden k�nnen. Zus�tzliche
+Tasten wurden in der Kartenauswahl hinzugef�gt, um schnell alle Karten
+einer bestimmten Art auszuw�hlen.
+
+Das oben gesagte gilt in erster Linie f�r die USA, wo es jede Menge
+Karten gibt. Bei uns gibt es zwar sch�nere topgraphische Karten, daf�r
+gibt es aber so gut wie nichts kostenlos, und damit auch kein
+verbreitetes Standardformat.
+
+Xastir unterst�tzt nun das Setzen und L�schen von Objekten. Objekte
+k�nnen verwendet werden, um Treffen anzuzeigen, Reisenden Hinweise zu
+geben oder Such- und Rettungseins�tze durchzuf�hren.
+
+Die amerikanischen County Wetterwarnungs-Karten werden nicht mehr direkt
+auf die Karten gezeichnet, sondern mit der Karte �berlagert. Einerseits
+sind die Farben dadurch verf�lscht, aber es ist nun m�glich, die
+Stra�enkarten auch im Warnungsgebiet zu erkennen.
+
+Eine neue und n�tzliche Eigenschaft ist, da� sich die Ausrichtung einiger
+Symbole �ndert, je nachdem in welche Richtung sich z.B. ein Fahrzeug
+bewegt. Auch ohne die zur�ckgelegte Spur kann man die Richtung einer
+Mobilstation mit einem Blick erfassen. Es gibt einige weitere Optionen
+im Menu Darstellung mit denen man genauer festlegen kann, was angezeigt
+werden soll und was nicht.
+
+Das Verschieben und die Kontrolle �ber den Kartenausschnitt wurde
+verbessert: Es gibt nun Pfeile oben rechts im Menu, um die Karte mit der
+Maus zu verschieben. Die Karte kann auch mit den Cursortasten verschoben
+werden und die Vergr��erung kann mit den PgUp und PgDn Tasten eingestellt
+werden. Im PopUp-Menu der linken Maustaste gibt es neue Optionen um die
+Karte an der aktuellen Position zu zentrieren oder dort ein Pbjekt zu
+platzieren. Die Verschiebem�glichkeiten �ber dieses Menu wurden zugunsten
+der oben genannten entfernt.
+
+Unterst�tzung f�r Alternative Netzwerke wurde hinzugef�gt, hiermit wird
+es m�glich, ein privates APRS(tm) Netzwerk einzurichten f�r
+Veranstaltungen, f�r Such- und Rettungseins�tze, Sturmjagd, oder f�r
+alles wo der Benutzer nicht von Hunderten von APRS(tm)-Stationen um ihn
+herum genervt werden will.
+
+Es gibt viele kleine �nderungen, sichtbar oder unsichtbar f�r den
+Benutzer. Die Schnittstellen-Steuerung hat nun eine Option, um alle
+Schnittstellen gleichzeitig zu starten oder zu stoppen, um dem Benutzer
+es zu ersparen, dies f�r jede Schnittstelle einzeln tun zu m�ssen. Die
+Stationseinstellungen zeigen nun das gew�hlte Symbol, so da� man das
+Fenster nicht mehr verlassen mu�, um es zu sehen. Einige Puffer�berl�ufe,
+die unvorhersagbares Verhalten oder Programmabst�rze hervorgerufen
+hatten, wurden beseitigt. Und viele kleinere �nderungen wurden am
+Quelltext vorgenommen, damit Xastir auf verschiedenen Systemen fehlerfrei
+�bersetzt werden kann.
+
+Viel Freude mit dem neuen Xastir!
+
diff --git a/help/help-Italian.dat b/help/help-Italian.dat
new file mode 100644
index 0000000..ea9e6ea
--- /dev/null
+++ b/help/help-Italian.dat
@@ -0,0 +1,1047 @@
+HELP-INDEX>Leggimi - Licenza
+
+ Leggimi - Licenza
+
+Per informazioni sulla versione corrente del programma leggere README.1ST nella
+cartella di Xastir.
+
+Questo programma � sviluppato per essere usato all'interno della comunit�
+radioamatoriale, negli Stati Uniti la FCC non autorizza a trasmettere per radio
+se non sei radioamatore.
+Gli utenti di altri paesi devono attenersi alle leggi locali in merito.
+
+
+LICENZA:
+
+XASTIR, Amateur Station Tracking and Information Reporting
+Copyright (C) 1999,2000 Frank Giannandrea
+Copyright (c) 2000-2012 The Xastir Group
+
+Questo programma � un software libero; pu�' essere ridistribuito e modificato
+secondo i termini della Licenza GNU GPL, pubblicata dalla Free Software
+Foundation;
+anche la versione 2 della licenza � valida, come anche le versioni seguenti.
+
+ma SENZA ALCUNA GARANZIA; senza la garanzia di COMMERCIABILITA' o ADATTAMENTO
+PER UN PARTICOLARE USO. Vedere la Licenza GNU GPL per maggiori dettagli.
+
+Dovrebbe essere pervenuta a voi la licenza GNU assieme al programma; se cos�
+non fosse segnalate l'evento alla Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Ulteriori informazioni sul software possono essere ottenute via:
+Web,
+ http://www.xastir.org
+ http://sourceforge.net/projects/xastir/
+ http://xastir.sourceforge.net
+
+
+Per maggiori informazioni riguardo la licenza pubblica GNU GPL:
+ http://www.gnu.org
+
+
+HELP-INDEX>Benvenuti! e note dell'Autore
+
+ Benvenuti! - note dell'autore
+
+XASTIR, o X-windows Amateur Station Tracking and Information Reporting.
+
+� un programma APRS(tm) sviluppato liberamente e di libero uso, pu� essere
+liberamente distribuito. Attualmente il programma � in fase di sviluppo e non
+deve essere visto come un prodotto finito! Il tuo aiuto servir� a renderlo
+migliore.
+Se sai programmare o vuoi scrivere documentazione, il tuo aiuto mi risulter�
+molto gradito! Ho molte idee ma cos� poco tempo! Quindi se pensi che manchi
+qualcosa, fammelo sapere.
+
+73,
+Frank Giannandrea
+
+Traduzione della guida a cura di Alessandro Frigeri, IK0YUP.
+
+APRS[tm] � un marchio registrato di Bob Bruninga,
+la sua pagina � "http://web.usna.navy.mil/~bruninga/aprs.html"
+
+HELP-INDEX>Novit� in Xastir 1.0
+
+ Novit� in Xastir 1.0
+
+Over the past year, Xastir has been under active development, and this new
+release is the culmination of those efforts. Development has been run by
+Chuck Byam, who agreed to take over for Frank Giannandrea. Many other
+individuals have contributed to this project, and are listed in the AUTHORS
+file.
+
+Nell'ultimo anno, Xastir � passato per una fase di notevole sviluppo, e questa
+nuova versione � il culmine dell'impegno di questo periodo. Lo sviluppo �
+stato coordinato da Chuck Byam, a cui Frank Giannandrea ha passato il
+testimone.
+Altre persone hanno contribuito allo sviluppo di questo progetto, e sono
+elencati nel file AUTHORS.
+
+Il programma Xastir ora utilizza GNU autoconf per la costruzione dei Makefile
+e la selezione delle caratteristiche in base alle librerie e del software
+installato nel sistema. Non sono quindi necessarie modifiche ai Makefile come
+nelle versioni precedenti.
+
+Avviando Xastir 1.0 probabilmente non si noteranno grandi differenze.
+L'interfaccia utente gi� buona � stata mantenuta pressoch� inalterata. La
+maggior parte dei cambiamenti � avvenuta in un miglioramento delle prestazioni
+complessive:
+* Sono stati migliorati i tempi di avvio del programma.
+* E' stato migliorato l'utilizzo della memoria, con l'allocazione dinamica
+ dei dati di stazione, tracciati, meteo. Non verr� utilizzata inutilmente
+ memoria per dati non aggiornati. Con questa modifica, Xastir potr� essere
+ collegato ad un server internet anche in un computer con 16Mb di RAM.
+* E' stata migliorata la modalit� di caricamento delle mappe. Infatti una
+ mappa non verr� pi� ricaricata per un semplice cambiamento di dat ida una
+ stazione. Allarmi meteo e tracciati di stazioni in movimento saranno
+ disegnati a parte.
+* Miglioramenti sono stati apportati nella frequenza d visualizzazione di
+ alcune finestre di dialogo che nella versione precedente apparivano con
+ una alta frequenza.
+
+Grazie a questi cambiamenti Xastir � perfettamente funzionante anche su
+computer lenti.
+
+Il supporto per le mappe GeoTIFF ora � incluso nel codice e verr� attivato se
+nel sistema sono presenti le librerie GeoTIFF. Questi file contengono mappe
+di alta qualit�, utili specialmente in operazioni di soccorso. Questo
+formato di mappe � disponibile presso l'USGS (United States Geological Survey)
+oppure commercialmente su CDROM. Xastir convertir� automaticamente le mappe
+trasferendo il datum NAD-27 al WGS-84. Sono state abilitate delle
+scorciatoie tramite tastiera che permettono di caricare tutte le mappe
+disponibili per una particolare area.
+
+E' disponibile il supporto per Festival Speech Synthesis System per l'annuncio
+vocale di nuovi dati in arrivo. Il precedente sistema di avvisi sonori �
+ancora disponibile.
+
+Xatir ora supporta la possibilit� di aggiungere oggetti alle mappe. Questa
+possibilit� fornisce all'utente molte possibilit� di utilizzo in coordinazione
+di eventi e operazioni di soccorso.
+
+Le mappe di allarme meteo (ndt: solo USA, per ora) sono visualizzate con una
+trasparenza, permettendo di vedere le mappe geografiche sottostanti.
+
+Una nuova ed utile funzione � il cambiamento della orientazione di un simbolo
+in base alla direzione del suo movimento. Anche senza un percorso, � possibile
+sapere la direzione di una stazione modile.. Ci sono diverse nuove funzioni
+nel men� di visualizzazione, che permettono all'utente di visualizzare solo le
+informazioni interressanti al momento.
+
+Il controllo di visualizzazione delle mappe � stato migliorato: sono presenti
+dei bottoni a freccia nella parte alta dello schermo. Le mappe possono essere
+cos� spostate con i suddetti bottoni, con i tasti freccia della tastiera e
+lo zoom pu� essere regolato con i tasti Pag-SU e Pag-Gi� della tastiera.
+Nel men� che appare cliccando sulla mappa � disponibile la nuova funzione che
+permette di centrare la mappa in un dato punto. Le funzioni di spostamento
+della mappa sono state rimosse in quanto presenti i bottoni in alto nello
+schermo.
+
+E' stato aggiunto il supporto altnet per permettere di avere reti APRS(tm)
+locali per eventi speciali, operazioni di soccorso, allarmi meteo o qualsiasi
+situazione in cui non � necessario analizzare dati da altre stazioni.
+
+Ci sono numerosi cambiamenti minori, visibili ed invisibili all'utente.
+Il controllo di interfaccia ha ora il bottone "Avvia tutte" e "Arresta tutte"
+per permettere all'utente di avviare tutte le interfacce in una sola
+operazione. La finestra di dialogo della configurazione della stazione ora
+mostra l'icona scelta, cos� non � pi� necessario controllare sulla mappa quale
+icona � stata scelta. Sono stati corretti errori nel codice che davano errori
+di overflow di memoria. Altre correzioni sono state fatte per rendere il
+codice compilabile senza problemi su diverse piattaforme con fiversi sistemi.
+
+E ora: Buon divertimento con il nuovo Xastir!
+
+
+
+HELP-INDEX>Avviare Xastir
+
+ Avviare Xastir per la prima volta
+
+La prima volta che si lancia Xastir, dovrebbe essere fatto da un terminale in
+maniera tale che qualsiasi messaggio di errore salti alla vista. Nella maggior
+parte dei sistemi il percorso di ricerca dei file eseguibili comprende la
+cartella /usr/local/bin e tutto quello che serve per avviare il programma �
+dare il comando xastir al prompt. Nei sistemi dove il percorso
+"/usr/local/bin" non � impostato bisogner� digitare "/usr/local/bin/xastir" per
+avviare il programma.
+
+Si pu� anche impostare un linguaggio diverso dall'originale. Per impostare o
+cambiare il linguaggio usato da xastir bisogna utilizzare la seguente sintassi:
+
+xastir -l
+
+Attualmente le scelte sono: English Dutch French German Spanish Italian
+ ElmerFudd MuppetsSwedishChef OldeEnglish PigLatin
+ PirateEnglish
+
+Questa opzione viene memorizzata nel file di configurazione dell'utente e resa
+disponibile per i seguenti usi del programma. Per le nuove installazioni
+Xastir user� l'inglese a meno che non venga specificato un linguaggio
+differente con l'opzione -l.
+
+NOTA: Nei menu, le opzioni in grigio sono quelle selezionate, come anche nelle
+opzioni di on/off, la scelta attivata sar� evidenziata dalla colorazione grigia.
+
+HELP-INDEX>Informazioni sulla configurazione della stazione
+
+ Informazioni sulla configurazione della stazione
+
+Seleziona Configura la Stazione
+
+Imposta il tuo nominativo nella apposita casella.
+
+Compila le caselle relative alla posizione (Lat,Long) se non si intende usare
+Xastir con un GPS. Se la posizione non � disponibile � possibile individuare la
+posizione sulla mappa e copiare i dati. Latitudine e longitudine potranno
+essere rilevati nella seconda casella partendo da destra, nella parte bassa
+della finestra principale.
+Se si intende utilizzare un GPS si pu� saltare questa sezione e configurare il
+GPS in un secondo momento.
+
+Il simbolo o il gruppo della stazione possono essere cambiati in qualsiasi
+momento, per fare questo si faccia riferimento alla guida ai simboli.
+
+Indicare ora i dati tecnici della stazione: questi dati sono interessanti ma
+non necessari al corretto funzionamento del programma.
+Utilizzare il seguente codice per indicare la potenza che pi� si avvicina a
+quella della vostra stazione:
+
+Codice 0 1 2 3 4 5 6 7 8 9
+Potenza (watts) 0 1 4 9 16 25 36 49 64 81
+
+Esempio: Se si sta trasmettendo con 36 watt, indicare "6".
+
+
+Lo stesso discorso vale per l'altezza, ma bisogna indicare l'altitudine e non
+l'altezza dell'antenna sul terreno.
+
+Codice 0 1 2 3 4 5 6 7 8 9
+Altitudine (piedi)10 20 40 80 160 320 640 1280 2560 5120
+
+Esempio: se l'altitudine della stazione � 1280 piedi, il codice da usare
+ sar� "7".
+
+
+Per impostare il guadagno scrivere semplicemente il valore dello stesso
+espresso in dB, nella apposita casella.
+
+La direzione ha bisogno di un codice che esprime la direzione dell'antenna
+espressa in gradi dal Nord.
+
+Codice 0 1 2 3 4 5 6 7 8 9
+Direzione(gradi) * 45 90 135 180 225 270 315 360 Nessuna
+
+Esempio: Se la vostra antenna � omnidirezionale, impostare "0". Se la
+ direzionalit� � verso nord, impostare "8".
+
+Inserire un commento, non necessario al programma, ma utile agli altri
+operatori.
+
+L'ambiguit� della posizione permette di trasmettere quanto � precisa la
+posizione fornita dalla nostra stazione. Una impostazione con ambiguit� nulla
+permetter� di comunicare alle altre stazioni esattamente la posizione che
+abbiamo impostato o che arriva dal GPS. Le altre scelte posizioneranno la
+stazione nel raggio indicato dal codice impostato.
+
+Selezionando OK, verranno applicati tutti i cambiamenti effettuati, mentre il
+tasto Annulla manterr� le opzioni correnti.
+
+HELP-INDEX>Configurazione delle Unit� di Misura
+
+ Configurazione delle Unit� di Misura
+
+L'impostazione originale del programma � per il sistema metrico, mm, cm, Km/ora
+ecc.
+Per selezionare il sistema di misura anglosassone (pollici,piedi,miglia/ora)
+selezionare Configura, Unit�, quindi il sistema che si vuole usare. L'opzione
+attiva � quella marcata dal grigio.
+
+
+HELP-INDEX>Configurazione delle Operazioni Base
+
+ Configurazione delle Operazioni Base
+
+Selezionare Configura e quindi Predefinito
+
+Questa scheda imposta una configurazione standard. Le vecchie stazioni saranno
+visualizzate con un'icona fantasma. Il "tempo lettura GPS" imposter�
+l'intervallo di tempo per acquisire nuovi dati dal GPS. Questa opzione �
+disponibile per le stazioni dotate di HSP o di un cavo condiviso con il proprio
+TNC.
+
+L'opzione "Trasmissioni Stazione" imposta con quali packet la stazione
+trasmetter� i propri dati.
+
+L'opzione "Trasmetti codici WX", se selezionato, mander� anche un pacchetto di
+dati provenienti dalla stazione meteo.Questa opzione � utile per i tipi di
+stazioni meteo che trasmettono i dati gi� in formato ASCII come le Peet Bros.
+
+Le opzioni Gateway permetteranno di impostare la stazione come un gateway tra
+internet e la rete radio. Questa opzione va usata con cautela, come
+radioamatore ognuno di noi � responsabile per i dati che trasmette, e quindi
+anche per quelli che provengono da internet e vengono trasmessi per radio in
+una simile configurazione.
+
+HELP-INDEX>Configurazione Interfacce
+
+ Configurazione Interfacce
+
+Selezionare Configura e quindi Interfacce.
+
+Dovrebbe apparire una scheda che indica le "Interfacce installate". Questa
+scheda vi permetter� di aggiungere, cancellare, e modificare le propriet�
+delle varie periferiche che possono essere utilizzate con Xastir.
+
+Le opzioni sono:
+TNC Seriale
+TNC Seriale con GPS tramite un cavo HSP
+GPS Seriale
+WX Seriale
+Server Internet
+TNC AX25
+GPS in rete (via gpsd)
+WX in rete
+
+Per aggiungere una periferica, selezionare aggiungi. Apparir� la scheda
+ "Scegli il tipo di interfaccia". Seleziona il tipo di interfaccia che vuoi
+aggiungere.
+Appariranno i parametri di quella periferica. Fornire le impostazioni
+richieste e selezionare "ok"
+
+Per eliminare una periferica, selezionarla e in seguito cliccare sul bottone
+Elimina.
+
+Per modificare le propriet� di una periferica, seleziona la periferica e quindi
+il bottone "Propriet�". La scheda con i parametri della periferica appariranno
+e potranno essere modificati a piacere. Per rendere effettive le impostazioni
+schiacciare il bottone OK dopo aver fatto le modifiche.
+
+HELP-INDEX>Configurazione di TNC Seriali
+
+
+ Configurazione di TNC Seriali
+
+CONFIGURAZIONE DI UN TNC SERIALE
+
+Questa sezione tratta l'impostazione di un TNC Seriale o di un TNC seriale con
+un cavo HSP per il collegamento del GPS.
+
+Se si ha il cavo HSP, che permette di condividere la porta del TNC con quella
+del GPS, la configurazione da selezionare sar� "TNC con GPS". Il cavo HSP � un
+cavo speciale che pu� non essere compatibile con tutte le combinazioni
+computer/TNC/GPS possibili. Se si usa questa configurazione, il TNC e il GPS
+devono avere una impostazione dei parametri di comunicazione che in genere
+prevede: 4800 bps, 8 bit di dati, nessuna parit�, 1 bit di stop.
+
+Opzioni della Porta TNC:
+Selezionando "Attivare all'avvio" si indica a Xastir di caricare questa
+periferica automaticamente all'avvio del programma.
+
+Selezionando "Permetti la Trasmissione", ordina a Xastir che ogni dato inviato
+all'interfaccia pu� essere trasmesso.
+
+La porta del TNC � la porta Unix alla quale � collegato il TNC. In genere sono
+chiamate /dev/ttyS0 (Dos com1), /dev/ttyS1 (Dos com2)
+
+Ora impostare la velocit� e il tipo di comunicazione in "Impostazioni porta", e
+i parametri in "Stile porta". Uno stile di porta 8N1 indica 8 bit di dati,
+Nessuna parit� e 1 bit di stop. 7E1 indica 7 bit di dati, parit� e 1 bit di
+stop. 7O1 indica 7 bit di dati, parit� dispari, e 1 bit di stop. Questi
+parametri DEVONO essere
+comuni sia al TNC che al GPS.
+
+Scegliere ora la corretta impostazione per il Gateway di questa interfaccia.
+Potresti avere diversi TNC e questa opzione pu� essere diversa per ogni TNC.
+Se non intendi attivare le funzionalit� di gateway lascia l'opzione
+"Disabilitato".
+
+Inserisci ora fino a tre percorsi UNPROTO. Xastir assume la parte XX VIA del
+percorso UNPROTO. � possibile impostare tre percorsi differenti in modo da
+ avere alternative nel caso le condizioni non siano buone. Se uno dei percorsi
+� occupato allora Xastir passer� al successivo ad ogni trasmissione e cos� via.
+
+Se sei in una condizione di stazioni locali, semplicemente un WIDE2-2 pu� essere
+una buona scelta. Se stai usando poca potenza e/o sei distante dal digipeater
+allora WIDE1-1,WIDE2-2 potrebbe essere la scelta giusta. Se conosci il nominativo
+del tuo pi� vicino digipeater allora si potr� usare NOMINATIVO_DIGI,WIDE2-2. La
+maggior parte di voi avr� bisogno di un solo percorso. Se ci si trova in un
+area remota e il segnale � difficilmente ascoltabile dalle altre stazioni allora
+potrebbe essere necessario aggiungere dei percorsi. Una buona norma � quella
+di chiedere al gruppo di radioamatori locali quale � il miglio percorso per i
+pacchetti in quella data area.
+
+File di inizializzazione e di spegnimento del TNC. Questi campi specificano i
+nomi di file presenti nelle cartella /usr/local/share/xastir/config. Ognuno
+di questi file di test contiene i comandi che si vogliono mandare al TNC
+all'avvio del programma e al termine dello stesso.
+
+CONFIGURAZIONE DEL TNC AX.25
+
+Questa sezione descrive l'aggiunta e la modifica di interfacce TNC AX.25.
+Per interfacce AX.25 si intendono tutte quelle periferiche che usano i driver
+AX.25 di Linux. Questo driver � a livello di kernel e periferiche come i
+Baycom o soundmodem possono essere usati come TNC. Queste periferiche devono
+essere rese disponibili (funzionanti) al programma prima del suo avvio.
+
+Selezionando "Attiva all'avvio" si ordiner� a Xastir di caricare questa
+interfaccia all'avvio.
+
+Selezionando "Permetti la Trasmissione", si permetter� che i dati vengano
+trasmessi per radio.
+
+Scegliere ora la corretta impostazione per il Gateway di questa interfaccia.
+Potresti avere diversi TNC AX.25 o TNC Seriali e questa opzione pu� essere
+diversa per ogni TNC.
+Se non si intende attivare le funzionalit� di gateway lascia l'opzione
+"Disabilitato".
+
+Impostare il nome della periferica AX.25 come specificato dal file axports.
+
+Inserisci ora fino a tre percorsi UNPROTO. Xastir assume la parte XX VIA del
+percorso UNPROTO. � possibile impostare tre percorsi differenti in modo da
+avere alternative nel caso le condizioni non siano buone. Se uno dei percorsi �
+occupato allora Xastir passer� al successivo ad ogni trasmissione e cos� via.
+
+Se sei in una condizione di stazioni locali, semplicemente un WIDE2-2 pu� essere
+una buona scelta. Se stai usando poca potenza e/o sei distante dal digipeater
+allora WIDE1-1,WIDE2-2 potrebbe essere la scelta giusta. Se conosci il nominativo
+del tuo pi� vicino digipeater allora si potr� usare NOMINATIVO_DIGI,WIDE2-2. La
+maggior parte di voi avr� bisogno di un solo percorso. Se ci si trova in
+un'area remota e il segnale � difficilmente ascoltabile dalle altre stazioni allora
+potrebbe essere necessario aggiungere dei percorsi. Una buona norma � quella
+di chiedere al gruppo di radioamatori locali quale � il miglio percorso per i
+pacchetti in quella data area.
+
+NOTA: Per usare le periferiche AX.25 con Xastir bisogna avere i privilegi di
+root.
+Se si vuole far eseguire Xastir da un utente qualsiasi, bisogner� cambiare il
+suid del programma Xastir. Il comando seguente eseguito da root potr� servire
+allo scopo:
+
+chmod a+s /usr/local/bin/xastir
+
+
+Come qualsiasi programma che venga eseguito in questa modalit�, questo � da
+considerarsi un rischio di sicurezza, visto che il programma ancora non � stato
+sperimentato per reagire a tentativi di intrusione.
+
+Configurazione del GPS
+
+
+ Configurazione GPS Seriali
+
+Imposta la porta seriale che usata dal vostro GPS. Valori comuni sono
+/dev/ttyS0 (dos com1) e /dev/ttyS1 (dos com2).
+
+Selezionando "Attiva all'avvio" si ordiner� a Xastir di caricare questa
+interfaccia all'avvio.
+
+Ora seleziona la velocit� di trasmissione espressa in bps e i parametri della
+porta sotto il menu "stile". Uno stile di porta 8N1 significa 8 but di dati,
+nessuna parit� e 1 bit di stop. 7E1 indica 7 bits di dati, parit� pari e 1 stop
+bit. 701 indica 7 bit di dati, parit� dispari e 1 stop bit. Questi parametri
+devono essere gli stessi che usa il GPS. La maggior parte dei GPS usa 4800 bps
+8N1.
+
+HELP-INDEX>Configurare un GPS in rete
+
+ Configurazione di un GPS in rete.
+
+Questa opzione permette di condividere i dati provenienti dal GPS con pi�
+programmi, e con pi� computer in rete. Xastir pu� ottenere i dati dal GPS
+attraverso il demone gpsd che permette, attraverso diverse connessioni, di
+condividere i dati del
+GPS con altrettante applicazioni.
+
+Impostare il nome dell'host (o l'indirizzo IP) e il numero della porta che gpsd
+utilizza per le connessioni (di solito la 5678).
+
+Selezionando "Attiva all'avvio" si ordiner� a Xastir di caricare questa
+interfaccia all'avvio.
+
+Selezionando "Riconnetti su Errore", indicher� ad Xastir di riconnettersi una
+volta che il flusso di dati si � per qualche motivo interrotto.
+
+HELP-INDEX>Configurare il Server Internet
+
+ Configurazione del Server Internet
+
+I server internet permettono di ricevere ed inviare dati a tutto il mondo
+attraverso internet.
+
+Selezionando "Attiva all'avvio" si ordiner� a Xastir di caricare questa
+interfaccia all'avvio.
+
+Selezionando "Permetti la Trasmissione", indicher� che Xastir potr� trasmettere
+via radio tutti i dati.
+
+Inserisci il nome dell'host (o l'indirizzo IP) e il numero della porta del
+server internet che vuoi connettere.
+
+Inserisci un codice di accesso valido per attivare la connessione, che
+permetter� ai tuoi dati di essere trasmessi attraverso Internet. Se non hai
+un codice di accesso puoi spedire un mail a fgiannan at earthlink.net con tutti i
+tuoi dati e informazioni radio, per ricevere il codice.
+
+Selezionare Riconnetti in caso di errore, che indica a Xastir di riconnettersi
+nel caso la comunicazione sia interrotta.
+
+HELP-INDEX>Configurare una Stazione Meteo
+
+ Configurare una stazione meteo
+
+Configurare una stazione meteo Seriale.
+
+Impostare la porta seriale alla quale � connessa l'unit� Meteo.
+Valori comuni sono /dev/ttyS0 (COM1) o /dev/ttyS1 (COM2).
+
+Selezionando "Attiva all'avvio" si ordiner� a Xastir di caricare questa
+interfaccia all'avvio.
+
+Ora bisogna selezionare la velocit� della porta in bps sotto Configurazione
+della Porta, e i parametri sotto 'Stile di Porta'. Lo 'Stile della Porta' 8N1
+indica 8 bit di dati, nessuna parit� e 1 bit di stop. 7E1 indica 7 bit di
+dati, parit� e 1 bit di stop.
+7O1 � usato per 7 bit di dati, parit�, un bit di stop. Questi parametri devono
+essere gli stessi della porta dell'apparecchio meteo.
+L'opzione 'Tipi di dati permette di aggiornare per quale tipo di comunicazione
+seriale il programma dovr� cercare. La funzione di autoriconoscimento
+(auto-detect) cercher� per primi dei dati in formato binario come quelli della
+stazione meteo Radio Shack WX-200.
+Nel caso non vengano rilevati dati binari allora Xastir cercher� per dati ASCII
+(utilizzati dalla stazione Peer Bros.).
+
+
+Configurare una stazione Meteo in Rete
+
+Xastir pu� usare dati meteo reperendoli da server come il wx200d.
+wx200d permette pi� connessioni, permettendo di condividere i dati meteo con
+pi� programmi o computer.
+
+Inserisci il nome dell'host (o l'indirizzo IP) e il numero della porta del
+server Meteo che si vuole connettere .
+
+Selezionando "Attiva all'avvio" si ordiner� a Xastir di caricare questa
+interfaccia all'avvio.
+
+Selezionando "Riconnetti se sconnesso", indicher� a Xastir di riconnettersi in
+caso di errore.
+
+Come prima, selezionando il "Tipo di dati" si escluder� l'auto-riconoscimento.
+
+
+
+HELP-INDEX>Configurzione allarmi Audio
+
+ Configurazione Suoni
+
+Selezionare Configurazione, e quindi Suoni.
+
+Per usare questa opzione bisogna avere una scheda sonora e un programma che
+esegua i file con estensione .wav. Il "Comando per eseguire i suoni" � il
+programma (e relative opzioni) che si vuole usare per ascoltare i suoni che
+vengono da Xastir.
+
+I campi conterranno il nome del file da eseguire, i campi sotto le opzioni
+imposteranno i parametri per le opzioni.
+
+Le possibili scelte sono:
+-Esegui un suono quando viene rilevata una nuova stazione.
+-Esegui un suono quando viene ricevuto un nuovo messaggio.
+-Esegui un suono quando arrivano dati da una stazione ad una distanza
+ Min/Max come segnalato dall'utente.
+-Esegui un suono quando viene rilevata una stazione (via TNC) con una distanza
+min/max impostata nei limiti di apertura di banda..
+
+HELP-INDEX>Configurazione delle unit� di misura (Inglese/Metrico)
+
+ Configurazione delle unit� di misura (Inglese/Metrico)
+
+Questo seleziona che in che unit� le grandezze verranno visualizzate dal
+programma.
+Il programma si configura automaticamente sul sistema metrico ma � possibile
+cambiare questa possibilit�.
+
+HELP-INDEX>Barra di stato inferiore
+
+ Barra di stato inferiore
+
+Nella parte inferiore della finestra principale sono disponibili diversi
+messaggi di controllo.
+
+I messaggi di controllo generale sono visualizzati nella paste sinistra.
+
+Nella seconda casella da sinistra � visualizzata la posizione sulla mappa del
+mouse in lat/lon.
+La terza casella visualizza il numero di stazioni ricevute e presenti nel
+database.
+La quarta casella visualizza il livello di zoom e visualizzer� Tr se
+sulla stazione selezionata � attivata la funzione di inseguimento.
+L'ultima casella visualizza lo stato di funzionamento delle periferiche, che
+sono visualizzate nell'ordine di inserimento da 0 a 9.
+Il controllo di stato delle interfacce � diviso in tre aree, la parte alta
+indica il tipo di periferica, in mezzo � indicato lo stato di flusso di dati e
+nella parte bassa � indicato lo stato operazionale della periferica, blu per i
+vari TNC, verde per i GPS, giallo per per i servizi Internet, arancio per le
+periferiche Meteo.
+Nella parte centrale il flusso di dati entrante � indicato con una freccia a
+sinistra per dati uscenti e a destra per dati entranti. Nella parte inferiore
+il verde indica che l'interfaccia � collegata e funziona correttamente, il
+rosso che l'interfaccia � collegata ma in uno stato di errore, l'assenza di
+colore indica che l'interfaccia non � collegata.
+
+
+HELP-INDEX>Spostare la mappa e opzioni.
+
+ Spostare la mappa e Opzioni
+
+Il movimento della mappa � molto semplice e la velocit� di visualizzazione
+della stessa � dipendente dal tipo di sistema in uso e dalla quantit� di
+dettagli visualizzata.
+
+Tutti i movimenti e ingrandimenti sono possibili cliccando il tasto sinistro
+del mouse (tenendolo premuto) sulla mappa. Questa azione visualizzer� un menu
+di Opzioni.
+
+Tutte le funzioni di Zoom sono riferite al punto della mappa dove � stato
+cliccato il bottone sinistro del mouse. Il menu degli zoom mostrer� ulteriori
+opzioni: livelli di zoom da 1 a 3 sono per aree locali mentre livelli da 4 a 6
+sono per aree
+maggiori, quindi pi� il numero � piccolo e pi� l'area visualizzata � stretta.
+
+Dal menu delle opzioni si pu� anche spostare la vista della mappa con la
+funzione Pan, che provocher� uno spostamento del centro della mappa.
+
+Le "informazioni della stazione" cerca per la stazione pi� vicina al punto
+selezionato dal click del mouse. Se pi� stazioni sono presenti apparir� una
+finestra di
+selezione che permetter� di indicare di quale stazione veramente si ha bisogno
+di
+informazioni.
+
+HELP-INDEX>Map Options and Map Chooser Opzioni della Mappa e Scelta della Mappa
+
+ Opzioni della Mappa e Scelta della mappa
+
+Opzioni della Mappa:
+
+Mappe Automatiche (Attiva/Disattiva)
+Quando attivato, qualsiasi mappa trovata nella directory delle mappe verr�
+visualizzata se nella sua area ricade la visualizzazione corrente. Questa
+funzione cercher� in tutte le sottocartelle della directory delle mappe. Se
+pi� mappe sono disponibili allora verranno sovrapposte, in questo caso un
+ computer poco veloce pu� produrre una visualizzazione lenta.
+Tuttavia � possibile disattivare questa funzione e selezionare manualmente la
+mappa da visualizzare.
+
+Griglia (Attiva/Disattiva)
+Quando � attiva, questa funzione visualizza una griglia ogni 10 gradi. Se si
+effettua uno zoom in avanti la risoluzione della griglia passer� ad 1 grado.
+
+Livelli della Mappa (Attiva/Disattiva)
+Quando attivata, questa funzione permette di filtrare i dati di mappe su
+grandi aree.
+Questa opzione funziona solo con le mappe Tiger Line maps reperibili presso
+http://aprs.rutgers.edu. Ci� non velocizzer� il caricamento delle mappe ma
+produrr� una visualizzazione di dettagli appropriata alla scala di
+visualizzazione.
+
+Colore in Aree Chiuse (Attiva/Disattiva)
+Questa opzione controlla il colore di riempimento delle mappe vettoriali.
+In alcuni casi pu� essere necessario eliminare il riempimento di un'area
+per permettere la visualizzazione dei livelli sottostanti. Le mappe sono
+caricate in ordine alfabetico e quindi i livelli rispetteranno tale ordine.
+
+Scelta della mappa.
+Questa funzione visualizza tutte le mappe disponibili. Si potr� selezionare
+pi� di una mappa e poi premere OK per confermare la selezione. Il bottone
+Cancella chiude la finestra di dialogo della scelta delle mappe.
+
+Nota: Xastir utilizza il Datum WGS 1984 per le mappe.
+
+HELP-INDEX>File di mappe, Dos, Windows, Pixmaps e WX Counties
+
+ File di mappe, Dos, Windows, Pixmaps e WX Counties
+
+Tipi di Mappa
+Xastir funziona con vari tipi di mappa. Tutte le mappe per il programma
+APRS[TM] Dos,Windows,Mac sono supportate. Dalla versione 0.3.2 � possibile
+caricare anche mappe in formato Pixmap. � possibile anche caricare le mappe di
+supporto per gli Allarmi Meteo Statunitensi.
+
+Dove posizionare le mappe
+Qualsiasi mappa Dos, Windows/Mac o Pixmap deve essere messa nella directory
+/usr/local/share/xastir/maps. Si possono creare sottocartelle per oridare il
+contenuto. Per esempio si pu� creare una cartella ITALIA per mettere tutte le
+mappe che comprendono il territorio italiano, oppure si possono dividere le
+mappe per tipo: Pixmap e Dos.
+
+Esempio
+
+ /usr/local/share/xastir/maps/
+ /italia/nord
+ /italia/centro
+ /italia/sud
+ /dos/italia/
+ /dos/germania/
+ /pixmaps/italia/
+ /pixmaps/germania/
+
+
+
+Le mappe Pixmap sono una combinazione di due file, un file binario grafico
+pixmap (.xpm) e un file di dati di locazione (.geo). Il file .xpm grafico � in
+formato .xpm
+standard modificabile con qualsiasi programma di grafica che supporti questo
+formato. Il
+file di dati .geo permette di posizionare la mappa nel mondo.
+Ecco un esempio di file .geo: world1.geo
+
+FILENAME world1.xpm
+# x y lon lat
+TIEPOINT 0 0 -180 90
+TIEPOINT 640 320 180 -90
+
+
+Questo semplice file ha 4 componenti. La prima riga indica il file grafico a
+cui sono riferiti i dati che deve essere nella stessa directory del file di
+dati.
+La seconda linea imposta un commento alla mappa. Ogni linea che inizia con un
+ # (cancelletto) indica un commento che non verr� letto dal programma.
+Le ultime due linee connettono un pixel di coordinate x,y ad un punto della
+terra con coordinate lat/long. Due punti sono necessari e dovrebbero essere
+presi in alto a
+sinistra e in basso a destra dell'immagine.
+Per usare la mappa Pixmap, selezionare la scelta di mappa e in seguito il file
+.geo
+
+Mappe di Allerta Meteo USA
+Tutte le mappe di Allerta meteo USA dovrebbero essere posizionate in
+/usr/local/share/xastir/Counties.
+Dovranno poi essere create delle sottocartelle per lo stato USA a cui
+appartiene la mappa chiamate con l'abbreviazione di due lettere dello stato.
+
+
+ /usr/local/share/xastir/Counties
+ /CO/
+ /CO/COPARK.map
+ /CO/CODOUGLA.map
+ /CO/COJEFFER.map
+ /CO/COZ001.map
+ /CO/COZ002.map
+ /CO/COZ003.map
+ /NJ/
+ /NJ/NJOCEAN.map
+ /NJ/NJBERGEN.map
+ /NJ/NJMONMOU.map
+ /NJ/NJZ001.map
+ /NJ/NJZ002.map
+ /NJ/NJZ003.map
+
+
+
+Ecco due siti dove � possibile avere questo tipo di mappe:
+ftp://aprs.rutgers.edu/pub/hamradio/APRS/NWSCounties/
+http://home.att.net/~kg5qd1/Maps.html
+
+HELP-INDEX>Informazioni stazione - Ricerca nel database FCC e RAC
+
+ Informazioni stazione - Ricerca nel database FCC e RAC
+
+Informazioni Stazione mostrer� tutti i dati acquisiti da Xastir per quel
+determinato nominativo.
+
+Il bottone Annulla Inseguimento toglier� tutti i percorsi che sono stati
+memorizzati nello schermo.
+
+Il bottone Spedisci Messaggio aprir� una finestra per spedire un messaggio.
+
+Se si � installato il database FCC o RAC si pu� fare una ricerca dei dati della
+stazione.
+I file di databse RAC e FCC devono essere posizionati in
+/usr/local/share/xastir/fcc.
+
+Questa funzione aggiunger� l'indirizzo della stazione alle informazioni
+ricevute via radio.
+
+Per usare il database FCC bisogna scaricarlo (40Mb) da:
+ftp://ftp.fcc.gov/pub/XFS_AlphaTest/amateur/appl.zip
+
+o la nuova versione da:
+ftp://ftp.fcc.gov/pub/Bureaus/Wireless/Databases/uls/complete/l_amat.zip
+(The only file needed form this 40Meg zip is the EN.dat file)
+
+**** NOTA: per usare la nuova versione, il database deve essere prima
+ordinato!!! ****
+Assicurarsi di avere spazio disco libero (100Mb)
+Per ordinare il file eseguire i seguenti comandi:
+sort +4 -t \| EN.dat >EN.dat.sorted
+rm EN.dat
+mv EN.dat.sorted EN.dat
+
+Il database RAC si pu� scaricare da:
+ftp://ftp.rac.ca/pub/cdncaldb.zip
+
+Xastir creer� degli indici per ogni database, se un nuovo callsign � immesso
+nel database allora Xastir creer� dei nuovi indici e render� subito disponibile
+il nuovo
+callsign.
+
+I prefissi speciali NON sono inclusi nei database.
+
+HELP-INDEX>Opzioni di Visualizzazione
+
+ Opzioni di visualizzazione
+
+Queste opzioni permettono di visualizzare i dati delle stazioni attorno
+all'icona che indica la posizione della stazione sulla mappa.
+
+Altitudine (on/off)
+Quando attivo, una linea blu di dati appare sopra al nominativo, ad indicare
+l'altitudine della stazione nell'ultima posizione ricevuta.
+
+Direzione (on/off)
+Quando attivo, una linea verde di dati apparir� sotto al nominativo. Questa
+indica la direzione in gradi del movimento della stazione l'ultima volta che �
+stata ascoltata.
+
+
+Velocit� Speed (on/off)
+Quando attiva, una linea di dati rossi indica la velocit� della stazione
+l'ultima volta che � stata ricevuta.
+
+Distanza/direzione (on/off)
+Quando attivata, due linee di dati verranno visualizzate alla sinistra
+dell'icona della stazione.
+La linea superiore indica la distanza dalla propria stazione, mentre la linea
+inferiore la direzione dalla propria stazione.
+
+Tracce della Stazione (on/off)
+Quando attiva, qualsiasi stazione in movimento lascer� una traccia della
+posizione precedente fino ad un numero di 100 posizioni. Quando i dati della
+stazione diventano vecchi e l'icona della stazione diventa trasparente, la
+traccia � indicata con un tratteggio.
+
+Potenza/Guadagno (on/off)
+Quando attiva, visualizza i cerchi di potenza e guadagno.
+
+Insegui stazione
+Questa funzione visualizza una finestra di dialogo simile a quella di
+localizzazione.
+Si pu� inserire un nominativo o parte di esso e quindi selezionare "Insegui
+ora!" per centrare lo schermo su quella stazione e mantenerlo centrato per ogni
+successivo spostamento.
+
+Selezionando "Elimina Inseguimento" si eliminer� la funzione.
+
+Il bottone "Annulla" nasconder� la finestra senza apportare cambiamenti.
+
+Informazioni Meteo (on/off)
+Quando selezionato, verranno visualizzate le ultime informazioni meteo
+(temperature,velocit� del vento/direzione/gust,umidit�).
+
+
+HELP-INDEX>Messaggi
+
+ Messaggi
+
+Spedire Messaggi e Apri Gruppo
+
+Queste funzioni sono molto simili. "Spedisci messaggio a" spedir� un messaggio
+solo ad una stazione. I messaggi di gruppo sono pi� generali.
+(ndt: la funzione messaggi di gruppo al momento non � completamente funzionante)
+
+Ognuna di queste finestre visualizza una scheda di messaggio, una linea per il
+nominativo/nome gruppo e vari bottoni.
+
+Una volta inserito il nominativo della stazione, tutti i messaggi ricevuti da
+essa verranno visualizzati. Se non ci sono messaggi allora una nuova finestra
+permetter� di inserire un nuovo messaggi da spedire. La lunghezza massima del
+ messaggio � di 250 caratteri. "Spedisci ora!" invier� il messaggio al
+destinatario.
+Il bottone "Spedisci ora!" rimarr� grigio fino a quando il messaggio non sar�
+correttamente inviato.
+
+Qualsiasi messaggio ricevuto sar� ordinato secondo la linea # e messo nella
+ finestra dei messaggi. Se si � nella funzione Gruppo, la lista dei messaggi
+ visualizzer� anche il nominativo del mittente.
+
+"Nuovo nominativo" visualizzer� i vecchi messaggi della stazione oppure
+permetter� la comunicazione con un'altra stazione. Il bottone "Cancella
+ Messaggi" eliminer� tutti i messaggi.
+
+Elimina i messaggi in uscita.
+
+Questo eliminer� tutti i messaggi che sono stati spediti.
+
+Risposta automatica
+
+Questa funzione attiva la risposta automatica ai messaggi in entrata.
+
+Imposta risposta automatica
+
+Render� possibile impostare il messaggio di risposta automatico.
+
+HELP-INDEX>Eliminare i percorsi dallo schermo
+
+ Eliminare i percorsi dallo schermo
+
+Selezionare File e quindi "Elimina Percorsi" per eliminare tutti i percorsi
+delle dallo schermo e dal database interno.
+
+HELP-INDEX>Ripulire lo schermo dai simboli di stazioni
+
+ Ripulire lo schermo dai simboli di stazioni
+
+Selezionare File e quindi "Elimina tutte le Stazioni". Questo eliminer� tutti
+dati delle stazioni ricevute fino a quel momento eccetto la vostra.
+
+HELP-INDEX>Rispondere ad un log
+
+ Rispondere ad un log
+
+Selezionare "Apri file log" e selezionare un file di log creato dal TNC o dalla
+rete con la funzione sotto le opzioni di rete. La stazione user� il file di log
+come se
+fosse direttamente connessa al TNC.
+
+HELP-INDEX>Localizzare una Stazione
+
+ Localizzare una Stazione
+
+Selezionare Vista e quindi "Localizza Stazione" per fare apparire una finestra
+di dialogo che permette di inserire un nominativo (completo, non case
+sensitive). Se si vuole cercare un nominativo parziale allora bisogna
+deselezionare "Nome esatto". Selezionando "Maius/Minus Esatti" verranno
+ osservati anche i criteri di Maiuscole/minuscole.
+Selezionando "Localizza Ora!" il Display verr� centrato sulla stazione cercata
+al livello di zoom corrente. "Annulla" chiuder� la finestra di dialogo.
+
+
+HELP-INDEX>Creare ed usare i Salti alla Stazione
+
+ Creare ed usare i Salti alla Stazione
+
+Selezionare Visualizza e quindi "Vai alla Stazione" per visualizzare una
+finestra di dialogo.
+La prima volta che si usa questa funzione la finestra di dialogo sar� vuota.
+Si pu� creare una nuova vista selezionando "Nuova posizione", inserire il nome
+e quindi Aggiungi.
+Per usare le posizioni registrate baster� selezionare la posizione e quindi il
+tasto "Vai!" per centrare la posizione registrata. E' possibile eliminare una
+posizione selezionandola e selezionando "Elimina".
+
+HELP-INDEX>Inseguimento di una stazione
+
+Inseguimento di una stazione
+
+Selezionare Visualizza e quindi Insegui stazione. Inserire il nominativo da
+inseguire (tutto o parte di esso) e quindi selezionare "Insegui Ora!". Appena
+la stazione si muove, essa viene centrata nello schermo. Per disattivare
+questa funzione bisogna selezionare "Annulla Inseguimento".
+
+HELP-INDEX>Tabella dei simboli
+
+ Tabella dei Simboli
+
+Simbolo Gruppo / Gruppo \
+
+! Triangolo w/! Triangolo w/!
+" Nuvola Nera Nuvola da Pioggia
+# Digi DIGI
+$ Telefono Simbolo $
+% DX DX
+& GATEWAY-HF GATE
+' Piccolo Aereo Incidente Aereo
+( Nuvola Nuvola
+) TBD
+* Fiocco di neve Fiocco di neve
++ Croce rossa
+, L inversa
+- Casa con antenna Omnidirezionale
+. Piccola x
+/ Punto rosso
+0 0 in un quadrato Cerchio
+1 1 in un quadrato
+2 2 in un quadrato
+3 3 in un quadrato
+4 4 in un quadrato
+5 5 in un quadrato
+6 6 in un quadrato
+7 7 in un quadrato
+8 8 in un quadrato
+9 9 in un quadrato GAS
+: Fuoco ?
+; Tenda Tenda
+< Motocicletta Banderuola
+= Locomotiva
+> Auto Auto
+? POS Antenna ? in un quadrato
+@ URAGANO/TEMPESTA URAGANO/TEMPESTA
+A Pronto Soccorso Quadrato
+B BBS Neve a vento
+C Canoa
+D D in un cerchio
+E E in un cerchio Fumogeno
+F F in un cerchio
+G Antenna Grid Square ?
+H Hotel/Letto
+I TCP/IP ?
+J J in un cerchio Fulmine
+K Scuola Casa
+L Faro Faro
+M Mac
+N NTS ?
+O Pallone Aerostatico
+P Auto Polizia Rx
+Q Cerchio con Cerchietti Cerchio con Cerchietti
+R RV Ristorante
+S Shuttle Satellite
+T Temporale (cloud/bolt) Temporale (cloud/bolt)
+U Scuolabus Sole
+V VOR TAC VOR TAC Symbol
+W National Weather Service NWS-Digi
+X Elicottero
+Y Barca a vela
+Z Windows
+[ Corridore Bagno
+\ Triangolo DF
+] Packet Mail Box
+^ Grande Aereo Grande Aereo
+_ Stazione meteo WS-Digi
+` Antenna parabolica
+a Ambulanza
+b Bicicletta Nuvola a vento
+c antenna DX
+d Caserma Pompieri Antenna DX
+e Cavallo Nuvola a Cirro
+f Mezzo Pompieri FC Cloud
+g aliante Banderuola (2)
+h Ospedale HAM
+i Isola Isola
+j Jeep Jeep
+k Camion Camion
+l Puntino Puntino
+m MIC Pietra Miliare
+n N Small Triangle
+o EOC Punto con cerchietti
+p Cagnolino Punto con cerchietti
+q GS Antenna GS Antenna
+r Traliccio Antenna Traliccio
+s Nave Nave
+t TS ?
+u 18 Wheel Truck
+v Van Punto con cerchietti
+w H20 Inondazione
+x X Windows Punto Rosso
+y House w/Yagi Casa con Yagi
+z X Windows
+{ NEBBIA NEBBIA
+| Linea Nera Linea Nera
+} TCP TCP
+~ Barca a vela Barca a vela
+
+
diff --git a/help/help-Portuguese.dat b/help/help-Portuguese.dat
new file mode 100644
index 0000000..a858ac6
--- /dev/null
+++ b/help/help-Portuguese.dat
@@ -0,0 +1,3099 @@
+HELP-INDEX>READ ME FIRST - License
+
+ READ ME FIRST - License
+
+For the most current information please read the README file in the Xastir
+directory. Also see the LICENSE and COPYING files for additional information.
+
+Remember this program is intended to be used by the HAM community, in the USA
+the FCC restricts you from transmitting over RF if you are not a licensed HAM.
+Users in countries outside the USA should seek their local government
+restrictions.
+
+LICENSE:
+
+XASTIR, Amateur Station Tracking and Information Reporting
+Copyright (C) 1999,2000 Frank Giannandrea
+Copyright (C) 2000-2012 The Xastir Group
+
+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.
+
+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.
+
+More information on the program can be found at:
+
+ http://www.xastir.org
+ http://sourceforge.net/projects/xastir/
+ http://xastir.sourceforge.net
+
+There are some mailing lists available that are Xastir-specific.
+Please subscribe to one or both of them for the latest Xastir
+information. See http://www.xastir.org to subscribe.
+
+For more information on the GNU License look at:
+http://www.gnu.org
+
+
+HELP-INDEX>Welcome! and Notes from the Authors
+
+ Welcome! and Notes from the Authors
+
+XASTIR, or X-windows Amateur Station Tracking and Information Reporting.
+
+Xastir is an APRS(tm) program that is Open Source and free to use and
+pass out to others. Currently this program is in development and should
+not be seen as a finished product! Your help will be needed to make this
+a better program. If you have programming skills and/or can write
+documentation, your help may be needed! We have a lot of ideas but very
+little time, so if you think you can add something to the effort let us
+know!
+
+
+
+APRS(tm) is a Trademark of Bob Bruninga, his home page is at
+"http://web.usna.navy.mil/~bruninga/aprs.html". A great deal of information
+on APRS(tm) can be found in the APRSdos documentation written by
+Bob Bruninga. An additional source of information is the APRS(tm)
+specification, available from http://www.tapr.org .
+
+HELP-INDEX>What's new in Xastir 2.0.1
+(Changes between 1.7 and 2.0.0 were never recorded here,this block
+describes a few of the changes from 1.9.8 to 2.0.0 that occured right
+before release of 2.0.0, but otherwise documents only changes from 2.0.0
+to 2.0.1)
+
+Added tiling for OpenStreetMaps (2.0.0).
+Added "setlocale()" calls to assure we aren't confused by user
+LANG variable settings.
+Improved speed of config file processing.
+Fixes for new One-Wire-Daemon protocol, allowing both old and
+new to work with Xastir.
+Fixed segfaults that could happen when closing list dialogs.
+Fix OSM code to support 16-bit quanta in Graphics/ImageMagick.
+Fixed broken makefile that was ignoring DESTDIR.
+Fixed broken build so internal shapelib builds correctly when
+proj.4 is not installed.
+Add dbfawk files for several generations of new NWS shapefiles.
+Update get-NWSdata to pull current NWS shapefiles.
+Add start/stop files for Kenwood D72 and D710 radios.
+Added a script to convert GeoPDF files to usable GeoTIFF files.
+Make the command to set a TNC into CONVERSE mode a run-time
+configurable option in the TNC Interface Properties dialog.
+Add support for Australian Bureau of Metrology weather alerts.
+Fixes for Davis APRS Data Logger, Davis Meteo and LaCrosse
+support so it gets rain totals correct.
+Allow "posit interval" in File->Configure->Timing to go all the
+way to zero, meaning "never send posits on a schedule."
+Add signal support so that Xastir will emit a posit when it
+receives SIGUSR2. Combined with zero "posit interval," this
+allows Xastir to emit a posit only when told to by an external
+script.
+Fixed error in logic for band-opening alerts (speech and audio
+alarms) so it does not incorrectly report third party traffic
+as a band opening.
+Add "Send Control-E to get GPS data?" to TNC interface
+properties for the "Serial TNC w/ GPS on AUX port" interface
+type. Defaults to enabled, which is correct for KPC-3+ TNCs,
+but should be turned off for any TNC that automatically
+streams GPS NMEA strings, such as Kenwood APRS radios.
+Update GPSMAN support to reflect changes in the gpsman command
+line.
+Add a small delay between sending the converse-mode command
+and sending data for transmission, because KAM TNCs don't
+work if you send the data immediately.
+Fix a bug in the OSM tile download loop that could prevent
+further downloading of tiles if any one tile download fails.
+Fixed a thread-unsafeness bug that could cause Xastir to start
+using corrupted file names when multiple logging options
+(TNC, NET, WX, IGATE, etc.) selected simultaneously.
+Fixed get-fcc-rac.pl script to reflect changes in RAC download
+site.
+
+
+
+
+HELP-INDEX>What's new in Xastir 1.7
+Added REGRESSION_TESTS in order to test interoperability of the
+configure-time flags.
+Added a replacement for malloc() for those cases where the OS
+provides a faulty one.
+Added more to the summary.log file: The tests and results from
+config.log.
+GDAL configure probe now uses gdal-config if it's in the user's
+path.
+Tweaked configure so that dependent libraries cause other library
+searches to fail, and to provide more user output.
+Added ASCII-art drawing to INSTALL showing most of the library
+dependencies.
+Updated symbols.dat to more closely correspond to the current spec.
+Implemented EMERGENCY BEACON transmit capability under the Help
+menu.
+Added decoding for "EMERGENCY" anywhere in the packet plus any of
+these in the TO: field: ALARM, ALERT, WARNING, WXALARM, EM. Any of
+these will invoke the normal emergency popup dialog.
+Waypoint symbols now have a line drawn between them and the station
+transmitting them, per the spec.
+Now using font metrics to determine size of font. We use that to
+determine size of black rectangle to draw underneath.
+Fixed the Fetch Findu Trail function so that it matches what Findu
+can provide.
+Fixed track->shapefile function so that it works on Cygwin too.
+Added reset button to Change Debug Levels dialog.
+Enable WX Alerts menu item is now grey'ed out if Shapelib isn't
+installed.
+RINO Download timing slider is now visible but grey'ed out if gpsman
+isn't installed.
+Added a custom zoom option to the right-click zoom levels menu.
+Moved the center & zoom dialog to the map menu.
+Changed a memcpy() to an xastir_snprintf() function in alert.c to
+assure that a string is terminated.
+Free'ing some malloc'ed space for cases where hash inserts fail.
+Added probe for sighandler_t definition.
+Changed includes, added leak_detector.h.
+A few small changes here and there to get rid of compiler warnings.
+Freeing some malloc'ed space for the cases where hash inserts fail.
+Fixed initializers for awk_rule[].
+Changed hash add functions so that they do a delete first instead of
+replacing hash values.
+Moved some wx-alert related code to debug level 2.
+Changed leak detect interval from 5 minutes to 60 seconds.
+Fixed a big memory leak in draw_nice_string() function.
+Changed include files around so memory leak detection stuff is in
+leak_detection.h.
+Added new compiler flags and cleaned up the code to eliminate many
+warnings created.
+Fixed Incoming Data dialog code so that packets transmitted to local
+interfaces would appear there.
+TNC/NET toggles work for those now too.
+Fixed memory leak in font metrics code.
+Simplfied get_long() and get_int() functions and callouts.
+Tweaks for sighandler_t and sigjmp_buf.
+Added a sign-on message for server connects.
+FCC/RAC lookup or Locate Now buttons don't destroy the dialog
+anymore.
+Fixing up strings.h includes.
+Added a new popup for EMERGENCY packets.
+Changed signal() with SIG_IGN to sigignore for some cases.
+Added a test for sigignore() to configure.ac.
+Changes to allow different versions of "gv" to be used.
+Moved "-lgdal" to end of link line to avoid conflict with other
+libraries.
+Added UDP server and client.
+Added more language strings for previously hard-coded values.
+Changed config file get_int and get_long functions to provide better
+output when config file entries are missing or out-of-range.
+We now allow gating to the internet and to RF for user-defined
+packets and telemetry packets.
+Changing to <CR><LF> for the TCP server signon message.
+Changing to timestamp per packet for log files, with long int
+seconds at the beginning.
+Added icon.
+Added support for -geometry command-line parameter.
+Added fast creation of standard SAR objects via mouse menu,
+including adding digits to the end of the object name if name would
+conflict with pre-existing objects.
+
+
+
+HELP-INDEX>What's new in Xastir 1.6
+Fix for DF lines having incorrect angles at times.
+Configurable display of layers for USGS topo maps.
+Better Map Feature Search: Shows up to 50 matches, user selects
+which one to center map on.
+Configurable "relay" digipeater calls: Up to 50 callsigns can be
+specified in the Xastir config file to use for relay digipeating.
+"WIDE1-1" is now the default.
+Added support for Web Map Service (WMS).
+Tweaked the GPGGA and GPRMC GPS sentence decoding.
+Added speed-ups for lat/long geotiff's.
+Added Aloha circle.
+Added new #defines in interface.h for specifying "conv" or 'k'
+command to TNC.
+Added new tnc-startup file for TAPR-2 style TNC's.
+Added transparency capability to WMS.
+Fixed digpeating code for "wide1-1,wide2-1" case.
+Fixed some compile errors that are seen on FC4 and OSX Tiger.
+Added new terraserver .geo file options.
+Changed Map Properties "fill" option to allow NO/YES/AUTO.
+Auto uses dbfawk if present, no/yes force fill to that state.
+Fixed some #ifdefs here and there so that compiles will work if
+some libraries aren't present.
+Added map caching for nearly all internet maps, plus two new toggles
+on the map menu for clearing out current-view maps or all maps from
+the cache.
+Moved Tigermap timeout slider to main timing dialog, renamed it, and
+made it function for ALL internet map fetches.
+Added timestamps to x_spider log messages.
+A fix for the emacs tempfile bug w.r.t. dbfawk files went in, but
+hasn't been verified to have fixed the problem yet.
+More bulletproofing added to the map_cache code.
+Fixed a compile problem that happens if ImageMagick isn't installed.
+Changed stipple style to solid for polygons drawn with dbfawk.
+Another fix so that linking works without map caching.
+
+
+
+HELP-INDEX>What's new in Xastir 1.5
+Optional Rtree shapefile extent caching
+Optional berkelydb-based internet map caching
+Modifier keys fix
+Improvements to the message GUI
+Tactical call support re-written, hashtable based
+Warnings on crazy paths
+Hashtable weather alert speedups
+Dead-reconing for Objects/items
+Igate of specific stations (in the nws-stations.txt)
+Fixed DF object properties
+Measure function more accurate
+Decoding for "Position with Timestamp no APRS messaging" packets.
+More thorough checking for scanf/sscanf/fscanf function calls
+Fixing 100% humidity for some weather stations, plus added more data for Davis stations
+Changed active internet connection check from 1 min to 5 minutes
+Fixed decoding of compressed DF objects
+Fixes to allow new WHO-IS server to be used from Xastir
+Got rid of extra 0x00 byts between transmitted KISS frames
+Tweak to not start an interface upon changing its properties
+Tweaks to allow use of http proxy servers for online map accesses (.netrc file)
+
+
+
+HELP-INDEX>What's new in Xastir 1.4
+Comment fields for interfaces
+split_gnis and ozi2geo scripts, need to add to section on scripts
+serial mkiss interface
+move objects without confirm
+new timing params w.r.t. trails, need to add to config|timing part
+geo-coder (already in docs)
+exponential/random back-off for almost everything
+dbfawk default, memory leaks fixed
+click+drag zoom boxes
+tactical callsign support
+numerous small memory leaks, uninitialized data uses, and similar bugs fixed.
+GPS quality info
+RINO waypoints downloading
+label trackpoints
+comment/status timestamps
+listener socket/ability to act like a limited internet server
+
+
+HELP-INDEX>Starting Xastir for the first time
+
+ Starting Xastir for the first time
+
+When first running Xastir, you should start it from a terminal window so
+that any warning or error messages can be seen. On most systems a path is
+set up to run programs in /usr/local/bin and all you need to do is type
+"xastir &" at the prompt. On systems that do not have this path installed
+type "/usr/local/bin/xastir &" to start the program. The '&' character
+will cause Xastir to start in the background, leaving the terminal window
+available for other uses.
+
+You may also set the language choice at this time. To set the language or
+change the current language choice, call Xastir with the option '-l':
+
+ xastir -lEnglish
+
+Language options are:
+ xastir -l Dutch
+ xastir -l English
+ xastir -l French
+ xastir -l German
+ xastir -l Italian
+ xastir -l Portuguese
+ xastir -l Spanish
+ xastir -l ElmerFudd
+ xastir -l MuppetsSwedishChef
+ xastir -l OldeEnglish
+ xastir -l PigLatin
+ xastir -l PirateEnglish
+
+The chosen language will be stored in your config file, so it is preserved
+for the next time you call Xastir. For new installs Xastir will default to
+English until you change the language with this command line option.
+
+The menus on the top may be accessed with the mouse or with keyboard
+shortcuts. The keyboard shortcuts may not work correctly with num-lock on.
+
+You will need to configure interfaces in order to actually use Xastir.
+Interface configuration is detailed under the "Configuring Interfaces" help
+topic and its subtopics.
+
+If you are operating in a situation where a coordinate system other than the
+default DD MM.MMMM system would be helpful, you may select your preferred
+system by going to File|Configure|Coordinate system. Any of the supported
+coordinate systems my be used as input by using the Coordinate Calculator.
+
+HELP-INDEX>Configure the Station Information
+
+ Configure the Station Information
+
+Click on File, then Configure, then Station.
+
+Fill in your Amateur Station call sign.
+
+Fill in your station position if you are not using Xastir with a GPS
+unit. You can locate your general position on the map with Xastir and
+use the position given by the cursor placement over the map. This
+position will be viewable in the box at the bottom of the Xastir screen
+2nd from the left, whenever the mouse is over the drawing area. You can also
+choose "Move My Station Here" from the right-click menu while your mouse is
+over your location. If you have a GPS you can skip this and set up the GPS
+later.
+
+"Send Compressed posits", if selected, will transmit in the newer compressed
+format. This format will reduce the amount of data on the air, thereby
+increasing the capacity of the APRS(tm) network. The maximum precision of the
+transmitted position is also higher. Some older programs, including recent
+versions of WinAPRS, do not decode this format yet. Findu.com might also have
+trouble with it. We transmit course/speed in this format but not altitude.
+In order to send course/speed AND altitude requires adding nine characters to
+the packet which negates part of the reason to use compressed posits.
+
+To select a symbol to be used for your station you need to specify
+a group and a symbol character. You can manually fill in these fields,
+or press select to graphically choose a symbol. There are two groups
+of symbols available. A text description of each symbol can be found
+in the "symbol table" help topic.
+
+For some symbols of the secondary group you can specify an overlay.
+With that a symbol will be displayed together with an additional
+overlay character, e.g. a car symbol with the number 1 overlay-ed on
+top of the symbol.
+
+For using overlays you need to select a symbol from the secondary symbol
+table and enter the overlay character to be shown in the group/overlay
+field. Only numbers and uppercase characters are allowed as overlay
+characters. According to the APRS(tm) specification not every symbol can
+be overlay-ed, Xastir doesn't enforce this, but some other programs may.
+Note that not all of the symbols have been implemented in the graphics
+chooser yet, and some of them are not per the APRS(tm) spec yet.
+
+Next, enter the data for the power/height/gain of your station. This
+is useful information but is not required; simply select "Disable PHG"
+to disable it. These choices present a granular representation of your
+stations range. Select the combination of values closest to the
+description of your station. Please use height above average
+terrain (HAAT) for the height value. Do NOT use average height
+above sea level or height above ground. All values must be
+specified if you wish to transmit PHG information.
+
+Another option would be to specify the RNG in the comment field in miles
+instead of using PHG. See the APRS(tm) spec for details.
+
+For Gain use the gain of your antenna in dBi.
+(FIXME: dBd? spec is unclear, I think it's implying dBi because it says "in
+absence of any data, stations are assumed to be running 10w to a 3dB omni at
+20ft. A typical omni is only 3dBi.....)
+
+Note: The gain setting is really intended for vertical antennas; the gain
+setting for a beam should be quite a bit below the forward gain of the beam.
+This is because with directivity set, the PHG circle is only offset by 1/3rd
+of its size toward the specified direction. Setting gain higher will enlarge
+the whole circle unrealistically, rather than increasing the directivity.
+There was talk several years ago about amending the specifications to better
+deal with beam antennas, but nothing was changed.
+
+Enter a comment, not required but it will add insight on your station.
+A common thing to enter here is your preferred e-mail address. It will
+be transmitted along with your posits.
+
+Position ambiguity will allow you control how accurately you transmit your
+position. A setting of none will allow your station to transmit the exact
+position you have entered or received from a GPS. The other choices will
+place you somewhere in the range of the choice you selected. Note that
+this may throw some non-spec compliant stations for a loop. Findu.com
+doesn't understand position ambiguity.
+
+Clicking OK will save your changes, Clicking on Cancel will keep the
+previous settings.
+
+HELP-INDEX>Configure Default Operation
+
+ Configure Default Operation
+
+Click on File, then Configure, then Defaults.
+
+This page sets up some standard defaults for the program operation.
+
+Transmit Station Option sets the type of packet your station will transmit
+its data as.
+
+IGate Options will set your station up as an Internet-RF gateway. This option
+should be used with caution; As a ham you are responsible for the data that
+comes in via the Internet and is transmitted via RF. You also will need to
+choose an IGate option on each interface in order for the IGate to function.
+If you want to have your IGate forward NWS weather alerts to RF, you must
+create a ~/.xastir/data/nws-stations.txt file listing each call or NWS station
+(like "PHISVR") that you would like to transmit via RF. This feature also
+works for gating specific callsigns to RF. Bob Bruninga, WB4APR, recommends
+gating these calls to RF: SCOUTS, SATERN, KIDS, REDCROSS, FOUR-H, YOUTH, GUARD,
+MARS, JOTA. See his link: "Generic Callsigns for National Events" off this web
+page for his current list of recommended callsigns:
+
+ http://www.ew.usna.edu/~bruninga/aprs.html
+
+"Transmit Compressed objects/items?", if selected, will transmit objects and
+items in the newer compressed format. The maximum precision of the transmitted
+position is higher, and the transmission is shorter, but some older programs do
+not decode this format yet. Currently this only compresses "standard"
+objects/items with an optional speed/course. It won't compress area, signpost,
+or DF objects/items, and won't currently represent altitude in "standard"
+objects/items.
+
+"Pop up new Bulletins", if selected, will cause Xastir to bring up the bulletin
+dialog when bulletins within the configured range are received. "View
+zero-distance bulletins" will cause bulletins with no known location not to
+be displayed or cause pop-ups.
+
+"Warn if Modifier keys" will cause Xastir to print a warning if you attempt to
+use Xastir while num-lock, scroll-lock, or caps-lock is engaged. Some users
+report the screen blanking on them and similar problems when they attempt to
+use Xastir with one of these modifier keys on.
+
+You can also select "Activate alternate net?" and choose an altnet call from
+this dialog. Altnet allows you to have a private APRS(tm) network among the
+stations that also have altnet configured, and have the same altnet call
+entered.
+
+"Disable Posit Dupe-Checks" disables the check for duplicate copies of a
+position. This should only be used when a station might return to exactly the
+same position (within 60' or so for non-compressed positions) and you wish to
+see the duplicate positions and/or tracks displayed on the map. This option
+is almost never needed in practice, but can be useful for special events like
+search and rescue operations.
+
+"My Trails in one color" shows all trails with your callsign but different
+ssids in the same color. With My trails in one color selected, mycall-1
+and mycall-2 are shown in the same color. With My trails in one color
+unchecked, mycall-1 and mycall-2 are shown in different colors.
+
+"Load predefined objects from file" and the pick list which follows it allows
+you to replace the list of Predefined objects that are accessible from the
+right click pop-up menu with your own list of objects. A set of standard
+Search and Rescue objects and a set of typical public event objects are
+supplied in the predefined_SAR.sys and predefined_EVENT.sys files. You may
+also use these files as a template to create a predefined_USER.sys file.
+See the instructions in the predefined_SAR.sys and predefined_EVENT.sys file
+for details on how to define objects for a custom predefined objects menu.
+If both "Load predefined objects from file" is selected and a file that
+exists in the xastir/config/ directory is selected, then the objects defined
+in that file will be shown on the Predefined objects menu. The unaltered
+predefined_SAR.sys file defines the same objects as the default menu.
+
+
+HELP-INDEX>Configure Timing
+
+ Configure Timing
+
+Click on File, then Configure, then Timing.
+
+Posit TX Interval specifies how often your station's position will be
+transmitted. For fixed stations a good recommendation is every 30 minutes,
+and definitely no less than 10 minutes. Mobile stations may wish to use a
+faster rate. Note that if you're using SmartBeaconing, this slider is
+ignored.
+
+Object/Item Max TX Interval is the maximum interval used for sending out
+objects and items. Try to keep these intervals reasonable, as transmitting
+to a long path every 5 minutes will really take up a lot of the air time.
+A decaying interval algorithm is triggered any time an object is created,
+modified, or killed. The transmit interval will increase until it hits the
+max interval indicated by the slider.
+
+GPS Check Interval will set the interval of time to look at the GPS for new
+data. This is available for stations using an HSP or shared cable with their
+TNC.
+
+Dead-Reckoning Timeout adjusts how long a position is assumed valid for the
+purpose of estimating its current position.
+
+New Track Time adjusts how many minutes must elapse before a new
+separate track is started. Caution: setting the new track time to 0 will turn
+off the display of all tracks.
+
+RINO -> Objects Interval adjusts how often waypoints are downloaded from an
+attached Garmin RINO radio/GPS unit. APRS(tm) Objects are created out of any
+waypoints beginning with "APRS". The "APRS" prefix is removed when creating
+the Object names.
+
+Station Ghosting Time specifies the ghosting interval. Stations that have not
+been heard in the given period will appear ghosted on screen.
+
+Station Clear Time specifies when a station will be removed from the screen.
+
+Station Delete Time specifies the number of full days before data from a
+station will be entirely removed from the Xastir database.
+
+Serial Inter-Char Delay specifies a wait time in milliseconds between each
+character sent to an attached TNC.
+
+New Track Interval (degrees) specifies distance in lat/long degrees at which
+a new track segment is started. Caution: setting new track interval to 0
+degreees will turn off the display of all tracks.
+
+Snapshot Interval (minutes) specifies how often snapshot files will be
+written if either File->PNG Snapshots or File->KML Snapshots are selected.
+
+HELP-INDEX>Configure Audio Alarms
+
+ Configure Audio Alarms
+
+Click on File, then Configure, then Audio Alarms.
+
+To use this option you must have a sound card and a program that will play
+wav files. The Audio Play Command should contain the program you want to
+execute to play the audio file (and any command line options). That of
+course doesn't work if the only sound card in the system is used for a
+soundmodem...
+
+Each type of alert has a check-box to enable it. The fields will contain the
+name of the file to play. Fields under the option will set parameters for the
+option.
+
+The current choices are:
+Play message on hearing a new station.
+Play message on receiving a new message.
+Play message on receiving data from a station within the min/max distance of
+ your proximity settings.
+Play message on receiving data from a station (via TNC) within the min/max
+ distance of your band opening settings.
+Play message on receiving and displaying a new weather alert.
+
+There is a standard set of sounds available most places where Xastir can be
+obtained, please see the file INSTALL for more information.
+
+HELP-INDEX>Configure Speech
+
+ Configure Speech Synthesis
+
+To use this option you must have a sound card and the 'festival' speech
+synthesis software installed. Install Festival and start it in 'server'
+mode prior to starting up XASTIR. The normal command for this is
+"festival_server &". If you use the "festival --server" option instead (old
+method), you may run into problems with connections getting rejected by the
+server.
+
+Once you have festival installed, Xastir will have the ability to speak using
+the following choices:
+
+New Station - Announce the call of a new station.
+New Message Alert - Announce the arrival of a new message.
+New Message Body - Speak the contents of a message.
+Proximity Alert - Announce when receiving data from a station within the
+ min.max distance of your proximity settings. This option uses the
+ proximity settings found in the Audio Alarms menu.
+Tracked station Proximity Alert - Announce when receiving data from a
+ station within the min.max distance of the tracked station. This option
+ uses the proximity settings found in the Audio Alarms menu.
+Band Opening - Announce when receiving data from a station (via TNC)
+ within the min/max distance of your band opening settings. This option
+ uses the distance settings found in the Audio Alarms menu.
+New Weather Alert - Not implemented yet.
+
+Info on Festival may be obtained from: http://www.speech.cs.cmu.edu/festival/
+
+HELP-INDEX>Configure Smart Beaconing
+
+Click File, then Configure, then Smart Beaconing.
+
+The main "Enable SmartBeaconing(tm)" Will cause Xastir to transmit positions at
+various rates and locations based on the movement of the station. It creates
+more realistic trails and makes dead-reckoning much more accurate. This option
+is only useful in a mobile station with a GPS attached.
+
+There are several options available to customize the operation of
+SmartBeaconing:
+
+High rate
+The interval (in seconds) at which beacons are sent when the speed is above the
+High speed setting. This parameter is also used to compute a beacon rate based
+on speed when traveling between the high and low speeds.
+
+High speed
+The speed threshold that will cause beacons at the rate specified above.
+
+Low rate
+The interval (in minutes) at which beacons are sent when the speed is below the
+Low speed setting. Basically consider this to be the stopped beacon rate.
+This parameter is not used at all when traveling at a rate of speed higher than
+"Low speed".
+
+Low speed
+The speed threshold that will cause beacons at the rate specified above.
+
+Minimum Turn
+The minimum degrees that corner pegging can occur at "High speed" or above.
+Lower speeds will require more degrees of turn to trigger a posit, based on
+the value of "Turn Slope" below.
+
+Turn Slope
+Fudge factor for making turns less sensitive at lower speeds. The parameter
+doesn't have any units. It ends up being non-linear over the speed range the
+way the original SmartBeaconing(tm) algorithm works.
+
+Wait Time
+The time in seconds between corner-pegging beacons, prevents multiple
+beacons in short succession.
+
+HELP-INDEX>Configure Units of Measure
+
+ Configure Units of Measure
+
+The default selection is for the Metric System: mm, cm, km/h, etc. To select
+English units, inches, feet, MPH, etc. Click on File, then Configure, then
+toggle the "Enable English Units" check-box.
+
+HELP-INDEX>Save Config Now!
+
+ Save Config Now!
+
+This button will save all of the current configuration to the config file.
+Note that when Xastir is closed, it also saves configuration to the config
+file.
+
+HELP-INDEX>Bottom Status Bar
+
+ Bottom Status Bar
+
+At the bottom of the window various status messages are available:
+
+In the first box on the left general status messages are displayed for a
+short time.
+
+The second box displays the current lat/long or UTM, and Maidenhead grid
+square position of the mouse over the map. If file|configure|Dist/Bearing
+Status is selected, this box will also contain the course and bearing of
+this position relative to your station.
+
+A third box is used to display how many stations are on screen, and how many
+are in the database.
+
+The fourth box will display the current zoom level and will display "Tr" if
+the station tracking is on. At some zoom levels the Tr is not
+displayed properly due to the size of the box.
+
+The fifth box indicates whether logging is enabled.
+
+The last area will display the device status for each interface. Each will
+display in order first to last or 0 to 9. The interface status is separated
+into three areas, top device type, center data flow, and bottom interface
+operational status.
+
+The device type will show what interfaces are configured. The color will
+show what type of device the interface is configured for. Blues are for
+the various TNC devices; Greens will show the GPS devices; Yellow for
+Internet Servers; Orange for WX interfaces.
+
+The center will show data flow in (arrow pointing left) or data flow out
+(arrow pointing right) for that interface.
+
+A green box at the bottom will show if that interface is active. A red
+box will show if the interface is active but in an error condition.
+Otherwise nothing will show if the interface is not active.
+
+HELP-INDEX>Moving the Map and the Options Menu
+
+ Moving the Map and the Options Menu
+
+Map movement is very simple, ease and quickness of movement is dependent on
+your processor speed and the amount of detail you load. Hint: You can
+disable all maps in the maps menu in order to move around quickly, then
+enable maps again.
+
+Zooming:
+Zooming can be accomplished by right clicking on the map (and holding the
+button down). This will bring up an options menu, with choices to zoom in or
+out a single level, or to change to one of the preset zoom levels.
+
+All zooming functions from the options menu will zoom in or out at the point
+on the map where you clicked the right mouse button. Zoom levels have a cascade
+menu. Levels 1-64 are for very local areas and levels 256 and above are for
+large areas. The lower number the level, the more local the area.
+
+A quicker zoom in function is to push and hold the left mouse button, drag it
+across the area of interest and let go. The map will zoom to approximately
+the size of the square you just described with the mouse drag operation. The
+"move" and "measure" toolbar check-boxes must be disabled for this feature to
+work. Clicking the middle button zooms out with a factor of 2, centering
+where you clicked as well.
+
+The map can also be zoomed with the keyboard Page-Up/Page-Down keys, or the "In"
+and "Out" buttons in the toolbar. The zooming in this case keeps the same map
+center (no centering).
+
+Panning/Centering:
+The map can be centered at a specific location by choosing center in the
+right-click options menu.
+
+Panning is also accomplished by using the options menu, or by using the arrow
+buttons on the toolbar. The map position will shift a portion of a screen.
+Enough data from the previous screen should be available to re-orient yourself.
+
+The map can also be panned with the keyboard arrow keys.
+
+More About Options Menu:
+
+Map Display Bookmarks
+See the help topic "Creating and using Map Display Bookmarks"
+
+The "Station Info" selection on the options menu will look for the station
+closest to where you right-clicked the mouse. If more than one station is
+close to that position a "Station chooser" list will appear, then you can
+choose what station's data you want to look at. If only one station is close
+to the mouse pointer then that station's data will display immediately. For
+mobile stations with a lot of track data this could need some time on slow
+computers. Note that expired stations still have their data stored in the
+Xastir database, and if one knows a station's former location, one can still
+view its info in this manner. Use the "Display Expired Data" option
+to display some data that disappears for ghosted stations, like
+speed/altitude, etc.
+
+With "Last Pos/Zoom" you can restore the previous map view by restoring the
+previous values of the map zoom and centering values.
+
+For Object and Item information, please see the help topic "Objects and Items"
+
+Draw CAD objects lets you create polygons on screen, for tactical or
+presentation use. This feature is still under construction.
+
+"Move my Station here" Allows you to move your station to a specified map
+location without editing the station configuration.
+
+HELP-INDEX>Objects and Items
+
+A station could place several different objects on the map, with their
+position transmitted to other stations. The object names are less restrictive
+than the normal station names.
+
+Objects and items are nearly the same things, but their use could differ a bit.
+Objects are generally used for moving or variable things such as thunderstorms,
+while items are generally used for more inanimate things, such as water
+stations. Because items may not be decoded by some flavors of APRS(tm)
+programs, objects are often used for inanimate things, too.
+
+Besides normal objects with a symbol at its position there are some special
+objects available. Area objects are useful for a variety of operations in
+which you want to draw or highlight an area of interest on the map. They can
+also be used to draw trails/roads/boundaries, watch boxes for severe weather,
+runways, perimeter of a search area or of a public service event, areas of
+damage, areas to stay out of, buildings that aren't on the map, checker/chess
+boards for gaming on APRS(tm). :-) Note that area objects are not
+implemented on all versions of APRS(tm) programs, and some of the details of
+how they are displayed may also be different on other programs.
+For the other three, probability circles, signposts and DF objects, see below.
+
+Objects/Items are retransmitted at a decaying rate up to the max interval
+specified in File|Configure|Timings. "killed" objects/items are also
+retransmitted in this manner until they expire from the queue (currently 20
+transmits). Objects/Items are persistent across Xastir sessions, and are
+stored in ~/.xastir/config/object.log. This file may be cleared by selecting
+"Clear Object/Item history" from the Stations menu.
+
+The Object/Item creation option in the right click menu will bring up a dialog
+with the position of your object filled in based on where you clicked the
+mouse. You may fill in the details, and add an object/item from this menu.
+
+The Object/Item modification option brings you the object modification dialog.
+It is similar to the object creation dialog, except the object's current
+information is already filled out, and the object's name and a few of the
+other options can't be changed. You could also delete the object with this
+option.
+
+Objects and items can be moved with the mouse if the "Move" check-box on the
+toolbar is enabled.
+
+The Predefined Objects option in the right click menu allows you to rapidly
+place standard Search and Rescue objects without having to go through the
+Object/Item creation dialog. These objects include standard Incident
+Command System symbols for ICP, Staging, Base, and Helibase, as well as
+SAR objects for PLS, IPP (with 4 area circles), and LKP If an object of the
+same name as an object you select off the list allready exists, a new
+object will be created with a number appended to the end. For example,
+the first time you select Staging from the Predefined objects menu, an
+object named Staging will be created. If you then create an additional
+Staging object from the Predefined objects menu, it will be named Staging2.
+Heli- (and user defined objects ending in a "-") will be created as Heli-1,
+Heli-2, Heli-3, etc. If you have recieved one of these standard objects that
+was transmitted by another station, your first object will be named with an
+appended number. You may wish to assign a tactical call to your object in
+this situation (for example, replacing ICP2 with a tactical call).
+
+The Predefined Objects menu is customizable by modifying the files
+predefined_SAR.sys, predefined_EVENT.sys, and predefined_USER.sys, and then
+selecting one these files through the File/Configuration/Defaults dialog.
+See the predefined_SAR.sys file for details.
+
+Description of the entries in the object dialogue:
+
+= Signpost =
+This makes the object a signpost object. These signs can contain one
+to three characters, and currently appear in Xastir as a blank sign.
+Station Info shows the value contained on the sign.
+
+= Area Object =
+This makes the object an area object, and enables the area object controls
+described below.
+
+= DF Object =
+This is a direction-finding report. Enabling it allows you to choose Omni or
+Beam report, and allows you to put in the specifics for each. See:
+ http://web.usna.navy.mil/~bruninga/dfing.html
+and the APRSdos documentation for details on these useful techniques.
+(FIXME: Separate section on DF'ing techniques?)
+
+= Probability Circles =
+This allows you to define the radius (in miles) of two circles centered on
+the object or item. Min is the radius (in miles) of the smaller, inner
+circle, and Max is the radius (in miles) of the larger, outer circle.
+These circles are drawn in red. They can be used to assist in planning
+Search and Rescue operations. To create more than two circles, add additional
+probability circle objects to the same location. Probability circles may not
+be displayed by other client software.
+
+= Name =
+This is the name of the object or item. It may be up to 9 characters long,
+with spaces allowed inside the name. When modifying an object, this may not
+be changed. To rename an object you must delete the original and then create
+a new object. Note that if you select Signpost/Area Object/DF Object that
+this field and perhaps others are cleared. Enter the name AFTER you've
+selected the type of object it will become.
+
+= Station Symbol =
+You may select a symbol for the object. Press select to choose graphically,
+or see the symbol table help section for descriptions of each symbol. Note
+also that area objects, signpost objects, and DF objects have special fixed
+symbols and therefore can't be selected here. Those particular symbols get
+automatically assigned when you change to that type of object.
+
+= Location =
+The location of the object is specified here. If you selected "Create
+Object/Item" from the right-click menu, the location you clicked will be filled
+in. If you moved an object with the mouse, the new location will be in these
+fields. You can also type in a location, for instance you may be placing an
+object from an over-the-air voice report.
+
+= Generic Options =
+You may specify the speed, direction, and altitude of objects here. Some object
+types cannot have a speed or direction, in which case the fields are grayed
+out.
+
+= Signpost Text =
+If the object is a signpost object, you may specify the 1 to 3 digit
+number that appears on the sign here. Note that Xastir doesn't display
+signpost objects properly yet.
+
+= Area Object =
+Area Objects are used to highlight specific parts of maps, or to draw extra
+detail onto maps. This will be done with the following entries:
+ = Bright Color =
+ Use the brighter version of the colors allowed.
+ = Color-Fill =
+ The area should be filled, not just outlined. This may be useful to
+ exclude an area from a search or other event.
+ = Object Type =
+ Choose from the geometric shapes allowed.
+ = Object Color =
+ Choose the color in which the object will display. This is also affected
+ by the "Bright Color" option above.
+ = Object Offset Up =
+ In hundredth of a degree latitude. An unfortunate detail of the spec,
+ and hard to calculate easily. Suffice it to say that you can change
+ the size of the object once you place it.
+ = Object Offset Left except / =
+ In hundredth of a degree longitude. See above.
+ = Object corridor =
+ This is the width of a line area object. Useful for runways, weather
+ watch boxes, describing an area of interest or an area of exclusion, etc.
+
+Always delete your objects and items when you are done with them!
+Don't just allow them to expire from your cache, as they may hang
+around on other peoples' screens for an extended period.
+
+
+Description of weather watch boxes:
+
+Watch boxes and "areas of maximum concern" (AOMC) generated by the WXSVR
+(http://wxsvr.net/) are colored as follows:
+
+ Yellow dashed = Severe Thunderstorm Watch (looks like crime scene tape)
+ Yellow solid = AOMC for Severe Thunderstorm Warning
+ Red dashed = Tornado Watch
+ Red solid = AOMC for Tornado Warning.
+ Green dashed = Mesoscale (larger) discussion area
+ Blue dashed = Test Watch
+ Blue solid = Test Warning
+
+HELP-INDEX>CAD Objects
+
+ CAD Objects
+
+[CAD object support has moved from the right click menu to
+Map/Draw CAD Objects].
+
+CAD object support is preliminary at this time. Features and the user
+interface are subject to change.
+
+CAD objects are arbitrary shapes that you can draw on maps in xastir, but
+can't transmit by APRS.
+
+Currently supported CAD objects are:
+Polygons: Closed areas of at least three points.
+
+To create a CAD object, first press the Draw radio button on the toolbar.
+This will change the cursor to a pencil. Begin drawing a polygon by
+clicking with the middle mouse button (or both buttons on a two button mouse,
+for which you will need to have three button mouse emulation enabled). This
+places a point on the map. Now move the cursor somewhere else (the normal
+left click/right click navigation and zoom functions still work normaly) and
+click the middle mouse button again. This draws a line between the two points
+you have selected. Middle click again to draw another line segment and keep
+repeating until you have drawn all except for the closing line segment of your
+polygon. To close the polygon, select Map/Draw
+CAD Objects/Close Polygon. This will close your polygon and bring up a dialog
+that will allow you to enter a name, comment, and probability for the polygon.
+
+When you have finished drawing CAD objects, exit the CAD drawing mode by
+deselecting the Draw radio button on the toolbar.
+
+CAD objects can be edited from the View/CAD Polygons menu and from the
+Map/Draw CAD Objects/CAD Polygons menu. CAD objects can be deleted from the
+Map/Draw CAD Objects/Erase CAD Polygons menu.
+
+HELP-INDEX>View Menu
+
+ View Menu Options
+
+The View menu presents various ways to look at data in Xastir.
+
+Bulletins
+This is the APRS(tm) bulletin board, where important announcements are posted.
+If you are connected with the internet interface, it is a good idea to set the
+range field to a few hundred miles, to ignore posts from other portions of the
+world. "0" in the range field means the entire world. Click the "Change range"
+button to make changes to this field effective. Xastir currently does not
+support sending bulletins. Incoming bulletins will open this dialog
+automatically if you select "pop up new bulletins" in the Configure|Defaults
+dialog. The "View zero-distance bulletins" button enables viewing bulletins
+for which you don't have a range yet (they haven't sent a posit yet, but you
+received a bulletin from them). If this is unchecked, you must get a position
+from a station, and the station must be within the range selected (or range
+must be set to zero), in order for the bulletin to be viewed.
+
+Incoming packet data
+This displays the incoming data on your TNC or internet interface. The radio
+buttons below select if you want to see only TNC data, only internet data, or
+both.
+
+Mobile Stations
+This is a list of stations that are moving. Stations qualify for this list if
+they have moved (more than one position received for them), the symbol of the
+station is not considered. Information shown includes course, speed, altitude,
+position, number of packets received, number of visible GPS satellites, course
+from your station, and distance from your station.
+
+All Stations
+This option displays a table of all stations sorted alphabetically. It includes
+the number of packets heard, the time the station was last heard, the path that
+the most recent packet took, the PHG, and the comment of the station.
+
+Local stations
+This option displays only stations that are heard via your TNC. It includes
+the number of packets heard, the time the station was last heard, the path that
+the most recent packet took, the PHG, and the comment of the station.
+
+Last Stations
+This option displays a table of all stations sorted from most recently heard
+to least recently heard. It includes the number of packets heard, the time
+the station was last heard, the path that the most recent packet took, the PHG,
+and the comment of the station.
+
+Objects & Items
+This option displays only objects and items. It includes the number of packets
+heard, the time the objects/item was last heard, the path that the most recent
+packet took, the PHG, and the comment of the object/item.
+
+Own Objects & Items
+This option displays only objects and items that you control (i.e.: Have sent
+the most recent update for). It includes the number of packets heard, the time
+the objects/item was last heard, the path that the most recent packet took, the
+PHG, and the comment of the object/item. A ghosted icon indicates that the
+object has been deleted.
+
+Weather Stations
+This option displays a table of all the APRS(tm) weather stations and their
+data. Data includes wind course, wind speed, wind gust speed, temperature,
+humidity, barometric pressure, rain in the past hour, rain since midnight,
+and rain in the last 24 hours.
+
+Own weather data
+Displays your weather data if you have a weather station and have configured
+Xastir to access it.
+
+Weather Alerts
+Displays weather alerts received, including the alert flags, alert source/type,
+alert destination, expiration, message, and effected location. This data
+is used for the alert highlighting. Double-clicking on an alert will request
+further information about it via finger from the online WXSVR. This only
+works if you have internet access; future versions may access this data over
+radio as well.
+
+Message Traffic
+Shows all message traffic while the window is open. It includes the source,
+destination, interface, and message. The range option can limit this display
+to nearby stations, much like the range control on bulletins. A range of 0
+causes all messages to be displayed.
+
+GPS Status
+Shows the status of your GPS unit, including the type of fix and number of
+satellites acquired.
+
+Uptime
+Shows the amount of time elapsed since Xastir was started.
+
+HELP-INDEX>Map Menu and the Map Chooser
+
+ Map Menu and the Map Chooser
+
+Map Menu:
+
+Map Chooser
+This will present you with a list of map directories and/or files in your
+map directory. Checking the "Expand Dirs" option toggles the expansion of
+directories into individual map files. The properties dialog allows more
+advanced controls, and is described below. Click on map names to highlight
+them, this will cause them to be displayed when you click the OK button. You
+may select any number of maps. Clicking "Clear" will select no maps,
+clicking "Vector" will select only vector maps. The three "topo" options will
+automatically select all GeoTIFF images of the listed size. Clicking the OK
+button will display the selected maps. Cancel will abandon any changes.
+
+ Map Chooser Properties
+ Clicking the Properties button will bring up a dialog where you can specify
+ the layer in which maps appear, and in which zoom levels they appear. Higher
+ layer numbers are displayed on top of lower numbers. The range may be
+ specified from -99999 to 99999; it is suggested that you space your layering
+ numbers widely to allow later insertion of additional map layers. From this
+ dialog you may specify whether a vector map is drawn with color fills. This
+ is a per-map setting; the global disable option on the Maps menu can override
+ this. The Filled setting is ignored for raster maps (images). A setting of
+ "auto" allows a dbfawk file to control this parameter directly (usable only
+ if dbfawk is compiled in and the map in question is a Shapefile). You can
+ also select whether a map is considered by the "Auto maps" feature here.
+ Finally, you can specify the minimum and maximum zoom levels at which a map
+ is displayed. This is useful to prevent very detailed local maps from loading
+ at very wide zoom positions, and visa-versa. A minimum zoom of 10 means a map
+ will be displayed at all zooms including and above 10. Likewise, a maximum
+ zoom of 256 means a map will be displayed at all zooms below and including
+ 256.
+
+Map Display Bookmarks
+See the help topic "Creating and using Map Display Bookmarks"
+
+Locate Map Feature
+This option brings up a search dialog where you can search through the labels
+in a GNIS file to find a specific location. It will center the map on the
+new location if it is found. The "GNIS File:" entry is saved between calls
+and between invocations of Xastir. You must put GNIS files into the
+xastir/GNIS directory in order to use this feature.
+
+Find Address
+This option brings up a search dialog where you can enter an address. It will
+center on the map if the address is found. The path to the geo-coder file is
+saved between calls.
+
+Coordinate Calc
+This option opens a simple calculator that can convert between coordinate
+systems. This is useful for converting positions to the various formats used
+by different groups of people. This same calculator can be called up by the
+Calc button on some of the other dialogs. It's useful for entering coordinates
+in other formats.
+
+Configure menu:
+ Background color
+ This option controls the color of the background behind the maps you have
+ displayed. The background color is often entirely hidden by filled maps
+ (see below).
+
+ Map Intensity
+ This controls the brightness of any graphics used as maps. This option only
+ appears if you have compiled with GeoTIFF support.
+
+ Adjust Gamma Correction
+ This allows you to apply gamma connection to all loaded map graphics. Maps
+ can be adjusted individually in their .geo files, see the section on .geos in
+ "Map files and WX Counties". This option only appears if you've compiled with
+ ImageMagick support, and does not apply to geoTIFF maps; see the above
+ option.
+
+ Map labels font
+ This allows you to set the font style and size used for map labels.
+
+ Station Text Style
+ Controls which font and style to use for station text and others.
+
+ Icon Outline Style
+ This allows you to specify an outline that surrounds station icons. This
+ helps improve visibility on various backgrounds.
+
+ Configure Tigermap
+ Turning this option on causes Xastir to download the map from the US census
+ bureau's online tiger mapping server. The dialog that comes up allows one to
+ select which layers are displayed, as well as the brightness of the resulting
+ map. This is only available if you have compiled with ImageMagick support.
+ Tigermaps are always loaded as the bottom layer; they do not have layering
+ settings in the Map Chooser.
+
+Disable All Maps
+This option disables the loading of any maps. It is most useful when doing
+rapid zooming or panning, because it saves the need to load the maps on each
+redraw. Note that this option is not saved between sessions.
+
+Enable Auto Maps
+When enabled, any map found in the map directory (or any directory under it)
+will be displayed if it falls within the current display region. You can add
+any number of directory levels under the main map directory for your maps. Auto
+maps will go through any that have Auto Maps enabled (in the Map Chooser
+Properties dialog) check them all and find what map (or part) should be
+displayed. All Maps will be merged into the viewing area. If you have a large
+quantity of maps, very detailed maps or a slower computer this can be quite
+slow. When this option is off, maps selected with the Map Chooser and/or Tiger
+Maps dialog will be displayed.
+
+Auto Maps - disable Raster maps
+This option prevents Auto Maps from loading maps which are graphics (images).
+Only vector maps will be displayed in this case.
+
+Enable Map Grid
+When enabled, this option will display a grid on the map. If the coordinate
+system is UTM a UTM grid will be displayed. If the coordinate system is
+latitude/longitude then a latitude and longitude grid will be displayed. As you
+zoom in the grid switches to a finer resolution. The spacing of the latitude
+and longitude grid may be manually adjusted with the "+" and "-" keys.
+
+Enable Map Border
+When both Enable Map Grid and Enable Map Border are enabled, a narrow white
+border is drawn around the map and the grid lines are labeled using the
+selected coordinate system (File/Configure/Coordinate System), and the selected
+border font (Map/Configure/Map Labels font/Border Font). If the UTM or MGRS
+coordinate systems are selected, the grid lines will be labeled with easting
+and northing values only at zoom levels smaller than about 2048.
+
+Enable Map Levels
+When enabled, this option will try to filter out data when the zoom level
+shows large areas. This does not work will all maps but will work with the
+maps generated from Tiger Line maps at the aprs.rutgers.edu site, and with
+ESRI Shapefile maps. This does not decrease the loading times of the maps very
+much, rather it simply reduces screen clutter.
+
+Enable Map Labels
+This option toggles the display of map labels embedded in DosAPRS, WinAPRS,
+GNIS, and ESRI Shapefile format maps.
+
+Enable Area Color Fills
+This option controls the filling of vector maps. In certain cases, you
+may want to eliminate the fill to see maps below the top maps. This is a global
+control, maps may individually have color fill toggled in the properties dialog
+of the Map Chooser.
+
+Enable Weather Alert Counties
+This toggles the display of county warning area maps for severe weather.
+These maps can be obtained and installed according to the directions in the
+README.MAPS file. They are displayed on screen when special weather alert
+messages are received, and expire after a time or can be remotely canceled.
+The weather alert text can be seen under View|Weather Alerts. The
+xastir/Counties directory must be populated with the correct files from NOAA
+and Shapelib support must be compiled into Xastir in order to enable this
+functionality.
+
+Index New Maps on Startup
+This option controls if the map index file is built on startup. Most users
+should leave this enabled. If the timestamp of the map file is newer than
+the map index file, the map will be indexed.
+
+Index: Add New Maps
+This option adds any new maps to the max index. Same rules as the above
+Index New Maps feature, but a manual method of invoking it.
+
+Index: Reindex ALL Maps
+This option starts over from scratch, indexing every map it recognizes in the
+maps directory. This is useful if the Add New Maps function is skipping some
+maps, perhaps because of old timestamps on the map files. This function may
+take quite a while to complete if you have a lot of maps.
+
+Mouse pointer menu
+This option brings up the options menu normally available by right clicking.
+
+One note on maps: Many of the currently available vector maps for the
+U.S. were created in NAD 1927 datum, while Xastir and other APRS(tm) programs
+use WGS 1984 datum. If zoomed in to a small area on the map the datum
+shift may be very noticeable. The USGS topographic maps have their datum
+corrected by Xastir as they are displayed, so positions will generally
+be more accurate with those topographic maps.
+
+HELP-INDEX>Map files and WX Counties
+
+ Map files and WX Counties
+
+Map Types
+Xastir will work with various types of map files. All DosAPRS, Windows/Mac
+APRS(tm) map files are supported, as well as PocketAPRS format maps and GNIS
+(Geographic Names Information System) label files. Xastir also can be
+compiled to use external libraries to support XPixmap (XPM) images, GeoTIFF
+topographic maps, and ESRI Shapefile maps. The graphics handling capability
+of Xastir can be greatly extended by compiling with ImageMagick support,
+enabling support for many graphic formats as maps (see
+"http://www.imagemagick.org/www/formats.html"). Xastir supports weather
+alert maps in ESRI Shapefile format, available from NOAA.
+
+Details of locations to obtain many of the above types of maps are found in
+the file README.MAPS
+
+Map Locations
+Any map file should be stored in the /usr/local/share/xastir/maps directory
+on your computer. This location may be different on some systems, depending on
+how Xastir was compiled/installed. You can create any number of directories
+under this directory to help organize and separate your data. The maps will be
+loaded in alphanumerical order unless layering is specified.
+
+Hints on installing and organizing maps are found in README.MAPS.
+Maps in a pixel graphics format actually need a combination of two files,
+a data file with a graphic pixmap (.xpm) (or other format if you compiled
+with ImageMagick), and a calibration file (.geo). The .xpm file is the
+standard graphic format, available without additional libraries. If you
+want to save storage space you can use gzip to compress those files
+("gzip map.xpm" will result in "map.xpm.gz"). Xastir detects this
+automatically during map loading. You can use XView/Gimp/ImageMagick and
+other programs to convert gif, jpg, and tif images into this format if
+you don't have support for many image types compiled in (ImageMagick). If
+you have problems with maps in xpm format, try to load and save the
+graphics with Gimp first, to convert all unknown color names into the
+binary representation.
+
+The .geo file is a text data file that will tie the image to a location
+in the world. Here is an example of a .geo file that will cover the entire
+world with the map world1.xpm:
+
+FILENAME world1.xpm
+# x y lon lat
+TIEPOINT 0 0 -180 90
+TIEPOINT 639 319 180 -90
+IMAGESIZE 640 320
+
+.geo files can have many elements:
+
+FILENAME <filename>
+This specifies the filename of a map image to be loaded from the local disk.
+
+URL <http://website>
+This specifies the URL of a map image to be loaded from a web or ftp site.
+ImageMagick only.
+
+TIEPOINT <x-pixel> <y-pixel> <longitude> <latitude>
+Two tie-points are required, and more than 2 will be ignored.
+these two lines are for connecting an x,y pixel position in the image
+to a lat and long position on the earth. The points should be as close as
+possible to the upper left corner and the lower right corner of the image for
+best accuracy. The latitude/longitude are specified in decimal degrees.
+
+IMAGESIZE <pixels horizontally> <pixels vertically>
+This specifies the size of the image in pixels. If this is not set, the image
+will be loaded each map redraw, regardless if it is on screen or not.
+IMAGESIZE is a REQUIRED OPTION if a URL is specified. For local files, it's
+an optional parameter (we use ImageMagick to query the image size for local
+files).
+
+DATUM <datum>
+This feature is not implemented.
+
+PROJECTION <projection>
+This feature is only partially implemented, default is "LatLon", other
+possibility is "TM" to specify that the map is in Transverse Mercator
+projection.
+
+# <anything>
+Any line with the first character of a '#' will be ignored.
+
+ImageMagick specific image enhancements:
+
+GAMMA
+eg: GAMMA 1.2 or GAMMA 1.2,2.0,1.2
+The first will change overall gamma for this image, the second will
+lighten green more than red or blue.
+
+CONTRAST
+eg: CONTRAST 0 or CONTRAST 1
+Doesn't seem to do that much, other values make no difference.
+
+NEGATE
+eg: NEGATE 0 or NEGATE 1
+0 will negate all colors, 1 just grayscale colors.
+
+EQUALIZE
+No argument.
+
+NORMALIZE
+No argument.
+
+LEVEL <black_point, mid_point, white_point>
+eg: LEVEL 0,1,65535
+These values seem to be the defaults.
+
+MODULATE <brightness, saturation, hue>
+eg: MODULATE 90,150,100
+These are percents, 100,100,100 is the default.
+
+REFRESH <seconds>
+eg: REFRESH 900
+This tag is used for dynamic URLs such as weather radar, where you
+wish Xastir to auto-redraw the map at a specified interval. By
+adding this tag to weather radar .geos, you can watch the weather
+move across your screen. Xastir contains only one interval counter,
+so the smallest REFRESH interval loaded takes effect for all selected
+maps.
+
+TRANSPARENT
+Color to remove from the background (make it transparent). Use a
+number, 0=black. Color-mapped images use the map value, so white is
+usually 0xffffffff (32-bits of 1s). Values must be in hexadecimal,
+and are preceeded by "0x". The value can be obtained by using debug
+level 16. The first of the four numbers after "Color allocated is"
+is the colormap index.
+
+CROP <left top right bottom>
+Removes borders (makes them transparent). Values are in pixels with
+(0,0) at the upper left. A good value for the 620x620 NWS radar
+images is "CROP 35 20 616 600"
+
+Special/nonstandard .geo files:
+
+TIGERMAP
+A file with just the word "TIGERMAP" will cause Xastir to retrieve an
+online Tiger map of the area on screen. These are not available for every
+place in the world. "tigermap.geo" is automatically installed in the maps
+directory.
+
+TERRASERVER-SATELLITE
+A file with just the word "TERRASERVER-SATELLITE" will cause Xastir to
+retrieve a Terraserver satellite photo of the area on screen. Those
+services are not available for every place in the world. Note that using
+the Terraserver maps at any zoom above 256 will probably take a long time
+to load, won't show much detail, and probably won't display correctly. This
+is a limit of Microsoft's Terraserver, not Xastir. Also note that
+crossing UTM zone boundaries is not supported by Terraserver.
+"terraserver.geo" is automatically installed in the maps directory.
+
+TERRASERVER-TOPO
+A file with just the word "TERRASERVER-TOPO" will cause Xastir to retrieve a
+topographic map of the area on screen. Those services are not available for
+every place in the world. Note that using the maps at any zoom above 256
+will probably take a long time to load, won't show much detail, and
+probably won't display correctly. This is a limit of Microsoft's
+Terraserver, not Xastir. Also note that crossing UTM zone boundaries is not
+supported by Terraserver. "terraserver-topo.geo" is automatically
+installed in the maps directory.
+
+TERRASERVER-URBAN
+Same as above but with Terraserver colored urban-area satellite
+images. "terraserver-urban.geo" is automatically installed in the
+maps directory.
+
+TERRASERVER-REFLECTIVITY
+Same as above but with Terraserver reflectivity images.
+"terraserver-reflectivity.geo" is automatically installed in the
+maps directory.
+
+TOPORAMA-250k
+Canadian 1:250k scale topo maps, downloaded from findu.com.
+"CanadaTopo250k.geo" is automatically installed in the maps
+directory.
+
+TOPORAMA-50k
+Canadian 1:50k scale topo maps, downloaded from findu.com.
+"CanadaTopo50k.geo" is automatically installed in the maps
+directory.
+
+WMSSERVER
+Allows use of Web Map Services (WMS). An example "WMSRadar.geo" is
+automatically installed in the maps directory.
+
+
+
+geoTIFF maps are a combination of two files as well: a .tif and a .fgd file.
+The .tif file is the actual map data. The .fgd file need only contain four
+lines like this (but may contain many other lines):
+
+1.5.1.1 WEST BOUNDING COORDINATE: -122.000000
+1.5.1.2 EAST BOUNDING COORDINATE: -120.000000
+1.5.1.3 NORTH BOUNDING COORDINATE: 48.000000
+1.5.1.4 SOUTH BOUNDING COORDINATE: 47.000000
+
+Xastir uses only those four lines in its calculations to determine the corner
+points of a map, to see whether the map fits in the current viewport (so it
+can decide whether to skip it). If your map data are USGS topographic maps,
+the .fgd file should be readily available to you. If it is not, the mapfgd.pl
+script can create it for you. If you don't have a .fgd file, the map will load
+fine, but the white borders won't be cropped and the size and rotation may be
+off a tad bit. An added feature in Xastir is the ability to do datum
+translations from NAD 1927 to WGS 84 datum, which makes the USGS topographic
+maps much more accurate on the Xastir screen.
+
+Xastir can use USGS geoTIFF topographic maps directly from the CD drive.
+Manually mount the disk or use auto-mounter to do it for you, and make sure
+you have a sym-link created in your maps directory that points to where you
+mounted your CD-ROM drive. That's it!
+
+
+ESRI Shapefile maps are also a combination of several files, a .shp file, a
+.dbf file, and a .shx file. You only need to select the .shp file to load the
+map, but the other(s) must be present for the map to load correctly.
+
+
+GNIS (Geographic Names Information System) data is a collection of names of
+locations, or geographic features. These labels behave like map labels in
+Dos/WinAPRS maps. As you zoom in, more labels will appear, assuming you've
+selected the GNIS file as a map and have enabled Map Labels in the Maps menu.
+If you have some of them in the xastir/GNIS directory, you can also search
+for map labels within Xastir.
+
+
+WX County Maps
+All WX County maps should be stored in the /usr/local/share/xastir/Counties
+and Xastir only supports the ESRI Shapefile standard for these. Installation
+is explained in README.MAPS. You must have Shapelib compiled in.
+
+As NWS messages are received, different areas will get tinted to designate
+areas of concern. They are color-coded to specify different types of
+alerts. The colors are: Cyan for advisory, yellow for watch, red for warning,
+orange for canceled alert, royal blue for tests, and green for undetermined
+alert levels. The coloring is done with a pixmap stipple that displays the
+type of alert, if it is able to be determined. These changes were made so that
+the underlying maps may still be seen underneath the weather alert areas, and
+so the alert type may be more easily determined, as sometimes matching the
+alerts on screen and in the weather alerts dialog is difficult. The display
+of weather alerts may be turned on/off via the Map menu.
+
+HELP-INDEX>Stations Menu
+
+ Stations Menu
+
+These options will allow you to control the data displayed around the stations
+on the map. It will also let you track and find stations, and clear stations
+and trails in the database and from the map.
+
+Find Station
+See the help topic "Locating a Station".
+
+Track Station
+See the help topic "Tracking a Station"
+
+Fetch Findu Trail
+Downloads historic trail data from findu.com. Slider bars control the starting
+point and duration of data downloaded. For an example, if you wished to see
+the track that happened two days ago, all day long, you might set the first
+slider to 48 hours (start time of two days ago) and the second slider to 24
+hours to snag exactly one day's worth of data, from the start until 24 hours
+later.
+
+
+Export all
+This sub-menu allows saving data for all stations to files [or databases]
+
+ Export to KML file
+ Saves all stations and their trails to a Keyhole Markup Language
+ file in ~/.xastir/tracklogs. The filename will be the current
+ date and time with a .kml extension, e.g. 20080125-033045.kml
+ KML files can also be written on a regular basis using KML
+ Snapshots on the file menu.
+
+ Store to open databases [Not yet implemented]
+ [Store to database interfaces is currently only implemented through
+ individual SQL database interface dialogs]
+
+ To save a png snapshot of the current map, use File->PNG Snapshots
+
+Filter Data
+This sub-menu allows filtering of the displayed symbols:
+
+ Select None
+ Determines if symbols should be drawn on the map. The other options depend
+ on this being enabled.
+
+ Select Mine
+ Determines if your own station is shown on the map.
+
+ Select via TNC
+ Global toggle for displaying data received via a TNC, but may be narrowed:
+
+ Select Direct
+ This option only displays stations heard directly (not digipeated).
+
+ Select via Digi
+ This option displays stations heard indirectly via a digipeater.
+
+ Select Net
+ This option displays stations with data received via the Internet.
+
+ Include Expired Data
+ Causes Xastir to continue to display the station data that normally goes
+ away when the symbol is ghosted. The expiration time can be adjusted in
+ the File|Configure|Defaults menu.
+
+
+ Select Stations
+ Global toggle for displaying stations, but may be narrowed:
+
+ Select Fixed Stations
+ This option displays stationary stations.
+
+ Select Moving Stations
+ This option displays stations with multiple positions or non-zero speed
+
+ Select WX Stations
+ This option displays Weather Stations.
+
+ Select CWOP WX Stations
+ This option includes the display of citizen weather (non-ham) weather
+ data.
+
+ Select Objects/Items
+ Global toggle for displaying objects/items, but may be narrowed:
+
+ Select WX Objects/Items
+ This option displays weather Objects and Items. This includes tropical
+ storms and remote weather stations.
+
+ Select Water Gauge Objects/Items
+ This option toggles the display of water gauge (/w) objects.
+
+ Select Other Objects/Items
+ This option enables or disables the display of objects other than those
+ listed above.
+
+
+Filter Display
+This sub-menu allows filtering of the displayed data:
+
+ Display Callsign
+ Determines if the callsign is displayed.
+
+ Label Trailpoints
+ This option includes callsigns along trails, to help identify which
+ points belong to which stations.
+
+ Display Symbol
+ Determines if the symbol is shown to the left of the callsign.
+
+ Rotate Symbol
+ Some symbols will change their orientation to show the direction in which
+ they are traveling.
+
+ Display Trail
+ When enabled, any moving station will trail a colored line. We now display
+ as many locations as we have in our database (old limit was 100). Long
+ trail segments (over 2 degrees latitude or 2 degrees long), or segments with
+ more than 45 minutes receive delay between the points will not be displayed.
+ Duplicate points are also eliminated from the track (SAR team returning to
+ base: Last segment may not be displayed due to the starting point appearing
+ twice in the trail list).
+
+ Display Course
+ When enabled, green text will appear below the call sign. This will display
+ the last known course (in degrees) the station was traveling.
+
+ Display Speed
+ When on, red text will appear below the call sign (or course). This will
+ display the last known speed of the station.
+
+ Display Short Speed
+ This option removes display of the measurement units for speed.
+
+ Display Altitude
+ When enabled, blue text will appear above the call sign. This will display
+ the last known altitude of the station.
+
+
+ Display Weather Info
+ Global toggle for displaying weather information, but may be narrowed:
+
+ Display Weather Text
+ When enabled, the latest weather data (temp,wind speed/course/gust,
+ humidity) is displayed. This may be adjusted with the following option:
+
+ Display Temperature Only
+ Displays only the temperature data for the station.
+
+ Display Wind Barb
+ When enabled, a wind barb showing the direction and speed of the wind is
+ drawn for all displayed stations reporting this information.
+
+
+ Display Position Ambiguity
+ When enabled, the area in which station using position ambiguity may be
+ located within is shaded, with the relevant station in the center.
+
+ Display Power/Gain
+ When on, Power/Gain Circles will be displayed. Overlapping circles indicate
+ that the stations are theoretically within simplex range of one another.
+ This is only roughly accurate, especially in areas of variable terrain.
+
+ Use Default Power/Gain
+ Enables a default power/gain setting as specified in the APRS(tm)
+ specification.
+
+ Display Mobile Power/Gain
+ Enables power/gain circles for mobile stations.
+
+
+ Display DF Attributes
+ When enabled, any DF circles/lines will be displayed on the screen.
+
+ Enable Dead-Reckoning
+ When enabled, the positions of stations are estimated based on past course
+ and speed. The recalculation rate should be reasonable, but can be adjusted
+ in the configuration file.
+
+ Display Arc
+ Displays an expanding arc of expected maximum travel distance, location and
+ course given the past course and speed. The arc slowly becomes a circle as
+ the position report gets older.
+
+ Display Course
+ Displays an expected course and distance traveled by the station, assuming
+ the course hasn't changed.
+
+ Display Symbols
+ Displays a ghosted version of the stations symbol at the expected position,
+ assuming the station has continued at its current course and speed.
+
+
+ Display Dist/Bearing
+ When enabled, two lines of text will be displayed on the left side of the
+ stations' icon. The top line will contain the distance from your station to
+ this station. The bottom line will contain the course from your station to
+ this station.
+
+ Display Last Report Age
+ Display the time since the station was last heard.
+
+Reload Object/Item History
+This will reload the ~/.xastir/config/objects.log file used for Object and Item
+persistence. This is needed if you edit the file while Xastir is running.
+
+Clear Object/Item History
+This will clear the ~/.xastir/config/objects.log file used for Object and Item
+persistence. It is recommended that you manually select and delete all Objects
+and Items that you own before doing this, otherwise they may remain on the
+screens of other APRS(tm) users.
+
+Clear All Tactical Calls
+Clears all assigned tactical calls. This will take effect the next
+redraw. Note that this will NOT clear tactical calls on other
+peoples' screens if you've published them via a message to
+"TACTICAL" (see the help text for "Send Message").
+
+Clear Tactical Call History
+This removes the tactical call history file, meaning that tactical calls
+assigned will not remain permanent between Xastir restarts. Note
+that this will NOT clear tactical calls on other peoples' screens if
+you've published them via a message to "TACTICAL" (see the help text
+for "Send Message".
+
+Clear All Trails
+This will wipe all the line tracking data from the station database and
+refresh the screen. This option is perhaps useful if you're low on memory
+or just want an uncluttered screen. You may also clear individual stations'
+trails from the Station Info dialog.
+
+Clear All Stations
+This will wipe all the data from the station database except yours. This
+option is perhaps useful if you're low on memory or just want to unclutter
+your screen.
+
+HELP-INDEX>Messages and the Messages menu
+
+ Messages and the Messages menu
+
+Send Message to and Open group messages
+
+These are very similar. "Send message to" will send your messages to one
+station and will only receive data from that station. Group messages are more
+general: you can receive any message for the group and you will send out your
+messages to that group name. Group messages code is not fully implemented yet
+and various problems still need to be worked out. The "groups" file is looked
+for in ~/.xastir/config. This is where the groups you are a member of are
+stored. As was said before the "groups" functionality may not be complete yet.
+
+At some point in the near future sending of bulletins should be added to this
+menu as well. It's not coded yet.
+
+Each of these two screens contains a message box, a call line, a message line,
+and various buttons. You must first enter the call of the group or station you
+want to contact. Once that is done any new message that has come in from that
+station to you will be displayed. If the station is sending you information
+and no message window is up it will automatically pop up a new window (up to
+10) with that station's call sign filled in for you. You can now enter a
+message on the message line. The message can be longer that the message line,
+and will max out at about 250+ characters. Once your message is entered,
+clicking on the "Send Now!" button will send your message. The "Send Now!"
+button will gray out until your message is completely ack'ed. Any message you
+receive will be sorted by the line # and be placed in the message window. If
+you are in a group mode each line will display the call sign from where the
+message was sent followed by the message itself. Currently group messages are
+sorted by call and then line #. When you are done sending messages clicking on
+the exit button will close the window. Other buttons are also available: The
+"New Call" button will allow you to look at old data a station has sent. Type
+in the call and click on this button, any old information will be displayed.
+You can also use this button to change the call of the station you're talking
+with. Enter the new call and click the button. The "Clear Msg History" button
+will clear any message displayed in the message window. "Cancel Pending Msgs"
+will cancel any messages in the transmit queue that haven't been acknowledged
+by the remote station yet. After canceling the pending messages or receiving
+and acknowledgment packet from the remote station, you may send new messages to
+the remote station. Xastir will allow you to type ahead, so you can just keep
+typing if you don't want to wait for the acknowledgments.
+
+Messages in reply to previous ones will attempt to use the path of the
+received message to avoid flooding the system with broadcast messages. You
+may adjust the path in the send message dialog, or the default path(s) set
+in the interface control will be used if you leave this blank. The path
+can be set for each message sent, but once a message is sent the path
+remains fixed for that particular message.
+
+Each outgoing message remains highlighted until it is ack'ed by the remote
+station. If it times out or if you cancel the pending messages, those
+messages will remain highlighted unless you clear the message history.
+
+To publish TACTICAL calls to other Xastir and APRS+SA stations as
+well as assign those tactical calls locally: Send a message to
+"TACTICAL" with the body of the message containing lines something
+like:
+
+ callsign-1=TAC1;callsign-2=TAC2;callsign-3=TAC3
+
+To remove these tactical calls later from local AND remote screens,
+assure that the original message(s) assigning them has timed-out or
+been cancelled, then send a message like this and let it retry until
+it times out (assigns blank tactical calls to the original
+callsigns, thereby removing the assignment):
+
+ callsign-1=;callsign-2=;callsign-3=
+
+Clear all outgoing messages
+This will clear all un-ack'ed messages you have sent.
+
+General Stations Query
+This sends an ?APRS? packet, which should cause all local stations to report
+their position and/or status. Most software ignores this query, because
+responding to it would cause massive floods of data.
+
+IGate Stations Query
+This sends an ?IGATE? packet, which should cause all local IGates to respond
+with their capabilities.
+
+WX Stations Query
+This sends an ?WX? packet, which should cause all local weather stations to
+report their position and weather.
+
+Modify Auto reply message
+This will set the message that is sent as an Auto Reply.
+
+Enable Auto Reply Msg
+This will turn on an automatic reply when an incoming message is received.
+
+Satellite Ack Mode
+This mode disables the sending of ack messages in response to received
+messages. Messages are still acknowledged using the reply-ack system. When
+operating over a satellite it is clear that your message made it, because you
+will hear it repeated. The receiving station sending an independent ack only
+adds QRM.
+
+HELP-INDEX>Interfaces Menu
+
+ Interfaces menu
+
+This menu contains interface related options.
+
+Interface Control
+This option displays a window where you can turn on and off your configured
+interfaces, as well as add, delete, or configure interfaces. See the "Configure
+Interfaces" help topic.
+
+Disable Transmit options
+These options disable the transmission of everything, one's position, or one's
+objects. These are global options and affect all interfaces. Most interfaces
+have an option to disable transmission on that specific interface in their
+configuration menus as well.
+
+Enable Server Port
+This enables/disables TCP and UDP listening sockets at port 2023. You may
+connect other APRS(tm) clients to the TCP port in order to send/receive
+APRS(tm) data. Once they authenticate, they'll be able to send data to Xastir.
+Without authentication, they'll be able to receive every bit of TNC and INET
+data that Xastir receives. Note that ANY user with the proper credentials can
+come in on the TCP or UDP ports if they are enabled. The only one of these two
+ports currently that can send to RF is the UDP Server port. The TCP
+port cannot.
+
+ "user WE7U-13 pass XXXX vers XASTIR 1.3.3"
+
+Connect another APRS(tm) client to that port and it should authenticate and be
+able to send to any server that Xastir is connected to, as well as receive
+packets from all ports/servers Xastir is hooked to.
+
+You should also have a binary called "xastir_udp_client" which can send packets
+into the UDP listening port. Invoke it like this:
+
+ xastir_udp_client localhost 2023 <callsign> <passcode> "APRS Packet Goes Here"
+
+Currently that will inject the packet into Xastir's decoding routines and send
+it to any TCP-connected clients. It will also igate it to the INET if you have
+igating enabled. It will send the packet out the RF ports as third-party
+packets only if you add the "-to_rf" flag after the passcode like this:
+
+ xastir_udp_client localhost 2023 <callsign> <passcode> -to_rf "APRS Packet"
+
+The UDP client is useful for generating and injecting APRS packets from
+external scripts. It can also be used to fetch the callsign of the remote
+xastir server by using the -identify flag:
+
+ xastir_udp_client localhost 2023 <callsign> <passcode> -identify
+
+Transmit now
+Causes all interfaces that have transmit enabled (see configure|interfaces) to
+transmit a position packet. It will be grayed out if Disable Transmit: ALL
+is selected.
+
+If you have GPSMan installed, you have these additional menu options
+displayed:
+
+Fetch GPS Track
+Download a set of trackpoints from an attached GPS.
+
+Fetch GPS Routes
+Download a set of routes from an attached GPS.
+
+Fetch GPS Waypoints
+Download a set of waypoints from an attached GPS.
+
+Fetch Garmin RINO Waypoints
+Snag waypoints from an attached Garmin RINO, create APRS(tm) Objects out of any
+waypoints which begin with "APRS".
+
+HELP-INDEX>Station info box - FCC and RAC lookup
+
+ Station info box - FCC and RAC lookup
+
+Station Info will display any data decoded by Xastir.
+
+You can assign (local only) tactical calls to stations from here, by
+clicking the "Assign Tactical Call" button. This will cause the
+station on screen to display as the tactical call instead of its
+callsign. Assigning a blank tactical call clears this feature, and
+it can also be cleared for all stations in the Stations menu. This
+feature assigns tactical calls to the local Xastir station only, but
+see below to publish them to others.
+
+To publish tactical calls across the air to other Xastir and APRS+SA
+stations (as well as assign them locally), see the "Send Message" help
+section.
+
+"Enable Automatic Updates" will cause the window to refresh frequently with the
+latest information.
+
+The information available may include: Number of packets heard, the time
+last heard, the device the packet came from, station comments,
+power/height/gain of the station, course/distance from your station,
+weather information, and current and previous positions.
+
+For moving stations a track-log follows with the most recent entries on top.
+A '+' in front indicates that a new track starts at that point (if there was
+a large gap in time or position). A star at the end of a line indicates that
+this station could be heard direct (without a digi) at that specific position.
+Positions are followed by the 6 digit Maidenhead grid square the station was
+located in at that point.
+
+For your own station, there is an "Echoed from" field, listing the
+last six digipeaters that heard you directly. This is useful for setting
+non-generic paths.
+
+Currently two rows of four buttons appear in the Station Info window. Some
+of the labels on the buttons change based on the type of station that you're
+dealing with.
+
+For objects/items:
+
+Store Modify Blank Close
+Track Object/
+ Item
+
+Station Trace Un-Acked Direct
+Version Query Messages Stations
+Query Query Query
+
+For other stations:
+
+Store Send Search Close
+Track Message FCC (RAC)
+ Database
+
+Station Trace Un-Acked Direct
+Version Query Messages Stations
+Query Query Query
+
+"Station Version Query" changes to "Clear Track" for mobile stations.
+The Clear Track button will clear any line tracking for this station that is
+currently stored or on the map display.
+
+"Store Track" will save the track of the station to a file on disk. The
+format is similar to that used by GPS receivers but its specification
+might be changed (enhanced) in future versions. There is currently no
+way to read that track data back in, but it is planned for the future.
+The goal is to also read and display GPS track-logs in a similar manner.
+These track-log files will be placed in the directory ~/.xastir/tracklogs
+with a name equal to the stations call with ".trk" as extension. "Store
+Track" will simultaneously save the station's track as a Keyhole Markup
+Language (.kml) file with a filename equal to the station's call, the
+current date and time and .kml as extension. If shapefile support has
+been included, the station's track will also be saved as a set of four
+files (.dbf,.prj,.shp,.shx). Subsequent presses of Store Track for the
+same station will write additional lines into the .trk file, and create
+new .kml (and shapefile) files (each containing all positions in the
+station's track.
+
+"Modify Object/Item" will bring up the Object Modify window.
+
+"Send message" will open up the message window and allow you to send a message
+to this station. It will fill in the call sign for you.
+
+If the FCC (U.S. Federal Communications Commission) or RAC (Radio Amateurs of
+Canada) database is installed and the callsign appears to be a Canadian or
+U.S. callsign, the "Search FCC/RAC Database" button will become active,
+otherwise this button will be inactive. The FCC and RAC files should be
+placed in the /usr/local/share/xastir/fcc directory, and case is important!
+Pressing this button adds the station's name and address into the Station
+Info box. Instructions for installing these databases are in the README.MAPS
+file.
+
+Xastir will create index files for each database file upon startup. If a newer
+callsign file is placed there while Xastir is running, it will create or
+rebuild the index on the next lookup. Special prefixes are NOT handled.
+
+HELP-INDEX>Creating a log
+ Creating a log
+
+Xastir can log data from the internet or TNC for later playback, or for
+debugging purposes. WARNING: Logging can fill up your hard drive, so be
+careful using it, or make preparations for rolling over the log files
+automatically via cron. An indication will be shown on the status bar when
+logging is enabled.
+
+All these choices are accessible via the File menu:
+
+Enable TNC Logging
+Logs all TNC data received and transmitted. These logs can be played back using
+the "Open Log File" feature.
+
+Enable Net logging
+Logs all internet data received and transmitted. These logs can be played back
+using the "Open Log File" feature. If you have no interfaces started but still
+want to log your posits and objects locally, this is the option to enable for
+that as well.
+
+Enable IGate logging
+Logs all data forwarded in both directions, and rejected forwards with reasons
+for rejection. Includes NWS messages forwarded to RF.
+
+Enable WX logging
+Logs all weather data received from your weather station.
+
+
+HELP-INDEX>Replaying a log
+
+ Replaying a log
+
+Click on "File", then "Open Log File" and a file selector window will display.
+You can use it to browse your hard drive and select any file containing raw
+TNC data like those created by the TNC and Net logging options. Your station
+will still function the same way, receiving and transmitting. If you were
+logging data, the typical place to look for those files would be
+~/.xastir/logs/
+
+NOTE: This function doesn't read the saved station tracklogs.
+
+HELP-INDEX>Locating a Station
+
+ Locating a Station
+
+Click on "Stations", then "Find Station". A window will pop up. You can now
+enter a call or part of a call. By default it will search for an exact match
+(full call, not partial) and is not case sensitive. If you are looking for a
+partial match, "Match Exact" should not be selected.
+
+For objects which could contain lower case letters you have to check
+"Match Case"! Opposite to the name, without "Match Case" the search
+text will only be converted to upper case...
+
+Clicking on the "Locate Now!" button will center the first station
+found in the center of your screen at the current zoom level.
+
+Clicking "FCC/RAC Lookup" will look up the user's information if the FCC or RAC
+database, of those databases are installed.
+
+Clicking on "Cancel" will close the window.
+
+This dialog will pop up if a station sends a Mic-e "Emergency!" packet, to
+encourage users to locate and perhaps help the listed station.
+
+HELP-INDEX>Creating and using Map Display Bookmarks
+
+ Creating and using Map Display Bookmarks
+
+Click on "Maps", then "Map Display Bookmarks" and a window will pop up.
+If this is the first time you have used this then the box will have no
+entries in it. To add a bookmark to the list: Position the main map to
+the area and zoom level you want to use. Enter a unique name in the
+"New Name" area, then click on add. Your entry will be added to the
+list (in alphabetical order). You can add as many map display bookmarks
+as you want. To use one of the bookmarks mark its name and click
+"Activate!". The main map will then show the stored area and zoom level.
+You can similarly delete a bookmark by clicking on the bookmark name and
+then the "Delete" button.
+
+"Maps->Locate Map Feature" is another method to jump to a location, if
+the name of the location is known and you have GNIS files installed.
+
+HELP-INDEX>Tracking a Station
+
+ Tracking a Station
+
+Click on "Stations", then "Track Station". Enter the callsign to track (all or
+part) then click on the "Track Now!" button. As the station moves it will
+remain viewable in the main map window. As the stations starts to get close
+to the edge of the map window the window will re-center so that the object is
+always visible. To stop tracking this station click on the "Clear Tracking"
+button. While tracking is active, a "Tr" is shown in the status bar next to
+the zoom level. If the station is not on the map yet, tracking will begin
+as soon as it shows up.
+
+HELP-INDEX>Printing
+
+ Printing the Map Screen
+
+Note: Printing has not been set up on Windows/Cygwin. These instructions
+are for Unix and Unix-like operating systems.
+
+Xastir can print the drawing area in either black & white or color. It does
+this by first dumping the image to an XPixmap file on disk, then using external
+tools to convert it to postscript, scale it, rotate it, preview it, then print
+it. You must have your system printing set up to handle postscript (usually
+this requires Ghostscript and a print filter installed, as well as lp or lpr
+print spoolers). You must also have the following tools installed for this
+capability: ImageMagick tools (specifically "convert"), "Ghostscript",
+Ghostscript fonts, and "gv". Once all of these packages are installed and
+functional, you should get a "gv" window popping up shortly after you tell
+Xastir to create a print file. From there you can view the printed image, and
+if acceptable, tell "gv" to print it. Note that sometimes changing to a white
+default background for the maps is recommended, depending on what maps you have
+viewable. This can save greatly on ink.
+
+HELP-INDEX>Creating Snapshots
+
+ Creating Automatic Snapshots
+
+Xastir has the capability to create automatic snapshots of the map screen
+on a recurring basis. The default time period is set at once per five
+minutes. Assuming that you have "convert" from the ImageMagick tools
+installed, Xastir will create an XPM format file in ~/.xastir/tmp/, then
+convert it to the PNG file ~/.xastir/tmp/snapshot.png. This file is useful for
+embedding in web pages to show a "live" image of what is on your Xastir
+screen. Enable this feature via the "File->PNG Snapshots" toggle-button.
+The rate is once every five minutes (configurable from the Configure
+Timing dialog from "File->Configure->Timing"), or every time the button is
+toggled from off to on. A .geo is created to allow you to use the snapshot
+as a map. A .kml file is also written to allow you to use the snapshot as
+a graphic overlay on terrain in applications capable of reading kml. See
+kml_snapshot_to_web.sh and kml_snapshot_feed.kml in the scripts directory
+for more information on using the snapshot.png and snapshot.kml file to
+produce a kml feed using the snapshots.
+
+ Creating Automatic KML Snapshots
+
+Xastir is capable of writing all current stations and tracks to a kml file
+on a recurring basis. Enable this feature via the "File->KML Snapshots"
+toggle button. The rate at which these snapshots are generated is the same
+as that of PNG snapshots, configured from "File->Configure->Timing" by
+setting the snapshot time interval. Each snapshot is written to a .kml
+file in ~/.xastir/tracklogs, with a filename based on the date and time
+of the snapshot, e.g. 20080206-000720.kml This behavior may change to
+make KML snapshots write to a single file like PNG snapshots.
+
+
+HELP-INDEX>Included Scripts
+
+ Included Scripts
+
+Xastir includes several Perl scripts and a shell script that may be useful:
+
+get-fcc-rac.pl
+This shell script automates retrieving and installing the FCC and the RAC
+callsign databases. Note that these databases are very large!
+
+icontable.pl
+This script generates an xpm bitmap of all Xastir's primary and secondary
+symbols from the symbols.dat file. The overlays and specials are ignored.
+Output is to STDOUT, so a typical call would be "icontable.pl > symbols.xpm".
+
+inf2geo.pl
+This script creates .geo files from UI-View .inf files. To create a map.geo
+from a map.inf, typical usage would be "inf2geo.pl map".
+
+kiss-off.pl
+This script sends the commands needed to turn off a TNC's KISS mode.
+
+mapblast2geo.pl
+This script creates .geo files for Mapblast pixel maps. It includes usage
+information.
+
+mapfgd.pl
+This script creates minimal .fgd files for GeoTIFF images lacking them, based
+on information found in the GeoTIFF file. The created files allow Xastir to
+crop the white borders and rotate/scale the map properly. Typical usage would
+be "mapfgd.pl mapdir" where mapdir is the directory containing the GeoTIFF
+images.
+
+overlay.pl
+This script creates .log format files from comma-separated overlay files. See
+the script comments for full usage information.
+
+ozi2geo.pl
+This script creates .geo files from OziExplorer .map files.
+
+permutations.pl
+This script converts between different lat/lon formats. See the script comments
+for further details.
+
+split_gnis.bash
+This will take a GNIS data-point file (typically for a whole state, 8+MB), break
+it down into smaller chunks (typically for a county, 30-200k) it will also
+throw away the trailing spaces and <CR>s at EOL.
+
+split_gnis.pl
+This is a Perl version of the above script.
+
+test_coord.pl
+Tests for the Coordinate.pm Perl module.
+
+track-get.pl
+This script downloads the track-log of a specified object from a Garmin GPS.
+It requires the GPS::Garmin module. It prompts for an object name, and writes
+the track-log to the ~/.xastir/logs directory.
+
+update_langfile.pl
+This script is targeted toward developers. It rebuilds a specified language
+file to contain all the strings of another. It is usually used to regenerate
+the non-English language files when significant changes have been made to the
+English file. When the second language file lacks a string in the main file,
+the untranslated string is inserted. Typical usage would be
+"update_langfile.pl language-German.sys" . The main language file is
+hard-coded but easily editable.
+
+waypoint-get.pl
+This similar script downloads the waypoints from a Garmin GPS, and creates a
+log in the ~/.xastir/logs directory containing the waypoints as objects. It
+also requires the GPS::Garmin module.
+
+db_gis_mysql.sql db_gis_postgis.sql
+These will create tables for storing station data in a mysql or postgresql/
+postgis database. SQL Server database support is experimental. See the
+"OPTIONAL: Experimental. Add GIS database support" section in INSTALL
+
+HELP-INDEX>Configuring Interfaces
+
+ Configuring Interfaces
+
+Click on Interfaces, then Interface Control.
+
+An "Installed Interfaces" box should appear. This box will allow you to add,
+delete, and modify the properties of various devices you may want to use with
+Xastir.
+
+Supported interface types are:
+Serial TNC
+Serial TNC w/GPS on HSP cable
+Serial GPS
+Serial WX
+Internet Server
+AX.25 TNC
+Networked GPS (via gpsd)
+Networked WX
+Serial TNC w/GPS on AUX port
+Serial KISS TNC
+Networked Database (Not Implemented Yet)
+Networked AGWPE
+Serial Multi-Port KISS TNC
+SQL Databases [MySQL,Postgis] (Experimental)
+
+To add a device, click on the add button. A "Choose Interface Type" box will
+appear. Click on the type of device you would like to add. Then click the Add
+button in the "Choose Interface Type" box. Properties for that device will
+appear. Fill out the requested information and click OK.
+
+To delete the device, click on the device you wish to delete and then click
+the delete button.
+
+To modify the properties of a device, click on the device you wish to modify,
+then click the properties button. The properties for that device will appear.
+Change the information you want and click OK.
+
+More specific help is available under the help topics of each interface type.
+
+SQL Databases will only appear as an option if you have MySQL or Postgis
+support compiled.
+
+HELP-INDEX>Configure Serial TNC Devices
+
+ Configure Serial TNC Devices
+
+This section covers adding or modifying Serial TNCs or Serial TNCs with a
+GPS on a HSP cable.
+
+If you have a HSP cable, which allows you to share the TNC port with a GPS
+unit you may choose a TNC with GPS (HSP Cable). This is a special cable and may
+not work on all computers/GPS/TNC combinations. If you use this device the TNC
+and the GPS should be set to the same communications parameters. Generally
+4800 bps, 8 data bits, no parity, and 1 stop bit.
+
+TNC Port Options:
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Allow Transmitting" will tell Xastir that any outgoing RF data can
+be sent to this device for broadcast.
+
+The TNC Port is the Unix device that the TNC (or TNC and GPS) is hooked to.
+Normally you can use /dev/ttyS0 (com1), /dev/ttyS1 (com2) etc.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Now set the bps rate under port settings, and the parameters under port
+style. Port Style setting 8N1 is used for 8 data bits, No parity and 1 stop
+bit. 7E1 is used for 7 data bits, even parity and 1 stop bit. 7O1 is used for
+7 data bits, odd parity, and 1 stop bit. These parameters must match your TNC
+and GPS.
+
+Choose the correct IGate operation for this device. You may have several TNC
+devices, and this option can be different for each device. If you are not
+running an IGate leave it at the default option of "Disable".
+
+Enter up to three UNPROTO paths. Xastir will assume the XX VIA part of the
+UNPROTO path. There are three paths allowed so that your signal will be heard
+if conditions are bad. XASTIR will cycle through each one that is filled in,
+one per transmission time. If you are local to a digi, just WIDE2-2 may be a
+good choice. If you are using low power and/or are distant from a digi then
+WIDE1-1, WIDE2-2 may work better. Or if you know the call of your closest digi you
+may use XXXCALL, WIDE2-2. Most of you will only need one path. If you are in a
+remote area and your signal is difficult to get out you may need more. Check
+with a local group and ask what path may be best for your area. If no paths are
+entered it will default to WIDE2-2.
+
+If you are IGating to RF, you may enter a specific path to use for the packets
+you send to RF. If you leave this blank, the UNPROTO paths above will be used.
+If the UNPROTO paths are blank, WIDE2-2 will be used.
+
+TNC Startup and Shutdown files. These fields specify a filename that is
+located in the /usr/local/share/xastir/config directory. Each file is a
+standard text file containing any commands you would like to send your TNC at
+the time the device is activated (startup file) or shut down.
+
+HELP-INDEX>Configure Serial TNC w/GPS on HSP cable or AUX port
+
+ Configure Serial TNC w/GPS on HSP cable or AUX port
+
+These hybrid interface types implement the options of both serial TNCs and
+GPSs. Please consult the configuration help for both serial TNCs and serial
+Gpsd for further information on the configuration of these devices.
+
+"Send Control-E to get GPS Data?"
+
+This checkbox controls whether Xastir sends a Control-E to the TNC every time
+it needs GPS data.
+
+Some TNCs that support a GPS on an auxilliary port require that Xastir
+send a Control-E to the TNC in order to get the GPS data each time it
+is needed. Devices in this class include the Kantronics KPC-3+.
+
+Some devices, like Kenwood APRS radios (D700, etc.) do NOT require
+this, and in fact the Control-E interferes with correct operation of
+these devices.
+
+Because Control-E was required by the most common TNCs that had an aux
+port for GPS at the time that this interface type was written, this is
+the default behavior of Xastir. If you have a Kenwood radio that you are
+using in this mode, you must DESELECT the "Send Control-E to get GPS data?"
+checkbox in the configuration dialog for this interface type.
+
+HELP-INDEX>Configure Serial KISS TNC
+
+ Configure Serial KISS TNC
+
+This section covers adding or modifying Serial KISS TNCs. KISS mode can be done
+by most standard TNCs too, and it eliminates the necessity to set the options
+specially in the startup files, at the expense of slightly higher processor
+usage. And of course this enables the use of purely KISS TNCs, such as the one
+described in the November 2000 issue of QST, without a separate program or
+kernel module.
+
+Options
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Allow Transmitting" will tell Xastir that any outgoing RF data can
+be sent to this device for broadcast.
+
+Selecting "RELAY Digipeat?" will tell Xastir to digipeat traffic. It will do
+this if the first unused digipeater call in the path matches your callsign or a
+callsign listed in your Xastir config file ("RELAY_DIGIPEAT_CALLS" line,
+default is "WIDE1-1"). This option is only recommended for base stations in
+regions where there are few other fill-in digipeaters in the area. Consult with
+a local group about the best setting for your region. You may hand-edit the
+Xastir config file when Xastir is not running in order to change this string to
+match your local recommendations. In the U.S., "WIDE1-1" is the recommended
+setting.
+
+The TNC Port is the Unix serial device that the TNC is hooked to.
+Normally you can use /dev/ttyS0 (com1), /dev/ttyS1 (com2) etc.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Now set the bps rate under port settings.
+
+Choose the correct IGate operation for this device. You may have several TNC
+devices, and this option can be different for each device. If you are not
+running an IGate leave it at the default option of "Disable".
+
+Enter up to three UNPROTO paths. Xastir will assume the XX VIA part of the
+UNPROTO path. There are three paths allowed so that your signal will be heard
+if conditions are bad. Xastir will cycle through each one that is filled in,
+one per transmission time. If you are local to a digi, just a WIDE2-2 may be a
+good choice. If you are using low power and/or are distant from a digi then
+WIDE1-1,WIDE2-2 may work better. Or if you know the call of your closest digi
+you may use XXXCALL,WIDE2-2. Most of you will only need one path. If you are in
+a remote area and your signal is difficult to get out you may need more. Check
+with a local group and ask what path may be best for your area. If no paths
+are entered it will default to WIDE2-2.
+
+If you are IGating to RF, you may enter a specific path to use for the packets
+you send to RF. If you leave this blank, the UNPROTO paths above will be used.
+If the UNPROTO paths are blank, WIDE2-2 will be used.
+
+Next configure the KISS parameters: TXdelay is the time (in 10ms units) needed
+between the keying of the radio and when it is ready to send data. Persistence
+and slottime are the channel access parameters: Slottime is how often the
+channel access algorithm is executed, and should usually be set to 10.
+Persistence is how aggressively your station tries to grab the channel when
+free, and should be ideally set to 255 divided by the number of stations on the
+channel. Full duplex allows the transmission to begin while there are packets
+being received on the channel, this should be disabled in most cases (set to
+"0").
+
+HELP-INDEX>Configure AX.25 TNC Devices
+
+ Configure AX.25 TNC Devices
+
+This section covers adding or modifying AX.25 TNC devices. AX.25 devices can
+be any device that uses the Linux AX.25 drivers. This is a kernel level
+driver, and device such as a Baycom or a sound modem can be used as a TNC.
+These devices must be set up and running before Xastir can use them.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Allow Transmitting" will tell Xastir that any outgoing RF data can
+be sent to this device for broadcast.
+
+Selecting "RELAY Digipeat?" will tell Xastir to digipeat traffic. It will do
+this if the first unused digipeater call in the path matches your callsign or a
+callsign listed in your Xastir config file ("RELAY_DIGIPEAT_CALLS" line,
+default is "WIDE1-1"). This option is only recommended for base stations in
+regions where there are few other fill-in digipeater stations in the area.
+Consult with a local group about the best setting for your region. This is
+only needed if you are not using any other software that performs this
+function, such as aprsdigi or DIGI_NED. You may hand-edit the Xastir config
+file when Xastir is not running in order to change this string to match your
+local recommendations. In the U.S., "WIDE1-1" is the recommended setting.
+
+Enter the AX.25 Device name you specified in the axports file for this device.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Choose the correct IGate operation for this device. You may have several TNC
+devices and this option can be different for each device. If you are not
+running an IGate leave it at the default option of "Disable".
+
+Enter in up to three UNPROTO paths. Xastir will assume the XX VIA part of the
+UNPROTO path. There are three paths allowed so that your signal will be heard
+if conditions are bad. Xastir will cycle through each one that is filled in,
+one per transmission time. If you are local to a digi, just a WIDE2-2 may be a
+good choice. If you are using low power and/or are distant from a digi then
+WIDE1-1,WIDE2-2 may work better. Or if you know the call of your closest digi
+you may use XXXCALL,WIDE2-2. Most of you will only need one path. If you are in
+a remote area and your signal is difficult to get out you may need more. Check
+with a local group and ask what path may be best for your area. If no paths
+are entered it will default to WIDE2-2.
+
+If you are IGating to RF, you may enter a specific path to use for the packets
+you send to RF. If you leave this blank, the UNPROTO paths above will be used.
+If the UNPROTO paths are blank, WIDE2-2 will be used.
+
+NOTE: To use AX.25 devices with Xastir you will need to run the program as
+"root". If you want to run Xastir as another user you may want to set the
+suid bit on the Xastir program file. Please see INSTALL file for more
+information; current Xastir drops the extra privileges but has not been audited
+for exploits. Use in this fashion in a multi-user environment at your own risk!
+
+HELP-INDEX>Configure Serial GPS Devices
+
+ Configure Serial GPS Devices
+
+Set the serial port device for your GPS unit. Common values of /dev/ttyS0
+(COM1) or /dev/ttyS1 (COM2) can be used.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Set system clock from GPS data" will tell Xastir to try setting the
+system's clock to the highly accurate time signal from the GPS receiver. This
+requires root privileges on most systems.
+
+Now set the bps rate under port settings, and the parameters under port
+style. Port Style setting 8N1 is used for 8 data bits, No parity and 1 stop
+bit. 7E1 is used for 7 data bits, even parity and 1 stop bit. 7O1 is used for
+7 data bits, odd parity, and 1 stop bit. These parameters must match your GPS.
+Most GPS units will use 4800 bps and 8,n,1.
+
+HELP-INDEX>Configure Networked GPS Devices
+
+ Configure Networked GPS Devices
+
+If you need to share the GPS data with different programs or machines, this
+option is best. Xastir will work with gpsd which will allow several
+connections to share your GPS data.
+
+Set the host name (or IP address) and the port number for the gpsd host on
+your network.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Reconnect on failure" will tell Xastir to try to reconnect when the
+data stream has failed.
+
+Selecting "Set system clock from GPS data" will tell Xastir to try setting the
+system's clock to the highly accurate time signal from the GPS receiver. This
+requires root privileges on most systems.
+
+HELP-INDEX>Configure the Internet Server
+
+ Configure the Internet Server
+
+Internet Servers allow you to send and receive data for all over the world.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+setup communications with it when the program first starts.
+
+Selecting "Allow Transmitting" will tell Xastir that any outgoing Internet
+data can be sent to this device.
+
+Enter the host name (or IP address) and the port number of the Internet
+Server you want to contact.
+
+Enter a valid pass-code to validate your connection, this will allow your
+data to be transmitted via an IGate. If you don't have a pass-code, use the
+included "callpass" program to generate one. Note that passcodes are dependent
+on callsigns. From the src directory, "make callpass" should create the
+executable if it isn't already compiled.
+
+Enter any filter parameters. This causes a special message to be sent to the
+server requesting that the data be filtered in a certain way. The exact format
+of this field is fully specified, please consult APRSSIG for more information.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Reconnect on failure" will tell Xastir to try to reconnect when the
+data stream has failed.
+
+HELP-INDEX>Configure a Serial WX Station
+
+ Configure a Serial WX Station
+
+Set the serial port device for your WX unit. Common values of /dev/ttyS0
+(COM1) or /dev/ttyS1 (COM2) can be used.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Now set the bps rate under port settings, and the parameters under port
+style. Port Style setting 8N1 is used for 8 data bits, No parity and 1 stop
+bit. 7E1 is used for 7 data bits, even parity and 1 stop bit. 7O1 is used for
+7 data bits, odd parity, and 1 stop bit. These parameters must match your WX
+unit. The Data Type option will allow you to override what type of serial data
+the program will look for. The auto-detect feature will first look for Weather
+data in a binary type as the Radio Shack WX-200 uses. If no binary data is
+found in the stream, Xastir will look for an ASCII type of WX station (like
+Peet Bros.).
+
+Now set the Rain Gauge correction factor. Xastir requires that the rain gauge
+report in .01 inch increments. If the unit reports in .1 inch or .1 millimeter
+increments, a correction must be specified to obtain accurate measurements.
+
+HELP-INDEX>Configure a Networked WX Station
+
+ Configure a Networked WX Station
+
+Xastir can use WX data servers such as wx200d. wx200d will allow several
+network connections, thus sharing the Weather data with several programs or
+computers.
+
+Enter the host name (or IP address) and the port number of the WX data server
+you want to contact.
+
+Comment will allow you to set a friendly name or comment for the port.
+
+Selecting "Activate on start up" will tell Xastir to look for this device and
+set up communications with it when the program first starts.
+
+Selecting "Reconnect on failure" will tell Xastir to try to reconnect when the
+data stream has failed.
+
+As before the Data Type will override the auto detection.
+
+Now set the Rain Gauge correction factor. Xastir requires that the rain gauge
+report in .01 inch increments. If the unit reports in .1 inch or .1 millimeter
+increments, a correction must be specified to obtain accurate measurements.
+
+HELP-INDEX>Configure an AGWPE Connection
+
+ Configure an AGWPE Connection
+
+Xastir can use an AGWPE network interface running on a Windows box
+as a TNC interface. It can also use the login/password security that
+AGWPE has built-in, but you must set up the account in the AGWPE
+application with your callsign for the username, in all capital
+letters. For instance: "AB7CD".
+
+The other options are described in the sections for Serial TNC and for
+Network interfaces.
+
+HELP-INDEX>Configure a SQL Database Connection
+
+ Configure a SQL Database Connection
+ [Experimental]
+
+Xastir can experimentally store and retrieve station data from either
+a MySQL database or a Postgresql + Postgis database. See the
+"OPTIONAL: Experimental. Add GIS database support." section in the
+INSTALL file for more information. Station and object data are stored
+as spatial data, and can be retrieved from other GIS applications, for example
+Xastir can write station locations into a Postgis database from which they
+can also be viewed using QGIS. SQL database connections also allow for the
+persistence of data between Xastir sessions. All aspects of spatial database
+support, including database structures, are currently experimental and may
+change at any time. You may configure multiple SQL database connections,
+but you should only have one active at a time.
+
+Before creating a database connection in Xastir, you will need to create a
+database to connect to, create an appropriate set of tables
+(see the db_gis_xxxxx.sql scripts in the scripts directory), and add a user
+with a password and rights to access the database. For postgis databases
+you may also need to appropriately configure the user in pg_hba.conf
+
+Configuration options on the SQL database dialog include:
+Database: MySQL (lat/long) for very old MySQL databases,
+ Postgis for postgresql + postgis, and
+ MySQL (Spatial) for current MySQL databases.
+With tables for: Currently only the Xastir simple schema - a very basic
+ flat table holding minimal information about stations.
+Host: IP address or hostname for the database server, default is localhost.
+Port: Default is 3306 for MySQL and 5432 for Postgresql. The database can
+ be on a remote server, but the appropriate port will need to be
+ open in any firewalls.
+Username: Can be unique to your database, e.g. xastir_user
+Password: Unique to your database.
+Schema name: Your database name. e.g. xastir
+MySQL Socket: check my.cnf, or mysql --help | grep socket
+ Leave blank for postgis databases.
+Reconnect on Net Failure: [Not yet implemented]
+MySQL defaults and Postgis defaults provided by the buttons may
+or may not be correct for your database.
+
+Three options control the behavior of the SQL Database interface:
+Activate on Startup: Try to connect to this database and begin storing heard
+station data as soon as Xastir starts (if store incoming data is also selected).
+
+Store incoming data: Stores each station (including objects and items) report
+as a record in the database. All stations heard on all interfaces will be
+stored to the database - if you are connected to internet feeds and leave
+xastir running this can easily be a million records per day.
+
+Load data on startup: Retrieve all station data from the database
+when restaring Xastir. Currently the only way to retrieve persistent
+data from a database. Will attempt to connect to database and retrieve data
+independent of the settings of either activate on startup or store incoming
+data. Due to rounding and conversion errors, non-mobile stations may move
+slightly.
+
+The "Most Recent Error" box may or may not contain an error message to help
+identify connection problems. When Xastir fails to connect to a database,
+the interface will show ERROR on the interface list, and the most recent error
+may be shown here. Running xastir from the console and observing error
+messages there, or running xastir from the console with xastir -v1 may help
+identify the cause of connection problems, as may examination of the
+database's error logs.
+
+You will only be able to configure a SQL Database interface if you have
+compiled Xastir with support for that DBMS (--with-mysql or --with-postgis).
+
+HELP-INDEX>Symbol Table
+
+These are the symbols that you can select for your station under the "Station
+Information" configuration menu. The current list can be found in the APRS(tm)
+Reference which you could get from http://www.tapr.org
+
+ Symbol Table
+
+Symbol Group / Group \
+
+! Triangle w/! Triangle w/!
+" Rain Cloud Rain Cloud
+# Digi DIGI
+$ Phone Symbol $ Symbol
+% DX DX
+& GATE-HF GATE
+' Small Aircraft Aircraft Crash
+( Cloud Cloud
+) TBD
+* SNOW Flake SNOW Flake
++ Red Cross
+, Reverse L
+- House w/omni
+. Small x
+/ Red Dot
+0 0 in a box Circle
+1 1 in a box
+2 2 in a box
+3 3 in a box
+4 4 in a box
+5 5 in a box
+6 6 in a box
+7 7 in a box
+8 8 in a box
+9 9 in a box GAS
+: Fire ?
+; Tent Tent
+< Motorcycle Pennant
+= Train Engine
+> Car Car
+? POS Antenna ? in a box
+@ HURRICANE/STORM HURRICANE/STORM
+A First Aid Box
+B BBS Blowing Snow
+C Canoe
+D D in a circle
+E E in a circle Smoke Stack
+F F in a circle
+G Grid Square Antenna ?
+H Hotel/Bed
+I TCP/IP ?
+J J in a circle Lightening
+K School House
+L Light House Light House
+M Mac
+N NTS ?
+O Balloon
+P Police car Rx
+Q Circle with in Circles Circle with in Circles
+R RV Restaurant
+S Shuttle Satellite
+T Thunderstorm (cloud/bolt) Thunderstorm (cloud/bolt)
+U School Bus Sun
+V VOR TAC VOR TAC Symbol
+W National Weather Service NWS-Digi
+X Helicopter
+Y Sail Boat
+Z Windows
+[ Runner WC
+\ DF Triangle
+] Packet Mail Box
+^ Large Aircraft Large Aircraft
+_ Weather Station WS-Digi
+` Satellite Dish
+a Ambulance
+b Bike blowing cloud
+c DX antenna
+d Fire dept. DX Antenna
+e Horse Sleet cloud
+f Fire Truck FC Cloud
+g glider Pennant (2)
+h Hospital HAM
+i Island Island
+j Jeep Jeep
+k Truck Truck
+l Small dot Small Dot
+m MIC Mile Post
+n N Small Triangle
+o EOC Dot with in Circles
+p Puppy Dot with in Circles
+q GS Antenna GS Antenna
+r Antenna Tower Antenna Tower
+s Boat Boat
+t TS ?
+u 18 Wheel Truck
+v Van Dot with in Circles
+w H20 Flood
+x X Windows Red Dot
+y House w/Yagi House w/yagi
+z X Windows
+{ FOG FOG
+| Black Line Black Line
+} TCP TCP
+~ Sail Boat Sail Boat
+
+HELP-INDEX>What was new in Xastir 1.0
+
+Over the past year, Xastir has been under active development, and this new
+release is the culmination of those efforts. Development has been run by
+Chuck Byam, who agreed to take over for Frank Giannandrea. Many other
+individuals have contributed to this project, and are listed in the AUTHORS
+file.
+
+The Xastir package now uses GNU autoconf to build makefiles and select
+features based on the libraries and software one has installed. No more
+editing makefiles as in previous releases!
+
+Starting Xastir 1.0, one probably won't immediately notice any major
+changes. The familiar interface of previous Xastir versions has been retained
+for the most part. The great majority of the changes are improvements in
+efficiency under the hood:
+* Startup time for the program has been improved.
+* Memory usage has greatly improved, with dynamic allocation of separate
+ station, trail, and weather data on an as-needed basis. No longer will
+ memory be wasted on stationary stations for trail data, nor will non-weather
+ stations waste memory for weather information. With these modifications,
+ Xastir can even be connected to the internet link comfortably on a 16MB
+ machine.
+* Improvements have been made to avoid having to reload maps from disk at every
+ minor change; Weather alerts and changes to the display and tracking options
+ no longer cause the maps to reload, rather the trails and symbols are
+ redrawn alone.
+* Improvements have been made to various dialog boxes that re-drew often, to
+ redraw less often, to allow them to be usable on slower systems. This is
+ also true of tracking a station, with the map redrawing only if the station
+ approaches the edge of the screen.
+Thanks to these changes, Xastir is perfectly usable on slower Pentium(tm)
+machines.
+
+Native GeoTIFF support is now included, and will be compiled into one's copy
+of Xastir if they have the GeoTIFF libraries installed on their system. These
+map files are of very high quality, and are especially useful in search and
+rescue operations. Maps on this format are available from the USGS, and
+commercially on CD-ROM. Xastir understands how to convert from the NAD-27
+datum to the new WGS-84 datum, so maps of both format can be read accurately.
+New shortcut buttons have been added to the map selection dialog to enable
+one to pick all maps of a specific type.
+
+Support for the Festival Speech Synthesis System is now available to announce
+new stations and band openings. The old system of alert sounds has been
+retained as well.
+
+Xastir now supports adding and deleting objects. Finally, Xastir users are able
+to manage resources with this useful feature. Objects are helpful for
+coordinating events, directing travelers, and doing search and rescue work.
+
+The County Warning Area maps that display weather alerts are no longer painted
+onto the maps below, but are shaded onto the maps. While this does make the
+colors unpredictable, it is now possible to see the road-maps below the
+alert!
+
+A new and useful feature is the change in the orientation of a symbol based on
+the direction in which it is moving. Even without a trail, a quick glance can
+tell you a mobile station's bearing. There are several more new options in the
+display menu, enabling one to decide more precisely what is displayed and what
+isn't.
+
+Panning and control over the map has been enhanced: There are now arrow buttons
+visible at the top of the screen to pan the map. The map can also be panned
+with the arrow keys, and the zoom can be adjusted with the page up and page
+down keys. There are new option in the click menu, to center the map where you
+clicked or to place an object where you clicked. The panning options in this
+menu have been removed in favor of the new controls at the top of the screen.
+
+Support for altnet has been added, enabling one to have a private APRS(tm)
+network for special events, search and rescue, storm chasing, or whenever else
+the user doesn't want to be bothered by the hundreds of APRS(tm) stations
+around.
+
+There are numerous small changes, both visible and invisible to the user. The
+interface control dialog now has a "Start all" and "Stop all" option, to save
+the user the time of performing these actions for each interface. The station
+setup dialog now shows you your symbol, so you don't have to exit the dialog to
+see which symbol you chose. Several buffer overflows that caused unpredictable
+behavior and/or crashes have been fixed. And many minor improvements have been
+made to the source code to ensure that it compiles correctly on various
+systems.
+
+Enjoy the new Xastir!
+
+
+HELP-INDEX>What was new in Xastir 1.1
+
+ What was new in Xastir 1.1
+
+This new release, Xastir 1.1, adds significant new features and enhancements
+to the user interface. Unlike 1.0, the interface changes will take some getting
+used to, but the flexibility and versatility of the enhanced interface will
+more than make up for the troubles.
+Among the improvements to the user interface:
+* Keyboard shortcuts for menus and dialogs, menu reorganization, and mouse
+ behavior changes.
+* The ability to move objects or measure distance with the mouse, using the
+ appropriate check-boxes in the toolbar.
+* A scale has been added to allow one to judge distance on a map.
+* Map labels for windows-style APRS(tm) maps are rotated to match the marked
+ map features.
+* The user interface for dealing with objects has been entirely redesigned.
+* Station info boxes can be set to automatically update.
+* Tear-off menus. Allow you to keep a menu on the screen and play with
+ different options. Tear off a menu by clicking on the dashed-line portion.
+
+Map support has been greatly enhanced, with PocketAPRS, ESRI Shapefiles, GNIS
+labels and many graphics formats with ImageMagick. Additionally, support for
+downloading graphical maps from web-servers has been added, allowing Xastir to
+use online radar, Tiger, and Terraserver maps.
+
+Xastir 1.1 supports much more of the APRS(tm) protocol than its predecessor:
+* It can add, modify, move and view area objects, signpost objects, and items.
+ These features are invaluable for event coordination and search and rescue
+ use. Objects and items are also periodically retransmitted.
+* Support for displaying position ambiguity squares, pre-calculated radio
+ ranges, Maidenhead grid squares, and weather objects. These features aren't
+ extremely common, but do come up occasionally.
+* Support for the APRS(tm) radio direction finding features. These features
+ are useful for anything from tracking jammers to locating lost hikers. Xastir
+ supports both Omni and Beam reports.
+
+Other notable improvements:
+* Xastir can now search for a specified location or landmark using GNIS data.
+* Track logs can now be exported to file.
+* Maps can be printed if certain tools and libraries are present.
+* Support for retrieving historical track data from findu.com.
+* Xastir now compiles and runs on Mac OS X, Solaris and FreeBSD with only
+ minimal changes; see README for details.
+* Several major bugs found in 1.0 have been corrected, including the problems
+ loading DOS maps and the problems with the weather reporting. Other minor
+ bugs and memory leaks have been fixed. And several more errors have been
+ corrected in the parsing routines, so Xastir should remain stable no matter
+ what is thrown at it!
+
+
+HELP-INDEX>What was new in Xastir 1.2
+
+ What was new in Xastir 1.2
+
+The latest Xastir release adds numerous new capabilities, keeping Xastir a
+benchmark for APRS(tm) programs on any operating system.
+
+Xastir's hardware support has been enhanced, with
+* Support for Serial KISS TNCs
+* Support for Serial TNCs with GPS on the AUX port
+* Support for using AGWPE as a TNC
+* Support for Dallas One-Wire weather station
+ (see http://melhuish.info/simon/projects/oww/)
+* Support for more weather stations via the wx200d daemon (WX-200/WM-918/
+ WMR-918/WMR-968)
+* Support for the different sized rain gauges of the Peet Brothers weather
+ stations.
+
+Additionally, several bugs in the weather reporting code were corrected, and
+support for setting the system clock based on the GPS was added.
+
+There have been many additions and improvements to the Xastir user interface:
+The most notable is the addition of dead-reckoning. This means that stations
+that are moving will continue to move on your screen in the direction and at
+the speed speed that they last reported. The estimated location can be shown
+with any combination of a ghosted icon, a dashed line from the last position,
+or an arc of expected possible distance and angle.
+
+Also very notable are the improvements to the Map Chooser. Maps can now be
+selected a directory at a time, or individually. And the new map properties
+dialog allows individual control of map layering, map color filling, and
+consideration for auto-maps. Additionally, with extent caching under the hood,
+auto-maps regains much of its formal usefulness even with many maps installed!
+
+Bulletins pop up on screen, and emergency beacons cause an alert with the
+locate station dialog on hand. These changes are helpful in emergencies and
+event coordination.
+
+Xastir can now be set to use one of several coordinate systems, including UTM,
+dd.ddddd, dd mm.mmm, and dd mm ss.s. This is helpful for coordinating with
+other groups using a different system.
+
+The online Tiger maps can now be enabled from the map menu, and options can
+be adjusted to request maps with just the data you want displayed.
+
+The stations menu has been reorganized, allowing more intuitive filtering of
+stations shown and of accompanying data.
+
+Other smaller interface changes include:
+* The density of the grid-lines can be adjusted with the +, =, and - keys.
+* Objects and item lists have been added to the view menu.
+* Station maidenhead grid squares are now shown in station info and the
+ coordinate calculator.
+* There is a check-box "Track me" to enable easily tracking your own station
+* The length of trails downloaded from findu.com can now be specified.
+* Xastir can now ID via voice IDs or Screen IDs, by editing the configuration
+ file. This is intended for configurations when the Xastir screen is seen
+ remotely via fast-scan TV.
+* Timestamps are written to log files every 30 seconds of operation, to keep a
+ record of when data was heard.
+* The status bar can display the course/distance to your station when
+ enabled in the file|configure menu.
+* Range scales are now shown opposite the map scale. This is an attempt to
+ standardize various APRS(tm) client approaches to zoom levels.
+
+New additions under-the-hood:
+* Tracked proximity alarms.
+* Export waypoints within proximity boundaries. Your GPS can show
+ you the locations of APRS(tm) stations as waypoints on the GPS map
+ screen.
+* Export trail as ESRI Shapefile. New feature if you have Shapelib
+ compiled in. Station Info->Store Track button also creates a
+ Shapefile map of the station's track now.
+
+The weather reporting features have been improved, with the addition of
+optional wind barbs to weather stations and decoding of storm wind radius data.
+Weather alert shading is now done with pixmap stipples showing the type of
+alert. Further information on an alert is available over the internet from
+the WXSVR by simply double-clicking the alert in the weather alerts list.
+Weather alerts now use the newer ESRI Shapefile-format maps.
+
+Xastir's map support has been improved with enhancements to the ESRI Shapefile
+code to handle point-type ESRI Shapefiles. Additionally, speed improvements
+have been made in the ImageMagick graphical map loading, and many
+color-correction features have been added. As mentioned above, the Map Chooser
+has been greatly improved, and weather alerts use ESRI Shapefile-format maps.
+
+Under the hood, Xastir has had several major improvements:
+
+The messaging system has been largely rewritten, and the annoying timed updates
+to dialogs no longer occur. The new messaging system allows multiple messages
+to be queued, and implements reply-ack's for speed. Xastir also attempts to
+specify a reasonable path for the message based on received messages. This
+improves speed and congestion control. The messaging GUI has been largely
+untouched, and remains high on the list of future improvements.
+
+The build process has been significantly improved; Xastir is now able to be
+built on numerous operating systems with few manual interventions.
+
+Xastir now supports GPSMan/gpsmanshp, allowing the importing of waypoints,
+tracks, and routes from several types of GPS receivers. This allows you to
+create ESRI Shapefile-format maps out of GPS data.
+
+Xastir now implements SmartBeaconing(tm), which greatly improves trail quality
+and reduces unneeded channel usage. See the "Configure SmartBeaconing" help
+topic.
+
+IGating support has also improved, with the ability to configure a specific RF
+path for IGated packets, and the addition of a 29 second anti-dupe queue to
+reduce unnecessary redundancy on the RF channel.
+
+Map extents and filenames are now cached, so maps will not be loaded from disk
+unless they are on screen. This is a major improvement for map types that did
+not specify this information. Additionally, auto-maps uses this information,
+making it usable even with many maps installed.
+
+Objects controlled by Xastir are now stored in a file, so a restart of Xastir
+will not cause them to be lost. Additionally, Xastir now supports the
+compressed format for objects and items, which can help reduce RF channel
+congestion. It also gives you better location accuracy of the placed objects.
+See the help topic "Configure Default Operation".
+
+Xastir now drops root privileges when not needed if run setuid root. Please
+read the information about this in INSTALL; this change provides only
+limited protection.
+
+Xastir now supports using a private colormap with the command-line argument
+"-i". This is recommended for systems running in 8-bit color mode.
+
+Additionally, several more buffer overruns and other errors were corrected in
+Xastir's data parser, and numerous other bugs have been fixed.
+
+Enjoy the new Xastir!
+
+HELP-INDEX>What's new in Xastir 1.3
+
+ What's new in Xastir 1.3
+
+This latest Xastir release greatly improves on the efficiency and usability of
+Xastir, and adds many helpful and often-requested new features.
+
+.geo files can now have REFRESH tags, to specify how often the file is
+reloaded. This is useful for weather radars and other dynamic images. .geo
+files can also have a TRANSPARENT tag to make a certain color transparent, and
+a CROP tag to specify a specific region to display.
+
+Some Opentrac packets are now decoded and displayed. See
+http://opentrac.org/ for more details.
+
+The default main Xastir directory is now /usr/local/share/xastir; please see
+the upgrade notes in README for migration information. This more closely
+mirrors the behavior of other applications. If you're installing
+from a binary package (rpm/deb/etc), the default install location
+may be /usr/share/xastir.
+
+Xastir efficiency has been greatly improved. Changes in data structures and
+timing values have made this Xastir release the most efficient yet.
+Additionally, map redraw sequences are interruptible, so map panning speed
+has been improved.
+
+dbfawk support - Experimental support for configurable shapefile metadata, in
+an awk-like language. See README.MAPS for more details; this must be turned
+on with a specific switch to the configure command.
+
+GDAL/OGR support - Experimental support for GDAL and loading of native Tiger
+data (.RT1 files). This is automatically enabled if the GDAL library is
+found.
+
+Support for UTM w/special zones and MGRS coordinate systems.
+
+Cad drawing mode allows one to draw regions on your screen using the center
+mouse button. This feature is not yet complete, but is functional.
+
+User interface changes:
+* Several of the menus have been reorganized to have a hierarchical design.
+* Additionally, a few colors have been modified for better visibility.
+* The map label font and style are more configurable
+* The cursor changes to let one know if they're in move object or measure mode.
+* If the coordinate system is set to UTM, and "Map Grid" is selected, an UTM
+ grid is displayed.
+
+Snapshot mode now generates a .geo file, allowing the image to later be used
+as a map.
+
+Tiger maps have been moved back the chooser, as was the pre-1.2 behavior.
+This is more consistent.
+
diff --git a/help/help-Spanish.dat b/help/help-Spanish.dat
new file mode 100644
index 0000000..d4bfe40
--- /dev/null
+++ b/help/help-Spanish.dat
@@ -0,0 +1,1681 @@
+HELP-INDEX>L�AME PRIMERO - Licencia
+
+ L�AME PRIMERO - Licencia
+
+!!! NOTA: �Este Documento se actualiz� en Fecha 04/09/02 !!
+
+Para la informaci�n m�s actualizada por favor
+lea el archivo README.1ST en el directorio de Xastir.
+
+Recuerde que este programa es usado por la comunidad HAM, en los EE.UU
+la FCC le restringe de transmitir sobre RF si usted no es un HAM con licencia.
+Usuarios autorizados en otros pa�ses fuera de los EE.UU.
+Deben buscar sus restricciones gubernamentales locales.
+
+LICENCIA:
+
+XASTIR, Estaci�n de Aficionado de Rastreo y Reportes de Informaci�n.
+Copyright (C) 1999-2000 Frank Giannandrea
+Copyright (C) 2000-2012 The Xastir Group
+
+Este programa es software libre; usted puedes redistribuirlo y/o
+modificarlo bajo los t�rminos del GNU Licencia P�blica General
+como publicado por la Fundaci�n del Software Libre; cualquier versi�n 2
+de la Licencia, o (a su opci�n) cualquier versi�n m�s atrazada.
+
+pero SIN NINGUNA GARANTIA; a�n sin la garant�a impl�cita de
+COMERCIABILIDAD o APTITUD PARA UN PROPOSITO PARTICULAR.
+Vea el (GNU) Licencia P�blica General para m�s detalles.
+
+Usted debes de haber recibido una copia del GNU Licencia P�blica General
+junto con este programa; si no, escriba al Software Libre
+Fundaci�n, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, EE.UU..
+
+M�s informaci�n sobre el programa puede encontrarse en:
+
+http://www.xastir.org/
+http://sourceforge.net/projects/xastir/
+http://xastir.sourceforge.net
+
+Hay algunos Forum de discusiones disponibles que son espec�ficamente sobre Xastir.
+Usted puedes subscribirse en uno o en ambos de ellos para recibir las �ltimas
+informaciones y novedades sobre el desarrollo de Xastir.
+Visite esta direcci�n para subscribirse en http://www.xastir.org/.
+
+Para m�s informaci�n sobre la Licencia GNU busque en:
+
+http://www.gnu.org/
+
+
+HELP-INDEX>Bienvenido! y Notas de los Autores
+
+ �Bienvenido! y Notas de los Autores
+
+XASTIR, Significa, X-ventanas Estaci�n de Aficionado de Rastreo y Reportes de Informaci�n.
+
+ El significado en ingl�s es como sigue:
+XASTIR, or (X)windows (A)mateur (S)tation (T)racking and (I)nformation (R)eporting.
+
+Es un APRS(tm) como programa que es Fuente Abierta y libre para usarlo y pasarlo a otros.
+Actualmente este programa est� en desarrollo y no debe verse
+como un producto finalizado! Su ayuda ser� necesaria para hacer de este
+un mejor programa.
+
+Si usted tienes habilidades programando y/o puede escribir documentaci�n,
+su ayuda puede ser necesaria! Yo tengo muchas ideas pero el tiempo muy corto.
+As� que si usted piensas que usted puedes anexar algo al esfuerzo d�jemelo saber!
+
+73,
+Frank Giannandrea
+fgiannan at eazy.net
+
+
+APRS[tm] es una Marca de f�brica de Bob Bruninga,
+su p�gina est� en "http://web.usna.navy.mil/~bruninga/aprs.html"
+Por favor note que mucha de la informaci�n sobre APRS(tm) puede encontrarse
+en la documentaci�n de APRSdos escrita por Bob Bruninga. Una adicional
+fuente de informaci�n es el APRS(tm) especificaci�n, disponible en
+http://www.tapr.org
+
+HELP-INDEX>Que hay de nuevo en Xastir 1.1
+
+ Que hay de nuevo en Xastir 1.1
+
+Esta nueva versi�n, Xastir 1.1, agrega nuevos rasgos significantes y perfeccionamientos
+a la interface del usuario. Al contrario de 1.0,
+los cambios de la interface tomar�n algunos uso conseguido,
+pero la flexibilidad y versatilidad de la interface reforzada ser�
+mayor, trantando de sacar fuera los problemas.
+Entre las mejoras a la interf�z de usuario:
+* Los atajos del teclado para los men�s y di�logos, reorganizaci�n del men�, y rat�n
+ cambios de conducta.
+* La habilidad de mover objetos o medida distancia con el rat�n, usando el
+ apropiado marcado de caja en la barra de herramienta.
+* Una balanza se ha agregado para permitir a uno a juzgar distancia sobre un mapa.
+* Las etiquetas del APRS(tm) mapas para el estilo de ventanas son rotado para machar los rasgos de mapas marcado.
+* La interf�z del usuario por tratar con objetos que han sido redise�ado completamente.
+* Pueden ponerse cajas de info de estaci�n para fijar autom�ticamente actualizaci�n.
+* Rasgar-fuera los men�s. Permitiendole a usted mantener un men� en la pantalla y jugar con
+ opciones diferentes. Rasgar fuera un men� por pulsar el bot�n del rat�n en la porci�n del golpear-l�nea.
+
+El soporte del mapa se ha reforzado grandemente, con PocketAPRS, ESRI Shapefiles, GNIS,
+etiquetas y muchos gr�ficos estructuran con ImageMagick. Adicionalmente, soporte para
+bajar graficalmente mapas desde varios webservers han sido agregado, permitiendo a Xastir a
+use radar en l�nea, Tigre (Tiger), y mapas de Terraserver.
+
+Xastir ahora soporta mucho m�s del APRS(tm) protocolo que su precursor:
+* Puede agregar, modificar y ver �reas de objetos, el poste indicador de objeto, y art�culos. �stos
+ rasgos son inestimables para la coordinaci�n de evento y b�squeda y uso en rescate.
+ Los objetos y art�culos tambi�n son peri�dicamente retransmitido.
+* El soporte para desplegar ambig�edad de posici�n cuadra, rangos de radio precalculado,
+ Cuadra de rejilla, y objetos de tiempo. Estos rasgos no son
+ sumamente com�n, pero surge de vez en cuando.
+* El soporte para el APRS(tm) rasgos de radio-direcci�n-encontrada (RDF). Estos rasgos
+ son �tilidad para algo, desde rastrear localizar excursionistas perdidos. Xastir
+ soportas ambas Omni y direccional.
+
+Otras mejoras notables:
+* Xastir puede ahora buscar una localizaci�n especificada o punto en tierra usando el GNIS data.
+* Pueden exportarse ahora las bit�coras (logs) hacia un archivo.
+* Pueden imprimirse mapas si ciertas herramientas y bibliotecas est�n presentes.
+* Soporte para recuperar datos de rastreo hist�ricos desde findu.com.
+* Se han corregido varios bichos (bugs) mayores encontrados en 1.0, incluso los problemas
+ cargando mapas de DOS y los problemas con el informe del tiempo. Otro menores
+ bichos y goteras de memoria han sido reparada. Y algunos m�s errores han sido
+ corregido en las rutinas de parsing, as� que Xastir debe permanecer estable no importa
+ �lo que se tire en �l!
+
+Y muchas mejoras menores han sido hecha en el c�digo fuente
+para asegurar que compile correctamente en varios sistemas.
+
+Esperamos que usted disfrute el nuevo Xastir!
+
+
+HELP-INDEX>Iniciando a Xastir por primera vez
+
+ Iniciando a Xastir por primera vez
+
+Cuando Xastir se inicie por primera vez, usted debes ejecutarlo en una ventana
+terminal asi que cualquier mensaje de advertencia o error puedan verse.
+
+En la mayor�a de los sistemas una ruta es configurada para correr el programa
+en /usr/local/bin y todo lo que usted necesitas hacer es tipear "xastir"
+en la l�nea de comando.
+
+En sistemas que no tienen este tipo de ruta instalado "/usr/local/bin/xastir"
+para empezar el programa.
+
+Usted tambi�n puedes poner la opci�n del Idioma en este momento.
+Para poner el idioma o cambiar el idioma actual, use �sta l�nea:
+
+xastir -l
+
+
+Los Idomas Actuales son:
+
+Alem�n (German)
+Espa�ol (Spanish)
+Franc�s (French)
+Holand�s (Dutch)
+Ingl�s (English)
+Italiano (Italian)
+ElmerFudd (English)
+MuppetsSwedishChef (English)
+OldeEnglish (English)
+PigLatin (English)
+PirateEnglish (English)
+
+Si Usted quieres correr el Xastir en espa�ol use �sta l�nea:
+
+Ej: xastir -lSpanish o xastir -l Spanish
+
+Esta opci�n ser� guardada en el archivo de configuraci�n de usuario
+para que la pr�xima vez que Xastir se ejecute corra con el idioma Espa�ol.
+
+En nueva instalaci�n xastir tendr� como valor predefinido el idioma ingl�s
+a menos que usted uses �sta opci�n de l�nea de comando.
+
+NOTA: En men�s, se seleccionan art�culos que son encanecido,
+como en las opciones del ON/OFF, si 'ON' es seleccionado
+se opacar� o se pondr� transparente (encanecido).
+
+HELP-INDEX>Configurando la informaci�n de la Estaci�n
+
+ Configure la Informaci�n de la Estaci�n
+
+Pulse el bot�n del rat�n en Archivo luego Configurar despu�s en Estaci�n
+llene la casilla con su Indicativo de Radioaficionado.
+
+llene su posici�n de la estaci�n si usted no est�s usando Xastir con una unidad de GPS.
+Si usted no la conoce, usted puedes localizar su posici�n general en el mapa
+con Xastir y puedes usar la posici�n dada por colocar el puntero del rat�n sobre el mapa.
+
+Esta posici�n ser� visible en la barra del fondo de Xastir cuadro 2
+de la izquierda. Si usted tienes un GPS usted puedes saltar esta opci�n.
+
+Los s�mbol/grupo de la estaci�n pueden configurarse aqu�. Pulse seleccionar gr�ficamente y
+escoja un s�mbolo, o manualmente rellene los campos. Una descripci�n de texto de cada uno
+de los s�mbolos pueden encontrarse en la "Tabla de s�mbolo" tema de ayuda. Las cubiertas son cumplidas seleccionando un s�mbolo
+ de la tabla alternada, y poniendo el campo de la tabla a
+el car�cter que usted desea recubrir encima del s�mbolo. Letras may�sculas y
+los n�meros pueden ser recubierto. El APRS(tm) especificaci�n s�lo permite cubiertas sobre
+s�mbolos espec�ficos; Xastir no forza esto, pero algunos otros programas pueden.
+Note que no todos los s�mbolos se han llevado a cabo en el selector gr�fico
+todav�a, y algunos de ellos no est�n por el APRS(tm) especificaci�n todav�a.
+
+Luego, entre en los datos para la potencia/altura/ganancia de su estaci�n. Esta es
+una informaci�n �til pero no se requiere; absolutamente seleccione "Desactive PHG"
+desactivarlo. Estas opciones presentan una representaci�n granular de su estaci�n.
+Seleccione la combinaci�n de valores cerca a la descripci�n de su estaci�n.
+
+Otra opci�n ser�a especificar el RNG en el campo de comentario en millas
+en lugar de usar PHG. Vea el APRS(tm) especificaci�n para detalles.
+
+Por favor use altura sobre el promedio del terreno para el valor de altura. No
+use el promedio de altura sobre el nivel del mar o altura sobre tierra.
+
+Para el uso de Ganancia la ganancia de su antena en dBi.
+�(CORRIGEME: dBd? la especificaci�n no es clara,
+yo pienso que est� implicando dBi porque dice "en ausencia de cualquier datos,
+las estaciones son asumida a estar corriendo 10w a un 3dB omni en 20pies.
+Una antena omni t�pica es s�lo 3dBi.....)
+Para Altura, use el HAAT (altura sobre el promedio del terreno) de su estaci�n,
+NO la altura sobre el nivel del mar o altura sobre geo-id.
+
+Nota: La ganancia puesta es realmente pensada para las antenas verticales; la ganancia
+puesta para una antena direcional deber�a ser por debajo de la ganancia hacia delante de una antena direcional.
+Esto es porque con la direccionabilidad puesta, el c�rculo de PHG es compensado s�lo a trav�s de 1/3rd
+de su tama�o hacia la direcci�n especificada. Poniendo la Ganancia m�s alta agrandar�
+el c�rculo entero no-realisticamente, en lugar del aumentado direccionalmente.
+Hab�a charla hace varios a�os sobre el enmendando las especificaciones para mejorar
+trato con antenas direccional, pero nada fue cambiado.
+
+Entrar un comentario, no requerido pero agregar� visi�n en su estaci�n.
+Una cosa com�n para entrar aqu� es su direcci�n de e-mail preferida. Que
+ser� transmitido a lo largo con su postula.
+
+La ambig�edad de la posici�n permitir� usted controlar que tan exacto usted transmite su
+posici�n. Si usted no pone nada, xastir permitir� a su estaci�n transmitir la exacta
+posici�n que usted ha entrado o ha recibido de un GPS. Las otras opciones lo pondr�n
+en alguna parte en el rango de la opci�n que usted seleccion�. Note que
+esto puede tirar estaciones d�ciles a alguna no-especificaci�n para un bucle. Findu.com
+no entiende la ambig�edad de posici�n.
+
+Pulsando el bot�n "Aceptar" guardar�s sus cambios.
+Pulsando el bot�n en "Cancelar" conservar�s las actuales configuraciones.
+
+HELP-INDEX>Configurar Operaci�n Predefinida
+
+ Configurar Operaci�n Predefinida
+
+Pulse el bot�n en Archivo despu�s en Configurar luego en Predefinidos
+
+Esta p�gina prepara algunos valores por defecto normales para el funcionamiento
+del programa. Viejas estaciones se desplegar�n con un icono fantasma,
+y el sendero correspondiente se fragmentar�.
+
+El primer juego de botones de barra especifica el intervalo de desdoblamiento. El segundo
+juego de botones que especifica cuando una estaci�n ser� removida de la pantalla.
+Las estaciones tambi�n son removida del banco de datos interno en el doble este tiempo,
+as� si usted lo pusiera durante 6 horas, se anular�n estaciones del banco de datos
+a las 12 horas.
+
+El tercer juego de botones especifica qu� a menudo la identificaci�n de su estaci�n ser�
+transmitido. Para las estaciones fijas una recomendaci�n buena es cada 30 minutos,
+y definitivamente ninguno menos de 10 minutos.
+Las estaciones m�viles pueden desear una m�s r�pida proporci�n.
+
+Este intervalo tambi�n se usa para mandar objetos y art�culos. Pruebe
+mantener este intervalo algo razonable, como transmitir hacia un largo camino,
+cada 30 segundo realmente subir� mucho el tiempo a�reo.
+
+GPS Tiempo pondr� el intervalo de tiempo mirar el GPS por nuevos datos.
+Esto es disponible para estaciones que usan un cable compartido HSP con su TNC.
+
+La Opci�n Trasmite Estaci�n fija el tipo de paquete que su estaci�n transmitir� sus datos como.
+Transmite datos Raw WX si seleccionado tambi�n enviar� un paquete que contiene Datos raw
+de una Estaci�n Meteorol�gica. Esto es �til en los tipos de ASCII de estaciones WX, como la Peet Bros.
+
+Estaci�n WX. Las Opciones de IGate preparar�n su estaci�n como un portal de Internet-RF.
+Esta opci�n podr�a ser usada con cuatela, Como un HAM usted es responsable
+por el data que viene v�a el Internet y es transmitido hacia el Puerto de RF.
+
+Usted tambi�n necesitar�
+escoger una opci�n del igate en cada interface para que el igate funcione.
+Si usted quiere tener su igate env�e NWS alarmas WX hacia el RF, usted debe
+crear un archivo ~/.xastir/data/nws-stations.txt listando cada llamada o estaci�n de NWS
+(como "PHISVR") que le gustar�a transmitir v�a RF.
+
+"Transmitir datos de WX RAW", si seleccionado, tambi�n enviar� un paquete que contiene crudo (raw)
+Datos de estaci�n meteorol�gica. Esto es �til en los tipos de ASCII de estaciones WX,
+como la Peet Bros. estaci�n meteorol�gica.
+
+"Los datos de posici�n comprimida pueden ser transmitida"?, si es seleccionado, transmitir� en
+el m�s nuevo formato comprimido. Este formato reducir� la cantidad de datos en
+el aire, por eso aumentando la capacidad de la red APRS(tm). La m�xima
+precisi�n de la posici�n transmitida tambi�n es m�s alta. Algunos programas m�s viejos,
+incluyendo las recientes versiones de WinAPRS, no decodificar� este formato todav�a.
+Findu.com tambi�n podr�an tener problema con el.
+
+Activar Red Alternada ?
+esta opci�n se usa para desplegar grupos de estaciones que muestran
+en el unproto en el campo '>To' la versi�n del software como el Xastir
+que muestra la versi�n en el unproto como esto: HI8GN>APX090.
+
+Usted tambi�n puede seleccionar Altnet y puede escoger una llamada del altnet de este di�logo.
+Altnet le permite tener un privado APRS(tm) red entre las estaciones que tambi�n
+tenga altnet configurado, y tiene la misma llamada del altnet entrada.
+
+Si cambiamos el valor por defecto que es XASTIR por ejemplo por APX110
+desplegar� toda las estaciones que tengan versiones de APX11x
+donde valor de 'x' puede ser desde 0-9.
+
+HELP-INDEX>Configurando las Alarmas de Audio
+
+ Configurando las alarmas de Audio
+
+Para usar esta opci�n usted debes tener una tarjeta de sonido y un programa que
+reproduzcan los archivos wav. El programa reproductor de Audio debe tener
+comando el cual usted quieres ejecutar para tocar el audio archivo (y cualquier
+opci�n en la l�nea de comando).
+
+Los campos tendr�n el nombre del archivo a reproducir, campos bajo la opci�n
+pondr� par�metros para la opci�n.
+
+Las opciones Actuales son:
+
+ Reproducir mensaje al encontrar una nueva estaci�n.
+
+ Reproducir mensaje al recibir un nuevo mensaje.
+
+ Reproducir mensaje de datos recibidos de una estaci�n dentro de la distancia
+ min/max de su proximidad.
+
+ Reproducir mensaje de datos recibidos de una estaci�n (v�a TNC) con la
+distancia de min/max de su banda abrierta.
+
+HELP-INDEX>Configurar el Sintetizador de Voz
+
+ Configurar el Sintetizador de Voz
+
+Para usar esta opci�n del sintetizador de voz usted debes tener una tarjeta de sonido
+configurada para poder reproducir sonido.
+
+Tambi�n usted necesita tener instalado y corriendo al Servidor Festival m�s
+el Speech_tools con su biblioteca de soporte para el Sistema Festival de Voz S�ntetizada
+
+y asi poder escuchar el sintetizador de voz anunciar
+nuevas estaciones y aperturas de banda proximidad de una estaci�n.
+
+El sistema de alarmas de sonidos ha sido tambi�n retenido.
+
+Con el Sintetizador de Voz adaptado por Curt Mills (we7u)
+
+ajuste las casillas en las cuales usted quieres ejecutar el sintetizador para las alarmas
+
+(y cualquier opci�n en la l�nea de comando).
+
+Los campos tendr�n el nombre del archivo a reproducir, campos bajo la opci�n
+pondr� par�metros para la opci�n.
+
+Las opciones Actuales son:
+
+ Anunciar un mensaje al encontrar una nueva estaci�n.
+ Anunciar un mensaje al recibir un nuevo mensaje.
+ Anunciar un mensaje al recibir el cuerpo un nuevo mensaje.
+ Anunciar un mensaje de datos recibidos de una estaci�n dentro de la distancia
+ min/max de su proximidad.
+
+ Anunciar un mensaje de datos recibidos de una estaci�n (v�a TNC o INET)
+ con la distancia de min/max de su banda abierta.
+
+ Anunciar un mensaje al recibir una nueva alerta sobre el tiempo climatol�gico.
+
+Info sobre Festival puede ser obtenida desde: http://www.speech.cs.cmu.edu/festival/
+
+HELP-INDEX>Configurando las Unidades de Medida
+
+ Configure Unidades de Medida
+
+La selecci�n predefinida es para el Sistema M�trico, mm, cm, KPH, etc.
+Seleccionar Ingl�s, pulgadas, pies, MPH, etc. Pulse el bot�n de Configurar,
+luego en Unidades, despu�s la unidad de medida que usted quieres usar.
+Recuerde encanecida opciones son selecciona actualmente.
+
+HELP-INDEX>Salvar Configuraci�n Ahora!
+
+ Salvar Configuraci�n Ahora!
+
+Este bot�n salvar� todas la configuraci�n actual al archivo de configuraci�n.
+Note que cuando Xastir est� cerrado, tambi�n salva configuraci�n al archivo
+de configuraci�n.
+
+HELP-INDEX>Barra de Estado de fondo
+
+ Barra de Estado de fondo
+
+En el fondo de la ventana varios mensajes de estado est�n disponibles:
+
+En la primera parte en la barra de estados general los mensajes son desplegados.
+
+La segunda parte se muestra la posici�n lat/long
+actual moviendo el rat�n sobre el mapa.
+
+En la tercera parte es usada para mostrar
+cu�ntas estaciones est�n en el banco de datos.
+
+La cuarta parte de la barra desplegar� el nivel de enfoque actual y desplegar�
+"Tr" si el rastreo de estaci�n est� encendida (on).
+
+El �ltima �rea desplegar� el estado de dispositivo para cada interf�z. Cada una
+desplegar� en orden primero hasta el �ltimo o de 0 a 9. El estado de la interface est� separado
+en tres �reas, tipo de dispositivo cima, datos de centro fluyendo, y interface de fondo
+estado operacional. El tipo de dispositivo mostrar� qu� interfaces se configuraron.
+El color mostrar� qu� tipo de dispositivo de la interface se configur�. Azul
+es para los varios dispositivos TNC; Verde mostrar� los dispositivos de GPS; Amarillo para los
+Servidores de Internet; Naranja para las interfaces de WX. El centro mostrar� que los datos fluyen en rx (flecha que apunta a l
+a izquierda) o los datos fluyen fuera tx (flecha que apunta a la derecha) para eso interface. Una caja verde al fondo mostrar�
+si esa interface es activa.
+Una caja roja mostrar� si la interface es activa pero en una condici�n de error.
+Por otra parte nada mostrar� si la interface no est� activa.
+
+Las �ltimas dos partes mostrar�n el estado del tnc y de la red. Una "=>"
+indicar� si el dato est� siendo enviado, y una "<=" si el dato est� entrando
+desde la interfaz.
+
+
+HELP-INDEX>Moviendo el Mapa y el Men� de Opciones
+
+ Moviendo el Mapa y el Men� de Opciones
+
+Movimiento en el mapa es muy simple, la facilidad y rapidez de movimiento son dependientes de
+la velocidad de su procesador y la cantidad de detalle que usted carga.
+
+Subiendo verticalmente:
+Subiendo verticalmente puede ser logrado por pulsar el bot�n derecho de rat�n sobre el mapa (y sosteniendo el bot�n abajo). Est
+o plantear� un men� de opciones, con opciones para hacer subir verticalmente o fuera a un solo nivel, o para cambiar a uno de l
+os niveles del enfoque prefijado.
+
+Todas las funciones de enfoque desde el men� de opciones har�n acercarse o alejarse al punto
+en el mapa donde usted puls� el bot�n del rat�n correcto. El nivel de enfoque tiene una men� en cascada. Niveles 1-64 son par
+a las �reas muy locales y niveles 256 y superior es para
+�reas grandes. El n�mero m�s bajo del nivel, la �rea m�s local.
+
+Una funci�n de enfoque m�s r�pida es empujar y sostener el bot�n del rat�n izquierdo, arr�strelo
+por el �rea de inter�s y permitida vaya. El mapa har� subir verticalmente aproximadamente a
+el tama�o del cuadrado usted apenas descrito con el rat�n la funci�n de arrastre.
+El programa usa el componente vertical para decidir en el nivel de enfoque, y el
+componentes verticales y horizontales para computar el nuevo centro del mapa. El "movimiento"
+y "medida" que deben desactivarse checkboxes de la bara de herramienta de este rasgo para trabajar.
+
+El mapa tambi�n puede acercarse con el teclado las llaves de PageUp/PageDown. El
+acercar en este caso guarda el mismo centro del mapa.
+
+Paneando/Centrando:
+El mapa puede centrarse a una situaci�n espec�fica por pulsar el bot�n izquierdo del rat�n.
+Pulsando el bot�n los enfoques del bot�n medio aleja con un factor de 2, centrando donde usted
+puls� el bot�n.
+
+Paneando tambi�n es cumplido usando el men� de opciones, o usando la flecha
+botones en la tope de la pantalla. La posici�n del mapa cambiar� una porci�n de
+pantalla. Bastantes datos de pantalla anterior deben estar disponibles reorientarlo
+.
+
+El mapa tambi�n puede ser paneado con las llaves de flecha del teclado.
+
+M�s Sobre el Men� de Opciones:
+La selecci�n de "Estaci�n Info" en el men� de opciones buscar� la estaci�n
+cerca a donde usted puls� el bot�n derecho del rat�n. Si m�s de una estaci�n est�
+cerca de esa posici�n un "escogedor de Estaci�n" de lista aparecer�, entonces usted puede
+escoger los datos de qu� estaci�n que usted quiere ver. Si s�lo una estaci�n es vista entonces el indicador del rat�n es cerrad
+o y los datos de esa estaci�n se desplegar�n inmediatamente. Note
+que expiradas estaciones todav�a tienen sus datos guardados en el banco de datos de Xastir, y
+si uno sabe la situaci�n anterior de una estaci�n, uno todav�a puede ver su info de esta
+manera. Tambi�n es posible desplegar estaciones viejas encendiendo el "el Despliegue
+de Datos Expirados" opci�n en el men� de las estaciones. CORRIGEME: Si no es completamente verdad. Esto s�lo despliega algunos
+ de los datos que desaparecen como estaciones fantasma,
+Velocidad/altitud, etc.,
+
+Para informaci�n de Objeto y Art�culo, por favor vea el tema de ayuda "Objetos y Art�culos"
+
+HELP-INDEX>Objetos y Art�culos
+
+ Objetos y Art�culos
+
+La opci�n de crear Objeto/Art�culo en el bot�n derecho pulsado el men� traear� un di�logo
+con la posici�n de basado objeto en donde usted puls� el bot�n del rat�n.
+Usted puede rellenar los detalles, y agregar un objeto/art�culo desde este men�.
+
+La opci�n de modificar Objeto/Art�culo le traer� un di�logo de modificaci�n de objeto.
+Es similar al di�logo de creaci�n de objeto, excepto por la actual informaci�n de objeto que
+ya est�n publicada, y el nombre del objeto y unas de las pocas otras opciones que no pueden ser cambiada.
+
+Los objetos son retransmitido dentro de la proporci�n de posici�n de la estaci�n reportada, configurada en Archivo|Configurar|P
+redefinidos, y cesar� la retransmisi�n despu�s doblar el
+tiempo de despliegue de la estaci�n, tambi�n configurada all�. "muerta" los objetos tambi�n son
+retransmitido de esta manera, hasta que ellos expiren desde la cola.
+
+Generalmente se usan los objetos para movimiento o cosas inconstantes como tormentas,
+mientras que los art�culos generalmente son usando para las cosas m�s inanimadas, como agua,
+estaciones. Cualquiera puede moverse con el rat�n si el "Movimiento" el checkbox en la
+barra de botones se habilita. Note que los art�culos no pueden ser descifrados por uno cuantos programas APRS(tm) .
+
+Las �rea de objetos son �tiles para una variedad de funcionamientos en lo que usted quiere dibujar
+o resaltar una �rea de inter�s en el mapa. Ellos tambi�n pueden ser personalizados para dibujar
+rastros/caminos/fronteras, sitios de vijilancia para mal el tiempo, las pistas de aterrizaje, per�metros, de una �rea de b�sque
+da o de un evento de servicio p�blico, �reas de da�o, �reas para quedarse fuera de, edificios que no est�n en el mapa, la tabla
+ checker/chess para juego por dinero en APRS(tm).: -) Note que las �rea de objetos no son llevada a cabo en todas las versiones
+ de programas APRS(tm), y algunos de los detalles de c�mo ellos se despliegan tambi�n pueden
+ser diferente en otros programas.
+
+Nombre
+�ste es el nombre del objeto o art�culo. Puede depender de hasta 9 car�cteres. Cuando
+modifica un objeto, este no puede ser cambiado. Para renombrar un objeto usted debe
+anular el original y entonces crear un nuevo objeto. Note que si usted selecciona
+Signpost/Area Object/DF Objeto que este campo y quiz�s otros ser�n aclarado.
+Entre en el nombre DESPU�S que usted ha seleccionado el tipo de objeto que volver�.
+
+Poste indicador
+Este hace al objeto un poste indicador de objeto. Estas se�ales pueden ser 3 car�cteres,
+visible en un poste indicador a la locaci�n cuando el enfoque es acercado. (CORRIGEME: Nosotros no hacemos el despliegue de los
+ postes indicadores todav�a de esta manera).
+
+Objeto del �rea
+Esto hace un objeto del �rea al objeto, y habilita los mandos de objeto de �rea
+descrito debajo.
+
+Objeto DF
+�ste es un informe de contrada-direcci�n. Habilit�ndolo le permite escoger reporte Omni o
+direccional, y le permite poner en el especifico para cada uno. Vea:
+ http://web.usna.navy.mil/~bruninga/dfing.html
+y la documentaci�n de APRSdos para los detalles en estas t�cnicas �tiles.
+(CORRIGEME: la secci�n Separada en las t�cnicas de DFing?)
+
+S�mbolo Estaci�n
+Usted puede seleccionar un s�mbolo para el objeto. Pulse seleccionar para escoger gr�ficamente,
+o ver la secci�n tabla de ayuda de s�mbolo para las descripciones de cada s�mbolo. Note
+que no todos los s�mbolos se han llevado a cabo todav�a en el escogedor de gr�ficos,
+y algunos no est�n por el APRS(tm) especificaci�n. Tambi�n note esa �rea de objeto, poste indicador de objetos, y los objetos d
+e DF tienen s�mbolos fijos especiales y por consiguiente no pueden ser seleccionado aqu�.
+
+Localizaci�n
+La localizaci�n del objeto se especifica aqu�. Si usted seleccionara "Crear
+Objeto/Art�culo" pulsando el bot�n derecho del men�, la locaci�n que usted pulsado se llenar�
+. Si usted moviera un objeto con el rat�n, la nueva posici�n estar� en esos campos. Usted tambi�n puede teclear en una posici�
+n, por ejemplo usted puede estar poniendo un
+objeto de un informe de voz sobre el aire.
+
+Opciones gen�ricas
+Usted puede especificar la velocidad, direcci�n, y altitud de objetos aqu�. Algunos tipos de objetos
+no pueden tener una velocidad o direcci�n en tales casos los campos son desgrisado
+.
+
+Objeto del poste indicador
+Si el objeto es un objeto de poste indicador, usted puede especificar de 1 a 3 car�cter
+de mensaje que aparece en la se�al aqu�. Note que Xastir no despliega los objetos
+de poste indicador a propiamente todav�a.
+
+Objeto �rea
+Se usan Objetos de �rea para resaltar partes espec�ficas del mapas, o para dibujar excepcionalmente detalle dentro de los mapas
+.
+ Color luminoso.
+ Use la versi�n m�s luminosa de los colores permitidos.
+ Colorido
+ El �rea debe llenarse, no s�lo perfilado. Esto puede ser �til para
+ excluir una �rea de una b�squeda u otro evento.
+ Tipo de objeto
+ Escoge desde las formas geom�tricas permitidas.
+ Color del objeto
+ Escoge el color en el que el objeto se desplegar�. Esto tambi�n es afectado
+ por el "Color Luminoso" la opci�n anteriormente.
+ El objeto Compensado
+ En cent�sima de un grado latitud. Un detalle infortunado de la especificaci�n,
+ y duro de calcular f�cilmente. Basta decir que usted puede cambiar
+ el tama�o del objeto una vez usted lo ponga.
+ El Desplazamiento izquierdo del objeto excepto /
+ En cent�sima de un grado latitud. Vea anteriormente.
+ Objeto corredor
+ �ste es el ancho de una l�nea de �rea de objeto. Util para las pistas de aterrizaje, tiempo
+ watchboxes, describiendo una �rea de inter�s o una �rea de exclusi�n, etc.,
+(CORRIGEME: Escriba esta parte! (el �rea objeto) La especificaci�n es incierta a m�, el c�digo,
+es incierto a m�, pero en el futuro yo lo deducir� todos!)
+
+�Siempre anule sus objetos y art�culos cuando usted halla terminado con ellos!
+No les permita simplemente expirar desde su escondite, como ellos pueden colgarse
+alrededor de las pantallas de otras personas por un periodo extendido.
+
+
+HELP-INDEX>Men� Visualizador
+
+ Opciones del Men� de Visualizar
+
+El men� de Visualizar presenta varias maneras de ver datos en Xastir.
+
+Boletines
+�ste es el APRS(tm) tabla de anuncios, donde importantes anuncios son puesto.
+Si usted se conecta con la interf�z del internet, es una buena idea para poner el
+rango del campo a unas cientas millas, para ignorar postes de otras porciones del
+mundo. "0" es el rango del campo, significa el mundo entero. Pulse el bot�n "Cambio de rango"
+pulse para hacer cambios a este campo eficaz. Xastir actualmente no soporta el env�o de boletines.
+
+Datos de paquete entrantes
+Esto despliega los datos entrantes en su TNC o interf�z del internet. Los botones radio
+debajo selecciona si usted quiere ver s�lo datos de TNC, s�lo datos del internet, o
+ambos.
+
+Estaciones m�viles
+�sta es una lista de estaciones que se est�n moviendo. Las estaciones califican para esta lista si
+ellas se han movido (m�s de una posici�n recibida para ellas), el s�mbolo de
+la estaci�n no es considerada. Informaci�n mostrada incluyendo curso, velocidad, altitud,
+posici�n, n�mero de paquetes recibido, n�mero de sat�lites de GPS visibles, curso,
+de su estaci�n, y distancia de su estaci�n.
+
+Todas las Estaciones
+Esta opci�n despliega una tabla de todas las estaciones ordenada alfab�ticamente. Incluyendo
+el n�mero de paquetes o�do, el tiempo que la estaci�n fue o�da �ltima vez, el camino
+m�s reciente paquete tomado, el PHG, y el comentario de la estaci�n.
+
+Estaciones locales
+Esta opci�n despliega s�lo estaciones que se oyen v�a su TNC. Incluye
+el n�mero de paquetes o�do, el tiempo que la estaci�n fue o�da �ltima vez, el camino
+m�s reciente paquete tomado, el PHG, y el comentario de la estaci�n.
+
+Ultimas Estaciones
+Esta opci�n despliega una tabla de todas las estaciones ordenada recientemente o�da
+a menor recientemente escuchada. Incluye el n�mero de paquetes o�do, el tiempo,
+la estaci�n fue o�da �ltima vez, el camino que el m�s reciente paquete tom�, el PHG,
+y el comentario de la estaci�n.
+
+Estaci�n WX
+Esta opci�n despliega una tabla de todo el APRS(tm) estaciones del tiempo y sus datos.
+El datos incluyen curso del viento, velocidad del viento, velocidad de r�faga dle viento, temperatura, humedad, presi�n barom�t
+rica, lluvia en la �ltima hora, lluvia medianoche subsecuentemente, y lluvia en las �ltimas 24 horas.
+
+Estaci�n Meteorol�gica Propia
+Despliega sus datos del tiempo si usted tiene una estaci�n del tiempo y la ha configurado
+Xastir para accederla.
+
+Alerta del Tiempo
+Los despliegues alarmas recibidas, incluso las banderas de alertas, la alerta fuente/tipo,
+destino alerta, expiraci�n, mensaje, y efectuada situaci�n. Esto datos
+se usa por el resalto de condado, y no es particularmente humanamente-le�ble.
+Usted generalmente puede deducir el estado y condado para la mayor�a de las alarmas.
+
+Tr�fico de mensaje
+Muestras todo el tr�fico de mensaje mientras la ventana est� abierta. Incluye la fuente,
+destino, interf�z, y mensaje. La opci�n de rango puede limitar este despliegue
+a las estaciones cercanas, mucho como el mando del rango en boletines. Un rango de 0
+causas todos los mensajes a ser desplegados.
+
+SobreHora
+Muestras la cantidad de tiempo pasado subsecuentemente que Xastir fue iniciado.
+
+HELP-INDEX>Mapas Opciones y Seleccionar Mapas
+
+ Mapas Opciones y Seleccionar Mapas
+
+Mapas Opciones:
+
+Auto mapas (on/off)
+ Cuando cualquier mapa es encontrado, en el directorio de mapas
+(o cualquier directorio bajo �l) ser� desplegado,
+si el cae dentro de la regi�n de despliegue actual.
+
+Usted puedes agregar cualquier n�mero de niveles de directorios bajo
+el directorio del mapa principal para sus mapas.
+El Auto mapa pasar� por todos ellos y hallar� que mapa (o parte) debe desplegarse.
+
+Todos los Mapas se unir�n en el �rea de visi�n.
+Si usted tienes una cantidad grandes de mapas, mapas muy detallados
+o una computadora muy lenta, esto puede ser mostrado bastante lento.
+
+Cuando esta opci�n est� apagada, se desplegar�n mapas seleccionados
+con el selector de Mapas.
+
+Rejillas sobre Mapa (on/off)
+ Cuando est� en 'ON', esta opci�n desplegar� una l�nea de reja cada 10 grados.
+
+ Niveles de mapas (on/off)
+ Cuando est� en 'ON', esta opci�n intentar� filtrar fuera los datos cuando el
+nivel de enfoque muesta grandes �reas. Esto no trabajar� con todos los mapas
+pero trabajar� con los mapas generados de 'Tiger line maps' en el sitio de
+aprs.rutgers.edu.
+
+Areas rellena en colores (on/off)
+Esta opcion controla el relleno del vector del mapa. En ciertos casos, usted
+podria querer enliminar el relleno para ver el mapa bajo el tope de mapas.
+Los mapas son cargados en orden alfabertico por tipo, asi que renombrando
+mapas es un segundo pero la via es menos elegante archivar la vista deseada.
+
+Seleccionar Mapas
+Esta se presentar� con una lista de todos los archivos en su directorio de
+mapas. Cualquier mapa que usted desear�as incluirlo en los datos desplegados,
+simplemente tiene que pulsar el bot�n del rat�n sobre el nombre.
+Esto resaltar� el nombre del mapa, Usted puedes seleccionar cualquier n�mero de mapas.
+Pulsando en el bot�n "Aceptar" se desplegar�n los mapas seleccionados.
+Oprimiendo el Bot�n de "Cancelar" abandonar�a cualquier cambio.
+
+Tambien hay botones de atajo para seleccionar todos de un cierto tipo de mapa,
+o de-seleccionar todos los mapas de una vez.
+
+Una nota sobre mapas: Muchos de los actuales mapas de vectores disponibles para
+los EE.UU. fueron creado en NAD 1927 datum, mientras Xastir y otros programas de APRS
+usan el WGS 1984 datum.
+Si es enfocado hacia una �rea peque�a en el mapa la variaci�n del datum
+puede ser muy notable. Los mapas topo USGS tienen sus datum corregido por Xastir
+como ellos son desplegados,
+asi que la posiciones generalmente ser�n m�s exacta con los mapas topo.
+
+HELP-INDEX>Archivos Mapas, Dos, Windows, Pixmaps, geoTIFF y Condados WX
+
+ Archivos mapas, Dos, Windows, Pixmaps, geoTIFF y Condados WX
+
+Tipos de mapas
+Xastir trabajar� con varios tipos archivos de mapas.
+Todo el Dos, Windows/MacAPRS[TM] son archivos de Mapas que son soportados.
+
+Un nuevo formato de Pixmap se ha agregado en versi�n 0.3.2.
+Xastir tambi�n soportar� mapas para las Alertas de condados WX.
+El �ltimo formato de mapa soportado es geoTIFF, tales mapas como son
+USGS DRG topo mapas.
+
+Locaciones de Mapas
+Cualquier Dos, Windows/Mac o archivo Pixmap y geoTIFF, deben guardarse en el
+Directorio de /usr/local/share/xastir/maps en su computadora.
+Usted puedes crear cualquier n�meros de directorios bajo este directorio
+para ayudar a separar sus datos.
+Por ejemplo usted puedes querer crear un directorio de USA.
+y despu�s uno por cada estado bajo el Directorio de USA.
+O tiene un directorio separado para DOS o Pixmaps y geoTIFF.
+
+
+ /usr/local/share/xastir/maps/
+ /usa/
+ /usa/CO/
+ /usa/NJ/
+ /dos/CO/
+ /dos/NJ/
+ /pixmaps/CO/
+ /pixmaps/NJ/
+
+
+Pixmaps realmente son una combinaci�n de dos archivos, un archivo de dato con un,
+pixmap (.xpm), gr�fico y un archivo de locaci�n (.geo).
+El archivo .xpm es una estructura de gr�fico normal,
+con una imagen de cualquier tipo.
+
+Usted puedes usar XView para convertir gif, jpg, y tif im�genes en este formato.
+El archivo geo es un archivo de dato que atar� la imagen a una locaci�n en el mundo.
+Aqu� est� un ejemplo de mi archivo world1.geo
+
+
+ARCHIVO world1.xpm
+# x y lon lat
+TIEPOINT 0 0 -180 90
+TIEPOINT 640 320 180 -90
+
+Este es un archivo simple, con 4 componentes b�sicos.
+La primera l�nea especifica este archivo data .geo es usado,
+este archivo debe estar en el mismo directorio como el archivo de .geo.
+
+La segunda l�nea muestra un comentario;
+cualquier l�nea con el car�cter como un "#" ser� ignorado.
+
+Las �ltimas dos l�neas son para conectar un pixel en la posici�n x,y
+en la imagen a una posici�n lat y long en la mundo. Dos puntos unidos
+son necesitado y debe estar cerca de la esquina izquierda superior
+y la esquina derecha m�s abajo de la imagen.
+
+Usar archivo pixmap con xastir, use el selector de mapa y seleccione el archivo .geo
+para incluir la imagen en la vista del mapa actual.
+
+Por razones de velocidad, otras l�neas de opciones pueden ser anexada
+en el archivo .geo.
+Aqu� algunos ejemplos del formato modificado:
+
+ARCHIVO Agnes_Mountain.xpm.gz
+#
+# X Y Lon Lat
+# ---- ---- ------------- -----------
+TIEPOINT 0 0 -121.00120491 48.37481943
+TIEPOINT 1337 1999 -120.87619806 48.24982052
+#
+#EDGES BOTTOM TOP LEFT RIGHT
+EDGES 48.24982052 48.37481943 -121.00120491 -120.87619806
+
+La l�nea EDGES especifica el min/max bordes del mapa. El mencionado
+mapa arriba es inclinado ligeramente, el cual es el porqu� los n�meros
+no corresponden a la esquina 'tiepoints' exactamente. Xastir usar� esa
+informaci�n saltar el mapa si no encaja en la vista actual.
+
+Mapas geoTIFF son una combinaci�n de dos archivos tambi�n:
+un archivo .tif y un .fgd. El archivo .tif es el actual data mapa.
+El archivo .fgd necesita solamente tener cuatro l�neas como estas:
+
+1.5.1.1 WEST BOUNDING COORDINATE: -122.000000
+1.5.1.2 EAST BOUNDING COORDINATE: -120.000000
+1.5.1.3 NORTH BOUNDING COORDINATE: 48.000000
+1.5.1.4 SOUTH BOUNDING COORDINATE: 47.000000
+
+Xastir usa esas cuatro l�neas en su calculaciones para determinar los puntos
+de la esquina del mapa, y si o no el mapa vuelve al actual punto de vista
+(asi que el puede decidir si saltarlo). Si su data mapa es un mapa topo USGS,
+el archivo .fgd podr�a ser le�damente disponible a usted.
+Una forma anexada en Xastir es la abilidad hacer traslaciones datum desde
+NAD 1927 a WGS 84 datum, el cual hace el mapa topo USGS mucho m�s posicionalmente
+exacto sobre la pantalla en Xastir.
+
+Mapas Condado WX
+Todos los mapas Condado WX deben guardarse en el directorio de
+/usr/local/share/xastir/Counties. Hay formatos diferentes para los mapas,
+pero de cualquier modo este directorio tendr� directorios (usted podr�as
+necesitar crearlos) bajo este para cada estado (2 abreviaciones de letras).
+
+ /usr/local/share/xastir/Counties
+ /CO/
+ /CO/COPARK.map
+ /CO/CODOUGLA.map
+ /CO/COJEFFER.map
+ /CO/COZ001.map
+ /CO/COZ002.map
+ /CO/COZ003.map
+ /NJ/
+ /NJ/NJOCEAN.map
+ /NJ/NJBERGEN.map
+ /NJ/NJMONMOU.map
+ /NJ/NJZ001.map
+ /NJ/NJZ002.map
+ /NJ/NJZ003.map
+
+
+Aqui estan dos lugares en el Internet donde usted puedes obtener esos mapas:
+
+ftp://aprs.rutgers.edu/pub/hamradio/APRS/NWSCounties/
+http://home.att.net/~kg5qd1/Maps.html
+
+Como los mensajes NWS son recibidos, diferentes areas obtendr�n un tintado
+hacia las �reas designadas.
+Ellas son coloreadas para especificar diferentes tipos de alertas.
+
+Los colores originales fueron:
+
+Cian para el asesor, amarillo para alerta del tiempo,
+rojo para advertencia, naranja para alerta cancelada, azul real para pruebas,
+y verde para niveles de indeterminadas alarmas.
+
+Con la �ltima versi�n de Xastir los colores pueden ser diferentes
+debido a un cambio mayor:
+Las �reas que ahora son tintadas en lugar de relleno de color,
+y la dependencia en el tintado debajo los colores.
+
+Este cambio fue hecho asi que los mapas estando debajo de esto pueden
+mantenerse visible debajo en las �reas de alertas del tiempo.
+Las alertas del tiempo podr�an ser fijada en on/off v�a el men� del mapa tambi�n.
+
+
+HELP-INDEX>Configurar Interfaces
+
+ Configurar Interfaces
+
+Pulse el bot�n en Configurar luego en Interfaces
+
+Un di�logo de "Interfaces Instalados" debe aparecer.
+Este di�logo le permitir�s a usted Agregar, Anular, y modificar las Propiedades
+en varios dispositivos que usted puedes querer usar con Xastir.
+
+Las opciones actuales son:
+TNC v�a el Puerto Serial
+TNC v�a un Puerto Serial con (GPS m�s cable HSP)
+GPS v�a un Puerto Serial
+Estaci�n Meteorol�gica v�a Puerto Serial
+Conexi�n a un Servidor en Internet
+TNC v�a la Uilidades del AX.25
+GPS Enlazado v�a el Servidor gpsd
+Estaci�n Meteorol�gica Enlazada a una RED
+TNC v�a un Puerto Serial con (GPS m�s AUX puerto)
+
+Para agregar un dispositivo, pulse el bot�n de agregar.
+Un di�logo "Elegir Tipo de Interfaz" aparecer�.
+Pulse el bot�n en el tipo de dispositivo que le gustar�a agregar.
+Luego pulse el bot�n de Agregar en el di�logo "Elegir Tipo de Interfaz".
+Las propiedades para ese dispositivo aparecer�.
+
+Rellene la informaci�n pedida y pulse el bot�n en Aceptar, anular el dispositivo,
+pulse el bot�n en el dispositivo usted deseas anular y entonces pulse el bot�n Anular.
+Para modificar las propiedades de un dispositivo,
+pulse el bot�n en el dispositivo usted deseas modificar,
+luego pulse sobre el bot�n de propiedades.
+
+Las propiedades para ese dispositivo aparecer�.
+Cambie la informaci�n que usted quieres y pulsar el bot�n en Aceptar.
+
+HELP-INDEX>Configurando el Serial sobre un TNC
+
+ Configurando el Serial sobre un TNC
+
+SERIAL TNC CONFIGURACION
+
+Pulse el bot�n "Configurar" luego en "Interfaces" despu�s en "Agregar"
+despu�s en "Serial TNC" luego "Agregar" y por �ltimo en "Puerto TNC"
+
+Si usted tienes un TNC y planea usarlo con XASTIR seleccione "Puerto TNC".
+El valor por defecto no, es seleccionado.
+
+Ahora entre en el puerto que el TNC est�, es decir /dev/ttyS0 para com1
+
+Seleccione los valores del puerto que se acoplan a su TNCs velocidad del puerto.
+
+Entre en tres rutas de UNPROTO.
+
+Xastir asumir� los XX VIA la parte de la ruta de UNPROTO. Hay tres Rutas
+permitidas para que su se�al sea escuchada si las condiciones son mala.
+Si cualquiera de �stos es llenado en XASTIR ciclar� a trav�s de uno de ellos
+a cada intervalo de transmision.
+
+Si usted est�s local, s�lo un WIDE2-2 puede ser una buena opci�n.
+Si usted est�s usando baja potencia y/o est�s distante de un digi entonces
+WIDE1-1,WIDE2-2 puede trabajar mejor.
+
+O si usted conoces el indicativo de su digi m�s cercano que usted
+puedes usar XXXCALL,WIDE2-2.
+La mayor�a de ustedes necesitar�n s�lo una ruta.
+
+Si usted est�s en una �rea remota y su se�al es dif�cil de conseguirla
+usted puedes necesitar m�s.
+
+Verifique con un grupo local y preg�ntele que ruta
+puede ser mejor para su �rea. Algunas areas
+usan el flujo de protocolos m�s eficientes, en tales caso usted podr�a usar
+WIDE3-3 o WIDE1-1,WIDE3-3.
+
+Los archivos de Inicio y Salida del TNC. Estos campos especifican a nombre
+de archivo qie es localizado en el directorio /usr/local/share/xastir/config.
+Cada archivo es un archivo de texto estandar conteniendo algunos comandos que
+usted le gustaria enviarle a su TNC a la vez que el dispositivo es activado
+(Archivo de Inicio - Startup file) o de deshabilitar (shut down).
+
+Pulsando el bot�n "Aceptar" guardar�s sus cambios.
+Pulsando el bot�n en "Cancelar" guardar� la configuracion actual.
+
+HELP-INDEX>Opciones del TNC
+
+ Opciones del TNC
+
+Permitir Transmisi�n (on/off)
+ Esto controla la transmisi�n de datos a trav�s del TNC. Usted puedes querer
+Simplemente escuchar en RF o si usted no es un HAM y no debes transmitir. Con
+Esta opci�n (el cual est� apagado por defecto) usted puedes controlar
+transmisi�n de cualquier datos v�a RF.
+
+Bit�cora (log) del TNC (on/off)
+ Si est� en 'ON', un archivo de log (Bit�cora) se crear� en el directorio logs.
+El archivo se llamar� tnc.log y se a�adir� con toda la informaci�n o�da v�a RF.
+
+Transmitir Ahora!
+ Este transmitir� su position/info de su estacion cuando usted pulses el bot�n
+en esta selecci�n. No transmitir� si la opci�n "Serial TNC" no est� seleccionada
+(en la secci�n Configurar/Interfaces/Agregar/Serial TNC/Adregar/Puerto TNC)
+o si la opci�n arriba mencionada permitir transmisi�n est� fijada en off.
+
+HELP-INDEX>Configurar TNC via Serial c/GPS en HSP cable o AUX puerto
+
+ Configurar TNC via Serial c/GPS en HSP cable o AUX puerto
+
+Esos tipos de interfaces h�bridos implementan las opciones de ambos serial TNCs
+y GPSs. Por favor consulte la configuraci�n de ayuda para ambos serial TNCs y
+serial GPSs para m�s detalles de informaci�n sobre la configuraci�n
+de esos dispositivos.
+
+HELP-INDEX>Configurando el AX.25 TNC
+
+ Configurando el AX.25 TNC
+
+AX.25 TNC CONFIGURACION
+
+Esta secci�n cubre agregando o modificando AX.25 TNC dispositivos.
+AX.25 dispositivos pueden sea cualquier dispositivo que use controladores AX.25
+en Linux.
+
+�ste es un controlador de nivel del n�cleo (kernel),
+y el dispositivo como un Baycom o una tarjeta de sonido como m�dem
+puede usarse como un TNC.
+Estos dispositivos deben ser configurado y correrlo
+ antes de que Xastir pueda usarlos.
+
+Seleccionando Activar en Inicio, le dir� a Xastir que busque este dispositivo
+y fije las comunicaciones con �l cuando el programa de su primer inicio.
+
+Seleccionando Permite Transmitir, le dir� a Xastir que cualquier
+salida de datos de RF puede ser enviado a este dispositivo para la transmisi�n.
+
+Escoja la operaci�n correcta de IGate para este dispositivo.
+Usted puedes tener varios dispositivos TNC, y esta opci�n puede ser diferente
+por cada dispositivo. Si usted no est�s ejecutando un IGate
+usted puedes dejar �sta opci�n predefinida de "Desactivar todo el tr�fico".
+
+Entre el nombre del Dispositivo AX.25
+que usted especific� en el archivo del axports para este dispositivo.
+
+Entre en tres rutas de UNPROTO. Xastir asumir� el XX VIA parte de la ruta
+del UNPROTO. Hay tres rutas permitidas para que su se�al sea escuchada
+si las condiciones son mala.
+
+Si cualquiera de �sas son llenada en XASTIR ciclar� a trav�s de uno de ellos
+en cada momento de la transmisi�n. Si usted es local, s�lo un
+WIDE2-2 puede ser una buena opci�n.
+
+Si usted est�s usando baja potencia y/o est�s distante de un digi
+entonces WIDE1-1,WIDE2-2 pueden trabajar mejor.
+O si usted sabes el indicativo de su digi m�s cercano
+a usted puedes usar XXXCALL,WIDE2-2. La mayor�a de ustedes necesitar�n s�lo una ruta.
+
+Si usted est�s en una �rea remota y su se�al es dif�cil de conseguir usted puedes
+necesitar m�s. Verifique con un grupo local y preg�ntele qu�
+ruta puede ser mejor para su �rea. Algunas areas
+usan el flujo de protocolos m�s eficientes, en tales caso usted podr�a usar
+WIDE3-3 o WIDE1-1,WIDE3-3.
+
+
+NOTA: Para usar dispositivos AX.25 con Xastir usted necesitar�s ejecutar el programa como "ra�z" ("root").
+
+Si usted quieres ejecutar Xastir como otro usuario usted necesitar�s
+fijar el suid en ON en el archivo de programa de xastir.
+El orden siguiente como ra�z debe fijar esto para usted. chmod a+s /usr/local/bin/xastir.
+
+como con cualquier programa que este corriendo de esta forma, por favor note que
+esto puede ser considerado como una seguridad de riesgo, como el programa no ha sido
+probado para explotar. Uselo en este modo en un multi-usuarios en su propio riesgo!
+
+HELP-INDEX>C�mo uso yo mi GPS con Xastir?
+
+ Usando UN GPS con Xastir
+
+Para usar una unidad de GPS con Xastir usted tienes tres opciones,
+un GPS Conectado a una red o a un serial GPS,
+o a un serial GPS con un TNC y cable HSP.
+
+ GPS conectado a una red:
+
+La ventaja de usar un GPS conectado a una red
+es que usted puedes compartir el GPS con otros programas.
+Xastir usa un programa llamado gpsd para hacer una connexi�n a una red.
+
+Este programa entrega datos de GPS normales en un s�calo de conexi�n de redes.
+Algunas versiones tambi�n permiten correcci�n de GPS v�a un servidor de Internet.
+
+Una vez que usted tengas bajado e Instalado el gpsd en su m�quina
+(u otra m�quina), usted puedes fijar el Xastir
+para conectar a �l creando una interfaz.
+
+Pulse el bot�n en "Configurar" y despu�s en "Interfaces".
+Cuando el di�logo de Interfaces aparezca Pulse el bot�n de "Agregar".
+Un nuevo di�logo aparecer� con los tipos de Interfaces,
+Elegir en "Enlazado GPS (via el gpsd)", y luego pulse el bot�n en Agregar.
+
+Hay 4 opciones a elegir.
+Primero entre el nombre del servidor del programa gpsd que est� ejecutando.
+Si est� en el mismo computador que Xastir entonces entre localhost.
+
+Luego entre en el puerto que usted puso el programa gpsd para escuchar.
+Si usted seleccionas "Activar en Inicio", Xastir tratar� de conectar
+al programa gpsd tan pronto se inicia y tan pronto usted hagas click
+en el bot�n "Aceptar". La �ltima opci�n, si seleccionado,
+intentar� hacer la reconexi�n al gpsd si un fallo fu� encontrado.
+
+Serial GPS: Un serial GPS es cualquier unidad de GPS normal
+que conecte al puerto serial y transmita datos en el NMEA normal.
+Permitir a Xastir a usar este tipo de GPS pulse el bot�n
+de "Configurar" luego en "Interfaces". Cuando el di�logo
+de Interfaces aparezca pulse el bot�n de "Agregar".
+
+Un di�logo con los tipos de Interfaces aparecer�,
+Pulse sobre el "Serial GPS" y despu�s en el bot�n Agregar.
+
+ Unas pocas opciones para fijar.
+
+Primero entre el puerto serial en donde el dispositivo
+est� conectado (como "/dev/ttyS1 (COM2)").
+Pr�ximo si usted seleccionas "Activar en Inicio",
+Xastir intentar� inicializar el "serial GPS" cuando �l se
+inicie y cuando usted pulses el bot�n "Aceptar".
+Las pr�ximas opciones pondr�n la velocidad del puerto serial y modo.
+
+Para la mayor�a de las unidades de GPS los valores predefinidos est�n bien.
+Pero Chequee usted el manual del GPS s�lo en caso de dudas.
+
+HSP TNC/GPS:
+Mire en "C�mo uso yo mi TNC con Xastir?"
+
+
+HELP-INDEX>Configurando el Puerto/GPS
+
+ Configurando el Puerto/GPS
+
+Pulse el bot�n en "Configurar" luego en "Interfaces" luego en "Agregar"
+elija "Serial GPS" luego "Agregar" despu�s ajuste los par�metros del Puerto/GPS.
+
+Para usar una posici�n "Serial GPS" en el puerto serial,
+pulse el bot�n en Posici�n Serial GPS.
+Este puerto puede especificarse en la Posici�n "S�lo el puerto de GPS".
+Usted puedes usar un dispositivo serial como /dev/ttyS1 (COM2).
+
+Si usted tienes un cable de HSP que le permitas compartir el Serial TNC con una
+unidad GPS usted puedes seleccionar "Serial TNC c/GPS m�s (Cable HSP).
+�ste es un cable especial y el m�o no trabaja en todas las combinaciones
+de computadores/GPS/TNC.
+
+Ahora usted puedes escoger un GPS muestreo y TNC relaci�n, Recuerde usarlo con
+precauci�n aqui, que sean amigables por sus estaciones cercanas.
+
+�Activar el uso de los datos de GPS seleccione el "Uso Posici�n GPS?" opci�n.
+Con esta selecci�n hecha la unidad de GPS pondr� al d�a su posici�n.
+Si esto no se selecciona la posici�n actual vendr� desde la locaci�n
+en configuraci�n informaci�n de la Estaci�n.
+
+Cuando active los datos de GPS tambi�n pondr�s al d�a
+la posici�n en configuraci�n de informaci�n de la Estaci�n.
+
+Cuando use el GPS sus paquetes cambian, usted obtendr�s una estaci�n m�vil con
+curso y velocidad a�n cuando la suya no est� moviendose (yo puedo cambiar esto
+despu�s a una opci�n).
+
+El tiempo del GPS le permitir� seleccionar proporciones de la relaci�n
+de muestra para el GPS y sobre pasar el tiempo del paquete normal
+por transmitir su estaci�n.
+
+Si usted est�s estacionado entonces use 10 minutos.
+Si usted est�s haciendo alg�n especial/rastreo etc..
+use la selecci�n que encajar�n mejor los datos que usted necesitas.
+Por favor no haga sobre transmisi�n, si usted no lo necesitas hacer.
+
+
+Pulsando el bot�n "Aceptar" guardar�s sus cambios.
+Pulsando el bot�n en "Cancelar" guardar�s las configuraciones actuales.
+
+HELP-INDEX>C�mo uso yo mi TNC con Xastir?
+
+ Usando UN TNC con Xastir
+
+Para usar un TNC con Xastir usted tienes tres opciones,
+un "serial TNC" o un "Serial TNC c/GPS m�s (cable HSP)"
+o un TNC Conectado a una red "AX.25 TNC".
+
+AX.25 o un TNC en una red:
+Este tipo de tnc le permitir� compartir el TNC con otros programas.
+Al usarlo usted debes tener la librer�a AX.25 , y el
+HamRadio soporte instalado en el n�cleo (kernel) de su Linux OS.
+
+Ellos son un poco m�s dif�ciles de configurar para usarlo
+pero hay muy buenas opciones y ventajas en su uso.
+
+Usando el soporte del "AX.25 TNC", usted tienes varios
+dispositivos que usted puedes usar con Xastir.
+Algunos de ellos son serial TNC que usan AX.25,
+tarjetas de sonidos como TNC's, Baycom, etc.
+
+SERIAL TNC: SERIAL TNC con (GPS m�s cable HSP):
+
+HELP-INDEX>Configurando la conexi�n de Internet
+
+ Configurando la conexi�n de Internet
+
+La conexion a los Servicios de Internet le permite a usted enviar
+y recibir datos desde y hacia todo el mundo.
+
+Para configurar el Internet usted necesitar�s conocer un host y un n�mero de
+puerto. El host predefinido es www.aprs.net y el puerto es 10151. Usted puedes
+escoger otros pero este debe trabajar. Una Palabra de paso v�lida le permitir�
+a su estaci�n transmitir por el Internet.
+
+Permitir� a su estaci�n salir de una I-Gate y conseguir retransmitir v�a RF.
+Para conseguir un c�digo de paso usted necesitar�s contactar con Frank,
+email fgiannan at earthlink.net, Enviarle su nombre, Indicativo, etc.
+
+Una vez �l verifique su estado como un HAM �l puede enviarle su c�digo.
+Usted puedes mantenerse recibiendo y transmitiendo datos v�a el
+Internet aunque usted no tengas un passcode. Pero sin el c�digo de paso sus
+datos no ser�n directamente retransmitido v�a RF.
+Cualquiera que est� conectado al Internet directamente conseguir� su mensaje.
+
+Host1 y Host2 son servidores opcionales que ser�n contactado si el servidor
+primario est� fuera. Cada servidor ser� intentado dos veces, siguiendo al
+pr�ximo si la conexi�n fracasa.
+
+Si usted quieres que XASTIR reconecte despu�s de una conexi�n perdida
+en el net entonces seleccione la opci�n "Reconecte en fracaso de la RED?"
+en la que por defecto est� en ON.
+
+Las �ltimas opciones son para preparar su estaci�n para ser un IGate. Esto
+permite a su estaci�n con su c�digo de paso simplemente actuar como una puerta
+(gateway), pero en lugar de otra banda sus datos atravesar�n el Internet.
+Esta opci�n no debe ser tomada ligeramente.
+
+Primero usted debes coordinar con otros
+en su �rea para que usted puedas agregar verdadera informaci�n que puede estar
+perdiendo. Usted tambi�n debes avisar a Steve sobre esto. Esta versi�n puede
+enviar informaci�n recibida desde su TNC hacia el Internet y transmitir�
+cualquier mensaje procedente de Internet a trav�s de su estaci�n via RF.
+
+Enviar� s�lo datos v�a RF si usted tienes el opci�n seleccionada de transmisi�n
+de mensajes. S�lo estaciones que usted has o�do (v�a RF) en las �ltimas horas
+tendr�n mensajes enviados a ellos en �sta v�a.
+
+Note tambi�n usted es responsable por los datos transmitidos
+por su estaci�n asi que tenga cuidado con esta
+opci�n (otros pueden enviarle mensajes que usted no quieres transmitir).
+
+Si usted quieres ver que su I-Gate esta haciendo encienda la opci�n Log I-Gate
+de transacciones. esto construir� un archivo de igate.log en su "logs" los
+directorios mostrar�n todos los datos pasados de RF local hacia la red con
+l�nea que tiene "IGATE-RF->NET": y conteniendo todo los datos.
+
+Tambi�n mostrar� todo el tr�fico entrante desde la red con "NET->RF-IGATE:".
+Note aqu� usted no ver�s la completa salida de paquetes, como su estaci�n y ruta son
+asumida. Solamente mostrar� el data como un mensaje de tercera persona.
+
+
+Pulsando el bot�n "Aceptar" guardar�s sus cambios.
+Pulsando el bot�n en "Cancelar" guardar�s los cambios actuales.
+
+
+APRS[tm] es una Marca de f�brica de Bob Bruninga,
+su p�gina est� en "http://web.usna.navy.mil/~bruninga/aprs.html"
+
+
+HELP-INDEX>Opciones de RED
+
+ Opciones de RED
+
+Permitir Transmisi�n (on/off)
+Esto controla la transmisi�n de datos a trav�s del Internet.
+El valor por defecto es apagado.
+Con esto en (off) apagado ning�n dato ser� enviado al Internet.
+
+Bit�cora de Internet (on/off)
+ Si esto est� en 'ON', un archivo log se crear� en el directorio logs. El archivo
+se llamar� net.log y se a�adir� con toda la informaci�n o�da v�a el Internet.
+
+Transmitir Ahora!
+ Esto transmitir� su position/info de la estaci�n cuando usted pulses el
+bot�n en esta selecci�n. No transmitir� si la opci�n est� apagada en Permitir
+transmisi�n.
+
+HELP-INDEX>Configurando una Estaci�n Meteorol�gica sobre un Puerto Serial.
+
+Configurando una Estaci�n Meteorol�gica sobre un Puerto Serial.
+
+Configurar el puerto serial para su estaci�n Meteorol�gica. A los valores
+comunes de /dev/ttyS0 (COM1) o /dev/ttyS1 (COM2) pueden ser usado.
+
+Seleccionado "Activar en Inicio" le dir�s a Xastir buscar este dispositivo y
+fijar comunicanciones con el cuando el programa se inicie primero.
+
+Ahora fije el bps bajo el puerto de configuraci�n, y los par�metros bajo el
+puerto estilo. El seteo del puerto estilo 8N1, es usado para 8 bitios de datos,
+No paridad y 1 bitio de parada (stop bit). 7E1 es usado para 7 bitios de datos,
+even paridad y 1 bitio de parada. 7O1 es usado para 7 bitios de datos, odd paridad
+y 1 bitio de parada. Esos par�metros deben de machar con su estaci�n Meteorol�gica.
+El tipo de opci�n de data le perimitir� sobrepasar que tipo de serial data el progrma
+ver�. La forma de auto-detecci�n primero buscar� datos del tiempo en un modo binario
+como lo usa el Radio Shack WX-200. Si no dato binario es encontrado,
+Xastir buscar� un tipo ASCII de estaci�n Meteorol�gica (como la Peet Bros.)
+
+HELP-INDEX>Configurando una Estaci�n Meteorl�gica en la RED
+
+Configurando una Estaci�n Meteorl�gica en la RED
+
+Xastir puede usar servicios de dato de una estaci�n Meteorol�gica
+tales como la wx200d. La wx200d le permitir�s varias conexiones de redes,
+asi compartiendo el informe del tiempo con varios programas o computadores.
+
+Entre el nombre del host (o la direcci�n num�rica IP) y el n�mero del puerto
+de la estaci�n Meteorol�gica servidora que usted quieres contactar.
+
+Seleccionado "Activar en Inicio" le dir�s a Xastir buscar este dispositivo y
+fijar comunicanciones con el cuando el programa se inicie primero.
+
+Seleccionado "Reconectar en fallo de la RED" le dir� a Xastir tratar de reconectar cuando
+el data conexi�n haya fracasado.
+Como antes el tipo de data sobrepasar� el auto-detecci�n.
+
+HELP-INDEX>Di�logo info estaci�n - b�squeda FCC y RAC
+
+ Di�logo info estaci�n - b�squeda FCC y RAC
+
+Info estaci�n desplegar� cualquier dato descifrado por Xastir.
+Actualmente dos o tres botones aparecen aqu� adem�s del bot�n Cerrar.
+
+Los botones de Anular Rastro anular�n cualquier l�nea de rastro para esa estaci�n
+que es actualmente guardada o en el despliegue de mapa.
+
+Env�e mensaje abrir� la ventana de mensaje y le permitir� enviar a mensje a esta estaci�n.
+El llenar� en el indicativo por usted.
+
+Si el banco de datos de FCC se instala,
+un bot�n de B�squeda en el Banco de datos FCC aparecer� en este Di�logo.
+Si el RAC (RadioAficionados de Canad�) banco de datos se instala,
+un bot�n de b�squeda RAC Banco de datos aparecer� para indicativo
+que empiezan con una "V".
+
+El archivo FCC y RAC deben colocarse en el directorio
+/usr/local/share/xastir/fcc, y el caso es importante!
+
+Usted puedes usar este bot�n para agregar los nombres de estaciones
+y dir�jase al Di�logo de Estaci�n Info.
+
+Para usar la b�squeda de FCC bajelo de aqui:
+ftp://ftp.fcc.gov/pub/XFS_AlphaTest/amateur/appl.zip
+
+ o el Nuevo banco de datos en:
+ftp://ftp.fcc.gov/pub/Bureaus/Wireless/Databases/uls/complete/l_amat.zip
+
+(El �nico archivo necesitado forma este 40Meg zip es el archivo EN.dat)
+
+* * * * NOTA para usar el NUEVO archivo base de datos debe ordenarse primero!!! * * * *
+
+�Aseg�rese que usted tienes espacio en el disco suficiente
+para esto como el archivo es GRANDE!
+
+Para ordenar el archivo: sort +4 -t \ | EN.dat >EN.dat.ordenado
+rm EN.dat
+mv EN.dat.ordenado EN.dat
+
+Para usar la b�squeda de RAC b�jelo de: ftp://ftp.rac.ca/pub/cdncaldb.zip
+Xastir crear� archivos �ndice por cada archivo del banco de datos en el inicio.
+
+Si un archivo de indicativo es eliminado mientras Xastir est� corriendo,
+crear� o reconstruir� el �ndice en la pr�xima b�squeda. No se manejan prefijos especiales.
+
+HELP-INDEX>Opciones de Despliegue
+
+ Opciones de Despliegue
+
+Estas opciones le permitir�n desplegar datos sobre la estaci�n alrededor del
+�cono de las estaciones en el mapa.
+
+Indicativo (on/off)
+ Cuando est� en 'ON', todo los indicativos de las estaciones se desplegar�n.
+Si este esta en 'OFF' los indicativos no se desplegar�n sobre el mapa.
+
+Para viejas estaciones el s�mbolo es dibujado
+como fantasma y en su orientaci�n estandar.
+
+Corespondiendo al arrastre que son subrayado m�s que s�lido y todo el data
+excepto el indicativo desaparece de la pantalla.
+
+Callsign (on/off)
+Determines if the callsign is displayed on the right side of the symbol.
+
+Altura (on/off)
+ Cuando est� en 'ON', una l�nea azul de datos aparecer� sobre el indicativo.
+Este desplegar� la �ltima altitud conocida de la estaci�n.
+
+Curso (on/off)
+ Cuando est� en 'ON', una l�nea verde de dato aparecer� debajo del indicativo.
+Esto desplegar� el �ltimo curso conocido (en grados) de la estaci�n que est� en
+movimiento.
+
+Velocidad (on/off)
+ Cuando est� en 'ON', una l�nea roja aparecer� debajo del indicativo (o curso).
+Esto despliegar� la �ltima velocidad conocida de la estaci�n que est� en
+movimiento.
+
+Dist/curso (on/off)
+ Cuando est� en 'ON', se desplegar�n dos l�neas de informaci�n en el lado
+izquierdo del �cono de la estaci�n. La l�nea de arriba tendr� la distancia
+de su estaci�n hacia esta estaci�n. La l�nea de abajo tendr� el curso desde su
+estaci�n hacia esta estaci�n.
+
+Rastros de estaciones (on/off)
+ Cuando est� en 'ON', cualquier estaci�n en movimiento arrastrar� una l�nea
+coloreada con las �ltimas 100+ localizaciones. Cuando la estaci�n se pone vieja
+el �cono es opaco la l�nea de rastro se volver� intermitente en lugar de la
+l�nea cont�nua.
+
+
+Estaci�n Potencia/Ganancia (on/off)
+ Cuando est� en 'ON', se desplegar�n C�rculos de Poder/Ganancia.
+ Sobrepasando los c�rculos indicado que las estaciones est�n te�ricamente
+ con simple rango uno del otro.
+ Esto es aproximandaemnte exacto, especialmente in �reas de terreno variable.
+
+Rastreo Estaci�n
+ Traer� una caja abierta similar a la opci�n localizar estaci�n. Usted puedes
+entrar todos o parte del indicativo. Al seleccionar "Rastrear Ahora!" El
+despliegue saltar� a la posici�n de la estaci�n (si es encuentrada). Cuando
+nuevos datos para esa estaci�n son encuentrados el despliegar� el rastro a lo largo
+de esa estaci�n.
+
+ El bot�n "Borrar Rastro" limpiar� todo el rastro.
+
+ El bot�n de "Cancelar" terminar� sin cambios realizados.
+
+Informe del Tiempo (on/off)
+Cuando est� en 'ON', los �ltimos datos del tiempo
+(velocidad/curso/r�faga,Humedad,temperatura,viento)
+ son desplegados.
+
+S�mbolos (on/off)
+Determina si los s�mbolos podr�an ser dibujado en el mapa.
+
+Rotar S�mbolos (on/off)
+Si 'ON', algunos s�mbolos deber�an cambiar su orientaci�n y mostrar la
+direcci�n en la cual una estaci�n m�vil se est� moviendo.
+
+HELP-INDEX>Mensajes
+
+ Mensajes
+
+Enviar mensaje a y Mensajes De grupo abierto
+�stos son muy similares. El "Enviar mensaje a" enviar� sus mensajes a una
+estaci�n y recibir� s�lo forma de datos de la estaci�n. Los mensajes de grupo
+son m�s en general usted puedes recibir cualquier mensaje para el grupo y usted
+enviar�s sus mensajes a ese nombre de grupo. Los mensajes de grupo no pueden
+trabajar mejor por el momento hay varios problemas que necesitan ser
+solucionado. Sin embargo, volviendo atr�s al
+uso de estas pantallas.
+
+Cada una de estas pantallas contienen una caja de mensaje, una l�nea de
+llamada, una l�nea de mensaje, y varios botones. Usted debes primero entrar la
+llamada del grupo o estaci�n que usted quieres avisar. Una vez que eso se hace
+cualquier nuevo mensaje que ha entrado de esa estaci�n hacia usted ser�s
+desplegado. Si la estaci�n est� envi�ndole informaci�n y ninguna ventana de
+mensaje est� abierta �l abrir� autom�ticamente a una nueva ventana (hasta 10)
+con esos indicativos de estaciones para usted. Usted puedes ahora entrar un
+mensaje en la l�nea de mensaje. El mensaje puede ser m�s largo que la l�nea de
+mensaje, y la m�xima salida es aproximadamente 250+ car�cteres. Una vez su
+mensaje es entrado, pulsando el bot�n "Enviar Ahora!" mandar� su mensaje.
+
+El bot�n "Enviar Ahora!" se pondr� opaco hasta que su mensaje sea completamente Reconocido.
+Cualquier mensaje que usted recibas ser� ordenado por la l�nea # y ser� puesto
+en la ventana de mensaje. Si usted est�s en un modo de grupo cada l�nea
+desplegar� el indicativo de donde el mensaje se envi� seguido por el propio
+mensaje. Los mensajes de grupos actuales son ordenados por llamada y despu�s
+la l�nea #. Cuando usted hayas enviado el mensaje pulsando el bot�n de "Cerrar"
+cerrar� la ventana.
+
+Dos otros botones son tambi�n disponible. El bot�n "Nuevo Indicativo"
+le permitir� mirar datos viejos que una estaci�n ha enviado.
+Teclee el indicativo y pulse en este bot�n, cualquier
+informaci�n vieja ser� desplegada.
+Usted tambi�n puedes usar este bot�n para cambiar el indicativo de la estaci�n
+con la que usted est�s hablando.
+Entre el nuevo indicativo y pulse el bot�n. El bot�n de "Borrar Mensajes"
+limpiar� cualquier mensaje desplegado en la ventana de mensajes.
+
+
+Borrar todos los mensajes salientes
+ Esto limpiar� todo los mensajes no-conocidos que usted has enviado.
+
+Auto Contestaci�n de Msj
+Esto encender� una contestaci�n autom�tica
+cuando un mensaje entrante se recibe.
+
+Fijar Mensaje en contestaci�n Autom�tica
+ Esto fijar� un mensaje que se enviar� en ausencia autom�ticamente.
+
+HELP-INDEX>Limpiando el despliegue de l�nea de rastros
+
+ Limpiando el despliegue de l�nea de rastros
+
+Pulse el bot�n en "Archivo" y despu�s "Borrar Todo rastro". Esto limpiar�
+todo el dato de la l�nea de rastreo del banco de datos de la estaci�n y
+actualiza la pantalla.
+
+HELP-INDEX>Limpiando el despliegue de estaciones
+
+ Limpiando el despliegue de estaciones
+
+Pulse el bot�n en "Archivo" y luego el bot�n "Borrar Toda las Estaciones". Esto
+limpiar� todo los datos del banco de datos de las estaciones excepto la suya.
+
+HELP-INDEX>Reenviando un log (Bit�cora)
+
+ Reenviando una Bit�cora
+
+Pulse el bot�n en "Archivo" y despu�s en "Abrir Bit�cora"
+una ventana de selecci�n de archivo se desplegar�.
+
+Usted puedes usarlo hojear su unidad de disco duro y seleccionar cualquier archivo
+que contenga un TNC datos raw como aqu�llos creados por el TNC y opciones de red.
+
+Su estaci�n todav�a funcionar� de la misma manera, recibiendo y transmitiendo.
+Y debe haber una palabra de advertencia aqu�, si su dato contiene una sessi�n
+de mensaje y usted tienes su estaci�n lista para transmitir, responder� al
+archivo como si el dato fu� recibido sobre el TNC o Internet.
+
+HELP-INDEX>Localizando una Estaci�n
+
+ Localizando una Estaci�n
+
+Pulse el bot�n sobre "Visualizador" luego en, "Localizar Estaci�n"
+o sobre el bot�n de "Desplegar" luego en "Estaci�n Rastreo" una ventana se abrir�.
+Usted puedes ahora entrar una estaci�n o parte de una estaci�n. Por
+defecto buscar� un macheo exacto (llamada completa, no parcial) y no es caso
+sensible. Si usted est�s buscando un macheo parcial, "Macheo Exacto" podr�a no
+ser seleccionado.
+
+Realmente usted puedes usar esto para localizar una estaci�n o un objeto. Qu� es
+donde nosotros venimos a la opci�n "Macheo Sensible". Yo he notado que algunos
+objetos est�n en caso mixto o min�scula. Con "Macheo Sensible" seleccionado,
+el localizador buscar� may�scula y min�scula cuando usted la entr�. Si
+"Macheo Sensible" no se selecciona, el localizador asumir� cualquier caso que usted
+teclees es may�scula y investigar� en eso. Pulsando el bot�n "Localizar Ahora!"
+centrar� la primera estaci�n encontrada en el centro de su pantalla
+al nivel del enfoque actual. Pulsando el bot�n "Cancelar" cerrar� la ventana.
+
+HELP-INDEX>Creando y usando Salto a Localizaciones
+
+ Creando y usando Salto a Localizaciones
+
+Pulse el bot�n "Visualizador", luego en "Saltar a la posici�n" una ventana aparecer�.
+Si �sta es la primera vez usted has usado este di�logo no tendr�s ninguna entrada en �l.
+Agregar una posici�n en la lista de posici�n vaya al �rea del mapa principal
+y enfoque el nivel que usted quieres usar.
+
+Entre un �nico nombre en el �rea "Nombre de Nueva localizaci�n",
+luego pulse el bot�n agregar.
+Su entrada se agregar� a la lista (en orden alfab�tico).
+Usted puedes agregar tantas locaci�n de mapas que usted quieras de esta manera.
+
+Para usar uno de la posici�n pulsar el bot�n en el nombre de la posici�n
+y pulsar el bot�n "IR!", el mapa principal entonces mostrar� esa posici�n.
+
+Usted puedes anular una posici�n similarmente pulsando el bot�n
+sobre el nombre de la posici�n y luego el bot�n "Anular".
+
+HELP-INDEX>Rastreando una Estaci�n
+
+Rastreando una Estaci�n
+
+Pulse sobre el bot�n de "Desplegar" luego en "Rastreo Estaci�n".
+Entre en el indicativo para rastrear (todos o parte) luego pulse el bot�n "Rastrear Ahora!".
+Como la estaci�n lo mueve ser� centrado en la ventana del mapa principal.
+Dejar de rastrear esta estaci�n pulsar el bot�n "Anular Rastro".
+
+HELP-INDEX>Tr�fico de mensajes
+
+ Tr�fico de todos los mensajes
+
+Pulse sobre la opci�n de "Tr�fico de Mensajes"
+luego un di�logo se abrir� e iniciar� el Monitoreo
+de todas las estaciones alrededor del mundo, en chat o enviando
+mensaje de prueba etc.
+
+HELP-INDEX>Imprimiendo
+
+ Imprimiendo la Pantalla del Mapa
+
+Xastir puede imprimir el �rea de dibujo en cualquier blanco y negro o color. Hace
+esto primero descargando la imagen a un archivo XPixmap en disco, entonces usando una
+herramienta externa para convertirlo al posdata, balancearlo, rotarlo, prevista, entonces la impresi�n
+. Usted debe tener su sistema que configure la impresi�n para manejar posdata (normalmente
+esto requiere Ghostscript y un filtro de impresi�n instalados, as� como lp o lpr
+imprime spoolers). Usted tambi�n debe tener las herramientas siguientes instaladas para esta
+capacidad: Herramientas de ImageMagick (espec�ficamente "convertido"), "Ghostscript",
+Conjuntos de caracteres de Ghostscript, y "gv". Una vez todos esos paquetes son instalando y
+funcional, usted debe una "gv" ventana sobre salte brevemente despu�s que usted le diga a
+Xastir crear un archivo de impresi�n. De all� usted puede ver la imagen impresa, y
+si aceptable, diga a "gv" imprimirlo. Note que algunas veces cambiando a un blanco
+el fondo predefinido para los mapas se recomienda, dependiendo de qu� mapas usted tienen
+visualizable. Esto puede ahorrar le grandemente la tinta.
+
+HELP-INDEX>Creando Captura Instant�nea Autom�ticamente
+
+ Creando Captura Instant�nea Autom�ticamente
+
+Xastir tiene la capacidad para crear captura instant�nea autom�ticamente en pantalla del mapa
+recurriendo al algo b�sico. Este periodo de tiempo es actualmente fijado por cinco
+minutos. Asumiendo que usted tiene "convertir" de la herramienta de ImageMagick
+instalado, Xastir crear� un archivo de formato XPM en /var/tmp, entonces lo converte,
+al archivo de PNG /var/tmp/xastir_snap.png. Este archivo es �til para ponerlo
+en p�ginas web para mostrar una imagen viva de lo que est� en su pantalla de Xastir. Habilite
+este rasgo v�a el "Archivo->Activar PNG Instant�nea".
+
+
+HELP-INDEX>Tabla de S�mbolo
+
+Eso son los s�mbolos que usted puedes selecionar para su estaci�n bajo la
+"Informaci�n de la Estaci�n" men� de configuraci�n.
+
+La lista actual puede ser encontrada en el APRS Referencia en el cual usted
+puedes obtenerlo desde http://www.tapr.org/
+
+ Tabla de s�mbolo
+
+S�mbolo Grupo/ Grupo/
+
+! Tri�ngulo w/! Tri�ngulo w/!
+" Lluvia Nube Lluvia Nube
+# Digi DIGI
+$ S�mbolo telef�nico $ S�mbolo
+% DX DX
+& GATE-HF GATE
+' Avi�n peque�o Avi�n Ca�do
+( Nube nube
+) TBD
+* NIEVE Hojuela NIEVE Hojuela
++ Cruz roja
+, Inverso L
+- w/omni casa
+. X peque�a
+/ Punto rojo
+0 0 en una caja C�rculo
+1 1 en una caja
+2 2 en una caja
+3 3 en una caja
+4 4 en una caja
+5 5 en una caja
+6 6 en una caja
+7 7 en una caja
+8 8 en una caja
+9 9 en un GAS de la caja
+: Bombero ?
+; Tienda tienda
+< motocicleta Bander�n
+= M�quina de tren
+> Autom�vil autom�vil
+? Antena POS ? en una caja
+@ HURRICAN/TORMENTA HURRICAN/TORMENTA
+A Primero auxilio Caja
+B BBS Blowing Nieve
+C Canoa
+D D en un c�rculo
+E E en un circulo Pila de Humo
+F F en un c�rculo
+G Reja Antena Cuadrada ?
+H Hotel/Cama
+I TCP/IP ?
+J J en un c�rculo descarga
+K Escuela
+L Casa Iluminada Casa Iluminada
+M Mac
+N NTS ?
+O Globo
+P Carro de Patrulla Rx
+Q Circle con C�rculos C�rculo con C�rculos
+R RV Restaurante
+S Transbordador Sat�lite
+T Tormenta (cloud/bolt) Tormenta (cloud/bolt)
+U Autob�s escolar Sol
+V VOR TAC VOR TAC S�mbolo
+W Servicio del Tiempo Nacional NWS-Digi
+X Helic�ptero
+Y Velero
+Z Windows
+[ corredor WC
+\ DF Tri�ngulo
+] Packet Mail Box
+^ Avi�n grande Avi�n Grande
+_ Estaci�n Meteorol�gica WS-Digi
+` Plato de sat�lite
+a Ambulancia
+b Bicicleta vuela nube
+c antena de DX
+d depto de bombero. Antena de DX
+e Caballo Aguanieve nube
+f Cami�n de bombero FC Nube
+g planeador Bander�n (2)
+h Hospital HAM
+i Isla Isla
+j Jeep Jeep
+k Cami�n Cami�n
+l Punto peque�o Punto peque�o
+m MIC Milla Poste
+n N Tri�ngulo Peque�o
+o EOC Punto en C�rculos
+p Cachorro Punto en C�rculos
+q GS Antena Antena de GS
+r Antena Torre Antena Torre
+s Bote Barco
+t TS ?
+u 18 Rueda de Cami�n
+v Carro de mudanzas Punto en C�rculos
+w H20 Diluvio
+x X Windows Punto Rojo
+y Casa w/Yagi Casa w/yagi
+z X Windows
+{ NIEBLA NIEBLA
+| L�nea Negra L�nea negra
+} TCP TCP
+~ Velero Velero
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..6781b98
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,520 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2009-04-28.21; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -t) dst_arg=$2
+ shift;;
+
+ -T) no_target_directory=true;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ trap '(exit $?); exit' 1 2 13 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dst_arg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writeable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ -*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test -z "$d" && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/m4/Makefile.am b/m4/Makefile.am
new file mode 100644
index 0000000..6503e4a
--- /dev/null
+++ b/m4/Makefile.am
@@ -0,0 +1,5 @@
+# $Id: Makefile.am,v 1.10 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+EXTRA_DIST= xmhtml.m4
diff --git a/m4/Makefile.in b/m4/Makefile.in
new file mode 100644
index 0000000..dce9d04
--- /dev/null
+++ b/m4/Makefile.in
@@ -0,0 +1,364 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = m4
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTSHP = @CONTSHP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GMAGIC_BIN = @GMAGIC_BIN@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBCOMPAT = @LIBCOMPAT@
+LIBOBJS = @LIBOBJS@
+LIBRTREE = @LIBRTREE@
+LIBS = @LIBS@
+LIBSHP = @LIBSHP@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LWPOSTGIS = @LWPOSTGIS@
+MAGIC_BIN = @MAGIC_BIN@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PG_CONFIG = @PG_CONFIG@
+POW_LIB = @POW_LIB@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUBRTREE = @SUBRTREE@
+SUBSHP = @SUBSHP@
+VERSION = @VERSION@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+convert = @convert@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+festival = @festival@
+found_gdal_config = @found_gdal_config@
+gm = @gm@
+gpsman = @gpsman@
+gv = @gv@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lpr = @lpr@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+mv = @mv@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sed = @sed@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+wget = @wget@
+xfontsel = @xfontsel@
+
+# $Id: Makefile.am,v 1.10 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+EXTRA_DIST = xmhtml.m4
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu m4/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu m4/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic distclean \
+ distclean-generic distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/m4/xmhtml.m4 b/m4/xmhtml.m4
new file mode 100644
index 0000000..760508d
--- /dev/null
+++ b/m4/xmhtml.m4
@@ -0,0 +1,215 @@
+dnl
+dnl
+dnl ICE_FIND_XmHTML
+dnl
+dnl Adapted from a macro by Andreas Zeller.
+dnl
+AC_DEFUN([ICE_FIND_XmHTML],
+[
+AC_REQUIRE([AC_PATH_XTRA])
+xmhtml_includes=
+xmhtml_libraries=
+AC_ARG_WITH(XmHTML,
+[ --without-XmHTML do not use XmHTML widgets])
+dnl Treat --without-XmHTML like
+dnl --without-XmHTML-includes --without-XmHTML-libraries.
+if test "$with_XmHTML" = "no"
+then
+xmhtml_includes=none
+xmhtml_libraries=none
+fi
+AC_ARG_WITH(xmhtml-includes,
+[ --with-xmhtml-includes=DIR Motif include files are in DIR],
+xmhtml_includes="$withval")
+AC_ARG_WITH(xmhtml-libraries,
+[ --with-xmhtml-libraries=DIR Motif libraries are in DIR],
+xmhtml_libraries="$withval")
+AC_MSG_CHECKING(for XmHTML)
+#
+#
+# Search the include files.
+#
+if test "$xmhtml_includes" = ""; then
+AC_CACHE_VAL(ice_cv_xmhtml_includes,
+[
+ice_xmhtml_save_LIBS="$LIBS"
+ice_xmhtml_save_CFLAGS="$CFLAGS"
+ice_xmhtml_save_CPPFLAGS="$CPPFLAGS"
+ice_xmhtml_save_LDFLAGS="$LDFLAGS"
+#
+LIBS="$X_PRE_LIBS -lXm -lXt -lX11 $X_EXTRA_LIBS $LIBS"
+CFLAGS="$X_CFLAGS $CFLAGS"
+CPPFLAGS="$X_CFLAGS $CPPFLAGS"
+LDFLAGS="$X_LIBS $LDFLAGS"
+#
+AC_TRY_COMPILE([#include <XmHTML/XmHTML.h>],[int a;],
+[
+# XmHTML/XmHTML.h is in the standard search path.
+ice_cv_xmhtml_includes=
+],
+[
+# XmHTML/XmHTML.h is not in the standard search path.
+# Locate it and put its directory in `xmhtml_includes'
+#
+# /usr/include/Motif* are used on HP-UX (Motif).
+# /usr/include/X11* are used on HP-UX (X and Athena).
+# /usr/dt is used on Solaris (Motif).
+# /usr/openwin is used on Solaris (X and Athena).
+# Other directories are just guesses.
+ice_cv_xmhtml_includes="none"
+for dir in "$x_includes" "${prefix}/include" /usr/include /usr/local/include \
+ /usr/include/Motif2.0 /usr/include/Motif1.2 /usr/include/Motif1.1 \
+ /usr/include/X11R6 /usr/include/X11R5 /usr/include/X11R4 \
+ /usr/dt/include /usr/openwin/include \
+ /usr/dt/*/include /opt/*/include /usr/include/Motif* \
+ /home/XmHTML/include /usr/XmHTML/include /opt/XmHTML/include \
+ /home/XmHTML*/include /usr/XmHTML*/include /opt/XmHTML*/include \
+ "${prefix}"/*/include /usr/*/include /usr/local/*/include \
+ "${prefix}"/include/* /usr/include/* /usr/local/include/*; do
+if test -f "$dir/XmHTML/XmHTML.h"; then
+ ice_cv_xmhtml_includes="$dir"
+ break
+fi
+done
+])
+#
+LIBS="$ice_xmhtml_save_LIBS"
+CFLAGS="$ice_xmhtml_save_CFLAGS"
+CPPFLAGS="$ice_xmhtml_save_CPPFLAGS"
+LDFLAGS="$ice_xmhtml_save_LDFLAGS"
+])
+xmhtml_includes="$ice_cv_xmhtml_includes"
+fi
+#
+#
+# Now for the libraries.
+#
+if test "$xmhtml_libraries" = ""; then
+AC_CACHE_VAL(ice_cv_xmhtml_libraries,
+[
+ice_xmhtml_save_LIBS="$LIBS"
+ice_xmhtml_save_CFLAGS="$CFLAGS"
+ice_xmhtml_save_CPPFLAGS="$CPPFLAGS"
+ice_xmhtml_save_LDFLAGS="$LDFLAGS"
+#
+LIBS="$X_PRE_LIBS -lXmHTML -lXm -lXt -lX11 $X_EXTRA_LIBS $LIBS"
+CFLAGS="$X_CFLAGS $CFLAGS"
+CPPFLAGS="$X_CFLAGS $CPPFLAGS"
+LDFLAGS="$X_LIBS $LDFLAGS"
+#
+AC_TRY_LINK([#include <XmHTML/XmHTML.h>],[XmCreateHTML();],
+[
+# libXm.a is in the standard search path.
+ice_cv_xmhtml_libraries=
+],
+[
+# libXm.a is not in the standard search path.
+# Locate it and put its directory in `xmhtml_libraries'
+#
+# /usr/lib/Motif* are used on HP-UX (Motif).
+# /usr/lib/X11* are used on HP-UX (X and Athena).
+# /usr/dt is used on Solaris (Motif).
+# /usr/lesstif is used on Linux (Lesstif).
+# /usr/openwin is used on Solaris (X and Athena).
+# Other directories are just guesses.
+ice_cv_xmhtml_libraries="none"
+for dir in "$x_libraries" "${prefix}/lib" /usr/lib /usr/local/lib \
+ /usr/lib/Motif2.0 /usr/lib/Motif1.2 /usr/lib/Motif1.1 \
+ /usr/lib/X11R6 /usr/lib/X11R5 /usr/lib/X11R4 /usr/lib/X11 \
+ /usr/dt/lib /usr/openwin/lib \
+ /usr/dt/*/lib /opt/*/lib /usr/lib/Motif* \
+ /usr/lesstif*/lib /usr/lib/Lesstif* \
+ /home/XmHTML/lib /usr/XmHTML/lib /opt/XmHTML/lib \
+ /home/XmHTML*/lib /usr/XmHTML*/lib /opt/XmHTML*/lib \
+ "${prefix}"/*/lib /usr/*/lib /usr/local/*/lib \
+ "${prefix}"/lib/* /usr/lib/* /usr/local/lib/*; do
+if test -d "$dir" && test "`ls $dir/libXmHTML.* 2> /dev/null`" != ""; then
+ ice_cv_xmhtml_libraries="$dir"
+ break
+fi
+done
+])
+#
+LIBS="$ice_xmhtml_save_LIBS"
+CFLAGS="$ice_xmhtml_save_CFLAGS"
+CPPFLAGS="$ice_xmhtml_save_CPPFLAGS"
+LDFLAGS="$ice_xmhtml_save_LDFLAGS"
+])
+#
+xmhtml_libraries="$ice_cv_xmhtml_libraries"
+fi
+#
+# Provide an easier way to link
+#
+# Okay
+#
+# Let's start by making sure that we completely abandon everything related
+# to XmHTML installation if either the library or the includes have not been
+# located, OR if there was a problem locating the Motif libraries, which are
+# required for the use of XmHTML. The opening three conditions, if true, will
+# bypass all XmHTML config operations; that is to say, if any of these
+# conditions is true, we call with_xmhtml "no", and that's the end of the
+# game.
+#
+if test "$with_xmhtml" = "no" ; then
+ with_xmhtml="no"
+elif test "$xmhtml_includes" = "none" ; then
+ with_xmhtml="no"
+elif test "$xmhtml_libraries" = "none"; then
+ with_xmhtml="no"
+else
+#
+# We now have established that we want to use XmHTML. It's time to set up the
+# basic environment, and do some discrete tests to set up the environment.
+#
+# First, let's set with_xmhtml to "yes" (don't know of this is really
+# necessary, but we'll be conservative here). We also send HAVE_XmHTML
+# to config.h and the cache file.
+#
+ AC_DEFINE(HAVE_XmHTML_H)
+ with_xmhtml="yes"
+#
+# Then let's see if the includes were NOT in the default path (if they were,
+# we won't be needing an -I to point at the headers, because the compiler
+# will find them by itself). We've already eliminated the possibility of
+# "none", so anything other than "" will definitely be a path.
+#
+#
+ if test "$xmhtml_includes" != ""; then
+ include_xmhtml="-I$xmhtml_includes"
+ fi
+#
+# Now that that's out of the way, let's deal with libraries. Here,
+# we check again to see if the variable (xmhtml_libraries this time)
+# is an empty string, but this time we have work to do whether the
+# test is true or false. We start with the case of an empty
+# string, which means we want to link with XmHTML, but don't need
+# a path to the library.
+#
+# This isn't quite happy yet. A test for the location of the jpeg
+# and Xext libraries should be added.
+#
+ if test "$xmhtml_libraries" = ""; then
+ link_xmhtml="-lXmHTML -lXext -ljpeg -lpng -lz"
+ else
+ link_xmhtml="-L$xmhtml_libraries -lXmHTML -lXext -ljpeg -lpng -lz"
+ fi
+#
+# We now close the enclosing conditional.
+#
+fi
+#
+AC_SUBST(include_xmhtml)
+AC_SUBST(link_xmhtml)
+#
+#
+#
+xmhtml_libraries_result="$xmhtml_libraries"
+xmhtml_includes_result="$xmhtml_includes"
+test "$xmhtml_libraries_result" = "" && xmhtml_libraries_result="in default path"
+test "$xmhtml_includes_result" = "" && xmhtml_includes_result="in default path"
+test "$xmhtml_libraries_result" = "none" && xmhtml_libraries_result="(none)"
+test "$xmhtml_includes_result" = "none" && xmhtml_includes_result="(none)"
+AC_MSG_RESULT(
+ [libraries $xmhtml_libraries_result, headers $xmhtml_includes_result])
+])dnl
diff --git a/missing b/missing
new file mode 100755
index 0000000..28055d2
--- /dev/null
+++ b/missing
@@ -0,0 +1,376 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
+# 2008, 2009 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard at iro.umontreal.ca>, 1996.
+
+# 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, 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, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ # Exit code 63 means version mismatch. This often happens
+ # when the user try to use an ancient version of a tool on
+ # a file that requires a minimum version. In this case we
+ # we should proceed has if the program had been absent, or
+ # if --run hadn't been passed.
+ if test $? = 63; then
+ run=:
+ msg="probably too old"
+ fi
+ ;;
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ autom4te touch the output file, or create a stub one
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
+\`g' are ignored when checking the name.
+
+Send bug reports to <bug-automake at gnu.org>."
+ exit $?
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing $scriptversion (GNU Automake)"
+ exit $?
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+esac
+
+# normalize program name to check for.
+program=`echo "$1" | sed '
+ s/^gnu-//; t
+ s/^gnu//; t
+ s/^g//; t'`
+
+# Now exit if we have it, but it failed. Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program). This is about non-GNU programs, so use $1 not
+# $program.
+case $1 in
+ lex*|yacc*)
+ # Not GNU programs, they don't have --version.
+ ;;
+
+ tar*)
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ exit 1
+ fi
+ ;;
+
+ *)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ # Could not run --version or --help. This is probably someone
+ # running `$TOOL --version' or `$TOOL --help' to check whether
+ # $TOOL exists and not knowing $TOOL uses missing.
+ exit 1
+ fi
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $program in
+ aclocal*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case $f in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ autom4te*)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them.
+ You can get \`$1' as part of \`Autoconf' from any GNU
+ archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo "#! /bin/sh"
+ echo "# Created by GNU Automake missing as a replacement of"
+ echo "# $ $@"
+ echo "exit 0"
+ chmod +x $file
+ exit 1
+ fi
+ ;;
+
+ bison*|yacc*)
+ echo 1>&2 "\
+WARNING: \`$1' $msg. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f y.tab.h; then
+ echo >y.tab.h
+ fi
+ if test ! -f y.tab.c; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex*|flex*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f lex.yy.c; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit $?
+ fi
+ ;;
+
+ makeinfo*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ # The file to touch is that specified with -o ...
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -z "$file"; then
+ # ... or it is the one specified with @setfilename ...
+ infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '
+ /^@setfilename/{
+ s/.* \([^ ]*\) *$/\1/
+ p
+ q
+ }' $infile`
+ # ... or it is derived from the source name (dir/f.texi becomes f.info)
+ test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+ fi
+ # If the file does not exist, the user really needs makeinfo;
+ # let's fail without touching anything.
+ test -f $file || exit 1
+ touch $file
+ ;;
+
+ tar*)
+ shift
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar "$@" && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar "$@" && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case $firstarg in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ case $firstarg in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequisites for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100755
index 0000000..4191a45
--- /dev/null
+++ b/mkinstalldirs
@@ -0,0 +1,162 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+
+scriptversion=2009-04-28.21; # UTC
+
+# Original author: Noah Friedman <friedman at prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain.
+#
+# This file is maintained in Automake, please report
+# bugs to <bug-automake at gnu.org> or send patches to
+# <automake-patches at gnu.org>.
+
+nl='
+'
+IFS=" "" $nl"
+errstatus=0
+dirmode=
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ...
+
+Create each directory DIR (with mode MODE, if specified), including all
+leading file name components.
+
+Report bugs to <bug-automake at gnu.org>."
+
+# process command line arguments
+while test $# -gt 0 ; do
+ case $1 in
+ -h | --help | --h*) # -h for help
+ echo "$usage"
+ exit $?
+ ;;
+ -m) # -m PERM arg
+ shift
+ test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
+ dirmode=$1
+ shift
+ ;;
+ --version)
+ echo "$0 $scriptversion"
+ exit $?
+ ;;
+ --) # stop option processing
+ shift
+ break
+ ;;
+ -*) # unknown option
+ echo "$usage" 1>&2
+ exit 1
+ ;;
+ *) # first non-opt arg
+ break
+ ;;
+ esac
+done
+
+for file
+do
+ if test -d "$file"; then
+ shift
+ else
+ break
+ fi
+done
+
+case $# in
+ 0) exit 0 ;;
+esac
+
+# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and
+# mkdir -p a/c at the same time, both will detect that a is missing,
+# one will create a, then the other will try to create a and die with
+# a "File exists" error. This is a problem when calling mkinstalldirs
+# from a parallel make. We use --version in the probe to restrict
+# ourselves to GNU mkdir, which is thread-safe.
+case $dirmode in
+ '')
+ if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+ echo "mkdir -p -- $*"
+ exec mkdir -p -- "$@"
+ else
+ # On NextStep and OpenStep, the `mkdir' command does not
+ # recognize any option. It will interpret all options as
+ # directories to create, and then abort because `.' already
+ # exists.
+ test -d ./-p && rmdir ./-p
+ test -d ./--version && rmdir ./--version
+ fi
+ ;;
+ *)
+ if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 &&
+ test ! -d ./--version; then
+ echo "mkdir -m $dirmode -p -- $*"
+ exec mkdir -m "$dirmode" -p -- "$@"
+ else
+ # Clean up after NextStep and OpenStep mkdir.
+ for d in ./-m ./-p ./--version "./$dirmode";
+ do
+ test -d $d && rmdir $d
+ done
+ fi
+ ;;
+esac
+
+for file
+do
+ case $file in
+ /*) pathcomp=/ ;;
+ *) pathcomp= ;;
+ esac
+ oIFS=$IFS
+ IFS=/
+ set fnord $file
+ shift
+ IFS=$oIFS
+
+ for d
+ do
+ test "x$d" = x && continue
+
+ pathcomp=$pathcomp$d
+ case $pathcomp in
+ -*) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ else
+ if test ! -z "$dirmode"; then
+ echo "chmod $dirmode $pathcomp"
+ lasterr=
+ chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+ if test ! -z "$lasterr"; then
+ errstatus=$lasterr
+ fi
+ fi
+ fi
+ fi
+
+ pathcomp=$pathcomp/
+ done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/placeholder b/placeholder
new file mode 100644
index 0000000..371ac01
--- /dev/null
+++ b/placeholder
@@ -0,0 +1,5 @@
+
+This file was needed in order to the directory created.
+
+Delete this file at will.
+
diff --git a/scripts/Coordinate.pm b/scripts/Coordinate.pm
new file mode 100644
index 0000000..1ffc076
--- /dev/null
+++ b/scripts/Coordinate.pm
@@ -0,0 +1,2465 @@
+#!/usr/bin/perl -w
+
+
+#
+# Coordinate.pm: Perl module for:
+#
+# 1) Creating and manipulating Coordinate objects,
+# 2) Translating coordinates between UTM and Latitude/Longitude,
+# 3) Translating coordinates between ~231 different datums,
+# 4) Formatting coordinates into decimal degrees, degrees/minutes,
+# and degrees/minutes/seconds.
+#
+# Copyright (C) 2000-2012 Curt Mills, WE7U
+#
+# 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.
+#
+
+
+#
+# $Id: Coordinate.pm,v 1.6 2012/11/01 18:57:19 we7u Exp $
+#
+#
+# Reference ellipsoids derived from Peter H. Dana's website-
+# New: http://www.Colorado.EDU/geography/gcraft/notes/datum/elist.html
+#
+# Old: http://www.utexas.edu/depts/grg/gcraft/notes/datum/elist.html
+# Department of Geography, University of Texas at Austin
+# Internet: pdana at mail.utexas.edu
+# 3/22/95
+#
+#
+# Reference datums derived from Peter H. Dana's website-
+# http://www.Colorado.EDU/geography/gcraft/notes/datum/datum.html#GeoDat
+#
+#
+# UTM<->LAT/LON translations were originally written in C++ by
+# Chuck Gantz- chuck.gantz at globalstar.com. Permission received
+# by Chuck Gantz via e-mail to release it under the GPL license.
+# Re-coded into Perl by Curt Mills.
+#
+# Datum translations were originally written in C by
+# John F. Waers - jfwaers at csn.net. His code was released to
+# the public domain. Re-coded into Perl by Curt Mills.
+#
+#
+# TODO:
+# -----
+# Please note that I didn't pay a lot of attention to
+# keeping the "double" notation in the form of higher
+# precision floating point routines. This means that
+# the Perl5 code won't be as accurate as the original
+# C-code. It doesn't matter for my purposes. If
+# anyone converts to Math::BigFloat for higher precision,
+# please send me the changes. As it is I did a
+# quick check and found a difference of only 1.4 meters
+# between my Perl results and the results from a web-based
+# datum-shift calculator on the 'net. -- Curt.
+#
+# Should probably add return values for each method. Check
+# for error conditions and return 0 if problem.
+#
+# Add method to tell distance in meters of datum shift (verbose flag?)
+#
+# Get rid of print statements unless verbose or debug mode.
+#
+# POD documentation.
+#
+
+
+#------------------------------------------------------------------------------------------------
+
+
+package CoordinateFormat;
+
+
+$VERSION = do { my @r=(q$Revision: 1.6 $=~/\d+/g); sprintf "%d."."%02d"x$#r, at r };
+
+
+#
+# Conversions between decimal degrees, degrees/decimal minutes, and
+# degrees/minutes/seconds. These are methods which all work on
+# "CoordinateFormat" objects.
+#
+# These routines probably need a bit of work yet. It'd be nice
+# to be able to specify field widths.
+#
+
+
+sub new
+{
+ my $class = shift; # What class are we constructing?
+ my $self = { }; # Allocate new memory
+ bless $self, $class; # Mark it of the right type
+ $self->_init(@_); # Call _init with remaining args
+ return $self;
+}
+
+
+sub _init
+{
+ my $self = shift;
+ $self->{RAW} = shift if @_; # Input string
+ $self->{FORMATTED} = shift if @_; # Output string, formatted
+}
+
+
+sub raw # Set'er/Get'er for input string
+{
+ my $self = shift;
+ $self->{RAW} = shift if @_;
+ return $self->{RAW};
+}
+
+
+sub formatted # Set'er/Get'er for formatted string
+{
+ my $self = shift;
+ $self->{FORMATTED} = shift if @_;
+ return $self->{FORMATTED};
+}
+
+
+#
+# Returns the version number (RCS version tag) of this module.
+#
+sub version
+{
+ return $VERSION;
+}
+
+
+
+
+
+#
+# Degrees and Decimal Minutes
+#
+# Fills in the FORMATTED variable in the object and also returns
+# the string. If unsuccessful, returns an empty string.
+#
+sub degrees_minutes
+{
+ my $self = shift; # Get the object to work on
+ my $input = $self->raw();
+
+ my ($degrees, $minutes, $seconds);
+
+ if ( $input =~ /\d+\s+\d+\s+\d+\.*\d*/ ) # Input is in "DD MM SS.SS" format
+ {
+ $degrees = $minutes = $seconds = $input;
+ $degrees =~ s/(\d+)\s+\d+\s+\d+\.*\d*/$1/;
+ $minutes =~ s/\d+\s+(\d+)\s+\d+\.*\d*/$1/;
+ $seconds =~ s/\d+\s+\d+\s+(\d+\.*\d*)/$1/;
+ $minutes = $minutes + ($seconds / 60.0);
+ $self->formatted( sprintf( "%02d %02.8f", $degrees, abs($minutes) ) );
+ return( $self->formatted() );
+ }
+ elsif ( $input =~ /\d+\s+\d+\.*\d*/ ) # Input is in "DD MM.MM" format
+ {
+ $self->formatted( $input ); # No translation necessary
+ return( $self->formatted() );
+ }
+ elsif ( $input =~ /\d+\.*\d*/ ) # Input is in "DD.DDDD" format
+ {
+ $degrees = int ($input);
+ $minutes = ($input - $degrees) * 60.0;
+ $self->formatted( sprintf( "%02d %02.8f", $degrees, abs($minutes) ) );
+ return( $self->formatted() );
+ }
+ else
+ {
+ print "degrees_minutes() method: Input format not recognized: $input\n";
+ $self->formatted( "" );
+ return( "" ); # Should I die here instead?
+ }
+}
+
+
+
+
+
+#
+# Degrees/Minutes/Seconds
+#
+# Fills in the FORMATTED variable in the object and also returns
+# the string. If unsuccessful, returns an empty string.
+#
+sub degrees_minutes_seconds
+{
+ my $self = shift; # Get the object to work on
+ my $input = $self->raw();
+
+ my ($degrees, $minutes, $seconds);
+
+ if ( $input =~ /\d+\s+\d+\s+\d+\.*\d*/ ) # Input is in "DD MM SS.SS" format
+ {
+ $self->formatted( $input ); # No translation necessary
+ return( $self->formatted() );
+ }
+ elsif ( $input =~ /\d+\s+\d+\.*\d*/ ) # Input is in "DD MM.MM" format
+ {
+ $degrees = $minutes = $input;
+ $degrees =~ s/(\d+)\s+\d+\.*\d*/$1/;
+ $minutes =~ s/\d+\s+(\d+\.*\d*)/$1/;
+ $seconds = $minutes;
+ $minutes = int ($minutes);
+ $seconds = ($seconds - $minutes) * 60.0;
+ $self->formatted( sprintf( "%02d %02d %02.8f", $degrees, abs($minutes), abs($seconds) ) );
+ return( $self->formatted() );
+ }
+ elsif ( $input =~ /\d+\.*\d*/ ) # Input is in "DD.DDDD" format
+ {
+ $degrees = int ($input);
+ $minutes = int ( ($input - $degrees) * 60.0 );
+ $seconds = ( ( ($input - $degrees) * 60.0) - $minutes) * 60.0;
+ $self->formatted( sprintf( "%02d %02d %02.8f", $degrees, abs($minutes), abs($seconds) ) );
+ return( $self->formatted() );
+ }
+ else
+ {
+ print "degrees_minutes_seconds() method: Input format not recognized: $input\n";
+ $self->formatted( "" );
+ return( "" ); # Should I die here instead?
+ }
+}
+
+
+
+
+
+#
+# Decimal Degrees
+#
+# Fills in the FORMATTED variable in the object and also returns
+# the string. If unsuccessful, returns an empty string.
+#
+sub decimal_degrees
+{
+ my $self = shift; # Get the object to work on
+ my $input = $self->raw();
+
+ my ($degrees, $minutes, $seconds);
+
+ if ( $input =~ /\d+\s+\d+\s+\d+\.*\d*/ ) # Input is in "DD MM SS.SS" format
+ {
+ $degrees = $minutes = $seconds = $input;
+ $degrees =~ s/(\d+)\s+\d+\s+\d+\.*\d*/$1/;
+ $minutes =~ s/\d+\s+(\d+)\s+\d+\.*\d*/$1/;
+ $seconds =~ s/\d+\s+\d+\s+(\d+\.*\d*)/$1/;
+ $self->formatted( sprintf( "%02.8f", $degrees + ($minutes/60.0) + ($seconds/(60.0 * 60.0) ) ) );
+ return( $self->formatted() );
+ }
+ elsif ( $input =~ /\d+\s+\d+\.*\d*/ ) # Input is in "DD MM.MM" format
+ {
+ $degrees = $minutes = $input;
+ $degrees =~ s/(\d+)\s+\d+\.*\d*/$1/;
+ $minutes =~ s/\d+\s+(\d+\.*\d*)/$1/;
+ $self->formatted( sprintf( "%02.8f", $degrees + ($minutes / 60.0) ) );
+ return( $self->formatted() );
+ }
+ elsif ( $input =~ /\d+\.*\d*/ ) # Input is in "DD.DDDD" format
+ {
+ $self->formatted( $input ); # No translation necessary
+ return( $self->formatted() );
+ }
+ else
+ {
+ print "decimal_degrees() method: Input format not recognized: $input\n";
+ $self->formatted( "" );
+ return( "" ); # Should I die here instead?
+ }
+}
+
+
+#------------------------------------------------------------------------------------------------
+
+
+package Ellipsoid;
+
+
+$VERSION = do { my @r=(q$Revision: 1.6 $=~/\d+/g); sprintf "%d."."%02d"x$#r, at r };
+
+
+#
+# Ellipsoid: Equatorial_Radius is the ellipsoid semimajor axis (a)
+# Polar_Radius is the ellipsoid semiminor axis (b).
+# First_Ecc_Squared is the first eccentricity squared, defined as: 2f - (f^2)
+# Inverse_flattening (1/f) is the inverse of ellipsoid flattening 'f'
+# Flattening (f) is defined as: (a-b)/a.
+#
+# This object is used to create the Ellipsoid_Table object below,
+# containing all of the parameters to describe the various
+# ellipsoids that we need for datum and UTM<->Lat/Lon translations.
+#
+# Equatorial_Radius and First_Ecc_Squared are used by the UTM<->Lat/Lon code.
+# Equatorial_Radius and Inverse_flattening are used by the datum_shift code.
+#
+
+
+sub new
+{
+ my $class = shift; # What class are we constructing?
+ my $self = { }; # Allocate new memory
+ bless $self, $class; # Mark it of the right type
+ $self->_init(@_); # Call _init with remaining args
+ return $self;
+}
+
+
+#
+# Notice that we compute first_ecc_squared, flattening, and polar_radius
+# from the other parameters.
+#
+sub _init
+{
+ my $self = shift;
+ my $f;
+ my $b;
+ my $inverse_f;
+
+ $self->{NAME} = shift if @_; # Name of ellipsoid
+ $a = $self->{EQUATORIAL_RADIUS} = shift if @_; # Semi-major axis, meters
+ $inverse_f = $self->{INVERSE_FLATTENING} = shift if @_; # Inverse of the ellipsoid flattening 'f'
+
+ if ($inverse_f)
+ {
+ $f = 1.0 / $inverse_f;
+ $self->{FLATTENING} = $f; # Store the flattening value as well
+ $self->{FIRST_ECC_SQUARED} = (2 * $f) - ($f**2); # Compute First Eccentricity Squared from 'f'
+
+ if ($a)
+ {
+ # f = (a-b)/a
+ # f = a/a - b/a
+ # f = 1 - b/a
+ # b/a + f = 1
+ # b/a = 1 - f
+ # b = (1-f)a
+ #
+ $b = (1.0 - $f) * $a;
+ $self->{POLAR_RADIUS} = $b;
+ }
+ }
+}
+
+
+#
+# Returns the version number (RCS version tag) of this module.
+#
+sub version
+{
+ return $VERSION;
+}
+
+
+sub name
+{
+ my $self = shift;
+ $self->{NAME} = shift if @_;
+ return $self->{NAME};
+}
+
+
+sub equatorial_radius
+{
+ my $self = shift;
+ $self->{EQUATORIAL_RADIUS} = shift if @_;
+ return $self->{EQUATORIAL_RADIUS};
+}
+
+
+#
+# Note that you can override the computed POLAR_RADIUS value
+# by using this method to store a new value in the hash.
+#
+sub polar_radius
+{
+ my $self = shift;
+ $self->{POLAR_RADIUS} = shift if @_;
+ return $self->{POLAR_RADIUS};
+}
+
+
+#
+# Note that you can override the computed FIRST_ECC_SQUARED value
+# by using this method to store a new value in the hash.
+#
+sub first_ecc_squared
+{
+ my $self = shift;
+ $self->{FIRST_ECC_SQUARED} = shift if @_;
+ return $self->{FIRST_ECC_SQUARED};
+}
+
+
+#
+# Note that you can override the computed FLATTENING value
+# by using this method to store a new value in the hash.
+#
+sub flattening
+{
+ my $self = shift;
+ $self->{FLATTENING} = shift if @_;
+ return $self->{FLATTENING};
+}
+
+
+sub inverse_flattening
+{
+ my $self = shift;
+ $self->{INVERSE_FLATTENING} = shift if @_;
+ return $self->{INVERSE_FLATTENING};
+}
+
+
+#-----------------------------------------------------------------------------------------------
+
+
+package EllipsoidTable;
+
+
+$VERSION = do { my @r=(q$Revision: 1.6 $=~/\d+/g); sprintf "%d."."%02d"x$#r, at r };
+
+
+#
+# I could have created this table as a hash of anonymous arrays, which might have been
+# faster/more efficient. Oh well.
+#
+# All of the methods here are class methods. There isn't even a way to make an
+# EllipsoidTable object given here. This class is merely a large collection
+# of Ellipsoid objects, collected in the %_ellipsoid hash.
+#
+
+
+my %_ellipsoid; # Class data
+
+
+#
+# Returns the version number (RCS version tag) of this module.
+#
+sub version
+{
+ return $VERSION;
+}
+
+
+# Note that this method is really useless. The name is the same as the
+# hash key used in the %_ellipsoid hash. Redundant.
+#
+sub name
+{
+ shift; # Object reference (don't need it)
+ my $ellipsoid_name = shift;
+
+ return $_ellipsoid{$ellipsoid_name}->name();
+}
+
+
+sub equatorial_radius # (a)
+{
+ shift; # Object reference (don't need it)
+ my $ellipsoid_name = shift;
+
+ return $_ellipsoid{$ellipsoid_name}->equatorial_radius();
+}
+
+
+sub polar_radius # (b)
+{
+ shift; # Object reference (don't need it)
+ my $ellipsoid_name = shift;
+
+ return $_ellipsoid{$ellipsoid_name}->polar_radius();
+}
+
+
+sub first_ecc_squared # (ecc)
+{
+ shift; # Object reference (don't need it)
+ my $ellipsoid_name = shift;
+
+ return $_ellipsoid{$ellipsoid_name}->first_ecc_squared();
+}
+
+
+sub flattening # (f)
+{
+ shift; # Object reference (don't need it)
+ my $ellipsoid_name = shift;
+
+ return $_ellipsoid{$ellipsoid_name}->flattening();
+}
+
+
+sub inverse_flattening # (1/f)
+{
+ shift; # Object reference (don't need it)
+ my $ellipsoid_name = shift;
+
+ return $_ellipsoid{$ellipsoid_name}->inverse_flattening();
+}
+
+
+#
+# This method allows printing out each defined Ellipsoid.
+#
+sub enumerate
+{
+ my $self = shift;
+
+ print "\nEllipsoid\t\tEquatorial Radius (a)\tPolar Radius (b)\tFirst Eccentricity^2\tFlattening (f)\t\t1/f\n";
+ print "---------\t\t---------------------\t----------------\t--------------------\t--------------\t\t---\n";
+
+ foreach my $key (sort keys %_ellipsoid)
+ {
+ printf("%23s,\t%s,\t%s,\t%s,\t%s,\t%s\n",
+ $key,
+ $self->equatorial_radius($key),
+ $self->polar_radius($key),
+ $self->first_ecc_squared($key),
+ $self->flattening($key),
+ $self->inverse_flattening($key) );
+ }
+ return(1);
+}
+
+
+
+
+
+#
+# Auto-run code
+#
+# Fill in the hash containing Ellipsoid objects (fill in the Class data)
+#
+# Name, Equatorial_Radius (a), Inverse_Flattening (1/f).
+#
+# Name: Reference Ellipsoid Name
+# Equatorial_Radius: (a) = Semi-Major Axis (WGS-84 value = 6378137.0 meters)
+# Polar_radius: (b) = Semi-Minor Axis (WGS-84 value = 6356752.3142 meters)
+# Flattening: f = (a-b)/a (WGS-84 value = 0.00335281066475)
+# First_Eccentricity_Squared: ecc = 2f - (f^2) (WGS-84 value = 0.00669437999013)
+# Inverse_flattening: Reciprocal Flattening (1/f) (WGS-84 value = 298.257223563)
+#
+# We can calculate Polar_Radius (b), Flattening (f), and First_Eccentricity_Squared (ecc)
+# from the values for Equatorial_Radius (a) and Inverse_flattening (1/f), so the table
+# includes only the latter two parameters.
+#
+
+
+#print "Creating ellipsoid data\n";
+# Equatorial
+# Name Name Radius Inverse_flattening
+$_ellipsoid{"Airy"} = Ellipsoid->new( "Airy", 6377563.396, 299.324964600 );
+$_ellipsoid{"Modified Airy"} = Ellipsoid->new( "Modified Airy", 6377340.189, 299.324964600 );
+$_ellipsoid{"Australian National"} = Ellipsoid->new( "Australian National", 6378160.000, 298.250000000 );
+$_ellipsoid{"Bessel 1841"} = Ellipsoid->new( "Bessel 1841", 6377397.155, 299.152812800 );
+$_ellipsoid{"Bessel 1841 (Namibia)"} = Ellipsoid->new( "Bessel 1841 (Namibia)", 6377483.865, 299.152812800 );
+$_ellipsoid{"Clarke 1866"} = Ellipsoid->new( "Clarke 1866", 6378206.400, 294.978698200 );
+$_ellipsoid{"Clarke 1880"} = Ellipsoid->new( "Clarke 1880", 6378249.145, 293.465000000 );
+$_ellipsoid{"Everest (India 1830)"} = Ellipsoid->new( "Everest (India 1830)", 6377276.345, 300.801700000 );
+$_ellipsoid{"Everest (Sabah Sarawak)"} = Ellipsoid->new( "Everest (Sabah Sarawak)",6377298.556, 300.801700000 );
+$_ellipsoid{"Everest (India 1956)"} = Ellipsoid->new( "Everest (India 1956)", 6377301.243, 300.801700000 );
+$_ellipsoid{"Everest (Malaysia 1969)"} = Ellipsoid->new( "Everest (Malaysia 1969)",6377295.664, 300.801700000 );
+$_ellipsoid{"Everest (Malay. & Sing)"} = Ellipsoid->new( "Everest (Malay. & Sing)",6377304.063, 300.801700000 );
+$_ellipsoid{"Everest 1948"} = Ellipsoid->new( "Everest 1948", 6377304.063, 300.801700000 );
+$_ellipsoid{"Everest (Pakistan)"} = Ellipsoid->new( "Everest (Pakistan)", 6377309.613, 300.801700000 );
+$_ellipsoid{"Fischer 1960 (Mercury)"} = Ellipsoid->new( "Fischer 1960 (Mercury)", 6378166.000, 298.300000000 );
+$_ellipsoid{"Fischer 1968"} = Ellipsoid->new( "Fischer 1968", 6378150.000, 298.300000000 );
+$_ellipsoid{"Modified Fischer 1960"} = Ellipsoid->new( "Modified Fischer 1960", 6378155.000, 298.300000000 );
+$_ellipsoid{"GRS 1967"} = Ellipsoid->new( "GRS 1967", 6378160.000, 298.247167427 );
+$_ellipsoid{"GRS 1980"} = Ellipsoid->new( "GRS 1980", 6378137.000, 298.257222101 );
+$_ellipsoid{"Helmert 1906"} = Ellipsoid->new( "Helmert 1906", 6378200.000, 298.300000000 );
+$_ellipsoid{"Hough 1960"} = Ellipsoid->new( "Hough 1960", 6378270.000, 297.000000000 );
+$_ellipsoid{"Indonesian 1974"} = Ellipsoid->new( "Indonesian 1974", 6378160.000, 298.247000000 );
+$_ellipsoid{"International 1924"} = Ellipsoid->new( "International 1924", 6378388.000, 297.000000000 );
+$_ellipsoid{"Krassovsky 1940"} = Ellipsoid->new( "Krassovsky 1940", 6378245.000, 298.300000000 );
+$_ellipsoid{"South American 1969"} = Ellipsoid->new( "South American 1969", 6378160.000, 298.250000000 );
+$_ellipsoid{"WGS 60"} = Ellipsoid->new( "WGS 60", 6378165.000, 298.300000000 );
+$_ellipsoid{"WGS 66"} = Ellipsoid->new( "WGS 66", 6378145.000, 298.250000000 );
+$_ellipsoid{"WGS 72"} = Ellipsoid->new( "WGS 72", 6378135.000, 298.260000000 );
+$_ellipsoid{"WGS 84"} = Ellipsoid->new( "WGS 84", 6378137.000, 298.257223563 );
+
+
+#------------------------------------------------------------------------------------------------
+
+
+package Datum;
+
+
+$VERSION = do { my @r=(q$Revision: 1.6 $=~/\d+/g); sprintf "%d."."%02d"x$#r, at r };
+
+
+#
+# These are the objects and methods used to create the DatumTable in the next package.
+#
+
+
+sub new
+{
+ my $class = shift; # What class are we constructing?
+ my $self = { }; # Allocate new memory
+ bless $self, $class; # Mark it of the right type
+ $self->_init(@_); # Call _init with remaining args
+ return $self;
+}
+
+
+sub _init
+{
+ my $self = shift;
+ $self->{NAME} = shift if @_;
+ $self->{ELLIPSOID} = shift if @_;
+ $self->{DX} = shift if @_;
+ $self->{DY} = shift if @_;
+ $self->{DZ} = shift if @_;
+}
+
+
+#
+# Returns the version number (RCS version tag) of this module.
+#
+sub version
+{
+ return $VERSION;
+}
+
+
+#
+# This is mostly a useless method. We store the name here, but it
+# is also present as the hash key in the %_datum hash. Redundant.
+#
+sub name # Name of datum
+{
+ my $self = shift;
+ $self->{NAME} = shift if @_;
+ return $self->{NAME};
+}
+
+
+sub ellipsoid # Name of ellipsoid used in datum
+{
+ my $self = shift;
+ $self->{ELLIPSOID} = shift if @_;
+ return $self->{ELLIPSOID};
+}
+
+
+sub dx # X-offset from WGS84 ellipsoid center
+{
+ my $self = shift;
+ $self->{DX} = shift if @_;
+ return $self->{DX};
+}
+
+
+sub dy # Y-offset from WGS84 ellipsoid center
+{
+ my $self = shift;
+ $self->{DY} = shift if @_;
+ return $self->{DY};
+}
+
+
+sub dz # Z-offset from WGS84 ellipsoid center
+{
+ my $self = shift;
+ $self->{DZ} = shift if @_;
+ return $self->{DZ};
+}
+
+
+#------------------------------------------------------------------------------------------------
+
+
+package DatumTable;
+
+
+$VERSION = do { my @r=(q$Revision: 1.6 $=~/\d+/g); sprintf "%d."."%02d"x$#r, at r };
+
+
+#
+# I could have created this table as a hash of anonymous arrays, which might have been
+# faster/more efficient. Oh well.
+#
+# All of the methods here are class methods. There isn't even a way to make a
+# DatumTable object given here. This class is merely a large collection
+# of Datum objects, collected in the %_datum hash.
+#
+
+my %_datum; # Class data
+
+
+#
+# Returns the version number (RCS version tag) of this module.
+#
+sub version
+{
+ return $VERSION;
+}
+
+
+sub name # Name of datum
+{
+ shift; # Object reference (don't need it)
+ my $datum_name = shift;
+
+ return $_datum{$datum_name}->name();
+}
+
+
+sub ellipsoid # Name of ellipsoid used in datum
+{
+ shift; # Object reference (don't need it)
+ my $datum_name = shift;
+
+ return $_datum{$datum_name}->ellipsoid();
+}
+
+
+sub dx # X-offset from WGS84 ellipsoid center
+{
+ shift; # Object reference (don't need it)
+ my $datum_name = shift;
+
+ return $_datum{$datum_name}->dx();
+}
+
+
+sub dy # Y-offset from WGS84 ellipsoid center
+{
+ shift; # Object reference (don't need it)
+ my $datum_name = shift;
+
+ return $_datum{$datum_name}->dy();
+}
+
+
+sub dz # Z-offset from WGS84 ellipsoid center
+{
+ shift; # Object reference (don't need it)
+ my $datum_name = shift;
+
+ return $_datum{$datum_name}->dz();
+}
+
+
+#
+# This method allows printing out each defined Datum.
+#
+sub enumerate
+{
+ my $self = shift;
+
+ print "\nDatum\t\t\t\t\t\t\t\tEllipsoid\tDx\tDy\tDz\n";
+ print "-----\t\t\t\t\t\t\t\t---------\t--\t--\t--\n";
+
+ foreach my $key (sort keys %_datum)
+ {
+ printf("%s\n\t\t\t\t\t\t%23s,\t%s,\t%s,\t%s\n",
+ $key,
+ $self->ellipsoid($key),
+ $self->dx($key),
+ $self->dy($key),
+ $self->dz($key) );
+ }
+ return(1);
+}
+
+
+
+
+
+#
+# Auto-run code
+#
+# Fill in the Class data.
+#
+# This code fills in the %_datum hash which has entries consisting of Datum objects.
+#
+# From the original C code:
+#
+# "Dx, Dy, Dz: ellipsoid center with respect to WGS 84 ellipsoid center
+# x axis is the prime meridian
+# y axis is 90 degrees east longitude
+# z axis is the axis of rotation of the ellipsoid"
+#
+# Most of the current data is from Peter Dana's website.
+# This increased the number of datums to around 231. -- Curt.
+#
+#
+# NOTE: Consider adding a field for "region of use".
+#
+#
+# Name Name Ellipsoid Dx Dy Dz
+$_datum{"Adindan (Burkina Faso)"}
+ = Datum->new( "Adindan (Burkina Faso)",
+ "Clarke 1880", -118, -14, 218 );
+
+$_datum{"Adindan (Cameroon)"}
+ = Datum->new( "Adindan (Cameroon)",
+ "Clarke 1880", -134, -2, 210 );
+
+$_datum{"Adindan (Ethiopia)"}
+ = Datum->new( "Adindan (Ethiopia)",
+ "Clarke 1880", -165, -11, 206 );
+
+$_datum{"Adindan (Mali)"}
+ = Datum->new( "Adindan (Mali)",
+ "Clarke 1880", -123, -20, 220 );
+
+$_datum{"Adindan (MEAN for Ethiopia/Sudan)"}
+ = Datum->new( "Adindan (MEAN for Ethiopia/Sudan)",
+ "Clarke 1880", -166, -15, 204 );
+
+$_datum{"Adindan (Senegal)"}
+ = Datum->new( "Adindan (Senegal)",
+ "Clarke 1880", -128, -18, 224 );
+
+$_datum{"Adindan (Sudan)"}
+ = Datum->new( "Adindan (Sudan)",
+ "Clarke 1880", -161, -14, 205 );
+
+$_datum{"Afgooye"}
+ = Datum->new( "Afgooye",
+ "Krassovsky 1940", -43, -163, 45 );
+
+$_datum{"Ain el Abd 1970 (Bahrain)"}
+ = Datum->new( "Ain el Abd 1970 (Bahrain)",
+ "International 1924", -150, -250, -1 );
+
+$_datum{"Ain el Abd 1970 (Saudi Arabia)"}
+ = Datum->new( "Ain el Abd 1970 (Saudi Arabia)",
+ "International 1924", -143, -236, 7 );
+
+$_datum{"American Samoa 1962"}
+ = Datum->new( "American Samoa 1962",
+ "Clarke 1866", -115, 118, 426 );
+
+$_datum{"Anna 1 Astro 1965"}
+ = Datum->new( "Anna 1 Astro 1965",
+ "Australian National", -491, -22, 435 );
+
+$_datum{"Antigua Island Astro 1943"}
+ = Datum->new( "Antigua Island Astro 1943",
+ "Clarke 1880", -270, 13, 62 );
+
+$_datum{"Arc 1950 (Botswana)"}
+ = Datum->new( "Arc 1950 (Botswana)",
+ "Clarke 1880", -138, -105, -289 );
+
+$_datum{"Arc 1950 (Burundi)"}
+ = Datum->new( "Arc 1950 (Burundi)",
+ "Clarke 1880", -153, -5, -292 );
+
+$_datum{"Arc 1950 (Lesotho)"}
+ = Datum->new( "Arc 1950 (Lesotho)",
+ "Clarke 1880", -125, -108, -295 );
+
+$_datum{"Arc 1950 (Malawi)"}
+ = Datum->new( "Arc 1950 (Malawi)",
+ "Clarke 1880", -161, -73, -317 );
+
+$_datum{"Arc 1950 (MEAN)"}
+ = Datum->new( "Arc 1950 (MEAN)",
+ "Clarke 1880", -143, -90, -294 );
+
+$_datum{"Arc 1950 (Swaziland)"}
+ = Datum->new( "Arc 1950",
+ "Clarke 1880", -134, -105, -295 );
+
+$_datum{"Arc 1950 (Zaire)"}
+ = Datum->new( "Arc 1950",
+ "Clarke 1880", -169, -19, -278 );
+
+$_datum{"Arc 1950 (Zambia)"}
+ = Datum->new( "Arc 1950",
+ "Clarke 1880", -147, -74, -283 );
+
+$_datum{"Arc 1950 (Zimbabwe)"}
+ = Datum->new( "Arc 1950",
+ "Clarke 1880", -142, -96, -293 );
+
+$_datum{"Arc 1960 (MEAN)"}
+ = Datum->new( "Arc 1960 (MEAN)",
+ "Clarke 1880", -160, -6, -302 );
+
+$_datum{"Arc 1960 (Kenya)"}
+ = Datum->new( "Arc 1960 (Kenya)",
+ "Clarke 1880", -157, -2, -299 );
+
+$_datum{"Arc 1960 (Tanzania)"}
+ = Datum->new( "Arc 1960 (Tanzania)",
+ "Clarke 1880", -175, -23, -303 );
+
+$_datum{"Ascension Island 1958"}
+ = Datum->new( "Ascension Island 1958",
+ "International 1924", -205, 107, 53 );
+
+$_datum{"Astro B4 Sorol Atoll"}
+ = Datum->new( "Astro B4 Sorol Atoll",
+ "International 1924", 114, -116, -333 );
+
+$_datum{"Astro Beacon E 1945"}
+ = Datum->new( "Astro Beacon E 1945",
+ "International 1924", 145, 75, -272 );
+
+$_datum{"Astro DOS 71/4"}
+ = Datum->new( "Astro DOS 71/4",
+ "International 1924", -320, 550, -494 );
+
+$_datum{"Astro Tern Island (FRIG) 1961"}
+ = Datum->new( "Astro Tern Island (FRIG) 1961",
+ "International 1924", 114, -116, -333 );
+
+$_datum{"Astronomical Station 1952"}
+ = Datum->new( "Astronomical Station 1952",
+ "International 1924", 124, -234, -25 );
+
+$_datum{"Australian Geodetic 1966"}
+ = Datum->new( "Australian Geodetic 1966",
+ "Australian National", -133, -48, 148 );
+
+$_datum{"Australian Geodetic 1984"}
+ = Datum->new( "Australian Geodetic 1984",
+ "Australian National", -134, -48, 149 );
+
+$_datum{"Ayabelle Lighthouse"}
+ = Datum->new( "Ayabelle Lighthouse",
+ "Clarke 1880", -79, -129, 145 );
+
+$_datum{"Bellevue (IGN)"}
+ = Datum->new( "Bellevue (IGN)",
+ "International 1924", -127, -769, 472 );
+
+$_datum{"Bermuda 1957"}
+ = Datum->new( "Bermuda 1957",
+ "Clarke 1866", -73, 213, 296 );
+
+$_datum{"Bogota Observatory"}
+ = Datum->new( "Bogota Observatory",
+ "International 1924", 307, 304, -318 );
+
+$_datum{"Bukit Rimpah"}
+ = Datum->new( "Bukit Rimpah",
+ "Bessel 1841", -384, 664, -48 );
+
+$_datum{"Camp Area Astro"}
+ = Datum->new( "Camp Area Astro",
+ "International 1924", -104, -129, 239 );
+
+$_datum{"Campo Inchauspe"}
+ = Datum->new( "Campo Inchauspe",
+ "International 1924", -148, 136, 90 );
+
+$_datum{"Canton Astro 1966"}
+ = Datum->new( "Canton Astro 1966",
+ "International 1924", 298, -304, -375 );
+
+$_datum{"Cape"}
+ = Datum->new( "Cape",
+ "Clarke 1880", -136, -108, -292 );
+
+$_datum{"Cape Canaveral"}
+ = Datum->new( "Cape Canaveral",
+ "Clarke 1866", -2, 151, 181 );
+
+$_datum{"Carthage"}
+ = Datum->new( "Carthage",
+ "Clarke 1880", -263, 6, 431 );
+
+$_datum{"CH-1903"}
+ = Datum->new( "CH-1903",
+ "Bessel 1841", 674, 15, 405);
+
+$_datum{"Chatham Island Astro 1971"}
+ = Datum->new( "Chatham Island Astro 1971",
+ "International 1924", 175, -38, 113);
+
+$_datum{"Chua Astro"}
+ = Datum->new( "Chua Astro",
+ "International 1924", -134, 229, -29 );
+
+$_datum{"Corrego Alegre"}
+ = Datum->new( "Corrego Alegre",
+ "International 1924", -206, 172, -6 );
+
+$_datum{"Dabola"}
+ = Datum->new( "Dabola",
+ "Clarke 1880", -83, 37, 124 );
+
+$_datum{"Deception Island"}
+ = Datum->new( "Deception Island",
+ "Clarke 1880", 260, 12, -147 );
+
+$_datum{"Djakarta (Batavia)"}
+ = Datum->new( "Djakarta (Batavia)",
+ "Bessel 1841", -377, 681, -50 );
+
+$_datum{"DOS 1968"}
+ = Datum->new( "DOS 1968",
+ "International 1924", 230, -199, -752 );
+
+$_datum{"Easter Island 1967"}
+ = Datum->new( "Easter Island 1967",
+ "International 1924", 211, 147, 111 );
+
+$_datum{"Estonia 1937"}
+ = Datum->new( "Estonia 1937",
+ "Bessel 1841", 374, 150, 588 );
+
+$_datum{"European 1950 (Cyprus)"}
+ = Datum->new( "European 1950 (Cyprus)",
+ "International 1924", -104, -101, -140 );
+
+$_datum{"European 1950 (Egypt)"}
+ = Datum->new( "European 1950 (Egypt)",
+ "International 1924", -130, -117, -151 );
+
+$_datum{"European 1950 (England/Channel Is/Scotland/Shetland Is)"}
+ = Datum->new( "European 1950 (England/Channel Is/Scotland/Shetland Is)",
+ "International 1924", -86, -96, -120 );
+
+$_datum{"European 1950 (England/Ireland/Scotland/Shetland Is)"}
+ = Datum->new( "European 1950 (England/Ireland/Scotland/Shetland Is)",
+ "International 1924", -86, -96, -120 );
+
+$_datum{"European 1950 (Finland/Norway)"}
+ = Datum->new( "European 1950 (Finland/Norway)",
+ "International 1924", -87, -95, -120 );
+
+$_datum{"European 1950 (Greece)"}
+ = Datum->new( "European 1950 (Greece)",
+ "International 1924", -84, -95, -130 );
+
+$_datum{"European 1950 (Iran)"}
+ = Datum->new( "European 1950 (Iran)",
+ "International 1924", -117, -132, -164 );
+
+$_datum{"European 1950 (Italy:Sardinia)"}
+ = Datum->new( "European 1950 (Italy:Sardinia)",
+ "International 1924", -97, -103, -120 );
+
+$_datum{"European 1950 (Italy:Sicily)"}
+ = Datum->new( "European 1950 (Italy:Sicily)",
+ "International 1924", -97, -88, -135 );
+
+$_datum{"European 1950 (Malta)"}
+ = Datum->new( "European 1950 (Malta)",
+ "International 1924", -107, -88, -149 );
+
+$_datum{"European 1950 (MEAN for Austria/Belgium/Denmark/Finland/France/W Germany/Gibraltar/Greece/Italy/Luxembourg/Netherlands/Norway/Portugal/Spain/Sweden/Switzerland)"}
+ = Datum->new( "European 1950 (MEAN for Austria/Belgium/Denmark/Finland/France/W Germany/Gibraltar/Greece/Italy/Luxembourg/Netherlands/Norway/Portugal/Spain/Sweden/Switzerland)",
+ "International 1924", -87, -98, -121 );
+
+$_datum{"European 1950 (MEAN for Austria/Denmark/France/W Germany/Netherlands/Switzerland)"}
+ = Datum->new( "European 1950 (MEAN for Austria/Denmark/France/W Germany/Netherlands/Switzerland)",
+ "International 1924", -87, -96, -120 );
+
+$_datum{"European 1950 (MEAN for Iraq/Israel/Jordan/Lebanon/Kuwait/Saudi Arabia/Syria)"}
+ = Datum->new( "European 1950 (MEAN for Iraq/Israel/Jordan/Lebanon/Kuwait/Saudi Arabia/Syria)",
+ "International 1924", -103, -106, -141 );
+
+$_datum{"European 1950 (Portugal/Spain)"}
+ = Datum->new( "European 1950 (Portugal/Spain)",
+ "International 1924", -84, -107, -120 );
+
+$_datum{"European 1950 (Tunisia)"}
+ = Datum->new( "European 1950 (Tunisia)",
+ "International 1924", -112, -77, -145 );
+
+$_datum{"European 1979 (MEAN for Austria/Finland/Netherlands/Norway/Spain/Sweden/Switzerland)"}
+ = Datum->new( "European 1979 (MEAN for Austria/Finland/Netherlands/Norway/Spain/Sweden/Switzerland)",
+ "International 1924", -86, -98, -119 );
+
+$_datum{"Finland Hayford"}
+ = Datum->new( "Finland Hayford",
+ "International 1924", -78, -231, -97 );
+
+$_datum{"Fort Thomas"}
+ = Datum->new( "Fort Thomas",
+ "Clarke 1880", -7, 215, 225 );
+
+$_datum{"Gandajika Base 1970"}
+ = Datum->new( "Gandajika Base 1970",
+ "International 1924", -133, -321, 50 );
+
+$_datum{"Geodetic Datum 1949"}
+ = Datum->new( "Geodetic Datum 1949",
+ "International 1924", 84, -22, 209 );
+
+$_datum{"Graciosa Base SW 1948"}
+ = Datum->new( "Graciosa Base SW 1948",
+ "International 1924", -104, 167, -38 );
+
+$_datum{"Guam 1963"}
+ = Datum->new( "Guam 1963",
+ "Clarke 1866", -100, -248, 259 );
+
+$_datum{"Gunung Segara"}
+ = Datum->new( "Gunung Segara",
+ "Bessel 1841", -403, 684, 41 );
+
+$_datum{"GUX 1 Astro"}
+ = Datum->new( "GUX 1 Astro",
+ "International 1924", 252, -209, -751 );
+
+$_datum{"Herat North"}
+ = Datum->new( "Herat North",
+ "International 1924", -333, -222, 114 );
+
+$_datum{"Hermannskogel Datum (Namibia)"}
+ = Datum->new( "Hermannskogel Datum (Namibia)",
+ "Bessel 1841", 653, -212, 449 );
+
+$_datum{"Hjorsey 1955"}
+ = Datum->new( "Hjorsey 1955",
+ "International 1924", -73, 46, -86 );
+
+$_datum{"Hong Kong 1963"}
+ = Datum->new( "Hong Kong 1963",
+ "International 1924", -156, -271, -189 );
+
+$_datum{"Hu-Tzu-Shan"}
+ = Datum->new( "Hu-Tzu-Shan",
+ "International 1924", -637, -549, -203 );
+
+$_datum{"Indian (Bangladesh)"}
+ = Datum->new( "Indian (Bangladesh)",
+ "Everest (India 1830)", 282, 726, 254 );
+
+$_datum{"Indian (India/Nepal)"}
+ = Datum->new( "Indian (India/Nepal)",
+ "Everest (India 1956)", 295, 736, 257 );
+
+$_datum{"Indian (Pakistan)"}
+ = Datum->new( "Indian (Pakistan)",
+ "Everest (Pakistan)", 283, 682, 231 );
+
+$_datum{"Indian 1954 (Thailand)"}
+ = Datum->new( "Indian 1954 (Thailand)",
+ "Everest (India 1830)", 217, 823, 299 );
+
+$_datum{"Indian 1960 (Vietnam:Con Son Is)"}
+ = Datum->new( "Indian 1960 (Vietnam:Con Son Is)",
+ "Everest (India 1830)", 182, 915, 344 );
+
+$_datum{"Indian 1960 (Vietnam:Near 160N)"}
+ = Datum->new( "Indian 1960 (Vietnam:Near 160N)",
+ "Everest (India 1830)", 198, 881, 317 );
+
+$_datum{"Indian 1975 (Thailand)"}
+ = Datum->new( "Indian 1975 (Thailand)",
+ "Everest (India 1830)", 210, 814, 289 );
+
+$_datum{"Indonesian 1974"}
+ = Datum->new( "Indonesian 1974)",
+ "Indonesian 1974)", -24, -15, 5 );
+
+$_datum{"Ireland 1965"}
+ = Datum->new( "Ireland 1965",
+ "Modified Airy", 506, -122, 611 );
+
+$_datum{"ISTS 061 Astro 1968"}
+ = Datum->new( "ISTS 061 Astro 1968",
+ "International 1924", -794, 119, -298 );
+
+$_datum{"ISTS 073 Astro 1969"}
+ = Datum->new( "ISTS 073 Astro 1969",
+ "International 1924", 208, -435, -229 );
+
+$_datum{"Johnston Island"}
+ = Datum->new( "Johnston Island",
+ "International 1924", 189, -79, -202 );
+
+$_datum{"Kandawala"}
+ = Datum->new( "Kandawala",
+ "Everest (India 1830)", -97, 787, 86 );
+
+$_datum{"Kerguelen Island 1949"}
+ = Datum->new( "Kerguelen Island 1949",
+ "International 1924", 145, -187, 103 );
+
+$_datum{"Kertau 1948"}
+ = Datum->new( "Kertau 1948",
+ "Everest (Malay. & Sing)", -11, 851, 5 );
+
+$_datum{"Kusaie Astro 1951"}
+ = Datum->new( "Kusaie Astro 1951",
+ "International 1924", 647, 1777, -1124 );
+
+$_datum{"Korean Geodetic System"}
+ = Datum->new( "Korean Geodetic System",
+ "GRS 1980", 0, 0, 0 );
+
+$_datum{"L. C. 5 Astro 1961"}
+ = Datum->new( "L. C. 5 Astro 1961",
+ "Clarke 1866", 42, 124, 147 );
+
+$_datum{"Leigon"}
+ = Datum->new( "Leigon",
+ "Clarke 1880", -130, 29, 364 );
+
+$_datum{"Liberia 1964"}
+ = Datum->new( "Liberia 1964",
+ "Clarke 1880", -90, 40, 88 );
+
+$_datum{"Luzon (Philippines:Except Mindanao)"}
+ = Datum->new( "Luzon (Philippines:Except Mindanao)",
+ "Clarke 1866", -133, -77, -51 );
+
+$_datum{"Luzon (Philippines:Mindanao)"}
+ = Datum->new( "Luzon (Philippines:Mindanao)",
+ "Clarke 1866", -133, -79, -72 );
+
+$_datum{"M\'Poraloko"}
+ = Datum->new( "M\'Poraloko",
+ "Clarke 1880", -74, -130, 42 );
+
+$_datum{"Mahe 1971"}
+ = Datum->new( "Mahe 1971",
+ "Clarke 1880", 41, -220, -134 );
+
+$_datum{"Marco Astro"}
+ = Datum->new( "Marco Astro",
+ "International 1924", -289, -124, 60 );
+
+$_datum{"Massawa"}
+ = Datum->new( "Massawa",
+ "Bessel 1841", 639, 405, 60 );
+
+$_datum{"Merchich"}
+ = Datum->new( "Merchich",
+ "Clarke 1880", 31, 146, 47 );
+
+$_datum{"Midway Astro 1961"}
+ = Datum->new( "Midway Astro 1961",
+ "International 1924", 912, -58, 1227 );
+
+$_datum{"Minna (Cameroon)"}
+ = Datum->new( "Minna (Cameroon)",
+ "Clarke 1880", -81, -84, 115 );
+
+$_datum{"Minna (Nigeria)"}
+ = Datum->new( "Minna (Nigeria)",
+ "Clarke 1880", -92, -93, 122 );
+
+$_datum{"Montserrat Island Astro 1958"}
+ = Datum->new( "Montserrat Island Astro 1958",
+ "Clarke 1880", 174, 359, 365 );
+
+$_datum{"Nahrwan (Oman:Masirah Is)"}
+ = Datum->new( "Nahrwan (Oman:Masirah Is)",
+ "Clarke 1880", -247, -148, 369 );
+
+$_datum{"Nahrwan (Saudi Arabia)"}
+ = Datum->new( "Nahrwan (Saudi Arabia)",
+ "Clarke 1880", -243, -192, 477 );
+
+$_datum{"Nahrwan (United Arab Emirates)"}
+ = Datum->new( "Nahrwan (United Arab Emirates)",
+ "Clarke 1880", -249, -156, 381 );
+
+$_datum{"Naparima BWI"}
+ = Datum->new( "Naparima BWI",
+ "International 1924", -10, 375, 165 );
+
+$_datum{"NAD27 Alaska:Except Aleutian Is"}
+ = Datum->new( "NAD27 Alaska:Except Aleutian Is",
+ "Clarke 1866", -5, 135, 172 );
+
+$_datum{"NAD27 Alaska:Aleutian Is E of 180W"}
+ = Datum->new( "NAD27 Alaska:Aleutian Is E of 180W",
+ "Clarke 1866", -2, 152, 149 );
+
+$_datum{"NAD27 Alaska:Aleutian Is W of 180W"}
+ = Datum->new( "NAD27 Alaska:Aleutian Is W of 180W",
+ "Clarke 1866", 2, 204, 105 );
+
+$_datum{"NAD27 Bahamas:Except San Salvador Is"}
+ = Datum->new( "NAD27 Bahamas:Except San Salvador Is",
+ "Clarke 1866", -4, 154, 178 );
+
+$_datum{"NAD27 Bahamas:San Salvador Is"}
+ = Datum->new( "NAD27 Bahamas:San Salvador Is",
+ "Clarke 1866", 1, 140, 165 );
+
+$_datum{"NAD27 Canada (Alberta/B.C.)"}
+ = Datum->new( "NAD27 Canada (Alberta/B.C.)",
+ "Clarke 1866", -7, 162, 188 );
+
+$_datum{"NAD27 Canada (Manitoba/Ontario)"}
+ = Datum->new( "NAD27 Canada (Manitoba/Ontario)",
+ "Clarke 1866", -9, 157, 184 );
+
+$_datum{"NAD27 Canada MEAN"}
+ = Datum->new( "NAD27 Canada MEAN",
+ "Clarke 1866", -10, 158, 189 );
+
+$_datum{"NAD27 Canada (New Brunswick/Newfoundland/Nova Scotia/Quebec)"}
+ = Datum->new( "NAD27 Canada (New Brunswick/Newfoundland/Nova Scotia/Quebec)",
+ "Clarke 1866", -22, 160, 190 );
+
+$_datum{"NAD27 Canada (Northwest Territories/Saskatchewan)"}
+ = Datum->new( "NAD27 Canada (Northwest Territories/Saskatchewan)",
+ "Clarke 1866", 4, 159, 188 );
+
+$_datum{"NAD27 Canada (Yukon)"}
+ = Datum->new( "NAD27 Canada (Yukon)",
+ "Clarke 1866", -7, 139, 181 );
+
+$_datum{"NAD27 Canal Zone"}
+ = Datum->new( "NAD27 Canal Zone",
+ "Clarke 1866", 0, 125, 201 );
+
+$_datum{"NAD27 Caribbean"}
+ = Datum->new( "NAD27 Caribbean",
+ "Clarke 1866", -7, 152, 178 );
+
+$_datum{"NAD27 MEAN:Antigua/Barbados/Barbuda/Caicos Islands/Cuba/Dominican Republic/Grand Cayman/Jamaica/Turks Islands"}
+ = Datum->new( "NAD27 MEAN:Antigua/Barbados/Barbuda/Caicos Islands/Cuba/Dominican Republic/Grand Cayman/Jamaica/Turks Islands",
+ "Clarke 1866", -3, 142, 183 );
+
+$_datum{"NAD27 MEAN:Belize/Costa Rica/El Salvador/Guatemala/Honduras/Nicaragua"}
+ = Datum->new( "NAD27 MEAN:Belize/Costa Rica/El Salvador/Guatemala/Honduras/Nicaragua",
+ "Clarke 1866", 0, 125, 194 );
+
+$_datum{"NAD27 CONUS MEAN"}
+ = Datum->new( "NAD27 CONUS MEAN",
+ "Clarke 1866", -8, 160, 176 );
+
+ # Added for compatibility reasons. Same as above.
+$_datum{"NAD27 CONUS"}
+ = Datum->new( "NAD27 CONUS",
+ "Clarke 1866", -8, 160, 176 );
+
+$_datum{"NAD27 CONUS MEAN:E of Mississippi/Louisiana/Missouri/Minnesota"}
+ = Datum->new( "NAD27 CONUS MEAN:E of Mississippi/Louisiana/Missouri/Minnesota",
+ "Clarke 1866", -9, 161, 179 );
+
+$_datum{"NAD27 CONUS MEAN:W of Mississippi/Except Louisiana/Minnesota/Missouri"}
+ = Datum->new( "NAD27 CONUS W of Mississippi/Except Louisiana/Minnesota/Missouri",
+ "Clarke 1866", -8, 159, 175 );
+
+$_datum{"NAD27 Cuba"}
+ = Datum->new( "NAD27 Cuba",
+ "Clarke 1866", -9, 152, 178 );
+
+$_datum{"NAD27 Greenland (Hayes Peninsula)"}
+ = Datum->new( "NAD27 Greenland (Hayes Peninsula)",
+ "Clarke 1866", 11, 114, 195 );
+
+$_datum{"NAD27 Mexico"}
+ = Datum->new( "NAD27 Mexico",
+ "Clarke 1866", -12, 130, 190 );
+
+$_datum{"NAD27 San Salvador"}
+ = Datum->new( "NAD27 San Salvador",
+ "Clarke 1866", 1, 140, 165 );
+
+$_datum{"NAD83 Alaska (Except Aleutian Is)"}
+ = Datum->new( "NAD83 Alaska (Except Aleutian Is)",
+ "GRS 1980", 0, 0, 0 );
+
+$_datum{"NAD83 Aleutian Is"}
+ = Datum->new( "NAD83 Aleutian Is",
+ "GRS 1980", -2, 0, 4 );
+
+$_datum{"NAD83 Canada"}
+ = Datum->new( "NAD83 Canada",
+ "GRS 1980", 0, 0, 0 );
+
+$_datum{"NAD83 CONUS"}
+ = Datum->new( "NAD83 CONUS",
+ "GRS 1980", 0, 0, 0 );
+
+$_datum{"NAD83 Hawaii"}
+ = Datum->new( "NAD83 Hawaii",
+ "GRS 1980", 1, 1, -1 );
+
+$_datum{"NAD83 Mexico/Central America"}
+ = Datum->new( "NAD83 Mexico/Central America",
+ "GRS 1980", 0, 0, 0 );
+
+$_datum{"North Sahara"}
+ = Datum->new( "North Sahara",
+ "Clarke 1880", -186, -93, 310 );
+
+$_datum{"Nahrwn Masirah Ilnd"}
+ = Datum->new( "Nahrwn Masirah Ilnd",
+ "Clarke 1880", -247, -148, 369 );
+
+$_datum{"Nahrwn Saudi Arbia"}
+ = Datum->new( "Nahrwn Saudi Arbia",
+ "Clarke 1880", -231, -196, 482 );
+
+$_datum{"Nahrwn United Arab"}
+ = Datum->new( "Nahrwn United Arab",
+ "Clarke 1880", -249, -156, 381 );
+
+$_datum{"Naparima BWI"}
+ = Datum->new( "Naparima BWI",
+ "International 1924", -2, 374, 172 );
+
+$_datum{"Observatorio Meteorologico 1939"}
+ = Datum->new( "Observatorio Meteorologico 1939",
+ "International 1924", -425, -169, 81 );
+
+$_datum{"Old Egyptian 1907"}
+ = Datum->new( "Old Egyptian 1907",
+ "Helmert 1906", -130, 110, -13 );
+
+$_datum{"Old Hawaiian Hawaii"}
+ = Datum->new( "Old Hawaiian Hawaii",
+ "Clarke 1866", 89, -279, -183 );
+
+$_datum{"Old Hawaiian Kauai"}
+ = Datum->new( "Old Hawaiian Kauai",
+ "Clarke 1866", 45, -290, -172 );
+
+$_datum{"Old Hawaiian Maui"}
+ = Datum->new( "Old Hawaiian Maui",
+ "Clarke 1866", 65, -290, -190 );
+
+$_datum{"Old Hawaiian MEAN"}
+ = Datum->new( "Old Hawaiian MEAN",
+ "Clarke 1866", 61, -285, -181 );
+
+$_datum{"Old Hawaiian Oahu"}
+ = Datum->new( "Old Hawaiian Oahu",
+ "Clarke 1866", 58, -283, -182 );
+
+$_datum{"Oman"}
+ = Datum->new( "Oman",
+ "Clarke 1880", -346, -1, 224 );
+
+$_datum{"Ordnance Survey Great Britain 1936 England"}
+ = Datum->new( "Ordnance Survey Great Britain 1936 England",
+ "Airy 1830", 371, -112, 434 );
+
+$_datum{"Ordnance Survey Great Britain 1936 England/Isle of Man/Wales"}
+ = Datum->new( "Ordnance Survey Great Britain 1936 England/Isle of Man/Wales",
+ "Airy 1830", 371, -111, 434 );
+
+$_datum{"Ordnance Survey Great Britain 1936 MEAN:England/Isle of Man/Scotland/Shetland Is/Wales"}
+ = Datum->new( "Ordnance Survey Great Britain 1936 MEAN:England/Isle of Man/Scotland/Shetland Is/Wales",
+ "Airy 1830", 375, -111, 431 );
+
+$_datum{"Ordnance Survey Great Britain 1936 Scotland/Shetland Is"}
+ = Datum->new( "Ordnance Survey Great Britain 1936 Scotland/Shetland Is",
+ "Airy 1830", 384, -111, 425 );
+
+$_datum{"Ordnance Survey Great Britain 1936 Wales"}
+ = Datum->new( "Ordnance Survey Great Britain 1936 Wales",
+ "Airy 1830", 370, -108, 434 );
+
+$_datum{"Pico De Las Nieves"}
+ = Datum->new( "Pico De Las Nieves",
+ "International 1924", -307, -92, 127 );
+
+$_datum{"Pitcairn Astro 1967"}
+ = Datum->new( "Pitcairn Astro 1967",
+ "International 1924", 185, 165, 42 );
+
+$_datum{"Point 58"}
+ = Datum->new( "Point 58",
+ "Clarke 1880", -106, -129, 165 );
+
+$_datum{"Pointe Noire 1948"}
+ = Datum->new( "Pointe Noire 1948",
+ "Clarke 1880", -148, 51, -291 );
+
+$_datum{"Porto Santo 1936"}
+ = Datum->new( "Porto Santo 1936",
+ "International 1924", -499, -249, 314 );
+
+$_datum{"Provisional South American 1956 Bolivia"}
+ = Datum->new( "Provisional South American 1956 Bolivia",
+ "International 1924", -270, 188, -388 );
+
+$_datum{"Provisional South American 1956 Chile Northern/Near 19S"}
+ = Datum->new( "Provisional South American 1956 Chile Northern/Near 19S",
+ "International 1924", -270, 183, -390 );
+
+$_datum{"Provisional South American 1956 Chile Southern/Near 43S"}
+ = Datum->new( "Provisional South American 1956 Chile Southern/Near 43S",
+ "International 1924", -305, 243, -442 );
+
+$_datum{"Provisional South American 1956 Columbia"}
+ = Datum->new( "Provisional South American 1956 Columbia",
+ "International 1924", -282, 169, -371 );
+
+$_datum{"Provisional South American 1956 Ecuador"}
+ = Datum->new( "Provisional South American 1956 Ecuador",
+ "International 1924", -278, 171, -367 );
+
+$_datum{"Provisional South American 1956 Guyana"}
+ = Datum->new( "Provisional South American 1956 Guyana",
+ "International 1924", -298, 159, -369 );
+
+$_datum{"Provisional South American 1956 MEAN:Bolivia/Chile/Columbia/Ecuador/Guyana/Peru/Venezuela"}
+ = Datum->new( "Provisional South American 1956 MEAN:Bolivia/Chile/Columbia/Ecuador/Guyana/Peru/Venezuela",
+ "International 1924", -288, 175, -376 );
+
+$_datum{"Provisional South American 1956 Peru"}
+ = Datum->new( "Provisional South American 1956 Peru",
+ "International 1924", -279, 175, -379 );
+
+$_datum{"Provisional South American 1956 Venezuela"}
+ = Datum->new( "Provisional South American 1956 Venezuela",
+ "International 1924", -295, 173, -371 );
+
+$_datum{"Provisional South Chilean 1963 Near 53S"}
+ = Datum->new( "Provisional South Chilean 1963 Near 53S",
+ "International 1924", 16, 196, 93 );
+
+$_datum{"Puerto Rico/Virgin Is"}
+ = Datum->new( "Puerto Rico/Virgin Is",
+ "Clarke 1866", 11, 72, -101 );
+
+$_datum{"Pulkovo 1942"}
+ = Datum->new( "Pulkovo 1942",
+ "Krassovsky 1940", 28, -130, -95 );
+
+$_datum{"Qatar National"}
+ = Datum->new( "Qatar National",
+ "International 1924", -128, -283, 22 );
+
+$_datum{"Qornoq"}
+ = Datum->new( "Qornoq",
+ "International 1924", 164, 138, -189 );
+
+$_datum{"Reunion"}
+ = Datum->new( "Reunion",
+ "International 1924", 94, -948, -1262 );
+
+$_datum{"Rome 1940"}
+ = Datum->new( "Rome 1940",
+ "International 1924", -225, -65, 9 );
+
+$_datum{"RT 90"}
+ = Datum->new( "RT 90",
+ "Bessel 1841", 498, -36, 568 );
+
+$_datum{"S-42 (Pulkovo 1942) Hungary"}
+ = Datum->new( "S-42 (Pulkovo 1942) Hungary",
+ "Krassovsky 1940", 28, -121, -77 );
+
+$_datum{"S-42 (Pulkovo 1942) Poland"}
+ = Datum->new( "S-42 (Pulkovo 1942) Poland",
+ "Krassovsky 1940", 23, -124, -82 );
+
+$_datum{"S-42 (Pulkovo 1942) Czechoslavakia"}
+ = Datum->new( "S-42 (Pulkovo 1942) Czechoslavakia",
+ "Krassovsky 1940", 26, -121, -78 );
+
+$_datum{"S-42 (Pulkovo 1942) Latvia"}
+ = Datum->new( "S-42 (Pulkovo 1942) Latvia",
+ "Krassovsky 1940", 24, -124, -82 );
+
+$_datum{"S-42 (Pulkovo 1942) Kazakhstan"}
+ = Datum->new( "S-42 (Pulkovo 1942) Kazakhstan",
+ "Krassovsky 1940", 15, -130, -84 );
+
+$_datum{"S-42 (Pulkovo 1942) Albania"}
+ = Datum->new( "S-42 (Pulkovo 1942) Albania",
+ "Krassovsky 1940", 24, -130, -92 );
+
+$_datum{"S-42 (Pulkovo 1942) Romania"}
+ = Datum->new( "S-42 (Pulkovo 1942) Romania",
+ "Krassovsky 1940", 28, -121, -77 );
+
+$_datum{"S-JTSK Czechoslavakia"}
+ = Datum->new( "S-JTSK Czechoslavakia",
+ "Bessel 1841", 589, 76, 480 );
+
+$_datum{"Santo (DOS) 1965"}
+ = Datum->new( "Santo (DOS) 1965",
+ "International 1924", 170, 42, 84 );
+
+$_datum{"Sao Braz"}
+ = Datum->new( "Sao Braz",
+ "International 1924", -203, 141, 53 );
+
+$_datum{"Sapper Hill 1943"}
+ = Datum->new( "Sapper Hill 1943",
+ "International 1924", -355, 21, 72 );
+
+$_datum{"Schwarzeck"}
+ = Datum->new( "Schwarzeck",
+ "Bessel 1841 (Namibia)", 616, 97, -251 );
+
+$_datum{"Selvagem Grande 1938"}
+ = Datum->new( "Selvagem Grande 1938",
+ "International 1924", -289, -124, 60 );
+
+$_datum{"Sierra Leone 1960"}
+ = Datum->new( "Sierra Leone 1960",
+ "Clarke 1880", -88, 4, 101 );
+
+$_datum{"South American 1969 Argentina"}
+ = Datum->new( "South American 1969 Argentina",
+ "South American 1969", -62, -1, -37 );
+
+$_datum{"South American 1969 Bolivia"}
+ = Datum->new( "South American 1969 Bolivia",
+ "South American 1969", -61, 2, -48 );
+
+$_datum{"South American 1969 Brazil"}
+ = Datum->new( "South American 1969 Brazil",
+ "South American 1969", -60, -2, -41 );
+
+$_datum{"South American 1969 Chile"}
+ = Datum->new( "South American 1969 Chile",
+ "South American 1969", -75, -1, -44 );
+
+$_datum{"South American 1969 Colombia"}
+ = Datum->new( "South American 1969 Colombia",
+ "South American 1969", -44, 6, -36 );
+
+$_datum{"South American 1969 Ecuador"}
+ = Datum->new( "South American 1969 Ecuador",
+ "South American 1969", -48, 3, -44 );
+
+$_datum{"South American 1969 Ecuador:Baltra/Galapagos"}
+ = Datum->new( "South American 1969 Ecuador:Baltra/Galapagos",
+ "South American 1969", -47, 26, -42 );
+
+$_datum{"South American 1969 Guyana"}
+ = Datum->new( "South American 1969 Guyana",
+ "South American 1969", -53, 3, -47 );
+
+$_datum{"South American 1969 MEAN"}
+ = Datum->new( "South American 1969 MEAN",
+ "South American 1969", -57, 1, -41 );
+
+$_datum{"South American 1969 Paraguay"}
+ = Datum->new( "South American 1969 Paraguay",
+ "South American 1969", -61, 2, -33 );
+
+$_datum{"South American 1969 Peru"}
+ = Datum->new( "South American 1969 Peru",
+ "South American 1969", -58, 0, -44 );
+
+$_datum{"South American 1969 Trinidad/Tobago"}
+ = Datum->new( "South American 1969 Trinidad/Tobago",
+ "South American 1969", -45, 12, -33 );
+
+$_datum{"South American 1969 Venezuela"}
+ = Datum->new( "South American 1969 Venezuela",
+ "South American 1969", -45, 8, -33 );
+
+$_datum{"South Asia"}
+ = Datum->new( "South Asia",
+ "Modified Fischer 1960", 7, -10, -26 );
+
+$_datum{"Southeast Base"}
+ = Datum->new( "Southeast Base",
+ "International 1924", -499, -249, 314 );
+
+$_datum{"Southwest Base"}
+ = Datum->new( "Southwest Base",
+ "International 1924", -104, 167, -38 );
+
+$_datum{"Tananarive Observatory 1925"}
+ = Datum->new( "Tananarive Observatory 1925",
+ "International 1924", -189, -242, -91 );
+
+$_datum{"Timbalai 1948"}
+ = Datum->new( "Timbalai 1948",
+ "Everest (Sabah Sarawak)", -679, 669, -48 );
+
+$_datum{"Tokyo Japan"}
+ = Datum->new( "Tokyo Japan",
+ "Bessel 1841", -148, 507, 685 );
+
+$_datum{"Tokyo MEAN"}
+ = Datum->new( "Tokyo MEAN",
+ "Bessel 1841", -148, 507, 685 );
+
+$_datum{"Tokyo Okinawa"}
+ = Datum->new( "Tokyo Okinawa",
+ "Bessel 1841", -158, 507, 676 );
+
+$_datum{"Tokyo South Korea"}
+ = Datum->new( "Tokyo South Korea",
+ "Bessel 1841", -147, 506, 687 );
+
+$_datum{"Tristan Astro 1968"}
+ = Datum->new( "Tristan Astro 1968",
+ "International 1924", -632, 438, -609 );
+
+$_datum{"Viti Levu 1916"}
+ = Datum->new( "Viti Levu 1916",
+ "Clarke 1880", 51, 391, -36 );
+
+$_datum{"Voirol 1960"}
+ = Datum->new( "Voirol 1960",
+ "Clarke 1880", -123, -206, 219 );
+
+$_datum{"Wake Island Astro 1952"}
+ = Datum->new( "Wake Island Astro 1952",
+ "International 1924", 276, -57, 149 );
+
+$_datum{"Wake-Eniwetok 1960"}
+ = Datum->new( "Wake-Eniwetok 1960",
+ "Hough 1960", 102, 52, -38 );
+
+$_datum{"WGS 72"}
+ = Datum->new( "WGS 72",
+ "WGS 72", 0, 0, 0 );
+
+$_datum{"WGS 84"}
+ = Datum->new( "WGS 84",
+ "WGS 84", 0, 0, 0 );
+
+$_datum{"Yacare"}
+ = Datum->new( "Yacare",
+ "International 1924", -155, 171, 37 );
+
+$_datum{"Zanderij"}
+ = Datum->new( "Zanderij",
+ "International 1924", -265, 120, -358 );
+
+
+#------------------------------------------------------------------------------------------------
+
+
+package Coordinate;
+
+
+#
+# Note that we export NOTHING! This module strives to be object-oriented,
+# therefore exporting is a bad thing. You can get to any of the public
+# methods by using normal method calls on an object.
+#
+
+
+$VERSION = do { my @r=(q$Revision: 1.6 $=~/\d+/g); sprintf "%d."."%02d"x$#r, at r };
+
+
+use Math::Trig;
+#use Math::BigFloat; # Allows arbitrary length floating point operations
+#use strict;
+
+
+
+
+
+#
+# Here is a Coordinate object. It contains all of the data
+# for describing a single point on the earth and the methods
+# for setting/getting these values.
+#
+
+#
+# This constructor can be used to create and initialize an object
+# with Latitude/Longitude/Datum fields.
+#
+sub new
+{
+ my $class = shift; # What class are we constructing?
+ my $self = { }; # Allocate new memory
+ bless $self, $class; # Mark it of the right type
+ $self->_init(@_); # Call _init with remaining args
+ return $self;
+}
+
+
+sub _init
+{
+ my $self = shift;
+ $self->{LATITUDE} = shift if @_;
+ $self->{LONGITUDE} = shift if @_;
+ $self->{DATUM} = shift if @_;
+}
+
+
+#
+# This constructor can be used to create and initialize an object
+# with easting/northing/zone/datum fields (UTM grid).
+#
+sub new_utm
+{
+ my $class = shift; # What class are we constructing?
+ my $self = { }; # Allocate new memory
+ bless $self, $class; # Mark it of the right type
+ $self->_init_utm(@_); # Call _init with remaining args
+ return $self;
+}
+
+
+sub _init_utm
+{
+ my $self = shift;
+ $self->{EASTING} = shift if @_;
+ $self->{NORTHING} = shift if @_;
+ $self->{ZONE} = shift if @_;
+ $self->{DATUM} = shift if @_;
+}
+
+
+#
+# Returns the version number (RCS version tag) of this module.
+#
+sub version
+{
+ return $VERSION;
+}
+
+
+
+sub latitude
+{
+ my $self = shift;
+ $self->{LATITUDE} = shift if @_;
+ return $self->{LATITUDE};
+}
+
+
+
+
+
+sub longitude
+{
+ my $self = shift;
+ $self->{LONGITUDE} = shift if @_;
+ return $self->{LONGITUDE};
+}
+
+
+
+
+
+sub formatted_latitude
+{
+ my $self = shift;
+ $self->{FORMATTED_LATITUDE} = shift if @_;
+ return $self->{FORMATTED_LATITUDE};
+}
+
+
+
+
+
+sub formatted_longitude
+{
+ my $self = shift;
+ $self->{FORMATTED_LONGITUDE} = shift if @_;
+ return $self->{FORMATTED_LONGITUDE};
+}
+
+
+
+
+
+sub easting
+{
+ my $self = shift;
+ $self->{EASTING} = shift if @_;
+ return $self->{EASTING};
+}
+
+
+
+
+
+sub northing
+{
+ my $self = shift;
+ $self->{NORTHING} = shift if @_;
+ return $self->{NORTHING};
+}
+
+
+
+
+
+sub zone
+{
+ my $self = shift;
+ $self->{ZONE} = shift if @_;
+ return $self->{ZONE};
+}
+
+
+
+
+
+sub datum
+{
+ my $self = shift;
+ $self->{DATUM} = shift if @_;
+ return $self->{DATUM};
+}
+
+
+
+
+
+#
+# Converts lat/lon to UTM coordinates. Equations from USGS Bulletin 1532
+# (According to comments in the original C code).
+#
+# East Longitudes are positive, West are negative.
+# North latitudes are positive, South are negative.
+# Latitude and longitude are in decimal degrees.
+#
+# This method fills in the Easting/Northing/Zone fields in the object.
+# The Zone field will look something like: "10U" when filled in.
+#
+sub lat_lon_to_utm
+{
+ my $position = shift; # Snag the pointer to the object.
+
+ my $PI = 3.14159265358979323846;
+ my $deg_2_rad = $PI / 180;
+ my $k0 = 0.9996;
+
+ # First get the datum used in the position from the object:
+ my $datum = $position->datum();
+
+ # Now find out the ellipsoid used by consulting the DatumTable:
+ my $ellipsoid = DatumTable->ellipsoid( $datum );
+
+ # Do a lookup in the $ellipsoid{} hash to find the Radius value.
+ my $a = EllipsoidTable->equatorial_radius( $ellipsoid );
+
+ # Do a lookup in the $ellipsoid{} hash to find the Ecc value.
+ my $ecc_Squared = EllipsoidTable->first_ecc_squared( $ellipsoid );
+
+ my $Lat = $position->latitude();
+ my $Long = $position->longitude();
+
+ # Make sure the longitude is between -180.00 .. 179.9
+ my $Long_Temp = ($Long+180)-int(($Long+180)/360)*360-180; # -180.00 .. 179.9;
+
+ my $Lat_Rad = $Lat * $deg_2_rad;
+ my $Long_Rad = $Long_Temp * $deg_2_rad;
+ my $Zone_Number = int(($Long_Temp + 180)/6) + 1;
+
+ if( $Lat >= 56.0 && $Lat < 64.0 && $Long_Temp >= 3.0 && $Long_Temp < 12.0 )
+ {
+ $Zone_Number = 32;
+ }
+
+ # Special zones for Svalbard
+ if( $Lat >= 72.0 && $Lat < 84.0 )
+ {
+ if( $Long_Temp >= 0.0 && $Long_Temp < 9.0 ) { $Zone_Number = 31 }
+ elsif( $Long_Temp >= 9.0 && $Long_Temp < 21.0 ) { $Zone_Number = 33 }
+ elsif( $Long_Temp >= 21.0 && $Long_Temp < 33.0 ) { $Zone_Number = 35 }
+ elsif( $Long_Temp >= 33.0 && $Long_Temp < 42.0 ) { $Zone_Number = 37 };
+ }
+ my $Long_Origin = ($Zone_Number - 1)*6 - 180 + 3; # +3 puts origin in middle of zone
+ my $Long_Origin_Rad = $Long_Origin * $deg_2_rad;
+
+ # Compute the UTM Zone from the latitude and longitude
+ # NOTE: Need to check for out-of-range here.
+ #
+ my $Zone_Letter = &_utm_letter_designator($Lat);
+ #printf( "Zone_Number: %d\t\tZone_Letter: %s\n", $Zone_Number, $Zone_Letter );
+ my $UTM_Zone = sprintf( "%d%s", $Zone_Number, $Zone_Letter );
+
+ my $ecc_Prime_Squared = ($ecc_Squared)/(1-$ecc_Squared);
+
+ my $N = $a/sqrt(1-$ecc_Squared*sin($Lat_Rad)*sin($Lat_Rad));
+ my $T = tan($Lat_Rad) * tan($Lat_Rad);
+ my $C = $ecc_Prime_Squared * cos($Lat_Rad) * cos($Lat_Rad);
+ my $A = cos($Lat_Rad) * ($Long_Rad-$Long_Origin_Rad);
+
+ my $M = $a * ((1 - $ecc_Squared/4 - 3 * $ecc_Squared * $ecc_Squared/64 - 5 * $ecc_Squared * $ecc_Squared * $ecc_Squared/256) * $Lat_Rad
+ - (3 * $ecc_Squared/8 + 3 * $ecc_Squared * $ecc_Squared/32 + 45 * $ecc_Squared * $ecc_Squared * $ecc_Squared/1024) * sin(2 * $Lat_Rad)
+ + (15 * $ecc_Squared * $ecc_Squared/256 + 45 * $ecc_Squared * $ecc_Squared * $ecc_Squared/1024) * sin(4 * $Lat_Rad)
+ - (35 * $ecc_Squared * $ecc_Squared * $ecc_Squared/3072) * sin(6 * $Lat_Rad));
+
+ my $UTM_Easting = ($k0 * $N * ($A + (1 - $T + $C) * $A * $A * $A/6
+ + (5 - 18 * $T + $T * $T + 72 * $C - 58 * $ecc_Prime_Squared) * $A * $A * $A * $A * $A/120)
+ + 500000.0);
+
+ my $UTM_Northing = ($k0 * ($M + $N * tan($Lat_Rad) * ($A * $A/2 + (5 - $T + 9 * $C + 4 * $C * $C) * $A * $A * $A * $A/24
+ + (61 - 58 * $T + $T * $T + 600 * $C - 330 * $ecc_Prime_Squared) * $A * $A * $A * $A * $A * $A/720)));
+
+ if($Lat < 0)
+ {
+ $UTM_Northing += 10000000.0; # 10000000 meter offset for southern hemisphere
+ }
+
+ # Write the results back to our position object
+ $position->easting( $UTM_Easting );
+ $position->northing( $UTM_Northing );
+ $position->zone( $UTM_Zone );
+ return(1);
+}
+
+
+
+
+
+#
+# This routine determines the correct UTM letter designator for the given latitude.
+# Returns 'Z' if latitude is outside the UTM limits of 84N to 80S.
+#
+# Note that this is a normal subroutine, not an object method. It is to
+# be used inside this module only and is not exported.
+#
+sub _utm_letter_designator
+{
+ my $Lat = shift;
+ my $Letter_Designator;
+
+ if (( 84 >= $Lat) && ($Lat >= 72)) { $Letter_Designator = 'X' }
+ elsif (( 72 > $Lat) && ($Lat >= 64)) { $Letter_Designator = 'W' }
+ elsif (( 64 > $Lat) && ($Lat >= 56)) { $Letter_Designator = 'V' }
+ elsif (( 56 > $Lat) && ($Lat >= 48)) { $Letter_Designator = 'U' }
+ elsif (( 48 > $Lat) && ($Lat >= 40)) { $Letter_Designator = 'T' }
+ elsif (( 40 > $Lat) && ($Lat >= 32)) { $Letter_Designator = 'S' }
+ elsif (( 32 > $Lat) && ($Lat >= 24)) { $Letter_Designator = 'R' }
+ elsif (( 24 > $Lat) && ($Lat >= 16)) { $Letter_Designator = 'Q' }
+ elsif (( 16 > $Lat) && ($Lat >= 8)) { $Letter_Designator = 'P' }
+ elsif (( 8 > $Lat) && ($Lat >= 0)) { $Letter_Designator = 'N' }
+ elsif (( 0 > $Lat) && ($Lat >= -8)) { $Letter_Designator = 'M' }
+ elsif (( -8 > $Lat) && ($Lat >= -16)) { $Letter_Designator = 'L' }
+ elsif ((-16 > $Lat) && ($Lat >= -24)) { $Letter_Designator = 'K' }
+ elsif ((-24 > $Lat) && ($Lat >= -32)) { $Letter_Designator = 'J' }
+ elsif ((-32 > $Lat) && ($Lat >= -40)) { $Letter_Designator = 'H' }
+ elsif ((-40 > $Lat) && ($Lat >= -48)) { $Letter_Designator = 'G' }
+ elsif ((-48 > $Lat) && ($Lat >= -56)) { $Letter_Designator = 'F' }
+ elsif ((-56 > $Lat) && ($Lat >= -64)) { $Letter_Designator = 'E' }
+ elsif ((-64 > $Lat) && ($Lat >= -72)) { $Letter_Designator = 'D' }
+ elsif ((-72 > $Lat) && ($Lat >= -80)) { $Letter_Designator = 'C' }
+ else { $Letter_Designator = 'Z' }; # An error flag: Latitude is outside UTM limits
+
+ return $Letter_Designator;
+}
+
+
+
+
+
+#
+# Converts UTM coordinates to lat/lon. Equations from USGS Bulletin 1532.
+# East longitudes are positive, West are negative.
+# North latitudes are positive, South are negative.
+# Latitude and longitude are in decimal degrees.
+# Zone should look something like: "10U" before starting the conversion.
+#
+sub utm_to_lat_lon
+{
+ my $position = shift; # Input is in the form of a "Coordinate" object
+
+ my $PI = 3.14159265358979323846;
+ my $rad_2_deg = 180.0 / $PI;
+ my $k0 = 0.9996;
+
+ # First get the datum used in the position from the object:
+ my $datum = $position->datum();
+
+ # Now find out the ellipsoid used by consulting the DatumTable:
+ my $ellipsoid = DatumTable->ellipsoid( $datum );
+
+ # Do a lookup in the $ellipsoid{} hash to find the Radius value.
+ my $a = EllipsoidTable->equatorial_radius( $ellipsoid );
+
+ # Do a lookup in the $ellipsoid{} hash to find the Ecc value.
+ my $ecc_Squared = EllipsoidTable->first_ecc_squared( $ellipsoid );
+
+ my $x = $position->easting();
+ my $y = $position->northing();
+ my $Zone_Letter = $position->zone();
+ my $Zone_Number = $Zone_Letter;
+ $Zone_Number =~ s/(\d+).*/$1/; # Convert to an integer
+
+ my $e1 = (1-sqrt(1-$ecc_Squared))/(1+sqrt(1-$ecc_Squared));
+
+ $Zone_Letter =~ s/\d+(\w)/$1/; # Convert UTM zone to just a letter
+ #print "$Zone_Letter\n\n";
+
+ my $Northern_Hemisphere; # 1 for northern hemisphere, 0 for southern
+
+ $x = $x - 500000.0; # Remove 500,000 meter offset for longitude
+ $y = $y;
+
+ if(($Zone_Letter ge 'N'))
+ {
+ $Northern_Hemisphere = 1; # 'N' or higher is in the northern hemisphere
+ #print "Northern Hemisphere\n";
+ }
+ else
+ {
+ $Northern_Hemisphere = 0; # Point is in southern hemisphere
+ $y -= 10000000.0; # Remove 10,000,000 meter offset used for southern hemisphere
+ #print "Southern Hemisphere\n";
+ }
+
+ #print "Zone_Number: $Zone_Number\n";
+ my $Long_Origin = ($Zone_Number - 1) * 6 - 180 + 3; # +3 puts origin in middle of zone
+
+ my $ecc_Prime_Squared = ($ecc_Squared)/(1 - $ecc_Squared);
+
+ my $M = $y / $k0;
+ my $mu = $M/($a * (1 - $ecc_Squared/4 - 3 * $ecc_Squared * $ecc_Squared/64 - 5 * $ecc_Squared * $ecc_Squared * $ecc_Squared/256));
+
+ my $phi1_Rad = $mu + (3 * $e1/2 - 27 * $e1 * $e1 * $e1/32) * sin(2 * $mu)
+ + (21 * $e1 * $e1/16 - 55 * $e1 * $e1 * $e1 * $e1/32) * sin(4 * $mu)
+ +(151 * $e1 * $e1 * $e1/96) * sin(6 * $mu);
+
+ my $phi1 = $phi1_Rad * $rad_2_deg;
+
+ my $N1 = $a/sqrt(1 - $ecc_Squared * sin($phi1_Rad) * sin($phi1_Rad));
+ my $T1 = tan($phi1_Rad) * tan($phi1_Rad);
+ my $C1 = $ecc_Prime_Squared * cos($phi1_Rad) * cos($phi1_Rad);
+
+ my $R1 = $a * (1 - $ecc_Squared)/(1 - $ecc_Squared * sin($phi1_Rad) * sin($phi1_Rad)**1.5);
+
+ my $D = $x/($N1 * $k0);
+
+ $Lat = $phi1_Rad - ($N1 * tan($phi1_Rad)/$R1) * ($D * $D/2 - (5 + 3 * $T1 + 10 * $C1 - 4 * $C1 * $C1 - 9 * $ecc_Prime_Squared) * $D * $D * $D * $D/24
+ +(61 + 90 * $T1 + 298 * $C1 + 45 * $T1 * $T1 - 252 * $ecc_Prime_Squared - 3 * $C1 * $C1) * $D * $D * $D * $D * $D * $D/720);
+
+ $Lat = $Lat * $rad_2_deg;
+
+ $Long = ($D - (1 + 2 * $T1 + $C1) * $D * $D * $D/6 + (5 - 2 * $C1 + 28 * $T1 - 3 * $C1 * $C1 + 8 * $ecc_Prime_Squared + 24 * $T1 * $T1)
+ *$D * $D * $D * $D * $D/120)/cos($phi1_Rad);
+
+ $Long = $Long_Origin + $Long * $rad_2_deg;
+
+ # Write the results back to our position object
+ $position->latitude( $Lat );
+ $position->longitude( $Long );
+
+ return(1);
+}
+
+
+
+
+
+#
+# Function to convert latitude and longitude in decimal degrees between WGS 84 and
+# another datum. The arguments to this function are a Coordinate object ($position)
+# and a direction flag ($from_WGS84). The Datum you're translating to/from is
+# stored in the Datum() field of the object (the other Datum is by default WGS 84).
+#
+sub _datum_shift
+{
+ my $position = shift; # This is our position object
+
+ my $from_WGS84 = shift; # If 1, then we're converting from WGS 84
+ # to the datum listed in the position object
+ # If 0, we're going the other way.
+
+ my $PI = 3.14159265358979323846;
+ my $rad_2_deg = 180.0 / $PI;
+ my $deg_2_rad = $PI / 180;
+
+ #printf("%s\n", $position->datum() );
+
+ my $datum = $position->datum(); # Snag the parameters from the position object
+ # (Get the "other" datum).
+
+ my $latitude = $position->latitude();
+ my $longitude = $position->longitude();
+
+ # Now find out the ellipsoid used by consulting the DatumTable:
+ my $ellipsoid = DatumTable->ellipsoid( $datum );
+
+ my $dx = DatumTable->dx($datum); # Grab the parameters for the "other" datum.
+ my $dy = DatumTable->dy($datum); # Offsets between "other" datum and WGS84
+ my $dz = DatumTable->dz($datum); # ellipsoid centers.
+
+ #print "$dx\t$dy\t$dz\n";
+
+
+ my $WGS_a = EllipsoidTable->equatorial_radius("WGS 84"); # WGS 84 semimajor axis
+ my $WGS_inv_f = EllipsoidTable->inverse_flattening("WGS 84"); # WGS 84 1/f
+
+ my $phi = $latitude * $deg_2_rad;
+ my $lambda = $longitude * $deg_2_rad;
+ my ($a0, $b0, $es0, $f0); # Reference ellipsoid of input data
+ my ($a1, $b1, $es1, $f1); # Reference ellipsoid of output data
+ my $psi; # geocentric latitude
+ my ($x, $y, $z); # 3D coordinates with respect to original datum
+ my $psi1; # transformed geocentric latitude
+
+ if ($datum eq "WGS 84") # do nothing if current datum is WGS 84
+ {
+ return(1);
+ }
+
+ if ($from_WGS84) # convert from WGS 84 to new datum
+ {
+ $a0 = $WGS_a; # WGS 84 semimajor axis
+ $f0 = 1.0 / $WGS_inv_f; # WGS 84 flattening
+ $a1 = EllipsoidTable->equatorial_radius($ellipsoid);
+ $f1 = 1.0 / EllipsoidTable->inverse_flattening($ellipsoid);
+ }
+ else # convert from old datum to WGS 84
+ {
+ $a0 = EllipsoidTable->equatorial_radius($ellipsoid); # semimajor axis
+ $f0 = 1.0 / EllipsoidTable->inverse_flattening($ellipsoid); # flattening
+ $a1 = $WGS_a; # WGS 84 semimajor axis
+ $f1 = 1 / $WGS_inv_f; # WGS 84 flattening
+ $dx = -$dx;
+ $dy = -$dy;
+ $dz = -$dz;
+ }
+
+ $b0 = $a0 * (1 - $f0); # semiminor axis for input datum
+ $es0 = 2 * $f0 - $f0*$f0; # eccentricity^2
+
+ $b1 = $a1 * (1 - $f1); # semiminor axis for output datum
+ $es1 = 2 * $f1 - $f1*$f1; # eccentricity^2
+
+ # Convert geodedic latitude to geocentric latitude, psi
+
+ if ($latitude == 0.0 || $latitude == 90.0 || $latitude == -90.0)
+ {
+ $psi = $phi;
+ }
+ else
+ {
+ $psi = atan((1 - $es0) * tan($phi));
+ }
+
+ # Calculate x and y axis coordinates with respect to the original ellipsoid
+
+ if ($longitude == 90.0 || $longitude == -90.0)
+ {
+ $x = 0.0;
+ $y = abs($a0 * $b0 / sqrt($b0*$b0 + $a0*$a0* ( tan($psi)**2.0) ) );
+ }
+ else
+ {
+ $x = abs(($a0 * $b0) /
+ sqrt( (1 + (tan($lambda)**2.0) ) * ($b0*$b0 + $a0*$a0 * (tan($psi)**2.0) ) ) );
+
+ $y = abs($x * tan($lambda));
+ }
+
+ if ($longitude < -90.0 || $longitude > 90.0)
+ {
+ $x = -$x;
+ }
+ if ($longitude < 0.0)
+ {
+ $y = -$y;
+ }
+
+ # Calculate z axis coordinate with respect to the original ellipsoid
+
+ if ($latitude == 90.0)
+ {
+ $z = $b0;
+ }
+ elsif ($latitude == -90.0)
+ {
+ $z = -$b0;
+ }
+ else
+ {
+ $z = tan($psi) * sqrt( ($a0*$a0 * $b0*$b0) / ($b0*$b0 + $a0*$a0 * (tan($psi)**2.0) ) );
+ }
+
+ # Calculate the geocentric latitude with respect to the new ellipsoid
+
+ $psi1 = atan(($z - $dz) / sqrt(($x - $dx)*($x - $dx) + ($y - $dy)*($y - $dy)));
+
+ # Convert to geocentric latitude and save return value
+
+ $latitude = atan(tan($psi1) / (1 - $es1)) * $rad_2_deg;
+
+ # Calculate the longitude with respect to the new ellipsoid
+
+ $longitude = atan(($y - $dy) / ($x - $dx)) * $rad_2_deg;
+
+ # Correct the resultant for negative x values
+
+ if ($x-$dx < 0.0)
+ {
+ if ($y-$dy > 0.0)
+ {
+ $longitude = 180.0 + $longitude;
+ }
+ else
+ {
+ $longitude = -180.0 + $longitude;
+ }
+ }
+
+ # Write the results back to our position object
+ $position->latitude($latitude);
+ $position->longitude($longitude);
+
+ if (! $from_WGS84) # If we're converting to WGS 84 datum
+ {
+ $position->datum( "WGS 84" ); # Change the datum to correspond to
+ # the new data in the object
+ }
+
+ #print "New one: $latitude, $longitude\n";
+
+ return(1);
+}
+
+
+
+
+
+#
+# Method to convert latitude and longitude in decimal degrees from another
+# datum to WGS 84. The only argument to this method is a Coordinate object
+# with the lat/lon/datum fields filled in.
+#
+# This method returns a NEW Coordinate object with lat/lon/datum fields
+# filled in and the other fields empty. The original object is not changed.
+#
+sub datum_shift_to_wgs84
+{
+ my $old_position = shift; # This is our original position object
+
+ my $to_WGS84 = 0;
+
+ # Create a new object and fill in a few fields
+ my $new_position = Coordinate->new( $old_position->latitude(),
+ $old_position->longitude(),
+ $old_position->datum() );
+
+ &_datum_shift( $new_position, $to_WGS84 );
+
+ return( $new_position ); # Return the datum-shifted object
+}
+
+
+
+
+
+#
+# Method to convert latitude and longitude in decimal degrees from WGS 84 to
+# another datum. The arguments to this method are a Coordinate object
+# with the lat/lon/datum fields filled in (the datum field must be "WGS 84"),
+# AND a datum (string) to shift to.
+#
+# This method returns a NEW Coordinate object with lat/lon/datum fields
+# filled in. The original object is not changed.
+#
+sub datum_shift_from_wgs84_to
+{
+ my $old_position = shift; # This is our original position object
+ my $new_datum = shift; # The datum we wish to shift to
+
+ my $from_WGS84 = 1;
+
+ # Create a new object and fill in a few fields
+ my $new_position = Coordinate->new( $old_position->latitude(),
+ $old_position->longitude(),
+ $new_datum );
+
+ &_datum_shift( $new_position, $from_WGS84 );
+
+ return( $new_position ); # Return the datum-shifted object
+}
+
+
+
+
+
+#
+# Degrees and Decimal Minutes
+#
+# Fills in the Formatted_latitude and Formatted_longitude variables
+# in the object.
+#
+sub degrees_minutes
+{
+ my $self = shift; # Get the object to work on
+
+ $temp = CoordinateFormat->new(); # Create temporary object
+
+ $temp->raw( $self->latitude() ); # Fill in with raw data
+ $self->formatted_latitude ( $temp->degrees_minutes() ); # Process it & fill in our finished string
+
+ $temp->raw( $self->longitude() ); # Fill in with raw data
+ $self->formatted_longitude( $temp->degrees_minutes() ); # process it & fill in our finished string
+
+ return(1);
+}
+
+
+
+
+
+#
+# Degrees/Minutes/Seconds
+#
+# Fills in the Formatted_latitude and Formatted_longitude variables
+# in the object.
+#
+sub degrees_minutes_seconds
+{
+ my $self = shift; # Get the object to work on
+
+ $temp = CoordinateFormat->new(); # Create the temporary object
+
+ $temp->raw( $self->latitude() ); # Fill in with raw data
+ $self->formatted_latitude ( $temp->degrees_minutes_seconds() ); # Process it & fill in our finished string
+
+ $temp->raw( $self->longitude() ); # Fill in with raw data
+ $self->formatted_longitude( $temp->degrees_minutes_seconds() ); # Process it & fill in our finished string
+
+ return(1);
+}
+
+
+
+
+
+#
+# Decimal Degrees
+#
+# Fills in the Formatted_latitude and Formatted_longitude variables
+# in the object.
+#
+sub decimal_degrees
+{
+ my $self = shift; # Get the object to work on
+
+ $temp = CoordinateFormat->new(); # Create the temporary object
+
+ $temp->raw( $self->latitude() ); # Fill in with raw data
+ $self->formatted_latitude ( $temp->decimal_degrees() ); # Process it & fill in our finished string
+
+ $temp->raw( $self->longitude() ); # Fill in with raw data
+ $self->formatted_longitude( $temp->decimal_degrees() ); # Process it & fill in our finished string
+
+ return(1);
+}
+
+
+#------------------------------------------------------------------------------------------------
+
+
+#
+# Auto-run code
+#
+# This code will get run automatically whenever this file gets "required"
+# or "used" in another Perl program.
+#
+
+
+1; # Needed to prevent exception when loading this module
+
+
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
new file mode 100644
index 0000000..948848c
--- /dev/null
+++ b/scripts/Makefile.am
@@ -0,0 +1,52 @@
+# $Id: Makefile.am,v 1.41 2012/11/27 04:41:23 tvrusso Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+
+scriptsdir=${pkgdatadir}/scripts
+dist_scripts_DATA = \
+ Coordinate.pm \
+ coord-convert.pl \
+ geopdf2gtiff.pl \
+ get-BOMdata \
+ get-fcc-rac.pl \
+ get-gnis \
+ get-pop \
+ get-maptools.sh \
+ get-NWSdata \
+ get_shapelib.sh \
+ gpx2shape \
+ icontable.pl \
+ inf2geo.pl \
+ kiss-off.pl \
+ langElmerFudd.pl \
+ langMuppetsChef.pl \
+ langOldeEnglish.pl \
+ langPigLatin.pl \
+ langPirateEnglish.pl \
+ mapblast2geo.pl \
+ mapfgd.pl \
+ object2shp.pl \
+ overlay.pl \
+ ozi2geo.pl \
+ permutations.pl \
+ pos2shp.pl \
+ ridge_radar.pl \
+ slideshow.pl \
+ split_gnis.bash \
+ split_gnis.pl \
+ test_coord.pl \
+ toporama50k.pl \
+ toporama250k.pl\
+ track-get.pl \
+ update_langfile.pl \
+ values \
+ values.pl \
+ waypoint-get.pl \
+ xastir-fixcfg.sh \
+ xastir-migrate.sh \
+ Xastir_tigerpoly.py
+
+install-data-hook:
+ cd $(DESTDIR)$(scriptsdir) && \
+ chmod a+x *.sh *.pl *.py get-* gpx2* *.bash
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
new file mode 100644
index 0000000..a00c7f4
--- /dev/null
+++ b/scripts/Makefile.in
@@ -0,0 +1,467 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+# $Id: Makefile.am,v 1.41 2012/11/27 04:41:23 tvrusso Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = scripts
+DIST_COMMON = $(dist_scripts_DATA) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/values.in \
+ $(srcdir)/values.pl.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = values values.pl
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(scriptsdir)"
+DATA = $(dist_scripts_DATA)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTSHP = @CONTSHP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GMAGIC_BIN = @GMAGIC_BIN@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBCOMPAT = @LIBCOMPAT@
+LIBOBJS = @LIBOBJS@
+LIBRTREE = @LIBRTREE@
+LIBS = @LIBS@
+LIBSHP = @LIBSHP@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LWPOSTGIS = @LWPOSTGIS@
+MAGIC_BIN = @MAGIC_BIN@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PG_CONFIG = @PG_CONFIG@
+POW_LIB = @POW_LIB@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUBRTREE = @SUBRTREE@
+SUBSHP = @SUBSHP@
+VERSION = @VERSION@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+convert = @convert@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+festival = @festival@
+found_gdal_config = @found_gdal_config@
+gm = @gm@
+gpsman = @gpsman@
+gv = @gv@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lpr = @lpr@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+mv = @mv@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sed = @sed@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+wget = @wget@
+xfontsel = @xfontsel@
+scriptsdir = ${pkgdatadir}/scripts
+dist_scripts_DATA = \
+ Coordinate.pm \
+ coord-convert.pl \
+ geopdf2gtiff.pl \
+ get-BOMdata \
+ get-fcc-rac.pl \
+ get-gnis \
+ get-pop \
+ get-maptools.sh \
+ get-NWSdata \
+ get_shapelib.sh \
+ gpx2shape \
+ icontable.pl \
+ inf2geo.pl \
+ kiss-off.pl \
+ langElmerFudd.pl \
+ langMuppetsChef.pl \
+ langOldeEnglish.pl \
+ langPigLatin.pl \
+ langPirateEnglish.pl \
+ mapblast2geo.pl \
+ mapfgd.pl \
+ object2shp.pl \
+ overlay.pl \
+ ozi2geo.pl \
+ permutations.pl \
+ pos2shp.pl \
+ ridge_radar.pl \
+ slideshow.pl \
+ split_gnis.bash \
+ split_gnis.pl \
+ test_coord.pl \
+ toporama50k.pl \
+ toporama250k.pl\
+ track-get.pl \
+ update_langfile.pl \
+ values \
+ values.pl \
+ waypoint-get.pl \
+ xastir-fixcfg.sh \
+ xastir-migrate.sh \
+ Xastir_tigerpoly.py
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu scripts/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu scripts/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+values: $(top_builddir)/config.status $(srcdir)/values.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+values.pl: $(top_builddir)/config.status $(srcdir)/values.pl.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-dist_scriptsDATA: $(dist_scripts_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(scriptsdir)" || $(MKDIR_P) "$(DESTDIR)$(scriptsdir)"
+ @list='$(dist_scripts_DATA)'; test -n "$(scriptsdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(scriptsdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(scriptsdir)" || exit $$?; \
+ done
+
+uninstall-dist_scriptsDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_scripts_DATA)'; test -n "$(scriptsdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(scriptsdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(scriptsdir)" && rm -f $$files
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(scriptsdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-dist_scriptsDATA
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-data-hook
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-dist_scriptsDATA
+
+.MAKE: install-am install-data-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic distclean \
+ distclean-generic distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am \
+ install-data-hook install-dist_scriptsDATA install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \
+ uninstall-dist_scriptsDATA
+
+
+install-data-hook:
+ cd $(DESTDIR)$(scriptsdir) && \
+ chmod a+x *.sh *.pl *.py get-* gpx2* *.bash
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/scripts/Xastir_tigerpoly.py b/scripts/Xastir_tigerpoly.py
new file mode 100755
index 0000000..65e713d
--- /dev/null
+++ b/scripts/Xastir_tigerpoly.py
@@ -0,0 +1,562 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: Xastir_tigerpoly.py,v 1.11 2012/11/01 18:57:19 we7u Exp $
+#
+# Portions Copyright (C) 2004-2012 The Xastir Group
+#
+# Modified version of GDAL/OGR "tigerpoly.py" script (as described below)
+# adapted to assemble information from more tables of the TIGER/Line data
+# than had been done by the original, and with the option of dissolving
+# common boundaries between areas with identical landmark values.
+#
+# You must have installed GDAL/OGR, configured to use python in order to use
+# this script
+###############################################################################
+#
+# Adapted for Xastir use by Tom Russo
+#
+# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
+# When run with the "-d" option, this script changes the topology of
+# TIGER/Line polygons by dissolving common bounaries between adjacent
+# polygons with identical Landmark values. This is done SOLELY for
+# improvement of on-screen presentation of the shapefiles, and the resulting
+# files have too much information removed to make them useful for any other
+# purpose but display in Xastir.
+#
+# If any shapefile data produced by this script with the -d option are
+# distributed publicly, they should have a prominent disclaimer to this
+# effect. The data produced by this script with that option bear only a
+# superficial, graphical resemblence to the TIGER/Line data from which they
+# were created.
+#
+####################Original comments follow
+###############################################################################
+# tigerpoly.py,v 1.3 2003/07/11 14:52:13 warmerda Exp
+#
+# Project: OGR Python samples
+# Purpose: Assemble TIGER Polygons.
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+###############################################################################
+
+
+import osr
+import ogr
+import string
+import sys
+
+#############################################################################
+class Module:
+
+ def __init__( self ):
+ self.lines = {}
+ self.poly_line_links = {}
+
+#############################################################################
+# I dunno, does this initializer make sense?
+class Field:
+ def __init__( self ):
+ self.layer = ''
+ self.layerName = ''
+ self.field_defn = ''
+ self.fld_index = ''
+
+#############################################################################
+# We'll use this class to keep track of polygons that get mapped into each
+# other
+class PolyMap:
+ def __init__( self ):
+ self.polyid=''
+ self.mappedlist=[]
+
+#############################################################################
+def Usage():
+ print 'Usage: tigerpoly.py [-d] infile [outfile].shp'
+ print
+ sys.exit(1)
+
+#############################################################################
+# Argument processing.
+
+infile = None
+outfile = None
+dissolve=0
+
+i = 1
+while i < len(sys.argv):
+ arg = sys.argv[i]
+
+ if arg == "-d":
+ dissolve=1
+
+ elif infile is None:
+ infile = arg
+
+ elif outfile is None:
+ outfile = arg
+
+ else:
+ Usage()
+
+ i = i + 1
+
+if outfile is None:
+ outfile = 'poly.shp'
+
+if infile is None:
+ Usage()
+
+if dissolve == 1:
+ print '*******************************************************************'
+ print 'WARNING! WARNING! WARNING!'
+ print 'You have chosen to dissolve polygons with identical landmark names/types.'
+ print ' Doing this changes the topology of the TIGER/Line data, and renders'
+ print ' the resulting shapefiles useful only for display purposes.'
+ print ' IF YOU DISTRIBUTE THIS DATA, PLEASE INCLUDE A DISCLAIMER THAT'
+ print ' THE DATA HAVE BEEN MODIFIED AND THAT THEIR USE FOR PURPOSES OTHER'
+ print ' DISPLAY IS NOT RECOMMENDED!'
+ print '*******************************************************************'
+
+#############################################################################
+# Open the datasource to operate on.
+
+ds = ogr.Open( infile, update = 0 )
+
+poly_layer = ds.GetLayerByName( 'Polygon' )
+pip_layer = ds.GetLayerByName( 'PIP' )
+areaLandmarks_layer = ds.GetLayerByName( 'AreaLandmarks' )
+Landmarks_layer = ds.GetLayerByName( 'Landmarks' )
+
+#############################################################################
+# Create output file for the composed polygons.
+
+shp_driver = ogr.GetDriverByName( 'ESRI Shapefile' )
+shp_driver.DeleteDataSource( outfile )
+
+shp_ds = shp_driver.CreateDataSource( outfile )
+
+shp_layer = shp_ds.CreateLayer( 'out', geom_type = ogr.wkbPolygon )
+
+# Now create a list of all the fields for the DBF file, using the unique
+# fields in Polygon, PIP, AreaLandmarks and Landmarks --- eliminate
+# all fields of identical names (because those are just the fields that
+# link the records to each other). When we do so, must store layer, field
+# index in the hash, and we'll write it back by
+
+# Create a hash of field definitions indexed by field name.
+fields_hash = {}
+field_names = []
+
+src_defn = poly_layer.GetLayerDefn()
+poly_field_count = src_defn.GetFieldCount()
+
+for fld_index in range(poly_field_count):
+ src_fd = src_defn.GetFieldDefn( fld_index )
+ fields_hash[src_fd.GetName()] = Field()
+ fields_hash[src_fd.GetName()].layer=poly_layer
+ fields_hash[src_fd.GetName()].layerName='Polygon'
+ fields_hash[src_fd.GetName()].field_defn=src_defn
+ fields_hash[src_fd.GetName()].fld_index=fld_index
+ field_names.append(src_fd.GetName())
+# print 'Got a Polygon field called %s' % src_fd.GetName()
+
+
+# now loop over other layers
+src_defn = pip_layer.GetLayerDefn()
+pip_field_count = src_defn.GetFieldCount()
+for fld_index in range(pip_field_count):
+ src_fd = src_defn.GetFieldDefn( fld_index )
+ try:
+ foo = fields_hash[src_fd.GetName()]
+# print ' found pip field %s already in hash' % src_fd.GetName()
+ except:
+ field=Field()
+ fields_hash[src_fd.GetName()] = field
+ fields_hash[src_fd.GetName()].layer=pip_layer
+ fields_hash[src_fd.GetName()].layerName='PIP'
+ fields_hash[src_fd.GetName()].field_defn=src_defn
+ fields_hash[src_fd.GetName()].fld_index=fld_index
+ field_names.append(src_fd.GetName())
+# print 'Got a pip field called %s' % src_fd.GetName()
+
+src_defn = areaLandmarks_layer.GetLayerDefn()
+areaLandmarks_field_count = src_defn.GetFieldCount()
+for fld_index in range(areaLandmarks_field_count):
+ src_fd = src_defn.GetFieldDefn( fld_index )
+ try:
+ foo = fields_hash[src_fd.GetName()]
+# print ' found areaLandmarks field %s already in hash' % src_fd.GetName()
+ except:
+ field=Field()
+ fields_hash[src_fd.GetName()] = field
+ fields_hash[src_fd.GetName()].layer=areaLandmarks_layer
+ fields_hash[src_fd.GetName()].layerName='AreaLandmarks'
+ fields_hash[src_fd.GetName()].field_defn=src_defn
+ fields_hash[src_fd.GetName()].fld_index=fld_index
+ field_names.append(src_fd.GetName())
+# print 'Got a areaLandmarks field called %s' % src_fd.GetName()
+src_defn = Landmarks_layer.GetLayerDefn()
+Landmarks_field_count = src_defn.GetFieldCount()
+for fld_index in range(Landmarks_field_count):
+ src_fd = src_defn.GetFieldDefn( fld_index )
+ try:
+ foo = fields_hash[src_fd.GetName()]
+# print ' found Landmarks field %s already in hash' % src_fd.GetName()
+ except:
+ field=Field()
+ fields_hash[src_fd.GetName()] = field
+ fields_hash[src_fd.GetName()].layer=Landmarks_layer
+ fields_hash[src_fd.GetName()].layerName='Landmarks'
+ fields_hash[src_fd.GetName()].field_defn=src_defn
+ fields_hash[src_fd.GetName()].fld_index=fld_index
+ field_names.append(src_fd.GetName())
+# print 'Got a Landmarks field called %s' % src_fd.GetName()
+
+# we now have a hash whose keys are all our field names, and from which
+# we *should* be able to retreive fields as needed
+#print ' we found %d fields' % len(fields_hash)
+#print ' the names array has %d names ' % len(field_names)
+#for field_name in (field_names):
+# print ' key %s we get field from %s ' % (field_name ,fields_hash[field_name].layerName)
+
+# Now loop over all those field names, create the dbf file definition
+
+for field_name in (field_names):
+ src_defn = fields_hash[field_name].field_defn
+ src_fd = src_defn.GetFieldDefn( fields_hash[field_name].fld_index )
+ fd = ogr.FieldDefn( src_fd.GetName(), src_fd.GetType() )
+ fd.SetWidth( src_fd.GetWidth() )
+ fd.SetPrecision( src_fd.GetPrecision() )
+ shp_layer.CreateField(fd)
+
+print 'Reading Lines'
+#############################################################################
+# Read all features in the line layer, holding just the geometry in a hash
+# for fast lookup by TLID.
+
+line_layer = ds.GetLayerByName( 'CompleteChain' )
+line_count = 0
+
+modules_hash = {}
+
+feat = line_layer.GetNextFeature()
+geom_id_field = feat.GetFieldIndex( 'TLID' )
+tile_ref_field = feat.GetFieldIndex( 'MODULE' )
+while feat is not None:
+ geom_id = feat.GetField( geom_id_field )
+ tile_ref = feat.GetField( tile_ref_field )
+
+ try:
+ module = modules_hash[tile_ref]
+ except:
+ module = Module()
+ modules_hash[tile_ref] = module
+
+ module.lines[geom_id] = feat.GetGeometryRef().Clone()
+ line_count = line_count + 1
+
+ feat.Destroy()
+
+ feat = line_layer.GetNextFeature()
+
+print 'Got %d lines in %d modules.' % (line_count,len(modules_hash))
+
+#############################################################################
+# Now we need to pull in all the PIP, AreaLandmarks and Landmarks features
+# and keep them in hashes based on POLYID
+
+#PIP:
+feat = pip_layer.GetNextFeature()
+polyid_field = feat.GetFieldIndex( 'POLYID' )
+pip_hash={}
+dest_polyid_hash={}
+
+while feat is not None:
+ poly_id = feat.GetField( polyid_field )
+ pip_hash[poly_id] = feat
+ # initially, every polygon is distinct, with no list of polys mapped into it
+ dest_polyid_hash[poly_id]=PolyMap()
+ dest_polyid_hash[poly_id].polyid=poly_id
+ feat = pip_layer.GetNextFeature()
+
+print 'Processed %d PIP records.' % len(pip_hash)
+
+#AreaLandmarks
+feat = areaLandmarks_layer.GetNextFeature()
+polyid_field = feat.GetFieldIndex( 'POLYID' )
+areaLandmarks_hash={}
+
+while feat is not None:
+ poly_id = feat.GetField( polyid_field )
+ areaLandmarks_hash[poly_id] = feat
+ feat = areaLandmarks_layer.GetNextFeature()
+print 'Processed %d AreaLandmarks records.' % len(areaLandmarks_hash)
+
+
+# Landmarks is not looked up by polyid, but by LAND, which links it to
+# Landmarks
+feat = Landmarks_layer.GetNextFeature()
+land_field = feat.GetFieldIndex( 'LAND' )
+Landmarks_hash={}
+
+while feat is not None:
+ land_id = feat.GetField( land_field )
+ Landmarks_hash[land_id] = feat
+ feat = Landmarks_layer.GetNextFeature()
+print 'Processed %d Landmarks records.' % len(Landmarks_hash)
+
+if dissolve == 1:
+ print 'Scanning PolyChains for polygons to dissolve.'
+ #############################################################################
+ #
+ # Now we sift through all the PolyChainLink records, find the ones that have
+ # distinct left and right polyids, but for which the associated landmark
+ # is identical. We will dissolve those polygons by mapping their polyids
+ link_layer = ds.GetLayerByName( 'PolyChainLink' )
+
+ feat = link_layer.GetNextFeature()
+ lpoly_field = feat.GetFieldIndex( 'POLYIDL' )
+ rpoly_field = feat.GetFieldIndex( 'POLYIDR' )
+
+ link_count=0
+ ndissolved=0
+
+ while feat is not None:
+ link_count = link_count+1
+
+ orig_lpoly_id=feat.GetField( lpoly_field )
+ orig_rpoly_id=feat.GetField( rpoly_field )
+ try:
+ lpoly_id = dest_polyid_hash[orig_lpoly_id].polyid
+ except:
+ lpoly_id = 0
+
+ try:
+ rpoly_id = dest_polyid_hash[orig_rpoly_id].polyid
+ except:
+ rpoly_id= 0
+
+ #if not already identical (either because already dissolved, or because
+ #internal
+ if lpoly_id != rpoly_id:
+ #find the left and right areaLandmark, if there are any
+ try:
+ left_areaLandmark=areaLandmarks_hash[lpoly_id]
+ l_landidx=left_areaLandmark.GetFieldIndex('LAND')
+ l_land=left_areaLandmark.GetField(l_landidx)
+ except:
+ left_areaLandmark=None
+
+ try:
+ right_areaLandmark=areaLandmarks_hash[rpoly_id]
+ r_landidx=right_areaLandmark.GetFieldIndex('LAND')
+ r_land=right_areaLandmark.GetField(r_landidx)
+ except:
+ right_areaLandmark=None
+
+ if left_areaLandmark is not None and right_areaLandmark is not None:
+ if l_land == r_land:
+ ndissolved = ndissolved+1
+ # we have two polys that need to be dissolved
+ # we will always do this by copying the left polygon's
+ # ID into the right base polygon and every polygon that was
+ # mapped to it, then adding the right polygon's
+ # ID and any IDs in its map list to the base polygon on the
+ # left.
+ dest_polyid_hash[rpoly_id].polyid=lpoly_id
+ for i in dest_polyid_hash[rpoly_id].mappedlist:
+ dest_polyid_hash[i].polyid=lpoly_id
+
+ dest_polyid_hash[lpoly_id].mappedlist.append(rpoly_id)
+ dest_polyid_hash[lpoly_id].mappedlist.extend(dest_polyid_hash[rpoly_id].mappedlist)
+ dest_polyid_hash[rpoly_id].mappedlist=[]
+
+ feat.Destroy()
+
+ feat = link_layer.GetNextFeature()
+
+ print 'Scanned %d links for polygon dissolve, dissolved %d boundaries.' % (link_count,ndissolved)
+
+
+
+#############################################################################
+# Read all polygon/chain links and build a hash keyed by POLY_ID listing
+# the chains (by TLID) attached to it.
+
+link_layer = ds.GetLayerByName( 'PolyChainLink' )
+link_layer.ResetReading()
+
+feat = link_layer.GetNextFeature()
+geom_id_field = feat.GetFieldIndex( 'TLID' )
+tile_ref_field = feat.GetFieldIndex( 'MODULE' )
+lpoly_field = feat.GetFieldIndex( 'POLYIDL' )
+rpoly_field = feat.GetFieldIndex( 'POLYIDR' )
+
+link_count = 0
+
+while feat is not None:
+ module = modules_hash[feat.GetField( tile_ref_field )]
+
+ tlid = feat.GetField( geom_id_field )
+
+ orig_lpoly_id=feat.GetField( lpoly_field )
+ orig_rpoly_id=feat.GetField( rpoly_field )
+ try:
+ lpoly_id = dest_polyid_hash[orig_lpoly_id].polyid
+ except:
+ lpoly_id = 0
+
+ try:
+ rpoly_id = dest_polyid_hash[orig_rpoly_id].polyid
+ except:
+ rpoly_id = 0
+
+ # sanity checking:
+ if lpoly_id != 0:
+ if lpoly_id != orig_lpoly_id and len(dest_polyid_hash[orig_lpoly_id].mappedlist) != 0:
+ print 'Arrgh --- found a left polygon mapped into another with a non-null list!'
+ sys.exit(1)
+
+ if rpoly_id != 0:
+ if rpoly_id != orig_rpoly_id and len(dest_polyid_hash[orig_rpoly_id].mappedlist) != 0:
+ print 'Arrgh --- found a right polygon mapped into another with a non-null list!'
+ sys.exit(1)
+
+ if lpoly_id != rpoly_id :
+ if lpoly_id != 0:
+ try:
+ module.poly_line_links[lpoly_id].append( tlid )
+ except:
+ module.poly_line_links[lpoly_id] = [ tlid ]
+
+ if rpoly_id != 0:
+ try:
+ module.poly_line_links[rpoly_id].append( tlid )
+ except:
+ module.poly_line_links[rpoly_id] = [ tlid ]
+
+ link_count = link_count + 1
+
+ feat.Destroy()
+
+ feat = link_layer.GetNextFeature()
+
+print 'Processed %d links.' % link_count
+
+
+# Boy, what a mess. But we now have all the data we need in hashes, so we
+# can loop over POLYGON records and extract data as we need it.
+# Do that now:
+#############################################################################
+# Process all polygon features.
+
+feat = poly_layer.GetNextFeature()
+tile_ref_field = feat.GetFieldIndex( 'MODULE' )
+polyid_field = feat.GetFieldIndex( 'POLYID' )
+
+poly_count = 0
+
+while feat is not None:
+ module = modules_hash[feat.GetField( tile_ref_field )]
+ orig_polyid = feat.GetField( polyid_field )
+
+ try:
+ polyid=dest_polyid_hash[orig_polyid].polyid
+ except:
+ polyid=0
+
+ # we must only do those polygons that have not been mapped to others, or
+ # we'll be doing them multiple times
+ if polyid != 0 and polyid == orig_polyid:
+ tlid_list = module.poly_line_links[polyid]
+
+ link_coll = ogr.Geometry( type = ogr.wkbGeometryCollection )
+ for tlid in tlid_list:
+ geom = module.lines[tlid]
+ link_coll.AddGeometry( geom )
+
+ try:
+ poly = ogr.BuildPolygonFromEdges( link_coll )
+
+ #print poly.ExportToWkt()
+ #feat.SetGeometryDirectly( poly )
+
+ feat2 = ogr.Feature(feature_def=shp_layer.GetLayerDefn())
+
+ for fld_index in range(len(field_names)):
+ theFieldName = field_names[fld_index]
+ layerName = fields_hash[theFieldName].layerName
+ theFieldIdx = fields_hash[theFieldName].fld_index
+# print 'fetching field %s from layer %s' % (theFieldName, layerName)
+ # if it's from Polygon just pop it in because we have it now:
+ if layerName == 'Polygon':
+ feat2.SetField( fld_index, feat.GetField(theFieldIdx) )
+ # If it's from PIP, we definitely have one
+ elif layerName == 'PIP':
+ feat2.SetField(fld_index, pip_hash[polyid].GetField(theFieldIdx))
+ # this could be a problem, coz there might not be one
+ elif layerName == 'AreaLandmarks':
+ try:
+ feat3 = areaLandmarks_hash[polyid]
+# print ' found feature with polyid %d in AreaLandmarks' % polyid
+ feat2.SetField(fld_index, feat3.GetField(theFieldIdx))
+ except:
+ feat2.UnsetField(fld_index)
+ # this one's mega tricky, coz it depends on there being
+ # an AreaLandmarks first
+ elif layerName == 'Landmarks':
+ try:
+ feat3 = areaLandmarks_hash[polyid]
+# print ' found feature with polyid %d in AreaLandmarks' % polyid
+ landidx1 = feat3.GetFieldIndex('LAND')
+# print ' LAND is field %d in AreaLandmarks' % landidx1
+# print ' LAND field in this record is %d.' % feat3.GetField(landidx1)
+ feat4 = Landmarks_hash[feat3.GetField(landidx1)]
+# print ' found feature with LAND %d in Landmarks' % feat3.GetField(landidx1)
+ feat2.SetField(fld_index, feat4.GetField(theFieldIdx))
+ except:
+ feat2.UnsetField(fld_index)
+ else:
+ print 'unknown layer %s referenced.' % layerName
+
+ feat2.SetGeometryDirectly( poly )
+
+ shp_layer.CreateFeature( feat2 )
+ feat2.Destroy()
+
+ poly_count = poly_count + 1
+ except:
+ print 'BuildPolygonFromEdges failed.'
+
+ feat.Destroy()
+
+ feat = poly_layer.GetNextFeature()
+
+print 'Built %d polygons.' % poly_count
+
+
+#############################################################################
+# Cleanup
+
+shp_ds.Destroy()
+ds.Destroy()
diff --git a/scripts/coord-convert.pl b/scripts/coord-convert.pl
new file mode 100755
index 0000000..b2df097
--- /dev/null
+++ b/scripts/coord-convert.pl
@@ -0,0 +1,280 @@
+#!/usr/bin/perl -w
+
+
+#
+# Written by Paul Lutt, KE7XT.
+# Released to the public domain.
+#
+#
+# $Id: coord-convert.pl,v 1.9 2010/07/03 22:09:48 we7u Exp $
+#
+#
+# Converts between different lat/lon formats. Will also give UMS
+# position if the lat/lon resides somewhere inside the Seattle area
+# aeronautical map.
+#
+# UMS coordinates have been used in the past by King County, WA SAR.
+# It can be useful for plotting positions on Green Trails maps and
+# perhaps other maps. The maps must be 15' topo maps and marked in
+# tenths of miles along the edge in order to make use of this
+# coordinate system.
+#
+# Web pages which discuss UMS format:
+# http://www.impulse.net/~mlynch/land_nav.html
+# http://www.logicsouth.com/~lcoble/dir9/land_nav.htm
+# http://www.aasar.org/training/academy/navigation.pdf
+#
+
+
+use lib "${prefix}/lib";
+use Coordinate; # WE7U's Coordinate.pm module
+
+
+# Create new Coordinate object
+my $position = Coordinate->new();
+
+
+$position->datum("WGS 84"); # Datum
+
+
+print "\n";
+print "Examples: 48.123N 122.123W\n";
+print " 48 07.380N 122 07.380W\n";
+print " 48 07 22.8N 122 07 22.8W\n";
+print " 10U 0565264 5330343\n";
+
+
+while (1) {
+
+ print "\nEnter a Lat/Long value or UTM value:\n";
+
+ # Snag the input
+ $_ = <>;
+
+ print "\n";
+
+ # If the first item has 2 digits and one character and there are
+ # three "words" in the input, we're starting with a UTM value.
+ if (/^\d\d[a-zA-Z]\s+\w+\s+\w+\s*$/) {
+
+ # printf("Found a UTM value\n");
+
+ # We'll convert it to the standard format first and then run
+ # through the rest of the code.
+
+ $zone = $_;
+ $easting = $_;
+ $northing = $_;
+
+ $zone =~ s/^(\d\d[a-zA-Z])\s+\w+\s+\w+\s*$/$1/;
+ $easting =~ s/^\d\d[a-zA-Z]\s+(\w+)\s+\w+\s*$/$1/;
+ $northing =~ s/^\d\d[a-zA-Z]\s+\w+\s+(\w+)\s*$/$1/;
+
+ if ($easting > 999999) {
+ printf("Easting value is too high!\n");
+ next;
+ }
+
+ $position->zone($zone);
+ $position->easting($easting);
+ $position->northing($northing);
+
+ # Convert to lat/lon values
+ $position->utm_to_lat_lon();
+
+ # printf("Calculated Lat, Long position(Lat, Long): %f %f\n",
+ # $position->latitude(),
+ # $position->longitude() );
+
+ $latitude = $position->latitude();
+ $longitude = $position->longitude();
+
+ $lat_dir = "N";
+ $long_dir = "E";
+
+ if ($latitude < 0.0) {
+ $latitude = abs($latitude);
+ $lat_dir = "S"
+ }
+ if ($longitude < 0.0) {
+ $longitude = abs($longitude);
+ $long_dir = "W";
+ }
+
+
+ # printf("%f%s %f%s\n", $latitude,$lat_dir,$longitude,$long_dir);
+
+ $_ = sprintf("%f%s %f%s",
+ $latitude,$lat_dir,$longitude,$long_dir);
+
+ }
+
+ # Look for lat/long value in the input
+
+ # Add missing decimal points.
+ s/^(\d+)([NSns])\s+(\d+)([EWew])\s*$/$1.$2 $3.$4/;
+
+ # Check for N/S/E/W characters in the input. Set the
+ # appropriate flags if found.
+ $lat_dir = "N";
+ $long_dir = "E";
+ if (/S/ || /s/) { $lat_dir = "S"; }
+ if (/W/ || /w/) { $long_dir = "W"; }
+ # Filter out these characters from the input
+ tr/nsewNSEW//d;
+
+ # Convert to DD MM SS format
+ ($lat_deg, $lat_min, $lat_sec,
+ $long_deg, $long_min, $long_sec) = split(' ');
+
+ # Decimal Degrees?
+ if ($lat_deg =~ /\./) {
+
+ $long_deg = $lat_min; # Save long_degrees in proper place
+
+ $temp = $lat_deg;
+ $lat_deg = int $temp;
+ $lat_min = int ((abs($temp) * 60.0) % 60);
+
+ # Modulus converts to integers, so we bump up by 10 and then
+ # back down.
+ $lat_sec = (abs($temp) * 36000.0) % 600;
+ $lat_sec = $lat_sec / 10;
+
+ $temp = $long_deg;
+
+ $long_deg = int $temp;
+ $long_min = int ((abs($temp) * 60.0) % 60);
+ $long_sec = (abs($temp) * 36000.0) % 600;
+ $long_sec = $long_sec / 10;
+ }
+ # Decimal Minutes?
+ elsif ($lat_min =~ /\./) {
+
+ $long_min = $long_deg; # Save long_minutes in proper place
+ $long_deg = $lat_sec; # Save long_degrees in proper place
+
+ $temp = $lat_min;
+ $lat_min = int abs($temp);
+ $lat_sec = (abs($temp) * 600.0) % 600;
+ $lat_sec = $lat_sec / 10;
+
+ $temp = $long_min;
+ $long_min = int abs($temp);
+ $long_sec = (abs($temp) * 600.0) % 600;
+ $long_sec = $long_sec / 10;
+ }
+ # Decimal Seconds
+ else { # Already in DD MM SS format, don't convert
+ }
+
+ # Print out the three lat/long formats
+ printf(" Decimal Degrees: %8.5f%s %8.5f%s\n",
+ $lat_deg + ($lat_min/60.0) + ($lat_sec/3600.0), $lat_dir,
+ $long_deg + ($long_min/60.0) + ($long_sec/3600.0), $long_dir );
+
+ printf(" Degrees/Decimal Minutes: %02d %06.3f%s %02d %06.3f%s\n",
+ $lat_deg, $lat_min + ($lat_sec/60.0), $lat_dir,
+ $long_deg, $long_min + ($long_sec/60.0), $long_dir );
+
+ printf(" Degrees/Minutes/Dec. Seconds: %02d %02d %4.1f%s %02d %02d %4.1f%s\n",
+ $lat_deg, $lat_min, $lat_sec, $lat_dir,
+ $long_deg, $long_min, $long_sec, $long_dir);
+
+ # Fill in the coordinate object with the current lat/lon.
+ # Assuming WGS84 datum
+ if ($lat_dir =~ /S/) {
+ $position->latitude( -( $lat_deg + ($lat_min/60.0) + ($lat_sec/3600.0) ) );
+ }
+ else {
+ $position->latitude( $lat_deg + ($lat_min/60.0) + ($lat_sec/3600.0) );
+ }
+
+ if ($long_dir =~ /W/) {
+ $position->longitude( -( $long_deg + ($long_min/60.0) + ($long_sec/3600.0) ) );
+ }
+ else {
+ $position->longitude( $long_deg + ($long_min/60.0) + ($long_sec/3600.0) );
+ }
+
+ #printf("%f %f\n",$position->latitude,$position->longitude);
+
+ $position->lat_lon_to_utm();
+ printf(" Universal Transverse Mercator: %s %07.0f %07.0f\n",
+ $position->zone(),
+ $position->easting(),
+ $position->northing() );
+
+ # Check whether the coordinates are within the SEA aeronautical
+ # map area
+ $lat_err = 0;
+ if ($lat_dir =~ /S/ ||
+ $lat_deg < 44 || $lat_deg > 49 ||
+ ($lat_deg == 44 && ($lat_min < 30 || ($lat_min == 30 && $lat_sec == 0))) ||
+ ($lat_deg == 49 && ($lat_min > 0 || $lat_sec > 0))) {
+ print " lat. out of range ";
+ $lat_err = 1;
+ }
+
+ $long_err = 0;
+ if ($long_dir =~ /E/ ||
+ $long_deg < 117 || $long_deg > 125 ||
+ ($long_deg == 117 && ($long_min == 0 && $long_sec == 0)) ||
+ ($long_deg == 125 && ($long_min > 0 || $long_sec > 0))) {
+ print " long. out of range";
+ $long_err = 1;
+ }
+
+ next if ( $lat_err || $long_err);
+
+
+ # Compute UMS coordinates
+ $y_sec = 3600 * ($lat_deg - 44) + 60 * $lat_min + $lat_sec;
+ $y_sec = 18000 - $y_sec;
+
+ $x_sec = 3600 * ($long_deg - 117) + 60 * $long_min + $long_sec;
+ $x_sec = 28800 - $x_sec;
+
+ $quad = 32 * int($y_sec / 900) + int($x_sec / 900) + 1;
+
+# print "\tx_sec= $x_sec, y_sec= $y_sec, quad= $quad\n";
+
+ $y_subquad_offset = int($y_sec / 450);
+ $x_subquad_offset = int($x_sec / 450);
+
+ if (&even($x_subquad_offset) && &even($y_subquad_offset)) {
+ print " UMS (Green Trails Maps): SEA ${quad} A ";
+ printf "%02d", &s2m_x($x_sec - (450 * $x_subquad_offset));
+ printf "%02d\n", &s2m_y($y_sec - (450 * $y_subquad_offset));
+ } elsif (&odd($x_subquad_offset) && &even($y_subquad_offset)) {
+ print " UMS (Green Trails Maps): SEA ${quad} B ";
+ printf "%02d", &s2m_x(450 * ($x_subquad_offset + 1) - $x_sec);
+ printf "%02d\n", &s2m_y($y_sec - (450 * $y_subquad_offset));
+ } elsif (&even($x_subquad_offset) && &odd($y_subquad_offset)) {
+ print " UMS (Green Trails Maps): SEA ${quad} C ";
+ printf "%02d", &s2m_x($x_sec - (450 * $x_subquad_offset));
+ printf "%02d\n", &s2m_y(450 * ($y_subquad_offset + 1) - $y_sec);
+ } else {
+ print " UMS (Green Trails Maps): SEA ${quad} D ";
+ printf "%02d", &s2m_x(450 * ($x_subquad_offset + 1) - $x_sec);
+ printf "%02d\n", &s2m_y(450 * ($y_subquad_offset + 1) - $y_sec);
+ }
+}
+
+sub even {
+ return (($_[0] & 1) == 0);
+}
+
+sub odd {
+ return (($_[0] & 1) == 1);
+}
+
+sub s2m_y {
+ return (int((0.1917966 * $_[0]) + 0.5));
+}
+
+sub s2m_x {
+ return (int((cos(($lat_deg + ($lat_min / 60.0) + ($lat_sec / 3600.0)) / 57.29578) * (0.1917966 * $_[0])) + 0.5));
+}
+
+
diff --git a/scripts/geopdf2gtiff.pl b/scripts/geopdf2gtiff.pl
new file mode 100755
index 0000000..0147342
--- /dev/null
+++ b/scripts/geopdf2gtiff.pl
@@ -0,0 +1,231 @@
+#!/usr/bin/env perl
+
+###############################################################################
+# $Id: geopdf2gtiff.pl,v 1.5 2012/11/01 18:57:19 we7u Exp $
+#
+# Portions Copyright (C) 2004-2012 The Xastir Group
+#
+# Script to convert a GeoPDF file with included neatline into a collar-stripped
+# geotiff in EPSG:4326 projection (WGS84 equidistant cylindrical) in 8-bit
+# color.
+#
+# You must have installed GDAL/OGR, configured to use python in order to use
+# this script. This is because the script attempts to run rgb2pct.py, which
+# is only installed if you've built GDAL with python support.
+#
+# This also depends on the -cutline and -crop_to_cutline features of
+# gdalwarp, which are only present in versions of GDAL after 1.8.1.
+#
+# Last Edit:$Date: 2012/11/01 18:57:19 $
+# Revision:$Revision: 1.5 $
+# Last Edited By: $Author: we7u $
+###############################################################################
+
+use Getopt::Long;
+
+my $fudgeNeatline;
+$result=GetOptions("fixneatline|f"=>\$fudgeNeatline);
+
+# Input file is a geopdf:
+if ($#ARGV<0)
+{
+ print STDERR "Usage: $0 <geopdfname>\n";
+ exit 1;
+}
+
+my $inputPDF=$ARGV[0];
+if (! -e $inputPDF)
+{
+ print STDERR "File $inputPDF does not exist.\n";
+ exit 1;
+}
+
+open GDALINFO, "gdalinfo $inputPDF |" or die "can't fork $!";
+my $readingCoordSys=0;
+my $coordSys="";
+my $readingMetadata=0;
+my $neatlinePoly="";
+my $minLat=360,$maxLat=-360,$minLon=360,$maxLon=-360,$templat,$templon;
+
+while (<GDALINFO>)
+{
+ if (/^Driver: (.*)$/)
+ {
+ if ($1 ne "PDF/Geospatial PDF")
+ {
+ print STDERR "This script is intended to run only on GeoPDF input files.\n";
+ exit 1;
+ }
+ next;
+ }
+ if (/^Coordinate System is:/)
+ {
+ $readingCoordSys=1;
+ next;
+ }
+ if ($readingCoordSys == 1)
+ {
+ # This is tricky --- finding the end of the coordinate system
+ # means looking for the first line that starts in column 1 that isn't
+ # the first line of the coordinate system. All lines of the coordinate
+ # system other than the first start with space.
+ if (/^[^ ]/ && $coordSys ne "")
+ {
+ $readingCoordSys=0;
+ next;
+ }
+ else
+ {
+ chomp($_);
+ $coordSys .= $_;
+ next;
+ }
+ }
+ if (/^Metadata:/)
+ {
+ $readingMetadata=1;
+ next;
+ }
+ if ($readingMetadata==1)
+ {
+ if (/^Corner Coordinates:/)
+ {
+ $readingMetadata=0;
+ next;
+ }
+ if (/^ *NEATLINE=(.*)$/)
+ {
+ $neatlinePoly=$1;
+ next;
+ }
+ }
+ if (/^Band ([0-9]+).*Type=([^,]*)/)
+ {
+ $bandinfo[$#bandinfo+1]=$2;
+ next;
+ }
+ if (/^(Upper|Lower) (Left|Right)/)
+ {
+ s/(Upper|Lower) (Left|Right) *\([^)]*\) *//;
+ /\(([^,]*), *([^\)]*)\)/;
+ $templonstr=$1;
+ $templatstr=$2;
+ $templonstr =~ /([0-9]*)d( *[0-9]*)'( *[0-9.]*)"([EW])/;
+ $deg=$1; $min=$2; $sec=$3; $hem=$4;
+ $templon=$deg+$min/60+$sec/3600;
+ $templon *= -1 if ($hem eq "W");
+ $minLon=$templon if ($templon<$minLon);
+ $maxLon=$templon if ($templon>$maxLon);
+
+ $templatstr =~ /([0-9]*)d( *[0-9]*)'( *[0-9.]*)"([NS])/;
+ $deg=$1; $min=$2; $sec=$3; $hem=$4;
+ $templat=$deg+$min/60+$sec/3600;
+ $templat *= -1 if ($hem eq "S");
+ $minLat=$templat if ($templat<$minLat);
+ $maxLat=$templat if ($templat>$maxLat);
+
+ }
+
+}
+close GDALINFO;
+
+if (! $fudgeNeatline)
+{
+# Create a CSV for the neatline. OGR will recognize this geometry
+ open CSVFILE, ">$inputPDF.csv";
+ print CSVFILE "foo,WKT\n";
+ print CSVFILE "bar,\"$neatlinePoly\"\n";
+ close CSVFILE;
+
+# Unfortunately, there's no easy way to attach a spatial reference system
+# (SRS) to the csv file so that gdalwarp will recognize it. So make a
+# virtual layer out of the CSV with the reference system in it.
+ open VRTFILE, ">$inputPDF.vrt";
+ print VRTFILE "<OGRVRTDataSource>\n";
+ print VRTFILE " <OGRVRTLayer name=\"$inputPDF\">\n";
+ print VRTFILE " <LayerSRS>$coordSys</LayerSRS>\n";
+ print VRTFILE " <SrcDataSource>$inputPDF.csv</SrcDataSource>\n";
+ print VRTFILE " <GeometryType>wkbPolygon</GeometryType>\n";
+ print VRTFILE " <GeometryField>WKT</GeometryField>\n";
+ print VRTFILE " </OGRVRTLayer>\n";
+ print VRTFILE "</OGRVRTDataSource>\n";
+ close VRTFILE;
+}
+else
+{
+ print "User asked us to fudge the neatline, finding nearest 7.5 minute quad boundaries\n";
+
+
+ # Instead of using the neatline specified, round it to nearest 7.5'
+ # quad boundary
+ $left=(int((abs($minLon)-int(abs($minLon)))/.125+.5)*.125+int(abs($minLon)))*($minLon/abs($minLon));
+ $right=(int((abs($maxLon)-int(abs($maxLon)))/.125+.5)*.125+int(abs($maxLon)))*($maxLon/abs($maxLon));
+ if ($maxLon<0)
+ {
+ $temp=$left;
+ $left=$right;
+ $right=$temp;
+ }
+ $bottom=(int((abs($minLat)-int(abs($minLat)))/.125+.5)*.125+int(abs($minLat)))*($minLat/abs($minLat));
+ $top=(int((abs($maxLat)-int(abs($maxLat)))/.125+.5)*.125+int(abs($maxLat)))*($maxLat/abs($maxLat));
+ if ($maxLat<0)
+ {
+ $temp=$top;
+ $top=$bottom;
+ $bottom=$temp;
+ }
+
+
+ open CSVFILE, ">$inputPDF.csv";
+ print CSVFILE "foo,WKT\n";
+ print CSVFILE "bar,\"POLYGON(($left $top,$right $top, $right $bottom, $left $bottom, $left $top))\"\n";
+ close CSVFILE;
+
+# Unfortunately, there's no easy way to attach a spatial reference system
+# (SRS) to the csv file so that gdalwarp will recognize it. So make a
+# virtual layer out of the CSV with the reference system in it.
+ open VRTFILE, ">$inputPDF.vrt";
+ print VRTFILE "<OGRVRTDataSource>\n";
+ print VRTFILE " <OGRVRTLayer name=\"$inputPDF\">\n";
+ print VRTFILE " <LayerSRS>EPSG:4326</LayerSRS>\n";
+ print VRTFILE " <SrcDataSource>$inputPDF.csv</SrcDataSource>\n";
+ print VRTFILE " <GeometryType>wkbPolygon</GeometryType>\n";
+ print VRTFILE " <GeometryField>WKT</GeometryField>\n";
+ print VRTFILE " </OGRVRTLayer>\n";
+ print VRTFILE "</OGRVRTDataSource>\n";
+ close VRTFILE;
+}
+
+# The VRT virtual source will now appear to gdal warp as a complete
+# specification of the neatline, with both coordinates *AND* description of
+# the coordinate system. This will enable gdalwarp to do the clipping of the
+# neatline *AND* conversion to a different coordinate system in the same
+# operation. Had we not done the vrt, gdalwarp would have assumed the
+# neatline to be in the coordinates of the DESTINATION raster, not the
+# source raster.
+
+$outputTif=$inputPDF;
+$outputTif =~ s/pdf/tif/i;
+
+# We will warp from whatever the coordinate system is into EPSG:4326, the
+# coordinate system that requires the least work and involves the fewest
+# approximations from Xastir.
+#$theGdalWarp="gdalwarp -cutline $inputPDF.vrt -crop_to_cutline -t_srs EPSG:4326 -co \"COMPRESS=PACKBITS\" $inputPDF $outputTif";
+$theGdalWarp="gdalwarp -cutline $inputPDF.vrt -crop_to_cutline -t_srs EPSG:4326 $inputPDF $outputTif";
+
+system ($theGdalWarp) == 0 or die "System $theGdalWarp failed: $?";
+
+
+if ($#bandinfo>0)
+{
+ print "This is a multi-band raster, dithering...\n";
+ system ("mv $outputTif $$.tif");
+# $theRGB2PCT="rgb2pct.py $$.tif $$-2.tif";
+ $theRGB2PCT="rgb2pct.py $$.tif $outputTif";
+ system ($theRGB2PCT) == 0 or die "Could not run rgb2pct: $?";
+# system("gdal_translate -co \"COMPRESS=PACKBITS\" $$-2.tif $outputTif") == 0 or die "Could not gdal_translate: $?";
+ system("rm -f $$.tif $$-2.tif");
+}
+
+# now clean up our mess:
+system ("rm $inputPDF.csv $inputPDF.vrt");
diff --git a/scripts/get-BOMdata b/scripts/get-BOMdata
new file mode 100755
index 0000000..cc4836b
--- /dev/null
+++ b/scripts/get-BOMdata
@@ -0,0 +1,95 @@
+#!/bin/sh
+#
+# $Id: get-BOMdata,v 1.1 2012/03/02 20:26:50 we7u Exp $
+#
+# Script to retrieve BOM data files.
+#
+# Originally written 2006/03/07 by Steven, WM5Z, and Curt, WE7U.
+# Modified from original get-NWSdata script by Geoff VK2XJG.
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# 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.
+#
+# See README.MAPS for a bit more information on the program.
+#
+#
+# NOTE: Run this script as root.
+#
+# MAINTAINERS: Go here to find out what the latest versions are:
+# <ftp://ftp.bom.gov.au/anon/home/adfd/spatial/>
+
+
+FILE1="gfe_public_weather" # BOM Spatial: Public Warning Zone Boundaries
+FILE2="gfe_metro_areas" # BOM Spatial: Metropolitan Warning Area Boundaries
+FILE3="gfe_coastal_waters" # BOM Spatial: Coastal Forecast Marine Zones
+FILE4="gfe_coastal_waters_warnings" # BOM Spatial: Coastal Warning Zones
+FILE5="gfe_local_effects" # BOM Spatial: Local Effects Areas
+FILE6="gfe_fire_weather" # BOM Spatial: Fire Weather Zone Boundaries
+FILE7="LGA08aAust" # Local Government Area Boundaries
+
+x=`dirname $0`
+. $x/values
+cd ${prefix}/share/xastir/Counties
+
+
+# Remove any old zip files hanging around in this directory
+#
+rm -f *.zip 2>&1 >/dev/null
+
+
+# Fetch new copies, unzip into place, delete archive.
+#
+#
+DIR=wsom
+for d in $FILE1 $FILE2 $FILE3 $FILE4 $FILE5 $FILE6; do
+if [ -e $d.shp ]
+ then
+ echo "Already have $d shapefile, skipping..."
+ else
+ # Remove possible older copies
+ cut=`echo $d|cut -c1-30 -`
+ rm -f $cut*.shx $cut*.shp $cut*.dbf $cut*.prj $cut*.zip 2>&1 >/dev/null
+ wget ftp://ftp.bom.gov.au/anon/home/adfd/spatial/$d.zip
+ unzip $d.zip
+ rm -f *.zip
+
+ mv $d*.shx $d.shx 2>&1 >/dev/null
+ mv $d*.shp $d.shp 2>&1 >/dev/null
+ mv $d*.dbf $d.dbf 2>&1 >/dev/null
+ mv $d*.prj $d.prj 2>&1 >/dev/null
+ mv $d*.sbx $d.sbx 2>&1 >/dev/null
+ mv $d*.sbn $d.sbn 2>&1 >/dev/null
+
+fi
+done
+
+DIR=county
+for d in $FILE7; do
+if [ -e $d.shp ]
+ then
+ echo "Already have $d shapefile, skipping..."
+ else
+ # Remove possible older copies
+ cut=`echo $d|cut -c1-2 -`
+ rm -f $cut*.shx $cut*.shp $cut*.dbf $cut*.prj $cut*.zip 2>&1 >/dev/null
+ wget http://wxsvr.aprs.net.au/shapefiles/$d\_shape.zip
+ unzip $d\_shape.zip
+ rm -f *.zip
+fi
+done
+
+
diff --git a/scripts/get-NWSdata b/scripts/get-NWSdata
new file mode 100755
index 0000000..f7652c4
--- /dev/null
+++ b/scripts/get-NWSdata
@@ -0,0 +1,91 @@
+#!/bin/sh
+#
+# $Id: get-NWSdata,v 1.32 2012/12/03 21:30:39 we7u Exp $
+#
+# Script to retrieve NWS data files.
+#
+# Originally written 2006/03/07 by Steven, WM5Z, and Curt, WE7U.
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# 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.
+#
+# See README.MAPS for a bit more information on the program.
+#
+#
+# NOTE: Run this script as root.
+#
+# MAINTAINERS: Go here to find out what the latest versions are:
+# <http://www.weather.gov/geodata/>
+
+
+# Please only have ONE of each variable listed here! Note that the "Valid
+# Date" listed on the NWS web pages is the date at which the Shapefile
+# should START to be used. Don't just blindly put the newest filename
+# here if that start-date hasn't arrived yet!
+#
+FILE1="w_11oc12" # NWSM Libraries: County Warning Area Boundaries
+FILE2="z_04de12" # NWSM Libraries: Public Zone Boundaries
+FILE3="mz11oc12" # NWSM Libraries: Coastal and Offshore Marine Zones
+FILE4="oz28jn12" # NWSM Libraries: Coastal and Offshore Marine Zones
+FILE5="hz30mr09" # NWSM Libraries: Coastal and Offshore Marine Zones
+FILE6="fz04de12" # NWSM Libraries: Fire Weather Zone Boundaries
+FILE7="c_11oc12" # AWIPS County Libraries (under "States, Provinces & Counties", "U.S. Counties")
+
+
+x=`dirname $0`
+. $x/values
+cd ${prefix}/share/xastir/Counties
+
+
+# Remove any old zip files hanging around in this directory
+#
+rm -f *.zip 2>&1 >/dev/null
+
+
+# Fetch new copies, unzip into place, delete archive.
+#
+#
+DIR=wsom
+for d in $FILE1 $FILE2 $FILE3 $FILE4 $FILE5 $FILE6; do
+if [ -e $d.shp ]
+ then
+ echo "Already have $d shapefile, skipping..."
+ else
+ # Remove possible older copies
+ cut=`echo $d|cut -c1-2 -`
+ rm -f $cut*.shx $cut*.shp $cut*.dbf $cut*.prj $cut*.zip 2>&1 >/dev/null
+ wget http://www.weather.gov/geodata/catalog/$DIR/data/$d.zip
+ unzip $d.zip
+ rm -f *.zip
+fi
+done
+
+DIR=county
+for d in $FILE7; do
+if [ -e $d.shp ]
+ then
+ echo "Already have $d shapefile, skipping..."
+ else
+ # Remove possible older copies
+ cut=`echo $d|cut -c1-2 -`
+ rm -f $cut*.shx $cut*.shp $cut*.dbf $cut*.prj $cut*.zip 2>&1 >/dev/null
+ wget http://www.weather.gov/geodata/catalog/$DIR/data/$d.zip
+ unzip $d.zip
+ rm -f *.zip
+fi
+done
+
diff --git a/scripts/get-fcc-rac.pl b/scripts/get-fcc-rac.pl
new file mode 100755
index 0000000..42fcdbb
--- /dev/null
+++ b/scripts/get-fcc-rac.pl
@@ -0,0 +1,141 @@
+#!/usr/bin/perl -W
+#
+# $Id: get-fcc-rac.pl,v 1.11 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# 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.
+#
+# Updated on 7/5/03 to reflect the new directory structure
+# N0VH
+#
+# Note: Run this script as root in order to write the files into the
+# destination directory listed below, or change directory write access.
+use File::Basename;
+$dirname=dirname($0);
+require ($dirname."/values.pl");
+
+my $XASTIR_BASE="${prefix}/share/xastir";
+
+
+# This script uses temporary storage space in /var/tmp to do its work.
+chdir "/var/tmp";
+
+
+#####################################################################
+# Get the RAC database, process it.
+# Download size: ~2MB
+# Final file size: ~13MB
+#####################################################################
+#
+
+$file = "amateur.zip";
+#$file2 = "amateur.rpt";
+$file2 = "amateur.txt";
+
+
+print STDERR "*********************************\n";
+print STDERR "*** Fetching the RAC database ***\n";
+print STDERR "*********************************\n";
+#`wget -c http://205.236.99.41/%7Eindicatif/download/$file`;
+`wget -c http://apc-cap.ic.gc.ca/datafiles/$file`;
+
+
+if (-e $file && -r $file && -f $file) {
+
+ print STDERR "***********************************\n";
+ print STDERR "*** Installing the RAC database ***\n";
+ print STDERR "***********************************\n";
+ `unzip $file $file2`;
+ `mv $file2 $XASTIR_BASE/fcc/AMACALL.LST`;
+}
+
+# Remove the RAC download files
+unlink $file, $file2;
+
+
+#####################################################################
+# Get the FCC database, process it.
+# Download size: ~84MB
+# Final file size: ~101MB
+#####################################################################
+#
+my $file = "l_amat.zip";
+my $file2 = "EN.dat";
+
+
+print STDERR "*********************************\n";
+print STDERR "*** Fetching the FCC database ***\n";
+print STDERR "*********************************\n";
+`wget -c http://wireless.fcc.gov/uls/data/complete/$file`;
+
+if (-e $file && -r $file && -f $file) {
+
+ my $file_out = "$XASTIR_BASE/fcc/$file2";
+
+ # Get rid of characters "^M^M^J" which are sometimes present, sort
+ # the file by callsign & remove old entries for vanity call access.
+ print STDERR "*****************************************************\n";
+ print STDERR "*** Filtering/sorting/installing the FCC database ***\n";
+ print STDERR "*****************************************************\n";
+
+ my %from = ();
+
+ open FILE, "unzip -p $file $file2|" or die "Can't open $file2 in $file : $!";
+ open FILE_OUT, '|-', "sort -k 5,5 -t \\| -o $file_out" or die "Can't sort $file_out : $!";
+ while( <FILE> ) {
+ if (/^EN\|(\d+)\|\|\|(\w+)\|.*/) {
+ $x = $1;
+ $z = $2;
+ chop;
+ chop;
+ $y = $_;
+ if (defined $from{$2}) { # check for vanity reassignment
+ if ($from{$z} =~ /^EN\|(\d+)\|\|\|(\w+)\|.*/) {
+ if ($1 < $x) {
+ $replaced++;
+ $from{$2} = $y;
+ }
+ }
+ }
+ else {
+ $from{$2} = $_;
+ }
+ }
+ }
+ close FILE;
+
+ for my $callsign ( keys %from ) {
+ $total++;
+ print FILE_OUT "$from{$callsign}\n";
+ }
+ close FILE_OUT;
+
+ print STDERR "Total callsigns: " . $total . ".\n";
+ print STDERR " Replaced callsigns: " . $replaced . ".\n";
+}
+
+# Remove the FCC download files
+unlink $file;
+
+
+
+
+print STDERR "*************\n";
+print STDERR "*** Done! ***\n";
+print STDERR "*************\n";
+
+
diff --git a/scripts/get-gnis b/scripts/get-gnis
new file mode 100755
index 0000000..878f04f
--- /dev/null
+++ b/scripts/get-gnis
@@ -0,0 +1,75 @@
+#!/bin/sh
+#
+# $Id: get-gnis,v 1.16 2012/11/01 18:57:19 we7u Exp $
+#
+# Script to retrieve GNIS files by state.
+#
+# Written 20041205 Dan Brown N8YSZ
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# 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.
+#
+# Look at the README for more information on the program.
+#
+
+GNIS_SITE=http://geonames.usgs.gov/docs/stategaz
+SUFFIX=_Features_20090401
+
+x=`dirname $0`
+. $x/values
+
+if [ $# -lt 1 ]
+then
+ printf "%s: error - Need at least one state to download\n" $0
+ printf "Usage: %s ST [ST]... \n" $0
+ exit 1
+fi
+
+cd /tmp
+
+while [ $1 ]
+do
+
+ MYSTATE=`printf ${1} | tr a-z A-Z `
+
+ printf "Retrieving GNIS file for %s\n" ${MYSTATE}
+
+ rm -f ${MYSTATE}${SUFFIX}.zip ${MYSTATE}${SUFFIX}.txt
+ if (wget ${GNIS_SITE}/${MYSTATE}${SUFFIX}.zip)
+ then
+ unzip ${MYSTATE}${SUFFIX}.zip
+ else
+ rm -f ${MYSTATE}${SUFFIX}.zip ${MYSTATE}${SUFFIX}.txt
+ wget ${GNIS_SITE}/${MYSTATE}${SUFFIX}.txt
+ fi
+
+ if ( [ -f ${MYSTATE}${SUFFIX}.txt ] )
+ then
+ printf "File successfully downloaded. Moving to ${prefix}/share/xastir/GNIS\n"
+ sudo mv ${MYSTATE}${SUFFIX}.txt ${prefix}/share/xastir/GNIS/${MYSTATE}.gnis
+ if [ ${MYSTATE} = "AK" -o ${MYSTATE} = "HI" ]; then
+ sudo recode utf16..utf8 ${prefix}/share/xastir/GNIS/${MYSTATE}.gnis
+ fi
+ else
+ printf "File for %s not successfully downloaded.\n" ${MYSTATE}
+ fi
+
+shift
+
+done
+
+
diff --git a/scripts/get-maptools.sh b/scripts/get-maptools.sh
new file mode 100755
index 0000000..9de4b20
--- /dev/null
+++ b/scripts/get-maptools.sh
@@ -0,0 +1,370 @@
+#!/bin/bash +x
+#
+# $Id: get-maptools.sh,v 1.14 2012/11/01 18:57:19 we7u Exp $
+#
+#
+# Script originally to retrieve and install Shapelib.
+# Written 20050227 Dan Brown N8YSZ
+# Modified 20060321 to generalize for all maptools - N8YSZ.
+#
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# 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.
+#
+# Look at the README for more information on the program.
+#
+
+#
+# Figure out whether we have bsdtar or gnutar on the system. Either
+# should work. If not, we'll have to check for "gunzip" and then do
+# "gunzip -c file.tar.gz | tar xf -" instead.
+#
+echo
+echo Checking for necessary utilities...
+if (wget --version 2>&1 | grep "GNU")
+then
+ echo ***Found wget. Good!
+else
+ echo ***Did not find wget. Exiting...
+fi
+TAR=gtar
+if ($TAR --version 2>&1 | grep "GNU")
+then
+ echo ***Found GNU tar as \'gtar\'. Good!
+else
+ echo Did not find gtar, checking for tar...
+ TAR=tar
+ if ($TAR --version 2>&1 | grep "GNU")
+ then
+ echo ***Found GNU tar as \'tar\'. Good!
+ else
+ echo Did not find GNU tar. Checking for bsdtar...
+ if ($TAR --version 2>&1 | grep "bsdtar")
+ then
+ echo ***Found bsdtar as \'tar\'. Good!
+ else
+ echo Did not find bsdtar. Checking for gunzip...
+ if (gunzip --version 2>&1 | grep "GNU")
+ then
+ echo ***Found gunzip. Good!
+ echo Checking for tar...
+ if test -e /usr/local/bin/tar -o -e /usr/bin/tar -o -e /bin/tar
+ then
+ echo ***Found tar. Good!
+ TAR=""
+ else
+ echo ***Did not find tar. Exiting...
+ exit
+ fi
+ else
+ echo ***Did not find gunzip. Exiting...
+ exit
+ fi
+ fi
+ fi
+fi
+#echo $TAR
+
+
+MAPTOOLS=http://dl.maptools.org/dl
+
+#
+XASDIR=$HOME/src/xastir
+XASTIR_TMP=$XASDIR/tmp
+XASTIR_LIB=$XASDIR/lib
+
+if [ ! -d $XASTIR_TMP ]
+then
+ printf "WARNING: %s Doesn't appear to exist. Creating temporary directory\n" $XASTIR_TMP
+ # Make sure this exists!
+ mkdir -p $XASTIR_TMP
+fi
+
+printf "Checking MACHTYPE found: %s\n" $MACHTYPE
+
+if [ ${MACHTYPE}.z = '.z' ]
+then
+ printf "You really ought to upgrade to a current version of bash \n"
+ printf "Making best guess attempt using uname\n"
+ UNAME=`uname`
+else
+ UNAME=$MACHTYPE
+fi
+
+if [ -e /sbin/ldconfig ]
+then
+ printf "OS is %s. Found ldconfig.\n" $UNAME
+ DO_LDCONFIG='yes'
+else
+ printf "OS is %s. Skipping ldconfig.\n" $UNAME
+ DO_LDCONFIG='no'
+fi
+
+printf "Checking for sudo\n"
+
+if SUDO=`which sudo`
+then
+ printf "$SUDO found - validating $SUDO privileges\n"
+ if $SUDO -v
+ then
+ printf "Ok, we can continue\n"
+ else
+ printf "ERROR: %s needs $SUDO privileges - aborting \n" $0
+ exit
+ fi
+else
+ printf "Sudo not found. Checking for appropriate privs\n"
+ if [ $DO_LD_CONFIG="yes" -a -f /etc/ld.so.conf ]
+ then
+ if touch -a /etc/ld.so.conf
+ then
+ printf "We can modify /etc/ld.so.conf\n"
+ else
+ printf "ERROR: We cannot modify /etc/ld.so.conf - aborting\n"
+ exit
+ fi
+ fi
+
+ if touch -a /usr/local/lib
+ then
+ printf "We can modify /usr/local/lib\n"
+ else
+ printf "ERROR: We cannot modify /usr/local/lib - aborting\n"
+ exit
+ fi
+fi
+
+if [ $DO_LDCONFIG = "no" ]
+then
+ printf "OS is %s - Skipping ldconfig \n" $UNAME
+else
+
+ printf "Checking /etc/ld.so.conf configuration\n"
+
+ if [ -d /etc/ld.so.conf.d ]
+ then
+ LDCONF_FILE=/etc/ld.so.conf.d/xastir.conf
+ else
+ LDCONF_FILE=/etc/ld.so.conf
+ fi
+
+ if [ ! -f $LDCONF_FILE ]
+ then
+ sudo touch $LDCONF_FILE
+ fi
+
+ if (! grep /usr/local/lib $LDCONF_FILE 2>&1 > /dev/null)
+ then
+ printf "Warning: /usr/local/lib not in %s - adding it\n" $LDCONF_FILE
+ if MKTEMP=`which mktemp`
+ then
+ TMPFILE=`mktemp -t ld.so.conf.XXXXXXXXXX`
+ else
+ TMPFILE='/tmp/ld.so.conf.XXXXXXXXXX'
+ $SUDO rm -f $TMPFILE
+ touch $TMPFILE
+ fi
+ cp $LDCONF_FILE $TMPFILE
+ $SUDO cp $LDCONF_FILE $LDCONF_FILE.orig.$$
+ printf "/usr/local/lib\n" >> $TMPFILE
+ $SUDO cp $TMPFILE $LDCONF_FILE
+
+ fi
+
+ if (! grep /usr/local/lib $LDCONF_FILE 2>&1 > /dev/null)
+ then
+ printf "ERROR: could not add /usr/local/lib to %s - aborting\n " $LDCONFIG_FILE
+ exit
+ fi
+
+fi
+
+
+# pcre arguably doesn't belong here
+
+ALL=" http://internap.dl.sourceforge.net/sourceforge/pcre/pcre-6.3.tar.gz
+ http://dl.maptools.org/dl/shapelib/shapelib-1.2.10.tar.gz\
+ http://dl.maptools.org/dl/proj/proj-4.4.9.tar.gz\
+ http://dl.maptools.org/dl/geotiff/libgeotiff/libgeotiff-1.2.3.tar.gz\
+ http://dl.maptools.org/dl/gdal/gdal-1.3.2.tar.gz"
+
+#for XA_LIB in shapelib-1.2.10 proj-4.4.9 gdal-1.3.1 libgeotiff-1.2.3
+
+for XA_LIB_URL in $ALL
+do
+
+
+# Check for a working dir
+
+ if [ ! -d $XASTIR_TMP ]
+ then
+ printf "ERROR: %s Doesn't appear to exist.\n" $XASTIR_TMP
+ printf "Please create dir and/or edit script. Exiting\n"
+ exit
+ else
+ cd $XASTIR_TMP
+ fi
+
+
+# PACKAGE_DIR=`echo $XA_LIB | sed -e "s/\-.*//"`
+
+ XA_LIB_FILE=`echo $XA_LIB_URL | sed -e "s/.*\///g"`
+# XA_LIB_URL=${MAPTOOLS}/${PACKAGE_DIR}/${XA_LIB_FILE}
+ XA_LIB=`echo $XA_LIB_FILE | sed -e "s/.tar.gz//"`
+ printf "Working on: %s\n" $XA_LIB
+ printf "Working in: %s\n" `pwd`
+
+
+# Cleanup Leftovers
+
+ if [ -e $XA_LIB_FILE -o -e $XA_LIB ]
+ then
+
+ printf "cleaning up old %s - will be saved under dir: %s \n" $XA_LIB old.$$
+ mkdir old.$$
+ mv -f ${XA_LIB}* old.$$/
+ fi
+
+# Get Files from Maptools
+
+ printf "Retrieving: %s\n" $XA_LIB
+
+ if (wget $XA_LIB_URL)
+ then
+ if test x"$TAR" != x
+ then
+ if ($TAR -xzf $XA_LIB_FILE )
+ then
+ printf "%s successfully downloaded.\n" $XA_LIB_FILE
+ else
+ printf "ERROR: %s not successfully downloaded - skipping.\n" $XA_LIB_FILE
+ fi
+ else
+ if (gunzip -c $XA_LIB_FILE | tar xf - )
+ then
+ printf "%s successfully downloaded.\n" $XA_LIB_FILE
+ else
+ printf "ERROR: %s not successfully downloaded - skipping.\n" $XA_LIB_FILE
+ fi
+ fi
+ fi
+
+ printf "Building %s\n\n" $XA_LIB
+ cd $XA_LIB
+ printf "Working in: %s\n" `pwd`
+
+ # Standards and methods and packaging - so many to chose from!
+
+ if ( printf $XA_LIB |grep -i proj)
+ then
+ cd nad
+ XA_LIB_URL=${MAPTOOLS}/proj/proj-datumgrid-1.3.zip
+ wget $XA_LIB_URL
+ unzip proj-datumgrid-1.3.zip
+ cd $XASTIR_TMP/$XA_LIB
+ fi
+
+ if [ $XA_LIB = 'shapelib-1.2.10' ]
+ then
+ # Need a couple fixes for shapelib on Cygwin.
+
+ if (echo $UNAME |grep -i cygwin ) 2>&1
+ then
+ mv Makefile Makefile.dist
+ sed -e "s/h libshp.so/hlibshp.sl/" -e "s/-lc/-lcygwin/" < Makefile.dist > Makefile
+ fi
+ make
+ make lib
+#WARNING WARNING WARNING
+# On any system that uses GCC 4.x as its compiler, it is probably necessary
+# to uncomment the stuff between here and the next "else". If you see
+# an error message of the form
+# /usr/bin/ld: makegeo: hidden symbol `__stack_chk_fail_local' in /usr/lib/libc_nonshared.a(stack_chk_fail_local.oS) is referenced by DSO
+# /usr/bin/ld: final link failed: Nonrepresentable section on output
+# collect2: ld returned 1 exit status
+# when libgeotiff's makefile gets to linking "makegeo", this is your
+# problem. Uncomment these lines and rerun the script.
+#----uncomment below--------
+# elif [ $XA_LIB = 'libgeotiff-1.2.3' ]
+# then
+# #The libgeotiff tar ball has last modification time of the configure
+# # script and the configure.in from which it's generated such that
+# # as soon as we type "make", the Makefile tries to regenerate
+# # configure and then run it with no arguments, interfering with
+# # our intentions here. So we "touch" configure so it's newer
+# # than configure.in, and make leaves them alone. The right
+# # fix would be to change that makefile, but this is easier
+# touch configure
+# # libgeotiff tries to use ld -shared for linking shared library,
+# # which is wrong on linux with GCC 4.x
+# ./configure --with-ld-shared="gcc -shared"
+# make
+ else
+ ./configure
+ make
+ fi 2>&1 >>${XA_LIB}.build.$$
+
+ printf "\n----------------------------------------------------------------------\n"
+ printf "Attempting install of %s\n" ${XA_LIB}
+
+ if [ ${XA_LIB} = 'shapelib-1.2.10' ]
+ then
+ $SUDO make lib_install
+ else
+ $SUDO make install
+ fi 2>&1 >> ${XA_LIB}.install.$$
+
+ printf "\n----------------------------------------------------------------------\n"
+ if $!
+ then
+
+ printf "If you got no errors(*), %s should now be installed!!\n" $XA_LIB
+ printf "\t(* warnings should be OK)\n"
+
+ else
+
+ printf "Error: Install of %s appears to have failed \n" $XA_LIB
+ fi
+
+ printf "If there are errors or warnings, please see: \n"
+ printf "\t%s\n" ${XASTIR_TMP}/${XA_LIB}/README
+ printf "\t%s\n" ${XASTIR_TMP}/${XA_LIB}/${XA_LIB}.build.$$
+ printf "\t%s\n" ${XASTIR_TMP}/${XA_LIB}/${XA_LIB}.install.$$
+ printf "\n----------------------------------------------------------------------\n"
+
+
+
+ if [ $DO_LDCONFIG = "no" ]
+ then
+ printf "OS is %s - Skipping ldconfig \n" $UNAME
+ else
+ printf "Running ldconfig\n"
+ if ($SUDO ldconfig )
+ then
+ printf "ldconfig completed successfully\n\n"
+ else
+ printf "ldconfig had errors - you may need to run ldconfig manually.\n"
+ fi
+ fi
+
+done # with getting and building
+
+
+printf "Congratulations, %s is done. \n" $0
+printf "For more information see %s\n" ${XASDIR}/README.MAPS
+
+
diff --git a/scripts/get-pop b/scripts/get-pop
new file mode 100755
index 0000000..e6d31b8
--- /dev/null
+++ b/scripts/get-pop
@@ -0,0 +1,81 @@
+#!/bin/sh
+#
+# $Id$
+#
+# Script to retrieve GNIS files by state.
+#
+# Written 20041205 Dan Brown N8YSZ
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# 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.
+#
+# Look at the README for more information on the program.
+#
+
+#GNIS_SITE=ftp://aprs.tamu.edu/pub/GNIS
+GNIS_SITE=http://www.eng.uah.edu/pub/xastir
+SUFFIX=.gnis
+
+x=`dirname $0`
+. $x/values
+
+if [ $# -lt 1 ]
+then
+ printf "%s: error - Need at least one state to download\n" $0
+ printf "Usage: %s ST [ST]... \n" $0
+ exit 1
+fi
+
+cd /tmp
+
+while [ $1 ]
+do
+
+ MYSTATE=`printf ${1} | tr a-z A-Z `
+
+ printf "Retrieving GNIS file for %s\n" ${MYSTATE}
+
+ rm -f ${MYSTATE}${SUFFIX}.bz2 ${MYSTATE}${SUFFIX}.txt ${MYSTATE}${SUFFIX}.gz
+ if (wget ${GNIS_SITE}/${MYSTATE}${SUFFIX}.bz2)
+ then
+ bunzip2 ${MYSTATE}${SUFFIX}.bz2
+ elif (wget ${GNIS_SITE}/${MYSTATE}${SUFFIX}.gz)
+ then
+ gunzip ${MYSTATE}${SUFFIX}.gz
+ else
+ rm -f ${MYSTATE}${SUFFIX}.zip ${MYSTATE}${SUFFIX} ${MYSTATE}${SUFFIX}.gz
+ wget ${GNIS_SITE}/${MYSTATE}${SUFFIX}
+ fi
+
+ if ( [ -f ${MYSTATE}${SUFFIX}.txt ] ) then
+ printf "File successfully downloaded. Moving to ${prefix}/share/xastir/GNIS\n"
+ sudo mv ${MYSTATE}${SUFFIX}.txt ${prefix}/share/xastir/GNIS/${MYSTATE}.pop
+ if [ ${MYSTATE} = "AK" -o ${MYSTATE} = "HI" ]; then
+ sudo recode utf16..utf8 ${prefix}/share/xastir/GNIS/${MYSTATE}.pop
+ fi
+ elif ( [ -f ${MYSTATE}${SUFFIX} ] ) then
+ printf "File successfully downloaded. Moving to ${prefix}/share/xastir/GNIS\n"
+ sudo mv ${MYSTATE}${SUFFIX} ${prefix}/share/xastir/GNIS/${MYSTATE}.pop
+ else
+ printf "File for %s not successfully downloaded.\n" ${MYSTATE}
+ fi
+
+shift
+
+done
+
+
diff --git a/scripts/get_shapelib.sh b/scripts/get_shapelib.sh
new file mode 100644
index 0000000..0c94b24
--- /dev/null
+++ b/scripts/get_shapelib.sh
@@ -0,0 +1,189 @@
+#!/bin/sh +x
+#
+#
+# Script to retrieve and install Shapelib.
+#
+# Written 20050227 Dan Brown N8YSZ
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+# 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.
+#
+# Look at the README for more information on the program.
+#
+
+SHAPELIB=shapelib-1.2.10
+
+SHAPELIB_FILE=${SHAPELIB}.tar.gz
+
+SHAPELIB_URL=http://dl.maptools.org/dl/shapelib/${SHAPELIB_FILE}
+
+XASDIR=$HOME/src/xastir
+XASTIR_TMP=$XASDIR/tmp
+XASTIR_LIB=$XASDIR/lib
+
+
+UNAME=`uname -o`
+
+if [ $UNAME = 'Cygwin' ]
+then
+ printf "OS is %s. Skipping sudo tests.\n" $UNAME
+else
+ printf "Checking for sudo\n"
+
+ if SUDO=`which sudo`
+ then
+ printf "$SUDO found - validating $SUDO privileges\n"
+ if $SUDO -v
+ then
+ printf "Ok, we can continue\n"
+ else
+ printf "ERROR: %s needs $SUDO privileges - aborting \n" $0
+ exit
+ fi
+ else
+
+#
+# The following isn't very portable and should be modified.
+#
+ printf "Sudo not found. Checking for appropriate privs\n"
+ if touch -a /etc/ld.so.conf
+ then
+ printf "We can modify /etc/ld.so.conf\n"
+ else
+ printf "ERROR: We cannot modify /etc/ld.so.conf - aborting\n"
+ exit
+ fi
+ if touch -a /usr/local/lib
+ then
+ printf "We can modify /usr/local/lib\n"
+ else
+ printf "ERROR: We cannot modify /usr/local/lib - aborting\n"
+ exit
+ fi
+ fi
+fi
+
+if [ ! -d $XASTIR_TMP ]
+then
+ printf "WARNING: %s Doesn't appear to exist. Creating temporary directory\n" $XASTIR_TMP
+ # Make sure this exists!
+ mkdir -p $XASTIR_TMP
+fi
+cd $XASTIR_TMP
+
+if [ -e $SHAPELIB_FILE -o -e $SHAPELIB ]
+then
+
+ printf "cleaning up old shapelib - will be saved under dir: %s \n" old.$$
+ mkdir old.$$
+ mv -f shapelib* old.$$/
+fi
+
+printf "Retrieving shapelib\n"
+
+if (wget $SHAPELIB_URL)
+then
+ if (tar -xzf $SHAPELIB_FILE )
+ then
+ printf "shapelib successfully downloaded.\n"
+ else
+ printf "ERROR: %s not successfully downloaded - aborting.\n" $SHAPELIB_FILE
+ fi
+fi
+
+printf "Building shapelib\n"
+cd $SHAPELIB
+
+# Need a couple fixes for shapelib on Cygwin.
+if [ $UNAME = 'Cygwin' ]
+then
+ mv Makefile Makefile.dist
+ sed -e "s/h libshp.so/hlibshp.sl/" -e "s/-lc/-lcygwin/" < Makefile.dist > Makefile
+fi
+
+make
+make lib
+
+printf "Attempting install\n"
+printf "\n----------------------------------------------------------------------\n"
+if $SUDO make lib_install
+then
+ printf "\n\n\n----------------------------------------------------------------------\n"
+else
+ printf "\n\n\n----------------------------------------------------------------------\n"
+ printf "Error: Install appears to have failed - aborting \n"
+fi
+
+
+if [ $UNAME = 'Cygwin' ]
+then
+ printf "OS is %s - Skipping ldconfig " $UNAME
+else
+
+ printf "Checking /etc/ld.so.conf"
+
+ if [ -d /etc/ld.so.conf.d ]
+ then
+ LDCONF_FILE=/etc/ld.so.conf.d/xastir.conf
+ else
+ LDCONF_FILE=/etc/ld.so.conf
+ fi
+
+ if [ ! -f $LDCONF_FILE ]
+ then
+ sudo touch $LDCONF_FILE
+ fi
+
+ if (! grep /usr/local/lib $LDCONF_FILE 2>&1 > /dev/null)
+ then
+ printf "Warning: /usr/local/lib not in %s - adding it\n" $LDCONF_FILE
+ if MKTEMP=`which mktemp`
+ then
+ TMPFILE=`mktemp -t ld.so.conf.XXXXXXXXXX`
+ else
+ TMPFILE='/tmp/ld.so.conf.XXXXXXXXXX'
+ $SUDO rm -f $TMPFILE
+ touch $TMPFILE
+ fi
+ cp $LDCONF_FILE $TMPFILE
+ printf "/usr/local/lib\n" >> $TMPFILE
+ $SUDO cp $LDCONF_FILE $LDCONF_FILE.save
+ $SUDO cp $TMPFILE $LDCONF_FILE
+ fi
+
+ if ( grep /usr/local/lib $LDCONF_FILE )
+ then
+ printf "Running ldconfig\n"
+ if ($SUDO ldconfig )
+ then
+ printf "ldconfig completed successfully\n\n"
+ else
+ printf "ldconfig had errors - you may need to run ldconfig manually.\n"
+ fi
+ else
+ printf "ERROR: could not add /usr/local/lib to $LDCONF_FILE - aborting\n"
+ exit
+ fi
+fi
+
+printf "Congratulations, %s is done. \n" $0
+printf "If you got no errors, shapelib should now be installed!!\n"
+printf "If there are errors, please see: \n"
+printf "\t%s\n" ${XASTIR_TMP}/${SHAPELIB}/README
+printf "\t%s\n" ${XASDIR}/README.MAPS
+
+
diff --git a/scripts/gpx2shape b/scripts/gpx2shape
new file mode 100755
index 0000000..4a114dd
--- /dev/null
+++ b/scripts/gpx2shape
@@ -0,0 +1,218 @@
+#!/usr/bin/perl
+
+# $Id: gpx2shape,v 1.1 2006/06/01 17:04:25 we7u Exp $
+
+#
+# Copyright (C) 2006 James Washer
+#
+# 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.
+#
+
+
+
+use strict;
+use XML::Simple;
+use Getopt::Std;
+use Geo::Shapelib qw/:all/;
+
+my $routenum=1;
+my @vertices;
+my $shp;
+my ($comment,$notes,$elevation)=("no comment", "no note",-9999);
+my %shapetype = ( wpt => 1, rte => 3, trk => 3 );
+
+our ( $opt_v, $opt_t, $opt_w, $opt_r, $opt_d, $opt_s);
+getopts("vtwrds");#v=verbose t=tracks w=waypoints r=routes d=dbfawk s=shapefile_prefix
+
+
+print " args are \"@ARGV\"vals are $opt_t, $opt_w, $opt_r, $opt_d\n" if $opt_v;
+my $f = $ARGV[0];
+$opt_s =$ARGV[0];
+$opt_s =~ s/.gpx$//;
+
+print "shapename is $opt_s\n" if $opt_v;
+
+my $xml = XMLin($f,ForceArray => 1);
+
+process_rte() if $opt_r;
+process_trk() if $opt_t;
+process_wpt() if $opt_w;
+
+
+exit;
+sub dumpit{
+ use Data::Dumper;
+ print Dumper($xml);
+ exit;
+}
+
+
+#################################################################
+###################### SHAPEFILE SETUP #######################
+#################################################################
+sub init_shape{
+ my $type=shift;
+
+
+ $shp = new Geo::Shapelib;
+ $shp->{Name}=${opt_s}."-".$type;
+ $shp->{Shapetype}= $shapetype{$type};
+
+
+ $shp->{FieldNames} = [ 'Name', 'Comment', 'Notes', 'Elevation' ];
+ $shp->{FieldTypes} = [ 'String:40','String:40','String:100','Integer:8' ];
+
+}
+
+sub save_shape{
+ $shp->save();
+}
+
+sub do_shape{
+ my($type,$name,$comment,$notes,$elevation)=@_;
+
+ push @{$shp->{Shapes}}, { SHPType => $shapetype{$type}, ShapeID => $name, NVertices => scalar @vertices, Vertices => [ @vertices ] };
+ push @{$shp->{ShapeRecords}}, [ $name, $comment, $notes, $elevation];
+
+ print "\t\tdo_shape $name $type ",scalar @vertices,"\n" if $opt_v;
+}
+
+#################################################################
+###################### ROUTE PROCESSING #######################
+#################################################################
+sub process_rte{
+ print "Process Route called\n";
+ unless(exists $xml->{rte}){
+ print "\tNo Routes\n" if $opt_v;
+ return;
+ }
+ my $aref=$xml->{rte};
+ return unless defined $aref;
+ die "Unepected reference $aref\n" unless ref($aref) eq "ARRAY";
+
+
+ init_shape('rte');
+ foreach my $rref ( @$aref ){
+ my $name="Route.$routenum++";
+ $name=$rref->{name}->[0] if defined $rref->{name};
+ print "\tProcessing route \"$name\"\n" if $opt_v;
+
+ @vertices=();
+ do_route($rref->{rtept});
+ do_shape('rte',$name,"","","");
+ }
+ save_shape();
+
+}
+
+sub do_route{
+ my $rtept_ref=shift;
+ die "do_route Unepected reference $rtept_ref\n" unless ref($rtept_ref) eq "ARRAY";
+ foreach my $rtept ( @$rtept_ref ){
+ #print "\t\t$rtept->{lon} $rtept->{lat} $rtept->{name}->[0] $rtept->{sym}->[0]\n";
+ my $snell=get_snell($rtept);
+ print_snell($snell) if $opt_v;
+ push @vertices, [ $snell->{lon}, $snell->{lat} ];
+
+ }
+}
+#################################################################
+###################### TRACK PROCESSING #######################
+#################################################################
+sub process_trk{
+ print "Process Track called\n";
+ unless(exists $xml->{trk}){
+ print "\tNo Tracks\n" if $opt_v;
+ return;
+ }
+ my $aref=$xml->{trk};
+
+ my $aref=$xml->{trk};
+ die "Unepected reference $aref\n" unless ref($aref) eq "ARRAY";
+
+ init_shape('trk');
+ foreach my $tref( @$aref ){
+ print "Track $tref->{name}->[0]\n" if $opt_v;
+
+ @vertices=();
+
+
+ foreach my $ele ( @{$tref->{trkseg}->[0]->{trkpt}}){
+ my $snell=get_snell($ele);
+ print_snell($snell) if $opt_v;
+ push @vertices, [ $snell->{lon}, $snell->{lat} ];
+ }
+
+ do_shape('trk',$tref->{name}->[0],"","","");
+
+ }
+ save_shape();
+
+
+}
+
+sub do_trk{
+ my $trk_aref=shift;
+ die "Unepected reference $trk_aref\n" unless ref($trk_aref) eq "ARRAY";
+}
+#################################################################
+##################### WAYPOINT PROCESSING #######################
+#################################################################
+sub process_wpt{
+ print "Process Waypoint called\n";
+ unless(exists $xml->{wpt}){
+ print "\tNo Waypoints\n" if $opt_v;
+ return;
+ }
+ my $aref=$xml->{wpt};
+ die "Unepected reference $aref\n" unless ref($aref) eq "ARRAY";
+ init_shape('wpt');
+ foreach my $wref ( @$aref ){
+ my $snell=get_snell($wref);
+ print_snell($snell) if $opt_v;
+ @vertices=[ $snell->{lon}, $snell->{lat} ];
+ do_shape('wpt',$snell->{name},$snell->{cmt},$snell->{ele});
+ }
+ save_shape();
+}
+
+#################################################################
+#################################################################
+#################################################################
+#cute "SNELL" is Symbol Name Elevation Latitude Longitude
+
+sub get_snell {
+ my $ref=shift;
+ my %val=(lat => "0.0", lon => "0.0", ele => "0.0", name => "NoName", sym => "Waypoint", cmt => "NoComment");
+ $val{lon}=$ref->{lon} if exists $ref->{lon};
+ $val{lat}=$ref->{lat} if exists $ref->{lat};
+ $val{name}=$ref->{name}->[0] if exists $ref->{name} and exists $ref->{name}->[0];
+ $val{sym}=$ref->{sym}->[0] if exists $ref->{sym};
+ $val{ele}=$ref->{ele}->[0] if exists $ref->{ele};
+ $val{cmt}=$ref->{cmt}->[0] if exists $ref->{cmt};
+ return \%val;
+
+}
+
+
+sub print_snell {
+ my $snell=shift;
+ print "\t\t$snell->{lon} $snell->{lat} $snell->{ele} $snell->{name} $snell->{sym}\n";
+}
+#################################################################
+#################################################################
+#################################################################
+
+
diff --git a/scripts/icontable.pl b/scripts/icontable.pl
new file mode 100755
index 0000000..8370ebd
--- /dev/null
+++ b/scripts/icontable.pl
@@ -0,0 +1,158 @@
+#!/usr/bin/perl
+# $Id: icontable.pl,v 1.5 2009/04/04 18:37:57 gstueve Exp $
+
+# XASTIR icon table overview generator 20.02.01
+# Copyright (C) 2001 Rolf Bleher http://www.dk7in.de
+
+# 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
+
+# see file COPYING for details
+
+#--------------------------------------------------------------------------
+
+# This script produces an overview graphics with all symbols used by Xastir
+# Output is as a XPM file to STDOUT
+# typical call: icontable.pl > symbols.xpm
+
+#--------------------------------------------------------------------------
+use File::Basename;
+$dirname=dirname($0);
+require ($dirname."/values.pl");
+
+# symbols file from XASTIR V2.1, change the path for your environment
+$SYMBFILE = $prefix."/share/xastir/symbols/symbols.dat";
+
+#--------------------------------------------------------------------------
+%sympix = ();
+$lasttable = $table;
+$lastsymbol = $symbol;
+$tablist = "/\\";
+ at coltab = qw(#FFFF00 #CD6500 #A020F0 #CCCCCC #CD0000 #FF4040 #CD3333 #00008B #00BFFF #006400 #EE0000 #00CD00 #0000CD #FFFFFF #5A5A5A #878787 #454545 #000000 None);
+setuppics();
+#storepics(); # store all icons as separate XPM files
+exit;
+#--------------------------------------------------------------------------
+sub setuppics {
+ my $table = '';
+ my $symbol = '';
+ my ($i,$j,$c);
+ my $line;
+ my $head;
+ my $str;
+ my $pix;
+ my $pixstr;
+ if (-f $SYMBFILE) {
+ if (open(FH, "<$SYMBFILE")) {
+ my %col = ();
+SYM: while(<FH>) {
+ last if (/DONE/);
+ if (/TABLE (.)/) {
+ $table = $1;
+ if(length($_)>20) { $descr = 1 }
+ next;
+ }
+ if (/APRS (.)/) {
+ $symbol = $1;
+ next if ($table ne '/' && $table ne '\\'); # ignore other
+ $pixstr = '';
+ for ($i=0;$i<20;$i++) {
+ $line = <FH>;
+ $line =~ s/\n//;
+ $line =~ s/\r//;
+ next SYM if (length($line) != 20);
+ $pixstr .= $line;
+ for ($j=0;$j<20;$j++) {
+ $c = substr($line,$j,1);
+ $col{$c} = $c;
+ }
+ }
+ $sympix{$table.$symbol} = $pixstr;
+ }
+ }
+ $str = "";
+ for ($i=0;$i<20;$i++) {
+ $str .= "....................";
+ }
+ $sympix{" "} = $str;
+
+ $head = ''; $j = 0;
+ foreach $c (keys %col) {
+ $head .= colstr($c);
+ $j++;
+ }
+ $head = "/* XPM */{\"337 258 $j 1 \",\n".$head;
+
+# 12 lines with 16 symbols each x 337 y
+
+ $pix = "";
+ foreach $table ("/","\\") {
+ for ($i=2;$i<8;$i++) { # symbol row
+ $pix .= "\"".("q" x 337)."\",\n"; # black hor line
+ for ($j=0;$j<20;$j++) { # scan line
+ $pix .= "\""; # start of scan line
+ for ($k=0;$k<16;$k++) { # symbol column
+ $pix .= "q"; # vert line
+ $symbol = chr($i*16+$k);
+ $pix .= substr(getpic($table.$symbol),$j*20,20);
+ }
+ $pix .= "q\",\n"; # vert line
+ }
+ }
+ if ($table eq "\\") { # {
+ $pix .= "\"".("q" x 337)."\"};\n"; # black hor line
+ } else {
+ $pix .= "\"".("q" x 337)."\",\n"; # black hor line
+ for ($i=0;$i<4;$i++) {
+ $pix .= "\"".("." x 337)."\",\n"; # hor space
+ }
+ }
+ }
+ printf($head.$pix);
+ close(FH);
+ }
+ }
+}
+#--------------------------------------------------------------------------
+sub colstr { # setup string for color
+ my ($c) = @_;
+ if ($c eq '#') { # Yellow
+ $cidx = 0;
+ } elsif ($c ge 'a' && $c le 'q') {
+ $cidx = ord($c)-ord('a')+1;
+ } else {
+ $cidx = @coltab-1; # Transparent
+ }
+ return("\"$c c $coltab[$cidx]\",\n");
+}
+#--------------------------------------------------------------------------
+sub getpic {
+ my ($id) = @_;
+ $str = $sympix{$id};
+ if (! $str) {
+ $str = $sympix{" "}; # default
+ }
+ $str;
+}
+#--------------------------------------------------------------------------
+sub storepics { # extract all icons to files
+ foreach $cc (keys %sympix) {
+ $fname = sprintf("Aprs%2.2X%2.2X.xpm",ord(substr($cc,0,1)),ord(substr($cc,1,1)));
+ if (open(FH,">$fname")) {
+ printf(FH "%s",getpic($cc));
+ close(FH);
+ }
+ }
+}
+#--------------------------------------------------------------------------
diff --git a/scripts/inf2geo.pl b/scripts/inf2geo.pl
new file mode 100755
index 0000000..a8c1fe7
--- /dev/null
+++ b/scripts/inf2geo.pl
@@ -0,0 +1,249 @@
+#!/usr/bin/perl
+
+# Written by Curt Mills, WE7U
+# Released to the public domain.
+#
+# $Id: inf2geo.pl,v 1.11 2010/07/03 22:09:48 we7u Exp $
+#
+#
+# Invoke this script against one or more info files by typing:
+#
+# inf2geo.pl filename.inf
+# -or-
+# inf2geo.pl *.inf
+#
+# To process all .inf files in that directory.
+#
+# Note: This script requires GraphicsMagick or ImageMagick packages
+# to be installed before it will function properly. Install one of
+# these via your package manager.
+#
+#
+# What the script does for you:
+# Read in .inf file (from Ui-View)
+# Convert the lat/long coordinates into dd.dddd format
+# Get the image extents via "identify -ping filename" or
+# "gm identify -ping filename".
+# Write out the .geo file
+# Note that this program assumes (and converts to)
+# lower-case for the filename.
+#
+# Note: It appears that .INF files store the lat/lon
+# in DD.MM.MMMM format. Converting the script to this
+# format.
+#
+# 2003-08-15 ZL2UMF: add processing multiple files in one go (masks and whot-not)
+# so you can convert all your ui-view maps in one step
+
+#use strict;
+use IO::File;
+
+#go through every filename passed to this script
+
+#printf("ARGV:%d\n",$#ARGV);
+
+if ($#ARGV == -1) {
+ # No filenames on the command line
+ printf("\n\n\nNo filenames specified. Invoke this script against one\n");
+ printf("or more .inf files by typing:\n\n");
+ printf(" inf2geo.pl filename.inf\n");
+ printf("-or-\n");
+ printf(" inf2geo.pl *.inf\n\n");
+ printf("To process all .inf files in that directory.\n\n");
+ exit;
+}
+else {
+ foreach my $file (@ARGV) {
+ print "*** $file ***\n";
+
+ #make a geo of this file
+ makeGeo ($file);
+ }
+
+}
+
+exit; #just in case
+
+sub makeGeo {
+ my $inf_filename = shift;
+
+ my $filename = $inf_filename;
+ $filename =~ s/\.inf$//i;
+
+ my $geo_filename = $filename . ".geo";
+
+# $inf = IO::File->new("< $ARGV[0].inf")
+# or $inf = IO::File->new("< $ARGV[0].INF")
+# or $inf = IO::File->new("< $ARGV[0].Inf")
+
+ #skip this file if geo already exists
+ return print "$filename.geo already exists, will not overwrite\n" if( -e "$filename.geo" );
+
+ #read the inf file
+ my $inf = IO::File->new ( "< $inf_filename" )
+ or return print "\nCouldn't open $inf_filename for reading:\n$!\n\n";
+
+ #make the new geo file
+ $geo = IO::File->new("> $geo_filename")
+ or return print "Couldn't open $geo_filename for writing: $!\n";
+
+ $upper_left = $inf->getline();
+ my ($tp0_lon, $tp0_lat) = split(',', $upper_left);
+ chomp($tp0_lat);
+
+ # Reverse them
+ if ( ($tp0_lat =~ /E/) || ($tp0_lat =~ /W/) ) {
+ $temp = $tp0_lat;
+ $tp0_lat = $tp0_lon;
+ $tp0_lon = $temp;
+ }
+
+ $lower_right = $inf->getline();
+ ($tp1_lon, $tp1_lat) = split(',', $lower_right);
+ chomp($tp1_lat);
+
+ # Reverse them
+ if ( ($tp1_lat =~ /E/) || ($tp1_lat =~ /W/) ) {
+ $temp = $tp1_lat;
+ $tp1_lat = $tp1_lon;
+ $tp1_lon = $temp;
+ }
+
+ #do some maths
+ $tp0_lat2 = &convert($tp0_lat) or return;
+ $tp0_lon2 = &convert($tp0_lon) or return;
+ $tp1_lat2 = &convert($tp1_lat) or return;
+ $tp1_lon2 = &convert($tp1_lon) or return;
+
+ my ($final_filename, $string) = &findImageFile($filename) or return;
+
+
+ # The format returned by string changed from this:
+ # test.gif 1148x830+0+0 PseudoClass 256c 48kb GIF 1s
+ # to this:
+ # test.gif GIF 1148x830+0+0 PseudoClass 256c Palette 8-bit 48kb 0.4u 0:01
+ # in later versions of ImageMagick.
+ #
+ # GraphicsMagick returns a string like this:
+ # i4-mo.gif GIF 1020x581+0+0 PseudoClass 256c 8-bit 475.8k 0.050u 0:01
+ #
+
+ chomp($string);
+ $string =~ s/.*\s(\d+x\d+).*/$1/; # Grab the 1148x830 portion
+
+ #print "String: $string\n";
+
+ $x = $y = $string;
+
+ $x =~ s/(\d+)x\d+/$1/;
+ $y =~ s/\d+x(\d+)/$1/;
+
+ #print "X: $x\nY: $y\n";
+
+ $x1 = $x - 1; # We start numbering pixels at zero, not 1
+ $y1 = $y - 1; # We start numbering pixels at zero, not 1
+
+ #print "X: $x\nY: $y\n";
+ #print "X1: $x1\nY1: $y1\n";
+
+
+ #write to the geo file
+ printf $geo "FILENAME $final_filename\n";
+ printf $geo "TIEPOINT 0\t\t0\t$tp0_lon2\t$tp0_lat2\n";
+ printf $geo "TIEPOINT $x1\t$y1\t$tp1_lon2\t$tp1_lat2\n";
+ printf $geo "IMAGESIZE $x\t$y\n";
+ printf $geo "#$string\n";
+ printf $geo "#\n# Converted from a .INF file by WE7U's inf2geo.pl script\n#\n";
+
+
+ $inf->close();
+ $geo->close();
+
+}
+
+
+
+
+sub convert
+{
+ #print "$_[0] -> ";
+ ($dd,$mm,$mm2) = split('\.', $_[0]);
+ $mm2 =~ s/(\d+).*/$1/;
+ $mm = $mm . "\." . $mm2;
+ $number = $dd + ($mm / 60.0);
+
+ if ( ($_[0] =~ /S/) || ($_[0] =~ /s/)
+ || ($_[0] =~ /W/) || ($_[0] =~ /w/) )
+ {
+ $number = -$number;
+ }
+
+ # Latitude bound checking
+ if ( ($_[0] =~ /S/) || ($_[0] =~ /s/) || ($_[0] =~ /N/) || ($_[0] =~ /n/) ) {
+ if ($dd > 90) {
+ print "Latitude degrees out-of-bounds: $dd. Must be <= 90\n";
+ return;
+ }
+ if ($mm >= 60) {
+ print "Latitude minutes out-of-bounds: $mm. Must be < 60\n";
+ return;
+ }
+ if (abs($number) > 90.0) {
+ print "Latitude out-of-bounds: $number. Must be between -90 and +90\n";
+ return;
+ }
+ }
+ # Longitude bounds checking
+ else {
+ if ($dd > 180) {
+ print "Longitude degrees out-of-bounds: $dd. Must be <= 180\n";
+ return;
+ }
+ if ($mm >= 60) {
+ print "Longitude minutes out-of-bounds: $mm. Must be < 60\n";
+ return;
+ }
+ if (abs($number) > 180.0) {
+ print "Longitude out-of-bounds: $number. Must be between -180 and +180\n";
+ return;
+ }
+ }
+
+ #print "$number\n";
+ #print "Temp = $temp\n";
+ return($number);
+}
+
+
+
+sub findImageFile {
+ $filename = shift;
+ @extensions = ("gif", "bmp", "jpg", "png", "emf");
+ foreach $xtn (@extensions) {
+ $try_filename = "$filename.$xtn";
+# print "Looking for $try_filename\n";
+
+ # Try GraphicsMagick's 'gm' first
+ $string = `gm identify -ping $try_filename 2>/dev/null`;
+ if ($string eq "") {
+ # Else try ImageMagick's 'identify'
+ $string = `identify -ping $try_filename 2>/dev/null`;
+ }
+ if ($string ne "") {
+ # Found the file and GM or IM
+ $filename = $try_filename;
+ $image_size = $string;
+ }
+ }
+ if ($image_size eq "") {
+ print "Image file not found for $filename, may be be a case problem\n" ;
+ print "or a problem finding GraphicsMagick's 'gm' or ImageMagick's 'identify' program\n";
+ print "Make sure that either GraphicsMagick or ImageMagick is installed.\n";
+ return;
+ }
+
+ print "Found this image: $image_size\n";
+ return ($filename, $image_size);
+}
+
+
diff --git a/scripts/kiss-off.pl b/scripts/kiss-off.pl
new file mode 100755
index 0000000..c145c21
--- /dev/null
+++ b/scripts/kiss-off.pl
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+# $Id: kiss-off.pl,v 1.3 2012/11/01 18:57:19 we7u Exp $
+
+# Copyright (C) 2004-2012 Curt Mills, WE7U
+#
+# 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.
+#
+
+# This script will send the proper characters to STDOUT to command a
+# KISS TNC out of KISS mode. Redirect it to the port that the TNC
+# is connected to. Turn off the port in Xastir first.
+
+# It is assumed that the baud rate on the port and the baud rate of
+# the TNC match, if not, this won't work. If you've just been using
+# the TNC in Xastir, they probably match.
+
+# Use the script like this:
+#
+# ./kiss-off.pl >/dev/ttyS1
+#
+
+
+sleep 1;
+printf("%c%c%c", 192, 255, 192);
+sleep 1;
+
diff --git a/scripts/langElmerFudd.pl b/scripts/langElmerFudd.pl
new file mode 100755
index 0000000..d56c518
--- /dev/null
+++ b/scripts/langElmerFudd.pl
@@ -0,0 +1,94 @@
+#!/usr/bin/perl -W
+
+# $Id: langElmerFudd.pl,v 1.6 2012/11/01 18:57:19 we7u Exp $
+
+# Copyright (C) 2008-2012 The Xastir Group
+#
+# 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.
+#
+# Look at the README for more information on the program.
+
+
+# Run it like this:
+#
+# cd xastir/config
+# ../scripts/langElmerFudd.pl -split <language-English.sys >language-ElmerFudd.sys
+# or
+# ../scripts/langElmerFudd.pl <some-input-file >some-output-file
+#
+# "-split": Translate 2nd part of line only (Xastir language file).
+# Without it: Translate entire text.
+
+
+# Regex strings derived from:
+# http://www.faqs.org/docs/diveintopython/dialect_divein.html
+# http://www.siafoo.net/snippet/133
+# http://dougal.gunters.org/blog/2004/08/30/text-filter-suite
+
+
+# Check whether we're translating an Xastir language file or plain
+# text:
+# "-split" present: Translate the 2nd piece of each line.
+# "-split" absent: Translate the entire text.
+my $a;
+if ($#ARGV < 0) { $a = ""; }
+else { $a = shift; }
+$do_split = 0;
+if (length($a) > 0 && $a =~ m/-split/) {
+ $do_split = 1;
+}
+
+while ( <> ) {
+
+ # Change the "Id:" RCS tag to show that we translated the file.
+ if (m/^#.*\$Id:/) {
+ print "# language-ElmerFudd.sys, translated from language-English.sys\n";
+ print "# Please do not edit this derived file.\n";
+ next;
+ }
+ # Skip other comment lines
+ if (m/^#/) {
+ next;
+ }
+
+ if ($do_split) {
+ # Split each incoming line by the '|' character
+ @pieces = split /\|/;
+
+ # Translate the second portion of each line only
+ $_ = $pieces[1];
+ }
+
+ s/[rl]/w/g;
+ s/[RL]/W/g;
+ s/([Qq])u/$1w/g;
+ s/th(\b)/f/g;
+ s/TH(\b)/F/g;
+ s/th/d/g;
+ s/Th/D/g;
+ s/([Nn])[.]/$1, uh-hah-hah-hah./g;
+
+ if ($do_split) {
+ # Combine the line again for output to STDOUT
+ $pieces[1] = $_;
+ print join '|', @pieces;
+ }
+ else {
+ print;
+ }
+}
+
+
diff --git a/scripts/langMuppetsChef.pl b/scripts/langMuppetsChef.pl
new file mode 100755
index 0000000..66b51f6
--- /dev/null
+++ b/scripts/langMuppetsChef.pl
@@ -0,0 +1,145 @@
+#!/usr/bin/perl -W
+
+# $Id: langMuppetsChef.pl,v 1.7 2012/11/01 18:57:19 we7u Exp $
+
+# Copyright (C) 2008-2012 The Xastir Group
+#
+# 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.
+#
+# Look at the README for more information on the program.
+
+
+# Run it like this:
+#
+# cd xastir/config
+# ../scripts/langMuppetsChef.pl -split <language-English.sys >language-MuppetsChef.sys
+# or
+# ../scripts/langMuppetsChef.pl <some-input-file >some-output-file
+#
+# "-split": Translate 2nd part of line only (Xastir language file).
+# Without it: Translate entire text.
+
+
+# Regex strings derived from:
+# http://www.siafoo.net/snippet/133
+# http://www.faqs.org/docs/diveintopython/dialect_divein.html
+# http://dougal.gunters.org/blog/2004/08/30/text-filter-suite
+
+
+# Check whether we're translating an Xastir language file or plain
+# text:
+# "-split" present: Translate the 2nd piece of each line.
+# "-split" absent: Translate the entire text.
+my $a;
+if ($#ARGV < 0) { $a = ""; }
+else { $a = shift; }
+$do_split = 0;
+if (length($a) > 0 && $a =~ m/-split/) {
+ $do_split = 1;
+}
+
+while ( <> ) {
+
+ # Change the "Id:" RCS tag to show that we translated the file.
+ if (m/^#.*\$Id:/) {
+ print "# language-MuppetsChef.sys, translated from language-English.sys\n";
+ print "# Please do not edit this derived file.\n";
+ next;
+ }
+ # Skip other comment lines
+ if (m/^#/) {
+ next;
+ }
+
+ if ($do_split) {
+ # Split each incoming line by the '|' character
+ @pieces = split /\|/;
+
+ # Translate the second portion of each line only
+ $_ = $pieces[1];
+ }
+
+ s/An/Un/g;
+ s/an/un/g;
+ s/Au/Oo/g;
+ s/au/oo/g;
+ s/a\b/e/g;
+ s/A\b/E/g;
+ s/en\b/ee/g;
+ s/\bew/oo/g;
+ s/\be\b/e-a/g;
+ s/\be/i/g;
+ s/\bE/I/g;
+ s/\bf/ff/g;
+ s/\bir/ur/g;
+ s/(\w*?)i(\w*?)$/$1ee$2/g;
+ s/\bow/oo/g;
+ s/\bo/oo/g;
+ s/\bO/Oo/g;
+ s/the/zee/g;
+ s/The/Zee/g;
+ s/th\b/t/g;
+ s/\btion/shun/g;
+ s/\bu/oo/g;
+ s/\bU/Oo/g;
+ s/v/f/g;
+ s/V/F/g;
+ s/w/w/g;
+ s/W/W/g;
+ s/([a-z])[.]/$&. Bork Bork Bork!/g;
+
+ # From the text-filter-suite:
+ s/(\w)ew/$1oo/g;
+ s/(\w)ow/$1oo/g;
+ s/(\W)o/$1oo/g;
+ s/(\W)O/$1Oo/g;
+ s/(\w)u/$1oo/g;
+ s/(\w)U/$1Oo/g;
+ s/a(\w)/e$1/g;
+ s/A(\w)/E$1/g;
+ s/en(\W)/ee$1/g;
+ s/(\w)e(\W)/$1e-a$2/g;
+ s/(\W)e/$1i/g;
+ s/(\W)E/$1I/g;
+ s/(\w)f/$1ff/g;
+ s/(\w)ir/$1ur/g;
+ s/([a-m])i/$1ee/g;
+ s/([A-M])i/$1EE/g;
+ s/(\w)o/$1u/g;
+ s/the/zee/g;
+ s/The/Zee/g;
+ s/th(\W)/t$1/g;
+ s/(\w)tion/$1shun/g;
+ s/v/f/g;
+ s/V/F/g;
+ s/w/v/g;
+ s/W/V/g;
+ s/f{2,}/ff/g;
+ s/o{2,}/oo/g;
+ s/e{2,}/ee/g;
+# s/([\.!\?])\s*(</[^>]+>)?\s*$/$1 Bork Bork Bork!$2/g;
+
+ if ($do_split) {
+ # Combine the line again for output to STDOUT
+ $pieces[1] = $_;
+ print join '|', @pieces;
+ }
+ else {
+ print;
+ }
+}
+
+
diff --git a/scripts/langOldeEnglish.pl b/scripts/langOldeEnglish.pl
new file mode 100755
index 0000000..2d75b10
--- /dev/null
+++ b/scripts/langOldeEnglish.pl
@@ -0,0 +1,129 @@
+#!/usr/bin/perl -W
+
+# $Id: langOldeEnglish.pl,v 1.6 2012/11/01 18:57:19 we7u Exp $
+
+# Copyright (C) 2008-2012 The Xastir Group
+#
+# 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.
+#
+# Look at the README for more information on the program.
+
+
+# Run it like this:
+#
+# cd xastir/config
+# ../scripts/langOldeEnglish.pl -split <language-English.sys >language-OldeEnglish.sys
+# or
+# ../scripts/langOldeEnglish.pl <some-input-file >some-output-file
+#
+# "-split": Translate 2nd part of line only (Xastir language file).
+# Without it: Translate entire text.
+
+
+# Regex strings derived from:
+# http://www.faqs.org/docs/diveintopython/dialect_divein.html
+# http://www.siafoo.net/snippet/133
+
+
+# Check whether we're translating an Xastir language file or plain
+# text:
+# "-split" present: Translate the 2nd piece of each line.
+# "-split" absent: Translate the entire text.
+my $a;
+if ($#ARGV < 0) { $a = ""; }
+else { $a = shift; }
+$do_split = 0;
+if (length($a) > 0 && $a =~ m/-split/) {
+ $do_split = 1;
+}
+
+while ( <> ) {
+
+ # Change the "Id:" RCS tag to show that we translated the file.
+ if (m/^#.*\$Id:/) {
+ print "# language-OldeEnglish.sys, translated from language-English.sys\n";
+ print "# Please do not edit this derived file.\n";
+ next;
+ }
+ # Skip other comment lines
+ if (m/^#/) {
+ next;
+ }
+
+ if ($do_split) {
+ # Split each incoming line by the '|' character
+ @pieces = split /\|/;
+
+ # Translate the second portion of each line only
+ $_ = $pieces[1];
+ }
+
+ s/i([bcdfghjklmnpqrstvwxyz])e\b/y$1/g;
+ s/i([bcdfghjklmnpqrstvwxyz])e/y$1$1e/g;
+ s/ick\b/yk/g;
+ s/ia([bcdfghjklmnpqrstvwxyz])/e$1e/g;
+ s/e[ea]([bcdfghjklmnpqrstvwxyz])/e$1e/g;
+ s/([bcdfghjklmnpqrstvwxyz])y/$1ee/g;
+ s/([bcdfghjklmnpqrstvwxyz])er/$1re/g;
+ s/([aeiou])re\b/$1r/g;
+ s/ia([bcdfghjklmnpqrstvwxyz])/i$1e/g;
+ s/tion\b/cioun/g;
+ s/ion\b/ioun/g;
+ s/aid/ayde/g;
+ s/ai/ey/g;
+ s/ay\b/y/g;
+ s/ay/ey/g;
+ s/ant/aunt/g;
+ s/ea/ee/g;
+ s/oa/oo/g;
+ s/ue/e/g;
+ s/oe/o/g;
+ s/ou/ow/g;
+ s/ow/ou/g;
+ s/\bhe/hi/g;
+ s/ve\b/veth/g;
+ s/se\b/e/g;
+ s/\'s\b/es/g;
+ s/ic\b/ick/g;
+ s/ics\b/icc/g;
+ s/ical\b/ick/g;
+ s/tle\b/til/g;
+ s/ll\b/l/g;
+ s/ould\b/olde/g;
+ s/own\b/oune/g;
+ s/un\b/onne/g;
+ s/rry\b/rye/g;
+ s/est\b/este/g;
+ s/pt\b/pte/g;
+ s/th\b/the/g;
+ s/ch\b/che/g;
+ s/ss\b/sse/g;
+ s/([wybdp])\b/$1e/g;
+ s/([rnt])\b/$1$1e/g;
+ s/from/fro/g;
+ s/when/whan/g;
+
+ if ($do_split) {
+ # Combine the line again for output to STDOUT
+ $pieces[1] = $_;
+ print join '|', @pieces;
+ }
+ else {
+ print;
+ }
+}
+
+
diff --git a/scripts/langPigLatin.pl b/scripts/langPigLatin.pl
new file mode 100755
index 0000000..82410b6
--- /dev/null
+++ b/scripts/langPigLatin.pl
@@ -0,0 +1,85 @@
+#!/usr/bin/perl -W
+
+# $Id: langPigLatin.pl,v 1.8 2012/11/01 18:57:19 we7u Exp $
+
+# Copyright (C) 2007-2012 The Xastir Group
+#
+# 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.
+#
+# Look at the README for more information on the program.
+
+
+# Run it like this:
+#
+# cd xastir/config
+# ../scripts/langPigLatin.pl -split <language-English.sys >language-PigLatin.sys
+# or
+# ../scripts/langPigLatin.pl <some-input-file >some-output-file
+#
+# "-split": Translate 2nd part of line only (Xastir language file).
+# Without it: Translate entire text.
+
+
+# Regex strings derived from:
+# http://www.perlmonks.org/?node_id=3586
+
+
+# Check whether we're translating an Xastir language file or plain
+# text:
+# "-split" present: Translate the 2nd piece of each line.
+# "-split" absent: Translate the entire text.
+my $a;
+if ($#ARGV < 0) { $a = ""; }
+else { $a = shift; }
+$do_split = 0;
+if (length($a) > 0 && $a =~ m/-split/) {
+ $do_split = 1;
+}
+
+while ( <> ) {
+
+ # Change the "Id:" RCS tag to show that we translated the file.
+ if (m/^#.*\$Id:/) {
+ print "# language-PigLatin.sys, translated from language-English.sys\n";
+ print "# Please do not edit this derived file.\n";
+ next;
+ }
+ # Skip other comment lines
+ if (m/^#/) {
+ next;
+ }
+
+ if ($do_split) {
+ # Split each incoming line by the '|' character
+ @pieces = split /\|/;
+
+ # Translate the second portion of each line only
+ $_ = $pieces[1];
+ }
+
+ s/\b(qu|y(?=[^t])|[^\W\daeiouy]*)([a-z']+)/$2.($1||"w")."ay"/eg;
+
+ if ($do_split) {
+ # Combine the line again for output to STDOUT
+ $pieces[1] = $_;
+ print join '|', @pieces;
+ }
+ else {
+ print;
+ }
+}
+
+
diff --git a/scripts/langPirateEnglish.pl b/scripts/langPirateEnglish.pl
new file mode 100755
index 0000000..8ea2def
--- /dev/null
+++ b/scripts/langPirateEnglish.pl
@@ -0,0 +1,545 @@
+#!/usr/bin/perl -W
+
+# $Id: langPirateEnglish.pl,v 1.11 2012/11/01 18:57:19 we7u Exp $
+
+# Copyright (C) 2008-2012 The Xastir Group
+#
+# 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.
+
+
+# Look at the README for more information on the program.
+#
+# Run it like this:
+#
+# cd xastir/config
+# ../scripts/langPirateEnglish.pl -split <language-English.sys >language-PirateEnglish.sys
+# or
+# ../scripts/langPirateEnglish.pl <some-input-file >some-output-file
+#
+# "-split": Translate 2nd part of line only (Xastir language file).
+# Without it: Translate entire text.
+
+
+# Regex strings derived from:
+# http://userscripts.org/scripts/review/25998
+# http://dougal.gunters.org/blog/2004/08/30/text-filter-suite
+
+
+# Check whether we're translating an Xastir language file or plain
+# text:
+# "-split" present: Translate the 2nd piece of each line.
+# "-split" absent: Translate the entire text.
+my $a;
+if ($#ARGV < 0) { $a = ""; }
+else { $a = shift; }
+$do_split = 0;
+if (length($a) > 0 && $a =~ m/-split/) {
+ $do_split = 1;
+}
+
+while ( <> ) {
+
+ # Change the "Id:" RCS tag to show that we translated the file.
+ if (m/^#.*\$Id:/) {
+ print "# language-PirateEnglish.sys, translated from language-English.sys\n";
+ print "# Please do not edit this derived file.\n";
+ next;
+ }
+ # Skip other comment lines
+ if (m/^#/) {
+ next;
+ }
+
+ if ($do_split) {
+ # Split each incoming line by the '|' character
+ @pieces = split /\|/;
+
+ # Translate the second portion of each line only
+ $_ = $pieces[1];
+ }
+
+ # Custom for Xastir:
+ s/\bham\b/matey/g;
+ s/\bhi hi\b/it be a joke, matey/g;
+ s/\bk7gps\b/Th\' Good Cap\'n/g;
+ s/\bDave Dobbins\b/Th\' Good Cap\'n/g;
+ s/\bAPRS\'er\b/Fellow Pirate/g;
+ s/\b[Aa]prs\'er\b/fellow pirate/g;
+ s/\bHerb Gerhardt\b/scurvy dog/g;
+ s/\bkb7uvc\b/scurvy dog/g;
+ s/\bwa7nwp\b/cabin boy/g;
+ s/\b[Mm]ap(s*)\b/Treasure Map/g;
+ s/\bXastir\b/HMS Xastir/g;
+ s/\bxastir\b/HMS xastir/g;
+ s/\bXASTIR\b/HMS XASTIR/g;
+ s/\bStation/Ship/g;
+ s/\bstation/ship/g;
+ s/\bView/Gander/g;
+ s/\bview/gander/g;
+ s/\bFile/Scroll/g;
+ s/\bfile/scroll/g;
+ #s/\bFile/Parchment/g;
+ #s/\bfile/parchment/g;
+ s/\bMessage/Dispatch/g;
+ s/\bmessage/dispatch/g;
+ s/\bLogging/Scribblin'/g;
+ s/\blogging/scribblin'/g;
+ s/\bLog/Scribble/g;
+ s/\blog/scribble/g;
+ s/\bPrint/Affix to parchment/g;
+ s/\bprint/affix to parchment/g;
+ s/\bCancel/Nay/g;
+ s/\bcancel/nay/g;
+ s/Close/Nay/g;
+ s/close/nay/g;
+ s/\bOK/Aye/g;
+ s/\bOk/Aye/g;
+ s/\bok/aye/g;
+ s/\bQuit/Nay/g;
+ s/\bquit/nay/g;
+ s/\bExit/Run Away!/g;
+ s/\bexit/run away!/g;
+ s/\bSelect/Choose 'yer Weapon!/g;
+ s/\bselect/choose 'yer weapon!/g;
+ s/\bCompressed/Scrawny/g;
+ s/\bcompressed/scrawny/g;
+ s/\bAudio/Racket/g;
+ s/\baudio/racket/g;
+ s/\bFont/Scribble/g;
+ s/\bfont/scribble/g;
+ s/\bSatellite/Heavenly Body/g;
+ s/\bsatellite/heavenly body/g;
+ s/\bSnapshot/Etching/g;
+ s/\bsnapshot/etching/g;
+ #s/\bObject//g;
+ #s/\bobject//g;
+ #s/\bItem//g;
+ #s/\bitem//g;
+ s/\bInterface/Grapple/g;
+ s/\binterface/grapple/g;
+ s/\bConfigure/Provision me' ship/g;
+ s/\bconfigure/provision me' ship/g;
+
+ # From userscripts:
+ s/About/\'bout/g;
+ s/\babout\b/\'bout/g;
+ s/\ba lot\b/mightily/g;
+ s/\bam\b/be/g;
+ s/\bamputee\b/peg leg/g;
+ s/\bafraid\b/lily-livered/g;
+ s/\band\b/an\'/g;
+ s/\baround\b/\'round/g;
+ s/\battack\b/pillage/g;
+ s/\battacked\b/raped and pillaged/g;
+ s/\barrest\b/keelhaul/g;
+ s/\bAIDS\b/scurvy/g;
+ s/\baids\b/scurvy/g;
+ s/\bATTN\b/AVAST/g;
+
+ s/\bbad\b/scurvy/g;
+ s/\bbeer\b/grog/g;
+ s/\bvodka\b/grog/g;
+ s/\bban him\b/make him walk the plank/g;
+ s/\bcar\b/ship/g;
+ s/\bBAN HIM\b/Make him walk the plank!/g;
+ s/\bBan him\b/Make him walk the plank/g;
+
+ s/\bale\b/grog/g;
+ s/\bbetween\b/betwixt/g;
+ s/\bwhiskey\b/grog/g;
+ s/\bbeauty\b/gov\'nor\'s daughter/g;
+ s/\bbefore\b/\'ere/g;
+ s/\bbanned\b/forced t\' walk the plank/g;
+ s/\bbetween\b/\'tween/g;
+ s/\bboy\b/jim lad/g;
+ s/\bboys\b/jim lads/g;
+ s/\bbought\b/pilfered/g;
+ s/\b4chan\b/House o\' Bilge Rats/g;
+
+ s/\bAsia\b/Th\' Mystic East/g;
+ s/\bJapan\b/Th\' Mystic East/g;
+ s/\bChina\b/Th\' Mystic East/g;
+ s/\bKorea\b/Th\' Mystic East/g;
+ s/\basia\b/Th\' Mystic East/g;
+ s/\bjapan\b/Th\' Mystic East/g;
+ s/\bchina\b/Th\' Mystic East/g;
+ s/\bkorea\b/Th\' Mystic East/g;
+ s/\bIndia\b/Hindustan/g;
+ s/\bIsrael\b/Th\' Holy Lands/g;
+ s/\bindia\b/Hindustan/g;
+ s/\bisrael\b/Th\' Holy Lands/g;
+ s/\bIraq\b/Th\' Ottoman Empire/g;
+ s/\bIran\b/Th\' Ottoman Empire/g;
+ s/\bPakistan\b/Th\' Ottoman Empire/g;
+ s/\bAfghanistan\b/Th\' Ottoman Empire/g;
+ s/\biraq\b/Th\' Ottoman Empire/g;
+ s/\biran\b/Th\' Ottoman Empire/g;
+ s/\bpakistan\b/Th\' Ottoman Empire/g;
+ s/\bafghanistan\b/Th\' Ottoman Empire/g;
+ s/\bAfrica\b/Th\' Dark Continent/g;
+ s/\bafrica\b/Th\' Dark Continent/g;
+
+ s/\bcheat\b/hornswaggle/g;
+ s/\bchild\b/wee one/g;
+ s/\bchildren\b/wee ones/g;
+ s/\bcoffee\b/grog/g;
+ s/\bcondemn\b/keelhaul/g;
+
+ s/\bconference\b/parlay/g;
+ s/\bcrazy\b/addled/g;
+ s/\bjapanophile\b/scurvy mutt/g;
+ s/\bweeaboo\b/scurvy mutt/g;
+ s/\boh crap\b/shiver me timbers!/g;
+ s/\bover\b/o\'er/g;
+ s/\bThe Token Shop\b/Honest Jack\'s Swag Shop/g;
+ s/\bToken Shop\b/Honest Jack\'s Swag Shop/g;
+
+ s/\bdamn\b/damn\'ed/g;
+ s/\bdevil\b/Davy Jones/g;
+ s/\bdie\b/head to Davy Jones\' Locker/g;
+ s/\bdead\b/\'n Davy Jones\' Locker/g;
+ s/\bdoesn\'t\b/don\'t/g;
+ s/\bdollars\b/pieces o\' eight/g;
+ s/\beveryone\b/all hands/g;
+ s/\beyewear\b/eye patch/g;
+ s/\bglasses\b/eye patches/g;
+ s/\bfight\b/duel/g;
+ s/\bgreatly\b/mightily/g;
+ s/\bgold\b/dubloons/g;
+ s/\bha\b/har har/g;
+ s/\bhaha\b/har har/g;
+ s/\bbase\b/port/g;
+ s/\bfort\b/port/g;
+ s/\bhah\b/har har/g;
+ s/\bheh\b/har har/g;
+ s/\bHa\b/Har har/g;
+ s/\bflag\b/Jolly Roger/g;
+ s/\bhouse\b/shanty/g;
+ s/\bidiot\b/bilge rat/g;
+
+ s/\bhit\b/flog/g;
+ s/\btorrents\b/Blackbeard\'s treasure /g;
+ s/\btorrent\b/Blackbeard\'s treasure/g;
+
+ s/\bn00b\b/landlubber/g;
+ s/\bnoob\b/landlubber/g;
+ s/\btroll\b/blowhard/g;
+ s/\bdrive\b/sail/g;
+ s/\bcoins\b/pieces o\' eight/g;
+ s/\bcorrect\b/right an\' true/g;
+
+ s/\bfly\b/sail/g;
+ s/\bfool\b/squiffy/g;
+ s/\bfoolish\b/addled/g;
+ s/\bfor\b/fer/g;
+ s/\bFor\b/Fer/g;
+ s/\bfriend\b/matey/g;
+ s/\bfriends\b/hearties/g;
+ s/\bgirl\b/lass/g;
+ s/\bex-girlfriend\b/festerin\' harlot/g;
+ s/\bex girlfriend\b/festerin\' harlot/g;
+ s/\bgood\b/worthy/g;
+ s/\byou\'re\b/yer/g;
+ s/\byour\b/yer/g;
+
+ s/\bhello\b/ahoy/g;
+ s/\bHello\b/Ahoy/g;
+ s/\bhey\b/avast!/g;
+ s/\bHey\b/Avast/g;
+ s/\bhey\b/avast!/g;
+ s/\bhi\b/ahoy/g;
+ s/\bHi\b/Ahoy/g;
+ s/\bHiya\b/Ahoy/g;
+ s/\bhiya\b/ahoy/g;
+ s/\bmoney\b/booty/g;
+ s/\bguy\b/feller/g;
+ s/\bfellow\b/feller/g;
+ s/\bidiot\b/scalawag/g;
+ s/ing\b/in\'/g;
+ s/\bin\b/\'n/g;
+ s/\bis\b/be/g;
+ s/\bit\'s\b/\'tis/g;
+ s/\bit is\b/\'tis/g;
+ s/\bkid\b/wee one/g;
+ s/\bkids\b/wee ones/g;
+ s/\bkill\b/keelhaul/g;
+
+ s/\bis not\b/be not/g;
+ s/\baren\'t\b/be not/g;
+ s/\bare\b/be/g;
+ s/\bam\b/be/g;
+ s/\bAre\b/Be/g;
+ s/\blol\b/yo ho ho!/g;
+ s/\blolol\b/Me sides be splittin\'!/g;
+ s/\bodd\b/addled/g;
+ s/\bof\b/o\'/g;
+ s/\bohmigod\b/begad!/g;
+ s/\bomigod\b/begad!/g;
+ s/\bomg\b/begad!/g;
+ s/\bOMG\b/BEGAD!/g;
+ s/\bo rly\b/be that right, sailor?/g;
+ s/\borly\b/be that right, sailor?/g;
+ s/\bya rly\b/Sailor, \'tis true/g;
+ s/\byarly\b/Sailor, \'tis true/g;
+ s/\bwhoamg\b/shiver me timbers!/g;
+
+ s/\bmoney\b/booty/g;
+ s/\bmy\b/me/g;
+ s/\bprosecute\b/keelhaul/g;
+ s/\bpants\b/britches/g;
+ s/\bHello\b/Ahoy!/g;
+ s/\bquick\b/smart/g;
+ s/\bquickly\b/smartly/g;
+ s/\bthe rules\b/the Pirate\'s Code/g;
+ s/\bnice\b/fine/g;
+ s/\bthe Internet\b/The Seven Seas/g;
+ s/\bThe Internet\b/The Seven Seas/g;
+ s/\binternet\b/Seven Seas/g;
+ s/\bInternet\b/Seven Seas/g;
+
+ s/\bsilly\b/addled/g;
+ s/\bsword\b/cutlass/g;
+ s/\bshe\b/the lass/g;
+ s/\bshut up\b/pipe down/g;
+ #s/\bspeech/parlance/g;
+ #s/\bSpeech/Parlance/g;
+ s/\bspeech/parley/g;
+ s/\bSpeech/Parley/g;
+ s/\bsteal\b/commandeer/g;
+ s/\bdownload\b/plunder/g;
+ s/\bDownload\b/Plunder/g;
+
+ s/\bsexy\b/saucy/g;
+ s/\btelescope\b/spyglass/g;
+ s/\bterrorist\b/scourge o\' the seven seas/g;
+ s/\bterrorists\b/scalawags/g;
+ s/tion\b/tin\'/g;
+ s/\bthere\b/thar/g;
+ s/tions\b/tin\'s/g;
+ s/\bto\b/t\'/g;
+ s/\btomorrow\b/the morrow/g;
+ s/\btruck\b/vessel/g;
+
+ s/\bwasn\'t\b/weren\'t/g;
+ s/\bwant to\b/wish t\'/g;
+ s/\bwanna\b/wish t\'/g;
+ s/\bYep\b/Aye/g;
+ s/\byep\b/aye/g;
+ s/\bwoman\b/buxom beauty/g;
+ s/\bwomen\b/wenches/g;
+ s/\bwin\b/triumph/g;
+ s/\bwins\b/triumphs/g;
+ s/\bwork\b/deck swabbing/g;
+ s/\bwine\b/grog/g;
+ s/\byes\b/aye/g;
+ s/\bYes\b/Aye/g;
+ s/\bno\b/nay/g;
+ s/\bNo\b/Nay/g;
+ s/\bnah\b/nay/g;
+ s/\bNah\b/Nay/g;
+ s/\bYeah\b/Aye/g;
+ s/\byeah\b/Aye/g;
+
+ s/\byou\b/ye/g;
+ s/\byour\b/yer/g;
+ s/\bwtf\b/what devilry!/g;
+ s/\bWTF\b/Begad, what devilry be is?!/g;
+ s/\bFacebook\b/PirateBook/g;
+ s/\bThis message was deleted at the request of the original poster\b/This here message be taken back by a yellow-bellied pirate/g;
+ s/\bThis message has been deleted by a moderator\b/This poor soul had a run-in with the authorities/g;
+ s/\bGood Tokens\b/Pieces o\' Eight/g;
+ s/\bBad Tokens\b/Black Marks/g;
+ s/\byou\'re\b/yer/g;
+ s/\bYou\'re\b/Yer/g;
+ s/\bwins\b/triumphs/g;
+
+ s/\bHome\b/Haven/g;
+ s/\bAdd a link\b/Add plunder/g;
+ s/\bRandom link\b/Who needs maps?/g;
+ s/\bTop rated links\b/Quality grog/g;
+ s/\bLinks o\' the week\b/Modern fashions/g;
+ s/\bWiki\b/Wikis/g;
+ s/\bAll links\b/All th\' plunder/g;
+ s/\bFavorites\b/Treasures/g;
+ s/\bSearch\b/Scour/g;
+ s/\bStats\b/Specs/g;
+ s/\bBoards\b/Th\' Tavern/g;
+ s/\bUser List\b/Roster/g;
+ s/\bLogout\b/Retreat/g;
+ s/\bHelp\b/Aid/g;
+ s/\bBoard List\b/Port/g;
+ s/\bCreate New Topic\b/Parley/g;
+ s/\bPost New Message\b/Parley/g;
+ s/\bNext Page\b/Next Map/g;
+ s/\bTagged\b/X\'d/g;
+ s/\bTag\b/X/g;
+
+ # From text-filter-suite/
+ s/\bmy\b/me/g;
+ s/\bboss\b/admiral/g;
+ s/\bmanager\b/admiral/g;
+ s/\b[Cc]aptain\b/Cap\'n/g;
+ s/\bmyself\b/meself/g;
+ s/\byour\b/yer/g;
+ s/\byou\b/ye/g;
+ s/\bfriend\b/matey/g;
+ s/\bfriends\b/maties/g;
+ s/\bco[-]?worker\b/shipmate/g;
+ s/\bco[-]?workers\b/shipmates/g;
+ s/\bpeople\b/scallywags/g;
+ s/\bearlier\b/afore/g;
+ s/\bold\b/auld/g;
+ s/\bthe\b/th\'/g;
+ s/\bof\b/o'/g;
+ s/\bdon\'t\b/dern\'t/g;
+ s/\bdo not\b/dern\'t/g;
+ s/\bnever\b/ne\'er/g;
+ s/\bever\b/e\'er/g;
+ s/\bover\b/o\'er/g;
+ s/\bYes\b/Aye/g;
+ s/\bNo\b/Nay/g;
+ s/\bYeah\b/Aye/g;
+ s/\byeah\b/aye/g;
+ s/\bdon\'t know\b/dinna/g;
+ s/\bdidn\'t know\b/did nay know/g;
+ s/\bhadn\'t\b/ha\'nae/g;
+ s/\bdidn\'t\b/di\'nae/g;
+ s/\bwasn\'t\b/weren\'t/g;
+ s/\bhaven\'t\b/ha\'nae/g;
+ s/\bfor\b/fer/g;
+ s/\bbetween\b/betwixt/g;
+ s/\baround\b/aroun\'/g;
+ s/\bto\b/t\'/g;
+ s/\bit\'s\b/\'tis/g;
+ s/\bwoman\b/wench/g;
+ s/\bwomen\b/wenches/g;
+ s/\blady\b/wench/g;
+ s/\bwife\b/lady/g;
+ s/\bgirl\b/lass/g;
+ s/\bgirls\b/lassies/g;
+ s/\bguy\b/lubber/g;
+ s/\bman\b/lubber/g;
+ s/\bfellow\b/lubber/g;
+ s/\bdude\b/lubber/g;
+ s/\bboy\b/lad/g;
+ s/\bboys\b/laddies/g;
+ s/\bchildren\b/little sandcrabs/g;
+ s/\bkids\b/minnows/g;
+ s/\bhim\b/that scurvey dog/g;
+ s/\bher\b/that comely wench/g;
+ s/\bhim\.\b/that drunken sailor/g;
+ s/\bHe\b/The ornery cuss/g;
+ s/\bShe\b/The winsome lass/g;
+ s/\bhe\'s\b/he be/g;
+ s/\bshe\'s\b/she be/g;
+ s/\bwas\b/were bein\'/g;
+ s/\bHey\b/Avast/g;
+ s/\bher\.\b/that lovely lass/g;
+ s/\bfood\b/chow/g;
+ s/\bmoney\b/dubloons/g;
+ s/\bdollars\b/pieces of eight/g;
+ s/\bcents\b/shillings/g;
+ s/\broad\b/sea/g;
+ s/\broads\b/seas/g;
+ s/\bstreet\b/river/g;
+ s/\bstreets\b/rivers/g;
+ s/\bhighway\b/ocean/g;
+ s/\bhighways\b/oceans/g;
+ s/\binterstate\b/high sea/g;
+ s/\bprobably\b/likely/g;
+ s/\bidea\b/notion/g;
+ s/\bcar\b/boat/g;
+ s/\bcars\b/boats/g;
+ s/\btruck\b/schooner/g;
+ s/\btrucks\b/schooners/g;
+ s/\bSUV\b/ship/g;
+ s/\bairplane\b/flying machine/g;
+ s/\bjet\b/flying machine/g;
+ s/\bmachine\b/contraption/g;
+ s/\bdriving\b/sailing/g;
+ s/\bunderstand\b/reckon/g;
+ s/\bdrive\b/sail/g;
+ s/\bdied\b/snuffed it/g;
+ s/ing\b/in\'/g;
+ s/ings\b/in\'s/g;
+
+ # These next two do cool random substitutions
+ #s/(\.\s)/e/avast("$0",3)/g;
+ #s/([!\?]\s)/e/avast("$0",2)/g; # Greater chance after exclamation
+
+
+# Add an opening phrase to each line randomly (see below)?
+
+
+ if ($do_split) {
+ # Combine the line again for output to STDOUT
+ $pieces[1] = $_;
+ print join '|', @pieces;
+ }
+ else {
+ print;
+ }
+}
+
+
+# Randomize use of this array, both in order and in frequency of
+# use. Not currently used at all.
+#my @shouts = (
+# ", avast$stub",
+# "$stub Ahoy!",
+# ", and a bottle of rum!",
+# ", by Blackbeard's sword$stub",
+# ", by Davy Jones' locker$stub",
+# "$stub Walk the plank!",
+# "$stub Aarrr!",
+# "$stub Yaaarrrrr!",
+# ", pass the grog!",
+# ", and dinna spare the whip!",
+# ", with a chest full of booty$stub",
+# ", and a bucket o' chum$stub",
+# ", we'll keel-haul ye!",
+# "$stub Shiver me timbers!",
+# "$stub And hoist the mainsail!",
+# "$stub And swab the deck!",
+# ", ye scurvey dog$stub",
+# "$stub Fire the cannons!",
+# ", to be sure$stub",
+# ", I'll warrant ye$stub",
+# ", on a dead man's chest!",
+# "$stub Load the cannons!",
+# "$stub Prepare to be boarded!",
+# ", I'll warrant ye$stub",
+# "$stub Ye'll be sleepin' with the fishes!",
+# "$stub The sharks will eat well tonight!",
+# "$stub Oho!",
+# "$stub Fetch me spyglass!",
+# );
+
+
+# Randomize use of this array both in order and frequency of use.
+# Not currently used at all.
+my @openings = (
+ 'Avast! ',
+ 'Yarrr! ',
+ 'Blimey! ',
+ 'Ahoy! ',
+ 'Harrr! ',
+ 'Aye aye! ',
+ 'Shiver me timbers! ',
+ 'Arrrr! '
+);
+
+
diff --git a/scripts/mapblast2geo.pl b/scripts/mapblast2geo.pl
new file mode 100755
index 0000000..01440b0
--- /dev/null
+++ b/scripts/mapblast2geo.pl
@@ -0,0 +1,200 @@
+#!/usr/bin/perl
+# $Id: mapblast2geo.pl,v 1.3 2002/03/05 21:28:23 we7u Exp $
+
+# XASTIR .geo file generator for mapblast pixel maps 16.10.2001
+# Copyright (C) 2001 Rolf Bleher http://www.dk7in.de
+
+# 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
+
+# see file COPYING for details
+
+#--------------------------------------------------------------------------
+
+use POSIX; # provides acos() function
+
+# some default values:
+$width = 1280; # seems to be the maximum supported by mapblast
+$height = 1024; # seems to be the maximum supported by mapblast
+$pfx = "../../pixelmaps/"; # prefix for path
+$pfx = "";
+
+# undefined values:
+$scale = 0;
+$lat = 9999;
+$lon = 9999;
+$help = 0;
+
+#--------------------------------------------------------------------------
+
+while (@ARGV) {
+ $arg = shift @ARGV;
+ if ($arg =~ /^\-N(\d{1,2}(\.\d+)?)$/) { $lat = $1 }
+ if ($arg =~ /^\-S(\d{1,2}(\.\d+)?)$/) { $lat = -$1 }
+ if ($arg =~ /^\-E(\d{1,3}(\.\d+)?)$/) { $lon = $1 }
+ if ($arg =~ /^\-W(\d{1,3}(\.\d+)?)$/) { $lon = -$1 }
+ if ($arg =~ /^\-w(\d+)$/) { $width = $1 }
+ if ($arg =~ /^\-h(\d+)$/) { $height= $1 }
+ if ($arg =~ /^\-s(\d+)$/) { $scale = $1 }
+ if ($arg =~ /^\-s(\d+)k$/) { $scale = $1 * 1000 }
+ if ($arg =~ /^\-s(\d+)M$/) { $scale = $1 * 1000000 }
+ if ($arg =~ /^\-p(.+)$/) { $pfx = $1 }
+ if ($arg eq '-?') { $help = 1 }
+ if ($arg eq '-h') { $help = 1 }
+ if ($arg eq '--help') { $help = 1 }
+}
+
+if (!$help && $arg && $arg !~ /^\-/) {
+ $file = $arg; # last arg is file name
+} else {
+ print("ERROR: Map file name is missing\n");
+ $help = 1;
+}
+
+if (!$help) {
+ if ($lat == 9999) { # we don't yet have a latitude
+ if ($file =~ /N(\d{1,2}(\.\d+)?)/) { $lat = $1 }
+ if ($file =~ /S(\d{1,2}(\.\d+)?)/) { $lat = -$1 }
+ }
+ if ($lon == 9999) { # we don't yet have a longitude
+ if ($file =~ /E(\d{1,3}(\.\d+)?)/) { $lon = $1 }
+ if ($file =~ /W(\d{1,3}(\.\d+)?)/) { $lon = -$1 }
+ }
+ if ($scale == 0) { # we don't yet have a map scale
+ if ($file =~ /\-(\d+)/) { $scale = $1 }
+ if ($file =~ /\-(\d+)k/) { $scale = $1 * 1000 }
+ if ($file =~ /\-(\d+)M/) { $scale = $1 * 1000000 }
+ }
+ if ($lat == 9999) { # we need a latitude
+ print("ERROR: Latitude is missing\n");
+ $help = 1;
+ }
+ if ($lon == 9999) { # we need a longitude
+ print("ERROR: Longitude is missing\n");
+ $help = 1;
+ }
+ if ($scale == 0) { # we need a map scale
+ print("ERROR: Map scale is missing\n");
+ $help = 1;
+ }
+}
+
+if ($help) {
+ usage();
+ exit 0;
+}
+
+if ($pfx && $pfx !~ /\/$/) { $pfx .= "/" } # add trailing '/' if missing
+
+#--------------------------------------------------------------------------
+
+if ($scale >= 1000000) {
+ printf("ERROR: Maps with scaling of 1M and above are not yet supported!\n");
+ printf(" They use a different projection...\n");
+ exit 1;
+}
+
+if (abs($lat) > 89) {
+ printf("ERROR: Map center too near to the poles!\n");
+ exit 1;
+}
+
+# This scaling factor is just a wild guess!
+# But I need one, and this one is nice AND works quite well... ;-)
+$scale_y = 100.0 * pi(); # pixel/degree at 1M map scale
+
+$scale_x = $scale_y * calcScale($lat); # adjust horizontal scale for latitude
+
+$scale_y *= (1000000 / $scale); # adjust for current map scale
+$scale_x *= (1000000 / $scale);
+
+#--------------------------------------------------------------------------
+
+# DK7IN: I'm not sure, if this formula is exact for what Xastir
+# is decoding, but in my region it works quite well
+# I need to do some further investigation for the best accuracy
+$latmin = $lat - ($height / 2.0 - 2.5) / $scale_y;
+$latmax = $lat + ($height / 2.0 - 0.5) / $scale_y;
+$lonmin = $lon - ($width / 2.0 - 0.5) / $scale_x;
+$lonmax = $lon + ($width / 2.0 - 2.5) / $scale_x;
+
+printf("FileName %s%s\n",$pfx,$file);
+printf("\n");
+printf("ImageSize %4d %4d\n",$width,$height);
+printf("TiePoint %4d %4d %10.6f %11.6f\n",0,0,$lonmin,$latmax);
+printf("TiePoint %4d %4d %10.6f %11.6f\n",$width-1,$height-1,$lonmax,$latmin);
+printf("Datum WGS84\n");
+printf("Projection LatLon\n");
+printf("\n");
+printf("# map from mapblast center %10.6f %11.6f, scale %d\n",$lat,$lon,$scale);
+printf("# created with mapblast2geo.pl (DK7IN)\n");
+
+exit 0;
+
+#--------------------------------------------------------------------------
+
+sub usage {
+ my $name = $0;
+ if ($name =~ /^.*\/(.+)$/) { $name = $1 }
+ print("\n");
+ print("$name (c) 2001 Rolf Bleher <Rolf\@dk7in.de>\n");
+ print("create Xastir .geo files for mapblast pixel maps\n");
+ print("usage: $name [options] mapfile\n");
+ print(" -N52.5 -S10 define latitude\n");
+ print(" -E13.3 -W0.5 define longitude\n");
+ print(" -h1024 define map height in pixels (default 1024)\n");
+ print(" -w1280 define map width in pixels (default 1280)\n");
+ print(" -s50000 define map scale, 50k or 1M is ok\n");
+ print(" -p../pixmaps define prefix for path\n");
+ print(" -h -? --help print this help file\n");
+ print(" it tries to extract center Lat/Lon and map scale\n");
+ print(" from the filename like N52.5E13.3-50k.xpm\n");
+ print("\n");
+}
+
+#--------------------------------------------------------------------------
+
+sub pi {
+ return(3.14159265358979323846);
+}
+
+#--------------------------------------------------------------------------
+
+sub deg2rad {
+ my ($deg) = @_;
+ return($deg * pi()/180.0);
+}
+
+#--------------------------------------------------------------------------
+
+# Calculate distance in meters between two locations
+sub dist {
+ my ($lat1, $lon1, $lat2, $lon2) = @_;
+ my $r_lat1 = deg2rad($lat1);
+ my $r_lon1 = deg2rad($lon1);
+ my $r_lat2 = deg2rad($lat2);
+ my $r_lon2 = deg2rad($lon2);
+ my $r_d = acos(sin($r_lat1) * sin($r_lat2) + cos($r_lat1) * cos($r_lat2) * cos($r_lon1-$r_lon2));
+ return($r_d*180.0*60.0/pi()*1852.0);
+}
+
+#--------------------------------------------------------------------------
+
+sub calcScale { # EW / NS scaling
+ my ($lat) = @_;
+ return(dist($lat,-1.0/120.0,$lat,1.0/120.0) / 1852.0);
+}
+
+#--------------------------------------------------------------------------
+
diff --git a/scripts/mapfgd.pl b/scripts/mapfgd.pl
new file mode 100755
index 0000000..e7342bb
--- /dev/null
+++ b/scripts/mapfgd.pl
@@ -0,0 +1,258 @@
+#!/usr/bin/perl
+# -*- perl -*-
+# Written by Derrick J Brashear, KB3EGH
+# Released to the public domain.
+
+# $Id: mapfgd.pl,v 1.5 2010/07/03 22:09:48 we7u Exp $
+
+# Usage: mapfgd <directory>
+# Creates fake fgd files for all correctly USGS-named maps which don't
+# already have them
+
+local (@dirlist) = @ARGV;
+local ($mapdir);
+foreach $mapdir (@dirlist)
+{
+ opendir (DIR, $mapdir) || die "mapini: couldn't open directory \`$mapdir': $!\n";
+ local ($file, $fullfile, $expr, $mlat, $mlon, $mlats, $mlons);
+ local ($nlat, $nlon, $nlats, $nlons);
+ local ($dlat, $dlon, $inifile);
+ local ($imgwidth, $imglength, $imgres, $imgdepth, $imgphotometric);
+ local ($imgtimestamp);
+ foreach $file (sort grep (! /^\./, readdir (DIR)))
+ {
+ # Only examine .tif files.
+ next unless $file =~ /\.tif$/;
+ next unless $file =~ /^[iIoOcCfFkKlLpPjJgG]/;
+ $fullfile = $mapdir . '/' . $file;
+ $inifile = $mapdir . '/' . $file;
+ $inifile =~ s/\.tif$/.fgd/;
+ next if (-f $inifile);
+ open (INI, ">$inifile");
+ $file =~ /^([iIoOcCfFkKlLpPjJgG])([0-9][0-9])([0-9][0-9][0-9])([a-hA-H])([1-8])/;
+ $letter = $1;
+ $mlat = $2;
+ $mlon = $3;
+ $mlats = $4;
+ $mlons = $5;
+
+ if ($letter eq 'c') {
+ $dlon = 0-$mlon-2;
+ printf INI "1.5.1.1 WEST BOUNDING COORDINATE: %.6f\n", $dlon;
+ $dlon = 0-$mlon;
+ printf INI "1.5.1.2 EAST BOUNDING COORDINATE: %.6f\n", $dlon;
+ $dlat = $mlat+1;
+ printf INI "1.5.1.3 NORTH BOUNDING COORDINATE: %.6f\n", $dlat;
+ $dlat = $mlat;
+ printf INI "1.5.1.4 SOUTH BOUNDING COORDINATE: %.6f\n", $dlat;
+ } else {
+ if (($letter eq 'f') || ($letter eq 'g')){
+ $dlon = 0-$mlon-1;
+ printf INI "1.5.1.1 WEST BOUNDING COORDINATE: %.6f\n", $dlon;
+ $dlon = 0-$mlon-(.125*$mlons)+.125;
+ printf INI "1.5.1.2 EAST BOUNDING COORDINATE: %.6f\n", $dlon;
+ $dlat = $mlat+.375+(.125*(&lettonum ($mlats)));
+ printf INI "1.5.1.3 NORTH BOUNDING COORDINATE: %.6f\n", $dlat;
+ $dlat = $mlat-.125+(.125*(&lettonum ($mlats)));
+ printf INI "1.5.1.4 SOUTH BOUNDING COORDINATE: %.6f\n", $dlat;
+ } else {
+ if ($letter eq 'k') {
+ $dlon = 0-$mlon-(.125*$mlons)-.125;
+ printf INI "1.5.1.1 WEST BOUNDING COORDINATE: %.6f\n", $dlon;
+ $dlon = 0-$mlon-(.125*$mlons)+.125;
+ printf INI "1.5.1.2 EAST BOUNDING COORDINATE: %.6f\n", $dlon;
+ $dlat = $mlat+(.125*(&lettonum ($mlats)));
+ printf INI "1.5.1.3 NORTH BOUNDING COORDINATE: %.6f\n", $dlat;
+ $dlat = $mlat-.125+(.125*(&lettonum ($mlats)));
+ printf INI "1.5.1.4 SOUTH BOUNDING COORDINATE: %.6f\n", $dlat;
+ } else {
+ if ($letter eq 'i') {
+ $dlon = 0-$mlon-(.125*$mlons)-.250;
+ printf INI "1.5.1.1 WEST BOUNDING COORDINATE: %.6f\n", $dlon;
+ $dlon = 0-$mlon-(.125*$mlons)+.125;
+ printf INI "1.5.1.2 EAST BOUNDING COORDINATE: %.6f\n", $dlon;
+ $dlat = $mlat+.125+(.125*(&lettonum ($mlats)));
+ printf INI "1.5.1.3 NORTH BOUNDING COORDINATE: %.6f\n", $dlat;
+ $dlat = $mlat-.125+(.125*(&lettonum ($mlats)));
+ printf INI "1.5.1.4 SOUTH BOUNDING COORDINATE: %.6f\n", $dlat;
+ } else {
+ $dlon = 0-$mlon-(.125*$mlons);
+ printf INI "1.5.1.1 WEST BOUNDING COORDINATE: %.6f\n", $dlon;
+ $dlon = 0-$mlon-(.125*$mlons)+.125;
+ printf INI "1.5.1.2 EAST BOUNDING COORDINATE: %.6f\n", $dlon;
+ $dlat = $mlat+(.125*(&lettonum ($mlats)));
+ printf INI "1.5.1.3 NORTH BOUNDING COORDINATE: %.6f\n", $dlat;
+ $dlat = $mlat-.125+(.125*(&lettonum ($mlats)));
+ printf INI "1.5.1.4 SOUTH BOUNDING COORDINATE: %.6f\n", $dlat;
+ }
+ }
+ }
+ }
+
+ close (INI);
+ }
+ closedir (DIR);
+}
+
+sub lettonum
+{
+ local ($let) = @_;
+ if ($let eq 'a')
+ {return 1;}
+ if ($let eq 'b')
+ {return 2;}
+ if ($let eq 'c')
+ {return 3;}
+ if ($let eq 'd')
+ {return 4;}
+ if ($let eq 'e')
+ {return 5;}
+ if ($let eq 'f')
+ {return 6;}
+ if ($let eq 'g')
+ {return 7;}
+ if ($let eq 'h')
+ {return 8;}
+}
+sub nextlet
+{
+ local ($let,$scale) = @_;
+ if ($scale eq 'c')
+ {$nlat++;return 'a';}
+ if ($scale eq 'f') {
+ if ($let eq 'a')
+ {return 'e';}
+ if ($let eq 'e')
+ {$nlat++;return 'a';}
+ }
+ if ($let eq 'a')
+ {return 'b';}
+ if ($let eq 'b')
+ {return 'c';}
+ if ($let eq 'c')
+ {return 'd';}
+ if ($let eq 'd')
+ {return 'e';}
+ if ($let eq 'e')
+ {return 'f';}
+ if ($let eq 'f')
+ {return 'g';}
+ if ($let eq 'g')
+ {return 'h';}
+ if ($let eq 'h')
+ {$nlat++;return 'a';}
+}
+sub nextnum
+{
+ local ($let,$scale) = @_;
+ if ($scale eq 'c') {
+ $nlon+=2;
+ if ($nlon < 100) {
+ $nlon="0$nlon";
+ }
+ return '1';
+ }
+ if ($scale eq 'f') {
+ $nlon++;
+ if ($nlon < 100) {
+ $nlon="0$nlon";
+ }
+ return '1';
+ }
+ if ($let eq '1')
+ {return '2';}
+ if ($let eq '2')
+ {return '3';}
+ if ($let eq '3')
+ {return '4';}
+ if ($let eq '4')
+ {return '5';}
+ if ($let eq '5')
+ {return '6';}
+ if ($let eq '6')
+ {return '7';}
+ if ($let eq '7')
+ {return '8';}
+ if ($let eq '8')
+ {$nlon++;
+ if ($nlon < 100) {
+ $nlon="0$nlon";
+ }
+ return '1';}
+}
+sub oldlastnum
+{
+ local ($let,$scale) = @_;
+ if ($let = 1)
+ {print INI "let was 1\n";$let=9; $nlon--; $nlon="0$nlon";}
+ $let--;
+ return $let;
+}
+sub lastnum
+{
+ local ($let,$scale) = @_;
+ if ($scale eq 'c') {
+ $nlon-=2;
+ if ($nlon < 100) {
+ $nlon="0$nlon";
+ }
+ return '1';
+ }
+ if ($scale eq 'f') {
+ $nlon--;
+ if ($nlon < 100) {
+ $nlon="0$nlon";
+ }
+ return '1';
+ }
+ if ($let eq '1') {
+ $nlon--;
+ if ($nlon < 100) {
+ $nlon="0$nlon";
+ }
+ return '8';
+ }
+ if ($let eq '2')
+ {return '1';}
+ if ($let eq '3')
+ {return '2';}
+ if ($let eq '4')
+ {return '3';}
+ if ($let eq '5')
+ {return '4';}
+ if ($let eq '6')
+ {return '5';}
+ if ($let eq '7')
+ {return '6';}
+ if ($let eq '8')
+ {return '7';}
+}
+sub lastlet
+{
+ local ($let,$scale) = @_;
+ if ($scale eq 'c')
+ {$nlat--;return 'a';}
+ if ($scale eq 'f') {
+ if ($let eq 'a')
+ {$nlat--;return 'e';}
+ if ($let eq 'e')
+ {return 'a';}
+ }
+ if ($let eq 'a')
+ {$nlat--;return 'h';}
+ if ($let eq 'b')
+ {return 'a';}
+ if ($let eq 'c')
+ {return 'b';}
+ if ($let eq 'd')
+ {return 'c';}
+ if ($let eq 'e')
+ {return 'd';}
+ if ($let eq 'f')
+ {return 'e';}
+ if ($let eq 'g')
+ {return 'f';}
+ if ($let eq 'h')
+ {return 'g';}
+}
+
diff --git a/scripts/object2shp.pl b/scripts/object2shp.pl
new file mode 100755
index 0000000..588f2c2
--- /dev/null
+++ b/scripts/object2shp.pl
@@ -0,0 +1,147 @@
+#!/usr/bin/env perl
+#
+# $Id: object2shp.pl,v 1.5 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2006-2012 Tom Russo
+
+# 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
+
+# see file COPYING for details
+
+#--------------------------------------------------------------------------
+
+# This script produces an ESRI point shapefile from the object.log file,
+# according to the "Rolling your own shapefile maps" section of README.MAPS
+# The point file will display using the TIGER Landmark Point dbfawk file
+#
+# This enables fast generation of point maps by using xastir to plop down
+# objects, then this script to turn the object.log file into a shapefile
+#
+# Typical usage:
+# object2shp.pl object.log myshape
+#
+# Remember to exit xastir and delete "object.log", otherwise xastir will
+# never forget your objects.
+#--------------------------------------------------------------------------
+
+
+if ($#ARGV != 1)
+{
+ print "Usage: $0 <object_file> <shapefile base name>\n";
+ exit 1;
+}
+
+
+open(INOBJ,"<$ARGV[0]") || die "Cannot open input object file $ARGV[0]\n";
+
+$cmd[0]="shpcreate $ARGV[1] point";
+$cmd[1]="dbfcreate $ARGV[1] -n ID 8 0 -s CFCC 4 -s NAME 30";
+$outfile=$ARGV[1];
+
+
+
+
+foreach $command (@cmd)
+{
+ system($command);
+ if ($? == -1)
+ {
+ print "failed to execute: $!\n";
+ }
+ elsif ($? & 127)
+ {
+ printf "child died with signal %d, %s coredump\n",
+ ($? & 127), ($? & 128) ? 'with' : 'without';
+ }
+ elsif ($?&0xF0)
+ {
+ printf "child exited with value %d\n", $? >> 8;
+ }
+}
+
+# We now have the shapefile and dbf file created, start populating from the
+# objects file:
+
+$i=0;
+while (<INOBJ>)
+{
+ chomp($_);
+ $semicolon=substr($_,0,1);
+ $name=substr($_,1,9);
+ $live_or_dead=substr($_,10,1);
+ $timestamp=substr($_,11,7);
+ $lat=substr($_,18,8);
+ $symtab=substr($_,26,1);
+ $long=substr($_,27,9);
+ $sym=substr($_,36,1);
+
+#sanity check --- don't try to convert if the line doesn't conform to what
+# it should, or if it represents a killed object. Sometimes objects get
+# commented out with #, etc.
+ next if ($semicolon ne ";");
+ next if ($live_or_dead eq "_");
+
+ $i++; # bump the ID number so every point has a unique one
+
+ $lat_deg=substr($lat,0,2);
+ $lat_min=substr($lat,2,5);
+ $lat_hem=substr($lat,7,1);
+
+ $long_deg=substr($long,0,3);
+ $long_min=substr($long,3,5);
+ $long_hem=substr($long,8,1);
+
+ $lat=$lat_deg+$lat_min/60;
+ $lat *= -1 if ($lat_hem eq "S");
+
+ $long=$long_deg+$long_min/60;
+ $long *= -1 if ($long_hem eq "W");
+
+ # Construct symbol
+
+ if ($symtab ne "/" && $symtab ne "\\")
+ {
+ print "overlay symbol, symtab is $symtab\n";
+ $overlay=$symtab;
+ $symtab="\\";
+ print " reset values symtab is $symtab, overlay is $overlay\n";
+ }
+ else
+ {
+ $overlay=" ";
+ }
+
+ $cmd[0]="shpadd $outfile $long $lat";
+ $cmd[1]="dbfadd $outfile $i \'X$symtab$sym$overlay\' $name";
+ print $cmd[1]."\n";
+ foreach $command (@cmd)
+ {
+ system($command);
+ if ($? == -1)
+ {
+ print "failed to execute: $!\n";
+ }
+ elsif ($? & 127)
+ {
+ printf "child died with signal %d, %s coredump\n",
+ ($? & 127), ($? & 128) ? 'with' : 'without';
+ }
+ elsif ($?&0xF0)
+ {
+ printf "child exited with value %d\n", $? >> 8;
+ }
+ }
+
+}
diff --git a/scripts/overlay.pl b/scripts/overlay.pl
new file mode 100755
index 0000000..61d8fdb
--- /dev/null
+++ b/scripts/overlay.pl
@@ -0,0 +1,248 @@
+#!/usr/bin/perl
+
+
+# Written by Curt Mills, WE7U
+# Released to the public domain.
+#
+# $Id: overlay.pl,v 1.5 2010/07/03 22:09:48 we7u Exp $
+
+
+# Script to create Xastir "Overlay" files from "CSV" files of the
+# proper format (comma-delimited files).
+#
+# 1) Creates files in Xastir "log" format if you enter a callsign
+# below. These files can then be put in your ~/.xastir/logs/
+# directory and brought in via the File->Open Log File menu option.
+# If you start with the CSV files in the ~/.xastir/logs/ directory
+# and process them there with this script, the output files will be
+# placed into the proper place for Xastir to find them.
+#
+# 2) If no callsign is entered, this script will create files in
+# Xastir's "~/.xastir/config/object.log" format. You can then
+# replace or append the file to the object.log file, restart Xastir
+# or "Reload Object/Item History".
+#
+# NOTE: These APRS Items will become part of your locally
+# owned/transmitted objects, so if you don't want them transmitted,
+# turn of Object/Item transmit before bringing them in.
+#
+# Input: Directory name. If no directory name passed in, it will
+# operate on every CSV file in the current directory.
+#
+# Input format:
+# Name N/S lat E/W long // comment fields.............
+# SUPPLY,N,34.0000,W,78.0000,ICON,text1,text2,text3,text4,...
+#
+#
+# The name will have spaces removed if it is longer than nine
+# characters. If it is still too long, vowels will be removed, then
+# it will be truncated to nine characters if still needed. The full
+# name will be transmitted as a comment. All other text fields will
+# also be transmitted as comments, so that they will all appear in
+# the Station Info dialog.
+#
+# Icons will be a default small red circle unless '/' or '\' is the
+# leading character in that field and the next specifies the APRS
+# symbol. In that case the two-letter combination will get used as
+# the symbol for the Item.
+
+
+
+# Change this to match whatever callsign you're running Xastir as,
+# so that the APRS Items appear to have been generated locally. You
+# can then suck this file in as a "log" file from within Xastir. If
+# this field is empty, then instead write the packets out without a
+# header, as in Xastir's "object.log" format.
+$callsign = "";
+
+if ($callsign ne "") {
+ $callsign = uc($callsign) . '>APRS:';
+}
+
+
+
+# Main program. Process every ".csv" file found in the directory.
+#
+$dirname = shift;
+if ($dirname == "") {
+ $dirname = ".";
+}
+
+opendir(DIR, $dirname) or die "Can't opendir $dirname: %!";
+
+while (defined($file = readdir(DIR))) {
+ chomp $file;
+
+ if ( $file =~ /\.csv$/ ) {
+
+ # Do something with "$dirname/$file"
+ &process_file($dirname, $file);
+ }
+ else {
+# printf("$dirname/$file\n");
+ }
+}
+
+
+
+# Process one file. Creates an output file that matches the
+# basename but changes the "csv" to "overlay".
+#
+sub process_file() {
+
+ $output_file = $_[1];
+ $output_file =~ s/\.csv$/.overlay/;
+
+ printf("$dirname/$file -> $output_file\n");
+
+ open(SOURCE, "< $_[1]")
+ or die "Couldn't open $path for reading: $!\n";
+
+ open(OUTPUT, "> $output_file")
+ or die "Couldn't open $output_file for writing: $!\n";
+
+ while (<SOURCE>) {
+ &process_line($_);
+ }
+
+ close(SOURCE);
+ close(OUTPUT);
+}
+
+
+
+# Process one line. Write the formatted data to the OUTPUT file.
+#
+sub process_line() {
+ #printf("$_[0]");
+
+ # Parse the CSV line into an array
+ @list = parse_csv($_[0]);
+
+ if (!($list[0] =~ m/Location/i)) {
+ #print OUTPUT @list;
+
+ # As a temporary measure, create items out of each of the lines,
+ # with a status line for each extra data object so that they
+ # appear in the Station Info dialog.
+ &create_items(@list);
+ }
+}
+
+
+
+# Create an APRS Item out of each array. Create a status line for
+# each extra column associated with a line so that the info shows up
+# in the Station Info dialog.
+#
+# Examples. Name is 3-9 characters:
+# )AID #2!4903.50N/07201.75WA
+# )G/WB4APR!53 . N\002 . Wd
+#
+sub create_items {
+
+ $name = $_[0];
+ if ($name eq "") {
+ printf("Error, name column is empty\n");
+ }
+
+ # If too long, try removing spaces first
+ if (length($name) > 9) {
+ $name =~ s/\s//ig;
+ }
+
+ # If still too long, remove vowels
+ if (length($name) > 9) {
+ $name =~ s/a//ig;
+ $name =~ s/e//ig;
+ $name =~ s/i//ig;
+ $name =~ s/o//ig;
+ $name =~ s/u//ig;
+ }
+
+ # Extend to three characters if short
+ if (length($name) < 3) {
+ $name = $name . " ";
+ }
+
+ $name = substr($name,0,9);
+ $name[9] = "\0"; # Terminate name at 9 characters, minimum 3
+
+ $n_s = uc( substr($_[1],0,1) );
+ $latitude = $_[2];
+ $e_w = uc( substr($_[3],0,1) );
+ $longitude = $_[4];
+ if ($_[5] =~ /ICON/i) {
+ $icon1 = "/";
+ $icon2 = "/";
+ }
+ else {
+ $icon1 = substr($_[5],0,1);
+ $icon2 = substr($_[5],1,1);
+ }
+
+ # Convert lat/long to APRS format (or Base-91 Compressed format)
+ $lat_deg = $latitude;
+ $lat_deg =~ s/\.\d+$//;
+ $lat_deg = sprintf("%02d", $lat_deg);
+ $lat_min = $latitude;
+ $lat_min =~ s/^\d+\./0./;
+ $lat_min = $lat_min * 60.0;
+ $lon_deg = $longitude;
+ $lon_deg =~ s/\.\d+$//;
+ $lon_deg = sprintf("%03d", $lon_deg);
+ $lon_min = $longitude;
+ $lon_min =~ s/^\d+\./0./;
+ $lon_min = $lon_min * 60;
+
+ # Create an APRS "Item" packet
+ $line = sprintf("%s)%s!%s%05.2f%s%s%s%05.2f%s%s",
+ $callsign,
+ $name,
+ $lat_deg,
+ $lat_min,
+ $n_s,
+ $icon1,
+ $lon_deg,
+ $lon_min,
+ $e_w,
+ $icon2);
+
+ # Go process the rest of the columns, if any. Create APRS Item
+ # packets with comments from them.
+ for ($i = 6; $i < 106; $i++) {
+ chomp $_[$i];
+ if ($_[$i] ne "") {
+ #printf("$_[$i]");
+ printf(OUTPUT "%s%s\n",
+ $line,
+ $_[$i]);
+ }
+ }
+
+ # Write it out to the file, with the full name as a comment
+ printf(OUTPUT "%s%s\n",
+ $line,
+ $_[0]);
+}
+
+
+
+# Parse CVS line into an array, removing double-quotes and such if
+# found.
+#
+sub parse_csv {
+ my $text = shift; # Record containing comma-separated values
+ my @new = ();
+ push(@new, $+) while $text =~ m{
+ # The first part groups the phrase inside the quotes.
+ # See explanation of this pattern in MRE
+ "([^\"\\]*(?:\\.[^\"\\]*)*)",?
+ | ([^,]+),?
+ | ,
+ }gx;
+ push(@new, undef) if substr($text, -1, 1) eq ',';
+ return @new; # List of values that were comma-separated
+}
+
+
diff --git a/scripts/ozi2geo.pl b/scripts/ozi2geo.pl
new file mode 100755
index 0000000..10f98a4
--- /dev/null
+++ b/scripts/ozi2geo.pl
@@ -0,0 +1,211 @@
+#!/usr/bin/perl
+
+# Written by Curt Mills, WE7U
+# Released to the public domain.
+# Modified from the earlier inf2geo.pl script.
+#
+# $Id: ozi2geo.pl,v 1.6 2010/07/03 22:09:48 we7u Exp $
+#
+# Read in .map file (an OziExplorer file in this case).
+# Check the version of the map format (1st line). My example is
+# version 2.2.
+# Get the filename from the 2nd line of the file.
+# Check that "WGS 84" or "NAD 83" are present in the file (5th
+# line?).
+# Check the "Map Projection".
+# Grab the first four points, which hopefully are the corners.
+# Snag the MMPXY lines and the MMPLL lines. These are the X/Y and
+# Lat/Long of the corners in the example I have.
+# Write out the .geo file
+#
+# 2003-08-15 ZL2UMF: add processing multiple files in one go (masks
+# and whot-not) so you can convert all your maps in one step.
+
+#use strict;
+use IO::File;
+
+
+#go through every filename passed to this script
+foreach my $file (@ARGV) {
+ print "*** $file ***\n";
+
+ #make a geo of this file
+ makeGeo ($file);
+
+}
+
+exit; #just in case
+
+
+
+
+
+sub makeGeo {
+ my $ozimap_filename = shift;
+
+ # Snag the filename out of the .map file instead? Here we
+ # create it from the.map filename.
+ #
+ my $filename = $ozimap_filename;
+ $filename =~ s/\.map$//i;
+
+ my $geo_filename = $filename . ".geo";
+
+# $ozimap = IO::File->new("< $ARGV[0].map")
+# or $ozimap = IO::File->new("< $ARGV[0].MAP")
+# or $ozimap = IO::File->new("< $ARGV[0].Map")
+
+ #skip this file if geo already exists
+ return print "$filename.geo already exists, will not overwrite\n" if( -e "$filename.geo" );
+
+ #read the map file
+ my $ozimap = IO::File->new ( "< $ozimap_filename" )
+ or return print "\nCouldn't open $ozimap_filename for reading:\n$!\n\n";
+
+ #make the new geo file
+ $geo = IO::File->new("> $geo_filename")
+ or return print "Couldn't open $geo_filename for writing: $!\n";
+
+ # First line should be something like:
+ # "OziExplorer Map Data File Version 2.2"
+ #
+ $tmp = $ozimap->getline();
+print "\t$tmp";
+
+ $final_filename = $ozimap->getline();
+ chomp($final_filename);
+#print $final_filename;
+
+# Check that the filename we just read matches the filename we
+# created from the .map filename.
+
+ $tmp = $ozimap->getline();
+#print $tmp;
+
+ $tmp = $ozimap->getline();
+
+ # Get the datum
+ $tmp = $ozimap->getline();
+#print $tmp;
+
+# Check that the datum is "WGS 84", "WGS84", "NAD 83", or "NAD83".
+ if ($tmp =~ /WGS 84/i
+ || $tmp =~ /WGS84/i
+ || $tmp =~ /NAD 83/i
+ || $tmp =~ /NAD83/i) {
+ }
+ else {
+ print "***Datum is not WGS84 or NAD83: Results will be inaccurate***\n";
+ }
+
+ # Read until we find "Map Projection" at the start of a line.
+ #
+ $done = 0;
+ while (!$done) {
+ $tmp = $ozimap->getline();
+#print $tmp;
+ if ($tmp=~ /Map Projection/) {
+ $done++;
+ }
+ }
+ if ($tmp =~ /UTM/i) {
+ print "***Found UTM projection: Results will be inaccurate***\n";
+#print "$tmp";
+ }
+
+# We have the map projection. Check it. Issue a warning if it's
+# not what we can handle easily.
+
+ # Read until we find "MMPXY" at the start of a line.
+ #
+ $done = 0;
+ while (!$done) {
+ $tmp = $ozimap->getline();
+ if ($tmp=~ /MMPXY/) {
+ $done++;
+ }
+ }
+ $MMPXY1 = $tmp;
+#print $MMPXY1;
+ $MMPXY2 = $ozimap->getline();
+#print $MMPXY2;
+ $MMPXY3 = $ozimap->getline();
+#print $MMPXY3;
+ $MMPXY4 = $ozimap->getline();
+#print $MMPXY4;
+ $MMPLL1 = $ozimap->getline();
+#print $MMPLL1;
+ $MMPLL2 = $ozimap->getline();
+#print $MMPLL2;
+ $MMPLL3 = $ozimap->getline();
+#print $MMPLL3;
+ $MMPLL4 = $ozimap->getline();
+#print $MMPLL4;
+
+# If the corners are always listed in circular order, we can choose
+# to use corners 1 and 3 for our tiepoints. Try this.
+
+
+ # Read until we find "Map Image Width" inside a line.
+ #
+ $done = 0;
+ while (!$done) {
+ $tmp = $ozimap->getline();
+ if ($tmp=~ /Map Image Width/) {
+ $done++;
+ }
+ }
+#print $tmp;
+ $image_size = $tmp;
+
+# That should be all that we need to read from the file.
+
+ # Get the X/Y for the tiepoints
+ my ($a, $b, $x0, $y0) = split(',', $MMPXY1);
+ chomp($x0);
+ chomp($y0);
+ # Convert to numbers
+ $x0 = $x0 * 1;
+ $y0 = $y0 * 1;
+
+#print "$x0 $y0\n";
+
+ my ($a, $b, $x1, $y1) = split(',', $MMPXY3);
+ chomp($x1);
+ chomp($y1);
+ # Convert to numbers
+ $x1 = $x1 * 1;
+ $y1 = $y1 * 1;
+
+#print "$x1 $y1\n";
+
+ # Get the lat/long for the tiepoints
+ my ($a, $b, $tp0_lon, $tp0_lat) = split(',', $MMPLL1);
+ chomp($tp0_lon);
+ chomp($tp0_lat);
+
+#print "$tp0_lon $tp0_lat\n";
+
+ my ($a, $b, $tp1_lon, $tp1_lat) = split(',', $MMPLL3);
+ chomp($tp1_lon);
+ chomp($tp1_lat);
+
+#print "$tp1_lon $tp1_lat\n";
+
+ # Split out the imagesize string
+ my ($a, $b, $width, $height) = split(',', $image_size);
+ chomp($width);
+ chomp($height);
+
+ #write to the geo file
+ printf $geo "FILENAME $final_filename\n";
+ printf $geo "TIEPOINT $x0\t\t$y0\t$tp0_lon\t$tp0_lat\n";
+ printf $geo "TIEPOINT $x1\t$y1\t$tp1_lon\t$tp1_lat\n";
+ printf $geo "IMAGESIZE $width\t$height\n";
+ printf $geo "#\n# Converted from an OziExplorer .MAP file by WE7U's ozi2geo.pl script\n#\n";
+
+ $ozimap->close();
+ $geo->close();
+}
+
+
diff --git a/scripts/permutations.pl b/scripts/permutations.pl
new file mode 100755
index 0000000..8baca20
--- /dev/null
+++ b/scripts/permutations.pl
@@ -0,0 +1,391 @@
+#!/usr/bin/perl -w
+
+
+#
+# Written by Paul Lutt, KE7XT & Curt Mills, WE7U.
+# Released to the public domain.
+#
+#
+# $Id: permutations.pl,v 1.11 2010/07/03 22:09:48 we7u Exp $
+#
+#
+# Finds the different lat/long representations corresponding to the
+# input numbers. A space is required between the degrees portion
+# and the rest of the input. Writes out a log file containing APRS
+# objects suitable for importing into Xastir, to graphically plot
+# the locations of the objects. Now that Xastir has a server port
+# we could directly inject them into the program via that route as
+# well, but we currently don't do that.
+#
+# Converts between different lat/lon formats. Will also give UMS
+# position if the lat/lon resides somewhere inside the Seattle area
+# aeronautical map.
+#
+# UMS coordinates have been used in the past by King County, WA SAR.
+# It can be useful for plotting positions on Green Trails maps and
+# perhaps other maps. The maps must be 15' topo maps and marked in
+# tenths of miles along the edge in order to make use of this
+# coordinate system.
+#
+# Web pages which discuss UMS format:
+# http://www.impulse.net/~mlynch/land_nav.html
+# http://www.logicsouth.com/~lcoble/dir9/land_nav.htm
+# http://www.aasar.org/training/academy/navigation.pdf
+#
+
+
+use lib "/usr/local/lib";
+use Coordinate; # WE7U's Coordinate.pm module
+
+
+# Get the username
+$user = getlogin;
+chomp $user;
+$filename = "/var/tmp/PERMUTATIONS-$user.log";
+
+
+sub convert {
+
+ # Snag the input
+ $_ = $_[0];
+
+ print "\n";
+
+ # If the first item has 2 digits and one character and there are
+ # three "words" in the input, we're starting with a UTM value.
+ if (/^\d\d[a-zA-Z]\s+\w+\s+\w+\s*$/) {
+
+ # printf("Found a UTM value\n");
+
+ # We'll convert it to the standard format first and then run
+ # through the rest of the code.
+
+ $zone = $_;
+ $easting = $_;
+ $northing = $_;
+
+ $zone =~ s/^(\d\d[a-zA-Z])\s+\w+\s+\w+\s*$/$1/;
+ $easting =~ s/^\d\d[a-zA-Z]\s+(\w+)\s+\w+\s*$/$1/;
+ $northing =~ s/^\d\d[a-zA-Z]\s+\w+\s+(\w+)\s*$/$1/;
+
+ if ($easting > 999999) {
+ printf("Easting value is too high!\n");
+ return;
+ }
+
+ $position->zone($zone);
+ $position->easting($easting);
+ $position->northing($northing);
+
+ # Convert to lat/lon values
+ $position->utm_to_lat_lon();
+
+ # printf("Calculated Lat, Long position(Lat, Long): %f %f\n",
+ # $position->latitude(),
+ # $position->longitude() );
+
+ $latitude = $position->latitude();
+ $longitude = $position->longitude();
+
+ $lat_dir = "N";
+ $long_dir = "E";
+
+ if ($latitude < 0.0) {
+ $latitude = abs($latitude);
+ $lat_dir = "S"
+ }
+ if ($longitude < 0.0) {
+ $longitude = abs($longitude);
+ $long_dir = "W";
+ }
+
+
+ # printf("%f%s %f%s\n", $latitude,$lat_dir,$longitude,$long_dir);
+
+ $_ = sprintf("%f%s %f%s",
+ $latitude,$lat_dir,$longitude,$long_dir);
+
+ }
+
+ # Look for lat/long value in the input
+
+ # Check for N/S/E/W characters in the input. Set the
+ # appropriate flags if found.
+ $lat_dir = "N";
+ $long_dir = "E";
+ if (/S/ || /s/) { $lat_dir = "S"; }
+ if (/W/ || /w/) { $long_dir = "W"; }
+ # Filter out these characters from the input
+ tr/nsewNSEW//d;
+
+ # Convert to DD MM SS format
+ ($lat_deg, $lat_min, $lat_sec,
+ $long_deg, $long_min, $long_sec) = split(' ');
+
+ # Decimal Degrees?
+ if ($lat_deg =~ /\./) {
+
+ $long_deg = $lat_min; # Save long_degrees in proper place
+
+ $temp = $lat_deg;
+ $lat_deg = int $temp;
+ $lat_min = int ((abs($temp) * 60.0) % 60);
+
+ # Modulus converts to integers, so we bump up by 10 and then
+ # back down.
+ $lat_sec = (abs($temp) * 36000.0) % 600;
+ $lat_sec = $lat_sec / 10;
+
+ $temp = $long_deg;
+
+ $long_deg = int $temp;
+ $long_min = int ((abs($temp) * 60.0) % 60);
+ $long_sec = (abs($temp) * 36000.0) % 600;
+ $long_sec = $long_sec / 10;
+ }
+ # Decimal Minutes?
+ elsif ($lat_min =~ /\./) {
+
+ $long_min = $long_deg; # Save long_minutes in proper place
+ $long_deg = $lat_sec; # Save long_degrees in proper place
+
+ $temp = $lat_min;
+ $lat_min = int abs($temp);
+ $lat_sec = (abs($temp) * 60.0) % 60;
+ $lat_sec = $lat_sec / 10;
+
+ $temp = $long_min;
+ $long_min = int abs($temp);
+ $long_sec = (abs($temp) * 600.0) % 600;
+ $long_sec = $long_sec / 10;
+ }
+ # Decimal Seconds
+ else { # Already in DD MM SS format, don't convert
+ }
+
+ # Print out the three lat/long formats
+ printf(" Decimal Degrees: %8.5f%s %8.5f%s\n",
+ $lat_deg + ($lat_min/60.0) + ($lat_sec/3600.0), $lat_dir,
+ $long_deg + ($long_min/60.0) + ($long_sec/3600.0), $long_dir );
+
+ printf(" Degrees/Decimal Minutes: %02d %06.3f%s %02d %06.3f%s\n",
+ $lat_deg, $lat_min + ($lat_sec/60.0), $lat_dir,
+ $long_deg, $long_min + ($long_sec/60.0), $long_dir );
+
+ printf(" Degrees/Minutes/Dec. Seconds: %02d %02d %4.1f%s %02d %02d %4.1f%s\n",
+ $lat_deg, $lat_min, $lat_sec, $lat_dir,
+ $long_deg, $long_min, $long_sec, $long_dir);
+
+ # Dump out the coordinate in APRS Item format:
+ printf(FH "TEST>APRS:)%s!%02d%05.2f%s/%03d%05.2f%s/\n",
+ $_[1],
+ $lat_deg,
+ $lat_min + ($lat_sec/60.0),
+ $lat_dir,
+ $long_deg,
+ $long_min + ($long_sec/60.0),
+ $long_dir );
+
+ # Fill in the coordinate object with the current lat/lon.
+ # Assuming WGS84 datum
+ if ($lat_dir =~ /S/) {
+ $position->latitude( -( $lat_deg + ($lat_min/60.0) + ($lat_sec/3600.0) ) );
+ }
+ else {
+ $position->latitude( $lat_deg + ($lat_min/60.0) + ($lat_sec/3600.0) );
+ }
+
+ if ($long_dir =~ /W/) {
+ $position->longitude( -( $long_deg + ($long_min/60.0) + ($long_sec/3600.0) ) );
+ }
+ else {
+ $position->longitude( $long_deg + ($long_min/60.0) + ($long_sec/3600.0) );
+ }
+
+ #printf("%f %f\n",$position->latitude,$position->longitude);
+
+ $position->lat_lon_to_utm();
+ printf(" Universal Transverse Mercator: %s %07.0f %07.0f\n",
+ $position->zone(),
+ $position->easting(),
+ $position->northing() );
+
+ # Check whether the coordinates are within the SEA aeronautical
+ # map area
+ $lat_err = 0;
+ if ($lat_dir =~ /S/ ||
+ $lat_deg < 44 || $lat_deg > 49 ||
+ ($lat_deg == 44 && ($lat_min < 30 || ($lat_min == 30 && $lat_sec == 0))) ||
+ ($lat_deg == 49 && ($lat_min > 0 || $lat_sec > 0))) {
+ print " lat. out of range ";
+ $lat_err = 1;
+ }
+
+ $long_err = 0;
+ if ($long_dir =~ /E/ ||
+ $long_deg < 117 || $long_deg > 125 ||
+ ($long_deg == 117 && ($long_min == 0 && $long_sec == 0)) ||
+ ($long_deg == 125 && ($long_min > 0 || $long_sec > 0))) {
+ print " long. out of range";
+ $long_err = 1;
+ }
+
+ return if ( $lat_err || $long_err);
+
+
+ # Compute UMS coordinates
+ $y_sec = 3600 * ($lat_deg - 44) + 60 * $lat_min + $lat_sec;
+ $y_sec = 18000 - $y_sec;
+
+ $x_sec = 3600 * ($long_deg - 117) + 60 * $long_min + $long_sec;
+ $x_sec = 28800 - $x_sec;
+
+ $quad = 32 * int($y_sec / 900) + int($x_sec / 900) + 1;
+
+# print "\tx_sec= $x_sec, y_sec= $y_sec, quad= $quad\n";
+
+ $y_subquad_offset = int($y_sec / 450);
+ $x_subquad_offset = int($x_sec / 450);
+
+ if (&even($x_subquad_offset) && &even($y_subquad_offset)) {
+ print " UMS (Green Trails Maps): SEA ${quad} A ";
+ printf "%02d", &s2m_x($x_sec - (450 * $x_subquad_offset));
+ printf "%02d\n", &s2m_y($y_sec - (450 * $y_subquad_offset));
+ } elsif (&odd($x_subquad_offset) && &even($y_subquad_offset)) {
+ print " UMS (Green Trails Maps): SEA ${quad} B ";
+ printf "%02d", &s2m_x(450 * ($x_subquad_offset + 1) - $x_sec);
+ printf "%02d\n", &s2m_y($y_sec - (450 * $y_subquad_offset));
+ } elsif (&even($x_subquad_offset) && &odd($y_subquad_offset)) {
+ print " UMS (Green Trails Maps): SEA ${quad} C ";
+ printf "%02d", &s2m_x($x_sec - (450 * $x_subquad_offset));
+ printf "%02d\n", &s2m_y(450 * ($y_subquad_offset + 1) - $y_sec);
+ } else {
+ print " UMS (Green Trails Maps): SEA ${quad} D ";
+ printf "%02d", &s2m_x(450 * ($x_subquad_offset + 1) - $x_sec);
+ printf "%02d\n", &s2m_y(450 * ($y_subquad_offset + 1) - $y_sec);
+ }
+}
+
+
+
+sub even {
+ return (($_[0] & 1) == 0);
+}
+
+
+
+sub odd {
+ return (($_[0] & 1) == 1);
+}
+
+
+
+sub s2m_y {
+ return (int((0.1917966 * $_[0]) + 0.5));
+}
+
+
+
+sub s2m_x {
+ return (int((cos(($lat_deg + ($lat_min / 60.0) + ($lat_sec / 3600.0)) / 57.29578) * (0.1917966 * $_[0])) + 0.5));
+}
+
+
+
+##############
+# Main Program
+##############
+
+open (FH, ">$filename") || die "Couldn't open file for writing:$!\n";
+
+
+# Create new Coordinate object
+$position = Coordinate->new();
+
+
+$position->datum("WGS 84"); # Datum
+
+
+print "\n";
+print "Examples: 48 07228N 122 07228W\n";
+print " 48 08N 122 07W\n";
+print " 10U 0565264 5330343\n";
+
+print "\nAPRS Items will be written to: $filename\n";
+print "Enter a Lat/Long value or UTM value:\n";
+
+
+# Snag the input
+$input = <>;
+
+# Get rid of whitespace at the beginning
+$input =~ s/\s*//;
+
+# UTM value?
+if ($input =~ /^\d\d[a-zA-Z]\s+\w+\s+\w+\s*$/) {
+
+ $input2 = $input;
+ &convert($input2, "UTM");
+
+print "\n";
+
+ # Swap Easting/Northing values and convert again. Leave the
+ # zone in it's original spot.
+ $input2 = $input;
+ $input2 =~ s/^(\d\d[a-zA-Z])\s+(\w+)\s+(\w+)\s*$/$1 $3 $2\n/;
+
+print $input2;
+ &convert($input2, "UTM2");
+}
+# else must be lat/lon value
+else {
+
+ # Need to break up the input into several possible formats,
+ # possibly including swapping lat/long pieces and plotting N/S
+ # and E/W variants.
+
+ # I'm going to assume that the user knows his/her approximate
+ # lat/lon, so they can input it in roughly the proper format to
+ # begin with. All that's left then is to determine which of the
+ # three lat/lon formats it's in.
+
+ # 48 07228N 122 07228W
+
+ $input =~ s/^(\w+)\s+(\d)(\w)\s+(\w+)\s+(\d)(\w)\s*$/$1 0$2$3 $4 0$5$6\n/;
+
+ # DD.DDD
+ $input2 = $input;
+ $input2 =~ s/^(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s*$/$1.$2 $3.$4\n/;
+print $input2;
+ &convert($input2, "DD.DDD");
+
+print "\n";
+
+ # DD MM.MMM
+ $input2 = $input;
+ $input2 =~ s/^(\w+)\s+(\d\d)(\w+)\s+(\w+)\s+(\d\d)(\w+)\s*$/$1 $2.$3 $4 $5.$6\n/;
+ $input2 =~ s/(\.N)/.00N/;
+ $input2 =~ s/(\.S)/.00S/;
+ $input2 =~ s/(\.E)/.00E/;
+ $input2 =~ s/(\.W)/.00W/;
+print $input2;
+ &convert($input2, "DD MM.MM");
+
+print "\n";
+
+ # DD MM SS.S
+ $input2 = $input;
+ $input2 =~ s/^(\w+)\s+(\d\d)(\w)\s+(\w+)\s+(\d\d)(\w)\s*$/$1 $2 00.$3 $4 $5 00.$6\n/;
+ $input2 =~ s/^(\w+)\s+(\d\d)(\d)(\w)\s+(\w+)\s+(\d\d)(\d)(\w)\s*$/$1 $2 $3.$4 $5 $6 $7.$8\n/;
+ $input2 =~ s/^(\w+)\s+(\d\d)(\d\d)(\w+)\s+(\w+)\s+(\d\d)(\d\d)(\w+)\s*$/$1 $2 $3.$4 $5 $6 $7.$8\n/;
+ $input2 =~ s/(\.N)/.0N/;
+ $input2 =~ s/(\.S)/.0S/;
+ $input2 =~ s/(\.E)/.0E/;
+ $input2 =~ s/(\.W)/.0W/;
+ $input2 =~ s/\s(\d)(\.\d)/ 0$1$2/g;
+print $input2;
+ &convert($input2, "DD MM SS");
+
+}
+
+close(FH);
diff --git a/scripts/pos2shp.pl b/scripts/pos2shp.pl
new file mode 100755
index 0000000..2fb3c5e
--- /dev/null
+++ b/scripts/pos2shp.pl
@@ -0,0 +1,162 @@
+#!/usr/bin/env perl
+#
+# $Id: pos2shp.pl,v 1.7 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2006-2012 Tom Russo
+
+# 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
+
+# see file COPYING for details
+
+#--------------------------------------------------------------------------
+# This script produces an ESRI point shapefile from an APRS overlay
+# file (*.pos), according to the "Rolling your own shapefile maps"
+# section of README.MAPS The point file will display using the TIGER
+# Landmark Point dbfawk file.
+#
+# This enables fast generation of point maps in Shapefile format
+# from APRS overlay files.
+#
+# Typical usage:
+# pos2shp.pl file.pos myshape
+#--------------------------------------------------------------------------
+
+
+if ($#ARGV != 1)
+{
+ print "Usage: $0 <file.pos> <shapefile base name>\n";
+ exit 1;
+}
+
+
+open(INOBJ,"<$ARGV[0]") || die "Cannot open input overlay file $ARGV[0]\n";
+
+$cmd[0]="shpcreate $ARGV[1] point";
+$cmd[1]="dbfcreate $ARGV[1] -n ID 8 0 -s CFCC 4 -s NAME 30";
+$outfile=$ARGV[1];
+
+
+
+
+foreach $command (@cmd)
+{
+ system($command);
+ if ($? == -1)
+ {
+ print "failed to execute: $!\n";
+ }
+ elsif ($? & 127)
+ {
+ printf "child died with signal %d, %s coredump\n",
+ ($? & 127), ($? & 128) ? 'with' : 'without';
+ }
+ elsif ($?&0xF0)
+ {
+ printf "child exited with value %d\n", $? >> 8;
+ }
+}
+
+
+# We now have the shapefile and dbf file created, start populating from the
+# overlay file:
+
+$i=0;
+$first_line = 1;
+while (<INOBJ>)
+{
+ chomp($_);
+
+ # Skip the first line if it starts with a '*' (comment line).
+ next if ($first_line && (substr($_,0,1) eq '*') );
+ $first_line = 0;
+
+ $temp = $_;
+ @bits = split('!', $temp);
+
+ # Sanity check --- don't try to convert if the line doesn't
+ # conform to what we expect. We should have two items in the
+ # array at this point.
+ next if (length(@bits) < 1);
+
+ $name2 = $bits[0];
+ $rest = $bits[1];
+
+ $name = substr($name2,0,9); # Chop at 9 chars
+ $name =~ s/\w+\s+$//; # Remove trailing spaces
+
+ $lat=substr($rest,0,8);
+ $symtab=substr($rest,8,1);
+ $long=substr($rest,9,9);
+ $sym=substr($rest,18,1);
+
+# TODO: Do something with the comment field? It appears that if we
+# add too much here we get strange results when displayed in Xastir.
+ $comment=substr($rest,19,100);
+# $name = $name . ":" . $comment;
+
+ $i++; # bump the ID number so every point has a unique one
+
+ $lat_deg=substr($lat,0,2);
+ $lat_min=substr($lat,2,5);
+ $lat_hem=substr($lat,7,1);
+
+ $long_deg=substr($long,0,3);
+ $long_min=substr($long,3,5);
+ $long_hem=substr($long,8,1);
+
+ $lat=$lat_deg+$lat_min/60;
+ $lat *= -1 if ($lat_hem eq "S");
+
+ $long=$long_deg+$long_min/60;
+ $long *= -1 if ($long_hem eq "W");
+
+ # Construct symbol
+
+ if ($symtab ne "/" && $symtab ne "\\")
+ {
+ print "overlay symbol, symtab is $symtab\n";
+ $overlay=$symtab;
+ $symtab="\\";
+ print " reset values symtab is $symtab, overlay is $overlay\n";
+ }
+ else
+ {
+ $overlay=" ";
+ }
+
+ $cmd[0]="shpadd $outfile $long $lat";
+ $cmd[1]="dbfadd $outfile $i \'X$symtab$sym$overlay\' $name";
+ print $cmd[1]."\n";
+ foreach $command (@cmd)
+ {
+ system($command);
+ if ($? == -1)
+ {
+ print "failed to execute: $!\n";
+ }
+ elsif ($? & 127)
+ {
+ printf "child died with signal %d, %s coredump\n",
+ ($? & 127), ($? & 128) ? 'with' : 'without';
+ }
+ elsif ($?&0xF0)
+ {
+ printf "child exited with value %d\n", $? >> 8;
+ }
+ }
+
+}
+
+
diff --git a/scripts/ridge_radar.pl b/scripts/ridge_radar.pl
new file mode 100755
index 0000000..2209fd8
--- /dev/null
+++ b/scripts/ridge_radar.pl
@@ -0,0 +1,62 @@
+#!/usr/bin/perl
+#
+# $Id: ridge_radar.pl,v 1.2 2010/07/03 22:09:48 we7u Exp $
+#
+# Contributed to the public domain. Authored by Jeremy McDermond
+# (NH6Z).
+#
+# This script takes a single argument: The abbreviation of the
+# radar station off of the NWS site, and outputs to STDOUT a .geo
+# file that should be correct.
+# NOTE: You'll need to install "LWP::UserAgent" and "Image::Size"
+# from CPAN to make it work.
+#
+# Here's a typical invocation which creates a NYC Ridge Radar .geo
+# file called OKX_NOR.geo:
+#
+# ./ridge_radar.pl OKX > OKX_NOR.geo
+#
+# Of course you'd typically put the resulting file in your Xastir
+# maps directory and reindex maps to make it available for use.
+
+
+use strict;
+use LWP::UserAgent;
+use Image::Size;
+
+my $station = uc($ARGV[0]);
+
+my $gif_url = 'http://radar.weather.gov/ridge/RadarImg/N0R/' . $station . '_N0R_0.gif';
+
+my $response = LWP::UserAgent->new->request(
+ HTTP::Request->new( GET => $gif_url )
+);
+
+unless($response->is_success) {
+ die "Couldn't get radar image: ", $response->status_line, "\n";
+}
+
+my ($img_x, $img_y) = imgsize(\$response->content);
+
+my $response = LWP::UserAgent->new->request(
+ HTTP::Request->new( GET => 'http://radar.weather.gov/ridge/RadarImg/N0R/' . $station . '_N0R_0.gfw' )
+);
+
+unless($response->is_success) {
+ die "Couldn't get radar descriptor: ", $response->status_line, "\n";
+}
+
+my ( $yscale, undef, undef, $xscale, $lon, $lat ) = split(/\r\n/, $response->content);
+
+my $tiepoint_lat = $lat - ($yscale * $img_y);
+my $tiepoint_lon = $lon - ($xscale * $img_x);
+
+print "URL\t\t$gif_url\n";
+print "TIEPOINT\t0\t0\t$lon\t$lat\n";
+print "TIEPOINT\t$img_x\t$img_y\t$tiepoint_lon\t$tiepoint_lat\n";
+print "IMAGESIZE\t$img_x\t$img_y\n";
+print "REFRESH\t\t60\n";
+print "TRANSPARENT\t0x0\n";
+print "PROJECTION\tLatLon\n";
+
+
diff --git a/scripts/slideshow.pl b/scripts/slideshow.pl
new file mode 100755
index 0000000..eb3897f
--- /dev/null
+++ b/scripts/slideshow.pl
@@ -0,0 +1,90 @@
+#!/usr/bin/perl
+
+# $Id: slideshow.pl,v 1.3 2012/11/01 18:57:19 we7u Exp $
+#
+# Script to create a slideshow from Xastir snapshot images. Note
+# that this script is Unix/Linux-centric due to the use of the $HOME
+# variable and the use of the "cp" command.
+#
+# Written 20090415 by Curt Mills, WE7U
+#
+# Copyright (C) 2012 The Xastir Group
+#
+# 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.
+#
+#
+# Copies/renames ~/.xastir/tmp/snapshot.png files so that a
+# slideshow can be created from the images at a later date. The
+# script monitors the input directory. Any new snapshot.png file
+# that appears is allowed to age for a few seconds to make sure that
+# Xastir is done writing the file, then the file is copied to the
+# ~/.xastir/tmp/slideshow/ directory as a numbered file. See below
+# for one method for turning these files into an animated GIF, or
+# else bring them up in some slideshow program and display them in
+# numerical order. The name of the file contains the Unix Epoch
+# timestamp (the exact second that the file was made).
+#
+#
+# A note from Carl Makin, vk1kcm, modified slightly by Curt, we7u,
+# regarding creation of an animated GIF from the slideshow images:
+#
+# -------------------------------------------------------------------
+# This will create an animated gif that loops in your browser.
+# gm convert -delay 20 -loop snapshot*.png animation.gif
+# See:
+# http://www.graphicsmagick.org/FAQ.html#how-do-i-create-a-gif-animation-sequence-to-display-within-netscape
+# I think you can also great mpegs by changing the filename to "animation.mpg".
+# -------------------------------------------------------------------
+#
+
+
+$home = $ENV{"HOME"};
+$input_dir = "$home/.xastir/tmp";
+$output_dir = "$input_dir/slideshow";
+
+
+# Create the slideshow directory if it doesn't exist
+mkdir $output_dir;
+
+chdir $input_dir;
+
+while (1) {
+ $current_time = time;
+
+ # Snag the age of the existing snapshot.png file
+ $number = (stat("snapshot.png"))[9];
+
+ $difference = $current_time - $number;
+
+ # If the age of the file is more than 15 seconds but less than 31
+ # minutes, copy the file to the slideshow directory and rename it
+ # along the way. Note that Xastir can produce snapshots at a rate
+ # of between one per minute, and one per 30 minutes.
+ #
+ if ( ($difference > 15) && ($difference < (31 * 60)) ) {
+
+ # Copy the snapshot image to the slideshow directory, renaming
+ # it with the Unix Epoch time, something like: "1239897417.png".
+ # Only copies the file if the source file is newer than the
+ # destination, which prevents copying the file again and again
+ # if it's the last file in your sequence.
+ #
+ `cp -u snapshot.png $output_dir/$number.png`;
+ }
+ sleep 30;
+}
+
+
diff --git a/scripts/split_gnis.bash b/scripts/split_gnis.bash
new file mode 100755
index 0000000..ee6292c
--- /dev/null
+++ b/scripts/split_gnis.bash
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+# $Id: split_gnis.bash,v 1.2 2004/03/15 23:49:20 we7u Exp $
+
+# script created 14-MAR-04 by William Baguhn, kc9asi
+# This script is in the public domain.
+# Comments or suggestions to kc9asi at arrl.net
+
+# This script uses the "fromdos" program. You may need to change
+# that line to use "dos2unix" instead, depending on what utilities
+# are available on your system.
+
+# This will take a GNIS datapoint file (typically for a whole state, 8+Mb),
+# break it down into smaller chunks (typically for a county, 30-200k)
+# it will also throw away the stupid trailing spaces and <CR>'s at EOL.
+
+# My short experiment: the state of wisconsin.
+# Started with a 12.5Mb file.
+# ended with 93 files, totaling 6.7Mb.
+# and, the data files run a whole lot faster, especially when zoomed in.
+
+test -e $1 || (echo Try calling $0 with a file as an argument.; exit)
+
+# field 4 isn't just counties, but it's an acceptable label
+# as it's usually counties
+cut -f4 -d, <$1 >$1.counties
+
+# remove duplicates (sort, uniq)
+# the cut here gets rid of any "quirks" because of commas that came earlier
+# than were expected, as cut doesn't recognize quoting depths
+sort <$1.counties | uniq | cut -f2 -d\" >$1.counties.uniq
+
+# now we want to replace spaces with periods, so that counties with
+# spaces in their names work appropriately both for grep and filenaming
+tr " " . <$1.counties.uniq >$1.counties
+rm $1.counties.uniq
+
+# OK, now we should have a file with a list of the various divisions
+# SO, split each one apart
+
+# the regexp for grep assures that we just get "county" and not county,
+# hopefully this will make more sensible breaks as county names are
+# sometimes found in other names as well.
+# (i.e. Grant county, and Grant Community Park)
+# the \"county\" should get the former, and ignore the latter.
+
+# the fromdos/sed call will drop any dead whitespace at the end of a line
+
+# the test/rm call will delete files if they are zero length.
+
+
+for foo in `cat $1.counties` ; do
+ rm -f $1.$foo
+ echo Extracting $foo
+ grep ,\"$foo\", $1 | fromdos | sed -e 's/[ ]*$//g' >>$1.$foo.gnis
+ test -s $1.$foo.gnis || rm $1.$foo.gnis
+done
+
+
+# clean up after ourselves
+rm $1.counties
diff --git a/scripts/split_gnis.pl b/scripts/split_gnis.pl
new file mode 100755
index 0000000..33dc07f
--- /dev/null
+++ b/scripts/split_gnis.pl
@@ -0,0 +1,35 @@
+#!/usr/bin/perl -w
+#
+# $Id: split_gnis.pl,v 1.3 2005/01/02 05:26:23 tvrusso Exp $
+#
+# split_gnis.pl -- 2004 Mar 15 -- jmt at twilley.org
+
+# This script is designed to break large GNIS datapoint files
+# into smaller chunks and will dispose of extra whitespace properly.
+
+# It is based on a bash script written by kc9asi at arrl.net.
+
+# The filenames used as input should be put on the command line.
+
+
+while (<>) {
+ next unless /[A-Z][a-z]/;
+ s/\s+$//;
+ my $line = $_;
+ my @fields = split /\|/, $line;
+# print "Fields is @fields\n";
+ # key is "state county"
+ my $key = $fields[1] . " " . $fields[4];
+ $key =~ s/ /_/g;
+ push @{$county{$key}}, $line;
+}
+
+foreach $elem (keys %county) {
+ my $name = $elem . ".gnis";
+ open(OUT,">$name");
+ foreach $line (@{$county{$elem}}) {
+ print OUT $line, "\n";
+ }
+ close(OUT);
+}
+
diff --git a/scripts/test_coord.pl b/scripts/test_coord.pl
new file mode 100755
index 0000000..6c824f6
--- /dev/null
+++ b/scripts/test_coord.pl
@@ -0,0 +1,151 @@
+#!/usr/bin/perl -w
+
+
+# test_coord.pl: Perl code to test out the Coordinate.pm
+# module.
+#
+# Copyright (C) 2000-2012 Curt Mills, WE7U
+#
+# 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.
+#
+
+
+#
+# $Id: test_coord.pl,v 1.7 2012/11/01 18:57:19 we7u Exp $
+#
+#
+# TODO:
+# -----
+#
+
+
+#------------------------------------------------------------------------------------------------
+
+use lib "/usr/local/lib";
+use Coordinate; # Snag WE7U's Coordinate module
+
+
+&test();
+
+
+#
+# Routine for testing out the module.
+#
+# Need to add in tests for each method and object type.
+#
+sub test
+{
+ my $to_WGS84 = 0;
+ my $from_WGS84 = 1;
+
+ my $position = Coordinate->new();
+
+
+ $position->latitude(48.125);
+ $position->longitude(-122.500);
+ $position->datum("NAD27 CONUS MEAN:W of Mississippi/Except Louisiana/Minnesota/Missouri"); # Datum
+
+
+ printf("Starting position(Lat, Long): %s %s\n",
+ $position->latitude(),
+ $position->longitude() );
+
+ $position->degrees_minutes_seconds(); # Convert to DD MM SS format
+ printf("Starting position(Lat, Long): %s %s\n",
+ $position->formatted_latitude(),
+ $position->formatted_longitude() );
+
+ $position->lat_lon_to_utm();
+ printf("Calculated UTM position(Easting, Northing, Zone): %f %f %s\n",
+ $position->easting(),
+ $position->northing(),
+ $position->zone() );
+
+ $position->utm_to_lat_lon();
+ printf("Calculated Lat, Long position(Lat, Long): %f %f\n",
+ $position->latitude(),
+ $position->longitude() );
+
+
+ print "Changing from NAD27 to WGS84 datum...\n";
+ $position = $position->datum_shift_to_wgs84();
+ printf("Calculated Lat, Long position(Lat, Long): %f %f\n",
+ $position->latitude(),
+ $position->longitude() );
+
+ $position->degrees_minutes_seconds(); # Convert to DD MM SS
+ printf("Calculated Lat, Long position(Lat, Long): %s %s\n",
+ $position->formatted_latitude(),
+ $position->formatted_longitude() );
+
+ print "Changing from WGS84 to NAD27 datum...\n";
+ $position = $position->datum_shift_from_wgs84_to( "NAD27 CONUS MEAN:W of Mississippi/Except Louisiana/Minnesota/Missouri" );
+ printf("Calculated Lat, Long position(Lat, Long): %f %f\n",
+ $position->latitude(),
+ $position->longitude() );
+
+ print "\n0\n";
+ my $temp = CoordinateFormat->new( "0" );
+ printf(" decimal_degrees: %s\n", $temp->decimal_degrees( ) );
+ printf(" degrees_minutes: %s\n", $temp->degrees_minutes( ) );
+ printf("degrees_minutes_seconds: %s\n\n", $temp->degrees_minutes_seconds() );
+
+ print "180\n";
+ $temp->raw( "180" );
+ printf(" decimal_degrees: %s\n", $temp->decimal_degrees( "180") );
+ printf(" degrees_minutes: %s\n", $temp->degrees_minutes( "180") );
+ printf("degrees_minutes_seconds: %s\n\n", $temp->degrees_minutes_seconds("180") );
+
+ print "180 30\n";
+ $temp->raw( "180 30" );
+ printf(" decimal_degrees: %s\n", $temp->decimal_degrees( "180 30") );
+ printf(" degrees_minutes: %s\n", $temp->degrees_minutes( "180 30") );
+ printf("degrees_minutes_seconds: %s\n\n", $temp->degrees_minutes_seconds("180 30") );
+
+ print "180.50\n";
+ $temp->raw( "180.50" );
+ printf(" decimal_degrees: %s\n", $temp->decimal_degrees( "180.50") );
+ printf(" degrees_minutes: %s\n", $temp->degrees_minutes( "180.50") );
+ printf("degrees_minutes_seconds: %s\n\n", $temp->degrees_minutes_seconds("180.50") );
+
+ $temp->raw( "180 30.50" );
+ print "180 30.50\n";
+ printf(" decimal_degrees: %s\n", $temp->decimal_degrees( "180 30.50") );
+ printf(" degrees_minutes: %s\n", $temp->degrees_minutes( "180 30.50") );
+ printf("degrees_minutes_seconds: %s\n\n", $temp->degrees_minutes_seconds("180 30.50") );
+
+ $temp->raw( "180 30 30" );
+ print "180 30 30\n";
+ printf(" decimal_degrees: %s\n", $temp->decimal_degrees( "180 30 30") );
+ printf(" degrees_minutes: %s\n", $temp->degrees_minutes( "180 30 30") );
+ printf("degrees_minutes_seconds: %s\n\n", $temp->degrees_minutes_seconds("180 30 30") );
+
+ $temp->raw( "180 30 30.5" );
+ print "180 30 30.5\n";
+ printf(" decimal_degrees: %s\n", $temp->decimal_degrees("180 30 30.5") );
+ printf(" degrees_minutes: %s\n", $temp->degrees_minutes("180 30 30.5") );
+ printf("degrees_minutes_seconds: %s\n\n", $temp->degrees_minutes_seconds("180 30 30.5") );
+
+ $temp->raw( "-180 30 30.5" );
+ print "-180 30 30.5\n";
+ printf(" decimal_degrees: %s\n", $temp->decimal_degrees("-180 30 30.5") );
+ printf(" degrees_minutes: %s\n", $temp->degrees_minutes("-180 30 30.5") );
+ printf("degrees_minutes_seconds: %s\n\n", $temp->degrees_minutes_seconds("-180 30 30.5") );
+
+ EllipsoidTable->enumerate();
+ DatumTable->enumerate();
+}
+
+
diff --git a/scripts/toporama250k.pl b/scripts/toporama250k.pl
new file mode 100755
index 0000000..06ff56d
--- /dev/null
+++ b/scripts/toporama250k.pl
@@ -0,0 +1,276 @@
+#!/usr/bin/perl -W
+
+
+# $Id: toporama250k.pl,v 1.13 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2004-2012 The Xastir Group.
+#
+# 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.
+#
+# Look at the README for more information on the program.
+
+
+# This will retrieve the 1:250k map images from the "Department of
+# Natural Resources Geomatics Canada" site. These are topographic
+# map files for the whole of Canada!
+#
+#
+# - "cd /usr/local/share/xastir/maps"
+#
+# - Assure you have write privileges in the directory above either
+# by becoming root using the "su" command, using "sudo", or
+# temporarily changing ownership and/or privileges on the
+# "maps" directory.
+#
+# - "/usr/local/lib/xastir/toporama250k.pl"
+#
+# - The script will create/populate this directory heirarchy:
+# .../maps/toporama/images/
+# .../maps/toporama/images/b250k/
+#
+# - Move/rename directories/contents as you wish.
+#
+# - In Xastir: "Map->Configure->Index: Reindex ALL Maps!"
+#
+#
+# Note that the same map files are also available from Steve Dimse's
+# site: "http://mm.aprs.net/maps/geo/toporama"
+#
+#
+# Code for this script contributed by Adi Linden, VA3ADI.
+# Modifications for latitudes above 67 degrees north contributed by Tom Tessier, VE4TRT
+
+
+
+# Create the "toporama" directory
+mkdir "toporama";
+chdir "toporama";
+
+
+# Retrieve the 1:250,000 map images. Skipping those that we've
+# already downloaded.
+`wget -nv -np -nH -N -r -m -l 0 -T 10 http://toporama.cits.rncan.gc.ca/images/b250k/`;
+
+
+# Remove index.html files
+`rm -rf \`find ./images -type f -name index.html\*\``;
+# Remove *.asc files
+`rm -rf \`find ./images -type f -name \*.asc\``;
+
+
+
+# Define some stuff
+$base_dir = "images/b250k";
+
+# This defines the top left corner of the 0 grid up to 67 degrees north latitude.
+$basex = '-56';
+$basey = '44';
+%offsetx = ( 'a' => 3,
+ 'b' => 2,
+ 'c' => 1,
+ 'd' => 0,
+ 'e' => 0,
+ 'f' => 1,
+ 'g' => 2,
+ 'h' => 3,
+ 'i' => 3,
+ 'j' => 2,
+ 'k' => 1,
+ 'l' => 0,
+ 'm' => 0,
+ 'n' => 1,
+ 'o' => 2,
+ 'p' => 3,
+ '1' => 3,
+ '2' => 2,
+ '3' => 1,
+ '4' => 0,
+ '5' => 0,
+ '6' => 1,
+ '7' => 2,
+ '8' => 3,
+ '9' => 3,
+ '10' => 2,
+ '11' => 1,
+ '12' => 0,
+ '13' => 0,
+ '14' => 1,
+ '15' => 2,
+ '16' => 3 );
+%offsety = ( 'a' => 3,
+ 'b' => 3,
+ 'c' => 3,
+ 'd' => 3,
+ 'e' => 2,
+ 'f' => 2,
+ 'g' => 2,
+ 'h' => 2,
+ 'i' => 1,
+ 'j' => 1,
+ 'k' => 1,
+ 'l' => 1,
+ 'm' => 0,
+ 'n' => 0,
+ 'o' => 0,
+ 'p' => 0,
+ '1' => 3,
+ '2' => 3,
+ '3' => 3,
+ '4' => 3,
+ '5' => 2,
+ '6' => 2,
+ '7' => 2,
+ '8' => 2,
+ '9' => 1,
+ '10' => 1,
+ '11' => 1,
+ '12' => 1,
+ '13' => 0,
+ '14' => 0,
+ '15' => 0,
+ '16' => 0 );
+
+# This defines the top left corner of the 0 grid between 68 and 84 degrees north latitude.
+%offsetx68 = ( 'a' => 4,
+ 'b' => 0,
+ 'c' => 0,
+ 'd' => 4,
+ 'e' => 4,
+ 'f' => 0,
+ 'g' => 0,
+ 'h' => 4,
+ '1' => 4,
+ '2' => 0,
+ '3' => 0,
+ '4' => 4,
+ '5' => 4,
+ '6' => 0,
+ '7' => 0,
+ '8' => 4 );
+%offsety68 = ( 'a' => 3,
+ 'b' => 3,
+ 'c' => 2,
+ 'd' => 2,
+ 'e' => 1,
+ 'f' => 1,
+ 'g' => 0,
+ 'h' => 0,
+ '1' => 3,
+ '2' => 3,
+ '3' => 2,
+ '4' => 2,
+ '5' => 1,
+ '6' => 1,
+ '7' => 0,
+ '8' => 0 );
+
+#def
+
+use File::Find;
+
+print "Writing .geo files\n";
+
+find(\&process, $base_dir);
+
+print "\nDone.\n";
+
+
+
+# Run for each file found
+sub process
+{
+ # Only look for .gif files
+ if ( /.gif$/ ) {
+
+ # Get the map sheet designation from the file name
+ $file = "$_";
+ $grida = substr($file, 0, 3);
+ $gridb = substr($file, 3, 1);
+ $hilat = substr($file, 2, 1);
+
+ # .geo calculations for lattitudes greater than 78 degrees north latitude.
+ if ( $grida > 119 ) {
+
+ # Calculate top left coordinates of the map sheet
+ use integer;
+ $topx = $basex - ((($grida/10) +10 ) / 22 * 16) + $offsetx68{$gridb} * 2;
+ $topy = 84 - $offsety68{$gridb} * 1;
+ $botx = $topx + 8;
+ $boty = $topy - 2;
+
+ # Create the output file
+ $out = substr($file, 0, 4) . ".geo";
+ open (OUT, ">$out") or die "Can't open $OUT: $!\n";
+ print OUT "# Automatically created by toporama250k.pl\n";
+ print OUT "FILENAME\t$file\n";
+ print OUT "#\t\tx\ty\tlon\tlat\n";
+ print OUT "TIEPOINT\t0\t0\t$topx\t$topy\n";
+ print OUT "TIEPOINT\t6399\t1599\t$botx\t$boty\n";
+ print OUT "IMAGESIZE\t6400\t1600\n";
+ close OUT;
+
+ print ".";
+ next;
+ }
+
+ # .geo calculations for lattitudes between 68 and 78 degrees north latitude.
+ if ( $hilat > 6 ) {
+
+ # Calculate top left coordinates of the map sheet
+ use integer;
+ $topx = $basex - $grida / 10 * 8 + $offsetx68{$gridb} * 1;
+ $topy = $basey + ($grida % 10) * 4 - $offsety68{$gridb} * 1;
+ $botx = $topx + 4;
+ $boty = $topy - 1;
+
+ # Create the output file
+ $out = substr($file, 0, 4) . ".geo";
+ open (OUT, ">$out") or die "Can't open $OUT: $!\n";
+ print OUT "# Automatically created by toporama250k.pl\n";
+ print OUT "FILENAME\t$file\n";
+ print OUT "#\t\tx\ty\tlon\tlat\n";
+ print OUT "TIEPOINT\t0\t0\t$topx\t$topy\n";
+ print OUT "TIEPOINT\t6399\t1599\t$botx\t$boty\n";
+ print OUT "IMAGESIZE\t6400\t1600\n";
+ close OUT;
+
+ print ".";
+ next;
+
+ }
+
+ # Calculate top left coordinates of the map sheet
+ use integer;
+ $topx = $basex - $grida / 10 * 8 + $offsetx{$gridb} * 2;
+ $topy = $basey + ($grida % 10) * 4 - $offsety{$gridb} * 1;
+ $botx = $topx + 2;
+ $boty = $topy - 1;
+
+ # Create the output file
+ $out = substr($file, 0, 4) . ".geo";
+ open (OUT, ">$out") or die "Can't open $OUT: $!\n";
+ print OUT "# Automatically created by toporama250k.pl\n";
+ print OUT "FILENAME\t$file\n";
+ print OUT "#\t\tx\ty\tlon\tlat\n";
+ print OUT "TIEPOINT\t0\t0\t$topx\t$topy\n";
+ print OUT "TIEPOINT\t3199\t1599\t$botx\t$boty\n";
+ print OUT "IMAGESIZE\t3200\t1600\n";
+ close OUT;
+
+ print ".";
+ }
+
+}
diff --git a/scripts/toporama50k.pl b/scripts/toporama50k.pl
new file mode 100755
index 0000000..a789be8
--- /dev/null
+++ b/scripts/toporama50k.pl
@@ -0,0 +1,195 @@
+#!/usr/bin/perl -W
+
+# $Id: toporama50k.pl,v 1.12 2012/11/01 18:57:19 we7u Exp $
+
+# Copyright (C) 2004-2012 The Xastir Group.
+#
+# 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.
+#
+# Look at the README for more information on the program.
+
+
+# This will retrieve the 1:50k map images from the "Department of
+# Natural Resources Geomatics Canada" site. These are topographic
+# map files for the whole of Canada!
+#
+#
+# - "cd /usr/local/share/xastir/maps"
+#
+# - Assure you have write privileges in the directory above either
+# by becoming root using the "su" command, using "sudo", or
+# temporarily changing ownership and/or privileges on the
+# "maps" directory.
+#
+# - "/usr/local/lib/xastir/toporama50k.pl"
+#
+# - The script will create/populate this directory heirarchy:
+# .../maps/toporama/images/
+# .../maps/toporama/images/b50k/
+#
+# - Move/rename directories/contents as you see fit.
+#
+# - In Xastir: "Map->Configure->Index: Reindex ALL Maps!"
+#
+#
+# Note that the same map files are also available from Steve Dimse's
+# site: "http://mm.aprs.net/maps/geo/toporama"
+#
+#
+# Code for this script contributed by Adi Linden, VA3ADI.
+
+
+
+# Create the "toporama" directory
+mkdir "toporama";
+chdir "toporama";
+
+
+# Retrieve the 1:50,000 map images. Skipping those that we've
+# already downloaded.
+`wget -nv -np -nH -N -r -m -l 0 -T 10 http://toporama.cits.rncan.gc.ca/images/b50k/`;
+
+
+# Remove index.html files
+`rm -rf \`find ./images -type f -name index.html\*\``;
+# Remove *.asc files
+`rm -rf \`find ./images -type f -name \*.asc\``;
+
+
+# Define some stuff
+$base_dir = "images/b50k";
+
+# This defines the top left corner of the 0 grid.
+$basex = '-56';
+$basey = '44';
+%offsetx = ( 'a' => 3,
+ 'b' => 2,
+ 'c' => 1,
+ 'd' => 0,
+ 'e' => 0,
+ 'f' => 1,
+ 'g' => 2,
+ 'h' => 3,
+ 'i' => 3,
+ 'j' => 2,
+ 'k' => 1,
+ 'l' => 0,
+ 'm' => 0,
+ 'n' => 1,
+ 'o' => 2,
+ 'p' => 3,
+ '01' => 3,
+ '02' => 2,
+ '03' => 1,
+ '04' => 0,
+ '05' => 0,
+ '06' => 1,
+ '07' => 2,
+ '08' => 3,
+ '09' => 3,
+ '10' => 2,
+ '11' => 1,
+ '12' => 0,
+ '13' => 0,
+ '14' => 1,
+ '15' => 2,
+ '16' => 3 );
+%offsety = ( 'a' => 3,
+ 'b' => 3,
+ 'c' => 3,
+ 'd' => 3,
+ 'e' => 2,
+ 'f' => 2,
+ 'g' => 2,
+ 'h' => 2,
+ 'i' => 1,
+ 'j' => 1,
+ 'k' => 1,
+ 'l' => 1,
+ 'm' => 0,
+ 'n' => 0,
+ 'o' => 0,
+ 'p' => 0,
+ '01' => 3,
+ '02' => 3,
+ '03' => 3,
+ '04' => 3,
+ '05' => 2,
+ '06' => 2,
+ '07' => 2,
+ '08' => 2,
+ '09' => 1,
+ '10' => 1,
+ '11' => 1,
+ '12' => 1,
+ '13' => 0,
+ '14' => 0,
+ '15' => 0,
+ '16' => 0 );
+
+use File::Find;
+
+print "Writing .geo files\n";
+
+find(\&process, $base_dir);
+
+print "\nDone.\n";
+
+
+
+# Run for each file found
+sub process
+{
+ # Only look for .gif files
+ if ( /.gif$/ ) {
+
+ # Get the map sheet designation from the file name
+ $file = "$_";
+ $grida = substr($file, 0, 3);
+ $gridb = substr($file, 3, 1);
+ $gridc = substr($file, 4, 2);
+
+ if ( $grida > 119 ) {
+ next;
+ }
+
+ # Calculate top left coordinates of the map sheet
+ use integer;
+ $topx = $basex - $grida / 10 * 8 + $offsetx{$gridb} * 2;
+ $topy = $basey + ($grida % 10) * 4 - $offsety{$gridb} * 1;
+ no integer;
+ $topx = $topx + $offsetx{$gridc} * 0.5;
+ $topy = $topy - $offsety{$gridc} * 0.25;
+ $botx = $topx + 0.5;
+ $boty = $topy - 0.25;
+
+ # Create the output file
+ $out = substr($file, 0, 6) . ".geo";
+ open (OUT, ">$out") or die "Can't open $OUT: $!\n";
+ print OUT "# Automatically created by toporama50k.pl\n";
+ print OUT "FILENAME\t$file\n";
+ print OUT "#\t\tx\ty\tlon\tlat\n";
+ print OUT "TIEPOINT\t0\t0\t$topx\t$topy\n";
+ print OUT "TIEPOINT\t3199\t1599\t$botx\t$boty\n";
+ print OUT "IMAGESIZE\t3200\t1600\n";
+ close OUT;
+
+ print ".";
+ }
+
+}
+
+
diff --git a/scripts/track-get.pl b/scripts/track-get.pl
new file mode 100755
index 0000000..5ed4589
--- /dev/null
+++ b/scripts/track-get.pl
@@ -0,0 +1,163 @@
+#!/usr/bin/perl
+
+# $Id: track-get.pl,v 1.5 2012/11/01 18:57:19 we7u Exp $
+
+# Copyright (C) 2000-2012 Curt Mills, WE7U
+#
+# 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.
+#
+
+# This script will ask for an item designator, then create a file
+# with that name + ".log" in the ~/.xastir/logs directory. The
+# file will contain APRS items created from the downloaded Garmin
+# tracklog. Reading that log file with Xastir will result in an
+# object with a track being displayed on the map screen.
+
+# You may wish to bump up MAX_TRACKS in db.h to 1024 in order to see
+# the entire log, but be careful with Xastir's memory image growing
+# too fast if you're connected to the 'net after making this change.
+
+# This script uses the GPS::Garmin module which can be obtained
+# from http://sourceforge.net/projects/perl-gps/
+
+
+use GPS::Garmin;
+use IO::File;
+
+
+# Flush STDOUT
+$| = 1;
+
+
+# Hard-coded "from" callsign name. This becomes the "sending"
+# callsign for the APRS Items.
+$from = "SAR";
+
+
+# Ask for the item name. This will turn into the 3-9 character APRS
+# item name.
+printf("\n\nEnter item designator: Length 1-9, all except '!' and '_' allowed, case respected:\n\n");
+printf("\t123456789\n\t");
+$name = <>;
+chomp $name;
+if (length($name) < 1) {
+ die "Must be at least one character!\n";
+}
+if (length($name) > 9) {
+ $name =~ s/(.{9}).*/\1/; # Terminate it at 9 chars
+}
+if (length($name) < 3) {
+ $name = $name . " "; # Pad the name with spaces
+ $name =~ s/(.{3}).*/\1/; # Terminate it at 3 chars
+}
+
+# We need to enforce the naming restrictions for APRS Items. '!'
+# and '_' are not allowed, anything else that's printable ASCII is
+# ok.
+ at j = split(//, $name);
+for ($i = 0; $i < length($name); $i++) {
+#printf("$i $j[$i]\n");
+ if ( ($j[$i] lt ' ')
+ || ($j[$i] gt '~')
+ || ($j[$i] eq '!')
+ || ($j[$i] eq '_') ) {
+ $j[$i] = ' ';
+ }
+}
+$name = join("", at j);
+
+$filename = "~/.xastir/logs/$name.log";
+
+# Get rid of spaces in the filename
+$filename =~ s/\s+//g;
+
+# Expand the tilde into the home directory
+$filename =~ s{ ^ ~ ( [^/]* ) }
+ { $1
+ ? (getpwnam($1))[7]
+ : ( $ENV{HOME} || $ENV{LOGDIR}
+ || (getpwuid($>))[7]
+ )
+}ex;
+
+printf("\nThe item designator will be: ($name)\n");
+printf("The output filename will be: ($filename)\n\n");
+printf("Connect Garmin GPS to /dev/ttyS0 (COM1), set it to Garmin/Garmin mode.\n");
+printf("Press <ENTER> to proceed with download, Ctrl-C to abort\n");
+<>;
+
+
+# Create a file to hold the data
+$output = IO::File->new("> $filename")
+ or die "Couldn't open $filename for writing: $!\n";
+
+
+$gps = new GPS::Garmin( 'Port' => '/dev/ttyS0',
+ 'Baud' => 9600,
+ ) or die "Unable to connect to receiver: $!";
+
+
+# Transfer trackpoints:
+$i = 0;
+$gps->prepare_transfer("trk");
+while ($gps->records)
+{
+ ($lat,$lon,$time) = $gps->grab;
+# printf("%f %f %d\n",$lat,$lon,$time);
+ if ($lon < 0) {
+ $londeg = sprintf("%d",-$lon);
+ $lonmin = (-$lon - $londeg) * 60;
+ $lonchar = "W";
+ }
+ else {
+ $londeg = sprintf("%d",$lon);
+ $lonchar = "E";
+ $lonmin = ($lon - $londeg) * 60;
+ }
+ if ($lat < 0) {
+ $latdeg = sprintf("%d",-$lat);
+ $latmin = (-$lat - $latdeg) * 60;
+ $latchar = "S";
+ }
+ else {
+ $latdeg = sprintf("%d",$lat);
+ $latmin = ($lat - $latdeg) * 60;
+ $latchar = "N";
+ }
+
+ # Write an APRS Item for each trackpoint
+ printf($output "%s>APRS:)%s!%02d%05.2f%s/%03d%05.2f%s%s\n",
+ $from,
+ $name,
+ $latdeg,
+ $latmin,
+ $latchar,
+ $londeg,
+ $lonmin,
+ $lonchar,
+ "/");
+
+ if (! ($i % 10) ) {
+ printf("$i ");
+ }
+ $i++;
+}
+
+printf("\n\nThe data has been saved in: ($filename)\n");
+printf("Please open this logfile with Xastir to display the track\n");
+printf("!!!Remember to set your GPS back to NMEA mode for APRS!!!\n");
+
+
diff --git a/scripts/update_langfile.pl b/scripts/update_langfile.pl
new file mode 100755
index 0000000..5531b2f
--- /dev/null
+++ b/scripts/update_langfile.pl
@@ -0,0 +1,117 @@
+#!/usr/bin/perl -w
+# $Id: update_langfile.pl,v 1.2 2002/02/12 01:27:39 dk7in Exp $
+
+# Update utility for XASTIR language files 17.04.2001
+# Copyright (C) 2001 Rolf Bleher http://www.dk7in.de
+
+# 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
+
+# see file COPYING for details
+
+#--------------------------------------------------------------------------
+
+# This program adds missing entries to the translated language files and
+# deletes obsolete entries.
+# If a translated comment before an entry block is found it will be preserved.
+# There might be problems with the comment with a changed block sequence.
+# I assume that you start it in the directory with the language files,
+# call it with the translated language file as parameter.
+
+# DK7IN: for now it assumes that the language files reside
+# in the current directory
+
+#--------------------------------------------------------------------------
+$LF1 = "language-English.sys"; # original language file
+$LF2 = "language-German.sys"; # translated language file
+$LFOUT = "language-new.sys"; # modified translated language file
+if (@ARGV) {
+ $LF2 = shift @ARGV;
+}
+#--------------------------------------------------------------------------
+open(IN1,$LF1) or die "ERROR: could not open $LF1!\n";
+open(IN2,$LF2) or die "ERROR: could not open $LF2!\n";
+open(OUT,">$LFOUT") or die "ERROR: could not write to $LFOUT!\n";
+#--------------------------------------------------------------------------
+%token = (); # translated tokens
+ at cmt1 = (); # original comment
+ at cmt2 = (); # translated comment
+
+# collect all available translated tokens
+while (<IN2>) {
+ next if (/^#/); # skip comment lines
+ if (/^([A-Z]+[0-9]+)(|.+|.?|.*)$/) {
+ $token{$1} = $2; # store translated text entry
+ }
+}
+
+# process language file
+while (<IN1>) { # original language file
+ if (/^#/) { # comment line
+ push(@cmt1,$_); # store comment
+ } else {
+ if (/^([A-Z]+)([0-9]+)(|.+|.?|.*)$/) { # data line
+ $name = $1;
+ $numb = $2;
+ $arg = $3;
+
+ if (@cmt1) { # pending comment
+ # try to find the translation
+ seek IN2, 0, 0; # reposition to begin of file
+ @cmt2 = (); # translated comment
+ $match = 0;
+ while (<IN2>) {
+ $line = $_;
+ if (/^([A-Z]+)([0-9]+)(|.+|.?|.*)$/) {
+ $curr = $1;
+ if ($name eq $curr) { # same block
+ $match = 1;
+ last;
+ } else {
+ @cmt2 = (); # clear wrong comment
+ }
+ } else {
+ if (/^#/) { # store comment
+ push(@cmt2,$_);
+ }
+ }
+ }
+ if ($match && @cmt2) { # found translated comment
+ foreach $line (@cmt2) {
+ print(OUT $line); # translated comment
+ }
+ } else {
+ foreach $line (@cmt1) {
+ print(OUT $line); # original comment
+ }
+ }
+ @cmt1 = ();
+ }
+
+ if ($token{$name.$numb}) { # found translation
+ $arg = $token{$name.$numb};
+ }
+ printf(OUT "%s%s%s\n",$name,$numb,$arg);
+ } else {
+ print("ERROR: $_"); # bad line format
+ }
+ }
+}
+close(IN1);
+close(IN2);
+close(OUT);
+
+exit;
+#--------------------------------------------------------------------------
+
diff --git a/scripts/values b/scripts/values
new file mode 100644
index 0000000..b0f7c27
--- /dev/null
+++ b/scripts/values
@@ -0,0 +1,2 @@
+#!/bin/sh
+prefix=/usr/local;
diff --git a/scripts/values.in b/scripts/values.in
new file mode 100644
index 0000000..a52ee4d
--- /dev/null
+++ b/scripts/values.in
@@ -0,0 +1,2 @@
+#!/bin/sh
+prefix=@prefix@;
diff --git a/scripts/values.pl b/scripts/values.pl
new file mode 100644
index 0000000..3362236
--- /dev/null
+++ b/scripts/values.pl
@@ -0,0 +1,8 @@
+#!/usr/bin/perl
+$prefix="/usr/local";
+
+=include for usage
+use File::Basename;
+$dirname=dirname($0);
+require ($dirname."/values.pl");
+
diff --git a/scripts/values.pl.in b/scripts/values.pl.in
new file mode 100644
index 0000000..5d66200
--- /dev/null
+++ b/scripts/values.pl.in
@@ -0,0 +1,8 @@
+#!/usr/bin/perl
+$prefix="@prefix@";
+
+=include for usage
+use File::Basename;
+$dirname=dirname($0);
+require ($dirname."/values.pl");
+
diff --git a/scripts/waypoint-get.pl b/scripts/waypoint-get.pl
new file mode 100755
index 0000000..18c33bf
--- /dev/null
+++ b/scripts/waypoint-get.pl
@@ -0,0 +1,165 @@
+#!/usr/bin/perl
+
+# $Id: waypoint-get.pl,v 1.4 2012/11/01 18:57:19 we7u Exp $
+
+# Copyright (C) 2000-2012 Curt Mills, WE7U
+#
+# 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.
+#
+
+# This script will ask for a name, then create a file
+# with that name + ".log" in the ~/.xastir/logs directory. The
+# file will contain APRS items created from the downloaded Garmin
+# waypoints. Reading that log file with Xastir will result in one
+# item appearing on the map screen for each waypoint, labeled with
+# the name of that waypoint.
+
+# This script uses the GPS::Garmin module which can be obtained
+# from http://sourceforge.net/projects/perl-gps/
+
+
+use GPS::Garmin;
+use IO::File;
+
+
+# Flush STDOUT
+$| = 1;
+
+
+# Hard-coded "from" callsign name. This becomes the "sending"
+# callsign for the APRS Items.
+$from = "SAR";
+
+
+# Ask for the name. This gets changed into the complete log file name.
+printf("\n\nEnter name for file: '.log' will get added to the end:\n\n");
+$name = <>;
+chomp $name;
+if (length($name) < 1) {
+ die "Must be at least one character!\n";
+}
+
+$filename = "~/.xastir/logs/$name.log";
+
+# Get rid of spaces in the filename
+$filename =~ s/\s+//g;
+
+# Expand the tilde into the home directory
+$filename =~ s{ ^ ~ ( [^/]* ) }
+ { $1
+ ? (getpwnam($1))[7]
+ : ( $ENV{HOME} || $ENV{LOGDIR}
+ || (getpwuid($>))[7]
+ )
+}ex;
+
+printf("\nThe output filename will be: ($filename)\n\n");
+printf("Connect Garmin GPS to /dev/ttyS0 (COM1), set it to Garmin/Garmin mode.\n");
+printf("Press <ENTER> to proceed with download, Ctrl-C to abort\n");
+<>;
+
+
+# Create a file to hold the data
+$output = IO::File->new("> $filename")
+ or die "Couldn't open $filename for writing: $!\n";
+
+
+$gps = new GPS::Garmin( 'Port' => '/dev/ttyS0',
+ 'Baud' => 9600,
+ ) or die "Unable to connect to receiver: $!";
+
+
+# Transfer waypoints:
+$i = 0;
+$gps->prepare_transfer("wpt");
+while ($gps->records)
+{
+ ($title,$lat,$lon,$desc) = $gps->grab;
+
+ #printf("%f\t%f\t%s\t%s\n",$lat,$lon,$desc,$title);
+
+ if ($lon < 0) {
+ $londeg = sprintf("%d",-$lon);
+ $lonmin = (-$lon - $londeg) * 60;
+ $lonchar = "W";
+ }
+ else {
+ $londeg = sprintf("%d",$lon);
+ $lonchar = "E";
+ $lonmin = ($lon - $londeg) * 60;
+ }
+ if ($lat < 0) {
+ $latdeg = sprintf("%d",-$lat);
+ $latmin = (-$lat - $latdeg) * 60;
+ $latchar = "S";
+ }
+ else {
+ $latdeg = sprintf("%d",$lat);
+ $latmin = ($lat - $latdeg) * 60;
+ $latchar = "N";
+ }
+
+ chomp $title;
+ if (length($title) < 1) {
+ die "Must be at least one character!\n";
+ }
+ if (length($title) > 9) {
+ $title =~ s/(.{9}).*/\1/; # Terminate it at 9 chars
+ }
+ if (length($title) < 3) {
+ $title = $title . " "; # Pad the title with spaces
+ $title =~ s/(.{3}).*/\1/; # Terminate it at 3 chars
+ }
+
+ # We need to enforce the naming restrictions for APRS Items. '!'
+ # and '_' are not allowed, anything else that's printable ASCII is
+ # ok.
+ @j = split(//, $title);
+ for ($k = 0; $k < length($title); $k++) {
+ #printf("$k $j[$k]\n");
+ if ( ($j[$k] lt ' ')
+ || ($j[$k] gt '~')
+ || ($j[$k] eq '!')
+ || ($j[$k] eq '_') ) {
+ $j[$k] = ' ';
+ }
+ }
+ $title = join("", at j);
+
+ # Write an APRS Item for each waypoint
+ printf($output "%s>APRS:)%s!%02d%05.2f%s/%03d%05.2f%s%s\n",
+ $from,
+ $title,
+ $latdeg,
+ $latmin,
+ $latchar,
+ $londeg,
+ $lonmin,
+ $lonchar,
+ "/");
+
+ if (! ($i % 10) ) {
+ printf("$i ");
+ }
+
+ $i++;
+}
+
+printf("\n\nThe data has been saved in: ($filename)\n");
+printf("Please open this logfile with Xastir to display the waypoints.\n");
+printf("!!!Remember to set your GPS back to NMEA mode for APRS!!!\n");
+
+
diff --git a/scripts/xastir-fixcfg.sh b/scripts/xastir-fixcfg.sh
new file mode 100755
index 0000000..f095add
--- /dev/null
+++ b/scripts/xastir-fixcfg.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# $Id: xastir-fixcfg.sh,v 1.12 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# fix up a user's .xastir/config/xastir.cnf to rewrite /usr/local/xastir
+# to ${prefix}/share/${name}.
+. `dirname $0`/values
+CNF=.xastir/config/xastir.cnf
+INDEX=.xastir/config/map_index.sys
+SELECT=.xastir/config/selected_maps.sys
+cd
+if [ -f $CNF ]; then
+ rm $INDEX
+ mv $CNF $CNF.backup
+ mv $SELECT $SELECT.backup
+ if [ $? -ne 0 ]; then
+ echo "$CNF: unable to rename!"
+ exit 1
+ fi
+ sed -e 's:/usr/local/xastir/:${prefix}/share/xastir/:' <$CNF.backup >$CNF
+ if [ $? -ne 0 ]; then
+ echo "$CNF: sed failed!"
+ mv $CNF.backup $CNF
+ exit 1
+ fi
+else
+ echo "No $CNF to edit"
+fi
+echo "Done. Old config file is in $CNF.backup"
+exit 0
+
+
diff --git a/scripts/xastir-migrate.sh b/scripts/xastir-migrate.sh
new file mode 100755
index 0000000..5984ed5
--- /dev/null
+++ b/scripts/xastir-migrate.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# $Id: xastir-migrate.sh,v 1.12 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2003-2012 The Xastir Group
+#
+# migrate from old xastir USER FILES to new directory structure.
+# Stuff that was under /usr/local/xastir is now under ${prefix}/share/xastir/
+# fixed up the .xastir/config/xastir.cfg as well.
+# XXX Do we throw away the xastir non-user files (config, doc, help)?
+. `dirname $0`/values
+PREFIX=
+OLD=$PREFIX/usr/local/xastir
+NEW=$PREFIX${prefix}/share/xastir
+rr=0
+if [ -d $OLD ]; then
+ if [ ! -d $NEW ]; then
+ (umask 022; mkdir -p $NEW)
+ fi
+ echo "Moving xastir user files"
+ echo "From: $OLD"
+ echo " To: $NEW"
+ for i in Counties GNIS config doc fcc help maps sounds symbols
+ do
+ if [ -d $OLD/$i ]; then
+ if [ -d $NEW/$i ]; then
+ echo "$NEW/$i: destination directory already exists; Overlaying files."
+ (cd $OLD/$i; tar cf - .) | (cd $NEW/$i; tar xvfp -)
+ r=$?
+ if [ $r -ne 0 ]; then
+ echo Failed to move directory $i
+ rr=`expr $rr + $r`
+ else
+ # clean up the source directory
+ rm -rf $OLD/$i
+ fi
+ else
+ # hope they are in the same FS!
+ mv $OLD/$i $NEW/$i
+ r=$?
+ rr=`expr $rr + $r`
+ if [ $r -ne 0 ]; then
+ echo Failed to move directory $i
+ fi
+ fi
+ else
+ echo "$OLD/$i: old directory not found."
+ fi
+ done
+else
+ echo "$OLD: not found. Nothing to migrate."
+fi
+if [ $rr -ne 0 ]; then
+ echo "WARNING: Some files/directories not moved. Please check $OLD and $NEW"
+else
+ echo "No Errors"
+fi
+exit $rr
+
+
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..7d65623
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,103 @@
+# $Id: Makefile.am,v 1.53 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+
+bin_PROGRAMS = xastir xastir_udp_client testdbfawk
+
+SUBDIRS = @SUBRTREE@ @SUBSHP@
+DIST_SUBDIRS = rtree shapelib
+
+EXTRA_DIST=icon.xbm
+
+XASTIR_SRC = \
+ alert.c alert.h \
+ awk.c awk.h \
+ bulletin_gui.c bulletin_gui.h \
+ color.c color.h \
+ datum.c datum.h \
+ db.c database.h \
+ db_gis.c db_gis.h \
+ dbfawk.c dbfawk.h \
+ draw_symbols.c draw_symbols.h \
+ fcc_data.c fcc_data.h \
+ festival.c festival.h \
+ fetch_remote.c fetch_remote.h \
+ geo-find.c geo.h \
+ geocoder_gui.c \
+ gps.c gps.h \
+ hashtable.c hashtable_private.h hashtable.h \
+ hashtable_itr.c hashtable_itr.h \
+ hostname.c hostname.h \
+ igate.c igate.h \
+ interface.c interface.h \
+ interface_gui.c \
+ io-common.c io-mmap.c io.h \
+ lang.c lang.h \
+ leak_detection.h \
+ list_gui.c list_gui.h \
+ locate_gui.c \
+ location.c \
+ location_gui.c \
+ main.c main.h \
+ maps.c maps.h \
+ map_cache.c map_cache.h \
+ map_dos.c \
+ map_gdal.c \
+ map_geo.c \
+ map_gnis.c \
+ map_OSM.c map_OSM.h \
+ map_pop.c \
+ map_pdb.c \
+ map_shp.c \
+ map_tif.c \
+ map_tiger.c \
+ map_WMS.c \
+ messages.c messages.h \
+ messages_gui.c \
+ objects.h objects.c \
+ popup.h \
+ popup_gui.c \
+ rac_data.c rac_data.h \
+ rotated.c rotated.h \
+ rpl_malloc.c rpl_malloc.h \
+ shp_hash.c shp_hash.h \
+ snprintf.c snprintf.h \
+ sound.c symbols.h \
+ tile_mgmnt.c tile_mgmnt.h \
+ track_gui.c track_gui.h \
+ util.c util.h \
+ view_message_gui.c \
+ wx.c wx.h \
+ wx_gui.c \
+ x_spider.c x_spider.h \
+ xa_config.c xa_config.h \
+ xastir.h
+
+xastir_SOURCES = $(XASTIR_SRC) compiledate.c
+
+xastir_udp_client_SOURCES = \
+ xastir_udp_client.c
+
+testdbfawk_SOURCES = \
+ testdbfawk.c \
+ awk.c \
+ dbfawk.c \
+ rpl_malloc.c rpl_malloc.h
+
+compiledate.c: $(XASTIR_SRC)
+ rm -f compiledate.c compiledate.o
+ echo 'char compiledate[] = "'"Compiled: `date`"'";' > compiledate.c
+
+remove_compiledate:
+ rm -f compiledate.c compiledate.o
+
+xastir_LDADD=@LIBRTREE@ @LIBSHP@
+
+testdbfawk_LDADD=@LIBSHP@
+
+xastir_LINK=$(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+
+xastir_udp_client_LINK=$(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+
+testdbfawk_LINK=$(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..afb3439
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,837 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+# $Id: Makefile.am,v 1.53 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = xastir$(EXEEXT) xastir_udp_client$(EXEEXT) \
+ testdbfawk$(EXEEXT)
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+am_testdbfawk_OBJECTS = testdbfawk.$(OBJEXT) awk.$(OBJEXT) \
+ dbfawk.$(OBJEXT) rpl_malloc.$(OBJEXT)
+testdbfawk_OBJECTS = $(am_testdbfawk_OBJECTS)
+testdbfawk_DEPENDENCIES =
+am__objects_1 = alert.$(OBJEXT) awk.$(OBJEXT) bulletin_gui.$(OBJEXT) \
+ color.$(OBJEXT) datum.$(OBJEXT) db.$(OBJEXT) db_gis.$(OBJEXT) \
+ dbfawk.$(OBJEXT) draw_symbols.$(OBJEXT) fcc_data.$(OBJEXT) \
+ festival.$(OBJEXT) fetch_remote.$(OBJEXT) geo-find.$(OBJEXT) \
+ geocoder_gui.$(OBJEXT) gps.$(OBJEXT) hashtable.$(OBJEXT) \
+ hashtable_itr.$(OBJEXT) hostname.$(OBJEXT) igate.$(OBJEXT) \
+ interface.$(OBJEXT) interface_gui.$(OBJEXT) \
+ io-common.$(OBJEXT) io-mmap.$(OBJEXT) lang.$(OBJEXT) \
+ list_gui.$(OBJEXT) locate_gui.$(OBJEXT) location.$(OBJEXT) \
+ location_gui.$(OBJEXT) main.$(OBJEXT) maps.$(OBJEXT) \
+ map_cache.$(OBJEXT) map_dos.$(OBJEXT) map_gdal.$(OBJEXT) \
+ map_geo.$(OBJEXT) map_gnis.$(OBJEXT) map_OSM.$(OBJEXT) \
+ map_pop.$(OBJEXT) map_pdb.$(OBJEXT) map_shp.$(OBJEXT) \
+ map_tif.$(OBJEXT) map_tiger.$(OBJEXT) map_WMS.$(OBJEXT) \
+ messages.$(OBJEXT) messages_gui.$(OBJEXT) objects.$(OBJEXT) \
+ popup_gui.$(OBJEXT) rac_data.$(OBJEXT) rotated.$(OBJEXT) \
+ rpl_malloc.$(OBJEXT) shp_hash.$(OBJEXT) snprintf.$(OBJEXT) \
+ sound.$(OBJEXT) tile_mgmnt.$(OBJEXT) track_gui.$(OBJEXT) \
+ util.$(OBJEXT) view_message_gui.$(OBJEXT) wx.$(OBJEXT) \
+ wx_gui.$(OBJEXT) x_spider.$(OBJEXT) xa_config.$(OBJEXT)
+am_xastir_OBJECTS = $(am__objects_1) compiledate.$(OBJEXT)
+xastir_OBJECTS = $(am_xastir_OBJECTS)
+xastir_DEPENDENCIES =
+am_xastir_udp_client_OBJECTS = xastir_udp_client.$(OBJEXT)
+xastir_udp_client_OBJECTS = $(am_xastir_udp_client_OBJECTS)
+xastir_udp_client_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(testdbfawk_SOURCES) $(xastir_SOURCES) \
+ $(xastir_udp_client_SOURCES)
+DIST_SOURCES = $(testdbfawk_SOURCES) $(xastir_SOURCES) \
+ $(xastir_udp_client_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTSHP = @CONTSHP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GMAGIC_BIN = @GMAGIC_BIN@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBCOMPAT = @LIBCOMPAT@
+LIBOBJS = @LIBOBJS@
+LIBRTREE = @LIBRTREE@
+LIBS = @LIBS@
+LIBSHP = @LIBSHP@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LWPOSTGIS = @LWPOSTGIS@
+MAGIC_BIN = @MAGIC_BIN@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PG_CONFIG = @PG_CONFIG@
+POW_LIB = @POW_LIB@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUBRTREE = @SUBRTREE@
+SUBSHP = @SUBSHP@
+VERSION = @VERSION@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+convert = @convert@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+festival = @festival@
+found_gdal_config = @found_gdal_config@
+gm = @gm@
+gpsman = @gpsman@
+gv = @gv@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lpr = @lpr@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+mv = @mv@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sed = @sed@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+wget = @wget@
+xfontsel = @xfontsel@
+SUBDIRS = @SUBRTREE@ @SUBSHP@
+DIST_SUBDIRS = rtree shapelib
+EXTRA_DIST = icon.xbm
+XASTIR_SRC = \
+ alert.c alert.h \
+ awk.c awk.h \
+ bulletin_gui.c bulletin_gui.h \
+ color.c color.h \
+ datum.c datum.h \
+ db.c database.h \
+ db_gis.c db_gis.h \
+ dbfawk.c dbfawk.h \
+ draw_symbols.c draw_symbols.h \
+ fcc_data.c fcc_data.h \
+ festival.c festival.h \
+ fetch_remote.c fetch_remote.h \
+ geo-find.c geo.h \
+ geocoder_gui.c \
+ gps.c gps.h \
+ hashtable.c hashtable_private.h hashtable.h \
+ hashtable_itr.c hashtable_itr.h \
+ hostname.c hostname.h \
+ igate.c igate.h \
+ interface.c interface.h \
+ interface_gui.c \
+ io-common.c io-mmap.c io.h \
+ lang.c lang.h \
+ leak_detection.h \
+ list_gui.c list_gui.h \
+ locate_gui.c \
+ location.c \
+ location_gui.c \
+ main.c main.h \
+ maps.c maps.h \
+ map_cache.c map_cache.h \
+ map_dos.c \
+ map_gdal.c \
+ map_geo.c \
+ map_gnis.c \
+ map_OSM.c map_OSM.h \
+ map_pop.c \
+ map_pdb.c \
+ map_shp.c \
+ map_tif.c \
+ map_tiger.c \
+ map_WMS.c \
+ messages.c messages.h \
+ messages_gui.c \
+ objects.h objects.c \
+ popup.h \
+ popup_gui.c \
+ rac_data.c rac_data.h \
+ rotated.c rotated.h \
+ rpl_malloc.c rpl_malloc.h \
+ shp_hash.c shp_hash.h \
+ snprintf.c snprintf.h \
+ sound.c symbols.h \
+ tile_mgmnt.c tile_mgmnt.h \
+ track_gui.c track_gui.h \
+ util.c util.h \
+ view_message_gui.c \
+ wx.c wx.h \
+ wx_gui.c \
+ x_spider.c x_spider.h \
+ xa_config.c xa_config.h \
+ xastir.h
+
+xastir_SOURCES = $(XASTIR_SRC) compiledate.c
+xastir_udp_client_SOURCES = \
+ xastir_udp_client.c
+
+testdbfawk_SOURCES = \
+ testdbfawk.c \
+ awk.c \
+ dbfawk.c \
+ rpl_malloc.c rpl_malloc.h
+
+xastir_LDADD = @LIBRTREE@ @LIBSHP@
+testdbfawk_LDADD = @LIBSHP@
+xastir_LINK = $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+xastir_udp_client_LINK = $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+testdbfawk_LINK = $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+testdbfawk$(EXEEXT): $(testdbfawk_OBJECTS) $(testdbfawk_DEPENDENCIES)
+ @rm -f testdbfawk$(EXEEXT)
+ $(testdbfawk_LINK) $(testdbfawk_OBJECTS) $(testdbfawk_LDADD) $(LIBS)
+xastir$(EXEEXT): $(xastir_OBJECTS) $(xastir_DEPENDENCIES)
+ @rm -f xastir$(EXEEXT)
+ $(xastir_LINK) $(xastir_OBJECTS) $(xastir_LDADD) $(LIBS)
+xastir_udp_client$(EXEEXT): $(xastir_udp_client_OBJECTS) $(xastir_udp_client_DEPENDENCIES)
+ @rm -f xastir_udp_client$(EXEEXT)
+ $(xastir_udp_client_LINK) $(xastir_udp_client_OBJECTS) $(xastir_udp_client_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/alert.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/awk.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/bulletin_gui.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/color.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/compiledate.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/datum.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/db.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/db_gis.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/dbfawk.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/draw_symbols.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/fcc_data.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/festival.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/fetch_remote.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/geo-find.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/geocoder_gui.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gps.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/hashtable.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/hashtable_itr.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/hostname.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/igate.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/interface.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/interface_gui.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/io-common.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/io-mmap.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/lang.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/list_gui.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/locate_gui.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/location.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/location_gui.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/main.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/map_OSM.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/map_WMS.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/map_cache.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/map_dos.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/map_gdal.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/map_geo.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/map_gnis.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/map_pdb.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/map_pop.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/map_shp.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/map_tif.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/map_tiger.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/maps.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/messages.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/messages_gui.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/objects.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/popup_gui.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/rac_data.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/rotated.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/rpl_malloc.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shp_hash.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/snprintf.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/sound.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/testdbfawk.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/tile_mgmnt.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/track_gui.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/util.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/view_message_gui.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/wx.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/wx_gui.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/x_spider.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/xa_config.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/xastir_udp_client.Po at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(PROGRAMS)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic ctags ctags-recursive distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
+ ps ps-am tags tags-recursive uninstall uninstall-am \
+ uninstall-binPROGRAMS
+
+
+compiledate.c: $(XASTIR_SRC)
+ rm -f compiledate.c compiledate.o
+ echo 'char compiledate[] = "'"Compiled: `date`"'";' > compiledate.c
+
+remove_compiledate:
+ rm -f compiledate.c compiledate.o
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/alert.c b/src/alert.c
new file mode 100644
index 0000000..4a33099
--- /dev/null
+++ b/src/alert.c
@@ -0,0 +1,2275 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: alert.c,v 1.113 2012/03/02 20:26:50 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+
+// alert_redraw_on_update will cause refresh_image to get called.
+// alert_add_entry sets it.
+
+
+// In the alert structure, flags[] is size 16. Only the first two
+// positions in the array are currently used.
+//
+// alert_entry.flags[0] // on_screen
+// ? Initial state or ready-to-recompute state
+// - Expired between 1 sec and 1 hour
+// Y Active alert within viewport
+// N Active alert outside viewport
+//
+// alert_entry.flags[1] // source
+// DATA_VIA_TNC
+// DATA_VIA_LOCAL
+//
+// alert_entry.to alert_entry.alert_level
+// CANCL C // Colors of alerts?????
+// TEST T // Colors of alerts?????
+// WARN R // Colors of alerts?????
+// CIVIL R // Colors of alerts?????
+// WATCH Y // Colors of alerts?????
+// ADVIS B // Colors of alerts?????
+// Other G // Colors of alerts?????
+// Unset ?
+//
+//
+// Here's how Xastir breaks down an alert into an alert struct:
+//
+// SFONPW>APRS::NWS-ADVIS:191700z,WIND,CA_Z007,CA_Z065, ALAMEDA AND CON & NAPA COUNTY {JDIAA
+// |----| |-------| |-----| |--| |-----| |-----| |-|
+// | | | | | | |
+// from to | | title title issue_date
+// | alert_tag
+// activity (expiration)
+//
+//
+// The code should also handle the case where the packet looks like
+// this (it's the same as the above packet except for no expiration
+// date):
+//
+// SFONPW>APRS::NWS-ADVIS:WIND,CA_Z007,CA_Z065, ALAMEDA AND CON & NAPA COUNTY {JDIAA
+//
+//
+// Expiration is then computed from the activity field. Alert_level
+// is computed from "to" and/or "alert_tag".
+//
+//
+// Stuff from Dale, paraphrased by Curt:
+//
+// WATCH - weather of some type is possible or probable for a geographic
+// area- at present I cannot do watches because they can cover huge areas
+// with hundreds of counties across many states. I have a prototye of a
+// polygon generator - but that is a whole other can of worms
+//
+// WARN - warning - Severe or dangerous weather is occuring or is about to
+// occur in a geographical area. This we do a pretty good job on output.
+//
+// ADVIS - advisory - this can be trivial all the way to a tornado report.
+// If a tornado warning is issued and another tornado sighting happens in
+// the same county/zone during the valid time of the first- the info is
+// transmitted as an advisory. Most of the time is is updates for other
+// messages.
+//
+// CANCL - cancelation- discussed in earlier e-mail
+//
+// I would add CIVIL for terrorist earthquake catostrophic type stuff -
+// the D7 and D&)) have special alarms built in so that a message to
+// NWS-CIVIL would alert folks no matter what there filters are set for.
+//
+//
+// The clue to which shapefile to use is in the 4th char in the
+// title (which is the first following an '_')
+//
+// ICTSVS>APRS::NWS-ADVIS:120145z,SEVERE_WEATHER,KS_Z091, {C14AA
+// TSASVR>APRS::NWS-WARN :120230z,SVRTSM,OK_C113, OSAGE COUNTY {C16AA
+//
+// C = county file (c_mmddyy.dbf)
+// A = County Warning File (w_mmddyy.dbf)
+// Z = Zone File (z_mmddyy.dbf or mz_mmddyy.dbf)
+// F = Fire zone file (fz_mmddyy.dbf)
+// A = Canadian Area (a_mmddyy.dbf)
+// R = Canadian Region (r_mmddyy.dbf)
+//
+// Alerts are comma-delimited on the air s.t. after the
+// :NWS-?????: the first field is the time in zulu (or local
+// with no 'z'), the 2nd is the warning type
+// (severe_thunderstorm etc.), the 3rd and up to 7th are s.t.
+// the first 2 letters are the state or marine zone (1st field
+// in both the county and zone .dbf files) followed by an
+// underline char '_', the area type as above (C, Z, or A),
+// then a 3 digit numerical code derived from:
+//
+// Counties: the fips code (4th field in the .dbf)
+//
+// Zones: the zone number (2nd field in the .dbf)
+//
+// Marine Zones: have proper code in 1st field with addition of '_' in correct place.
+//
+// CWA: 2nd field has cwa-, these are always "CW_A" plus the cwa
+//
+// You must ignore anything after a space in the alert.
+//
+// We will probably want to add the "issue time" to the alert record
+// and parse that out if it's present. Change the view dialog to
+// show expiration time, issue time, who the alert is apparently
+// from, and the stuff after the curly brace. Some of that info
+// will be useful soon in a finger command to the weather server.
+//
+// New compressed-mode weather alert packets:
+//
+// LZKNPW>APRS::NWS-ADVIS:221000z,WINTER_STORM,ARZ003>007-012>016-021>025-030>034-037>047-052>057-062>069{LLSAA
+//
+// The trick is to step thru the data base contained in the
+// shapefiles to determine what areas to light up. In the above
+// example read ">" as "thru" and "-" as "and".
+//
+// More from Dale:
+// It occurs to me you might need some insight into what shapefile to look
+// through for a zone/county. The current shape files are c_22mr02,
+// z_16mr02, and mz21fe02.
+//
+// ICTSVS>APRS::NWS-ADVIS:120145z,SEVERE_WEATHER,KS_Z091, {C14AA
+// would be in z_ file
+//
+// TSASVR>APRS::NWS-WARN :120230z,SVRTSM,OK_C113, OSAGE COUNTY {C16AA
+// would be in c_ file
+//
+// problem comes with marine warnings-
+//
+// AM,AN,GM,PZ,PK,PM,LS,LM,LH,LO,LE,SL will look like states, but will all
+// come from the mz file.
+//
+// so AM_Z686 looks like a state zone, but is a marine zone.
+// Aprs Plus requires the exact file name to be specified - winaprs just
+// looks for a file in the nwsshape folder starting c_ z_ and mz. Someone
+// in the middle of Kansas might not need the marine at all- but here I am
+// closer to marine zones than land. The fact there is an index file for
+// the shapes should help the speed in a lookup.
+//
+// More from Dale:
+// The CWA areas themselves were included for just one product- generally
+// called the "Hazardous Weather Outlook". The idea was to be able to
+// click on your region and get a synopsis as a Skywarn Heads-up. In
+// winaprs it turned out that you would get (unwanted) the CWA outline
+// instead of some other data about a specific station. It makes more
+// sense to have three or 4 "home CWA'S" that are defined in the config
+// file - and have a dialog box to view the Hazardous WX Outlook and
+// watches and warnings just for that CWA. One step futher- I assume there
+// is something that trips alarms when a warning is received for a county
+// or zone right around you - the cwa or cwa's of interest could be derived
+// from that if it already exists. A long way to say don't worry about CWA
+// maps as far as watches/warnings.
+//
+// I think the easy coding for determining which shapefile to use would
+// look like;
+//
+// char sevenCharStr[8]; // seven character string in warning or derived
+// // from compressed string i. e. AL_Z001
+//
+// if the 4th char == 'C' then use "c_shapefile"
+// if the 4th char == 'Z';
+// if the first two char == 'AN' ||
+// if the first two char == 'AM' ||
+// if the first two char == 'GM' ||
+// If the first two char == 'PZ' ||
+// if the first two char == 'LH' ||
+// if the first two char == 'LO' ||
+// if the first two char == 'LS' ||
+// if the first two char == 'SL' ||
+// if the first two char == 'LM' ||
+// then use the "mzshapefile"
+// else use the "z_shapefile"
+//
+// I am running out of time but that should be all there is to it- I
+// will send you a complete list of marine zones later today- I
+// think there are no more than 13 or 14 to search through - better
+// that the 54 "states"- could be hard coded.
+
+// We now have fire weather alerts also. From Dale:
+// "Ok I think we can use this to solve a problem with the Fire
+// Watches and Warnings taking over the map of someone not
+// interested. Roger, I had to take Fire warnings off the regular
+// aprs-is feeds and send it to firenet.us server only because of
+// complaints of the maps getting cluttered-- with data most people
+// didn't want. Even though the NWS sends "AZZ148" just as if it
+// were to be found in the z_mmddyy.dbf (warning zone) type file,
+// wxsvr knows it is coming out of a "Fire Weather" type product and
+// can substitute "AZF148" . Client software (read xastir &
+// Ui-view) would know to look in the fireweather shapefile. If
+// someone doesn't have the fire shapefile loaded, it would just be
+// ignored (I think)."
+
+
+// Found on the AWIPS web pages so far:
+// AWIPS Counties C
+// County Warning Areas A
+// Zone Forecast Areas Z
+// Coastal Marine Zones Z
+// Offshore Marine Zones Z
+// High Seas Marine Zones Z (Says "Not for operational use")
+// Fire Weather Zones FZ
+//
+// Don't forget about the Canadian Areas and Regions, which are
+// created by Dale Huguley from Environment Canada data.
+//
+//
+// AWIPS Counties:
+// -----------------------------
+// STATE character 2
+// CWA character 9
+// COUNTYNAME character 24
+// FIPS character 5
+// TIME_ZONE character 2
+// FE_AREA character 2
+// LON numeric 10,5
+// LAT numeric 9,5
+//
+//
+// County Warning Areas:
+// -----------------------------
+// WFO character 3
+// CWA character 3
+// LON numeric 10,5
+// LAT numeric 9,5
+//
+//
+// Zone Forecast Areas:
+// -----------------------------
+// STATE character 2
+// ZONE character 3
+// CWA character 3
+// NAME character 254
+// STATE_ZONE character 5
+// TIME_ZONE character 2
+// FE_AREA character 2
+// LON numeric 10,5
+// LAT numeric 9,5
+//
+//
+// Coastal and Offshore Marine Zones:
+// ----------------------------------
+// ID character 6
+// WFO character 3
+// NAME character 250
+// LON numeric 10,5
+// LAT numeric 9,5
+// WFO_AREA character 200
+//
+//
+// High Seas Marine Zones:
+// -----------------------------
+// WFO character 3
+// LON numeric 10,5
+// LAT numeric 9,5
+// HEADING character 250
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <assert.h>
+#include <ctype.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif // HAVE_LOCALE_H
+
+#ifdef HAVE_LIBINTL_H
+#include <libintl.h>
+#define _(x) gettext(x)
+#else // HAVE_LIBINTL_H
+#define _(x) (x)
+#endif // HAVE_LIBINTL_H
+
+#include <Xm/XmAll.h>
+
+#include "xastir.h"
+#include "alert.h"
+#include "util.h"
+#include "snprintf.h"
+#include "wx.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+
+// New method for weather alerts, using a hash
+//
+#define ALERT_HASH_SIZE 4096
+static struct hashtable *wx_alert_hash = NULL;
+
+int alert_redraw_on_update = 0;
+
+
+
+
+
+/////////////////////////////////////////////////////////////////////
+// The following group of functions implement hash storage for
+// weather alerts. This makes the code very fast, which is good
+// because we run through these alerts often.
+/////////////////////////////////////////////////////////////////////
+
+
+
+// Starting with an alert_entry, create a concatenated string
+// containing:
+//
+// *) "From" callsign
+// *) Zone
+// *) First four chars after the '{' char (the "issue date" field
+// plus one more character).
+//
+// These items should make the alert unique or nearly unique whether
+// it was received from the WXSVR software or from hand-entered
+// alerts. WXSVR is where all of the machine-readable alerts come
+// from and is run by Dale Huguley.
+//
+// This function takes a mostly filled-in alert_entry and fills in
+// the unique_string variable portion with values from other
+// variables in the record.
+//
+void alert_fill_unique_string(alert_entry *alert) {
+ xastir_snprintf(alert->unique_string,
+ sizeof(alert->unique_string),
+ "%s%s%c%c%c%c",
+ alert->from,
+ alert->title,
+ alert->seq[0],
+ alert->seq[1],
+ alert->seq[2],
+ alert->seq[3]);
+
+ //fprintf(stderr,"'%s'\t'%s'\t'%s'\n", alert->from, alert->title, alert->seq);
+// fprintf(stderr,"Unique string:'%s'\n", alert->unique_string);
+}
+
+
+
+
+
+// Add the chars (multiplied by a function of their index number to
+// weight them) then truncate the final number to ALERT_HASH_SIZE.
+// This should spread them nicely over the entire hash table.
+//
+unsigned int wx_alert_hash_from_key(void *key) {
+ alert_entry *temp = key;
+ char *jj = temp->unique_string;
+ unsigned int hash = 1;
+ int ii = 1;
+
+ while (*jj != '\0') {
+ hash = hash + ((unsigned int)*jj++ * ii);
+ ii += 4;
+ }
+
+ hash = hash % ALERT_HASH_SIZE;
+
+//fprintf(stderr,"%d\n", hash);
+
+ return ((unsigned int)hash);
+}
+
+
+
+
+
+// According to Dale Huguley the FROM callsign plus the first four
+// chars after the curly brace (at the end) should make the record
+// unique. Whether or not CANCEL messages get assigned to the
+// proper live record is another matter. They may, or may not match
+// using this scheme, but it's probably better than other schemes.
+// Multiple types of alerts can come out in the same message for the
+// same zone/county. In this case the fourth character will change
+// from an 'A' to a 'B' or other char to denote the different
+// messages with the same FROM and timestamp chars. This again
+// keeps each alert unique.
+//
+int wx_alert_keys_equal(void *key1, void *key2) {
+ alert_entry *t1 = key1;
+ alert_entry *t2 = key2;
+
+ // These fprintf's allow us to see how many cache hits we get
+ // and what the results were of the match. If different
+ // unique_string's hash to the same value, we run through this
+ // compare once for each already-inserted record that also has
+ // the same hash vaue.
+// fprintf(stderr,"Comparing %s to %s\t",(char *)key1,(char *)key2);
+
+ if (strlen((char *)t1->unique_string) == strlen((char *)t2->unique_string)
+ && strncmp((char *)t1->unique_string,
+ (char *)t2->unique_string,
+ strlen((char *)t1->unique_string))==0) {
+
+// fprintf(stderr," match %s = %s\n", t1->unique_string, t2->unique_string);
+ return(1);
+ }
+ else {
+// fprintf(stderr," no match\n");
+ return(0);
+ }
+}
+
+
+
+
+
+// Creates the wx_alert_hash if it doesn't exist yet. If clobber is
+// non-zero, destroys any existing hash then creates a new one.
+//
+void init_wx_alert_hash(int clobber) {
+// fprintf(stderr," Initializing wx_alert_hash \n");
+ // make sure we don't leak
+//fprintf(stderr,"init_wx_alert_hash\n");
+ if (wx_alert_hash) {
+//fprintf(stderr,"Already have one!\n");
+ if (clobber) {
+//fprintf(stderr,"Clobbering hash table\n");
+ hashtable_destroy(wx_alert_hash, 1);
+ wx_alert_hash = create_hashtable(ALERT_HASH_SIZE,
+ wx_alert_hash_from_key,
+ wx_alert_keys_equal);
+ }
+ }
+ else {
+//fprintf(stderr,"Creating hash table from scratch\n");
+ wx_alert_hash = create_hashtable(ALERT_HASH_SIZE,
+ wx_alert_hash_from_key,
+ wx_alert_keys_equal);
+ }
+}
+
+
+
+
+
+// Fetch an alert from the wx_alert_hash based on the from call
+// concatenated with the first four chars after the '{' character.
+// This concatenated string should be unique across weather alerts
+// if the alert came from the WXSVR.
+//
+// If it was a hand-entered alert, it won't have the '{' string at
+// the end. In that case use the from call and zone concatenated
+// together instead for matching purposes.
+//
+alert_entry *get_wx_alert_from_hash(char *unique_string) {
+ alert_entry *result = NULL;
+
+ if (unique_string == NULL || *unique_string == '\0') {
+ fprintf(stderr,"Empty unique_string passed to get_wx_alert_from_hash()\n");
+ return(NULL);
+ }
+
+ if (!wx_alert_hash) { // no table to search
+//fprintf(stderr,"Creating hash table\n");
+ init_wx_alert_hash(1); // so create one
+ return NULL;
+ }
+
+//fprintf(stderr," searching for %s...",unique_string);
+
+ result = hashtable_search(wx_alert_hash, unique_string);
+ return (result);
+}
+
+
+
+
+
+// Add a wx alert to the hash.
+// This function checks whether there already is something in the
+// hash table that matches. If a match found, it skips the record,
+// else it inserts a new wx alert record into the hash.
+//
+// Unfortunately it appears that any unique_string that hashes to
+// the same value causes us to think it's a duplicate.
+//
+void add_wx_alert_to_hash(char *unique_string, alert_entry *alert_record) {
+ alert_entry *temp; // alert_record
+ alert_entry *new_record;
+ char *new_unique_str;
+
+
+ if (debug_level & 2)
+ fprintf(stderr,"add_wx_alert_to_hash start\n");
+
+ if (unique_string == NULL
+ || unique_string[0] == '\0'
+ || alert_record == NULL) {
+ if (debug_level & 2)
+ fprintf(stderr,"add_wx_alert_to_hash finish\n");
+ return;
+ }
+
+ if (!wx_alert_hash) { // no table to add to
+//fprintf(stderr,"init_wx_alert_hash\n");
+ init_wx_alert_hash(1); // so create one
+ }
+
+ // Remove any matching entry to avoid duplicates
+ temp = hashtable_remove(wx_alert_hash, unique_string);
+ if (temp) { // If value found, free the storage space for it as
+ // the hashtable_remove function doesn't. It does
+ // however remove the key (callsign) ok.
+ free(temp);
+ }
+
+//fprintf(stderr, "\t\t\tAdding %s...\n", unique_string);
+
+ // Allocate new space for the key and the record
+ new_unique_str = (char *)malloc(50);
+ CHECKMALLOC(new_unique_str);
+
+ new_record = (alert_entry*)malloc(sizeof(alert_entry));
+ CHECKMALLOC(new_record);
+
+ xastir_snprintf(new_unique_str, 50, "%s", unique_string);
+
+ memcpy(new_record, alert_record, sizeof(alert_entry));
+
+ // hash title alert_record
+ if (!hashtable_insert(wx_alert_hash, new_unique_str, new_record)) {
+ fprintf(stderr,"Insert failed on wx alert hash --- fatal\n");
+ free(new_unique_str);
+ free(new_record);
+// exit(1);
+ }
+
+ // Yet another check to see whether hash insert/update worked
+ // properly
+ temp = get_wx_alert_from_hash(unique_string);
+ if (!temp) {
+ fprintf(stderr,"***Failed wx alert hash insert/update***\n");
+ }
+ else {
+//fprintf(stderr,"Current: %s -> %s\n",
+// unique_string,
+// temp);
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"add_wx_alert_to_hash finish\n");
+}
+
+
+
+
+
+// Create the wx alert hash table iterator so that we can iterate
+// through the entire hash table and draw the alerts.
+//
+struct hashtable_itr *create_wx_alert_iterator(void) {
+
+ if (wx_alert_hash && hashtable_count(wx_alert_hash) > 0) {
+ return(hashtable_iterator(wx_alert_hash));
+ }
+ else {
+ return(NULL);
+ }
+}
+
+
+
+
+
+// Get the wx alert entry that the iterator is pointing to. Advance
+// the iterator to the following wx alert.
+//
+alert_entry *get_next_wx_alert(struct hashtable_itr *iterator) {
+ alert_entry *temp = NULL;
+
+ if (wx_alert_hash
+ && iterator
+ && hashtable_count(wx_alert_hash) > 0) {
+
+ // Get record
+ temp = hashtable_iterator_value(iterator);
+
+ // Advance to the next record
+ hashtable_iterator_advance(iterator);
+ }
+ return(temp);
+}
+
+
+
+
+// alert_print_list()
+//
+// Debug routine. Currently attached to the Test() function in
+// main.c, but the button in the file menu is normally grey'ed out.
+// This function prints the current weather alert list out to the
+// xterm.
+//
+void alert_print_list(void) {
+
+}
+
+
+
+
+
+// Needed by alert_expire() below
+static time_t last_alert_expire = 0;
+
+
+
+// alert_expire()
+//
+// Function which iterates through the wx alert hash table, removing
+// expired alerts as it goes. Makes sure that the expired alert
+// doesn't get drawn or shown in the View->WX Alerts dialog.
+//
+// Returns the quantity of alerts that were just expired.
+//
+int alert_expire(int curr_sec) {
+// int ii;
+ int expire_count = 0;
+ struct hashtable_itr *iterator;
+ alert_entry *temp;
+
+
+ // Check only every 60 seconds
+ if ( (last_alert_expire + 60) > curr_sec ) {
+ return(0);
+ }
+ last_alert_expire = curr_sec;
+
+ if (debug_level & 2)
+ fprintf(stderr,"Checking for expired alerts...\n");
+
+ iterator = create_wx_alert_iterator();
+ while (iterator) {
+
+ // Get current record
+ temp = hashtable_iterator_value(iterator);
+
+ if (!temp) {
+#ifndef USING_LIBGC
+//fprintf(stderr,"free iterator 1\n");
+ if (iterator) free(iterator);
+#endif // USING_LIBGC
+ return(expire_count);
+ }
+
+ // If wx alert has expired, remove the record from the hash.
+ if (temp->expiration < time(NULL)) {
+
+ if (debug_level & 2) {
+ fprintf(stderr,
+ "alert_expire: Clearing %s, current: %lu, alert: %lu\n",
+ temp->unique_string,
+ (unsigned long)time(NULL),
+ (unsigned long)temp->expiration);
+ }
+
+ // Free the storage space
+ free(temp);
+
+ // Delete the entry and advance to the next
+ hashtable_iterator_remove(iterator);
+
+ expire_count++;
+ }
+ else {
+ if (temp && iterator) {
+ // Else advance to the next entry
+ hashtable_iterator_advance(iterator);
+ }
+ }
+ }
+#ifndef USING_LIBGC
+//fprintf(stderr,"free iterator 2\n");
+ if (iterator) free(iterator);
+#endif // USING_LIBGC
+
+ // Cause a screen redraw if we expired some alerts
+ if (expire_count) {
+ // Schedule a screen update 'cuz we have a new alert
+ alert_redraw_on_update = redraw_on_new_data = 2;
+
+ }
+
+ return(expire_count);
+}
+
+
+
+
+
+// alert_add_entry()
+//
+// This function adds a new alert to our alert list.
+//
+// Returns address of new entry or NULL.
+// Called from alert_build_list() function.
+//
+/*@null@*/ static alert_entry *alert_add_entry(alert_entry *entry) {
+// alert_entry *ptr;
+// int i;
+
+set_dangerous("alert.c:alert_add_entry()");
+
+ if (debug_level & 2)
+ fprintf(stderr,"alert_add_entry\n");
+
+ if (strlen(entry->title) == 0) {
+ if (debug_level & 2)
+ fprintf(stderr,"alert_add_entry: Empty title!\n");
+
+clear_dangerous();
+
+ return(NULL);
+ }
+
+ // Skip NWS_SOLAR and -NoActivationExpected alerts, they don't
+ // interest us.
+ if ( (strcmp(entry->to, "NWS-SOLAR") == 0)
+ || (strcmp(entry->to, "NWS_SOLAR") == 0) ) {
+ if (debug_level & 2)
+ fprintf(stderr,"NWS-SOLAR, skipping\n");
+
+clear_dangerous();
+
+ return(NULL);
+ }
+ if (strcasecmp(entry->title, "-NoActivationExpected") == 0) {
+ if (debug_level & 2)
+ fprintf(stderr,"NoActivationExpected, skipping\n");
+
+clear_dangerous();
+
+ return(NULL);
+ }
+
+ // Check whether this new alert has already expired. If so,
+ // don't add it.
+ if (entry->expiration < time(NULL)) {
+ if (debug_level & 2) {
+ fprintf(stderr,
+ "Newest Alert Expired->Clearing, current: %lu, alert: %lu\n",
+ (unsigned long)time(NULL),
+ (unsigned long)entry->expiration );
+ }
+
+clear_dangerous();
+
+ return(NULL);
+ }
+
+ // Check for non-zero alert title, non-expired alert time in new
+ // alert.
+ if (entry->title[0] != '\0' && entry->expiration >= time(NULL)) {
+
+ // Schedule a screen update 'cuz we have a new alert
+ alert_redraw_on_update = redraw_on_new_data = 2;
+
+//WE7U
+
+set_dangerous("alert.c:add_wx_alert_to_hash()");
+
+add_wx_alert_to_hash(entry->unique_string, entry);
+
+clear_dangerous();
+
+return(entry);
+
+ }
+
+ // If we got to here, the title was empty or the alert has
+ // already expired? Figure out why we might ever get here.
+ if (debug_level & 2) {
+ fprintf(stderr,"Exiting alert_add_entry() without actually adding the alert:\n");
+ fprintf(stderr,"%s %s %lu\n",
+ entry->to,
+ entry->title,
+ (unsigned long)entry->expiration);
+ }
+
+clear_dangerous();
+
+ return(NULL);
+}
+
+
+
+// alert_active()
+//
+// Here's where we get rid of expired alerts in the list. Called
+// from alert_display_request(), alert_on_screen(),
+// and alert_build_list() functions. Also called from
+// maps.c:load_alert_maps() function.
+//
+// Returns the alert level.
+//
+// Alert Match Levels:
+// 0 = ?
+// 1 = R
+// 2 = Y
+// 3 = B
+// 4 = T
+// 5 = G
+// 6 = C
+//
+int alert_active(alert_entry *alert, alert_match_level match_level) {
+ alert_entry *a_ptr;
+ char l_list[] = {"?RYBTGC"};
+ int level = 0;
+ time_t now;
+
+
+ if (strlen(alert->title) == 0) {
+ if (debug_level & 2)
+ fprintf(stderr,"alert_active:NULL\n");
+ return(0);
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"alert_active:%s\n",alert->title);
+
+ (void)time(&now);
+
+// if ((a_ptr = alert_match(alert, match_level))) {
+ if ((a_ptr = get_wx_alert_from_hash(alert->unique_string))) {
+ if (a_ptr->expiration >= now) {
+ for (level = 0; a_ptr->alert_level != l_list[level] && level < (int)sizeof(l_list); level++);
+ }
+ else if (a_ptr->expiration < (now - 3600)) { // More than an hour past the expiration,
+ a_ptr->title[0] = '\0'; // so delete it from list by clearing
+ // out the title.
+//WE7U
+
+ // Schedule an update 'cuz we need to delete an expired
+ // alert from the list.
+ alert_redraw_on_update = redraw_on_new_data = 2;
+ }
+ else if (a_ptr->flags[on_screen] == '?') { // Expired between 1sec and 1hr and found '?'
+ a_ptr->flags[on_screen] = '-';
+
+ // Schedule a screen update 'cuz we have an expired alert
+ alert_redraw_on_update = redraw_on_new_data = 2;
+ }
+ }
+ return (level);
+}
+
+
+
+
+
+// alert_display_request()
+//
+// Function which checks whether an alert should be displayed.
+// Called from maps.c:load_alert_maps() function.
+//
+int alert_display_request(void) {
+// int i;
+ int alert_count;
+ static int last_alert_count;
+
+
+ if (debug_level & 2)
+ fprintf(stderr,"alert_display_request\n");
+
+//WE7U
+ if (wx_alert_hash)
+ alert_count = hashtable_count(wx_alert_hash);
+ else
+ return((int)FALSE);
+
+ // If we found any, return TRUE.
+ if (alert_count != last_alert_count) {
+ last_alert_count = alert_count;
+ return ((int)TRUE);
+ }
+
+ return ((int)FALSE);
+}
+
+
+// alert_list_count
+int alert_list_count(void) {
+ int count = 0;
+ if (wx_alert_hash)
+ return(hashtable_count(wx_alert_hash));
+ else
+ return count;
+}
+
+
+// alert_on_screen()
+//
+// Returns a count of active weather alerts in the list which are
+// within our viewport.
+// Called from main.c:UpdateTime() function. Used for sounding
+// alarm if a new weather alert appears on screen.
+//
+int alert_on_screen(void) {
+// int i;
+ int alert_count = 0;
+ struct hashtable_itr *iterator;
+ alert_entry *temp;
+
+
+ if (debug_level & 2)
+ fprintf(stderr,"alert_on_screen\n");
+
+//WE7U
+
+ iterator = create_wx_alert_iterator();
+ temp = get_next_wx_alert(iterator);
+ while (iterator != NULL && temp) {
+ if (alert_active(temp, ALERT_ALL)
+ && temp->flags[on_screen] == 'Y') {
+ alert_count++;
+ }
+ temp = get_next_wx_alert(iterator);
+ }
+#ifndef USING_LIBGC
+//fprintf(stderr,"free iterator 3\n");
+ if (iterator) free(iterator);
+#endif // USING_LIBGC
+
+ return (alert_count);
+}
+
+
+
+
+
+// alert_build_list()
+//
+// This function builds alert_entry structs from message entries that
+// contain NWS alert messages.
+//
+// Called from alert_data_add() function.
+//
+//
+// Here's how Xastir breaks down an alert into an alert struct:
+//
+// SFONPW>APRS::NWS-ADVIS:191700z,WIND,CA_Z007,CA_Z065, ALAMEDA AND CON & NAPA COUNTY {JDIAA
+// |----| |-------| |-----| |--| |-----| |-----| |-|
+// | | | | | | |
+// from to | | title title issue_date
+// | alert_tag
+// activity (expiration)
+//
+//
+// The code should also handle the case where the packet looks like
+// this (same except no expiration date):
+//
+// SFONPW>APRS::NWS-ADVIS:WIND,CA_Z007,CA_Z065, ALAMEDA AND CON & NAPA COUNTY {JDIAA
+//
+// We also have compressed NWS alerts, signified by NWS_ADVIS
+// (underline instead of dash). Note that Pete Loveall, AE5PL, is
+// also sending out alerts and sending the "compressed" zone format
+// with "NWS-" which is different than how Dale Huguley was sending
+// them out. Pete's change is to support Kenwood radios.
+//
+//
+// Expiration is then computed from the activity field. Alert_level
+// is computed from "to" and/or "alert_tag". There can be up to
+// five titles in this original format.
+//
+// Here are some real examples captured over the 'net (may be quite old):
+//
+// TAEFFS>APRS::NWS-ADVIS:181830z,FLOOD,FL_C013,FL_C037,FL_C045,FL_C077, {HHEAA
+// ICTFFS>APRS::NWS-ADVIS:180200z,FLOOD,KS_C035, {HEtAA
+// JANFFS>APRS::NWS-ADVIS:180200z,FLOOD,MS_C049,MS_C079,MS_C089,MS_C099,MS_C121, {HEvAA
+// DSMFFS>APRS::NWS-ADVIS:180500z,FLOOD,IA_Z086, {HHGAA
+// EAXFFS>APRS::NWS-ADVIS:180500z,FLOOD,MO_Z023,MO_Z024,MO_Z028,MO_Z030,MO_Z031, {HHIAA
+// SECIND>APRS::NWS-SOLAR:Flx134 A004 BK0001232. PlnK0000232.Ep............Ee........ {HLaAA
+// SHVFFS>APRS::NWS-ADVIS:181800z,FLOOD,TX_C005,TX_C073,TX_C347,TX_C365,TX_C401, {HF2AA
+// FWDFFS>APRS::NWS-ADVIS:180200z,FLOOD,TX_C379,TX_C467, {HF5AA
+// LCHFFS>APRS::NWS-ADVIS:180400z,FLOOD,LA_C003,LA_C079, {HIdAA
+// GIDFFS>APRS::NWS-ADVIS:180200z,FLOOD,NE_C125, {H2uAA
+// FWDSWO>APRS::NWS-ADVIS:181100z,SKY,CW_AFWD, -NO Activation Expected {HLqAA
+// BGMWSW>APRS::NWS-ADVIS:180500z,WINTER_WEATHER,NY_Z015,NY_Z016,NY_Z017,NY_Z022,NY_Z023, {HKYAA
+// AMAWSW>APRS::NWS-WARN :180400z,WINTER_STORM,OK_Z001,OK_Z002,TX_Z001,TX_Z002,TX_Z003, {HLGBA
+//
+// New compressed-mode weather alert packets:
+//
+// LZKNPW>APRS::NWS-ADVIS:221000z,WINTER_STORM,ARZ003>007-012>016-021>025-030>034-037>047-052>057-062>069{LLSAA
+//
+// or perhaps (leading zeroes removed):
+//
+// LZKNPW>APRS::NWS-ADVIS:221000z,WINTER_STORM,ARZ3>7-12>16-21>25-30>34-37>47-52>57-62>69{LLSAA
+//
+// This one's real:
+// DVNFFS>APRS,qAO,WXSVR::NWS_ADVIS:022300z,FLOOD,IAC57-95-103-111-115-163-171-ILC1-67-71-131-MOC45 {2FsAA
+//
+// The trick is to step thru the data base contained in the
+// shapefiles to determine what areas to light up. In the above
+// example read ">" as "thru" and "-" as "and".
+//
+//
+// RIWWSW>APRS::NWS-WARN :191800z,WINTER_STORM,WY_Z014, GREEN MOUNTAINS {JBNBA
+// RIWWSW>APRS::SKYRIW :WINTER STORM WARNING CONTINUING TODAY {JBNBB
+// RIWWSW>APRS::SKYRIW :THROUGH SATURDAY {JBNBC
+//
+//
+// We'll create and fill in "entry", then copy various "titles" into
+// is such as "ID_C001", then insert that alert into the system.
+//
+//
+// VK2XJG - November 2011:
+// Here are some examples of strings from the new WXSVR-AU for the Aussie Bureau of Meteorology (BOM) alerts:
+//
+// NECMWW>APRS::BOM_WARN :141300z,WIND,TAS_MW002>003-005>007-009 {D55AG
+// YKPMWW>APRS::BOM_ADVIS:131330z,WIND,SA_MW005 {D5aAA
+//
+// For the BOM alerts note that the STATE portion of the zone can be two or three characters - valid state
+// prefixes are "NSW,VIC,QLD,TAS,NT,WA,SA". The two characters following the underscore denote the shapefile to use
+// These will be one of "CW,MW,PW,FW or ME".
+//
+// WXSVR-AU also does NOT strip leading zeros from the zone strings, however the existing NWS code allows for this, so
+// it should be supported if WXSVR-AU strips the zeros in the future.
+//
+//
+//
+#define TITLE_SIZE 64
+void alert_build_list(Message *fill) {
+ alert_entry entry, *list_ptr;
+ char title[5][TITLE_SIZE+1]; // Storage place for zone/county titles
+ int ii, jj;
+ char *ptr;
+ DataRow *p_station;
+ int compressed_wx_packet = 0;
+ char uncompressed_wx[10000];
+ struct hashtable_itr *iterator;
+
+
+ //fprintf(stderr,"Message_line:%s\n",fill->message_line);
+
+ if (debug_level & 2) {
+ fprintf(stderr,"alert_build_list:%s>%s:%s\n",
+ fill->from_call_sign,
+ fill->call_sign,
+ fill->message_line);
+ }
+
+ // Empty this string first
+ uncompressed_wx[0] = uncompressed_wx[1] = '\0';
+
+ // Check for "SKY" text in the "call_sign" field.
+ if (strncmp(fill->call_sign,"SKY",3) == 0) {
+ // Special handling for SKY messages only.
+
+ if (debug_level & 2)
+ fprintf(stderr,"Sky Message: %s\n",fill->message_line);
+
+ // Find a matching alert_record, check whether or not it is
+ // expired. If not, add this additional text into the
+ // "desc[0123]" fields, in order. Check that the
+ // FROM callsign and the first four chars after the curly
+ // brace match. The next character specifies which message
+ // block to fill in. In order they should be:
+ //
+ // B = "desc0"
+ // C = "desc1"
+ // D = "desc2"
+ // E = "desc3".
+ //
+ // A matching alert record would have the same "from" field
+ // and the first four characters of the "seq" field would
+ // match.
+ //
+ // Need to make this SKY data expire from the message list
+ // somehow?
+ //
+ // Remember to blank out these fields when we expire an
+ // alert. Check that all other fields are cleared in this
+ // case as well.
+ //
+
+ // Run through the alert list looking for a match to the
+ // FROM and first four chars of SEQ
+//WE7U
+ iterator = create_wx_alert_iterator();
+ for (list_ptr = get_next_wx_alert(iterator); iterator != NULL && list_ptr; list_ptr = get_next_wx_alert(iterator)) {
+ if ( (strcasecmp(list_ptr->from, fill->from_call_sign) == 0)
+ && ( strncmp(list_ptr->seq,fill->seq,4) == 0 ) ) {
+
+ if (debug_level & 2)
+ fprintf(stderr,"%s:Found a matching alert to a SKY message:\t",list_ptr->seq);
+
+ switch (fill->seq[4]) {
+ case 'B':
+ xastir_snprintf(list_ptr->desc0,
+ sizeof(list_ptr->desc0),
+ "%s",
+ fill->message_line);
+ if (debug_level & 2)
+ fprintf(stderr,"Wrote into desc0: %s\n",fill->message_line);
+ break;
+ case 'C':
+ xastir_snprintf(list_ptr->desc1,
+ sizeof(list_ptr->desc1),
+ "%s",
+ fill->message_line);
+ if (debug_level & 2)
+ fprintf(stderr,"Wrote into desc1: %s\n",fill->message_line);
+ break;
+ case 'D':
+ xastir_snprintf(list_ptr->desc2,
+ sizeof(list_ptr->desc2),
+ "%s",
+ fill->message_line);
+ if (debug_level & 2)
+ fprintf(stderr,"Wrote into desc2: %s\n",fill->message_line);
+ break;
+ case 'E':
+ default:
+ xastir_snprintf(list_ptr->desc3,
+ sizeof(list_ptr->desc3),
+ "%s",
+ fill->message_line);
+ if (debug_level & 2)
+ fprintf(stderr,"Wrote into desc3: %s\n",fill->message_line);
+ break;
+ }
+ }
+ }
+ if (debug_level & 2)
+ fprintf(stderr,"alert_build_list return 1\n");
+#ifndef USING_LIBGC
+//fprintf(stderr,"free iterator a4\n");
+ if (iterator) free(iterator);
+#endif // USING_LIBGC
+ return;
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"1\n");
+
+ if (fill->active == RECORD_ACTIVE) {
+ int ignore_title = 0;
+#define MAX_SUB_ALERTS 5000
+ char *title_ptr[MAX_SUB_ALERTS];
+ int ret;
+
+
+ if (debug_level & 2)
+ fprintf(stderr,"2\n");
+
+ memset(&entry, 0, sizeof(entry));
+ // flags[0] specifies whether it's onscreen or not
+ memset(entry.flags, (int)'?', sizeof(entry.flags));
+
+ // flags[source] specifies source of the alert DATA_VIA_TNC or
+ // DATA_VIA_LOCAL
+ entry.flags[source] = fill->heard_via_tnc;
+ p_station = NULL;
+ if (search_station_name(&p_station,fill->from_call_sign,1))
+ entry.flags[source] = p_station->data_via;
+
+ // Zero the title strings. We can have up to five alerts in
+ // a non-compressed weather alert.
+ title[0][0] = '\0';
+ title[1][0] = '\0';
+ title[2][0] = '\0';
+ title[3][0] = '\0';
+ title[4][0] = '\0';
+
+ // This fills in the zone numbers (title) for uncompressed
+ // alerts with up to five alerts per message. This doesn't
+ // handle filling in the title for compressed alerts though.
+ ret = sscanf(fill->message_line,
+ "%20[^,],%20[^,],%32[^,],%32[^,],%32[^,],%32[^,],%32[^,]",
+ entry.activity, // 191700z
+ entry.alert_tag, // WIND
+ &title[0][0], // CA_Z007
+ &title[1][0], // ...
+ &title[2][0], // ...
+ &title[3][0], // ...
+ &title[4][0]); // ...
+
+ if (ret < 3)
+ fprintf(stderr,"sscanf parsed %d values in alert.c (3-7 ok) %s->%s: %s\n", ret,
+ fill->from_call_sign, fill->call_sign, fill->message_line);
+
+ // Force a termination for each
+ entry.activity[20] = '\0';
+ entry.alert_tag[20] = '\0';
+ title[0][TITLE_SIZE] = '\0';
+ title[1][TITLE_SIZE] = '\0';
+ title[2][TITLE_SIZE] = '\0';
+ title[3][TITLE_SIZE] = '\0';
+ title[4][TITLE_SIZE] = '\0';
+
+ // Check for "NWS_" in the call_sign field. Underline
+ // signifies compressed alert format. Dash signifies
+ // non-compressed format.
+//
+// TEMPORARY CHANGE: Process all NWS_ or NWS- as compressed to
+// handle the format that Pete Loveall, AE5PL, is putting out on the
+// 'net. The correct change would be to check inside the data
+// portion for compressed-format zones in all cases and de-compress
+// them when found.
+// WE7U.
+//
+// if (strncmp(fill->call_sign,"NWS_",4) == 0) {
+ if ( (strncmp(fill->call_sign,"NWS_",4) == 0)
+ || (strncmp(fill->call_sign,"NWS-",4) == 0) ) {
+
+ char compressed_wx[512];
+ char *ptr;
+
+/////////////////////////////////////////////////////////////////////
+// Compressed weather alert special code
+/////////////////////////////////////////////////////////////////////
+
+ compressed_wx_packet++; // Set the flag
+
+//fprintf(stderr, "Found compressed alert packet via NWS_!\n");
+
+//fprintf(stderr,"Compressed Weather Alert:%s\n",fill->message_line);
+//fprintf(stderr,"Compressed alerts are not fully implemented yet.\n");
+
+ // Create a new weather alert for each of these and then
+ // call this function on each one? Seems like it might
+ // work fine if we watch out for global variables.
+ // Another method would be to create an incoming message
+ // for each one and add it to the message queue, or just
+ // a really long new message and add it to the queue,
+ // in which case we'd exit from this routine as soon as
+ // it was submitted.
+ ret = sscanf(fill->message_line, "%20[^,],%20[^,],%255[^, ]",
+ entry.activity,
+ entry.alert_tag,
+ compressed_wx); // Stick the long string in here
+
+ if (ret != 3) {
+ fprintf(stderr,"sscanf parsed %d/3 values in alert.c\n", ret);
+ compressed_wx[0] = '\0'; // Remove stale compressed alerts.
+ compressed_wx_packet = 0; //Clear flag in error condition.
+ }
+
+ compressed_wx[255] = '\0';
+
+//fprintf(stderr,"Line:%s\n",compressed_wx);
+
+ // Snag alpha characters (should be three) at the start
+ // of the string. Use those until we hit more alpha
+ // characters. First two characters of each 3-letter
+ // alpha group are the state, last character is the
+ // zone/county/marine-zone indicator.
+
+// Need to be very careful here to validate the letters/numbers, and
+// to not run off the end of the string. Need more code here to do
+// this validation.
+
+
+ // Scan through entire string
+ ptr = compressed_wx;
+ while (ptr < (compressed_wx + strlen(compressed_wx))) {
+ char prefix[5];
+ char suffix[4];
+ char temp_suffix[4];
+ char ending[4];
+ int iterations = 0;
+
+
+ // Snag the ALPHA portion
+ xastir_snprintf(prefix,
+ sizeof(prefix),
+ "%s",
+ ptr);
+ ptr += 2;
+ prefix[2] = '_';
+ prefix[3] = ptr[0];
+ prefix[4] = '\0'; // Terminate the string
+ ptr += 1;
+
+ // prefix should now contain something like "MN_Z"
+
+ // Snag the NUMERIC portion. Note that the field
+ // width can vary between 1 and 3. The leading
+ // zeroes have been removed.
+ xastir_snprintf(temp_suffix,
+ sizeof(temp_suffix),
+ "%s",
+ ptr);
+
+ temp_suffix[3] = '\0'; // Terminate the string
+ if (temp_suffix[1] == '-' || temp_suffix[1] == '>') {
+ temp_suffix[1] = '\0';
+ ptr += 1;
+ }
+ else if (temp_suffix[1] != '\0' &&
+ (temp_suffix[2] == '-' || temp_suffix[2] == '>')) {
+ temp_suffix[2] = '\0';
+ ptr += 2;
+ }
+ else {
+ ptr += 3;
+ }
+
+ // temp_suffix should now contain something like
+ // "039" or "45" or "2". Add leading zeroes to give
+ // "suffix" a length of 3.
+ xastir_snprintf(suffix,
+ sizeof(suffix),
+ "000");
+ switch (strlen(temp_suffix)) {
+ case 1: // Copy one char across
+ suffix[2] = temp_suffix[0];
+ break;
+ case 2: // Copy two chars across
+ suffix[1] = temp_suffix[0];
+ suffix[2] = temp_suffix[1];
+ break;
+ case 3: // Copy all three chars across
+ xastir_snprintf(suffix,
+ sizeof(suffix),
+ "%s",
+ temp_suffix);
+ break;
+ }
+ // Make sure suffix is terminated properly
+ suffix[3] = '\0';
+
+// We have our first zone (of this loop) extracted!
+if (debug_level & 2)
+ fprintf(stderr,"1Zone:%s%s\n",prefix,suffix);
+
+ // Add it to our zone string. In this case we know
+ // that the lengths of the strings we're working
+ // with are quite short. Little danger of
+ // overrunning our destination string.
+ strncat(uncompressed_wx,
+ ",",
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ strncat(uncompressed_wx,
+ prefix,
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ strncat(uncompressed_wx,
+ suffix,
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ // Terminate it every time
+ uncompressed_wx[9999] = '\0';
+
+if (debug_level & 2)
+ fprintf(stderr,"uncompressed_wx:%s\n",uncompressed_wx);
+
+ // Here we keep looping until we hit another alpha
+ // portion. We need to look at the field separator
+ // to determine whether we have another separate
+ // field coming up or a range to enumerate.
+ while ( (ptr < (compressed_wx + strlen(compressed_wx)))
+ && ( is_num_chr(ptr[1]) ) ) {
+
+ iterations++;
+
+ // Break out of this loop if we don't find an
+ // alpha character fairly quickly. That way the
+ // Xastir main thread can't hang in this loop
+ // forever if the input string is malformed.
+ if (iterations > 30)
+ break;
+
+ // Look for '>' or '-' character. If former, we
+ // have a numeric sequence to ennumerate. If the
+ // latter, we either have another zone number or
+ // another prefix coming up.
+ if (ptr[0] == '>' || ptr[0] == '<') { // Numeric zone sequence
+ int start_number;
+ int end_number;
+ int kk;
+
+
+ ptr++; // Skip past the '>' or '<' characters
+
+ // Snag the NUMERIC portion. May be between
+ // 1 and three digits long.
+ xastir_snprintf(ending,
+ sizeof(ending),
+ "%s",
+ ptr);
+
+ // Terminate the string and advance the
+ // pointer past it.
+ if (!is_num_chr(ending[0])) {
+ // We have a problem, 'cuz we didn't
+ // find at least one number. Packet is
+ // badly formatted.
+ return;
+ }
+ else if (!is_num_chr(ending[1])) {
+ ending[1] = '\0';
+ ptr++;
+ }
+ else if (!is_num_chr(ending[2])) {
+ ending[2] = '\0';
+ ptr+=2;
+ }
+ else {
+ ending[3] = '\0';
+ ptr+=3;
+ }
+
+ // ending should now contain something like
+ // "046" or "35" or "2"
+if (debug_level & 2)
+ fprintf(stderr,"Ending:%s\n",ending);
+
+ start_number = (int)atoi(suffix);
+ end_number = (int)atoi(ending);
+ for ( kk=start_number+1; kk<=end_number; kk++) {
+ xastir_snprintf(suffix,4,"%03d",kk);
+
+if (debug_level & 2)
+ fprintf(stderr,"2Zone:%s%s\n",prefix,suffix);
+
+ // And another zone... Ennumerate
+ // through the sequence, adding each
+ // new zone to our zone string. In this
+ // case we know that the lengths of the
+ // strings we're working with are quite
+ // short. Little danger of overrunning
+ // our destination string.
+ strncat(uncompressed_wx,
+ ",",
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ strncat(uncompressed_wx,
+ prefix,
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ strncat(uncompressed_wx,
+ suffix,
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ // Terminate it every time
+ uncompressed_wx[9999] = '\0';
+ }
+ }
+
+ // Wasn't a '>' character, so check for a '-'
+ else if (ptr[0] == '-') {
+ // New zone number, not a numeric sequence.
+
+ ptr++; // Skip past the '-' character
+
+ if ( is_num_chr(ptr[0]) ) {
+ // Found another number. Use the prefix
+ // stored from last time.
+
+ // Snag the NUMERIC portion. Note that the field
+ // width can vary between 1 and 3. The leading
+ // zeroes have been removed.
+ xastir_snprintf(temp_suffix,
+ sizeof(temp_suffix),
+ "%s",
+ ptr);
+
+ // Terminate the string and advance the
+ // pointer past it.
+ if (!is_num_chr(temp_suffix[0])) {
+ // We have a problem, 'cuz we didn't
+ // find at least one number. Packet is
+ // badly formatted.
+ return;
+ }
+ else if (!is_num_chr(temp_suffix[1])) {
+ temp_suffix[1] = '\0';
+ ptr++;
+ }
+ else if (!is_num_chr(temp_suffix[2])) {
+ temp_suffix[2] = '\0';
+ ptr+=2;
+ }
+ else {
+ temp_suffix[3] = '\0';
+ ptr+=3;
+ }
+
+ // temp_suffix should now contain something like
+ // "039" or "45" or "2". Add leading zeroes to give
+ // "suffix" a length of 3.
+ xastir_snprintf(suffix,
+ sizeof(suffix),
+ "000");
+ switch (strlen(temp_suffix)) {
+ case 1: // Copy one char across
+ suffix[2] = temp_suffix[0];
+ break;
+ case 2: // Copy two chars across
+ suffix[1] = temp_suffix[0];
+ suffix[2] = temp_suffix[1];
+ break;
+ case 3: // Copy all three chars across
+ xastir_snprintf(suffix,
+ sizeof(suffix),
+ "%s",
+ temp_suffix);
+ break;
+ }
+
+if (debug_level & 2)
+ fprintf(stderr,"3Zone:%s%s\n",prefix,suffix);
+
+ // And another zone...
+ // Add it to our zone string. In this
+ // case we know that the lengths of the
+ // strings we're working with are quite
+ // short. Little danger of overrunning
+ // our destination string.
+ strncat(uncompressed_wx,
+ ",",
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ strncat(uncompressed_wx,
+ prefix,
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ strncat(uncompressed_wx,
+ suffix,
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ // Terminate it every time
+ uncompressed_wx[9999] = '\0';
+ }
+ else { // New prefix (not a number)
+ // Start at the top of the outer loop again
+ }
+ }
+ }
+ // Skip past '-' character, if any, so that we can
+ // get to the next prefix
+ // RZG:Added the ptr check, so we don't read a byte off the end
+ if ( (ptr < (compressed_wx + strlen(compressed_wx))) && (ptr[0] == '-') ) {
+ ptr++;
+ }
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"Uncompressed: %s\n",
+ uncompressed_wx);
+ }
+/////////////////////////////////////////////////////////////////////
+// End of compressed weather alert special code
+/////////////////////////////////////////////////////////////////////
+
+ // Australian Buerau of Meeorology alerts (BOM)
+ // Geoff VK2XJG
+
+ // Check for "BOM_" in the call_sign field.
+ // WXSVR-AU delivers messages in this format, keeping the protocol as close to
+ // the NWS WXSVR as possible.
+ // Underline signifies compressed alert format. Dash signifies
+ // non-compressed format, although this has not been implemented on the server.
+
+ if ( (strncmp(fill->call_sign,"BOM_",4) == 0)
+ || (strncmp(fill->call_sign,"BOM-",4) == 0) ) {
+
+ char compressed_wx[512];
+ char *ptr;
+
+/////////////////////////////////////////////////////////////////////
+// Compressed weather alert (BOM) special code
+/////////////////////////////////////////////////////////////////////
+
+ compressed_wx_packet++; // Set the flag
+
+//fprintf(stderr, "Found compressed alert packet via BOM_!\n");
+
+//fprintf(stderr,"Compressed Weather Alert:%s\n",fill->message_line);
+//fprintf(stderr,"Compressed alerts are not fully implemented yet.\n");
+
+ // Create a new weather alert for each of these and then
+ // call this function on each one? Seems like it might
+ // work fine if we watch out for global variables.
+ // Another method would be to create an incoming message
+ // for each one and add it to the message queue, or just
+ // a really long new message and add it to the queue,
+ // in which case we'd exit from this routine as soon as
+ // it was submitted.
+ ret = sscanf(fill->message_line, "%20[^,],%20[^,],%255[^, ]",
+ entry.activity,
+ entry.alert_tag,
+ compressed_wx); // Stick the long string in here
+
+ if (ret != 3) {
+ fprintf(stderr,"sscanf parsed %d/3 values in alert.c\n", ret);
+ compressed_wx[0] = '\0'; // Remove stale compressed alerts.
+ compressed_wx_packet = 0; //Clear flag in error condition.
+ }
+
+ compressed_wx[255] = '\0';
+
+//fprintf(stderr,"Line:%s\n",compressed_wx);
+
+ // Snag alpha characters (should be five) at the start
+ // of the string. Use those until we hit more alpha
+ // characters. First two/three characters of each 5-letter
+ // alpha group are the state, last two characters are the
+ // zone/county/marine-zone indicator.
+
+// Need to be very careful here to validate the letters/numbers, and
+// to not run off the end of the string. Need more code here to do
+// this validation.
+
+
+ // Scan through entire string
+ ptr = compressed_wx;
+ while (ptr < (compressed_wx + strlen(compressed_wx))) {
+ char prefix[7];
+ char suffix[4];
+ char temp_suffix[4];
+ char ending[4];
+ int iterations = 0;
+
+
+ // Snag the ALPHA portion
+ xastir_snprintf(prefix,
+ sizeof(prefix),
+ "%s",
+ ptr);
+ ptr += 3;
+ // Handle a 2 letter state abbreviation (SA/WA/NT)
+ if (prefix[2] == '_' ) {
+ prefix[3] = ptr[0];
+ prefix[5] = '\0'; // Terminate the string
+ ptr += 3;
+ }
+ // All other cases are 3 letter states (NSW/VIC/TAS/QLD)
+ else {
+ prefix[3] = ptr[0];
+ prefix[6] = '\0'; // Terminate the string
+ ptr += 3;
+ }
+
+ // prefix should now contain something like "TAS_CW" or "SA_PW"
+
+ // Snag the NUMERIC portion. Note that the field
+ // width can vary between 1 and 3. The leading
+ // zeroes have been removed.
+ xastir_snprintf(temp_suffix,
+ sizeof(temp_suffix),
+ "%s",
+ ptr);
+
+ temp_suffix[3] = '\0'; // Terminate the string
+ if (temp_suffix[1] == '-' || temp_suffix[1] == '>') {
+ temp_suffix[1] = '\0';
+ ptr += 1;
+ }
+ else if (temp_suffix[1] != '\0' &&
+ (temp_suffix[2] == '-' || temp_suffix[2] == '>')) {
+ temp_suffix[2] = '\0';
+ ptr += 2;
+ }
+ else {
+ ptr += 3;
+ }
+
+ // temp_suffix should now contain something like
+ // "039" or "45" or "2". Add leading zeroes to give
+ // "suffix" a length of 3.
+ xastir_snprintf(suffix,
+ sizeof(suffix),
+ "000");
+ switch (strlen(temp_suffix)) {
+ case 1: // Copy one char across
+ suffix[2] = temp_suffix[0];
+ break;
+ case 2: // Copy two chars across
+ suffix[1] = temp_suffix[0];
+ suffix[2] = temp_suffix[1];
+ break;
+ case 3: // Copy all three chars across
+ xastir_snprintf(suffix,
+ sizeof(suffix),
+ "%s",
+ temp_suffix);
+ break;
+ }
+ // Make sure suffix is terminated properly
+ suffix[3] = '\0';
+
+// We have our first zone (of this loop) extracted!
+if (debug_level & 2)
+ fprintf(stderr,"1Zone:%s%s\n",prefix,suffix);
+
+ // Add it to our zone string. In this case we know
+ // that the lengths of the strings we're working
+ // with are quite short. Little danger of
+ // overrunning our destination string.
+ strncat(uncompressed_wx,
+ ",",
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ strncat(uncompressed_wx,
+ prefix,
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ strncat(uncompressed_wx,
+ suffix,
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ // Terminate it every time
+ uncompressed_wx[9999] = '\0';
+
+if (debug_level & 2)
+ fprintf(stderr,"uncompressed_wx:%s\n",uncompressed_wx);
+
+ // Here we keep looping until we hit another alpha
+ // portion. We need to look at the field separator
+ // to determine whether we have another separate
+ // field coming up or a range to enumerate.
+ while ( (ptr < (compressed_wx + strlen(compressed_wx)))
+ && ( is_num_chr(ptr[1]) ) ) {
+
+ iterations++;
+
+ // Break out of this loop if we don't find an
+ // alpha character fairly quickly. That way the
+ // Xastir main thread can't hang in this loop
+ // forever if the input string is malformed.
+ if (iterations > 30)
+ break;
+
+ // Look for '>' or '-' character. If former, we
+ // have a numeric sequence to ennumerate. If the
+ // latter, we either have another zone number or
+ // another prefix coming up.
+ if (ptr[0] == '>' || ptr[0] == '<') { // Numeric zone sequence
+ int start_number;
+ int end_number;
+ int kk;
+
+
+ ptr++; // Skip past the '>' or '<' characters
+
+ // Snag the NUMERIC portion. May be between
+ // 1 and three digits long.
+ xastir_snprintf(ending,
+ sizeof(ending),
+ "%s",
+ ptr);
+
+ // Terminate the string and advance the
+ // pointer past it.
+ if (!is_num_chr(ending[0])) {
+ // We have a problem, 'cuz we didn't
+ // find at least one number. Packet is
+ // badly formatted.
+ return;
+ }
+ else if (!is_num_chr(ending[1])) {
+ ending[1] = '\0';
+ ptr++;
+ }
+ else if (!is_num_chr(ending[2])) {
+ ending[2] = '\0';
+ ptr+=2;
+ }
+ else {
+ ending[3] = '\0';
+ ptr+=3;
+ }
+
+ // ending should now contain something like
+ // "046" or "35" or "2"
+if (debug_level & 2)
+ fprintf(stderr,"Ending:%s\n",ending);
+
+ start_number = (int)atoi(suffix);
+ end_number = (int)atoi(ending);
+ for ( kk=start_number+1; kk<=end_number; kk++) {
+ xastir_snprintf(suffix,4,"%03d",kk);
+
+if (debug_level & 2)
+ fprintf(stderr,"2Zone:%s%s\n",prefix,suffix);
+
+ // And another zone... Ennumerate
+ // through the sequence, adding each
+ // new zone to our zone string. In this
+ // case we know that the lengths of the
+ // strings we're working with are quite
+ // short. Little danger of overrunning
+ // our destination string.
+ strncat(uncompressed_wx,
+ ",",
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ strncat(uncompressed_wx,
+ prefix,
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ strncat(uncompressed_wx,
+ suffix,
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ // Terminate it every time
+ uncompressed_wx[9999] = '\0';
+ }
+ }
+
+ // Wasn't a '>' character, so check for a '-'
+ else if (ptr[0] == '-') {
+ // New zone number, not a numeric sequence.
+
+ ptr++; // Skip past the '-' character
+
+ if ( is_num_chr(ptr[0]) ) {
+ // Found another number. Use the prefix
+ // stored from last time.
+
+ // Snag the NUMERIC portion. Note that the field
+ // width can vary between 1 and 3. The leading
+ // zeroes have been removed.
+ xastir_snprintf(temp_suffix,
+ sizeof(temp_suffix),
+ "%s",
+ ptr);
+
+ // Terminate the string and advance the
+ // pointer past it.
+ if (!is_num_chr(temp_suffix[0])) {
+ // We have a problem, 'cuz we didn't
+ // find at least one number. Packet is
+ // badly formatted.
+ return;
+ }
+ else if (!is_num_chr(temp_suffix[1])) {
+ temp_suffix[1] = '\0';
+ ptr++;
+ }
+ else if (!is_num_chr(temp_suffix[2])) {
+ temp_suffix[2] = '\0';
+ ptr+=2;
+ }
+ else {
+ temp_suffix[3] = '\0';
+ ptr+=3;
+ }
+
+ // temp_suffix should now contain something like
+ // "039" or "45" or "2". Add leading zeroes to give
+ // "suffix" a length of 3.
+ xastir_snprintf(suffix,
+ sizeof(suffix),
+ "000");
+ switch (strlen(temp_suffix)) {
+ case 1: // Copy one char across
+ suffix[2] = temp_suffix[0];
+ break;
+ case 2: // Copy two chars across
+ suffix[1] = temp_suffix[0];
+ suffix[2] = temp_suffix[1];
+ break;
+ case 3: // Copy all three chars across
+ xastir_snprintf(suffix,
+ sizeof(suffix),
+ "%s",
+ temp_suffix);
+ break;
+ }
+
+if (debug_level & 2)
+ fprintf(stderr,"3Zone:%s%s\n",prefix,suffix);
+
+ // And another zone...
+ // Add it to our zone string. In this
+ // case we know that the lengths of the
+ // strings we're working with are quite
+ // short. Little danger of overrunning
+ // our destination string.
+ strncat(uncompressed_wx,
+ ",",
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ strncat(uncompressed_wx,
+ prefix,
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ strncat(uncompressed_wx,
+ suffix,
+ sizeof(uncompressed_wx) - 1 - strlen(uncompressed_wx));
+ // Terminate it every time
+ uncompressed_wx[9999] = '\0';
+ }
+ else { // New prefix (not a number)
+ // Start at the top of the outer loop again
+ }
+ }
+ }
+ // Skip past '-' character, if any, so that we can
+ // get to the next prefix
+ // RZG:Added the ptr check, so we don't read a byte off the end
+ if ( (ptr < (compressed_wx + strlen(compressed_wx))) && (ptr[0] == '-') ) {
+ ptr++;
+ }
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"Uncompressed: %s\n",
+ uncompressed_wx);
+ }
+/////////////////////////////////////////////////////////////////////
+// End of compressed weather (BOM) alert special code
+/////////////////////////////////////////////////////////////////////
+
+
+
+ if (debug_level & 2)
+ fprintf(stderr,"3\n");
+
+ // Terminate the strings
+ entry.activity[20] = entry.alert_tag[20] = '\0';
+
+ // If the expire time is missing, shift fields to the right
+ // by one field. Evidently we can have an alert come across
+ // that doesn't have an expire time. The code shuffles the
+ // titles to the next record before fixing up the title and
+ // alert_tag for entry.
+ if (!isdigit((int)entry.activity[0]) && entry.activity[0] != '-') {
+
+ if (title[0][0] == '\0') {
+ // No alerts in this message
+ }
+
+ // If it's a trashed packet, we may have entries here
+ // that are too long. Assure that we don't overwrite
+ // the strings.
+ for (jj = 4; jj > 0; jj--) {
+ xastir_snprintf(&title[jj][0],
+ sizeof(&title[jj][0]),
+ "%s",
+ &title[jj-1][0]);
+ }
+
+ xastir_snprintf(&title[0][0],
+ sizeof(&title[0][0]),
+ "%s",
+ entry.alert_tag);
+
+ xastir_snprintf(entry.alert_tag,
+ sizeof(entry.alert_tag),
+ "%s",
+ entry.activity);
+ entry.alert_tag[20] = '\0';
+
+ // Shouldn't we clear out entry.activity in this
+ // case??? We've determined it's not a date/time value.
+ xastir_snprintf(entry.activity,sizeof(entry.activity),"------z");
+ entry.expiration = sec_now() + (24 * 60 * 60); // Add a day
+ }
+ else {
+ // Compute expiration time_t from zulu time
+ entry.expiration = time_from_aprsstring(entry.activity);
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"4\n");
+
+ // Copy the sequence (which contains issue_date_time and
+ // message sequence) into the record.
+ xastir_snprintf(entry.seq,sizeof(entry.seq),"%s",fill->seq);
+
+ if (debug_level & 2)
+ fprintf(stderr,"5\n");
+
+ // Now compute issue_date_time from the first three characters of
+ // the sequence number:
+ // 0-9 = 0-9
+ // 10-35 = A-Z
+ // 36-61 = a-z
+ // The 3 characters are Day/Hour/Minute of the issue date time in
+ // zulu time.
+ if (strlen(fill->seq) == 5) { // Looks ok so far
+ // Could add another check to make sure that the first two
+ // chars are a digit or a capital letter.
+ char c;
+ char date_time[10];
+ char temp[3];
+
+
+ date_time[0] = '\0';
+ for ( ii = 0; ii < 3; ii++ ) {
+ c = fill->seq[ii]; // Snag one character
+
+ if (is_num_chr(c)) { // Found numeric char
+ temp[0] = '0';
+ temp[1] = c;
+ temp[2] = '\0';
+ }
+
+ else if (c >= 'A' && c <= 'Z') { // Found upper-case letter
+ // Need to take ord(c) - 55 to get the number
+ xastir_snprintf(temp,sizeof(temp),"%02d",(int)c - 55);
+ }
+
+ else if (c >= 'a' && c <= 'z') { // Found lower-case letter
+ // Need to take ord(c) - 61 to get the number
+ xastir_snprintf(temp,sizeof(temp),"%02d",(int)c - 61);
+ }
+
+ strncat(date_time,temp,2); // Concatenate the strings
+ }
+ strncat(date_time,"z",1); // Add a 'z' on the end.
+
+ if (debug_level & 2)
+ fprintf(stderr,"Seq: %s,\tIssue_time: %s\n",fill->seq,date_time);
+
+ xastir_snprintf(entry.issue_date_time,
+ sizeof(entry.issue_date_time),
+ "%s",
+ date_time);
+ //entry.issue_date_time = time_from_aprsstring(date_time);
+ } else {
+ xastir_snprintf(entry.issue_date_time,
+ sizeof(entry.issue_date_time),
+ "%s",
+ "312359z");
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"6\n");
+
+
+///////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////
+
+
+ // Iterate through up to five uncompressed alerts, or
+ // through the string of now-uncompressed "compressed"
+ // alerts, creating an alert out of each.
+ //
+ if (compressed_wx_packet) { // Handle compressed packet.
+ // Skip the first character of our uncompressed_wx
+ // string, as it's a leading comma. Snag out each
+ // string in turn and use that as the title for a
+ // weather alert.
+
+ // Feed &uncompressed_wx[1] to split_string to fill in
+ // an array with the various zone names.
+ split_string(&uncompressed_wx[1],
+ title_ptr,
+ MAX_SUB_ALERTS,
+ ',');
+ }
+ else { // Handle non-compressed packet
+ // We have up to five alerts to process.
+
+ // Set up an array of char pointers so that we can use
+ // the same code for either compressed or uncompressed
+ // weather alerts.
+ title_ptr[0] = &title[0][0];
+ title_ptr[1] = &title[1][0];
+ title_ptr[2] = &title[2][0];
+ title_ptr[3] = &title[3][0];
+ title_ptr[4] = &title[4][0];
+ title_ptr[5] = NULL; // Make sure we terminate
+ }
+
+// We now have all of our titles pointed to by the title_ptr[]
+// array. Either type of alert can be processed identically now.
+
+
+ // Try to create alerts out of each one.
+
+ for (ii = 0; ii < MAX_SUB_ALERTS && title_ptr[ii]; ii++) {
+
+ // Copy into our entry.title variable
+ xastir_snprintf(entry.title,
+ sizeof(entry.title),
+ "%s",
+ title_ptr[ii]);
+
+ // Terminate title string
+ entry.title[sizeof(entry.title)-1] = '\0';
+//fprintf(stderr,"Title: %s\n",entry.title);
+
+ // This one removes spaces from the title.
+ //while ((ptr = strpbrk(entry.title, " ")))
+ // memmove(ptr, ptr+1, strlen(ptr)+1);
+
+ // Instead we should blank out the title and any
+ // following alert titles if a space is encountered, as
+ // we're to disregard anything after a space in the
+ // information field.
+ if (ignore_title) // Blank out title if flag is set
+ entry.title[0] = '\0';
+
+ // If we found a space in a title, this signifies that
+ // we hit the end of the current list of zones.
+ if ( (ptr = strpbrk(entry.title, " ")) ) {
+ ignore_title++; // Set flag for following titles
+ entry.title[0] = '\0'; // Blank out title
+ }
+
+ if ((ptr = strpbrk(entry.title, "}>=!:/*+;"))) {
+ if (debug_level & 2) {
+ fprintf(stderr,
+ "Warning: Weird Weather Message: %ld:%s>%s:%s!\n",
+ (long)fill->sec_heard,
+ fill->from_call_sign,
+ fill->call_sign,
+ fill->message_line);
+ }
+ *ptr = '\0';
+ }
+
+ // Skip loop iterations if we don't have a title for an
+ // entry
+ if (entry.title[0] == '\0')
+ continue;
+
+ xastir_snprintf(entry.from,
+ sizeof(entry.from),
+ "%s",
+ fill->from_call_sign);
+ xastir_snprintf(entry.to,
+ sizeof(entry.to),
+ "%s",
+ fill->call_sign);
+ xastir_snprintf(entry.seq,
+ sizeof(entry.seq),
+ "%s",
+ fill->seq);
+
+ // NWS_ADVIS or NWS_CANCL normally appear in the "to"
+ // field. ADVIS can appear in the alert_tag field on a
+ // CANCL message though, and we want CANCL to have
+ // priority.
+ if (strstr(entry.alert_tag, "CANCL") || strstr(entry.to, "CANCL"))
+ entry.alert_level = 'C';
+
+ else if (!strncmp(entry.alert_tag, "TEST", 4) || strstr(entry.to, "TEST"))
+ entry.alert_level = 'T';
+
+ else if (strstr(entry.alert_tag, "WARN") || strstr(entry.to, "WARN"))
+ entry.alert_level = 'R';
+
+ else if (strstr(entry.alert_tag, "CIVIL") || strstr(entry.to, "CIVIL"))
+ entry.alert_level = 'R';
+
+ else if (strstr(entry.alert_tag, "WATCH") || strstr(entry.to, "WATCH"))
+ entry.alert_level = 'Y';
+
+ else if (strstr(entry.alert_tag, "ADVIS") || strstr(entry.to, "ADVIS"))
+ entry.alert_level = 'B';
+
+ else
+ entry.alert_level = 'G';
+
+
+ // Kludge for fire zones
+ if (!strncmp(entry.alert_tag,"RED_FLAG",8))
+ {
+ // Replace "Z" in the zone field with "F"
+ if (entry.title[3] == 'Z')
+ entry.title[3] = 'F';
+ }
+ // Look for a similar alert
+
+
+// We need some improvements here. We compare these fields:
+//
+// from SFONPW SFONPW
+// to NWS-ADVIS NWS-CANCL
+// alert_tag WIND WIND_ADVIS_CANCEL
+// title CA_Z007 CA_Z007
+//
+// Of these, "from" and "title" should remain the same between an
+// alert and a cancelled alert. "to" and "alert_tag" change. Since
+// we're comparing all four fields, the cancels don't match any
+// existing alerts.
+
+
+//WE7U
+ // Fill in the unique_string variable. We need this for
+ // our hash code.
+ alert_fill_unique_string(&entry);
+
+ if ((list_ptr = get_wx_alert_from_hash(entry.unique_string))) {
+//fprintf(stderr,"alert_build_list: found match: %s\n",entry.unique_string);
+
+
+// We found a match! We probably need to copy some more data across
+// between the records: seq, alert_tag, alert_level, from, to,
+// issue_date_time, expiration?
+// If it's a CANCL or CANCEL, we need to make sure the cancel
+// packet's information is kept and the other's info is tossed, so
+// that the alert doesn't get drawn anymore.
+
+ // If we're not trying to replace a cancelled alert with
+ // a new non-cancelled alert, go ahead and copy the
+ // fields across.
+ if ( (list_ptr->alert_level != 'C') // Stored alert is _not_ a CANCEL
+ || (entry.alert_level == 'C') ) { // Or new one _is_ a CANCEL
+ list_ptr->expiration = entry.expiration;
+ xastir_snprintf(list_ptr->activity,
+ sizeof(list_ptr->activity),
+ "%s",
+ entry.activity);
+ xastir_snprintf(list_ptr->alert_tag,
+ sizeof(list_ptr->alert_tag),
+ "%s",
+ entry.alert_tag);
+ list_ptr->alert_level = entry.alert_level;
+ xastir_snprintf(list_ptr->seq,
+ sizeof(list_ptr->seq),
+ "%s",
+ entry.seq);
+ xastir_snprintf(list_ptr->from,
+ sizeof(list_ptr->from),
+ "%s",
+ entry.from);
+ xastir_snprintf(list_ptr->to,
+ sizeof(list_ptr->to),
+ "%s",
+ entry.to);
+ xastir_snprintf(list_ptr->issue_date_time,
+ sizeof(list_ptr->issue_date_time),
+ "%s",
+ entry.issue_date_time);
+ }
+ else {
+ // Don't copy the info across, as we'd be making a
+ // cancelled alert active again if we did.
+ }
+ }
+ else { // No similar alert, add a new one to the list
+ entry.index = -1; // Haven't found it in a file yet
+
+ (void)alert_add_entry(&entry);
+ }
+
+ if (alert_active(&entry, ALERT_ALL)) {
+ // Empty "if" body here????? LCLINT caught this.
+ }
+
+ } // End of for loop
+
+
+ // Signify that we're done processing the NWS message
+ fill->active = RECORD_CLOSED;
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"alert_build_list return 2\n");
+}
+
+
diff --git a/src/alert.h b/src/alert.h
new file mode 100644
index 0000000..76de546
--- /dev/null
+++ b/src/alert.h
@@ -0,0 +1,98 @@
+/*
+ * $Id: alert.h,v 1.31 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifndef __XASTIR_ALERT_H
+#define __XASTIR_ALERT_H
+
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+
+#include "database.h"
+//#include "maps.h"
+
+
+// How many alerts we add storage for each time we're short.
+#define ALERT_COUNT_INCREMENT 200
+
+
+typedef enum {
+ ALERT_TITLE,
+ ALERT_TAG,
+ ALERT_TO,
+ ALERT_FROM
+} alert_match_level;
+
+#define ALERT_ALL ALERT_FROM
+enum flag_list {on_screen, source, max_flag=16};
+
+typedef struct {
+ char unique_string[50];
+ double top_boundary, left_boundary, bottom_boundary, right_boundary;
+ time_t expiration; // In local time (secs since epoch)
+ char activity[21];
+ char alert_tag[21];
+ char title[33];
+ char alert_level;
+ char from[10];
+ char to[10];
+ /* referenced flags
+ 0 - on screen
+ 1 - source
+ */
+ char flags[max_flag];
+ char filename[64];
+ int index; // Index into shapefile
+ char seq[10];
+ char issue_date_time[10];
+ char desc0[68]; // Space for additional text.
+ char desc1[68]; // Spec allows 67 chars per
+ char desc2[68]; // message.
+ char desc3[68]; //
+} alert_entry;
+
+
+extern void alert_print_list(void);
+extern int alert_active(alert_entry *alert, alert_match_level match_level);
+extern int alert_display_request(void);
+extern int alert_on_screen(void);
+extern int alert_redraw_on_update;
+extern int alert_expire(int curr_sec);
+extern void alert_build_list(Message *fill);
+extern struct hashtable_itr *create_wx_alert_iterator(void);
+extern alert_entry *get_next_wx_alert(struct hashtable_itr *iterator);
+extern int alert_list_count(void);
+
+#endif /* __XASTIR_ALERT_H */
+
+
diff --git a/src/awk.c b/src/awk.c
new file mode 100644
index 0000000..28ed1eb
--- /dev/null
+++ b/src/awk.c
@@ -0,0 +1,1111 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: awk.c,v 1.40 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 2003-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ *
+ */
+
+
+//
+// These functions allocate new memory:
+// ------------------------------------
+// awk_new_symtab
+// awk_declare_sym
+// awk_compile_action
+// awk_new_rule
+// awk_new_program
+// awk_load_program_file
+// awk_load_program_array
+//
+// These functions free memory:
+// ----------------------------
+// awk_free_symtab
+// awk_free_action
+// awk_free_rule
+// awk_free_program
+// awk_uncompile_program (indirectly)
+//
+
+
+/*
+ * This is a library of Awk-like functions to facilitate, for example,
+ * canonicalizing DBF attributes for shapefiles into internal Xastir
+ * values when rendering shapefile maps, or rewriting labels
+ * (e.g. callsigns into tactical calls), etc.
+ *
+ * Uses Philip Hazel's Perl-compatible regular expression library (pcre).
+ * See www.pcre.org.
+ *
+ * Alan Crosswell, n2ygk at weca.org
+ *
+ * TODO
+ * permit embedded ;#} inside string assignment (balance delims)
+ * implement \t, \n, \0[x]nn etc.
+ * instantiate new symbols instead of ignoring them?
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#ifdef HAVE_LIBPCRE
+#include <stdio.h>
+#include <string.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <ctype.h>
+#include <sys/types.h>
+#include "awk.h"
+#include "snprintf.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+#define min(a,b) ((a)<(b)?(a):(b))
+
+/*
+ * Symbol table
+ *
+ * Symbols $0-$9 are set by the results of the pcre pattern match.
+ * Other symbols are declared by the caller and bound to variables
+ * in the caller's program. Make sure they are still in scope when
+ * the pattern matcher is invoked!
+ *
+ * This assumes a very small symbol table, so it is searched linearly.
+ * No fancy hash table lookups are needed.
+ * XXX YES THEY ARE!
+ */
+
+#define MAXSUBS 10 /* $0 thru $9 should be plenty */
+
+
+
+
+
+/*
+ * awk_new_symtab: alloc a symbol table with $0-$9 pre-declared.
+ */
+awk_symtab *awk_new_symtab(void) {
+ awk_symtab *n = calloc(1,sizeof(awk_symtab));
+ static char sym[MAXSUBS][2];
+ int i;
+
+
+ if (!n) {
+ fprintf(stderr, "Couldn't allocate memory in awk_new_symtab()\n");
+ return(NULL);
+ }
+
+ for (i = 0; i < MAXSUBS; i++) {
+ sym[i][0] = i+'0';
+ sym[i][1] = '\0';
+ awk_declare_sym(n,sym[i],STRING,NULL,0); /* just reserve the name */
+ }
+ return n;
+}
+
+
+
+
+
+void awk_free_symtab(awk_symtab *s) {
+ int i;
+
+ for (i = 0; i < AWK_SYMTAB_HASH_SIZE; i++) {
+ awk_symbol *p,*x;
+
+ for (x = s->hash[i]; x ; x = p) {
+ p = x->next_sym;
+
+ free(x);
+ }
+ }
+}
+
+
+
+
+
+/*
+ * awk_declare_sym: declare a symbol and bind to storage for its value.
+ */
+int awk_declare_sym(awk_symtab *this,
+ const char *name,
+ enum awk_symtype type,
+ const void *val,
+ const int size) {
+ awk_symbol *s = calloc(1,sizeof(awk_symbol));
+ awk_symbol *p;
+ u_int i;
+
+
+ if (!s) {
+ fprintf(stderr, "Couldn't allocate memory in awk_declare_sym()\n");
+ return -1;
+ }
+
+ s->name = name;
+ s->namelen = strlen(name);
+ s->type = type;
+ s->val = (void *)val;
+ s->size = size;
+ s->len = 0;
+ i = AWK_SYM_HASH(s->name,s->namelen);
+ if ((p = this->hash[i]) != NULL) {
+ s->next_sym = p; /* insert at top of bucket */
+ }
+ this->hash[i] = s; /* make (new) top of bucket */
+
+ return 0;
+}
+
+
+
+
+
+/*
+ * awk_find_sym: search symtab for symbol
+ */
+awk_symbol *awk_find_sym(awk_symtab *this,
+ const char *name,
+ const int len) {
+ awk_symbol *s;
+ char c;
+
+
+ // Create holding spot for first character in order to speed up
+ // the loop below. Note that "toupper()" is very slow on some
+ // systems so we took it out of this function to speed things
+ // up. We evidently don't need case insensitive behavior here
+ // anyway.
+ //
+ c = name[0];
+
+ // Check through the hash
+ //
+ for (s = this->hash[AWK_SYM_HASH(name,len)]; s; s = s->next_sym) {
+
+ // Check length first (fast operation)
+ if (s->namelen == len) {
+
+ // Check first char next (fast operation)
+ if (s->name[0] == c) {
+
+ // Ok so far, test the entire string (slow
+ // operation, case sensitive)
+ if (len == 1)
+ return s;
+ if (len > 1 && strncmp(s->name+1,name+1,len-1) == 0)
+ return s;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+
+
+
+/*
+ * awk_set_sym: set a symbol's value (writes into bound storage).
+ * Returns -1 if it was unable to (symbol not found).
+ */
+/*
+int awk_set_sym(awk_symbol *s,
+ const char *val,
+ const int len) {
+ int l = len + 1;
+ int minlen = min(s->size-1,l);
+
+ if (!s)
+ return -1;
+ switch(s->type) {
+ case STRING:
+ if (minlen > 0) {
+ // Change this to an xastir_snprintf() function if we
+ // need to use this awk_set_sym() function later.
+ // strncpy won't null-terminate the string if there's no
+ // '\0' in the first minlen bytes.
+ strncpy(s->val,val,minlen);
+ s->len = l - 1;
+ }
+ break;
+ case INT:
+ *((int *)s->val) = atoi(val);
+ s->len = sizeof(int);
+ break;
+ case FLOAT:
+ *((double *)s->val) = atof(val);
+ s->len = sizeof(double);
+ break;
+ default:
+ return -1;
+ break;
+ }
+ return 0;
+}
+*/
+
+
+
+
+
+/*
+ * awk_get_sym: copy (and cast) symbol's value into supplied string buffer
+ */
+int awk_get_sym(awk_symbol *s, /* symbol */
+ char *store, /* store result here */
+ int size, /* sizeof(*store) */
+ int *len) { /* store length here */
+ int minlen;
+ char cbuf[128]; /* conversion buffer for int/float */
+ int cbl;
+
+ if (!s)
+ return -1;
+ *store = '\0';
+ *len = 0;
+ switch(s->type) {
+ case STRING:
+ if (s->len > 0) {
+ minlen = min(s->len,size-1);
+ if (minlen > 0) {
+ xastir_snprintf(store,
+ size,
+ "%s",
+ (char *)(s->val));
+ *len = minlen;
+ } else
+ *len = 0;
+ } else
+ *len = 0;
+ break;
+ case INT:
+ if (s->len > 0) {
+ sprintf(cbuf,"%d",*((int *)s->val));
+ cbl = strlen(cbuf);
+ minlen = min(cbl,size-1);
+ if (minlen > 0) {
+ xastir_snprintf(store,
+ size,
+ "%s",
+ cbuf);
+ *len = minlen;
+ } else
+ *len = 0;
+ } else
+ *len = 0;
+ break;
+ case FLOAT:
+ if (s->len > 0) {
+ sprintf(cbuf,"%f",*((double *)s->val));
+ cbl = strlen(cbuf);
+ minlen = min(cbl,size-1);
+ if (minlen > 0) {
+ xastir_snprintf(store,
+ size,
+ "%s",
+ cbuf);
+ *len = minlen;
+ } else
+ *len = 0;
+ } else
+ *len = 0;
+ break;
+ }
+ return 0;
+}
+
+
+
+
+
+/*
+ * Action compilation and interpretation.
+ *
+ * Action grammar is:
+ * <attr_set> := <attr> "=" value
+ * <op> := "next" | "skip" (next skips to next field; skip skips to next
+ * record.)
+ * <stmt> := <attr_set> | <op>
+ * <stmt_list> := <stmt_list> ";" <stmt> | <stmt>
+ * <action> := <stmt_list>
+ *
+ * It's a trivial grammar so no need for yacc/bison.
+ */
+
+/*
+ * awk_compile_stmt: "Compiles" a single action statement.
+ */
+int awk_compile_stmt(awk_symtab *this,
+ awk_action *p,
+ const char *stmt,
+ int len) {
+ const char *s = stmt, *op, *ep;
+
+ while (isspace((int)*s)) { /* clean up leading white space */
+ ++s;
+ --len;
+ }
+ ep = &s[len];
+
+ if ((op = strchr(s,'=')) != NULL) { /* it's either an assignment */
+ const char *val = op+1;
+ while (isspace((int)*val)) {
+ val++;
+ len--;
+ }
+ --op;
+ while (isspace((int)*op) && op>s) op--;
+ p->opcode = ASSIGN;
+ p->dest = awk_find_sym(this,s,(op-s+1));
+ if (!p->dest) {
+ return -1;
+ }
+ p->expr = val;
+ p->exprlen = (ep-val);
+ } else { /* or the "next" keyword */
+ const char *r;
+
+ for (r=&s[len-1]; isspace((int)*r); r--,len--) ; /* trim trailing white space */
+ if (len == 4 && strncmp(s,"next",4) == 0) {
+ p->opcode = NEXT;
+ } else if (len == 4 && strncmp(s,"skip",4) == 0) {
+ p->opcode = SKIP;
+ } else { /* failed to parse */
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+
+
+
+/*
+ * awk_compile_action: Break the action up into stmts and compile them
+ * and link them together.
+ */
+awk_action *awk_compile_action(awk_symtab *this, const char *act) {
+ awk_action *p, *first = calloc(1,sizeof(awk_action));
+ const char *cs,*ns; /* current, next stmt */
+
+
+ p = first;
+
+ if (!p) {
+ fprintf(stderr,"Couldn't allocate memory in awk_compile_action()\n");
+ return NULL;
+ }
+
+ for (cs = ns = act; ns && *ns; cs = (*ns==';')?ns+1:ns) {
+ ns = strchr(cs,';');
+ if (!ns) /* end of string */
+ ns = &cs[strlen(cs)];
+ if (awk_compile_stmt(this,p,cs,(ns-cs)) >= 0) {
+ p->next_act = calloc(1,sizeof(awk_action));
+ if (!p->next_act) {
+ fprintf(stderr,"Couldn't allocate memoryin awk_compile_action (2)\n");
+ }
+ p = p->next_act;
+ }
+ }
+ return first;
+}
+
+
+
+
+
+/*
+ * awk_free_action: Free the compiled action
+ */
+void awk_free_action(awk_action *a) {
+
+ while (a) {
+ awk_action *p = a;
+ a = p->next_act;
+ free(p);
+ }
+}
+
+
+
+
+
+/*
+ * awk_eval_expr: expand $vars into dest and do type conversions as
+ * needed. For strings, just write directly into dest->val. For
+ * ints/floats, write to a temp buffer and then atoi() or atof().
+ */
+void awk_eval_expr(awk_symtab *this,
+ awk_symbol *dest,
+ const char *expr,
+ int exprlen) {
+ int i,dmax,dl,newlen;
+ char c,delim;
+ char *dp;
+ const char *symname;
+ int done;
+ char tbuf[128];
+ awk_symbol *src;
+
+ if (dest && expr) {
+ if (dest->type == STRING) {
+ dp = dest->val; /* just expand directly to result buffer */
+ dmax = dest->size;
+ } else {
+ dp = tbuf; /* use temp buffer */
+ dmax = sizeof(tbuf);
+ }
+ for (done = 0, i = 0, dl = 0; !done && i < dmax && exprlen > 0; i++) {
+ switch (c = *expr) {
+ case '"':
+ case '\'': /* trim off string delims */
+ ++expr;
+ --exprlen;
+ if (expr[exprlen-1] == c) /* look for matching close delim */
+ --exprlen;
+ break;
+ case '$': /* $... look for variable substitution */
+ if (--exprlen < 0) {
+ done = 1;
+ break;
+ }
+ c = *++expr; /* what's after the $? */
+ switch (c) {
+ case '{': /* ${var}... currently broken (see TODO) */
+ delim='}';
+ ++expr; /* skip the open delim */
+ --exprlen;
+ break;
+ case '(': /* $(var)... */
+ delim=')';
+ ++expr;
+ --exprlen;
+ break;
+ default: /* $var ... */
+ delim='\0';
+ break;
+ }
+ /* now search for the var name using closing delim */
+ symname = expr;
+ if (delim == '\0') { /* no close delim */
+ while (!isspace((int)*expr) && !ispunct((int)*expr) && exprlen > 0) {
+ ++expr;
+ --exprlen;
+ }
+ } else { /* search for close delim */
+ while (*expr != delim && exprlen > 0) {
+ ++expr;
+ --exprlen;
+ }
+ }
+ src = awk_find_sym(this,symname,(expr-symname));
+ if (delim) { /* gotta skip over the close delim */
+ ++expr;
+ --exprlen;
+ }
+ /* make sure src and dest of string copy don't overlap */
+ if (src && src->type == STRING
+ && dp >= (char *)src->val
+ && dp <= &((char *)src->val)[src->size]) {
+ char *sp;
+ int free_it = 0;
+
+ if ((int)sizeof(tbuf) >= src->size) { /* tbuf big enuf */
+ sp = tbuf;
+ } else { /* tbuf too small */
+ free_it++;
+ sp = malloc(src->size);
+ if (!sp) { /* oh well! */
+ fprintf(stderr,"Couldn't allocate memory in awk_eval_expr()\n");
+ break;
+ }
+ }
+ awk_get_sym(src,sp,src->size,&newlen);
+ bcopy(sp,dp,newlen); /* now copy it in */
+
+ // We only want to free it if we malloc'ed it.
+ if (free_it)
+ free(sp);
+
+ } else {
+ awk_get_sym(src,dp,(dmax-dl),&newlen);
+ }
+ dl += newlen;
+ dp += newlen;
+ break;
+ case '\\': /* \... quote next char */
+ /* XXX TODO: implement \n,\t,\0[x].. etc. */
+ if (--exprlen < 0) {
+ done = 1;
+ } else {
+ if (dl < dmax) {
+ *dp++ = *expr++; /* copy the quoted char */
+ ++dl;
+ }
+ }
+ break;
+ default: /* just copy the character */
+ if (--exprlen < 0) {
+ done = 1;
+ } else {
+ if (dl < dmax) {
+ *dp++ = *expr++; /* copy the char */
+ ++dl;
+ }
+ }
+ break;
+ } /* end switch (*expr) */
+ } /* end for loop */
+ *dp = '\0'; /* null terminate the string */
+ switch(dest->type) {
+ case INT:
+ if (dest->size >= (int)sizeof(int)) {
+ *((int *)dest->val) = atoi(tbuf);
+ dest->len = sizeof(int);
+ }
+ break;
+ case FLOAT:
+ if (dest->size >= (int)sizeof(double)) {
+ *((double *)dest->val) = atof(tbuf);
+ dest->len = sizeof(double);
+ }
+ break;
+ case STRING: /* already filled val in */
+ dest->len = dl; /* just update len */
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+
+
+
+
+/*
+ * awk_exec_action: interpret the compiled action.
+ */
+int awk_exec_action(awk_symtab *this, const awk_action *code) {
+ const awk_action *p;
+ int done = 0;
+
+ for (p = code; p && !done; p = p->next_act) {
+ switch (p->opcode) {
+ case NEXT:
+ done = 1;
+ break;
+ case SKIP:
+ done = 2;
+ break;
+ case ASSIGN:
+ awk_eval_expr(this,p->dest,p->expr,p->exprlen);
+ break;
+ case NOOP:
+ break;
+ default:
+ break;
+ }
+ }
+ return done;
+}
+
+
+
+/*
+ * Rules consists of pcre patterns and actions. A program is
+ * the collection of rules to apply as a group.
+ */
+
+
+
+/*
+ * awk_new_rule: alloc a rule
+ */
+awk_rule *awk_new_rule(void) {
+ awk_rule *n = calloc(1,sizeof(awk_rule));
+
+ if (!n)
+ fprintf(stderr,"Couldn't allocate memory in awk_new_rule()\n");
+
+ return n;
+}
+
+
+
+
+
+void awk_free_rule(awk_rule *r) {
+
+ if (r) {
+ if (r->flags&AR_MALLOC) {
+ if (r->act)
+ free((char *)r->act);
+ if (r->pattern)
+ free((char *)r->pattern);
+ if (r->tables)
+ pcre_free((void *)r->tables);
+ if (r->re)
+ pcre_free(r->re);
+ if (r->pe)
+ pcre_free(r->pe);
+ }
+ if (r->code)
+ awk_free_action(r->code);
+ free(r);
+ }
+}
+
+
+
+
+
+/*
+ * awk_new_program: alloc a program
+ */
+awk_program *awk_new_program(void) {
+ awk_program *n = calloc(1,sizeof(awk_program));
+
+ if (!n)
+ fprintf(stderr,"Couldn't allocate memory in awk_new_program()\n");
+
+ return n;
+}
+
+
+
+
+
+void awk_free_program(awk_program *rs) {
+ awk_rule *r;
+
+ if (rs) {
+ for (r = rs->head; r; ) {
+ awk_rule *x = r;
+ r = r->next_rule;
+ awk_free_rule(x);
+ }
+ free(rs);
+ }
+}
+
+
+
+
+
+/*
+ * awk_add_rule: add a rule to a program
+ */
+void awk_add_rule(awk_program *this, awk_rule *r) {
+ if (!this)
+ return;
+ if (!this->last) {
+ this->head = this->last = r;
+ r->next_rule = NULL;
+ } else {
+ this->last->next_rule = r;
+ this->last = r;
+ }
+}
+
+
+
+
+
+/*
+ * awk_load_program_array: load program from an array of rules. Use this
+ * to load a program from a statically declared array (see test main
+ * program for an example).
+ */
+awk_program *awk_load_program_array(awk_rule rules[], /* rules array */
+ int nrules) { /* size of array */
+ awk_program *n = awk_new_program();
+ awk_rule *r;
+
+ if (!n)
+ return NULL;
+
+ for (r = rules; r < &rules[nrules]; r++) {
+ awk_add_rule(n,r);
+ }
+ return n;
+}
+
+
+
+
+
+static void garbage(const char *file,
+ int line,
+ const char *buf,
+ const char *cp) {
+ fprintf(stderr,"%s:%d: parse error:\n",file,line);
+ fputs(buf,stderr);
+ fputc('\n',stderr);
+ while (cp-- > buf)
+ fputc(' ',stderr);
+ fputs("^\n\n",stderr);
+}
+
+
+
+
+
+/*
+ * awk_load_program_file: load program from a file.
+ *
+ * File syntax is a simplified version of awk:
+ *
+ * {action}
+ * /pattern/ {action}
+ * BEGIN {action}
+ * BEGIN_RECORD {action}
+ * END_RECORD {action}
+ * END {action}
+ * # comments...
+ * (blank lines)
+ *
+ * Note that action can continue onto subsequent lines.
+ */
+awk_program *awk_load_program_file(const char *file) { /* rules filename */
+ awk_program *n = awk_new_program();
+ awk_rule *r;
+ FILE *f = fopen(file,"r");
+ char in[1024];
+ int line = 0;
+
+ if (!f) {
+ if (n)
+ awk_free_program(n);
+ return NULL;
+ }
+
+ if (!n)
+ return NULL;
+
+ while (fgets(in,sizeof(in),f)) {
+ char *cp = in, *p;
+ int l = strlen(in);
+
+ ++line;
+ if (in[l-1] == '\n')
+ in[--l] = '\0';
+ while (isspace((int)*cp)) ++cp;
+ switch(*cp) {
+ case '\0': /* empty line */
+ continue;
+ case '#': /* comment line */
+ continue;
+ case '/': /* begin regexp */
+ r = awk_new_rule();
+ r->ruletype = REGEXP;
+ p = ++cp;; /* now points at pattern */
+ more:
+ while (*cp && *cp != '/') ++cp; /* find end of pattern */
+ if (cp > in && cp[-1] == '\\') { /* '/' quoted */
+ ++cp;
+ goto more; /* so keep going */
+ }
+ if (*cp != '\0') /* zap end of pattern */
+ *cp++ = '\0';
+ r->pattern = strdup(p);
+
+ break;
+ case 'B': /* BEGIN? */
+ if (strncmp(cp,"BEGIN_RECORD",12) == 0) {
+ r = awk_new_rule();
+ r->ruletype = BEGIN_REC;
+ cp += 12; /* strlen("BEGIN_RECORD") */
+ } else if (strncmp(cp,"BEGIN",5) == 0) {
+ r = awk_new_rule();
+ r->ruletype = BEGIN;
+ cp += 5; /* strlen("BEGIN") */
+ } else {
+ garbage(file,line,in,cp);
+ continue;
+ }
+ break;
+ case 'E': /* END? */
+ if (strncmp(cp,"END_RECORD",10) == 0) {
+ r = awk_new_rule();
+ r->ruletype = END_REC;
+ cp += 10; /* strlen("END_RECORD") */
+ } else if (strncmp(cp,"END",3) == 0) {
+ r = awk_new_rule();
+ r->ruletype = END;
+ cp += 3; /* strlen("END") */
+ } else {
+ garbage(file,line,in,cp);
+ continue;
+ }
+ break;
+ default:
+ garbage(file,line,in,cp);
+ continue;
+ }
+ while (isspace((int)*cp)) ++cp; /* skip whitespace */
+ if (*cp == '{') {
+ p = ++cp;
+ loop:
+ while (*cp && *cp != '}' && *cp != '#') ++cp;
+ if (*cp == '\0' || *cp == '#') { /* continues on next line */
+ *cp++=' '; /* replace \n w/white space */
+ if (cp >= &in[sizeof(in)-1]) {
+ garbage(file,line,"line too long",0);
+ return n;
+ }
+ if (!fgets(cp,sizeof(in)-(cp-in),f)) {
+ fprintf(stderr,"%s:%d: failed to parse\n",file,line);
+ return n;
+ }
+ ++line;
+ goto loop; /* keep looking for that close bracket */
+ }
+ if (*cp != '\0') /* zap end of act */
+ *cp++ = '\0';
+
+ r->act = strdup(p);
+
+ r->flags |= AR_MALLOC;
+ /* make sure there's no extraneous junk on the line */
+ while (*cp && isspace((int)*cp)) ++cp;
+ if (*cp == '#' || *cp == '\0')
+ awk_add_rule(n,r);
+ else {
+ garbage(file,line,in,cp);
+ continue;
+ }
+ } else {
+ garbage(file,line,in,cp);
+ continue;
+ }
+ } /* end while */
+ fclose(f);
+ return n;
+}
+
+
+
+
+
+/*
+ * awk_compile_program: Once loaded (from array or file), the program is compiled. Check for already compiled program.
+ */
+int awk_compile_program(awk_symtab *symtab, awk_program *rs) {
+ const char *error;
+ awk_rule *r;
+ int erroffset;
+
+ if (!rs)
+ return -1;
+
+ rs->symtbl = symtab;
+ for (r = rs->head; r; r = r->next_rule) {
+ if (r->ruletype == REGEXP) {
+ if (r->tables)
+ pcre_free((void *)r->tables);
+ r->tables = pcre_maketables(); /* NLS locale parse tables */
+ if (!r->re)
+ r->re = pcre_compile(r->pattern, /* the pattern */
+ 0, /* default options */
+ &error, /* for error message */
+ &erroffset, /* for error offset */
+ r->tables); /* NLS locale character tables */
+
+ if (!r->re) {
+ int i;
+
+ fprintf(stderr,"parse error: %s\n",r->pattern);
+ fprintf(stderr," ");
+ for (i = 0; i < erroffset; i++)
+ fputc(' ',stderr);
+ fprintf(stderr,"^\n");
+ return -1;
+ }
+ if (!r->pe)
+ r->pe = pcre_study(r->re, 0, &error); /* optimize the regexp */
+ } else if (r->ruletype == BEGIN) {
+ rs->begin = r;
+ } else if (r->ruletype == BEGIN_REC) {
+ rs->begin_rec = r;
+ } else if (r->ruletype == END_REC) {
+ rs->end_rec = r;
+ } else if (r->ruletype == END) {
+ rs->end = r;
+ }
+ if (!r->code)
+ r->code = awk_compile_action(rs->symtbl,r->act); /* compile the action */
+ }
+ return 0;
+}
+
+
+
+
+
+/*
+ * awk_uncompile_program: Frees the compiled program (patterns and stmts)
+ * but keeps the program text loaded so it can be recompiled (e.g. with a
+ * new symtbl).
+ */
+void awk_uncompile_program(awk_program *p) {
+ awk_rule *r;
+
+ if (!p)
+ return;
+
+ for (r = p->head; r; r = r->next_rule) {
+ if (r->ruletype == REGEXP) {
+ if (r->tables)
+ pcre_free((void *)r->tables);
+ r->tables = NULL;
+ if (r->re)
+ pcre_free(r->re);
+ r->re = NULL;
+ if (r->pe)
+ pcre_free(r->pe);
+ r->pe = NULL;
+ }
+ if (r->code)
+ awk_free_action(r->code); /* free the action */
+ r->code = NULL;
+ }
+}
+
+
+
+
+
+/*
+ * awk_exec_program: apply the program to the given buffer
+ */
+int awk_exec_program(awk_program *this, char *buf, int len) {
+ int i,rc,done = 0;
+ awk_rule *r;
+ int ovector[3*MAXSUBS];
+#define OVECLEN (sizeof(ovector)/sizeof(ovector[0]))
+
+ if (!this || !buf || len <= 0)
+ return 0;
+
+ for (r = this->head; r && !done ; r = r->next_rule) {
+ if (r->ruletype == REGEXP) {
+ rc = pcre_exec(r->re,r->pe,buf,len,0,0,ovector,OVECLEN);
+ /* assign values to as many of $0 thru $9 as were set */
+ /* XXX - avoid calling awk_find_sym for these known values */
+ for (i = 0; rc > 0 && i < rc && i < MAXSUBS ; i++) {
+ char symname[2];
+ awk_symbol *s;
+
+ symname[0] = i + '0';
+ symname[1] = '\0';
+ s = awk_find_sym(this->symtbl,symname,1);
+ s->val = &buf[ovector[2*i]];
+ s->len = ovector[2*i+1]-ovector[2*i];
+ }
+ /* clobber the remaining $n thru $9 */
+ for (; i < MAXSUBS; i++) {
+ char symname[10];
+ awk_symbol *s;
+
+ symname[0] = i + '0';
+ symname[1] = '\0';
+ s = awk_find_sym(this->symtbl,symname,1);
+ s->len = 0;
+ }
+ if (rc > 0) {
+ done = awk_exec_action(this->symtbl,r->code);
+ }
+ }
+ }
+ return done;
+}
+
+
+
+
+
+/*
+ * awk_exec_begin_record: run the special BEGIN_RECORD rule, if any
+ */
+int awk_exec_begin_record(awk_program *this) {
+ if (this && this->begin_rec)
+ return awk_exec_action(this->symtbl,this->begin_rec->code);
+ else
+ return 0;
+}
+
+
+
+
+
+/*
+ * awk_exec_begin: run the special BEGIN rule, if any
+ */
+int awk_exec_begin(awk_program *this) {
+ if (this && this->begin)
+ return awk_exec_action(this->symtbl,this->begin->code);
+ else
+ return 0;
+}
+
+
+
+
+
+/*
+ * awk_exec_end_record: run the special END_RECORD rule, if any
+ */
+int awk_exec_end_record(awk_program *this) {
+ if (this && this->end_rec)
+ return awk_exec_action(this->symtbl,this->end_rec->code);
+ else
+ return 0;
+}
+
+
+
+
+
+/*
+ * awk_exec_end: run the special END rule, if any
+ */
+int awk_exec_end(awk_program *this) {
+ if (this && this->end)
+ return awk_exec_action(this->symtbl,this->end->code);
+ else
+ return 0;
+}
+
+
+#endif /* HAVE_LIBPCRE */
+
+
diff --git a/src/awk.h b/src/awk.h
new file mode 100644
index 0000000..7fb98dd
--- /dev/null
+++ b/src/awk.h
@@ -0,0 +1,127 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: awk.h,v 1.14 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 2003-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ *
+ */
+#ifndef AWK_H
+#define AWK_H
+#ifdef HAVE_PCRE_H
+#include <pcre.h>
+#endif
+#ifdef HAVE_PCRE_PCRE_H
+#include <pcre/pcre.h>
+#endif
+
+enum awk_symtype {STRING,INT,FLOAT}; /* the only data types */
+
+typedef struct awk_symbol_ { /* symbol table entry */
+ struct awk_symbol_ *next_sym; /* linked list */
+ const char *name; /* name of the symbol */
+ int namelen; /* length of the name */
+ enum awk_symtype type; /* data type of symbol value */
+ void *val; /* storage for the value */
+ int size; /* size of *val */
+ int len; /* current length of *val */
+} awk_symbol;
+
+#define AWK_SYMTAB_HASH_SIZE 0xff
+typedef struct awk_symtab_ { /* symbol table anchor */
+ awk_symbol *hash[AWK_SYMTAB_HASH_SIZE];
+} awk_symtab;
+
+#define AWK_SYM_HASH(n,l) ((*n)&AWK_SYMTAB_HASH_SIZE)
+//#define AWK_SYM_HASH(n,l) ((n[0]+((l>1)?n[1]:0))&AWK_SYMTAB_HASH_SIZE)
+
+typedef struct awk_action_ { /* a program statement */
+ struct awk_action_ *next_act;
+ enum {NOOP=0, NEXT, SKIP, ASSIGN} opcode;
+ awk_symbol *dest; /* destination of assignment */
+ const char *expr; /* value setting expression */
+ int exprlen; /* length of expression */
+} awk_action;
+
+typedef struct awk_rule_ {
+ struct awk_rule_ *next_rule; /* linked list */
+ enum {BEGIN,BEGIN_REC,END_REC,END,REGEXP} ruletype;
+ const char *pattern; /* pcre pattern string */
+ const u_char *tables; /* pcre NLS tables */
+ pcre *re; /* pcre compiled pattern */
+ pcre_extra *pe; /* pcre optimized pattern */
+ const char *act; /* the program string */
+ awk_action *code; /* compiled program */
+ int flags; /* some flags */
+#define AR_MALLOC 0x01 /* pattern, act were malloc'd by me */
+} awk_rule;
+
+typedef struct awk_program_ { /* anchor for the list of rules */
+ awk_symtab *symtbl; /* the symbol table for this program */
+ awk_rule *head; /* head of list */
+ awk_rule *last; /* last element */
+ awk_rule *begin; /* optional BEGIN rule */
+ awk_rule *begin_rec; /* optional BEGIN_RECORD rule */
+ awk_rule *end_rec; /* optional END_RECORD rule */
+ awk_rule *end; /* optional END rule */
+} awk_program;
+
+extern awk_symtab *awk_new_symtab(void);
+extern void awk_free_symtab(awk_symtab *s);
+extern int awk_declare_sym(awk_symtab *this,
+ const char *name,
+ enum awk_symtype type,
+ const void *val,
+ const int size);
+extern awk_symbol *awk_find_sym(awk_symtab *this,
+ const char *name,
+ const int len);
+extern int awk_set_sym(awk_symbol *s,
+ const char *val,
+ const int len);
+extern int awk_get_sym(awk_symbol *s,
+ char *store,
+ int size,
+ int *len);
+extern int awk_compile_stmt(awk_symtab *this,
+ awk_action *p,
+ const char *stmt,
+ int len);
+extern awk_action *awk_compile_action(awk_symtab *this, const char *act);
+extern void awk_free_action(awk_action *a);
+extern void awk_eval_expr(awk_symtab *this,
+ awk_symbol *dest,
+ const char *expr,
+ int exprlen);
+extern int awk_exec_action(awk_symtab *this, const awk_action *code);
+extern awk_rule *awk_new_rule(void);
+extern void awk_free_rule(awk_rule *r);
+extern awk_program *awk_new_program(void);
+extern void awk_free_program(awk_program *rs);
+void awk_add_rule(awk_program *this, awk_rule *r);
+extern awk_program *awk_load_program_array(awk_rule rules[],int nrules);
+extern awk_program *awk_load_program_file(const char *file);
+extern int awk_compile_program(awk_symtab *symtbl,awk_program *rs);
+extern void awk_uncompile_program(awk_program *rs);
+extern int awk_exec_program(awk_program *this, char *buf, int len);
+extern int awk_exec_begin_record(awk_program *this);
+extern int awk_exec_end_record(awk_program *this);
+extern int awk_exec_begin(awk_program *this);
+extern int awk_exec_end(awk_program *this);
+
+#endif /*!AWK_H*/
diff --git a/src/bulletin_gui.c b/src/bulletin_gui.c
new file mode 100644
index 0000000..2eb82fc
--- /dev/null
+++ b/src/bulletin_gui.c
@@ -0,0 +1,804 @@
+/*
+ * $Id: bulletin_gui.c,v 1.46 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <ctype.h>
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+#include <Xm/XmAll.h>
+
+#ifdef HAVE_XBAE_MATRIX_H
+#include <Xbae/Matrix.h>
+#endif // HAVE_XBAE_MATRIX_H
+
+#include <X11/Xatom.h>
+#include <X11/Shell.h>
+
+#ifdef HAVE_LIBINTL_H
+#include <libintl.h>
+#define _(x) gettext(x)
+#else // HAVE_LIBINTL_H
+#define _(x) (x)
+#endif // HAVE_LIBINTL_H
+
+#include "xastir.h"
+#include "main.h"
+#include "bulletin_gui.h"
+#include "interface.h"
+#include "util.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+extern XmFontList fontlist1; // Menu/System fontlist
+Widget Display_bulletins_dialog = NULL;
+Widget Display_bulletins_text = NULL;
+Widget dist_data = NULL;
+Widget zero_bulletin_data = NULL;
+
+static xastir_mutex display_bulletins_dialog_lock;
+
+int bulletin_range;
+int new_bulletin_flag = 0;
+int new_bulletin_count = 0;
+static time_t first_new_bulletin_time = 0;
+static time_t last_new_bulletin_time = 0;
+
+
+
+
+
+void bulletin_gui_init(void)
+{
+ init_critical_section(&display_bulletins_dialog_lock);
+}
+
+
+
+
+
+// Function called from check_for_new_bulletins() if a new bulletin
+// has come in that's within our range and we have
+// pop_up_new_bulletins enabled. This causes the Bulletins() dialog
+// to come up and rescan the message database for all bulletins that
+// are within the radius specified. By the time this gets called
+// we've already waited a few seconds to try to get the posit to
+// come in that matches the bulletin, and have then checked the
+// database to make sure that the new bulletins received are still
+// within our range.
+void popup_bulletins(void) {
+ if ((Display_bulletins_dialog == NULL)) { // Dialog not up
+
+ // Bring up the dialog
+ Bulletins( (Widget)NULL, (XtPointer)NULL, (XtPointer)NULL );
+ }
+}
+
+
+
+
+
+void bulletin_message(char *call_sign, char *tag, char *packet_message, time_t sec_heard) {
+ char temp[200];
+ char temp_my_course[10];
+ char temp_text[30];
+ double distance;
+ XmTextPosition pos, eol, eod;
+ struct tm *tmp;
+ time_t timehd;
+ char time_str[20];
+ char *temp_ptr;
+
+
+ timehd=sec_heard;
+ tmp = localtime(&timehd);
+
+ if ( (packet_message != NULL) && (strlen(packet_message) > MAX_MESSAGE_LENGTH) ) {
+ if (debug_level & 1)
+ fprintf(stderr,"bulletin_message: Message length too long\n");
+ return;
+ }
+
+ (void)strftime(time_str,sizeof(time_str),"%b %d %H:%M",tmp);
+
+ distance = distance_from_my_station(call_sign,temp_my_course);
+ xastir_snprintf(temp, sizeof(temp), "%-9s:%-4s (%s %6.1f %s) %s\n",
+ call_sign, &tag[3], time_str, distance,
+ english_units ? langcode("UNIOP00004"): langcode("UNIOP00005"),
+ packet_message);
+
+// Operands of <= have incompatible types (double, int):
+ if ( ( ((int)distance <= bulletin_range) && (distance > 0.0) )
+ || (view_zero_distance_bulletins && distance == 0.0)
+ || ( (bulletin_range == 0) && (distance > 0.0) ) ) {
+
+begin_critical_section(&display_bulletins_dialog_lock, "bulletin_gui.c:bulletin_message" );
+
+ if ((Display_bulletins_dialog != NULL) && Display_bulletins_text != NULL) { // Dialog is up
+
+ eod = XmTextGetLastPosition(Display_bulletins_text);
+ xastir_snprintf(temp_text,
+ sizeof(temp_text),
+ "%s",
+ temp);
+
+ temp_text[14] = '\0';
+
+ // Look for this bulletin ID. "pos" will hold the first char position if found.
+ if (XmTextFindString(Display_bulletins_text, 0, temp_text, XmTEXT_FORWARD, &pos)) {
+
+ // Found it, so now find the end-of-line for it
+ if (XmTextFindString(Display_bulletins_text, pos, "\n", XmTEXT_FORWARD, &eol))
+ eol++;
+ else
+ eol = eod;
+
+ // And replace the old bulletin with a new copy
+ if (eol == eod)
+ temp[strlen(temp)-1] = '\0';
+ XmTextReplace(Display_bulletins_text, pos, eol, temp);
+ } else {
+ for (pos = 0; strlen(temp_text) > 12 && pos < eod;) {
+ if (XmCOPY_SUCCEEDED == XmTextGetSubstring(Display_bulletins_text, pos, 14, 30, temp_text)) {
+ if (temp_text[0] && strncmp(temp, temp_text, 14) < 0)
+ break;
+ } else
+ break;
+
+ if (XmTextFindString(Display_bulletins_text, pos, "\n", XmTEXT_FORWARD, &eol))
+ pos = ++eol;
+ else
+ pos = eod;
+ }
+ if (pos == eod) {
+ temp[strlen(temp)-1] = '\0'; // End-of-Data remove trailing LF
+ if (pos > 0) { // Already have text. Need to insert LF between items
+ memmove(&temp[1], temp, strlen(temp));
+ temp[0] = '\n';
+ }
+ }
+ XmTextInsert(Display_bulletins_text,pos,temp);
+ }
+ temp_ptr = XmTextFieldGetString(dist_data);
+ bulletin_range = atoi(temp_ptr);
+ XtFree(temp_ptr);
+ }
+
+end_critical_section(&display_bulletins_dialog_lock, "bulletin_gui.c:bulletin_message" );
+
+ }
+}
+
+
+
+
+
+static void bulletin_line(Message *fill) {
+ bulletin_message(fill->from_call_sign, fill->call_sign, fill->message_line, fill->sec_heard);
+}
+
+
+
+
+
+static void scan_bulletin_file(void) {
+ mscan_file(MESSAGE_BULLETIN, bulletin_line);
+}
+
+
+
+
+
+// bulletin_data_add
+//
+// Adds the bulletin to the message database. Updates the Bulletins
+// dialog if it is up. Causes Bulletins dialog to pop up if the
+// bulletin matches certain parameters.
+//
+long temp_bulletin_record;
+
+void bulletin_data_add(char *call_sign, char *from_call, char *data,
+ char *seq, char type, char from) {
+ int distance = -1;
+
+ // Add to the message database
+ (void)msg_data_add(call_sign,
+ from_call,
+ data,
+ " ", // Need something here. Empty string no good.
+ MESSAGE_BULLETIN,
+ from,
+ &temp_bulletin_record);
+
+ // If we received a NEW bulletin
+ if (temp_bulletin_record == -1L) {
+ char temp[10];
+
+
+//fprintf(stderr,"We think it's a new bulletin!\n");
+
+ // We add to the distance in order to come up with 0.0
+ // if the distance is not known at all (no position
+ // found yet).
+ distance = (int)(distance_from_my_station(from_call,temp) + 0.9999);
+
+ if ( (bulletin_range == 0)
+ || (distance <= bulletin_range && distance > 0)
+ || (view_zero_distance_bulletins && distance == 0.0) ) {
+ // We have a _new_ bulletin that's within our
+ // current range setting. Note that it's also possible
+ // to have a zero distance for the bulletin (we haven't
+ // heard a posit from the sending station yet), then get
+ // a posit later.
+
+ if (debug_level & 1) {
+ fprintf(stderr,"New bulletin:");
+ fprintf(stderr,"%05d:%9s:%c:%c:%9s:%s:%s ",
+ distance,
+ call_sign,
+ type,
+ from,
+ from_call,
+ data,
+ seq);
+ fprintf(stderr," Distance ok:%d miles",distance);
+ }
+
+ if (pop_up_new_bulletins) {
+//fprintf(stderr,"bulletin_data_add: popping up bulletins\n");
+ popup_bulletins();
+ if (debug_level & 1)
+ fprintf(stderr,"\n");
+ }
+ else {
+ if (debug_level & 1) {
+ fprintf(stderr,", but popups disabled!\n");
+ }
+ }
+ }
+ else {
+// fprintf(stderr,", but distance didn't work out!\n");
+ }
+ }
+ // Update the View->Bulletins dialog if it's up
+ bulletin_message(from_call,
+ call_sign,
+ data,
+ sec_now());
+
+}
+
+
+
+
+
+// Find each bulletin that is within our range _and_ within our time
+// parameters for new bulletins. Count them only. Results returned
+// in the new_bulletin_count variable.
+void count_bulletin_messages(char *call_sign, char *packet_message, time_t sec_heard) {
+ char temp_my_course[10];
+ double distance;
+
+ if ( (packet_message != NULL) && (strlen(packet_message) > MAX_MESSAGE_LENGTH) ) {
+ if (debug_level & 1)
+ fprintf(stderr,"bulletin_message: Message length too long\n");
+ return;
+ }
+
+ distance = distance_from_my_station(call_sign,temp_my_course);
+
+// Operands of <= have incompatible types (double, int):
+ if ( ( ((int)distance <= bulletin_range) && (distance > 0.0) )
+ || (view_zero_distance_bulletins && distance == 0.0)
+ || ( (bulletin_range == 0) && (distance > 0.0) ) ) {
+
+ // Is it newer than our first new_bulletin timestamp?
+ if (sec_heard >= first_new_bulletin_time) {
+ new_bulletin_count++;
+ }
+ }
+}
+
+
+
+
+
+static void count_bulletin_line(Message *fill) {
+ count_bulletin_messages(fill->from_call_sign, fill->message_line, fill->sec_heard);
+}
+
+
+
+
+
+static void count_new_bulletins(void) {
+ mscan_file(MESSAGE_BULLETIN, count_bulletin_line);
+}
+
+
+
+
+
+// Function called by mscan_file for each bulletin with zero for the
+// position_known flag. See next function find_zero_position_bulletins()
+//
+static void zero_bulletin_processing(Message *fill) {
+ DataRow *p_station; // Pointer to station data
+
+
+ if (!fill->position_known) {
+
+ //fprintf(stderr,"Position unknown: %s:%s\n",
+ // fill->from_call_sign,
+ // fill->message_line);
+
+ // Check to see if we _now_ have a position for this non-new
+ // bulletin. If so, change the position_known flag on that
+ // record to a one, update the record, set the proper timers
+ // and then schedule a popup if it fits within our current
+ // parameters.
+
+ if ( search_station_name(&p_station,fill->from_call_sign,1) ) {
+ // Found a bulletin for which we get to fill in a new
+ // position!
+
+ if ( (p_station->coord_lon == 0l)
+ && (p_station->coord_lat == 0l) ) {
+ //fprintf(stderr,"Found it but still no valid position!\n");
+ }
+ else { // Found valid position for this bulletin
+
+ //fprintf(stderr,"Found it now! %s:%s\n",
+ // fill->from_call_sign,
+ // fill->message_line);
+
+ // Mark it as found
+ fill->position_known = 1;
+
+ // Fake the timestamp so that we check messages back
+ // to at least this one we just found. Allow for the
+ // fact that we might find several older messages, so
+ // we only want to keep taking the timestamp backwards
+ // in time here.
+ if (first_new_bulletin_time > (fill->sec_heard) )
+ first_new_bulletin_time = fill->sec_heard;
+
+ // Check whether we really wish to pop them up
+ if (pop_up_new_bulletins) {
+ int distance;
+ char temp_my_course[10];
+
+ distance = (int)(distance_from_my_station(fill->from_call_sign,
+ temp_my_course) + 0.9999);
+
+ if ( (bulletin_range == 0)
+ || (distance <= bulletin_range && distance > 0) ) {
+ if (debug_level & 1) {
+ fprintf(stderr,"Filled in distance for earlier bulletin:%d miles\n",
+ distance);
+ }
+
+ // If view_zero_distance_bulletins was not
+ // turned on, then we probably haven't seen
+ // this bulletin until now. Popup up the
+ // Bulletin dialog.
+ if (!view_zero_distance_bulletins) {
+//fprintf(stderr,"zero_bulletin_processing: popping up bulletins\n");
+ popup_bulletins();
+ }
+ }
+ }
+ }
+ }
+ else {
+ // No position known for the bulletin. Skip it for now.
+ //fprintf(stderr,"Still not found\n");
+ }
+ }
+}
+
+
+
+
+
+// Find all bulletins that have a zero for the position_known flag.
+// Calls the function above for each bulletin.
+//
+static void find_zero_position_bulletins(void) {
+ mscan_file(MESSAGE_BULLETIN, zero_bulletin_processing);
+}
+
+
+
+
+
+// Function called by main.c:UpdateTime(). Checks whether enough
+// time has passed since the last new bulletin came in (so that the
+// posit for it might come in as well). If so, checks for bulletins
+// that are newer than first_new_bulletin_time and fit within our
+// range. If any found, it updates the Bulletins dialog.
+time_t last_bulletin_check = (time_t)0l;
+
+void check_for_new_bulletins(int curr_sec) {
+
+ // Check every 15 seconds max
+ if ( (last_bulletin_check + 15) > curr_sec ) {
+ return;
+ }
+ last_bulletin_check = curr_sec;
+
+ // Look first to see if we might be able to fill in positions on
+ // any older bulletins, then cause a popup for those that fit
+ // our parameters. The below function sets new_bulletin_flag if
+ // it is able to fill in a distance for an older bulletin.
+// Note: This is time-consuming!
+ find_zero_position_bulletins();
+
+ // Any new bulletins to check? If not, return
+ if (!new_bulletin_flag) {
+ return;
+ }
+
+ // Enough time passed since most recent bulletin? Need to have
+ // enough time to perhaps fill in a distance for each bulletin.
+ if ( (last_new_bulletin_time + 15) > curr_sec ) {
+ //fprintf(stderr,"Not enough time has passed\n");
+ return;
+ }
+
+ // If we get to here, then we think we may have at least one new
+ // bulletin, and the latest arrived more than XX seconds ago
+ // (currently 15 seconds). Check for bulletins which have
+ // timestamps equal to or newer than first_new_bulletin_time and
+ // fit within our range.
+
+ new_bulletin_count = 0;
+
+//fprintf(stderr,"Checking for new bulletins\n");
+
+ count_new_bulletins();
+
+//fprintf(stderr,"%d new bulletins found\n",new_bulletin_count);
+
+ if (new_bulletin_count) {
+//fprintf(stderr,"check_for_new_bulletins: popping up bulletins\n");
+ popup_bulletins();
+
+ if (debug_level & 1)
+ fprintf(stderr,"New bulletins (%d) caused popup!\n",new_bulletin_count);
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"No bulletin popup generated.\n");
+ }
+
+ // Reset so that we can do it all over again later. We need
+ // mutex locks protecting these variables.
+ first_new_bulletin_time = last_new_bulletin_time + 1;
+ new_bulletin_flag = 0;
+}
+
+
+
+
+
+void Display_bulletins_destroy_shell(/*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ char *temp_ptr;
+
+
+ // Keep this. It stores the range in a global variable when we destroy the dialog.
+ temp_ptr = XmTextFieldGetString(dist_data);
+ bulletin_range = atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ XtPopdown(shell);
+
+begin_critical_section(&display_bulletins_dialog_lock, "bulletin_gui.c:Display_bulletins_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ Display_bulletins_dialog = (Widget)NULL;
+
+end_critical_section(&display_bulletins_dialog_lock, "bulletin_gui.c:Display_bulletins_destroy_shell" );
+
+}
+
+
+
+
+
+void Display_bulletins_change_range(/*@unused@*/ Widget widget, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char *temp_ptr;
+
+
+ // Keep this. It stores the range in a global variable when we destroy the dialog.
+ temp_ptr = XmTextFieldGetString(dist_data);
+ bulletin_range = atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ view_zero_distance_bulletins = (int)XmToggleButtonGetState(zero_bulletin_data);
+ //fprintf(stderr,"%d\n",view_zero_distance_bulletins);
+
+ Display_bulletins_destroy_shell( widget, clientData, callData);
+ Bulletins( widget, clientData, callData);
+}
+
+
+
+
+
+void Zero_Bulletin_Data_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ view_zero_distance_bulletins = atoi(which);
+ else
+ view_zero_distance_bulletins = 0;
+
+ Display_bulletins_destroy_shell( widget, Display_bulletins_dialog, callData);
+ Bulletins( widget, clientData, callData);
+}
+
+
+
+
+
+void Bulletins(/*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget pane, form, button_range, button_close, dist, dist_units;
+ unsigned int n;
+ Arg args[50];
+ Atom delw;
+ char temp[10];
+
+
+ if(!Display_bulletins_dialog) {
+
+
+begin_critical_section(&display_bulletins_dialog_lock, "bulletin_gui.c:Bulletins" );
+
+
+ Display_bulletins_dialog = XtVaCreatePopupShell(langcode("BULMW00001"),
+ xmDialogShellWidgetClass,
+ appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Bulletins pane",
+ xmPanedWindowWidgetClass,
+ Display_bulletins_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ form = XtVaCreateWidget("Bulletins form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ dist = XtVaCreateManagedWidget(langcode("BULMW00002"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ dist_data = XtVaCreateManagedWidget("dist_data",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 8,
+ XmNwidth, ((8*7)+2),
+ XmNmaxLength, 8,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, dist,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ dist_units = XtVaCreateManagedWidget((english_units?langcode("UNIOP00004"):langcode("UNIOP00005")),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, dist_data,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_range = XtVaCreateManagedWidget(langcode("BULMW00003"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, dist_units,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ zero_bulletin_data = XtVaCreateManagedWidget(langcode("WPUPCFD029"),
+ xmToggleButtonWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, button_range,
+ XmNleftOffset,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(zero_bulletin_data,XmNvalueChangedCallback,Zero_Bulletin_Data_toggle,"1");
+ if (view_zero_distance_bulletins)
+ XmToggleButtonSetState(zero_bulletin_data,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(zero_bulletin_data,FALSE,FALSE);
+
+ n=0;
+ XtSetArg(args[n], XmNrows, 15); n++;
+ XtSetArg(args[n], XmNcolumns, 108); n++;
+ XtSetArg(args[n], XmNtraversalOn, FALSE); n++;
+ XtSetArg(args[n], XmNeditable, FALSE); n++;
+ XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
+ XtSetArg(args[n], XmNwordWrap, TRUE); n++;
+ XtSetArg(args[n], XmNscrollHorizontal, TRUE); n++;
+ XtSetArg(args[n], XmNscrollVertical, TRUE); n++;
+ XtSetArg(args[n], XmNcursorPositionVisible, FALSE); n++;
+ XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
+ XtSetArg(args[n], XmNtopWidget, dist); n++;
+ XtSetArg(args[n], XmNtopOffset, 20); n++;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNbottomOffset, 30); n++;
+ XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNleftOffset, 5); n++;
+ XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNrightOffset, 5); n++;
+ XtSetArg(args[n], XmNforeground, MY_FG_COLOR); n++;
+ XtSetArg(args[n], XmNbackground, MY_BG_COLOR); n++;
+ XtSetArg(args[n], XmNfontList, fontlist1); n++;
+
+
+ Display_bulletins_text = XmCreateScrolledText(form,
+ "Bulletins text",
+ args,
+ n);
+
+ button_close = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_range, XmNactivateCallback, Display_bulletins_change_range, Display_bulletins_dialog);
+ XtAddCallback(button_close, XmNactivateCallback, Display_bulletins_destroy_shell, Display_bulletins_dialog);
+
+ pos_dialog(Display_bulletins_dialog);
+
+ delw = XmInternAtom(XtDisplay(Display_bulletins_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(Display_bulletins_dialog, delw, Display_bulletins_destroy_shell, (XtPointer)Display_bulletins_dialog);
+
+ xastir_snprintf(temp, sizeof(temp), "%d", bulletin_range);
+ XmTextFieldSetString(dist_data, temp);
+
+ XtManageChild(form);
+ XtManageChild(Display_bulletins_text);
+ XtVaSetValues(Display_bulletins_text, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(pane);
+
+ redraw_on_new_packet_data=1;
+ XtPopup(Display_bulletins_dialog,XtGrabNone);
+
+end_critical_section(&display_bulletins_dialog_lock, "bulletin_gui.c:Bulletins" );
+
+ scan_bulletin_file();
+
+ // Move focus to the Close button. This appears to
+ // highlight the button fine, but we're not able to hit the
+ // <Enter> key to have that default function happen. Note:
+ // We _can_ hit the <SPACE> key, and that activates the
+ // option.
+ //XmUpdateDisplay(Display_bulletins_dialog);
+ XmProcessTraversal(button_close, XmTRAVERSE_CURRENT);
+
+ } else {
+ (void)XRaiseWindow(XtDisplay(Display_bulletins_dialog), XtWindow(Display_bulletins_dialog));
+ }
+}
+
+
diff --git a/src/bulletin_gui.h b/src/bulletin_gui.h
new file mode 100644
index 0000000..e2500c3
--- /dev/null
+++ b/src/bulletin_gui.h
@@ -0,0 +1,38 @@
+/*
+ * $Id: bulletin_gui.h,v 1.16 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifndef __XASTIR_BULLETIN_GUI_H
+#define __XASTIR_BULLETIN_GUI_H
+
+extern int bulletin_range;
+
+
+// From bulletin_gui.c
+extern void bulletin_gui_init(void);
+extern void bulletin_data_add(char *call_sign, char *from_call, char *data, char *seq, char type, char from);
+extern void check_for_new_bulletins(int current_sec);
+
+#endif // __XASTIR_BULLETIN_GUI_H
+
+
diff --git a/src/color.c b/src/color.c
new file mode 100644
index 0000000..da06aed
--- /dev/null
+++ b/src/color.c
@@ -0,0 +1,304 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: color.c,v 1.23 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <Xm/XmAll.h>
+
+#include "xastir.h"
+#include "color.h"
+#include "xa_config.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+static color_load color_choice[MAX_COLORS];
+static int colors_loaded;
+static int rm, gm, bm; // rgb masks
+static int rs, gs, bs; // rgb shifts
+int visual_depth;
+
+
+
+
+
+/**********************************************************************************/
+/* load color file */
+/* load the colors to be used with Xastir */
+/* Return 1 if good 0 if not found or error */
+/**********************************************************************************/
+
+int load_color_file(void) {
+ FILE *f;
+ char temp[40];
+ int r,g,b;
+ char colorname[50];
+ int ok,x;
+
+ xastir_snprintf(temp, sizeof(temp), "config/xastir.rgb");
+ colors_loaded=0;
+ ok=1;
+ f=fopen(get_data_base_dir(temp),"r");
+ if (f!=NULL) {
+ while (!feof(f) && ok) {
+ if (fscanf(f,"%d %d %d %49s",&r,&g,&b,colorname)==4) {
+ if (colors_loaded < MAX_COLORS) {
+ for (x=0; x<colors_loaded;x++) {
+ if (strcmp(color_choice[x].colorname,colorname)==0) {
+ ok=0;
+ fprintf(stderr,"Error! Duplicate color found %s\n",colorname);
+ }
+ }
+ if (ok) {
+
+ xastir_snprintf(color_choice[colors_loaded].colorname,
+ MAX_COLORNAME,
+ "%s",
+ colorname);
+
+// Do we really want to assign to unsigned short int's here?
+ color_choice[colors_loaded].color.red=(unsigned short)(r*257);
+ color_choice[colors_loaded].color.blue=(unsigned short)(b*257);
+ color_choice[colors_loaded].color.green=(unsigned short)(g*257);
+ colors_loaded++;
+ }
+ } else {
+ ok=0;
+ fprintf(stderr,"Error! MAX_COLORS has been exceeded\n");
+ }
+ }
+ }
+ (void)fclose(f);
+ } else {
+ ok=0;
+ fprintf(stderr,"Error! can not find color file: %s\n", get_data_base_dir(temp));
+ }
+ return(ok);
+}
+
+
+
+
+
+/**********************************************************************************/
+/* GetPixelbyName */
+/* get color for the named choice */
+/* return the pixel data */
+/**********************************************************************************/
+
+Pixel GetPixelByName( Widget w, char *colorname) {
+ Display *dpy = XtDisplay(w);
+ int scr = DefaultScreen(dpy);
+ char warning[200];
+ int i,found;
+
+ found=-1;
+ i=0;
+
+ do {
+ if (strcmp(color_choice[i].colorname, colorname)==0)
+ found=i;
+
+ i++;
+ } while (i<colors_loaded && found <0);
+
+ if (found >= 0) {
+
+ // XFreeColors() here generates an error. Why?
+ // "BadAccess (attempt to access private resource denied)"
+ // XFreeColors(dpy, cmap, &(color_choice[found].color.pixel),1,0);
+
+ if (XAllocColor(dpy,cmap,&color_choice[found].color)) {
+ return(color_choice[found].color.pixel);
+ }
+ else {
+ xastir_snprintf(warning, sizeof(warning), "Couldn't allocate color %s", colorname);
+ XtWarning(warning);
+ return(BlackPixel(dpy,scr));
+ }
+ }
+ else {
+ xastir_snprintf(warning, sizeof(warning), "Couldn't find color %s", colorname);
+ XtWarning(warning);
+ return(BlackPixel(dpy,scr));
+ }
+}
+
+
+
+
+
+void setup_visual_info(Display* dpy, int scr) {
+ int visuals_matched, i, j;
+ XVisualInfo *visual_list, *vp;
+ XVisualInfo visual_template;
+ rm = gm = bm = rs = gs = bs = 0;
+
+ visual_list = XGetVisualInfo(dpy, VisualNoMask, &visual_template, &visuals_matched);
+ if (visuals_matched) {
+ if (debug_level & 16)
+ fprintf(stderr,"Found %d visuals\n", visuals_matched);
+
+ for (i = 0; i < visuals_matched; i++) {
+ vp = &visual_list[i];
+
+ if (vp->visualid == XVisualIDFromVisual(DefaultVisual(dpy, scr))) {
+ if (vp->class == TrueColor ||
+ vp->class == DirectColor) {
+ if (vp->red_mask == 0xf800 &&
+ vp->green_mask == 0x07e0 &&
+ vp->blue_mask == 0x001f)
+ visual_type = RGB_565;
+ else if (vp->red_mask == 0x7c00 &&
+ vp->green_mask == 0x03e0 &&
+ vp->blue_mask == 0x001f)
+ visual_type = RGB_555;
+ else if (vp->red_mask == 0xff0000 &&
+ vp->green_mask == 0x00ff00 &&
+ vp->blue_mask == 0x0000ff)
+ visual_type = RGB_888;
+ else {
+ rm = vp->red_mask;
+ gm = vp->green_mask;
+ bm = vp->blue_mask;
+ for (j = 31; j >= 0; j--) {
+ if (rm >= (1 << j)) {
+ rs = j - 15;
+ break;
+ }
+ }
+ for (j = 31; j >= 0; j--) {
+ if (gm >= (1 << j)) {
+ gs = j - 15;
+ break;
+ }
+ }
+ for (j = 31; j >= 0; j--) {
+ if (bm >= (1 << j)) {
+ bs = j - 15;
+ break;
+ }
+ }
+ visual_type = RGB_OTHER;
+ }
+ }
+ else
+ visual_type = NOT_TRUE_NOR_DIRECT;
+ if (debug_level & 16)
+ fprintf(stderr,"\tID: 0x%lx, Default\n", vp->visualid);
+ }
+ else if (debug_level & 16)
+ fprintf(stderr,"\tID: 0x%lx\n", vp->visualid);
+
+ // Store color depth for use by other routines.
+ visual_depth = vp->depth;
+
+ if (debug_level & 16) {
+ fprintf(stderr,"\tScreen: %d\n", vp->screen);
+ fprintf(stderr,"\tDepth: %d\n", vp->depth);
+ fprintf(stderr,"\tClass: %d", vp->class);
+ switch (vp->class) {
+ case StaticGray:
+ fprintf(stderr,", StaticGray\n");
+ break;
+ case GrayScale:
+ fprintf(stderr,", GrayScale\n");
+ break;
+ case StaticColor:
+ fprintf(stderr,", StaticColor\n");
+ break;
+ case PseudoColor:
+ fprintf(stderr,", PseudoColor\n");
+ break;
+ case TrueColor:
+ fprintf(stderr,", TrueColor\n");
+ break;
+ case DirectColor:
+ fprintf(stderr,", DirectColor\n");
+ break;
+ default:
+ fprintf(stderr,", ??\n");
+ break;
+ }
+ fprintf(stderr,"\tClrmap Size: %d\n", vp->colormap_size);
+ fprintf(stderr,"\tBits per RGB: %d\n", vp->bits_per_rgb);
+ fprintf(stderr,"\tRed Mask: 0x%lx\n", vp->red_mask);
+ fprintf(stderr,"\tGreen Mask: 0x%lx\n", vp->green_mask);
+ fprintf(stderr,"\tBlue Mask: 0x%lx\n\n", vp->blue_mask);
+ }
+ }
+ }
+ XFree(visual_list);
+}
+
+
+
+
+
+void pack_pixel_bits(unsigned short r, unsigned short g, unsigned short b, unsigned long* pixel)
+{
+ switch (visual_type) {
+ case RGB_565:
+ *pixel = (( r & 0xf800) |
+ ((g >> 5) & 0x07e0) |
+ (b >> 11));
+ break;
+ case RGB_555:
+ *pixel = (((r >> 1) & 0x7c00) |
+ ((g >> 6) & 0x03e0) |
+ (b >> 11));
+ break;
+ case RGB_888:
+ *pixel = (((r << 8) & 0xff0000) |
+ ( g & 0x00ff00) |
+ (b >> 8));
+ break;
+ case RGB_OTHER:
+ if (rs >= 0)
+ *pixel = ((r << rs) & rm);
+ else
+ *pixel = ((r >> (-rs)) & rm);
+ if (gs >= 0)
+ *pixel |= ((g << gs) & gm);
+ else
+ *pixel |= ((g >> (-gs)) & gm);
+ if (bs >= 0)
+ *pixel |= ((b << bs) & bm);
+ else
+ *pixel |= ((b >> (-bs)) & bm);
+ break;
+ case NOT_TRUE_NOR_DIRECT:
+ default:
+ break;
+ }
+}
+
+
diff --git a/src/color.h b/src/color.h
new file mode 100644
index 0000000..92fb590
--- /dev/null
+++ b/src/color.h
@@ -0,0 +1,53 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: color.h,v 1.15 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifndef XASTIR_COLOR_H
+#define XASTIR_COLOR_H
+
+#define MAX_COLORS 81
+
+#define MAX_COLORNAME 40
+typedef struct {
+ char colorname[MAX_COLORNAME];
+ XColor color;
+} color_load;
+
+typedef enum {
+ NOT_TRUE_NOR_DIRECT,
+ RGB_565,
+ RGB_555,
+ RGB_888,
+ RGB_OTHER
+} Pixel_Format;
+extern Pixel_Format visual_type;
+extern int visual_depth;
+
+/* from color.c */
+extern int load_color_file(void);
+extern Pixel GetPixelByName(Widget w, char *colorname);
+extern void setup_visual_info(Display* dpy, int scr);
+extern void pack_pixel_bits(unsigned short r, unsigned short g, unsigned short b, unsigned long* pixel);
+
+#endif /* XASTIR_COLOR_H */
+
diff --git a/src/compiledate.c b/src/compiledate.c
new file mode 100644
index 0000000..cdddd97
--- /dev/null
+++ b/src/compiledate.c
@@ -0,0 +1 @@
+char compiledate[] = "Compiled: Tue Dec 4 15:36:48 PST 2012";
diff --git a/src/database.h b/src/database.h
new file mode 100644
index 0000000..35635b9
--- /dev/null
+++ b/src/database.h
@@ -0,0 +1,669 @@
+/*
+ * $Id: database.h,v 1.56 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+/* Note: this file should be called db.h, but was renamed to database.h
+ * to avoid conflicts with the Berkeley DB package. */
+
+/*
+ * Database structures
+ *
+ */
+
+#ifndef XASTIR_DATABASE_H
+#define XASTIR_DATABASE_H
+
+
+#define MSG_INCREMENT 200
+#define MAX_CALLSIGN 9 // Objects are up to 9 chars
+#define MAX_TACTICAL_CALL 57 // Up to XX chars for tactical calls
+#define MAX_COMMENT_LINES 20 // Save XX unique comment strings per station
+#define MAX_STATUS_LINES 20 // Save XX unique status strings per station
+
+/* define max size of info field */
+#define MAX_INFO_FIELD_SIZE 256
+
+// Number of times to send killed objects/items before ceasing to
+// transmit them.
+#define MAX_KILLED_OBJECT_RETRANSMIT 20
+
+// Check entire station list at this rate for objects/items that
+// might need to be transmitted via the decaying algorithm. This is
+// the start rate, which gets doubled on each transmit.
+#define OBJECT_CHECK_RATE 20
+
+// We should probably be using APRS_DF in extract_bearing_NRQ()
+// and extract_omnidf() functions. We aren't currently.
+/* Define APRS Types */
+enum APRS_Types {
+ APRS_NULL,
+ APRS_MSGCAP,
+ APRS_FIXED,
+ APRS_DOWN, // Not used anymore
+ APRS_MOBILE,
+ APRS_DF,
+ APRS_OBJECT,
+ APRS_ITEM,
+ APRS_STATUS,
+ APRS_WX1,
+ APRS_WX2,
+ APRS_WX3,
+ APRS_WX4,
+ APRS_WX5,
+ APRS_WX6,
+ QM_WX,
+ PEET_COMPLETE,
+ RSWX200,
+ GPS_RMC,
+ GPS_GGA,
+ GPS_GLL,
+ STATION_CALL_DATA,
+ OTHER_DATA,
+ APRS_MICE,
+ APRS_GRID,
+ DALLAS_ONE_WIRE,
+ DAVISMETEO,
+ DAVISAPRSDL
+};
+
+
+/* Define Record Types */
+#define NORMAL_APRS 'N'
+#define MOBILE_APRS 'M'
+#define DF_APRS 'D'
+#define DOWN_APRS 'Q'
+#define NORMAL_GPS_RMC 'C'
+#define NORMAL_GPS_GGA 'A'
+#define NORMAL_GPS_GLL 'L'
+#define APRS_WX1 '1'
+#define APRS_WX2 '2'
+#define APRS_WX3 '3'
+#define APRS_WX4 '4'
+#define APRS_WX5 '5'
+#define APRS_WX6 '6'
+
+/* define RECORD ACTIVES */
+#define RECORD_ACTIVE 'A'
+#define RECORD_NOTACTIVE 'N'
+#define RECORD_CLOSED 'C'
+
+/* define data from info type */
+#define DATA_VIA_LOCAL 'L'
+#define DATA_VIA_TNC 'T'
+#define DATA_VIA_NET 'I'
+#define DATA_VIA_FILE 'F'
+#define DATA_VIA_DATABASE 'D'
+
+
+/* define Heard info type */
+#define VIA_TNC 'Y'
+#define NOT_VIA_TNC 'N'
+
+/* define Message types */
+#define MESSAGE_MESSAGE 'M'
+#define MESSAGE_BULLETIN 'B'
+#define MESSAGE_NWS 'W'
+
+// Define file info, string length are without trailing '\0'
+#define MAX_TIME 20
+#define MAX_LONG 12
+#define MAX_LAT 11
+#define MAX_ALTITUDE 10 //-32808.4 to 300000.0? feet
+#define MAX_SPEED 9 /* ?? 3 in knots */
+#define MAX_COURSE 7 /* ?? */
+#define MAX_POWERGAIN 7
+#define MAX_STATION_TIME 10 /* 6+1 */
+#define MAX_SAT 4
+#define MAX_DISTANCE 10
+#define MAX_WXSTATION 50
+#define MAX_TEMP 100
+
+#define MAX_MESSAGE_LENGTH 100
+#define MAX_MESSAGE_ORDER 10
+
+// track export file formats
+#define EXPORT_XASTIR_TRACK 0
+#define EXPORT_KML_TRACK 1
+
+extern char *get_most_recent_ack(char *callsign);
+
+extern void Set_Del_Object(Widget w, XtPointer clientData, XtPointer calldata); // From main.c
+
+
+extern char my_callsign[MAX_CALLSIGN+1];
+extern char my_lat[MAX_LAT];
+extern char my_long[MAX_LONG];
+
+
+
+// Used for messages and bulletins
+typedef struct {
+ char active;
+ char data_via;
+ char type;
+ char heard_via_tnc;
+ time_t sec_heard;
+ time_t last_ack_sent;
+ char packet_time[MAX_TIME];
+ char call_sign[MAX_CALLSIGN+1];
+ char from_call_sign[MAX_CALLSIGN+1];
+ char message_line[MAX_MESSAGE_LENGTH+1];
+ char seq[MAX_MESSAGE_ORDER+1];
+ char acked;
+ char position_known;
+ time_t interval;
+ int tries;
+} Message;
+
+
+
+// Struct used to create linked list of most recent ack's
+typedef struct _ack_record {
+ char callsign[MAX_CALLSIGN+1];
+ char ack[5+1];
+ struct _ack_record *next;
+} ack_record;
+
+
+
+#ifdef MSG_DEBUG
+extern void msg_clear_data(Message *clear);
+extern void msg_copy_data(Message *to, Message *from);
+#else // MSG_DEBUG
+#define msg_clear_data(clear) memset((Message *)clear, 0, sizeof(Message))
+#define msg_copy_data(to, from) memmove((Message *)to, (Message *)from, \
+ sizeof(Message))
+#endif /* MSG_DEBUG */
+
+extern int message_update_time(void);
+
+
+
+enum AreaObjectTypes {
+ AREA_OPEN_CIRCLE = 0x0,
+ AREA_LINE_LEFT = 0x1,
+ AREA_OPEN_ELLIPSE = 0x2,
+ AREA_OPEN_TRIANGLE = 0x3,
+ AREA_OPEN_BOX = 0x4,
+ AREA_FILLED_CIRCLE = 0x5,
+ AREA_LINE_RIGHT = 0x6,
+ AREA_FILLED_ELLIPSE = 0x7,
+ AREA_FILLED_TRIANGLE = 0x8,
+ AREA_FILLED_BOX = 0x9,
+ AREA_MAX = 0x9,
+ AREA_NONE = 0xF
+};
+
+
+
+enum AreaObjectColors {
+ AREA_BLACK_HI = 0x0,
+ AREA_BLUE_HI = 0x1,
+ AREA_GREEN_HI = 0x2,
+ AREA_CYAN_HI = 0x3,
+ AREA_RED_HI = 0x4,
+ AREA_VIOLET_HI = 0x5,
+ AREA_YELLOW_HI = 0x6,
+ AREA_GRAY_HI = 0x7,
+ AREA_BLACK_LO = 0x8,
+ AREA_BLUE_LO = 0x9,
+ AREA_GREEN_LO = 0xA,
+ AREA_CYAN_LO = 0xB,
+ AREA_RED_LO = 0xC,
+ AREA_VIOLET_LO = 0xD,
+ AREA_YELLOW_LO = 0xE,
+ AREA_GRAY_LO = 0xF
+};
+
+
+
+typedef struct {
+ unsigned type : 4;
+ unsigned color : 4;
+ unsigned sqrt_lat_off : 8;
+ unsigned sqrt_lon_off : 8;
+ unsigned corridor_width : 16;
+} AreaObject;
+
+
+
+typedef struct {
+ char aprs_type;
+ char aprs_symbol;
+ char special_overlay;
+ AreaObject area_object;
+} APRS_Symbol;
+
+
+
+// Struct for holding current weather data.
+// This struct is pointed to by the DataRow structure.
+// An empty string indicates undefined data.
+typedef struct { // strlen
+ time_t wx_sec_time;
+ int wx_storm; // Set to one if severe storm
+ char wx_time[MAX_TIME];
+ char wx_course[4]; // in � 3
+ char wx_speed[4]; // in mph 3
+ time_t wx_speed_sec_time;
+ char wx_gust[4]; // in mph 3
+ char wx_hurricane_radius[4]; //nautical miles 3
+ char wx_trop_storm_radius[4]; //nautical miles 3
+ char wx_whole_gale_radius[4]; // nautical miles 3
+ char wx_temp[5]; // in �F 3
+ char wx_rain[10]; // in hundredths inch/h 3
+ char wx_rain_total[10]; // in hundredths inch
+ char wx_snow[6]; // in inches/24h 3
+ char wx_prec_24[10]; // in hundredths inch/day 3
+ char wx_prec_00[10]; // in hundredths inch 3
+ char wx_hum[5]; // in % 3
+ char wx_baro[10]; // in hPa 6
+ char wx_fuel_temp[5]; // in �F 3
+ char wx_fuel_moisture[5];// in % 2
+ char wx_type;
+ char wx_station[MAX_WXSTATION];
+ int wx_compute_rain_rates; // Some stations provide rain rates
+ // directly, others require Xastir to
+ // compute from total rain. Flag this,
+ // so we don't clobber useful info from
+ // a station.
+} WeatherRow;
+
+
+
+// Struct for holding track data. Keeps a dynamically allocated
+// doubly-linked list of track points. The first record should have its
+// "prev" pointer set to NULL and the last record should have its "next"
+// pointer set to NULL. If no track storage exists then the pointers to
+// these structs in the DataRow struct should be NULL.
+typedef struct _TrackRow{
+ long trail_long_pos; // coordinate of trail point
+ long trail_lat_pos; // coordinate of trail point
+ time_t sec; // date/time of position
+ long speed; // in 0.1 km/h undefined: -1
+ int course; // in degrees undefined: -1
+ long altitude; // in 0.1 m undefined: -99999
+ char flag; // several flags, see below
+ struct _TrackRow *prev; // pointer to previous record in list
+ struct _TrackRow *next; // pointer to next record in list
+} TrackRow;
+
+
+
+// trail flag definitions
+#define TR_LOCAL 0x01 // heard direct (not via digis)
+#define TR_NEWTRK 0x02 // start new track
+
+
+
+// Struct for holding comment/status data. Will keep a dynamically
+// allocated list of text. Every different comment field will be
+// stored in a separate line.
+typedef struct _CommentRow{
+ char *text_ptr; // Ptr to the comment text
+ time_t sec_heard; // Latest timestamp for this comment/status
+ struct _CommentRow *next; // Ptr to next record or NULL
+} CommentRow;
+
+
+
+#define MAX_MULTIPOINTS 35
+
+
+
+// Struct for holding multipoint data.
+typedef struct _MultipointRow{
+ long multipoints[MAX_MULTIPOINTS][2];
+} MultipointRow;
+
+
+
+// Break DataRow into several structures. DataRow will contain the
+// parameters that are common across all types of stations. DataRow
+// will contain a pointer to TrackRow if it is a moving station, and
+// contain a pointer to WeatherRow if it is a weather station. If no
+// weather or track data existed, the pointers will be NULL. This new
+// way of storing station data will save a LOT of memory. If a
+// station suddenly starts moving or spitting out weather data the new
+// structures will be allocated, filled in, and pointers to them
+// installed in DataRow.
+//
+// Station storage now is organized as an ordered linked list. We have
+// both sorting by name and by time last heard
+//
+// todo: check the string length!
+//
+typedef struct _DataRow {
+
+ struct _DataRow *n_next; // pointer to next element in name ordered list
+ struct _DataRow *n_prev; // pointer to previous element in name ordered
+ // list
+ struct _DataRow *t_newer; // pointer to next element in time ordered
+ // list (newer)
+ struct _DataRow *t_older; // pointer to previous element in time ordered
+ // list (older)
+
+ char call_sign[MAX_CALLSIGN+1]; // call sign or name index or object/item
+ // name
+ char *tactical_call_sign; // Tactical callsign. NULL if not assigned
+ APRS_Symbol aprs_symbol;
+ long coord_lon; // Xastir coordinates 1/100 sec, 0 = 180�W
+ long coord_lat; // Xastir coordinates 1/100 sec, 0 = 90�N
+
+ int time_sn; // serial number for making time index unique
+ time_t sec_heard; // time last heard, used also for time index
+ time_t heard_via_tnc_last_time;
+ time_t direct_heard; // KC2ELS - time last heard direct
+
+// Change into time_t structs? It'd save us a bunch of space.
+ char packet_time[MAX_TIME];
+ char pos_time[MAX_TIME];
+
+// char altitude_time[MAX_TIME];
+// char speed_time[MAX_TIME];
+// char station_time[MAX_STATION_TIME];
+// char station_time_type;
+
+ short flag; // several flags, see below
+ char pos_amb; // Position ambiguity, 0 = none,
+ // 1 = 0.1 minute...
+
+ unsigned int error_ellipse_radius; // Degrades precision for this
+ // station, from 0 to 65535 cm or
+ // 655.35 meters. Assigned when we
+ // decode each type of packet.
+ // Default is 6.0 meters (600 cm)
+ // unless we know the GPS position
+ // is augmented, or is degraded by
+ // less precision in the packet.
+
+ unsigned int lat_precision; // In 100ths of a second latitude
+ unsigned int lon_precision; // In 100ths of a second longitude
+
+ int trail_color; // trail color (when assigned)
+ char record_type;
+ char data_via; // L local, T TNC, I internet, F file
+
+// Change to char's to save space?
+ int heard_via_tnc_port;
+ int last_port_heard;
+ unsigned int num_packets;
+ char *node_path_ptr; // Pointer to path string
+ char altitude[MAX_ALTITUDE]; // in meters (feet gives better resolution ??)
+ char speed[MAX_SPEED+1]; // in knots (same as nautical miles/hour)
+ char course[MAX_COURSE+1];
+ char bearing[MAX_COURSE+1];
+ char NRQ[MAX_COURSE+1];
+ char power_gain[MAX_POWERGAIN+1]; // Holds the phgd values
+ char signal_gain[MAX_POWERGAIN+1]; // Holds the shgd values (for DF'ing)
+
+ WeatherRow *weather_data; // Pointer to weather data or NULL
+
+ CommentRow *status_data; // Ptr to status records or NULL
+ CommentRow *comment_data; // Ptr to comment records or NULL
+
+ // Below two pointers are NULL if only one position has been received
+ TrackRow *oldest_trackpoint; // Pointer to oldest track point in
+ // doubly-linked list
+ TrackRow *newest_trackpoint; // Pointer to newest track point in
+ // doubly-linked list
+
+ // When the station is an object, it can include coordinates
+ // of related points. Currently these are being used to draw
+ // outlines of NWS severe weather watches and warnings, and
+ // storm regions. The coordinates are stored here in Xastir
+ // coordinate form. Element [x][0] is the latitude, and
+ // element [x][1] is the longitude. --KG4NBB
+ //
+ // Is there anything preventing a multipoint string from being
+ // in other types of packets, in the comment field? --WE7U
+ //
+ int num_multipoints;
+ char type; // from '0' to '9'
+ char style; // from 'a' to 'z'
+ MultipointRow *multipoint_data;
+
+
+///////////////////////////////////////////////////////////////////////
+// Optional stuff for Objects/Items only (I think, needs to be
+// checked). These could be moved into an ObjectRow structure, with
+// only a NULL pointer here if not an object/item.
+///////////////////////////////////////////////////////////////////////
+
+ char origin[MAX_CALLSIGN+1]; // call sign originating an object
+ short object_retransmit; // Number of times to retransmit object.
+ // -1 = forever
+ // Used currently to stop sending killed
+ // objects.
+ time_t last_transmit_time; // Time we last transmitted an object/item.
+ // Used to implement decaying transmit time
+ // algorithm
+ short transmit_time_increment; // Seconds to add to transmit next time
+ // around. Used to implement decaying
+ // transmit time algorithm
+// time_t last_modified_time; // Seconds since the object/item
+ // was last modified. We'll
+ // eventually use this for
+ // dead-reckoning.
+ char signpost[5+1]; // Holds signpost data
+ int df_color;
+ char sats_visible[MAX_SAT];
+ char probability_min[10+1]; // Holds prob_min (miles)
+ char probability_max[10+1]; // Holds prob_max (miles)
+
+} DataRow;
+
+
+
+// Used to store one vertice in CADRow object
+typedef struct _VerticeRow{
+ long latitude; // Xastir coordinates 1/100sec, 0 = 180W
+ long longitude; // Xastir coordinates 1/100sec, 0 = 90N
+ struct _VerticeRow *next; // Pointer to next record in list
+} VerticeRow;
+
+#define CAD_LABEL_MAX_SIZE 40
+#define CAD_COMMENT_MAX_SIZE 256
+
+
+// CAD Objects
+typedef struct _CADRow {
+ struct _CADRow *next; // Pointer to next element in list
+ time_t creation_time; // Time at which object was first created
+ VerticeRow *start; // Pointer to first VerticeRow
+ int line_color; // Border color
+ int line_type; // Border linetype
+ int line_width; // Border line width
+ float computed_area; // Area in square kilometers
+ float raw_probability; // Probability of area (POA) or probability of
+ // detection (POD) stored as probability
+ // with a value between 0 and 1.
+ // Set and get with CAD_object_get_raw_probability()
+ // and CAD_object_set_raw_probability(), rather
+ // than by a direct request for CADRow->raw_probability.
+ long label_latitude; // Latitude for label placement
+ long label_longitude; // Longitude for label placement
+ char label[CAD_LABEL_MAX_SIZE]; // Name of polygon
+ char comment[CAD_COMMENT_MAX_SIZE]; // Comments associated with polygon
+} CADRow;
+
+
+extern CADRow *CAD_list_head;
+
+
+
+// station flag definitions. We have 16 bits available here as
+// "flag" in "DataRow" is defined as a short.
+//
+#define ST_OBJECT 0x01 // station is an object
+#define ST_ITEM 0x02 // station is an item
+#define ST_ACTIVE 0x04 // station is active (deleted objects are
+ // inactive)
+#define ST_MOVING 0x08 // station is moving
+#define ST_DIRECT 0x10 // heard direct (not via digis)
+#define ST_VIATNC 0x20 // station heard via TNC
+#define ST_3RD_PT 0x40 // third party traffic
+#define ST_MSGCAP 0x80 // message capable (not used yet)
+#define ST_STATUS 0x100 // got real status message
+#define ST_INVIEW 0x200 // station is in current screen view
+#define ST_MYSTATION 0x400 // station is owned by my call-SSID
+#define ST_MYOBJITEM 0x800 // object/item owned by me
+
+
+#ifdef DATA_DEBUG
+extern void clear_data(DataRow *clear);
+extern void copy_data(DataRow *to, DataRow *from);
+#else // DATA_DEBUG
+#define clear_data(clear) memset((DataRow *)clear, 0, sizeof(DataRow))
+#define copy_data(to, from) memmove((DataRow *)to, (DataRow *)from, \
+ sizeof(DataRow))
+#endif /* DATA_DEBUG */
+
+
+extern void db_init(void);
+extern void export_trail_as_kml(DataRow *p_station); // export trail of one or all stations to kml file
+
+//
+extern int is_my_call(char *call, int exact);
+extern int is_my_station(DataRow *p_station);
+extern int is_my_object_item(DataRow *p_station);
+
+void mscan_file(char msg_type, void (*function)(Message *fill));
+extern void msg_record_ack(char *to_call_sign, char *my_call, char *seq,
+ int timeout, int cancel);
+extern void msg_record_interval_tries(char *to_call_sign, char *my_call,
+ char *seq, time_t interval, int tries);
+extern void display_file(Widget w);
+extern void clean_data_file(void);
+extern void read_file_line(FILE *f);
+extern void mdisplay_file(char msg_type);
+extern void mem_display(void);
+extern long sort_input_database(char *filename, char *fill, int size);
+extern void sort_display_file(char *filename, int size);
+extern void clear_sort_file(char *filename);
+extern void display_packet_data(void);
+extern int redraw_on_new_packet_data;
+extern int decode_ax25_header(unsigned char *data_string, int *length);
+extern int decode_ax25_line(char *line, char from, int port, int dbadd);
+
+// utilities
+extern void packet_data_add(char *from, char *line, int data_port);
+extern void General_query(Widget w, XtPointer clientData, XtPointer calldata);
+extern void IGate_query(Widget w, XtPointer clientData, XtPointer calldata);
+extern void WX_query(Widget w, XtPointer clientData, XtPointer calldata);
+extern unsigned long max_stations;
+extern int heard_via_tnc_in_past_hour(char *call);
+
+// messages
+extern void update_messages(int force);
+extern void mdelete_messages_from(char *from);
+extern void mdelete_messages_to(char *to);
+extern void init_message_data(void);
+extern void check_message_remove(time_t curr_sec);
+extern int new_message_data;
+extern time_t msg_data_add(char *call_sign, char *from_call, char *data,
+ char *seq, char type, char from, long *record_out);
+
+// stations
+extern int st_direct_timeout; // Interval that ST_DIRECT flag stays set
+extern int station_count; // Count of stations in the database
+extern int station_count_save; // Old copy of the above
+extern DataRow *n_first; // pointer to first element in name ordered station
+ // list
+extern DataRow *n_last; // pointer to last element in name ordered station
+ // list
+extern DataRow *t_oldest; // pointer to first element in time ordered station
+ // list
+extern DataRow *t_newest; // pointer to last element in time ordered station
+ // list
+extern void init_station_data(void);
+extern void Station_data(Widget w, XtPointer clientData, XtPointer calldata);
+extern int station_data_auto_update;
+extern int next_station_name(DataRow **p_curr);
+extern int prev_station_name(DataRow **p_curr);
+extern int next_station_time(DataRow **p_curr);
+extern int prev_station_time(DataRow **p_curr);
+extern int search_station_name(DataRow **p_name, char *call, int exact);
+extern int search_station_time(DataRow **p_time, time_t heard, int serial);
+extern void check_station_remove(time_t curr_sec);
+extern void delete_all_stations(void);
+extern void station_del(char *callsign);
+extern void my_station_add(char *my_call_sign, char my_group, char my_symbol,
+ char *my_long, char *my_lat, char *my_phg,
+ char *my_comment, char my_amb);
+extern void my_station_gps_change(char *pos_long, char *pos_lat, char *course,
+ char *speed, char speedu, char *alt,
+ char *sats);
+extern int locate_station(Widget w, char *call, int follow_case,
+ int get_match, int center_map);
+extern void update_station_info(Widget w);
+
+// objects/items
+extern time_t last_object_check;
+
+// trails
+extern int delete_trail(DataRow *fill);
+
+// weather
+extern int get_weather_record(DataRow *fill);
+
+extern void set_map_position(Widget w, long lat, long lon);
+
+
+// just used for aloha calcs
+typedef struct {
+ double distance;
+ char call_sign[MAX_CALLSIGN+1]; // call sign or name index or object/item
+ // name
+ char is_mobile;
+ char is_other_mobile;
+ char is_wx;
+ char is_digi; // can only tell this if using a digi icon!
+ char is_home; // stationary stations that are not digis
+} aloha_entry;
+typedef struct {
+ int digis;
+ int wxs;
+ int other_mobiles;
+ int mobiles_in_motion;
+ int homes;
+ int total;
+} aloha_stats;
+
+double calc_aloha_distance(void); //meat
+void calc_aloha(int curr_sec); // periodic function
+void Show_Aloha_Stats(Widget w, XtPointer clientData,
+ XtPointer callData); // popup window
+
+int comp_by_dist(const void *,const void *);// used only for qsort
+DataRow * sanity_check_time_list(time_t); // used only for debugging
+void dump_time_sorted_list(void);
+
+extern int store_trail_point(DataRow *p_station, long lon, long lat, time_t sec, char *alt, char *speed, char *course, short stn_flag);
+
+#ifdef HAVE_DB
+extern int add_simple_station(DataRow *p_new_station,char *station, char *origin, char *symbol, char *overlay, char *aprs_type, char *latitude, char *longitude, char *record_type, char *node_path, char *transmit_time, char *timeformat);
+
+#endif /* HAVE_DB */
+
+#endif /* XASTIR_DATABASE_H */
diff --git a/src/datum.c b/src/datum.c
new file mode 100644
index 0000000..ee91b30
--- /dev/null
+++ b/src/datum.c
@@ -0,0 +1,818 @@
+/*
+ See the top of datum.h for information on this code.
+ N7TAP
+
+ Portions Copyright (C) 2002-2012 The Xastir Group
+
+ $Id: datum.c,v 1.28 2012/08/25 16:38:29 tvrusso Exp $
+*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "xastir.h"
+#include "datum.h"
+#include "main.h"
+#include "util.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+// ellipsoid: index into the gEllipsoid[] array, in which
+// a is the ellipsoid semimajor axis
+// invf is the inverse of the ellipsoid flattening f
+// dx, dy, dz: ellipsoid center with respect to WGS84 ellipsoid center
+// x axis is the prime meridian
+// y axis is 90 degrees east longitude
+// z axis is the axis of rotation of the ellipsoid
+
+// The following values for dx, dy and dz were extracted from the output of
+// the GARMIN PCX5 program. The output also includes values for da and df, the
+// difference between the reference ellipsoid and the WGS84 ellipsoid semi-
+// major axis and flattening, respectively. These are replaced by the
+// data contained in the structure array gEllipsoid[], which was obtained from
+// the Defence Mapping Agency document number TR8350.2, "Department of Defense
+// World Geodetic System 1984."
+
+/*
+ The above are the original comments by John Waers.
+
+ Curt Mills, WE7U wrote a perl version of this code and added more datums
+ from Peter H. Dana's website.
+
+ Reference Ellipsoids:
+ http://www.Colorado.EDU/geography/gcraft/notes/datum/elist.html
+
+ Reference Ellipsoids and Datums:
+ http://www.Colorado.EDU/geography/gcraft/notes/datum/edlist.html
+
+ I've loaded the numbers from that second, newer web page.
+ N7TAP
+*/
+
+/* Keep the enum in datum.h up to date with the order of this array */
+const Ellipsoid gEllipsoid[] = {
+// name a 1/f
+ { "Airy 1830", 6377563.396, 299.3249646 },
+ { "Modified Airy", 6377340.189, 299.3249646 },
+ { "Australian National", 6378160.0, 298.25 },
+ { "Bessel 1841", 6377397.155, 299.1528128 },
+ { "Bessel 1841 (Namibia)", 6377483.865, 299.1528128 },
+ { "Clarke 1866", 6378206.4, 294.9786982 },
+ { "Clarke 1880", 6378249.145, 293.465 },
+ { "Everest (India 1830)", 6377276.345, 300.8017 },
+ { "Everest (India 1956)", 6377301.243, 300.8017 },
+ { "Everest (Sabah Sarawak)", 6377298.556, 300.8017 },
+ { "Everest (Malaysia 1969)", 6377295.664, 300.8017 },
+ { "Everest (Malay. & Sing)", 6377304.063, 300.8017 },
+ { "Everest (Pakistan)", 6377309.613, 300.8017 },
+ { "Fischer 1960 (Mercury)", 6378166.0, 298.3 },
+ { "Modified Fischer 1960", 6378155.0, 298.3 },
+ { "Fischer 1968", 6378150.0, 298.3 },
+ { "Helmert 1906", 6378200.0, 298.3 },
+ { "Hough 1960", 6378270.0, 297.0 },
+ { "Indonesian 1974", 6378160.0, 298.247 },
+ { "International 1924", 6378388.0, 297.0 },
+ { "Krassovsky 1940", 6378245.0, 298.3 },
+ { "GRS 67", 6378160.0, 298.247167427 },
+ { "GRS 80", 6378137.0, 298.257222101 },
+ { "South American 1969", 6378160.0, 298.25 },
+ { "WGS 60", 6378165.0, 298.3 },
+ { "WGS 66", 6378145.0, 298.25 },
+ { "WGS 72", 6378135.0, 298.26 },
+ { "WGS 84", 6378137.0, 298.257223563 }
+};
+
+
+
+
+
+/* Keep correct indices to commonly used datums in the enum in datum.h */
+/* Feel free to add mnemonic indices for datums that you use */
+const Datum gDatum[] = {
+// name ellipsoid dx dy dz
+ { "Adindan (Burkina Faso)", E_CLARKE_80, -118, -14, 218 }, // 0
+ { "Adindan (Cameroon)", E_CLARKE_80, -134, -2, 210 }, // 1
+ { "Adindan (Ethiopia)", E_CLARKE_80, -165, -11, 206 }, // 2
+ { "Adindan (Mali)", E_CLARKE_80, -123, -20, 220 }, // 3
+ { "Adindan (MEAN FOR Ethiopia; Sudan)", E_CLARKE_80, -166, -15, 204 }, // 4
+ { "Adindan (Senegal)", E_CLARKE_80, -128, -18, 224 }, // 5
+ { "Adindan (Sudan)", E_CLARKE_80, -161, -14, 205 }, // 6
+ { "Afgooye (Somalia)", E_KRASS_40, -43, -163, 45 }, // 7
+ { "Ain el Abd 1970 (Bahrain)", E_INT_24, -150, -250, -1 }, // 8
+ { "Ain el Abd 1970 (Saudi Arabia)", E_INT_24, -143, -236, 7 }, // 9
+ { "American Samoa 1962 (American Samoa Islands)", E_CLARKE_66, -115, 118, 426 }, // 10
+ { "Anna 1 Astro 1965 (Cocos Islands)", E_AUS_NAT, -491, -22, 435 }, // 11
+ { "Antigua Island Astro 1943 (Antigua (Leeward Islands))", E_CLARKE_80, -270, 13, 62 }, // 12
+ { "Arc 1950 (Botswana)", E_CLARKE_80, -138, -105, -289 }, // 13
+ { "Arc 1950 (Burundi)", E_CLARKE_80, -153, -5, -292 }, // 14
+ { "Arc 1950 (Lesotho)", E_CLARKE_80, -125, -108, -295 }, // 15
+ { "Arc 1950 (Malawi)", E_CLARKE_80, -161, -73, -317 }, // 16
+ { "Arc 1950 (MEAN FOR Botswana; Lesotho; Malawi; Swaziland; Zaire; Zambia; Zimbabwe)", E_CLARKE_80, -143, -90, -294 }, // 17
+ { "Arc 1950 (Swaziland)", E_CLARKE_80, -134, -105, -295 }, // 18
+ { "Arc 1950 (Zaire)", E_CLARKE_80, -169, -19, -278 }, // 19
+ { "Arc 1950 (Zambia)", E_CLARKE_80, -147, -74, -283 }, // 20
+ { "Arc 1950 (Zimbabwe)", E_CLARKE_80, -142, -96, -293 }, // 21
+ { "Arc 1960 (MEAN FOR Kenya; Tanzania)", E_CLARKE_80, -160, -6, -302 }, // 22
+ { "Arc 1960 (Kenya)", E_CLARKE_80, -157, -2, -299 }, // 23
+ { "Arc 1960 (Taanzania)", E_CLARKE_80, -175, -23, -303 }, // 24
+ { "Ascension Island 1958 (Ascension Island)", E_INT_24, -205, 107, 53 }, // 25
+ { "Astro Beacon E 1945 (Iwo Jima)", E_INT_24, 145, 75, -272 }, // 26
+ { "Astro DOS 71/4 (St Helena Island)", E_INT_24, -320, 550, -494 }, // 27
+ { "Astro Tern Island (FRIG) 1961 (Tern Island)", E_INT_24, 114, -116, -333 }, // 28
+ { "Astronomical Station 1952 (Marcus Island)", E_INT_24, 124, -234, -25 }, // 29
+ { "Australian Geodetic 1966 (Australia; Tasmania)", E_AUS_NAT, -133, -48, 148 }, // 30
+ { "Australian Geodetic 1984 (Australia; Tasmania)", E_AUS_NAT, -134, -48, 149 }, // 31
+ { "Ayabelle Lighthouse (Djibouti)", E_CLARKE_80, -79, -129, 145 }, // 32
+ { "Bellevue (IGN) (Efate & Erromango Islands)", E_INT_24, -127, -769, 472 }, // 33
+ { "Bermuda 1957 (Bermuda)", E_CLARKE_66, -73, 213, 296 }, // 34
+ { "Bissau (Guinea-Bissau)", E_INT_24, -173, 253, 27 }, // 35
+ { "Bogota Observatory (Colombia)", E_INT_24, 307, 304, -318 }, // 36
+ { "Bukit Rimpah (Indonesia (Bangka & Belitung Ids))", E_BESS_41, -384, 664, -48 }, // 37
+ { "Camp Area Astro (Antarctica (McMurdo Camp Area))", E_INT_24, -104, -129, 239 }, // 38
+ { "Campo Inchauspe (Argentina)", E_INT_24, -148, 136, 90 }, // 39
+ { "Canton Astro 1966 (Phoenix Islands)", E_INT_24, 298, -304, -375 }, // 40
+ { "Cape (South Africa)", E_CLARKE_80, -136, -108, -292 }, // 41
+ { "Cape Canaveral (Bahamas; Florida)", E_CLARKE_66, -2, 151, 181 }, // 42
+ { "Carthage (Tunisia)", E_CLARKE_80, -263, 6, 431 }, // 43
+ { "Chatham Island Astro 1971 (New Zealand (Chatham Island))", E_INT_24, 175, -38, 113 }, // 44
+ { "Chua Astro (Paraguay)", E_INT_24, -134, 229, -29 }, // 45
+ { "Corrego Alegre (Brazil)", E_INT_24, -206, 172, -6 }, // 46
+ { "Dabola (Guinea)", E_CLARKE_80, -83, 37, 124 }, // 47
+ { "Deception Island (Deception Island; Antarctia)", E_CLARKE_80, 260, 12, -147 }, // 48
+ { "Djakarta (Batavia) (Indonesia (Sumatra))", E_BESS_41, -377, 681, -50 }, // 49
+ { "DOS 1968 (New Georgia Islands (Gizo Island))", E_INT_24, 230, -199, -752 }, // 50
+ { "Easter Island 1967 (Easter Island)", E_INT_24, 211, 147, 111 }, // 51
+ { "Estonia; Coordinate System 1937 (Estonia)", E_BESS_41, 374, 150, 588 }, // 52
+ { "European 1950 (Cyprus)", E_INT_24, -104, -101, -140 }, // 53
+ { "European 1950 (Egypt)", E_INT_24, -130, -117, -151 }, // 54
+ { "European 1950 (England; Channel Islands; Scotland; Shetland Islands)", E_INT_24, -86, -96, -120 }, // 55
+ { "European 1950 (England; Ireland; Scotland; Shetland Islands)", E_INT_24, -86, -96, -120 }, // 56
+ { "European 1950 (Finland; Norway)", E_INT_24, -87, -95, -120 }, // 57
+ { "European 1950 (Greece)", E_INT_24, -84, -95, -130 }, // 58
+ { "European 1950 (Iran)", E_INT_24, -117, -132, -164 }, // 59
+ { "European 1950 (Italy (Sardinia))", E_INT_24, -97, -103, -120 }, // 60
+ { "European 1950 (Italy (Sicily))", E_INT_24, -97, -88, -135 }, // 61
+ { "European 1950 (Malta)", E_INT_24, -107, -88, -149 }, // 62
+ { "European 1950 (MEAN FOR Austria; Belgium; Denmark; Finland; France; W Germany; Gibraltar; Greece; Italy; Luxembourg; Netherlands; Norway; Portugal; Spain; Sweden; Switzerland)", E_INT_24, -87, -98, -121 }, // 63
+ { "European 1950 (MEAN FOR Austria; Denmark; France; W Germany; Netherlands; Switzerland)", E_INT_24, -87, -96, -120 }, // 64
+ { "European 1950 (MEAN FOR Iraq; Israel; Jordan; Lebanon; Kuwait; Saudi Arabia; Syria)", E_INT_24, -103, -106, -141 }, // 65
+ { "European 1950 (Portugal; Spain)", E_INT_24, -84, -107, -120 }, // 66
+ { "European 1950 (Tunisia)", E_INT_24, -112, -77, -145 }, // 67
+ { "European 1979 (MEAN FOR Austria; Finland; Netherlands; Norway; Spain; Sweden; Switzerland)", E_INT_24, -86, -98, -119 }, // 68
+ { "Fort Thomas 1955 (Nevis; St. Kitts (Leeward Islands))", E_CLARKE_80, -7, 215, 225 }, // 69
+ { "Gan 1970 (Republic of Maldives)", E_INT_24, -133, -321, 50 }, // 70
+ { "Geodetic Datum 1949 (New Zealand)", E_INT_24, 84, -22, 209 }, // 71
+ { "Graciosa Base SW 1948 (Azores (Faial; Graciosa; Pico; Sao Jorge; Terceira))", E_INT_24, -104, 167, -38 }, // 72
+ { "Guam 1963 (Guam)", E_CLARKE_66, -100, -248, 259 }, // 73
+ { "Gunung Segara (Indonesia (Kalimantan))", E_BESS_41, -403, 684, 41 }, // 74
+ { "GUX 1 Astro (Guadalcanal Island)", E_INT_24, 252, -209, -751 }, // 75
+ { "Herat North (Afghanistan)", E_INT_24, -333, -222, 114 }, // 76
+ { "Hermannskogel Datum (Croatia -Serbia, Bosnia-Herzegovina)", E_BESS_41_NAM, 653, -212, 449 }, // 77
+ { "Hjorsey 1955 (Iceland)", E_INT_24, -73, 46, -86 }, // 78
+ { "Hong Kong 1963 (Hong Kong)", E_INT_24, -156, -271, -189 }, // 79
+ { "Hu-Tzu-Shan (Taiwan)", E_INT_24, -637, -549, -203 }, // 80
+ { "Indian (Bangladesh)", E_EVR_IND_30, 282, 726, 254 }, // 81
+ { "Indian (India; Nepal)", E_EVR_IND_56, 295, 736, 257 }, // 82
+ { "Indian (Pakistan)", E_EVR_PAK, 283, 682, 231 }, // 83
+ { "Indian 1954 (Thailand)", E_EVR_IND_30, 217, 823, 299 }, // 84
+ { "Indian 1960 (Vietnam (Con Son Island))", E_EVR_IND_30, 182, 915, 344 }, // 85
+ { "Indian 1960 (Vietnam (Near 16�N))", E_EVR_IND_30, 198, 881, 317 }, // 86
+ { "Indian 1975 (Thailand)", E_EVR_IND_30, 210, 814, 289 }, // 87
+ { "Indonesian 1974 (Indonesia)", E_IND_74, -24, -15, 5 }, // 88
+ { "Ireland 1965 (Ireland)", E_MOD_AIRY, 506, -122, 611 }, // 89
+ { "ISTS 061 Astro 1968 (South Georgia Islands)", E_INT_24, -794, 119, -298 }, // 90
+ { "ISTS 073 Astro 1969 (Diego Garcia)", E_INT_24, 208, -435, -229 }, // 91
+ { "Johnston Island 1961 (Johnston Island)", E_INT_24, 189, -79, -202 }, // 92
+ { "Kandawala (Sri Lanka)", E_EVR_IND_30, -97, 787, 86 }, // 93
+ { "Kerguelen Island 1949 (Kerguelen Island)", E_INT_24, 145, -187, 103 }, // 94
+ { "Kertau 1948 (West Malaysia & Singapore)", E_EVR_MAL_SING, -11, 851, 5 }, // 95
+ { "Kusaie Astro 1951 (Caroline Islands)", E_INT_24, 647, 1777, -1124 }, // 96
+ { "Korean Geodetic System (South Korea)", E_GRS_80, 0, 0, 0 }, // 97
+ { "L. C. 5 Astro 1961 (Cayman Brac Island)", E_CLARKE_66, 42, 124, 147 }, // 98
+ { "Leigon (Ghana)", E_CLARKE_80, -130, 29, 364 }, // 99
+ { "Liberia 1964 (Liberia)", E_CLARKE_80, -90, 40, 88 }, // 100
+ { "Luzon (Philippines (Excluding Mindanao))", E_CLARKE_66, -133, -77, -51 }, // 101
+ { "Luzon (Philippines (Mindanao))", E_CLARKE_66, -133, -79, -72 }, // 102
+ { "M'Poraloko (Gabon)", E_CLARKE_80, -74, -130, 42 }, // 103
+ { "Mahe 1971 (Mahe Island)", E_CLARKE_80, 41, -220, -134 }, // 104
+ { "Massawa (Ethiopia (Eritrea))", E_BESS_41, 639, 405, 60 }, // 105
+ { "Merchich (Morocco)", E_CLARKE_80, 31, 146, 47 }, // 106
+ { "Midway Astro 1961 (Midway Islands)", E_INT_24, 912, -58, 1227 }, // 107
+ { "Minna (Cameroon)", E_CLARKE_80, -81, -84, 115 }, // 108
+ { "Minna (Nigeria)", E_CLARKE_80, -92, -93, 122 }, // 109
+ { "Montserrat Island Astro 1958 (Montserrat (Leeward Islands))", E_CLARKE_80, 174, 359, 365 }, // 110
+ { "Nahrwan (Oman (Masirah Island))", E_CLARKE_80, -247, -148, 369 }, // 111
+ { "Nahrwan (Saudi Arabia)", E_CLARKE_80, -243, -192, 477 }, // 112
+ { "Nahrwan (United Arab Emirates)", E_CLARKE_80, -249, -156, 381 }, // 113
+ { "Naparima BWI (Trinidad & Tobago)", E_INT_24, -10, 375, 165 }, // 114
+ { "North American 1927 (Alaska (Excluding Aleutian Ids))", E_CLARKE_66, -5, 135, 172 }, // 115
+ { "North American 1927 (Alaska (Aleutian Ids East of 180�W))", E_CLARKE_66, -2, 152, 149 }, // 116
+ { "North American 1927 (Alaska (Aleutian Ids West of 180�W))", E_CLARKE_66, 2, 204, 105 }, // 117
+ { "North American 1927 (Bahamas (Except San Salvador Id))", E_CLARKE_66, -4, 154, 178 }, // 118
+ { "North American 1927 (Bahamas (San Salvador Island))", E_CLARKE_66, 1, 140, 165 }, // 119
+ { "North American 1927 (Canada (Alberta; British Columbia))", E_CLARKE_66, -7, 162, 188 }, // 120
+ { "North American 1927 (Canada (Manitoba; Ontario))", E_CLARKE_66, -9, 157, 184 }, // 121
+ { "North American 1927 (Canada (New Brunswick; Newfoundland; Nova Scotia; Quebec))", E_CLARKE_66, -22, 160, 190 }, // 122
+ { "North American 1927 (Canada (Northwest Territories; Saskatchewan))", E_CLARKE_66, 4, 159, 188 }, // 123
+ { "North American 1927 (Canada (Yukon))", E_CLARKE_66, -7, 139, 181 }, // 124
+ { "North American 1927 (Canal Zone)", E_CLARKE_66, 0, 125, 201 }, // 125
+ { "North American 1927 (Cuba)", E_CLARKE_66, -9, 152, 178 }, // 126
+ { "North American 1927 (Greenland (Hayes Peninsula))", E_CLARKE_66, 11, 114, 195 }, // 127
+ { "North American 1927 (MEAN FOR Antigua; Barbados; Barbuda; Caicos Islands; Cuba; Dominican Republic; Grand Cayman; Jamaica; Turks Islands)", E_CLARKE_66, -3, 142, 183 }, // 128
+ { "North American 1927 (MEAN FOR Belize; Costa Rica; El Salvador; Guatemala; Honduras; Nicaragua)", E_CLARKE_66, 0, 125, 194 }, // 129
+ { "North American 1927 (MEAN FOR Canada)", E_CLARKE_66, -10, 158, 187 }, // 130
+ { "North American 1927 (MEAN FOR CONUS)", E_CLARKE_66, -8, 160, 176 }, // 131
+ { "North American 1927 (MEAN FOR CONUS (East of Mississippi; River Including Louisiana; Missouri; Minnesota))", E_CLARKE_66, -9, 161, 179 }, // 132
+ { "North American 1927 (MEAN FOR CONUS (West of Mississippi; River Excluding Louisiana; Minnesota; Missouri))", E_CLARKE_66, -8, 159, 175 }, // 133
+ { "North American 1927 (Mexico)", E_CLARKE_66, -12, 130, 190 }, // 134
+ { "North American 1983 (Alaska (Excluding Aleutian Ids))", E_GRS_80, 0, 0, 0 }, // 135
+ { "North American 1983 (Aleutian Ids)", E_GRS_80, -2, 0, 4 }, // 136
+ { "North American 1983 (Canada)", E_GRS_80, 0, 0, 0 }, // 137
+ { "North American 1983 (CONUS)", E_GRS_80, 0, 0, 0 }, // 138
+ { "North American 1983 (Hawaii)", E_GRS_80, 1, 1, -1 }, // 139
+ { "North American 1983 (Mexico; Central America)", E_GRS_80, 0, 0, 0 }, // 140
+ { "North Sahara 1959 (Algeria)", E_CLARKE_80, -186, -93, 310 }, // 141
+ { "Observatorio Meteorologico 1939 (Azores (Corvo & Flores Islands))", E_INT_24, -425, -169, 81 }, // 142
+ { "Old Egyptian 1907 (Egypt)", E_HELM_06, -130, 110, -13 }, // 143
+ { "Old Hawaiian (Hawaii)", E_CLARKE_66, 89, -279, -183 }, // 144
+ { "Old Hawaiian (Kauai)", E_CLARKE_66, 45, -290, -172 }, // 145
+ { "Old Hawaiian (Maui)", E_CLARKE_66, 65, -290, -190 }, // 146
+ { "Old Hawaiian (MEAN FOR Hawaii; Kauai; Maui; Oahu)", E_CLARKE_66, 61, -285, -181 }, // 147
+ { "Old Hawaiian (Oahu)", E_CLARKE_66, 58, -283, -182 }, // 148
+ { "Oman (Oman)", E_CLARKE_80, -346, -1, 224 }, // 149
+ { "Ordnance Survey Great Britain 1936 (England)", E_AIRY_30, 371, -112, 434 }, // 150
+ { "Ordnance Survey Great Britain 1936 (England; Isle of Man; Wales)", E_AIRY_30, 371, -111, 434 }, // 151
+ { "Ordnance Survey Great Britain 1936 (MEAN FOR England; Isle of Man; Scotland; Shetland Islands; Wales)", E_AIRY_30, 375, -111, 431 }, // 152
+ { "Ordnance Survey Great Britain 1936 (Scotland; Shetland Islands)", E_AIRY_30, 384, -111, 425 }, // 153
+ { "Ordnance Survey Great Britain 1936 (Wales)", E_AIRY_30, 370, -108, 434 }, // 154
+ { "Pico de las Nieves (Canary Islands)", E_INT_24, -307, -92, 127 }, // 155
+ { "Pitcairn Astro 1967 (Pitcairn Island)", E_INT_24, 185, 165, 42 }, // 156
+ { "Point 58 (MEAN FOR Burkina Faso & Niger)", E_CLARKE_80, -106, -129, 165 }, // 157
+ { "Pointe Noire 1948 (Congo)", E_CLARKE_80, -148, 51, -291 }, // 158
+ { "Porto Santo 1936 (Porto Santo; Madeira Islands)", E_INT_24, -499, -249, 314 }, // 159
+ { "Provisional South American 1956 (Bolivia)", E_INT_24, -270, 188, -388 }, // 160
+ { "Provisional South American 1956 (Chile (Northern; Near 19�S))", E_INT_24, -270, 183, -390 }, // 161
+ { "Provisional South American 1956 (Chile (Southern; Near 43�S))", E_INT_24, -305, 243, -442 }, // 162
+ { "Provisional South American 1956 (Colombia)", E_INT_24, -282, 169, -371 }, // 163
+ { "Provisional South American 1956 (Ecuador)", E_INT_24, -278, 171, -367 }, // 164
+ { "Provisional South American 1956 (Guyana)", E_INT_24, -298, 159, -369 }, // 165
+ { "Provisional South American 1956 (MEAN FOR Bolivia; Chile; Colombia; Ecuador; Guyana; Peru; Venezuela)", E_INT_24, -288, 175, -376 }, // 166
+ { "Provisional South American 1956 (Peru)", E_INT_24, -279, 175, -379 }, // 167
+ { "Provisional South American 1956 (Venezuela)", E_INT_24, -295, 173, -371 }, // 168
+ { "Provisional South Chilean 1963 (Chile (Near 53�S) (Hito XVIII))", E_INT_24, 16, 196, 93 }, // 169
+ { "Puerto Rico (Puerto Rico; Virgin Islands)", E_CLARKE_66, 11, 72, -101 }, // 170
+ { "Pulkovo 1942 (Russia)", E_KRASS_40, 28, -130, -95 }, // 171
+ { "Qatar National (Qatar)", E_INT_24, -128, -283, 22 }, // 172
+ { "Qornoq (Greenland (South))", E_INT_24, 164, 138, -189 }, // 173
+ { "Reunion (Mascarene Islands)", E_INT_24, 94, -948, -1262 }, // 174
+ { "Rome 1940 (Italy (Sardinia))", E_INT_24, -225, -65, 9 }, // 175
+ { "S-42 (Pulkovo 1942) (Hungary)", E_KRASS_40, 28, -121, -77 }, // 176
+ { "S-42 (Pulkovo 1942) (Poland)", E_KRASS_40, 23, -124, -82 }, // 177
+ { "S-42 (Pulkovo 1942) (Czechoslavakia)", E_KRASS_40, 26, -121, -78 }, // 178
+ { "S-42 (Pulkovo 1942) (Latvia)", E_KRASS_40, 24, -124, -82 }, // 179
+ { "S-42 (Pulkovo 1942) (Kazakhstan)", E_KRASS_40, 15, -130, -84 }, // 180
+ { "S-42 (Pulkovo 1942) (Albania)", E_KRASS_40, 24, -130, -92 }, // 181
+ { "S-42 (Pulkovo 1942) (Romania)", E_KRASS_40, 28, -121, -77 }, // 182
+ { "S-JTSK (Czechoslavakia (Prior 1 JAN 1993))", E_BESS_41, 589, 76, 480 }, // 183
+ { "Santo (DOS) 1965 (Espirito Santo Island)", E_INT_24, 170, 42, 84 }, // 184
+ { "Sao Braz (Azores (Sao Miguel; Santa Maria Ids))", E_INT_24, -203, 141, 53 }, // 185
+ { "Sapper Hill 1943 (East Falkland Island)", E_INT_24, -355, 21, 72 }, // 186
+ { "Schwarzeck (Namibia)", E_BESS_41_NAM, 616, 97, -251 }, // 187
+ { "Selvagem Grande 1938 (Salvage Islands)", E_INT_24, -289, -124, 60 }, // 188
+ { "Sierra Leone 1960 (Sierra Leone)", E_CLARKE_80, -88, 4, 101 }, // 189
+ { "South American 1969 (Argentina)", E_S_AMER_69, -62, -1, -37 }, // 190
+ { "South American 1969 (Bolivia)", E_S_AMER_69, -61, 2, -48 }, // 191
+ { "South American 1969 (Brazil)", E_S_AMER_69, -60, -2, -41 }, // 192
+ { "South American 1969 (Chile)", E_S_AMER_69, -75, -1, -44 }, // 193
+ { "South American 1969 (Colombia)", E_S_AMER_69, -44, 6, -36 }, // 194
+ { "South American 1969 (Ecuador)", E_S_AMER_69, -48, 3, -44 }, // 195
+ { "South American 1969 (Ecuador (Baltra; Galapagos))", E_S_AMER_69, -47, 26, -42 }, // 196
+ { "South American 1969 (Guyana)", E_S_AMER_69, -53, 3, -47 }, // 197
+ { "South American 1969 (MEAN FOR Argentina; Bolivia; Brazil; Chile; Colombia; Ecuador; Guyana; Paraguay; Peru; Trinidad & Tobago; Venezuela)", E_S_AMER_69, -57, 1, -41 }, // 198
+ { "South American 1969 (Paraguay)", E_S_AMER_69, -61, 2, -33 }, // 199
+ { "South American 1969 (Peru)", E_S_AMER_69, -58, 0, -44 }, // 200
+ { "South American 1969 (Trinidad & Tobago)", E_S_AMER_69, -45, 12, -33 }, // 201
+ { "South American 1969 (Venezuela)", E_S_AMER_69, -45, 8, -33 }, // 202
+ { "South Asia (Singapore)", E_MOD_FISCH_60, 7, -10, -26 }, // 203
+ { "Tananarive Observatory 1925 (Madagascar)", E_INT_24, -189, -242, -91 }, // 204
+ { "Timbalai 1948 (Brunei; E. Malaysia (Sabah Sarawak))", E_EVR_SAB_SAR, -679, 669, -48 }, // 205
+ { "Tokyo (Japan)", E_BESS_41, -148, 507, 685 }, // 206
+ { "Tokyo (MEAN FOR Japan; South Korea; Okinawa)", E_BESS_41, -148, 507, 685 }, // 207
+ { "Tokyo (Okinawa)", E_BESS_41, -158, 507, 676 }, // 208
+ { "Tokyo (South Korea)", E_BESS_41, -147, 506, 687 }, // 209
+ { "Tristan Astro 1968 (Tristan da Cunha)", E_INT_24, -632, 438, -609 }, // 210
+ { "Viti Levu 1916 (Fiji (Viti Levu Island))", E_CLARKE_80, 51, 391, -36 }, // 211
+ { "Voirol 1960 (Algeria)", E_CLARKE_80, -123, -206, 219 }, // 212
+ { "Wake Island Astro 1952 (Wake Atoll)", E_INT_24, 276, -57, 149 }, // 213
+ { "Wake-Eniwetok 1960 (Marshall Islands)", E_HOUGH_60, 102, 52, -38 }, // 214
+ { "WGS 1972 (Global Definition)", E_WGS_72, 0, 0, 0 }, // 215
+ { "WGS 1984 (Global Definition)", E_WGS_84, 0, 0, 0 }, // 216
+ { "Yacare (Uruguay)", E_INT_24, -155, 171, 37 }, // 217
+ { "Zanderij (Suriname)", E_INT_24, -265, 120, -358 } // 218
+};
+
+
+
+static const double PI = 3.14159265358979323846;
+
+
+
+
+
+/* As you can see this little function is just a 2 step datum shift, going through WGS84. */
+void datum_shift(double *latitude, double *longitude, short fromDatumID, short toDatumID)
+{
+ wgs84_datum_shift(TO_WGS_84, latitude, longitude, fromDatumID);
+ wgs84_datum_shift(FROM_WGS_84, latitude, longitude, toDatumID);
+}
+
+
+
+
+
+/*
+ Function to convert latitude and longitude in decimal degrees from WGS84 to
+ another datum or from another datum to WGS84. The arguments to this function
+ include a direction flag 'fromWGS84', pointers to double precision latitude
+ and longitude, and an index to the gDatum[] array.
+*/
+void wgs84_datum_shift(short fromWGS84, double *latitude, double *longitude, short datumID)
+{
+ double dx = gDatum[datumID].dx;
+ double dy = gDatum[datumID].dy;
+ double dz = gDatum[datumID].dz;
+
+ double phi = *latitude * PI / 180.0;
+ double lambda = *longitude * PI / 180.0;
+ double a0, b0, es0, f0; /* Reference ellipsoid of input data */
+ double a1, b1, es1, f1; /* Reference ellipsoid of output data */
+ double psi; /* geocentric latitude */
+ double x, y, z; /* 3D coordinates with respect to original datum */
+ double psi1; /* transformed geocentric latitude */
+
+ if (datumID == D_WGS_84) // do nothing if current datum is WGS84
+ return;
+
+ if (fromWGS84) { /* convert from WGS84 to new datum */
+ a0 = gEllipsoid[E_WGS_84].a; /* WGS84 semimajor axis */
+ f0 = 1.0 / gEllipsoid[E_WGS_84].invf; /* WGS84 flattening */
+ a1 = gEllipsoid[gDatum[datumID].ellipsoid].a;
+ f1 = 1.0 / gEllipsoid[gDatum[datumID].ellipsoid].invf;
+ }
+ else { /* convert from datum to WGS84 */
+ a0 = gEllipsoid[gDatum[datumID].ellipsoid].a; /* semimajor axis */
+ f0 = 1.0 / gEllipsoid[gDatum[datumID].ellipsoid].invf; /* flattening */
+ a1 = gEllipsoid[E_WGS_84].a; /* WGS84 semimajor axis */
+ f1 = 1.0 / gEllipsoid[E_WGS_84].invf; /* WGS84 flattening */
+ dx = -dx;
+ dy = -dy;
+ dz = -dz;
+ }
+
+ b0 = a0 * (1 - f0); /* semiminor axis for input datum */
+ es0 = 2 * f0 - f0*f0; /* eccentricity^2 */
+
+ b1 = a1 * (1 - f1); /* semiminor axis for output datum */
+ es1 = 2 * f1 - f1*f1; /* eccentricity^2 */
+
+ /* Convert geodedic latitude to geocentric latitude, psi */
+ if (*latitude == 0.0 || *latitude == 90.0 || *latitude == -90.0)
+ psi = phi;
+ else
+ psi = atan((1 - es0) * tan(phi));
+
+ /* Calculate x and y axis coordinates with respect to the original ellipsoid */
+ if (*longitude == 90.0 || *longitude == -90.0) {
+ x = 0.0;
+ y = fabs(a0 * b0 / sqrt(b0*b0 + a0*a0*pow(tan(psi), 2.0)));
+ }
+ else {
+ x = fabs((a0 * b0) /
+ sqrt((1 + pow(tan(lambda), 2.0)) * (b0*b0 + a0*a0 * pow(tan(psi), 2.0))));
+ y = fabs(x * tan(lambda));
+ }
+
+ if (*longitude < -90.0 || *longitude > 90.0)
+ x = -x;
+ if (*longitude < 0.0)
+ y = -y;
+
+ /* Calculate z axis coordinate with respect to the original ellipsoid */
+ if (*latitude == 90.0)
+ z = b0;
+ else if (*latitude == -90.0)
+ z = -b0;
+ else
+ z = tan(psi) * sqrt((a0*a0 * b0*b0) / (b0*b0 + a0*a0 * pow(tan(psi), 2.0)));
+
+ /* Calculate the geocentric latitude with respect to the new ellipsoid */
+ psi1 = atan((z - dz) / sqrt((x - dx)*(x - dx) + (y - dy)*(y - dy)));
+
+ /* Convert to geocentric latitude and save return value */
+ *latitude = atan(tan(psi1) / (1 - es1)) * 180.0 / PI;
+
+ /* Calculate the longitude with respect to the new ellipsoid */
+ *longitude = atan((y - dy) / (x - dx)) * 180.0 / PI;
+
+ /* Correct the resultant for negative x values */
+ if (x-dx < 0.0) {
+ if (y-dy > 0.0)
+ *longitude = 180.0 + *longitude;
+ else
+ *longitude = -180.0 + *longitude;
+ }
+}
+
+
+
+
+
+#define deg2rad (PI / 180)
+#define rad2deg (180.0 / PI)
+
+
+
+
+
+/*
+ Source
+ Defense Mapping Agency. 1987b. DMA Technical Report: Supplement to Department of Defense World Geodetic System
+ 1984 Technical Report. Part I and II. Washington, DC: Defense Mapping Agency
+*/
+//
+// Convert lat/long to UTM/UPS coordinates
+void ll_to_utm_ups(short ellipsoidID, const double lat, const double lon,
+ double *utmNorthing, double *utmEasting, char* utmZone, int utmZoneLength)
+{
+ //converts lat/long to UTM coords. Equations from USGS Bulletin 1532
+ //East Longitudes are positive, West longitudes are negative.
+ //North latitudes are positive, South latitudes are negative
+ //Lat and Long are in decimal degrees
+ //Written by Chuck Gantz- chuck.gantz at globalstar.com
+
+ double a = gEllipsoid[ellipsoidID].a;
+ double f = 1.0 / gEllipsoid[ellipsoidID].invf;
+ double eccSquared = (2 * f) - (f * f);
+ double k0 = 0.9996;
+
+ double LongOrigin;
+ double eccPrimeSquared;
+ double N, T, C, A, M;
+
+ //Make sure the longitude is between -180.00 .. 179.9
+ double LongTemp = (lon+180)-(int)((lon+180)/360)*360-180; // -180.00 .. 179.9;
+
+ double LatRad = lat*deg2rad;
+ double LongRad = LongTemp*deg2rad;
+ double LongOriginRad;
+ int ZoneNumber;
+
+ ZoneNumber = (int)((LongTemp + 180)/6) + 1;
+
+ if (coordinate_system == USE_UTM_SPECIAL
+ || coordinate_system == USE_MGRS) {
+
+ // Special zone for southern Norway. Used for military
+ // version of UTM (MGRS) only.
+ if ( lat >= 56.0 && lat < 64.0 && LongTemp >= 3.0 && LongTemp < 12.0 )
+ ZoneNumber = 32;
+
+ // Handle the special zones for Svalbard. Used for military
+ // version of UTM (MGRS) only.
+ if (lat >= 72.0 && lat < 84.0) {
+ if (LongTemp >= 0.0 && LongTemp < 9.0)
+ ZoneNumber = 31;
+ else if (LongTemp >= 9.0 && LongTemp < 21.0)
+ ZoneNumber = 33;
+ else if (LongTemp >= 21.0 && LongTemp < 33.0)
+ ZoneNumber = 35;
+ else if (LongTemp >= 33.0 && LongTemp < 42.0)
+ ZoneNumber = 37;
+ }
+ }
+
+ LongOrigin = (ZoneNumber - 1)*6 - 180 + 3; //+3 puts origin in middle of zone
+ LongOriginRad = LongOrigin * deg2rad;
+
+ if (lat > 84.0 || lat < -80.0) {
+ // We're in the UPS areas (near the poles). ZoneNumber
+ // should not be printed in this case.
+ xastir_snprintf(utmZone,
+ utmZoneLength,
+ "%c",
+ utm_letter_designator(lat, lon));
+ }
+ else { // We're in the UTM areas (not near the poles).
+ //compute the UTM Zone from the latitude and longitude
+ xastir_snprintf(utmZone,
+ utmZoneLength,
+ "%d%c",
+ ZoneNumber,
+ utm_letter_designator(lat, lon));
+ }
+
+ eccPrimeSquared = (eccSquared)/(1-eccSquared);
+
+ if (lat > 84.0 || lat < -80.0) {
+ //
+ // We're dealing with UPS coordinates (near the poles)
+ //
+ // The following piece of code which implements UPS
+ // conversion is derived from code that John Waers
+ // <jfwaers at csn.net> placed in the public domain. It's from
+ // his program "MacGPS45".
+
+ double t, e, rho;
+ const double k0 = 0.994;
+ double lambda = lon * (PI/180.0);
+ double phi = fabs(lat * (PI/180.0) );
+
+ e = sqrt(eccSquared);
+ t = tan(PI/4.0 - phi/2.0) / pow( (1.0 - e * sin(phi)) / (1.0 + e * sin(phi)), (e/2.0) );
+ rho = 2.0 * a * k0 * t / sqrt(pow(1.0+e, 1.0+e) * pow(1.0-e, 1.0-e));
+ *utmEasting = rho * sin(lambda);
+ *utmNorthing = rho * cos(lambda);
+
+ if (lat > 0.0) // Northern hemisphere
+ *utmNorthing = -(*utmNorthing);
+
+ *utmEasting += 2.0e6; // Add in false easting and northing
+ *utmNorthing += 2.0e6;
+ }
+ else {
+ //
+ // We're dealing with UTM coordinates
+ //
+ N = a/sqrt(1-eccSquared*sin(LatRad)*sin(LatRad));
+ T = tan(LatRad)*tan(LatRad);
+ C = eccPrimeSquared*cos(LatRad)*cos(LatRad);
+ A = cos(LatRad)*(LongRad-LongOriginRad);
+
+ M = a*((1 -
+ eccSquared/4 -
+ 3*eccSquared*eccSquared/64 -
+ 5*eccSquared*eccSquared*eccSquared/256) * LatRad -
+ (3*eccSquared/8 +
+ 3*eccSquared*eccSquared/32 +
+ 45*eccSquared*eccSquared*eccSquared/1024) * sin(2*LatRad) +
+ (15*eccSquared*eccSquared/256 + 45*eccSquared*eccSquared*eccSquared/1024) * sin(4*LatRad) -
+ (35*eccSquared*eccSquared*eccSquared/3072) * sin(6*LatRad));
+
+ *utmEasting = (double)(k0*N*(A+(1-T+C)*A*A*A/6
+ + (5-18*T+T*T+72*C-58*eccPrimeSquared)*A*A*A*A*A/120)
+ + 500000.0);
+
+ *utmNorthing = (double)(k0*(M+N*tan(LatRad)*
+ (A*A/2+(5-T+9*C+4*C*C)*A*A*A*A/24
+ + (61-58*T+T*T+600*C-330*eccPrimeSquared)*A*A*A*A*A*A/720)));
+
+ if (lat < 0)
+ *utmNorthing += 10000000.0; //10000000 meter offset for southern hemisphere
+ }
+}
+
+
+
+
+
+// Handles UPS/UTM coordinates equally well!
+//
+char utm_letter_designator(double lat, double lon)
+{
+ // This routine determines the correct UTM/UPS letter designator
+ // for the given latitude. Originally written by Chuck Gantz-
+ // chuck.gantz at globalstar.com
+ // Modified to handle UPS zones. --we7u
+ char LetterDesignator;
+
+ if ((84 >= lat) && (lat >= 72)) LetterDesignator = 'X';
+ else if ((72 > lat) && (lat >= 64)) LetterDesignator = 'W';
+ else if ((64 > lat) && (lat >= 56)) LetterDesignator = 'V';
+ else if ((56 > lat) && (lat >= 48)) LetterDesignator = 'U';
+ else if ((48 > lat) && (lat >= 40)) LetterDesignator = 'T';
+ else if ((40 > lat) && (lat >= 32)) LetterDesignator = 'S';
+ else if ((32 > lat) && (lat >= 24)) LetterDesignator = 'R';
+ else if ((24 > lat) && (lat >= 16)) LetterDesignator = 'Q';
+ else if ((16 > lat) && (lat >= 8)) LetterDesignator = 'P';
+ else if (( 8 > lat) && (lat >= 0)) LetterDesignator = 'N';
+ else if (( 0 > lat) && (lat >= -8)) LetterDesignator = 'M';
+ else if ((-8 > lat) && (lat >= -16)) LetterDesignator = 'L';
+ else if ((-16 > lat) && (lat >= -24)) LetterDesignator = 'K';
+ else if ((-24 > lat) && (lat >= -32)) LetterDesignator = 'J';
+ else if ((-32 > lat) && (lat >= -40)) LetterDesignator = 'H';
+ else if ((-40 > lat) && (lat >= -48)) LetterDesignator = 'G';
+ else if ((-48 > lat) && (lat >= -56)) LetterDesignator = 'F';
+ else if ((-56 > lat) && (lat >= -64)) LetterDesignator = 'E';
+ else if ((-64 > lat) && (lat >= -72)) LetterDesignator = 'D';
+ else if ((-72 > lat) && (lat >= -80)) LetterDesignator = 'C';
+ else {
+ //
+ // We're dealing with UPS (N/S Pole) coordinates, not UTM
+ //
+ if (lat > 84) { // North Pole, Y/Z zones
+ if ((0 <= lon) && (lon <= 180))
+ LetterDesignator = 'Z'; // E or + longitude
+ else
+ LetterDesignator = 'Y'; // W or - longitude
+ }
+ else { // Lat < 80S, South Pole, A/B zones
+ if ((0 <= lon) && (lon <= 180))
+ LetterDesignator = 'B'; // E or + longitude
+ else
+ LetterDesignator = 'A'; // W or - longitude
+ }
+ }
+ return LetterDesignator;
+}
+
+
+
+
+
+// The following piece of code which implements UPS conversion is
+// derived from code that John Waers <jfwaers at csn.net> placed in
+// the public domain. It's from his program "MacGPS45".
+//
+static void calcPhi(double *phi, double e, double t)
+{
+ double old = PI/2.0 - 2.0 * atan(t);
+ short maxIterations = 20;
+
+ while ( (fabs((*phi - old) / *phi) > 1.0e-8) && maxIterations-- ) {
+ old = *phi;
+ *phi = PI/ 2.0 - 2.0 * atan( t * pow((1.0 - e * sin(*phi)) / ((1.0 + e * sin(*phi))), (e / 2.0)) );
+ }
+}
+
+
+
+
+
+// Converts from UTM/UPS coordinates to Lat/Long coordinates.
+//
+void utm_ups_to_ll(short ellipsoidID, const double utmNorthing, const double utmEasting,
+ const char* utmZone, double *lat, double *lon)
+{
+ // Converts UTM coords to lat/long. Equations from USGS
+ // Bulletin 1532. East Longitudes are positive, West longitudes
+ // are negative. North latitudes are positive, South latitudes
+ // are negative Lat and Long are in decimal degrees.
+ // Written by Chuck Gantz- chuck.gantz at globalstar.com
+ // Modified by WE7U to add UPS support.
+
+ double k0 = 0.9996;
+ double a = gEllipsoid[ellipsoidID].a;
+ double f = 1.0 / gEllipsoid[ellipsoidID].invf;
+ double eccSquared = (2 * f) - (f * f);
+ double eccPrimeSquared;
+ double e1 = (1-sqrt(1-eccSquared))/(1+sqrt(1-eccSquared));
+ double N1, T1, C1, R1, D, M;
+ double LongOrigin;
+ double mu, phi1, phi1Rad;
+ double x, y;
+ int ZoneNumber;
+ char* ZoneLetter;
+ int NorthernHemisphere; // 1=northern hemisphere, 0=southern
+
+
+//fprintf(stderr,"%s %f %f\n",
+// utmZone,
+// utmEasting,
+// utmNorthing);
+
+ x = utmEasting;
+ y = utmNorthing;
+
+ ZoneNumber = strtoul(utmZone, &ZoneLetter, 10);
+
+ // Remove any possible leading spaces
+ remove_leading_spaces(ZoneLetter);
+
+ // Make sure the zone letter is upper-case
+ *ZoneLetter = toupper(*ZoneLetter);
+
+//fprintf(stderr,"ZoneLetter: %s\n", ZoneLetter);
+
+ if ( *ZoneLetter == 'Y' // North Pole
+ || *ZoneLetter == 'Z' // North Pole
+ || *ZoneLetter == 'A' // South Pole
+ || *ZoneLetter == 'B') { // South Pole
+
+ // The following piece of code which implements UPS
+ // conversion is derived from code that John Waers
+ // <jfwaers at csn.net> placed in the public domain. It's from
+ // his program "MacGPS45".
+
+ //
+ // We're dealing with a UPS coordinate (near the poles)
+ // instead of a UTM coordinate. We need to do entirely
+ // different calculations for UPS.
+ //
+ double e, t, rho;
+ const double k0 = 0.994;
+
+
+//fprintf(stderr,"UPS Coordinates\n");
+
+
+ e = sqrt(eccSquared);
+
+ x -= 2.0e6; // Remove false easting and northing
+ y -= 2.0e6;
+
+ rho = sqrt(x*x + y*y);
+ t = rho * sqrt(pow(1.0+e, 1.0+e) * pow(1.0-e, 1.0-e)) / (2.0 * a * k0);
+
+ calcPhi(lat, e, t);
+
+ *lat /= (PI/180.0);
+
+ // This appears to be necessary in order to get proper
+ // positions in the south polar region
+ if (*ZoneLetter == 'A' || *ZoneLetter == 'B') {
+ *lat = -*lat;
+ }
+
+ if (y != 0.0)
+ t = atan(fabs(x/y));
+ else {
+ t = PI / 2.0;
+ if (x < 0.0) t = -t;
+ }
+
+ if (*ZoneLetter == 'Z' || *ZoneLetter == 'Y')
+ y = -y; // Northern hemisphere
+
+ if (y < 0.0)
+ t = PI - t;
+
+ if (x < 0.0)
+ t = -t;
+
+ *lon = t / (PI/180.0);
+
+/*
+ fprintf(stderr,"datum.c:utm_ups_to_ll(): Found UPS Coordinate: %s %f %f\n",
+ utmZone,
+ utmEasting,
+ utmNorthing);
+*/
+ return; // Done computing UPS coordinates
+ }
+
+
+ // If we make it here, we're working on UTM coordinates (not
+ // UPS coordinates).
+
+
+ x = utmEasting - 500000.0; //remove 500,000 meter offset for longitude
+ y = utmNorthing;
+
+
+ if ((*ZoneLetter - 'N') >= 0)
+ NorthernHemisphere = 1;//point is in northern hemisphere
+ else {
+ NorthernHemisphere = 0;//point is in southern hemisphere
+ y -= 10000000.0;//remove 10,000,000 meter offset used for southern hemisphere
+ }
+
+ LongOrigin = (ZoneNumber - 1)*6 - 180 + 3; //+3 puts origin in middle of zone
+
+ eccPrimeSquared = (eccSquared)/(1-eccSquared);
+
+ M = y / k0;
+ mu = M/(a*(1-eccSquared/4-3*eccSquared*eccSquared/64-5*eccSquared*eccSquared*eccSquared/256));
+
+ phi1Rad = mu + (3*e1/2-27*e1*e1*e1/32)*sin(2*mu)
+ + (21*e1*e1/16-55*e1*e1*e1*e1/32)*sin(4*mu)
+ + (151*e1*e1*e1/96)*sin(6*mu);
+ phi1 = phi1Rad*rad2deg;
+
+ N1 = a/sqrt(1-eccSquared*sin(phi1Rad)*sin(phi1Rad));
+ T1 = tan(phi1Rad)*tan(phi1Rad);
+ C1 = eccPrimeSquared*cos(phi1Rad)*cos(phi1Rad);
+ R1 = a*(1-eccSquared)/pow(1-eccSquared*sin(phi1Rad)*sin(phi1Rad), 1.5);
+ D = x/(N1*k0);
+
+ *lat = phi1Rad - (N1*tan(phi1Rad)/R1)*(D*D/2-(5+3*T1+10*C1-4*C1*C1-9*eccPrimeSquared)*D*D*D*D/24
+ +(61+90*T1+298*C1+45*T1*T1-252*eccPrimeSquared-3*C1*C1)*D*D*D*D*D*D/720);
+ *lat *= rad2deg;
+
+ *lon = (D-(1+2*T1+C1)*D*D*D/6+(5-2*C1+28*T1-3*C1*C1+8*eccPrimeSquared+24*T1*T1)
+ *D*D*D*D*D/120)/cos(phi1Rad);
+ *lon = LongOrigin + (*lon) * rad2deg;
+}
+
+
diff --git a/src/datum.h b/src/datum.h
new file mode 100644
index 0000000..0d90d35
--- /dev/null
+++ b/src/datum.h
@@ -0,0 +1,112 @@
+/*
+ Portions Copyright (C) 2002-2012 The Xastir Group
+
+ The datum conversion code here and in datum.c is from MacGPS 45.
+
+ According to the Read_Me file in the source archive of that program,
+ the author says the following:
+
+ "I've read the legalese statements that everyone attaches to works like this,
+ but I can never remember what they say. Suffice it to say that I am releasing
+ this source code to the public domain, and you are free to do with it what you
+ like. If you find it of some use and include any of it in an application,
+ credits (and perhaps a copy of your program, if your feel so inclined) would
+ be appreciated.
+
+ John F. Waers <jfwaers at csn.net>"
+
+ If you ever read this, John, thanks for the code and feel free to try out
+ Xastir, it's free.
+
+ The UTM to/from Lat/Long translations were written by Chuck Gantz
+ <chuck.gantz at globalstar.com>. Curt Mills received permission via e-mail
+ to release the code under the GPL for a conversion he did to perl.
+ I deduce from this that including it in Xastir, a GPL program is no problem.
+ Thanks Chuck!
+
+ N7TAP
+ $Id: datum.h,v 1.18 2012/11/01 18:57:19 we7u Exp $
+*/
+
+
+
+// Equatorial radius of the Earth. In our distance/angular/area
+// calculations (not here in datum.h/datum.c, but elsewhere in the
+// code) we currently ignore flattening as you go towards the poles.
+//
+// The datum translation code in datum.h/datum.c doesn't use these
+// three defines at all: That code uses ellipsoids and so
+// flattening is accounted for there.
+#define EARTH_RADIUS_METERS 6378138.0
+#define EARTH_RADIUS_KILOMETERS 6378.138
+#define EARTH_RADIUS_MILES 3963.1836
+
+
+#define FROM_WGS_84 1
+#define TO_WGS_84 0
+void wgs84_datum_shift(short fromWGS84, double *latitude, double *longitude, short datumID);
+void datum_shift(double *latitude, double *longitude, short fromDatumID, short toDatumID);
+
+typedef struct {
+ char *name; // name of ellipsoid
+ double a; // semi-major axis, meters
+ double invf; // 1/f
+} Ellipsoid;
+
+extern const Ellipsoid gEllipsoid[];
+
+enum Ellipsoid_Names { // Must match the order of the Ellipsoids defined in datum.c
+ E_AIRY_30,
+ E_MOD_AIRY,
+ E_AUS_NAT,
+ E_BESS_41,
+ E_BESS_41_NAM,
+ E_CLARKE_66,
+ E_CLARKE_80,
+ E_EVR_IND_30,
+ E_EVR_IND_56,
+ E_EVR_SAB_SAR,
+ E_EVR_MAL_69,
+ E_EVR_MAL_SING,
+ E_EVR_PAK,
+ E_FISCH_60_MERC,
+ E_MOD_FISCH_60,
+ E_FISCH_68,
+ E_HELM_06,
+ E_HOUGH_60,
+ E_IND_74,
+ E_INT_24,
+ E_KRASS_40,
+ E_GRS_67,
+ E_GRS_80,
+ E_S_AMER_69,
+ E_WGS_60,
+ E_WGS_66,
+ E_WGS_72,
+ E_WGS_84
+};
+
+typedef struct {
+ char *name;
+ short ellipsoid;
+ short dx;
+ short dy;
+ short dz;
+} Datum;
+
+extern const Datum gDatum[];
+
+enum Common_Datum_Names { // Must match the indices of the Datums defined in datum.c
+ D_NAD_27_CONUS = 131,
+ D_NAD_83_CONUS = 138,
+ D_WGS_72 = 215,
+ D_WGS_84 = 216
+};
+
+void ll_to_utm_ups(short ellipsoidID, const double lat, const double lon,
+ double *utmNorthing, double *utmEasting, char* utmZone, int utmZoneLength);
+void utm_ups_to_ll(short ellipsoidID, const double utmNorthing, const double utmEasting,
+ const char* utmZone, double *lat, double *lon);
+char utm_letter_designator(double lat, double lon);
+
+
diff --git a/src/db.c b/src/db.c
new file mode 100644
index 0000000..8b09df9
--- /dev/null
+++ b/src/db.c
@@ -0,0 +1,19490 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: db.c,v 1.663 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+/* Note: the header file for db.c should be called db.h,
+ * but is named database.h to avoid conflicts with the
+ * Berkeley DB package.
+ */
+
+// NOTE: decode_info_field() is a good place to start for decoding.
+
+
+// Used only for special debugging of message/station expiration.
+// Leave commented out for normal operation.
+//#define EXPIRE_DEBUG
+#define DEBUG_MESSAGE_REMOVE_CYCLE 15
+#define DEBUG_STATION_REMOVE_CYCLE 15
+#define DEBUG_MESSAGE_REMOVE 600
+#define DEBUG_STATION_REMOVE 600
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <math.h>
+
+#include <Xm/XmAll.h>
+
+#include "xastir.h"
+#include "main.h"
+#include "draw_symbols.h"
+#include "alert.h"
+#include "util.h"
+#include "bulletin_gui.h"
+#include "fcc_data.h"
+#include "geo.h"
+#include "gps.h"
+#include "rac_data.h"
+#include "interface.h"
+#include "maps.h"
+#include "wx.h"
+#include "igate.h"
+#include "list_gui.h"
+#include "objects.h"
+#include "track_gui.h"
+#include "xa_config.h"
+#include "x_spider.h"
+#include "db_gis.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+
+#define STATION_REMOVE_CYCLE 300 /* check station remove in seconds (every 5 minutes) */
+#define MESSAGE_REMOVE_CYCLE 600 /* check message remove in seconds (every 10 minutes) */
+#define IN_VIEW_MIN 600l /* margin for off-screen stations, with possible trails on screen, in minutes */
+#define TRAIL_POINT_MARGIN 30l /* margin for off-screen trails points, for segment to be drawn, in minutes */
+#define TRAIL_MAX_SPEED 900 /* max. acceptible speed for drawing trails, in mph */
+#define MY_TRAIL_COLOR 0x16 /* trail color index reserved for my station */
+#define TRAIL_ECHO_TIME 30 /* check for delayed echos during last 30 minutes */
+/* MY_TRAIL_DIFF_COLOR changed to user configurable my_trail_diff_color */
+
+
+/////////////////////////////////////
+#define GUARD_SIZE 10
+char GUARD_BAND_THREE[GUARD_SIZE];
+/////////////////////////////////////
+
+extern XmFontList fontlist1; // Menu/System fontlist
+
+// Station Info
+Widget db_station_popup = (Widget)NULL;
+char *db_station_info_callsign = NULL;
+Pixmap SiS_icon0, SiS_icon;
+Widget SiS_symb;
+Widget station_list;
+Widget button_store_track;
+int station_data_auto_update = 0;
+
+
+// Used to store all the calls we might "relay" digipeat by.
+// Separated by commas. Up to 50 callsigns of 9 chars each plus
+// comma delimiters.
+char relay_digipeater_calls[10*MAX_RELAY_DIGIPEATER_CALLS];
+
+Widget si_text;
+Widget db_station_info = (Widget)NULL;
+
+static xastir_mutex db_station_info_lock;
+static xastir_mutex db_station_popup_lock;
+
+void redraw_symbols(Widget w);
+int delete_weather(DataRow *fill);
+int delete_multipoints(DataRow *fill);
+void Station_data_destroy_track(Widget widget, XtPointer clientData, XtPointer callData);
+void my_station_gps_change(char *pos_long, char *pos_lat, char *course, char *speed, char speedu, char *alt, char *sats);
+void station_shortcuts_update_function(int hash_key, DataRow *p_rem);
+int position_on_extd_screen(long lat, long lon);
+
+int extract_speed_course(char *info, char *speed, char *course);
+int extract_bearing_NRQ(char *info, char *bearing, char *nrq);
+
+int skip_dupe_checking;
+int tracked_stations = 0; // A count variable used in debug code only
+void track_station(Widget w, char *call_tracked, DataRow *p_station);
+
+int new_message_data;
+time_t last_message_remove; // last time we did a check for message removing
+
+////////////////////////////////////
+char GUARD_BAND_FOUR[GUARD_SIZE];
+////////////////////////////////////
+
+//// Save most recent 100 packets in an array called packet_data_string[]
+#define MAX_PACKET_DATA_DISPLAY 100
+int redraw_on_new_packet_data;
+char packet_data_string[MAX_PACKET_DATA_DISPLAY][MAX_LINE_SIZE+1];
+int first_line=-1;
+int next_line=0;
+int ncharsdel=0;
+int nlinesadd=0;
+
+///////////////////////////////////
+char GUARD_BAND_ONE[GUARD_SIZE];
+///////////////////////////////////
+
+int station_count; // number of stored stations
+int station_count_save = 0; // old copy of above
+DataRow *n_first; // pointer to first element in name sorted station list
+DataRow *n_last; // pointer to last element in name sorted station list
+DataRow *t_oldest; // pointer to first element in time sorted station list (oldest)
+DataRow *t_newest; // pointer to last element in time sorted station list (newest)
+time_t last_station_remove; // last time we did a check for station removing
+time_t last_sec,curr_sec; // for comparing if seconds in time have changed
+int next_time_sn; // time serial number for unique time index
+
+///////////////////////////////////
+char GUARD_BAND_TWO[GUARD_SIZE];
+///////////////////////////////////
+
+
+
+int emergency_distance_check = 1;
+float emergency_range = 280.0; // Default is 4hrs @ 70mph distance
+
+CADRow *CAD_list_head = NULL; // pointer to first element in CAD objects list
+
+void draw_trail(Widget w, DataRow *fill, int solid);
+void export_trail(DataRow *p_station); // export trail of one or all stations to xastir export file
+//void export_trail_as_kml(DataRow *p_station); // export trail of one or all stations to kml file
+
+int decoration_offset_x = 0;
+int decoration_offset_y = 0;
+int last_station_info_x = 0;
+int last_station_info_y = 0;
+int fcc_lookup_pushed = 0;
+int rac_lookup_pushed = 0;
+
+time_t last_object_check = 0; // Used to determine when to re-transmit objects/items
+
+time_t last_emergency_time = 0;
+char last_emergency_callsign[MAX_CALLSIGN+1];
+int st_direct_timeout = 60 * 60; // 60 minutes.
+
+// Used in search_station_name() function. Shortcuts into the
+// station list based on the least-significant 7 bits of the first
+// two letters of the callsign/object name.
+DataRow *station_shortcuts[16384];
+
+// used to time aloha calculations
+static time_t aloha_time = 0;
+static time_t aloha_status_time = 0;
+static double aloha_radius=-1; // in miles
+static aloha_stats the_aloha_stats;
+// calculate every half hour, display in status line every 5 minutes
+#define ALOHA_CALC_INTERVAL 1800
+#define ALOHA_STATUS_INTERVAL 300
+
+int process_emergency_packet_again = 0;
+
+
+
+
+
+void db_init(void)
+{
+ int ii;
+
+
+ // Set up guard bands around important global pointers
+ for (ii = 0; ii < GUARD_SIZE; ii++) {
+ GUARD_BAND_ONE[ii] = 0x00;
+ GUARD_BAND_TWO[ii] = 0x00;
+ GUARD_BAND_THREE[ii] = 0x00;
+ GUARD_BAND_FOUR[ii] = 0x00;
+ }
+
+ init_critical_section( &db_station_info_lock );
+ init_critical_section( &db_station_popup_lock );
+ last_emergency_callsign[0] = '\0';
+
+ // Seed the random number generator
+ srand(1);
+}
+
+
+
+
+
+/////////////////////////////////// Utilities ////////////////////////////////////////////////////
+
+
+
+// Variable used for below test code
+//int we7u_count = 50;
+
+
+
+// Check guard bands around important global pointers.
+//
+// These guard bands are initialized in db.c:db_init()
+//
+// Returns: 0 if ok
+// 1 if guard band has been tampered with
+//
+int check_guard_band(void) {
+ int ii;
+
+ for (ii = 0; ii < GUARD_SIZE; ii++) {
+ if (GUARD_BAND_ONE[ii] != 0x00
+ || GUARD_BAND_TWO[ii] != 0x00
+ || GUARD_BAND_THREE[ii] != 0x00
+ || GUARD_BAND_FOUR[ii] != 0x00) {
+
+ if (GUARD_BAND_ONE[ii] != 0x00)
+ fprintf(stderr, "WARNING: GUARD_BAND_ONE was corrupted!\n");
+
+ if (GUARD_BAND_TWO[ii] != 0x00)
+ fprintf(stderr, "WARNING: GUARD_BAND_TWO was corrupted!\n");
+
+ if (GUARD_BAND_THREE[ii] != 0x00)
+ fprintf(stderr, "WARNING: GUARD_BAND_THREE was corrupted!\n");
+
+ if (GUARD_BAND_FOUR[ii] != 0x00)
+ fprintf(stderr, "WARNING: GUARD_BAND_FOUR was corrupted!\n");
+
+fprintf(stderr, "Previous incoming line was: %s\n", incoming_data_copy_previous);
+fprintf(stderr, " Last incoming line was: %s\n", incoming_data_copy);
+
+abort(); // Cause immediate exit to aid in debugging
+
+ return(1);
+ }
+ }
+
+// Test code
+/*
+if (we7u_count-- <= 0) {
+ GUARD_BAND_ONE[0] = 0x01;
+ GUARD_BAND_TWO[0] = 0x01;
+ GUARD_BAND_THREE[0] = 0x01;
+ GUARD_BAND_FOUR[0] = 0x01;
+}
+*/
+
+ return(0);
+}
+
+
+
+
+
+/*
+ * Check whether callsign is mine. "exact == 1" checks the SSID
+ * for a match as well. "exact == 0" checks only the base
+ * callsign.
+ */
+int is_my_call(char *call, int exact) {
+ char *p_del;
+ int ok;
+
+
+ // U.S. special-event callsigns can be as short as three
+ // characters, any less and we don't have a valid callsign. We
+ // don't check for that restriction here though.
+
+ if (exact) {
+ // We're looking for an exact match
+ ok = (int)( !strcmp(call,my_callsign) );
+ //fprintf(stderr,"My exact call found: %s\n",call);
+ }
+ else {
+ // We're looking for a similar match. Compare only up to
+ // the '-' in each (if present).
+ int len1,len2;
+
+ p_del = index(call,'-');
+ if (p_del == NULL)
+ len1 = (int)strlen(call);
+ else
+ len1 = p_del - call;
+
+ p_del = index(my_callsign,'-');
+ if (p_del == NULL)
+ len2 = (int)strlen(my_callsign);
+ else
+ len2 = p_del - my_callsign;
+
+ ok = (int)(len1 == len2 && !strncmp(call,my_callsign,(size_t)len1));
+ //fprintf(stderr,"My base call found: %s\n",call);
+ }
+
+ return(ok);
+}
+
+
+
+
+
+int is_my_station(DataRow *p_station) {
+ // if station is owned by me (including SSID)
+ return(p_station->flag & ST_MYSTATION);
+}
+
+
+
+
+
+int is_my_object_item(DataRow *p_station) {
+ // If object/item is owned by me (including SSID)
+ return(p_station->flag & ST_MYOBJITEM);
+}
+
+
+
+
+
+/*
+ * Change map position if neccessary while tracking a station
+ * we call it with defined station call and position
+ */
+int is_tracked_station(char *call_sign) {
+ int found;
+ char call_find[MAX_CALLSIGN+1];
+ int ii;
+ int call_len;
+
+ if (!track_station_on)
+ return(0);
+
+ call_len = 0;
+ found = 0;
+
+ if (!track_case) {
+ for ( ii = 0; ii < (int)strlen(tracking_station_call); ii++ ) {
+ if (isalpha((int)tracking_station_call[ii]))
+ call_find[ii] = toupper((int)tracking_station_call[ii]);
+ else
+ call_find[ii] = tracking_station_call[ii];
+ }
+ call_find[ii] = '\0';
+ }
+ else {
+ xastir_snprintf(call_find,
+ sizeof(call_find),
+ "%s",
+ tracking_station_call);
+ }
+
+ if (debug_level & 256) {
+ fprintf(stderr,"is_tracked_station(): CALL %s %s %s\n",
+ tracking_station_call,
+ call_find, call_sign);
+ }
+
+ if (track_match) {
+ if (strcmp(call_find,call_sign) == 0) { // we want an exact match
+ found = 1;
+ }
+ }
+ else {
+ found = 0;
+ call_len = (int)(strlen(call_sign) - strlen(call_find));
+ if (strlen(call_find) <= strlen(call_sign)) {
+ found = 1;
+ for ( ii = 0; ii <= call_len; ii++ ) {
+ if (!track_case) {
+ if (!strncasecmp(call_find,call_sign+ii,strlen(call_find)) == 0) {
+ found = 0; // Found a mis-match
+ }
+ }
+ else {
+ if (!strncmp(call_find,call_sign+ii,strlen(call_find)) == 0) {
+ found = 0;
+ }
+ }
+ }
+ }
+ }
+ return(found);
+}
+
+
+
+
+
+/////////////////////////////////////////// Messages ///////////////////////////////////////////
+
+static long *msg_index;
+static long msg_index_end;
+static long msg_index_max;
+
+static Message *msg_data; // Array containing all messages,
+ // including ones we've transmitted (via
+ // loopback in the code)
+
+time_t last_message_update = 0;
+ack_record *ack_list_head = NULL; // Head of linked list storing most recent ack's
+int satellite_ack_mode;
+
+
+// How often update_messages() will run, in seconds.
+// This is necessary because routines like UpdateTime()
+// call update_messages() VERY OFTEN.
+//
+// Actually, we just changed the code around so that we only call
+// update_messages() with the force option, and only when we receive a
+// message. message_update_delay is no longer used, and we don't call
+// update_messages() from UpdateTime() anymore.
+static int message_update_delay = 300;
+
+
+
+
+
+// Saves latest ack in a linked list. We need this value in order
+// to use Reply/Ack protocol when sending out messages.
+void store_most_recent_ack(char *callsign, char *ack) {
+ ack_record *p;
+ int done = 0;
+ char call[MAX_CALLSIGN+1];
+ char new_ack[5+1];
+
+ xastir_snprintf(call,
+ sizeof(call),
+ "%s",
+ callsign);
+ remove_trailing_spaces(call);
+
+ // Get a copy of "ack". We might need to change it.
+ xastir_snprintf(new_ack,
+ sizeof(new_ack),
+ "%s",
+ ack);
+
+ // If it's more than 2 characters long, we can't use it for
+ // Reply/Ack protocol as there's only space enough for two.
+ // In this case we need to make sure that we blank out any
+ // former ack that was 1 or 2 characters, so that communications
+ // doesn't stop.
+ if ( strlen(new_ack) > 2 ) {
+ // It's too long, blank it out so that gets saved as "",
+ // which will overwrite any previously saved ack's that were
+ // short enough to use.
+ new_ack[0] = '\0';
+ }
+
+ // Search for matching callsign through linked list
+ p = ack_list_head;
+ while ( !done && (p != NULL) ) {
+ if (strcasecmp(call,p->callsign) == 0) {
+ done++;
+ }
+ else {
+ p = p->next;
+ }
+ }
+
+ if (done) { // Found it. Update the ack field.
+ //fprintf(stderr,"Found callsign %s on recent ack list, Old:%s, New:%s\n",call,p->ack,new_ack);
+ xastir_snprintf(p->ack,sizeof(p->ack),"%s",new_ack);
+ }
+ else { // Not found. Add a new record to the beginning of the
+ // list.
+ //fprintf(stderr,"New callsign %s, adding to list. Ack: %s\n",call,new_ack);
+ p = (ack_record *)malloc(sizeof(ack_record));
+ CHECKMALLOC(p);
+
+ xastir_snprintf(p->callsign,sizeof(p->callsign),"%s",call);
+ xastir_snprintf(p->ack,sizeof(p->ack),"%s",new_ack);
+ p->next = ack_list_head;
+ ack_list_head = p;
+ }
+}
+
+
+
+
+
+// Gets latest ack by callsign
+char *get_most_recent_ack(char *callsign) {
+ ack_record *p;
+ int done = 0;
+ char call[MAX_CALLSIGN+1];
+
+ xastir_snprintf(call,
+ sizeof(call),
+ "%s",
+ callsign);
+ remove_trailing_spaces(call);
+
+ // Search for matching callsign through linked list
+ p = ack_list_head;
+ while ( !done && (p != NULL) ) {
+ if (strcasecmp(call,p->callsign) == 0) {
+ done++;
+ }
+ else {
+ p = p->next;
+ }
+ }
+
+ if (done) { // Found it. Return pointer to ack string.
+ //fprintf(stderr,"Found callsign %s on linked list, returning ack: %s\n",call,p->ack);
+ return(&p->ack[0]);
+ }
+ else {
+ //fprintf(stderr,"Callsign %s not found\n",call);
+ return(NULL);
+ }
+}
+
+
+
+
+
+void init_message_data(void) { // called at start of main
+
+ new_message_data = 0;
+ last_message_remove = sec_now();
+}
+
+
+
+
+
+#ifdef MSG_DEBUG
+void msg_clear_data(Message *clear) {
+ int size;
+ int i;
+ unsigned char *data_ptr;
+
+ data_ptr = (unsigned char *)clear;
+ size=sizeof(Message);
+ for(i=0;i<size;i++)
+ *data_ptr++ = 0;
+}
+
+
+
+
+
+void msg_copy_data(Message *to, Message *from) {
+ int size;
+ int i;
+ unsigned char *data_ptr;
+ unsigned char *data_ptr_from;
+
+ data_ptr = (unsigned char *)to;
+ data_ptr_from = (unsigned char *)from;
+ size=sizeof(Message);
+ for(i=0;i<size;i++)
+ *data_ptr++ = *data_ptr_from++;
+}
+#endif /* MSG_DEBUG */
+
+
+
+
+
+// Returns 1 if it's time to update the messages again
+int message_update_time (void) {
+ if ( sec_now() > (last_message_update + message_update_delay) )
+ return(1);
+ else
+ return(0);
+}
+
+
+
+
+
+int msg_comp_active(const void *a, const void *b) {
+ char temp_a[MAX_CALLSIGN+MAX_CALLSIGN+MAX_MESSAGE_ORDER+2];
+ char temp_b[MAX_CALLSIGN+MAX_CALLSIGN+MAX_MESSAGE_ORDER+2];
+
+ xastir_snprintf(temp_a, sizeof(temp_a), "%c%s%s%s",
+ ((Message*)a)->active, ((Message*)a)->call_sign,
+ ((Message*)a)->from_call_sign,
+ ((Message*)a)->seq);
+ xastir_snprintf(temp_b, sizeof(temp_b), "%c%s%s%s",
+ ((Message*)b)->active, ((Message*)b)->call_sign,
+ ((Message*)b)->from_call_sign,
+ ((Message*)b)->seq);
+
+ return(strcmp(temp_a, temp_b));
+}
+
+
+
+
+
+int msg_comp_data(const void *a, const void *b) {
+ char temp_a[MAX_CALLSIGN+MAX_CALLSIGN+MAX_MESSAGE_ORDER+1];
+ char temp_b[MAX_CALLSIGN+MAX_CALLSIGN+MAX_MESSAGE_ORDER+1];
+
+ xastir_snprintf(temp_a, sizeof(temp_a), "%s%s%s",
+ msg_data[*(long*)a].call_sign, msg_data[*(long *)a].from_call_sign,
+ msg_data[*(long *)a].seq);
+ xastir_snprintf(temp_b, sizeof(temp_b), "%s%s%s", msg_data[*(long*)b].call_sign,
+ msg_data[*(long *)b].from_call_sign, msg_data[*(long *)b].seq);
+
+ return(strcmp(temp_a, temp_b));
+}
+
+
+
+
+
+void msg_input_database(Message *m_fill) {
+ void *m_ptr;
+ long i;
+
+ if (msg_index_end == msg_index_max) {
+ for (i = 0; i < msg_index_end; i++) {
+
+ // Check for a record that is marked RECORD_NOTACTIVE.
+ // If found, use that record instead of malloc'ing a new
+ // one.
+ if (msg_data[msg_index[i]].active == RECORD_NOTACTIVE) {
+
+ // Found an unused record. Fill it in.
+ memcpy(&msg_data[msg_index[i]], m_fill, sizeof(Message));
+
+// Sort msg_data
+ qsort(msg_data, (size_t)msg_index_end, sizeof(Message), msg_comp_active);
+
+ for (i = 0; i < msg_index_end; i++) {
+ msg_index[i] = i;
+ if (msg_data[i].active == RECORD_NOTACTIVE) {
+ msg_index_end = i;
+ break;
+ }
+ }
+
+// Sort msg_index
+ qsort(msg_index, (size_t)msg_index_end, sizeof(long *), msg_comp_data);
+
+ // All done with this message.
+ return;
+ }
+ }
+
+ // Didn't find free message record. Fetch some more space.
+ // Get more msg_data space.
+ m_ptr = realloc(msg_data, (msg_index_max+MSG_INCREMENT)*sizeof(Message));
+ if (m_ptr) {
+ msg_data = m_ptr;
+
+ // Get more msg_index space
+ m_ptr = realloc(msg_index, (msg_index_max+MSG_INCREMENT)*sizeof(Message *));
+ if (m_ptr) {
+ msg_index = m_ptr;
+ msg_index_max += MSG_INCREMENT;
+
+//fprintf(stderr, "Max Message Array: %ld\n", msg_index_max);
+
+ }
+ else {
+ XtWarning("Unable to allocate more space for message index.\n");
+ }
+ }
+ else {
+ XtWarning("Unable to allocate more space for message database.\n");
+ }
+ }
+ if (msg_index_end < msg_index_max) {
+ msg_index[msg_index_end] = msg_index_end;
+
+ // Copy message data into new message record.
+ memcpy(&msg_data[msg_index_end++], m_fill, sizeof(Message));
+
+// Sort msg_index
+ qsort(msg_index, (size_t)msg_index_end, sizeof(long *), msg_comp_data);
+ }
+}
+
+
+
+
+
+// Does a binary search through a sorted message database looking
+// for a string match.
+//
+// If two or more messages match, this routine _should_ return the
+// message with the latest timestamp. This will ensure that earlier
+// messages don't get mistaken for current messages, for the case
+// where the remote station did a restart and is using the same
+// sequence numbers over again.
+//
+long msg_find_data(Message *m_fill) {
+ long record_start, record_mid, record_end, return_record, done;
+ char tempfile[MAX_CALLSIGN+MAX_CALLSIGN+MAX_MESSAGE_ORDER+1];
+ char tempfill[MAX_CALLSIGN+MAX_CALLSIGN+MAX_MESSAGE_ORDER+1];
+
+
+ xastir_snprintf(tempfill, sizeof(tempfill), "%s%s%s",
+ m_fill->call_sign,
+ m_fill->from_call_sign,
+ m_fill->seq);
+
+ return_record = -1L;
+ if (msg_index && msg_index_end >= 1) {
+ /* more than one record */
+ record_start=0L;
+ record_end = (msg_index_end - 1);
+ record_mid=(record_end-record_start)/2;
+
+ done=0;
+ while (!done) {
+
+ /* get data for record start */
+ xastir_snprintf(tempfile, sizeof(tempfile), "%s%s%s",
+ msg_data[msg_index[record_start]].call_sign,
+ msg_data[msg_index[record_start]].from_call_sign,
+ msg_data[msg_index[record_start]].seq);
+
+ if (strcmp(tempfill, tempfile) < 0) {
+ /* filename comes before */
+ /*fprintf(stderr,"Before No data found!!\n");*/
+ done=1;
+ break;
+ }
+ else { /* get data for record end */
+
+ xastir_snprintf(tempfile, sizeof(tempfile), "%s%s%s",
+ msg_data[msg_index[record_end]].call_sign,
+ msg_data[msg_index[record_end]].from_call_sign,
+ msg_data[msg_index[record_end]].seq);
+
+ if (strcmp(tempfill,tempfile)>=0) { /* at end or beyond */
+ if (strcmp(tempfill, tempfile) == 0) {
+ return_record = record_end;
+//fprintf(stderr,"record %ld",return_record);
+ }
+
+ done=1;
+ break;
+ }
+ else if ((record_mid == record_start) || (record_mid == record_end)) {
+ /* no mid for compare check to see if in the middle */
+ done=1;
+ xastir_snprintf(tempfile, sizeof(tempfile), "%s%s%s",
+ msg_data[msg_index[record_mid]].call_sign,
+ msg_data[msg_index[record_mid]].from_call_sign,
+ msg_data[msg_index[record_mid]].seq);
+ if (strcmp(tempfill,tempfile)==0) {
+ return_record = record_mid;
+//fprintf(stderr,"record: %ld",return_record);
+ }
+ }
+ }
+ if (!done) { /* get data for record mid */
+ xastir_snprintf(tempfile, sizeof(tempfile), "%s%s%s",
+ msg_data[msg_index[record_mid]].call_sign,
+ msg_data[msg_index[record_mid]].from_call_sign,
+ msg_data[msg_index[record_mid]].seq);
+
+ if (strcmp(tempfill, tempfile) == 0) {
+ return_record = record_mid;
+//fprintf(stderr,"record %ld",return_record);
+ done = 1;
+ break;
+ }
+
+ if(strcmp(tempfill, tempfile)<0)
+ record_end = record_mid;
+ else
+ record_start = record_mid;
+
+ record_mid = record_start+(record_end-record_start)/2;
+ }
+ }
+ }
+ return(return_record);
+}
+
+
+
+
+
+void msg_replace_data(Message *m_fill, long record_num) {
+ memcpy(&msg_data[msg_index[record_num]], m_fill, sizeof(Message));
+}
+
+
+
+
+
+void msg_get_data(Message *m_fill, long record_num) {
+ memcpy(m_fill, &msg_data[msg_index[record_num]], sizeof(Message));
+}
+
+
+
+
+
+void msg_update_ack_stamp(long record_num) {
+
+ //fprintf(stderr,"Attempting to update ack stamp: %ld\n",record_num);
+ if ( (record_num >= 0) && (record_num < msg_index_end) ) {
+ msg_data[msg_index[record_num]].last_ack_sent = sec_now();
+ //fprintf(stderr,"Ack stamp: %ld\n",msg_data[msg_index[record_num]].last_ack_sent);
+ }
+ //fprintf(stderr,"\n\n\n*** Record: %ld ***\n\n\n",record_num);
+}
+
+
+
+
+
+// Called when we receive an ACK. Sets the "acked" field in a
+// Message which gets rid of the highlighting in the Send Message
+// dialog for that message line. This lets us know which messages
+// have been acked and which have not. If timeout is non-zero, then
+// set acked to 2: We use this in update_messages() to flag that
+// "*TIMEOUT*" should prefix the string. If cancelled is non-zero,
+// set acked to 3: We use this in update_messages() to flag that
+// "*CANCELLED*" should prefix the string.
+//
+void msg_record_ack(char *to_call_sign,
+ char *my_call,
+ char *seq,
+ int timeout,
+ int cancel) {
+ Message m_fill;
+ long record;
+ int do_update = 0;
+
+ if (debug_level & 1) {
+ fprintf(stderr,"Recording ack for message to: %s, seq: %s\n",
+ to_call_sign,
+ seq);
+ }
+
+ // Find the corresponding message in msg_data[i], set the
+ // "acked" field to one.
+
+ substr(m_fill.call_sign, to_call_sign, MAX_CALLSIGN);
+ (void)remove_trailing_asterisk(m_fill.call_sign);
+
+ substr(m_fill.from_call_sign, my_call, MAX_CALLSIGN);
+ (void)remove_trailing_asterisk(m_fill.from_call_sign);
+
+ substr(m_fill.seq, seq, MAX_MESSAGE_ORDER);
+ (void)remove_trailing_spaces(m_fill.seq);
+ (void)remove_leading_spaces(m_fill.seq);
+
+ // Look for a message with the same to_call_sign, my_call,
+ // and seq number
+ record = msg_find_data(&m_fill);
+
+ if (record == -1L) { // No match yet, try another tactic.
+ if (seq[2] == '}' && strlen(seq) == 3) {
+
+ // Try it again without the trailing '}' character
+ m_fill.from_call_sign[2] = '\0';
+
+ // Look for a message with the same to_call_sign,
+ // my_call, and seq number (minus the trailing '}')
+ record = msg_find_data(&m_fill);
+ }
+ }
+
+ if(record != -1L) { // Found a match!
+ if (debug_level & 1) {
+ fprintf(stderr,"Found in msg db, updating acked field %d -> 1, seq %s, record %ld\n",
+ msg_data[msg_index[record]].acked,
+ seq,
+ record);
+ }
+ // Only cause an update if this is the first ack. This
+ // reduces dialog "flashing" a great deal
+ if ( msg_data[msg_index[record]].acked == 0 ) {
+
+ // Check for my callsign (including SSID). If found,
+ // update any open message dialogs
+ if (is_my_call(msg_data[msg_index[record]].from_call_sign, 1) ) {
+
+ //fprintf(stderr,"From: %s\tTo: %s\n",
+ // msg_data[msg_index[record]].from_call_sign,
+ // msg_data[msg_index[record]].call_sign);
+
+ do_update++;
+ }
+ }
+ else { // This message has already been acked.
+ }
+
+ if (cancel)
+ msg_data[msg_index[record]].acked = (char)3;
+ else if (timeout)
+ msg_data[msg_index[record]].acked = (char)2;
+ else
+ msg_data[msg_index[record]].acked = (char)1;
+
+ // Set the interval to zero so that we don't display it
+ // anymore in the dialog. Same for tries.
+ msg_data[msg_index[record]].interval = 0;
+ msg_data[msg_index[record]].tries = 0;
+
+ if (debug_level & 1) {
+ fprintf(stderr,"Found in msg db, updating acked field %d -> 1, seq %s, record %ld\n\n",
+ msg_data[msg_index[record]].acked,
+ seq,
+ record);
+ }
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"Matching message not found\n");
+ }
+
+ if (do_update) {
+
+ update_messages(1); // Force an update
+
+ // Call check_popup_messages() here in order to pop up any
+ // closed Send Message dialogs. For first ack's or
+ // CANCELLED messages it is less important, but for TIMEOUT
+ // messages it is very important.
+ //
+ (void)check_popup_window(m_fill.call_sign, 2); // Calls update_messages()
+ }
+}
+
+
+
+
+
+// Called when we receive a REJ packet (reject). Sets the "acked"
+// field in a Message to 4 to indicate that the message has been
+// rejected by the remote station. This gets rid of the
+// highlighting in the Send Message dialog for that message line.
+// This lets us know which messages have been rejected and which
+// have not. We use this in update_messages() to flag that
+// "*REJECTED*" should prefix the string.
+//
+// The most common source of REJ packets would be from sending to a
+// D700A who's buffers are full, so that it can't take another
+// message.
+//
+void msg_record_rej(char *to_call_sign,
+ char *my_call,
+ char *seq) {
+ Message m_fill;
+ long record;
+ int do_update = 0;
+
+ if (debug_level & 1) {
+ fprintf(stderr,"Recording rej for message to: %s, seq: %s\n",
+ to_call_sign,
+ seq);
+ }
+
+ // Find the corresponding message in msg_data[i], set the
+ // "acked" field to four.
+
+ substr(m_fill.call_sign, to_call_sign, MAX_CALLSIGN);
+ (void)remove_trailing_asterisk(m_fill.call_sign);
+
+ substr(m_fill.from_call_sign, my_call, MAX_CALLSIGN);
+ (void)remove_trailing_asterisk(m_fill.from_call_sign);
+
+ substr(m_fill.seq, seq, MAX_MESSAGE_ORDER);
+ (void)remove_trailing_spaces(m_fill.seq);
+ (void)remove_leading_spaces(m_fill.seq);
+
+ // Look for a message with the same to_call_sign, my_call,
+ // and seq number
+ record = msg_find_data(&m_fill);
+
+ if (record == -1L) { // No match yet, try another tactic.
+ if (seq[2] == '}' && strlen(seq) == 3) {
+
+ // Try it again without the trailing '}' character
+ m_fill.from_call_sign[2] = '\0';
+
+ // Look for a message with the same to_call_sign,
+ // my_call, and seq number (minus the trailing '}')
+ record = msg_find_data(&m_fill);
+ }
+ }
+
+ if(record != -1L) { // Found a match!
+ if (debug_level & 1) {
+ fprintf(stderr,"Found in msg db, updating acked field %d -> 4, seq %s, record %ld\n",
+ msg_data[msg_index[record]].acked,
+ seq,
+ record);
+ }
+ // Only cause an update if this is the first rej. This
+ // reduces dialog "flashing" a great deal
+ if ( msg_data[msg_index[record]].acked == 0 ) {
+
+ // Check for my callsign (including SSID). If found,
+ // update any open message dialogs
+ if (is_my_call(msg_data[msg_index[record]].from_call_sign, 1) ) {
+
+ //fprintf(stderr,"From: %s\tTo: %s\n",
+ // msg_data[msg_index[record]].from_call_sign,
+ // msg_data[msg_index[record]].call_sign);
+
+ do_update++;
+ }
+ }
+ else { // This message has already been acked.
+ }
+
+ // Actually record the REJ here
+ msg_data[msg_index[record]].acked = (char)4;
+
+ // Set the interval to zero so that we don't display it
+ // anymore in the dialog. Same for tries.
+ msg_data[msg_index[record]].interval = 0;
+ msg_data[msg_index[record]].tries = 0;
+
+ if (debug_level & 1) {
+ fprintf(stderr,"Found in msg db, updating acked field %d -> 4, seq %s, record %ld\n\n",
+ msg_data[msg_index[record]].acked,
+ seq,
+ record);
+ }
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"Matching message not found\n");
+ }
+
+ if (do_update) {
+
+ update_messages(1); // Force an update
+
+ // Call check_popup_messages() here in order to pop up any
+ // closed Send Message dialogs. For first ack's or
+ // CANCELLED messages it is less important, but for TIMEOUT
+ // messages it is very important.
+ //
+ (void)check_popup_window(m_fill.call_sign, 2); // Calls update_messages()
+ }
+}
+
+
+
+
+
+// Called from check_and_transmit_messages(). Updates the interval
+// field in our message record for the message currently being
+// transmitted. We'll use this in the Send Message dialog to
+// display the current message interval.
+//
+void msg_record_interval_tries(char *to_call_sign,
+ char *my_call,
+ char *seq,
+ time_t interval,
+ int tries) {
+ Message m_fill;
+ long record;
+
+ if (debug_level & 1) {
+ fprintf(stderr,"Recording interval for message to: %s, seq: %s\n",
+ to_call_sign,
+ seq);
+ }
+
+ // Find the corresponding message in msg_data[i]
+
+ substr(m_fill.call_sign, to_call_sign, MAX_CALLSIGN);
+ (void)remove_trailing_asterisk(m_fill.call_sign);
+
+ substr(m_fill.from_call_sign, my_call, MAX_CALLSIGN);
+ (void)remove_trailing_asterisk(m_fill.from_call_sign);
+
+ substr(m_fill.seq, seq, MAX_MESSAGE_ORDER);
+ (void)remove_trailing_spaces(m_fill.seq);
+ (void)remove_leading_spaces(m_fill.seq);
+
+ // Look for a message with the same to_call_sign, my_call,
+ // and seq number
+ record = msg_find_data(&m_fill);
+ if(record != -1L) { // Found a match!
+ if (debug_level & 1) {
+ fprintf(stderr,
+ "Found in msg db, updating interval field %ld -> 1, seq %s, record %ld\n",
+ (long)msg_data[msg_index[record]].interval,
+ seq,
+ record);
+ }
+
+ msg_data[msg_index[record]].interval = interval;
+ msg_data[msg_index[record]].tries = tries;
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"Matching message not found\n");
+ }
+
+ update_messages(1); // Force an update
+}
+
+
+
+
+
+// Returns: time_t for last_ack_sent
+// -1 if the message doesn't pass our tests
+// 0 if it is a new message.
+//
+// Also returns the record number found if not passed a NULL pointer
+// in record_out or -1L if it's a new record.
+//
+time_t msg_data_add(char *call_sign, char *from_call, char *data,
+ char *seq, char type, char from, long *record_out) {
+ Message m_fill;
+ long record;
+ char time_data[MAX_TIME];
+ int do_msg_update = 0;
+ time_t last_ack_sent;
+ int distance = -1;
+ char temp[10];
+ int group_message = 0;
+
+
+ if (debug_level & 1)
+ fprintf(stderr,"msg_data_add start\n");
+//fprintf(stderr,"from:%s, to:%s, seq:%s\n", from_call, call_sign, seq);
+
+ // Set the default output condition. We'll change this later if
+ // we need to.
+ if (record_out != NULL)
+ *record_out = -1l;
+
+ // Check for some reasonable string in call_sign parameter
+ if (call_sign == NULL || strlen(call_sign) == 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"msg_data_add():call_sign was NULL or empty, exiting\n");
+ return((time_t)-1l);
+ }
+//else
+//fprintf(stderr,"msg_data_add():call_sign: %s\n", call_sign);
+
+ if ( (data != NULL) && (strlen(data) > MAX_MESSAGE_LENGTH) ) {
+ if (debug_level & 2)
+ fprintf(stderr,"msg_data_add: Message length too long\n");
+ return((time_t)-1l);
+ }
+
+ substr(m_fill.call_sign, call_sign, MAX_CALLSIGN);
+ (void)remove_trailing_asterisk(m_fill.call_sign);
+
+ substr(m_fill.from_call_sign, from_call, MAX_CALLSIGN);
+ (void)remove_trailing_asterisk(m_fill.call_sign);
+
+ substr(m_fill.seq, seq, MAX_MESSAGE_ORDER);
+ (void)remove_trailing_spaces(m_fill.seq);
+ (void)remove_leading_spaces(m_fill.seq);
+
+// If the sequence number is blank, then it may have been a query,
+// directed query, or group message. Assume it is a new message in
+// each case and add it.
+
+ if (seq[0] != '\0') { // Normal station->station messaging or
+ // bulletins
+ // Look for a message with the same call_sign,
+ // from_call_sign, and seq number
+ record = msg_find_data(&m_fill);
+//fprintf(stderr,"RECORD %ld \n",record);
+//fprintf(stderr,"Normal station->station message\n");
+ }
+ else { // Group message/query/etc.
+ record = -1L;
+ group_message++; // Flag it as a group message
+//fprintf(stderr,"Group message/query/etc\n");
+ }
+ msg_clear_data(&m_fill);
+ if(record != -1L) { /* fill old data */
+ msg_get_data(&m_fill, record);
+ last_ack_sent = m_fill.last_ack_sent;
+ //fprintf(stderr,"Found: last_ack_sent: %ld\n",m_fill.last_ack_sent);
+
+ //fprintf(stderr,"Found a duplicate message. Updating fields, seq %s\n",seq);
+
+ // If message is different this time, do an update to the
+ // send message window and update the sec_heard field. The
+ // remote station must have restarted and is re-using the
+ // sequence numbers. What a pain!
+ if (strcmp(m_fill.message_line,data) != 0) {
+ m_fill.sec_heard = sec_now();
+ last_ack_sent = (time_t)0;
+//fprintf(stderr,"Message is different this time: Setting last_ack_sent to 0\n");
+
+ if (type != MESSAGE_BULLETIN) { // Not a bulletin
+ do_msg_update++;
+ }
+ }
+
+ // If message is the same, but the sec_heard field is quite
+ // old (more than 8 hours), the remote station must have
+ // restarted, is re-using the sequence numbers, and just
+ // happened to send the same message with the same sequence
+ // number. Again, what a pain! Either that, or we
+ // connected to a spigot with a _really_ long queue!
+ if (m_fill.sec_heard < (sec_now() - (8 * 60 * 60) )) {
+ m_fill.sec_heard = sec_now();
+ last_ack_sent = (time_t)0;
+//fprintf(stderr,"Found >8hrs old: Setting last_ack_sent to 0\n");
+
+ if (type != MESSAGE_BULLETIN) { // Not a bulletin
+ do_msg_update++;
+ }
+ }
+
+ // Check for zero time
+ if (m_fill.sec_heard == (time_t)0) {
+ m_fill.sec_heard = sec_now();
+ fprintf(stderr,"Zero time on a previous message.\n");
+ }
+ }
+ else {
+ // Only do this if it's a new message. This keeps things
+ // more in sequence by not updating the time stamps
+ // constantly on old messages that don't get ack'ed.
+ m_fill.sec_heard = sec_now();
+ last_ack_sent = (time_t)0;
+ //fprintf(stderr,"New msg: Setting last_ack_sent to 0\n");
+
+ if (type != MESSAGE_BULLETIN) { // Not a bulletin
+//fprintf(stderr,"Found new message\n");
+ do_msg_update++; // Always do an update to the
+ // message window for new messages
+ }
+ }
+
+ /* FROM */
+ m_fill.data_via=from;
+ m_fill.active=RECORD_ACTIVE;
+ m_fill.type=type;
+ if (m_fill.heard_via_tnc != VIA_TNC)
+ m_fill.heard_via_tnc = (from == 'T') ? VIA_TNC : NOT_VIA_TNC;
+
+ distance = (int)(distance_from_my_station(from_call,temp) + 0.9999);
+
+ if (distance != 0) { // Have a posit from the sending station
+ m_fill.position_known = 1;
+ //fprintf(stderr,"Position known: %s\n",from_call);
+ }
+ else {
+ //fprintf(stderr,"Position not known: %s\n",from_call);
+ }
+
+ substr(m_fill.call_sign,call_sign,MAX_CALLSIGN);
+ (void)remove_trailing_asterisk(m_fill.call_sign);
+
+ substr(m_fill.from_call_sign,from_call,MAX_CALLSIGN);
+ (void)remove_trailing_asterisk(m_fill.from_call_sign);
+
+ // Update the message field
+ substr(m_fill.message_line,data,MAX_MESSAGE_LENGTH);
+
+ substr(m_fill.seq,seq,MAX_MESSAGE_ORDER);
+ (void)remove_trailing_spaces(m_fill.seq);
+ (void)remove_leading_spaces(m_fill.seq);
+
+ // Create a timestamp from the current time
+ xastir_snprintf(m_fill.packet_time,
+ sizeof(m_fill.packet_time),
+ "%s",
+ get_time(time_data));
+
+ if(record == -1L) { // No old record found
+ if (group_message)
+ m_fill.acked = 1; // Group msgs/queries need no ack
+ else
+ m_fill.acked = 0; // We can't have been acked yet
+
+ m_fill.interval = 0;
+ m_fill.tries = 0;
+
+ // We'll be sending an ack right away if this is a new
+ // message, so might as well set the time now so that we
+ // don't care about failing to set it in
+ // msg_update_ack_stamp due to the record number being -1.
+ m_fill.last_ack_sent = sec_now();
+
+ msg_input_database(&m_fill); // Create a new entry
+ //fprintf(stderr,"No record found: Setting last_ack_sent to sec_now()00\n");
+ }
+ else { // Old record found
+ //fprintf(stderr,"Replacing the message in the database, seq %s\n",seq);
+ msg_replace_data(&m_fill, record); // Copy fields from m_fill to record
+ }
+
+ /* display messages */
+ if (type == MESSAGE_MESSAGE)
+ all_messages(from,call_sign,from_call,data);
+
+ // Check for my callsign (including SSID). If found, update any
+ // open message dialogs
+ if ( is_my_call(m_fill.from_call_sign, 1)
+ || is_my_call(m_fill.call_sign, 1) ) {
+
+ if (do_msg_update) {
+ update_messages(1); // Force an update
+ }
+ }
+
+ if (debug_level & 1)
+ fprintf(stderr,"msg_data_add end\n");
+
+ // Return the important variables we'll need
+ if (record_out != NULL)
+ *record_out = record;
+
+//fprintf(stderr,"\nrecord_out:%ld record %ld\n",*record_out,record);
+ return(last_ack_sent);
+
+} // End of msg_data_add()
+
+
+
+
+
+// alert_data_add: Function which adds NWS weather alerts to the
+// alert hash.
+//
+// This function adds alerts directly to the alert hash, bypassing
+// the message list and associated message-scan functions.
+//
+void alert_data_add(char *call_sign, char *from_call, char *data,
+ char *seq, char type, char from) {
+ Message m_fill;
+ char time_data[MAX_TIME];
+ char user_base_dir[MAX_VALUE];
+
+ if (debug_level & 2)
+ fprintf(stderr,"alert_data_add start\n");
+
+
+ if (log_wx_alert_data && from != DATA_VIA_FILE) {
+ char temp_msg[MAX_MESSAGE_LENGTH+1];
+
+ // Attempt to reconstruct the original weather alert packet
+ // here, minus the path.
+ xastir_snprintf(temp_msg,
+ sizeof(temp_msg),
+ "%s>APRS::%-9s:%s{%s",
+ from_call,
+ call_sign,
+ data,
+ seq);
+ log_data( get_user_base_dir(LOGFILE_WX_ALERT, user_base_dir,
+ sizeof(user_base_dir)),
+ temp_msg);
+// fprintf(stderr, "%s\n", temp_msg);
+ }
+
+
+ if ( (data != NULL) && (strlen(data) > MAX_MESSAGE_LENGTH) ) {
+ if (debug_level & 2)
+ fprintf(stderr,"alert_data_add: Message length too long\n");
+ return;
+ }
+
+ substr(m_fill.call_sign, call_sign, MAX_CALLSIGN);
+ (void)remove_trailing_asterisk(m_fill.call_sign);
+
+ substr(m_fill.from_call_sign, from_call, MAX_CALLSIGN);
+ (void)remove_trailing_asterisk(m_fill.call_sign);
+
+ substr(m_fill.seq, seq, MAX_MESSAGE_ORDER);
+ (void)remove_trailing_spaces(m_fill.seq);
+ (void)remove_leading_spaces(m_fill.seq);
+
+ m_fill.sec_heard = sec_now();
+
+ /* FROM */
+ m_fill.data_via=from;
+ m_fill.active=RECORD_ACTIVE;
+ m_fill.type=type;
+
+ // We don't have a value filled in yet here!
+ //if (m_fill.heard_via_tnc != VIA_TNC)
+ m_fill.heard_via_tnc = (from == 'T') ? VIA_TNC : NOT_VIA_TNC;
+
+ substr(m_fill.call_sign,call_sign,MAX_CALLSIGN);
+ (void)remove_trailing_asterisk(m_fill.call_sign);
+
+ substr(m_fill.from_call_sign,from_call,MAX_CALLSIGN);
+ (void)remove_trailing_asterisk(m_fill.from_call_sign);
+
+ // Update the message field
+ substr(m_fill.message_line,data,MAX_MESSAGE_LENGTH);
+
+ substr(m_fill.seq,seq,MAX_MESSAGE_ORDER);
+ (void)remove_trailing_spaces(m_fill.seq);
+ (void)remove_leading_spaces(m_fill.seq);
+
+ // Create a timestamp from the current time
+ xastir_snprintf(m_fill.packet_time,
+ sizeof(m_fill.packet_time),
+ "%s",
+ get_time(time_data));
+
+ // Go try to add it to our alert hash. alert_build_list() will
+ // check for duplicates before adding it.
+
+ alert_build_list(&m_fill);
+
+ // This function fills in the Shapefile filename and index
+ // so that we can later draw it.
+ fill_in_new_alert_entries();
+
+ if (debug_level & 2)
+ fprintf(stderr,"alert_data_add end\n");
+
+} // End of alert_data_add()
+
+
+
+
+
+// What I'd like to do for the following routine: Use
+// XmTextGetInsertionPosition() or XmTextGetCursorPosition() to
+// find the last of the text. Could also save the position for
+// each SendMessage window. Compare the timestamps of messages
+// found with the last update time. If newer, then add them to
+// the end. This should stop the incessant scrolling.
+
+// Another idea, easier method: Create a buffer. Snag out the
+// messages from the array and sort by time. Put them into a
+// buffer. Figure out the length of the text widget, and append
+// the extra length of the buffer onto the end of the text widget.
+// Once the message data is turned into a linked list, it might
+// be sorted already by time, so this window will look better
+// anyway.
+
+// Calling update_messages with force == 1 will cause an update
+// no matter what message_update_time() says.
+void update_messages(int force) {
+ static XmTextPosition pos;
+ char temp1[MAX_CALLSIGN+1];
+ char temp2[500];
+ char stemp[20];
+ long i;
+ int mw_p;
+ char *temp_ptr;
+
+
+ if ( message_update_time() || force) {
+
+//fprintf(stderr,"update_messages()\n");
+
+ //fprintf(stderr,"Um %d\n",(int)sec_now() );
+
+ /* go through all mw_p's! */
+
+ // Perform this for each message window
+ for (mw_p=0; msg_index && mw_p < MAX_MESSAGE_WINDOWS; mw_p++) {
+ //pos=0;
+
+begin_critical_section(&send_message_dialog_lock, "db.c:update_messages" );
+
+ if (mw[mw_p].send_message_dialog!=NULL/* && mw[mw_p].message_group==1*/) {
+
+//fprintf(stderr,"\n");
+
+//fprintf(stderr,"found send_message_dialog\n");
+
+ // Clear the text from message window
+ XmTextReplace(mw[mw_p].send_message_text,
+ (XmTextPosition) 0,
+ XmTextGetLastPosition(mw[mw_p].send_message_text),
+ "");
+
+ // Snag the callsign you're dealing with from the message dialogue
+ if (mw[mw_p].send_message_call_data != NULL) {
+ temp_ptr = XmTextFieldGetString(mw[mw_p].send_message_call_data);
+ xastir_snprintf(temp1,
+ sizeof(temp1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ new_message_data--;
+ if (new_message_data<0)
+ new_message_data=0;
+
+ if(strlen(temp1)>0) { // We got a callsign from the dialog so
+ // create a linked list of the message indexes in time-sorted order
+
+ typedef struct _index_record {
+ int index;
+ time_t sec_heard;
+ struct _index_record *next;
+ } index_record;
+ index_record *head = NULL;
+ index_record *p_prev = NULL;
+ index_record *p_next = NULL;
+
+ // Allocate the first record (a dummy record)
+ head = (index_record *)malloc(sizeof(index_record));
+ CHECKMALLOC(head);
+
+ head->index = -1;
+ head->sec_heard = (time_t)0;
+ head->next = NULL;
+
+ (void)remove_trailing_spaces(temp1);
+ (void)to_upper(temp1);
+
+ pos = 0;
+ // Loop through looking for messages to/from
+ // that callsign (including SSID)
+ for (i = 0; i < msg_index_end; i++) {
+ if (msg_data[msg_index[i]].active == RECORD_ACTIVE
+ && (strcmp(temp1, msg_data[msg_index[i]].from_call_sign) == 0
+ || strcmp(temp1,msg_data[msg_index[i]].call_sign) == 0)
+ && (is_my_call(msg_data[msg_index[i]].from_call_sign, 1)
+ || is_my_call(msg_data[msg_index[i]].call_sign, 1)
+ || mw[mw_p].message_group ) ) {
+ int done = 0;
+
+ // Message matches our parameters so
+ // save the relevant data about the
+ // message in our linked list. Compare
+ // the sec_heard field to see whether
+ // we're higher or lower, and insert the
+ // record at the correct spot in the
+ // list. We end up with a time-sorted
+ // list.
+ p_prev = head;
+ p_next = p_prev->next;
+ while (!done && (p_next != NULL)) { // Loop until end of list or record inserted
+
+ //fprintf(stderr,"Looping, looking for insertion spot\n");
+
+ if (p_next->sec_heard <= msg_data[msg_index[i]].sec_heard) {
+ // Advance one record
+ p_prev = p_next;
+ p_next = p_prev->next;
+ }
+ else { // We found the correct insertion spot
+ done++;
+ }
+ }
+
+ //fprintf(stderr,"Inserting\n");
+
+ // Add the record in between p_prev and
+ // p_next, even if we're at the end of
+ // the list (in that case p_next will be
+ // NULL.
+ p_prev->next = (index_record *)malloc(sizeof(index_record));
+ CHECKMALLOC(p_prev->next);
+
+ p_prev->next->next = p_next; // Link to rest of records or NULL
+ p_prev->next->index = i;
+ p_prev->next->sec_heard = msg_data[msg_index[i]].sec_heard;
+// Remember to free this entire linked list before exiting the loop for
+// this message window!
+ }
+ }
+ // Done processing the entire list for this
+ // message window.
+
+ //fprintf(stderr,"Done inserting/looping\n");
+
+ if (head->next != NULL) { // We have messages to display
+ int done = 0;
+
+ //fprintf(stderr,"We have messages to display\n");
+
+ // Run through the linked list and dump the
+ // info out. It's now in time-sorted order.
+
+// Another optimization would be to keep a count of records added, then
+// later when we were dumping it out to the window, only dump the last
+// XX records out.
+
+ p_prev = head->next; // Skip the first dummy record
+ p_next = p_prev->next;
+ while (!done && (p_prev != NULL)) { // Loop until end of list
+ int j = p_prev->index; // Snag the index out of the record
+ char prefix[50];
+ char interval_str[50];
+ int offset = 22; // Offset for highlighting
+
+
+ //fprintf(stderr,"\nLooping through, reading messages\n");
+
+//fprintf(stderr,"acked: %d\n",msg_data[msg_index[j]].acked);
+
+ // Message matches so snag the important pieces into a string
+ xastir_snprintf(stemp, sizeof(stemp),
+ "%c%c/%c%c %c%c:%c%c",
+ msg_data[msg_index[j]].packet_time[0],
+ msg_data[msg_index[j]].packet_time[1],
+ msg_data[msg_index[j]].packet_time[2],
+ msg_data[msg_index[j]].packet_time[3],
+ msg_data[msg_index[j]].packet_time[8],
+ msg_data[msg_index[j]].packet_time[9],
+ msg_data[msg_index[j]].packet_time[10],
+ msg_data[msg_index[j]].packet_time[11]
+ );
+
+// Somewhere in here we appear to be losing the first message. It
+// doesn't get written to the window later in the QSO. Same for
+// closing the window and re-opening it, putting the same callsign
+// in and pressing "New Call" button. First message is missing.
+
+ // Label the message line with who sent it.
+ // If acked = 2 a timeout has occurred
+ // If acked = 3 a cancel has occurred
+ if (msg_data[msg_index[j]].acked == 2) {
+ xastir_snprintf(prefix,
+ sizeof(prefix),
+ "%s ",
+ langcode("WPUPMSB016") ); // "*TIMEOUT*"
+ }
+ else if (msg_data[msg_index[j]].acked == 3) {
+ xastir_snprintf(prefix,
+ sizeof(prefix),
+ "%s ",
+ langcode("WPUPMSB017") ); // "*CANCELLED*"
+ }
+ else if (msg_data[msg_index[j]].acked == 4) {
+ xastir_snprintf(prefix,
+ sizeof(prefix),
+ "%s ",
+ langcode("WPUPMSB018") ); // "*REJECTED*"
+ }
+ else prefix[0] = '\0';
+
+ if (msg_data[msg_index[j]].interval) {
+ xastir_snprintf(interval_str,
+ sizeof(interval_str),
+ ">%d/%lds",
+ msg_data[msg_index[j]].tries + 1,
+ (long)msg_data[msg_index[j]].interval);
+
+ // Don't highlight the interval
+ // value
+ offset = offset + strlen(interval_str);
+ }
+ else {
+ interval_str[0] = '\0';
+ }
+
+ xastir_snprintf(temp2, sizeof(temp2),
+ "%s %-9s%s>%s%s\n",
+ // Debug code. Trying to find sorting error
+ //"%ld %s %-9s>%s\n",
+ //msg_data[msg_index[j]].sec_heard,
+ stemp,
+ msg_data[msg_index[j]].from_call_sign,
+ interval_str,
+ prefix,
+ msg_data[msg_index[j]].message_line);
+
+//fprintf(stderr,"message: %s\n", msg_data[msg_index[j]].message_line);
+//fprintf(stderr,"update_messages: %s|%s", temp1, temp2);
+
+ if (debug_level & 2) fprintf(stderr,"update_messages: %s|%s\n", temp1, temp2);
+ // Replace the text from pos to pos+strlen(temp2) by the string "temp2"
+ if (mw[mw_p].send_message_text != NULL) {
+
+ // Insert the text at the end
+// XmTextReplace(mw[mw_p].send_message_text,
+// pos,
+// pos+strlen(temp2),
+// temp2);
+
+ XmTextInsert(mw[mw_p].send_message_text,
+ pos,
+ temp2);
+
+ // Set highlighting based on the
+ // "acked" field. Callsign
+ // match here includes SSID.
+//fprintf(stderr,"acked: %d\t",msg_data[msg_index[j]].acked);
+ if ( (msg_data[msg_index[j]].acked == 0) // Not acked yet
+ && ( is_my_call(msg_data[msg_index[j]].from_call_sign, 1)) ) {
+//fprintf(stderr,"Setting underline\t");
+ XmTextSetHighlight(mw[mw_p].send_message_text,
+ pos+offset,
+ pos+strlen(temp2),
+ //XmHIGHLIGHT_SECONDARY_SELECTED); // Underlining
+ XmHIGHLIGHT_SELECTED); // Reverse Video
+ }
+ else { // Message was acked, get rid of highlighting
+//fprintf(stderr,"Setting normal\t");
+ XmTextSetHighlight(mw[mw_p].send_message_text,
+ pos+offset,
+ pos+strlen(temp2),
+ XmHIGHLIGHT_NORMAL);
+ }
+
+//fprintf(stderr,"Text: %s\n",temp2);
+
+ pos += strlen(temp2);
+
+ }
+
+ // Advance to the next record in the list
+ p_prev = p_next;
+ if (p_next != NULL)
+ p_next = p_prev->next;
+
+ } // End of while
+ } // End of if
+ else { // No messages matched, list is empty
+ }
+
+// What does this do? Move all of the text?
+// if (pos > 0) {
+// if (mw[mw_p].send_message_text != NULL) {
+// XmTextReplace(mw[mw_p].send_message_text,
+// --pos,
+// XmTextGetLastPosition(mw[mw_p].send_message_text),
+// "");
+// }
+// }
+
+ //fprintf(stderr,"Free'ing list\n");
+
+ // De-allocate the linked list
+ p_prev = head;
+ while (p_prev != NULL) {
+
+ //fprintf(stderr,"You're free!\n");
+
+ p_next = p_prev->next;
+ free(p_prev);
+ p_prev = p_next;
+ }
+
+ // Show the last added message in the window
+ XmTextShowPosition(mw[mw_p].send_message_text,
+ pos);
+ }
+ }
+ }
+
+end_critical_section(&send_message_dialog_lock, "db.c:update_messages" );
+
+ }
+ last_message_update = sec_now();
+
+//fprintf(stderr,"Message index end: %ld\n",msg_index_end);
+
+ }
+}
+
+
+
+
+
+void mdelete_messages_from(char *from) {
+ long i;
+
+ // Mark message records with RECORD_NOTACTIVE. This will mark
+ // them for re-use.
+ for (i = 0; msg_index && i < msg_index_end; i++)
+ if (strcmp(msg_data[i].call_sign, my_callsign) == 0 && strcmp(msg_data[i].from_call_sign, from) == 0)
+ msg_data[i].active = RECORD_NOTACTIVE;
+}
+
+
+
+
+
+void mdelete_messages_to(char *to) {
+ long i;
+
+ // Mark message records with RECORD_NOTACTIVE. This will mark
+ // them for re-use.
+ for (i = 0; msg_index && i < msg_index_end; i++)
+ if (strcmp(msg_data[i].call_sign, to) == 0)
+ msg_data[i].active = RECORD_NOTACTIVE;
+}
+
+
+
+
+
+void mdelete_messages(char *to_from) {
+ long i;
+
+ // Mark message records with RECORD_NOTACTIVE. This will mark
+ // them for re-use.
+ for (i = 0; msg_index && i < msg_index_end; i++)
+ if (strcmp(msg_data[i].call_sign, to_from) == 0 || strcmp(msg_data[i].from_call_sign, to_from) == 0)
+ msg_data[i].active = RECORD_NOTACTIVE;
+}
+
+
+
+
+
+void mdata_delete_type(const char msg_type, const time_t reference_time) {
+ long i;
+
+ // Mark message records with RECORD_NOTACTIVE. This will mark
+ // them for re-use.
+ for (i = 0; msg_index && i < msg_index_end; i++)
+
+ if ((msg_type == '\0' || msg_type == msg_data[i].type)
+ && msg_data[i].active == RECORD_ACTIVE
+ && msg_data[i].sec_heard < reference_time)
+
+ msg_data[i].active = RECORD_NOTACTIVE;
+}
+
+
+
+
+
+void check_message_remove(time_t curr_sec) { // called in timing loop
+
+ // Time to check for old messages again? (Currently every ten
+ // minutes)
+#ifdef EXPIRE_DEBUG
+ if ( last_message_remove < (curr_sec - DEBUG_MESSAGE_REMOVE_CYCLE) ) {
+#else // EXPIRE_DEBUG
+ if ( last_message_remove < (curr_sec - MESSAGE_REMOVE_CYCLE) ) {
+#endif
+
+ // Yes it is. Mark all messages that are older than
+ // sec_remove with the RECORD_NOTACTIVE flag. This will
+ // mark them for re-use.
+#ifdef EXPIRE_DEBUG
+ mdata_delete_type('\0', curr_sec-DEBUG_MESSAGE_REMOVE);
+#else // EXPIRE_DEBUG
+ mdata_delete_type('\0', curr_sec-sec_remove);
+#endif
+
+ last_message_remove = curr_sec;
+ }
+
+ // Should we sort them at this point so that the unused ones are
+ // near the end? It looks like the message input functions do
+ // this, so I guess we don't need to do it here.
+}
+
+
+
+
+
+void mscan_file(char msg_type, void (*function)(Message *)) {
+ long i;
+
+ for (i = 0; msg_index && i < msg_index_end; i++)
+ if ((msg_type == '\0' || msg_type == msg_data[msg_index[i]].type) &&
+ msg_data[msg_index[i]].active == RECORD_ACTIVE)
+ function(&msg_data[msg_index[i]]);
+}
+
+
+
+
+
+void mprint_record(Message *m_fill) {
+ fprintf(stderr,
+ "%-9s>%-9s %s:%5s %s:%c :%s\n",
+ m_fill->from_call_sign,
+ m_fill->call_sign,
+ langcode("WPUPMSB013"), // "seq"
+ m_fill->seq,
+ langcode("WPUPMSB014"), // "type"
+ m_fill->type,
+ m_fill->message_line);
+}
+
+
+
+
+
+void mdisplay_file(char msg_type) {
+ fprintf(stderr,"\n\n");
+ mscan_file(msg_type, mprint_record);
+ fprintf(stderr,"\tmsg_index_end %ld, msg_index_max %ld\n", msg_index_end, msg_index_max);
+}
+
+
+
+
+
+/////////////////////////////////////// Station Data ///////////////////////////////////////////
+
+
+
+
+
+void pad_callsign(char *callsignout, char *callsignin) {
+ int i,l;
+
+ l=(int)strlen(callsignin);
+ for(i=0; i<9;i++) {
+ if(i<l) {
+ if(isalnum((int)callsignin[i]) || callsignin[i]=='-') {
+ callsignout[i]=callsignin[i];
+ }
+ else {
+ callsignout[i] = ' ';
+ }
+ }
+ else {
+ callsignout[i] = ' ';
+ }
+ }
+ callsignout[i] = '\0';
+}
+
+
+
+
+
+// Check for valid overlay characters: 'A-Z', '0-9', and 'a-j'. If
+// 'a-j', it's from a compressed posit, and we need to convert it to
+// '0-9'.
+void overlay_symbol(char symbol, char data, DataRow *fill) {
+
+ if ( data != '/' && data !='\\') { // Symbol overlay
+
+ if (data >= 'a' && data <= 'j') {
+ // Found a compressed posit numerical overlay
+ data = data - 'a'+'0'; // Convert to a digit
+ }
+ if ( (data >= '0' && data <= '9')
+ || (data >= 'A' && data <= 'Z') ) {
+ // Found normal overlay character
+ fill->aprs_symbol.aprs_type = '\\';
+ fill->aprs_symbol.special_overlay = data;
+ }
+ else {
+ // Bad overlay character. Don't use it. Insert the
+ // normal alternate table character instead.
+ fill->aprs_symbol.aprs_type = '\\';
+ fill->aprs_symbol.special_overlay='\0';
+ }
+ }
+ else { // No overlay character
+ fill->aprs_symbol.aprs_type = data;
+ fill->aprs_symbol.special_overlay='\0';
+ }
+ fill->aprs_symbol.aprs_symbol = symbol;
+}
+
+
+
+
+
+APRS_Symbol *id_callsign(char *call_sign, char * to_call) {
+ char *ptr;
+ char *id = "/aUfbYX's><OjRkv";
+ char hold[MAX_CALLSIGN+1];
+ int index;
+ static APRS_Symbol symbol;
+
+ symbol.aprs_symbol = '/';
+ symbol.special_overlay = '\0';
+ symbol.aprs_type ='/';
+ ptr=strchr(call_sign,'-');
+ if(ptr!=NULL) /* get symbol from SSID */
+ if((index=atoi(ptr+1))<= 15)
+ symbol.aprs_symbol = id[index];
+
+ if (strncmp(to_call, "GPS", 3) == 0 || strncmp(to_call, "SPC", 3) == 0 || strncmp(to_call, "SYM", 3) == 0) {
+ substr(hold, to_call+3, 3);
+ if ((ptr = strpbrk(hold, "->,")) != NULL)
+ *ptr = '\0';
+
+ if (strlen(hold) >= 2) {
+ switch (hold[0]) {
+ case 'A':
+ symbol.aprs_type = '\\';
+
+ case 'P':
+ if (('0' <= hold[1] && hold[1] <= '9') || ('A' <= hold[1] && hold[1] <= 'Z'))
+ symbol.aprs_symbol = hold[1];
+
+ break;
+
+ case 'O':
+ symbol.aprs_type = '\\';
+
+ case 'B':
+ switch (hold[1]) {
+ case 'B':
+ symbol.aprs_symbol = '!';
+ break;
+ case 'C':
+ symbol.aprs_symbol = '"';
+ break;
+ case 'D':
+ symbol.aprs_symbol = '#';
+ break;
+ case 'E':
+ symbol.aprs_symbol = '$';
+ break;
+ case 'F':
+ symbol.aprs_symbol = '%';
+ break;
+ case 'G':
+ symbol.aprs_symbol = '&';
+ break;
+ case 'H':
+ symbol.aprs_symbol = '\'';
+ break;
+ case 'I':
+ symbol.aprs_symbol = '(';
+ break;
+ case 'J':
+ symbol.aprs_symbol = ')';
+ break;
+ case 'K':
+ symbol.aprs_symbol = '*';
+ break;
+ case 'L':
+ symbol.aprs_symbol = '+';
+ break;
+ case 'M':
+ symbol.aprs_symbol = ',';
+ break;
+ case 'N':
+ symbol.aprs_symbol = '-';
+ break;
+ case 'O':
+ symbol.aprs_symbol = '.';
+ break;
+ case 'P':
+ symbol.aprs_symbol = '/';
+ break;
+ }
+ break;
+
+ case 'D':
+ symbol.aprs_type = '\\';
+
+ case 'H':
+ switch (hold[1]) {
+ case 'S':
+ symbol.aprs_symbol = '[';
+ break;
+ case 'T':
+ symbol.aprs_symbol = '\\';
+ break;
+ case 'U':
+ symbol.aprs_symbol = ']';
+ break;
+ case 'V':
+ symbol.aprs_symbol = '^';
+ break;
+ case 'W':
+ symbol.aprs_symbol = '_';
+ break;
+ case 'X':
+ symbol.aprs_symbol = '`';
+ break;
+ }
+ break;
+
+ case 'N':
+ symbol.aprs_type = '\\';
+
+ case 'M':
+ switch (hold[1]) {
+ case 'R':
+ symbol.aprs_symbol = ':';
+ break;
+ case 'S':
+ symbol.aprs_symbol = ';';
+ break;
+ case 'T':
+ symbol.aprs_symbol = '<';
+ break;
+ case 'U':
+ symbol.aprs_symbol = '=';
+ break;
+ case 'V':
+ symbol.aprs_symbol = '>';
+ break;
+ case 'W':
+ symbol.aprs_symbol = '?';
+ break;
+ case 'X':
+ symbol.aprs_symbol = '@';
+ break;
+ }
+ break;
+
+ case 'Q':
+ symbol.aprs_type = '\\';
+
+ case 'J':
+ switch (hold[1]) {
+ case '1':
+ symbol.aprs_symbol = '{';
+ break;
+ case '2':
+ symbol.aprs_symbol = '|';
+ break;
+ case '3':
+ symbol.aprs_symbol = '}';
+ break;
+ case '4':
+ symbol.aprs_symbol = '~';
+ break;
+ }
+ break;
+
+ case 'S':
+ symbol.aprs_type = '\\';
+
+ case 'L':
+ if ('A' <= hold[1] && hold[1] <= 'Z')
+ symbol.aprs_symbol = tolower((int)hold[1]);
+
+ break;
+ }
+ if (hold[2]) {
+ if (hold[2] >= 'a' && hold[2] <= 'j') {
+ // Compressed mode numeric overlay
+ symbol.special_overlay = hold[2] - 'a';
+ }
+ else if ( (hold[2] >= '0' && hold[2] <= '9')
+ || (hold[2] >= 'A' && hold[2] <= 'Z') ) {
+ // Normal overlay character
+ symbol.special_overlay = hold[2];
+ }
+ else {
+ // Bad overlay character found
+ symbol.special_overlay = '\0';
+ }
+ }
+ else {
+ // No overlay character found
+ symbol.special_overlay = '\0';
+ }
+ }
+ }
+ return(&symbol);
+}
+
+
+
+
+
+/******************************** Sort begin *************************** ****/
+
+
+
+
+
+void clear_sort_file(char *filename) {
+ char ptr_filename[400];
+
+ xastir_snprintf(ptr_filename, sizeof(ptr_filename), "%s-ptr", filename);
+ (void)unlink(filename);
+ (void)unlink(ptr_filename);
+}
+
+
+
+
+
+void sort_reset_pointers(FILE *pointer,long new_data_ptr,long records, int type, long start_ptr) {
+ long cp;
+ long temp[13000];
+ long buffn,start_buffn;
+ long cp_records;
+ long max_buffer;
+ int my_size;
+
+ my_size=(int)sizeof(new_data_ptr);
+ max_buffer=13000l;
+ if(type==0) {
+ /* before start_ptr */
+ /* copy back pointers */
+ cp=start_ptr;
+ for(buffn=records; buffn > start_ptr; buffn-=max_buffer) {
+ start_buffn=buffn-max_buffer;
+ if(start_buffn<start_ptr)
+ start_buffn=start_ptr;
+
+ cp_records=buffn-start_buffn;
+ (void)fseek(pointer,(my_size*start_buffn),SEEK_SET);
+ if(fread(&temp,(my_size*cp_records),1,pointer)==1) {
+ (void)fseek(pointer,(my_size*(start_buffn+1)),SEEK_SET);
+ (void)fwrite(&temp,(my_size*cp_records),1,pointer);
+ }
+ }
+ /* copy new pointer in */
+ (void)fseek(pointer,(my_size*start_ptr),SEEK_SET);
+ (void)fwrite(&new_data_ptr,(size_t)my_size,1,pointer);
+ }
+}
+
+
+
+
+
+long sort_input_database(char *filename, char *fill, int size) {
+ FILE *my_data;
+ FILE *pointer;
+ char file_data[2000];
+
+ char ptr_filename[400];
+
+ char tempfile[2000];
+ char tempfill[2000];
+
+ int ptr_size;
+ long data_ptr;
+ long new_data_ptr;
+ long return_records;
+ long records;
+ long record_start;
+ long record_end;
+ long record_mid;
+ int done;
+
+ ptr_size=(int)sizeof(new_data_ptr);
+ xastir_snprintf(ptr_filename, sizeof(ptr_filename), "%s-ptr", filename);
+
+ /* get first string to sort on */
+ if (1 != sscanf(fill,"%1999s",tempfill)) {
+ fprintf(stderr,"sort_input_database(1): sscanf failed to parse\n");
+ }
+
+ data_ptr=0l;
+ my_data=NULL;
+ return_records=0l;
+ pointer = fopen(ptr_filename,"r+");
+ /* check if file is there */
+ if(pointer == NULL)
+ pointer = fopen(ptr_filename,"a+");
+
+ if(pointer!=NULL) {
+ my_data = fopen(filename,"a+");
+ if(my_data!=NULL) {
+
+ // Next statement needed for Solaris 7, as the fopen above
+ // doesn't put the filepointer at the end of the file.
+ (void) fseek(my_data,0l,SEEK_END); //KD6ZWR
+
+ new_data_ptr = data_ptr = ftell(my_data);
+ (void)fwrite(fill,(size_t)size,1,my_data);
+ records = (data_ptr/size);
+ return_records=records+1;
+ if(records<1) {
+ /* no data yet */
+ (void)fseek(pointer,0l,SEEK_SET);
+ (void)fwrite(&data_ptr,(size_t)ptr_size,1,pointer);
+ }
+ else {
+ /* more than one record*/
+ (void)fseek(pointer,(ptr_size*records),SEEK_SET);
+ (void)fwrite(&data_ptr,(size_t)ptr_size,1,pointer);
+ record_start=0l;
+ record_end=records;
+ record_mid=(record_end-record_start)/2;
+ done=0;
+ while(!done) {
+ /*fprintf(stderr,"Records Start %ld, Mid %ld, End %ld\n",record_start,record_mid,record_end);*/
+ /* get data for record start */
+ (void)fseek(pointer,(ptr_size*record_start),SEEK_SET);
+ (void)fread(&data_ptr,(size_t)ptr_size,1,pointer);
+ (void)fseek(my_data,data_ptr,SEEK_SET);
+ if(fread(file_data,(size_t)size,1,my_data)==1) {
+ /* COMPARE HERE */
+ if (1 != sscanf(file_data,"%1999s",tempfile)) {
+ fprintf(stderr,"sort_input_database(2): sscanf failed to parse\n");
+ }
+ if(strcasecmp(tempfill,tempfile)<0) {
+ /* file name comes before */
+ /*fprintf(stderr,"END - Before start\n");*/
+ done=1;
+ /* now place pointer before start*/
+ sort_reset_pointers(pointer,new_data_ptr,records,0,record_start);
+ }
+ else {
+ /* get data for record end */
+ (void)fseek(pointer,(ptr_size*record_end),SEEK_SET);
+ (void)fread(&data_ptr,(size_t)ptr_size,1,pointer);
+ (void)fseek(my_data,data_ptr,SEEK_SET);
+ if(fread(file_data,(size_t)size,1,my_data)==1) {
+ /* COMPARE HERE */
+ if (1 != sscanf(file_data,"%1999s",tempfile)) {
+ fprintf(stderr,"sort_input_database(3): sscanf failed to parse\n");
+ }
+ if(strcasecmp(tempfill,tempfile)>0) {
+ /* file name comes after */
+ /*fprintf(stderr,"END - After end\n");*/
+ done=1;
+ /* now place pointer after end */
+ }
+ else {
+ if((record_mid==record_start) || (record_mid==record_end)) {
+ /* no mid for compare check to see if in the middle */
+ /*fprintf(stderr,"END - NO Middle\n");*/
+ done=1;
+ /* now place pointer before start*/
+ if (record_mid==record_start)
+ sort_reset_pointers(pointer,new_data_ptr,records,0,record_mid+1);
+ else
+ sort_reset_pointers(pointer,new_data_ptr,records,0,record_mid-1);
+ }
+ else {
+ /* get data for record mid */
+ (void)fseek(pointer,(ptr_size*record_mid),SEEK_SET);
+ (void)fread(&data_ptr,(size_t)ptr_size,1,pointer);
+ (void)fseek(my_data,data_ptr,SEEK_SET);
+ if(fread(file_data,(size_t)size,1,my_data)==1) {
+ /* COMPARE HERE */
+ if (1 != sscanf(file_data,"%1999s",tempfile)) {
+ fprintf(stderr,"sort_input_database(4): sscanf failed to parse\n");
+ }
+ if(strcasecmp(tempfill,tempfile)<0) {
+ /* checking comes before */
+ /*record_start=0l;*/
+ record_end=record_mid;
+ record_mid=record_start+(record_end-record_start)/2;
+ /*fprintf(stderr,"TOP %ld, mid %ld\n",record_mid,record_end);*/
+ }
+ else {
+ /* checking comes after*/
+ record_start=record_mid;
+ /*record_end=end*/
+ record_mid=record_start+(record_end-record_start)/2;
+ /*fprintf(stderr,"BOTTOM start %ld, mid %ld\n",record_start,record_mid);*/
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ fprintf(stderr,"Could not open file %s\n",filename);
+ }
+ else
+ fprintf(stderr,"Could not open file %s\n",filename);
+
+ if(my_data!=NULL)
+ (void)fclose(my_data);
+
+ if(pointer!=NULL)
+ (void)fclose(pointer);
+
+ return(return_records);
+}
+
+
+
+
+
+/******************** sort end **********************/
+
+
+
+// is_altnet()
+//
+// Returns true if station fits the current altnet description.
+//
+int is_altnet(DataRow *p_station) {
+ char temp_altnet_call[20+1];
+ char temp2[20+1];
+ char *net_ptr;
+ int altnet_match;
+ int result;
+
+
+ // Snag a possible altnet call out of the record for later use
+ if (p_station->node_path_ptr != NULL)
+ substr(temp_altnet_call, p_station->node_path_ptr, MAX_CALLSIGN);
+ else
+ temp_altnet_call[0] = '\0';
+
+ // Save for later
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ temp_altnet_call);
+
+ if ((net_ptr = strchr(temp_altnet_call, ',')))
+ *net_ptr = '\0'; // Chop the string at the first ',' character
+
+ for (altnet_match = (int)strlen(altnet_call); altnet && altnet_call[altnet_match-1] == '*'; altnet_match--);
+
+ result = (!strncmp(temp_altnet_call, altnet_call, (size_t)altnet_match)
+ || !strcmp(temp_altnet_call, "local")
+ || !strncmp(temp_altnet_call, "SPC", 3)
+ || !strcmp(temp_altnet_call, "SPECL")
+// || is_my_call(p_station->call_sign,1)); // Check SSID as well
+ || ( is_my_station(p_station) ) ) ; // It's my callsign/SSID
+
+ if ( (debug_level & 1) && result )
+ fprintf(stderr,"%s %-9s %s\n", altnet_call, temp_altnet_call, temp2 );
+
+ return(result);
+}
+
+
+
+
+
+// Function which checks various filtering criteria (the Select struct)
+// and decides whether this station/object should be displayed.
+//
+// 0 = don't draw this station/object
+// 1 = ok to draw this station/object
+//
+int ok_to_draw_station(DataRow *p_station) {
+ time_t secs_now = sec_now();
+ // Check overall flag
+ if (Select_.none)
+ return 0;
+
+ // Check tactical flag
+ if (Select_.tactical
+ && (p_station->tactical_call_sign == NULL
+ || p_station->tactical_call_sign[0] == '\0'))
+ return 0;
+
+ // Check for my station and my objects/items
+// if (strcmp(p_station->call_sign, my_callsign) == 0
+// || (is_my_call(p_station->origin, 1) // If station is owned by me (including SSID)
+// && ( p_station->flag & ST_OBJECT // And it's an object
+// || p_station->flag & ST_ITEM) ) ) { // or an item
+// if ( is_my_station(p_station) || is_my_object_item(p_station) ) {
+ if ( is_my_station(p_station) ) {
+ if (!Select_.mine)
+ return 0;
+ }
+ // Not mine, so check these next things
+ else {
+ // Check whether we wish to display TNC heard stations
+ if (p_station->flag & ST_VIATNC) {
+ if (!Select_.tnc)
+ return 0;
+
+ // Check whether we wish to display directly heard stations
+ if (p_station->flag & ST_DIRECT
+ && secs_now < (p_station->direct_heard + st_direct_timeout)) {
+ if (!Select_.direct)
+ return 0;
+ }
+ // Check whether we wish to display stations heard via a digi
+ else {
+ if (!Select_.via_digi)
+ return 0;
+ }
+ }
+ // Check whether we wish to display net stations
+ else {
+ if (!Select_.net)
+ return 0;
+ }
+
+ // Check if we want to display data past the clear time
+ if (!Select_.old_data) {
+ if ((p_station->sec_heard + sec_clear) < secs_now)
+ return 0;
+ }
+ }
+
+
+ // Check whether object or item
+ if (p_station->flag & (ST_OBJECT | ST_ITEM)) {
+ // Check whether we wish to display objects/items
+ if (!Select_.objects ||
+ (!Select_.weather_objects && !Select_.gauge_objects && !Select_.other_objects))
+ return 0;
+
+ // Check if WX info and we wish to see it
+ if (p_station->weather_data) {
+ return Select_.weather_objects;
+ }
+ // Check if water gauge and we wish to see it
+ else if (p_station->aprs_symbol.aprs_type == '/'
+ && p_station->aprs_symbol.aprs_symbol == 'w') {
+ return Select_.gauge_objects;
+ }
+ // Check if we wish to see other objects/items
+ else {
+ return Select_.other_objects;
+ }
+ }
+ else { // Not an object or item
+ if (!Select_.stations ||
+ (!Select_.fixed_stations && !Select_.moving_stations && !Select_.weather_stations))
+ return 0;
+
+ // Check if we wish to see weather stations
+ if (p_station->weather_data) {
+ // We have weather data
+
+ // Check whether it is a citizen's weather station.
+ // Note that a "CW" prefix is Uruguay and "DW" prefix is
+ // Phillipines, so let's be careful how we filter here.
+ // All Cititzen's weather stations seen to date have had
+ // CW or DW and then four digits.
+ if ( (strncasecmp(p_station->call_sign,"CW",2) == 0)
+ || (strncasecmp(p_station->call_sign,"DW",2) == 0) ) {
+ if ( is_num_chr(p_station->call_sign[2])
+ && is_num_chr(p_station->call_sign[3])
+ && is_num_chr(p_station->call_sign[4])
+ && is_num_chr(p_station->call_sign[5]) ) {
+ return(Select_.weather_stations && Select_.CWOP_wx_stations);
+ }
+ else {
+ return Select_.weather_stations;
+ }
+ }
+ else {
+ return Select_.weather_stations;
+ }
+ }
+ // Check if we wish to see other stations
+ else {
+ if (p_station->flag & ST_MOVING) {
+ return Select_.moving_stations;
+ }
+ else {
+ return Select_.fixed_stations;
+ }
+ }
+ }
+}
+
+
+
+
+
+// display_station
+//
+// single is 1 if the calling station wants to update only a
+// single station. If updating multiple stations in a row, then
+// "single" will be passed to us as a zero.
+//
+// If current course/speed/altitude are absent, we check the last
+// track point to try to snag those numbers.
+//
+void display_station(Widget w, DataRow *p_station, int single) {
+ char temp_altitude[20];
+ char temp_course[20];
+ char temp_speed[20];
+ char dr_speed[20];
+ char temp_call[MAX_TACTICAL_CALL+1];
+ char wx_tm[50];
+ char temp_wx_temp[30];
+ char temp_wx_wind[40];
+ char temp_my_distance[20];
+ char temp_my_course[20];
+ char temp1_my_course[20];
+ char temp2_my_gauge_data[50];
+ time_t temp_sec_heard;
+ int temp_show_last_heard;
+ long l_lon, l_lat;
+ char orient;
+ float value;
+ char tmp[7+1];
+ int speed_ok = 0;
+ int course_ok = 0;
+ int wx_ghost = 0;
+ Pixmap drawing_target;
+ WeatherRow *weather = p_station->weather_data;
+ time_t secs_now = sec_now();
+ int ambiguity_flag;
+ long ambiguity_coord_lon, ambiguity_coord_lat;
+
+
+ if (debug_level & 128)
+ fprintf(stderr,"Display station (%s) called for Single=%d.\n", p_station->call_sign, single);
+
+ if (!ok_to_draw_station(p_station))
+ return;
+
+ // Set up call string for display
+ if (Display_.callsign) {
+ if (p_station->tactical_call_sign
+ && p_station->tactical_call_sign[0] != '\0') {
+ // Display tactical callsign instead if it has one
+ // defined.
+ xastir_snprintf(temp_call,
+ sizeof(temp_call),
+ "%s",
+ p_station->tactical_call_sign);
+ }
+ else {
+ // Display normal callsign.
+ xastir_snprintf(temp_call,
+ sizeof(temp_call),
+ "%s",
+ p_station->call_sign);
+ }
+ }
+ else {
+ temp_call[0] = '\0';
+ }
+
+ // Set up altitude string for display
+ temp_altitude[0] = '\0';
+
+ if (Display_.altitude) {
+ // Check whether we have altitude in the current data
+ if (strlen(p_station->altitude)>0) {
+ // Found it in the current data
+ xastir_snprintf(temp_altitude, sizeof(temp_altitude), "%.0f%s",
+ atof(p_station->altitude) * cvt_m2len, un_alt);
+ }
+
+ // Else check whether the previous position had altitude.
+ // Note that newest_trackpoint if it exists should be the
+ // same as the current data, so we have to go back one
+ // further trackpoint.
+ else if ( (p_station->newest_trackpoint != NULL)
+ && (p_station->newest_trackpoint->prev != NULL) ) {
+ if ( p_station->newest_trackpoint->prev->altitude > -99999l) {
+ // Found it in the tracklog
+ xastir_snprintf(temp_altitude, sizeof(temp_altitude), "%.0f%s",
+ (float)(p_station->newest_trackpoint->prev->altitude * cvt_dm2len),
+ un_alt);
+
+// fprintf(stderr,"Trail data with altitude: %s : %s\n",
+// p_station->call_sign,
+// temp_altitude);
+ }
+ else {
+ //fprintf(stderr,"Trail data w/o altitude %s\n",
+ // p_station->call_sign);
+ }
+ }
+ }
+
+ // Set up speed and course strings for display
+ temp_speed[0] = '\0';
+ dr_speed[0] = '\0';
+ temp_course[0] = '\0';
+
+ if (Display_.speed || Display_.dr_data) {
+ // don't display 'fixed' stations speed and course.
+ // Check whether we have speed in the current data and it's
+ // >= 0.
+ if ( (strlen(p_station->speed)>0) && (atof(p_station->speed) >= 0) ) {
+ speed_ok++;
+ xastir_snprintf(tmp,
+ sizeof(tmp),
+ "%s",
+ un_spd);
+ if (Display_.speed_short)
+ tmp[0] = '\0'; // without unit
+
+ xastir_snprintf(temp_speed, sizeof(temp_speed), "%.0f%s",
+ atof(p_station->speed)*cvt_kn2len,tmp);
+ }
+ // Else check whether the previous position had speed
+ // Note that newest_trackpoint if it exists should be the
+ // same as the current data, so we have to go back one
+ // further trackpoint.
+ else if ( (p_station->newest_trackpoint != NULL)
+ && (p_station->newest_trackpoint->prev != NULL) ) {
+
+ xastir_snprintf(tmp,
+ sizeof(tmp),
+ "%s",
+ un_spd);
+
+ if (Display_.speed_short)
+ tmp[0] = '\0'; // without unit
+
+ if ( p_station->newest_trackpoint->prev->speed > 0) {
+ speed_ok++;
+
+ xastir_snprintf(temp_speed, sizeof(temp_speed), "%.0f%s",
+ p_station->newest_trackpoint->prev->speed * cvt_hm2len,
+ tmp);
+ }
+ }
+ }
+
+ if (Display_.course || Display_.dr_data) {
+ // Check whether we have course in the current data
+ if ( (strlen(p_station->course)>0) && (atof(p_station->course) > 0) ) {
+ course_ok++;
+ xastir_snprintf(temp_course, sizeof(temp_course), "%.0f�",
+ atof(p_station->course));
+ }
+ // Else check whether the previous position had a course
+ // Note that newest_trackpoint if it exists should be the
+ // same as the current data, so we have to go back one
+ // further trackpoint.
+ else if ( (p_station->newest_trackpoint != NULL)
+ && (p_station->newest_trackpoint->prev != NULL) ) {
+ if( p_station->newest_trackpoint->prev->course > 0 ) {
+ course_ok++;
+ xastir_snprintf(temp_course, sizeof(temp_course), "%.0f�",
+ (float)p_station->newest_trackpoint->prev->course);
+ }
+ }
+ }
+
+ // Save the speed into the dr string for later
+ xastir_snprintf(dr_speed,
+ sizeof(dr_speed),
+ "%s",
+ temp_speed);
+
+ if (!speed_ok || !Display_.speed)
+ temp_speed[0] = '\0';
+
+ if (!course_ok || !Display_.course)
+ temp_course[0] = '\0';
+
+ // Set up distance and bearing strings for display
+ temp_my_distance[0] = '\0';
+ temp_my_course[0] = '\0';
+
+ if (Display_.dist_bearing && strcmp(p_station->call_sign,my_callsign) != 0) {
+ l_lat = convert_lat_s2l(my_lat);
+ l_lon = convert_lon_s2l(my_long);
+
+ // Get distance in nautical miles, convert to current measurement standard
+ value = cvt_kn2len * calc_distance_course(l_lat,l_lon,
+ p_station->coord_lat,p_station->coord_lon,temp1_my_course,sizeof(temp1_my_course));
+
+ if (value < 5.0)
+ sprintf(temp_my_distance,"%0.1f%s",value,un_dst);
+ else
+ sprintf(temp_my_distance,"%0.0f%s",value,un_dst);
+
+ xastir_snprintf(temp_my_course, sizeof(temp_my_course), "%.0f�",
+ atof(temp1_my_course));
+ }
+
+ // Set up weather strings for display
+ temp_wx_temp[0] = '\0';
+ temp_wx_wind[0] = '\0';
+
+ if (weather != NULL) {
+ // wx_ghost = 1 if the weather data is too old to display
+ wx_ghost = (int)(((sec_old + weather->wx_sec_time)) < secs_now);
+ }
+
+ if (Display_.weather
+ && Display_.weather_text
+ && weather != NULL // We have weather data
+ && !wx_ghost) { // Weather is current, display it
+
+ if (strlen(weather->wx_temp) > 0) {
+ xastir_snprintf(tmp,
+ sizeof(tmp),
+ "T:");
+ if (Display_.temperature_only)
+ tmp[0] = '\0';
+
+ if (english_units)
+ xastir_snprintf(temp_wx_temp, sizeof(temp_wx_temp), "%s%.0f�F ",
+ tmp, atof(weather->wx_temp));
+ else
+ xastir_snprintf(temp_wx_temp, sizeof(temp_wx_temp), "%s%.0f�C ",
+ tmp,((atof(weather->wx_temp)-32.0)*5.0)/9.0);
+ }
+
+ if (!Display_.temperature_only) {
+ if (strlen(weather->wx_hum) > 0) {
+ xastir_snprintf(wx_tm, sizeof(wx_tm), "H:%.0f%%", atof(weather->wx_hum));
+ strncat(temp_wx_temp,
+ wx_tm,
+ sizeof(temp_wx_temp) - 1 - strlen(temp_wx_temp));
+ }
+
+ if (strlen(weather->wx_speed) > 0) {
+ xastir_snprintf(temp_wx_wind, sizeof(temp_wx_wind), "S:%.0f%s ",
+ atof(weather->wx_speed)*cvt_mi2len,un_spd);
+ }
+
+ if (strlen(weather->wx_gust) > 0) {
+ xastir_snprintf(wx_tm, sizeof(wx_tm), "G:%.0f%s ",
+ atof(weather->wx_gust)*cvt_mi2len,un_spd);
+ strncat(temp_wx_wind,
+ wx_tm,
+ sizeof(temp_wx_wind) - 1 - strlen(temp_wx_wind));
+ }
+
+ if (strlen(weather->wx_course) > 0) {
+ xastir_snprintf(wx_tm, sizeof(wx_tm), "C:%.0f�", atof(weather->wx_course));
+ strncat(temp_wx_wind,
+ wx_tm,
+ sizeof(temp_wx_wind) - 1 - strlen(temp_wx_wind));
+ }
+
+ if (temp_wx_wind[strlen(temp_wx_wind)-1] == ' ') {
+ temp_wx_wind[strlen(temp_wx_wind)-1] = '\0'; // delete blank at EOL
+ }
+ }
+
+ if (temp_wx_temp[strlen(temp_wx_temp)-1] == ' ')
+ temp_wx_temp[strlen(temp_wx_temp)-1] = '\0'; // delete blank at EOL
+ }
+
+
+ (void)remove_trailing_asterisk(p_station->call_sign); // DK7IN: is this needed here?
+
+ if (Display_.symbol_rotate)
+ orient = symbol_orient(p_station->course); // rotate symbol
+ else
+ orient = ' ';
+
+ // Prevents my own call from "ghosting"?
+// temp_sec_heard = (strcmp(p_station->call_sign, my_callsign) == 0) ? secs_now: p_station->sec_heard;
+ temp_sec_heard = (is_my_station(p_station)) ? secs_now : p_station->sec_heard;
+
+ // Check whether it's a locally-owned object/item
+// if ( (is_my_call(p_station->origin,1)) // If station is owned by me (including SSID)
+// && ( (p_station->flag & ST_OBJECT) // And it's an object
+// || (p_station->flag & ST_ITEM) ) ) { // or an item
+// if ( is_my_object_item(p_station) ) {
+// temp_sec_heard = secs_now; // We don't want our own objects/items to "ghost"
+// }
+
+ // Show last heard times only for others stations and their
+ // objects/items.
+// temp_show_last_heard = (strcmp(p_station->call_sign, my_callsign) == 0) ? 0 : Display_.last_heard;
+ temp_show_last_heard = (is_my_station(p_station)) ? 0 : Display_.last_heard;
+
+
+
+//------------------------------------------------------------------------------------------
+
+ // If we're only planning on updating a single station at this time, we go
+ // through the drawing calls twice, the first time drawing directly onto
+ // the screen.
+ if (!pending_ID_message && single)
+ drawing_target = XtWindow(da);
+ else
+ drawing_target = pixmap_final;
+
+//_do_the_drawing:
+
+ // Check whether it's a locally-owned object/item
+// if ( (is_my_call(p_station->origin,1)) // If station is owned by me (including SSID)
+// && ( (p_station->flag & ST_OBJECT) // And it's an object
+// || (p_station->flag & ST_ITEM ) ) ) { // or an item
+// if ( is_my_object_item(p_station) ) {
+// temp_sec_heard = secs_now; // We don't want our own objects/items to "ghost"
+ // This isn't quite right since if it's a moving object, passing an incorrect
+ // sec_heard should give the wrong results.
+// }
+
+ ambiguity_flag = 0; // Default
+
+ if (Display_.ambiguity && p_station->pos_amb) {
+ ambiguity_flag = 1;
+ draw_ambiguity(p_station->coord_lon,
+ p_station->coord_lat,
+ p_station->pos_amb,
+ &ambiguity_coord_lon, // New longitude may get passed back to us
+ &ambiguity_coord_lat, // New latitude may get passed back to us
+ temp_sec_heard,
+ drawing_target);
+ }
+
+ // Check for DF'ing data, draw DF circles if present and enabled
+ if (Display_.df_data && strlen(p_station->signal_gain) == 7) { // There's an SHGD defined
+ //fprintf(stderr,"SHGD:%s\n",p_station->signal_gain);
+ draw_DF_circle( (ambiguity_flag) ? ambiguity_coord_lon : p_station->coord_lon,
+ (ambiguity_flag) ? ambiguity_coord_lat : p_station->coord_lat,
+ p_station->signal_gain,
+ temp_sec_heard,
+ drawing_target);
+ }
+
+ // Check for DF'ing beam heading/NRQ data
+ if (Display_.df_data && (strlen(p_station->bearing) == 3) && (strlen(p_station->NRQ) == 3)) {
+ //fprintf(stderr,"Bearing: %s\n",p_station->signal_gain,NRQ);
+ if (p_station->df_color == -1)
+ p_station->df_color = rand() % MAX_TRAIL_COLORS;
+
+ draw_bearing( (ambiguity_flag) ? ambiguity_coord_lon : p_station->coord_lon,
+ (ambiguity_flag) ? ambiguity_coord_lat : p_station->coord_lat,
+ p_station->course,
+ p_station->bearing,
+ p_station->NRQ,
+ trail_colors[p_station->df_color],
+ Display_.df_beamwidth_data, Display_.df_bearing_data,
+ temp_sec_heard,
+ drawing_target);
+ }
+
+ // Check whether to draw dead-reckoning data by KJ5O
+ if (Display_.dr_data
+ && ( (p_station->flag & ST_MOVING)
+// && (p_station->newest_trackpoint!=0
+ && course_ok
+ && speed_ok
+ && scale_y < 8000
+ && atof(dr_speed) > 0) ) {
+
+ // Does it make sense to try to do dead-reckoning on an
+ // object that has position ambiguity enabled? I don't
+ // think so!
+ //
+ if ( ! ambiguity_flag && ( (secs_now-temp_sec_heard) < dead_reckoning_timeout) ) {
+
+ draw_deadreckoning_features(p_station,
+ drawing_target,
+ w);
+ }
+ }
+
+ if (p_station->aprs_symbol.area_object.type != AREA_NONE) {
+ draw_area( (ambiguity_flag) ? ambiguity_coord_lon : p_station->coord_lon,
+ (ambiguity_flag) ? ambiguity_coord_lat : p_station->coord_lat,
+ p_station->aprs_symbol.area_object.type,
+ p_station->aprs_symbol.area_object.color,
+ p_station->aprs_symbol.area_object.sqrt_lat_off,
+ p_station->aprs_symbol.area_object.sqrt_lon_off,
+ p_station->aprs_symbol.area_object.corridor_width,
+ temp_sec_heard,
+ drawing_target);
+ }
+
+
+ // Draw additional stuff if this is the tracked station
+ if (is_tracked_station(p_station->call_sign)) {
+//WE7U
+ draw_pod_circle( (ambiguity_flag) ? ambiguity_coord_lon : p_station->coord_lon,
+ (ambiguity_flag) ? ambiguity_coord_lat : p_station->coord_lat,
+ 0.0020 * scale_y,
+ colors[0x0e], // Yellow
+ drawing_target);
+ draw_pod_circle( (ambiguity_flag) ? ambiguity_coord_lon : p_station->coord_lon,
+ (ambiguity_flag) ? ambiguity_coord_lat : p_station->coord_lat,
+ 0.0023 * scale_y,
+ colors[0x44], // Red
+ drawing_target);
+ draw_pod_circle( (ambiguity_flag) ? ambiguity_coord_lon : p_station->coord_lon,
+ (ambiguity_flag) ? ambiguity_coord_lat : p_station->coord_lat,
+ 0.0026 * scale_y,
+ colors[0x61], // Blue
+ drawing_target);
+ }
+
+
+ // Draw additional stuff if this is a storm and the weather data
+ // is not too old to display.
+ if ( (weather != NULL) && weather->wx_storm && !wx_ghost ) {
+ char temp[4];
+
+
+ //fprintf(stderr,"Plotting a storm symbol:%s:%s:%s:\n",
+ // weather->wx_hurricane_radius,
+ // weather->wx_trop_storm_radius,
+ // weather->wx_whole_gale_radius);
+
+// Still need to draw the circles in different colors for the
+// different ranges. Might be nice to tint it as well.
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ weather->wx_hurricane_radius);
+
+ if ( (temp[0] != '\0') && (strncmp(temp,"000",3) != 0) ) {
+
+ draw_pod_circle( (ambiguity_flag) ? ambiguity_coord_lon : p_station->coord_lon,
+ (ambiguity_flag) ? ambiguity_coord_lat : p_station->coord_lat,
+ atof(temp) * 1.15078, // nautical miles to miles
+ colors[0x44], // Red
+ drawing_target);
+ }
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ weather->wx_trop_storm_radius);
+
+ if ( (temp[0] != '\0') && (strncmp(temp,"000",3) != 0) ) {
+ draw_pod_circle( (ambiguity_flag) ? ambiguity_coord_lon : p_station->coord_lon,
+ (ambiguity_flag) ? ambiguity_coord_lat : p_station->coord_lat,
+ atof(temp) * 1.15078, // nautical miles to miles
+ colors[0x0e], // Yellow
+ drawing_target);
+ }
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ weather->wx_whole_gale_radius);
+
+ if ( (temp[0] != '\0') && (strncmp(temp,"000",3) != 0) ) {
+ draw_pod_circle( (ambiguity_flag) ? ambiguity_coord_lon : p_station->coord_lon,
+ (ambiguity_flag) ? ambiguity_coord_lat : p_station->coord_lat,
+ atof(temp) * 1.15078, // nautical miles to miles
+ colors[0x0a], // Green
+ drawing_target);
+ }
+ }
+
+
+ // Draw wind barb if selected and we have wind, but not a severe
+ // storm (wind barbs just confuse the matter).
+ if (Display_.weather && Display_.wind_barb
+ && weather != NULL && atoi(weather->wx_speed) >= 5
+ && !weather->wx_storm
+ && !wx_ghost ) {
+ draw_wind_barb( (ambiguity_flag) ? ambiguity_coord_lon : p_station->coord_lon,
+ (ambiguity_flag) ? ambiguity_coord_lat : p_station->coord_lat,
+ weather->wx_speed,
+ weather->wx_course,
+ temp_sec_heard,
+ drawing_target);
+ }
+
+
+// WE7U
+ //
+ // Draw truncation/rounding rectangles plus error ellipses.
+ //
+//
+// We need to keep track of ellipse northing/easting radii plus
+// rectangle northing/easting offsets. If both sets are present
+// we'll need to draw the summation of both geometric figures.
+// Check that the math works at/near the poles. We may need to keep
+// track of truncation/rounding rectangles separately if some
+// devices or software use one method, some the other.
+//
+ if (!ambiguity_flag) {
+
+ // Check whether we're at a close enough zoom level to have
+ // the ellipses/rectangles be visible, else skip drawing for
+ // efficiency.
+ //
+//fprintf(stderr,"scale_y: %ld\t", scale_y);
+ if (scale_y < 17) { // 60' figures are good out to about zoom 16
+
+// Here we may have to check what type of device is being used (if
+// possible to determine) to decide whether to draw a truncation/
+// rounding rectangles or GPS error ellipses. Truncation rectangles
+// have the symbol at one corner, rounding have it in the middle.
+// Based on the precision inherent in the packet we wish to draw a
+// GPS error ellipse instead, the decision point is when the packet
+// precision is adequate to show ~6 meters.
+//
+// OpenTracker APRS: Truncation, rectangle
+// OpenTracker Base91:Truncation, ellipse
+// OpenTracker OpenTrac: Truncation, ellipse
+// TinyTrak APRS: Truncation, rectangle
+// TinyTrak NMEA: Truncation, ellipse/rectangle based on precision
+// TinyTrak Mic-E: Truncation, rectangle
+// GPGGA: Truncation, ellipse/rectangle based on precision/HDOP/Augmentation
+// GPRMC: Truncation, ellipse/rectangle based on precision
+// GPGLL: Truncation, ellipse/rectangle based on precision
+// Xastir APRS: Truncation, rectangle
+// Xastir Base91: Truncation, ellipse
+// UI-View APRS: ??, rectangle
+// UI-View Base91: ??, ellipse
+// APRS+SA APRS: ??, rectangle
+// APRS+SA Base91: ??, ellipse
+// PocketAPRS: ??, rectangle
+// SmartAPRS: ??, rectangle
+// HamHUD: Truncation, ??
+// HamHUD GPRMC: Truncation, ellipse/rectangle based on precision
+// Linksys NSLU2: ??, rectangle
+// AGW Tracker: ??, ??
+// APRSPoint: ??, rectangle
+// APRSce: ??, rectangle
+// APRSdos APRS: ??, rectangle
+// APRSdos Base91: ??, ellipse
+// BalloonTrack: ??, ??
+// DMapper: ??, ??
+// JavAPRS APRS: ??, rectangle
+// JavAPRS Base91: ??, ellipse
+// WinAPRS APRS: ??, rectangle
+// WinAPRS Base91: ??, ellipse
+// MacAPRS APRS: ??, rectangle
+// MacAPRS Base91: ??, ellipse
+// MacAPRSOSX APRS: ??, rectangle
+// MacAPRSOSX Base91: ??, ellipse
+// X-APRS APRS: ??, rectangle
+// X-APRS Base91: ??, ellipse
+// OziAPRS: ??, rectangle
+// NetAPRS: ??, rectangle
+// APRS SCS: ??, ??
+// RadioMobile: ??, rectangle
+// KPC-3: ??, rectangle
+// MicroTNC: ??, rectangle
+// TigerTrak: ??, rectangle
+// PicoPacket: ??, rectangle
+// MIM: ??, rectangle
+// Mic-Encoder: ??, rectangle
+// Pic-Encoder: ??, rectangle
+// Generic Mic-E: ??, rectangle
+// D7A/D7E: ??, rectangle
+// D700A: ??, rectangle
+// Alinco DR-135: ??, rectangle
+// Alinco DR-620: ??, rectangle
+// Alinco DR-635: ??, rectangle
+// Other: ??, ??
+
+
+ // Initial try at drawing the error_ellipse_radius
+ // circles around the posit. error_ellipse_radius is in
+ // centimeters. Convert from cm to miles for
+ // draw_pod_circle().
+ //
+/*
+ draw_pod_circle( p_station->coord_lon,
+ p_station->coord_lat,
+ p_station->error_ellipse_radius / 100000.0 * 0.62137, // cm to mi
+ colors[0x0f], // White
+ drawing_target);
+*/
+ draw_precision_rectangle( p_station->coord_lon,
+ p_station->coord_lat,
+ p_station->error_ellipse_radius, // centimeters (not implemented yet)
+ p_station->lat_precision, // 100ths of seconds latitude
+ p_station->lon_precision, // 100ths of seconds longitude
+ colors[0x0f], // White
+ drawing_target);
+
+
+// Perhaps draw vectors from the symbol out to the borders of these
+// odd figures? Draw an outline without vectors to the symbol?
+// Have the color match the track color assigned to that station so
+// the geometric figures can be kept separate from nearby stations?
+//
+// draw_truncation_rectangle + error_ellipse (symbol at corner)
+// draw_rounding_rectangle + error_ellipse (symbol in middle)
+
+ }
+ }
+
+ // Zero out the variable in case we don't use it below.
+ temp2_my_gauge_data[0] = '\0';
+
+ // If an H2O object, create a timestamp + last comment variable
+ // (which should contain gage-height and/or water-flow numbers)
+ // for use in the draw_symbol() function below.
+ if (p_station->aprs_symbol.aprs_type == '/'
+ && p_station->aprs_symbol.aprs_symbol == 'w'
+ && ( p_station->flag & ST_OBJECT // And it's an object
+ || p_station->flag & ST_ITEM) ) { // or an item
+
+// NOTE: Also check whether it was sent by the Firenet GAGE
+// script?? "GAGE-*"
+
+// NOTE: Check most recent comment time against
+// p_station->sec_heard. If they don't match, don't display the
+// comment. This will make sure that older comment data doesn't get
+// displayed which can be quite misleading for stream gauges.
+
+ // Check whether we have any comment data at all. If so,
+ // the first one will be the most recent comment and the one
+ // we wish to display.
+ if (p_station->comment_data != NULL) {
+ CommentRow *ptr;
+// time_t sec;
+// struct tm *time;
+
+
+ ptr = p_station->comment_data;
+
+ // Check most recent comment's sec_heard time against
+ // the station record's sec_heard time. If they don't
+ // match, don't display the comment. This will make
+ // sure that older comment data doesn't get displayed
+ // which can be quite misleading for stream gauges.
+ if (p_station->sec_heard == ptr->sec_heard) {
+
+ // Note that text_ptr can be an empty string.
+ // That's ok.
+
+ // Also print the sec_heard timestamp so we know
+ // when this particular gauge data was received
+ // (Very important!).
+// sec = ptr->sec_heard;
+// time = localtime(&sec);
+
+ xastir_snprintf(temp2_my_gauge_data,
+ sizeof(temp2_my_gauge_data),
+ "%s",
+// "%02d/%02d %02d:%02d %s",
+// time->tm_mon + 1,
+// time->tm_mday,
+// time->tm_hour,
+// time->tm_min,
+ ptr->text_ptr);
+//fprintf(stderr, "%s\n", temp2_my_gauge_data);
+ }
+ }
+ }
+
+ draw_symbol(w,
+ p_station->aprs_symbol.aprs_type,
+ p_station->aprs_symbol.aprs_symbol,
+ p_station->aprs_symbol.special_overlay,
+ (ambiguity_flag) ? ambiguity_coord_lon : p_station->coord_lon,
+ (ambiguity_flag) ? ambiguity_coord_lat : p_station->coord_lat,
+ temp_call,
+ temp_altitude,
+ temp_course, // ??
+ temp_speed, // ??
+ temp_my_distance,
+ temp_my_course,
+// Display only if wx temp is current
+ (wx_ghost) ? "" : temp_wx_temp,
+// Display only if wind speed is current
+ (wx_ghost) ? "" : temp_wx_wind,
+ temp_sec_heard,
+ temp_show_last_heard,
+ drawing_target,
+ orient,
+ p_station->aprs_symbol.area_object.type,
+ p_station->signpost,
+ temp2_my_gauge_data,
+ 1); // Increment "currently_selected_stations"
+
+ // If it's a Waypoint symbol, draw a line from it to the
+ // transmitting station.
+ if (p_station->aprs_symbol.aprs_type == '\\'
+ && p_station->aprs_symbol.aprs_symbol == '/') {
+
+ draw_WP_line(p_station,
+ ambiguity_flag,
+ ambiguity_coord_lon,
+ ambiguity_coord_lat,
+ drawing_target,
+ w);
+ }
+
+ // Draw other points associated with the station, if any.
+ // KG4NBB
+ if (debug_level & 128)
+ fprintf(stderr," Number of multipoints = %d\n",p_station->num_multipoints);
+ if (p_station->num_multipoints != 0) {
+ draw_multipoints( (ambiguity_flag) ? ambiguity_coord_lon : p_station->coord_lon,
+ (ambiguity_flag) ? ambiguity_coord_lat : p_station->coord_lat,
+ p_station->num_multipoints,
+ p_station->multipoint_data->multipoints,
+ p_station->type, p_station->style,
+ temp_sec_heard,
+ drawing_target);
+ }
+
+ temp_sec_heard = p_station->sec_heard; // DK7IN: ???
+
+ if (Display_.phg
+ && (!(p_station->flag & ST_MOVING) || Display_.phg_of_moving)) {
+
+ // Check for Map View "eyeball" symbol
+ if ( strncmp(p_station->power_gain,"RNG",3) == 0
+ && p_station->aprs_symbol.aprs_type == '/'
+ && p_station->aprs_symbol.aprs_symbol == 'E' ) {
+ // Map View "eyeball" symbol. Don't draw the RNG ring
+ // for it.
+ }
+ else if (strlen(p_station->power_gain) == 7) {
+ // Station has PHG or RNG defined
+ //
+ draw_phg_rng( (ambiguity_flag) ? ambiguity_coord_lon : p_station->coord_lon,
+ (ambiguity_flag) ? ambiguity_coord_lat : p_station->coord_lat,
+ p_station->power_gain,
+ temp_sec_heard,
+ drawing_target);
+ }
+ else if (Display_.default_phg && !(p_station->flag & (ST_OBJECT | ST_ITEM))) {
+ // No PHG defined and not an object/item. Display a PHG
+ // of 3130 as default as specified in the spec: 9W, 3dB
+ // omni at 20 feet = 6.2 mile PHG radius.
+ //
+ draw_phg_rng( (ambiguity_flag) ? ambiguity_coord_lon : p_station->coord_lon,
+ (ambiguity_flag) ? ambiguity_coord_lat : p_station->coord_lat,
+ "PHG3130",
+ temp_sec_heard,
+ drawing_target);
+ }
+ }
+
+
+ // Draw minimum proximity circle?
+ if (p_station->probability_min[0] != '\0') {
+ double range = atof(p_station->probability_min);
+
+ // Draw red circle
+ draw_pod_circle(p_station->coord_lon,
+ p_station->coord_lat,
+ range,
+ colors[0x44],
+ drawing_target);
+ }
+
+ // Draw maximum proximity circle?
+ if (p_station->probability_max[0] != '\0') {
+ double range = atof(p_station->probability_max);
+
+ // Draw red circle
+ draw_pod_circle(p_station->coord_lon,
+ p_station->coord_lat,
+ range,
+ colors[0x44],
+ drawing_target);
+ }
+
+// DEBUG STUFF
+// draw_pod_circle(x_long, y_lat, 1.5, colors[0x44], where);
+// draw_pod_circle(x_long, y_lat, 3.0, colors[0x44], where);
+
+
+ // Now if we just did the single drawing, we want to go back and draw
+ // the same things onto pixmap_final so that when we do update from it
+ // to the screen all of the stuff will be there.
+// if (drawing_target == XtWindow(da)) {
+// drawing_target = pixmap_final;
+// goto _do_the_drawing;
+// }
+}
+
+
+
+
+
+// draw line relative
+void draw_test_line(Widget w, long x, long y, long dx, long dy, long ofs) {
+
+ x += screen_width - 10 - ofs;
+ y += screen_height - 10;
+ (void)XDrawLine(XtDisplay(w),
+ pixmap_final,
+ gc,
+ l16(x),
+ l16(y),
+ l16(x+dx),
+ l16(y+dy));
+}
+
+
+
+
+
+// draw text
+void draw_ruler_text(Widget w, char * text, long ofs) {
+ int x,y;
+ int len;
+
+ len = (int)strlen(text);
+ x = screen_width - 10 - ofs / 2;
+ y = screen_height - 10;
+ x -= len * 3;
+ y -= 3;
+ if (draw_labeled_grid_border==TRUE) {
+ // move text up a few pixels to leave space for labeled border
+ y = y - 15;
+ x = x - 10;
+ }
+ draw_nice_string(w,pixmap_final,letter_style,x,y,text,0x10,0x20,len);
+}
+
+
+
+
+
+// Compute Range Scale in miles or kilometers.
+//
+// For this we need to figure out x-distance and y-distance across
+// the screen. Take the smaller of the two, then figure out which
+// power of 2 miles fits from the center to the edge of the screen.
+// "For metric, use the nearest whole number kilometer in powers of
+// two of 1.5 km above the 1 mile scale. At 1 mile and below, do
+// the conversion to meters where 1 mi is equal to 1600m..." (Bob
+// Bruninga's words).
+void draw_range_scale(Widget w) {
+ Dimension width, height;
+ long x, x0, y, y0;
+ double x_miles_km, y_miles_km, distance;
+ char temp_course[10];
+ long temp;
+ double temp2;
+ long range;
+ int small_flag = 0;
+ int x_screen, y_screen;
+ int len;
+ char text[80];
+ int border_offset = 0; // number of pixels to offset the scale if a labeled map border is drawn
+
+
+ // Find out the screen values
+ XtVaGetValues(da,XmNwidth, &width, XmNheight, &height, NULL);
+
+ // Convert points to Xastir coordinate system
+
+ // X
+ x = center_longitude - ((width *scale_x)/2);
+ x0 = center_longitude; // Center of screen
+
+ // Y
+ y = center_latitude - ((height*scale_y)/2);
+ y0 = center_latitude; // Center of screen
+
+ // Compute distance from center to each edge
+
+ // X distance. Keep Y constant.
+ x_miles_km = cvt_kn2len * calc_distance_course(y0,x0,y0,x,temp_course,sizeof(temp_course));
+
+ // Y distance. Keep X constant.
+ y_miles_km = cvt_kn2len * calc_distance_course(y0,x0,y,x0,temp_course,sizeof(temp_course));
+
+ // Choose the smaller distance
+ if (x_miles_km < y_miles_km) {
+ distance = x_miles_km;
+ }
+ else {
+ distance = y_miles_km;
+ }
+
+ // Convert it to nearest power of two that fits inside
+
+ if (english_units) { // English units
+ if (distance >= 1.0) {
+ // Shift it right until it is less than 2.
+ temp = (long)distance;
+ range = 1;
+ while (temp >= 2) {
+ temp = temp / 2;
+ range = range * 2;
+ }
+ }
+ else { // Distance is less than one
+ // divide 1.0 by 2 until distance is greater
+ small_flag++;
+ temp2 = 1.0;
+ range = 1;
+ while (temp2 > distance) {
+ //fprintf(stderr,"temp2: %f, distance: %f\n", temp2, distance);
+ temp2 = temp2 / 2.0;
+ range = range * 2;
+ }
+ }
+ }
+ else { // Metric units
+ if (distance >= 12800.0)
+ range = 12800;
+ else if (distance >= 6400.0)
+ range = 6400;
+ else if (distance >= 3200.0)
+ range = 3200;
+ else if (distance >= 1600.0)
+ range = 1600;
+ else if (distance >= 800.0)
+ range = 800;
+ else if (distance >= 400.0)
+ range = 400;
+ else if (distance >= 200.0)
+ range = 200;
+ else if (distance >= 100.0)
+ range = 100;
+ else if (distance >= 50.0)
+ range = 50;
+ else if (distance >= 25.0)
+ range = 25;
+ else if (distance >= 12.0)
+ range = 12;
+ else if (distance >= 6.0)
+ range = 6;
+ else if (distance >= 3.0)
+ range = 3;
+ else {
+ small_flag++;
+ if (distance >= 1.6)
+ range = 1600;
+ else if (distance >= 0.8)
+ range = 800;
+ else if (distance >= 0.4)
+ range = 400;
+ else if (distance >= 0.2)
+ range = 200;
+ else if (distance >= 0.1)
+ range = 100;
+ else if (distance >= 0.05)
+ range = 50;
+ else if (distance >= 0.025)
+ range = 25;
+ else range = 12;
+ }
+ }
+
+ //fprintf(stderr,"Distance: %f\t", distance);
+ //fprintf(stderr,"Range: %ld\n", range);
+
+ if (english_units) { // English units
+ if (small_flag) {
+ xastir_snprintf(text,
+ sizeof(text),
+ "%s 1/%ld mi",
+ langcode("RANGE001"), // "RANGE SCALE"
+ range);
+ }
+ else {
+ xastir_snprintf(text,
+ sizeof(text),
+ "%s %ld mi",
+ langcode("RANGE001"), // "RANGE SCALE"
+ range);
+ }
+ }
+ else { // Metric units
+ if (small_flag) {
+ xastir_snprintf(text,
+ sizeof(text),
+ "%s %ld m",
+ langcode("RANGE001"), // "RANGE SCALE"
+ range);
+ }
+ else {
+ xastir_snprintf(text,
+ sizeof(text),
+ "%s %ld km",
+ langcode("RANGE001"), // "RANGE SCALE"
+ range);
+ }
+ }
+
+ // Draw it on the screen
+ len = (int)strlen(text);
+ x_screen = 10;
+ y_screen = screen_height - 5;
+ if ((draw_labeled_grid_border==TRUE) && long_lat_grid) {
+ border_offset = get_rotated_label_text_length_pixels(w, "0", FONT_BORDER) + 3;
+ // don't draw range scale right on top of labeled border, move into map
+ draw_nice_string(w,pixmap_final,letter_style,x_screen+border_offset,y_screen-border_offset-3,text,0x10,0x20,len);
+ }
+ else {
+ // draw range scale in lower left corder of map
+ draw_nice_string(w,pixmap_final,letter_style,x_screen,y_screen,text,0x10,0x20,len);
+ }
+
+}
+
+
+
+
+
+/*
+ * Calculate and draw ruler on right bottom of screen
+ */
+void draw_ruler(Widget w) {
+ int ruler_pix; // min size of ruler in pixel
+ char unit[5+1]; // units
+ char text[20]; // ruler text
+ double ruler_siz; // len of ruler in meters etc.
+ int mag;
+ int i;
+ int dx, dy;
+ int border_offset = 0; // number of pixels to offset the scale if a labeled map border is drawn
+
+ ruler_pix = (int)(screen_width / 9); // ruler size (in pixels)
+ ruler_siz = ruler_pix * scale_x * calc_dscale_x(center_longitude,center_latitude); // size in meter
+
+ if(english_units) {
+ if (ruler_siz > 1609.3/2) {
+ xastir_snprintf(unit,
+ sizeof(unit),
+ "mi");
+ ruler_siz /= 1609.3;
+ }
+ else {
+ xastir_snprintf(unit,
+ sizeof(unit),
+ "ft");
+ ruler_siz /= 0.3048;
+ }
+ }
+ else {
+ xastir_snprintf(unit,
+ sizeof(unit),
+ "m");
+ if (ruler_siz > 1000/2) {
+ xastir_snprintf(unit,
+ sizeof(unit),
+ "km");
+ ruler_siz /= 1000.0;
+ }
+ }
+
+ mag = 1;
+ while (ruler_siz > 5.0) { // get magnitude
+ ruler_siz /= 10.0;
+ mag *= 10;
+ }
+ // select best value and adjust ruler length
+ if (ruler_siz > 2.0) {
+ ruler_pix = (int)(ruler_pix * 5.0 / ruler_siz +0.5);
+ ruler_siz = 5.0 * mag;
+ }
+ else {
+ if (ruler_siz > 1.0) {
+ ruler_pix = (int)(ruler_pix * 2.0 / ruler_siz +0.5);
+ ruler_siz = 2.0 * mag;
+ }
+ else {
+ ruler_pix = (int)(ruler_pix * 1.0 / ruler_siz +0.5);
+ ruler_siz = 1.0 * mag;
+ }
+ }
+ xastir_snprintf(text, sizeof(text), "%.0f %s",ruler_siz,unit); // Set up string
+ //fprintf(stderr,"Ruler: %s, %d\n",text,ruler_pix);
+
+ (void)XSetLineAttributes(XtDisplay(w),gc,1,LineSolid,CapRound,JoinRound);
+ (void)XSetForeground(XtDisplay(w),gc,colors[0x20]); // white
+ for (i = 8; i >= 0; i--) {
+ dx = (((i / 3)+1) % 3)-1; // looks complicated...
+ dy = (((i % 3)+1) % 3)-1; // I want 0 / 0 as last entry
+ if ((draw_labeled_grid_border==TRUE) && long_lat_grid) {
+ // move ruler up a few pixels to leave space for labeled border
+ border_offset = get_rotated_label_text_length_pixels(w, "0", FONT_BORDER) + 3;
+ dy = dy - border_offset - 3;
+ dx = dx - border_offset - 3;
+ }
+
+ // If text on black background style selected, draw a black
+ // rectangle in that corner of the map first so that the
+ // scale lines show up well.
+ //
+ // If first time through and text-on-black style
+ if ( (i == 8) && (letter_style == 2) ) {
+ XSetForeground(XtDisplay(w),gc,colors[0x10]); // black
+ (void)XSetLineAttributes(XtDisplay(w),gc,20,LineSolid,CapProjecting,JoinMiter);
+ draw_test_line(w, dx, dy+5, ruler_pix, 0, ruler_pix);
+
+ // Reset to needed parameters for drawing the scale
+ (void)XSetLineAttributes(XtDisplay(w),gc,1,LineSolid,CapRound,JoinRound);
+ (void)XSetForeground(XtDisplay(w),gc,colors[0x20]); // white
+ }
+
+ if (i == 0)
+ (void)XSetForeground(XtDisplay(w),gc,colors[0x10]); // black
+
+ draw_test_line(w,dx,dy, ruler_pix,0,ruler_pix); // hor line
+ draw_test_line(w,dx,dy, 0,5, ruler_pix); // ver left
+ draw_test_line(w,dx+ruler_pix,dy, 0,5, ruler_pix); // ver right
+ if (text[0] == '2')
+ draw_test_line(w,dx+0.5*ruler_pix,dy,0,3,ruler_pix); // ver middle
+
+ if (text[0] == '5') {
+ draw_test_line(w,dx+0.2*ruler_pix,dy,0,3,ruler_pix); // ver middle
+ draw_test_line(w,dx+0.4*ruler_pix,dy,0,3,ruler_pix); // ver middle
+ draw_test_line(w,dx+0.6*ruler_pix,dy,0,3,ruler_pix); // ver middle
+ draw_test_line(w,dx+0.8*ruler_pix,dy,0,3,ruler_pix); // ver middle
+ }
+ }
+
+ draw_ruler_text(w,text,ruler_pix);
+
+ draw_range_scale(w);
+}
+
+
+
+
+
+/*
+ * Display all stations on screen (trail, symbol, info text)
+ */
+void display_file(Widget w) {
+ DataRow *p_station; // pointer to station data
+ time_t temp_sec_heard; // time last heard
+ time_t t_clr, t_old, now;
+
+ if(debug_level & 1)
+ fprintf(stderr,"Display File Start\n");
+
+ // Keep track of how many station we are currently displaying on
+ // the screen. We'll display this number and the total number
+ // of objects in the database as displayed/total on the status
+ // line. Each time we call display_station() we'll bump this
+ // number.
+ currently_selected_stations = 0;
+
+// Draw probability of detection circle, if enabled
+//draw_pod_circle(64000000l, 32400000l, 10, colors[0x44], pixmap_final);
+
+ now = sec_now();
+ t_old = now - sec_old; // precalc compare times
+ t_clr = now - sec_clear;
+ temp_sec_heard = 0l;
+ p_station = t_oldest; // start with oldest station, have newest on top at t_newest
+
+ while (p_station != NULL) {
+
+ if (debug_level & 64) {
+ fprintf(stderr,"display_file: Examining %s\n", p_station->call_sign);
+ }
+
+ // Skip deleted stations
+ if ( !(p_station->flag & ST_ACTIVE) ) {
+
+ if (debug_level & 64) {
+ fprintf(stderr,"display_file: ignored deleted %s\n", p_station->call_sign);
+ }
+
+ // Skip to the next station in the list
+ p_station = p_station->t_newer; // next station
+ continue;
+ }
+
+ // Check for my objects/items
+// if ( (is_my_call(p_station->origin, 1) // If station is owned by me (including SSID)
+// && ( p_station->flag & ST_OBJECT // And it's an object
+// || p_station->flag & ST_ITEM) ) ) { // or an item
+//
+ // This case is covered by the is_my_station() call, so we
+ // don't need it here.
+// if (is_my_object_item(p_station) ) {
+// temp_sec_heard = now;
+// }
+// else {
+ // Callsign match here includes checking SSID
+// temp_sec_heard = (is_my_call(p_station->call_sign,1))? now: p_station->sec_heard;
+ temp_sec_heard = (is_my_station(p_station)) ? now : p_station->sec_heard;
+// }
+
+ // Skip far away station
+ if ((p_station->flag & ST_INVIEW) == 0) {
+ // we make better use of the In View flag in the future
+
+ if (debug_level & 256) {
+ fprintf(stderr,"display_file: Station outside viewport\n");
+ }
+
+ // Skip to the next station in the list
+ p_station = p_station->t_newer; // next station
+ continue;
+ }
+
+ // Skip if we're running an altnet and this station's not in
+ // it
+ if ( altnet && !is_altnet(p_station) ) {
+
+ if (debug_level & 64) {
+ fprintf(stderr,"display_file: Station %s skipped altnet\n",
+ p_station->call_sign);
+ }
+
+ // Skip to the next station in the list
+ p_station = p_station->t_newer; // next station
+ continue;
+ }
+
+ if (debug_level & 256) {
+ fprintf(stderr,"display_file: Inview, check for trail\n");
+ }
+
+ // Display trail if we should
+ if (Display_.trail && p_station->newest_trackpoint != NULL) {
+ // ???????????? what is the difference? :
+
+ if (debug_level & 256) {
+ fprintf(stderr,"%s: Trails on and have track data\n",
+ "display_file");
+ }
+
+ if (temp_sec_heard > t_clr) {
+ // Not too old, so draw trail
+
+ if (temp_sec_heard > t_old) {
+ // New trail, so draw solid trail
+
+ if (debug_level & 256) {
+ fprintf(stderr,"Drawing Solid trail for %s, secs old: %ld\n",
+ p_station->call_sign,
+ (long)(now - temp_sec_heard) );
+ }
+ draw_trail(w,p_station,1);
+ }
+ else {
+
+ if (debug_level & 256) {
+ fprintf(stderr,"Drawing trail for %s, secs old: %ld\n",
+ p_station->call_sign,
+ (long)(now - temp_sec_heard) );
+ }
+ draw_trail(w,p_station,0);
+ }
+ }
+ else {
+ if (debug_level & 256) {
+ fprintf(stderr,"Station too old\n");
+ }
+ }
+ }
+ else {
+ if (debug_level & 256) {
+ fprintf(stderr,"Station trails %d, track data %lx\n",
+ Display_.trail, (long int)p_station->newest_trackpoint);
+ }
+ }
+
+ if (debug_level & 256)
+ fprintf(stderr,"calling display_station()\n");
+
+ // This routine will also update the
+ // currently_selected_stations variable, if we're
+ // updating all of the stations at once.
+ display_station(w,p_station,0);
+
+ p_station = p_station->t_newer; // next station
+ }
+
+ draw_ruler(w);
+
+ Draw_All_CAD_Objects(w); // Draw all CAD objects, duh.
+
+ // Check if we should mark where we found an address
+ if (mark_destination && show_destination_mark) {
+ int offset;
+
+ // Set the line width in the GC. Make it nice and fat.
+ (void)XSetLineAttributes (XtDisplay (w), gc_tint, 7, LineSolid, CapButt,JoinMiter);
+ (void)XSetForeground (XtDisplay (w), gc_tint, colors[0x27]);
+ (void)(void)XSetFunction (XtDisplay (da), gc_tint, GXxor);
+
+ // Scale it so that the 'X' stays the same size at all zoom
+ // levels.
+ offset = 25 * scale_y;
+
+ // Make a big 'X'
+ draw_vector(w,
+ destination_coord_lon-offset, // x1
+ destination_coord_lat-offset, // y1
+ destination_coord_lon+offset, // x2
+ destination_coord_lat+offset, // y2
+ gc_tint,
+ pixmap_final,
+ 0);
+
+ draw_vector(w,
+ destination_coord_lon+offset, // x1
+ destination_coord_lat-offset, // y1
+ destination_coord_lon-offset, // x2
+ destination_coord_lat+offset, // y2
+ gc_tint,
+ pixmap_final,
+ 0);
+ }
+
+ // And last, draw the ALOHA circle
+ if (Display_.aloha_circle) {
+ if (aloha_radius != -1) {
+ // if we actually have an aloha radius calculated already
+ long l_lat,l_lon;
+
+ l_lat = convert_lat_s2l(my_lat);
+ l_lon = convert_lon_s2l(my_long);
+ draw_aloha_circle(l_lon,
+ l_lat,
+ aloha_radius,
+ colors[0x0e],
+ pixmap_final);
+ }
+ }
+
+ // Check whether currently_selected_stations has changed. If
+ // so, set station_count_save to 0 so that main.c will come
+ // along and update the counts on the status line.
+ if (currently_selected_stations != currently_selected_stations_save) {
+ station_count_save = 0; // Cause an update to occur
+ }
+ currently_selected_stations_save = currently_selected_stations;
+
+
+ if (debug_level & 1)
+ fprintf(stderr,"Display File Stop\n");
+}
+
+
+
+
+
+////////////////////////////// Station Info /////////////////////////////////////
+
+
+
+
+
+/*
+ * Delete Station Info PopUp
+ */
+void Station_data_destroy_shell(/*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+
+begin_critical_section(&db_station_info_lock, "db.c:Station_data_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ db_station_info = (Widget)NULL;
+
+end_critical_section(&db_station_info_lock, "db.c:Station_data_destroy_shell" );
+
+}
+
+
+
+
+
+/*
+ * Store track data for current station
+ */
+void Station_data_store_track(Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ DataRow *p_station = clientData;
+
+ //busy_cursor(XtParent(w));
+ busy_cursor(appshell);
+
+ // Grey-out button so it doesn't get pressed twice
+ XtSetSensitive(button_store_track,FALSE);
+
+ // Store trail to file
+ export_trail(p_station);
+
+#ifdef HAVE_LIBSHP
+ // Save trail as a Shapefile map
+ create_map_from_trail(p_station->call_sign);
+#endif // HAVE_LIBSHP
+
+ // store trail to kml file
+ export_trail_as_kml(p_station);
+}
+
+
+
+
+
+/*
+ * Delete tracklog for current station
+ */
+void Station_data_destroy_track( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ DataRow *p_station = clientData;
+
+ if (delete_trail(p_station))
+ redraw_on_new_data = 2; // redraw immediately
+}
+
+
+
+
+
+// This function merely reformats the button callback in order to
+// call wx_alert_double_click_action, which expects the parameter in
+// calldata instead of in clientData.
+//
+void Station_data_wx_alert(Widget w, XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+//fprintf(stderr, "Station_data_wx_alert start\n");
+ wx_alert_finger_output( w, clientData);
+//fprintf(stderr, "Station_data_wx_alert end\n");
+}
+
+
+
+
+
+void Station_data_add_fcc(Widget w, XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ char temp[500];
+ FccAppl my_data;
+ char *station = (char *) clientData;
+
+ (void)check_fcc_data();
+ //busy_cursor(XtParent(w));
+ busy_cursor(appshell);
+ if (search_fcc_data_appl(station, &my_data)==1) {
+ /*fprintf(stderr,"FCC call %s\n",station);*/
+ xastir_snprintf(temp, sizeof(temp), "%s\n%s %s\n%s %s %s\n%s %s, %s %s, %s %s\n\n",
+ langcode("STIFCC0001"),
+ langcode("STIFCC0003"),my_data.name_licensee,
+ langcode("STIFCC0004"),my_data.text_street,my_data.text_pobox,
+ langcode("STIFCC0005"),my_data.city,
+ langcode("STIFCC0006"),my_data.state,
+ langcode("STIFCC0007"),my_data.zipcode);
+ XmTextInsert(si_text,0,temp);
+ XmTextShowPosition(si_text,0);
+
+ fcc_lookup_pushed = 1;
+ }
+}
+
+
+
+
+
+void Station_data_add_rac(Widget w, XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ char temp[512];
+ char club[512];
+ rac_record my_data;
+ char *station = (char *) clientData;
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ " ");
+ (void)check_rac_data();
+ //busy_cursor(XtParent(w));
+ busy_cursor(appshell);
+ if (search_rac_data(station, &my_data)==1) {
+ /*fprintf(stderr,"IC call %s\n",station);*/
+ xastir_snprintf(temp, sizeof(temp), "%s\n%s %s\n%s\n%s, %s\n%s\n",
+ langcode("STIFCC0002"),my_data.first_name,my_data.last_name,my_data.address,
+ my_data.city,my_data.province,my_data.postal_code);
+
+ if (my_data.qual_a[0] == 'A')
+ strncat(temp,
+ langcode("STIFCC0008"),
+ sizeof(temp) - 1 - strlen(temp));
+
+ if (my_data.qual_d[0] == 'D')
+ strncat(temp,
+ langcode("STIFCC0009"),
+ sizeof(temp) - 1 - strlen(temp));
+
+ if (my_data.qual_b[0] == 'B' && my_data.qual_c[0] != 'C')
+ strncat(temp,
+ langcode("STIFCC0010"),
+ sizeof(temp) - 1 - strlen(temp));
+
+ if (my_data.qual_c[0] == 'C')
+ strncat(temp,
+ langcode("STIFCC0011"),
+ sizeof(temp) - 1 - strlen(temp));
+
+ strncat(temp,
+ "\n",
+ sizeof(temp) - 1 - strlen(temp));
+
+ if (strlen(my_data.club_name) > 1){
+ xastir_snprintf(club, sizeof(club), "%s\n%s\n%s, %s\n%s\n",
+ my_data.club_name, my_data.club_address,
+ my_data.club_city, my_data.club_province, my_data.club_postal_code);
+ strncat(temp,
+ club,
+ sizeof(temp) - 1 - strlen(temp));
+ }
+ strncat(temp,
+ "\n",
+ sizeof(temp) - 1 - strlen(temp));
+ XmTextInsert(si_text,0,temp);
+ XmTextShowPosition(si_text,0);
+
+ rac_lookup_pushed = 1;
+ }
+}
+
+
+
+
+
+void Station_query_trace(/*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ char *station = (char *) clientData;
+ char temp[50];
+ char call[25];
+
+ pad_callsign(call,station);
+ xastir_snprintf(temp, sizeof(temp), ":%s:?APRST", call);
+
+// Nice to return via the reverse path here? No! Better to use the
+// default paths instead of a calculated reverse path.
+
+ transmit_message_data(station,temp,NULL);
+}
+
+
+
+
+
+void Station_query_messages(/*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ char *station = (char *) clientData;
+ char temp[50];
+ char call[25];
+
+ pad_callsign(call,station);
+ xastir_snprintf(temp, sizeof(temp), ":%s:?APRSM", call);
+
+// Nice to return via the reverse path here? No! Better to use the
+// default paths instead of a calculated reverse path.
+
+ transmit_message_data(station,temp,NULL);
+}
+
+
+
+
+
+void Station_query_direct(/*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ char *station = (char *) clientData;
+ char temp[50];
+ char call[25];
+
+ pad_callsign(call,station);
+ xastir_snprintf(temp, sizeof(temp), ":%s:?APRSD", call);
+
+// Nice to return via the reverse path here? No! Better to use the
+// default paths instead of a calculated reverse path.
+
+ transmit_message_data(station,temp,NULL);
+}
+
+
+
+
+
+void Station_query_version(/*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ char *station = (char *) clientData;
+ char temp[50];
+ char call[25];
+
+ pad_callsign(call,station);
+ xastir_snprintf(temp, sizeof(temp), ":%s:?VER", call);
+
+// Nice to return via the reverse path here? No! Better to use the
+// default paths instead of a calculated reverse path.
+
+ transmit_message_data(station,temp,NULL);
+}
+
+
+
+
+
+void General_query(/*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ char *location = (char *) clientData;
+ char temp[50];
+
+ xastir_snprintf(temp, sizeof(temp), "?APRS?%s", location);
+ output_my_data(temp,-1,0,0,0,NULL); // Not igating
+}
+
+
+
+
+
+void IGate_query(/*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ output_my_data("?IGATE?",-1,0,0,0,NULL); // Not igating
+}
+
+
+
+
+
+void WX_query(/*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ output_my_data("?WX?",-1,0,0,0,NULL); // Not igating
+}
+
+
+
+
+
+// Global variables for use with routines following
+Widget change_tactical_dialog = (Widget)NULL;
+Widget tactical_text = (Widget)NULL;
+DataRow *tactical_pointer = NULL;
+
+
+void Change_tactical_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ change_tactical_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Change_tactical_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ char *temp;
+
+ temp = XmTextGetString(tactical_text);
+
+ if (tactical_pointer->tactical_call_sign == NULL) {
+ // Malloc some memory to hold it.
+ tactical_pointer->tactical_call_sign = (char *)malloc(MAX_TACTICAL_CALL+1);
+ }
+
+ if (tactical_pointer->tactical_call_sign != NULL) {
+
+ // Check for blank tactical call. If so, free the space.
+ if (temp[0] == '\0') {
+ free(tactical_pointer->tactical_call_sign);
+ tactical_pointer->tactical_call_sign = NULL;
+ }
+ else {
+ xastir_snprintf(tactical_pointer->tactical_call_sign,
+ MAX_TACTICAL_CALL+1,
+ "%s",
+ temp);
+ }
+
+ fprintf(stderr,
+ "Assigned tactical call \"%s\" to %s\n",
+ temp,
+ tactical_pointer->call_sign);
+
+ // Log the change in the tactical_calls.log file.
+ // Also adds it to the tactical callsign hash here.
+ log_tactical_call(tactical_pointer->call_sign,
+ tactical_pointer->tactical_call_sign);
+ }
+ else {
+ fprintf(stderr,
+ "Couldn't malloc space for tactical callsign\n");
+ }
+
+ XtFree(temp);
+
+ redraw_on_new_data = 2; // redraw now
+
+ Change_tactical_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void Change_tactical(Widget w, XtPointer clientData, XtPointer callData) {
+ static Widget pane, my_form, button_ok, button_close, label;
+ Atom delw;
+ Arg al[50]; // Arg List
+ register unsigned int ac = 0; // Arg Count
+
+ if (!change_tactical_dialog) {
+ change_tactical_dialog =
+ XtVaCreatePopupShell(langcode("WPUPSTI065"),
+ xmDialogShellWidgetClass,
+ appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Change Tactical pane",
+ xmPanedWindowWidgetClass,
+ change_tactical_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Change Tactical my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 3,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ // set args for color
+ ac=0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ // Display the callsign or object/item name we're working on
+ // in a label at the top of the dialog. Otherwise we don't
+ // know what station we're operating on.
+ //
+ label = XtVaCreateManagedWidget(tactical_pointer->call_sign,
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tactical_text = XtVaCreateManagedWidget("Change_Tactical text",
+ xmTextWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, MAX_TACTICAL_CALL,
+ XmNwidth, ((MAX_TACTICAL_CALL*7)+2),
+ XmNmaxLength, MAX_TACTICAL_CALL,
+ XmNbackground, colors[0x0f],
+ XmNtopOffset, 5,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, label,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Fill in the current value of tactical callsign
+ XmTextSetString(tactical_text, tactical_pointer->tactical_call_sign);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tactical_text,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ button_close = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tactical_text,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok,
+ XmNactivateCallback,
+ Change_tactical_change_data,
+ change_tactical_dialog);
+ XtAddCallback(button_close,
+ XmNactivateCallback,
+ Change_tactical_destroy_shell,
+ change_tactical_dialog);
+
+ pos_dialog(change_tactical_dialog);
+
+ delw = XmInternAtom(XtDisplay(change_tactical_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(change_tactical_dialog, delw, Change_tactical_destroy_shell, (XtPointer)change_tactical_dialog);
+
+ XtManageChild(my_form);
+ XtManageChild(pane);
+
+ XtPopup(change_tactical_dialog,XtGrabNone);
+ fix_dialog_size(change_tactical_dialog);
+
+ // Move focus to the Close button. This appears to
+ // highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit
+ // the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(change_tactical_dialog);
+ XmProcessTraversal(button_close, XmTRAVERSE_CURRENT);
+
+ }
+ else {
+ (void)XRaiseWindow(XtDisplay(change_tactical_dialog),
+ XtWindow(change_tactical_dialog));
+ }
+}
+
+
+
+
+
+/*
+ * Assign a tactical call to a station
+ */
+void Assign_Tactical_Call( Widget w, XtPointer clientData, XtPointer calldata) {
+ DataRow *p_station = clientData;
+
+ //fprintf(stderr,"Object Name: %s\n", p_station->call_sign);
+ tactical_pointer = p_station;
+ Change_tactical(w, p_station, NULL);
+}
+
+
+
+
+
+/*
+ * Change the trail color for a station
+ */
+void Change_trail_color( Widget w, XtPointer clientData, XtPointer calldata) {
+ DataRow *p_station = clientData;
+ int temp;
+
+ temp = p_station->trail_color;
+
+ // Increment to the next color, round-robin style
+ temp = (temp + 1) % MAX_TRAIL_COLORS;
+
+ // Test for and skip if my trail color
+ if (temp == MY_TRAIL_COLOR) {
+ temp = (temp + 1) % MAX_TRAIL_COLORS;
+ }
+
+ p_station->trail_color = temp;
+
+ redraw_on_new_data = 2; // redraw symbols now
+}
+
+
+
+
+
+static void PosTestExpose(Widget parent, XtPointer clientData, XEvent *event, Boolean * continueToDispatch) {
+ Position x, y;
+
+ XtVaGetValues(parent, XmNx, &x, XmNy, &y, NULL);
+
+ if (debug_level & 1)
+ fprintf(stderr,"Window Decoration Offsets: X:%d\tY:%d\n", x, y);
+
+ // Store the new-found offets in global variables
+ decoration_offset_x = (int)x;
+ decoration_offset_y = (int)y;
+
+ // Get rid of the event handler and the test dialog
+ XtRemoveEventHandler(parent, ExposureMask, True, (XtEventHandler) PosTestExpose, (XtPointer)NULL);
+// XtRemoveGrab(XtParent(parent)); // Not needed?
+ XtDestroyWidget(XtParent(parent));
+}
+
+
+
+
+
+// Here's a stupid trick that we have to do in order to find out how big
+// window decorations are. We need to know this information in order to
+// be able to kill/recreate dialogs in the same place each time. If we
+// were to just get and set the X/Y values of the dialog, we would creep
+// across the screen by the size of the decorations each time.
+// I've seen it. It's ugly.
+//
+void compute_decorations( void ) {
+ Widget cdtest = (Widget)NULL;
+ Widget cdform = (Widget)NULL;
+ Cardinal n = 0;
+ Arg args[50];
+
+
+ // We'll create a dummy dialog at 0,0, then query its
+ // position. That'll give us back the position of the
+ // widget. Subtract 0,0 from it (easy huh?) and we get
+ // the size of the window decorations. Store these values
+ // in global variables for later use.
+
+ n = 0;
+ XtSetArg(args[n], XmNx, 0); n++;
+ XtSetArg(args[n], XmNy, 0); n++;
+
+ cdtest = (Widget) XtVaCreatePopupShell("compute_decorations test",
+ xmDialogShellWidgetClass,
+ appshell,
+ args, n,
+ NULL);
+
+ n = 0;
+ XtSetArg(args[n], XmNwidth, 0); n++; // Make it tiny
+ XtSetArg(args[n], XmNheight, 0); n++; // Make it tiny
+ cdform = XmCreateForm(cdtest, "compute_decorations test form", args, n);
+
+ XtAddEventHandler(cdform, ExposureMask, True, (XtEventHandler) PosTestExpose,
+ (XtPointer)NULL);
+
+ XtManageChild(cdform);
+ XtManageChild(cdtest);
+}
+
+
+
+
+
+// Enable/disable auto-update of Station_data dialog
+void station_data_auto_update_toggle ( /*@unused@*/ Widget widget, /*@unused@*/ XtPointer clientData, XtPointer callData) {
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ station_data_auto_update = 1;
+ else
+ station_data_auto_update = 0;
+}
+
+
+
+
+
+// Fill in the station data window with real data
+void station_data_fill_in ( /*@unused@*/ Widget w, XtPointer clientData, XtPointer calldata ) {
+ DataRow *p_station;
+ char *station = (char *) clientData;
+ char temp[300];
+ int pos, last_pos;
+ char temp_my_distance[20];
+ char temp_my_course[20];
+ char temp1_my_course[20];
+ float temp_out_C, e, humidex;
+ long l_lat, l_lon;
+ float value;
+ WeatherRow *weather;
+ time_t sec;
+ struct tm *time;
+ int i;
+ int track_count = 0;
+
+// Maximum tracks listed in Station Info dialog. This prevents
+// lockups on extremely long tracks.
+#define MAX_TRACK_LIST 50
+
+
+ db_station_info_callsign = (char *) clientData; // Used for auto-updating this dialog
+ temp_out_C=0;
+ pos=0;
+
+begin_critical_section(&db_station_info_lock, "db.c:Station_data" );
+
+ if (db_station_info == NULL) { // We don't have a dialog to write to
+
+end_critical_section(&db_station_info_lock, "db.c:Station_data" );
+
+ return;
+ }
+
+ if (!search_station_name(&p_station,station,1) // Can't find call,
+ || (p_station->flag & ST_ACTIVE) == 0) { // or found deleted objects
+
+end_critical_section(&db_station_info_lock, "db.c:Station_data" );
+
+ return;
+ }
+
+
+ // Clear the text
+ XmTextSetString(si_text,NULL);
+
+
+ // Weather Data ...
+ if (p_station->weather_data != NULL
+ // Make sure the timestamp on the weather is current
+ && (int)(((sec_old + p_station->weather_data->wx_sec_time)) >= sec_now()) ) {
+
+ last_pos = pos;
+
+ weather = p_station->weather_data;
+
+ pos += strlen(temp);
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI024"),weather->wx_type,weather->wx_station);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ sprintf(temp, "\n");
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ if (english_units)
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI026"),weather->wx_course,weather->wx_speed);
+ else
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI025"),weather->wx_course,(int)(atof(weather->wx_speed)*1.6094));
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ if (strlen(weather->wx_gust) > 0) {
+ if (english_units)
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI028"),weather->wx_gust);
+ else
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI027"),(int)(atof(weather->wx_gust)*1.6094));
+
+ strncat(temp,
+ "\n",
+ sizeof(temp) - 1 - strlen(temp));
+ }
+ else
+ xastir_snprintf(temp, sizeof(temp), "\n");
+
+ XmTextInsert(si_text, pos, temp);
+ pos += strlen(temp);
+
+ if (strlen(weather->wx_temp) > 0) {
+ if (english_units)
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI030"),weather->wx_temp);
+ else {
+ temp_out_C =(((atof(weather->wx_temp)-32)*5.0)/9.0);
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI029"),temp_out_C);
+ }
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ if (strlen(weather->wx_hum) > 0) {
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI031"),weather->wx_hum);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+// NOTE: The below (Humidex) is not coded for english units, only for metric.
+// What is Humidex anyway? Heat Index? Wind Chill? --we7u
+
+ // DK7IN: ??? english_units ???
+ if (strlen(weather->wx_hum) > 0
+ && strlen(weather->wx_temp) > 0
+ && (!english_units) &&
+ (atof(weather->wx_hum) > 0.0) ) {
+
+ e = (float)(6.112 * pow(10,(7.5 * temp_out_C)/(237.7 + temp_out_C)) * atof(weather->wx_hum) / 100.0);
+ humidex = (temp_out_C + ((5.0/9.0) * (e-10.0)));
+
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI032"),humidex);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ if (strlen(weather->wx_baro) > 0) {
+ if (!english_units) { // hPa
+ xastir_snprintf(temp, sizeof(temp),
+ langcode("WPUPSTI033"),
+ weather->wx_baro);
+ }
+ else { // Inches Mercury
+ xastir_snprintf(temp, sizeof(temp),
+ langcode("WPUPSTI063"),
+ atof(weather->wx_baro)*0.02953);
+ }
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+ else {
+ if(last_pos!=pos) {
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+ }
+
+ if (strlen(weather->wx_snow) > 0) {
+ if(english_units)
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI035"),atof(weather->wx_snow));
+ else
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI034"),atof(weather->wx_snow)*2.54);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ if (strlen(weather->wx_rain) > 0 || strlen(weather->wx_prec_00) > 0
+ || strlen(weather->wx_prec_24) > 0) {
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("WPUPSTI036"));
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ if (strlen(weather->wx_rain) > 0) {
+ if (english_units)
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI038"),atof(weather->wx_rain)/100.0);
+ else
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI037"),atof(weather->wx_rain)*.254);
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ if (strlen(weather->wx_prec_24) > 0) {
+ if(english_units)
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI040"),atof(weather->wx_prec_24)/100.0);
+ else
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI039"),atof(weather->wx_prec_24)*.254);
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ if (strlen(weather->wx_prec_00) > 0) {
+ if (english_units)
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI042"),atof(weather->wx_prec_00)/100.0);
+ else
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI041"),atof(weather->wx_prec_00)*.254);
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ if (strlen(weather->wx_rain_total) > 0) {
+ xastir_snprintf(temp, sizeof(temp), "\n%s",langcode("WPUPSTI046"));
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ if (english_units)
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI048"),atof(weather->wx_rain_total)/100.0);
+ else
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI047"),atof(weather->wx_rain_total)*.254);
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ // Fuel temp/moisture for RAWS weather stations
+ if (strlen(weather->wx_fuel_temp) > 0) {
+ if (english_units)
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI061"),weather->wx_fuel_temp);
+ else {
+ temp_out_C =(((atof(weather->wx_fuel_temp)-32)*5.0)/9.0);
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI060"),temp_out_C);
+ }
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ if (strlen(weather->wx_fuel_moisture) > 0) {
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI062"),weather->wx_fuel_moisture);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ xastir_snprintf(temp, sizeof(temp), "\n\n");
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+
+ // Packets received ...
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI005"),p_station->num_packets);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ p_station->packet_time);
+ temp[2]='/';
+ temp[3]='\0';
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ p_station->packet_time+2);
+ temp[2]='/';
+ temp[3]='\0';
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ p_station->packet_time+4);
+ temp[4]=' ';
+ temp[5]='\0';
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ p_station->packet_time+8);
+ temp[2]=':';
+ temp[3]='\0';
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ p_station->packet_time+10);
+ temp[2]=':';
+ temp[3]='\0';
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ p_station->packet_time+12);
+ temp[2]='\n';
+ temp[3]='\0';
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ // Object
+ if (strlen(p_station->origin) > 0) {
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI000"),p_station->origin);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ // Print the tactical call, if any
+ if (p_station->tactical_call_sign
+ && p_station->tactical_call_sign[0] != '\0') {
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI065"), p_station->tactical_call_sign);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ // Heard via TNC ...
+ if ((p_station->flag & ST_VIATNC) != 0) { // test "via TNC" flag
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI006"),p_station->heard_via_tnc_port);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+ else {
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("WPUPSTI007"));
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ switch(p_station->data_via) {
+ case('L'):
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("WPUPSTI008"));
+ break;
+
+ case('T'):
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI009"),p_station->last_port_heard);
+ break;
+
+ case('I'):
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI010"),p_station->last_port_heard);
+ break;
+
+ case('F'):
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("WPUPSTI011"));
+ break;
+
+ case(DATA_VIA_DATABASE):
+ xastir_snprintf(temp, sizeof(temp), "last via db on interface %d",p_station->last_port_heard);
+ break;
+
+ default:
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("WPUPSTI012"));
+ break;
+ }
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ if (p_station->newest_trackpoint != NULL) {
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("WPUPSTI013"));
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ // Echoed from: ...
+ // Callsign check here includes checking SSID
+// if (is_my_call(p_station->call_sign,1)) {
+ if ( is_my_station(p_station) ) {
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("WPUPSTI055"));
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ for (i=0;i<6;i++) {
+ if (echo_digis[i][0] == '\0')
+ break;
+
+ xastir_snprintf(temp, sizeof(temp), " %s",echo_digis[i]);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ // Data Path ...
+ if (p_station->node_path_ptr != NULL)
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI043"),p_station->node_path_ptr);
+ else
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI043"), "");
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ // Status ...
+ if(p_station->status_data != NULL) { // Found at least one record
+ CommentRow *ptr;
+
+ ptr = p_station->status_data;
+
+ while (ptr != NULL) {
+ // We don't care if the pointer is NULL. This will
+ // succeed anyway. It'll just make an empty string.
+
+ // Note that text_ptr may be an empty string. That's
+ // ok.
+
+ //Also print the sec_heard timestamp.
+ sec = ptr->sec_heard;
+ time = localtime(&sec);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ langcode("WPUPSTI059"),
+ time->tm_mon + 1,
+ time->tm_mday,
+ time->tm_hour,
+ time->tm_min,
+ ptr->text_ptr);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ xastir_snprintf(temp, sizeof(temp), "\n");
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ ptr = ptr->next; // Advance to next record (if any)
+ }
+ }
+
+
+// // Comments ...
+// if(strlen(p_station->comments)>0) {
+// xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI044"),p_station->comments);
+// XmTextInsert(si_text,pos,temp);
+// pos += strlen(temp);
+// xastir_snprintf(temp, sizeof(temp), "\n");
+// XmTextInsert(si_text,pos,temp);
+// pos += strlen(temp);
+// }
+
+ // Comments ...
+ if(p_station->comment_data != NULL) { // Found at least one record
+ CommentRow *ptr;
+
+ ptr = p_station->comment_data;
+
+ while (ptr != NULL) {
+ // We don't care if the pointer is NULL. This will
+ // succeed anyway. It'll just make an empty string.
+
+ // Note that text_ptr can be an empty string. That's
+ // ok.
+
+ //Also print the sec_heard timestamp.
+ sec = ptr->sec_heard;
+ time = localtime(&sec);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ langcode("WPUPSTI044"),
+ time->tm_mon + 1,
+ time->tm_mday,
+ time->tm_hour,
+ time->tm_min,
+ ptr->text_ptr);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ xastir_snprintf(temp, sizeof(temp), "\n");
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ ptr = ptr->next; // Advance to next record (if any)
+ }
+ }
+
+ // Current Power Gain ...
+ if (strlen(p_station->power_gain) == 7) {
+ // Check for RNG instead of PHG
+ if (p_station->power_gain[0] == 'R') {
+ // Found a Range
+ xastir_snprintf(temp,
+ sizeof(temp),
+ langcode("WPUPSTI067"),
+ atoi(&p_station->power_gain[3]));
+ }
+ else {
+ // Found PHG
+ phg_decode(langcode("WPUPSTI014"), // "Current Power Gain"
+ p_station->power_gain,
+ temp,
+ sizeof(temp) );
+ }
+
+ // Check for Map View symbol: Eyeball symbol with // RNG
+ // extension.
+ if ( strncmp(p_station->power_gain,"RNG",3) == 0
+ && p_station->aprs_symbol.aprs_type == '/'
+ && p_station->aprs_symbol.aprs_symbol == 'E' ) {
+
+//fprintf(stderr,"Found a Map View 'eyeball' symbol!\n");
+
+ // Center_Zoom() normally fills in the values with the
+ // current zoom/center for the map window. We want to
+ // be able to override these with our own values in this
+ // case, derived from the object info.
+ center_zoom_override++;
+ Center_Zoom(w,NULL,(XtPointer)p_station);
+ }
+ }
+ else if (p_station->flag & (ST_OBJECT | ST_ITEM)) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s %s",
+ langcode("WPUPSTI014"), // "Current Power Gain:"
+ langcode("WPUPSTI068") ); // "none"
+ }
+ else if (english_units) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s %s (9W @ 20ft %s, 3dB %s, %s 6.2mi)",
+ langcode("WPUPSTI014"), // "Current Power Gain:"
+ langcode("WPUPSTI069"), // "default"
+ langcode("WPUPSTI070"), // "HAAT"
+ langcode("WPUPSTI071"), // "omni"
+ langcode("WPUPSTI072") ); // "range"
+// "default (9W @ 20ft HAAT, 3dB omni, range 6.2mi)");
+ }
+ else {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s %s (9W @ 6.1m %s, 3dB %s, %s 10.0km)",
+ langcode("WPUPSTI014"), // "Current Power Gain:"
+ langcode("WPUPSTI069"), // "default"
+ langcode("WPUPSTI070"), // "HAAT"
+ langcode("WPUPSTI071"), // "omni"
+ langcode("WPUPSTI072") ); // "range"
+// "default (9W @ 6.1m HAAT, 3dB omni, range 10.0km)");
+
+ }
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ // Current DF Info ...
+ if (strlen(p_station->signal_gain) == 7) {
+ shg_decode(langcode("WPUPSTI057"), p_station->signal_gain, temp, sizeof(temp) );
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+ if (strlen(p_station->bearing) == 3) {
+ bearing_decode(langcode("WPUPSTI058"), p_station->bearing, p_station->NRQ, temp, sizeof(temp) );
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ // Signpost Data
+ if (strlen(p_station->signpost) > 0) {
+ xastir_snprintf(temp, sizeof(temp), "%s: %s",langcode("POPUPOB029"), p_station->signpost);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ // Altitude ...
+ last_pos=pos;
+ if (strlen(p_station->altitude) > 0) {
+ if (english_units)
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI016"),atof(p_station->altitude)*3.28084,"ft");
+ else
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI016"),atof(p_station->altitude),"m");
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ // Course ...
+ if (strlen(p_station->course) > 0) {
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI017"),p_station->course);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ // Speed ...
+ if (strlen(p_station->speed) > 0) {
+ if (english_units)
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI019"),atof(p_station->speed)*1.1508);
+
+ else
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI018"),atof(p_station->speed)*1.852);
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ if (last_pos!=pos) {
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ // Distance ...
+ last_pos = pos;
+
+ // do my course
+// if (!is_my_call(p_station->call_sign,1)) { // Checks SSID as well
+ if ( !(is_my_station(p_station)) ) { // Checks SSID as well
+
+ l_lat = convert_lat_s2l(my_lat);
+ l_lon = convert_lon_s2l(my_long);
+
+ // Get distance in nautical miles.
+ value = (float)calc_distance_course(l_lat,l_lon,p_station->coord_lat,
+ p_station->coord_lon,temp1_my_course,sizeof(temp1_my_course));
+
+ // n7tap: This is a quick hack to get some more useful values for
+ // distance to near ojects.
+ if (english_units) {
+ if (value*1.15078 < 0.99) {
+ xastir_snprintf(temp_my_distance,
+ sizeof(temp_my_distance),
+ "%d %s",
+ (int)(value*1.15078*1760),
+ langcode("SPCHSTR004")); // yards
+ }
+ else {
+ xastir_snprintf(temp_my_distance,
+ sizeof(temp_my_distance),
+ langcode("WPUPSTI020"), // miles
+ value*1.15078);
+ }
+ }
+ else {
+ if (value*1.852 < 0.99) {
+ xastir_snprintf(temp_my_distance,
+ sizeof(temp_my_distance),
+ "%d %s",
+ (int)(value*1.852*1000),
+ langcode("UNIOP00031")); // 'm' as in meters
+ }
+ else {
+ xastir_snprintf(temp_my_distance,
+ sizeof(temp_my_distance),
+ langcode("WPUPSTI021"), // km
+ value*1.852);
+ }
+ }
+ xastir_snprintf(temp_my_course, sizeof(temp_my_course), "%s�",temp1_my_course);
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPSTI022"),temp_my_distance,temp_my_course);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ if(last_pos!=pos) {
+ xastir_snprintf(temp, sizeof(temp), "\n");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ // Last Position
+ sec = p_station->sec_heard;
+ time = localtime(&sec);
+ xastir_snprintf(temp, sizeof(temp), "%s%02d/%02d %02d:%02d ",langcode("WPUPSTI023"),
+ time->tm_mon + 1, time->tm_mday,time->tm_hour,time->tm_min);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ if (coordinate_system == USE_UTM
+ || coordinate_system == USE_UTM_SPECIAL) {
+ convert_xastir_to_UTM_str(temp, sizeof(temp),
+ p_station->coord_lon, p_station->coord_lat);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+ else if (coordinate_system == USE_MGRS) {
+ convert_xastir_to_MGRS_str(temp,
+ sizeof(temp),
+ p_station->coord_lon,
+ p_station->coord_lat,
+ 0);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+ else {
+ if (coordinate_system == USE_DDDDDD) {
+ convert_lat_l2s(p_station->coord_lat, temp, sizeof(temp), CONVERT_DEC_DEG);
+ }
+ else if (coordinate_system == USE_DDMMSS) {
+ convert_lat_l2s(p_station->coord_lat, temp, sizeof(temp), CONVERT_DMS_NORMAL);
+ }
+ else { // Assume coordinate_system == USE_DDMMMM
+ convert_lat_l2s(p_station->coord_lat, temp, sizeof(temp), CONVERT_HP_NORMAL);
+ }
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ xastir_snprintf(temp, sizeof(temp), " ");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ if (coordinate_system == USE_DDDDDD) {
+ convert_lon_l2s(p_station->coord_lon, temp, sizeof(temp), CONVERT_DEC_DEG);
+ }
+ else if (coordinate_system == USE_DDMMSS) {
+ convert_lon_l2s(p_station->coord_lon, temp, sizeof(temp), CONVERT_DMS_NORMAL);
+ }
+ else { // Assume coordinate_system == USE_DDMMMM
+ convert_lon_l2s(p_station->coord_lon, temp, sizeof(temp), CONVERT_HP_NORMAL);
+ }
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ if (p_station->altitude[0] != '\0')
+ xastir_snprintf(temp, sizeof(temp), " %5.0f%s", atof(p_station->altitude)*cvt_m2len, un_alt);
+ else
+ substr(temp," ",1+5+strlen(un_alt));
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ if (p_station->speed[0] != '\0')
+ xastir_snprintf(temp, sizeof(temp), " %4.0f%s",atof(p_station->speed)*cvt_kn2len,un_spd);
+ else
+ substr(temp," ",1+4+strlen(un_spd));
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ if (p_station->course[0] != '\0')
+ xastir_snprintf(temp, sizeof(temp), " %3d�",atoi(p_station->course));
+ else
+ xastir_snprintf(temp, sizeof(temp), " ");
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ // dl9sau
+ // Maidenhead Grid Locator
+ xastir_snprintf(temp, sizeof(temp), " %s", sec_to_loc(p_station->coord_lon, p_station->coord_lat) );
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ if ((p_station->flag & ST_DIRECT) != 0)
+ xastir_snprintf(temp, sizeof(temp), " *\n");
+
+ else
+ xastir_snprintf(temp, sizeof(temp), " \n");
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ // list rest of trail data
+ if (p_station->newest_trackpoint != NULL) {
+ TrackRow *ptr;
+
+ ptr = p_station->newest_trackpoint;
+
+ // Skip the first (latest) trackpoint as if it exists, it'll
+ // be the same as the data in the station record, which we
+ // just printed out.
+ if (ptr->prev != NULL)
+ ptr = ptr->prev;
+
+ while ( (ptr != NULL) && (track_count <= MAX_TRACK_LIST) ) {
+
+ track_count++;
+
+ sec = ptr->sec;
+ time = localtime(&sec);
+ if ((ptr->flag & TR_NEWTRK) != '\0')
+ xastir_snprintf(temp, sizeof(temp), " + %02d/%02d %02d:%02d ",
+ time->tm_mon + 1,time->tm_mday,time->tm_hour,time->tm_min);
+ else
+ xastir_snprintf(temp, sizeof(temp), " %02d/%02d %02d:%02d ",
+ time->tm_mon + 1,time->tm_mday,time->tm_hour,time->tm_min);
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ if (coordinate_system == USE_UTM
+ || coordinate_system == USE_UTM_SPECIAL) {
+ convert_xastir_to_UTM_str(temp, sizeof(temp),
+ ptr->trail_long_pos,
+ ptr->trail_lat_pos);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+ else if (coordinate_system == USE_MGRS) {
+ convert_xastir_to_MGRS_str(temp,
+ sizeof(temp),
+ ptr->trail_long_pos,
+ ptr->trail_lat_pos,
+ 0);
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+ else {
+ if (coordinate_system == USE_DDDDDD) {
+ convert_lat_l2s(ptr->trail_lat_pos,
+ temp,
+ sizeof(temp),
+ CONVERT_DEC_DEG);
+ }
+ else if (coordinate_system == USE_DDMMSS) {
+ convert_lat_l2s(ptr->trail_lat_pos,
+ temp,
+ sizeof(temp),
+ CONVERT_DMS_NORMAL);
+ }
+ else { // Assume coordinate_system == USE_DDMMMM
+ convert_lat_l2s(ptr->trail_lat_pos,
+ temp,
+ sizeof(temp),
+ CONVERT_HP_NORMAL);
+ }
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ xastir_snprintf(temp, sizeof(temp), " ");
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ if (coordinate_system == USE_DDDDDD) {
+ convert_lon_l2s(ptr->trail_long_pos,
+ temp,
+ sizeof(temp),
+ CONVERT_DEC_DEG);
+ }
+ else if (coordinate_system == USE_DDMMSS) {
+ convert_lon_l2s(ptr->trail_long_pos,
+ temp,
+ sizeof(temp),
+ CONVERT_DMS_NORMAL);
+ }
+ else { // Assume coordinate_system == USE_DDMMMM
+ convert_lon_l2s(ptr->trail_long_pos,
+ temp,
+ sizeof(temp),
+ CONVERT_HP_NORMAL);
+ }
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+ }
+
+ if (ptr->altitude > -99999l)
+ xastir_snprintf(temp, sizeof(temp), " %5.0f%s",
+ ptr->altitude * cvt_dm2len,
+ un_alt);
+ else
+ substr(temp," ",1+5+strlen(un_alt));
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ if (ptr->speed >= 0)
+ xastir_snprintf(temp, sizeof(temp), " %4.0f%s",
+ ptr->speed * cvt_hm2len,
+ un_spd);
+ else
+ substr(temp," ",1+4+strlen(un_spd));
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ if (ptr->course >= 0)
+ xastir_snprintf(temp, sizeof(temp), " %3d�",
+ ptr->course);
+ else
+ xastir_snprintf(temp, sizeof(temp), " ");
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ // dl9sau
+ xastir_snprintf(temp, sizeof(temp), " %s",
+ sec_to_loc(ptr->trail_long_pos,
+ ptr->trail_lat_pos) );
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ if ((ptr->flag & TR_LOCAL) != '\0')
+ xastir_snprintf(temp, sizeof(temp), " *\n");
+ else
+ xastir_snprintf(temp, sizeof(temp), " \n");
+
+ XmTextInsert(si_text,pos,temp);
+ pos += strlen(temp);
+
+ // Go back in time one trackpoint
+ ptr = ptr->prev;
+ }
+ }
+
+
+ if (fcc_lookup_pushed) {
+ Station_data_add_fcc(w, clientData, calldata);
+ }
+ else if (rac_lookup_pushed) {
+ Station_data_add_rac(w, clientData, calldata);
+ }
+
+ XmTextShowPosition(si_text,0);
+
+end_critical_section(&db_station_info_lock, "db.c:Station_data" );
+
+}
+
+
+
+
+
+/*
+ * Track from Station_data
+ *
+ * Called by Station_data function below from the Track Station
+ * button in Station Info.
+ */
+void Track_from_Station_data(/*@unused@*/ Widget w, XtPointer clientData, XtPointer calldata) {
+ DataRow *p_station = clientData;
+
+ if (p_station->call_sign[0] != '\0') {
+ xastir_snprintf(tracking_station_call,
+ sizeof(tracking_station_call),
+ "%s",
+ p_station->call_sign);
+ track_station_on = 1;
+ }
+ else {
+ tracking_station_call[0] = '\0';
+ }
+}
+
+/*
+ * Clear DF from Station_data
+ *
+ * Called by Station_data function below from the Clear DF Bearing
+ * button in Station Info.
+ */
+void Clear_DF_from_Station_data(/*@unused@*/ Widget w, XtPointer clientData, XtPointer calldata) {
+ DataRow *p_station = clientData;
+
+ if (strlen(p_station->bearing) == 3) {
+ // we have DF data to clear
+ p_station->bearing[0]='\0';
+ p_station->NRQ[0]='\0';
+ }
+}
+
+
+
+
+
+/*
+ * List station info and trail
+ * If calldata is non-NULL, then we drop straight through to the
+ * Modify->Object or Assign_Tactical_Call dialogs.
+ *
+ * Input parameters:
+ * clientData: Station callsign
+ *
+ * calldata: NULL = Station Info
+ * "1" = Object -> Modify
+ * "2" = Move Object
+ * "3" = Assign Tactical Call
+ * "4" = Send Message To
+ *
+ */
+void Station_data(/*@unused@*/ Widget w, XtPointer clientData, XtPointer calldata) {
+ DataRow *p_station;
+ char *station = (char *) clientData;
+ static char local_station[25];
+ char temp[300];
+ unsigned int n;
+ Atom delw;
+ static Widget pane, form, button_cancel, button_message,
+ button_nws, button_fcc, button_rac, button_clear_track,
+ button_trace, button_messages, button_object_modify,
+ button_direct, button_version, station_icon, station_call,
+ station_type, station_data_auto_update_w,
+ button_tactical, button_change_trail_color,
+ button_track_station,button_clear_df;
+ Arg args[50];
+ Pixmap icon;
+ Position x,y; // For saving current dialog position
+ int restore_position = 0;
+
+
+//fprintf(stderr,"db.c:Station_data start\n");
+
+ busy_cursor(appshell);
+
+ db_station_info_callsign = (char *) clientData; // Used for auto-updating this dialog
+
+
+ // Make a copy of the name.
+ xastir_snprintf(local_station,sizeof(local_station),"%s",station);
+
+ if (search_station_name(&p_station,station,1) // find call
+ && (p_station->flag & ST_ACTIVE) != 0) { // ignore deleted objects
+ }
+ else {
+ fprintf(stderr,"Couldn't find station in database\n");
+ return; // Don't update current/create new dialog
+ }
+
+
+ if (calldata != NULL) { // We were called from the
+ // Object->Modify, Assign Tactical Call,
+ // or Send Message To menu items.
+ if (strncmp(calldata,"1",1) == 0) {
+ Modify_object(w, (XtPointer)p_station, calldata);
+ }
+ else if (strncmp(calldata,"2",1) == 0) {
+ Modify_object(w, (XtPointer)p_station, calldata);
+ }
+ else if (strncmp(calldata,"3",1) == 0) {
+ Assign_Tactical_Call(w, (XtPointer)p_station, calldata);
+ }
+ else if (strncmp(calldata,"4",1) == 0) {
+//fprintf(stderr,"Send Message To: %s\n", p_station->call_sign);
+ Send_message_call(NULL, (XtPointer) p_station->call_sign, NULL);
+ }
+ return;
+ }
+
+
+ // If we haven't calculated our decoration offsets yet, do so now
+ if ( (decoration_offset_x == 0) && (decoration_offset_y == 0) ) {
+ compute_decorations();
+ }
+
+ if (db_station_info != NULL) { // We already have a dialog
+ restore_position = 1;
+
+ // This is a pain. We can get the X/Y position, but when
+ // we restore the new dialog to the same position we're
+ // off by the width/height of our window decorations. Call
+ // above was added to pre-compute the offsets that we'll need.
+ XtVaGetValues(db_station_info, XmNx, &x, XmNy, &y, NULL);
+
+ // This call doesn't work. It returns the widget location,
+ // just like the XtVaGetValues call does. I need the window
+ // decoration location instead.
+ //XtTranslateCoords(db_station_info, 0, 0, &xnew, &ynew);
+ //fprintf(stderr,"%d:%d\t%d:%d\n", x, xnew, y, ynew);
+
+ if (last_station_info_x == 0)
+ last_station_info_x = x - decoration_offset_x;
+
+ if (last_station_info_y == 0)
+ last_station_info_y = y - decoration_offset_y;
+
+ // Now get rid of the old dialog
+ Station_data_destroy_shell(db_station_info, db_station_info, NULL);
+ }
+ else {
+ // Clear the global state variables
+ fcc_lookup_pushed = 0;
+ rac_lookup_pushed = 0;
+ }
+
+
+begin_critical_section(&db_station_info_lock, "db.c:Station_data" );
+
+
+ if (db_station_info == NULL) {
+ // Start building the dialog from the bottom up. That way
+ // we can keep the buttons attached to the bottom of the
+ // form and the correct height, and let the text widget
+ // grow/shrink as the dialog is resized.
+
+ db_station_info = XtVaCreatePopupShell(langcode("WPUPSTI001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Station Data pane",
+ xmPanedWindowWidgetClass, db_station_info,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Station Data form",
+ xmFormWidgetClass, pane,
+ XmNfractionBase, 4,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+
+// Start with the bottom row, left button
+
+
+ button_clear_track = NULL; // Need this later, don't delete!
+ if (p_station->newest_trackpoint != NULL) {
+ // [ Clear Track ]
+ button_clear_track = XtVaCreateManagedWidget(langcode("WPUPSTI045"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset,5,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_clear_track, XmNactivateCallback, Station_data_destroy_track ,(XtPointer)p_station);
+
+ }
+ else {
+ // DK7IN: I drop the version button for mobile stations
+ // we just have too much buttons...
+ // and should find another solution
+ // [ Station Version Query ]
+ button_version = XtVaCreateManagedWidget(langcode("WPUPSTI052"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset,5,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_version, XmNactivateCallback, Station_query_version ,(XtPointer)p_station->call_sign);
+ }
+
+ // [ Trace Query ]
+ button_trace = XtVaCreateManagedWidget(langcode("WPUPSTI049"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_trace, XmNactivateCallback, Station_query_trace ,(XtPointer)p_station->call_sign);
+
+ // [ Un-Acked Messages Query ]
+ button_messages = XtVaCreateManagedWidget(langcode("WPUPSTI050"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_messages, XmNactivateCallback, Station_query_messages ,(XtPointer)p_station->call_sign);
+
+ // [ Direct Stations Query ]
+ button_direct = XtVaCreateManagedWidget(langcode("WPUPSTI051"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_direct, XmNactivateCallback, Station_query_direct ,(XtPointer)p_station->call_sign);
+
+
+// Now proceed to the row above it, left button first
+
+
+ // [ Store Track ] or single Position
+ button_store_track = XtVaCreateManagedWidget(langcode("WPUPSTI054"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+//XmNtopWidget,XtParent(si_text),
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, (button_clear_track) ? button_clear_track : button_version,
+ XmNbottomOffset, 1,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset,5,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_store_track, XmNactivateCallback, Station_data_store_track ,(XtPointer)p_station);
+
+ if ( ((p_station->flag & ST_OBJECT) == 0) && ((p_station->flag & ST_ITEM) == 0) ) { // Not an object/
+ // fprintf(stderr,"Not an object or item...\n");
+ // [Send Message]
+ button_message = XtVaCreateManagedWidget(langcode("WPUPSTI002"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, button_trace,
+ XmNbottomOffset, 1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_message, XmNactivateCallback, Send_message_call ,(XtPointer)p_station->call_sign);
+ }
+ else {
+ // fprintf(stderr,"Found an object or item...\n");
+ button_object_modify = XtVaCreateManagedWidget(langcode("WPUPSTI053"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, button_trace,
+ XmNbottomOffset, 1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_object_modify,
+ XmNactivateCallback,
+ Modify_object,
+ (XtPointer)p_station);
+ }
+
+
+ // Check whether it is a non-weather alert object/item. If
+ // so, try to use the origin callsign instead of the object
+ // for FCC/RAC lookups.
+ //
+ if ( (p_station->flag & ST_OBJECT) || (p_station->flag & ST_ITEM) ) {
+
+ // It turns out that objects transmitted by a station
+ // called "WINLINK" are what mess up the RAC button for
+ // Canadian stations. Xastir sees the 'W' of WINLINK
+ // (the originating station) and assumes it is a U.S.
+ // station. Here's a sample packet:
+ //
+// WINLINK>APWL2K,TCPIP*,qAC,T2MIDWEST:;VE7SEP-10*240521z4826.2 NW12322.5 Wa145.690MHz 1200b R11m RMSPacket EMCOMM
+ //
+ // If match on "WINLINK": Don't copy origin callsign
+ // into local_station. Use the object name instead
+ // which should be a callsign.
+ if (strncmp(p_station->origin,"WINLINK",7)) {
+ xastir_snprintf(local_station,sizeof(local_station),"%s",p_station->origin);
+ }
+ }
+
+
+ // Add "Fetch NWS Info" button if it is an object or item
+ // and has "WXSVR" in its path somewhere.
+ //
+ // Note from Dale Huguley:
+ // "I would say an object with 6 upper alpha chars for the
+ // "from" call and " {AAAAA" (space curly 5 alphanumerics)
+ // at the end is almost guaranteed to be from Wxsvr.
+ // Fingering for the six alphas and the first three
+ // characters after the curly brace should be a reliable
+ // finger - as in SEWSVR>APRS::a_bunch_of_info_in_here_
+ // {H45AA finger SEWSVRH45 at wxsvr.net"
+ //
+ // Note from Curt: I had to remove the space from the
+ // search as well, 'cuz the multipoint objects don't have
+ // the space before the final curly-brace.
+ //
+ if ( ( (p_station->flag & ST_OBJECT) || (p_station->flag & ST_ITEM) )
+ && (p_station->comment_data != NULL)
+ && ( strstr(p_station->comment_data->text_ptr, "{") != NULL ) ) {
+
+ static char temp[25];
+ char *ptr3;
+
+
+ button_nws = XtVaCreateManagedWidget(langcode("WPUPSTI064"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, button_messages,
+ XmNbottomOffset, 1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // We need to contruct the "special" finger address.
+ // We'll use the FROM callsign and the first three chars
+ // of the curly-brace portion of the comment field.
+ // Callsign in this case is from the "origin" field.
+ // The curly-brace text is at the end of one of the
+ // "comment_data" records, hopefully the first one
+ // checked (most recent).
+ //
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ p_station->origin);
+ temp[6] = '\0';
+ ptr3 = strstr(p_station->comment_data->text_ptr,"{");
+ ptr3++; // Skip over the '{' character
+ strncat(temp,ptr3,3);
+
+//fprintf(stderr,"New Handle: %s\n", temp);
+
+ XtAddCallback(button_nws,
+ XmNactivateCallback,
+ Station_data_wx_alert,
+ (XtPointer)temp);
+ }
+
+
+ // Add FCC button only if probable match. The U.S. has
+ // these prefixes assigned but not all are used for amateur
+ // stations:
+ //
+ // AAA-ALZ
+ // KAA-KZZ
+ // NAA-NZZ
+ // WAA-WZZ
+ //
+ else if ((! strncmp(local_station,"A",1)) || (! strncmp(local_station,"K",1)) ||
+ (! strncmp(local_station,"N",1)) || (! strncmp(local_station,"W",1)) ) {
+
+ button_fcc = XtVaCreateManagedWidget(langcode("WPUPSTI003"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, button_messages,
+ XmNbottomOffset, 1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_fcc,
+ XmNactivateCallback,
+ Station_data_add_fcc,
+ (XtPointer)local_station);
+
+ if ( ! check_fcc_data())
+ XtSetSensitive(button_fcc,FALSE);
+ }
+
+
+ // Add RAC button only if probable match. Canada has these
+ // prefixes assigned but not all are used for amateur
+ // stations:
+ //
+ // CFA-CKZ
+ // CYA-CZZ
+ // VAA-VGZ
+ // VOA-VOZ
+ // VXA-VYZ
+ // XJA-XOZ
+ //
+ else if (!strncmp(local_station,"VA",2) || !strncmp(local_station,"VE",2) || !strncmp(local_station,"VO",2) || !strncmp(local_station,"VY",2)) {
+ button_rac = XtVaCreateManagedWidget(langcode("WPUPSTI004"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, button_messages,
+ XmNbottomOffset, 1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_rac,
+ XmNactivateCallback,
+ Station_data_add_rac,
+ (XtPointer)local_station);
+
+ if ( ! check_rac_data())
+ XtSetSensitive(button_rac,FALSE);
+ }
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, button_direct,
+ XmNbottomOffset, 1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNrightOffset, 5,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_cancel, XmNactivateCallback, Station_data_destroy_shell, db_station_info);
+
+ // Button to clear DF bearing data if we actually have some.
+ if (strlen(p_station->bearing) == 3) {
+ button_clear_df = XtVaCreateManagedWidget(langcode("WPUPSTI092"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, button_cancel,
+ XmNbottomOffset, 1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNrightOffset, 5,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_clear_df, XmNactivateCallback,Clear_DF_from_Station_data, (XtPointer)p_station);
+ }
+
+ button_track_station = XtVaCreateManagedWidget(langcode("WPUPTSP001"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, button_store_track,
+ XmNbottomOffset, 1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset,5,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+// XmNrightOffset, 5,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_track_station, XmNactivateCallback,Track_from_Station_data, (XtPointer)p_station);
+
+
+
+// Now build from the top of the dialog to the buttons.
+
+
+ icon = XCreatePixmap(XtDisplay(appshell),RootWindowOfScreen(XtScreen(appshell)),
+ 20,20,DefaultDepthOfScreen(XtScreen(appshell)));
+
+ symbol(db_station_info,0,p_station->aprs_symbol.aprs_type,
+ p_station->aprs_symbol.aprs_symbol,
+ p_station->aprs_symbol.special_overlay,icon,0,0,0,' ');
+
+ station_icon = XtVaCreateManagedWidget("Station Data icon", xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNlabelType, XmPIXMAP,
+ XmNlabelPixmap,icon,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ station_type = XtVaCreateManagedWidget("Station Data type", xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNshadowThickness, 0,
+ XmNcolumns,5,
+ XmNwidth,((5*7)+2),
+ XmNbackground, colors[0xff],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 2,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget,station_icon,
+ XmNleftOffset,10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ xastir_snprintf(temp, sizeof(temp), "%c%c%c", p_station->aprs_symbol.aprs_type,
+ p_station->aprs_symbol.aprs_symbol,
+ p_station->aprs_symbol.special_overlay);
+
+ XmTextFieldSetString(station_type, temp);
+ XtManageChild(station_type);
+
+ station_call = XtVaCreateManagedWidget("Station Data call", xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNshadowThickness, 0,
+ XmNcolumns,10,
+ XmNwidth,((10*7)+2),
+ XmNbackground, colors[0xff],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 2,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, station_type,
+ XmNleftOffset,10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(station_call,p_station->call_sign);
+ XtManageChild(station_call);
+
+ station_data_auto_update_w = XtVaCreateManagedWidget(langcode("WPUPSTI056"),
+ xmToggleButtonGadgetClass, form,
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 2,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, station_call,
+ XmNleftOffset,10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground,colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(station_data_auto_update_w,XmNvalueChangedCallback,station_data_auto_update_toggle,"1");
+
+ //Add tactical button at the top/right
+ // "Assign Tactical Call"
+ button_tactical = XtVaCreateManagedWidget(langcode("WPUPSTI066"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftOffset, 10,
+ XmNleftWidget, station_data_auto_update_w,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_tactical,
+ XmNactivateCallback,
+ Assign_Tactical_Call,
+ (XtPointer)p_station);
+ if (p_station->flag & (ST_OBJECT | ST_ITEM)) {
+ // We don't allow setting tac-calls for objects/items,
+ // so make the button insensitive.
+ XtSetSensitive(button_tactical,FALSE);
+ }
+
+ //Add change_trail_color button at the top/right
+ // "Trail Color"
+ button_change_trail_color = XtVaCreateManagedWidget(langcode("WPUPSTI091"),
+ xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftOffset, 10,
+ XmNleftWidget, button_tactical,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_change_trail_color,
+ XmNactivateCallback,
+ Change_trail_color,
+ (XtPointer)p_station);
+
+ n=0;
+ XtSetArg(args[n], XmNrows, 15); n++;
+ XtSetArg(args[n], XmNcolumns, 100); n++;
+ XtSetArg(args[n], XmNeditable, FALSE); n++;
+ XtSetArg(args[n], XmNtraversalOn, FALSE); n++;
+ XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
+ XtSetArg(args[n], XmNwordWrap, TRUE); n++;
+ XtSetArg(args[n], XmNbackground, colors[0xff]); n++;
+ XtSetArg(args[n], XmNscrollHorizontal, FALSE); n++;
+ XtSetArg(args[n], XmNcursorPositionVisible, FALSE); n++;
+ XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
+ XtSetArg(args[n], XmNtopWidget, station_icon); n++;
+ XtSetArg(args[n], XmNtopOffset, 5); n++;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
+// XtSetArg(args[n], XmNbottomWidget, button_store_track); n++;
+ XtSetArg(args[n], XmNbottomWidget, button_track_station); n++;
+ XtSetArg(args[n], XmNbottomOffset, 1); n++;
+ XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNleftOffset, 5); n++;
+ XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNrightOffset, 5); n++;
+ XtSetArg(args[n], XmNfontList, fontlist1); n++;
+
+ si_text = NULL;
+ si_text = XmCreateScrolledText(form,"Station_data",args,n);
+
+end_critical_section(&db_station_info_lock, "db.c:Station_data" );
+
+ // Fill in the si_text widget with real data
+ station_data_fill_in( w, (XtPointer)db_station_info_callsign, NULL);
+
+begin_critical_section(&db_station_info_lock, "db.c:Station_data" );
+
+// restore_position doesn't appear to work. I get the dialog
+// positioned all over my virtual consoles if I try. Reverting to
+// pos_dialog() for now.
+// if (restore_position) {
+// XtVaSetValues(db_station_info,XmNx,x - decoration_offset_x,XmNy,y - decoration_offset_y,NULL);
+// }
+// else {
+ pos_dialog(db_station_info);
+// }
+
+ delw = XmInternAtom(XtDisplay(db_station_info),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(db_station_info, delw, Station_data_destroy_shell, (XtPointer)db_station_info);
+
+ XtManageChild(form);
+ XtManageChild(si_text);
+ XtVaSetValues(si_text, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(pane);
+
+ if (station_data_auto_update)
+ XmToggleButtonSetState(station_data_auto_update_w,TRUE,FALSE);
+
+ if (calldata == NULL) { // We're not going straight to the Modify dialog
+ // and will actually use the dialog we just drew
+
+ XtPopup(db_station_info,XtGrabNone);
+
+// fix_dialog_size(db_station_info);
+ XmTextShowPosition(si_text,0);
+
+ // Move focus to the Cancel button. This appears to highlight t
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+ }
+ }
+
+end_critical_section(&db_station_info_lock, "db.c:Station_data" );
+
+}
+
+
+
+
+
+// Used for auto-refreshing the Station_info dialog. Called from
+// main.c:UpdateTime() every 30 seconds.
+//
+void update_station_info(Widget w) {
+
+begin_critical_section(&db_station_info_lock, "db.c:update_station_info" );
+
+ // If we have a dialog to update and a callsign to pass to it
+ if (( db_station_info != NULL)
+ && (db_station_info_callsign != NULL)
+ && (strlen(db_station_info_callsign) != 0) ) {
+
+end_critical_section(&db_station_info_lock, "db.c:update_station_info" );
+
+ // Fill in the si_text widget with real data
+ station_data_fill_in( w, (XtPointer)db_station_info_callsign, NULL);
+ }
+ else {
+
+end_critical_section(&db_station_info_lock, "db.c:update_station_info" );
+
+ }
+}
+
+
+
+
+
+/*
+ * Station Info Selection PopUp window: Canceled
+ */
+void Station_info_destroy_shell(/*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+
+// We used to close the detailed Station Info dialog here too, which
+// makes no sense. Commenting this out so that we can close the
+// Station Chooser but leave the Station Info dialog open.
+//
+// if (db_station_info!=NULL)
+// Station_data_destroy_shell(db_station_info, db_station_info, NULL);
+
+ XtPopdown(shell);
+ (void)XFreePixmap(XtDisplay(appshell),SiS_icon0);
+ (void)XFreePixmap(XtDisplay(appshell),SiS_icon);
+
+begin_critical_section(&db_station_popup_lock, "db.c:Station_info_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ db_station_popup = (Widget)NULL;
+
+end_critical_section(&db_station_popup_lock, "db.c:Station_info_destroy_shell" );
+
+}
+
+
+
+
+
+// Global parameter so that we can pass another value to the below
+// function from the Station_info() function. We need to be able to
+// pass this value off to the Station_data() function for special
+// operations like moves, where objects are on top of each other.
+//
+XtPointer station_info_select_global = NULL;
+
+
+
+
+
+/*
+ * Station Info Selection PopUp window: Quit with selected station
+ */
+void Station_info_select_destroy_shell(Widget widget, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ int i,x;
+ char *temp;
+ char temp2[50];
+ XmString *list;
+ int found;
+ //Widget shell = (Widget) clientData;
+
+ found=0;
+
+begin_critical_section(&db_station_popup_lock, "db.c:Station_info_select_destroy_shell" );
+
+ if (db_station_popup) {
+ XtVaGetValues(station_list,XmNitemCount,&i,XmNitems,&list,NULL);
+
+ for (x=1; x<=i;x++) {
+ if (XmListPosSelected(station_list,x)) {
+ found=1;
+ if (XmStringGetLtoR(list[(x-1)],XmFONTLIST_DEFAULT_TAG,&temp))
+ x=i+1;
+ }
+ }
+
+ // DK7IN ?? should we not first close the PopUp, then call Station_data ??
+ if (found) {
+ xastir_snprintf(temp2, sizeof(temp2), "%s", temp);
+ // Only keep the station info, remove Tactical Call Sign
+ temp2[strcspn(temp2, "(")] = '\0';
+ remove_trailing_spaces(temp2);
+
+ // Call it with the global parameter at the last, so we
+ // can pass special parameters down that we couldn't
+ // directly pass to Station_info_select_destroy_shell().
+ Station_data(widget, temp2, station_info_select_global);
+
+ // Clear the global variable so that nothing else calls
+ // it with the wrong parameter
+ station_info_select_global = NULL;
+
+ XtFree(temp);
+ }
+/*
+ // This section of code gets rid of the Station Chooser. Frank wanted to
+ // be able to leave the Station Chooser up after selection so that other
+ // stations could be selected, therefore I commented this out.
+ XtPopdown(shell); // Get rid of the station chooser popup here
+ (void)XFreePixmap(XtDisplay(appshell),SiS_icon0);
+ (void)XFreePixmap(XtDisplay(appshell),SiS_icon);
+ XtDestroyWidget(shell); // and here
+ db_station_popup = (Widget)NULL; // and here
+*/
+ }
+
+end_critical_section(&db_station_popup_lock, "db.c:Station_info_select_destroy_shell" );
+
+}
+
+
+
+
+
+/*
+ * Station Info PopUp
+ * if only one station in view it shows the data with Station_data()
+ * otherwise we get a selection box
+ * clientData will be non-null if we wish to drop through to the object->modify
+ * or Assign Tactical Call dialogs.
+ *
+ * clientData: NULL = Station Info
+ * "1" = Object -> Modify
+ * "2" = Move Object
+ * "3" = Assign Tactical Call
+ * "4" = Send Message To
+ */
+void Station_info(Widget w, /*@unused@*/ XtPointer clientData, XtPointer calldata) {
+ DataRow *p_station;
+ DataRow *p_found;
+ int num_found = 0;
+ unsigned long min_diff_x, diff_x, min_diff_y, diff_y;
+ XmString str_ptr;
+ unsigned int n;
+ Atom delw;
+ static Widget pane, form, button_ok, button_cancel;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+ char tactical_string[50];
+
+
+ busy_cursor(appshell);
+
+ min_diff_y = scale_y * 20; // Pixels each way in y-direction.
+ min_diff_x = scale_x * 20; // Pixels each way in x-direction.
+ p_found = NULL;
+ p_station = n_first;
+
+ // Here we just count them. We go through the same type of code
+ // again later if we find more than one station.
+ while (p_station != NULL) { // search through database for nearby stations
+
+ if ( ( (p_station->flag & ST_INVIEW) != 0)
+ && ok_to_draw_station(p_station) ) { // only test stations in view
+
+ if (!altnet || is_altnet(p_station)) {
+
+ // Here we calculate diff in terms of XX pixels,
+ // changed into lat/long values. This keeps the
+ // affected rectangle the same at any zoom level.
+ // scale_y/scale_x is Xastir units/pixel. Xastir
+ // units are in 1/100 of a second. If we want to go
+ // 10 pixels in any direction (roughly, scale_x
+ // varies by latitude), then we want (10 * scale_y),
+ // and (10 * scale_x) if we want to make a very
+ // accurate square.
+
+ diff_y = (unsigned long)( labs((NW_corner_latitude+(menu_y*scale_y))
+ - p_station->coord_lat));
+
+ diff_x = (unsigned long)( labs((NW_corner_longitude+(menu_x*scale_x))
+ - p_station->coord_lon));
+
+ // If the station fits within our bounding box,
+ // count it
+ if ((diff_y < min_diff_y) && (diff_x < min_diff_x)) {
+ p_found = p_station;
+ num_found++;
+ }
+ }
+ }
+ p_station = p_station->n_next;
+ }
+
+ if (p_found != NULL) { // We found at least one station
+
+ if (num_found == 1) {
+ // We only found one station, so it's easy
+ Station_data(w,p_found->call_sign,clientData);
+ }
+ else { // We found more: create dialog to choose a station
+
+ // Set up this global variable so that we can pass it
+ // off to Station_data from the
+ // Station_info_select_destroy_shell() function above.
+ // Without this global variable we don't have enough
+ // parameters passed to the final routine, so we can't
+ // move an object that is on top of another. With it,
+ // we can.
+ station_info_select_global = clientData;
+
+ if (db_station_popup != NULL)
+ Station_info_destroy_shell(db_station_popup, db_station_popup, NULL);
+
+begin_critical_section(&db_station_popup_lock, "db.c:Station_info" );
+
+ if (db_station_popup == NULL) {
+ // Set up a selection box:
+ db_station_popup = XtVaCreatePopupShell(langcode("STCHO00001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Station_info pane",xmPanedWindowWidgetClass, db_station_popup,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Station_info form",xmFormWidgetClass, pane,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ // Attach buttons first to the bottom of the form,
+ // so that we'll be able to stretch this thing
+ // vertically to see all the callsigns.
+ //
+ button_ok = XtVaCreateManagedWidget("Info",xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_cancel, XmNactivateCallback, Station_info_destroy_shell, db_station_popup);
+ XtAddCallback(button_ok, XmNactivateCallback, Station_info_select_destroy_shell, db_station_popup);
+
+
+ /*set args for color */
+ ac = 0;
+ XtSetArg(al[ac], XmNbackground, colors[0xff]); ac++;
+ XtSetArg(al[ac], XmNvisibleItemCount, 6); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNshadowThickness, 3); ac++;
+ XtSetArg(al[ac], XmNselectionPolicy, XmSINGLE_SELECT); ac++;
+ XtSetArg(al[ac], XmNscrollBarPlacement, XmBOTTOM_RIGHT); ac++;
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 5); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, button_ok); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 5); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 5); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 5); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ station_list = XmCreateScrolledList(form,"Station_info list",al,ac);
+
+// DK7IN: I want to add the symbol in front of the call...
+ // icon
+ SiS_icon0 = XCreatePixmap(XtDisplay(appshell),RootWindowOfScreen(XtScreen(appshell)),20,20,
+ DefaultDepthOfScreen(XtScreen(appshell)));
+ SiS_icon = XCreatePixmap(XtDisplay(appshell),RootWindowOfScreen(XtScreen(appshell)),20,20,
+ DefaultDepthOfScreen(XtScreen(appshell)));
+/* SiS_symb = XtVaCreateManagedWidget("Station_info icon", xmLabelWidgetClass, ob_form1,
+ XmNlabelType, XmPIXMAP,
+ XmNlabelPixmap, SiS_icon,
+ XmNbackground, colors[0xff],
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ NULL);
+*/
+
+ /*fprintf(stderr,"What station\n");*/
+ n = 1;
+ p_station = n_first;
+ while (p_station != NULL) { // search through database for nearby stations
+
+ if ( ( (p_station->flag & ST_INVIEW) != 0)
+ && ok_to_draw_station(p_station) ) { // only test stations in view
+
+ if (!altnet || is_altnet(p_station)) {
+
+ diff_y = (unsigned long)( labs((NW_corner_latitude+(menu_y*scale_y))
+ - p_station->coord_lat));
+
+ diff_x = (unsigned long)( labs((NW_corner_longitude+(menu_x*scale_x))
+ - p_station->coord_lon));
+
+ // If the station fits within our
+ // bounding box, count it.
+ if ((diff_y < min_diff_y) && (diff_x < min_diff_x)) {
+ /*fprintf(stderr,"Station %s\n",p_station->call_sign);*/
+ if (p_station->tactical_call_sign) {
+ xastir_snprintf(tactical_string, sizeof(tactical_string), "%s (%s)", p_station->call_sign,
+ p_station->tactical_call_sign);
+ XmListAddItem(station_list, str_ptr = XmStringCreateLtoR(tactical_string,
+ XmFONTLIST_DEFAULT_TAG), (int)n++);
+ } else {
+ XmListAddItem(station_list, str_ptr = XmStringCreateLtoR(p_station->call_sign,
+ XmFONTLIST_DEFAULT_TAG), (int)n++);
+ }
+ XmStringFree(str_ptr);
+ }
+ }
+ }
+ p_station = p_station->n_next;
+ }
+
+
+ pos_dialog(db_station_popup);
+
+ delw = XmInternAtom(XtDisplay(db_station_popup),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(db_station_popup, delw, Station_info_destroy_shell, (XtPointer)db_station_popup);
+
+ XtManageChild(form);
+ XtManageChild(station_list);
+ XtVaSetValues(station_list, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(pane);
+
+ XtPopup(db_station_popup,XtGrabNone);
+
+ // Move focus to the Cancel button. This appears to highlight t
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ }
+
+end_critical_section(&db_station_popup_lock, "db.c:Station_info" );
+
+ }
+ }
+}
+
+
+
+
+
+int heard_via_tnc_in_past_hour(char *call) {
+ DataRow *p_station;
+ int in_hour;
+
+ in_hour=0;
+ if (search_station_name(&p_station,call,1)) { // find call
+
+ // Check the heard_via_tnc_last_time timestamp. This is a
+ // timestamp that is saved each time a station is heard via
+ // RF. It is initially set to 0. It does not get reset
+ // when a packet comes in via a non-TNC interface.
+ //
+ if (p_station->heard_via_tnc_last_time) { // non-zero entry
+
+ // Should we check to see if the last packet was message
+ // capable?
+
+ // Decide whether it was heard on a TNC interface within
+ // the hour
+ in_hour = (int)((p_station->heard_via_tnc_last_time+3600l) > sec_now());
+
+ if(debug_level & 2)
+ fprintf(stderr, "Call %s: %ld %ld ok %d\n",
+ call,
+ (long)(p_station->heard_via_tnc_last_time),
+ (long)sec_now(),
+ in_hour);
+
+ }
+ else {
+ if (debug_level & 2)
+ fprintf(stderr,"Call %s Not heard via tnc\n",call);
+ }
+ }
+ else {
+ if (debug_level & 2)
+ fprintf(stderr,"IG:station not found\n");
+ }
+ return(in_hour);
+}
+
+
+
+
+
+//////////////////////////////////// Weather Data //////////////////////////////////////////////////
+
+
+
+
+
+/* valid characters for APRS weather data fields */
+int is_aprs_chr(char ch) {
+
+ if (isdigit((int)ch) || ch==' ' || ch=='.' || ch=='-')
+ return(1);
+ else
+ return(0);
+}
+
+
+
+
+
+int count_filler_chars(char ch) {
+
+ if (isdigit((int)ch) || ch==' ' || ch=='.' || ch=='-')
+ return(1);
+ else
+ return(0);
+}
+
+
+
+
+
+/* check data format 123 ___ ... */
+// We wish to count how many ' ' or '.' characters we find. If it
+// equals zero or the field width, it might be a weather field. If
+// not, then it might be part of a comment field or something else.
+//
+int is_weather_data(char *data, int len) {
+ int ok = 1;
+ int i;
+ int count = 0;
+
+ for (i=0;ok && i<len;i++)
+ if (!is_aprs_chr(data[i]))
+ ok = 0;
+
+ // Count filler characters. Must equal zero or field width to
+ // be a weather field. There doesn't appear to be a case where
+ // a single period is allowed in any weather-related fields.
+ //
+ for (i=0;ok && i<len;i++) {
+ if (data[i] == ' ' || data[i] == '.') {
+ count++;
+ }
+ }
+ if (count != 0 && count != len) {
+ ok = 0;
+ }
+
+ return(ok);
+}
+
+
+
+
+
+// Extract single weather data item from "data". Returns it in
+// "temp". Modifies "data" to remove the found data from the
+// string. Returns a 1 if found, 0 if not found.
+//
+// PE1DNN
+// If the item is contained in the string but does not contain a
+// value then regard the item as "not found" in the weather string.
+//
+int extract_weather_item(char *data, char type, int datalen, char *temp) {
+ int i,ofs,found,len;
+
+
+//fprintf(stderr,"%s\n",data);
+
+ found=0;
+ len = (int)strlen(data);
+ for(ofs=0; !found && ofs<len-datalen; ofs++) // search for start sequence
+ if (data[ofs]==type) {
+ found=1;
+ if (!is_weather_data(data+ofs+1, datalen))
+ found=0;
+ }
+ if (found) { // ofs now points after type character
+ substr(temp,data+ofs,datalen);
+ for (i=ofs-1;i<len-datalen;i++) // delete item from info field
+ data[i] = data[i+datalen+1];
+ if((temp[0] == ' ') || (temp[0] == '.')) {
+ // found it, but it doesn't contain a value!
+ // Clean up and report "not found" - PE1DNN
+ temp[0] = '\0';
+ found = 0;
+ }
+ else
+ {
+ if (debug_level & 2) {
+ fprintf(stderr,"extract_weather_item: %s\n",temp);
+ }
+ }
+ }
+ else
+ temp[0] = '\0';
+ return(found);
+}
+
+
+
+
+
+// test-extract single weather data item from information field. In
+// other words: Does not change the input string, but does test
+// whether the data is present. Returns a 1 if found, 0 if not
+// found.
+//
+// PE1DNN
+// If the item is contained in the string but does not contain a
+// value then regard the item as "not found" in the weather string.
+//
+int test_extract_weather_item(char *data, char type, int datalen) {
+ int ofs,found,len;
+
+ found=0;
+ len = (int)strlen(data);
+ for(ofs=0; !found && ofs<len-datalen; ofs++) // search for start sequence
+ if (data[ofs]==type) {
+ found=1;
+ if (!is_weather_data(data+ofs+1, datalen))
+ found=0;
+ }
+
+ // We really should test for numbers here (with an optional
+ // leading '-'), and test across the length of the substring.
+ //
+ if(found && ((data[ofs+1] == ' ') || (data[ofs+1] == '.'))) {
+ // found it, but it doesn't contain a value!
+ // report "not found" - PE1DNN
+ found = 0;
+ }
+
+ //fprintf(stderr,"test_extract: %c %d\n",type,found);
+ return(found);
+}
+
+
+
+
+
+// DK7IN 77
+// raw weather report in information field
+// positionless weather report in information field
+// complete weather report with lat/lon
+// see APRS Reference page 62ff
+//
+// Added 'F' for Fuel Temp and 'f' for Fuel Moisture in order to
+// decode these two new parameters used for RAWS weather station
+// objects.
+//
+// By the time we call this function we've already extracted any
+// time/position info at the beginning of the string.
+//
+int extract_weather(DataRow *p_station, char *data, int compr) {
+ char time_data[MAX_TIME];
+ char temp[5];
+ int ok = 1;
+ WeatherRow *weather;
+ char course[4];
+ char speed[4];
+ int in_knots = 0;
+
+//WE7U
+// Try copying the string to a temporary string, then do some
+// extractions to see if a few weather items are present? This
+// would allow us to have the weather items in any order, and if
+// enough of them were present, we consider it to be a weather
+// packet? We'd need to qualify all of the data to make sure we had
+// the proper number of digits for each. The trick is to make sure
+// we don't decide it's a weather packet if it's not. We don't know
+// what people might send in packets in the future.
+
+ if (compr) { // compressed position report
+ // Look for weather data in fixed locations first
+ if (strlen(data) >= 8
+ && data[0] =='g' && is_weather_data(&data[1],3)
+ && data[4] =='t' && is_weather_data(&data[5],3)) {
+
+ // Snag WX course/speed from compressed position data.
+ // This speed is in knots. This assumes that we've
+ // already extracted speed/course from the compressed
+ // packet. extract_comp_position() extracts
+ // course/speed as well.
+ xastir_snprintf(speed,
+ sizeof(speed),
+ "%s",
+ p_station->speed);
+ xastir_snprintf(course,
+ sizeof(course),
+ "%s",
+ p_station->course);
+ in_knots = 1;
+
+ //fprintf(stderr,"Found compressed wx\n");
+ }
+ // Look for weather data in non-fixed locations (RAWS WX
+ // Stations?)
+ else if ( strlen(data) >= 8
+ && test_extract_weather_item(data,'g',3)
+ && test_extract_weather_item(data,'t',3) ) {
+
+ // Snag WX course/speed from compressed position data.
+ // This speed is in knots. This assumes that we've
+ // already extracted speed/course from the compressed
+ // packet. extract_comp_position() extracts
+ // course/speed as well.
+ xastir_snprintf(speed,
+ sizeof(speed),
+ "%s",
+ p_station->speed);
+ xastir_snprintf(course,
+ sizeof(course),
+ "%s",
+ p_station->course);
+ in_knots = 1;
+
+ //fprintf(stderr,"Found compressed WX in non-fixed locations! %s:%s\n",
+ // p_station->call_sign,data);
+
+ }
+ else { // No weather data found
+ ok = 0;
+
+ //fprintf(stderr,"No compressed wx\n");
+ }
+ }
+ else { // Look for non-compressed weather data
+ // Look for weather data in defined locations first
+ if (strlen(data)>=15 && data[3]=='/'
+ && is_weather_data(data,3) && is_weather_data(&data[4],3)
+ && data[7] =='g' && is_weather_data(&data[8], 3)
+ && data[11]=='t' && is_weather_data(&data[12],3)) { // Complete Weather Report
+
+ // Get speed/course. Speed is in knots.
+ (void)extract_speed_course(data,speed,course);
+ in_knots = 1;
+
+ // Either one not found? Try again.
+ if ( (speed[0] == '\0') || (course[0] == '\0') ) {
+
+ // Try to get speed/course from 's' and 'c' fields
+ // (another wx format). Speed is in mph.
+ (void)extract_weather_item(data,'c',3,course); // wind direction (in degrees)
+ (void)extract_weather_item(data,'s',3,speed); // sustained one-minute wind speed (in mph)
+ in_knots = 0;
+ }
+
+ //fprintf(stderr,"Found Complete Weather Report\n");
+ }
+ // Look for date/time and weather in fixed locations first
+ else if (strlen(data)>=16
+ && data[0] =='c' && is_weather_data(&data[1], 3)
+ && data[4] =='s' && is_weather_data(&data[5], 3)
+ && data[8] =='g' && is_weather_data(&data[9], 3)
+ && data[12]=='t' && is_weather_data(&data[13],3)) { // Positionless Weather Data
+//fprintf(stderr,"Found positionless wx data\n");
+ // Try to snag speed/course out of first 7 bytes. Speed
+ // is in knots.
+ (void)extract_speed_course(data,speed,course);
+ in_knots = 1;
+
+ // Either one not found? Try again.
+ if ( (speed[0] == '\0') || (course[0] == '\0') ) {
+//fprintf(stderr,"Trying again for course/speed\n");
+ // Also try to get speed/course from 's' and 'c' fields
+ // (another wx format)
+ (void)extract_weather_item(data,'c',3,course); // wind direction (in degrees)
+ (void)extract_weather_item(data,'s',3,speed); // sustained one-minute wind speed (in mph)
+ in_knots = 0;
+ }
+
+ //fprintf(stderr,"Found weather\n");
+ }
+ // Look for weather data in non-fixed locations (RAWS WX
+ // Stations?)
+ else if (strlen (data) >= 16
+ && test_extract_weather_item(data,'h',2)
+ && test_extract_weather_item(data,'g',3)
+ && test_extract_weather_item(data,'t',3) ) {
+
+ // Try to snag speed/course out of first 7 bytes. Speed
+ // is in knots.
+ (void)extract_speed_course(data,speed,course);
+ in_knots = 1;
+
+ // Either one not found? Try again.
+ if ( (speed[0] == '\0') || (course[0] == '\0') ) {
+
+ // Also try to get speed/course from 's' and 'c' fields
+ // (another wx format)
+ (void)extract_weather_item(data,'c',3,course); // wind direction (in degrees)
+ (void)extract_weather_item(data,'s',3,speed); // sustained one-minute wind speed (in mph)
+ in_knots = 0;
+ }
+
+ //fprintf(stderr,"Found WX in non-fixed locations! %s:%s\n",
+ // p_station->call_sign,data);
+ }
+ else { // No weather data found
+ ok = 0;
+
+ //fprintf(stderr,"No wx found\n");
+ }
+ }
+
+ if (ok) {
+ ok = get_weather_record(p_station); // get existing or create new weather record
+ }
+
+ if (ok) {
+ weather = p_station->weather_data;
+
+ // Copy into weather speed variable. Convert knots to mph
+ // if necessary.
+ if (in_knots) {
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03.0f",
+ atoi(speed) * 1.1508); // Convert knots to mph
+ }
+ else {
+ // Already in mph. Copy w/no conversion.
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%s",
+ speed);
+ }
+
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "%s",
+ course);
+
+ if (compr) { // course/speed was taken from normal data, delete that
+ // fix me: we delete a potential real speed/course now
+ // we should differentiate between normal and weather data in compressed position decoding...
+// p_station->speed_time[0] = '\0';
+ p_station->speed[0] = '\0';
+ p_station->course[0] = '\0';
+ }
+
+ (void)extract_weather_item(data,'g',3,weather->wx_gust); // gust (peak wind speed in mph in the last 5 minutes)
+
+ (void)extract_weather_item(data,'t',3,weather->wx_temp); // temperature (in deg Fahrenheit), could be negative
+
+ (void)extract_weather_item(data,'r',3,weather->wx_rain); // rainfall (1/100 inch) in the last hour
+
+ (void)extract_weather_item(data,'p',3,weather->wx_prec_24); // rainfall (1/100 inch) in the last 24 hours
+
+ (void)extract_weather_item(data,'P',3,weather->wx_prec_00); // rainfall (1/100 inch) since midnight
+
+ if (extract_weather_item(data,'h',2,weather->wx_hum)) // humidity (in %, 00 = 100%)
+ xastir_snprintf(weather->wx_hum, sizeof(weather->wx_hum), "%03d",(atoi(weather->wx_hum)+99)%100+1);
+
+ if (extract_weather_item(data,'b',5,weather->wx_baro)) // barometric pressure (1/10 mbar / 1/10 hPascal)
+ xastir_snprintf(weather->wx_baro,
+ sizeof(weather->wx_baro),
+ "%0.1f",
+ (float)(atoi(weather->wx_baro)/10.0));
+
+ // If we parsed a speed/course, a second 's' parameter means
+ // snowfall. Try to parse it, but only in the case where
+ // we've parsed speed out of this packet already.
+ if ( (speed[0] != '\0') && (course[0] != '\0') ) {
+ (void)extract_weather_item(data,'s',3,weather->wx_snow); // snowfall, inches in the last 24 hours
+ }
+
+ (void)extract_weather_item(data,'L',3,temp); // luminosity (in watts per square meter) 999 and below
+
+ (void)extract_weather_item(data,'l',3,temp); // luminosity (in watts per square meter) 1000 and above
+
+ (void)extract_weather_item(data,'#',3,temp); // raw rain counter
+
+ (void)extract_weather_item(data,'F',3,weather->wx_fuel_temp); // Fuel Temperature in �F (RAWS)
+
+ if (extract_weather_item(data,'f',2,weather->wx_fuel_moisture))// Fuel Moisture (RAWS) (in %, 00 = 100%)
+ xastir_snprintf(weather->wx_fuel_moisture,
+ sizeof(weather->wx_fuel_moisture),
+ "%03d",
+ (atoi(weather->wx_fuel_moisture)+99)%100+1);
+
+// extract_weather_item(data,'w',3,temp); // ?? text wUII
+
+ // now there should be the name of the weather station...
+
+ // Create a timestamp from the current time
+ xastir_snprintf(weather->wx_time,
+ sizeof(weather->wx_time),
+ "%s",
+ get_time(time_data));
+
+ // Set the timestamp in the weather record so that we can
+ // decide whether or not to "ghost" the weather data later.
+ weather->wx_sec_time=sec_now();
+// weather->wx_data=1; // we don't need this
+
+// case ('.'):/* skip */
+// wx_strpos+=4;
+// break;
+
+// default:
+// wx_done=1;
+// weather->wx_type=data[wx_strpos];
+// if(strlen(data)>wx_strpos+1)
+// xastir_snprintf(weather->wx_station,
+// sizeof(weather->wx_station),
+// "%s",
+// data+wx_strpos+1);
+// break;
+ }
+ return(ok);
+}
+
+
+
+
+
+// Initial attempt at decoding tropical storm, tropical depression,
+// and hurricane data.
+//
+// This data can be in an Object report, but can also be in an Item
+// or position report.
+// "/TS" = Tropical Storm
+// "/HC" = Hurricane
+// "/TD" = Tropical Depression
+// "/TY" = Typhoon
+// "/ST" = Super Typhoon
+// "/SC" = Severe Cyclone
+
+// The symbol will be either "\@" for current position, or "/@" for
+// predicted position.
+//
+int extract_storm(DataRow *p_station, char *data, int compr) {
+ char time_data[MAX_TIME];
+ int ok = 1;
+ WeatherRow *weather;
+ char course[4];
+ char speed[4]; // Speed in knots
+ char *p, *p2;
+
+
+// Should probably encode the storm type in the weather object and
+// print it out in plain text in the Station Info dialog.
+
+ if ((p = strstr(data, "/TS")) != NULL) {
+ // We have a Tropical Storm
+//fprintf(stderr,"Tropical Storm! %s\n",data);
+ }
+ else if ((p = strstr(data, "/TD")) != NULL) {
+ // We have a Tropical Depression
+//fprintf(stderr,"Tropical Depression! %s\n",data);
+ }
+ else if ((p = strstr(data, "/HC")) != NULL) {
+ // We have a Hurricane
+//fprintf(stderr,"Hurricane! %s\n",data);
+ }
+ else if ((p = strstr(data, "/TY")) != NULL) {
+ // We have a Typhoon
+//fprintf(stderr,"Hurricane! %s\n",data);
+ }
+ else if ((p = strstr(data, "/ST")) != NULL) {
+ // We have a Super Typhoon
+//fprintf(stderr,"Hurricane! %s\n",data);
+ }
+ else if ((p = strstr(data, "/SC")) != NULL) {
+ // We have a Severe Cyclone
+//fprintf(stderr,"Hurricane! %s\n",data);
+ }
+ else { // Not one of the three we're trying to decode
+ ok = 0;
+ return(ok);
+ }
+
+//fprintf(stderr,"\n%s\n",data);
+
+ // Back up 7 spots to try to extract the next items
+ p2 = p - 7;
+ if (p2 >= data) {
+ // Attempt to extract course/speed. Speed in knots.
+ if (!extract_speed_course(p2,speed,course)) {
+ // No speed/course to extract
+//fprintf(stderr,"No speed/course found\n");
+ ok = 0;
+ return(ok);
+ }
+ }
+ else { // Not enough characters for speed/course. Must have
+ // guessed wrong on what type of data it is.
+//fprintf(stderr,"No speed/course found 2\n");
+ ok = 0;
+ return(ok);
+ }
+
+
+//fprintf(stderr,"%s\n",data);
+
+ if (ok) {
+
+ // If we got this far, we have speed/course and know what type
+ // of storm it is.
+//fprintf(stderr,"Speed: %s, Course: %s\n",speed,course);
+
+ ok = get_weather_record(p_station); // get existing or create new weather record
+ }
+
+ if (ok) {
+// p_station->speed_time[0] = '\0';
+
+ p_station->weather_data->wx_storm = 1; // We found a storm
+
+ // Note that speed is in knots. If we were stuffing it into
+ // "wx_speed" we'd have to convert it to MPH.
+ if (strcmp(speed," ") != 0 && strcmp(speed,"...") != 0) {
+ xastir_snprintf(p_station->speed,
+ sizeof(p_station->speed),
+ "%s",
+ speed);
+ }
+ else {
+ p_station->speed[0] = '\0';
+ }
+
+ if (strcmp(course," ") != 0 && strcmp(course,"...") != 0)
+ xastir_snprintf(p_station->course,
+ sizeof(p_station->course),
+ "%s",
+ course);
+ else
+ p_station->course[0] = '\0';
+
+ weather = p_station->weather_data;
+
+ p2++; // Skip the description text, "/TS", "/HC", "/TD", "/TY", "/ST", or "/SC"
+
+ // Extract the sustained wind speed in knots
+ if(extract_weather_item(p2,'/',3,weather->wx_speed))
+ // Convert from knots to MPH
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%0.1f",
+ (float)(atoi(weather->wx_speed)) * 1.1508);
+
+//fprintf(stderr,"%s\n",data);
+
+ // Extract gust speed in knots
+ if (extract_weather_item(p2,'^',3,weather->wx_gust)) // gust (peak wind speed in knots)
+ // Convert from knots to MPH
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%0.1f",
+ (float)(atoi(weather->wx_gust)) * 1.1508);
+
+//fprintf(stderr,"%s\n",data);
+
+ // Pressure is already in millibars/hPa. No conversion
+ // needed.
+ if (extract_weather_item(p2,'/',4,weather->wx_baro)) // barometric pressure (1/10 mbar / 1/10 hPascal)
+ xastir_snprintf(weather->wx_baro,
+ sizeof(weather->wx_baro),
+ "%0.1f",
+ (float)(atoi(weather->wx_baro)));
+
+//fprintf(stderr,"%s\n",data);
+
+ (void)extract_weather_item(p2,'>',3,weather->wx_hurricane_radius); // Nautical miles
+
+//fprintf(stderr,"%s\n",data);
+
+ (void)extract_weather_item(p2,'&',3,weather->wx_trop_storm_radius); // Nautical miles
+
+//fprintf(stderr,"%s\n",data);
+
+ (void)extract_weather_item(p2,'%',3,weather->wx_whole_gale_radius); // Nautical miles
+
+//fprintf(stderr,"%s\n",data);
+
+ // Create a timestamp from the current time
+ xastir_snprintf(weather->wx_time,
+ sizeof(weather->wx_time),
+ "%s",
+ get_time(time_data));
+
+ // Set the timestamp in the weather record so that we can
+ // decide whether or not to "ghost" the weather data later.
+ weather->wx_sec_time=sec_now();
+ }
+ return(ok);
+}
+
+
+
+
+
+/*
+ * Look for information about other points associated with this station.
+ * If found, compute the coordinates and save the information in the
+ * station structure.
+ * KG4NBB
+ */
+// If remove_string == 0, don't remove the string from the comment
+// field. Useful for objects/items where we need to retransmit the
+// string unchanged.
+
+#define MULTI_DEBUG 2048
+#define LBRACE '{'
+#define RBRACE '}'
+#define START_STR " }"
+
+static void extract_multipoints(DataRow *p_station,
+ char *data,
+ int type,
+ int remove_string) {
+ // If they're in there, the multipoints start with the
+ // sequence <space><rbrace><lower><digit> and end with a <lbrace>.
+ // In addition, there must be no spaces in there, and there
+ // must be an even number of characters (after the lead-in).
+
+ char *p, *p2;
+ int found = 0;
+ char *end;
+ int data_size;
+
+
+ if (debug_level & MULTI_DEBUG)
+ fprintf(stderr,"extract_multipoints: start processing %s\n",
+ p_station->call_sign);
+
+ if (data == NULL) {
+ if (debug_level & MULTI_DEBUG)
+ fprintf(stderr,"extract_multipoints: No Data, returning\n");
+ return;
+ }
+
+ if (debug_level & MULTI_DEBUG)
+ fprintf(stderr,"Data: %s\t\t\n", data);
+
+ data_size = strlen(data);
+
+ end = data + (strlen(data) - 7); // 7 == 3 lead-in chars, plus 2 points
+
+ p_station->num_multipoints = 0;
+
+ /*
+ for (p = data; !found && p <= end; ++p) {
+ if (*p == ' ' && *(p+1) == RBRACE && islower((int)*(p+2)) && isdigit((int)*(p+3)) &&
+ (p2 = strchr(p+4, LBRACE)) != NULL && ((p2 - p) % 2) == 1) {
+ found = 1;
+ }
+ }
+ */
+
+ // Start looking at the beginning of the data.
+
+ p = data;
+
+ if (debug_level & MULTI_DEBUG) {
+ if (strstr(p,START_STR) == NULL)
+ fprintf(stderr," Data does not start with space-brace, it starts with %c%c\n", p[0],p[1]);
+ else
+ fprintf(stderr," Data starts with space-brace\n");
+ }
+
+ // Look for the opening string.
+
+ while (!found && p < end && (p = strstr(p, START_STR)) != NULL) {
+ // The opening string was found. Check the following information.
+ if (debug_level & MULTI_DEBUG)
+ fprintf(stderr," Found opening brace, next chars are %c %c %c\n",
+ *(p+2),*(p+3),*(p+4));
+
+ if (islower((int)*(p+2)) && isdigit((int)*(p+3)) && (p2 = strchr(p+4, LBRACE)) != NULL && ((p2 - p) % 2) == 1) {
+ // It all looks good!
+
+ found = 1;
+ }
+ else {
+ // The following characters are not right. Advance and
+ // look again.
+ if (debug_level & MULTI_DEBUG)
+ fprintf(stderr," Found opening string (}) but next characters are not right: %c %c %c\n",*(p+2),*(p+3),*(p+4));
+ ++p;
+ }
+ }
+
+ if (found) {
+ long multiplier;
+ double d;
+ char *m_start = p; // Start of multipoint string
+ char ok = 1;
+
+ if (debug_level & MULTI_DEBUG)
+ fprintf(stderr,"station %s contains \"%s\"\n", p_station->call_sign, p);
+
+ // The second character (the lowercase) indicates additional style information,
+ // such as color, line type, etc.
+
+ p_station->style = *(p+2);
+
+ // The third character (the digit) indicates the way the points should be
+ // used. They may be used to draw a closed polygon, a series of line segments,
+ // etc.
+
+ p_station->type = *(p+3);
+
+ // The fourth character indicates the scale of the coordinates that
+ // follow. It may range from '!' to '|' (124). The value represents the
+ // unit of measure (1, 0.1, 0.001, etc., in degrees) used in the offsets.
+ //
+ // Use the following formula to convert the char to the value:
+ // (10 ^ ((c - 33) / 20)) / 10000 degrees
+ //
+ // Finally we have to convert to Xastir units. Xastir stores coordinates
+ // as hudredths of seconds. There are 360,000 of those per degree, so we
+ // need to multiply by that factor so our numbers will be converted to
+ // Xastir units.
+
+ p = p + 4;
+
+ if (*p < '!' || *p > '|') {
+ fprintf(stderr,"extract_multipoints: invalid scale character %d\n", *p);
+ ok = 0; // Failure
+ }
+ else {
+
+ d = (double)(*p);
+ d = pow(10.0, ((d - 33) / 20)) / 10000.0 * 360000.0;
+ multiplier = (long)d;
+ if (debug_level & MULTI_DEBUG)
+ fprintf(stderr," multiplier factor is: %c %d %f (%ld)\n", *p, *p, d, multiplier);
+
+ ++p;
+
+ // The remaining characters are in pairs. Each pair is the
+ // offset lat and lon for one of the points. (The offset is
+ // from the actual location of the object.) Convert each
+ // character to its numeric value and save it.
+
+ while (*p != LBRACE && p_station->num_multipoints < MAX_MULTIPOINTS) {
+ // The characters are in the range '"' (34 decimal) to 'z' (122). They
+ // encode values in the range -44 to +44. To convert to the correct
+ // value 78 is subtracted from the character's value.
+
+ int lat_val = *p - 78;
+ int lon_val = *(p+1) - 78;
+
+ // Check for correct values.
+
+ if (lon_val < -44 || lon_val > 44 || lat_val < -44 || lat_val > 44) {
+ char temp[MAX_LINE_SIZE+1];
+ int i;
+
+ // Filter the string so we don't send strange
+ // chars to the xterm
+ for (i = 0; i < (int)strlen(data); i++) {
+ temp[i] = data[i] & 0x7f;
+ if ( (temp[i] < 0x20) || (temp[i] > 0x7e) )
+ temp[i] = ' ';
+ }
+ temp[strlen(data)] = '\0';
+
+ fprintf(stderr,"extract_multipoints: invalid value in (filtered) \"%s\": %d,%d\n",
+ temp,
+ lat_val,
+ lon_val);
+
+ p_station->num_multipoints = 0; // forget any points we already set
+ ok = 0; // Failure to decode
+ break;
+ }
+
+ // Malloc the storage area for this if we don't have
+ // it yet.
+ if (p_station->multipoint_data == NULL) {
+//fprintf(stderr, "Malloc'ing MultipointRow record, %s\n", p_station->call_sign);
+ p_station->multipoint_data = malloc(sizeof(MultipointRow));
+ if (p_station->multipoint_data == NULL) {
+ p_station->num_multipoints = 0;
+ fprintf(stderr,"Couldn't malloc MultipointRow'\n");
+ if (debug_level & MULTI_DEBUG)
+ fprintf(stderr,"extract_multipoints: Malloc failure, returning\n");
+ return;
+ }
+ }
+
+ if (debug_level & MULTI_DEBUG)
+ fprintf(stderr,"computed offset %d,%d\n", lat_val, lon_val);
+
+ // Add the offset to the object's position to obtain the position of the point.
+ // Note that we're working in Xastir coordinates, and in North America they
+ // are exactly opposite to lat/lon (larger numbers are farther east and south).
+ // An offset with a positive value means that the point should be north and/or
+ // west of the object, so we have to *subtract* the offset to get the correct
+ // placement in Xastir coordinates.
+ // TODO: Consider what we should do in the other geographic quadrants. Should we
+ // check here for the correct sign of the offset? Or should the program that
+ // creates the offsets take that into account?
+
+ p_station->multipoint_data->multipoints[p_station->num_multipoints][0]
+ = p_station->coord_lon - (lon_val * multiplier);
+ p_station->multipoint_data->multipoints[p_station->num_multipoints][1]
+ = p_station->coord_lat - (lat_val * multiplier);
+
+ if (debug_level & MULTI_DEBUG)
+ fprintf(stderr,
+ "computed point %ld, %ld\n",
+ p_station->multipoint_data->multipoints[p_station->num_multipoints][0],
+ p_station->multipoint_data->multipoints[p_station->num_multipoints][1]);
+ p += 2;
+ ++p_station->num_multipoints;
+ } // End of while loop
+ }
+
+ if (ok && remove_string) {
+ // We've successfully decoded a multipoint object?
+ // Remove the multipoint strings (and the sequence
+ // number at the end if present) from the data string.
+ // m_start points to the first character (a space). 'p'
+ // should be pointing at the LBRACE character.
+
+ // Make 'p' point to just after the end of the chars
+ while ( (p < data+strlen(data)) && (*p != ' ') ) {
+ p++;
+ }
+ // The string that 'p' points to now may be empty
+
+ // Truncate "data" at the starting brace - 1
+ *m_start = '\0';
+
+ // Now we have two strings inside "data". Copy the 2nd
+ // string directly onto the end of the first.
+ strncat(data, p, data_size+1);
+
+ // The multipoint string and sequence number should be
+ // erased now from "data".
+//fprintf(stderr,"New Data: %s\n", data);
+ }
+
+ if (debug_level & MULTI_DEBUG)
+ fprintf(stderr," station has %d points\n", p_station->num_multipoints);
+ }
+
+ if (debug_level & MULTI_DEBUG)
+ fprintf(stderr,"extract_multipoints: Normal Return\n");
+}
+
+#undef MULTI_DEBUG
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+void init_weather(WeatherRow *weather) { // clear weather data
+
+ weather->wx_sec_time = (time_t)0;
+ weather->wx_storm = 0;
+ weather->wx_time[0] = '\0';
+ weather->wx_course[0] = '\0';
+ weather->wx_speed[0] = '\0';
+ weather->wx_speed_sec_time = 0; // ??
+ weather->wx_gust[0] = '\0';
+ weather->wx_hurricane_radius[0] = '\0';
+ weather->wx_trop_storm_radius[0] = '\0';
+ weather->wx_whole_gale_radius[0] = '\0';
+ weather->wx_temp[0] = '\0';
+ weather->wx_rain[0] = '\0';
+ weather->wx_rain_total[0] = '\0';
+ weather->wx_snow[0] = '\0';
+ weather->wx_prec_24[0] = '\0';
+ weather->wx_prec_00[0] = '\0';
+ weather->wx_hum[0] = '\0';
+ weather->wx_baro[0] = '\0';
+ weather->wx_fuel_temp[0] = '\0';
+ weather->wx_fuel_moisture[0] = '\0';
+ weather->wx_type = '\0';
+ weather->wx_station[0] = '\0';
+}
+
+
+
+
+
+int get_weather_record(DataRow *fill) { // get or create weather storage
+ int ok=1;
+
+ if (fill->weather_data == NULL) { // new weather data, allocate storage and init
+ fill->weather_data = malloc(sizeof(WeatherRow));
+ if (fill->weather_data == NULL) {
+ fprintf(stderr,"Couldn't allocate memory in get_weather_record()\n");
+ ok = 0;
+ }
+ else {
+ init_weather(fill->weather_data);
+ }
+ }
+ return(ok);
+}
+
+
+
+
+
+int delete_weather(DataRow *fill) { // delete weather storage, if allocated
+
+ if (fill->weather_data != NULL) {
+ free(fill->weather_data);
+ fill->weather_data = NULL;
+ return(1);
+ }
+ return(0);
+}
+
+
+
+
+
+int delete_multipoints(DataRow *fill) { // delete multipoint storage, if allocated
+
+ if (fill->multipoint_data != NULL) {
+//fprintf(stderr,"Removing multipoint data, %s\n", fill->call_sign);
+ free(fill->multipoint_data);
+ fill->multipoint_data = NULL;
+ fill->num_multipoints = 0;
+ return(1);
+ }
+ return(0);
+}
+
+
+
+////////////////////////////////////////// Trails //////////////////////////////////////////////////
+
+
+
+/*
+ * See if current color is defined as active trail color
+ */
+int trail_color_active(int color_index) {
+
+ // this should be made configurable...
+ // to select trail colors to use
+
+ return(1); // accept this color
+}
+
+
+
+
+
+/*
+ * Get new trail color for a call
+ */
+int new_trail_color(char *call) {
+ int color, found, i;
+
+ // If my_trail_diff_color is set a 0, then we'll
+ // assign one color to every SSID from our callsign. If
+ // 1, they get the next color available (round-robin style) just
+ // like all the other stations.
+ //
+ // 0 for last parameter in is_my_call() means skip SSID in
+ // callsign check. Non-zero means the callsign + SSID must be
+ // an exact match.
+ if (is_my_call(call,my_trail_diff_color)) {
+ color = MY_TRAIL_COLOR; // It's my call, so use special color
+ }
+ else {
+ // all other callsigns get some other color out of the color table
+ color = current_trail_color;
+ for(i=0,found=0;!found && i<MAX_TRAIL_COLORS;i++) {
+ color = (color + 1) % MAX_TRAIL_COLORS; // try next color in list
+ // skip special and or inactive colors.
+ if (color != MY_TRAIL_COLOR && trail_color_active(color))
+ found = 1;
+ }
+ if (found)
+ current_trail_color = color; // save it for next time
+ else
+ color = current_trail_color; // keep old color
+ }
+ return(color);
+}
+
+
+
+
+
+//
+// Store one trail point. Allocate storage for the new data.
+//
+// We now store track data in a doubly-linked list. Each record has a
+// pointer to the previous and the next record in the list. The main
+// station record has a pointer to the oldest and the newest end of the
+// chain, and the chain can be traversed in either order.
+//
+int store_trail_point(DataRow *p_station,
+ long lon,
+ long lat,
+ time_t sec,
+ char *alt,
+ char *speed,
+ char *course,
+ short stn_flag) {
+
+ char flag;
+ TrackRow *ptr;
+
+ //fprintf(stderr,"store_trail_point: %s\n",p_station->call_sign);
+
+ if (debug_level & 256) {
+ fprintf(stderr,"store_trail_point: for %s\n", p_station->call_sign);
+ }
+
+ // Allocate storage for the new track point
+ ptr = malloc(sizeof(TrackRow));
+ if (ptr == NULL) {
+ if (debug_level & 256) {
+ fprintf(stderr,"store_trail_point: MALLOC failed for trail.\n");
+ }
+ return(0); // Failed due to malloc
+ }
+
+ // Check whether we have any track data saved
+ if (p_station->newest_trackpoint == NULL) {
+ // new trail, do initialization
+
+ if (debug_level & 256) {
+ fprintf(stderr,"Creating new trail.\n");
+ }
+ tracked_stations++;
+
+ // Assign a new trail color 'cuz it's a new trail
+ p_station->trail_color = new_trail_color(p_station->call_sign);
+ }
+
+ // Start linking the record to the new end of the chain
+ ptr->prev = p_station->newest_trackpoint; // Link to record or NULL
+ ptr->next = NULL; // Newest end of chain
+
+ // Have an older record already?
+ if (p_station->newest_trackpoint != NULL) { // Yes
+ p_station->newest_trackpoint->next = ptr;
+ }
+ else { // No, this is our first record
+ p_station->oldest_trackpoint = ptr;
+ }
+
+ // Link it in as our newest record
+ p_station->newest_trackpoint = ptr;
+
+ if (debug_level & 256) {
+ fprintf(stderr,"store_trail_point: Storing data for %s\n", p_station->call_sign);
+ }
+
+ ptr->trail_long_pos = lon;
+ ptr->trail_lat_pos = lat;
+ ptr->sec = sec;
+
+ if (alt[0] != '\0')
+ ptr->altitude = atoi(alt)*10;
+ else
+ ptr->altitude = -99999l;
+
+ if (speed[0] != '\0')
+ ptr->speed = (long)(atof(speed)*18.52);
+ else
+ ptr->speed = -1;
+
+ if (course[0] != '\0')
+ ptr->course = (int)(atof(course) + 0.5); // Poor man's rounding
+ else
+ ptr->course = -1;
+
+ flag = '\0'; // init flags
+
+ if ((stn_flag & ST_DIRECT) != 0)
+ flag |= TR_LOCAL; // set "local" flag
+
+ if (ptr->prev != NULL) { // we have at least two points...
+ // Check whether distance between points is too far. We
+ // must convert from degrees to the Xastir coordinate system
+ // units, which are 100th of a second.
+ if ( abs(lon - ptr->prev->trail_long_pos) > (trail_segment_distance * 60*60*100) ||
+ abs(lat - ptr->prev->trail_lat_pos) > (trail_segment_distance * 60*60*100) ) {
+
+ // Set "new track" flag if there's
+ // "trail_segment_distance" degrees or more between
+ // points. Originally was hard-coded to one degree, now
+ // set by a slider in the timing dialog.
+ flag |= TR_NEWTRK;
+ }
+ else {
+ // Check whether trail went above our maximum time
+ // between points. If so, don't draw segment.
+ if (abs(sec - ptr->prev->sec) > (trail_segment_time *60)) {
+
+ // Set "new track" flag if long delay between
+ // reception of two points. Time is set by a slider
+ // in the timing dialog.
+ flag |= TR_NEWTRK;
+ }
+ }
+ }
+ else {
+ // Set "new track" flag for first point received.
+ flag |= TR_NEWTRK;
+ }
+ ptr->flag = flag;
+
+ return(1); // We succeeded
+}
+
+
+
+
+
+/*
+ * Check if current packet is a delayed echo
+ */
+int is_trailpoint_echo(DataRow *p_station) {
+ int packets = 1;
+ time_t checktime;
+ char temp[50];
+ TrackRow *ptr;
+
+
+ // Check whether we're to skip checking for dupes (reading in
+ // objects/items from file is one such case).
+ //
+ if (skip_dupe_checking) {
+ return(0); // Say that it isn't an echo
+ }
+
+ // Start at newest end of linked list and compare. Return if we're
+ // beyond the checktime.
+ ptr = p_station->newest_trackpoint;
+
+ if (ptr == NULL)
+ return(0); // first point couldn't be an echo
+
+ checktime = p_station->sec_heard - TRAIL_ECHO_TIME*60;
+
+ while (ptr != NULL) {
+
+ if (ptr->sec < checktime)
+ return(0); // outside time frame, no echo found
+
+ if ((p_station->coord_lon == ptr->trail_long_pos)
+ && (p_station->coord_lat == ptr->trail_lat_pos)
+ && (p_station->speed == '\0' || ptr->speed < 0
+ || (long)(atof(p_station->speed)*18.52) == ptr->speed)
+ // current: char knots, trail: long 0.1m (-1 is undef)
+ && (p_station->course == '\0' || ptr->course <= 0
+ || atoi(p_station->course) == ptr->course)
+ // current: char, trail: int (-1 is undef)
+ && (p_station->altitude == '\0' || ptr->altitude <= -99999l
+ || atoi(p_station->altitude)*10 == ptr->altitude)) {
+ // current: char, trail: int (-99999l is undef)
+ if (debug_level & 1) {
+ fprintf(stderr,"delayed echo for %s",p_station->call_sign);
+ convert_lat_l2s(p_station->coord_lat, temp, sizeof(temp), CONVERT_HP_NORMAL);
+ fprintf(stderr," at %s",temp);
+ convert_lon_l2s(p_station->coord_lon, temp, sizeof(temp), CONVERT_HP_NORMAL);
+ fprintf(stderr," %s, already heard %d packets ago\n",temp,packets);
+ }
+ return(1); // we found a delayed echo
+ }
+ ptr = ptr->prev;
+ packets++;
+ }
+ return(0); // no echo found
+}
+
+
+
+
+
+//
+// Expire trail points.
+//
+// We now store track data in a doubly-linked list. Each record has a
+// pointer to the previous and the next record in the list. The main
+// station record has a pointer to the oldest and the newest end of the
+// chain, and the chain can be traversed in either order. We use
+// this to advantage by adding records at one end of the list and
+// expiring them at the other.
+//
+void expire_trail_points(DataRow *p_station, time_t sec) {
+ int ii = 0;
+ int done = 0;
+ TrackRow *ptr;
+
+
+ //fprintf(stderr,"expire_trail_points: %s\n",p_station->call_sign);
+
+ if (debug_level & 256) {
+ fprintf(stderr,"expire_trail_points: %s\n",p_station->call_sign);
+ }
+
+ // Check whether we have any track data saved
+ if (p_station->oldest_trackpoint == NULL) {
+ return; // Nothing to expire
+ }
+
+ // Iterate from oldest->newest trackpoints
+ while (!done && p_station->oldest_trackpoint != NULL) {
+ ptr = p_station->oldest_trackpoint;
+ if ( (ptr->sec + sec) >= sec_now() ) {
+ // New trackpoint, within expire time. Quit checking
+ // the rest of the trackpoints for this station.
+ done++;
+ }
+ else {
+ //fprintf(stderr,"Found old trackpoint\n");
+
+ // Track too old. Unlink this trackpoint and free it.
+ p_station->oldest_trackpoint = ptr->next;
+
+ // End of chain in this direction
+ if (p_station->oldest_trackpoint != NULL) {
+ p_station->oldest_trackpoint->prev = NULL;
+ }
+ else {
+ p_station->newest_trackpoint = NULL;
+ }
+
+ // Free up the space used by the expired trackpoint
+ free(ptr);
+
+ //fprintf(stderr,"Free'ing a trackpoint\n");
+
+ ii++;
+
+ // Reduce our count of mobile stations if the size of
+ // the track just went to zero.
+ if (p_station->oldest_trackpoint == NULL)
+ tracked_stations--;
+ }
+ }
+
+ if ( (debug_level & 256) && ii ) {
+ fprintf(stderr,"expire_trail_points: %d trackpoints free'd for %s\n",
+ ii,
+ p_station->call_sign);
+ }
+}
+
+
+
+
+
+/*
+ * Delete comment records and free memory
+ */
+int delete_comments_and_status(DataRow *fill) {
+
+ // If the pointers are empty, we're done
+ if ( (fill->comment_data == NULL)
+ && (fill->status_data == NULL) ) {
+ return(0);
+ }
+
+ if (fill->comment_data != NULL) { // We have comment records
+ CommentRow *ptr;
+ CommentRow *ptr_next;
+
+ ptr = fill->comment_data;
+ ptr_next = ptr->next;
+ while (ptr != NULL) {
+ // Free the actual text string that we malloc'ed
+ if (ptr->text_ptr != NULL) {
+ free(ptr->text_ptr);
+ }
+ free(ptr);
+ ptr = ptr_next; // Advance to next record
+ if (ptr != NULL)
+ ptr_next = ptr->next;
+ else
+ ptr_next = NULL;
+ }
+ }
+ if (fill->status_data != NULL) { // We have status records
+ CommentRow *ptr;
+ CommentRow *ptr_next;
+
+ ptr = fill->status_data;
+ ptr_next = ptr->next;
+ while (ptr != NULL) {
+ // Free the actual text string that we malloc'ed
+ if (ptr->text_ptr != NULL) {
+ free(ptr->text_ptr);
+ }
+ free(ptr);
+ ptr = ptr_next; // Advance to next record
+ if (ptr != NULL)
+ ptr_next = ptr->next;
+ else
+ ptr_next = NULL;
+ }
+ }
+ return(1);
+}
+
+
+
+
+
+/*
+ * Delete trail and free memory
+ */
+int delete_trail(DataRow *fill) {
+
+ if (fill->newest_trackpoint != NULL) {
+ TrackRow *current;
+ TrackRow *next;
+
+ // Free the TrackRow records
+ current = fill->oldest_trackpoint;
+ while (current != NULL) {
+ next = current->next;
+ free(current);
+ current = next;
+ }
+
+ fill->oldest_trackpoint = NULL;
+ fill->newest_trackpoint = NULL;
+ tracked_stations--;
+ return(1);
+ }
+ return(0);
+}
+
+
+
+
+
+/*
+ * Draw trail on screen. If solid=1, draw type LineSolid, else
+ * draw type LineOnOffDash.
+ *
+ * If label_all_trackpoints=1, add the callsign next to each
+ * trackpoint. We may modify this and just add the callsign at the
+ * start/end of each new track segment.
+ *
+ */
+void draw_trail(Widget w, DataRow *fill, int solid) {
+ char short_dashed[2] = {(char)1,(char)5};
+ char medium_dashed[2] = {(char)5,(char)5};
+ unsigned long lat0, lon0, lat1, lon1; // trail segment points
+ int col_trail, col_dot;
+ XColor rgb;
+ long brightness;
+ char flag1;
+ TrackRow *ptr;
+
+
+ if (!ok_to_draw_station(fill))
+ return;
+
+ // Expire old trackpoints first. We use the
+ // remove-station-from-display time as the expire time for
+ // trackpoints. This can be set from the Configure->Defaults
+ // dialog.
+ expire_trail_points(fill, sec_clear);
+
+ ptr = fill->newest_trackpoint;
+
+ // Trail should have at least two points
+ if ( (ptr != NULL) && (ptr->prev != NULL) ) {
+ int skip_dupes = 0; // Don't skip points first time through
+
+ if (debug_level & 256) {
+ fprintf(stderr,"draw_trail called for %s with %s.\n",
+ fill->call_sign, (solid? "Solid" : "Non-Solid"));
+ }
+
+ col_trail = trail_colors[fill->trail_color];
+
+ // define color of position dots in trail
+ rgb.pixel = col_trail;
+ XQueryColor(XtDisplay(w),cmap,&rgb);
+
+ brightness = (long)(0.3*rgb.red + 0.55*rgb.green + 0.15*rgb.blue);
+ if (brightness > 32000l) {
+ col_dot = trail_colors[0x05]; // black dot on light trails
+ }
+ else {
+ col_dot = trail_colors[0x06]; // white dot on dark trail
+ }
+
+ if (solid)
+ // Used to be "JoinMiter" and "CapButt" below
+ (void)XSetLineAttributes(XtDisplay(w), gc, 3, LineSolid, CapRound, JoinRound);
+ else {
+ // Another choice is LineDoubleDash
+ (void)XSetLineAttributes(XtDisplay(w), gc, 3, LineOnOffDash, CapRound, JoinRound);
+ (void)XSetDashes(XtDisplay(w), gc, 0, short_dashed , 2);
+ }
+
+ // Traverse linked list of trail points from newest to
+ // oldest
+ while ( (ptr != NULL) && (ptr->prev != NULL) ) {
+ lon0 = ptr->trail_long_pos; // Trail segment start
+ lat0 = ptr->trail_lat_pos;
+ lon1 = ptr->prev->trail_long_pos; // Trail segment end
+ lat1 = ptr->prev->trail_lat_pos;
+ flag1 = ptr->flag; // Are we at the start of a new trail?
+
+ if ((flag1 & TR_NEWTRK) == '\0') {
+ int lon0_screen, lat0_screen, lon1_screen, lat1_screen;
+
+ // draw trail segment
+ //
+ (void)XSetForeground(XtDisplay(w),gc,col_trail);
+ draw_vector(da,
+ lon0,
+ lat0,
+ lon1,
+ lat1,
+ gc,
+ pixmap_final,
+ skip_dupes);
+
+ // draw position point itself
+ //
+ (void)XSetForeground(XtDisplay(w),gc,col_dot);
+ draw_point(w,
+ lon0,
+ lat0,
+ gc,
+ pixmap_final,
+ skip_dupes);
+
+ // Draw the callsign to go with the point if
+ // label_all_trackpoints=1
+ //
+ if (Display_.callsign && Display_.label_all_trackpoints) {
+
+ // Convert to screen coordinates
+ lon0_screen = (lon0 - NW_corner_longitude) / scale_x;
+ lat0_screen = (lat0 - NW_corner_latitude) / scale_y;
+
+ // Convert to screen coordinates.
+ lon1_screen = (lon1 - NW_corner_longitude) / scale_x;
+ lat1_screen = (lat1 - NW_corner_latitude) / scale_y;
+
+ // The last position already gets its callsign
+ // string drawn, plus that gets shifted based on
+ // other parameters. Draw both points of all
+ // line segments except that one. This will
+ // result in strings getting drawn twice at
+ // times, but they overlay on top of each other
+ // so no big deal.
+ //
+ if (ptr != fill->newest_trackpoint) {
+
+ draw_nice_string(da,
+ pixmap_final,
+ letter_style,
+ lon0_screen+10,
+ lat0_screen,
+ fill->call_sign,
+ 0x08,
+ 0x0f,
+ strlen(fill->call_sign));
+
+ // If not same screen position as last drawn
+ if (lon0_screen != lon1_screen
+ && lat0_screen != lat1_screen) {
+
+ draw_nice_string(da,
+ pixmap_final,
+ letter_style,
+ lon1_screen+10,
+ lat1_screen,
+ fill->call_sign,
+ 0x08,
+ 0x0f,
+ strlen(fill->call_sign));
+ }
+ }
+ }
+ }
+ ptr = ptr->prev;
+ skip_dupes = 1;
+ }
+ (void)XSetDashes(XtDisplay(w), gc, 0, medium_dashed , 2);
+ }
+ else if (debug_level & 256) {
+ fprintf(stderr,"Trail for %s does not contain 2 or more points.\n",
+ fill->call_sign);
+ }
+}
+
+
+
+
+
+// DK7IN: there should be some library functions for the next two,
+// but I don't have any documentation while being in holidays...
+void month2str(int month, char *str, int str_size) {
+
+ switch (month) {
+ case 0: xastir_snprintf(str,str_size,"Jan"); break;
+ case 1: xastir_snprintf(str,str_size,"Feb"); break;
+ case 2: xastir_snprintf(str,str_size,"Mar"); break;
+ case 3: xastir_snprintf(str,str_size,"Apr"); break;
+ case 4: xastir_snprintf(str,str_size,"May"); break;
+ case 5: xastir_snprintf(str,str_size,"Jun"); break;
+ case 6: xastir_snprintf(str,str_size,"Jul"); break;
+ case 7: xastir_snprintf(str,str_size,"Aug"); break;
+ case 8: xastir_snprintf(str,str_size,"Sep"); break;
+ case 9: xastir_snprintf(str,str_size,"Oct"); break;
+ case 10: xastir_snprintf(str,str_size,"Nov"); break;
+ case 11: xastir_snprintf(str,str_size,"Dec"); break;
+ default: xastir_snprintf(str,str_size," "); break;
+ }
+}
+
+
+
+
+
+void wday2str(int wday, char *str, int str_size) {
+
+ switch (wday) {
+ case 0: xastir_snprintf(str,str_size,"Sun"); break;
+ case 1: xastir_snprintf(str,str_size,"Mon"); break;
+ case 2: xastir_snprintf(str,str_size,"Tue"); break;
+ case 3: xastir_snprintf(str,str_size,"Wed"); break;
+ case 4: xastir_snprintf(str,str_size,"Thu"); break;
+ case 5: xastir_snprintf(str,str_size,"Fri"); break;
+ case 6: xastir_snprintf(str,str_size,"Sat"); break;
+ default: xastir_snprintf(str,str_size," "); break;
+ }
+}
+
+
+
+
+
+/*
+ * Export trail point to file
+ *
+ * Don't call directly, call export_trail() or export_trail_as_kml() instead
+ * as they need to open the file, set appropriate headers, and call export_trailstation()
+ * to set the context for the position.
+ */
+void exp_trailpos(FILE *f,long lat,long lon,time_t sec,long speed,int course,long alt,int newtrk, int export_format) {
+ struct tm *time;
+ char lat_string[12+1];
+ char lon_string[12+1];
+ char month[3+1];
+ char wday[3+1];
+ float deg;
+
+ time = gmtime(&sec);
+ month2str(time->tm_mon, month, sizeof(month));
+ wday2str(time->tm_wday, wday, sizeof(wday));
+ switch (export_format) {
+ case EXPORT_KML_TRACK:
+ // kml format is longitude,latitude,altitude triplets with
+ // a comma and no spaces separating elements of the triplet
+ // and a single space seperating sets of triplets in a
+ // coordinates element. Latitude and longitude are
+ // both in decimal degrees.
+ deg = (float)(lon - 64800000l) / 360000.0;
+ fprintf(f,"%09.5f,",deg);
+ deg = -(float)(lat - 32400000l) / 360000.0;
+ fprintf(f,"%08.5f,",deg);
+ if (alt > -99999l)
+ fprintf(f,"%05.0f ",(float)(alt/10.0));
+ else // undefined
+ fprintf(f,"0 ");
+ break;
+ case EXPORT_XASTIR_TRACK:
+ default:
+ if (newtrk)
+ fprintf(f,"\nN New Track Start\n");
+ // DK7IN: The format may change in the near future !
+ // Are there any standards? I want to be able to be compatible to
+ // GPS data formats (e.g. G7TO) for easy interchange from/to GPS
+ // How should we present undefined data? (speed/course/altitude)
+ convert_lat_l2s(lat, lat_string, sizeof(lat_string), CONVERT_UP_TRK);
+ convert_lon_l2s(lon, lon_string, sizeof(lon_string), CONVERT_UP_TRK);
+ fprintf(f,"T %s",lat_string);
+ fprintf(f," %s",lon_string);
+ fprintf(f," %s %s %02d %02d:%02d:%02d %04d",wday,month,time->tm_mday,time->tm_hour,time->tm_min,time->tm_sec,time->tm_year+1900);
+
+ if (alt > -99999l)
+ fprintf(f," %5.0fm",(float)(alt/10.0));
+ else // undefined
+ fprintf(f," ");
+
+ if (speed >= 0)
+ fprintf(f," %4.0fkm/h",(float)(speed/10.0));
+ else // undefined
+ fprintf(f," ");
+
+ if (course >= 0) // DK7IN: is 0 undefined ?? 1..360 ?
+ fprintf(f," %3d�\n",course);
+ else // undefined
+ fprintf(f," \n");
+ }
+}
+
+
+
+
+
+/*
+ * Export trail for one station to file.
+ * Don't call directly, call export_trail() or export_trail_as_kml() instead
+ * as they need to open the file and set appropriate headers.
+ *
+ * @param f handle of file to write to
+ * @param p_station pointer to station to write
+ * @param export_format file format to use (xastir tracklog or kml).
+ */
+void exp_trailstation(FILE *f, DataRow *p_station, int export_format) {
+ char timestring[101]; // string representation of the time heard or the current time
+ long lat0, lon0;
+ int newtrk;
+ time_t sec;
+ long speed; // 0.1km/h
+ int course; // degrees
+ long alt; // 0.1m
+ TrackRow *current;
+
+ newtrk = 1;
+
+ current = p_station->oldest_trackpoint;
+
+ switch (export_format) {
+
+ case EXPORT_KML_TRACK:
+ // This placemark is for a single position
+ // or for the most recent position of a trail
+ // in either case represented as a <Point/>
+ // and will show up as a labeled pushpin point.
+ fprintf(f,"<Placemark>");
+ get_iso_datetime(p_station->sec_heard,timestring,True,True);
+
+ if (p_station->origin == NULL || p_station->origin[0] == '\0') {
+ fprintf(f,"<name>%s</name>\n",p_station->call_sign);
+ fprintf(f,"<description>");
+ } else {
+ fprintf(f,"<name>%s</name>\n<description>Object from %s. \n",p_station->call_sign,p_station->origin);
+ }
+ // packets recieved %d last heard %s
+ fprintf(f,langcode("WPUPSTI005"),p_station->num_packets, timestring);
+ if (p_station->tactical_call_sign && p_station->tactical_call_sign[0] != '\0') {
+ // tactical call %s
+ fprintf(f, langcode("WPUPSTI065"), p_station->tactical_call_sign);
+ }
+ fprintf(f,"</description>\n");
+
+ // kml specifies w3c's date time format for timestamps
+ if (get_w3cdtf_datetime(p_station->sec_heard, timestring, False, False))
+ if (strlen(timestring) > 0)
+ fprintf(f,"<TimeStamp><when>%s</when></TimeStamp>",timestring);
+
+ if (current != NULL) {
+ // We have trail points, create both a set of time stamp labled point placemarks
+ // and a linestring placemark to draw the trail.
+ fprintf(f,"<Point>\n<coordinates>");
+ if (p_station->altitude[0] != '\0')
+ alt = atoi(p_station->altitude)*10;
+ else
+ alt = -99999l;
+ if (p_station->speed[0] != '\0')
+ speed = (long)(atof(p_station->speed)*18.52);
+ else
+ speed = -1;
+ if (p_station->course[0] != '\0')
+ course = atoi(p_station->course);
+ else
+ course = -1;
+ exp_trailpos(f,p_station->coord_lat,p_station->coord_lon,p_station->sec_heard,speed,course,alt,newtrk, export_format);
+ fprintf(f,"</coordinates></Point>");
+
+ fprintf(f,"</Placemark>\n");
+
+ // folow with a set of timestamped placemarks for each point on trail
+ while (current != NULL) {
+ lon0 = current->trail_long_pos; // Trail segment start
+ lat0 = current->trail_lat_pos;
+ sec = current->sec;
+ speed = current->speed;
+ course = current->course;
+ alt = current->altitude;
+ // kml specifies w3c's date time format for timestamps
+ if (get_w3cdtf_datetime(sec,timestring,False,False) && (int)sec>0) {
+ // point has valid timestamp, write it
+ fprintf(f,"<Placemark>");
+ fprintf(f,"<name>%s at %s</name>\n",p_station->call_sign, timestring);
+ fprintf(f,"<TimeStamp><when>%s</when></TimeStamp>",timestring);
+ fprintf(f,"<Point><coordinates>");
+ exp_trailpos(f,lat0,lon0,sec,speed,course,alt,newtrk, export_format);
+ fprintf(f,"</coordinates></Point>");
+ fprintf(f,"</Placemark>\n");
+ }
+ // Advance to the next point
+ current = current->next;
+ }
+ // Prepare to follow with a trail (as a <LineString/>).
+ fprintf(f,"<Placemark>");
+ if (p_station->origin == NULL || p_station->origin[0] == '\0')
+ fprintf(f,"<name>%s (trail)</name>\n",p_station->call_sign);
+ else
+ fprintf(f,"<name>%s (trail)</name>\n<description>Object from %s</description>\n",p_station->call_sign,p_station->origin);
+ }
+ break;
+
+ case EXPORT_XASTIR_TRACK:
+ default:
+ if (p_station->origin == NULL || p_station->origin[0] == '\0')
+ fprintf(f,"\n#C %s\n",p_station->call_sign);
+ else
+ fprintf(f,"\n#O %s %s\n",p_station->call_sign,p_station->origin);
+ }
+
+ // A trail must have at least two points: One in the struct,
+ // and one in the tracklog. If the station only has one point,
+ // there won't be a tracklog. If the station has moved, then
+ // it'll have both.
+
+ // reset current, as we may have moved it past the last trackpoint
+ // while generating kml above.
+ current = p_station->oldest_trackpoint;
+
+ if (current != NULL) { // We have trail points, loop through
+ // them. Skip the most current position
+ // because it is included in the
+ // tracklog (if we have a tracklog!).
+
+ switch (export_format) {
+ case EXPORT_KML_TRACK:
+ fprintf(f,"<LineString>\n<coordinates>");
+ break;
+ //default:
+ // no heading for set of points
+ }
+ while (current != NULL) {
+ lon0 = current->trail_long_pos; // Trail segment start
+ lat0 = current->trail_lat_pos;
+ sec = current->sec;
+ speed = current->speed;
+ course = current->course;
+ alt = current->altitude;
+ if ((current->flag & TR_NEWTRK) != '\0')
+ newtrk = 1;
+
+ // identical for kml and xastir tracks, but could be different for other formats
+ switch (export_format) {
+ case EXPORT_KML_TRACK:
+ exp_trailpos(f,lat0,lon0,sec,speed,course,alt,newtrk, export_format);
+ break;
+ case EXPORT_XASTIR_TRACK:
+ default:
+ exp_trailpos(f,lat0,lon0,sec,speed,course,alt,newtrk, export_format);
+ }
+
+ newtrk = 0;
+
+ // Advance to the next point
+ current = current->next;
+ }
+ switch (export_format) {
+ case EXPORT_KML_TRACK:
+ fprintf(f,"</coordinates>\n</LineString>\n");
+ break;
+ //default:
+ // no close for set of points
+ }
+ }
+ else { // We don't have any tracklog, so write out the most
+ // current position only.
+
+ if (p_station->altitude[0] != '\0')
+ alt = atoi(p_station->altitude)*10;
+ else
+ alt = -99999l;
+
+ if (p_station->speed[0] != '\0')
+ speed = (long)(atof(p_station->speed)*18.52);
+ else
+ speed = -1;
+
+ if (p_station->course[0] != '\0')
+ course = atoi(p_station->course);
+ else
+ course = -1;
+
+ switch (export_format) {
+ case EXPORT_KML_TRACK:
+ fprintf(f,"<Point>\n\t<coordinates>");
+ exp_trailpos(f,p_station->coord_lat,p_station->coord_lon,p_station->sec_heard,speed,course,alt,newtrk, export_format);
+ fprintf(f,"</coordinates>\n\t</Point>\n");
+ break;
+ case EXPORT_XASTIR_TRACK:
+ default:
+ exp_trailpos(f,p_station->coord_lat,p_station->coord_lon,p_station->sec_heard,speed,course,alt,newtrk, export_format);
+ }
+ }
+
+
+ switch (export_format) {
+ case (EXPORT_KML_TRACK):
+ fprintf(f,"</Placemark>\n");
+ break;
+ case (EXPORT_XASTIR_TRACK):
+ default:
+ fprintf(f,"\n");
+ }
+}
+
+
+
+
+//
+// Export trail data for one or all stations to file
+//
+// If p_station == NULL, store all stations, else store only one
+// station.
+//
+void export_trail(DataRow *p_station) {
+ char file[420];
+ FILE *f;
+ time_t sec;
+ struct tm *time;
+ int storeall;
+ char user_base_dir[MAX_VALUE];
+
+ sec = sec_now();
+ time = gmtime(&sec);
+
+ if (p_station == NULL)
+ storeall = 1;
+ else
+ storeall = 0;
+
+ if (storeall) {
+ // define filename for storing all station
+ xastir_snprintf(file, sizeof(file),
+ "%s/%04d%02d%02d-%02d%02d%02d.trk",
+ get_user_base_dir("tracklogs", user_base_dir,
+ sizeof(user_base_dir)),
+ time->tm_year+1900,
+ time->tm_mon+1,
+ time->tm_mday,
+ time->tm_hour,
+ time->tm_min,
+ time->tm_sec);
+ }
+ else {
+ // define filename for current station
+ xastir_snprintf(file, sizeof(file), "%s/%s.trk",
+ get_user_base_dir("tracklogs", user_base_dir,
+ sizeof(user_base_dir)),
+ p_station->call_sign);
+ }
+
+ // create or open file
+ (void)filecreate(file); // create empty file if it doesn't exist
+ // DK7IN: owner should better be set to user, it is now root with kernel AX.25!
+
+ f=fopen(file,"a"); // open file for append
+ if (f != NULL) {
+
+ fprintf(f,
+ "# WGS-84 tracklog created by Xastir %04d/%02d/%02d %02d:%02d\n",
+ time->tm_year+1900,
+ time->tm_mon+1,
+ time->tm_mday,
+ time->tm_hour,
+ time->tm_min);
+
+ if (storeall) {
+ p_station = n_first;
+ while (p_station != NULL) {
+ exp_trailstation(f,p_station, EXPORT_XASTIR_TRACK);
+ p_station = p_station->n_next;
+ }
+ }
+ else {
+ exp_trailstation(f,p_station, EXPORT_XASTIR_TRACK);
+ }
+ (void)fclose(f);
+ }
+ else
+ fprintf(stderr,"Couldn't create or open tracklog file %s\n",file);
+}
+
+
+
+
+
+//
+// Export trail data for one or all stations to a klm file suitable for
+// loading into google earth/google maps/NASA worldwind etc.
+// For documentation of the KML (Keyhole Markup Language) format,
+// see: http://
+//
+// @param p_station pointer to datarow containing station to export
+// If p_station == NULL, store all stations, else store only one
+// station.
+//
+void export_trail_as_kml(DataRow *p_station) {
+ char file[420];
+ FILE *f;
+ time_t sec;
+ struct tm *time;
+ int storeall;
+ char user_base_dir[MAX_VALUE];
+
+ sec = sec_now();
+ time = gmtime(&sec);
+
+ if (p_station == NULL)
+ storeall = 1;
+ else
+ storeall = 0;
+
+ if (storeall) {
+ // define filename for storing all station
+ xastir_snprintf(file, sizeof(file),
+ "%s/%04d%02d%02d-%02d%02d%02d.kml",
+ get_user_base_dir("tracklogs", user_base_dir,
+ sizeof(user_base_dir)),
+ time->tm_year+1900,
+ time->tm_mon+1,
+ time->tm_mday,
+ time->tm_hour,
+ time->tm_min,
+ time->tm_sec);
+ }
+ else {
+ // define filename for current station, call + current time.
+ xastir_snprintf(file, sizeof(file),
+ "%s/%s_%04d%02d%02d-%02d%02d%02d.kml",
+ get_user_base_dir("tracklogs", user_base_dir,
+ sizeof(user_base_dir)),
+ p_station->call_sign,
+ time->tm_year+1900,
+ time->tm_mon+1,
+ time->tm_mday,
+ time->tm_hour,
+ time->tm_min,
+ time->tm_sec);
+ }
+
+ // create or open file
+ (void)filecreate(file); // create empty file if it doesn't exist
+ // DK7IN: owner should better be set to user, it is now root with kernel AX.25!
+
+ f=fopen(file,"w+"); // open file for writing
+ if (f != NULL) {
+
+ fprintf(f,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://earth.google.com/kml/2.2\">\n<Document>\n<name>APRS Data</name>\n<open>1</open>\n");
+
+ fprintf(f,
+ "<description>WGS-84 tracklog created by Xastir %04d/%02d/%02d %02d:%02d</description>\n",
+ time->tm_year+1900,
+ time->tm_mon+1,
+ time->tm_mday,
+ time->tm_hour,
+ time->tm_min);
+
+ if (storeall) {
+ p_station = n_first;
+ while (p_station != NULL) {
+ exp_trailstation(f,p_station,EXPORT_KML_TRACK);
+ p_station = p_station->n_next;
+ }
+ }
+ else {
+ exp_trailstation(f,p_station,EXPORT_KML_TRACK);
+ }
+
+ fprintf(f,"</Document>\n</kml>");
+
+ (void)fclose(f);
+ }
+ else
+ fprintf(stderr,"Couldn't create or open tracklog file %s\n",file);
+}
+
+
+
+////////////////////////////////////// Station storage ///////////////////////////////////////////
+
+// Station storage is done in a double-linked list. In fact there are two such
+// pointer structures, one for sorting by name and one for sorting by time.
+// We store both the pointers to the next and to the previous elements. DK7IN
+
+/*
+ * Setup station storage structure
+ */
+void init_station_data(void) {
+
+ station_count = 0; // empty station list
+ n_first = NULL; // pointer to next element in name sorted list
+ n_last = NULL; // pointer to previous element in name sorted list
+ t_oldest = NULL; // pointer to oldest element in time sorted list
+ t_newest = NULL; // pointer to newest element in time sorted list
+ last_sec = sec_now(); // check value for detecting changed seconds in time
+ next_time_sn = 0; // serial number for unique time index
+ current_trail_color = 0x00; // first trail color used will be 0x01
+ last_station_remove = sec_now(); // last time we checked for stations to remove
+}
+
+
+
+
+
+/*
+ * Initialize station data
+ */
+void init_station(DataRow *p_station) {
+ // the list pointers should already be set
+ p_station->oldest_trackpoint = NULL; // no trail
+ p_station->newest_trackpoint = NULL; // no trail
+ p_station->trail_color = 0;
+ p_station->weather_data = NULL; // no weather
+ p_station->coord_lat = 0l; // 90�N \ undefined
+ p_station->coord_lon = 0l; // 180�W / position
+ p_station->pos_amb = 0; // No ambiguity
+ p_station->error_ellipse_radius = 600; // In cm, default 6 meters
+ p_station->lat_precision = 60; // In 100ths of seconds latitude (60 = 0.01 minutes)
+ p_station->lon_precision = 60; // In 100ths of seconds longitude (60 = 0.01 minutes)
+ p_station->call_sign[0] = '\0'; // ?????
+ p_station->tactical_call_sign = NULL;
+ p_station->sec_heard = 0;
+ p_station->time_sn = 0;
+ p_station->flag = 0; // set all flags to inactive
+ p_station->object_retransmit = -1; // transmit forever
+ p_station->last_transmit_time = sec_now(); // Used for object/item decaying algorithm
+ p_station->transmit_time_increment = 0; // Used in data_add()
+// p_station->last_modified_time = 0; // Used for object/item dead-reckoning
+ p_station->record_type = '\0';
+ p_station->data_via = '\0'; // L local, T TNC, I internet, F file
+ p_station->heard_via_tnc_port = 0;
+ p_station->heard_via_tnc_last_time = 0;
+ p_station->last_port_heard = 0;
+ p_station->num_packets = 0;
+ p_station->aprs_symbol.aprs_type = '\0';
+ p_station->aprs_symbol.aprs_symbol = '\0';
+ p_station->aprs_symbol.special_overlay = '\0';
+ p_station->aprs_symbol.area_object.type = AREA_NONE;
+ p_station->aprs_symbol.area_object.color = AREA_GRAY_LO;
+ p_station->aprs_symbol.area_object.sqrt_lat_off = 0;
+ p_station->aprs_symbol.area_object.sqrt_lon_off = 0;
+ p_station->aprs_symbol.area_object.corridor_width = 0;
+// p_station->station_time_type = '\0';
+ p_station->origin[0] = '\0'; // no object
+ p_station->packet_time[0] = '\0';
+ p_station->node_path_ptr = NULL;
+ p_station->pos_time[0] = '\0';
+// p_station->altitude_time[0] = '\0';
+ p_station->altitude[0] = '\0';
+// p_station->speed_time[0] = '\0';
+ p_station->speed[0] = '\0';
+ p_station->course[0] = '\0';
+ p_station->bearing[0] = '\0';
+ p_station->NRQ[0] = '\0';
+ p_station->power_gain[0] = '\0';
+ p_station->signal_gain[0] = '\0';
+ p_station->signpost[0] = '\0';
+ p_station->probability_min[0] = '\0';
+ p_station->probability_max[0] = '\0';
+// p_station->station_time[0] = '\0';
+ p_station->sats_visible[0] = '\0';
+ p_station->status_data = NULL;
+ p_station->comment_data = NULL;
+ p_station->df_color = -1;
+
+ // Show that there are no other points associated with this
+ // station. We could also zero all the entries of the
+ // multipoints[][] array, but nobody should be looking there
+ // unless this is non-zero.
+ // KG4NBB
+
+ p_station->num_multipoints = 0;
+ p_station->multipoint_data = NULL;
+}
+
+
+
+
+
+/*
+ * Remove element from name ordered list
+ */
+void remove_name(DataRow *p_rem) { // todo: return pointer to next element
+ int update_shortcuts = 0;
+ int hash_key; // We use a 14-bit hash key
+
+
+ // Do a quick check to see if we're removing a station record
+ // that is pointed to by our pointer shortcuts array.
+ // If so, update our pointer shortcuts after we're done.
+ //
+ // We create the hash key out of the lower 7 bits of the first
+ // two characters, creating a 14-bit key (1 of 16384)
+ //
+ hash_key = (int)((p_rem->call_sign[0] & 0x7f) << 7);
+ hash_key = hash_key | (int)(p_rem->call_sign[1] & 0x7f);
+
+ if (station_shortcuts[hash_key] == p_rem) {
+ // Yes, we're trying to remove a record that a hash key
+ // directly points to. We'll need to redo that hash key
+ // after we remove the record.
+ update_shortcuts++;
+ }
+
+
+ // Proceed to the station record removal
+ //
+ if (p_rem->n_prev == NULL) { // Appears to be first element in list
+
+ if (n_first == p_rem) { // Yes, head of list
+
+ // Make list head point to 2nd element in list (or NULL)
+ // so that we can delete the current record.
+ n_first = p_rem->n_next;
+ }
+ else { // No, not first element in list. Problem! The
+ // list pointers are inconsistent for some reason.
+ // The chain has been broken and we have dangling
+ // pointers.
+
+ fprintf(stderr,
+ "remove_name(): ERROR: p->n_prev == NULL but p != n_first\n");
+
+abort(); // Cause a core dump at this point
+// Perhaps we could do some repair to the list pointers here? Start
+// at the other end of the chain and navigate back to this end, then
+// fix up n_first to point to it? This is at the risk of a memory
+// leak, but at least Xastir might continue to run.
+
+ }
+ }
+ else { // Not the first element in the list. Fix up pointers
+ // to skip the current record.
+ p_rem->n_prev->n_next = p_rem->n_next;
+ }
+
+
+ if (p_rem->n_next == NULL) { // Appears to be last element in list
+
+ if (n_last == p_rem) { // Yes, tail of list
+
+ // Make list tail point to previous element in list (or
+ // NULL) so that we can delete the current record.
+ n_last = p_rem->n_prev;
+ }
+ else { // No, not last element in list. Problem! The list
+ // pointers are inconsistent for some reason. The
+ // chain has been broken and we have dangling
+ // pointers.
+
+ fprintf(stderr,
+ "remove_name(): ERROR: p->n_next == NULL but p != n_last\n");
+
+abort(); // Cause a core dump at this point
+// Perhaps we could do some repair to the list pointers here? Start
+// at the other end of the chain and navigate back to this end, then
+// fix up n_last to point to it? This is at the risk of a memory
+// leak, but at least Xastir might continue to run.
+
+ }
+ }
+ else { // Not the last element in the list. Fix up pointers to
+ // skip the current record.
+ p_rem->n_next->n_prev = p_rem->n_prev;
+ }
+
+
+ // Update our pointer shortcuts. Pass the removed hash_key to
+ // the function so that we can try to redo just that hash_key
+ // pointer.
+ if (update_shortcuts) {
+//fprintf(stderr,"\t\t\t\t\t\tRemoval of hash key: %i\n", hash_key);
+
+ // The -1 tells the function to redo all of the hash table
+ // pointers because we deleted one of them. Later we could
+ // optimize this so that only the specific pointer is fixed
+ // up.
+ station_shortcuts_update_function(-1, NULL);
+ }
+}
+
+
+
+
+
+/*
+ * Remove element from time ordered list
+ */
+void remove_time(DataRow *p_rem) { // todo: return pointer to next element
+
+ if (p_rem->t_older == NULL) { // Appears to be first element in list
+
+ if (t_oldest == p_rem) { // Yes, head of list (oldest)
+
+ // Make oldest list head point to 2nd element in list (or NULL)
+ // so that we can delete the current record.
+ t_oldest = p_rem->t_newer;
+ }
+ else { // No, not first (oldest) element in list. Problem!
+ // The list pointers are inconsistent for some
+ // reason. The chain has been broken and we have
+ // dangling pointers.
+
+ fprintf(stderr,
+ "remove_time(): ERROR: p->t_older == NULL but p != t_oldest\n");
+
+abort(); // Cause a core dump at this point
+// Perhaps we could do some repair to the list pointers here? Start
+// at the other end of the chain and navigate back to this end, then
+// fix up t_oldest to point to it? This is at the risk of a memory
+// leak, but at least Xastir might continue to run.
+
+ }
+ }
+ else { // Not the first (oldest) element in the list. Fix up
+ // pointers to skip the current record.
+ p_rem->t_older->t_newer = p_rem->t_newer;
+ }
+
+
+ if (p_rem->t_newer == NULL) { // Appears to be last (newest) element in list
+
+ if (t_newest == p_rem) { // Yes, head of list (newest)
+
+ // Make newest list head point to previous element in
+ // list (or NULL) so that we can delete the current
+ // record.
+ t_newest = p_rem->t_older;
+ }
+ else { // No, not newest element in list. Problem! The
+ // list pointers are inconsistent for some reason.
+ // The chain has been broken and we have dangling
+ // pointers.
+
+ fprintf(stderr,
+ "remove_time(): ERROR: p->t_newer == NULL but p != t_newest\n");
+
+abort(); // Cause a core dump at this point
+// Perhaps we could do some repair to the list pointers here? Start
+// at the other end of the chain and navigate back to this end, then
+// fix up t_newest to point to it? This is at the risk of a memory
+// leak, but at least Xastir might continue to run.
+
+ }
+ }
+ else { // Not the newest element in the list. Fix up pointers
+ // to skip the current record.
+ p_rem->t_newer->t_older = p_rem->t_older;
+ }
+}
+
+
+
+
+
+/*
+ * Insert existing element into name ordered list before p_name.
+ * If p_name is NULL then we add it to the end instead.
+ */
+void insert_name(DataRow *p_new, DataRow *p_name) {
+
+ // Set up pointer to next record (or NULL), sorted by name
+ p_new->n_next = p_name;
+
+ if (p_name == NULL) { // Add to end of list
+
+ p_new->n_prev = n_last;
+
+ if (n_last == NULL) // If we have an empty list
+ n_first = p_new; // Add it to the head of the list
+
+ else // List wasn't empty, add to the end of the list.
+ n_last->n_next = p_new;
+
+ n_last = p_new;
+ }
+
+ else { // Insert new record ahead of p_name record
+
+ p_new->n_prev = p_name->n_prev;
+
+ if (p_name->n_prev == NULL) // add to begin of list
+ n_first = p_new;
+ else
+ p_name->n_prev->n_next = p_new;
+
+ p_name->n_prev = p_new;
+ }
+}
+
+
+
+
+
+/*
+ * Insert existing element into time ordered list before p_time
+ * The p_new record ends up being on the "older" side of p_time when
+ * all done inserting (closer in the list to the t_oldest pointer).
+ * If p_time == NULL, insert at newest end of list.
+ */
+void insert_time(DataRow *p_new, DataRow *p_time) {
+
+ // Set up pointer to next record (or NULL), sorted by time
+ p_new->t_newer = p_time;
+
+ if (p_time == NULL) { // add to end of list (becomes newest station)
+
+ p_new->t_older = t_newest; // connect to previous end of list
+
+ if (t_newest == NULL) // if list empty, create list
+ t_oldest = p_new; // it's now our only station on the list
+ else
+ t_newest->t_newer = p_new; // list not empty, link original last record to our new one
+
+ t_newest = p_new; // end of list (newest record pointer) points to our new record
+ }
+
+ else { // Else we're inserting into the middle of the list somewhere
+
+ p_new->t_older = p_time->t_older;
+
+ if (p_time->t_older == NULL) // add to end of list (new record becomes oldest station)
+ t_oldest = p_new;
+ else
+ p_time->t_older->t_newer = p_new; // else
+
+ p_time->t_older = p_new;
+ }
+}
+
+
+
+
+
+/*
+ * Free station memory for one entry
+ */
+void delete_station_memory(DataRow *p_del) {
+ if (p_del == NULL)
+ return;
+ remove_name(p_del);
+ remove_time(p_del);
+ free(p_del);
+ station_count--;
+}
+
+
+
+
+
+/*
+ * Create new uninitialized element in station list
+ * and insert it before p_name after p_time entries.
+ *
+ * Returns NULL if malloc error.
+ */
+/*@null@*/ DataRow *insert_new_station(DataRow *p_name, DataRow *p_time) {
+ DataRow *p_new;
+
+ p_new = (DataRow *)calloc(1, sizeof(DataRow));
+
+ if (p_new != NULL) { // we really got the memory
+ insert_name(p_new,p_name); // insert element into name ordered list
+ insert_time(p_new,p_time); // insert element into time ordered list
+ }
+ else { // p_new == NULL
+ fprintf(stderr,"ERROR: we got no memory for station storage\n");
+ }
+
+ return(p_new); // return pointer to new element
+}
+
+
+
+
+
+/*
+ * Create new initialized element for call in station list
+ * and insert it before p_name after p_time entries.
+ *
+ * Returns NULL if mallc error.
+ */
+/*@null@*/ DataRow *add_new_station(DataRow *p_name, DataRow *p_time, char *call) {
+ DataRow *p_new;
+ int hash_key; // We use a 14-bit hash key
+ char *tactical_call;
+
+
+ if (call[0] == '\0') {
+ // Do nothing. No update needed. Callsign is empty.
+ return(NULL);
+ }
+
+//fprintf(stderr,"Adding new station: %s\n",call);
+
+ p_new = insert_new_station(p_name,p_time); // allocate memory
+
+ if (p_new == NULL) {
+ // Couldn't allocate space for the station
+ return(NULL);
+ }
+
+ init_station(p_new); // initialize new station record
+ xastir_snprintf(p_new->call_sign,
+ sizeof(p_new->call_sign),
+ "%s",
+ call);
+ station_count++;
+
+ // Do some quick checks to see if we just inserted a new hash
+ // key or inserted at the beginning of a hash key (making the
+ // old pointer incorrect). If so, update our pointers to match.
+
+ // We create the hash key out of the lower 7 bits of the first
+ // two characters, creating a 14-bit key (1 of 16384)
+ //
+ hash_key = (int)((call[0] & 0x7f) << 7);
+ hash_key = hash_key | (int)(call[1] & 0x7f);
+
+ if (station_shortcuts[hash_key] == NULL) {
+ // New hash key entry point found. Fill in the pointer.
+//fprintf(stderr,"New hash key: %i, call: %s\n",
+// hash_key,
+// call);
+
+ station_shortcuts_update_function(hash_key, p_new);
+ }
+ else if (p_new->n_prev == NULL) {
+ // We just inserted at the beginning of the list. Assume
+ // that we inserted at the beginning of our hash_key
+ // segment.
+//fprintf(stderr,"Start of list hash_key: %i, call: %s\n",
+// hash_key,
+// call);
+
+ station_shortcuts_update_function(hash_key, p_new);
+ }
+ else {
+ // Check whether either of the first two chars of the new
+ // callsign and the previous callsign are different. If so,
+ // we need to update the hash table entry for our new record
+ // 'cuz we're at the start of a new hash table entry.
+ if (p_new->n_prev->call_sign[0] != call[0]
+ || p_new->n_prev->call_sign[1] != call[1]) {
+//fprintf(stderr,"Hash segment start: %i, call: %s\n",
+// hash_key,
+// call);
+
+ station_shortcuts_update_function(hash_key, p_new);
+ }
+ }
+
+//if (p_new->n_prev != NULL) {
+// fprintf(stderr,"\tprev: %s",
+// p_new->n_prev->call_sign);
+//}
+
+//if (p_new->n_next != NULL) {
+// fprintf(stderr,"\t\tnext: %s",
+// p_new->n_next->call_sign);
+//}
+//
+//fprintf(stderr,"\n");
+
+ // Check whether we have a tactical call to assign to this
+ // station in our tactical hash table.
+//fprintf(stderr,"Call:'%s'\n", call);
+ tactical_call = get_tactical_from_hash(call);
+
+ // If tactical call found and not blank
+ if (tactical_call && tactical_call[0] != '\0') {
+
+ // Malloc some memory to hold it in the station record.
+ p_new->tactical_call_sign = (char *)malloc(MAX_TACTICAL_CALL+1);
+ CHECKMALLOC(p_new->tactical_call_sign);
+
+//fprintf(stderr,"***Assigning tactical call to new record***\n");
+ xastir_snprintf(p_new->tactical_call_sign,
+ MAX_TACTICAL_CALL+1,
+ "%s",
+ tactical_call);
+
+ //if (tactical_call[0] == '\0')
+ // fprintf(stderr,"Blank tactical call\n");
+ }
+ else {
+//fprintf(stderr,".");
+ }
+
+ return(p_new); // return pointer to new element
+}
+
+
+
+
+#ifdef HAVE_DB
+/* function add_simple_station()
+ * adds an xastir DataRow using station and additional data from a simpleStation
+ * record in a SQL database.
+ * @param p_new_station Pointer to a DataRow for the new station, probably initalized as DataRow p_new_station = NULL
+ * @param station String pointer for the callsign or object name
+ * @param origin String pointer for the callsign for an object
+ * @param symbol String pointer to an aprs symbol, will take the first character
+ * @param overlay String pointer to an aprs overlay, will take the first character
+ * @param aprs_type String pointer to an aprs type, will take the first character
+ * @param latitude in decimal degrees
+ * @param longitude in decimal degrees
+ * @param record_type
+ * @param node_path
+ * @param transmit_time Time at which the station position was transmitted in a string pointer with format described by timeformat
+ * @param timeformat Format for the transmit_time, e.g. "%Y-%M-%D %h:%d:%m" see documentation for strptime
+ *
+ * @returns 0 if unable to add new station (p_new_station should be null)
+ * otherwise returns 1 (and p_new_station should be a pointer to the DataRow
+ * for the new station record.
+ */
+int add_simple_station(DataRow *p_new_station,char *station, char *origin, char *symbol, char *overlay, char *aprs_type, char *latitude, char *longitude, char *record_type, char *node_path, char *transmit_time, char *timeformat) {
+ int returnvalue = 0;
+ unsigned long x; // xastir coordinate for longitude
+ unsigned long y; // xastir coordinate for latitide
+ float lat; // latitude converted from retrieved string
+ float lon; // longitude converted from retrieved string
+ DataRow *p_time; // pointer to new station record
+ //DataRow *p_new_station_unused;
+ struct tm time;
+ time_t sec;
+ char timestring[100+1];
+ char empty[MAX_ALTITUDE]; // for storing trailpoint data (altitude, course, speed) we don't know here.
+ empty[0]='\0';
+
+ // Add a datarow using the retrieved station record from the postgis/mysql database.
+ p_time = NULL;
+ p_new_station = NULL;
+
+ if (debug_level & 4096)
+ fprintf(stderr,"add_simple_station(%s)\n",station);
+
+ if (search_station_name(&p_new_station,station,1)) {
+ // A datarow for this station exists, find out if the new record
+ // is older or younger than the existing DataRow for this station
+ strptime(transmit_time,timeformat,&time);
+ p_new_station->sec_heard = mktime(&time);
+ if(p_new_station->sec_heard > mktime(&time)) {
+ // Add the new record as a trailpoint.
+ if (strlen(transmit_time) > 0) {
+ strptime(transmit_time, timeformat, &time);
+ sec = mktime(&time);
+ lat = strtof(latitude,NULL);
+ lon = strtof(longitude,NULL);
+ if (convert_to_xastir_coordinates (&x, &y, lon, lat))
+ (void)store_trail_point(p_new_station, x, y, sec, empty, empty, empty, 0);
+ }
+
+ // all done
+ returnvalue = 1;
+ } else {
+ // Append the position of the existing record as a trailpoint
+ // and set the station DataRow to the new values.
+ (void)store_trail_point(p_new_station, p_new_station->coord_lon, p_new_station->coord_lat, p_new_station->sec_heard, empty, empty, empty, 0);
+ }
+ } else {
+ // add a new station
+ p_new_station = add_new_station(p_new_station,p_time,station);
+ }
+ if(returnvalue==0) {
+ // Set the values for the p_new_station DataRow based on the
+ // supplied parameters. At this point p_new_station might
+ // be either a brand new station record, or an existing
+ // station record for the callsign that we were passed.
+ if (!(p_new_station==NULL)) {
+ // set values for new station based on the database row
+ xastir_snprintf(p_new_station->origin,58,"%s",origin);
+ p_new_station->aprs_symbol.aprs_symbol = symbol[0];
+ p_new_station->aprs_symbol.special_overlay = overlay[0];
+ p_new_station->aprs_symbol.aprs_type = aprs_type[0];
+ lat = strtof(latitude,NULL);
+ lon = strtof(longitude,NULL);
+ if (convert_to_xastir_coordinates (&x, &y, lon, lat)) {
+ p_new_station->coord_lon = x;
+ p_new_station->coord_lat = y;
+ }
+ p_new_station->record_type = record_type[0];
+ // free node path, Malloc, and store the new path
+ if (p_new_station->node_path_ptr != NULL) {
+ free(p_new_station->node_path_ptr);
+ }
+ p_new_station->node_path_ptr = (char *)malloc(strlen(node_path) + 1);
+ CHECKMALLOC(p_new_station->node_path_ptr);
+ substr(p_new_station->node_path_ptr,node_path,strlen(node_path));
+
+ // also set flags for the station
+ p_new_station->flag |= ST_ACTIVE;
+ if (position_on_extd_screen(p_new_station->coord_lat,p_new_station->coord_lon)) {
+ p_new_station->flag |= (ST_INVIEW); // set "In View" flag
+ } else {
+ p_new_station->flag &= (~ST_INVIEW); // clear "In View" flag
+ }
+ p_new_station->data_via = DATA_VIA_DATABASE; // treat as data from a file.
+ if (strlen(transmit_time) > 0) {
+ //strptime(transmit_time,"%Y-%m-%d %H:%M:%S",&time);
+ strptime(transmit_time,timeformat,&time);
+ p_new_station->sec_heard = mktime(&time);
+ if (debug_level & 4096) {
+ get_iso_datetime(p_new_station->sec_heard,timestring,False,False);
+ fprintf(stderr,"time %s to [%s] using [%s]\n",transmit_time,timestring,timeformat);
+ }
+ if (p_new_station->sec_heard > sec_now())
+ p_new_station->sec_heard = sec_now();
+ (void)strftime(timestring,MAX_TIME,"%m%d%Y%H%M%S",&time);
+ xastir_snprintf(p_new_station->pos_time,
+ sizeof(p_new_station->pos_time),
+ "%s",
+ timestring);
+ }
+ returnvalue = 1;
+ }
+ }
+ return returnvalue;
+}
+#endif /* HAVE_DB */
+
+
+
+
+
+/*
+ * Move station record before p_time in time ordered list
+ */
+void move_station_time(DataRow *p_curr, DataRow *p_time) {
+
+ if (p_curr != NULL) { // need a valid record
+ remove_time(p_curr);
+ insert_time(p_curr,p_time);
+ }
+}
+
+
+
+
+
+/*
+ * Move station record before p_name in name ordered list
+ */
+void move_station_name(DataRow *p_curr, DataRow *p_name) {
+
+ if (p_curr != NULL) { // need a valid record
+ remove_name(p_curr);
+ insert_name(p_curr,p_name);
+ }
+}
+
+
+
+
+
+// Update all of the pointers so that they accurately reflect the
+// current state of the station database.
+//
+// NOTE: This part of the code could be made smarter so that the
+// pointers are updated whenever they are found to be out of whack,
+// instead of zeroing all of them and starting from scratch each
+// time. Alternate: Follow the current pointer if non-NULL then go
+// up/down the list to find the current switchover point between
+// letters.
+//
+// Better: Tie into the station insert function. If a new letter
+// is inserted, or a new station at the beginning of a letter group,
+// run this function to keep things up to date. That way we won't
+// have to traverse in both directions to find a callsign in the
+// search_station_name() function.
+//
+// If hash_key_in is -1, we need to redo all of the hash keys. If
+// it is between 0 and 16383, then we need to redo just that one
+// hash key. The 2nd parameter is either NULL for a removed record,
+// or a pointer to a new station record in the case of an addition.
+//
+void station_shortcuts_update_function(int hash_key_in, DataRow *p_rem) {
+ int ii;
+ DataRow *ptr;
+ int prev_hash_key = 0x0000;
+ int hash_key;
+
+
+// I just changed the function so that we can pass in the hash_key
+// that we wish to update: We should be able to speed things up by
+// updating one hash key instead of all 16384 pointers.
+
+ if ( (hash_key_in != -1)
+ && (hash_key_in >= 0)
+ && (hash_key_in < 16384) ) {
+
+ // We're adding/changing a hash key entry
+ station_shortcuts[hash_key_in] = p_rem;
+//fprintf(stderr,"%i ",hash_key_in);
+ }
+ else { // We're removing a hash key entry.
+
+ // Clear and rebuild the entire hash table.
+
+//??????????????????????????????????????????????????
+ // Clear all of the pointers before we begin????
+//??????????????????????????????????????????????????
+ for (ii = 0; ii < 16384; ii++) {
+ station_shortcuts[ii] = NULL;
+ }
+
+ ptr = n_first; // Start of list
+
+
+ // Loop through entire list, writing the pointer into the
+ // station_shortcuts array whenever a new character is
+ // encountered. Do this until the end of the array or the end
+ // of the list.
+ //
+ while ( (ptr != NULL) && (prev_hash_key < 16384) ) {
+
+ // We create the hash key out of the lower 7 bits of the
+ // first two characters, creating a 14-bit key (1 of 16384)
+ //
+ hash_key = (int)((ptr->call_sign[0] & 0x7f) << 7);
+ hash_key = hash_key | (int)(ptr->call_sign[1] & 0x7f);
+
+ if (hash_key > prev_hash_key) {
+
+ // We found the next hash_key. Store the pointer at the
+ // correct location.
+ if (hash_key < 16384) {
+ station_shortcuts[hash_key] = ptr;
+//fprintf(stderr,"%i ", hash_key);
+ }
+ prev_hash_key = hash_key;
+ }
+ ptr = ptr->n_next;
+ }
+//fprintf(stderr,"\n");
+
+ }
+
+}
+
+
+
+
+
+//
+// Search station record by callsign
+// Returns a station with a call equal or after the searched one
+//
+// We use a doubly-linked list for the stations, so we can traverse
+// in either direction. We also use a 14-bit hash table created
+// from the first two letters of the call to dump us into the
+// beginning of the correct area that may hold the callsign, which
+// reduces search time quite a bit. We end up doing a linear search
+// only through a small area of the linked list.
+//
+// DK7IN: I don't look at case, objects and internet names could
+// have lower case.
+//
+int search_station_name(DataRow **p_name, char *call, int exact) {
+ int kk;
+ int hash_key;
+ int result;
+ int ok = 1;
+
+
+ (*p_name) = n_first; // start of alphabet
+
+ if (call[0] == '\0') {
+ // If call we're searching for is empty, return n_first as
+ // the pointer.
+ return(0);
+ }
+
+ // We create the hash key out of the lower 7 bits of the first
+ // two characters, creating a 14-bit key (1 of 16384)
+ //
+ hash_key = (int)((call[0] & 0x7f) << 7);
+ hash_key = hash_key | (int)(call[1] & 0x7f);
+
+ // Look for a match using hash table lookup
+ //
+ (*p_name) = station_shortcuts[hash_key];
+
+ if ((*p_name) == NULL) { // No hash-table entry found.
+ int mm;
+
+//fprintf(stderr,"No hash-table entry found: call:%s\n",call);
+
+
+ // No index found for that letter. Walk the array until
+ // we find an entry that is filled. That'll be our
+ // potential insertion point (insertion into the list will
+ // occur just ahead of the hash entry).
+ for (mm = hash_key; mm < 16384; mm++) {
+ if (station_shortcuts[mm] != NULL) {
+ (*p_name) = station_shortcuts[mm];
+ break;
+ }
+ }
+ }
+// else {
+//fprintf(stderr,"Hash key %d=%s, searching for call: %s\n",
+// hash_key,
+// (*p_name)->call_sign,
+// call);
+// }
+
+ // If we got to this point, we either have a NULL pointer or a
+ // real hash-table pointer entry. A non-NULL pointer means that
+ // we have a match for the lower seven bits of the first two
+ // characters of the callsign. Check the rest of the callsign,
+ // and jump out of the loop if we get outside the linear search
+ // area (if first two chars are different).
+
+ kk = (int)strlen(call);
+
+ // Search linearly through list. Stop at end of list or break.
+ while ( (*p_name) != NULL) {
+
+ if (exact) {
+ // Check entire string for exact match
+ result = strcmp( call, (*p_name)->call_sign );
+ }
+ else {
+ // Check first part of string for match
+ result = strncmp( call, (*p_name)->call_sign, kk );
+ }
+
+ if (result < 0) { // We went past the right location.
+ // We're done.
+ ok = 0;
+//fprintf(stderr,"Went past possible entry point, searching for call: %s\n",call);
+ break;
+ }
+ else if (result == 0) { // Found a possible match
+//fprintf(stderr,"Found possible match: list:%s call:%s\n",
+// (*p_name)->call_sign,
+// call);
+ break;
+ }
+ else { // Result > 0. We haven't found it yet.
+ (*p_name) = (*p_name)->n_next; // Next element in list
+ }
+ }
+
+ // Did we find anything?
+ if ( (*p_name) == NULL) {
+ ok = 0;
+//fprintf(stderr,"End of list reached, call: %s\n",call);
+ return(ok); // Nope. No match found.
+ }
+
+ // If "exact" is set, check that the string lengths match as
+ // well. If not, we didn't find it.
+ if (exact && ok && strlen((*p_name)->call_sign) != strlen(call))
+ ok = 0;
+
+ return(ok); // if not ok: p_name points to correct insert position in name list
+}
+
+
+
+
+
+/*
+ * Search station record by time and time serial number, serial ignored if -1
+ * Returns a station that is equal or older than the search criterium
+ */
+int search_station_time(DataRow **p_time, time_t heard, int serial) {
+ int ok = 1;
+
+ (*p_time) = t_newest; // newest station
+ if (heard == 0) { // we want the newest station
+ if (t_newest == NULL)
+ ok = 0; // empty list
+ }
+ else {
+ while((*p_time) != NULL) { // check time
+ if ((*p_time)->sec_heard <= heard) // compare
+ break; // found time or earlier
+ (*p_time) = (*p_time)->t_older; // next element
+ }
+ // we now probably have found the entry
+ if ((*p_time) != NULL && (*p_time)->sec_heard == heard) {
+ // we got a match, but there may be more of them
+ if (serial >= 0) { // check serial number, ignored if -1
+ while((*p_time) != NULL) { // for unique time index
+ if ((*p_time)->sec_heard == heard && (*p_time)->time_sn <= serial) // compare
+ break; // found it (same time, maybe earlier SN)
+ if ((*p_time)->sec_heard < heard) // compare
+ break; // found it (earlier time)
+ (*p_time) = (*p_time)->t_older; // consider next element
+ }
+ if ((*p_time) == NULL || (*p_time)->sec_heard != heard || (*p_time)->time_sn != serial)
+ ok = 0; // no perfect match
+ }
+ }
+ else
+ ok = 0; // no perfect match
+ }
+ return(ok);
+}
+
+
+
+
+
+/*
+ * Get pointer to next station in name sorted list
+ */
+int next_station_name(DataRow **p_curr) {
+
+ if ((*p_curr) == NULL)
+ (*p_curr) = n_first;
+ else
+ (*p_curr) = (*p_curr)->n_next;
+ if ((*p_curr) != NULL)
+ return(1);
+ else
+ return(0);
+}
+
+
+
+
+
+/*
+ * Get pointer to previous station in name sorted list
+ */
+int prev_station_name(DataRow **p_curr) {
+
+ if ((*p_curr) == NULL)
+ (*p_curr) = n_last;
+ else
+ (*p_curr) = (*p_curr)->n_prev;
+ if ((*p_curr) != NULL)
+ return(1);
+ else
+ return(0);
+}
+
+
+
+
+
+/*
+ * Get pointer to newer station in time sorted list
+ */
+int next_station_time(DataRow **p_curr) {
+
+ if ((*p_curr) == NULL)
+ (*p_curr) = t_oldest; // Grab oldest station if NULL passed to us???
+ else
+ (*p_curr) = (*p_curr)->t_newer; // Else grab newer station
+ if ((*p_curr) != NULL)
+ return(1);
+ else
+ return(0);
+}
+
+
+
+
+
+/*
+ * Get pointer to older station in time sorted list
+ */
+int prev_station_time(DataRow **p_curr) {
+
+ if ((*p_curr) == NULL)
+ (*p_curr) = t_newest; // Grab newest station if NULL passed to us???
+ else
+ (*p_curr) = (*p_curr)->t_older;
+ if ((*p_curr) != NULL)
+ return(1);
+ else
+ return(0);
+}
+
+
+
+
+
+/*
+ * Set flag for all stations in current view area or a margin area around it
+ * That are the stations we look at if we want to draw symbols or trails
+ */
+void setup_in_view(void) {
+ DataRow *p_station;
+ long min_lat, max_lat; // screen borders plus space
+ long min_lon, max_lon; // for trails from off-screen stations
+ long marg_lat, marg_lon; // margin around screen
+
+ marg_lat = (long)(3 * screen_height * scale_y/2);
+ marg_lon = (long)(3 * screen_width * scale_x/2);
+ if (marg_lat < IN_VIEW_MIN*60*100) // allow a minimum area,
+ marg_lat = IN_VIEW_MIN*60*100; // there could be outside stations
+ if (marg_lon < IN_VIEW_MIN*60*100) // with trail parts on screen
+ marg_lon = IN_VIEW_MIN*60*100;
+
+ // Only screen view
+ // min_lat = SE_corner_latitude
+ // max_lat = NW_corner_latitude;
+ // min_lon = NW_corner_longitude;
+ // max_lon = SE_corner_longitude;
+
+ // Screen view plus one screen wide margin
+ // There could be stations off screen with on screen trails
+ // See also the use of position_on_extd_screen()
+ min_lat = center_latitude - marg_lat;
+ max_lat = center_latitude + marg_lat;
+ min_lon = center_longitude - marg_lon;
+ max_lon = center_longitude + marg_lon;
+
+ p_station = n_first;
+ while (p_station != NULL) {
+ if ((p_station->flag & ST_ACTIVE) == 0 // ignore deleted objects
+ || p_station->coord_lon < min_lon || p_station->coord_lon > max_lon
+ || p_station->coord_lat < min_lat || p_station->coord_lat > max_lat
+ || (p_station->coord_lat == 0 && p_station->coord_lon == 0)) {
+ // outside view and undefined stations:
+ p_station->flag &= (~ST_INVIEW); // clear "In View" flag
+ }
+ else
+ p_station->flag |= ST_INVIEW; // set "In View" flag
+ p_station = p_station->n_next;
+ }
+}
+
+
+
+
+
+/*
+ * Check if position is inside screen borders
+ */
+int position_on_screen(long lat, long lon) {
+
+ if ( lon > NW_corner_longitude && lon < SE_corner_longitude
+ && lat > NW_corner_latitude && lat < SE_corner_latitude
+ && !(lat == 0 && lon == 0)) // discard undef positions from screen
+ return(1); // position is inside the screen
+ else
+ return(0);
+}
+
+
+
+
+
+/*
+ * Check if position is inside extended screen borders
+ * (real screen + one screen margin for trails)
+ * used for station "In View" flag
+ */
+int position_on_extd_screen(long lat, long lon) {
+ long marg_lat, marg_lon; // margin around screen
+
+ marg_lat = (long)(3 * screen_height * scale_y/2);
+ marg_lon = (long)(3 * screen_width * scale_x/2);
+ if (marg_lat < IN_VIEW_MIN*60*100) // allow a minimum area,
+ marg_lat = IN_VIEW_MIN*60*100; // there could be outside stations
+ if (marg_lon < IN_VIEW_MIN*60*100) // with trail parts on screen
+ marg_lon = IN_VIEW_MIN*60*100;
+
+ if ( abs(lon - center_longitude) < marg_lon
+ && abs(lat - center_latitude) < marg_lat
+ && !(lat == 0 && lon == 0)) // discard undef positions from screen
+ return(1); // position is inside the area
+ else
+ return(0);
+}
+
+
+
+
+
+/*
+ * Check if position is inside inner screen area
+ * (real screen + minus 1/6 screen margin)
+ * used for station tracking
+ */
+int position_on_inner_screen(long lat, long lon) {
+
+ if ( lon > center_longitude-(long)(screen_width *scale_x/3)
+ && lon < center_longitude+(long)(screen_width *scale_x/3)
+ && lat > center_latitude -(long)(screen_height*scale_y/3)
+ && lat < center_latitude +(long)(screen_height*scale_y/3)
+ && !(lat == 0 && lon == 0)) // discard undef positions from screen
+ return(1); // position is inside the area
+ else
+ return(0);
+}
+
+
+
+
+
+/*
+ * Delete single station with all its data ?? delete messages ??
+ * This function is called with a callsign parameter. Only used for
+ * my callsign, not for any other.
+ */
+void station_del(char *call) {
+ DataRow *p_name; // DK7IN: do it with move... ?
+
+ if (search_station_name(&p_name, call, 1)) {
+ (void)delete_trail(p_name); // Free track storage if it exists.
+ (void)delete_weather(p_name); // Free weather memory, if allocated
+ (void)delete_multipoints(p_name); // Free multipoint memory, if allocated
+ (void)delete_comments_and_status(p_name); // Free comment storage if it exists
+ if (p_name->node_path_ptr != NULL)// Free malloc'ed path
+ free(p_name->node_path_ptr);
+ if (p_name->tactical_call_sign != NULL)
+ free(p_name->tactical_call_sign);
+ delete_station_memory(p_name); // Free memory
+ }
+}
+
+
+
+
+
+/*
+ * Delete single station with all its data ?? delete messages ??
+ * This function is called with a pointer instead of a callsign.
+ */
+void station_del_ptr(DataRow *p_name) {
+
+//fprintf(stderr,"db.c:station_del_ptr(): %s\n",p_name->call_sign);
+
+ if (p_name != NULL) {
+
+ // A bit of debug code: Attempting to find out if we're
+ // deleting our own objects from time to time. Leave this
+ // in until we're sure the problem has been fixed.
+//// if (is_my_call(p_name->origin,1)) { // Check SSID as well
+// if ( is_my_object_item(p_name) ) { // Check SSID as well
+// fprintf(stderr,"station_del_ptr: Removing my own object: %s\n",
+// p_name->call_sign);
+// }
+
+#ifdef EXPIRE_DEBUG
+ fprintf(stderr,"Removing: %s heard %d seconds ago\n",p_name->call_sign, (int)(sec_now() - p_name->sec_heard));
+#endif
+
+ (void)delete_trail(p_name); // Free track storage if it exists.
+ (void)delete_weather(p_name); // free weather memory, if allocated
+ (void)delete_multipoints(p_name); // Free multipoint memory, if allocated
+ (void)delete_comments_and_status(p_name); // Free comment storage if it exists
+ if (p_name->node_path_ptr != NULL) // Free malloc'ed path
+ free(p_name->node_path_ptr);
+ if (p_name->tactical_call_sign != NULL)
+ free(p_name->tactical_call_sign);
+ delete_station_memory(p_name); // free memory, update
+ // linked lists, update
+ // station_count
+
+//fprintf(stderr,"db.c:station_del_ptr(): Deleted station\n");
+
+ }
+}
+
+
+
+
+
+/*
+ * Delete all stations ?? delete messages ??
+ */
+void delete_all_stations(void) {
+ DataRow *p_name;
+ DataRow *p_curr;
+ int ii;
+
+
+ // Clear all of the pointers before we begin
+ for (ii = 0; ii < 16384; ii++) {
+ station_shortcuts[ii] = NULL;
+ }
+
+ p_name = n_first;
+ while (p_name != NULL) {
+ p_curr = p_name;
+ p_name = p_name->n_next;
+ station_del_ptr(p_curr);
+ //(void)delete_trail(p_curr); // free trail memory, if allocated
+ //(void)delete_weather(p_curr); // free weather memory, if allocated
+ //(void)delete_multipoints(p_curr);// Free multipoint memory, if allocated
+ //delete_station_memory(p_curr); // free station memory
+ }
+ if (station_count != 0) {
+ fprintf(stderr,
+ "ERROR: station_count should be 0 after stations delete, is %d\n",
+ station_count);
+ station_count = 0;
+ }
+}
+
+
+
+
+
+/*
+ * Check if we have to delete old stations.
+ *
+ * Called from main.c:UpdateTime() on a periodic basis.
+ *
+ */
+void check_station_remove(time_t curr_sec) {
+ DataRow *p_station, *p_station_t_newer;
+ time_t t_rem;
+ int done;
+
+
+ // Run through this routine every STATION_REMOVE_CYCLE
+ // seconds (currently every five minutes)
+#ifdef EXPIRE_DEBUG
+ // Check every 15 seconds, useful for debug only.
+ if (last_station_remove < (curr_sec - DEBUG_STATION_REMOVE_CYCLE)) { // DEBUG
+#else
+ if (last_station_remove < (curr_sec - STATION_REMOVE_CYCLE)) {
+#endif
+
+
+//fprintf(stderr,"db.c:check_station_remove() is running\n");
+
+ // Compute the cutoff time. Any stations older than t_rem
+ // will be removed, unless they have a tactical call or
+ // belong to us.
+ t_rem = curr_sec - sec_remove;
+
+#ifdef EXPIRE_DEBUG
+ // Expire every 15 seconds, useful for debug only.
+ t_rem = curr_sec - (1 * DEBUG_STATION_REMOVE);
+#endif
+
+ for (done = 0, p_station = t_oldest; p_station != NULL && !done; p_station = p_station_t_newer) {
+
+ // Save a pointer to the next record in time-order
+ // before we delete a record and lose it.
+ p_station_t_newer = p_station->t_newer;
+
+ if (p_station->sec_heard < t_rem) {
+
+// if ( (is_my_call(p_station->call_sign,1)) // It's my station (including SSID) or
+// || ( (is_my_call(p_station->origin,1)) // Station is owned by me (including SSID)
+// && ( ((p_station->flag & ST_OBJECT) != 0) // and it's an object
+// || ((p_station->flag & ST_ITEM ) != 0) ) ) ) { // or an item
+ if ( is_my_station(p_station) || is_my_object_item(p_station)) {
+
+ // It's one of mine, leave it alone!
+
+#ifdef EXPIRE_DEBUG
+ fprintf(stderr,"found old station: %s\t\t",p_station->call_sign);
+ fprintf(stderr,"mine\n");
+#endif
+
+ }
+
+/*
+ else if (p_station->tactical_call_sign) {
+ // Station has a tactical callsign assigned,
+ // don't delete it.
+
+#ifdef EXPIRE_DEBUG
+ fprintf(stderr,"found old station: %s\t\t",p_station->call_sign);
+ fprintf(stderr,"tactical\n");
+#endif
+
+ }
+*/
+
+ else { // Not one of mine, doesn't have a tactical
+ // callsign assigned, so start deleting
+
+ //The debug output needs to be before the delete, as
+ // we're freeing the data pointed to by p_station!
+#ifdef EXPIRE_DEBUG
+ fprintf(stderr,"found old station: %s\t\t",p_station->call_sign);
+ fprintf(stderr,"deleting\n");
+ fprintf(stderr,"Last heard time: %ld\n",p_station->sec_heard);
+ fprintf(stderr," t_rem: %ld\n",t_rem);
+ fprintf(stderr," next older record has time %ld\n",p_station_t_newer->sec_heard);
+#endif
+
+ mdelete_messages(p_station->call_sign); // Delete messages
+ station_del_ptr(p_station);
+ //(void)delete_trail(p_station); // Free track storage if it exists.
+ //(void)delete_weather(p_station); // Free weather memory, if allocated
+ //(void)delete_multipoints(p_station); // Free multipoint memory, if allocated
+ //delete_station_memory(p_station); // Free memory
+
+ }
+ }
+ else {
+#ifdef EXPIRE_DEBUG
+ DataRow *testPtr = sanity_check_time_list(t_rem);
+ if (testPtr) {
+ fprintf(stderr,"TIME-SORTED LIST SANITY CHECK FAILED!\n");
+ fprintf(stderr," At least one station left after expire with time older than %ld\n",t_rem);
+ fprintf(stderr," Station name: %s\n", testPtr->call_sign);
+ fprintf(stderr," Last heard time %ld\n",testPtr->sec_heard);
+ fprintf(stderr," Seconds ago: %ld\n",curr_sec-testPtr->sec_heard);
+ fprintf(stderr," Seconds older than expire time: %ld\n",t_rem-testPtr->sec_heard);
+ fprintf(stderr,"--------\n");
+ dump_time_sorted_list();
+ }
+#endif
+ done++; // all other stations are newer...
+ }
+ }
+ last_station_remove = curr_sec;
+ }
+}
+
+
+
+
+
+/*
+ * Delete an object (mark it as deleted)
+ */
+void delete_object(char *name) {
+ DataRow *p_station;
+
+//fprintf(stderr,"delete_object\n");
+
+ p_station = NULL;
+ if (search_station_name(&p_station,name,1)) { // find object name
+ p_station->flag &= (~ST_ACTIVE); // clear flag
+ p_station->flag &= (~ST_INVIEW); // clear "In View" flag
+ if (position_on_screen(p_station->coord_lat,p_station->coord_lon))
+ redraw_on_new_data = 2; // redraw now
+ // there is some problem... it is not redrawn immediately! ????
+ // but deleted from list immediatetly
+ redo_list = (int)TRUE; // and update lists
+ }
+}
+
+
+
+
+
+/////////////////////////////////////// APRS Decoding ////////////////////////////////////////////
+
+/*
+ * Try to find a !DAO! format datum and extra precision string from the
+ * comment field of an APRS location packet (incl. objects and items).
+ * If !DAO! is found, it is removed from the comment.
+ * See http://web.ew.usna.edu/~bruninga/aprs/datum.txt
+ *
+ * lat and lon will contain the thousandth and ten thousandth
+ * minute digits of the location, if valid (see below).
+ * For example, if the final location is 70 deg 12.3456 minutes,
+ * lat or lon will contain 56. If the final location is
+ * 50 deg 56.2104 minutes, lat or lon will contain 4. So remember
+ * to zero pad! The range for lat/lon, when valid, is 0-99.
+ * datumch will contain the datum character, if found.
+ *
+ * daocomment must be null-terminated and must contain the comment field
+ *
+ * returns 3 if dao was found and contained a base-91 position
+ * (= datumch, lat, and lon contents are all valid)
+ * returns 2 if dao was found and contained a human readable position
+ * (= datumch, lat, and lon contents are all valid)
+ * returns 1 if dao was found but only included datum information
+ * (= only datumch is valid)
+ * returns 0 if no valid dao was found
+ * (= datumch, lat, and lon contents are all invalid, daocomment is unmodified)
+ *
+ * Tapio Sokura OH2KKU <tapio.sokura at iki.fi> 2007-11-15
+ */
+int decode_dao (int *lat, int *lon, char *datumch, char *daocomment) {
+ char *searchval, *rval;
+ size_t slen;
+
+ // Loop around searching for !DAO!, return the first valid match.
+ // The first '!' is found using strchr, the rest of the
+ // string is validated more manually.
+ searchval = daocomment;
+ rval = strchr(searchval, '!');
+ while (rval != NULL) {
+
+ // Check the remaining string length so we don't
+ // run past string end
+ slen = strlen(rval);
+ if (slen < 5) {
+ break;
+ }
+
+ if (rval[4] == '!' && rval[1] >= '!' && rval[1] <= '{') {
+ // found the !DAO! terminator and datum char is
+ // within the allowable range
+
+ if (rval[1] >= 'A' && rval[1] <= 'Z') {
+ // looks like human readable format
+
+ if (rval[2] == ' ' && rval[3] == ' ') {
+ // only datum information present
+ *datumch = rval[1];
+ memmove(rval, rval + 5, slen - 4);
+ return 1;
+
+ } else if (rval[2] >= '0' && rval[2] <= '9' &&
+ rval[3] >= '0' && rval[3] <= '9') {
+ // human readable format 0-9 lat/lon ok
+
+ // ASCII - 48 = the integer digit we want.
+ // Multiply by 10, because we only get
+ // thousandths of a minute with human
+ // readable format.
+ *lat = ((int)rval[2] - 48) * 10;
+ *lon = ((int)rval[3] - 48) * 10;
+ *datumch = rval[1];
+ memmove(rval, rval + 5, slen - 4);
+ return 2;
+ }
+ // not ok for human readable format, continue searching
+
+ } else if (rval[1] >= 'a' && rval[1] <= 'z') {
+ // looks like base-91 format
+
+ if (rval[2] == ' ' && rval[3] == ' ') {
+ // only datum information present
+ *datumch = rval[1];
+ memmove(rval, rval + 5, slen - 4);
+ return 1;
+
+ } else if (rval[2] >= '!' && rval[2] <= '{' &&
+ rval[3] >= '!' && rval[3] <= '{') {
+ // base-91 lat/lon ok
+ unsigned int lats, lons;
+ float latval, lonval;
+ lats = rval[2] - 33; // get base91 values
+ lons = rval[3] - 33;
+ latval = lats / 91.0 * 100; // do proper scaling
+ lonval = lons / 91.0 * 100;
+ *lat = (int)(latval + 0.5); // round and store
+ *lon = (int)(lonval + 0.5);
+ *datumch = rval[1];
+ memmove(rval, rval + 5, slen - 4);
+ return 3;
+ }
+ // not ok for base91 format, continue searching
+ }
+ // Datum chars outside A-Z and a-z are not
+ // handled (here at least).
+ }
+
+ // If we end up here, we didn't find a match.
+ // Search for the next '!' char.
+ searchval = rval + 1;
+ rval = strchr(searchval, '!');
+ }
+
+ // No more string left to search and no match.
+ return 0;
+}
+
+
+
+/*
+ * Extract Uncompressed Position Report from begin of line
+ *
+ * If a position is found, it is deleted from the data.
+ */
+int extract_position(DataRow *p_station, char **info, int type) {
+ int ok, dao_lat, dao_lon, dao_rval;
+ char temp_lat[10+1];
+ char temp_lon[11+1];
+ char temp_grid[8+1];
+ char *my_data;
+ char dao_datumch;
+ float gridlat;
+ float gridlon;
+ my_data = (*info);
+
+ if (type != APRS_GRID){ // Not a grid
+ ok = (int)(strlen(my_data) >= 19);
+ ok = (int)(ok && my_data[4]=='.' && my_data[14]=='.'
+ && (toupper(my_data[7]) =='N' || toupper(my_data[7]) =='S')
+ && (toupper(my_data[17])=='E' || toupper(my_data[17])=='W'));
+ // errors found: [4]: X [7]: n s [17]: w e
+ if (ok) {
+ ok = is_num_chr(my_data[0]); // 5230.31N/01316.88E>
+ ok = (int)(ok && is_num_chr(my_data[1])); // 0123456789012345678
+ ok = (int)(ok && is_num_or_sp(my_data[2]));
+ ok = (int)(ok && is_num_or_sp(my_data[3]));
+ ok = (int)(ok && is_num_or_sp(my_data[5]));
+ ok = (int)(ok && is_num_or_sp(my_data[6]));
+ ok = (int)(ok && is_num_chr(my_data[9]));
+ ok = (int)(ok && is_num_chr(my_data[10]));
+ ok = (int)(ok && is_num_chr(my_data[11]));
+ ok = (int)(ok && is_num_or_sp(my_data[12]));
+ ok = (int)(ok && is_num_or_sp(my_data[13]));
+ ok = (int)(ok && is_num_or_sp(my_data[15]));
+ ok = (int)(ok && is_num_or_sp(my_data[16]));
+ }
+
+ if (ok) {
+ overlay_symbol(my_data[18], my_data[8], p_station);
+ p_station->pos_amb = 0;
+ // spaces in latitude set position ambiguity, spaces in longitude do not matter
+ // we will adjust the lat/long to the center of the rectangle of ambiguity
+ if (my_data[2] == ' ') { // nearest degree
+ p_station->pos_amb = 4;
+ my_data[2] = my_data[12] = '3';
+ my_data[3] = my_data[5] = my_data[6] = '0';
+ my_data[13] = my_data[15] = my_data[16] = '0';
+ }
+ else if (my_data[3] == ' ') { // nearest 10 minutes
+ p_station->pos_amb = 3;
+ my_data[3] = my_data[13] = '5';
+ my_data[5] = my_data[6] = '0';
+ my_data[15] = my_data[16] = '0';
+ }
+ else if (my_data[5] == ' ') { // nearest minute
+ p_station->pos_amb = 2;
+ my_data[5] = my_data[15] = '5';
+ my_data[6] = '0';
+ my_data[16] = '0';
+ }
+ else if (my_data[6] == ' ') { // nearest 1/10th minute
+ p_station->pos_amb = 1;
+ my_data[6] = my_data[16] = '5';
+ }
+
+ xastir_snprintf(temp_lat,
+ sizeof(temp_lat),
+ "%s",
+ my_data);
+ temp_lat[9] = toupper(my_data[7]);
+ temp_lat[10] = '\0';
+
+ xastir_snprintf(temp_lon,
+ sizeof(temp_lon),
+ "%s",
+ my_data+9);
+ temp_lon[10] = toupper(my_data[17]);
+ temp_lon[11] = '\0';
+
+ // Check for !DAO!, beginning from the comment field.
+ // Datum is not used for the time being.
+ // Note: error/precision information (the white box on the map) is
+ // not updated here, because changes to p_station->lat/lon_precision
+ // are overridden in the calling function.
+ dao_rval = decode_dao(&dao_lat, &dao_lon, &dao_datumch, my_data + 19);
+ if (dao_rval == 2 || dao_rval == 3) {
+ // 48 is the magic number to add to a single digit integer to
+ // get the same digit in ASCII.
+ temp_lat[7] = (char)(dao_lat / 10 + 48);
+ temp_lat[8] = (char)(dao_lat % 10 + 48);
+ temp_lon[8] = (char)(dao_lon / 10 + 48);
+ temp_lon[9] = (char)(dao_lon % 10 + 48);
+ // Signal that this is an accuracy-enhanced !DAO! position,
+ // so the calling function can set the error boxes accordingly
+ // (once somebody implements it).
+ ok = dao_rval;
+ } else {
+ // no valid !DAO! _location_ found, pad with zeroes instead
+ temp_lat[7] = '0';
+ temp_lat[8] = '0';
+ temp_lon[8] = '0';
+ temp_lon[9] = '0';
+ }
+
+ // Callsign check here also checks SSID for an exact
+ // match
+// if (!is_my_call(p_station->call_sign,1)) { // don't change my position, I know it better...
+ if ( !(is_my_station(p_station)) ) { // don't change my position, I know it better...
+
+ p_station->coord_lat = convert_lat_s2l(temp_lat); // ...in case of position ambiguity
+ p_station->coord_lon = convert_lon_s2l(temp_lon);
+ }
+
+ (*info) += 19; // delete position from comment
+ }
+ }
+ else { // It is a grid
+ // first sanity checks, need more
+ ok = (int)(is_num_chr(my_data[2]));
+ ok = (int)(ok && is_num_chr(my_data[3]));
+ ok = (int)(ok && ((my_data[0]>='A')&&(my_data[0]<='R')));
+ ok = (int)(ok && ((my_data[1]>='A')&&(my_data[1]<='R')));
+ if (ok) {
+ xastir_snprintf(temp_grid,
+ sizeof(temp_grid),
+ "%s",
+ my_data);
+ // this test treats >6 digit grids as 4 digit grids; >6 are uncommon.
+ // the spec mentioned 4 or 6, I'm not sure >6 is even allowed.
+ if ( (temp_grid[6] != ']') || (temp_grid[4] == 0) || (temp_grid[5] == 0)){
+ p_station->pos_amb = 6; // 1deg lat x 2deg lon
+ temp_grid[4] = 'L';
+ temp_grid[5] = 'L';
+ }
+ else {
+ p_station->pos_amb = 5; // 2.5min lat x 5min lon
+ temp_grid[4] = toupper(temp_grid[4]);
+ temp_grid[5] = toupper(temp_grid[5]);
+ }
+ // These equations came from what I read in the qgrid source code and
+ // various mailing list archives.
+ gridlon= (20.*((float)temp_grid[0]-65.) + 2.*((float)temp_grid[2]-48.) + 5.*((float)temp_grid[4]-65.)/60.) - 180.;
+ gridlat= (10.*((float)temp_grid[1]-65.) + ((float)temp_grid[3]-48.) + 5.*(temp_grid[5]-65.)/120.) - 90.;
+ // could check for my callsign here, and avoid changing it...
+ p_station->coord_lat = (unsigned long)(32400000l + (360000.0 * (-gridlat)));
+ p_station->coord_lon = (unsigned long)(64800000l + (360000.0 * gridlon));
+ p_station->aprs_symbol.aprs_type = '/';
+ p_station->aprs_symbol.aprs_symbol = 'G';
+ } // is it valid grid or not - "ok"
+ // could cut off the grid square from the comment here, but why bother?
+ } // is it grid or not
+ return(ok);
+}
+
+
+
+
+
+// DK7IN 99
+/*
+ * Extract Compressed Position Report Data Formats from begin of line
+ * [APRS Reference, chapter 9]
+ *
+ * If a position is found, it is deleted from the data. If a
+ * compressed position is found, delete the three csT bytes as well,
+ * even if all spaces.
+ * Returns 0 if the packet is NOT a properly compressed position
+ * packet, returns 1 if ok.
+ */
+int extract_comp_position(DataRow *p_station, char **info, /*@unused@*/ int type) {
+ int ok;
+ int x1, x2, x3, x4, y1, y2, y3, y4;
+ int c = 0;
+ int s = 0;
+ int T = 0;
+ int len;
+ char *my_data;
+ float lon = 0;
+ float lat = 0;
+ float range;
+ int skip = 0;
+ char L;
+
+
+ if (debug_level & 1)
+ fprintf(stderr,"extract_comp_position: Start\n");
+
+ //fprintf(stderr,"extract_comp_position start: %s\n",*info);
+
+ // compressed data format /YYYYXXXX$csT is a fixed 13-character field
+ // used for ! / @ = data IDs
+ // / Symbol Table ID or overlay: '/' '\' A-Z a-j
+ // YYYY compressed latitude
+ // XXXX compressed longitude
+ // $ Symbol Code
+ // cs compressed
+ // course/speed
+ // radio range
+ // altitude
+ // T compression type ID
+
+ my_data = (*info);
+
+ // Check leading char. Must be one of these:
+ // '/'
+ // '\'
+ // A-Z
+ // a-j
+ //
+ L = my_data[0];
+ if ( L == '/'
+ || L == '\\'
+ || ( L >= 'A' && L <= 'Z' )
+ || ( L >= 'a' && L <= 'j' ) ) {
+ // We're good so far
+ }
+ else {
+ // Note one of the symbol table or overlay characters, so
+ // there's something funky about this packet. It's not a
+ // properly formatted compressed position.
+ return(0);
+ }
+
+ //fprintf(stderr,"my_data: %s\n",my_data);
+
+ // If c = space, csT bytes are ignored. Minimum length: 8
+ // bytes for lat/lon, 2 for symbol, 3 for csT for a total of 13.
+ len = strlen(my_data);
+ ok = (int)(len >= 13);
+
+ if (ok) {
+ y1 = (int)my_data[1] - '!';
+ y2 = (int)my_data[2] - '!';
+ y3 = (int)my_data[3] - '!';
+ y4 = (int)my_data[4] - '!';
+ x1 = (int)my_data[5] - '!';
+ x2 = (int)my_data[6] - '!';
+ x3 = (int)my_data[7] - '!';
+ x4 = (int)my_data[8] - '!';
+
+ // csT bytes
+ if (my_data[10] == ' ') // Space
+ c = -1; // This causes us to ignore csT
+ else {
+ c = (int)my_data[10] - '!';
+ s = (int)my_data[11] - '!';
+ T = (int)my_data[12] - '!';
+ }
+ skip = 13;
+
+ // Convert ' ' to '0'. Not specified in APRS Reference! Do
+ // we need it?
+ if (x1 == -1) x1 = '\0';
+ if (x2 == -1) x2 = '\0';
+ if (x3 == -1) x3 = '\0';
+ if (x4 == -1) x4 = '\0';
+ if (y1 == -1) y1 = '\0';
+ if (y2 == -1) y2 = '\0';
+ if (y3 == -1) y3 = '\0';
+ if (y4 == -1) y4 = '\0';
+
+ ok = (int)(ok && (x1 >= '\0' && x1 < 91)); // /YYYYXXXX$csT
+ ok = (int)(ok && (x2 >= '\0' && x2 < 91)); // 0123456789012
+ ok = (int)(ok && (x3 >= '\0' && x3 < 91));
+ ok = (int)(ok && (x4 >= '\0' && x4 < 91));
+ ok = (int)(ok && (y1 >= '\0' && y1 < 91));
+ ok = (int)(ok && (y2 >= '\0' && y2 < 91));
+ ok = (int)(ok && (y3 >= '\0' && y3 < 91));
+ ok = (int)(ok && (y4 >= '\0' && y4 < 91));
+
+ T &= 0x3F; // DK7IN: force Compression Byte to valid format
+ // mask off upper two unused bits, they should be zero!?
+
+ ok = (int)(ok && (c == -1 || ((c >=0 && c < 91) && (s >= 0 && s < 91) && (T >= 0 && T < 64))));
+
+ if (ok) {
+ lat = (((y1 * 91 + y2) * 91 + y3) * 91 + y4 ) / 380926.0; // in deg, 0: 90�N
+ lon = (((x1 * 91 + x2) * 91 + x3) * 91 + x4 ) / 190463.0; // in deg, 0: 180�W
+ lat *= 60 * 60 * 100; // in 1/100 sec
+ lon *= 60 * 60 * 100; // in 1/100 sec
+
+ // The below check should _not_ be done. Compressed
+ // format can resolve down to about 1 foot worldwide
+ // (0.3 meters).
+ //if ((((long)(lat+4) % 60) > 8) || (((long)(lon+4) % 60) > 8))
+ // ok = 0; // check max resolution 0.01 min to
+ // catch even more errors
+ }
+ }
+
+ if (ok) {
+ overlay_symbol(my_data[9], my_data[0], p_station); // Symbol / Table
+
+ // Callsign check here includes checking SSID for an exact
+ // match
+// if (!is_my_call(p_station->call_sign,1)) { // don't change my position, I know it better...
+ if ( !(is_my_station(p_station)) ) { // don't change my position, I know it better...
+
+ // Record the uncompressed lat/long that we just
+ // computed.
+ p_station->coord_lat = (long)((lat)); // in 1/100 sec
+ p_station->coord_lon = (long)((lon)); // in 1/100 sec
+ }
+
+ if (c >= 0) { // ignore csT if c = ' '
+ if (c < 90) { // Found course/speed or altitude bytes
+ if ((T & 0x18) == 0x10) { // check for GGA (with altitude)
+ xastir_snprintf(p_station->altitude, sizeof(p_station->altitude), "%06.0f",pow(1.002,(double)(c*91+s))*0.3048);
+ }
+ else { // Found compressed course/speed bytes
+
+ // Convert 0 degrees to 360 degrees so that
+ // Xastir will see it as a valid course and do
+ // dead-reckoning properly on this station
+ if (c == 0) {
+ c = 90;
+ }
+
+ // Compute course in degrees
+ xastir_snprintf(p_station->course,
+ sizeof(p_station->course),
+ "%03d",
+ c*4);
+
+ // Compute speed in knots
+ xastir_snprintf(p_station->speed,
+ sizeof(p_station->speed),
+ "%03.0f",
+ pow( 1.08,(double)s ) - 1.0);
+
+ //fprintf(stderr,"Decoded speed:%s, course:%s\n",p_station->speed,p_station->course);
+
+ }
+ }
+ else { // Found pre-calculated radio range bytes
+ if (c == 90) {
+ // pre-calculated radio range
+ range = 2 * pow(1.08,(double)s); // miles
+
+ // DK7IN: dirty hack... but better than nothing
+ if (s <= 5) // 2.9387 mi
+ xastir_snprintf(p_station->power_gain, sizeof(p_station->power_gain), "PHG%s0", "000");
+ else if (s <= 17) // 7.40 mi
+ xastir_snprintf(p_station->power_gain, sizeof(p_station->power_gain), "PHG%s0", "111");
+ else if (s <= 36) // 31.936 mi
+ xastir_snprintf(p_station->power_gain, sizeof(p_station->power_gain), "PHG%s0", "222");
+ else if (s <= 75) // 642.41 mi
+ xastir_snprintf(p_station->power_gain, sizeof(p_station->power_gain), "PHG%s0", "333");
+ else // max 90: 2037.8 mi
+ xastir_snprintf(p_station->power_gain, sizeof(p_station->power_gain), "PHG%s0", "444");
+ }
+ }
+ }
+ (*info) += skip; // delete position from comment
+ }
+
+ if (debug_level & 1) {
+ if (ok) {
+ fprintf(stderr,"*** extract_comp_position: Succeeded: %ld\t%ld\n",
+ p_station->coord_lat,
+ p_station->coord_lon);
+ }
+ else {
+ fprintf(stderr,"*** extract_comp_position: Failed!\n");
+ }
+ }
+
+ //fprintf(stderr," extract_comp_position end: %s\n",*info);
+
+ return(ok);
+}
+
+
+
+
+
+//
+// Extract speed and/or course from beginning of info field
+//
+// Returns course in degrees, speed in KNOTS.
+//
+int extract_speed_course(char *info, char *speed, char *course) {
+ int i,found,len;
+
+ len = (int)strlen(info);
+ found = 0;
+ speed[0] = course[0] = '\0';
+ if (len >= 7) {
+ found = 1;
+ for(i=0; found && i<7; i++) { // check data format
+ if (i==3) { // check separator
+ if (info[i]!='/')
+ found = 0;
+ }
+ else {
+ if( !( isdigit((int)info[i])
+ || (info[i] == ' ') // Spaces and periods are allowed. Need these
+ || (info[i] == '.') ) ) // here so that we can get the field deleted
+ found = 0;
+ }
+ }
+ }
+ if (found) {
+ substr(course,info,3);
+ substr(speed,info+4,3);
+ for (i=0;i<=len-7;i++) // delete speed/course from info field
+ info[i] = info[i+7];
+ }
+ if (!found || atoi(course) < 1) { // course 0 means undefined
+// speed[0] ='\0'; // Don't do this! We can have a valid
+// speed without a valid course.
+ course[0]='\0';
+ }
+ else { // recheck data format looking for undefined fields
+ for(i=0; i<2; i++) {
+ if( !(isdigit((int)speed[i]) ) )
+ speed[0] = '\0';
+ if( !(isdigit((int)course[i]) ) )
+ course[0] = '\0';
+ }
+ }
+
+ return(found);
+}
+
+
+
+
+
+/*
+ * Extract bearing and number/range/quality from beginning of info field
+ */
+int extract_bearing_NRQ(char *info, char *bearing, char *nrq) {
+ int i,found,len;
+
+ len = (int)strlen(info);
+ found = 0;
+ if (len >= 8) {
+ found = 1;
+ for(i=1; found && i<8; i++) // check data format
+ if(!(isdigit((int)info[i]) || (i==4 && info[i]=='/')))
+ found=0;
+ }
+ if (found) {
+ substr(bearing,info+1,3);
+ substr(nrq,info+5,3);
+
+//fprintf(stderr,"Bearing: %s\tNRQ: %s\n", bearing, nrq);
+
+ for (i=0;i<=len-8;i++) // delete bearing/nrq from info field
+ info[i] = info[i+8];
+ }
+
+// if (!found || nrq[2] == '0') { // Q of 0 means useless bearing
+ if (!found) {
+ bearing[0] ='\0';
+ nrq[0]='\0';
+ }
+ return(found);
+}
+
+
+
+
+
+/*
+ * Extract altitude from APRS info field "/A=012345" in feet
+ */
+int extract_altitude(char *info, char *altitude) {
+ int i,ofs,found,len;
+
+ found=0;
+ len = (int)strlen(info);
+ for(ofs=0; !found && ofs<len-8; ofs++) // search for start sequence
+ if (strncmp(info+ofs,"/A=",3)==0) {
+ found=1;
+ // Are negative altitudes even defined? Yes! In Mic-E spec to -10,000 meters
+ if(!isdigit((int)info[ofs+3]) && info[ofs+3]!='-') // First char must be digit or '-'
+ found=0;
+ for(i=4; found && i<9; i++) // check data format for next 5 chars
+ if(!isdigit((int)info[ofs+i]))
+ found=0;
+ }
+ if (found) {
+ ofs--; // was one too much on exit from for loop
+ substr(altitude,info+ofs+3,6);
+ for (i=ofs;i<=len-9;i++) // delete altitude from info field
+ info[i] = info[i+9];
+ }
+ else
+ altitude[0] = '\0';
+ return(found);
+}
+
+
+
+
+
+// TODO:
+// Comment Field
+
+
+
+
+
+/*
+ * Extract powergain and/or range from APRS info field:
+ * "PHG1234/", "PHG1234", or "RNG1234" from APRS data extension.
+ */
+int extract_powergain_range(char *info, char *phgd) {
+ int i,found,len;
+ char *info2;
+
+
+//fprintf(stderr,"Info:%s\n",info);
+
+ // Check whether two strings of interest are present and snag a
+ // pointer to them.
+ info2 = strstr(info,"RNG");
+ if (!info2)
+ info2 = strstr(info,"PHG");
+ if (!info2) {
+ phgd[0] = '\0';
+ return(0);
+ }
+
+ found=0;
+ len = (int)strlen(info2);
+
+ if (len >= 9 && strncmp(info2,"PHG",3)==0
+ && info2[7]=='/'
+ && info2[8]!='A' // trailing '/' not defined in Reference...
+ && isdigit((int)info2[3])
+ && isdigit((int)info2[4])
+ && isdigit((int)info2[5])
+ && isdigit((int)info2[6])) {
+ substr(phgd,info2,7);
+ found = 1;
+ for (i=0;i<=len-8;i++) // delete powergain from data extension field
+ info2[i] = info2[i+8];
+ }
+ else {
+ if (len >= 7 && strncmp(info2,"PHG",3)==0
+ && isdigit((int)info2[3])
+ && isdigit((int)info2[4])
+ && isdigit((int)info2[5])
+ && isdigit((int)info2[6])) {
+ substr(phgd,info2,7);
+ found = 1;
+ for (i=0;i<=len-7;i++) // delete powergain from data extension field
+ info2[i] = info2[i+7];
+ }
+ else if (len >= 7 && strncmp(info2,"RNG",3)==0
+ && isdigit((int)info2[3])
+ && isdigit((int)info2[4])
+ && isdigit((int)info2[5])
+ && isdigit((int)info2[6])) {
+ substr(phgd,info2,7);
+ found = 1;
+ for (i=0;i<=len-7;i++) // delete powergain from data extension field
+ info2[i] = info2[i+7];
+ }
+ else {
+ phgd[0] = '\0';
+ }
+ }
+ return(found);
+}
+
+
+
+
+
+/*
+ * Extract omnidf from APRS info field "DFS1234/" from APRS data extension
+ */
+int extract_omnidf(char *info, char *phgd) {
+ int i,found,len;
+
+ found=0;
+ len = (int)strlen(info);
+ if (len >= 8 && strncmp(info,"DFS",3)==0 && info[7]=='/' // trailing '/' not defined in Reference...
+ && isdigit((int)info[3]) && isdigit((int)info[5]) && isdigit((int)info[6])) {
+ substr(phgd,info,7);
+ for (i=0;i<=len-8;i++) // delete omnidf from data extension field
+ info[i] = info[i+8];
+ return(1);
+ }
+ else {
+ phgd[0] = '\0';
+ return(0);
+ }
+}
+
+
+
+
+
+/*
+ * Extract signpost data from APRS info field: "{123}", an APRS data extension
+ * Format can be {1}, {12}, or {123}. Letters or digits are ok.
+ */
+int extract_signpost(char *info, char *signpost) {
+ int i,found,len,done;
+
+//0123456
+//{1}
+//{12}
+//{121}
+
+ found=0;
+ len = (int)strlen(info);
+ if ( (len > 2)
+ && (info[0] == '{')
+ && ( (info[2] == '}' ) || (info[3] == '}' ) || (info[4] == '}' ) ) ) {
+
+ i = 1;
+ done = 0;
+ while (!done) { // Snag up to three digits
+ if (info[i] == '}') { // We're done
+ found = i; // found = position of '}' character
+ done++;
+ }
+ else {
+ signpost[i-1] = info[i];
+ }
+
+ i++;
+
+ if ( (i > 4) && !done) { // Something is wrong, we should be done by now
+ done++;
+ signpost[0] = '\0';
+ return(0);
+ }
+ }
+ substr(signpost,info+1,found-1);
+ found++;
+ for (i=0;i<=len-found;i++) { // delete omnidf from data extension field
+ info[i] = info[i+found];
+ }
+ return(1);
+ }
+ else {
+ signpost[0] = '\0';
+ return(0);
+ }
+}
+
+
+
+
+
+/*
+ * Extract probability_min data from APRS info field: "Pmin1.23,"
+ * Please note the ending comma. We use it to delimit the field.
+ */
+int extract_probability_min(char *info, char *prob_min, int prob_min_size) {
+ int len,done;
+ char *c;
+ char *d;
+
+
+//fprintf(stderr,"%s\n",info);
+
+ len = (int)strlen(info);
+ if (len < 6) { // Too short
+//fprintf(stderr,"Pmin too short: %s\n",info);
+ prob_min[0] = '\0';
+ return(0);
+ }
+
+ c = strstr(info,"Pmin");
+ if (c == NULL) { // Pmin not found
+//fprintf(stderr,"Pmin not found: %s\n",info);
+ prob_min[0] = '\0';
+ return(0);
+ }
+
+ c = c+4; // Skip the Pmin part
+ // Find the ending comma
+ d = c;
+ done = 0;
+ while (!done) {
+ if (*d == ',') { // We're done
+ done++;
+ }
+ else {
+ d++;
+ }
+
+ // Check for string too long
+ if ( ((d-c) > 10) && !done) { // Something is wrong, we should be done by now
+//fprintf(stderr,"Pmin too long: %d,%s\n",d-c,info);
+ prob_min[0] = '\0';
+ return(0);
+ }
+ }
+
+ // Copy the substring across
+ xastir_snprintf(prob_min,
+ prob_min_size,
+ "%s",
+ c);
+ prob_min[d-c] = '\0';
+ prob_min[10] = '\0'; // Just to make sure
+
+ // Delete data from data extension field
+ d++; // Skip the comma
+ done = 0;
+ while (!done) {
+ *(c-4) = *d;
+ if (*d == '\0')
+ done++;
+ c++;
+ d++;
+ }
+
+ return(1);
+}
+
+
+
+
+
+/*
+ * Extract probability_max data from APRS info field: "Pmax1.23,"
+ * Please note the ending comma. We use it to delimit the field.
+ */
+int extract_probability_max(char *info, char *prob_max, int prob_max_size) {
+ int len,done;
+ char *c;
+ char *d;
+
+
+//fprintf(stderr,"%s\n",info);
+
+ len = (int)strlen(info);
+ if (len < 6) { // Too short
+//fprintf(stderr,"Pmax too short: %s\n",info);
+ prob_max[0] = '\0';
+ return(0);
+ }
+
+ c = strstr(info,"Pmax");
+ if (c == NULL) { // Pmax not found
+//fprintf(stderr,"Pmax not found: %s\n",info);
+ prob_max[0] = '\0';
+ return(0);
+ }
+
+ c = c+4; // Skip the Pmax part
+ // Find the ending comma
+ d = c;
+ done = 0;
+ while (!done) {
+ if (*d == ',') { // We're done
+ done++;
+ }
+ else {
+ d++;
+ }
+
+ // Check for string too long
+ if ( ((d-c) > 10) && !done) { // Something is wrong, we should be done by now
+//fprintf(stderr,"Pmax too long: %d,%s\n",d-c,info);
+ prob_max[0] = '\0';
+ return(0);
+ }
+ }
+
+ // Copy the substring across
+ xastir_snprintf(prob_max,
+ prob_max_size,
+ "%s",
+ c);
+ prob_max[d-c] = '\0';
+ prob_max[10] = '\0'; // Just to make sure
+
+ // Delete data from data extension field
+ d++; // Skip the comma
+ done = 0;
+ while (!done) {
+ *(c-4) = *d;
+ if (*d == '\0')
+ done++;
+ c++;
+ d++;
+ }
+
+ return(1);
+}
+
+
+
+
+
+static void clear_area(DataRow *p_station) {
+ p_station->aprs_symbol.area_object.type = AREA_NONE;
+ p_station->aprs_symbol.area_object.color = AREA_GRAY_LO;
+ p_station->aprs_symbol.area_object.sqrt_lat_off = 0;
+ p_station->aprs_symbol.area_object.sqrt_lon_off = 0;
+ p_station->aprs_symbol.area_object.corridor_width = 0;
+}
+
+
+
+
+
+/*
+ * Extract Area Object
+ */
+void extract_area(DataRow *p_station, char *data) {
+ int i, val, len;
+ unsigned int uval;
+ AreaObject temp_area;
+
+ /* NOTE: If we are here, the symbol was the area symbol. But if this
+ is a slightly corrupted packet, we shouldn't blow away the area info
+ for this station, since it could be from a previously received good
+ packet. So we will work on temp_area and only copy to p_station at
+ the end, returning on any error as we parse. N7TAP */
+
+ //fprintf(stderr,"Area Data: %s\n", data);
+
+ len = (int)strlen(data);
+ val = data[0] - '0';
+ if (val >= 0 && val <= AREA_MAX) {
+ temp_area.type = val;
+ val = data[4] - '0';
+ temp_area.color = AREA_BLACK_HI; // Initial value
+ if (data[3] == '/') {
+ if (val >=0 && val <= 9) {
+ temp_area.color = val;
+ }
+ else {
+ if (debug_level & 2)
+ fprintf(stderr,"Bad area color (/)");
+ return;
+ }
+ }
+ else if (data[3] == '1') {
+ if (val >=0 && val <= 5) {
+ temp_area.color = 10 + val;
+ }
+ else {
+ if (debug_level & 2)
+ fprintf(stderr,"Bad area color (1)");
+ return;
+ }
+ }
+
+ val = 0;
+ if (isdigit((int)data[1]) && isdigit((int)data[2])) {
+ val = (10 * (data[1] - '0')) + (data[2] - '0');
+ }
+ else {
+ if (debug_level & 2)
+ fprintf(stderr,"Bad area sqrt_lat_off");
+ return;
+ }
+ temp_area.sqrt_lat_off = val;
+
+ val = 0;
+ if (isdigit((int)data[5]) && isdigit((int)data[6])) {
+ val = (10 * (data[5] - '0')) + (data[6] - '0');
+ }
+ else {
+ if (debug_level & 2)
+ fprintf(stderr,"Bad area sqrt_lon_off");
+ return;
+ }
+ temp_area.sqrt_lon_off = val;
+
+ for (i = 0; i <= len-7; i++) // delete area object from data extension field
+ data[i] = data[i+7];
+ len -= 7;
+
+ if (temp_area.type == AREA_LINE_RIGHT || temp_area.type == AREA_LINE_LEFT) {
+ if (data[0] == '{') {
+ if (sscanf(data, "{%u}", &uval) == 1) {
+ temp_area.corridor_width = uval & 0xffff;
+ for (i = 0; i <= len; i++)
+ if (data[i] == '}')
+ break;
+ uval = i+1;
+ for (i = 0; i <= (int)(len-uval); i++)
+ data[i] = data[i+uval]; // delete corridor width
+ }
+ else {
+ if (debug_level & 2)
+ fprintf(stderr,"Bad corridor width identifier");
+ temp_area.corridor_width = 0;
+ return;
+ }
+ }
+ else {
+ if (debug_level & 2)
+ fprintf(stderr,"No corridor width specified");
+ temp_area.corridor_width = 0;
+ }
+ }
+ else {
+ temp_area.corridor_width = 0;
+ }
+ }
+ else {
+ if (debug_level & 2)
+ fprintf(stderr,"Bad area type: %c\n", data[0]);
+ return;
+ }
+
+ memcpy(&(p_station->aprs_symbol.area_object), &temp_area, sizeof(AreaObject));
+
+ if (debug_level & 2) {
+ fprintf(stderr,"AreaObject: type=%d color=%d sqrt_lat_off=%d sqrt_lon_off=%d corridor_width=%d\n",
+ p_station->aprs_symbol.area_object.type,
+ p_station->aprs_symbol.area_object.color,
+ p_station->aprs_symbol.area_object.sqrt_lat_off,
+ p_station->aprs_symbol.area_object.sqrt_lon_off,
+ p_station->aprs_symbol.area_object.corridor_width);
+ }
+}
+
+
+
+
+
+/*
+ * Extract Time from begin of line [APRS Reference, chapter 6]
+ *
+ * If a time string is found in "data", it is deleted from the
+ * beginning of the string.
+ */
+int extract_time(DataRow *p_station, char *data, int type) {
+ int len, i;
+ int ok = 0;
+
+ // todo: better check of time data ranges
+ len = (int)strlen(data);
+ if (type == APRS_WX2) {
+ // 8 digit time from stand-alone positionless weather stations...
+ if (len > 8) {
+ // MMDDHHMM zulu time
+ // MM 01-12 todo: better check of time data ranges
+ // DD 01-31
+ // HH 01-23
+ // MM 01-59
+ ok = 1;
+ for (i=0;ok && i<8;i++)
+ if (!isdigit((int)data[i]))
+ ok = 0;
+ if (ok) {
+// substr(p_station->station_time,data+2,6);
+// p_station->station_time_type = 'z';
+ for (i=0;i<=len-8;i++) // delete time from data
+ data[i] = data[i+8];
+ }
+ }
+ }
+ else {
+ if (len > 6) {
+ // Status messages only with optional zulu format
+ // DK7IN: APRS ref says one of 'z' '/' 'h', but I found 'c' at HB9TJM-8 ???
+ if (toupper(data[6])=='Z' || data[6]=='/' || toupper(data[6])=='H')
+ ok = 1;
+ for (i=0;ok && i<6;i++)
+ if (!isdigit((int)data[i]))
+ ok = 0;
+ if (ok) {
+// substr(p_station->station_time,data,6);
+// p_station->station_time_type = data[6];
+ for (i=0;i<=len-7;i++) // delete time from data
+ data[i] = data[i+7];
+ }
+ }
+ }
+ return(ok);
+}
+
+
+
+
+
+// APRS Data Extensions [APRS Reference p.27]
+// .../... Course & Speed, may be followed by others (see p.27)
+// .../... Wind Dir and Speed
+// PHG.... Station Power and Effective Antenna Height/Gain
+// RNG.... Pre-Calculated Radio Range
+// DFS.... DF Signal Strength and Effective Antenna Height/Gain
+// T../C.. Area Object Descriptor
+
+/* Extract one of several possible APRS Data Extensions */
+void process_data_extension(DataRow *p_station, char *data, /*@unused@*/ int type) {
+ char temp1[7+1];
+ char temp2[3+1];
+ char temp3[10+1];
+ char bearing[3+1];
+ char nrq[3+1];
+
+ if (p_station->aprs_symbol.aprs_type == '\\' && p_station->aprs_symbol.aprs_symbol == 'l') {
+ /* This check needs to come first because the area object extension can look
+ exactly like what extract_speed_course will attempt to decode. */
+ extract_area(p_station, data);
+ }
+ else {
+ clear_area(p_station); // we got a packet with a non area symbol, so clear the data
+
+ if (extract_speed_course(data,temp1,temp2)) { // ... from Mic-E, etc.
+ //fprintf(stderr,"extracted speed/course\n");
+
+ if (atof(temp2) > 0) {
+ //fprintf(stderr,"course is non-zero\n");
+ xastir_snprintf(p_station->speed,
+ sizeof(p_station->speed),
+ "%06.2f",
+ atof(temp1));
+ xastir_snprintf(p_station->course, // in degrees
+ sizeof(p_station->course),
+ "%s",
+ temp2);
+ }
+
+ if (extract_bearing_NRQ(data, bearing, nrq)) { // Beam headings from DF'ing
+ //fprintf(stderr,"extracted bearing and NRQ\n");
+ xastir_snprintf(p_station->bearing,
+ sizeof(p_station->bearing),
+ "%s",
+ bearing);
+ xastir_snprintf(p_station->NRQ,
+ sizeof(p_station->NRQ),
+ "%s",
+ nrq);
+ p_station->signal_gain[0] = '\0'; // And blank out the shgd values
+ }
+ }
+ // Don't try to extract speed & course if a compressed
+ // object. Test for beam headings for compressed packets
+ // here
+ else if (extract_bearing_NRQ(data, bearing, nrq)) { // Beam headings from DF'ing
+
+ //fprintf(stderr,"extracted bearing and NRQ\n");
+ xastir_snprintf(p_station->bearing,
+ sizeof(p_station->bearing),
+ "%s",
+ bearing);
+ xastir_snprintf(p_station->NRQ,
+ sizeof(p_station->NRQ),
+ "%s",
+ nrq);
+ p_station->signal_gain[0] = '\0'; // And blank out the shgd values
+ }
+ else {
+ if (extract_powergain_range(data,temp1)) {
+
+//fprintf(stderr,"Found power_gain: %s\n", temp1);
+
+ xastir_snprintf(p_station->power_gain,
+ sizeof(p_station->power_gain),
+ "%s",
+ temp1);
+
+ if (extract_bearing_NRQ(data, bearing, nrq)) { // Beam headings from DF'ing
+ //fprintf(stderr,"extracted bearing and NRQ\n");
+ xastir_snprintf(p_station->bearing,
+ sizeof(p_station->bearing),
+ "%s",
+ bearing);
+ xastir_snprintf(p_station->NRQ,
+ sizeof(p_station->NRQ),
+ "%s",
+ nrq);
+ p_station->signal_gain[0] = '\0'; // And blank out the shgd values
+ }
+ }
+ else {
+ if (extract_omnidf(data,temp1)) {
+ xastir_snprintf(p_station->signal_gain,
+ sizeof(p_station->signal_gain),
+ "%s",
+ temp1); // Grab the SHGD values
+ p_station->bearing[0] = '\0'; // And blank out the bearing/NRQ values
+ p_station->NRQ[0] = '\0';
+
+ // The spec shows speed/course before DFS, but example packets that
+ // come with DOSaprs show DFSxxxx/speed/course. We'll take care of
+ // that possibility by trying to decode speed/course again.
+ if (extract_speed_course(data,temp1,temp2)) { // ... from Mic-E, etc.
+ //fprintf(stderr,"extracted speed/course\n");
+ if (atof(temp2) > 0) {
+ //fprintf(stderr,"course is non-zero\n");
+ xastir_snprintf(p_station->speed,
+ sizeof(p_station->speed),
+ "%06.2f",
+ atof(temp1));
+ xastir_snprintf(p_station->course,
+ sizeof(p_station->course),
+ "%s",
+ temp2); // in degrees
+ }
+ }
+
+ // The spec shows that omnidf and bearing/NRQ can be in the same
+ // packet, which makes no sense, but we'll try to decode it that
+ // way anyway.
+ if (extract_bearing_NRQ(data, bearing, nrq)) { // Beam headings from DF'ing
+ //fprintf(stderr,"extracted bearing and NRQ\n");
+ xastir_snprintf(p_station->bearing,
+ sizeof(p_station->bearing),
+ "%s",
+ bearing);
+ xastir_snprintf(p_station->NRQ,
+ sizeof(p_station->NRQ),
+ "%s",
+ nrq);
+ //p_station->signal_gain[0] = '\0'; // And blank out the shgd values
+ }
+ }
+ }
+ }
+
+ if (extract_signpost(data, temp2)) {
+ //fprintf(stderr,"extracted signpost data\n");
+ xastir_snprintf(p_station->signpost,
+ sizeof(p_station->signpost),
+ "%s",
+ temp2);
+ }
+
+ if (extract_probability_min(data, temp3, sizeof(temp3))) {
+ //fprintf(stderr,"extracted probability_min data: %s\n",temp3);
+ xastir_snprintf(p_station->probability_min,
+ sizeof(p_station->probability_min),
+ "%s",
+ temp3);
+ }
+
+ if (extract_probability_max(data, temp3, sizeof(temp3))) {
+ //fprintf(stderr,"extracted probability_max data: %s\n",temp3);
+ xastir_snprintf(p_station->probability_max,
+ sizeof(p_station->probability_max),
+ "%s",
+ temp3);
+ }
+ }
+}
+
+
+
+
+
+/* extract all available information from info field */
+void process_info_field(DataRow *p_station, char *info, /*@unused@*/ int type) {
+ char temp_data[6+1];
+// char time_data[MAX_TIME];
+
+ if (extract_altitude(info,temp_data)) { // get altitude
+ xastir_snprintf(p_station->altitude, sizeof(p_station->altitude), "%.2f",atof(temp_data)*0.3048);
+ //fprintf(stderr,"%.2f\n",atof(temp_data)*0.3048);
+ }
+ // do other things...
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+// type: 18
+// call_sign: VE6GRR-15
+// path: GPSLV,TCPIP,VE7DIE*
+// data: GPRMC,034728,A,5101.016,N,11359.464,W,000.0,284.9,110701,018.0,
+// from: T
+// port: 0
+// origin:
+// third_party: 1
+
+
+
+
+
+//
+// Extract data for $GPRMC, it fails if there is no position!!
+//
+// GPRMC,UTC-Time,status(A/V),lat,N/S,lon,E/W,SOG,COG,UTC-Date,Mag-Var,E/W,Fix-Quality[*CHK]
+// GPRMC,hhmmss[.sss],{A|V},ddmm.mm[mm],{N|S},dddmm.mm[mm],{E|W},[dd]d.d[ddddd],[dd]d.d[d],ddmmyy,[ddd.d],[{E|W}][,A|D|E|N|S][*CHK]
+//
+// The last field before the checksum is entirely optional, and in
+// fact first appeared in NMEA 2.3 (fairly recently). Most GPS's do
+// not currently put out that field. The field may be null or
+// nonexistent including the comma. Only "A" or "D" are considered
+// to be active and reliable fixes if this field is present.
+// Fix-Quality:
+// A: Autonomous
+// D: Differential
+// E: Estimated
+// N: Not Valid
+// S: Simulator
+//
+// $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62
+// $GPRMC,104748.821,A,4301.1492,N,08803.0374,W,0.085048,102.36,010605,,*1A
+// $GPRMC,104749.821,A,4301.1492,N,08803.0377,W,0.054215,74.60,010605,,*2D
+//
+int extract_RMC(DataRow *p_station, char *data, char *call_sign, char *path, int *num_digits) {
+ char temp_data[40]; // short term string storage, MAX_CALLSIGN, ... ???
+ char lat_s[20];
+ char long_s[20];
+ int ok;
+ char *Substring[12]; // Pointers to substrings parsed by split_string()
+ char temp_string[MAX_MESSAGE_LENGTH+1];
+ char temp_char;
+
+
+ if (debug_level & 256)
+ fprintf(stderr,"extract_RMC\n");
+
+ // should we copy it before processing? it changes data: ',' gets substituted by '\0' !!
+ ok = 0; // Start out as invalid. If we get enough info, we change this to a 1.
+
+ if ( (data == NULL) || (strlen(data) < 34) ) { // Not enough data to parse position from.
+ if (debug_level & 256)
+ fprintf(stderr,"Invalid RMC string: Too short\n");
+ return(ok);
+ }
+
+ p_station->record_type = NORMAL_GPS_RMC;
+ // Create a timestamp from the current time
+ // get_time saves the time in temp_data
+ xastir_snprintf(p_station->pos_time,
+ sizeof(p_station->pos_time),
+ "%s",
+ get_time(temp_data));
+ p_station->flag &= (~ST_MSGCAP); // clear "message capable" flag
+
+ /* check aprs type on call sign */
+ p_station->aprs_symbol = *id_callsign(call_sign, path);
+
+ // Make a copy of the incoming data. The string passed to
+ // split_string() gets destroyed.
+ xastir_snprintf(temp_string,
+ sizeof(temp_string),
+ "%s",
+ data);
+ split_string(temp_string, Substring, 12, ',');
+
+ // The Substring[] array contains pointers to each substring in
+ // the original data string.
+
+// GPRMC,034728,A,5101.016,N,11359.464,W,000.0,284.9,110701,018.0,E*7D
+// 0 1 2 3 4 5 6 7 8 9 10 11
+
+ if (Substring[0] == NULL) // No GPRMC string
+ return(ok);
+
+ if (Substring[1] == NULL) // No time string
+ return(ok);
+
+ if (Substring[2] == NULL) // No valid fix char
+ return(ok);
+
+ if (Substring[2][0] != 'A' && Substring[2][0] != 'V')
+ return(ok);
+// V is a warning but we can get good data still ?
+// DK7IN: got no position with 'V' !
+
+ if (Substring[3] == NULL) // No latitude string
+ return(ok);
+
+ if (Substring[4] == NULL) // No latitude N/S
+ return(ok);
+
+// Need to check lat_s for validity here. Note that some GPS's put out another digit of precision
+// (4801.1234) or leave one out (4801.12). Next character after digits should be a ','
+
+ // Count digits after the decimal point for latitude
+ if (strchr(Substring[3],'.')) {
+ *num_digits = strlen(Substring[3]) - (int)(strchr(Substring[3],'.') - Substring[3]) - 1;
+ }
+ else {
+ *num_digits = 0;
+ }
+
+ temp_char = toupper((int)Substring[4][0]);
+
+ if (temp_char != 'N' && temp_char != 'S') // Bad N/S
+ return(ok);
+
+ xastir_snprintf(lat_s,
+ sizeof(lat_s),
+ "%s%c",
+ Substring[3],
+ temp_char);
+
+ if (Substring[5] == NULL) // No longitude string
+ return(ok);
+
+ if (Substring[6] == NULL) // No longitude E/W
+ return(ok);
+
+// Need to check long_s for validity here. Should be all digits. Note that some GPS's put out another
+// digit of precision. (12201.1234). Next character after digits should be a ','
+
+ temp_char = toupper((int)Substring[6][0]);
+
+ if (temp_char != 'E' && temp_char != 'W') // Bad E/W
+ return(ok);
+
+ xastir_snprintf(long_s,
+ sizeof(long_s),
+ "%s%c",
+ Substring[5],
+ temp_char);
+
+ p_station->coord_lat = convert_lat_s2l(lat_s);
+ p_station->coord_lon = convert_lon_s2l(long_s);
+
+ // If we've made it this far, We have enough for a position now!
+ ok = 1;
+
+ // Now that we have a basic position, let's see what other data
+ // can be parsed from the packet. The rest of it can still be
+ // corrupt, so we're proceeding carefully under yellow alert on
+ // impulse engines only.
+
+// GPRMC,034728,A,5101.016,N,11359.464,W,000.0,284.9,110701,018.0,E*7D
+// 0 1 2 3 4 5 6 7 8 9 10 11
+
+ if (Substring[7] == NULL) { // No speed string
+ p_station->speed[0] = '\0'; // No speed available
+ return(ok);
+ }
+ else {
+ xastir_snprintf(p_station->speed,
+ MAX_SPEED,
+ "%s",
+ Substring[7]);
+ // Is it always knots, otherwise we need a conversion!
+ }
+
+ if (Substring[8] == NULL) { // No course string
+ xastir_snprintf(p_station->course,
+ sizeof(p_station->course),
+ "000.0"); // No course available
+ return(ok);
+ }
+ else {
+ xastir_snprintf(p_station->course,
+ MAX_COURSE,
+ "%s",
+ Substring[8]);
+ }
+
+ if (debug_level & 256) {
+ if (ok)
+ fprintf(stderr,"extract_RMC succeeded: %s\n",data);
+ else
+ fprintf(stderr,"extract_RMC failed: %s\n",data);
+ }
+
+ return(ok);
+}
+
+
+
+
+
+//
+// Extract data for $GPGGA
+//
+// GPGGA,UTC-Time,lat,N/S,long,E/W,GPS-Quality,nsat,HDOP,MSL-Meters,M,Geoidal-Meters,M,DGPS-Data-Age(seconds),DGPS-Ref-Station-ID[*CHK]
+// GPGGA,hhmmss[.sss],ddmm.mm[mm],{N|S},dddmm.mm[mm],{E|W},{0-8},dd,[d]d.d,[-dddd]d.d,M,[-ddd]d.d,M,[dddd.d],[dddd][*CHK]
+//
+// GPS-Quality:
+// 0: Invalid Fix
+// 1: GPS Fix
+// 2: DGPS Fix
+// 3: PPS Fix
+// 4: RTK Fix
+// 5: Float RTK Fix
+// 6: Estimated (dead-reckoning) Fix
+// 7: Manual Input Mode
+// 8: Simulation Mode
+//
+// $GPGGA,170834,4124.8963,N,08151.6838,W,1,05,1.5,280.2,M,-34.0,M,,,*75
+// $GPGGA,104438.833,4301.1439,N,08803.0338,W,1,05,1.8,185.8,M,-34.2,M,0.0,0000*40
+//
+// nsat=Number of Satellites being tracked
+//
+//
+int extract_GGA(DataRow *p_station,char *data,char *call_sign, char *path, int *num_digits) {
+ char temp_data[40]; // short term string storage, MAX_CALLSIGN, ... ???
+ char lat_s[20];
+ char long_s[20];
+ int ok;
+ char *Substring[15]; // Pointers to substrings parsed by split_string()
+ char temp_string[MAX_MESSAGE_LENGTH+1];
+ char temp_char;
+ int temp_num;
+
+
+ if (debug_level & 256)
+ fprintf(stderr, "extract_GGA\n");
+
+ ok = 0; // Start out as invalid. If we get enough info, we change this to a 1.
+
+ if ( (data == NULL) || (strlen(data) < 32) ) // Not enough data to parse position from.
+ return(ok);
+
+ p_station->record_type = NORMAL_GPS_GGA;
+ // Create a timestamp from the current time
+ // get_time saves the time in temp_data
+ xastir_snprintf(p_station->pos_time,
+ sizeof(p_station->pos_time),
+ "%s",
+ get_time(temp_data));
+ p_station->flag &= (~ST_MSGCAP); // clear "message capable" flag
+
+ /* check aprs type on call sign */
+ p_station->aprs_symbol = *id_callsign(call_sign, path);
+
+ // Make a copy of the incoming data. The string passed to
+ // split_string() gets destroyed.
+ xastir_snprintf(temp_string,
+ sizeof(temp_string),
+ "%s",
+ data);
+ split_string(temp_string, Substring, 15, ',');
+
+ // The Substring[] array contains pointers to each substring in
+ // the original data string.
+
+
+// GPGGA,hhmmss[.sss],ddmm.mm[mm],{N|S},dddmm.mm[mm],{E|W},{0-8},dd,[d]d.d,[-dddd]d.d,M,[-ddd]d.d,M,[dddd.d],[dddd][*CHK]
+// 0 1 2 3 4 5 6 7 8 9 1 1 1 1 1
+// 0 1 2 3 4
+
+ if (Substring[0] == NULL) // No GPGGA string
+ return(ok);
+
+ if (Substring[1] == NULL) // No time string
+ return(ok);
+
+ if (Substring[2] == NULL) // No latitude string
+ return(ok);
+
+ if (Substring[3] == NULL) // No latitude N/S
+ return(ok);
+
+// Need to check lat_s for validity here. Note that some GPS's put out another digit of precision
+// (4801.1234). Next character after digits should be a ','
+
+ // Count digits after the decimal point for latitude
+ if (strchr(Substring[2],'.')) {
+ *num_digits = strlen(Substring[2]) - (int)(strchr(Substring[2],'.') - Substring[2]) - 1;
+ }
+ else {
+ *num_digits = 0;
+ }
+
+ temp_char = toupper((int)Substring[3][0]);
+
+ if (temp_char != 'N' && temp_char != 'S') // Bad N/S
+ return(ok);
+
+ xastir_snprintf(lat_s,
+ sizeof(lat_s),
+ "%s%c",
+ Substring[2],
+ temp_char);
+
+ if (Substring[4] == NULL) // No longitude string
+ return(ok);
+
+ if (Substring[5] == NULL) // No longitude E/W
+ return(ok);
+
+// Need to check long_s for validity here. Should be all digits. Note that some GPS's put out another
+// digit of precision. (12201.1234). Next character after digits should be a ','
+
+ temp_char = toupper((int)Substring[5][0]);
+
+ if (temp_char != 'E' && temp_char != 'W') // Bad E/W
+ return(ok);
+
+ xastir_snprintf(long_s,
+ sizeof(long_s),
+ "%s%c",
+ Substring[4],
+ temp_char);
+
+ p_station->coord_lat = convert_lat_s2l(lat_s);
+ p_station->coord_lon = convert_lon_s2l(long_s);
+
+ // If we've made it this far, We have enough for a position now!
+ ok = 1;
+
+
+ // Now that we have a basic position, let's see what other data
+ // can be parsed from the packet. The rest of it can still be
+ // corrupt, so we're proceeding carefully under yellow alert on
+ // impulse engines only.
+
+ // Check for valid fix {
+ if (Substring[6] == NULL
+ || Substring[6][0] == '0' // Fix quality
+ || Substring[7] == NULL // Sat number
+ || Substring[8] == NULL // hdop
+ || Substring[9] == NULL) { // Altitude in meters
+ p_station->sats_visible[0] = '\0'; // Store empty sats visible
+ p_station->altitude[0] = '\0';; // Store empty altitude
+ return(ok); // A field between fix quality and altitude is missing
+ }
+
+// Need to check for validity of this number. Should be 0-12? Perhaps a few more with WAAS, GLONASS, etc?
+ temp_num = atoi(Substring[7]);
+ if (temp_num < 0 || temp_num > 30) {
+ return(ok); // Number of satellites not valid
+ }
+ else {
+ // Store
+ xastir_snprintf(p_station->sats_visible,
+ sizeof(p_station->sats_visible),
+ "%d",
+ temp_num);
+ }
+
+
+// Check for valid number for HDOP instead of just throwing it away?
+
+
+ xastir_snprintf(p_station->altitude,
+ sizeof(p_station->altitude),
+ "%s",
+ Substring[9]); // Get altitude
+
+// Need to check for valid altitude before conversion
+
+ // unit is in meters, if not adjust value ???
+
+ if (Substring[10] == NULL) // No units for altitude
+ return(ok);
+
+ if (Substring[10][0] != 'M') {
+ //fprintf(stderr,"ERROR: should adjust altitude for meters\n");
+ //} else { // Altitude units wrong. Assume altitude bad
+ p_station->altitude[0] = '\0';
+ }
+
+ if (debug_level & 256) {
+ if (ok)
+ fprintf(stderr,"extract_GGA succeeded: %s\n",data);
+ else
+ fprintf(stderr,"extract_GGA failed: %s\n",data);
+ }
+
+ return(ok);
+}
+
+
+
+
+
+//
+// Extract data for $GPGLL
+//
+// $GPGLL,4748.811,N,12219.564,W,033850,A*3C
+// lat, long, UTCtime in hhmmss, A=Valid, checksum
+//
+// GPGLL,4748.811,N,12219.564,W,033850,A*3C
+// 0 1 2 3 4 5 6
+//
+int extract_GLL(DataRow *p_station,char *data,char *call_sign, char *path, int *num_digits) {
+ char temp_data[40]; // short term string storage, MAX_CALLSIGN, ... ???
+ char lat_s[20];
+ char long_s[20];
+ int ok;
+ char *Substring[7]; // Pointers to substrings parsed by split_string()
+ char temp_string[MAX_MESSAGE_LENGTH+1];
+ char temp_char;
+
+
+ if (debug_level & 256)
+ fprintf(stderr, "extract_GLL\n");
+
+ ok = 0; // Start out as invalid. If we get enough info, we change this to a 1.
+
+ if ( (data == NULL) || (strlen(data) < 28) ) // Not enough data to parse position from.
+ return(ok);
+
+ p_station->record_type = NORMAL_GPS_GLL;
+ // Create a timestamp from the current time
+ // get_time saves the time in temp_data
+ xastir_snprintf(p_station->pos_time,
+ sizeof(p_station->pos_time),
+ "%s",
+ get_time(temp_data));
+ p_station->flag &= (~ST_MSGCAP); // clear "message capable" flag
+
+ /* check aprs type on call sign */
+ p_station->aprs_symbol = *id_callsign(call_sign, path);
+
+ // Make a copy of the incoming data. The string passed to
+ // split_string() gets destroyed.
+ xastir_snprintf(temp_string,
+ sizeof(temp_string),
+ "%s",
+ data);
+ split_string(temp_string, Substring, 7, ',');
+
+ // The Substring[] array contains pointers to each substring in
+ // the original data string.
+
+ if (Substring[0] == NULL) // No GPGGA string
+ return(ok);
+
+ if (Substring[1] == NULL) // No latitude string
+ return(ok);
+
+ if (Substring[2] == NULL) // No N/S string
+ return(ok);
+
+ if (Substring[3] == NULL) // No longitude string
+ return(ok);
+
+ if (Substring[4] == NULL) // No E/W string
+ return(ok);
+
+ temp_char = toupper((int)Substring[2][0]);
+ if (temp_char != 'N' && temp_char != 'S')
+ return(ok);
+
+ xastir_snprintf(lat_s,
+ sizeof(lat_s),
+ "%s%c",
+ Substring[1],
+ temp_char);
+// Need to check lat_s for validity here. Note that some GPS's put out another digit of precision
+// (4801.1234). Next character after digits should be a ','
+
+ // Count digits after the decimal point for latitude
+ if (strchr(Substring[1],'.')) {
+ *num_digits = strlen(Substring[1]) - (int)(strchr(Substring[1],'.') - Substring[1]) - 1;
+ }
+ else {
+ *num_digits = 0;
+ }
+
+ temp_char = toupper((int)Substring[4][0]);
+ if (temp_char != 'E' && temp_char != 'W')
+ return(ok);
+
+ xastir_snprintf(long_s,
+ sizeof(long_s),
+ "%s%c",
+ Substring[3],
+ temp_char);
+// Need to check long_s for validity here. Should be all digits. Note that some GPS's put out another
+// digit of precision. (12201.1234). Next character after digits should be a ','
+
+ p_station->coord_lat = convert_lat_s2l(lat_s);
+ p_station->coord_lon = convert_lon_s2l(long_s);
+ ok = 1; // We have enough for a position now
+
+ xastir_snprintf(p_station->course,
+ sizeof(p_station->course),
+ "000.0"); // Fill in with dummy values
+ p_station->speed[0] = '\0'; // Fill in with dummy values
+
+ // A is valid, V is a warning but we can get good data still?
+ // We don't currently check the data valid flag.
+
+ return(ok);
+}
+
+
+
+
+
+// Add a status line to the linked-list of status records
+// associated with a station. Note that a blank status line is
+// allowed, but we don't store that unless we have seen a non-blank
+// status line previously.
+//
+void add_status(DataRow *p_station, char *status_string) {
+ CommentRow *ptr;
+ int add_it = 0;
+ int len;
+
+
+ len = strlen(status_string);
+
+ // Eliminate line-end chars
+ if (len > 1) {
+ if ( (status_string[len-1] == '\n')
+ || (status_string[len-1] == '\r') ) {
+ status_string[len-1] = '\0';
+ }
+ }
+
+ // Shorten it
+ //fprintf(stderr,"1Status: (%s)\n",status_string);
+ (void)remove_trailing_spaces(status_string);
+ //fprintf(stderr,"2Status: (%s)\n",status_string);
+ (void)remove_leading_spaces(status_string);
+ //fprintf(stderr,"3Status: (%s)\n",status_string);
+
+ len = strlen(status_string);
+
+ // Check for valid pointer
+ if (p_station != NULL) {
+
+// We should probably create a new station record for this station
+// if there isn't one. This allows us to collect as much info about
+// a station as we can until a posit comes in for it. Right now we
+// don't do this. If we decide to do this in the future, we also
+// need a method to find out the info about that station without
+// having to click on an icon, 'cuz the symbol won't be on our map
+// until we have a posit.
+
+ //fprintf(stderr,"Station:%s\tStatus:%s\n",p_station->call_sign,status_string);
+
+ // Check whether we have any data stored for this station
+ if (p_station->status_data == NULL) {
+ if (len > 0) {
+ // No status stored yet and new status is non-NULL,
+ // so add it to the list.
+ add_it++;
+ }
+ }
+ else { // We have status data stored already
+ // Check for an identical string
+ CommentRow *ptr2;
+ int ii = 0;
+
+ ptr = p_station->status_data;
+ ptr2 = ptr;
+ while (ptr != NULL) {
+
+ // Note that both text_ptr and comment_string can be
+ // empty strings.
+
+ if (strcasecmp(ptr->text_ptr, status_string) == 0) {
+ // Found a matching string
+ //fprintf(stderr,"Found match:
+ //%s:%s\n",p_station->call_sign,status_string);
+
+// Instead of updating the timestamp, we'll delete the record from
+// the list and add it to the top in the code below. Make sure to
+// tweak the "ii" pointer so that we don't end up shortening the
+// list unnecessarily.
+ if (ptr == p_station->status_data) {
+
+ // Only update the timestamp: We're at the
+ // beginning of the list already.
+ ptr->sec_heard = sec_now();
+
+ return; // No need to add a new record
+ }
+ else { // Delete the record
+ CommentRow *ptr3;
+
+ // Keep a pointer to the record
+ ptr3 = ptr;
+
+ // Close the chain, skipping this record
+ ptr2->next = ptr3->next;
+
+ // Skip "ptr" over the record we wish to
+ // delete
+ ptr = ptr3->next;
+
+ // Free the record
+ free(ptr3->text_ptr);
+ free(ptr3);
+
+ // Muck with the counter 'cuz we just
+ // deleted one record
+ ii--;
+ }
+ }
+ ptr2 = ptr; // Back one record
+ if (ptr != NULL) {
+ ptr = ptr->next;
+ }
+ ii++;
+ }
+
+
+ // No matching string found, or new timestamp found for
+ // old record. Add it to the top of the list.
+ add_it++;
+ //fprintf(stderr,"No match:
+ //%s:%s\n",p_station->call_sign,status_string);
+
+ // We counted the records. If we have more than
+ // MAX_STATUS_LINES records we'll delete/free the last
+ // one to make room for the next. This keeps us from
+ // storing unique status records ad infinitum for active
+ // stations, limiting the total space used.
+ //
+ if (ii >= MAX_STATUS_LINES) {
+ // We know we didn't get a match, and that our list
+ // is full (as full as we want it to be). Traverse
+ // the list again, looking for ptr2->next->next ==
+ // NULL. If found, free last record and set the
+ // ptr2->next pointer to NULL.
+ ptr2 = p_station->status_data;
+ while (ptr2->next->next != NULL) {
+ ptr2 = ptr2->next;
+ }
+ // At this point, we have a pointer to the last
+ // record in ptr2->next. Free it and the text
+ // string in it.
+ free(ptr2->next->text_ptr);
+ free(ptr2->next);
+ ptr2->next = NULL;
+ }
+ }
+
+ if (add_it) { // We add to the beginning so we don't have
+ // to traverse the linked list. This also
+ // puts new records at the beginning of the
+ // list to keep them in sorted order.
+
+ ptr = p_station->status_data; // Save old pointer to records
+ p_station->status_data = (CommentRow *)malloc(sizeof(CommentRow));
+ CHECKMALLOC(p_station->status_data);
+
+ p_station->status_data->next = ptr; // Link in old records or NULL
+
+ // Malloc the string space we'll need, attach it to our
+ // new record
+ p_station->status_data->text_ptr = (char *)malloc(sizeof(char) * (len+1));
+ CHECKMALLOC(p_station->status_data->text_ptr);
+
+ // Fill in the string
+ xastir_snprintf(p_station->status_data->text_ptr,
+ len+1,
+ "%s",
+ status_string);
+
+ // Fill in the timestamp
+ p_station->status_data->sec_heard = sec_now();
+
+ //fprintf(stderr,"Station:%s\tStatus:%s\n\n",p_station->call_sign,p_station->status_data->text_ptr);
+ }
+ }
+}
+
+
+
+
+
+// Add a comment line to the linked-list of comment records
+// associated with a station. Note that a blank comment is allowed
+// and necessary for the times when we wish to blank out the comment
+// on an object/item, but we don't store that unless we have seen a
+// non-blank comment line previously.
+//
+void add_comment(DataRow *p_station, char *comment_string) {
+ CommentRow *ptr;
+ int add_it = 0;
+ int len;
+
+
+ len = strlen(comment_string);
+
+ // Eliminate line-end chars
+ if (len > 1) {
+ if ( (comment_string[len-1] == '\n')
+ || (comment_string[len-1] == '\r') ) {
+ comment_string[len-1] = '\0';
+ }
+ }
+
+ // Shorten it
+ //fprintf(stderr,"1Comment: (%s)\n",comment_string);
+ (void)remove_trailing_spaces(comment_string);
+ //fprintf(stderr,"2Comment: (%s)\n",comment_string);
+
+ ///////TVR DEBUGING RESULTS 28 March 2007:
+ //NO! DON'T DO THIS --- it breaks multipoint objects!
+ // (void)remove_leading_spaces(comment_string);
+ ///////////////////////////////////////////
+
+ //fprintf(stderr,"3Comment: (%s)\n",comment_string);
+
+ len = strlen(comment_string);
+
+ // Check for valid pointer
+ if (p_station != NULL) {
+
+ // Check whether we have any data stored for this station
+ if (p_station->comment_data == NULL) {
+ if (len > 0) {
+ // No comments stored yet and new comment is
+ // non-NULL, so add it to the list.
+ add_it++;
+ }
+ }
+ else { // We have comment data stored already
+ // Check for an identical string
+ CommentRow *ptr2;
+ int ii = 0;
+
+ ptr = p_station->comment_data;
+ ptr2 = ptr;
+ while (ptr != NULL) {
+
+ // Note that both text_ptr and comment_string can be
+ // empty strings.
+
+ if (strcasecmp(ptr->text_ptr, comment_string) == 0) {
+ // Found a matching string
+//fprintf(stderr,"Found match: %s:%s\n",p_station->call_sign,comment_string);
+
+// Instead of updating the timestamp, we'll delete the record from
+// the list and add it to the top in the code below. Make sure to
+// tweak the "ii" pointer so that we don't end up shortening the
+// list unnecessarily.
+ if (ptr == p_station->comment_data) {
+ // Only update the timestamp: We're at the
+ // beginning of the list already.
+ ptr->sec_heard = sec_now();
+
+ return; // No need to add a new record
+ }
+ else { // Delete the record
+ CommentRow *ptr3;
+
+ // Keep a pointer to the record
+ ptr3 = ptr;
+
+ // Close the chain, skipping this record
+ ptr2->next = ptr3->next;
+
+ // Skip "ptr" over the record we with to
+ // delete
+ ptr = ptr3->next;
+
+ // Free the record
+ free(ptr3->text_ptr);
+ free(ptr3);
+
+ // Muck with the counter 'cuz we just
+ // deleted one record
+ ii--;
+ }
+ }
+ ptr2 = ptr; // Keep this pointer one record back as
+ // we progress.
+
+ if (ptr != NULL) {
+ ptr = ptr->next;
+ }
+
+ ii++;
+ }
+ // No matching string found, or new timestamp found for
+ // old record. Add it to the top of the list.
+ add_it++;
+ //fprintf(stderr,"No match: %s:%s\n",p_station->call_sign,comment_string);
+
+ // We counted the records. If we have more than
+ // MAX_COMMENT_LINES records we'll delete/free the last
+ // one to make room for the next. This keeps us from
+ // storing unique comment records ad infinitum for
+ // active stations, limiting the total space used.
+ //
+ if (ii >= MAX_COMMENT_LINES) {
+
+ // We know we didn't get a match, and that our list
+ // is full (as we want it to be). Traverse the list
+ // again, looking for ptr2->next->next == NULL. If
+ // found, free that last record and set the
+ // ptr2->next pointer to NULL.
+ ptr2 = p_station->comment_data;
+ while (ptr2->next->next != NULL) {
+ ptr2 = ptr2->next;
+ }
+ // At this point, we have a pointer to the last
+ // record in ptr2->next. Free it and the text
+ // string in it.
+ free(ptr2->next->text_ptr);
+ free(ptr2->next);
+ ptr2->next = NULL;
+ }
+ }
+
+ if (add_it) { // We add to the beginning so we don't have
+ // to traverse the linked list. This also
+ // puts new records at the beginning of the
+ // list to keep them in sorted order.
+
+ ptr = p_station->comment_data; // Save old pointer to records
+ p_station->comment_data = (CommentRow *)malloc(sizeof(CommentRow));
+ CHECKMALLOC(p_station->comment_data);
+
+ p_station->comment_data->next = ptr; // Link in old records or NULL
+
+ // Malloc the string space we'll need, attach it to our
+ // new record
+ p_station->comment_data->text_ptr = (char *)malloc(sizeof(char) * (len+1));
+ CHECKMALLOC(p_station->comment_data->text_ptr);
+
+ // Fill in the string
+ xastir_snprintf(p_station->comment_data->text_ptr,
+ len+1,
+ "%s",
+ comment_string);
+
+ // Fill in the timestamp
+ p_station->comment_data->sec_heard = sec_now();
+ }
+ }
+}
+
+
+
+
+
+/*
+ * Add data from APRS information field to station database
+ * Returns a 1 if successful
+ */
+int data_add(int type,
+ char *call_sign,
+ char *path,
+ char *data,
+ char from,
+ int port,
+ char *origin,
+ int third_party,
+ int station_is_mine,
+ int object_is_mine) {
+
+ DataRow *p_station;
+ DataRow *p_time;
+ char call[MAX_CALLSIGN+1];
+ char new_station;
+ long last_lat, last_lon;
+ char last_alt[MAX_ALTITUDE];
+ char last_speed[MAX_SPEED+1];
+ char last_course[MAX_COURSE+1];
+ time_t last_stn_sec;
+ short last_flag;
+ char temp_data[40]; // short term string storage, MAX_CALLSIGN, ...
+ long l_lat, l_lon;
+ double distance;
+ char station_id[600];
+ int found_pos;
+ float value;
+ WeatherRow *weather;
+ int moving;
+ int changed_pos;
+ int screen_update;
+ int ok, store;
+ int ok_to_display;
+ int compr_pos;
+ char *p = NULL; // KC2ELS - used for WIDEn-N
+ int direct = 0;
+ int new_origin_is_mine = 0;
+ int num_digits = 0; // Number of digits after decimal point in NMEA string
+
+#ifdef HAVE_DB
+ int ii; // loop counter for interfaces list
+#endif /* HAVE_DB */
+
+ // call and path had been validated before
+ // Check "data" against the max APRS length, and dump the packet if too long.
+ if ( (data != NULL) && (strlen(data) > MAX_INFO_FIELD_SIZE) ) { // Overly long packet. Throw it away.
+ if (debug_level & 1)
+ fprintf(stderr,"data_add: Overly long packet. Throwing it away.\n");
+ return(0); // Not an ok packet
+ }
+
+ // Check for some reasonable string in call_sign parameter
+ if (call_sign == NULL || strlen(call_sign) == 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"data_add():call_sign was NULL or empty, exiting\n");
+ return(0);
+ }
+
+ if (debug_level & 1)
+ fprintf(stderr,"data_add:\n\ttype: %d\n\tcall_sign: %s\n\tpath: %s\n\tdata: %s\n\tfrom: %c\n\tport: %d\n\torigin: %s\n\tthird_party: %d\n",
+ type,
+ call_sign,
+ path,
+ data ? data : "NULL", // This parameter may be NULL, if exp1 then exp2 else exp3
+ from,
+ port,
+ origin ? origin : "NULL", // This parameter may be NULL
+ third_party);
+
+ if (origin && is_my_call(origin, 1)) {
+ new_origin_is_mine++; // The new object/item is owned by me
+ }
+
+ weather = NULL; // only to make the compiler happy...
+ found_pos = 1;
+ xastir_snprintf(call,
+ sizeof(call),
+ "%s",
+ call_sign);
+ p_station = NULL;
+ new_station = (char)FALSE; // to make the compiler happy...
+ last_lat = 0L;
+ last_lon = 0L;
+ last_stn_sec = sec_now();
+ last_alt[0] = '\0';
+ last_speed[0] = '\0';
+ last_course[0] = '\0';
+ last_flag = 0;
+ ok = 0;
+ store = 0;
+ p_time = NULL; // add to end of time sorted list (newest)
+ compr_pos = 0;
+
+ if (search_station_name(&p_station,call,1)) { // If we found the station in our list
+
+ if (debug_level & 1)
+ fprintf(stderr,"data_add: Found existing station record.\n");
+
+ move_station_time(p_station,p_time); // update time, change position in time sorted list
+ new_station = (char)FALSE; // we have seen this one before
+
+ if (is_my_station(p_station)) {
+ station_is_mine++; // Station is me
+ }
+ //fprintf(stderr,"checks ok\n");
+ }
+ else {
+ //fprintf(stderr,"data_add()\n");
+
+ if (debug_level & 1)
+ fprintf(stderr,"data_add: No existing station record found.\n");
+
+ p_station = add_new_station(p_station,p_time,call); // create storage
+ new_station = (char)TRUE; // for new station
+ }
+
+ if (p_station != NULL) {
+
+ last_lat = p_station->coord_lat; // remember last position
+ last_lon = p_station->coord_lon;
+ last_stn_sec = p_station->sec_heard;
+ xastir_snprintf(last_alt,
+ sizeof(last_alt),
+ "%s",
+ p_station->altitude);
+ xastir_snprintf(last_speed,
+ sizeof(last_speed),
+ "%s",
+ p_station->speed);
+ xastir_snprintf(last_course,
+ sizeof(last_course),
+ "%s",
+ p_station->course);
+ last_flag = p_station->flag;
+
+ // Wipe out old data so that it doesn't hang around forever
+ p_station->altitude[0] = '\0';
+ p_station->speed[0] = '\0';
+ p_station->course[0] = '\0';
+
+ ok = 1; // succeed as default
+
+
+ switch (type) {
+
+ case (APRS_MICE): // Mic-E format
+ case (APRS_FIXED): // '!'
+ case (APRS_MSGCAP): // '='
+
+ if (!extract_position(p_station,&data,type)) { // uncompressed lat/lon
+ compr_pos = 1;
+ if (!extract_comp_position(p_station,&data,type)) // compressed lat/lon
+ ok = 0;
+ else
+ p_station->pos_amb = 0; // No ambiguity in compressed posits
+ }
+
+ if (ok) {
+
+ // Create a timestamp from the current time
+ xastir_snprintf(p_station->pos_time,
+ sizeof(p_station->pos_time),
+ "%s",
+ get_time(temp_data));
+ (void)extract_storm(p_station,data,compr_pos);
+ (void)extract_weather(p_station,data,compr_pos); // look for weather data first
+ process_data_extension(p_station,data,type); // PHG, speed, etc.
+ process_info_field(p_station,data,type); // altitude
+
+ if ( (p_station->coord_lat > 0) && (p_station->coord_lon > 0) )
+ extract_multipoints(p_station, data, type, 1);
+
+ add_comment(p_station,data);
+
+ p_station->record_type = NORMAL_APRS;
+ if (type == APRS_MSGCAP)
+ p_station->flag |= ST_MSGCAP; // set "message capable" flag
+ else
+ p_station->flag &= (~ST_MSGCAP); // clear "message capable" flag
+
+ // Assign a non-default value for the error
+ // ellipse?
+ if (type == APRS_MICE || !compr_pos) {
+ p_station->error_ellipse_radius = 2550; // 25.5m, or about 60ft resolution
+ p_station->lat_precision = 60;
+ p_station->lon_precision = 60;
+ }
+ else {
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 6;
+ p_station->lon_precision = 6;
+ }
+
+ }
+ break;
+
+/*
+ case (APRS_DOWN): // '/'
+ ok = extract_time(p_station, data, type); // we need a time
+ if (ok) {
+ if (!extract_position(p_station,&data,type)) { // uncompressed lat/lon
+ compr_pos = 1;
+ if (!extract_comp_position(p_station,&data,type)) // compressed lat/lon
+ ok = 0;
+ else
+ p_station->pos_amb = 0; // No ambiguity in compressed posits
+ }
+ }
+
+ if (ok) {
+
+ // Create a timestamp from the current time
+ xastir_snprintf(p_station->pos_time,
+ sizeof(p_station->pos_time),
+ "%s",
+ get_time(temp_data));
+ process_data_extension(p_station,data,type); // PHG, speed, etc.
+ process_info_field(p_station,data,type); // altitude
+
+ if ( (p_station->coord_lat > 0) && (p_station->coord_lon > 0) )
+ extract_multipoints(p_station, data, type, 1);
+
+ add_comment(p_station,data);
+
+ p_station->record_type = DOWN_APRS;
+ p_station->flag &= (~ST_MSGCAP); // clear "message capable" flag
+
+ // Assign a non-default value for the error
+ // ellipse?
+ if (!compr_pos) {
+ p_station->error_ellipse_radius = 2550; // 25.5m, or about 60ft resolution
+ p_station->lat_precision = 60;
+ p_station->lon_precision = 60;
+ }
+ else {
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 6;
+ p_station->lon_precision = 6;
+ }
+ }
+ break;
+*/
+
+ case (APRS_DF): // '@'
+ case (APRS_MOBILE): // '@'
+
+ ok = extract_time(p_station, data, type); // we need a time
+ if (ok) {
+ if (!extract_position(p_station,&data,type)) { // uncompressed lat/lon
+ compr_pos = 1;
+ if (!extract_comp_position(p_station,&data,type)) // compressed lat/lon
+ ok = 0;
+ else
+ p_station->pos_amb = 0; // No ambiguity in compressed posits
+ }
+ }
+ if (ok) {
+
+ process_data_extension(p_station,data,type); // PHG, speed, etc.
+ process_info_field(p_station,data,type); // altitude
+
+ if ( (p_station->coord_lat > 0) && (p_station->coord_lon > 0) )
+ extract_multipoints(p_station, data, type, 1);
+
+ add_comment(p_station,data);
+
+ if(type == APRS_MOBILE)
+ p_station->record_type = MOBILE_APRS;
+ else
+ p_station->record_type = DF_APRS;
+ //@ stations have messaging per spec
+ p_station->flag |= (ST_MSGCAP); // set "message capable" flag
+
+ // Assign a non-default value for the error
+ // ellipse?
+ if (!compr_pos) {
+ p_station->error_ellipse_radius = 2550; // 25.5m, or about 60ft resolution
+ p_station->lat_precision = 60;
+ p_station->lon_precision = 60;
+ }
+ else {
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 6;
+ p_station->lon_precision = 6;
+ }
+ }
+ break;
+
+ case (APRS_GRID):
+
+ ok = extract_position(p_station, &data, type);
+ if (ok) {
+
+ if (debug_level & 1)
+ fprintf(stderr,"data_add: Got grid data for %s\n", call);
+
+ process_info_field(p_station,data,type); // altitude
+
+ if ( (p_station->coord_lat > 0) && (p_station->coord_lon > 0) )
+ extract_multipoints(p_station, data, type, 1);
+
+ add_comment(p_station,data);
+
+ // Assign a non-default value for the error
+ // ellipse?
+// p_station->error_ellipse_radius = 2550; // 25.5m, or about 60ft resolution
+
+// WE7U
+// This needs to change based on the number of grid letters/digits specified
+// p_station->lat_precision = 60;
+// p_station->lon_precision = 60;
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"data_add: Bad grid data for %s : %s\n", call, data);
+ }
+ break;
+
+ case (STATION_CALL_DATA):
+
+ p_station->record_type = NORMAL_APRS;
+ found_pos = 0;
+ break;
+
+ case (APRS_STATUS): // '>' Status Reports [APRS Reference, chapter 16]
+
+ (void)extract_time(p_station, data, type); // we need a time
+ // todo: could contain Maidenhead or beam heading+power
+
+ if ( (p_station->coord_lat > 0) && (p_station->coord_lon > 0) )
+ extract_multipoints(p_station, data, type, 1);
+
+ add_status(p_station,data);
+
+ p_station->flag |= (ST_STATUS); // set "Status" flag
+ p_station->record_type = NORMAL_APRS; // ???
+ found_pos = 0;
+ break;
+
+ case (OTHER_DATA): // Other Packets [APRS Reference, chapter 19]
+
+ // non-APRS beacons, treated as status reports until we get a real one
+
+ if ( (p_station->coord_lat > 0) && (p_station->coord_lon > 0) )
+ extract_multipoints(p_station, data, type, 1);
+
+ if ((p_station->flag & (~ST_STATUS)) == 0) { // only store if no status yet
+
+ add_status(p_station,data);
+
+ p_station->record_type = NORMAL_APRS; // ???
+ }
+ found_pos = 0;
+ break;
+
+ case (APRS_OBJECT):
+ if (debug_level & 2048) {
+ fprintf (stderr," Object: before any extractions at all, data is \"%s\"\n",data);
+ }
+
+ // If old match is a killed Object (owner doesn't
+ // matter), new one is an active Object and owned by
+ // us, remove the old record and create a new one
+ // for storing this Object. Do the same for Items
+ // in the next section below.
+ //
+ // The easiest implementation might be to remove the
+ // old record and then call this routine again with
+ // the same parameters, which will cause a brand-new
+ // record to be created.
+ //
+ // The new record we're processing is an active
+ // object, as data_add() won't be called on a killed
+ // object.
+ //
+// if ( is_my_call(origin,1) // If new Object is owned by me (including SSID)
+ if (new_origin_is_mine
+ && !(p_station->flag & ST_ACTIVE)
+ && (p_station->flag & ST_OBJECT) ) { // Old record was a killed Object
+ station_del_ptr(p_station); // Remove old killed Object
+ // *completely*
+ redo_list = (int)TRUE;
+ return( data_add(type, call_sign, path, data, from, port, origin, third_party, 0, 1) );
+ }
+
+ ok = extract_time(p_station, data, type); // we need a time
+ if (ok) {
+ if (!extract_position(p_station,&data,type)) { // uncompressed lat/lon
+ compr_pos = 1;
+ if (!extract_comp_position(p_station,&data,type)) // compressed lat/lon
+ ok = 0;
+ else
+ p_station->pos_amb = 0; // No ambiguity in compressed posits
+ }
+ }
+ p_station->flag |= ST_OBJECT; // Set "Object" flag
+ if (ok) {
+
+ // If object was owned by me but another station
+ // is transmitting it now, write entries into
+ // the object.log file showing that we don't own
+ // this object anymore.
+// if ( (is_my_call(p_station->origin,1)) // If station was owned by me (including SSID)
+// && (!is_my_call(origin,1)) ) { // But isn't now
+ if (is_my_object_item(p_station) // If station was owned by me (include SSID)
+ && !new_origin_is_mine) { // But isn't now
+
+ disown_object_item(call_sign, origin);
+ }
+
+ // If station is owned by me (including SSID)
+ // but it's a new object/item
+// if ( (is_my_call(p_station->origin,1))
+ if (new_origin_is_mine
+ && (p_station->transmit_time_increment == 0) ) {
+ // This will get us transmitting this object
+ // on the decaying algorithm schedule.
+ // We've transmitted it once if we've just
+ // gotten to this code.
+ p_station->transmit_time_increment = OBJECT_CHECK_RATE;
+//fprintf(stderr,"data_add(): Setting transmit_time_increment to %d\n", OBJECT_CHECK_RATE);
+ }
+
+ // Create a timestamp from the current time
+ xastir_snprintf(p_station->pos_time,
+ sizeof(p_station->pos_time),
+ "%s",
+ get_time(temp_data));
+
+ xastir_snprintf(p_station->origin,
+ sizeof(p_station->origin),
+ "%s",
+ origin); // define it as object
+ if (debug_level & 2048) {
+ fprintf (stderr," Object: before any extractions, data is \"%s\"\n",data);
+ }
+ (void)extract_storm(p_station,data,compr_pos);
+ (void)extract_weather(p_station,data,compr_pos); // look for wx info
+ process_data_extension(p_station,data,type); // PHG, speed, etc.
+ process_info_field(p_station,data,type); // altitude
+
+ if (debug_level & 2048) {
+ fprintf (stderr," Object: calling extract_multipoints with data \"%s\"\n",data);
+ }
+ if ( (p_station->coord_lat > 0) && (p_station->coord_lon > 0) )
+ extract_multipoints(p_station, data, type, 0);
+
+ add_comment(p_station,data);
+
+ // the last char always was missing...
+ //p_station->comments[ strlen(p_station->comments) - 1 ] = '\0'; // Wipe out '\n'
+ // moved that to decode_ax25_line
+ // and don't added a '\n' in interface.c
+ p_station->record_type = NORMAL_APRS;
+ p_station->flag &= (~ST_MSGCAP); // clear "message capable" flag
+
+ // Assign a non-default value for the error
+ // ellipse?
+ if (!compr_pos) {
+ p_station->error_ellipse_radius = 2550; // 25.5m, or about 60ft resolution
+ p_station->lat_precision = 60;
+ p_station->lon_precision = 60;
+ }
+ else {
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 6;
+ p_station->lon_precision = 6;
+ }
+ }
+ break;
+
+ case (APRS_ITEM):
+
+ // If old match is a killed Item (owner doesn't
+ // matter), new one is an active Item and owned by
+ // us, remove the old record and create a new one
+ // for storing this Item. Do the same for Objects
+ // in the previous section above.
+ //
+ // The easiest implementation might be to remove the
+ // old record and then call this routine again with
+ // the same parameters, which will cause a brand-new
+ // record to be created.
+ //
+ // The new record we're processing is an active
+ // Item, as data_add() won't be called on a killed
+ // Item.
+ //
+// if ( is_my_call(origin,1) // If new Item is owned by me (including SSID)
+ if (new_origin_is_mine
+ && !(p_station->flag & ST_ACTIVE)
+ && (p_station->flag & ST_ITEM) ) { // Old record was a killed Item
+
+ station_del_ptr(p_station); // Remove old killed Item
+ // *completely*
+ redo_list = (int)TRUE;
+ return( data_add(type, call_sign, path, data, from, port, origin, third_party, 0, 1) );
+ }
+
+ if (!extract_position(p_station,&data,type)) { // uncompressed lat/lon
+ compr_pos = 1;
+ if (!extract_comp_position(p_station,&data,type)) // compressed lat/lon
+ ok = 0;
+ else
+ p_station->pos_amb = 0; // No ambiguity in compressed posits
+ }
+ p_station->flag |= ST_ITEM; // Set "Item" flag
+ if (ok) {
+
+ // If item was owned by me but another station
+ // is transmitting it now, write entries into
+ // the object.log file showing that we don't own
+ // this item anymore.
+// if ( (is_my_call(p_station->origin,1)) // If station was owned by me (including SSID)
+// && (!is_my_call(origin,1)) ) { // But isn't now
+ if (is_my_object_item(p_station)
+ && !new_origin_is_mine) { // But isn't now
+
+ disown_object_item(call_sign,origin);
+ }
+
+ // If station is owned by me (including SSID)
+ // but it's a new object/item
+// if ( (is_my_call(p_station->origin,1))
+ if (is_my_object_item(p_station)
+ && (p_station->transmit_time_increment == 0) ) {
+ // This will get us transmitting this object
+ // on the decaying algorithm schedule.
+ // We've transmitted it once if we've just
+ // gotten to this code.
+ p_station->transmit_time_increment = OBJECT_CHECK_RATE;
+//fprintf(stderr,"data_add(): Setting transmit_time_increment to %d\n", OBJECT_CHECK_RATE);
+ }
+
+ // Create a timestamp from the current time
+ xastir_snprintf(p_station->pos_time,
+ sizeof(p_station->pos_time),
+ "%s",
+ get_time(temp_data));
+ xastir_snprintf(p_station->origin,
+ sizeof(p_station->origin),
+ "%s",
+ origin); // define it as item
+ (void)extract_storm(p_station,data,compr_pos);
+ (void)extract_weather(p_station,data,compr_pos); // look for wx info
+ process_data_extension(p_station,data,type); // PHG, speed, etc.
+ process_info_field(p_station,data,type); // altitude
+
+ if ( (p_station->coord_lat > 0) && (p_station->coord_lon > 0) )
+ extract_multipoints(p_station, data, type, 0);
+
+ add_comment(p_station,data);
+
+ // the last char always was missing...
+ //p_station->comments[ strlen(p_station->comments) - 1 ] = '\0'; // Wipe out '\n'
+ // moved that to decode_ax25_line
+ // and don't added a '\n' in interface.c
+ p_station->record_type = NORMAL_APRS;
+ p_station->flag &= (~ST_MSGCAP); // clear "message capable" flag
+
+ // Assign a non-default value for the error
+ // ellipse?
+ if (!compr_pos) {
+ p_station->error_ellipse_radius = 2550; // 25.5m, or about 60ft resolution
+ p_station->lat_precision = 60;
+ p_station->lon_precision = 60;
+ }
+ else {
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 6;
+ p_station->lon_precision = 6;
+ }
+ }
+ break;
+
+ case (APRS_WX1): // weather in '@' or '/' packet
+
+ ok = extract_time(p_station, data, type); // we need a time
+ if (ok) {
+ if (!extract_position(p_station,&data,type)) { // uncompressed lat/lon
+ compr_pos = 1;
+ if (!extract_comp_position(p_station,&data,type)) // compressed lat/lon
+ ok = 0;
+ else
+ p_station->pos_amb = 0; // No ambiguity in compressed posits
+ }
+ }
+ if (ok) {
+
+ (void)extract_storm(p_station,data,compr_pos);
+ (void)extract_weather(p_station,data,compr_pos);
+ p_station->record_type = (char)APRS_WX1;
+
+ process_info_field(p_station,data,type); // altitude
+
+ if ( (p_station->coord_lat > 0) && (p_station->coord_lon > 0) )
+ extract_multipoints(p_station, data, type, 1);
+
+ add_comment(p_station,data);
+
+ // Assign a non-default value for the error
+ // ellipse?
+ if (!compr_pos) {
+ p_station->error_ellipse_radius = 2550; // 25.5m, or about 60ft resolution
+ p_station->lat_precision = 60;
+ p_station->lon_precision = 60;
+ }
+ else {
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 6;
+ p_station->lon_precision = 6;
+ }
+ }
+ break;
+
+ case (APRS_WX2): // '_'
+
+ ok = extract_time(p_station, data, type); // we need a time
+ if (ok) {
+ (void)extract_storm(p_station,data,compr_pos);
+ (void)extract_weather(p_station,data,0); // look for weather data first
+ p_station->record_type = (char)APRS_WX2;
+ found_pos = 0;
+
+ process_info_field(p_station,data,type); // altitude
+
+ if ( (p_station->coord_lat > 0) && (p_station->coord_lon > 0) )
+ extract_multipoints(p_station, data, type, 1);
+ }
+ break;
+
+ case (APRS_WX4): // '#' Peet Bros U-II (km/h)
+ case (APRS_WX6): // '*' Peet Bros U-II (mph)
+ case (APRS_WX3): // '!' Peet Bros Ultimeter 2000 (data logging mode)
+ case (APRS_WX5): // '$ULTW' Peet Bros Ultimeter 2000 (packet mode)
+
+ if (get_weather_record(p_station)) { // get existing or create new weather record
+ weather = p_station->weather_data;
+ if (type == APRS_WX3) // Peet Bros Ultimeter 2000 data logging mode
+ decode_U2000_L(1,(unsigned char *)data,weather);
+ else if (type == APRS_WX5) // Peet Bros Ultimeter 2000 packet mode
+ decode_U2000_P(1,(unsigned char *)data,weather);
+ else // Peet Bros Ultimeter-II
+ decode_Peet_Bros(1,(unsigned char *)data,weather,type);
+ p_station->record_type = (char)type;
+ // Create a timestamp from the current time
+ xastir_snprintf(weather->wx_time,
+ sizeof(weather->wx_time),
+ "%s",
+ get_time(temp_data));
+ weather->wx_sec_time = sec_now();
+ found_pos = 0;
+ }
+ break;
+
+
+// GPRMC, digits after decimal point
+// ---------------------------------
+// 2 = 25.5 meter error ellipse
+// 3 = 6.0 meter error ellipse
+// 4+ = 6.0 meter error ellipse
+
+
+ case (GPS_RMC): // $GPRMC
+
+// WE7U
+// Change this function to return HDOP and the number of characters
+// after the decimal point.
+ ok = extract_RMC(p_station,data,call_sign,path,&num_digits);
+
+ if (ok) {
+ // Assign a non-default value for the error
+ // ellipse?
+//
+// WE7U
+// Degrade based on the precision provided in the sentence. If only
+// 2 digits after decimal point, give it 2550 as a radius (25.5m).
+// Best (smallest) circle should be 600 as we have no augmentation
+// flag to check here for anything better.
+//
+ switch (num_digits) {
+
+ case 0:
+ p_station->error_ellipse_radius = 2550; // 25.5m, or about 60ft resolution
+ p_station->lat_precision = 6000;
+ p_station->lon_precision = 6000;
+ break;
+
+ case 1:
+ p_station->error_ellipse_radius = 2550; // 25.5m, or about 60ft resolution
+ p_station->lat_precision = 600;
+ p_station->lon_precision = 600;
+ break;
+
+ case 2:
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 60;
+ p_station->lon_precision = 60;
+ break;
+
+ case 3:
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 6;
+ p_station->lon_precision = 6;
+ break;
+
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 0;
+ p_station->lon_precision = 0;
+ break;
+
+ default:
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 60;
+ p_station->lon_precision = 60;
+ break;
+ }
+ }
+ break;
+
+
+// GPGGA, digits after decimal point, w/o augmentation
+// ---------------------------------------------------
+// 2 = 25.5 meter error ellipse
+// 3 = 6.0 meter error ellipse unless HDOP>4, then 10.0 meters
+// 4+ = 6.0 meter error ellipse unless HDOP>4, then 10.0 meters
+//
+//
+// GPGGA, digits after decimal point, w/augmentation
+// --------------------------------------------------
+// 2 = 25.5 meter error ellipse
+// 3 = 2.5 meter error ellipse unless HDOP>4, then 10.0 meters
+// 4+ = 0.6 meter error ellipse unless HDOP>4, then 10.0 meters
+
+
+ case (GPS_GGA): // $GPGGA
+
+// WE7U
+// Change this function to return HDOP and the number of characters
+// after the decimal point.
+ ok = extract_GGA(p_station,data,call_sign,path,&num_digits);
+
+ if (ok) {
+ // Assign a non-default value for the error
+ // ellipse?
+//
+// WE7U
+// Degrade based on the precision provided in the sentence. If only
+// 2 digits after decimal point, give it 2550 as a radius (25.5m).
+// 3 digits: 6m w/o augmentation unless HDOP >4 = 10m, 2.5m w/augmentation.
+// 4+ digits: 6m w/o augmentation unless HDOP >4 = 10m, 0.6m w/augmentation.
+//
+ switch (num_digits) {
+
+ case 0:
+ p_station->error_ellipse_radius = 2550; // 25.5m, or about 60ft resolution
+ p_station->lat_precision = 6000;
+ p_station->lon_precision = 6000;
+ break;
+
+ case 1:
+ p_station->error_ellipse_radius = 2550; // 25.5m, or about 60ft resolution
+ p_station->lat_precision = 600;
+ p_station->lon_precision = 600;
+ break;
+
+ case 2:
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 60;
+ p_station->lon_precision = 60;
+ break;
+
+ case 3:
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 6;
+ p_station->lon_precision = 6;
+ break;
+
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 0;
+ p_station->lon_precision = 0;
+ break;
+
+ default:
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 60;
+ p_station->lon_precision = 60;
+ break;
+ }
+ }
+ break;
+
+
+// GPGLL, digits after decimal point
+// ---------------------------------
+// 2 = 25.5 meter error ellipse
+// 3 = 6.0 meter error ellipse
+// 4+ = 6.0 meter error ellipse
+
+
+ case (GPS_GLL): // $GPGLL
+ ok = extract_GLL(p_station,data,call_sign,path,&num_digits);
+
+ if (ok) {
+ // Assign a non-default value for the error
+ // ellipse?
+//
+// WE7U
+// Degrade based on the precision provided in the sentence. If only
+// 2 digits after decimal point, give it 2550 as a radius, otherwise
+// give it 600.
+//
+ switch (num_digits) {
+
+ case 0:
+ p_station->error_ellipse_radius = 2550; // 25.5m, or about 60ft resolution
+ p_station->lat_precision = 6000;
+ p_station->lon_precision = 6000;
+ break;
+
+ case 1:
+ p_station->error_ellipse_radius = 2550; // 25.5m, or about 60ft resolution
+ p_station->lat_precision = 600;
+ p_station->lon_precision = 600;
+ break;
+
+ case 2:
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 60;
+ p_station->lon_precision = 60;
+ break;
+
+ case 3:
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 6;
+ p_station->lon_precision = 6;
+ break;
+
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 0;
+ p_station->lon_precision = 0;
+ break;
+
+ default:
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 60;
+ p_station->lon_precision = 60;
+ break;
+ }
+
+ }
+ break;
+
+ default:
+
+ fprintf(stderr,"ERROR: UNKNOWN TYPE in data_add\n");
+ ok = 0;
+ break;
+ }
+
+ // Left this one in, just in case. Perhaps somebody might
+ // attach a multipoint string onto the end of a packet we
+ // might not expect. For this case we need to check whether
+ // we have multipoints first, as we don't want to erase the
+ // work we might have done with a previous call to
+ // extract_multipoints().
+ if (ok && (p_station->coord_lat > 0)
+ && (p_station->coord_lon > 0)
+ && (p_station->num_multipoints == 0) ) { // No multipoints found yet
+
+ extract_multipoints(p_station, data, type, 0);
+ }
+ }
+
+ if (!ok) { // non-APRS beacon, treat it as Other Packet [APRS Reference, chapter 19]
+
+ if (debug_level & 1) {
+ char filtered_data[MAX_LINE_SIZE + 1];
+
+ xastir_snprintf(filtered_data,
+ sizeof(filtered_data),
+ "%s",
+ data-1);
+ makePrintable(filtered_data);
+ fprintf(stderr,"store non-APRS data as status: %s: |%s|\n",call,filtered_data);
+ }
+
+ // GPRMC etc. without a position is here too, but it should not be stored as status!
+
+ // store it as status report until we get a real one
+ if ((p_station->flag & (~ST_STATUS)) == 0) { // only store it if no status yet
+
+ add_status(p_station,data-1);
+
+ p_station->record_type = NORMAL_APRS; // ???
+
+ }
+
+ ok = 1;
+ found_pos = 0;
+ }
+
+ curr_sec = sec_now();
+ if (ok) {
+
+ // data packet is valid
+ // announce own echo, we soon discard that packet...
+// if (!new_station && is_my_call(p_station->call_sign,1) // Check SSID as well
+ if (!new_station
+ && is_my_station(p_station) // Check SSID as well
+ && strchr(path,'*') != NULL) {
+
+ upd_echo(path); // store digi that echoes my signal...
+ statusline(langcode("BBARSTA033"),0); // Echo from digipeater
+
+ }
+ // check if data is just a secondary echo from another digi
+ if ((last_flag & ST_VIATNC) == 0
+ || (curr_sec - last_stn_sec) > 15
+ || p_station->coord_lon != last_lon
+ || p_station->coord_lat != last_lat)
+
+ store = 1; // don't store secondary echos
+ }
+
+ if (!ok && new_station)
+ delete_station_memory(p_station); // remove unused record
+
+ if (store) {
+
+ // we now have valid data to store into database
+ // make time index unique by adding a serial number
+
+ if (station_is_mine) {
+ // This station is me. Set the
+ // flag which shows that we own/control this
+ // station. We use this flag later in lieu
+ // of the is_my_call() function in order to speed things
+ // up.
+ //
+ p_station->flag |= ST_MYSTATION;
+ }
+
+ // Check whether it's a locally-owned object/item
+ if ( object_is_mine
+ || ( new_origin_is_mine
+ && (p_station->flag & ST_ACTIVE)
+ && (p_station->flag & ST_OBJECT) ) ) {
+
+ p_station->flag |= ST_MYOBJITEM;
+
+ // Do nothing else. We don't want to update the
+ // last-heard time so that it'll expire from the queue
+ // normally, unless it is a new object/item.
+ //
+ if (new_station) {
+ p_station->sec_heard = curr_sec;
+ }
+
+ // We need an exception later in this function for the
+ // case where we've moved an object/item (by how much?).
+ // We need to update the time in this case so that it'll
+ // expire later (in fact it could already be expired
+ // when we move it). We should be able to move expired
+ // objects/items to make them active again. Perhaps
+ // some other method as well?.
+ }
+ else {
+ // Reset the "my object" flag
+ p_station->flag &= ~ST_MYOBJITEM;
+
+ p_station->sec_heard = curr_sec; // Give it a new timestamp
+ }
+
+ if (curr_sec != last_sec) { // todo: if old time calculate time_sn from database
+ last_sec = curr_sec;
+ next_time_sn = 0; // restart time serial number
+ }
+
+ p_station->time_sn = next_time_sn++; // todo: warning if serial number too high
+ if (from == DATA_VIA_TNC) { // heard via TNC
+ if (!third_party) { // Not a third-party packet
+ p_station->flag |= ST_VIATNC; // set "via TNC" flag
+ p_station->heard_via_tnc_last_time = curr_sec;
+ p_station->heard_via_tnc_port = port;
+ }
+ else { // Third-party packet
+ // Leave the previous setting of "flag" alone.
+ // Specifically do NOT set the ST_VIATNC flag if it
+ // was a third-party packet.
+ }
+ }
+ else { // heard other than TNC
+ if (new_station) { // new station
+ p_station->flag &= (~ST_VIATNC); // clear "via TNC" flag
+//fprintf(stderr,"New_station: Cleared ST_VIATNC flag: %s\n", p_station->call_sign);
+ p_station->heard_via_tnc_last_time = 0l;
+ }
+ }
+ p_station->last_port_heard = port;
+ p_station->data_via = from;
+ // Create a timestamp from the current time
+ xastir_snprintf(p_station->packet_time,
+ sizeof(p_station->packet_time),
+ "%s",
+ get_time(temp_data)); // get_time returns value in temp_data
+
+ p_station->flag |= ST_ACTIVE;
+ if (third_party)
+ p_station->flag |= ST_3RD_PT; // set "third party" flag
+ else
+ p_station->flag &= (~ST_3RD_PT); // clear "third party" flag
+ if (origin != NULL && strcmp(origin,"INET") == 0) // special treatment for inet names
+ xastir_snprintf(p_station->origin,
+ sizeof(p_station->origin),
+ "%s",
+ origin); // to keep them separated from calls
+ if (origin != NULL && strcmp(origin,"INET-NWS") == 0) // special treatment for NWS
+ xastir_snprintf(p_station->origin,
+ sizeof(p_station->origin),
+ "%s",
+ origin); // to keep them separated from calls
+
+ if (origin != NULL && strcmp(origin,"INET-BOM") == 0) // special treatment for BOM (AU)
+ xastir_snprintf(p_station->origin,
+ sizeof(p_station->origin),
+ "%s",
+ origin); // to keep them separated from calls
+
+ if (origin == NULL || origin[0] == '\0') // normal call
+ p_station->origin[0] = '\0'; // undefine possible former object with same name
+
+
+ //--------------------------------------------------------------------
+
+ // KC2ELS
+ // Okay, here are the standards for ST_DIRECT:
+ // 1. The packet must have been received via TNC.
+ // 2. The packet must not have any * flags.
+ // 3. If present, the first WIDEn-N (or TRACEn-N) must have n=N.
+ // A station retains the ST_DIRECT setting. If
+ // "st_direct_timeout" seconds have passed since we set
+ // that bit then APRSD queries and displays based on the
+ // ST_DIRECT bit will skip that station.
+
+// In order to make this scheme work for stations that straddle both
+// RF and INET, we need to make sure that node_path_ptr doesn't get
+// overwritten with an INET path if there's an RF path already in
+// there and it has been less than st_direct_timeout seconds since
+// the station was last heard on RF.
+
+ if ((from == DATA_VIA_TNC) // Heard via TNC
+ && !third_party // Not a 3RD-Party packet
+ && path != NULL // Path is not NULL
+ && strchr(path,'*') == NULL) { // No asterisk found
+
+ // Look for WIDE or TRACE
+ if ((((p = strstr(path,"WIDE")) != NULL)
+ && (p+=4)) ||
+ (((p = strstr(path,"TRACE")) != NULL)
+ && (p+=5))) {
+
+ // Look for n=N on WIDEn-N/TRACEn-N digi field
+ if ((*p != '\0') && isdigit((int)*p)) {
+ if ((*(p+1) != '\0') && (*(p+1) == '-')) {
+ if ((*(p+2) != '\0') && isdigit((int)*(p+2))) {
+ if (*(p) == *(p+2)) {
+ direct = 1;
+ }
+ else {
+ direct = 0;
+ }
+ }
+ else {
+ direct = 0;
+ }
+ }
+ else {
+ direct = 0;
+ }
+ }
+ else {
+ direct = 1;
+ }
+ }
+ else {
+ direct = 1;
+ }
+ }
+ else {
+ direct = 0;
+ }
+
+ if (direct == 1) {
+ // This packet was heard direct. Set the ST_DIRECT bit
+ // and save the timestamp away.
+ if (debug_level & 1) {
+ fprintf(stderr,"Setting ST_DIRECT for station %s\n",
+ p_station->call_sign);
+ }
+ p_station->direct_heard = curr_sec;
+ p_station->flag |= (ST_DIRECT);
+ }
+ else {
+ // This packet was NOT heard direct. Check whether we
+ // need to expire the ST_DIRECT bit. A lot of fixed
+ // stations transmit every 30 minutes. One hour gives
+ // us time to receive a direct packet from them among
+ // all the digipeated packets.
+
+ if ((p_station->flag & ST_DIRECT) != 0 &&
+ curr_sec > (p_station->direct_heard + st_direct_timeout)) {
+ if (debug_level & 1)
+ fprintf(stderr,"Clearing ST_DIRECT for station %s\n",
+ p_station->call_sign);
+ p_station->flag &= (~ST_DIRECT);
+ }
+ }
+
+ // If heard on TNC, overwrite node_path_ptr if any of these
+ // conditions are met:
+ // *) direct == 1 (packet was heard direct)
+ // *) ST_DIRECT flag == 0 (packet hasn't been heard
+ // direct recently)
+ // *) ST_DIRECT is set, st_direct_timeout has expired
+ // (packet hasn't been heard direct recently)
+ //
+ // These rules will allow us to keep directly heard paths
+ // saved for at least an hour (st_direct_timeout), and not
+ // get overwritten with digipeated paths during that time.
+ //
+ if ((from == DATA_VIA_TNC) // Heard via TNC
+ && !third_party // Not a 3RD-Party packet
+ && path != NULL) { // Path is not NULL
+
+ // Heard on TNC interface and not third party. Check
+ // the other conditions listed in the comments above to
+ // decide whether we should overwrite the node_path_ptr
+ // variable.
+ //
+ if ( direct // This packet was heard direct
+ || (p_station->flag & ST_DIRECT) == 0 // Not heard direct lately
+ || ( (p_station->flag & ST_DIRECT) != 0 // Not heard direct lately
+ && (curr_sec > (p_station->direct_heard+st_direct_timeout) ) ) ) {
+
+ // Free any old path we might have
+ if (p_station->node_path_ptr != NULL)
+ free(p_station->node_path_ptr);
+ // Malloc and store the new path
+ p_station->node_path_ptr = (char *)malloc(strlen(path) + 1);
+ CHECKMALLOC(p_station->node_path_ptr);
+
+ substr(p_station->node_path_ptr,path,strlen(path));
+ }
+ }
+
+ // If a 3rd-party packet heard on TNC, overwrite
+ // node_path_ptr only if heard_via_tnc_last_time is older
+ // than one hour (zero counts as well!), plus clear the
+ // ST_DIRECT and ST_VIATNC bits in this case. This makes us
+ // keep the RF path around for at least one hour after the
+ // station is heard.
+ //
+ else if ((from == DATA_VIA_TNC) // Heard via TNC
+ && third_party // It's a 3RD-Party packet
+ && path != NULL) { // Path is not NULL
+
+ // 3rd-party packet heard on TNC interface. Check if
+ // heard_via_tnc_last_time is older than an hour. If
+ // so, overwrite the path and clear a few bits to show
+ // that it has timed out on RF and we're now receiving
+ // that station from an igate.
+ //
+ if (curr_sec > (p_station->heard_via_tnc_last_time + 60*60)) {
+
+ // Yep, more than one hour old or is a zero,
+ // overwrite the node_path_ptr variable with the new
+ // one. We're only hearing this station on INET
+ // now.
+
+ // Free any old path we might have
+ if (p_station->node_path_ptr != NULL)
+ free(p_station->node_path_ptr);
+ // Malloc and store the new path
+ p_station->node_path_ptr = (char *)malloc(strlen(path) + 1);
+ CHECKMALLOC(p_station->node_path_ptr);
+
+ substr(p_station->node_path_ptr,path,strlen(path));
+
+ // Clear the ST_VIATNC bit
+ p_station->flag &= ~ST_VIATNC;
+ }
+
+ // If direct_heard is over an hour old, clear the
+ // ST_DIRECT flag. We're only hearing this station on
+ // INET now.
+ //
+ if (curr_sec > (p_station->direct_heard + st_direct_timeout)) {
+
+ // Yep, more than one hour old or is a zero, clear
+ // the ST_DIRECT flag.
+ p_station->flag &= ~ST_DIRECT;
+ }
+ }
+
+ // If heard on INET then overwrite node_path_ptr only if
+ // heard_via_tnc_last_time is older than one hour (zero
+ // counts as well!), plus clear the ST_DIRECT and ST_VIATNC
+ // bits in this case. This makes us keep the RF path around
+ // for at least one hour after the station is heard.
+ //
+ else if (from != DATA_VIA_TNC // From an INET interface
+ && !third_party // Not a 3RD-Party packet
+ && path != NULL) { // Path is not NULL
+
+ // Heard on INET interface. Check if
+ // heard_via_tnc_last_time is older than an hour. If
+ // so, overwrite the path and clear a few bits to show
+ // that it has timed out on RF and we're now receiving
+ // that station from the INET feeds.
+ //
+ if (curr_sec > (p_station->heard_via_tnc_last_time + 60*60)) {
+
+ // Yep, more than one hour old or is a zero,
+ // overwrite the node_path_ptr variable with the new
+ // one. We're only hearing this station on INET
+ // now.
+
+ // Free any old path we might have
+ if (p_station->node_path_ptr != NULL)
+ free(p_station->node_path_ptr);
+ // Malloc and store the new path
+ p_station->node_path_ptr = (char *)malloc(strlen(path) + 1);
+ CHECKMALLOC(p_station->node_path_ptr);
+
+ substr(p_station->node_path_ptr,path,strlen(path));
+
+ // Clear the ST_VIATNC bit
+ p_station->flag &= ~ST_VIATNC;
+/*
+fprintf(stderr,
+ "\ntype:%d call:%s path:%s data:%s from:%c port:%d origin:%s 3rd:%d\n",
+ type,
+ call_sign,
+ path,
+ data,
+ from,
+ port,
+ origin,
+ third_party);
+fprintf(stderr,"Cleared ST_VIATNC flag (2): %s\n", p_station->call_sign);
+*/
+ }
+
+ // If direct_heard is over an hour old, clear the
+ // ST_DIRECT flag. We're only hearing this station on
+ // INET now.
+ //
+ if (curr_sec > (p_station->direct_heard + st_direct_timeout)) {
+
+ // Yep, more than one hour old or is a zero, clear
+ // the ST_DIRECT flag.
+ p_station->flag &= ~ST_DIRECT;
+ }
+ }
+
+
+ //---------------------------------------------------------------------
+
+ p_station->num_packets += 1;
+ redo_list = (int)TRUE; // we may need to update the lists
+
+ if (found_pos) { // if station has a position with the data
+ if (position_on_extd_screen(p_station->coord_lat,p_station->coord_lon)) {
+ p_station->flag |= (ST_INVIEW); // set "In View" flag
+ if (debug_level & 256)
+ fprintf(stderr,"Setting ST_INVIEW flag\n");
+ }
+ else {
+ p_station->flag &= (~ST_INVIEW); // clear "In View" flag
+ if (debug_level & 256)
+ fprintf(stderr,"Clearing ST_INVIEW flag\n");
+ }
+ }
+
+ screen_update = 0;
+ if (new_station) {
+ if (debug_level & 256) {
+ fprintf(stderr,"New Station %s\n", p_station->call_sign);
+ }
+ if (strlen(p_station->speed) > 0 && atof(p_station->speed) > 0) {
+ p_station->flag |= (ST_MOVING); // it has a speed, so it's moving
+ moving = 1;
+ }
+ if (position_on_screen(p_station->coord_lat,p_station->coord_lon)) {
+
+ if (p_station->coord_lat != 0 && p_station->coord_lon != 0) { // discard undef positions from screen
+ if (!altnet || is_altnet(p_station) ) {
+ display_station(da,p_station,1);
+ screen_update = 1; // ???
+ }
+ }
+ }
+ }
+ else { // we had seen this station before...
+ if (debug_level & 256) {
+ fprintf(stderr,"New Data for %s %ld %ld\n", p_station->call_sign,
+ p_station->coord_lat, p_station->coord_lon);
+ }
+ if (found_pos && position_defined(p_station->coord_lat,p_station->coord_lon,1)) { // ignore undefined and 0N/0E
+ if (debug_level & 256) {
+ fprintf(stderr," Valid position for %s\n",
+ p_station->call_sign);
+ }
+ if (p_station->newest_trackpoint != NULL) {
+ if (debug_level & 256) {
+ fprintf(stderr,"Station has a trail: %s\n",
+ p_station->call_sign);
+ }
+ moving = 1; // it's moving if it has a trail
+ }
+ else {
+ if (strlen(p_station->speed) > 0 && atof(p_station->speed) > 0) {
+ if (debug_level & 256) {
+ fprintf(stderr,"Speed detected on %s\n",
+ p_station->call_sign);
+ }
+ moving = 1; // declare it moving, if it has a speed
+ }
+ else {
+ if (debug_level & 256) {
+ fprintf(stderr,"Position defined: %d, Changed: %s\n",
+ position_defined(last_lat, last_lon, 1),
+ (p_station->coord_lat != last_lat ||
+ p_station->coord_lon != last_lon) ?
+ "Yes" : "No");
+ }
+
+ // Here's where we detect movement
+ if (position_defined(last_lat,last_lon,1)
+ && (p_station->coord_lat != last_lat || p_station->coord_lon != last_lon)) {
+ if (debug_level & 256) {
+ fprintf(stderr,"Position Change detected on %s\n",
+ p_station->call_sign);
+ }
+ moving = 1; // it's moving if it has changed the position
+ }
+ else {
+ if (debug_level & 256) {
+ fprintf(stderr,"Station %s still appears stationary.\n",
+ p_station->call_sign);
+ fprintf(stderr," %s stationary at %ld %ld (%ld %ld)\n",
+ p_station->call_sign,
+ p_station->coord_lat, p_station->coord_lon,
+ last_lat, last_lon);
+ }
+ moving = 0;
+ }
+ }
+ }
+ changed_pos = 0;
+ if (moving == 1) {
+ p_station->flag |= (ST_MOVING);
+ // we have a moving station, process trails
+ if (atoi(p_station->speed) < TRAIL_MAX_SPEED) { // reject high speed data (undef gives 0)
+ // we now may already have the 2nd position, so store the old one first
+ if (debug_level & 256) {
+ fprintf(stderr,"Station %s valid speed %s\n",
+ p_station->call_sign, p_station->speed);
+ }
+ if (p_station->newest_trackpoint == NULL) {
+ if (debug_level & 256) {
+ fprintf(stderr,"Station %s no trail history.\n",
+ p_station->call_sign);
+ }
+ if (position_defined(last_lat,last_lon,1)) { // ignore undefined and 0N/0E
+ if (debug_level & 256) {
+ fprintf(stderr,"Storing old position for %s\n",
+ p_station->call_sign);
+ }
+ (void)store_trail_point(p_station,
+ last_lon,
+ last_lat,
+ last_stn_sec,
+ last_alt,
+ last_speed,
+ last_course,
+ last_flag);
+ }
+ }
+ //if ( p_station->coord_lon != last_lon
+ // || p_station->coord_lat != last_lat ) {
+ // we don't store redundant points (may change this
+ // later ?)
+ //
+ // There are often echoes delayed 15 minutes
+ // or so it looks ugly on the trail, so I
+ // want to discard them This also discards
+ // immediate echoes. Duplicates back in time
+ // up to TRAIL_ECHO_TIME minutes are
+ // discarded.
+ //
+ if (!is_trailpoint_echo(p_station)) {
+ (void)store_trail_point(p_station,
+ p_station->coord_lon,
+ p_station->coord_lat,
+ p_station->sec_heard,
+ p_station->altitude,
+ p_station->speed,
+ p_station->course,
+ p_station->flag);
+ changed_pos = 1;
+
+ // Check whether it's a locally-owned object/item
+ if (object_is_mine) {
+
+ // Update time, change position in
+ // time-sorted list to change
+ // expiration time.
+ move_station_time(p_station,p_time);
+ // Give it a new timestamp
+ p_station->sec_heard = curr_sec;
+
+ //fprintf(stderr,"Updating last heard time\n");
+ }
+ }
+ else if (debug_level & 256) {
+ fprintf(stderr,"Trailpoint echo detected for %s\n",
+ p_station->call_sign);
+ }
+ }
+ else {
+ if (debug_level & 256 || debug_level & 1)
+ fprintf(stderr,"Speed over %d mph\n",TRAIL_MAX_SPEED);
+ }
+
+ if (track_station_on == 1) // maybe we are tracking a station
+ track_station(da,tracking_station_call,p_station);
+ } // moving...
+
+ // now do the drawing to the screen
+ ok_to_display = !altnet || is_altnet(p_station); // Optimization step, needed twice below.
+ screen_update = 0;
+ if (changed_pos == 1 && Display_.trail && ((p_station->flag & ST_INVIEW) != 0)) {
+ if (ok_to_display) {
+ if (debug_level & 256) {
+ fprintf(stderr,"Adding Solid Trail for %s\n",
+ p_station->call_sign);
+ }
+ draw_trail(da,p_station,1); // update trail
+ screen_update = 1;
+ }
+ else if (debug_level & 256) {
+ fprintf(stderr,"Skipped trail for %s (altnet)\n",
+ p_station->call_sign);
+ }
+ }
+ if (position_on_screen(p_station->coord_lat,p_station->coord_lon)) {
+ if (changed_pos == 1 || !position_defined(last_lat,last_lon,0)) {
+ if (ok_to_display) {
+ display_station(da,p_station,1);// update symbol
+ screen_update = 1;
+ }
+ }
+ }
+ } // defined position
+ }
+
+ if (screen_update) {
+ if (p_station->data_via == 'T') { // Data from local TNC
+//WE7U
+// or data_via == 'I' and last_port_heard == AGWPE interface
+ redraw_on_new_data = 2; // Update all symbols NOW!
+ }
+ else if (p_station->data_via == 'F') { // If data from file
+ redraw_on_new_data = 1; // Update each 2 secs
+ }
+// else if (scale_y > 2048) { // Wider area of world
+ else {
+ redraw_on_new_data = 0; // Update each 60 secs
+ }
+ }
+
+ // announce stations in the status line
+// if (!is_my_call(p_station->call_sign,1) // Check SSID as well
+// && !is_my_call(p_station->origin,1) // Check SSID as well
+ if (!is_my_station(p_station)
+ && !is_my_object_item(p_station) // Check SSID as well
+ && !wait_to_redraw) {
+ if (new_station) {
+ if (p_station->origin[0] == '\0') // new station
+ xastir_snprintf(station_id, sizeof(station_id), langcode("BBARSTA001"),p_station->call_sign);
+ else // new object
+ xastir_snprintf(station_id, sizeof(station_id), langcode("BBARSTA000"),p_station->call_sign);
+ }
+ else // updated data
+ xastir_snprintf(station_id, sizeof(station_id), langcode("BBARSTA002"),p_station->call_sign);
+
+ statusline(station_id,0);
+ }
+
+ // announce new station with sound file or speech synthesis
+ if (new_station && !wait_to_redraw) { // && !is_my_call(p_station->call_sign,1) // ???
+ if (sound_play_new_station)
+ play_sound(sound_command,sound_new_station);
+
+#ifdef HAVE_FESTIVAL
+ if (festival_speak_new_station) {
+ char speech_callsign[50];
+
+ xastir_snprintf(speech_callsign,
+ sizeof(speech_callsign),
+ "%s",
+ p_station->call_sign);
+ spell_it_out(speech_callsign, 50);
+
+ xastir_snprintf(station_id,
+ sizeof(station_id),
+ "%s, %s",
+ langcode("SPCHSTR010"),
+ speech_callsign);
+ SayText(station_id);
+ }
+#endif // HAVE_FESTIVAL
+ }
+
+ // check for range and DX
+// if (found_pos && !is_my_call(p_station->call_sign,1)) { // Check SSID also
+ if (found_pos
+ && !is_my_station(p_station)) { // Check SSID also
+
+ // if station has a position with the data
+ /* Check Audio Alarms based on incoming packet */
+ /* FG don't care if this is on screen or off get position */
+ l_lat = convert_lat_s2l(my_lat);
+ l_lon = convert_lon_s2l(my_long);
+
+ // Get distance in nautical miles.
+ value = (float)calc_distance_course(l_lat,l_lon,
+ p_station->coord_lat,p_station->coord_lon,temp_data,sizeof(temp_data));
+
+ // Convert to whatever measurement value we're currently using
+ distance = value * cvt_kn2len;
+
+ /* check ranges */
+ if ((distance > atof(prox_min)) && (distance < atof(prox_max))) {
+
+ //fprintf(stderr,"Station within proximity circle, creating waypoint\n");
+ create_garmin_waypoint(p_station->coord_lat,
+ p_station->coord_lon,
+ p_station->call_sign);
+
+ if (sound_play_prox_message) {
+ xastir_snprintf(station_id, sizeof(station_id),
+ "%s < %.3f %s",p_station->call_sign,
+ distance,
+ english_units?langcode("UNIOP00004"):langcode("UNIOP00005"));
+ statusline(station_id,0);
+ play_sound(sound_command,sound_prox_message);
+ /*fprintf(stderr,"%s> PROX distance %f\n",p_station->call_sign, distance);*/
+ }
+ }
+#ifdef HAVE_FESTIVAL
+ if ((distance > atof(prox_min)) && (distance < atof(prox_max)) && festival_speak_proximity_alert) {
+ char speech_callsign[50];
+
+ xastir_snprintf(speech_callsign,
+ sizeof(speech_callsign),
+ "%s",
+ p_station->call_sign);
+ spell_it_out(speech_callsign, 50);
+
+ if (english_units) {
+ if (distance < 1.0)
+ xastir_snprintf(station_id, sizeof(station_id), langcode("SPCHSTR005"), speech_callsign,
+ (int)(distance * 1760), langcode("SPCHSTR004")); // say it in yards
+ else if ((int)((distance * 10) + 0.5) % 10)
+ xastir_snprintf(station_id, sizeof(station_id), langcode("SPCHSTR006"), speech_callsign, distance,
+ langcode("SPCHSTR003")); // say it in miles with one decimal
+ else
+ xastir_snprintf(station_id, sizeof(station_id), langcode("SPCHSTR005"), speech_callsign, (int)(distance + 0.5),
+ langcode("SPCHSTR003")); // say it in miles with no decimal
+ }
+ else {
+ if (distance < 1.0)
+ xastir_snprintf(station_id, sizeof(station_id), langcode("SPCHSTR005"), speech_callsign,
+ (int)(distance * 1000), langcode("SPCHSTR002")); // say it in meters
+ else if ((int)((distance * 10) + 0.5) % 10)
+ xastir_snprintf(station_id, sizeof(station_id), langcode("SPCHSTR006"), speech_callsign, distance,
+ langcode("SPCHSTR001")); // say it in kilometers with one decimal
+ else
+ xastir_snprintf(station_id, sizeof(station_id), langcode("SPCHSTR005"), speech_callsign, (int)(distance + 0.5),
+ langcode("SPCHSTR001")); // say it in kilometers with no decimal
+ }
+ SayText(station_id);
+ }
+#endif // HAVE_FESTIVAL
+ /* FG really should check the path before we do this and add setup for these ranges */
+ if (sound_play_band_open_message && from == DATA_VIA_TNC && !(p_station->flag & ST_3RD_PT) &&
+ (distance > atof(bando_min)) && (distance < atof(bando_max))) {
+ xastir_snprintf(station_id, sizeof(station_id), "%s %s %.1f %s",p_station->call_sign, langcode("UMBNDO0001"),
+ distance, english_units?langcode("UNIOP00004"):langcode("UNIOP00005"));
+ statusline(station_id,0);
+ play_sound(sound_command,sound_band_open_message);
+ /*fprintf(stderr,"%s> BO distance %f\n",p_station->call_sign, distance);*/
+ }
+#ifdef HAVE_FESTIVAL
+ if (festival_speak_band_opening && from == DATA_VIA_TNC && !(p_station->flag & ST_3RD_PT) &&
+ (distance > atof(bando_min)) && (distance < atof(bando_max))) {
+ char speech_callsign[50];
+
+ xastir_snprintf(speech_callsign,
+ sizeof(speech_callsign),
+ "%s",
+ p_station->call_sign);
+ spell_it_out(speech_callsign, 50);
+
+ xastir_snprintf(station_id,
+ sizeof(station_id),
+ langcode("SPCHSTR011"),
+ speech_callsign,
+ distance,
+ english_units?langcode("SPCHSTR003"):langcode("SPCHSTR001"));
+ SayText(station_id);
+ }
+#endif // HAVE_FESTIVAL
+
+ } // end found_pos
+
+
+#ifdef HAVE_DB
+ // Clumsy way of doing things - needs a more elegant approach
+ // iterate through interfaces
+ if (p_station->data_via != DATA_VIA_DATABASE) {
+ if (debug_level & 4096)
+ fprintf(stderr,"Trying to store station %s to database interfaces.\n",p_station->call_sign);
+ for (ii=0;ii<MAX_IFACE_DEVICES;ii++) {
+ if (debug_level & 4096) {
+ fprintf(stderr,"Trying interface [%d] ",ii);
+ fprintf(stderr,"connection [%p]\n",&connections[ii]);
+ }
+ if (&connections[ii] != NULL){
+ // Note < 4 is an artificial upper limit that may catch cases where the memmory
+ // for the connection has been overwritten.
+ if (connections[ii].type > 0 && connections[ii].type < 4){
+ if (debug_level & 4096)
+ fprintf(stderr,"type=[%d]\n",connections[ii].type);
+ if (port_data[ii].status == DEVICE_UP) {
+ if (connections[ii].descriptor->device_type==DEVICE_SQL_DATABASE) {
+ if (debug_level & 4096)
+ fprintf(stderr,"Trying interface %d\n",ii);
+ // if interface is a sql server interface
+ // write station data to sql database
+ ok = storeStationSimpleToGisDb(&connections[ii], p_station);
+ if (ok==1) {
+ if (debug_level & 4096) {
+ fprintf(stderr,"Stored station %s to database interface %d.\n",p_station->call_sign,ii);
+ }
+ } else {
+ pingConnection(&connections[ii]);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+#endif /* HAVE_DB */
+
+ } // valid data into database
+
+ return(ok);
+} // End of data_add() function
+
+
+
+
+
+// Code to compute SmartBeaconing(tm) rates.
+//
+// SmartBeaconing(tm) was invented by Steve Bragg (KA9MVA) and Tony Arnerich
+// (KD7TA). Its main goal is to change the beacon rate based on speed
+// and cornering. It does speed-variant corner pegging and
+// speed-variant posit rate.
+
+// Some tweaks have been added to the generic SmartBeaconing(tm) algorithm,
+// but are current labeled as experimental and commented out: 1) We do
+// a posit as soon as we first cross below the sb_low_speed_limit, and
+// 2) We do a posit as soon as we cross above the sb_low_speed_limit if
+// we haven't done a posit for sb_turn_time seconds. These tweaks are
+// intended to help show that the mobile station has stopped (so that
+// dead-reckoning doesn't keep it moving across the map on other
+// people's displays) and to more quickly show that the station is
+// moving again (for the case where they're in stop-and-go traffic
+// perhaps).
+//
+// It's possible that these new tweaks won't work well for the case
+// where a station is traveling near the speed of sb_low_speed_limit.
+// In this case they'll generate a posit each time they go below it and
+// every time they go above it if they haven't done a posit in
+// sb_turn_time seconds. This could result in a lot of posits very
+// quickly. We may need to add yet another limit just above the
+// sb_low_speed_limit for hysteresis, and not posit until we cross above
+// that new limit.
+//
+// Several special SmartBeaconing(tm) parameters come into play here:
+//
+// sb_turn_min Minimum degrees at which corner pegging will
+// occur. The next parameter affects this for
+// lower speeds.
+//
+// sb_turn_slope Fudget factor for making turns less sensitive at
+// lower speeds. No real units on this one.
+// It ends up being non-linear over the speed
+// range the way the original SmartBeaconing(tm)
+// algorithm works.
+//
+// sb_turn_time Dead-time before/after a corner peg beacon.
+// Units are in seconds.
+//
+// sb_posit_fast Fast posit rate, used if >= sb_high_speed_limit.
+// Units are in seconds.
+//
+// sb_posit_slow Slow posit rate, used if <= sb_low_speed_limit.
+// Units are in minutes.
+//
+// sb_low_speed_limit Low speed limit, units are in Mph.
+//
+// sb_high_speed_limit High speed limit, units are in Mph.
+//
+//
+// Input: Course in degrees
+// Speed in knots
+//
+// Output: May force beacons by setting posit_next_time to various
+// values.
+//
+// Modify: sb_POSIT_rate
+// sb_current_heading
+// sb_last_heading
+// posit_next_time
+//
+//
+// With the defaults compiled into the code, here are the
+// turn_thresholds for a few speeds:
+//
+// Example: sb_turn_min = 20
+// sb_turn_slope = 25
+// sb_high_speed_limit = 60
+//
+// > 60mph 20 degrees
+// 50mph 25 degrees
+// 40mph 26 degrees
+// 30mph 28 degrees
+// 20mph 33 degrees
+// 10mph 45 degrees
+// 3mph 103 degrees (we limit it to 80 now)
+// 2mph 145 degrees (we limit it to 80 now)
+//
+// I added a max threshold of 80 degrees into the code. 145 degrees
+// is unreasonable to expect except for perhaps switchback or 'U'
+// turns.
+//
+// It'd probably be better to do a linear interpolation of
+// turn_threshold based on min/max speed and min/max turns. That's
+// not how the SmartBeaconing(tm) algorithm coders implemented it in
+// the HamHud though.
+//
+void compute_smart_beacon(char *current_course, char *current_speed) {
+ int course;
+ int speed;
+ int turn_threshold;
+ time_t secs_since_beacon;
+ int heading_change_since_beacon;
+ int beacon_now = 0;
+ int curr_sec = sec_now();
+
+ // Don't compute SmartBeaconing(tm) parameters or force any beacons
+ // if we're not in that mode!
+ if (!smart_beaconing)
+ return;
+
+ // Convert from knots to mph/kph (whichever is selected)
+ speed = (int)(atof(current_speed) * cvt_kn2len + 0.5); // Poor man's rounding
+
+ course = atoi(current_course);
+
+ secs_since_beacon = curr_sec - posit_last_time;
+
+ // Check for the low speed threshold, set to slow posit rate if
+ // we're going slow.
+ if (speed <= sb_low_speed_limit) {
+ //fprintf(stderr,"Slow speed\n");
+
+
+// EXPERIMENTAL!!!
+////////////////////////////////////////////////////////////////////
+ // Check to see if we're just crossing the threshold, if so,
+ // beacon. This keeps dead-reckoning working properly on
+ // other people's displays. Be careful for speeds near this
+ // threshold though. We really need a slow-speed rate and a
+ // stop rate, with some distance between them, in order to
+ // have some hysteresis for these posits.
+// if (sb_POSIT_rate != (sb_posit_slow * 60) ) { // Previous rate was _not_ the slow rate
+// beacon_now++; // Force a posit right away
+// //fprintf(stderr,"Stopping, POSIT!\n");
+// }
+////////////////////////////////////////////////////////////////////
+
+
+ // Set to slow posit rate
+ sb_POSIT_rate = sb_posit_slow * 60; // Convert to seconds
+ }
+ else { // We're moving faster than the low speed limit
+
+
+// EXPERIMENTAL!!!
+////////////////////////////////////////////////////////////////////
+ // Check to see if we're just starting to move. Again, we
+ // probably need yet-another-speed-limit here to provide
+ // some hysteresis.
+// if ( (secs_since_beacon > sb_turn_time) // Haven't beaconed for a bit
+// && (sb_POSIT_rate == (sb_posit_slow * 60) ) ) { // Last rate was the slow rate
+// beacon_now++; // Force a posit right away
+// //fprintf(stderr,"Starting to move, POSIT!\n");
+// }
+////////////////////////////////////////////////////////////////////
+
+
+ // Start with turn_min degrees as the threshold
+ turn_threshold = sb_turn_min;
+
+ // Adjust rate according to speed
+ if (speed > sb_high_speed_limit) { // We're above the high limit
+ sb_POSIT_rate = sb_posit_fast;
+ //fprintf(stderr,"Setting fast rate\n");
+ }
+ else { // We're between the high/low limits. Set a between rate
+ sb_POSIT_rate = (sb_posit_fast * sb_high_speed_limit) / speed;
+ //fprintf(stderr,"Setting medium rate\n");
+
+ // Adjust turn threshold according to speed
+ turn_threshold += (int)( (sb_turn_slope * 10) / speed);
+ }
+
+ // Force a maximum turn threshold of 80 degrees (still too
+ // high?)
+ if (turn_threshold > 80)
+ turn_threshold = 80;
+
+ // Check to see if we've written anything into
+ // sb_last_heading variable yet. If not, write the current
+ // course into it.
+ if (sb_last_heading == -1)
+ sb_last_heading = course;
+
+ // Corner-pegging. Note that we don't corner-peg if we're
+ // below the low-speed threshold.
+ heading_change_since_beacon = abs(course - sb_last_heading);
+ if (heading_change_since_beacon > 180)
+ heading_change_since_beacon = 360 - heading_change_since_beacon;
+
+ //fprintf(stderr,"course change:%d\n",heading_change_since_beacon);
+
+ if ( (heading_change_since_beacon > turn_threshold)
+ && (secs_since_beacon > sb_turn_time) ) {
+ beacon_now++; // Force a posit right away
+
+ //fprintf(stderr,"Corner, POSIT!\tOld:%d\tNew:%d\tDifference:%d\tSpeed: %d\tTurn Threshold:%d\n",
+ // sb_last_heading,
+ // course,
+ // heading_change_since_beacon,
+ // speed,
+ // turn_threshold);
+ }
+
+
+// EXPERIMENTAL
+////////////////////////////////////////////////////////////////////
+ // If we haven't beaconed for a bit (3 * sb_turn_time?), and
+ // just completed a turn, check to see if our heading has
+ // stabilized yet. If so, beacon the latest heading. We'll
+ // have to save another variable which says whether the last
+ // beacon was caused by corner-pegging. The net effect is
+ // that we'll get an extra posit coming out of a turn that
+ // specifies our correct course and probably a more accurate
+ // speed until the next posit. This should make
+ // dead-reckoning work even better.
+ if (0) {
+ }
+////////////////////////////////////////////////////////////////////
+
+
+ }
+
+ // Check to see whether we've sped up sufficiently for the
+ // posit_next_time variable to be too far out. If so, shorten
+ // that interval to match the current speed.
+ if ( (posit_next_time - curr_sec) > sb_POSIT_rate)
+ posit_next_time = curr_sec + sb_POSIT_rate;
+
+
+ if (beacon_now) {
+ posit_next_time = 0; // Force a posit right away
+ }
+
+ // Should we also check for a rate too fast for the current
+ // speed? Probably not. It'll get modified at the next beacon
+ // time, which will happen quickly.
+
+ // Save course for use later. It gets put into sb_last_heading
+ // in UpdateTime() if a beacon occurs. We then use it above to
+ // determine the course deviation since the last time we
+ // beaconed.
+ sb_current_heading = course;
+}
+
+
+
+
+
+// Speed is in knots
+void my_station_gps_change(char *pos_long, char *pos_lat, char *course, char *speed, /*@unused@*/ char speedu, char *alt, char *sats) {
+ long pos_long_temp, pos_lat_temp;
+ char temp_data[40]; // short term string storage
+ char temp_lat[12];
+ char temp_long[12];
+ DataRow *p_station;
+ DataRow *p_time;
+
+ // Note that speed will be in knots 'cuz it was derived from a
+ // GPRMC string without modification.
+
+ // Recompute the SmartBeaconing(tm) parameters based on current/past
+ // course & speed. Sending the speed in knots.
+ //fprintf(stderr,"Speed: %s\n",speed);
+ compute_smart_beacon(course, speed);
+
+ p_station = NULL;
+ if (!search_station_name(&p_station,my_callsign,1)) { // find my data in the database
+ p_time = NULL; // add to end of time sorted list
+//fprintf(stderr,"my_station_gps_change()\n");
+ p_station = add_new_station(p_station,p_time,my_callsign);
+ }
+ p_station->flag |= ST_ACTIVE;
+ p_station->data_via = 'L';
+ p_station->flag &= (~ST_3RD_PT); // clear "third party" flag
+ p_station->record_type = NORMAL_APRS;
+
+ // Free any old path we might have
+ if (p_station->node_path_ptr != NULL)
+ free(p_station->node_path_ptr);
+ // Malloc and store the new path
+ p_station->node_path_ptr = (char *)malloc(strlen("local") + 1);
+ CHECKMALLOC(p_station->node_path_ptr);
+
+ substr(p_station->node_path_ptr,"local",strlen("local"));
+
+ // Create a timestamp from the current time
+ xastir_snprintf(p_station->packet_time,
+ sizeof(p_station->packet_time),
+ "%s",
+ get_time(temp_data));
+ // Create a timestamp from the current time
+ xastir_snprintf(p_station->pos_time,
+ sizeof(p_station->pos_time),
+ "%s",
+ get_time(temp_data));
+ p_station->flag |= ST_MSGCAP; // set "message capable" flag
+
+ /* convert to long and weed out any odd data */
+ pos_long_temp = convert_lon_s2l(pos_long);
+ pos_lat_temp = convert_lat_s2l(pos_lat);
+
+ /* convert back to clean string for config data */
+ convert_lon_l2s(pos_long_temp, temp_data, sizeof(temp_data), CONVERT_HP_NORMAL);
+ xastir_snprintf(temp_long, sizeof(temp_long), "%c%c%c%c%c.%c%c%c%c",temp_data[0],temp_data[1],temp_data[2], temp_data[4],temp_data[5],
+ temp_data[7],temp_data[8], temp_data[9], temp_data[10]);
+ convert_lat_l2s(pos_lat_temp, temp_data, sizeof(temp_data), CONVERT_HP_NORMAL);
+ xastir_snprintf(temp_lat, sizeof(temp_lat), "%c%c%c%c.%c%c%c%c",temp_data[0],temp_data[1],temp_data[3],temp_data[4], temp_data[6],
+ temp_data[7], temp_data[8],temp_data[9]);
+
+ /* fill the data in */ // ???????????????
+ xastir_snprintf(my_lat,
+ sizeof(my_lat),
+ "%s",
+ temp_lat);
+ xastir_snprintf(my_long,
+ sizeof(my_long),
+ "%s",
+ temp_long);
+ p_station->coord_lat = convert_lat_s2l(my_lat);
+ p_station->coord_lon = convert_lon_s2l(my_long);
+
+ if ((p_station->coord_lon != pos_long_temp) || (p_station->coord_lat != pos_lat_temp)) {
+ /* check to see if enough to change pos on screen */
+ if ((pos_long_temp>NW_corner_longitude) && (pos_long_temp<SE_corner_longitude)) {
+ if ((pos_lat_temp>NW_corner_latitude) && (pos_lat_temp<SE_corner_latitude)) {
+ if((labs((p_station->coord_lon+(scale_x/2))-pos_long_temp)/scale_x)>0
+ || (labs((p_station->coord_lat+(scale_y/2))-pos_lat_temp)/scale_y)>0) {
+ //redraw_on_new_data = 1; // redraw next chance
+ //redraw_on_new_data = 2; // better response?
+ if (debug_level & 256) {
+ fprintf(stderr,"Redraw on new gps data \n");
+ }
+ statusline(langcode("BBARSTA038"),0);
+ }
+ else if (debug_level & 256) {
+ fprintf(stderr,"New Position same pixel as old.\n");
+ }
+ }
+ else if (debug_level & 256) {
+ fprintf(stderr,"New Position is off edge of screen.\n");
+ }
+ }
+ else if (debug_level & 256) {
+ fprintf(stderr,"New position is off side of screen.\n");
+ }
+ }
+
+ p_station->coord_lat = pos_lat_temp; // DK7IN: we have it already !??
+ p_station->coord_lon = pos_long_temp;
+
+ curr_sec = sec_now();
+ my_last_altitude_time = curr_sec;
+ xastir_snprintf(p_station->speed,
+ sizeof(p_station->speed),
+ "%s",
+ speed);
+ // is speed always in knots, otherwise we need a conversion!
+ xastir_snprintf(p_station->course,
+ sizeof(p_station->course),
+ "%s",
+ course);
+ xastir_snprintf(p_station->altitude,
+ sizeof(p_station->altitude),
+ "%s",
+ alt);
+ // altu; unit should always be meters ????
+
+ if(debug_level & 256)
+ fprintf(stderr,"GPS MY_LAT <%s> MY_LONG <%s> MY_ALT <%s>\n",
+ my_lat, my_long, alt);
+
+ /* get my last altitude meters to feet */
+ my_last_altitude=(long)(atof(alt)*3.28084);
+
+ /* get my last course in deg */
+ my_last_course=atoi(course);
+
+ /* get my last speed in knots */
+ my_last_speed=(int)(atof(speed));
+ xastir_snprintf(p_station->sats_visible,
+ sizeof(p_station->sats_visible),
+ "%s",
+ sats);
+
+ // Update "heard" time for our new position
+ p_station->sec_heard = curr_sec;
+
+ //if ( p_station->coord_lon != last_lon
+ // || p_station->coord_lat != last_lat ) {
+ // we don't store redundant points (may change this later ?)
+ // There are often echoes delayed 15 minutes or so it looks ugly
+ // on the trail, so I want to discard them This also discards
+ // immediate echoes. Duplicates back in time up to
+ // TRAIL_ECHO_TIME minutes are discarded.
+ //
+ if (!is_trailpoint_echo(p_station)) {
+ (void)store_trail_point(p_station,
+ p_station->coord_lon,
+ p_station->coord_lat,
+ curr_sec,
+ p_station->altitude,
+ p_station->speed,
+ p_station->course,
+ p_station->flag);
+ }
+ if (debug_level & 256) {
+ fprintf(stderr,"Adding Solid Trail for %s\n",
+ p_station->call_sign);
+ }
+ draw_trail(da,p_station,1); // update trail
+ display_station(da,p_station,1); // update symbol
+
+ if (track_station_on == 1) // maybe we are tracking ourselves?
+ track_station(da,tracking_station_call,p_station);
+
+ // We parsed a good GPS string, so allow beaconing to proceed
+ // normally for a while.
+ my_position_valid = 3;
+ //fprintf(stderr,"Valid GPS input: my_position_valid = 3\n");
+
+ //redraw_on_new_data = 1; // redraw next chance
+ redraw_on_new_data = 2; // Immediate update of symbols/tracks
+}
+
+
+
+
+
+void my_station_add(char *my_callsign, char my_group, char my_symbol, char *my_long, char *my_lat, char *my_phg, char *my_comment, char my_amb) {
+ DataRow *p_station;
+ DataRow *p_time;
+ char temp_data[40]; // short term string storage
+ char *strp;
+
+ p_station = NULL;
+ if (!search_station_name(&p_station,my_callsign,1)) { // find call
+ p_time = NULL; // add to end of time sorted list
+//fprintf(stderr,"my_station_add()\n");
+ p_station = add_new_station(p_station,p_time,my_callsign);
+ }
+ p_station->flag |= ST_ACTIVE;
+ p_station->flag |= ST_MYSTATION;
+ p_station->data_via = 'L';
+ p_station->flag &= (~ST_3RD_PT); // clear "third party" flag
+ p_station->record_type = NORMAL_APRS;
+
+ if (transmit_compressed_posit) {
+ // Compressed posit
+ p_station->error_ellipse_radius = 600; // Default of 6m
+ p_station->lat_precision = 6;
+ p_station->lon_precision = 6;
+ }
+ else {
+ // Standard APRS posit
+ p_station->error_ellipse_radius = 2550; // 25.5m, or about 60ft resolution
+ p_station->lat_precision = 60;
+ p_station->lon_precision = 60;
+ }
+
+ // Free any old path we might have
+ if (p_station->node_path_ptr != NULL)
+ free(p_station->node_path_ptr);
+ // Malloc and store the new path
+ p_station->node_path_ptr = (char *)malloc(strlen("local") + 1);
+ CHECKMALLOC(p_station->node_path_ptr);
+
+ substr(p_station->node_path_ptr,"local",strlen("local"));
+
+ // Create a timestamp from the current time
+ xastir_snprintf(p_station->packet_time,
+ sizeof(p_station->packet_time),
+ "%s",
+ get_time(temp_data));
+ // Create a timestamp from the current time
+ xastir_snprintf(p_station->pos_time,
+ sizeof(p_station->pos_time),
+ "%s",
+ get_time(temp_data));
+ p_station->flag |= ST_MSGCAP; // set "message capable" flag
+
+ /* Symbol overlay */
+ if(my_group != '/' && my_group != '\\') {
+ // Found an overlay character. Check it.
+ if ( (my_group >= '0' && my_group <= '9')
+ || (my_group >= 'A' && my_group <= 'Z') ) {
+ // Overlay character is good
+ p_station->aprs_symbol.aprs_type = '\\';
+ p_station->aprs_symbol.special_overlay = my_group;
+ }
+ else {
+ // Found a bad overlay character
+ p_station->aprs_symbol.aprs_type = my_group;
+ p_station->aprs_symbol.special_overlay = '\0';
+ }
+ }
+ else { // Normal symbol, no overlay
+ p_station->aprs_symbol.aprs_type = my_group;
+ p_station->aprs_symbol.special_overlay = '\0';
+ }
+ p_station->aprs_symbol.aprs_symbol = my_symbol;
+
+ p_station->pos_amb = my_amb;
+ xastir_snprintf(temp_data,
+ sizeof(temp_data),
+ "%s",
+ my_lat);
+
+//fprintf(stderr," my_lat:%s\n",temp_data);
+
+ temp_data[9] = '\0';
+
+ strp = &temp_data[20];
+ xastir_snprintf(strp,
+// sizeof(strp), // No good, as strp is a pointer
+ (int)(sizeof(temp_data) / 2),
+ "%s",
+ my_long);
+ strp[10] = '\0';
+
+//fprintf(stderr,"my_long:%s\n",my_long);
+//fprintf(stderr,"my_long:%s\n",strp);
+
+ switch (my_amb) {
+ case 1: // 1/10th minute
+ temp_data[6] = strp[7] = '5';
+ break;
+ case 2: // 1 minute
+ temp_data[5] = strp[6] = '5';
+ temp_data[6] = '0';
+ strp[7] = '0';
+ break;
+ case 3: // 10 minutes
+ temp_data[3] = strp[4] = '5';
+ temp_data[5] = temp_data[6] = '0';
+ strp[6] = strp[7] = '0';
+ break;
+ case 4: // 1 degree
+ temp_data[2] = strp[3] = '3';
+ temp_data[3] = temp_data[5] = temp_data[6] = '0';
+ strp[4] = strp[6] = strp[7] = '0';
+ break;
+ case 0:
+ default:
+ break;
+ }
+ p_station->coord_lat = convert_lat_s2l(temp_data);
+ p_station->coord_lon = convert_lon_s2l(strp);
+
+ if (position_on_extd_screen(p_station->coord_lat,p_station->coord_lon)) {
+ p_station->flag |= (ST_INVIEW); // set "In View" flag
+ }
+ else {
+ p_station->flag &= (~ST_INVIEW); // clear "In View" flag
+ }
+
+ substr(p_station->power_gain,my_phg,7);
+
+ add_comment(p_station,my_comment);
+
+ my_last_course = 0; // set my last course in deg to zero
+ redo_list = (int)TRUE; // update active station lists
+}
+
+
+
+
+
+// Write the text from the packet_data_string out to the dialog if
+// the dialog exists. The user can contract/expand the dialog and
+// always have it filled with the most current data out of the
+// string.
+//
+void display_packet_data(void) {
+
+ if( (Display_data_dialog != NULL)
+ && (redraw_on_new_packet_data !=0)) {
+ int pos;
+ int last_char;
+ int i;
+
+ // Find out the last character position in the dialog text
+ // area.
+ last_char = XmTextGetLastPosition(Display_data_text);
+
+ //fprintf(stderr,"In display_packet_data: first_line=%d,next_line=%d,ncharsdel=%d,nlinesadd=%d\n",first_line,next_line,ncharsdel,nlinesadd);
+
+ if (first_line != -1) { // there is data in the array
+ if (last_char == 0 || ncharsdel>=last_char) {
+ //fprintf(stderr," Starting from clean slate...\n");
+ // but there is no text in the dialog or more chars to delete than
+ // there actually are in the dialog
+ // Clear the dialog just in case:
+ XmTextReplace(Display_data_text,0,last_char,"");
+
+ // display all the data in the ring
+ for (i=first_line;i != next_line;
+ i=(i+1)%MAX_PACKET_DATA_DISPLAY) {
+ XmTextReplace(Display_data_text,last_char,last_char,
+ packet_data_string[i]);
+ last_char=XmTextGetLastPosition(Display_data_text);
+ pos=last_char;
+ XtVaSetValues(Display_data_text,XmNcursorPosition,
+ pos,NULL);
+ }
+ // Now clear counters so they're always the number of lines to
+ // add or characters to delete *since last display*
+ nlinesadd=0;
+ ncharsdel=0;
+ } else { // there is stuff left over after we delete old stuff
+ if (ncharsdel) { // we have something to delete off the top
+ //fprintf(stderr," Must delete %d characters\n",ncharsdel);
+ XmTextReplace(Display_data_text,0,ncharsdel,"");
+ ncharsdel=0;
+ }
+ if (nlinesadd) { // and there's new stuff to add at end
+ //fprintf(stderr," Must add %d lines\n",nlinesadd);
+ last_char=XmTextGetLastPosition(Display_data_text);
+ for (i=(next_line+MAX_PACKET_DATA_DISPLAY
+ -nlinesadd)%MAX_PACKET_DATA_DISPLAY;
+ i != next_line;
+ i=(i+1)%MAX_PACKET_DATA_DISPLAY) {
+ //fprintf(stderr," Adding data from line %d\n",i);
+ XmTextReplace(Display_data_text,last_char,last_char,
+ packet_data_string[i]);
+ last_char=XmTextGetLastPosition(Display_data_text);
+ pos=last_char;
+ XtVaSetValues(Display_data_text,XmNcursorPosition,
+ pos,NULL);
+ }
+ nlinesadd=0;
+ }
+ }
+ }
+ }
+ redraw_on_new_packet_data=0;
+}
+
+
+
+
+
+//
+// Note that the length of "line" can be up to MAX_DEVICE_BUFFER,
+// which is currently set to 4096.
+//
+// data_port == -1 for x_spider port, normal interface number
+// otherwise. -99 should give a "**" display, meaning all ports.
+//
+void packet_data_add(char *from, char *line, int data_port) {
+ int offset;
+ char prefix[3] = "";
+ int local_tnc_interface = 0;
+ int network_interface = 0;
+
+
+ if (data_port == -1) { // x_spider port (server port)
+ xastir_snprintf(prefix,sizeof(prefix),"sp");
+ }
+ else if (data_port == -99){ // All ports, used for transmitting
+ xastir_snprintf(prefix,sizeof(prefix),"**");
+ }
+ else {
+ xastir_snprintf(prefix,sizeof(prefix),"%2d",data_port);
+ }
+
+ offset=0;
+ if (line[0]==(char)3)
+ offset=1;
+
+ // Check whether local or network interface
+ if (is_local_interface(data_port) || data_port == -99)
+ local_tnc_interface++;
+
+ if (is_network_interface(data_port) || data_port == -1 || data_port == -99)
+ network_interface++;
+
+ // Compare Display_packet_data_type against the port type
+ // associated with data_port to determine whether or not to
+ // display it.
+ //
+ switch (Display_packet_data_type) {
+
+ case 2: // Display NET data only
+ if (!network_interface)
+ return; // Don't display it
+ break;
+
+ case 1: // Display TNC data only
+ if (!local_tnc_interface)
+ return; // Don't display it
+ break;
+
+ case 0: // Display both TNC and NET data
+ default:
+ break;
+ }
+
+// fprintf(stderr,"display:%d, port:%d\n",
+// Display_packet_data_type,
+// data_port);
+
+ // Check the Capabilities toggle to see if we only want to show
+ // Station Capability packets
+ if (show_only_station_capabilities) {
+ if (!strstr(line, ":<") // Not a capabilities response
+ && !( strstr(line, my_callsign) && strstr(line, "?IGATE?") ) ) {
+ // Not a capabilities response and not my ?IGATE?
+ // request, don't display the packet.
+ return;
+ }
+ }
+
+ // Check the "Mine Only" toggle to see if we only want to show
+ // our own packets
+ if (Display_packet_data_mine_only) {
+ char short_call[MAX_CALLSIGN];
+ char *p;
+
+ xastir_snprintf(short_call,
+ sizeof(short_call),
+ "%s",
+ my_callsign);
+ if ( (p = index(short_call,'-')) ) {
+ *p = '\0'; // Terminate it
+ }
+
+ if (!strstr(line, short_call))
+ return;
+ }
+
+ redraw_on_new_packet_data++;
+
+ // Now save the packet in the history:
+ xastir_snprintf(packet_data_string[next_line],MAX_LINE_SIZE,"%s:%s-> %s\n",
+ prefix,from,line+offset);
+ next_line = (next_line+1)%MAX_PACKET_DATA_DISPLAY;
+ nlinesadd++;
+ if (first_line == -1) {
+ first_line = 0;
+ }
+ else if (first_line == next_line) {
+ ncharsdel += strlen(packet_data_string[first_line]);
+ first_line = (first_line + 1) %MAX_PACKET_DATA_DISPLAY;
+ }
+
+}
+
+
+
+
+
+/*
+ * Decode Mic-E encoded data
+ */
+int decode_Mic_E(char *call_sign,char *path,char *info,char from,int port,int third_party) {
+ int ii;
+ int offset;
+ unsigned char s_b1;
+ unsigned char s_b2;
+ unsigned char s_b3;
+ unsigned char s_b4;
+ unsigned char s_b5;
+ unsigned char s_b6;
+ unsigned char s_b7;
+ int north,west,long_offset;
+ int d,m,h;
+ char temp[MAX_LINE_SIZE+1]; // Note: Must be big in case we get long concatenated packets
+ char new_info[MAX_LINE_SIZE+1]; // Note: Must be big in case we get long concatenated packets
+ int course;
+ int speed;
+ int msg1,msg2,msg3,msg;
+ int info_size;
+ long alt;
+ int msgtyp;
+ char rig_type[10];
+ int ok;
+
+ // MIC-E Data Format [APRS Reference, chapter 10]
+
+ // todo: error check
+ // drop wrong positions from receive errors...
+ // drop 0N/0E position (p.25)
+
+ /* First 7 bytes of info[] contains the APRS data type ID, */
+ /* longitude, speed, course. */
+ /* The 6-byte destination field of path[] contains latitude, */
+ /* N/S bit, E/W bit, longitude offset, message code. */
+ /*
+
+ MIC-E Destination Field Format:
+ -------------------------------
+ Ar1DDDD0 Br1DDDD0 Cr1MMMM0 Nr1MMMM0 Lr1HHHH0 Wr1HHHH0 CrrSSID0
+ D = Latitude Degrees.
+ M = Latitude Minutes.
+ H = Latitude Hundredths of Minutes.
+ ABC = Message bits, complemented.
+ N = N/S latitude bit (N=1).
+ W = E/W longitude bit (W=1).
+ L = 100's of longitude degrees (L=1 means add 100 degrees to longitude
+ in the Info field).
+ C = Command/Response flag (see AX.25 specification).
+ r = reserved for future use (currently 0).
+
+ */
+ /****************************************************************************
+ * I still don't handle: *
+ * Custom message bits *
+ * SSID special routing *
+ * Beta versions of the MIC-E (which use a slightly different format). *
+ * *
+ * DK7IN : lat/long with custom msg works, altitude/course/speed works *
+ *****************************************************************************/
+
+ if (debug_level & 1)
+ fprintf(stderr,"decode_Mic_E: FOUND MIC-E\n");
+
+ // Note that the first MIC-E character was not passed to us, so we're
+ // starting just past it.
+ // Check for valid symbol table character. Should be '/' or '\'
+ // or 0-9, A-Z.
+ //
+ if ( info[7] == '/' // Primary table
+ || info[7] == '\\' // Alternate table
+ || (info[7] >= '0' && info[7] <= '9') // Overlay char
+ || (info[7] >= 'A' && info[7] <= 'Z') ) { // Overlay char
+
+ // We're good, keep going
+
+ }
+ else { // Symbol table or overlay char incorrect
+
+ if (info[6] == '/' || info[6] == '\\') { // Found it back one char in string
+ // Don't print out the full info string here because it
+ // can contain unprintable characters. In fact, we
+ // should check the chars we do print out to make sure
+ // they're printable, else print a space char.
+ if (debug_level & 1) {
+ fprintf(stderr,"decode_Mic_E: Symbol table (%c), symbol (%c) swapped or corrupted packet? Call=%s, Path=%s\n",
+ ((info[7] > 0x1f) && (info[7] < 0x7f)) ? info[7] : ' ',
+ ((info[6] > 0x1f) && (info[6] < 0x7f)) ? info[6] : ' ',
+ call_sign,
+ path);
+ fprintf(stderr,"Returned from data_add, invalid symbol table character: %c\n",info[7]);
+ }
+ }
+
+ return(1); // No good, not MIC-E format or corrupted packet. Return 1
+ // so that it won't get added to the database at all.
+ }
+
+ // Check for valid symbol. Should be between '!' and '~' only.
+ if (info[6] < '!' || info[6] > '~') {
+ if (debug_level & 1)
+ fprintf(stderr,"Returned from data_add, invalid symbol\n");
+
+ return(1); // No good, not MIC-E format or corrupted packet. Return 1
+ // so that it won't get added to the database at all.
+ }
+
+ // Check for minimum MIC-E size.
+ if (strlen(info) < 8) {
+ if (debug_level & 1)
+ fprintf(stderr,"Returned from data_add, packet too short\n");
+
+ return(1); // No good, not MIC-E format or corrupted packet. Return 1
+ // so that it won't get added to the database at all.
+ }
+
+ // Check for 8-bit characters in the first eight slots. Not
+ // allowed per Mic-E chapter of the spec.
+ for (ii = 0; ii < 8; ii++) {
+ if ((unsigned char)info[ii] > 0x7f) {
+ // 8-bit data was found in the lat/long/course/speed
+ // portion. Bad packet. Drop it.
+//fprintf(stderr, "%s: 8-bits found in Mic-E packet initial portion. Dropping it.\n", call_sign);
+ return(1);
+ }
+ }
+
+ // Check whether we have more data. If flag character is 0x1d
+ // (8-bit telemetry flag) then don't do the 8-bit check below.
+ if (strlen(info) > 8) {
+
+ // Check for the 8-bit telemetry flag
+ if ((unsigned char)info[8] == 0x1d) {
+ // 8-bit telemetry found, skip the check loop below
+ }
+ else { // 8-bit telemetry flag was not found. Check that
+ // we only have 7-bit characters through the rest of
+ // the packet.
+
+ for (ii = 8; ii < (int)strlen(info); ii++) {
+
+ if ((unsigned char)info[ii] > 0x7f) {
+ // 8-bit data was found. Bad packet. Drop it.
+//fprintf(stderr, "%s: 8-bits found in Mic-E packet final portion (not 8-bit telemetry). Dropping it.\n", call_sign);
+ return(1);
+ }
+ }
+ }
+ }
+
+ //fprintf(stderr,"Path1:%s\n",path);
+
+ msg1 = (int)( ((unsigned char)path[0] & 0x40) >>4 );
+ msg2 = (int)( ((unsigned char)path[1] & 0x40) >>5 );
+ msg3 = (int)( ((unsigned char)path[2] & 0x40) >>6 );
+ msg = msg1 | msg2 | msg3; // We now have the complemented message number in one variable
+ msg = msg ^ 0x07; // And this is now the normal message number
+ msgtyp = 0; // DK7IN: Std message, I have to add custom msg decoding
+
+ //fprintf(stderr,"Msg: %d\n",msg);
+
+ /* Snag the latitude from the destination field, Assume TAPR-2 */
+ /* DK7IN: latitude now works with custom message */
+ s_b1 = (unsigned char)( (path[0] & 0x0f) + (char)0x2f );
+ //fprintf(stderr,"path0:%c\ts_b1:%c\n",path[0],s_b1);
+ if (path[0] & 0x10) // A-J
+ s_b1 += (unsigned char)1;
+
+ if (s_b1 > (unsigned char)0x39) // K,L,Z
+ s_b1 = (unsigned char)0x20;
+ //fprintf(stderr,"s_b1:%c\n",s_b1);
+
+ s_b2 = (unsigned char)( (path[1] & 0x0f) + (char)0x2f );
+ //fprintf(stderr,"path1:%c\ts_b2:%c\n",path[1],s_b2);
+ if (path[1] & 0x10) // A-J
+ s_b2 += (unsigned char)1;
+
+ if (s_b2 > (unsigned char)0x39) // K,L,Z
+ s_b2 = (unsigned char)0x20;
+ //fprintf(stderr,"s_b2:%c\n",s_b2);
+
+ s_b3 = (unsigned char)( (path[2] & (char)0x0f) + (char)0x2f );
+ //fprintf(stderr,"path2:%c\ts_b3:%c\n",path[2],s_b3);
+ if (path[2] & 0x10) // A-J
+ s_b3 += (unsigned char)1;
+
+ if (s_b3 > (unsigned char)0x39) // K,L,Z
+ s_b3 = (unsigned char)0x20;
+ //fprintf(stderr,"s_b3:%c\n",s_b3);
+
+ s_b4 = (unsigned char)( (path[3] & 0x0f) + (char)0x30 );
+ //fprintf(stderr,"path3:%c\ts_b4:%c\n",path[3],s_b4);
+ if (s_b4 > (unsigned char)0x39) // L,Z
+ s_b4 = (unsigned char)0x20;
+ //fprintf(stderr,"s_b4:%c\n",s_b4);
+
+ s_b5 = (unsigned char)( (path[4] & 0x0f) + (char)0x30 );
+ //fprintf(stderr,"path4:%c\ts_b5:%c\n",path[4],s_b5);
+ if (s_b5 > (unsigned char)0x39) // L,Z
+ s_b5 = (unsigned char)0x20;
+ //fprintf(stderr,"s_b5:%c\n",s_b5);
+
+ s_b6 = (unsigned char)( (path[5] & 0x0f) + (char)0x30 );
+ //fprintf(stderr,"path5:%c\ts_b6:%c\n",path[5],s_b6);
+ if (s_b6 > (unsigned char)0x39) // L,Z
+ s_b6 = (unsigned char)0x20;
+ //fprintf(stderr,"s_b6:%c\n",s_b6);
+
+ s_b7 = (unsigned char)path[6]; // SSID, not used here
+ //fprintf(stderr,"path6:%c\ts_b7:%c\n",path[6],s_b7);
+
+ //fprintf(stderr,"\n");
+
+ // Special tests for 'L' due to position ambiguity deviances in
+ // the APRS spec table. 'L' has the 0x40 bit set, but they
+ // chose in the spec to have that represent position ambiguity
+ // _without_ the North/West/Long Offset bit being set. Yuk!
+ // Please also note that the tapr.org Mic-E document (not the
+ // APRS spec) has the state of the bit wrong in columns 2 and 3
+ // of their table. Reverse them.
+ if (path[3] == 'L')
+ north = 0;
+ else
+ north = (int)((path[3] & 0x40) == (char)0x40); // N/S Lat Indicator
+
+ if (path[4] == 'L')
+ long_offset = 0;
+ else
+ long_offset = (int)((path[4] & 0x40) == (char)0x40); // Longitude Offset
+
+ if (path[5] == 'L')
+ west = 0;
+ else
+ west = (int)((path[5] & 0x40) == (char)0x40); // W/E Long Indicator
+
+ //fprintf(stderr,"north:%c->%d\tlat:%c->%d\twest:%c->%d\n",path[3],north,path[4],long_offset,path[5],west);
+
+ /* Put the latitude string into the temp variable */
+ xastir_snprintf(temp, sizeof(temp), "%c%c%c%c.%c%c%c%c",s_b1,s_b2,s_b3,s_b4,s_b5,s_b6,
+ (north ? 'N': 'S'), info[7]); // info[7] = symbol table
+
+ /* Compute degrees longitude */
+ xastir_snprintf(new_info,
+ sizeof(new_info),
+ "%s",
+ temp);
+ d = (int) info[0]-28;
+
+ if (long_offset)
+ d += 100;
+
+ if ((180<=d)&&(d<=189)) // ??
+ d -= 80;
+
+ if ((190<=d)&&(d<=199)) // ??
+ d -= 190;
+
+ /* Compute minutes longitude */
+ m = (int) info[1]-28;
+ if (m>=60)
+ m -= 60;
+
+ /* Compute hundredths of minutes longitude */
+ h = (int) info[2]-28;
+ /* Add the longitude string into the temp variable */
+ xastir_snprintf(temp, sizeof(temp), "%03d%02d.%02d%c%c",d,m,h,(west ? 'W': 'E'), info[6]);
+ strncat(new_info,
+ temp,
+ sizeof(new_info) - 1 - strlen(new_info));
+
+ /* Compute speed in knots */
+ speed = (int)( ( info[3] - (char)28 ) * (char)10 );
+ speed += ( (int)( (info[4] - (char)28) / (char)10) );
+ if (speed >= 800)
+ speed -= 800; // in knots
+
+ /* Compute course */
+ course = (int)( ( ( (info[4] - (char)28) % 10) * (char)100) + (info[5] - (char)28) );
+ if (course >= 400)
+ course -= 400;
+
+ /* ???
+ fprintf(stderr,"info[4]-28 mod 10 - 4 = %d\n",( ( (int)info[4]) - 28) % 10 - 4);
+ fprintf(stderr,"info[5]-28 = %d\n", ( (int)info[5]) - 28 );
+ */
+ xastir_snprintf(temp, sizeof(temp), "%03d/%03d",course,speed);
+ strncat(new_info,
+ temp,
+ sizeof(new_info) - 1 - strlen(new_info));
+ offset = 8; // start of rest of info
+
+ /* search for rig type in Mic-E data */
+ rig_type[0] = '\0';
+ if (info[offset] != '\0' && (info[offset] == '>' || info[offset] == ']')) {
+ /* detected type code: > TH-D7 ] TM-D700 */
+ if (info[offset] == '>')
+ xastir_snprintf(rig_type,
+ sizeof(rig_type),
+ " TH-D7");
+ else
+ xastir_snprintf(rig_type,
+ sizeof(rig_type),
+ " TM-D700");
+
+ offset++;
+ }
+
+ info_size = (int)strlen(info);
+ /* search for compressed altitude in Mic-E data */ // {
+ if (info_size >= offset+4 && info[offset+3] == '}') { // {
+ /* detected altitude ___} */
+ alt = ((((long)info[offset] - (long)33) * (long)91 +(long)info[offset+1] - (long)33) * (long)91
+ + (long)info[offset+2] - (long)33) - 10000; // altitude in meters
+ alt /= 0.3048; // altitude in feet, as in normal APRS
+
+ //32808 is -10000 meters, or 10 km (deepest ocean), which is as low as a MIC-E
+ //packet may go. Upper limit is mostly a guess.
+ if ( (alt > 500000) || (alt < -32809) ) { // Altitude is whacko. Skip it.
+ if (debug_level & 1)
+ fprintf(stderr,"decode_Mic_E: Altitude is whacko: %ld feet, skipping altitude...\n", alt);
+ offset += 4;
+ }
+ else { // Altitude is ok
+ xastir_snprintf(temp, sizeof(temp), " /A=%06ld",alt);
+ offset += 4;
+ strncat(new_info,
+ temp,
+ sizeof(new_info) - 1 - strlen(new_info));
+ }
+ }
+
+ /* start of comment */
+ if (strlen(rig_type) > 0) {
+ xastir_snprintf(temp, sizeof(temp), "%s",rig_type);
+ strncat(new_info,
+ temp,
+ sizeof(new_info) - 1 - strlen(new_info));
+ }
+
+ strncat(new_info,
+ " Mic-E ",
+ sizeof(new_info) - 1 - strlen(new_info));
+ if (msgtyp == 0) {
+ switch (msg) {
+ case 1:
+ strncat(new_info,
+ "Enroute",
+ sizeof(new_info) - 1 - strlen(new_info));
+ break;
+
+ case 2:
+ strncat(new_info,
+ "In Service",
+ sizeof(new_info) - 1 - strlen(new_info));
+ break;
+
+ case 3:
+ strncat(new_info,
+ "Returning",
+ sizeof(new_info) - 1 - strlen(new_info));
+ break;
+
+ case 4:
+ strncat(new_info,
+ "Committed",
+ sizeof(new_info) - 1 - strlen(new_info));
+ break;
+
+ case 5:
+ strncat(new_info,
+ "Special",
+ sizeof(new_info) - 1 - strlen(new_info));
+ break;
+
+ case 6:
+ strncat(new_info,
+ "Priority",
+ sizeof(new_info) - 1 - strlen(new_info));
+ break;
+
+ case 7:
+ strncat(new_info,
+ "Emergency",
+ sizeof(new_info) - 1 - strlen(new_info));
+
+ // Do a popup to alert the operator to this
+ // condition. Make sure we haven't popped up an
+ // emergency message for this station within the
+ // last 30 minutes. If we pop these up constantly
+ // it gets quite annoying.
+// EMERGENCY
+
+ if (emergency_distance_check) {
+ double distance;
+ char course_deg[5];
+
+
+ distance = distance_from_my_station(call_sign, course_deg);
+
+// Because of the distance check we have to receive a valid position
+// from the station BEFORE we process the EMERGENCY portion and
+// check distance, doing the popups. We need to figure out a way to
+// throw the packet back into the queue if it was an emergency
+// packet so that we process these packets twice each. That way
+// only one packet from the emergency station is required to
+// generate the popups.
+
+ if (distance == 0.0) {
+ process_emergency_packet_again++;
+ }
+
+ // Check whether the station is near enough to
+ // us to require that we alert on the packet.
+ //
+ // This may be slightly controversial, but if we
+ // don't know WHERE a station is, we can't help
+ // much in an emergency, can we? The
+ // zero-distance check helps in the case where
+ // we haven't yet or never get a position packet
+ // for a station. As soon as we have a position
+ // and it is within a reasonable range, we do
+ // our emergency popups.
+ //
+ if ( distance != 0.0 && (float)distance <= emergency_range ) {
+
+ if ( (strncmp(call_sign, last_emergency_callsign, strlen(call_sign)) != 0)
+ || ((last_emergency_time + 60*30) < sec_now()) ) {
+
+ char temp[50];
+ char temp2[150];
+ char temp3[300];
+ char timestring[101];
+
+ // Callsign is different or enough time has
+ // passed
+
+ last_emergency_time = sec_now();
+ xastir_snprintf(last_emergency_callsign,
+ sizeof(last_emergency_callsign),
+ "%s",
+ call_sign);
+
+ // Bring up the Find Station dialog so that the
+ // operator can go to the location quickly
+ xastir_snprintf(locate_station_call,
+ sizeof(locate_station_call),
+ "%s",
+ call_sign);
+
+ Locate_station( (Widget)NULL, (XtPointer)NULL, (XtPointer)1 );
+
+ // Bring up another dialog with the
+ // callsign plus distance/bearing to the
+ // station.
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%0.1f",
+ distance);
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ langcode("WPUPSTI022"),
+ temp,
+ course_deg);
+ get_timestamp(timestring);
+ xastir_snprintf(temp3,
+ sizeof(temp3),
+ "%s %s",
+ timestring,
+ temp2);
+ popup_message_always(call_sign, temp3);
+ }
+ }
+ }
+ break;
+
+ default:
+ strncat(new_info,
+ "Off Duty",
+ sizeof(new_info) - 1 - strlen(new_info));
+ }
+ }
+ else {
+ xastir_snprintf(temp, sizeof(temp), "Custom%d",msg);
+ strncat(new_info,
+ temp,
+ sizeof(new_info) - 1 - strlen(new_info));
+ }
+
+ if (info[offset] != '\0') {
+ /* Append the rest of the message to the expanded MIC-E message */
+ for (ii=offset; ii<info_size; ii++)
+ temp[ii-offset] = info[ii];
+
+ temp[info_size-offset] = '\0';
+ strncat(new_info,
+ " ",
+ sizeof(new_info) - 1 - strlen(new_info));
+ strncat(new_info,
+ temp,
+ sizeof(new_info) - 1 - strlen(new_info));
+ }
+
+ if (debug_level & 1) {
+ fprintf(stderr,"decode_Mic_E: Done decoding MIC-E\n");
+ fprintf(stderr,"APRS_MICE, %s, %s, %s, %d, %d, NULL, %d\n",call_sign,path,new_info,from,port,third_party);
+ // type: APRS_MICE,
+ // callsign: N0EST-9,
+ // path: TTPQ9P,W0MXW-1,WIDE,N0QK-1*,
+ // new_info: 4401.90N/09228.79W>278/007 /A=-05685 TM-D700 Mic-E Off Duty N0EST ,
+ // from: 70,
+ // port: -1,
+ // NULL,
+ // third_party: 0
+ }
+
+ // We don't transmit Mic-E protocol from Xastir, so we know it's
+ // not our station's packets or our object/item packets,
+ // therefore the last two parameters here are both zero.
+ //
+ ok = data_add(APRS_MICE,call_sign,path,new_info,from,port,NULL,third_party, 0, 0);
+
+ if (debug_level & 1)
+ fprintf(stderr,"Returned from data_add, end of function\n");
+
+ return(ok);
+} // End of decode_Mic_E()
+
+
+
+
+
+/*
+ * Directed Station Query (query to my station) [APRS Reference, chapter 15]
+ */
+int process_directed_query(char *call,char *path,char *message,char from) {
+ DataRow *p_station;
+ char from_call[MAX_CALLSIGN+1];
+ char temp[100];
+ int ok = 0;
+
+
+ if (debug_level & 1)
+ fprintf(stderr,"process_directed_query: %s\n",message);
+
+ // Check for proper usage of the APRSD query
+ if (!ok && strncmp(message,"APRSD",5) == 0 && from != 'F') { // stations heard direct
+ pad_callsign(from_call,call);
+ xastir_snprintf(temp, sizeof(temp), ":%s:Directs=",from_call);
+ p_station = n_first;
+ while (p_station != NULL) {
+ if ((p_station->flag & ST_ACTIVE) != 0) { // ignore deleted objects
+ if ( ((p_station->flag & ST_VIATNC) != 0) // test "via TNC" flag
+ && ((p_station->flag & ST_DIRECT) != 0) // And "direct" flag
+ && sec_now() < (p_station->direct_heard + st_direct_timeout) // Within the last hour
+// && !is_my_call(p_station->call_sign,1) ) { // and not me (checks SSID too)
+ && !(is_my_station(p_station)) ) { // and not me (checks SSID too)
+ if (strlen(temp)+strlen(p_station->call_sign) < 65) {
+ strncat(temp,
+ " ",
+ sizeof(temp) - 1 - strlen(temp));
+ strncat(temp,
+ p_station->call_sign,
+ sizeof(temp) - 1 - strlen(temp));
+ }
+ else {
+
+// Nice to return via the reverse path here? No! Better to use the
+// default paths instead of a calculated reverse path.
+
+ transmit_message_data(call,temp,NULL);
+ xastir_snprintf(temp, sizeof(temp),
+ ":%s:Directs=",from_call);
+ strncat(temp,
+ " ",
+ sizeof(temp) - 1 - strlen(temp));
+ strncat(temp,
+ p_station->call_sign,
+ sizeof(temp) - 1 - strlen(temp));
+ }
+ }
+ }
+ p_station = p_station->n_next;
+ }
+
+// Nice to return via the reverse path here? No! Better to use the
+// default paths instead of a calculated reverse path.
+
+ transmit_message_data(call,temp,NULL);
+ ok = 1;
+ }
+ // Check for illegal case for the APRSD query
+ if (!ok && strncasecmp(message,"APRSD",5) == 0 && from != 'F') { // stations heard direct
+ fprintf(stderr,
+ "%s just queried us with an illegal query: %s\n",
+ call,
+ message),
+ fprintf(stderr,
+ "Consider sending a message, asking them to follow the spec\n");
+ ok = 1;
+ }
+
+
+// NOT IMPLEMENTED YET
+ // Check for proper usage of the APRSH query
+ if (!ok && strncmp(message,"APRSH",5)==0) {
+ ok = 1;
+ }
+ // Check for illegal case for the APRSH query
+ if (!ok && strncasecmp(message,"APRSH",5)==0) {
+// fprintf(stderr,
+// "%s just queried us with an illegal query: %s\n",
+// call,
+// message),
+// fprintf(stderr,
+// "Consider sending a message, asking them to follow the spec\n");
+ ok = 1;
+ }
+
+
+// NOT IMPLEMENTED YET
+ // Check for proper usage of the APRSM query
+ if (!ok && strncmp(message,"APRSM",5)==0) {
+ ok = 1;
+ }
+ // Check for illegal case for the APRSM query
+ if (!ok && strncasecmp(message,"APRSM",5)==0) {
+// fprintf(stderr,
+// "%s just queried us with an illegal query: %s\n",
+// call,
+// message),
+// fprintf(stderr,
+// "Consider sending a message, asking them to follow the spec\n");
+ ok = 1;
+ }
+
+
+// NOT IMPLEMENTED YET
+ // Check for proper usage of the APRSO query
+ if (!ok && strncmp(message,"APRSO",5)==0) {
+ ok = 1;
+ }
+ // Check for illegal case for the APRSO query
+ if (!ok && strncasecmp(message,"APRSO",5)==0) {
+// fprintf(stderr,
+// "%s just queried us with an illegal query: %s\n",
+// call,
+// message),
+// fprintf(stderr,
+// "Consider sending a message, asking them to follow the spec\n");
+ ok = 1;
+ }
+
+
+ // Check for proper usage of the APRSP query
+ if (!ok && strncmp(message,"APRSP",5) == 0 && from != 'F') {
+ transmit_now = 1; //send position
+ ok = 1;
+ }
+ // Check for illegal case for the APRSP query
+ if (!ok && strncasecmp(message,"APRSP",5) == 0 && from != 'F') {
+ fprintf(stderr,
+ "%s just queried us with an illegal query: %s\n",
+ call,
+ message),
+ fprintf(stderr,
+ "Consider sending a message, asking them to follow the spec\n");
+ ok = 1;
+ }
+
+
+// NOT IMPLEMENTED YET
+ // Check for proper usage of the APRSS query
+ if (!ok && strncmp(message,"APRSS",5)==0) {
+ ok = 1;
+ }
+ // Check for illegal case for the APRSS query
+ if (!ok && strncasecmp(message,"APRSS",5)==0) {
+// fprintf(stderr,
+// "%s just queried us with an illegal query: %s\n",
+// call,
+// message),
+// fprintf(stderr,
+// "Consider sending a message, asking them to follow the spec\n");
+ ok = 1;
+ }
+
+
+ // Check for proper usage of the APRST/PING? queries
+ if (!ok && (strncmp(message,"APRST",5)==0
+ || strncmp(message,"PING?",5)==0) && from != 'F') {
+ pad_callsign(from_call,call);
+ xastir_snprintf(temp, sizeof(temp), ":%s:PATH= %s>%s",from_call,call,path); // correct format ?????
+
+// Nice to return via the reverse path here? No! Better to use the
+// default paths instead of a calculated reverse path.
+
+ transmit_message_data(call,temp,NULL);
+ ok = 1;
+ }
+
+
+ // Check for illegal case for the APRST/PING? queries
+ if (!ok && (strncasecmp(message,"APRST",5)==0
+ || strncasecmp(message,"PING?",5)==0) && from != 'F') {
+ fprintf(stderr,
+ "%s just queried us with an illegal query: %s\n",
+ call,
+ message),
+ fprintf(stderr,
+ "Consider sending a message, asking them to follow the spec\n");
+ ok = 1;
+ }
+
+
+ // Check for proper usage of the VER query (either case?)
+ if (!ok && strncasecmp("VER",message,3) == 0 && from != 'F') { // not in Reference !???
+ pad_callsign(from_call,call);
+ xastir_snprintf(temp, sizeof(temp), ":%s:%s",from_call,VERSIONLABEL);
+
+// Nice to return via the reverse path here? No! Better to use the
+// default paths instead of a calculated reverse path.
+
+ transmit_message_data(call,temp,NULL);
+ if (debug_level & 1)
+ fprintf(stderr,"Sent to %s:%s\n",call,temp);
+ ok = 1;
+ }
+
+ return(ok);
+}
+
+
+
+
+
+/*
+ * Station Capabilities, Queries and Responses [APRS Reference, chapter 15]
+ */
+//
+// According to Bob Bruninga we should wait a random time between 0
+// and 120 seconds before responding to a general query. We use the
+// delayed-ack mechanism to add this randomness.
+//
+// NOTE: We may end up sending these to RF when the query came in
+// over the internet. We should check that.
+//
+int process_query( /*@unused@*/ char *call_sign, /*@unused@*/ char *path,char *message,char from,int port, /*@unused@*/ int third_party) {
+ char temp[100];
+ int ok = 0;
+ float randomize;
+
+
+ // Generate a random number between 0.0 and 1.0
+ randomize = rand() / (float)RAND_MAX;
+
+ // Convert to between 0 and 120 seconds
+ randomize = randomize * 120.0;
+//fprintf(stderr,"Randomize:%f\n", randomize);
+
+
+
+ // Check for proper usage of the ?APRS? query
+//
+// NOTE: We need to add support in here for the radius circle as
+// listed in the spec for general queries. Right now we respond to
+// all queries, whether we're inside the circle or not. Spec says
+// this:
+//
+// ?Query?Lat,Long,Radius
+// 1 n 1 n 1 n 1 4 Bytes
+//
+// i.e. ?APRS? 34.02,-117.15,0200
+//
+// Note leading space in latitude as its value is positive.
+// Lat/long are floating point degrees. N/E are positive, indicated
+// by a leading space. S/W are negative. Radius is in miles
+// expressed as a fixed 4-digit number in whole miles. All stations
+// inside the specified circle should respond with a position report
+// and a status report.
+//
+ if (!ok && strncmp(message,"APRS?",5)==0) {
+ //
+ // Initiate a delayed transmit of our own posit.
+ // UpdateTime() uses posit_next_time to decide when to
+ // transmit, so we'll just muck with that.
+ //
+ if ( posit_next_time - sec_now() < randomize ) {
+ // Skip setting it, as we'll transmit soon anyway
+ }
+ else {
+ posit_next_time = (size_t)(sec_now() + randomize);
+ }
+ ok = 1;
+ }
+ // Check for illegal case for the ?APRS? query
+ if (!ok && strncasecmp(message,"APRS?",5)==0) {
+ ok = 1;
+// fprintf(stderr,
+// "%s just queried us with an illegal query: %s\n",
+// call_sign,
+// message),
+// fprintf(stderr,
+// "Consider sending a message, asking them to follow the spec\n");
+ }
+
+
+
+ // Check for proper usage of the ?IGATE? query
+ if (!ok
+ && strncmp(message,"IGATE?",6)==0
+ && port != -1) { // Not from a log file
+
+ if (operate_as_an_igate && from != 'F') {
+ xastir_snprintf(temp, sizeof(temp), "<IGATE,MSG_CNT=%d,LOC_CNT=%d",(int)igate_msgs_tx,stations_types(3));
+
+ // OLD:
+ //output_my_data(temp,port,0,0,0,NULL); // Not igating
+ // NEW:
+ transmit_message_data_delayed("ALL", temp, NULL, (time_t)(sec_now() + randomize) );
+ }
+ ok = 1;
+ }
+ // Check for illegal case for the ?IGATE? query
+ if (!ok
+ && strncasecmp(message,"IGATE?",6)==0
+ && port != -1) { // Not from a log file
+
+ if (operate_as_an_igate && from != 'F') {
+ fprintf(stderr,
+ "%s just queried us with an illegal query: %s\n",
+ call_sign,
+ message),
+ fprintf(stderr,
+ "Consider sending a message, asking them to follow the spec\n");
+ }
+ ok = 1;
+ }
+
+
+
+ // Check for proper usage of the ?WX? query
+ if (!ok && strncmp(message,"WX?",3)==0) {
+
+// NOT IMPLEMENTED YET
+
+// Here we should check whether we are a weather station, and if so,
+// send out a delayed posit/weather string.
+// if (we're a weather_station) {
+// //
+// // Initiate a delayed transmit of our own posit.
+// // UpdateTime() uses posit_next_time to decide when to
+// // transmit, so we'll just muck with that.
+// //
+// if ( posit_next_time - sec_now() < randomize ) {
+// // Skip setting it, as we'll transmit soon anyway
+// }
+// else {
+// posit_next_time = (size_t)(sec_now() + randomize);
+// }
+// }
+ ok = 1;
+ }
+ // Check for illegal case for the ?WX? query
+ if (!ok && strncasecmp(message,"WX?",3)==0) {
+ ok = 1;
+// fprintf(stderr,
+// "%s just queried us with an illegal query: %s\n",
+// call_sign,
+// message),
+// fprintf(stderr,
+// "Consider sending a message, asking them to follow the spec\n");
+ }
+
+ return(ok);
+}
+
+
+
+
+
+/*
+ * Status Reports [APRS Reference, chapter 16]
+ */
+int process_status( /*@unused@*/ char *call_sign, /*@unused@*/ char *path, /*@unused@*/ char *message, /*@unused@*/ char from, /*@unused@*/ int port, /*@unused@*/ int third_party) {
+
+// popup_message(langcode("POPEM00018"),message); // What is it ???
+ return(1);
+}
+
+
+
+
+
+/*
+ * shorten_path
+ *
+ * What to do with this one?
+ * APW250,TCPIP*,ZZ2RMV-5*
+ * We currently convert it to:
+ * APW250
+ * It's a packet that went across the 'net, then to RF, then back to
+ * the 'net. We should probably drop it altogether?
+ *
+ * Gets rid of unused digipeater fields (after the asterisk) and the
+ * TCPIP field if it exists. Used for creating the third-party
+ * headers for igating purposes. Note that for TRACEn-N and WIDEn-N
+ * digi's, it's impossible to tell via the '*' character whether that
+ * part of the path was used, but we can tell by the difference of
+ * 'n' and 'N'. If they're different, then that part of the path was
+ * used. If it has counted down to just a TRACE or a WIDE (or TRACE7
+ * or WIDE5), then it should have a '*' after it like normal.
+ */
+void shorten_path( char *path, char *short_path, int short_path_size ) {
+ int i,j,found_trace_wide,found_asterisk;
+ char *ptr;
+
+
+ if ( (path != NULL) && (strlen(path) >= 1) ) {
+
+ xastir_snprintf(short_path,
+ short_path_size,
+ "%s",
+ path);
+
+ // Terminate the path at the end of the last used digipeater
+ // This is trickier than it seems due to WIDEn-N and TRACEn-N
+ // digipeaters.
+
+ // Take a run through the entire path string looking for unused
+ // TRACE/WIDE paths.
+ for ( i = (strlen(path)-1); i >= 0; i-- ) { // Count backwards
+ // If we find ",WIDE3-3" or ",TRACE7-7" (numbers match),
+ // jam '\0' in at the comma. These are unused digipeaters.
+ if ( (strstr(&short_path[i],",WIDE7-7") != NULL)
+ || (strstr(&short_path[i],",WIDE6-6") != NULL)
+ || (strstr(&short_path[i],",WIDE5-5") != NULL)
+ || (strstr(&short_path[i],",WIDE4-4") != NULL)
+ || (strstr(&short_path[i],",WIDE3-3") != NULL)
+ || (strstr(&short_path[i],",WIDE2-2") != NULL)
+ || (strstr(&short_path[i],",WIDE1-1") != NULL)
+ || (strstr(&short_path[i],",TRACE7-7") != NULL)
+ || (strstr(&short_path[i],",TRACE6-6") != NULL)
+ || (strstr(&short_path[i],",TRACE5-5") != NULL)
+ || (strstr(&short_path[i],",TRACE4-4") != NULL)
+ || (strstr(&short_path[i],",TRACE3-3") != NULL)
+ || (strstr(&short_path[i],",TRACE2-2") != NULL)
+ || (strstr(&short_path[i],",TRACE1-1") != NULL) ) {
+ short_path[i] = '\0';
+ }
+ }
+
+
+ // Take another run through short_string looking for used
+ // TRACE/WIDE paths. Also look for '*' characters and flag
+ // if we see any. If no '*' found, but a used TRACE/WIDE
+ // path found, chop the path after the used TRACE/WIDE. This
+ // is to modify paths like this:
+ // APRS,PY1AYH-15*,RELAY,WIDE3-2,PY1EU-1
+ // to this:
+ // APRS,PY1AYH-15*,RELAY,WIDE3-2
+ j = 0;
+ found_trace_wide = 0;
+ found_asterisk = 0;
+ for ( i = (strlen(short_path)-1); i >= 0; i-- ) { // Count backwards
+
+ if (short_path[i] == '*')
+ found_asterisk++;
+
+ // Search for TRACEn/WIDEn. If found (N!=n is guaranteed
+ // by the previous loop) set the lower increment for the next
+ // loop just past the last TRACEn/WIDEn found. The used part
+ // of the TRACEn/WIDEn will still remain in our shorter path.
+ if ( (strstr(&short_path[i],"WIDE7") != NULL)
+ || (strstr(&short_path[i],"WIDE6") != NULL)
+ || (strstr(&short_path[i],"WIDE5") != NULL)
+ || (strstr(&short_path[i],"WIDE4") != NULL)
+ || (strstr(&short_path[i],"WIDE3") != NULL)
+ || (strstr(&short_path[i],"WIDE2") != NULL)
+ || (strstr(&short_path[i],"WIDE1") != NULL)
+ || (strstr(&short_path[i],"TRACE7") != NULL)
+ || (strstr(&short_path[i],"TRACE6") != NULL)
+ || (strstr(&short_path[i],"TRACE5") != NULL)
+ || (strstr(&short_path[i],"TRACE4") != NULL)
+ || (strstr(&short_path[i],"TRACE3") != NULL)
+ || (strstr(&short_path[i],"TRACE2") != NULL)
+ || (strstr(&short_path[i],"TRACE1") != NULL) ) {
+ j = i;
+ found_trace_wide++;
+ break; // We only want to find the right-most one.
+ // We've found a used digipeater!
+ }
+ }
+
+
+ // Chop off any unused digi's after a used TRACEn/WIDEn
+ if (!found_asterisk && found_trace_wide) {
+ for ( i = (strlen(short_path)-1); i >= j; i-- ) { // Count backwards
+ if (short_path[i] == ',') {
+ short_path[i] = '\0'; // Terminate the string
+ }
+ }
+ }
+
+
+ // At this point, if we found a TRACEn or WIDEn, the "j"
+ // variable will be non-zero. If not then it'll be zero and
+ // we'll run completely through the shorter path converting
+ // '*' characters to '\0'.
+ found_asterisk = 0;
+ for ( i = (strlen(short_path)-1); i >= j; i-- ) { // Count backwards
+ if (short_path[i] == '*') {
+ short_path[i] = '\0'; // Terminate the string
+ found_asterisk++;
+ }
+ }
+
+
+ // Check for TCPIP or TCPXX as the last digipeater. If present,
+ // remove them. TCPXX means that the packet came from an unregistered
+ // user, and those packets will be rejected in igate.c before they're
+ // sent to RF anyway. igate.c will check for its presence in path,
+ // not in short_path, so we're ok here to get rid of it in short_path.
+ if (strlen(short_path) >= 5) { // Get rid of "TCPIP" & "TCPXX"
+
+ ptr = &short_path[strlen(short_path) - 5];
+ if ( (strcasecmp(ptr,"TCPIP") == 0)
+ || (strcasecmp(ptr,"TCPXX") == 0) ) {
+ *ptr = '\0';
+ }
+ if ( (strlen(short_path) >= 1) // Get rid of possible ending comma
+ && (short_path[strlen(short_path) - 1] == ',') ) {
+ short_path[strlen(short_path) - 1] = '\0';
+ }
+ }
+
+
+ // We might have a string with zero used digipeaters. In this case
+ // we will have no '*' characters and no WIDEn-N/TRACEn-N digis.
+ // Get rid of everything except the destination call. These packets
+ // must have been heard directly by an igate station.
+ if (!found_trace_wide && !found_asterisk) {
+ for ( i = (strlen(short_path)-1); i >= j; i-- ) { // Count backwards
+ if (short_path[i] == ',') {
+ short_path[i] = '\0'; // Terminate the string
+ }
+ }
+ }
+
+
+ // The final step: Remove any asterisks in the path.
+ // We'll insert our own on the way out to RF again.
+ for ( i = 0; i < (int)(strlen(short_path) - 1); i++ ) {
+ if (short_path[i] == '*') {
+ for (j = i; j <= (int)(strlen(short_path) - 1); j++ ) {
+ short_path[j] = short_path[j+1]; // Shift left by one char
+ }
+ }
+ }
+
+
+ }
+ else {
+ short_path[0] = '\0'; // We were passed an empty string or a NULL.
+ }
+
+ if (debug_level & 1) {
+ fprintf(stderr,"%s\n",path);
+ fprintf(stderr,"%s\n\n",short_path);
+ }
+}
+
+
+
+
+
+// TODO:
+// *) Use the valid_call(call) function here?
+// *) Add a "Tactical Call Disable" togglebutton. Default =
+// disabled.
+// *) Send out TAC assignments as they are created via an APRS
+// message?
+// *) Add "Send All Tactical Calls" menu entry. Another entry to
+// send them out repetitively?
+// *) Create a public/private distinction for TAC calls?
+// *) Add public/private toggle to the Tactical Callsign box, and
+// have it send an APRS Message if public when changed?
+// *) Add a method to list the public/private TAC calls we currently
+// have assigned.
+// *) Create an easier method to remove one or more TAC calls?
+// Currently we have to send a blank assignment ("we7u-12=").
+// *) Log TAC calls and date/time for each assignment, including
+// NULL assignments.
+//
+// From Bob:
+// *) Range filter - won't accept tactical assignments without a
+// position within X miles of source.
+// *) Change filter - won't accept changes from others for locally
+// created tac assignment. Kind of implies two tables - local
+// and remote Button/menu item to send local, or send all - each
+// a manual operation, as we discussed.
+// *) Perhaps repeat messages fewer times if sent to TACTICAL than
+// for a normal message? This is so that more than one
+// controller can manipulate them without having to wait for the
+// timeout of the first message.
+//
+//
+int fill_in_tactical_callsign(char *call, char *tactical_call) {
+ DataRow *p_station;
+
+
+ // Convert callsign to upper-case
+ (void)to_upper(call);
+
+ // Get rid of white space on either end
+ (void)remove_leading_spaces(call);
+ (void)remove_trailing_spaces(call);
+ (void)remove_leading_spaces(tactical_call);
+ (void)remove_trailing_spaces(tactical_call);
+
+ // Find the station record.
+ if (!search_station_name(&p_station, call, 1)) {
+ // Station not found.
+
+ // Add the TAC call to the tactical hash for future
+ // application to a callsign via the log_tactical_call()
+ // function call below...
+ }
+
+ else { // Found it! Assign the new tactical call. Some code
+ // here borrowed from db.c:Change_tactical_change_data()
+
+ // Check for blank incoming tactical call.
+ if (tactical_call[0] == '\0') {
+ // Blank tactical call string. Free space and null
+ // pointer.
+ free(p_station->tactical_call_sign);
+ p_station->tactical_call_sign = NULL;
+ }
+
+ else { // Non-blank incoming tactical call string
+
+ if (p_station->tactical_call_sign == NULL) {
+ // Malloc some memory to hold it.
+ p_station->tactical_call_sign = (char *)malloc(MAX_TACTICAL_CALL+1);
+ }
+ if (p_station->tactical_call_sign == NULL) {
+ fprintf(stderr,
+ "Couldn't malloc space for tactical callsign\n");
+ return -1;
+ }
+
+ xastir_snprintf(p_station->tactical_call_sign,
+ MAX_TACTICAL_CALL+1,
+ "%s",
+ tactical_call);
+ }
+ redraw_on_new_data = 2; // redraw now
+ }
+
+ // Log the change in the tactical_calls.log file. Also adds it
+ // to the tactical callsign hash.
+ log_tactical_call(call, tactical_call);
+
+ return(0);
+}
+
+
+
+
+
+//
+// Assign tactical callsigns based on messages sent to "TACTICAL"
+//
+// *) To set your own tactical callsign and send it to others,
+// send an APRS message to "TACTICAL" with your callsign in
+// the message text.
+//
+// *) To send multiple tactical calls to others, send an APRS
+// message to "TACTICAL" and enter:
+// "CALL1=TAC1;CALL2=TAC2;CALL3=TAC3" in the message text.
+//
+// '=' or ';' characters can not be in the TAC callsign.
+//
+int tactical_data_add(char *call, char *message, char from) {
+ char *temp_ptr;
+
+
+ if (strlen(message) <= 1) {
+ return -1;
+ }
+
+ // Check whether we're dealing with one or multiple tactical
+ // callsign assignments. Look for a '=' character.
+ temp_ptr = strrchr(message,'=');
+
+ if (temp_ptr == NULL) {
+ // No '=' character was found. We're dealing with a single
+ // tactical assignment for the "call" callsign. Extract the
+ // tactical call and assign it to the station data record
+ // for the station.
+
+ if (debug_level & 2)
+ fprintf(stderr, "One tactical assignment.\n");
+
+ fill_in_tactical_callsign(call, message);
+ }
+
+ else { // We're dealing with multiple tactical assignments.
+ int ii;
+ const int max = 50;
+ char *Substring[max];
+ char *Call_Tac[2];
+
+
+ if (debug_level & 2)
+ fprintf(stderr, "Possibly multiple tactical assignments.\n");
+
+ // Split the message first on ';' characters to get the
+ // callsign=tactical pairs separated from each other.
+ split_string( message, Substring, max, ';' );
+
+ // Check whether we found more than one pair.
+ if (Substring[0] == NULL) { // No ';' chars were found.
+ // We might still have a single tactical definition in
+ // the message. Assign "message" to Substring[0] for
+ // further processing below.
+
+ if (debug_level & 2)
+ fprintf(stderr, "No semicolons found.\n");
+
+ Substring[0] = message;
+ }
+
+ ii = 0;
+
+ while (Substring[ii] != NULL) {
+ // Split each string and process. The results of each
+ // split will be in:
+ // Call_Tac[0] (Callsign)
+ // Call_Tac[1] (Tactical Callsign)
+ //
+ split_string( Substring[ii], Call_Tac, 2, '=' );
+
+ if (Call_Tac[0] != NULL) { // Found '=' char.
+
+ if (debug_level & 2) {
+ fprintf(stderr, "Found a tactical pair: %s->%s\n",
+ Call_Tac[0],
+ Call_Tac[1]);
+ }
+
+ fill_in_tactical_callsign(Call_Tac[0], Call_Tac[1]);
+ }
+ ii++;
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+
+//
+// Messages, Bulletins and Announcements [APRS Reference, chapter 14]
+//
+//
+// Returns 1 if successful
+// 0 if not successful
+//
+int decode_message(char *call,char *path,char *message,char from,int port,int third_party) {
+ char *temp_ptr;
+ char ipacket_message[300];
+ char message_plus_acks[MAX_MESSAGE_LENGTH + 10];
+ char from_call[MAX_CALLSIGN+1];
+ char ack[20];
+ int ok, len;
+ char addr[9+1];
+ char addr9[9+1];
+ char msg_id[5+1];
+ char orig_msg_id[5+1];
+ char ack_string[6];
+ int done;
+ int reply_ack = 0;
+ int to_my_call = 0;
+ int to_my_base_call = 0;
+ int from_my_call = 0;
+
+
+ // :xxxxxxxxx:____0-67____ message printable, except '|', '~', '{'
+ // :TACTICAL :text Tactical definition for sending station
+ // :TACTICAL :CALL1=TAC1;CALL2=TAC2 Tactical definitions for multiple stations
+ // :BLNn :____0-67____ general bulletin printable, except '|', '~'
+ // :BLNnxxxxx:____0-67____ + Group Bulletin
+ // :BLNX :____0-67____ Announcement
+ // :NWS-xxxxx:____0-67____ NWS Service Bulletin
+ // :NWS_xxxxx:____0-67____ NWS Service Bulletin
+ // :BOM-xxxxx:____0-67____ BOM Service Bulletin (AU Wx)
+ // :BOM_xxxxx:____0-67____ BOM Service Bulletin (AU Wx)
+ // :xxxxxxxxx:ackn1-5n + ack
+ // :xxxxxxxxx:rejn1-5n + rej
+ // :xxxxxxxxx:____0-67____{n1-5n + message
+ // :NTS....
+ // 01234567890123456
+ // 01234567890123456 old
+ // we get message with already extracted data ID
+
+ if (debug_level & 1)
+ fprintf(stderr,"decode_message: start\n");
+
+ if (debug_level & 1) {
+ if ( (message != NULL) && (strlen(message) > (MAX_MESSAGE_LENGTH + 10) ) ) {
+ //
+ // Overly long message. Throw it away. We're done.
+ //
+ fprintf(stderr,"decode_message: LONG message. Dumping it.\n");
+ return(0);
+ }
+ }
+
+ if (is_my_call(call, 1) ) { // Check SSID also
+ from_my_call++;
+ }
+
+ ack_string[0] = '\0'; // Clear out the Reply/Ack result string
+
+ len = (int)strlen(message);
+ ok = (int)(len > 9 && message[9] == ':');
+
+ if (ok) {
+
+ substr(addr9,message,9); // extract addressee
+ xastir_snprintf(addr,
+ sizeof(addr),
+ "%s",
+ addr9);
+ (void)remove_trailing_spaces(addr);
+
+ if (is_my_call(addr,1)) { // Check includes SSID
+ to_my_call++;
+ }
+
+ if (is_my_call(addr,0)) { // Check ignores SSID. We use
+ // this to catch messages to some
+ // of our other SSID's
+ to_my_base_call++;
+ }
+
+ message = message + 10; // pointer to message text
+
+ // Save the message text and the acks/reply-acks before we
+ // extract the acks below.
+ xastir_snprintf(message_plus_acks,
+ sizeof(message_plus_acks),
+ "%s",
+ message);
+
+ temp_ptr = strrchr(message,'{'); // look for message ID after
+ //*last* { in message.
+ msg_id[0] = '\0';
+ if (temp_ptr != NULL) {
+ substr(msg_id,temp_ptr+1,5); // extract message ID, could be non-digit
+ temp_ptr[0] = '\0'; // adjust message end (chops off message ID)
+ }
+
+ // Save the original msg_id away.
+ xastir_snprintf(orig_msg_id,
+ sizeof(orig_msg_id),
+ "%s",
+ msg_id);
+
+ // Check for Reply/Ack protocol in msg_id, which looks like
+ // this: "{XX}BB", where XX is the sequence number for the
+ // message, and BB is the ack for the previous message from
+ // my station. I've also seen this from APRS+: "{XX}B", so
+ // perhaps this is also possible "{X}B" or "{X}BB}". We can
+ // also get auto-reply responses from APRS+ that just have
+ // "}X" or "}XX" at the end. We decode those as well.
+ //
+
+ temp_ptr = strstr(msg_id,"}"); // look for Reply Ack in msg_id
+
+ if (temp_ptr != NULL) { // Found Reply/Ack protocol!
+
+ reply_ack++;
+
+// if ( (debug_level & 1) && (is_my_call(addr,1)) ) { // Check SSID also
+ if ( (debug_level & 1) && to_my_call) { // Check SSID also
+ fprintf(stderr,"1Found Reply/Ack:%s\n",message);
+ fprintf(stderr,"Orig_msg_id:%s\t",msg_id);
+ }
+
+// Put this code into the UI message area as well (if applicable).
+
+ // Separate out the extra ack so that we can deal with
+ // it properly.
+ xastir_snprintf(ack_string,
+ sizeof(ack_string),
+ "%s",
+ temp_ptr+1); // After the '}' character!
+
+ // Terminate it here so that rest of decode works
+ // properly. We can get duplicate messages
+ // otherwise.
+ //
+// Note that we modify msg_id here. Use orig_msg_id if we need the
+// unmodified version (full REPLY-ACK version) later.
+ //
+ temp_ptr[0] = '\0'; // adjust msg_id end
+
+// if ( (debug_level & 1) && (is_my_call(addr,1)) ) { // Check SSID also
+ if ( (debug_level & 1) && to_my_call) { // Check SSID also
+ fprintf(stderr,"New_msg_id:%s\tReply_ack:%s\n\n",
+ msg_id,ack_string);
+ }
+
+ }
+ else { // Look for Reply Ack in message without sequence
+ // number
+ temp_ptr = strstr(message,"}");
+
+ if (temp_ptr != NULL) {
+ int yy = 0;
+
+
+ reply_ack++;
+
+// if ( (debug_level & 1) && (is_my_call(addr,1)) ) { // Check SSID also
+ if ( (debug_level & 1) && to_my_call) { // Check SSID also
+ fprintf(stderr,"2Found Reply/Ack:%s\n",message);
+ }
+
+// Put this code into the UI message area as well (if applicable).
+ xastir_snprintf(ack_string,
+ sizeof(ack_string),
+ "%s",
+ temp_ptr+1); // After the '}' character!
+
+ ack_string[yy] = '\0'; // Terminate the string
+
+ // Terminate it here so that rest of decode works
+ // properly. We can get duplicate messages
+ // otherwise.
+ temp_ptr[0] = '\0'; // adjust message end
+
+// if ( (debug_level & 1) && (is_my_call(addr,1)) ) { // Check SSID also
+ if ( (debug_level & 1) && to_my_call) { // Check SSID also
+ fprintf(stderr,"Reply_ack:%s\n\n",ack_string);
+ }
+ }
+ }
+
+ done = 0;
+ }
+ else {
+ done = 1; // fall through...
+ }
+
+ if (debug_level & 1)
+ fprintf(stderr,"1\n");
+ len = (int)strlen(message);
+ //--------------------------------------------------------------------------
+ if (!done && len > 3 && strncmp(message,"ack",3) == 0) { // ACK
+
+ // Received an ACK packet. Note that these can carry the
+ // REPLY-ACK protocol or a single ACK sequence number plus
+ // perhaps an extra '}' on the end. They should have one of
+ // these formats:
+ // ack1 Normal ACK
+ // ackY Normal ACK
+ // ack23 Normal ACK
+ // ackfH Normal ACK
+ // ack23{ REPLY-ACK Protocol
+ // ack2Q}3d REPLY-ACK Protocol
+
+ substr(msg_id,message+3,5);
+ // fprintf(stderr,"ACK: %s: |%s| |%s|\n",call,addr,msg_id);
+// if (is_my_call(addr,1)) { // Check SSID also
+ if (to_my_call) { // Check SSID also
+
+ // Note: This function handles REPLY-ACK protocol just
+ // fine, stripping off the 2nd ack if present. It uses
+ // only the first sequence number.
+ clear_acked_message(call,addr,msg_id); // got an ACK for me
+
+ // This one also handles REPLY-ACK protocol just fine.
+ msg_record_ack(call,addr,msg_id,0,0); // Record the ack for this message
+ }
+ else { // ACK is for another station
+ // Now if I have Igate on and I allow to retransmit station data
+ // check if this message is to a person I have heard on my TNC within an X
+ // time frame. If if is a station I heard and all the conditions are ok
+ // spit the ACK out on the TNC -FG
+ if (operate_as_an_igate>1
+ && from==DATA_VIA_NET
+// && !is_my_call(call,1) // Check SSID also
+ && !from_my_call // Check SSID also
+ && port != -1) { // Not from a log file
+ char short_path[100];
+
+//fprintf(stderr,"Igate check o:%d f:%c myc:%s cf:%s ct:%s\n",
+// operate_as_an_igate,
+// from,
+// my_callsign,
+// call,
+// addr);
+ shorten_path(path,short_path,sizeof(short_path));
+
+ // Only send '}' and the ack_string if it's not
+ // empty, else just end the packet with the message
+ // string. This keeps us from appending a '}' when
+ // it's not called for.
+ xastir_snprintf(ipacket_message,
+ sizeof(ipacket_message),
+// "}%s>%s,TCPIP,%s*::%s:%s%s%s",
+ "}%s>%s,TCPIP,%s*::%s:%s",
+
+ call,
+ short_path,
+ my_callsign,
+ addr9,
+// message,
+ message_plus_acks);
+// (ack_string[0] == '\0') ? "" : "}",
+// ack_string);
+
+if (reply_ack) { // For debugging, so we only have reply-ack
+ // messages and acks scrolling across the screen.
+// fprintf(stderr,"Attempting to send ACK to RF: %s\n", ipacket_message);
+}
+
+ output_igate_rf(call,
+ addr,
+ path,
+ ipacket_message,
+ port,
+ third_party,
+ NULL);
+
+ igate_msgs_tx++;
+ }
+ }
+ done = 1;
+ }
+ if (debug_level & 1)
+ fprintf(stderr,"2\n");
+ //--------------------------------------------------------------------------
+ if (!done && len > 3 && strncmp(message,"rej",3) == 0) { // REJ
+
+ substr(msg_id,message+3,5);
+
+// if ( is_my_call(addr,1) ) { // Check SSID also
+ if (to_my_call) { // Check SSID also
+
+ // REJ is for me!
+// fprintf(stderr,"Received a REJ packet from %s: |%s| |%s|\n",call,addr,msg_id);
+
+ // Note: This function handles REPLY-ACK protocol just
+ // fine, stripping off the 2nd ack if present. It uses
+ // only the first sequence number.
+ clear_acked_message(call,addr,msg_id); // got an REJ for me
+
+ // This one also handles REPLY-ACK protocol just fine.
+ msg_record_rej(call,addr,msg_id); // Record the REJ for this message
+ }
+ else { // REJ is for another station
+ /* Now if I have Igate on and I allow to retransmit station data */
+ /* check if this message is to a person I have heard on my TNC within an X */
+ /* time frame. If if is a station I heard and all the conditions are ok */
+ /* spit the REJ out on the TNC */
+ if (operate_as_an_igate>1
+ && from==DATA_VIA_NET
+// && !is_my_call(call,1) // Check SSID also
+ && !from_my_call // Check SSID also
+ && port != -1) { // Not from a log file
+ char short_path[100];
+
+//fprintf(stderr,"Igate check o:%d f:%c myc:%s cf:%s ct:%s\n",
+// operate_as_an_igate,
+// from,
+// my_callsign,
+// call,
+// addr);
+ shorten_path(path,short_path,sizeof(short_path));
+
+ // Only send '}' and the rej_string if it's not
+ // empty, else just end the packet with the message
+ // string. This keeps us from appending a '}' when
+ // it's not called for.
+ xastir_snprintf(ipacket_message,
+ sizeof(ipacket_message),
+// "}%s>%s,TCPIP,%s*::%s:%s%s%s",
+ "}%s>%s,TCPIP,%s*::%s:%s",
+
+ call,
+ short_path,
+ my_callsign,
+ addr9,
+// message,
+ message_plus_acks);
+// (ack_string[0] == '\0') ? "" : "}",
+// ack_string);
+
+if (reply_ack) { // For debugging, so we only have reply-ack
+ // messages and acks scrolling across the screen.
+// fprintf(stderr,"Attempting to send REJ to RF: %s\n", ipacket_message);
+}
+
+ output_igate_rf(call,
+ addr,
+ path,
+ ipacket_message,
+ port,
+ third_party,
+ NULL);
+
+ igate_msgs_tx++;
+ }
+ }
+
+ done = 1;
+ }
+ if (debug_level & 1)
+ fprintf(stderr,"3\n");
+ //--------------------------------------------------------------------------
+ if (!done && strncmp(addr,"TACTICAL",8) == 0) { // Tactical definition
+
+ if (debug_level & 2)
+ fprintf(stderr,"found TACTICAL: |%s| |%s|\n",call,message);
+
+ tactical_data_add(call,message,from);
+ done = 1;
+ }
+ if (debug_level & 1)
+ fprintf(stderr,"TAC\n");
+ //--------------------------------------------------------------------------
+ if (!done && strncmp(addr,"BLN",3) == 0) { // Bulletin
+ // fprintf(stderr,"found BLN: |%s| |%s|\n",addr,message);
+ bulletin_data_add(addr,call,message,"",MESSAGE_BULLETIN,from);
+ done = 1;
+ }
+ if (debug_level & 1)
+ fprintf(stderr,"4\n");
+
+ //--------------------------------------------------------------------------
+// if (!done && strlen(msg_id) > 0 && is_my_call(addr,1)) { // Message for me (including SSID check)
+ if (!done && strlen(msg_id) > 0 && to_my_call) { // Message for me (including SSID check)
+ // with msg_id (sequence number)
+ time_t last_ack_sent;
+ long record;
+
+
+// Remember to put this code into the UI message area as well (if
+// applicable).
+
+ // Check for Reply/Ack
+ if (reply_ack && strlen(ack_string) != 0) { // Have a free-ride ack to deal with
+
+//fprintf(stderr, "reply-ack: clear_acked_message()\n");
+ clear_acked_message(call,addr,ack_string); // got an ACK for me
+
+//fprintf(stderr, "reply-ack: msg_record_ack()\n");
+ msg_record_ack(call,addr,ack_string,0,0); // Record the ack for this message
+ }
+
+ // Save the ack 'cuz we might need it while talking to this
+ // station. We need it to implement Reply/Ack protocol.
+
+// Note that msg_id has already been truncated by this point.
+// orig_msg_id contains the full REPLY-ACK text.
+
+//fprintf(stderr, "store_most_recent_ack()\n");
+ store_most_recent_ack(call,msg_id);
+
+ // fprintf(stderr,"found Msg w line to me: |%s| |%s|\n",message,msg_id);
+ last_ack_sent = msg_data_add(addr,
+ call,
+ message,
+ msg_id,
+ MESSAGE_MESSAGE,
+ from,
+ &record); // id_fixed
+
+ // Here we need to know if it is a new message or an old.
+ // If we've already received it, we don't want to kick off
+ // the alerts or pop up the Send Message dialog again. If
+ // last_ack_sent == (time_t)0, then it is a new message.
+ //
+ if (last_ack_sent == (time_t)0l && record == -1l) { // Msg we've never received before
+
+ new_message_data += 1;
+
+ // Note that the check_popup_window() function will
+ // re-create a Send Message dialog if one doesn't exist
+ // for this QSO. Only call it for the first message
+ // line or the first ack, not for any repeats.
+ //
+//fprintf(stderr,"***check_popup_window 1\n");
+ (void)check_popup_window(call, 2); // Calls update_messages()
+
+ //update_messages(1); // Force an update
+
+ if (sound_play_new_message)
+ play_sound(sound_command,sound_new_message);
+
+#ifdef HAVE_FESTIVAL
+/* I re-use ipacket_message as my string buffer */
+ if (festival_speak_new_message_alert) {
+ xastir_snprintf(ipacket_message,
+ sizeof(ipacket_message),
+ "You have a new message from %s.",
+ call);
+ SayText(ipacket_message);
+ }
+ if (festival_speak_new_message_body) {
+ xastir_snprintf(ipacket_message,
+ sizeof(ipacket_message),
+ " %s",
+ message);
+ SayText(ipacket_message);
+ }
+
+#endif // HAVE_FESTIVAL
+
+ }
+
+ // Try to only send an ack out once per 30 seconds at the
+ // fastest.
+//WE7U
+// Does this 30-second check work?
+ //
+ if ( from != 'F' // Not from a log file
+ && (last_ack_sent != (time_t)-1l) // Not an error
+ && (last_ack_sent + 30 ) < sec_now()
+ && !satellite_ack_mode // Disable separate ack's for satellite work
+ && port != -1 ) { // Not from a log file
+
+ char path[MAX_LINE_SIZE+1];
+
+
+ //fprintf(stderr,"Sending ack: %ld %ld %ld\n",last_ack_sent,sec_now(),record);
+
+ // Update the last_ack_sent field for the message
+ msg_update_ack_stamp(record);
+
+ pad_callsign(from_call,call); /* ack the message */
+
+
+ // Attempt to snag a custom path out of the Send Message
+ // dialog, if set. If not set, path will contain '\0';
+ get_send_message_path(call, path, MAX_LINE_SIZE+1);
+//fprintf(stderr,"Path: %s\n", path);
+
+
+ // In this case we want to send orig_msg_id back, not
+ // the (possibly) truncated msg_id. This is per Bob B's
+ // Reply/Ack spec, sent to xastir-dev on Nov 14, 2001.
+ xastir_snprintf(ack, sizeof(ack), ":%s:ack%s",from_call,orig_msg_id);
+
+//WE7U
+// Need to figure out the reverse path for this one instead of
+// passing a NULL for the path? Probably not, as auto-calculation
+// of paths isn't a good idea.
+//
+// What we need to do here is check whether we have a custom path
+// set for this QSO. If so, pass that path along as the transmit
+// path. messages.h:Message_Window struct has the send_message_path
+// variable in it. If a Message_Window still exists for this QSO
+// then we can snag the user-entered path from there. If the struct
+// has already been destroyed then we have nowhere to snag the
+// custom path from and have to rely on the default paths in each
+// interface properties dialog instead. Then again, we _could_ snag
+// the path out of the last received message in the message database
+// for that case. Might be better to disable the Close button, or
+// warn the user that the custom path will be lost if they close the
+// Send Message dialog.
+
+
+ // Send out the immediate ACK
+ if (path[0] == '\0')
+ transmit_message_data(call,ack,NULL);
+ else
+ transmit_message_data(call,ack,path);
+
+
+ if (record != -1l) { // Msg we've received before
+
+ // It's a message that we've received before,
+ // consider sending an extra ACK in about 30 seconds
+ // to try to get it to the remote station. Perhaps
+ // another one in 60 seconds as well.
+
+// fprintf(stderr,
+// "We've received this message before.\n");
+// fprintf(stderr,
+// "Sending a couple of delayed ack's.\n");
+
+ if (path[0] == '\0') {
+ transmit_message_data_delayed(call,ack,NULL,sec_now()+30);
+ transmit_message_data_delayed(call,ack,NULL,sec_now()+60);
+ transmit_message_data_delayed(call,ack,NULL,sec_now()+120);
+ }
+ else {
+ transmit_message_data_delayed(call,ack,path,sec_now()+30);
+ transmit_message_data_delayed(call,ack,path,sec_now()+60);
+ transmit_message_data_delayed(call,ack,path,sec_now()+120);
+ }
+ }
+
+
+ if (auto_reply == 1) {
+
+ xastir_snprintf(ipacket_message,
+ sizeof(ipacket_message), "AA:%s", auto_reply_message);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Send autoreply to <%s> from <%s> :%s\n",
+ call, my_callsign, ipacket_message);
+
+// if (!is_my_call(call,1)) // Check SSID also
+ if (!from_my_call) // Check SSID also
+ output_message(my_callsign, call, ipacket_message, "");
+ }
+ }
+
+else {
+//fprintf(stderr,"Skipping ack: %ld %ld\n",last_ack_sent,sec_now());
+}
+
+ done = 1;
+ }
+ if (debug_level & 1)
+ fprintf(stderr,"5a\n");
+
+ //--------------------------------------------------------------------------
+ if (!done && strlen(msg_id) == 0 && to_my_call) { // Message for me (including SSID check)
+ // but without message-ID.
+ // These should appear in a Send Message dialog and should
+ // NOT get ack'ed. Kenwood radios send this message type as
+ // an auto-answer or a buffer-full message. They look
+ // something like:
+ //
+ // :WE7U-13 :Not at keyboard.
+ //
+
+ time_t last_ack_sent;
+ long record;
+
+
+ if (len > 2
+ && message[0] == '?'
+ && port != -1 // Not from a log file
+ && to_my_call) { // directed query (check SSID also)
+ // Smallest query known is "?WX".
+ if (debug_level & 1)
+ fprintf(stderr,"Received a directed query\n");
+ done = process_directed_query(call,path,message+1,from);
+ }
+
+ // fprintf(stderr,"found Msg w line to me: |%s| |%s|\n",message,msg_id);
+ last_ack_sent = msg_data_add(addr,
+ call,
+ message,
+ msg_id,
+ MESSAGE_MESSAGE,
+ from,
+ &record); // id_fixed
+
+ // Here we need to know if it is a new message or an old.
+ // If we've already received it, we don't want to kick off
+ // the alerts or pop up the Send Message dialog again. If
+ // last_ack_sent == (time_t)0, then it is a new message.
+ //
+ if (last_ack_sent == (time_t)0l && record == -1l) { // Msg we've never received before
+
+ new_message_data += 1;
+
+ // Note that the check_popup_window() function will
+ // re-create a Send Message dialog if one doesn't exist
+ // for this QSO. Only call it for the first message
+ // line or the first ack, not for any repeats.
+ //
+//fprintf(stderr,"***check_popup_window 1\n");
+ (void)check_popup_window(call, 2); // Calls update_messages()
+
+ //update_messages(1); // Force an update
+
+ if (sound_play_new_message)
+ play_sound(sound_command,sound_new_message);
+
+#ifdef HAVE_FESTIVAL
+/* I re-use ipacket_message as my string buffer */
+ if (festival_speak_new_message_alert) {
+ xastir_snprintf(ipacket_message,
+ sizeof(ipacket_message),
+ "You have a new message from %s.",
+ call);
+ SayText(ipacket_message);
+ }
+ if (festival_speak_new_message_body) {
+ xastir_snprintf(ipacket_message,
+ sizeof(ipacket_message),
+ " %s",
+ message);
+ SayText(ipacket_message);
+ }
+
+#endif // HAVE_FESTIVAL
+
+ }
+
+ // Update the last_ack_sent field for the message, even
+ // though we won't be sending an ack in response.
+ msg_update_ack_stamp(record);
+
+
+//fprintf(stderr,"Received msg for me w/o ack\n");
+
+ done = 1;
+ }
+ if (debug_level & 1)
+ fprintf(stderr,"5b\n");
+
+ //--------------------------------------------------------------------------
+ if (!done
+ && ( (strncmp(addr,"NWS-",4) == 0) // NWS weather alert
+ || (strncmp(addr,"NWS_",4) == 0) // NWS weather alert compressed
+ || (strncmp(addr,"BOM-",4) == 0) // BOM (AU) weather alert
+ || (strncmp(addr,"BOM_",4) == 0) ) ) { // BOM (AU) weather alert compressed
+
+ // could have sort of line number
+ //fprintf(stderr,"found NWS: |%s| |%s| |%s|\n",addr,message,msg_id);
+
+ (void)alert_data_add(addr,
+ call,
+ message,
+ msg_id,
+ MESSAGE_NWS,
+ from);
+
+ done = 1;
+ if (operate_as_an_igate>1
+ && from==DATA_VIA_NET
+// && !is_my_call(call,1) // Check SSID also
+ && !from_my_call // Check SSID also
+ && port != -1) { // Not from a log file
+ char short_path[100];
+
+ shorten_path(path,short_path,sizeof(short_path));
+
+ xastir_snprintf(ipacket_message,
+ sizeof(ipacket_message),
+ "}%s>%s,TCPIP,%s*::%s:%s",
+ call,
+ short_path,
+ my_callsign,
+ addr9,
+ message);
+
+ output_nws_igate_rf(call,
+ path,
+ ipacket_message,
+ port,
+ third_party);
+ }
+ }
+ if (debug_level & 1)
+ fprintf(stderr,"6a\n");
+ //--------------------------------------------------------------------------
+ if (!done && strncmp(addr,"SKY",3) == 0) { // NWS weather alert additional info
+
+ // could have sort of line number
+ //fprintf(stderr,"found SKY: |%s| |%s| |%s|\n",addr,message,msg_id);
+
+/*
+ (void)alert_data_add(addr,
+ call,
+ message,
+ msg_id,
+ MESSAGE_NWS,
+ from);
+*/
+
+// We don't wish to record these in memory. They cause an infinite
+// loop in the current code and a massive memory leak.
+return(1); // Tell the calling program that the packet was ok so
+ // that it doesn't add it with data_add() itself!
+
+
+ done = 1;
+ if (operate_as_an_igate>1
+ && from==DATA_VIA_NET
+// && !is_my_call(call,1) // Check SSID also
+ && !from_my_call // Check SSID also
+ && port != -1) { // Not from a log file
+ char short_path[100];
+
+ shorten_path(path,short_path,sizeof(short_path));
+
+ xastir_snprintf(ipacket_message,
+ sizeof(ipacket_message),
+ "}%s>%s,TCPIP,%s*::%s:%s",
+ call,
+ short_path,
+ my_callsign,
+ addr9,
+ message);
+
+ output_nws_igate_rf(call,
+ path,
+ ipacket_message,
+ port,
+ third_party);
+ }
+ }
+ if (debug_level & 1)
+ fprintf(stderr,"6b\n");
+ //--------------------------------------------------------------------------
+ if (!done && strlen(msg_id) > 0) { // Other message with linenumber. This
+ // is either a message for someone else
+ // or a message for another one of my
+ // SSID's.
+ long record_out;
+ time_t last_ack_sent;
+ char message_plus_note[MAX_MESSAGE_LENGTH + 30];
+
+
+ if (debug_level & 2)
+ fprintf(stderr,"found Msg w/line: |%s| |%s| |%s|\n",
+ addr,
+ message,
+ orig_msg_id);
+
+ if (to_my_base_call && !from_my_call) {
+ // Special case: We saw a message w/msg_id that was to
+ // one of our other SSID's, but it was not from
+ // ourselves. That last bit (!from_my_call) is
+ // important in the case where we're working an event
+ // with several stations using the same callsign.
+ //
+ // Store as if it came to my callsign, with a zeroed-out
+ // msg_id so we can't try to ack it. We also need some
+ // other indication in the "Send Message" dialog as to
+ // what's happening. Perhaps add the original callsign
+ // to the message itself in a note at the start?
+ //
+ xastir_snprintf(message_plus_note,
+ sizeof(message_plus_note),
+ "(Sent to:%s) %s",
+ addr,
+ message);
+ last_ack_sent = msg_data_add(my_callsign,
+ call,
+ message_plus_note,
+ "",
+ MESSAGE_MESSAGE,
+ from,
+ &record_out);
+ }
+ else { // Normal case, messaging between other people
+ last_ack_sent = msg_data_add(addr,
+ call,
+ message,
+ msg_id,
+ MESSAGE_MESSAGE,
+ from,
+ &record_out);
+ }
+
+ new_message_data += look_for_open_group_data(addr);
+
+ // Note that the check_popup_window() function will
+ // re-create a Send Message dialog if one doesn't exist for
+ // this QSO. Only call it for the first message line or the
+ // first ack, not for any repeats.
+ //
+ if (last_ack_sent == (time_t)0l && record_out == -1l) { // Msg we've never received before
+//fprintf(stderr,"***check_popup_window 2\n");
+
+ // Callsign check here also checks SSID for exact match
+// if ((is_my_call(call,1) && check_popup_window(addr, 2) != -1)
+// if ((from_my_call && check_popup_window(addr, 2) != -1)
+// We need to do an SSID-non-specific check here so that we can pick
+// up messages intended for other stations of ours.
+// if ((to_my_base_call && check_popup_window(addr, 2) != -1)
+ if ((to_my_base_call && check_popup_window(call, 2) != -1)
+ || check_popup_window(call, 0) != -1
+ || check_popup_window(addr, 1) != -1) {
+//fprintf(stderr,"Matches my base call\n");
+ update_messages(1); // Force an update
+ }
+ }
+
+ /* Now if I have Igate on and I allow to retransmit station data */
+ /* check if this message is to a person I have heard on my TNC within an X */
+ /* time frame. If if is a station I heard and all the conditions are ok */
+ /* spit the message out on the TNC -FG */
+ if (operate_as_an_igate>1
+ && last_ack_sent != (time_t)-1l
+ && from==DATA_VIA_NET
+// && !is_my_call(call,1) // Check SSID also
+ && !from_my_call // Check SSID also
+// && !is_my_call(addr,1) // Check SSID also
+ && !to_my_call // Check SSID also
+ && port != -1) { // Not from a log file
+ char short_path[100];
+
+//fprintf(stderr,"Igate check o:%d f:%c myc:%s cf:%s ct:%s\n",
+// operate_as_an_igate,
+// from,
+// my_callsign,
+// call,
+// addr);
+
+ shorten_path(path,short_path,sizeof(short_path));
+ xastir_snprintf(ipacket_message,
+ sizeof(ipacket_message),
+// "}%s>%s,TCPIP,%s*::%s:%s{%s",
+ "}%s>%s,TCPIP,%s*::%s:%s",
+ call,
+ short_path,
+ my_callsign,
+ addr9,
+ message_plus_acks);
+// message,
+// orig_msg_id);
+
+if (reply_ack) { // For debugging, so we only have reply-ack
+ // messages and acks scrolling across the screen.
+// fprintf(stderr,"Attempting to send message to RF: %s\n", ipacket_message);
+}
+
+ output_igate_rf(call,
+ addr,
+ path,
+ ipacket_message,
+ port,
+ third_party,
+ NULL);
+
+ igate_msgs_tx++;
+ }
+ done = 1;
+ }
+ if (debug_level & 1)
+ fprintf(stderr,"7\n");
+ //--------------------------------------------------------------------------
+
+ if (!done) { // message without line number
+ long record_out;
+ time_t last_ack_sent;
+
+
+ if (debug_level & 4)
+ fprintf(stderr,"found Msg: |%s| |%s|\n",addr,message);
+//found Msg: |WE7U-13| |?APRSD|
+//found Msg: |WE7U-14| |Directs=|
+
+
+ last_ack_sent = msg_data_add(addr,
+ call,
+ message,
+ "",
+ MESSAGE_MESSAGE,
+ from,
+ &record_out);
+
+ new_message_data++; // ??????
+
+ // Note that the check_popup_window() function will
+ // re-create a Send Message dialog if one doesn't exist for
+ // this QSO. Only call it for the first message line or the
+ // first ack, not for any repeats.
+ //
+ if (last_ack_sent == (time_t)0l && record_out == -1l) { // Msg we've never received before
+//fprintf(stderr,"***check_popup_window 3\n");
+ if (check_popup_window(addr, 1) != -1) {
+ //update_messages(1); // Force an update
+ }
+ }
+
+ // Could be response to a query. Popup a messsage.
+
+// Check addr for my_call and !third_party, then check later in the
+// packet for my_call if it is a third_party message? Depends on
+// what the packet looks like by this point.
+ if ( last_ack_sent != (time_t)-1l
+ && (message[0] != '?')
+// && is_my_call(addr,1) ) { // Check SSID also
+ && to_my_call ) { // Check SSID also
+
+ // We no longer wish to have both popups and the Send
+ // Group Message dialogs come up for every query
+ // response, so we use popup_message() here instead of
+ // popup_message_always() so that by default we'll see
+ // the below message in STDERR. If --with-errorpopups
+ // has been configured in, we'll get a popup as well.
+ // Send Group Message dialogs work well for multi-line
+ // query responses, so we'll leave it that way.
+ //
+ popup_message(langcode("POPEM00018"),message);
+
+ // Check for Reply/Ack. APRS+ sends an AA: response back
+ // for auto-reply, with an embedded free-ride Ack.
+ if (strlen(ack_string) != 0) { // Have an extra ack to deal with
+
+ clear_acked_message(call,addr,ack_string); // got an ACK for me
+
+ msg_record_ack(call,addr,ack_string,0,0); // Record the ack for this message
+ }
+ }
+
+ // done = 1;
+ }
+ if (debug_level & 1)
+ fprintf(stderr,"9\n");
+ //--------------------------------------------------------------------------
+
+ if (ok)
+ (void)data_add(STATION_CALL_DATA,
+ call,
+ path,
+ message,
+ from,
+ port,
+ NULL,
+ third_party,
+ 0, // Not a packet from my station
+ 0); // Not my object/item
+
+ if (debug_level & 1)
+ fprintf(stderr,"decode_message: finish\n");
+
+ return(ok);
+}
+
+
+
+
+
+/*
+ * UI-View format messages, not relevant for APRS, format is not specified in APRS Reference
+ *
+ * This function is not currently called anywhere in the code.
+ */
+int decode_UI_message(char *call,char *path,char *message,char from,int port,int third_party) {
+ char *temp_ptr;
+ char from_call[MAX_CALLSIGN+1];
+ char ack[20];
+ char addr[9+1];
+ int ok, len;
+ char msg_id[5+1];
+ int done;
+ int from_my_call = 0;
+ int to_my_call = 0;
+
+
+ if (is_my_call(call, 1) ) { // Check SSID also
+ from_my_call++;
+ }
+
+ // I'm not sure, but I think they use 2 digit line numbers only
+ // extract addr from path
+ substr(addr,path,9);
+ ok = (int)(strlen(addr) > 0);
+ if (ok) {
+ temp_ptr = strstr(addr,","); // look for end of first call
+ if (temp_ptr != NULL)
+ temp_ptr[0] = '\0'; // adjust addr end
+ ok = (int)(strlen(addr) > 0);
+ }
+
+ if (is_my_call(addr, 1) ) { // Check SSID also
+ to_my_call++;
+ }
+
+ len = (int)strlen(message);
+ ok = (int)(len >= 2);
+ if (ok) {
+ temp_ptr = strstr(message,"~"); // look for message ID
+ msg_id[0] = '\0';
+ if (temp_ptr != NULL) {
+ substr(msg_id,temp_ptr+1,2); // extract message ID, could be non-digit
+ temp_ptr[0] = '\0'; // adjust message end
+ }
+ done = 0;
+ }
+ else
+ done = 1; // fall through...
+ len = (int)strlen(message);
+ //--------------------------------------------------------------------------
+ // Callsign check here checks SSID as well
+// if (!done && msg_id[0] != '\0' && is_my_call(addr,1)) { // message for me
+ if (!done && msg_id[0] != '\0' && to_my_call) { // message for me
+ time_t last_ack_sent;
+ long record;
+
+ last_ack_sent = msg_data_add(addr,
+ call,
+ message,
+ msg_id,
+ MESSAGE_MESSAGE,
+ from,
+ &record);
+
+ new_message_data += 1;
+
+ // Note that the check_popup_window() function will
+ // re-create a Send Message dialog if one doesn't exist for
+ // this QSO. Only call it for the first message line or the
+ // first ack, not for any repeats.
+ //
+ if (last_ack_sent == (time_t)0l && record == -1l) { // Msg we've never received before
+//fprintf(stderr,"***check_popup_window 4\n");
+ (void)check_popup_window(call, 2);
+ //update_messages(1); // Force an update
+ }
+
+ if (last_ack_sent != (time_t)-1l) {
+
+ if (sound_play_new_message)
+ play_sound(sound_command,sound_new_message);
+
+ // Only send an ack or autoresponse once per 30 seconds
+ if ( (from != 'F')
+ && ( (last_ack_sent + 30) < sec_now()) ) {
+
+ //fprintf(stderr,"Sending ack: %ld %ld %ld\n",last_ack_sent,sec_now(),record);
+
+ // Record the fact that we're sending an ack now
+ msg_update_ack_stamp(record);
+
+ pad_callsign(from_call,call); /* ack the message */
+ xastir_snprintf(ack, sizeof(ack), ":%s:ack%s",from_call,msg_id);
+
+// Nice to return via the reverse path here? No! Better to use the
+// default paths instead of a calculated reverse path.
+
+ transmit_message_data(call,ack,NULL);
+ if (auto_reply == 1) {
+ char temp[300];
+
+ xastir_snprintf(temp, sizeof(temp), "AA:%s", auto_reply_message);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Send autoreply to <%s> from <%s> :%s\n",
+ call, my_callsign, temp);
+
+// if (!is_my_call(call,1)) // Check SSID also
+ if (!from_my_call) // Check SSID also
+ output_message(my_callsign, call, temp, "");
+ }
+ }
+ }
+ done = 1;
+ }
+ //--------------------------------------------------------------------------
+ if (!done && len == 2 && msg_id[0] == '\0') { // ACK
+ substr(msg_id,message,5);
+// if (is_my_call(addr,1)) { // Check SSID also
+ if (to_my_call) { // Check SSID also
+
+ clear_acked_message(call,addr,msg_id); // got an ACK for me
+
+ msg_record_ack(call,addr,msg_id,0,0); // Record the ack for this message
+ }
+// else { // ACK for other station
+ /* Now if I have Igate on and I allow to retransmit station data */
+ /* check if this message is to a person I have heard on my TNC within an X */
+ /* time frame. If if is a station I heard and all the conditions are ok */
+ /* spit the ACK out on the TNC -FG */
+//// if (operate_as_an_igate>1 && from==DATA_VIA_NET && !is_my_call(call,1)) {
+// if (operate_as_an_igate>1 && from==DATA_VIA_NET && !from_my_call) {
+// char short_path[100];
+ //fprintf(stderr,"Igate check o:%d f:%c myc:%s cf:%s ct:%s\n",operate_as_an_igate,from,my_callsign,call,addr); {
+
+// shorten_path(path,short_path,sizeof(short_path));
+ //sprintf(ipacket_message,"}%s>%s:%s:%s",call,path,addr9,message);
+// sprintf(ipacket_message,"}%s>%s,TCPIP,%s*::%s:%s",call,short_path,my_callsign,addr9,message);
+// output_igate_rf(call,addr,path,ipacket_message,port,third_party,NULL);
+// igate_msgs_tx++;
+// }
+// }
+ done = 1;
+ }
+ //--------------------------------------------------------------------------
+ if (ok) {
+ (void)data_add(STATION_CALL_DATA,
+ call,
+ path,
+ message,
+ from,
+ port,
+ NULL,
+ third_party,
+ 0, // Not a packet from my station
+ 0); // Not my object/item
+ }
+
+ return(ok);
+}
+
+
+
+
+
+/*
+ * Decode APRS Information Field and dispatch it depending on the Data Type ID
+ *
+ * call = Callsign or object/item name string
+ * path = Path string
+ * message = Info field (corrupted already if object/item packet)
+ * origin = Originating callsign if object/item, otherwise NULL
+ * from = DATA_VIA_LOCAL/DATA_VIA_TNC/DATA_VIA_NET/DATA_VIA_FILE
+ * port = Port number
+ * third_party = Set to one if third-party packet
+ * orig_message = Unmodified info field
+ *
+ */
+void decode_info_field(char *call,
+ char *path,
+ char *message,
+ char *origin,
+ char from, int port,
+ int third_party,
+ char *orig_message) {
+
+ char line[MAX_LINE_SIZE+1];
+ int ok_igate_net;
+ int ok_igate_rf;
+ int done, ignore;
+ char data_id;
+ int station_is_mine = 0;
+ int object_is_mine = 0;
+ char user_base_dir[MAX_VALUE];
+
+ /* remember fixed format starts with ! and can be up to 24 chars in the message */ // ???
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: c:%s p:%s m:%s f:%c o:%s\n",call,path,message,from,origin);
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: Past check\n");
+
+ done = 0; // if 1, packet was decoded
+ ignore = 0; // if 1, don't treat undecoded packets as status text
+ ok_igate_net = 0; // if 1, send packet to internet
+ ok_igate_rf = 0; // if 1, igate packet to RF if "from" is in nws-stations.txt
+
+ if ( is_my_call(call, 1) ) {
+ station_is_mine++; // Station is controlled by me
+ }
+
+ if ( (message != NULL) && (strlen(message) > MAX_LINE_SIZE) ) { // Overly long message, throw it away.
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: Overly long message. Throwing it away.\n");
+ done = 1;
+ }
+ else if (message == NULL || strlen(message) == 0) { // we could have an empty message
+ (void)data_add(STATION_CALL_DATA,call,path,NULL,from,port,origin,third_party, station_is_mine, 0);
+ done = 1; // don't report it to internet
+ }
+
+ // special treatment for objects/items.
+ if (!done && origin[0] != '\0') {
+
+ // If station/object/item is owned by me (including SSID)
+ if ( is_my_call(origin, 1) ) {
+ object_is_mine++;
+ }
+
+ if (message[0] == '*') { // set object
+ (void)data_add(APRS_OBJECT,call,path,message+1,from,port,origin,third_party, station_is_mine, object_is_mine);
+ if (strlen(origin) > 0 && strncmp(origin,"INET",4)!=0) {
+ ok_igate_net = 1; // report it to internet
+ }
+ ok_igate_rf = 1;
+ done = 1;
+ }
+
+ else if (message[0] == '!') { // set item
+ (void)data_add(APRS_ITEM,call,path,message+1,from,port,origin,third_party, station_is_mine, object_is_mine);
+ if (strlen(origin) > 0 && strncmp(origin,"INET",4)!=0) {
+ ok_igate_net = 1; // report it to internet
+ }
+ ok_igate_rf = 1;
+ done = 1;
+ }
+
+ else if (message[0] == '_') { // delete object/item
+ DataRow *p_station;
+
+ delete_object(call); // ?? does not vanish from map immediately !!???
+
+ // If object was owned by me but another station is
+ // transmitting it now, write entries into the
+ // object.log file showing that we don't own this object
+ // anymore.
+ p_station = NULL;
+ if (search_station_name(&p_station,call,1)) {
+// if ( (is_my_call(p_station->origin,1)) // If station was owned by me (including SSID)
+// && (!is_my_call(origin,1)) ) { // But isn't now
+ if (is_my_object_item(p_station) // If station was owned by me (including SSID)
+ && (!object_is_mine) ) { // But isn't now
+ disown_object_item(call,origin);
+ }
+ }
+ if (strlen(origin) > 0 && strncmp(origin,"INET",4)!=0) {
+ ok_igate_net = 1; // report it to internet
+ }
+ ok_igate_rf = 1;
+ done = 1;
+ }
+ }
+
+ if (!done) {
+ int rdf_type;
+
+ data_id = message[0]; // look at the APRS Data Type ID (first char in information field)
+ message += 1; // extract data ID from information field
+ ok_igate_net = 1; // as default report packet to internet
+
+ if (debug_level & 1) {
+ if (ok_igate_net)
+ fprintf(stderr,"decode_info_field: ok_igate_net can be read\n");
+ }
+
+ switch (data_id) {
+ case '=': // Position without timestamp (with APRS messaging)
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: = (position w/o timestamp)\n");
+
+//WE7U
+// Need to check for weather info in this packet type as well?
+
+ done = data_add(APRS_MSGCAP,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ ok_igate_rf = done;
+ break;
+
+ case '!': // Position without timestamp (no APRS messaging) or Ultimeter 2000 WX
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: ! (position w/o timestamp or Ultimeter 2000 WX)\n");
+ if (message[0] == '!' && is_xnum_or_dash(message+1,40)) // Ultimeter 2000 WX
+ done = data_add(APRS_WX3,call,path,message+1,from,port,origin,third_party, station_is_mine, 0);
+ else
+ done = data_add(APRS_FIXED,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ ok_igate_rf = done;
+ break;
+
+ case '/': // Position with timestamp (no APRS messaging)
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: / (position w/timestamp)\n");
+
+//WE7U
+// Need weather decode in this section similar to the '@' section
+// below.
+
+ if ((toupper(message[14]) == 'N' || toupper(message[14]) == 'S') &&
+ (toupper(message[24]) == 'W' || toupper(message[24]) == 'E')) { // uncompressed format
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: / (uncompressed position w/timestamp no messaging)\n");
+ if (message[29] == '/') {
+ if (message[33] == 'g' && message[37] == 't')
+ done = data_add(APRS_WX1,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ else
+ done = data_add(APRS_MOBILE,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ }
+ else
+ done = data_add(APRS_DF,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ }
+ else { // compressed format
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: / (compressed position w/timestamp no messaging)\n");
+ if (message[16] >= '!' && message[16] <= 'z') { // csT is speed/course
+ if (message[20] == 'g' && message[24] == 't') // Wx data
+ done = data_add(APRS_WX1,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ else
+ done = data_add(APRS_MOBILE,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ }
+ else
+ done = data_add(APRS_DF,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ }
+// done = data_add(APRS_DOWN,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ ok_igate_rf = done;
+ break;
+
+ case '@': // Position with timestamp (with APRS messaging)
+ // DK7IN: could we need to test the message length first?
+ if ((toupper(message[14]) == 'N' || toupper(message[14]) == 'S') &&
+ (toupper(message[24]) == 'W' || toupper(message[24]) == 'E')) { // uncompressed format
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: @ (uncompressed position w/timestamp)\n");
+ if (message[29] == '/') {
+ if (message[33] == 'g' && message[37] == 't')
+ done = data_add(APRS_WX1,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ else
+ done = data_add(APRS_MOBILE,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ }
+ else
+ done = data_add(APRS_DF,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ }
+ else { // compressed format
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: @ (compressed position w/timestamp)\n");
+ if (message[16] >= '!' && message[16] <= 'z') { // csT is speed/course
+ if (message[20] == 'g' && message[24] == 't') // Wx data
+ done = data_add(APRS_WX1,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ else
+ done = data_add(APRS_MOBILE,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ }
+ else
+ done = data_add(APRS_DF,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ }
+ ok_igate_rf = done;
+ break;
+
+ case '[': // Maidenhead grid locator beacon (obsolete- but used for meteor scatter)
+ done = data_add(APRS_GRID,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ ok_igate_rf = done;
+ break;
+ case 0x27: // Mic-E Old GPS data (or current GPS data in Kenwood TM-D700)
+ case 0x60: // Mic-E Current GPS data (but not used in Kennwood TM-D700)
+ //case 0x1c:// Mic-E Current GPS data (Rev. 0 beta units only)
+ //case 0x1d:// Mic-E Old GPS data (Rev. 0 beta units only)
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: 0x27 or 0x60 (Mic-E)\n");
+ done = decode_Mic_E(call,path,message,from,port,third_party);
+ ok_igate_rf = done;
+ break;
+
+ case '_': // Positionless weather data [APRS Reference, chapter 12]
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: _ (positionless wx data)\n");
+ done = data_add(APRS_WX2,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ ok_igate_rf = done;
+ break;
+
+ case '#': // Peet Bros U-II Weather Station (km/h) [APRS Reference, chapter 12]
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: # (peet bros u-II wx station)\n");
+ if (is_xnum_or_dash(message,13))
+ done = data_add(APRS_WX4,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ ok_igate_rf = done;
+ break;
+
+ case '*': // Peet Bros U-II Weather Station (mph)
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: * (peet bros u-II wx station)\n");
+ if (is_xnum_or_dash(message,13))
+ done = data_add(APRS_WX6,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ ok_igate_rf = done;
+ break;
+
+ case '$': // Raw GPS data or Ultimeter 2000
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: $ (raw gps or ultimeter 2000)\n");
+ if (strncmp("ULTW",message,4) == 0 && is_xnum_or_dash(message+4,44))
+ done = data_add(APRS_WX5,call,path,message+4,from,port,origin,third_party, station_is_mine, 0);
+ else if (strncmp("GPGGA",message,5) == 0)
+ done = data_add(GPS_GGA,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ else if (strncmp("GPRMC",message,5) == 0)
+ done = data_add(GPS_RMC,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ else if (strncmp("GPGLL",message,5) == 0)
+ done = data_add(GPS_GLL,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ else {
+ // handle VTG and WPT too (APRS Ref p.25)
+ }
+ ok_igate_rf = done;
+ break;
+
+ case ':': // Message
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: : (message)\n");
+
+ // Do message logging if that feature is enabled.
+ if (log_message_data && from != DATA_VIA_FILE) {
+ char temp_msg[MAX_MESSAGE_LENGTH+1];
+
+ xastir_snprintf(temp_msg,
+ sizeof(temp_msg),
+ "%s>%s:%s",
+ call,
+ path,
+ orig_message);
+ log_data( get_user_base_dir(LOGFILE_MESSAGE, user_base_dir,
+ sizeof(user_base_dir)),
+ temp_msg );
+ }
+
+//fprintf(stderr,"Calling decode_message\n");
+ done = decode_message(call,path,message,from,port,third_party);
+//fprintf(stderr,"Back from decode_message\n");
+ // there could be messages I should not retransmit to internet... ??? Queries to me...
+ break;
+
+ case '>': // Status [APRS Reference, chapter 16]
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: > (status)\n");
+ done = data_add(APRS_STATUS,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ ok_igate_rf = done;
+ break;
+
+ case '?': // Query
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: ? (query)\n");
+ done = process_query(call,path,message,from,port,third_party);
+ ignore = 1; // don't treat undecoded packets as status text
+ break;
+
+ case 'T': // Telemetry data [APRS Reference, chapter 13]
+ // We treat these as status packets currently.
+ ok_igate_rf = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: T (telem)\n");
+ done = data_add(APRS_STATUS,call,path,message,from,port,origin,third_party, station_is_mine, 0);
+ break;
+
+ case '{': // User-defined APRS packet format //}
+ // We treat these as status packets currently.
+ ok_igate_rf = 1;
+ break;
+
+ case '<': // Station capabilities [APRS Reference, chapter 15]
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: ~,<\n");
+ //
+ // We could tweak the Incoming Data dialog to add
+ // filter togglebuttons. One such toggle could be
+ // "Station Capabilities". We'd then have a usable
+ // dialog for displaying things like ?IGATE?
+ // responses. In this case we wouldn't have to do
+ // anything special with the packet for decoding,
+ // just let it hit the default block below for
+ // putting them into the status field of the record.
+ // One downside is that we'd only be able to catch
+ // new station capability records in that dialog.
+ // The only way to look at past capability records
+ // would be the Station Info dialog for each
+ // station.
+ //
+ //fprintf(stderr,"%10s: %s\n", call, message);
+
+ // Don't set "done" as we want these to appear in
+ // the status text for the record.
+ break;
+
+ case '%': // Agrelo DFJr / MicroFinder Radio Direction Finding
+
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: %%\n");
+
+ // Here is where we'd add a call to an RDF decode
+ // function so that we could display vectors on the
+ // map for each RDF position.
+
+//
+// Agrelo format: "%XXX/Q<cr>"
+//
+// "XXX" is relative bearing to the signal (000-359). Careful here:
+// At least one unit reports in magnetic instead of relative
+// degrees. "000" means no direction info available, 360 means true
+// north.
+//
+// "Q" is bearing quality (0-9). 0 = unsuitable. 9 = manually
+// entered. 1-8 = varying quality with 8 being the best.
+//
+// I've also seen these formats, which may not be Agrelo compatible:
+//
+// "%136.0/9"
+// "%136.0/8/158.0" (That last number is magnetic bearing)
+//
+// These sentences may be sent MULTIPLE times per second, like 20 or
+// more! If we decide to average readings, we'll need to dump our
+// averages and start over if our course changes.
+//
+
+ // Check for Agrelo format:
+ if ( strlen(message) >= 5
+ && is_num_chr(message[0]) // "%136/9"
+ && is_num_chr(message[1])
+ && is_num_chr(message[2])
+ && message[3] == '/'
+ && is_num_chr(message[4]) ) {
+
+ rdf_type = 1;
+
+ fprintf(stderr,
+ "Type 1 RDF packet from call: %s\tBearing: %c%c%c\tQuality: %c\n",
+ call,
+ message[0],
+ message[1],
+ message[2],
+ message[4]);
+
+ }
+
+ // Check for extended formats (not
+ // Agrelo-compatible):
+ else if (strlen(message) >= 13
+ && is_num_chr(message[0]) // "%136.0/8/158.0"
+ && is_num_chr(message[1])
+ && is_num_chr(message[2])
+ && message[3] == '.'
+ && is_num_chr(message[4])
+ && message[5] == '/'
+ && is_num_chr(message[6])
+ && message[7] == '/'
+ && is_num_chr(message[8])
+ && is_num_chr(message[9])
+ && is_num_chr(message[10])
+ && message[11] == '.'
+ && is_num_chr(message[12]) ) {
+
+ rdf_type = 3;
+
+ fprintf(stderr,
+ "Type 3 RDF packet from call: %s\tBearing: %c%c%c%c%c\tQuality: %c\tMag Bearing: %c%c%c%c%c\n",
+ call,
+ message[0],
+ message[1],
+ message[2],
+ message[3],
+ message[4],
+ message[6],
+ message[8],
+ message[9],
+ message[10],
+ message[11],
+ message[12]);
+ }
+
+ // Check for extended formats (not
+ // Agrelo-compatible):
+ else if (strlen(message) >= 7
+ && is_num_chr(message[0]) // "%136.0/9"
+ && is_num_chr(message[1])
+ && is_num_chr(message[2])
+ && message[3] == '.'
+ && is_num_chr(message[4])
+ && message[5] == '/'
+ && is_num_chr(message[6]) ) {
+
+ rdf_type = 2;
+
+ fprintf(stderr,
+ "Type 2 RDF packet from call: %s\tBearing: %c%c%c%c%c\tQuality: %c\n",
+ call,
+ message[0],
+ message[1],
+ message[2],
+ message[3],
+ message[4],
+ message[6]);
+ }
+
+ // Don't set "done" as we want these to appear in
+ // the status text for the record until we get the
+ // full decoding for this type of packet coded up.
+ break;
+
+ case '~': // UI-format messages, not relevant for APRS ("Do not use" in Reference)
+ case ',': // Invalid data or test packets [APRS Reference, chapter 19]
+ case '&': // Reserved -- Map Feature
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: ~,&\n");
+ ignore = 1; // Don't treat undecoded packets as status text
+ break;
+ }
+
+ if (debug_level & 1) {
+ if (done)
+ fprintf(stderr,"decode_info_field: done = 1\n");
+ else
+ fprintf(stderr,"decode_info_field: done = 0\n");
+ if (ok_igate_net)
+ fprintf(stderr,"decode_info_field: ok_igate_net can be read 2\n");
+ }
+
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: done with big switch\n");
+
+ // Add most remaining data to the station record as status
+ // info
+ //
+ if (!done && !ignore) { // Other Packets [APRS Reference, chapter 19]
+ done = data_add(OTHER_DATA,call,path,message-1,from,port,origin,third_party, station_is_mine, 0);
+ ok_igate_net = 0; // don't put data on internet ????
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: done with data_add(OTHER_DATA)\n");
+ }
+
+ if (!done) { // data that we do ignore...
+ //fprintf(stderr,"decode_info_field: not decoding info: Call:%s ID:%c Msg:|%s|\n",call,data_id,message);
+ ok_igate_net = 0; // don't put data on internet
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: done with ignored data\n");
+ }
+ }
+
+ if (third_party)
+ ok_igate_net = 0; // don't put third party traffic on internet
+
+// if (is_my_call(call,1)) // Check SSID as well
+ if (station_is_mine)
+ ok_igate_net = 0; // don't put my data on internet ???
+
+ if (ok_igate_net) {
+
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: ok_igate_net start\n");
+
+ if ( (from == DATA_VIA_TNC) // Came in via a TNC
+ && (strlen(orig_message) > 0) ) { // Not empty
+
+ // Here's where we inject our own callsign like this:
+ // "WE7U-15,I" in order to provide injection ID for our
+ // igate.
+ xastir_snprintf(line,
+ sizeof(line),
+ "%s>%s,%s,I:%s",
+ (strlen(origin)) ? origin : call,
+ path,
+ my_callsign,
+ orig_message);
+
+//fprintf(stderr,"decode_info_field: IGATE>NET %s\n",line);
+ output_igate_net(line, port, third_party);
+ }
+ }
+
+ // Attempt to gate to RF only if the following conditions are
+ // met:
+ //
+ // *) ok_igate_rf flag is set.
+ // *) Not my exact callsign.
+ // *) Packet was from the INET, not local RF
+ // *) The "from" call matches a line in data/nws-stations.txt,
+ // verified by igate.c:check_NWS_stations().
+ //
+ // The output_igate_rf() function will also do some checks on
+ // the packet before allowing it to be igated, including a
+ // dupe-check.
+ //
+ // Callsign check here checks SSID as well
+// if (ok_igate_rf && !is_my_call(call,1) && from == DATA_VIA_NET) {
+ if (ok_igate_rf
+ && !station_is_mine
+ && from == DATA_VIA_NET) {
+
+ char ipacket_message[300];
+ char short_path[100];
+
+ shorten_path(path,short_path,sizeof(short_path));
+
+ xastir_snprintf(ipacket_message,
+ sizeof(ipacket_message),
+ "}%s>%s,TCPIP,%s*:%s",
+ (strlen(origin)) ? origin : call,
+ short_path,
+ my_callsign,
+ orig_message);
+
+ // If origin, pass "call" to output_igate_rf() as the last
+ // parameter. This would be the object/item name.
+ output_igate_rf((strlen(origin)) ? origin : call,
+ (strlen(origin)) ? origin : call,
+ path,
+ ipacket_message,
+ port,
+ third_party,
+ (strlen(origin)) ? call : NULL);
+
+//fprintf(stderr,"decode_info_field: IGATE>RF %s\n",ipacket_message);
+ }
+
+ if (debug_level & 1)
+ fprintf(stderr,"decode_info_field: done\n");
+}
+
+
+
+
+
+/*
+ * Extract object or item data from information field before processing
+ *
+ * Returns 1 if valid object found, else returns 0.
+ *
+ */
+int extract_object(char *call, char **info, char *origin) {
+ int ok, i;
+
+ // Object and Item Reports [APRS Reference, chapter 11]
+ ok = 0;
+ // todo: add station originator to database
+ if ((*info)[0] == ';') { // object
+ // fixed 9 character object name with any printable ASCII character
+ if (strlen((*info)) > 1+9) {
+ substr(call,(*info)+1,9); // extract object name
+ (*info) = (*info) + 10;
+ // Remove leading spaces ? They look bad, but are allowed by the APRS Reference ???
+ (void)remove_trailing_spaces(call);
+ if (valid_object(call)) {
+ // info length is at least 1
+ ok = 1;
+ }
+ }
+ }
+ else if ((*info)[0] == ')') { // item
+ // 3 - 9 character item name with any printable ASCII character
+ if (strlen((*info)) > 1+3) {
+ for (i = 1; i <= 9; i++) {
+ if ((*info)[i] == '!' || (*info)[i] == '_') {
+ call[i-1] = '\0';
+ break;
+ }
+ call[i-1] = (*info)[i];
+ }
+ call[9] = '\0'; // In case we never saw '!' || '_'
+ (*info) = &(*info)[i];
+ // Remove leading spaces ? They look bad, but are allowed by the APRS Reference ???
+ //(void)remove_trailing_spaces(call); // This statement messed up our searching!!! Don't use it!
+ if (valid_object(call)) {
+ // info length is at least 1
+ ok = 1;
+ }
+ }
+ }
+ else {
+ fprintf(stderr,"Not an object, nor an item!!! call=%s, info=%s, origin=%s.\n",
+ call, *info, origin);
+ }
+ return(ok);
+}
+
+
+
+
+
+/*
+ * Extract third-party traffic from information field before processing
+ */
+int extract_third_party(char *call,
+ char *path,
+ int path_size,
+ char **info,
+ char *origin,
+ int origin_size) {
+ int ok;
+ char *p_call;
+ char *p_path;
+
+ p_call = NULL; // to make the compiler happy...
+ p_path = NULL; // to make the compiler happy...
+ ok = 0;
+ if (!is_my_call(call,1)) { // Check SSID also
+ // todo: add reporting station call to database ??
+ // but only if not identical to reported call
+ (*info) = (*info) +1; // strip '}' character
+ p_call = strtok((*info),">"); // extract call
+ if (p_call != NULL) {
+ p_path = strtok(NULL,":"); // extract path
+ if (p_path != NULL) {
+ (*info) = strtok(NULL,""); // rest is information field
+ if ((*info) != NULL) // the above looks dangerous, but works on same string
+ if (strlen(p_path) < 100)
+ ok = 1; // we have found all three components
+ }
+ }
+ }
+
+ if ((debug_level & 1) && !ok)
+ fprintf(stderr,"extract_third_party: invalid format from %s\n",call);
+
+ if (ok) {
+
+ xastir_snprintf(path,
+ path_size,
+ "%s",
+ p_path);
+
+ ok = valid_path(path); // check the path and convert it to TAPR format
+ // Note that valid_path() also removes igate injection identifiers
+
+ if ((debug_level & 1) && !ok) {
+ char filtered_data[MAX_LINE_SIZE + 1];
+
+ xastir_snprintf(filtered_data,
+ sizeof(filtered_data),
+ "%s",
+ path);
+ makePrintable(filtered_data);
+ fprintf(stderr,"extract_third_party: invalid path: %s\n",filtered_data);
+ }
+ }
+
+ if (ok) { // check callsign
+ (void)remove_trailing_asterisk(p_call); // is an asterisk valid here ???
+ if (valid_inet_name(p_call,(*info),origin,origin_size)) { // accept some of the names used in internet
+ // Treat it as object with special origin
+ xastir_snprintf(call,
+ MAX_CALLSIGN+1,
+ "%s",
+ p_call);
+ }
+ else if (valid_call(p_call)) { // accept real AX.25 calls
+ xastir_snprintf(call,
+ MAX_CALLSIGN+1,
+ "%s",
+ p_call);
+ }
+ else {
+ ok = 0;
+ if (debug_level & 1) {
+ char filtered_data[MAX_LINE_SIZE + 1];
+
+ xastir_snprintf(filtered_data,
+ sizeof(filtered_data),
+ "%s",
+ p_call);
+ makePrintable(filtered_data);
+ fprintf(stderr,"extract_third_party: invalid call: %s\n",filtered_data);
+ }
+ }
+ }
+ return(ok);
+}
+
+
+
+
+
+/*
+ * Extract text inserted by TNC X-1J4 from start of info line
+ */
+void extract_TNC_text(char *info) {
+ int i,j,len;
+
+ if (strncasecmp(info,"thenet ",7) == 0) { // 1st match
+ len = strlen(info)-1;
+ for (i=7;i<len;i++) {
+ if (info[i] == ')')
+ break;
+ }
+ len++;
+ if (i>7 && info[i] == ')' && info[i+1] == ' ') { // found
+ i += 2;
+ for (j=0;i<=len;i++,j++) {
+ info[j] = info[i];
+ }
+ }
+ }
+}
+
+
+
+
+
+//WE7U2
+// We feed a raw 7-byte string into this routine. It decodes the
+// callsign-SSID and tells us whether there are more callsigns after
+// this. If the "asterisk" input parameter is nonzero it'll add an
+// asterisk to the callsign if it has been digipeated. This
+// function is called by the decode_ax25_header() function.
+//
+// Inputs: string Raw input string
+// asterisk 1 = add "digipeated" asterisk
+//
+// Outputs: callsign Processed string
+// returned int 1=more callsigns follow, 0=end of address field
+//
+int decode_ax25_address(char *string, char *callsign, int asterisk) {
+ int i,j;
+ char ssid;
+ char t;
+ int more = 0;
+ int digipeated = 0;
+
+ // Shift each of the six callsign characters right one bit to
+ // convert to ASCII. We also get rid of the extra spaces here.
+ j = 0;
+ for (i = 0; i < 6; i++) {
+ t = ((unsigned char)string[i] >> 1) & 0x7f;
+ if (t != ' ') {
+ callsign[j++] = t;
+ }
+ }
+
+ // Snag out the SSID byte to play with. We need more than just
+ // the 4 SSID bits out of it.
+ ssid = (unsigned char)string[6];
+
+ // Check the digipeat bit
+ if ( (ssid & 0x80) && asterisk)
+ digipeated++; // Has been digipeated
+
+ // Check whether it is the end of the address field
+ if ( !(ssid & 0x01) )
+ more++; // More callsigns to come after this one
+
+ // Snag the four SSID bits
+ ssid = (ssid >> 1) & 0x0f;
+
+ // Construct the SSID number and add it to the end of the
+ // callsign if non-zero. If it's zero we don't add it.
+ if (ssid) {
+ callsign[j++] = '-';
+ if (ssid > 9) {
+ callsign[j++] = '1';
+ }
+ ssid = ssid % 10;
+ callsign[j++] = '0' + ssid;
+ }
+
+ // Add an asterisk if the packet has been digipeated through
+ // this callsign
+ if (digipeated)
+ callsign[j++] = '*';
+
+ // Terminate the string
+ callsign[j] = '\0';
+
+ return(more);
+}
+
+
+
+
+
+// Function which receives raw AX.25 packets from a KISS interface and
+// converts them to a printable TAPR-2 (more or less) style string.
+// We receive the packet with a KISS Frame End character at the
+// beginning and a "\0" character at the end. We can end up with
+// multiple asterisks, one for each callsign that the packet was
+// digipeated through. A few other TNC's put out this same sort of
+// format.
+//
+// Note about KISS & CRC's: The TNC checks the CRC. If bad, it
+// drops the packet. If good, it sends it to the computer WITHOUT
+// the CRC bytes. There's no way at the computer end to check
+// whether the packet was corrupted over the serial channel between
+// the TNC and the computer. Upon sending a KISS packet to the TNC,
+// the TNC itself adds the CRC bytes back on before sending it over
+// the air. In Xastir we can just assume that we're getting
+// error-free packets from the TNC, ignoring possible corruption
+// over the serial line.
+//
+// Some versions of KISS can encode the radio channel (for
+// multi-port TNC's) in the command byte. How do we know we're
+// running those versions of KISS though? Here are the KISS
+// variants that I've been able to discover to date:
+//
+// KISS No CRC, one radio port
+//
+// SMACK 16-bit CRC, multiport TNC's
+//
+// KISS-CRC
+//
+// 6-PACK
+//
+// KISS Multi-drop (Kantronics) 8-bit XOR Checksum, multiport TNC's (AGWPE compatible)
+// BPQKISS (Multi-drop) 8-bit XOR Checksum, multiport TNC's
+// XKISS (Kantronics) 8-bit XOR Checksum, multiport TNC's
+//
+// JKISS (AGWPE and BPQ32 compatible)
+//
+// MKISS Linux driver which supports KISS/BPQ and
+// hardware handshaking? Also Paccomm command to
+// immediately enter KISS mode.
+//
+// FlexKISS -,
+// FlexCRC -|-- These are all the same!
+// RMNC-KISS -|
+// CRC-RMNC -'
+//
+//
+// It appears that none of the above protocols implement any form of
+// hardware flow control.
+//
+//
+// Compare this function with interface.c:process_ax25_packet() to
+// see if we're missing anything important.
+//
+//
+// Inputs: data_string Raw string (must be MAX_LINE_SIZE or bigger)
+// length Length of raw string (may get changed here)
+//
+// Outputs: int 0 if it is a bad packet,
+// 1 if it is good
+// data_string Processed string
+//
+int decode_ax25_header(unsigned char *data_string, int *length) {
+ char temp[20];
+ char result[MAX_LINE_SIZE+100];
+ char dest[15];
+ int i, ptr;
+ char callsign[15];
+ char more;
+ char num_digis = 0;
+
+
+ // Do we have a string at all?
+ if (data_string == NULL)
+ return(0);
+
+ // Drop the packet if it is too long. Note that for KISS packets
+ // we can't use strlen() as there can be 0x00 bytes in the
+ // data itself.
+ if (*length > 1024) {
+ data_string[0] = '\0';
+ *length = 0;
+ return(0);
+ }
+
+ // Start with an empty string for the result
+ result[0] = '\0';
+
+ ptr = 0;
+
+ // Process the destination address
+ for (i = 0; i < 7; i++)
+ temp[i] = data_string[ptr++];
+ temp[7] = '\0';
+ more = decode_ax25_address(temp, callsign, 0); // No asterisk
+ xastir_snprintf(dest,sizeof(dest),"%s",callsign);
+
+ // Process the source address
+ for (i = 0; i < 7; i++)
+ temp[i] = data_string[ptr++];
+ temp[7] = '\0';
+ more = decode_ax25_address(temp, callsign, 0); // No asterisk
+
+ // Store the two callsigns we have into "result" in the correct
+ // order
+ xastir_snprintf(result,sizeof(result),"%s>%s",callsign,dest);
+
+ // Process the digipeater addresses (if any)
+ num_digis = 0;
+ while (more && num_digis < 8) {
+ for (i = 0; i < 7; i++)
+ temp[i] = data_string[ptr++];
+ temp[7] = '\0';
+
+ more = decode_ax25_address(temp, callsign, 1); // Add asterisk
+ strncat(result,
+ ",",
+ sizeof(result) - 1 - strlen(result));
+ strncat(result,
+ callsign,
+ sizeof(result) - 1 - strlen(result));
+ num_digis++;
+ }
+
+ strncat(result,
+ ":",
+ sizeof(result) - 1 - strlen(result));
+
+
+ // Check the Control and PID bytes and toss packets that are
+ // AX.25 connect/disconnect or information packets. We only
+ // want to process UI packets in Xastir.
+
+
+ // Control byte should be 0x03 (UI Frame). Strip the poll-bit
+ // from the PID byte before doing the comparison.
+ if ( (data_string[ptr++] & (~0x10)) != 0x03) {
+ return(0);
+ }
+
+
+ // PID byte should be 0xf0 (normal AX.25 text)
+ if (data_string[ptr++] != 0xf0)
+ return(0);
+
+
+// WE7U: We get multiple concatenated KISS packets sometimes. Look
+// for that here and flag when it happens (so we know about it and
+// can fix it someplace earlier in the process). Correct the
+// current packet so we don't get the extra garbage tacked onto the
+// end.
+ for (i = ptr; i < *length; i++) {
+ if (data_string[i] == KISS_FEND) {
+ fprintf(stderr,"***Found concatenated KISS packets:***\n");
+ data_string[i] = '\0'; // Truncate the string
+ break;
+ }
+ }
+
+ // Add the Info field to the decoded header info
+ strncat(result,
+ (char *)(&data_string[ptr]),
+ sizeof(result) - 1 - strlen(result));
+
+ // Copy the result onto the top of the input data. Note that
+ // the length can sometimes be longer than the input string, so
+ // we can't just use the "length" variable here or we'll
+ // truncate our string. Make sure the data_string variable is
+ // MAX_LINE_SIZE or bigger.
+ //
+ xastir_snprintf((char *)data_string,
+ MAX_LINE_SIZE,
+ "%s",
+ result);
+
+ // Write out the new length
+ *length = strlen(result);
+
+//fprintf(stderr,"%s\n",data_string);
+
+ return(1);
+}
+
+
+
+
+
+// RELAY the packet back out onto RF if received on a port with
+// digipeat enabled and the packet header has a non-digipeated RELAY
+// or my_callsign entry. This is for AX.25 kernel networking ports
+// or Serial KISS TNC ports only: Regular serial TNC's have these
+// features enabled/disabled through the startup/shutdown files.
+//
+// Adding asterisks:
+// Keep whatever digipeated fields have already been set. If
+// there's a "RELAY", "WIDE1-1", or "my_callsign" entry that hasn't
+// been digipeated yet, change it to "my_callsign*".
+//
+// This might be much easier to code into the routine that first
+// receives the packet (for Serial KISS TNC's). There we'd have
+// access to every digipeated bit directly instead of parsing
+// asterisks out of a string.
+//
+// NOTE: We don't handle this case properly: Multiple
+// RELAY's/WIDE1-1's or my_callsign's in the path, where one of the
+// earlier matching callsigns has been digipeated, but a later one
+// has not. We'll find the first matching callsign and the last
+// digi, and we won't relay the packet. This probably won't happen
+// much in the real world.
+//
+// We could also do premptive digipeating here and skip over
+// callsigns that haven't been digipeated yet. Should we set the
+// digipeated bits on everything before it? Probably. Either that
+// or remove the callsigns ahead of it in the list that weren't
+// digipeated.
+//
+void relay_digipeat(char *call, char *path, char *info, int port) {
+ char new_path[110+1];
+ char new_digi[MAX_CALLSIGN+2]; // Need extra for '*' storage
+ int ii, jj;
+ int done;
+ char destination[MAX_CALLSIGN+1];
+
+#define MAX_RELAY_SUBSTRINGS 10
+ char *Substring[MAX_RELAY_SUBSTRINGS]; // Pointers to substrings parsed by split_string()
+
+ // Pointers to all of the possible calls we with to digipeat by
+ char *Relay_Calls[MAX_RELAY_DIGIPEATER_CALLS];
+
+ char temp_string[MAX_LINE_SIZE+1];
+
+ // These strings are debugging tools
+ char small_string[200];
+ char big_string[2000];
+
+
+ // Check whether transmits are disabled globally
+ if (transmit_disable) {
+ return;
+ }
+
+ // Check whether relay_digipeat has been enabled for this interface.
+ // If not, get out while the gettin's good.
+ if (devices[port].relay_digipeat != 1) {
+ return;
+ }
+
+ // Check whether transmit has been enabled for this interface.
+ // If not, get out while the gettin's good.
+ if (devices[port].transmit_data != 1) {
+ return;
+ }
+
+ // Check for the only four types of interfaces where we might
+ // want to do RELAY digipeating. If not one of these, go
+ // bye-bye.
+ if ( (devices[port].device_type != DEVICE_SERIAL_KISS_TNC)
+ && (devices[port].device_type != DEVICE_SERIAL_MKISS_TNC)
+ && (devices[port].device_type != DEVICE_AX25_TNC)
+ && (devices[port].device_type != DEVICE_NET_AGWPE) ) {
+ return;
+ }
+
+
+sprintf(big_string,"\nrelay_digipeat: inputs:\n\tport: %d\n\tcall: %s\n\tpath: %s\n\tinfo: %s\n",
+ port, call, path, info);
+
+
+ // Check to see if this is my own transmitted packet (in some
+ // cases you get your own packets back from interfaces)
+ if (!strcasecmp(call, my_callsign)) {
+ //fprintf(stderr,"relay_digipeat: packet was mine, don't digipeat it!\n");
+ return;
+ }
+
+
+ // Make a copy of the incoming path. The string passed to
+ // split_string() gets destroyed.
+ xastir_snprintf(temp_string,
+ sizeof(temp_string),
+ "%s",
+ path);
+ split_string(temp_string, Substring, MAX_RELAY_SUBSTRINGS, ',');
+ // Each element in the path is now pointed to by a char ptr in
+ // the Substring array. If a NULL is found in the array, that's
+ // the end of the path.
+
+
+ if (Substring[0] == NULL) {
+ // Something's wrong! Couldn't find anything in the path
+ // string, not even a destination callsign?
+//fprintf(stderr, "\t\tNo path: %s\n", path);
+ return;
+ }
+ else { // Save the destination callsign away
+ xastir_snprintf(destination,
+ sizeof(destination),
+ "%s",
+ Substring[0]);
+ //fprintf(stderr,"Destination: %s\n",destination);
+ }
+ // We'll skip the first call in the path (pointed to by
+ // Substring[0]) in the loops below. That's the destination
+ // call and we don't want to look for RELAY or my_callsign
+ // there.
+
+
+ // Check to see if we just ran out of path
+ if (Substring[1] == NULL) { // No digipeaters listed
+ //fprintf(stderr,"relay_digipeat: ran out of path, don't digipeat it!\n");
+//fprintf(stderr, "\t\tNo digi's listed: %s\n", path);
+ return;
+ }
+
+
+ //fprintf(stderr," Path: %s\n",path);
+ // We could also loop through the array and dump them out until
+ // we hit a NULL if necessary.
+
+
+ // Find the first digipeater callsign _after_ any digis that
+ // have asterisks. Run through the array in reverse, looking
+ // for the digi callsign with an asterisk after it that's
+ // closest to the end of the path.
+ ii = MAX_RELAY_SUBSTRINGS - 1;
+ done = 0;
+ while (!done && ii > 0) {
+
+ if (Substring[ii] != NULL) {
+
+ if (strstr(Substring[ii],"*")) {
+ ii++; // Found an asterisk: Used digi. Point to
+ // the digi _after_ this one.
+ done++; // We found what we're looking for!
+ }
+ else { // No asterisk found yet.
+ ii--;
+ }
+ }
+ else { // No filled-in digipeater field found yet.
+ ii--;
+ }
+ }
+
+
+ if (ii == 0) { // No asterisks found. Entire path unused?
+ // Set ii to first actual digi field instead of the
+ // destination callsign.
+ ii = 1;
+ }
+ else { // ii points to first unused digi field.
+ }
+
+
+ if (Substring[ii] == NULL) { // No unused digi's found.
+ // We're done here.
+//fprintf(stderr, "\t\tPath used up: %s\n", path);
+ return;
+ }
+
+
+//fprintf(stderr,"\t\tUnused digi: %s\tPath: %s\n", Substring[ii], path);
+
+
+ // Split the relay digipeater calls into separate substrings.
+ // Split on comma delimiters. We get rid of extra spaces at the
+ // point where we read the string in from the config file
+ // (xa_config.c), so spaces between the calls are ok (but not
+ // tabs).
+ split_string(relay_digipeater_calls, Relay_Calls, MAX_RELAY_DIGIPEATER_CALLS, ',');
+
+ // Check for match against my_callsign in this digipeater slot
+ done = 0;
+ if (strcmp(Substring[ii], my_callsign) == 0) {
+ // It's our callsign. Digipeat using this call slot.
+ done++;
+ }
+ else { // Not my_callsign. Check every non-empty string in
+ // Relay_Calls[] for a match.
+
+ jj = 0;
+ while (!done && jj < MAX_RELAY_DIGIPEATER_CALLS) {
+
+ // Check for ending conditions
+ if (Relay_Calls[jj] == NULL || Relay_Calls[jj][0] == '\0') {
+ // We hit the end of the array of possible
+ // digipeater calls and had no match. Exit from
+ // this routine as we're not going to digipeat on
+ // this callsign slot.
+
+// Later we could add the option of "preemptive digipeating", where
+// we look further down the path for a possible match. We're not
+// doing that now.
+
+// fprintf(stderr,"End of Relay_Calls array: %d\n",jj);
+ return;
+ }
+
+ // If we made it to here, we should have a valid
+ // digipeater callsign in the Relay_Calls[jj] slot to
+ // compare against.
+
+ if (debug_level & 1) {
+ fprintf(stderr,"\tComparing %s to %s\n",
+ Substring[ii],
+ Relay_Calls[jj]);
+ }
+
+ if (strcmp(Substring[ii], Relay_Calls[jj]) == 0) {
+ done++;
+// fprintf(stderr,"match, done++\n");
+ }
+ else {
+ jj++;
+// fprintf(stderr,"incrementing jj: %d\n", jj);
+ }
+ }
+ }
+ if (!done) {
+ // No valid digipeating callsign found in this slot, exit
+ // this routine as we're not going to digipeat this packet.
+ return;
+ }
+
+
+/*
+OLD CODE:
+ // Check for RELAY, WIDE1-1 (the new relay) or my_callsign in
+ // this digipeater slot. If none of these found then exit this
+ // routine.
+ if ( (strcmp(Substring[ii], "RELAY") != 0)
+ && (strcmp(Substring[ii], "WIDE1-1") != 0)
+ && (strcmp(Substring[ii], my_callsign) != 0) ) {
+ // Some other callsign found in this digi field. Don't
+ // relay the packet.
+//fprintf(stderr,"Not relay, wide1-1, or %s, skipping\n", my_callsign);
+ return;
+ }
+*/
+
+
+ // Ok, we made it! We have RELAY, WIDE1-1, or my_callsign that
+ // hasn't been digipeated through, and we wish to change that
+ // fact. Put in our callsign for all three cases and add an
+ // asterisk to the end of the call. Also had to fix up the KISS
+ // transmit routine so that it'll set the digipeated bit for
+ // each callsign that has an asterisk.
+
+ // Contruct the new digi call, with the trailing asterisk
+ xastir_snprintf(new_digi,
+ sizeof(new_digi),
+ "%s*",
+ my_callsign);
+ Substring[ii] = new_digi; // Point to new digi string instead of old
+ //fprintf(stderr,"*** new_digi: %s\tSubstring: %s\n",
+ // new_digi,
+ // Substring[ii]);
+
+ // Construct the new path, substituting the correct portion.
+ // Start with the first digi and a comma:
+ xastir_snprintf(new_path,
+ sizeof(new_path),
+ "%s,",
+ Substring[1]);
+
+ ii = 2;
+ while ( (Substring[ii] != NULL)
+ && (ii < MAX_RELAY_SUBSTRINGS) ) {
+ strncat(new_path,
+ Substring[ii],
+ sizeof(new_path) - 1 - strlen(new_path));
+ ii++;
+ if (Substring[ii] != NULL) // Add a comma if more to come
+ strncat(new_path,
+ ",",
+ sizeof(new_path) - 1 - strlen(new_path));
+ }
+
+//fprintf(stderr,"*** New Path: %s,%s\n", destination, new_path);
+
+
+ if ( (devices[port].device_type == DEVICE_SERIAL_KISS_TNC)
+ || (devices[port].device_type == DEVICE_SERIAL_MKISS_TNC) ) {
+
+
+#ifdef SERIAL_KISS_RELAY_DIGI
+// fprintf(stderr,"KISS RELAY short_path: %s\n", short_path);
+// fprintf(stderr,"KISS RELAY new_path: %s\n", new_path);
+ send_ax25_frame(port, call, destination, new_path, info);
+#endif
+
+ }
+ else if (devices[port].device_type == DEVICE_AX25_TNC) {
+ char header_txt[MAX_LINE_SIZE+5];
+
+ //fprintf(stderr,"AX25 RELAY new_path: %s\n", new_path);
+
+ // set from call
+ xastir_snprintf(header_txt, sizeof(header_txt), "%c%s %s\r", '\3', "MYCALL", call);
+ if (port_data[port].status == DEVICE_UP)
+ port_write_string(port, header_txt);
+ // set path
+ xastir_snprintf(header_txt, sizeof(header_txt), "%c%s %s VIA %s\r", '\3', "UNPROTO",
+ destination, new_path);
+ if (port_data[port].status == DEVICE_UP)
+ port_write_string(port, header_txt);
+ // set converse mode
+ xastir_snprintf(header_txt, sizeof(header_txt), "%c%s\r", '\3', "CONV");
+ if (port_data[port].status == DEVICE_UP)
+ port_write_string(port, header_txt);
+ // send packet
+ if (port_data[port].status == DEVICE_UP)
+ port_write_string(port, info);
+ }
+ else if (devices[port].device_type == DEVICE_NET_AGWPE) {
+ send_agwpe_packet(port, // Xastir interface port
+ atoi(devices[port].device_host_filter_string), // AGWPE RadioPort
+ '\0', // Type of frame (data)
+ (unsigned char *)call, // source
+ (unsigned char *)destination, // destination
+ (unsigned char *)new_path, // Path,
+ (unsigned char *)info,
+ strlen(info));
+ }
+
+
+//WE7U
+sprintf(small_string,"relay_digipeat: outputs:\n\tport: %d\n\tcall: %s\n\tdest: %s\n\tpath: %s\n\tinfo: %s\n",
+ port, call, destination, new_path, info);
+strncat(big_string,
+ small_string,
+ sizeof(big_string) - 1 - strlen(big_string));
+//fprintf(stderr,"%s",big_string);
+
+
+// Example packet:
+//K7FZO>APW251,SEATAC*,WIDE4-1:=4728.00N/12140.83W;PHG3030/Middle Fork Snoqualmie River -251-<630>
+
+}
+
+
+
+
+
+/*
+ * Decode AX.25 line
+ * \r and \n should already be stripped from end of line
+ * line should not be NULL
+ *
+ * If dbadd is set, add to database. Otherwise, just return true/false
+ * to indicate whether input is valid AX25 line.
+ */
+//
+// Note that the length of "line" can be up to MAX_DEVICE_BUFFER,
+// which is currently set to 4096.
+//
+int decode_ax25_line(char *line, char from, int port, int dbadd) {
+ char *call_sign;
+ char *path0;
+ char path[100+1]; // new one, we may add an '*'
+ char *info;
+ char info_copy[MAX_LINE_SIZE+1];
+ char call[MAX_CALLSIGN+1];
+ char origin[MAX_CALLSIGN+1];
+ int ok;
+ int third_party;
+ char backup[MAX_LINE_SIZE+1];
+ char tmp_line[MAX_LINE_SIZE+1];
+ char tmp_path[100+1];
+ char *ViaCalls[10];
+
+
+ // Check guard band around pointers. Make sure it's pristine.
+ if ( check_guard_band() ) {
+ fprintf(stderr, "WARNING: Guard band around global pointers was corrupted!\n");
+ }
+
+ xastir_snprintf(backup,
+ sizeof(backup),
+ "%s",
+ line);
+
+// This is a good one to enable for debugging without getting too
+// many other types of messages to the xterm. It will enable the
+// block below.
+//#define WE7U_DEBUG
+
+#ifndef WE7U_DEBUG
+ if (debug_level & 1)
+#endif
+ {
+ char filtered_data[MAX_LINE_SIZE+1];
+
+ xastir_snprintf(filtered_data,
+ sizeof(filtered_data),
+ "%s",
+ line);
+ filtered_data[MAX_LINE_SIZE] = '\0'; // Terminate it
+
+ makePrintable(filtered_data);
+ fprintf(stderr,"decode_ax25_line: start parsing %s\n", filtered_data);
+ }
+
+ if (line == NULL) {
+ fprintf(stderr,"decode_ax25_line: line == NULL.\n");
+ return(FALSE);
+ }
+
+ if ( (line != NULL) && (strlen(line) > MAX_LINE_SIZE) ) { // Overly long message, throw it away. We're done.
+ if (debug_level & 1)
+ fprintf(stderr,"\ndecode_ax25_line: LONG packet. Dumping it:\n%s\n",line);
+ return(FALSE);
+ }
+
+ if (line[strlen(line)-1] == '\n') // better: look at other places,
+ // so that we don't get it here...
+ line[strlen(line)-1] = '\0'; // Wipe out '\n', to be sure
+ if (line[strlen(line)-1] == '\r')
+ line[strlen(line)-1] = '\0'; // Wipe out '\r'
+
+ call_sign = NULL;
+ path0 = NULL;
+ info = NULL;
+ origin[0] = '\0';
+ call[0] = '\0';
+ path[0] = '\0';
+ third_party = 0;
+
+ // CALL>PATH:APRS-INFO-FIELD // split line into components
+ // ^ ^
+ ok = 0;
+ call_sign = strtok(line,">"); // extract call from AX.25 line
+ if (call_sign != NULL) {
+ path0 = strtok(NULL,":"); // extract path from AX.25 line
+ if (path0 != NULL) {
+ info = strtok(NULL,""); // rest is info_field
+ if (info != NULL) {
+ if ((info - path0) < 100) { // check if path could be copied
+ ok = 1; // we have found all three components
+ }
+ }
+ }
+ }
+
+ if (ok) {
+
+ xastir_snprintf(path,
+ sizeof(path),
+ "%s",
+ path0);
+
+ memset(info_copy, '\0', sizeof(info_copy));
+ xastir_snprintf(info_copy,
+ sizeof(info_copy),
+ "%s",
+ info);
+
+ ok = valid_path(path); // check the path and convert it to TAPR format
+ // Note that valid_path() also removes igate injection identifiers
+
+ if ((debug_level & 1) && !ok) {
+ char filtered_data[MAX_LINE_SIZE + 1];
+
+ xastir_snprintf(filtered_data,
+ sizeof(filtered_data),
+ "%s",
+ path);
+ makePrintable(filtered_data);
+ fprintf(stderr,"decode_ax25_line: invalid path: %s\n",filtered_data);
+ }
+ }
+
+ if (ok) {
+ // If it's not me transmitting it:
+ if (strcmp(my_callsign,call_sign) != 0) {
+
+ // Check for "EMERGENCY" anywhere in the line.
+ // APRS+SA also supports any of these in the TO: field:
+ //
+ // EMERGENCY
+ // ALARM
+ // ALERT
+ // WARNING
+ // WXALARM
+ // EM
+ //
+ // Snag just the TO: field from the path, used for most of the
+ // comparisons below. It will be pointed to by ViaCalls[0];
+ xastir_snprintf(tmp_path, // Make a temporary backup
+ sizeof(tmp_path),
+ "%s",
+ path);
+ split_string(tmp_path, ViaCalls, 10, ',');
+
+ if ( (strstr(backup, "EMERGENCY")) // Checks entire line
+ || (strcmp(ViaCalls[0], "ALARM") == 0) // Checks to_field
+ || (strcmp(ViaCalls[0], "ALERT") == 0) // Checks to_field
+ || (strcmp(ViaCalls[0], "WARNING") == 0) // Checks to_field
+ || (strcmp(ViaCalls[0], "WXALARM") == 0) // Checks to_field
+ || (strcmp(ViaCalls[0], "EM") == 0) ) { // Checks to_field
+
+ double distance; // miles or km
+ char course_deg[5];
+
+// EMERGENCY
+ if (emergency_distance_check) {
+
+ distance = distance_from_my_station(call_sign, course_deg);
+
+// Because of the distance check we have to receive a valid position
+// from the station BEFORE we process the EMERGENCY portion and
+// check distance, doing the popups. We need to figure out a way to
+// throw the packet back into the queue if it was an emergency
+// packet so that we process these packets twice each. That way
+// only one packet from the emergency station is required to
+// generate the popups.
+
+ if (distance == 0.0) {
+ process_emergency_packet_again++;
+ }
+
+ // Check whether the station is near enough to
+ // us to require that we alert on the packet.
+ //
+ // This may be slightly controversial, but if we
+ // don't know WHERE a station is, we can't help
+ // much in an emergency, can we? The
+ // zero-distance check helps in the case where
+ // we haven't yet or never get a position packet
+ // for a station. As soon as we have a position
+ // and it is within a reasonable range, we do
+ // our emergency popups.
+ //
+ if ( distance != 0.0 && (float)distance <= emergency_range ) {
+
+// Do the conversion for emergency_range to mi or km as needed.
+// if (english_units) {
+// }
+// else {
+// }
+
+ // Do a popup to alert the operator to this
+ // condition. Make sure we haven't popped
+ // up an emergency message for this station
+ // within the last 30 minutes. If we pop
+ // these up constantly it gets quite
+ // annoying.
+ if ( (strncmp(call_sign, last_emergency_callsign, strlen(call_sign)) != 0)
+ || ((last_emergency_time + 60*30) < sec_now()) ) {
+
+ char temp[50];
+ char temp2[150];
+ char temp3[300];
+ char timestring[101];
+
+ // Callsign is different or enough time
+ // has passed
+
+ last_emergency_time = sec_now();
+ xastir_snprintf(last_emergency_callsign,
+ sizeof(last_emergency_callsign),
+ "%s",
+ call_sign);
+
+ // Bring up the Find Station dialog so
+ // that the operator can go to the
+ // location quickly.
+ xastir_snprintf(locate_station_call,
+ sizeof(locate_station_call),
+ "%s",
+ call_sign);
+
+ Locate_station( (Widget)NULL,
+ (XtPointer)NULL,
+ (XtPointer)1 );
+
+ // Bring up an additional popup dialog
+ // that shows the entire packet, so the
+ // user can make a determination as to
+ // whether the packet is or is not a
+ // real emergency.
+ //
+ popup_message_always(langcode("POPEM00036"), backup);
+
+ // Bring up another dialog with the
+ // callsign plus distance/bearing to the
+ // station.
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%0.1f",
+ distance);
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ langcode("WPUPSTI022"),
+ temp,
+ course_deg);
+ get_timestamp(timestring);
+ xastir_snprintf(temp3,
+ sizeof(temp3),
+ "%s %s",
+ timestring,
+ temp2);
+ popup_message_always(call_sign, temp3);
+
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (ok) {
+
+ // Attempt to digipeat this packet if we should. If port=-2,
+ // we received this packet from the x_spider server and we
+ // should not attempt to digipeat it. If port=-1, it's from
+ // a log file. Again, don't digipeat it.
+ if (port >= 0)
+ relay_digipeat(call_sign, path, info, port);
+
+ extract_TNC_text(info); // extract leading text from TNC X-1J4
+ if (strlen(info) > 256) // first check if information field conforms to APRS specs
+ ok = 0; // drop packets too long
+ if ((debug_level & 1) && !ok) {
+ char filtered_data[MAX_LINE_SIZE + 1];
+
+ xastir_snprintf(filtered_data,
+ sizeof(filtered_data),
+ "%s",
+ info);
+ makePrintable(filtered_data);
+ fprintf(stderr,"decode_ax25_line: info field too long: %s\n",filtered_data);
+ }
+ }
+
+ if (ok) { // check callsign
+ (void)remove_trailing_asterisk(call_sign); // is an asterisk valid here ???
+ if (valid_inet_name(call_sign,info,origin,sizeof(origin))) { // accept some of the names used in internet
+ xastir_snprintf(call,
+ sizeof(call),
+ "%s",
+ call_sign);
+ }
+ else if (valid_call(call_sign)) { // accept real AX.25 calls
+ xastir_snprintf(call,
+ sizeof(call),
+ "%s",
+ call_sign);
+ }
+ else {
+ ok = 0;
+ if (debug_level & 1) {
+ char filtered_data[MAX_LINE_SIZE + 1];
+
+ xastir_snprintf(filtered_data,
+ sizeof(filtered_data),
+ "%s",
+ call_sign);
+ makePrintable(filtered_data);
+ fprintf(stderr,"decode_ax25_line: invalid call: %s\n",filtered_data);
+ }
+ }
+ }
+
+ if (!dbadd)
+ {
+ if (debug_level & 1)
+ fprintf(stderr,"decode_ax25_line: exiting\n");
+
+ return(ok);
+ }
+
+ if (ok && info[0] == '}') { // look for third-party traffic
+ ok = extract_third_party(call,path,sizeof(path),&info,origin,sizeof(origin)); // extract third-party data
+ third_party = 1;
+
+ // Add it to the HEARD queue for this interface. We use this
+ // for igating purposes. If some other igate beat us to this
+ // packet, we don't want to duplicate it over the air. If
+ // port=-2, we received it from the x_spider server and we
+ // should not save it in the queue. If port=-1, the packet
+ // came from a log file and again we shouldn't save it to
+ // the queue.
+ if (port >= 0)
+ insert_into_heard_queue(port, backup);
+ }
+
+ if (ok && (info[0] == ';' || info[0] == ')')) { // look for objects or items
+ xastir_snprintf(origin,
+ sizeof(origin),
+ "%s",
+ call);
+ ok = extract_object(call,&info,origin); // extract object data
+ }
+
+ if (ok) {
+ // decode APRS information field, always called with valid call and path
+ // info is a string with 0 - 256 bytes
+ // fprintf(stderr,"dec: %s (%s) %s\n",call,origin,info);
+ if (debug_level & 1) {
+ char filtered_data[MAX_LINE_SIZE+80];
+ sprintf(filtered_data,
+ "Registering data %s %s %s %s %c %d %d",
+ call, path, info, origin, from, port, third_party);
+ makePrintable(filtered_data);
+ fprintf(stderr,"c/p/i/o fr pt tp: %s\n", filtered_data);
+ }
+ decode_info_field(call,
+ path,
+ info,
+ origin,
+ from,
+ port,
+ third_party,
+ info_copy);
+ }
+
+
+ if (port == -2) { // We received this packet from an x_spider
+ // server. We need to dump it out all of our
+ // transmit-enabled ports.
+
+ // If the string starts with "user" or "pass", it's an
+ // authentication string. We need to send those through as
+ // well so that the user gets logged into the internet
+ // server and can send/receive packets/messages. We also
+ // dump it to our console so that we can see who logged in
+ // to us.
+ if (strncasecmp(line,"user",4) == 0
+ || strncasecmp(line,"pass",4 == 0)
+ || strncasecmp(line,"filter",6 == 0)) {
+ fprintf(stderr,"\tLogged on: %s\n", line);
+
+// If the line has a "filter" parameter in it, we need to remove it,
+// else a client may change our filtering parameters. Perhaps we
+// should skip the authentication stuff as well, as the servers
+// might get confused if we pass two different authentications on
+// the same socket?
+
+ }
+ else if (strlen(line) > 0) { // Not empty
+ // Send the packet unchanged out all of our
+ // transmit-enabled ports. We should send it as
+ // third-party igated packets if we're sending to
+ // servers, send it unchanged if sending through TNC?
+
+//fprintf(stderr,"Retransmitting x_spider packet: %s\n", line);
+
+ // Here's where we inject our own callsign like this:
+ // "WE7U-15,I" in order to provide injection ID for our
+ // igate.
+ xastir_snprintf(tmp_line,
+ sizeof(tmp_line),
+ "%s>%s,%s,I:%s",
+ call_sign,
+ path,
+ my_callsign,
+ info_copy);
+
+//fprintf(stderr,"decode_ax25_line: IGATE>NET %s\n",tmp_line);
+//fprintf(stderr,"call: %s\tcall_sign: %s\n", call, call_sign);
+
+ output_igate_net(tmp_line, port, 0); // 0="not third-party"
+ }
+ }
+
+// EMERGENCY
+ // For emergency packets we need to process them twice, to try
+ // to get a position before we do the distance check.
+ //
+// This causes an infinite loop on packets that don't have a
+// distance! Disabling it for now.
+ if (process_emergency_packet_again) {
+ process_emergency_packet_again = 0;
+//fprintf(stderr,"Again: %s\n", backup);
+// decode_ax25_line(backup, from, port, dbadd);
+ }
+
+ if (debug_level & 1)
+ fprintf(stderr,"decode_ax25_line: exiting\n");
+
+ return(ok);
+}
+
+
+
+
+
+/*
+ * Read a line from file. We use this to read in log files and to
+ * read in findu track files. For findu track files we need to get
+ * rid of the <br> at the end of the lines, else it shows up in our
+ * comment lines in Station_info.
+ */
+void read_file_line(FILE *f) {
+ char line[MAX_LINE_SIZE+1];
+ char cin;
+ int pos;
+
+ pos = 0;
+ line[0] = '\0';
+ while (!feof(f)) {
+ if (fread(&cin,1,1,f) == 1) {
+ if (cin != (char)10 && cin != (char)13) { // normal characters
+ if (pos < MAX_LINE_SIZE) {
+ line[pos++] = cin;
+ }
+ }
+ else { // CR or LF
+ if (cin == (char)10) { // Found LF as EOL char
+ char *ptr;
+
+ line[pos] = '\0'; // Always add a terminating zero after last char
+ pos = 0; // start next line
+
+ // Get rid of <br> HTML tag at end of line here.
+ // Findu track files have them.
+ ptr = strstr(line, "<br>");
+ if (ptr) { // Found one of them
+ *ptr = '\0'; // Terminate the line at that point
+ }
+
+ // Save backup copies of this string and the
+ // previous string. Used for debugging
+ // purposes. If we get a segfault, we can print
+ // out the last two messages received.
+ xastir_snprintf((char *)incoming_data_copy_previous,
+ MAX_LINE_SIZE,
+ "%s",
+ incoming_data_copy);
+ xastir_snprintf((char *)incoming_data_copy,
+ MAX_LINE_SIZE,
+ "%s",
+ line);
+
+ if (line[0] != '#') {
+ decode_ax25_line(line,'F',-1, 1); // Decode the packet
+ }
+
+ return; // only read line by line
+ }
+ }
+ }
+ }
+ if (feof(f)) { // Close file if at the end
+ (void)fclose(f);
+ read_file = 0;
+ statusline(langcode("BBARSTA012"),0); // File done..
+ redraw_on_new_data = 2; // redraw immediately after finish
+ }
+}
+
+
+
+
+
+/*
+ * Center map to new position
+ */
+void set_map_position(Widget w, long lat, long lon) {
+ // see also map_pos() in location.c
+
+ // Set interrupt_drawing_now because conditions have changed
+ // (new map center).
+ interrupt_drawing_now++;
+
+ set_last_position();
+ center_latitude = lat;
+ center_longitude = lon;
+ setup_in_view(); // flag all stations in new screen view
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(w)) {
+// (void)XCopyArea(XtDisplay(w),pixmap_final,XtWindow(w),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+}
+
+
+
+
+
+/*
+ * Search for a station to be located (for Tracking and Find Station)
+ */
+int locate_station(Widget w, char *call, int follow_case, int get_match, int center_map) {
+ DataRow *p_station;
+ char call_find[MAX_CALLSIGN+1];
+ char call_find1[MAX_CALLSIGN+1];
+ int ii;
+ int call_len;
+
+ call_len = 0;
+ if (!follow_case) {
+ for (ii=0; ii<(int)strlen(call); ii++) {
+ if (isalpha((int)call[ii]))
+ call_find[ii] = toupper((int)call[ii]); // Problem with lowercase objects/names!!
+ else
+ call_find[ii] = call[ii];
+ }
+ call_find[ii] = '\0';
+ xastir_snprintf(call_find1,
+ sizeof(call_find1),
+ "%s",
+ call_find);
+ }
+ else
+ xastir_snprintf(call_find1,
+ sizeof(call_find1),
+ "%s",
+ call);
+
+ if (search_station_name(&p_station,call_find1,get_match)) {
+ if (position_defined(p_station->coord_lat,p_station->coord_lon,0)) {
+ if (center_map || !position_on_inner_screen(p_station->coord_lat,p_station->coord_lon))
+ // only change map if really neccessary
+ set_map_position(w, p_station->coord_lat, p_station->coord_lon);
+ return(1); // we found it
+ }
+ }
+ return(0);
+}
+
+
+
+
+
+/*
+ * Look for other stations that the tracked one has gotten close to.
+ * and speak a proximity warning.
+ * TODO:
+ * - sort matches by distance
+ * - set upper bound on number of matches so we don't speak forever
+ * - use different proximity distances for different station types?
+ * - look for proximity to embedded map objects
+ */
+void search_tracked_station(DataRow **p_tracked) {
+ DataRow *t = (*p_tracked);
+ DataRow *curr = NULL;
+
+
+ if (debug_level & 1) {
+ char lat[20],lon[20];
+
+ convert_lat_l2s(t->coord_lat,
+ lat,
+ sizeof(lat),
+ CONVERT_HP_NORMAL);
+ convert_lon_l2s(t->coord_lon,
+ lon,
+ sizeof(lat),
+ CONVERT_HP_NORMAL);
+
+ fprintf(stderr,"Searching for stations close to tracked station %s at %s %s ...\n",
+ t->call_sign,lat,lon);
+ }
+
+ while (next_station_time(&curr)) {
+ if (curr != t && curr->flag&ST_ACTIVE) {
+
+ float distance; // Distance in whatever measurement
+ // units we're currently using.
+ char bearing[10];
+ char station_id[600];
+
+ distance = (float)calc_distance_course(t->coord_lat,
+ t->coord_lon,
+ curr->coord_lat,
+ curr->coord_lon,
+ bearing,
+ sizeof(bearing)) * cvt_kn2len;
+
+ if (debug_level & 1)
+ fprintf(stderr,"Looking at %s: distance %.3f bearing %s (%s)\n",
+ curr->call_sign,distance,bearing,convert_bearing_to_name(bearing,1));
+
+ /* check ranges (copied from earlier prox alert code, above) */
+ if ((distance > atof(prox_min)) && (distance < atof(prox_max))) {
+ if (debug_level & 1)
+ fprintf(stderr," tracked station is near %s!\n",curr->call_sign);
+
+ if (sound_play_prox_message) {
+ sprintf(station_id,"%s < %.3f %s from %s",t->call_sign, distance,
+ english_units?langcode("UNIOP00004"):langcode("UNIOP00005"),
+ curr->call_sign);
+ statusline(station_id,0);
+ play_sound(sound_command,sound_prox_message);
+ }
+#ifdef HAVE_FESTIVAL
+ if (festival_speak_tracked_proximity_alert) {
+ if (english_units) {
+ if (distance < 1.0)
+ sprintf(station_id, langcode("SPCHSTR007"), t->call_sign,
+ (int)(distance * 1760), langcode("SPCHSTR004"),
+ convert_bearing_to_name(bearing,1), curr->call_sign);
+ else if ((int)((distance * 10) + 0.5) % 10)
+ sprintf(station_id, langcode("SPCHSTR008"), t->call_sign, distance,
+ langcode("SPCHSTR003"), convert_bearing_to_name(bearing,1),
+ curr->call_sign);
+ else
+ sprintf(station_id, langcode("SPCHSTR007"), t->call_sign, (int)(distance + 0.5),
+ langcode("SPCHSTR003"), convert_bearing_to_name(bearing,1),
+ curr->call_sign);
+ }
+ else { /* metric */
+ if (distance < 1.0)
+ sprintf(station_id, langcode("SPCHSTR007"), t->call_sign,
+ (int)(distance * 1000), langcode("SPCHSTR002"),
+ convert_bearing_to_name(bearing,1), curr->call_sign);
+ else if ((int)((distance * 10) + 0.5) % 10)
+ sprintf(station_id, langcode("SPCHSTR008"), t->call_sign, distance,
+ langcode("SPCHSTR001"),
+ convert_bearing_to_name(bearing,1), curr->call_sign);
+ else
+ sprintf(station_id, langcode("SPCHSTR007"), t->call_sign, (int)(distance + 0.5),
+ langcode("SPCHSTR001"), convert_bearing_to_name(bearing,1),
+ curr->call_sign);
+ }
+ if (debug_level & 1)
+ fprintf(stderr," %s\n",station_id);
+ SayText(station_id);
+ }
+#endif /* HAVE_FESTIVAL */
+ }
+ }
+ } // end of while
+}
+
+
+
+
+
+/*
+ * Change map position if neccessary while tracking a station
+ * we call it with defined station call and position
+ */
+void track_station(Widget w, char *call_tracked, DataRow *p_station) {
+ long x_ofs, y_ofs;
+ long new_lat, new_lon;
+
+ if ( is_tracked_station(p_station->call_sign) ) { // We want to track this station
+ new_lat = p_station->coord_lat; // center map to station position as default
+ new_lon = p_station->coord_lon;
+ x_ofs = new_lon - center_longitude; // current offset from screen center
+ y_ofs = new_lat - center_latitude;
+ if ((labs(x_ofs) > (screen_width*scale_x/3)) || (labs(y_ofs) > (screen_height*scale_y/3))) {
+ // only redraw map if near border (margin 1/6 of screen at each side)
+ if (labs(y_ofs) < (screen_height*scale_y/2))
+ new_lat += y_ofs/2; // give more space in driving direction
+ if (labs(x_ofs) < (screen_width*scale_x/2))
+ new_lon += x_ofs/2;
+
+ set_map_position(w, new_lat, new_lon); // center map to new position
+
+ }
+ search_tracked_station(&p_station);
+ }
+}
+
+
+
+
+
+// ********************************************************************
+// calc aloha_distance()
+// calculate and return alhoa circle radius in current distance units
+// The ALOHA radius is computed according to the algorithm described by
+// Bob Bruninga at http://web.usna.navy.mil/~bruninga/aprs/ALOHAcir.txt
+// with some clarification provided py private email.
+//
+// The gist of it is that we grab a list of all stations heard via TNC
+// and sort it b distance from our station. We then accumulate a
+// count of how many theoretical packets would be introduced into the local
+// area in 30 minutes from these stations, and stop when we hit 1800
+// (the supposed limit of the channel capacity). The distance to the last
+// station we counted is our ALOHA limit. Per Bob B., this should be plotted
+// on the map as a circle with no user-selectable way of turning it off.
+//
+double calc_aloha_distance(void) {
+ DataRow *p_station = n_first; // walk in alphabetical order
+ aloha_entry *aloha_array;
+ aloha_entry *temp_aloha_array;
+
+ int num_aloha_alloc=1000;
+ int num_aloha_entries=0;
+ int digi_copies=1;
+ char temp[10]; // needed for course_deg argument of
+ // distance_from_my_station
+
+ int sum;
+ double distance;
+ int ii;
+
+ // This should be enough, though we'll realloc if necessary
+ aloha_array = (aloha_entry *)malloc (num_aloha_alloc*sizeof(aloha_entry));
+ CHECKMALLOC(aloha_array);
+
+ // We need a list of all stations that were heard via tnc:
+ while (p_station != NULL) {
+ if (num_aloha_entries == num_aloha_alloc) {
+ num_aloha_alloc *= 2;
+ temp_aloha_array=realloc(aloha_array,num_aloha_alloc);
+ if (temp_aloha_array) {
+ aloha_array=temp_aloha_array;
+ }
+ else {
+ fprintf(stderr,"***** Realloc failed *****\n");
+ exit(1);
+ }
+ }
+ if ( (p_station->flag & ST_VIATNC) != 0 &&
+ (p_station->flag & ST_ACTIVE) != 0 ) {
+ if (position_defined(p_station->coord_lat,p_station->coord_lon,1)){
+ xastir_snprintf(aloha_array[num_aloha_entries].call_sign,
+ MAX_CALLSIGN+1,
+ "%s",
+ p_station->call_sign);
+ aloha_array[num_aloha_entries].is_digi =
+ aloha_array[num_aloha_entries].is_mobile =
+ aloha_array[num_aloha_entries].is_other_mobile =
+ aloha_array[num_aloha_entries].is_home =
+ aloha_array[num_aloha_entries].is_wx = (char) FALSE;
+ aloha_array[num_aloha_entries].distance =
+ distance_from_my_station(p_station->call_sign,temp);
+
+ if ( p_station->newest_trackpoint != NULL
+ && strlen(p_station->speed) > 0) {
+ // If the station has a track and a speed of any value
+ // (even zero), it's a mobile.
+ aloha_array[num_aloha_entries].is_mobile = (char) TRUE;
+ }
+ else if ( (p_station->aprs_symbol.aprs_type=='/'
+ && (strchr("'<=>()*0COPRSUXY[^abefgjkpsuv",
+ p_station->aprs_symbol.aprs_symbol)
+ != NULL))
+ || (p_station->aprs_symbol.aprs_type=='\\'
+ && (strchr("/0>AKOS^knsuv",
+ p_station->aprs_symbol.aprs_symbol)
+ != NULL))) {
+ //
+ // Per private email exchange with Bob Bruninga:
+ // If the station has one of these symbols,
+ // it's "other mobile"
+ // these are also listed on
+ // web.usna.navy.mil/~bruninga/aprs/aprs11.html
+ //
+ aloha_array[num_aloha_entries].is_other_mobile =(char)TRUE;
+ }
+ else if ( p_station-> record_type == APRS_WX1 ||
+ p_station-> record_type == APRS_WX2 ||
+ p_station-> record_type == APRS_WX3 ||
+ p_station-> record_type == APRS_WX4 ||
+ p_station-> record_type == APRS_WX5 ||
+ p_station-> record_type == APRS_WX6 ||
+ p_station-> aprs_symbol.aprs_symbol=='_') {
+ // Bob B. uses the station symbol "_" to select this, but
+ // agrees that if we do it this way it's probably better
+ // -- this says if we've gotten any WX data, it's a WX
+ // station
+ aloha_array[num_aloha_entries].is_wx = (char) TRUE;
+ }
+ else if (p_station->aprs_symbol.aprs_symbol=='#') {
+ // Per Bob B., if it has "#" as its symbol, it's
+ // assumed to be a digi.
+ aloha_array[num_aloha_entries].is_digi = (char) TRUE;
+ }
+ else {
+ // Anything that hasn't gotten selected yet is just a home
+ aloha_array[num_aloha_entries].is_home = (char) TRUE;
+ }
+
+ num_aloha_entries++;
+ }
+ }
+ p_station = p_station-> n_next;
+ }
+
+ if (debug_level & 2048) {
+ fprintf (stderr,"aloha_distance: Found %d local stations\n",
+ num_aloha_entries);
+ }
+
+ // we now have all the stations heard via TNC. Now sort it by distance
+ qsort((void *) aloha_array,num_aloha_entries,sizeof(aloha_entry),
+ comp_by_dist);
+
+ // Starting from the closest, working outward, accumulate
+ sum=0;
+ the_aloha_stats.digis=0;
+ the_aloha_stats.wxs = 0;
+ the_aloha_stats.other_mobiles = 0;
+ the_aloha_stats.mobiles_in_motion = 0;
+ the_aloha_stats.homes = 0;
+ the_aloha_stats.total = 0;
+
+ for (ii=0;(ii<num_aloha_entries && sum < 1800);ii++) {
+ the_aloha_stats.total++;
+ if (aloha_array[ii].is_digi) {
+ sum += digi_copies*3;
+ digi_copies++; // per Bob's web page. Makes more distant
+ // stations than this digi count for more, since
+ // they have been digipeated.
+ the_aloha_stats.digis++;
+ }
+ else if (aloha_array[ii].is_home) {
+ sum += digi_copies*2;
+ the_aloha_stats.homes++;
+ }
+ else if (aloha_array[ii].is_wx) {
+ sum += digi_copies*6;
+ the_aloha_stats.wxs++;
+ }
+ else if (aloha_array[ii].is_mobile) {
+ sum += digi_copies*15;
+ the_aloha_stats.mobiles_in_motion++;
+ }
+ else if (aloha_array[ii].is_other_mobile) {
+ sum += digi_copies*7;
+ the_aloha_stats.other_mobiles++;
+ }
+ if (debug_level & 2048) {
+ fprintf(stderr," %d:%s: d=%f, digi=%c, mobile=%c, motion=%c, home=%c, wx=%c (cum=%d)\n",
+ ii,
+ aloha_array[ii].call_sign,
+ aloha_array[ii].distance,
+ (aloha_array[ii].is_digi)?'y':'n',
+ (aloha_array[ii].is_other_mobile)?'y':'n',
+ (aloha_array[ii].is_mobile)?'y':'n',
+ (aloha_array[ii].is_home)?'y':'n',
+ (aloha_array[ii].is_wx)?'y':'n',sum);
+ }
+ }
+
+ if (ii>0 && ii < num_aloha_entries && sum >= 1800) { // we hit the limit
+ distance = aloha_array[ii-1].distance;
+ }
+ else {
+ distance = -1; // indeterminate, not enough data yet
+ }
+
+ free (aloha_array); // make sure we don't leak
+ return distance;
+
+}
+
+
+
+
+
+// Used by qsort to sort the aloha entries
+int comp_by_dist(const void *av,const void *bv) {
+ aloha_entry *a = (aloha_entry *) av;
+ aloha_entry *b = (aloha_entry *) bv;
+ if (a->distance < b->distance)
+ return -1;
+ if (a->distance > b->distance)
+ return 1;
+
+ return 0;
+}
+
+
+
+
+
+// Called periodically by UpdateTime, we calculate our aloha radius every
+// so often. (Bob B. recommends every 30 minutes)
+void calc_aloha(int secs_now) {
+ char status_text[100];
+
+ if (aloha_time == 0) { // first call
+ aloha_time = secs_now+ALOHA_CALC_INTERVAL;
+ aloha_status_time = secs_now+ALOHA_STATUS_INTERVAL;
+ aloha_radius = -1.0;
+
+// Debug: Let's us play with/display aloha circles right away:
+//aloha_radius = 40.0; // Miles
+
+ the_aloha_stats.digis=0;
+ the_aloha_stats.wxs = 0;
+ the_aloha_stats.other_mobiles = 0;
+ the_aloha_stats.mobiles_in_motion = 0;
+ the_aloha_stats.homes = 0;
+ the_aloha_stats.total = 0;
+ //fprintf(stderr,"Initialized aloha radius time\n");
+ }
+ else {
+ if (secs_now > aloha_time) {
+ aloha_radius = calc_aloha_distance();
+ aloha_time = secs_now + ALOHA_CALC_INTERVAL;
+ if (debug_level & 2048) {
+ if (aloha_radius < 0) {
+ fprintf(stderr,"Aloha distance indeterminate\n");
+ }
+ else {
+ fprintf(stderr,"Aloha distance is %f",aloha_radius);
+ if (english_units) {
+ fprintf(stderr," miles.\n");
+ }
+ else {
+ fprintf(stderr," km.\n");
+ }
+ }
+ }
+ }
+ if (secs_now > aloha_status_time) {
+ if ( aloha_radius != -1 ) {
+ xastir_snprintf(status_text,
+ sizeof(status_text),
+ langcode("BBARSTA044"),
+ (english_units) ? (int)aloha_radius : (int)(aloha_radius * cvt_mi2len),
+ (english_units) ? " miles" : " km");
+ statusline(status_text,1);
+ }
+ aloha_status_time = secs_now + ALOHA_STATUS_INTERVAL;
+ }
+ }
+}
+
+
+
+
+
+// popup window on menu request
+void Show_Aloha_Stats(Widget w, XtPointer clientData, XtPointer callData) {
+
+ char temp[2000];
+ char format[1000];
+
+ unsigned long time_since_aloha_update;
+ int minutes, hours;
+ char Hours[7];
+ char Minutes[9];
+
+ if (aloha_radius != -1) {
+ // we've done at least one interval, and aloha_time is the time
+ // for the *next* one. We want the time since the last one.
+ time_since_aloha_update = sec_now()-(aloha_time-ALOHA_CALC_INTERVAL);
+
+
+ hours = time_since_aloha_update/3600;
+ time_since_aloha_update -= hours*3600;
+ minutes = time_since_aloha_update/60;
+
+ if (hours == 1)
+ xastir_snprintf(Hours,sizeof(Hours),"%s",
+ langcode("TIME003")); // Hour
+ else
+ xastir_snprintf(Hours,sizeof(Hours),"%s",
+ langcode("TIME004")); // Hours
+
+
+ if (minutes == 1)
+ xastir_snprintf(Minutes,sizeof(Minutes),"%s",
+ langcode("TIME005")); // Minute
+ else
+ xastir_snprintf(Minutes,sizeof(Minutes),"%s",
+ langcode("TIME006")); // Minutes
+
+ // Build up the whole format string
+ // "Aloha radius %d"
+ xastir_snprintf(format,sizeof(format),"%s",langcode("WPUPALO001"));
+ strncat(format,"\n",sizeof(format) - 1 - strlen(format));
+ // "Stations inside...: %d"
+ strncat(format,langcode("WPUPALO002"),sizeof(format) - 1 - strlen(format));
+ strncat(format,"\n",sizeof(format) - 1 - strlen(format));
+ //" Digis: %d"
+ strncat(format,langcode("WPUPALO003"),sizeof(format) - 1 - strlen(format));
+ strncat(format,"\n",sizeof(format) - 1 - strlen(format));
+ //" Mobiles (in motion): %d"
+ strncat(format,langcode("WPUPALO004"),sizeof(format) - 1 - strlen(format));
+ strncat(format,"\n",sizeof(format) - 1 - strlen(format));
+ //" Mobiles (other): %d"
+ strncat(format,langcode("WPUPALO005"),sizeof(format) - 1 - strlen(format));
+ strncat(format,"\n",sizeof(format) - 1 - strlen(format));
+ //" WX stations: %d"
+ strncat(format,langcode("WPUPALO006"),sizeof(format) - 1 - strlen(format));
+ strncat(format,"\n",sizeof(format) - 1 - strlen(format));
+ //" Home stations: %d"
+ strncat(format,langcode("WPUPALO007"),sizeof(format) - 1 - strlen(format));
+ strncat(format,"\n",sizeof(format) - 1 - strlen(format));
+ //"Last calculated %s ago."
+ strncat(format,langcode("WPUPALO008"),sizeof(format) - 1 - strlen(format));
+ strncat(format,"\n",sizeof(format) - 1 - strlen(format));
+
+ // We now have the whole format string, now print using it:
+ xastir_snprintf(temp,sizeof(temp),format,
+ (english_units) ? (int)aloha_radius : (int)(aloha_radius * cvt_mi2len),
+ (english_units)?" miles":" km",
+ the_aloha_stats.total,
+ the_aloha_stats.digis,
+ the_aloha_stats.mobiles_in_motion,
+ the_aloha_stats.other_mobiles,
+ the_aloha_stats.wxs,
+ the_aloha_stats.homes,
+ hours, Hours,
+ minutes, Minutes);
+
+ popup_message_always(langcode("PULDNVI016"),temp);
+ }
+ else {
+ // Not calculated yet
+ popup_message_always(langcode("PULDNVI016"),langcode("WPUPALO666"));
+ }
+}
+
+// Debugging tool:
+// Check to see if time list contains any stations older than remove_time.
+// If the expire code did its job properly, there should be none. If there
+// are none, we return NULL. If there are any, we return the pointer to the
+// last one found (which should be the newest of them by virtue of how we
+// walk the list).
+DataRow * sanity_check_time_list(time_t remove_time) {
+ DataRow *p_station, *p_station_t_newer, *retval;
+ retval=NULL;
+
+ for (p_station = t_oldest; p_station != NULL;
+ p_station = p_station_t_newer) {
+ p_station_t_newer = p_station->t_newer;
+ // Don't count my station in this.
+ if (!is_my_station(p_station) && p_station->sec_heard < remove_time) {
+ retval=p_station;
+ }
+ }
+
+ return (retval);
+}
+
+// Debugging tool
+// dump out the entire time-sorted list starting from oldest and proceeding
+// to newest
+void dump_time_sorted_list(void) {
+ DataRow *p_station, *p_station_t_newer;
+ struct tm *time;
+ fprintf(stderr,"\tTime-sorted list dump \n");
+ fprintf(stderr, "\t Call Sign:\tsec_heard\tdate/time\n");
+ for (p_station = t_oldest; p_station != NULL;
+ p_station = p_station_t_newer) {
+ p_station_t_newer = p_station->t_newer;
+ time = localtime(&p_station->sec_heard);
+
+ fprintf(stderr,"\t%s\t%ld\t%02d/%02d %02d:%02d:%02d\n",
+ p_station->call_sign, (long int) p_station->sec_heard,
+ time->tm_mon+1,time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
+ }
+}
+
+
diff --git a/src/db_gis.c b/src/db_gis.c
new file mode 100644
index 0000000..bc1245d
--- /dev/null
+++ b/src/db_gis.c
@@ -0,0 +1,2675 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: db_gis.c,v 1.27 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 2007-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+// include postgresql library for postgis support
+#ifdef HAVE_POSTGIS
+#include <libpq-fe.h>
+// pg_type.h contains constants for OID values to use in paramTypes arrays
+// in prepared queries.
+#include <pg_type.h>
+#endif // HAVE_POSTGIS
+
+// mysql error library for mysql error code constants
+#ifdef HAVE_MYSQL
+#include <my_global.h>
+#include <my_sys.h>
+#include <mysql.h>
+#include <errmsg.h>
+#include <time.h>
+#endif // HAVE_MYSQL
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+// Some systems don't have strtof
+#ifndef HAVE_STRTOF
+ #define strtof(a,b) atof(a)
+#endif
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <Xm/XmAll.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "database.h"
+#include "main.h"
+#include "util.h"
+#include "xastir.h"
+#include "db_gis.h"
+
+#ifdef HAVE_DB
+/* db_gis.c
+ *
+ * Functions supporting connections to databases, including GIS enabled
+ * databases that hold OpenGIS objects and can apply spatial indicies.
+ *
+ * XASTIR GIS database code is separated into three layers
+ *
+ * 1) Supporting XASTIR logic (ui elements, cad integration,
+ * map drawing, etc).
+ * 2a) Generic db storage/retrieval code - wrappers for layer 3
+ * 2b) Connection management code
+ * 3a) DBMS specific db storage/retrieval code for spatial databases
+ * 3b) DBMS specific db storage/retrieval code for non-spatial databases
+ *
+ * Data structures in an underlying database can be considered as a fourth
+ * level.
+ *
+ * Code for layers 2 and 3 is in this file.
+ *
+ * Layer 2 functions should be extern and called from elsewhere to
+ * perform spatial database operations. Xastir shouldn't need to care
+ * if an underlying database has spatial support or not for simple data.
+ * Some functionality might require spatial object support and might be
+ * included only if a spatial database is available. Thus 3b code may only
+ * support a subset of the 2a functions, while 3a code should support all
+ * 2a functions.
+ * Layer 2a wrappers should take and return values in xastir coordinates,
+ * and convert them to decimal degrees to pass on to layer 3. Likewise
+ * return values from layer 3 to layer 2a should be in decimal degrees,
+ * limiting the number of different places at which the xastir/decimal
+ * degree conversion code needs to be invoked. This would not be true if
+ * data are fed directly from decimal degree feeds into the database, so
+ * there may also be a need for layer 2 functions that deal only with
+ * latitude and longitude in decimal degrees.
+ *
+ * Layer 3 functions should not be extern and should only be called
+ * by layer 2 functions from within this file.
+ * Layer 3 functions should take and return values in decimal degrees.
+ * Xastir objects should be passed down into layer 3, as doing
+ * so should make code easier to maintain (but harder to extend) than using
+ * generic structures for transport of data between layers 2 and 3.
+ * Passing a station struct from layer 2 to 3 makes layer 2 a very simple
+ * wrapper, but requires new layer 3 code to write station data to a map
+ * layer rather than to a DataRow (to, for example, prepare a layer of
+ * temperature data at points for analysis and generation of a temperature
+ * grid.) [Using generic structures for transport would let the layer 3
+ * code remain unchanged while layer 2 functions are added or extended, but
+ * requires added maintainance to synchronise xastir structs, the generic
+ * structs, and database structures.]
+ *
+ * A spatially enabled database is expected to support OpenGIS spatial
+ * objects and be able to apply spatial indicies to the data. A
+ * non-spatially enabled database is expected to hold coordinates using
+ * separate fields for latitude and longitude. Layer 3 functions that
+ * interact with a spatial database will need to convert decimal degrees
+ * to well known text (WKT, and perhaps also well known binary, WKB)
+ * representations. Layer 3 functions that interact with non-spatially
+ * enabled databases can just pass raw latitudes and longitudes.
+ *
+ * All spatial data are expected to be in WGS84 projection EPSG:4326
+ *
+ * Support for five sets of underlying database schema elements is envisioned
+ * - a very simple station at point and time table
+ * - schema elements to support CAD objects with arbitrary associated data
+ * tables.
+ * - a schema capable of holding the full range of aprs data using spatial
+ * elements (Points, Polygons, etc).
+ * - full support for APRSWorld tables (using latitude and longitude fields
+ * rather than spatial elements).
+ * - arbitrary tables with schema discovery for arbitrary GIS databases
+ * such as Tiger data.
+ * The first three of these will require schema version awareness and will
+ * produce compatability/database lifecycle issues.
+ *
+ * Descriptions of how to make connections to databases are stored in
+ * connection descriptors. Connection descriptors describe the DBMS, whether
+ * the database has/lacks spatial support, the schema type (simple,
+ * simple+cad, xastir full, APRSWorld, etc for the database, and connection
+ * parameters (server, user, database). The layer 2/3 separation is intended
+ * to allow functions (layer 2) to be called from within xastir (layer 1)
+ * without the need to test which function to call for which dbms. Some
+ * functions may be schema specific, others may be able to use any of
+ * several different schemas. Connections can be opened from a database
+ * descriptor, and more than one descriptor can point to the same database.
+ * (Thus a single MySQL database may contain simple xastir tables, xastir
+ * CAD object tables, and APRSWorld tables, but two different descriptors
+ * would be used to define connections to talk to the APRSWorld tables and
+ * the simple+cad tables within what MySQL considers one schema. A given
+ * version of xastir will expect a particular version or range of versions
+ * for database schemas - an older version of xastir may expect fields that
+ * no longer exist in a database created for a newer version of xastir and
+ * vice versa.
+ *
+ * Data selected from a spatial database might be brought into xastir as
+ * stations just like an internet feed or findu fetch trail query, as
+ * editable CAD objects, or as map layers.
+ */
+
+/******************* DATABASE SUPPORT IS EXPERIMENTAL ***********************/
+/**************** CODE IN THIS FILE MAY CHANGE AT ANY TIME ******************/
+// Layer 3 declarations
+
+// xastir_dbms_type is used in interface_gui.c to set up cb_items to populate
+// database picklist. Define and internationalise here.
+char xastir_dbms_type[4][XASTIR_DB_DESCRIPTOR_MAX_SIZE+1] = {"","MySQL (lat/long)","Postgresql/Postgis","MySQL Spatial"} ;
+// xastir_schema_type is used in interface_gui.c to set up cb_item to populate
+// schema type picklist Sql_Database_schema_type_data. Define and internationalize here.
+char xastir_schema_type[5][XASTIR_SCHEMA_DESCRIPTOR_MAX_SIZE+1] = {"","Xastir Simple","Xastir CAD","Xastir Full","APRSWorld"} ;
+
+const char *POSTGIS_TIMEFORMAT = "%Y-%m-%d %H:%M:%S%z";
+const char *MYSQL_TIMEFORMAT = "%Y-%m-%d %H:%M:%S";
+
+/*
+// store integer values for picklist items, but use localized strings on picklists
+char xastir_dbms_type[3][XASTIR_DB_DESCRIPTOR_MAX_SIZE+1]; // array of xastir database type strings
+xastir_snprintf(&xastir_dbms_type[DB_MYSQL][0],
+ XASTIR_DB_DESCRIPTOR_MAX_SIZE,
+ "%s",langcode("XADBMST001"));
+xastir_snprintf(&xastir_dbms_type[DB_POSTGIS][0],
+ sizeof(&xastir_dbms_type[DB_POSTGIS][0]),
+ "%s", langcode("XADBMST002"));
+xastir_snprintf(&xastir_dbms_type[DB_MYSQL_SPATIAL][0],
+ sizeof(&xastir_dbms_type[DB_MYSQL_SPATIAL][0]),
+ "%s",langcode("XADBMST003"));
+
+char xastir_schema_type[4][XASTIR_SCHEMA_DESCRIPTOR_MAX_SIZE+1]; // array of xastir schema type strings
+xastir_snprintf(xastir_schema_type[XASTIR_SCHEMA_SIMPLE],
+ sizeof(xastir_schema_type[XASTIR_SCHEMA_SIMPLE][0]),
+ "%s",langcode ("XASCHEMA01"));
+xastir_snprintf(xastir_schema_type[XASTIR_SCHEMA_CAD][0],
+ sizeof(xastir_schema_type[XASTIR_SCHEMA_CAD][0]),
+ "%s", langcode("XASCHEMA02"));
+xastir_snprintf(xastir_schema_type[XASTIR_SCHEMA_COMPLEX][0],
+ sizeof(xastir_schema_type[XASTIR_SCHEMA_COMPLEX][0]),
+ "%s", langcode("XASCHEMA03"));
+xastir_snprintf(xastir_schema_type[XASTIR_SCHEMA_APRSWORLD],
+ sizeof(xastir_schema_type[XASTIR_SCHEMA_APRSWORLD][0]),
+ "%s", langcode("XASCHEMA04"));
+*/
+
+#ifdef HAVE_SPATIAL_DB
+#ifdef HAVE_POSTGIS
+int storeStationToGisDbPostgis(Connection *aDbConnection, DataRow *aStation);
+int storeCadToGisDbPostgis(Connection *aDbConnection, CADRow *aCadObject);
+int storeStationSimplePointToGisDbPostgis(Connection *aDbConnection, DataRow *aStation);
+int testXastirVersionPostgis(Connection *aDbConnection);
+int getAllSimplePositionsPostgis(Connection *aDbConnection);
+int getAllSimplePositionsPostgisInBoundingBox(Connection *aDbConnection, char* str_e_long, char* str_w_long, char* str_n_lat, char* str_s_lat);
+//PGconn postgres_conn_struct[MAX_DB_CONNECTIONS];
+#endif /* HAVE_POSTGIS*/
+#ifdef HAVE_MYSQL_SPATIAL
+int storeStationToGisDbMysql(Connection *aDbConnection, DataRow *aStation);
+int storeCadToGisDbMysql(Connection *aDbConnection, CADRow *aCadObject);
+int storeStationSimplePointToGisDbMysql(Connection *aDbConnection, DataRow *aStation);
+int getAllSimplePositionsMysqlSpatial(Connection *aDbConnection);
+int getAllCadFromGisDbMysql(Connection *aDbConnection);
+int getAllSimplePositionsMysqlSpatialInBoundingBox(Connection *aDbConnection, char* str_e_long, char* str_w_long, char* str_n_lat, char* str_s_lat);
+#endif /* HAVE_MYSQL_SPATIAL */
+#endif /* HAVE_SPATIAL_DB */
+//Connection connection_struc[MAX_DB_CONNECTIONS];
+Connection connections[MAX_IFACE_DEVICES];
+int connections_initialized = 0;
+#ifdef HAVE_MYSQL
+//MYSQL mysql_conn_struct, *mysql_connection = &mysql_conn_struct;
+//MYSQL mcs[MAX_DB_CONNECTIONS];
+Connection dbc_struct, *dbc = &dbc_struct;
+int testXastirVersionMysql(Connection *aDbConnection);
+int storeStationSimplePointToDbMysql(Connection *aDbConnection, DataRow *aStation);
+int getAllSimplePositionsMysql(Connection *aDbConnection);
+int getAllSimplePositionsMysqlInBoundingBox(Connection *aDbConnection, char *str_e_long, char *str_w_long, char *str_n_lat, char *str_s_lat);
+int storeStationToDbMysql(Connection *aDbConnection, DataRow *aStation);
+void mysql_interpret_error(int errorcode, Connection *aDbConnection);
+#endif /* HAVE_MYSQL*/
+
+// Layer 2a: Generic GIS db storage code. ************************************
+// Wrapper functions for actual DBMS specific actions
+
+#ifdef HAVE_SPATIAL_DB
+
+// ******** Functions that require spatialy enabled database support *********
+
+
+
+
+
+/* function storeStationToGisDb()
+ * Stores the information about a station and its most recent position
+ * to a spatial database.
+ * @param aDbConnection generic database connection to the database in
+ * which the station information is to be stored.
+ * @param aStation the station to store.
+ * @returns 0 on failure, 1 on success. On failure, stores error message
+ * in connection.
+ */
+int storeStationToGisDb(Connection *aDbConnection, DataRow *aStation) {
+ int returnvalue = 0;
+ if (aDbConnection==NULL || aStation==NULL)
+ return returnvalue;
+ // This function is dbms agnostic, and hands the call off to a
+ // function for the relevant database type. That function picks the
+ // relevant schema and either handles the query or passes it on to
+ // a function to handle that schema.
+
+
+
+ switch (aDbConnection->type) {
+ #ifdef HAVE_POSTGIS
+ case DB_POSTGIS :
+ returnvalue = storeStationToGisDbPostgis(aDbConnection, aStation);
+ break;
+ #endif /* HAVE_POSTGIS */
+ #ifdef HAVE_MYSQL_SPATIAL
+ case DB_MYSQL_SPATIAL :
+ returnvalue = storeStationToGisDbMysql(aDbConnection, aStation);
+ break;
+ #endif /* HAVE_MYSQL_SPATIAL */
+ #ifdef HAVE_MYSQL
+ case DB_MYSQL :
+ returnvalue = storeStationToDbMysql(aDbConnection, aStation);
+ break;
+ #endif /* HAVE_MYSQL*/
+ }
+ return returnvalue;
+}
+
+
+
+
+
+
+/* function storeCadToGisDb()
+ * Stores current data about objects (including CAD objects) and their
+ * most recent positions to a spatial database. Objects are treated as
+ * points
+*/
+int storeCadToGisDb(Connection *aDbConnection, CADRow *aCadObject) {
+ int returnvalue = 0;
+ if (aDbConnection==NULL || aCadObject==NULL)
+ return returnvalue;
+
+
+ // check that connection has cad support in schema
+ return returnvalue;
+}
+
+
+
+
+
+
+/* function storeStationTrackToGisDb()
+ * Stores information about a station and track of all recieved positions from
+ * that station (including weather information if present) to a spatial
+ * database.
+ * @param aDbConnection generic database connection to the database in
+ * which the station information is to be stored.
+ * @param aStation the station to store.
+ * @returns 0 on failure, 1 on success. On failure, stores error message
+ * in connection.
+ */
+int storeStationTrackToGisDb(Connection *aDbConnection, DataRow *aStation) {
+ int returnvalue = 0;
+ if (aDbConnection==NULL || aStation==NULL)
+ return returnvalue;
+
+ return returnvalue;
+}
+
+
+
+
+
+
+#endif /* HAVE_SPATIAL_DB */
+
+
+
+
+
+// ***** Functions that do not require spatialy enabled database support ******
+// Include "Simple" in these function names. They should only deal with point
+// data, not polygons or complex spatial objects. Station positions and times
+// demarking implicit tracks should be ok.
+
+
+
+
+
+
+/* function storeStationSimpleToGisDb()
+ * Stores basic information about a station and its most recent position
+ * to a spatial database. Stores only callsign, most recent position,
+ * and time. Intended for testing and simple logging uses.
+ * Underlying table should have structure:
+ * create table simpleStation (
+ * simpleStationId int primary key not null auto_increment
+ * station varchar(9) not null, // max_callsign
+ * time date not null default now(),
+ * position POINT // or latitude float, longitude float for simple db.
+ * );
+ **** or perhaps it should be an APRSWorld table?? ****
+ **** or perhaps it should be an APRSWorld table, but with POINT when supported?? ****
+ *
+ * ********* generalize to lat/lon fields or position POINT. ******
+ * @param aDbConnection generic database connection to the database in
+ * which the station information is to be stored.
+ * @param aStation the station to store.
+ * @returns 0 on failure, 1 on success. On failure, stores error message
+ * in connection.
+ */
+int storeStationSimpleToGisDb(Connection *aDbConnection, DataRow *aStation) {
+ int returnvalue = 0;
+ int triedDatabase = 0;
+ if (debug_level & 4096)
+ fprintf(stderr,"in storeStationSimpleToGisDb() ");
+ if (aDbConnection==NULL || aStation==NULL)
+ return returnvalue;
+ if (aStation->data_via == DATA_VIA_DATABASE) {
+ if (debug_level & 4096)
+ fprintf(stderr,"skipping station heard from Database\n");
+ returnvalue = 1;
+ return returnvalue;
+ }
+ if (debug_level & 4096)
+ fprintf(stderr,"with connection->type: %d\n",aDbConnection->type);
+
+ switch (aDbConnection->type) {
+ #ifdef HAVE_POSTGIS
+ case DB_POSTGIS :
+ returnvalue = storeStationSimplePointToGisDbPostgis(aDbConnection, aStation);
+ triedDatabase++;
+ break;
+ #endif /* HAVE_POSTGIS */
+ #ifdef HAVE_MYSQL_SPATIAL
+ case DB_MYSQL_SPATIAL :
+ returnvalue = storeStationSimplePointToGisDbMysql(aDbConnection, aStation);
+ triedDatabase++;
+ break;
+ #endif /* HAVE_MYSQL_SPATIAL */
+ #ifdef HAVE_MYSQL
+ case DB_MYSQL :
+ returnvalue = storeStationSimplePointToDbMysql(aDbConnection, aStation);
+ triedDatabase++;
+ break;
+ #endif /* HAVE_MYSQL*/
+ }
+ if (triedDatabase==0) {
+ }
+ return returnvalue;
+}
+
+
+
+
+
+
+/* function getAllSimplePositions()
+ * Given a database connection, return all simple station positions stored in
+ * that database.
+ */
+int getAllSimplePositions(Connection *aDbConnection) {
+ int returnvalue = 0;
+ int triedDatabase = 0;
+ if (aDbConnection==NULL)
+ return returnvalue;
+ if (debug_level & 4096) {
+ fprintf(stderr,"in getAllSimplePositions ");
+ fprintf(stderr,"with aDbConnection->type %d\n",aDbConnection->type);
+ }
+
+ switch (aDbConnection->type) {
+ #ifdef HAVE_POSTGIS
+ case DB_POSTGIS :
+ //fprintf(stderr,"connection [%p]\n",aDbConnection);
+ //fprintf(stderr,"connection->phandle [%p]\n",aDbConnection->phandle);
+ returnvalue = getAllSimplePositionsPostgis(aDbConnection);
+ triedDatabase++;
+ break;
+ #endif /* HAVE_POSTGIS */
+ #ifdef HAVE_MYSQL_SPATIAL
+ case DB_MYSQL_SPATIAL :
+ returnvalue = getAllSimplePositionsMysqlSpatial(aDbConnection);
+ triedDatabase++;
+ break;
+ #endif /* HAVE_MYSQL_SPATIAL */
+ #ifdef HAVE_MYSQL
+ case DB_MYSQL :
+ returnvalue = getAllSimplePositionsMysql(aDbConnection);
+ triedDatabase++;
+ break;
+ #endif /* HAVE_MYSQL*/
+ }
+ if (triedDatabase==0) {
+ }
+ return returnvalue;
+}
+
+
+
+
+
+/* function getAllSimplePositionsInBoundingBox()
+ * Given a database connection and a bounding box, return all simple station
+ * positions stored in that database that fall within the bounds of the box.
+ * Takes eastern, western, northern, and southern bounds of box in xastir
+ * coordinates.
+ */
+int getAllSimplePositionsInBoundingBox(Connection *aDbConnection, int east, int west, int north, int south) {
+ int returnvalue = 0;
+ int triedDatabase = 0;
+ char str_e_long[11];
+ char str_n_lat[10];
+ char str_w_long[11];
+ char str_s_lat[10];
+ if (aDbConnection==NULL)
+ return returnvalue;
+ // convert from xastir coordinates to decimal degrees
+ convert_lon_l2s(east, str_e_long, sizeof(str_e_long), CONVERT_DEC_DEG);
+ convert_lat_l2s(north, str_n_lat, sizeof(str_n_lat), CONVERT_DEC_DEG);
+ convert_lon_l2s(west, str_w_long, sizeof(str_w_long), CONVERT_DEC_DEG);
+ convert_lat_l2s(south, str_s_lat, sizeof(str_s_lat), CONVERT_DEC_DEG);
+ switch (aDbConnection->type) {
+ #ifdef HAVE_POSTGIS
+ case DB_POSTGIS :
+ returnvalue = getAllSimplePositionsPostgisInBoundingBox(aDbConnection,str_e_long,str_w_long,str_n_lat,str_s_lat);
+ triedDatabase++;
+ break;
+ #endif /* HAVE_POSTGIS */
+ #ifdef HAVE_MYSQL_SPATIAL
+ case DB_MYSQL_SPATIAL :
+ returnvalue = getAllSimplePositionsMysqlSpatialInBoundingBox(aDbConnection,str_e_long,str_w_long,str_n_lat,str_s_lat);
+ triedDatabase++;
+ break;
+ #endif /* HAVE_MYSQL_SPATIAL */
+ #ifdef HAVE_MYSQL
+ case DB_MYSQL :
+ returnvalue = getAllSimplePositionsMysqlInBoundingBox(aDbConnection,str_e_long,str_w_long,str_n_lat,str_s_lat);
+ triedDatabase++;
+ break;
+ #endif /* HAVE_MYSQL*/
+ }
+ if (triedDatabase==0) {
+ }
+ return returnvalue;
+}
+
+
+// Layer 2b: Connection managment. *******************************************
+/* It should be possible to maintain a list of an arbitrary number of defined
+ * data sources of different types, and to have an arbitrary number of
+ * connections to these data sources open at the same time.
+ *
+ * Some issues: How to handle login credentials for databases? Request on
+ * connection? How to perform multiple operations with the same datasource
+ * (e.g. logging to the database from feeds while querying CAD objects).
+ * Probably want to be able to store password, request password on connect,
+ * or use configuration file (e.g. my.ini) for password) - let user tune
+ * choices to environment.
+ *
+ * The existing interface code seems better suited to having a fixed number
+ * of interfaces with zero or one database connection associated with each
+ * interface than handing an arbitrary number of connections per interface.
+ */
+
+
+
+// simple testing hardcoded database connection testing function
+// remove this function and call in main.c when integration with
+// interfaces is working.
+// fill in password, uncomment, and uncomment code in main.c for
+// simple database write test - writes station in n_first to simple mysql db
+/*
+ioparam simpleDbTest(void) {
+ ioparam test;
+ Connection conn;
+ int ok;
+ xastir_snprintf(test.device_name, sizeof(test.device_name), "Test Connection");
+ test.database_type = DB_MYSQL;
+ xastir_snprintf(test.device_host_name, sizeof(test.device_host_name), "localhost");
+ test.sp = 3306;
+ xastir_snprintf(test.database_username, sizeof(test.database_username), "xastir_test");
+ // hardcode a test password here for simple test
+ xastir_snprintf(test.device_host_pswd, sizeof(test.device_host_pswd), "hardcoded test password");
+ xastir_snprintf(test.database_schema, sizeof(test.database_schema), "xastir");
+ test.database_schema_type = XASTIR_SCHEMA_SIMPLE;
+ xastir_snprintf(test.database_unix_socket, sizeof(test.database_unix_socket), "/var/lib/mysql/mysql.sock");
+
+ got_conn=openConnection(&test, conn);
+ ok = storeStationSimpleToGisDb(&conn, n_first);
+
+ return test;
+}
+*/
+
+
+int initConnections() {
+ int x;
+ if (debug_level & 4096)
+ fprintf(stderr,"initConnections()\n");
+ for (x=0;x<MAX_IFACE_DEVICES;x++) {
+ initAConnection(&connections[x], x);
+ }
+ if (debug_level & 4096) {
+ for (x=0;x<MAX_IFACE_DEVICES;x++) {
+ #ifdef HAVE_POSTGIS
+ fprintf(stderr,"Initialized connection %d [%p] type=%d phandle=[%p]\n",x,&connections[x],connections[x].type,connections[x].phandle);
+ #endif /* HAVE_POSTGIS */
+ #ifdef HAVE_MYSQL
+ fprintf(stderr,"Initialized connection %d mhandle=[%p]\n",x,&connections[x].mhandle);
+ #endif /* HAVE_MYSQL */
+ }
+ }
+ return 1;
+}
+
+/* Function initAConnections()
+ * Given a connection structure, initialize the storage for the
+ * database connections, link the connection to the relevant
+ * interface, and set default values for other parameters. */
+int initAConnection(Connection *connection, int x) {
+ int y;
+ connection->descriptor = &devices[x];
+ connection->type = 0; // assign no type by default
+ connection->interface_number = x; // so we can reference port_data[] from a connection
+ // without knowing the connection's position in
+ // connections[]
+ // malloc for the PGconn will cause segfault on trying to
+ // open the connection
+#ifdef HAVE_POSTGIS
+ connection->phandle = (PGconn*)malloc(sizeof(PGconn*));
+#endif /* HAVE_POSTGIS */
+#ifdef HAVE_MYSQL
+ //connection->mhandle = (MYSQL)malloc(sizeof(MYSQL));
+ mysql_init(&connection->mhandle);
+#endif /* HAVE_MYSQL */
+ for(y=0;y<MAX_CONNECTION_ERROR_MESSAGE;y++) {
+ connection->errormessage[y]=' ';
+ }
+ connection->errormessage[MAX_CONNECTION_ERROR_MESSAGE-1]='\0';
+ if (debug_level & 4096) {
+ fprintf(stderr,"initAConnection() [%d]\n",x);
+ }
+ return 1;
+}
+
+/* Function openConnection()
+ * Opens the specified database connection.
+ * @param anIface a database connection description (host username etc).
+ * @param connection a generic database connection for which the
+ * appropriate MySQL or Postgresql connection handle will be used
+ * for the open connection on success.
+ * @returns 0 on any error, 1 for successful connection
+ * on connection failure, returns 0 and sets error message in
+ * the connection descriptor.
+ */
+int openConnection(ioparam *anIface, Connection *connection) {
+ int returnvalue = 0;
+ int connection_made = 0;
+ #ifdef HAVE_POSTGIS
+ char connection_string[900];
+ int connected; // status of connection polling loop
+ time_t start_time;
+ PGconn *postgres_connection;
+ PostgresPollingStatusType poll;
+ #endif /* HAVE_POSTGIS */
+ #ifdef HAVE_MYSQL
+ unsigned long client_flag = 0; // parameter used for mysql connection, is normally 0.
+ unsigned int port; // port to make connection on
+ #endif /* HAVE_MYSQL */
+
+
+ if (anIface==NULL) {
+ fprintf(stderr,"Null iface\n");
+ return returnvalue;
+ }
+ if (anIface==NULL || connection==NULL) {
+ fprintf(stderr,"Null connection\n");
+ return returnvalue;
+ }
+ if (debug_level & 4096) {
+ fprintf(stderr,"opening connection [%p] \n",connection);
+ }
+// #ifdef HAVE_MYSQL
+// switch (anIface->database_type) {
+// #ifdef HAVE_MYSQL_SPATIAL
+// case DB_MYSQL_SPATIAL :
+// #endif /* HAVE_MYSQL_SPATIAL */
+// #ifdef HAVE_MYSQL
+// case DB_MYSQL :
+// #endif /* HAVE_MYSQL */
+// // instantiate the MYSQL structure for the connection
+// //fprintf(stderr,"calling mysql_init\n");
+// //connection->mhandle = mysql_init(&connection->mhandle);
+// //fprintf(stderr,"called mysql_init\n");
+// }
+// #endif /* HAVE_MYSQL */
+ // clear any existing error message
+ xastir_snprintf(anIface->database_errormessage, sizeof(anIface->database_errormessage), " ");
+ if (debug_level & 4096)
+ fprintf(stderr,"Entering openConnection with anIface [%p] and conn [%p]\n",anIface,connection);
+
+ connection->type = anIface->database_type;
+ //connection->descriptor = anIface;
+
+ if (connections_initialized == 0) {
+ connections_initialized = initConnections();
+ connections_initialized = 1;
+ }
+
+ // TODO: need some sort of connection listener to handle reconnection attempts when a connection fails...
+
+ // try to open connection
+ if (!(anIface==NULL)) {
+ switch (anIface->database_type) {
+ #ifdef HAVE_POSTGIS
+ case DB_POSTGIS :
+ if (debug_level & 4096)
+ fprintf(stderr,"Opening Connection to a Postgresql/Postgis database.\n");
+ // If type is postgis, connect to postgis database.
+ // build connection string from parameters
+ xastir_snprintf(connection_string, sizeof(connection_string), \
+ "host=%s user=%s password=%s dbname=%s port=%d", \
+ anIface->device_host_name, anIface->database_username, anIface->device_host_pswd, anIface->database_schema, anIface->sp);
+ // Use nonblocking connection (connectStart and connectPoll)
+ //connection->phandle = PQconnectStart(connection_string);
+ postgres_connection = PQconnectStart(connection_string);
+ //if (connection->phandle == NULL) {
+ if (postgres_connection == NULL) {
+ xastir_snprintf(anIface->database_errormessage, sizeof(anIface->database_errormessage), "Insufficient memory to open connection.");
+ } else {
+ connected = 0;
+ // can connect, run PQ_connect_poll loop
+ // Note: xastir needs to decide when to time out
+ start_time = sec_now();
+ statusline("Connecting to Postgresql database",1);
+ while ((connected==0) & (sec_now()<(start_time+30))) {
+ // need to add a timer to polling loop
+ //poll = PQconnectPoll(connection->phandle);
+ poll = PQconnectPoll(postgres_connection);
+ if (poll == PGRES_POLLING_FAILED || poll == PGRES_POLLING_OK) {
+ connected = 1;
+ }
+ // add connection status feedback here if desired
+ }
+ //if (PQstatus(connection->phandle)==CONNECTION_OK) {
+ if (PQstatus(postgres_connection)==CONNECTION_OK) {
+ if (debug_level & 4096)
+ fprintf(stderr,"Connected to Postgresql database on %s\n",anIface->device_host_name);
+ // connection successfull
+ connection->phandle = postgres_connection;
+ connection->type=DB_POSTGIS;
+ //connection->descriptor = anIface;
+ xastir_snprintf(connection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, " ");
+ connection_made = 1;
+ } else {
+ // connection attempt failed
+ fprintf(stderr,"Failed to connect to Postgresql database on %s\n",anIface->device_host_name);
+ fprintf(stderr,"Postgres Error: %s\n", PQerrorMessage(postgres_connection));
+ xastir_snprintf(anIface->database_errormessage, sizeof(anIface->database_errormessage), "Unable to make Postgresql connection %s. %s", PQerrorMessage(postgres_connection), connection_string);
+ }
+ }
+ break;
+ #endif /* HAVE_POSTGIS */
+ #ifdef HAVE_MYSQL_SPATIAL
+ case DB_MYSQL_SPATIAL :
+ // if type is mysql (=>4.1), connect to mysql database
+ if (debug_level & 4096)
+ fprintf(stderr,"Opening connection to a MySQL (spatial) database.\n");
+ if (&connection->mhandle == NULL) {
+ // insufficient memory to initalize a new database handle
+ xastir_snprintf(anIface->database_errormessage, sizeof(anIface->database_errormessage), "Insufficient memory to open connection.");
+ } else {
+ port = anIface->sp;
+ statusline("Connecting to MySQL database",1);
+ if (debug_level & 4096)
+ fprintf(stderr,"Opening connection to %s.\n",anIface->device_host_name);
+ mysql_real_connect(&connection->mhandle, anIface->device_host_name, anIface->database_username, anIface->device_host_pswd, anIface->database_schema, port, anIface->database_unix_socket, client_flag);
+ //MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag)
+ if (&connection->mhandle == NULL) {
+ // unable to establish connection
+ xastir_snprintf(anIface->database_errormessage, sizeof(anIface->database_errormessage), "Unable to establish connection: %s", mysql_error(&connection->mhandle));
+ fprintf(stderr,"Failed to connect to MySQL database on %s\n",anIface->device_host_name);
+ fprintf(stderr, "MySQL Error: %s", mysql_error(&connection->mhandle));
+ } else {
+
+// mysql_real_connect is coming back with non-null failed connection.
+
+ // connected to database
+ // make sure error message for making connection is empty.
+ xastir_snprintf(anIface->database_errormessage, sizeof(anIface->database_errormessage), " ");
+ xastir_snprintf(connection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, " ");
+
+ // ping the server
+ if (mysql_ping(&connection->mhandle)==0) {
+ fprintf(stderr,"mysql ping ok [0]\n");
+ connection_made = 1;
+ // store connection information
+ connection->type = DB_MYSQL_SPATIAL;
+ //connection->descriptor = anIface;
+ if (debug_level & 4096)
+ fprintf(stderr,"Connected to MySQL database, connection stored\n");
+ } else {
+ fprintf(stderr,"mysql ping failed [1]\n");
+ fprintf(stderr,"Can't connect to MySQL database: Can't ping server.\n");
+ xastir_snprintf(anIface->database_errormessage, sizeof(anIface->database_errormessage), "Unable to ping MySQL server. Server may be down. Check connection paramenters.");
+ }
+ }
+ }
+ break;
+ #endif /* HAVE_MYSQL_SPATIAL */
+ #ifdef HAVE_MYSQL
+ case DB_MYSQL :
+ // if type is mysql (<4.1), connect to mysql database
+ if (debug_level & 4096)
+ fprintf(stderr,"Opening connection to a MySQL database.\n");
+ if (&connection->mhandle == NULL) {
+ // insufficient memory to initalize a new database handle
+ xastir_snprintf(anIface->database_errormessage, sizeof(anIface->database_errormessage), "Insufficient memory to open connection.");
+ fprintf(stderr,"Insufficient memory to open mysql connection [mysql_init(*MYSQL) returned null].\n");
+ } else {
+ client_flag = CLIENT_COMPRESS;
+ port = anIface->sp;
+// **** fails if database_unix_socket doesn't exist
+ mysql_real_connect(&connection->mhandle, anIface->device_host_name, anIface->database_username, anIface->device_host_pswd, anIface->database_schema, port, anIface->database_unix_socket, client_flag);
+ if (&connection->mhandle == NULL) {
+ fprintf(stderr,"Unable to establish connection to MySQL database\nHost: %s Schema: %s Username: %s\n",anIface->device_host_name, anIface->database_schema, anIface->database_username);
+ // unable to establish connection
+ xastir_snprintf(anIface->database_errormessage, sizeof(anIface->database_errormessage), "Unable to establish MySQL connection. Host: %s Username: %s Password: %s Schema %s Port: %d", anIface->device_host_name, anIface->database_username, anIface->device_host_pswd, anIface->database_schema, port);
+ fprintf(stderr,"Failed to connect to MySQL database on %s\n",anIface->device_host_name);
+ fprintf(stderr, "MySQL Error: %s", mysql_error(&connection->mhandle));
+ } else {
+ fprintf(stderr,"Connected to MySQL database on %s\n",anIface->device_host_name);
+ // connected to database
+ // make sure error message for making connection is empty.
+ xastir_snprintf(anIface->database_errormessage, sizeof(anIface->database_errormessage), " ");
+ xastir_snprintf(connection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, " ");
+
+ // ping the server
+ if (mysql_ping(&connection->mhandle)==0) {
+ fprintf(stderr,"mysql ping ok [0]\n");
+ connection_made = 1;
+ // store connection information
+ connection->type = DB_MYSQL;
+ //connection->descriptor = anIface;
+ if (debug_level & 4096)
+ fprintf(stderr,"Connected to MySQL database, connection stored\n");
+ } else {
+ fprintf(stderr,"mysql ping failed [1]\n");
+ xastir_snprintf(anIface->database_errormessage, sizeof(anIface->database_errormessage), "Unable to ping MySQL server. Server may be down. Check connection paramenters.");
+ fprintf(stderr,"Can't connect to MySQL database: Can't ping server.\n");
+ }
+ }
+ }
+ break;
+ #endif /* HAVE_MYSQL*/
+ } /* end switch */
+ } /* end test for null interface */
+
+ if (connection_made==1) {
+ if (debug_level & 4096) {
+ fprintf(stderr,"Connection made: ");
+ fprintf(stderr,"connection->type [%d]\n",connection->type);
+ }
+ if (testConnection((Connection*)connection)==True) {
+ returnvalue = 1;
+ statusline("Connected to database",1);
+ } else {
+ statusline("Incompatable database schema",1);
+ fprintf(stderr,"Connection OK, but incompatable schema. [%s]\n",connection->errormessage);
+ xastir_snprintf(anIface->database_errormessage, sizeof(anIface->database_errormessage), "%s",connection->errormessage);
+ closeConnection(connection,-1);
+ //free(connection);
+ }
+ } else {
+ // Detailed error message should have been returned above, but make sure
+ // there is at least a minimal failure message regardless of the problem.
+ statusline("Failed to connect to database",1);
+ fprintf(stderr,"Failed to make database connection.\n");
+ //free(connection); // not pointing to the right thing ??
+ port_data[connection->interface_number].status = DEVICE_ERROR;
+ }
+ return returnvalue;
+}
+
+
+
+
+
+/* Function closeConnection()
+ * Closes the specified database connection.
+ * @param aDbConnection a generic database connection handle.
+ */
+int closeConnection(Connection *aDbConnection, int port_number) {
+ //ioparam db = aDbConnection->descriptor;
+fprintf(stderr,"Closing connection on port %d\n",port_number);
+ if (aDbConnection==NULL)
+ return 0;
+ // free up connection resources
+ switch (aDbConnection->type) {
+ #ifdef HAVE_POSTGIS
+ case DB_POSTGIS :
+fprintf(stderr,"Connection type is postgis.\n");
+ // if type is postgis, close connection to postgis database
+ if (aDbConnection->phandle!=NULL) {
+ if (port_data[port_number].status==DEVICE_UP) {
+ PQfinish(aDbConnection->phandle);
+ }
+ //free(aDbConnection->phandle);
+ }
+ break;
+ #endif /* HAVE_POSTGIS */
+ #ifdef HAVE_MYSQL_SPATIAL
+ case DB_MYSQL_SPATIAL :
+ // if type is mysql, close connection to mysql database
+ if (&aDbConnection->mhandle!=NULL) {
+ if (debug_level & 4096) {
+ fprintf(stderr,"Connection type to close is mysql spatial.\n");
+ fprintf(stderr,"mysql_stat [%s]\n",mysql_stat(&aDbConnection->mhandle));
+ }
+ mysql_close(&aDbConnection->mhandle);
+ //free(aDbConnection->mhandle);
+ }
+ break;
+ #endif /* HAVE_MYSQL_SPATIAL */
+ #ifdef HAVE_MYSQL
+ case DB_MYSQL :
+fprintf(stderr,"Connection type is mysql.\n");
+ // if type is mysql, close connection to mysql database
+ if (&aDbConnection->mhandle!=NULL) {
+ mysql_close(&aDbConnection->mhandle);
+ //free(aDbConnection->mhandle);
+ }
+ break;
+ #endif /* HAVE_MYSQL*/
+ }
+
+ return 1;
+}
+
+
+
+
+
+/* Tests a database connection to see if the server is responding.
+ * @param aDbConnection pointer to a generic connection handle.
+ * @returns 0 on any error, 1 for successful ping.
+ */
+int pingConnection(Connection *aDbConnection) {
+ int returnvalue = True;
+ int dbreturn;
+ #ifdef HAVE_POSTGIS
+ ConnStatusType psql_status;
+ #endif /* HAVE_POSTGIS */
+
+ if (aDbConnection==NULL)
+ return 0;
+
+ if (debug_level & 4096) {
+ fprintf(stderr,"Pinging database server type=[%d]\n",aDbConnection->type);
+ //} else {
+ //fprintf(stderr,"Pinging database server.\n");
+ }
+
+ switch (aDbConnection->type) {
+ #ifdef HAVE_POSTGIS
+ case DB_POSTGIS:
+ returnvalue = False;
+ // is the connection open [required]
+ if (aDbConnection->phandle!=NULL) {
+ psql_status = PQstatus(aDbConnection->phandle);
+ if (psql_status!=CONNECTION_OK) {
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Postgresql connection failed");
+ fprintf(stderr, "PQstatus returned CONNECTION_BAD, probably unable to connect to server.\n");
+
+ } else {
+ if (debug_level & 4096) {
+ fprintf(stderr, "PQstatus returned CONNECTION_OK.\n");
+ }
+ returnvalue = True;
+ }
+ }
+ break;
+ #endif /* HAVE_POSTGIS */
+ #ifdef HAVE_MYSQL_SPATIAL
+ case DB_MYSQL_SPATIAL:
+ returnvalue = False;
+ // is the connection open [required]
+ if (&aDbConnection->mhandle!=NULL) {
+ // can we ping the server [required]
+ dbreturn = mysql_ping(&aDbConnection->mhandle);
+ if (dbreturn>0) {
+ mysql_interpret_error(dbreturn, aDbConnection);
+ fprintf(stderr, "MySQL Ping failed, probably unable to connect to server.\n");
+ } else {
+ if (debug_level & 4096) {
+ fprintf(stderr, "MySQL Ping OK.\n");
+ fprintf(stderr,"mysql_stat [%s]\n",mysql_stat(&aDbConnection->mhandle));
+ }
+ returnvalue = True;
+ }
+ }
+ break;
+ #endif /* HAVE_MYSQL_SPATIAL */
+ #ifdef HAVE_MYSQL
+ case DB_MYSQL:
+ // is the connection open [required]
+ if (&aDbConnection->mhandle != NULL) {
+ dbreturn = mysql_ping(&aDbConnection->mhandle);
+ if (dbreturn>0) {
+ mysql_interpret_error(dbreturn, aDbConnection);
+ fprintf(stderr, "MySQL Ping failed, probably unable to connect to server.\n");
+ } else {
+ if (debug_level & 4096) {
+ fprintf(stderr, "MySQL Ping OK.\n");
+ fprintf(stderr,"mysql_stat [%s]\n",mysql_stat(&aDbConnection->mhandle));
+ }
+ returnvalue = True;
+ }
+ }
+ break;
+ #endif /* HAVE_MYSQL*/
+ }
+ if (returnvalue==0) {
+ fprintf(stderr,"\n[%s]\n",aDbConnection->errormessage);
+ statusline("Database Ping Failed",1);
+ port_data[aDbConnection->interface_number].status = DEVICE_ERROR;
+ }
+ return returnvalue;
+}
+
+
+
+
+
+/* Tests a database connection and the underlying schema to see
+ * if the connection is open, the schema version is supported by
+ * this version of the code, and to see what permissions are
+ * available */
+int testConnection(Connection *aDbConnection){
+ int returnvalue = True;
+ int dbreturn;
+ int major_version;
+ int minor_version;
+ char warning[100];
+
+ #ifdef HAVE_POSTGIS
+ ConnStatusType psql_status;
+ PGresult *result;
+ const char *postgis_sql = "SELECT COUNT(*) FROM geometry_columns"; // test to see if schema used in connection has postgis support added
+ #endif /* HAVE_POSTGIS */
+ if (aDbConnection==NULL)
+ return 0;
+ xastir_snprintf(warning, 100, " "); // make sure warning is empty
+ switch (aDbConnection->type) {
+ #ifdef HAVE_POSTGIS
+ case DB_POSTGIS:
+ returnvalue = False;
+ // is the connection open [required]
+ if (aDbConnection->phandle!=NULL) {
+ psql_status = PQstatus(aDbConnection->phandle);
+ if (psql_status!=CONNECTION_OK) {
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Postgresql connection failed");
+ fprintf(stderr, "PQstatus returned CONNECTION_BAD, probably unable to connect to server.\n");
+
+ } else {
+ fprintf(stderr, "PQstatus returned CONNECTION_OK.\n");
+ // which version of postgresql are we running
+ dbreturn = PQserverVersion(aDbConnection->phandle);
+ major_version = dbreturn / 10000;
+ minor_version = (dbreturn - (major_version*10000)) / 100;
+ fprintf(stderr,"Postgresql version [%d] %d.%d\n",dbreturn,major_version,minor_version);
+
+ // is the database spatially enabled [required]
+ result = PQexec(aDbConnection->phandle,postgis_sql);
+ if (result==NULL) {
+ // PQexec probably couldn't allocate memory for the result set.
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Null result: %s\n",PQerrorMessage(aDbConnection->phandle));
+ fprintf(stderr, "testConnection() Null result\nPostgresql Error : %s\n",PQerrorMessage(aDbConnection->phandle));
+ } else {
+ // PQexec returned a result, but it may not be valid, check to see.
+ if (PQresultStatus(result)==PGRES_COMMAND_OK || PQresultStatus(result)==PGRES_TUPLES_OK) {
+ // PQexec returned a valid result set, meaning that a geometry_types table exists.
+
+
+ // are the needed tables present [required]
+ // check schema type (simple, simple+cad, full, aprsworld)
+ // check version of database schema for compatability
+ if (testXastirVersionPostgis(aDbConnection)==1) {
+ returnvalue = True;
+ }
+ // does the user have select privileges [required]
+ // does the user have update privileges [optional]
+ // does the user have inesrt privileges [optional]
+ // does the user have delete privileges [optional]
+ } else {
+ // schema lacks a geometry_columns table, either schema or database lacks postgis support
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "No geometry_columns table found. Is PostGIS installed and added to this schema?\n");
+ xastir_snprintf(warning, 100, "No geometry_columns table found. PostGIS may not be installed, or the schema may not have PostGIS support added.");
+ fprintf(stderr, "No geometry_columns table found.\nPostGIS may not be installed, or the schema may not have PostGIS support added.\n");
+ fprintf(stderr, "Postgresql Error : %s\n",PQerrorMessage(aDbConnection->phandle));
+ }
+ }
+ }
+ }
+ break;
+ #endif /* HAVE_POSTGIS */
+ #ifdef HAVE_MYSQL_SPATIAL
+ case DB_MYSQL_SPATIAL:
+ returnvalue = False;
+ // is the connection open [required]
+ if (&aDbConnection->mhandle!=NULL) {
+ // can we ping the server [required]
+ dbreturn = mysql_ping(&aDbConnection->mhandle);
+ if (dbreturn>0) {
+ mysql_interpret_error(dbreturn, aDbConnection);
+ fprintf(stderr,"Ping of mysql server failed.\n");
+ xastir_snprintf(warning, 100, "%s",aDbConnection->errormessage);
+
+ } else {
+ if (debug_level & 4096) {
+ fprintf(stderr,"mysql_stat [%s]\n",mysql_stat(&aDbConnection->mhandle));
+ }
+ // is the database spatially enabled [required]
+ // determine from db version >= 4.2
+ // MySQL 4.1 is past end of life, 4.2 at end of life but still in widespread use, e.g. RHEL4 (in early 2008).
+ // mysql_server_version is new to mysql 4.1, prepared queries stabilized in 4.2
+ dbreturn = mysql_get_server_version(&aDbConnection->mhandle);
+ if (dbreturn>0) {
+ major_version = dbreturn / 10000;
+ minor_version = (dbreturn - (major_version*10000)) / 100;
+ if (major_version>=5 || (major_version==4 && minor_version >=2)) {
+ fprintf(stderr,"MySQL Server version %d.%d OK.\n",major_version,minor_version);
+ // check version of database schema for compatability
+ dbreturn = testXastirVersionMysql(aDbConnection);
+ if (dbreturn==1) {
+ fprintf(stderr,"Compatible Xastir database version found on server.\n");
+
+ // are the needed tables present [required]
+ // check schema type (simple, simple+cad, full, aprsworld)
+ // does the user have select privileges [required]
+ // does the user have update privileges [optional]
+ // does the user have insert privileges [optional]
+ // does the user have delete privileges [optional]
+ returnvalue = True;
+ } else {
+ fprintf(stderr,"Xastir database version on server is not compatable with this version of Xastir.\n");
+ // aDbConnection->errormessage should have been set in testXastirVersionMysql
+ xastir_snprintf(warning, 100, "%s",aDbConnection->errormessage);
+ }
+ } else {
+ // version too low
+ fprintf(stderr,"MySQL Server version %d.%d is too low and is not supported in Xastir.\n",major_version,minor_version);
+ xastir_snprintf(warning, 100, "MySQL Server version %d.%d is too low and is not supported in Xastir.",major_version,minor_version);
+ }
+ } else {
+ // ? mysql<4.1
+ }
+ }
+ }
+ break;
+ #endif /* HAVE_MYSQL_SPATIAL */
+ #ifdef HAVE_MYSQL
+ case DB_MYSQL:
+ // is the connection open [required]
+ if (&aDbConnection->mhandle != NULL) {
+ dbreturn = mysql_ping(&aDbConnection->mhandle);
+ if (dbreturn>0) {
+ mysql_interpret_error(dbreturn, aDbConnection);
+ } else {
+ if (debug_level & 4096) {
+ fprintf(stderr,"mysql_stat [%s]\n",mysql_stat(&aDbConnection->mhandle));
+ }
+ // is the database spatially enabled [optional]
+ // determine from db version >= 4.1
+ #ifdef HAVE_MYSQL_SPATIAL
+ // mysql_server_version is new to mysql 4.1
+ dbreturn = mysql_get_server_version(&aDbConnection->mhandle);
+ #endif /* HAVE_MYSQL_SPATIAL */
+ // are the needed tables present [required]
+ // check schema type (simple, simple+cad, aprsworld)
+ // full requires objects, not supported here.
+ // check version of database schema for compatability
+ dbreturn = testXastirVersionMysql(aDbConnection);
+ // does the user have select privileges [required]
+ // does the user have update privileges [optional]
+ // does the user have insert privileges [optional]
+ // does the user have delete privileges [optional]
+ }
+ }
+ break;
+ #endif /* HAVE_MYSQL*/
+ }
+ if (returnvalue==0) {
+ fprintf(stderr,"\n[%s]\n",aDbConnection->errormessage);
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Incompatable schema: %s",warning);
+ fprintf(stderr,"\n[%s]\n",aDbConnection->errormessage);
+ // Note: Don't close connection here, we haven't handed the error to the user yet.
+ //closeConnection(aDbConnection,-1);
+ fprintf(stderr,"\n[%s]\n",aDbConnection->errormessage);
+ }
+ return returnvalue;
+}
+
+
+
+
+// Layer 3: DBMS specific db storage code *************************************
+// Functions in this section should be local to this file and not exported
+// Export functions in section 2a above.
+//
+// Layer 3a: DBMS specific GIS db storage code ********************************
+// Functions supporting queries to specific types of GIS enabled databasesa
+//
+
+#ifdef HAVE_SPATIAL_DB
+
+#ifdef HAVE_POSTGIS
+// Postgis implementation of spatial database functions
+
+
+
+
+
+/* postgresql+postgis implementation of storeStationToGisDb(). */
+int storeStationToGisDbPostgis(Connection *aDbConnection, DataRow *aStation) {
+ int returnvalue = 0;
+ //ioparam *device = aDbConnection->descriptor;
+ // check type of schema to use (XASTIR simple, full or APRSWorld)
+ switch (devices[aDbConnection->interface_number].database_schema_type) {
+ case XASTIR_SCHEMA_SIMPLE :
+ returnvalue = storeStationSimplePointToGisDbPostgis(aDbConnection,aStation);
+ break;
+ case XASTIR_SCHEMA_APRSWORLD :
+ break;
+ case XASTIR_SCHEMA_COMPLEX :
+ break;
+ // otherwise error message
+ }
+ return returnvalue;
+}
+
+
+
+
+
+/* postgresql+postgis implementation of storeCadToGisDb(). */
+int storeCadToGisDbPostgis(Connection *aDbConnection, CADRow *aCadObject) {
+ int returnvalue = 0;
+
+ return returnvalue;
+}
+
+
+
+
+
+/* function storeStationSimplePointToGisDbPostgis()
+ * Postgresql/Postgis implementation of wrapper storeStationSimplePointToGisDb().
+ * Should only be called through wrapper function. Do not call directly.
+ */
+int storeStationSimplePointToGisDbPostgis(Connection *aDbConnection, DataRow *aStation) {
+ int returnvalue = 0; // Default return value is failure.
+ int ok; // Holds results of tests when building query.
+ char wkt[MAX_WKT]; // well know text representation of latitude and longitude of point
+ char timestring[101]; // string representation of the time heard or the current time
+ char call_sign[(MAX_CALLSIGN*2)+1]; // temporary holding for escaped callsign
+ char aprs_symbol[2]; // temporary holding for escaped aprs symbol
+ char aprs_type[2]; // temporary holding for escaped aprs type
+ char special_overlay[2]; // temporary holding for escaped overlay
+ char origin[(MAX_CALLSIGN*2)+1]; // temporary holding for escaped origin
+ char node_path[(NODE_PATH_SIZE*2)+1]; // temporary holding for escaped node_path
+ char record_type[2]; // temporary holding for escaped record_type
+ //PGconn *conn = aDbConnection->phandle;
+ PGresult *prepared = NULL;
+ PGresult *result = NULL;
+ int count; // returned value from count query
+ const int PARAMETERS = 9;
+ // parameter arrays for prepared query
+ const char *paramValues[PARAMETERS];
+ // To use native Postgres POINT for position instead of postgis geometry point.
+ //const Oid paramTypes[6] = { VARCHAROID, TIMESTAMPTZOID, POINTOID, VARCHAROID, VARCHAROID, VARCHAROID };
+ //const Oid paramTypes[6] = { 1043, 1184, 600, 1043, 1043, 1043 };
+ // Native postgres (8.2) geometries don't have spatial support as rich as Postgis extensions.
+ // use postgis geometry Point instead:
+ // lookup OID for geometry: select OID from pg_type where typname = 'geometry'; returns 19480
+ //const Oid paramTypes[6] = { VARCHAROID, TIMESTAMPTZOID, 19480, VARCHAROID, VARCHAROID, VARCHAROID };
+ //const Oid paramTypes[6] = { 1043, 1184, 19480, 1043, 1043, 1043 };
+ // Value 18480 is probably installation specific, use unknownOID instead:
+ //const Oid paramTypes[9] = { VARCHAROID, TIMESTAMPTZOID, UNKNOWNOID, VARCHAROID, VARCHAROID, VARCHAROID, VARCHAROID, VARCHAROID, VARCHAROID };
+ const Oid paramTypes[9] = { 1043, 1184, 705, 1043, 1043, 1043, 1043, 1043, 1043 };
+ const char *sql = "insert into simpleStation (station, transmit_time, position, symbol, overlay, aprstype, origin, record_type, node_path) values ($1, $2, $3, $4, $5, $6, $7, $8, $9)";
+ const char *StatementName = "InsertSimpleStation";
+ const char *StatementExists = "select count(*) from pg_prepared_statements where name = 'InsertSimpleStation'";
+
+
+ if (debug_level & 4096) {
+ fprintf(stderr,"In postgres simple station insert\n");
+ fprintf(stderr,"with connection [%p] \n",aDbConnection);
+ fprintf(stderr,"connection->phandle [%p]\n",aDbConnection->phandle);
+ }
+ if (aDbConnection->phandle==NULL) {
+ fprintf(stderr,"Trying to save station on null postgresql connection\n");
+ return returnvalue;
+ }
+ if (PQserverVersion(aDbConnection->phandle)==0) {
+ // no connection to server
+ fprintf(stderr,"Trying to save station on closed postgresql connection\n");
+ return returnvalue;
+ }
+ if (debug_level & 4096) {
+ fprintf(stderr,"Postgresql version=%d\n",PQserverVersion(aDbConnection->phandle));
+ }
+
+ // Check to see if this prepared statement exists in the current session
+ // and create it if it does not.
+ // Query adds connection overhead - should probably track with a global variable,
+ // and query/recreate statment only on failure.
+ ok = 0;
+ // pg_prepared_statements system view added in postgresql 8.2
+ if (PQserverVersion(aDbConnection->phandle)>80199) {
+ result = PQexec(aDbConnection->phandle, "select count(*) from pg_prepared_statements where name = 'InsertSimpleStation'");
+ result = PQexec(aDbConnection->phandle, StatementExists);
+ if (result==NULL) {
+ fprintf(stderr,"Postgres Check for Prepared Query exec Failed: %s\n", PQerrorMessage(aDbConnection->phandle));
+ xastir_snprintf(aDbConnection->errormessage,MAX_CONNECTION_ERROR_MESSAGE,PQerrorMessage(aDbConnection->phandle));
+ } else {
+ count = 0;
+ if (PQresultStatus(result) == PGRES_TUPLES_OK) {
+ count = atoi(PQgetvalue(result,0,0));
+ }
+ if (count==0) {
+ // Statement doesn't exist, so prepare it, let PQprepare report on any error that got us a NULL result.
+ prepared = PQprepare(aDbConnection->phandle, StatementName, sql, PARAMETERS, paramTypes);
+ if (PQresultStatus(prepared)==PGRES_COMMAND_OK) {
+ ok = 1;
+ } else {
+ // error condition - can't prepare statement
+ fprintf(stderr,"Postgres Prepare Query Failed: %s\n", PQerrorMessage(aDbConnection->phandle));
+ xastir_snprintf(aDbConnection->errormessage,MAX_CONNECTION_ERROR_MESSAGE,PQerrorMessage(aDbConnection->phandle));
+ exit(1);
+
+ }
+ } else if (count==1) {
+ // prepared statement exists, we can go ahead with query.
+ ok = 1;
+ } else {
+ fprintf(stderr,"Postgres Check for Prepared Query getvalue (count=%d) failed: %s\n",count, PQresultErrorMessage(result));
+ xastir_snprintf(aDbConnection->errormessage,MAX_CONNECTION_ERROR_MESSAGE,PQresultErrorMessage(result));
+ }
+ }
+ } else {
+ prepared = PQprepare(aDbConnection->phandle, StatementName, sql, PARAMETERS, paramTypes);
+ ok = 1;
+ }
+ if (ok==1) {
+ // native postgis POINT is (99.999 099.999) instead of POINT (99.999 099.999)
+ // ok = xastirCoordToLatLongPosgresPoint(aStation->coord_lon, aStation->coord_lat, wkt);
+ //
+ // Prepared query is ready, get and fill in the parameter values
+ // from the station provided, then fire the query.
+ ok = xastirCoordToLatLongWKT(aStation->coord_lon, aStation->coord_lat, wkt);
+ if (ok==1) {
+ // Postgresql 8 documentation indicates that escape string should not be performed
+ // when calling PQexecParams or its sibling routines, not explicit, but implication
+ // is that PQexecPrepared with passed parameters is a sibling routine and we
+ // shouldn't be running PQescapeStringConn() on the parameters.
+ // If used, form would be:
+ // PQescapeStringConn(conn,call_sign,aStation->call_sign,(MAX_CALLSIGN*2)+1,escape_error);
+ xastir_snprintf(call_sign,MAX_CALLSIGN+1,"%s",aStation->call_sign);
+ if (strlen(aStation->origin) > 0) {
+ xastir_snprintf(origin,sizeof(origin),"%s",aStation->origin);
+ } else {
+ xastir_snprintf(origin,1,"%c",'\0');
+ }
+ xastir_snprintf(record_type,2,"%c",aStation->record_type);
+ if (aStation->node_path_ptr==NULL) {
+ xastir_snprintf(node_path,2," ");
+ } else {
+ xastir_snprintf(node_path,sizeof(node_path),"%s",aStation->node_path_ptr);
+ }
+ if (debug_level & 4096) {
+ fprintf(stderr,"node_path (12345678901234567890123456789012345678901234567890123456)\n");
+ fprintf(stderr,"node_path = [%s]\n",node_path);
+ }
+ // Get time in seconds, adjust to datetime
+ // If aStation is my station or another unset sec_heard is
+ // encountered, use current time instead. Conversely, use time
+ // provided in sec_heard if sec_heard is an invalid time.
+ get_iso_datetime(aStation->sec_heard,timestring,True,False);
+
+ // set parameter values to call, transmit_time, and position
+ paramValues[0]=call_sign;
+ paramValues[1]=timestring;
+ paramValues[2]=wkt;
+ if (aStation->aprs_symbol.aprs_symbol==NULL) {
+ xastir_snprintf(aprs_symbol,2," ");
+ paramValues[3]=&aprs_symbol;
+ } else {
+ xastir_snprintf(aprs_symbol,2,"%c",aStation->aprs_symbol.aprs_symbol);
+ paramValues[3]=aprs_symbol;
+ }
+ if (aStation->aprs_symbol.special_overlay==NULL) {
+ xastir_snprintf(special_overlay,2," ");
+ paramValues[4]=&special_overlay;
+ } else {
+ xastir_snprintf(special_overlay,2,"%c",aStation->aprs_symbol.special_overlay);
+ paramValues[4]=&special_overlay;
+ }
+ if (aStation->aprs_symbol.aprs_type==NULL) {
+ xastir_snprintf(aprs_type,2," ");
+ paramValues[5]=&aprs_type;
+ } else {
+ xastir_snprintf(aprs_type,2,"%c",aStation->aprs_symbol.aprs_type);
+ paramValues[5]=aprs_type;
+ }
+ paramValues[6]=origin;
+ paramValues[7]=record_type;
+ paramValues[8]=node_path;
+
+ if (debug_level & 4096) {
+ fprintf(stderr,"Inserting: Call: %s, Time: %s, Position: %s, Symbol:%s,%s,%s Origin:%s, Node_path:%s, Record type:%s\n",paramValues[0],paramValues[1],paramValues[2],paramValues[3],paramValues[4],paramValues[5],paramValues[6],paramValues[8],paramValues[7]);
+ }
+
+ // send query
+ result = PQexecPrepared(aDbConnection->phandle,StatementName,PARAMETERS,paramValues,NULL,NULL,POSTGRES_RESULTFORMAT_TEXT);
+ if (PQresultStatus(result)!=PGRES_COMMAND_OK) {
+ fprintf(stderr,"Postgres Insert query failed:%s\n",PQresultErrorMessage(result));
+ // error, get error message.
+ xastir_snprintf(aDbConnection->errormessage,MAX_CONNECTION_ERROR_MESSAGE,PQresultErrorMessage(result));
+ } else {
+ // query was successfull
+ returnvalue=1;
+ }
+ } else {
+ // problem with coordinates of station
+ fprintf(stderr,"Unable to save station to Postgres db, Error converting latitude or longitude from xastir coordinates\n");
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Error converting latitude or longitude from xastir coordinates: %ld,%ld",aStation->coord_lat,aStation->coord_lon);
+ }
+ }
+ if (result!=NULL)
+ PQclear(result);
+ if (prepared!=NULL)
+ PQclear(prepared);
+ return returnvalue;
+}
+
+
+
+
+
+/* function testXastirVersionPostgis()
+ * Postgresql/Postgis implementation of wrapper testXastirVersionPostgis().
+ * Should only be called through wrapper function. Do not call directly.
+ */
+int testXastirVersionPostgis(Connection *aDbConnection) {
+ int returnvalue = 0;
+ int version_number;
+ int compatable_series;
+ const char sql[100] = "select version_number, compatable_series from version order by version_number desc limit 1";
+ PGresult *result;
+ PGconn *conn = aDbConnection->phandle;
+
+ result = PQexec(conn,sql);
+ if (result==NULL) {
+ // PQexec probably couldn't allocate memory for the result set.
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Null result: %s\n",PQerrorMessage(conn));
+ fprintf(stderr, "testXastirVersionPostgis() Null result\nPostgresql Error : %s\n",PQerrorMessage(conn));
+ } else {
+ // PQexec returned a result, but it may not be valid, check to see.
+ if (PQresultStatus(result)==PGRES_COMMAND_OK || PQresultStatus(result)==PGRES_TUPLES_OK) {
+ if (PQntuples(result)!=1) {
+ fprintf(stderr,"Version table doesn't appear to contain any rows.\n");
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Version table doesn't appear to contain any rows.");
+ } else {
+ version_number = atoi(PQgetvalue(result,0,0));
+ compatable_series = atoi(PQgetvalue(result,0,1));
+ if (version_number == XASTIR_SPATIAL_DB_VERSION) {
+ returnvalue = 1;
+ } else {
+ if (version_number < XASTIR_SPATIAL_DB_VERSION && compatable_series == XASTIR_SPATIAL_DB_COMPATABLE_SERIES) {
+ returnvalue = 1;
+ fprintf(stderr,"Version in schema (%d) is compatible with this version of xastir (%d).\n",version_number,XASTIR_SPATIAL_DB_VERSION);
+ } else {
+ fprintf(stderr,"Version in schema (%d) is not compatible with this version of xastir (%d).\n",version_number,XASTIR_SPATIAL_DB_VERSION);
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Version in schema (%d) is not compatible with this version of xastir (%d).",version_number,XASTIR_SPATIAL_DB_VERSION);
+ fprintf(stderr,"%s",aDbConnection->errormessage);
+ returnvalue = 0;
+ }
+
+ }
+ }
+
+ }
+ PQclear(result);
+ }
+ return returnvalue;
+}
+
+
+
+
+
+/* function getAllSimplePositionsPostgis()
+ * Postgresql/Postgis implementation of wrapper getAllSimplePositions().
+ * Should only be called through wrapper function. Do not call directly.
+ */
+int getAllSimplePositionsPostgis(Connection *aDbConnection) {
+ int returnvalue = 0; // value to return from function, 1 for success, 0 for failure
+ int row; // row counter for result set loop
+ int station_count = 0; // number of new stations retrieved
+ unsigned long x; // xastir coordinate for longitude
+ unsigned long y; // xastir coordinate for latitide
+ unsigned long u_long;
+ unsigned long u_lat;
+ char *s_lat[13]; // string latitude
+ char *s_lon[13]; // string longitude
+ float lat; // latitude converted from retrieved string
+ float lon; // longitude converted from retrieved string
+ const char *sql = "select station, symbol, overlay, aprstype, transmit_time, AsText(position), origin, record_type, node_path, X(position), Y(position) from simpleStation order by station, transmit_time asc";
+ // station is column 0, symbol is column 1, etc.
+ PGconn *conn = aDbConnection->phandle;
+ char feedback[100];
+ char lastcall[MAX_CALLSIGN+1]; //holds last retrieved callsign
+ int exists; //shortcut to skip db check if currently retrieved callsign equals last retrieved callsign
+ DataRow *p_new_station; // pointer to new station record
+ DataRow *p_time; // pointer to new station record
+ int skip;
+ int points_this_station; // number of times this station has been heard.
+ char empty[MAX_ALTITUDE];
+ struct tm time;
+ time_t sec;
+ empty[0]='\0';
+ xastir_snprintf(feedback,100,"Retrieving Postgis records\n");
+ stderr_and_statusline(feedback);
+ //fprintf(stderr,"connection->phandle [%p]\n",aDbConnection->phandle);
+ // run query and retrieve result set
+ PGresult *result = PQexec(conn,sql);
+
+ if (result==NULL) {
+ // PQexec probably couldn't allocate memory for the result set.
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Null result: %s\n",PQerrorMessage(conn));
+ fprintf(stderr, "getAllSimplePositionsPostgis() Null result\nPostgresql Error : %s\n",PQerrorMessage(conn));
+ } else {
+ // PQexec returned a result, but it may not be valid, check to see.
+ if (PQresultStatus(result)==PGRES_COMMAND_OK || PQresultStatus(result)==PGRES_TUPLES_OK) {
+ // PQexec returned a valid result set.
+ xastir_snprintf(feedback,100,"Retrieving %i Postgis records\n",PQntuples(result));
+ stderr_and_statusline(feedback);
+ xastir_snprintf(lastcall,MAX_CALLSIGN+1," ");
+ points_this_station = 0;
+ for (row=0; row<PQntuples(result); row++) {
+ // step through rows in result set and add each to xastir db as a minimal DataRow
+ if (PQgetisnull(result,row,0)) {
+ // station name is null, skip.
+ } else {
+ // check if station exists
+ p_new_station = NULL;
+ exists = 0;
+ // Shortcut check to see if this station has been loaded already
+ // works as returned rows are ordered by station.
+ // TODO: add_simple_station will not update the linked list of station properly,
+ // when data from more than one database for the same station is loaded
+ // and a more recently loaded database contains station data with timestamps
+ // older than the timestamp from a previously loaded database.
+ // This shows up as search_station_name failing to locate
+ // existing stations and stations not being found on station info
+ // (because they have expired from the list).
+ // This will also be a problem if old data for stations heard live are
+ // retrieved from a database while xastir is running.
+ if (strcmp(PQgetvalue(result,row,0),lastcall)==0) {
+ points_this_station++;
+ exists = 1;
+ } else {
+ if (search_station_name(&p_new_station,PQgetvalue(result,row,0),1)) {
+ points_this_station++;
+ exists = 1;
+ } else {
+ points_this_station=1;
+ }
+ }
+ xastir_snprintf(lastcall,MAX_CALLSIGN+1,PQgetvalue(result,row,0));
+ if (exists==1) {
+ // This station allready exists as a DataRow in the xastir db.
+ // Don't create a duplicate record, but add to the DataRow's track.
+
+ // check if it is a mobile station
+ // We can't easily identify mobile stations from position position
+ // becaue of rounding errors, therefore exclude stations that are likely to be fixed.
+ // _/ = wx
+ skip = 0;
+ if ((PQgetvalue(result,row,1)[0]=='_') && (PQgetvalue(result,row,3)[0]=='/')) {
+ skip = 1; // wx
+ }
+ if ((PQgetvalue(result,row,1)[0]=='-') && (PQgetvalue(result,row,3)[0]=='/')) {
+ skip = 1; // house
+ }
+
+
+ if (skip==0) {
+ // add to track
+ if (search_station_name(&p_new_station,PQgetvalue(result,row,0),1)) {
+ if (points_this_station<3) {
+ //existing station record needs to be added as a trailpoint
+ (void)store_trail_point(p_new_station, p_new_station->coord_lon, p_new_station->coord_lat, p_new_station->sec_heard, empty, empty, empty, 0);
+ }
+
+ // store this trail point
+ lat = atof(PQgetvalue(result,row,10));
+ lon = atof(PQgetvalue(result,row,9));
+ if (strlen(PQgetvalue(result,row,4)) > 0) {
+ strptime(PQgetvalue(result,row,4), "%Y-%m-%d %H:%M:%S%z", &time);
+ sec = mktime(&time);
+ }
+ if(convert_to_xastir_coordinates( &u_long, &u_lat, lon, lat))
+ (void)store_trail_point(p_new_station, u_long, u_lat, sec, empty, empty, empty, 0);
+
+ if (p_new_station->sec_heard < sec) {
+ // update the station record to this position
+ if(convert_to_xastir_coordinates(&u_long, &u_lat, lon, lat)) {
+ p_new_station->coord_lat = u_lat;
+ p_new_station->coord_lon = u_long;
+ p_new_station->sec_heard = sec;
+ }
+ }
+ }
+ }
+
+ } else {
+ // This station isn't in the xastir db.
+ //int add_simple_station(DataRow *p_new_station,char *station, char *origin, char *symbol, char *overlay, char *aprs_type, char *latitude, char *longitude, char *record_type, char *node_path, char *transmit_time) {
+ //const char *sql = "select station, symbol, overlay, aprstype, transmit_time, AsText(position), origin, record_type, node_path, X(position), Y(position) from simpleStation order by station, transmit_time asc";
+ add_simple_station(p_new_station,PQgetvalue(result,row,0), PQgetvalue(result,row,6), PQgetvalue(result,row,1), PQgetvalue(result,row,2), PQgetvalue(result,row,3), PQgetvalue(result,row,10), PQgetvalue(result,row,9), PQgetvalue(result,row,7), PQgetvalue(result,row,8), PQgetvalue(result,row,4), POSTGIS_TIMEFORMAT);
+
+ station_count ++;
+ } // end else, new station
+ } // end else, station is not null
+ } // end for loop stepping through rows
+ redo_list = (int)TRUE; // update active station lists
+ xastir_snprintf(feedback,100,"Added %d stations from Postgis\n",station_count);
+ stderr_and_statusline(feedback);
+ } else {
+ // sql query had a problem retrieving result set.
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "%s %s\n",PQresStatus(PQresultStatus(result)),PQerrorMessage(conn));
+ fprintf(stderr, "getAllSimplePositionsPostgis() %s\nPostgresql Error : %s\n",PQresStatus(PQresultStatus(result)),PQerrorMessage(conn));
+ }
+ // done with result set, so free the resource.
+ PQclear(result);
+ }
+ return returnvalue;
+}
+
+
+
+
+
+/* function getAllSimplePositionsPostgisInBoundingBox()
+ * Postgresql/Postgis implementation of wrapper getAllSimplePositionsInBoundingBox().
+ * Should only be called through wrapper function. Do not call directly.
+ */
+int getAllSimplePositionsPostgisInBoundingBox(Connection *aDbConnection, char* str_e_long, char* str_w_long, char* str_n_lat, char* str_s_lat) {
+ int returnvalue = 0;
+ // set up prepared query with bounding box
+ // postgis simple table uses POINT
+ char sql[100] = "select call, transmit_time, position from simpleStation where ";
+ PGconn *conn = aDbConnection->phandle;
+
+
+ return returnvalue;
+}
+
+
+
+
+#endif /* HAVE_POSTGIS */
+
+#ifdef HAVE_MYSQL_SPATIAL
+// Mysql 5 implementation of spatial database functions
+
+
+
+
+
+/* function storeStationToGisDbMysql
+ * MySQL implemenation of storeStationToGisDb
+ * Should be private to db_gis.c
+ * Should only be called through wrapper function. Do not call directly.
+ * @param aDbConnection an exastir database connection struct describing
+ * the connection.
+ * @param aStation
+ * Returns 0 for failure, 1 for success.
+ * If failure, stores error message in aDbConnection->errormessage.
+ */
+int storeStationToGisDbMysql(Connection *aDbConnection, DataRow *aStation) {
+ int returnvalue = 0;
+ //ioparam *device = aDbConnection->descriptor;
+ // check type of schema to use (XASTIR simple, full or APRSWorld)
+ switch (devices[aDbConnection->interface_number].database_schema_type) {
+ case XASTIR_SCHEMA_SIMPLE :
+ returnvalue = storeStationSimplePointToGisDbMysql(aDbConnection,aStation);
+ break;
+ case XASTIR_SCHEMA_APRSWORLD :
+ break;
+ case XASTIR_SCHEMA_COMPLEX :
+ break;
+ // otherwise error message
+ }
+ return returnvalue;
+}
+
+
+
+
+
+
+/* function storeCadToGisDbMysql
+ * MySQL implementation of storeCadToGisDbMysql
+ * Should be private to db_gis.c
+ * Should only be called through wrapper function. Do not call directly.
+ * @param aDbConnection an exastir database connection struct describing
+ * the connection.
+ * @param aCadObject
+ * Returns 0 for failure, 1 for success.
+ * If failure, stores error message in aDbConnection->errormessage.
+ */
+int storeCadToGisDbMysql(Connection *aDbConnection, CADRow *aCadObject) {
+ int returnvalue = 0;
+
+ return returnvalue;
+}
+
+
+
+
+
+
+/* support function for prepared statements
+int bind_mysql_string_parameter(MYSQL_BIND *bind, int bind_number, char* buffer, int provided_length, int buffer_length, my_bool is_null) {
+ bind[bind_number]->buffer = buffer;
+ bind[bind_number]->length = provided_length;
+ bind[bind_number]->buffer_length = buffer_length;
+ bind[bind_number]->buffer_type = MYSQL_TYPE_STRING
+ bind[bind_number]->is_null = is_null;
+}
+*/
+
+
+
+
+
+/* function storeStationSimplePointToGisDbMysql()
+ * MySQL implementation of wrapper storeStationSimplePointToGisDb().
+ * Should be private to db_gis.c
+ * Should only be called through wrapper function. Do not call directly.
+ * @param aDbConnection an xastir database connection struct describing
+ * the connection.
+ * @param aStation
+ * Returns 0 for failure, 1 for success.
+ * On failure sets error message in aDbConnection->errormessage.
+ */
+int storeStationSimplePointToGisDbMysql(Connection *aDbConnection, DataRow *aStation) {
+ int returnvalue = 0;
+ int mysqlreturn; // hold return value of mysql query
+ int param_count; // check on the number of parameters present in the prepared statement
+ int ok; // variable to store results of tests preparatory to firing query
+ // temporary holding variables for bind buffers
+ char wkt[MAX_WKT]; // well know text representation of latitude and longitude of point
+ char aprs_symbol[2]; // temporary holding for escaped aprs symbol
+ char aprs_type[2]; // temporary holding for escaped aprs type
+ char special_overlay[2]; // temporary holding for escaped overlay
+ char record_type[2]; // temporary holding for escaped record type
+ char origin[MAX_CALLSIGN+1]; // temporary holding for escaped origin
+ char node_path[NODE_PATH_SIZE+1]; // temporary holding for escaped node_path_ptr
+ MYSQL_STMT *statement;
+ // bind string lengths
+ unsigned long call_sign_length;
+ unsigned long wkt_length;
+ unsigned long aprs_symbol_length;
+ unsigned long aprs_type_length;
+ unsigned long special_overlay_length;
+ unsigned long origin_length;
+ unsigned long record_type_length;
+ unsigned long node_path_length;
+ // time
+ MYSQL_TIME timestamp;
+ char timestring[100+1];
+ time_t secs_now;
+ struct tm *ts; // to convert time to component parts for bind.buffer_type MYSQL_TYPE_DATETIME
+ // define prepared statement and matching bind array
+ #define SQL "INSERT INTO simpleStationSpatial (station, transmit_time, position, symbol, overlay, aprstype, origin, record_type, node_path) VALUES (?,?,PointFromText(?),?,?,?,?,?,?)"
+ MYSQL_BIND bind[9]; // bind array for prepared query.
+ int parameters = 9;
+ // Note:
+ // bind[9], SQL "?????????", and param_count must all match value of parameters
+ // nine bound parameters, nine question marks in the statement, and param_count returned as nine.
+
+ if (debug_level & 4096) {
+ fprintf(stderr,"in storeStationSimplePointToGisDbMysql\n");
+ fprintf(stderr,"with connection [%p] \n",aDbConnection);
+ }
+
+ if (&aDbConnection->mhandle==NULL)
+ return returnvalue;
+
+ statement = mysql_stmt_init(&aDbConnection->mhandle);
+ if (!statement) {
+ fprintf(stderr,"Unable to create mysql prepared statement. May be out of memmory.\n");
+ }
+ mysql_stmt_prepare(statement, SQL, strlen(SQL));
+ if (!statement) {
+ mysql_interpret_error(*mysql_error(&aDbConnection->mhandle),aDbConnection);
+ } else {
+ // test to make sure that statement has the correct number of parameters
+ param_count=mysql_stmt_param_count(statement);
+ if (param_count!=parameters) {
+ fprintf(stderr,"Number of bound parameters %d does not match expected value %d\nFor query[%s]",param_count,parameters,SQL);
+ fprintf(stderr, " %s\n", mysql_stmt_error(statement));
+ } else {
+ // set up the buffers
+ memset(bind, 0, sizeof(bind));
+
+ bind[0].buffer = (char *)&aStation->call_sign;
+ bind[0].length = &call_sign_length;
+ bind[0].buffer_length = MAX_CALLSIGN;
+ bind[0].buffer_type = MYSQL_TYPE_STRING;
+ bind[0].is_null = 0;
+
+ bind[1].buffer = (char *)×tamp;
+ bind[1].length = 0;
+ bind[1].buffer_type = MYSQL_TYPE_DATETIME;
+ bind[1].is_null = 0;
+
+ bind[2].buffer = (char *)&wkt;
+ bind[2].length = &wkt_length;
+ bind[2].buffer_length = MAX_WKT;
+ bind[2].buffer_type = MYSQL_TYPE_STRING;
+ bind[2].is_null = 0;
+
+ bind[3].buffer = (char *)&aprs_symbol;
+ bind[3].length = &aprs_symbol_length;
+ bind[3].buffer_length = 2;
+ bind[3].buffer_type = MYSQL_TYPE_STRING;
+ bind[3].is_null = 0;
+
+ bind[4].buffer = (char *)&special_overlay;
+ bind[4].length = &special_overlay_length;
+ bind[4].buffer_length = 2;
+ bind[4].buffer_type = MYSQL_TYPE_STRING;
+ bind[4].is_null = 0;
+
+ bind[5].buffer = (char *)&aprs_type;
+ bind[5].length = &aprs_type_length;
+ bind[5].buffer_length = 2;
+ bind[5].buffer_type = MYSQL_TYPE_STRING;
+ bind[5].is_null = 0;
+
+ bind[6].buffer = (char *)&origin; // segfaults with origin of zero length, otherwise writes bad data
+ bind[6].length = &origin_length;
+ bind[6].buffer_length = MAX_CALLSIGN;
+ bind[6].buffer_type = MYSQL_TYPE_STRING;
+ bind[6].is_null = 0;
+
+ bind[7].buffer = (char *)&record_type;
+ bind[7].length = &record_type_length;
+ bind[7].buffer_length = 2;
+ bind[7].buffer_type = MYSQL_TYPE_STRING;
+ bind[7].is_null = 0;
+
+ bind[8].buffer = (char *)&node_path;
+ bind[8].length = &node_path_length;
+ bind[8].buffer_length = NODE_PATH_SIZE;
+ bind[8].buffer_type = MYSQL_TYPE_STRING;
+ bind[8].is_null = 0;
+
+ ok = mysql_stmt_bind_param(statement,bind);
+ if (ok!=0) {
+ fprintf(stderr,"Error binding parameters to mysql prepared statement.\n");
+ mysql_interpret_error(mysql_errno(&aDbConnection->mhandle),aDbConnection);
+ fprintf(stderr,mysql_stmt_error(statement));
+ } else {
+
+ // get call, time, and position
+ // call is required
+ if (aStation->call_sign!=NULL && strlen(aStation->call_sign)>0) {
+ call_sign_length = strlen(aStation->call_sign);
+
+ // get time in seconds, adjust to datetime
+ // If my station or another unset sec_heard is
+ // encountered, use current time instead, use time
+ // provided if it was invalid.
+ get_iso_datetime(aStation->sec_heard,timestring,True,False);
+ if ((int)aStation->sec_heard==0 ) {
+ secs_now = sec_now();
+ ts = localtime(&secs_now);
+ } else {
+ ts = localtime(&aStation->sec_heard);
+ }
+ timestamp.year = ts->tm_year + 1900; // tm_year is from 1900
+ timestamp.month = ts->tm_mon + 1; // tm_mon is from 0
+ timestamp.day = ts->tm_mday; // tm_mday is from 1
+ timestamp.hour = ts->tm_hour;
+ timestamp.minute = ts->tm_min;
+ timestamp.second = ts->tm_sec;
+ ok = xastirCoordToLatLongWKT(aStation->coord_lon, aStation->coord_lat, wkt);
+ if (ok==1) {
+ wkt_length = strlen(wkt);
+
+
+ if (aStation->aprs_symbol.aprs_symbol) {
+ xastir_snprintf(aprs_symbol,2,"%c",aStation->aprs_symbol.aprs_symbol);
+ } else {
+ xastir_snprintf(aprs_symbol,2,"%c",'\0');
+ }
+ aprs_symbol_length = strlen(aprs_symbol);
+
+ if (aStation->aprs_symbol.aprs_type) {
+ xastir_snprintf(aprs_type,2,"%c",aStation->aprs_symbol.aprs_type);
+ } else {
+ xastir_snprintf(aprs_type,2,"%c",'\0');
+ }
+ aprs_type_length = strlen(aprs_type);
+
+ if (aStation->aprs_symbol.special_overlay) {
+ xastir_snprintf(special_overlay,2,"%c",aStation->aprs_symbol.special_overlay);
+ } else {
+ xastir_snprintf(special_overlay,2,"%c",'\0');
+ }
+ special_overlay_length = strlen(special_overlay);
+
+ if (aStation->origin) {
+ xastir_snprintf(origin,MAX_CALLSIGN+1,"%s",aStation->origin);
+ } else {
+ //xastir_snprintf(origin,2,"%c",'\0');
+ origin[0]='\0';
+ }
+ origin_length = strlen(origin);
+
+ if (aStation->record_type) {
+ xastir_snprintf(record_type,2,"%c",aStation->record_type);
+ } else {
+ //xastir_snprintf(record_type,2,"%c",'\0');
+ record_type[0]='\0';
+ }
+ record_type_length = strlen(record_type);
+
+ if (aStation->node_path_ptr) {
+ if (debug_level & 4096) {
+ fprintf(stderr,"node_path (12345678901234567890123456789012345678901234567890123456)\n");
+ fprintf(stderr,"node_path = [%s]\n",aStation->node_path_ptr);
+ }
+ xastir_snprintf(node_path,NODE_PATH_SIZE+1,"%s",aStation->node_path_ptr);
+ } else {
+ //xastir_snprintf(node_path,2,"%c",'\0');
+ node_path[0]='\0';
+ }
+ node_path_length = strlen(node_path);
+
+ // all the bound parameters should be available and correct
+ if (debug_level & 4096)
+ fprintf(stderr,"saving station %s %d %d %d %d:%d:%d wkt=%s [%s][%s][%s] \n",aStation->call_sign,ts->tm_year,ts->tm_mon,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec,wkt,aprs_type,aprs_symbol,record_type);
+ // send query
+ mysqlreturn = mysql_stmt_execute(statement);
+ if (mysqlreturn!=0) {
+ returnvalue=0;
+ fprintf(stderr,"%s\n",mysql_stmt_error(statement));
+ mysql_interpret_error(mysqlreturn,aDbConnection);
+ } else {
+ returnvalue=1;
+ }
+ } else {
+ fprintf(stderr,"Unable to save station to mysql db, Error converting latitude or longitude from xastir coordinates\n");
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Error converting latitude or longitude from xastir coordinates: %ld,%ld",aStation->coord_lat,aStation->coord_lon);
+ }
+ } else {
+ // set call not null error message
+ fprintf(stderr,"Unable to save station to mysql db, Station call sign was blank or null.\n");
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Station callsign is required and was blank or null.");
+ }
+ } // end of bind check
+ } // end of parameter count check
+ }
+ mysql_stmt_free_result(statement);
+ mysql_stmt_close(statement);
+ if (returnvalue==0) {
+ pingConnection(aDbConnection);
+ }
+
+ return returnvalue;
+}
+
+
+
+
+
+
+int getAllSimplePositionsMysqlSpatial(Connection *aDbConnection) {
+ int returnvalue = 0;
+ DataRow *p_new_station;
+ int station_count = 0; // number of new stations retrieved
+ char *s_lat[13]; // string latitude
+ char *s_lon[13]; // string longitude
+ float lat; // latitude converted from retrieved string
+ float lon; // longitude converted from retrieved string
+ unsigned long u_lat;
+ unsigned long u_long;
+ int points_this_station;
+ char feedback[100];
+ struct tm time;
+ time_t sec;
+ int skip; // used in identifying mobile stations
+ char sql[] = "select station, transmit_time, AsText(position), symbol, overlay, aprstype, origin, record_type, node_path from simpleStationSpatial order by station, transmit_time asc";
+ char lastcall[MAX_CALLSIGN+1]; //holds last retrieved callsign
+ int exists; //shortcut to skip db check if currently retrieved callsign equals last retrieved callsign
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ char empty[MAX_ALTITUDE];
+ int ok; // to hold mysql_query return value
+ empty[0]='\0';
+ ok = mysql_query(&aDbConnection->mhandle,sql);
+ if (ok==0) {
+ result = mysql_use_result(&aDbConnection->mhandle);
+ if (result!=NULL) {
+ xastir_snprintf(feedback,100,"Retrieving MySQL records\n");
+ stderr_and_statusline(feedback);
+ // with mysql_use_result each call to mysql_fetch_row retrieves
+ // a row of data from the server. Mysql_store_result might use
+ // too much memory in retrieving a large result set all at once.
+ xastir_snprintf(lastcall,MAX_CALLSIGN+1," ");
+ points_this_station=0;
+ while ((row = mysql_fetch_row(result))) {
+ // retrieve data from the row
+ // test to see if this is a valid station
+ if (row[0]==NULL) {
+ // station is null, skip
+ } else {
+ p_new_station = NULL;
+ exists = 0;
+ // Shortcut check to see if station has allready been heard
+ // works as query is ordered by station.
+ if (strcmp(lastcall,row[0])==1) {
+ exists = 1;
+ points_this_station++;
+ } else {
+ if (search_station_name(&p_new_station,row[0],1)) {
+ exists = 1;
+ points_this_station++;
+ } else {
+ points_this_station=1;
+ }
+ }
+ xastir_snprintf(lastcall,MAX_CALLSIGN+1,row[0]);
+ if (exists==1) {
+ // This station is allready in present as a DataRow in the xastir db.
+ // check to see if this is likely to be a mobile station
+
+ // We can't easily identify mobile stations from position position
+ // becaue of rounding errors, therefore exclude stations that are likely to be fixed.
+ // _/ = wx
+ skip = 0;
+ if ((strcmp(row[3],"_")==0) & (strcmp(row[5],"/")==0)) {
+ skip = 1; // wx
+ }
+ if ((strcmp(row[3],"-")==0) & (strcmp(row[5],"/")==0)) {
+ skip = 1; // house
+ }
+
+ if (skip==0) {
+ // add to track
+
+ if (search_station_name(&p_new_station,row[0],1)) {
+ if (points_this_station<3) {
+ //existing station record needs to be added as a trailpoint
+ (void)store_trail_point(p_new_station, p_new_station->coord_lon, p_new_station->coord_lat, p_new_station->sec_heard, empty, empty, empty, 0);
+ }
+ // store this trail point
+ lat = xastirWKTPointToLatitude(row[2]);
+ lon = xastirWKTPointToLongitude(row[2]);
+ if (strlen(row[1]) > 0) {
+ strptime(row[1], "%Y-%m-%d %H:%M:%S", &time);
+ sec = mktime(&time);
+ //fprintf(stderr,"trailpoint time: %ld [%s]\n", sec, row[1]);
+ }
+ if(convert_to_xastir_coordinates( &u_long, &u_lat, lon, lat)) {
+ (void)store_trail_point(p_new_station, u_long, u_lat, sec, empty, empty, empty, 0);
+ }
+ if (p_new_station->sec_heard < sec) {
+ // update the station record to this position
+ if(convert_to_xastir_coordinates(&u_long, &u_lat, lon, lat)) {
+ p_new_station->coord_lat = u_lat;
+ p_new_station->coord_lon = u_long;
+ p_new_station->sec_heard = sec;
+ }
+ }
+ } // search_station_name
+ } // !skip
+ } else {
+ // This station isn't in the xastir db.
+ // Add a datarow using the retrieved station record from the postgis database.
+ lat = xastirWKTPointToLatitude(row[2]);
+ lon = xastirWKTPointToLongitude(row[2]);
+ xastir_snprintf(s_lat,13,"%3.6f",lat);
+ xastir_snprintf(s_lon,13,"%3.6f",lon);
+ add_simple_station(p_new_station, row[0], row[6], row[3], row[4], row[5], s_lat, s_lon, row[7], row[8], row[1],(char*)MYSQL_TIMEFORMAT);
+
+ station_count++;
+ }
+ }
+ }
+ } else {
+ // error fetching the result set
+ fprintf(stderr,"mysql error: %s\n",mysql_error(&aDbConnection->mhandle));
+ mysql_interpret_error(mysql_errno(&aDbConnection->mhandle),aDbConnection);
+ }
+ xastir_snprintf(feedback,100,"Retreived %d new stations from MySQL\n",station_count);
+ stderr_and_statusline(feedback);
+ mysql_free_result(result);
+ } else {
+ // query didn't execute correctly
+ mysql_interpret_error(ok,aDbConnection);
+ }
+
+ return returnvalue;
+}
+
+
+
+
+
+
+int getAllCadFromGisDbMysql(Connection *aDbConnection) {
+ int returnvalue = 0;
+ int mysqlreturn;
+ MYSQL *conn = &aDbConnection->mhandle;
+
+ return returnvalue;
+}
+
+
+
+
+
+int getAllSimplePositionsMysqlSpatialInBoundingBox(Connection *aDbConnection, char* str_e_long, char* str_w_long, char* str_n_lat, char* str_s_lat) {
+ int returnvalue = 0;
+ int mysqlreturn;
+ MYSQL *conn = &aDbConnection->mhandle;
+
+ return returnvalue;
+
+}
+
+
+
+
+/*
+
+ // some thoughts on database schema elements
+
+ create database xastir;
+ grant select on xastir to user xastir_user at localhost identified by encrypted password '<password>';
+
+ create table version (
+ version_number int,
+ compatable_series int
+ );
+ grant select on version to xastir_user at localhost
+ insert into version (version_number) values (XASTIR_SPATIAL_DB_VERSION);
+ insert into version (version_number) values (XASTIR_SPATIAL_DB_COMPATIBLE_SERIES);
+
+ # should be minimum fields needed to populate a DataRow and a related
+ # APRS_Symbol in xastir
+ create table simpleStation (
+ simpleStationId int primary key not null auto_increment
+ station varchar(MAX_CALLSIGN) not null, # callsign of station, length up to max_callsign
+ symbol varchar(1), # aprs symbol character
+ overlay varchar(1), # aprs overlay table character
+ aprstype varchar(1), # aprs type, required???
+ transmit_time datetime not null default now(), # transmission time, if available, otherwise storage time
+ position POINT # position of station or null if latitude and longitude are not available
+ );
+
+
+
+ grant select, insert on simpleStation to xastir_user at localhost;
+
+
+ create table datarow (
+ datarow_id int not null primary key auto_increment,
+ call_sign varchar(10) not null,
+ tactical_call_sign varchar() not null default '',
+ c_aprs_symbol_id int
+ location POINT,
+ time_sn int,
+ sec_heard long,
+ heard_via_tnc_last_time long,
+ direct_heard long,
+ packet_time varchar,
+ pos_time varchar,
+ flag int,
+ pos_amb varchar(1),
+ error_ellipse_radius int,
+ lon_precision int,
+ lat_precision int,
+ trail_color int,
+ record_type varchar(1),
+ data_via varchar(1),
+ heard_via_tnc_port int,
+ last_port_heard int,
+ num_packets int,
+ altitude varchar([MAX_ALTITUDE]),
+ speed varchar([MAX_SPEED+1]),
+ course varchar([MAX_COURSE+1]),
+ bearing varchar([MAX_COURSE+1]),
+ NRQ varchar([MAX_COURSE+1]),
+ power_gain varchar([MAX_POWERGAIN+1]),
+ signal_gain varchar([MAX_POWERGAIN+1])
+ );
+
+
+
+*/
+
+#endif /* HAVE_MYSQL_SPATIAL */
+
+#endif /* HAVE_SPATIAL_DB */
+
+
+
+
+
+
+// Layer 3b: DBMS specific db storage code for non spatial databases **********
+// Functions supporting queries to specific types of databases that lack
+// spatial extensions. Limited to storing points using latitude and longitude
+// fields without spatial objects or spatial indexing.
+//
+
+#ifdef HAVE_MYSQL
+// functions for MySQL database version < 4.1, or MySQL schema objects that don't
+// include spatial indicies.
+//
+//********* Support for MySQL < 4.1 is depreciated *****************************
+//********* Expect MySQL support to be limited to MySQL 5+ **********************
+//
+
+
+
+
+
+/* function storeStationSimplePointToDbMysql()
+ * MySQL implementation of wrapper storeStationSimplePointToGisDb().
+ * Should be private to db_gis.c
+ * Should only be called through wrapper function. Do not call directly.
+ * Returns 0 for failure, 1 for success.
+ * If failure, stores error message in aDbConnection->errormessage.
+ */
+int storeStationSimplePointToDbMysql(Connection *aDbConnection, DataRow *aStation) {
+ int returnvalue = 0; // default return value is failure.
+ int mysqlreturn = 1; // result of sending mysql query.
+ char sql[400];
+ // Next three variables are one character in two bytes plus one character for
+ // filling by mysql_real_escape_string().
+ char aprs_symbol[3]; // temporary holding for escaped aprs symbol
+ char aprs_type[3]; // temporary holding for escaped aprs type
+ char special_overlay[3]; // temporary holding for escaped overlay
+ char record_type[3]; // temporary holding for escaped record type
+ char from[3]; // temporary holding for all of the above length 3 variables
+ char call_sign[(MAX_CALLSIGN)*2+1]; // temporary holding for escaped callsign
+ char origin[(MAX_CALLSIGN)*2+1]; // temporary holding for escaped origin
+ char node_path[(NODE_PATH_SIZE*2)+1]; // temporary holding for escaped node_path_ptr
+ float longitude;
+ float latitude;
+ int ok;
+ char timestring[100+1];
+
+ if (debug_level & 4096)
+ fprintf(stderr,"In storestationsimpletodbmysql()\n");
+
+ // prepared statements not present below MySQL version 4.1
+ // details of prepared statement support changed between versions 4.1 and 5.0.
+ // char [] sql = "insert into simpleStation (call, transmit_time, latitude, longitude) values ('%1','%2','%3','%4'))";
+ // call is a required element for a simple station
+ if (aStation!=NULL && aStation->call_sign!=NULL && strlen(aStation->call_sign)>0) {
+ // get time in seconds, adjust to datetime
+ // If my station or another unset sec_heard is
+ // encountered, use current time instead, use time
+ // provided if it was invalid.
+ get_iso_datetime(aStation->sec_heard,timestring,True,False);
+ // get coord_lat, coord_long in xastir coordinates and convert to decimal degrees
+ ok = convert_from_xastir_coordinates (&longitude, &latitude, aStation->coord_lon, aStation->coord_lat);
+ // latitude and longitude are required elements for a simple station record.
+ if (ok==1) {
+ // build insert query with call, time, and position
+ // handle special cases of null, \ and ' characters in type, symbol, and overlay.
+ if (aStation->aprs_symbol.aprs_symbol) {
+ xastir_snprintf(from,2,"%c",aStation->aprs_symbol.aprs_symbol);
+ mysql_real_escape_string(&aDbConnection->mhandle,aprs_symbol,from,1);
+ } else {
+ xastir_snprintf(aprs_symbol,2,"%c",'\0');
+ }
+ if (aStation->aprs_symbol.aprs_type) {
+ xastir_snprintf(from,2,"%c",aStation->aprs_symbol.aprs_type);
+ mysql_real_escape_string(&aDbConnection->mhandle,aprs_type,from,1);
+ } else {
+ xastir_snprintf(aprs_type,2,"%c",'\0');
+ }
+ if (aStation->aprs_symbol.special_overlay) {
+ xastir_snprintf(from,2,"%c",aStation->aprs_symbol.special_overlay);
+ mysql_real_escape_string(&aDbConnection->mhandle,special_overlay,from,1);
+ } else {
+ xastir_snprintf(special_overlay,2,"%c",'\0');
+ }
+
+ // Need to escape call sign - may contain special characters:
+ // insert into simpleStation (station, symbol, overlay, aprstype, transmit_time, latitude, longitude)
+ // values ('Fry's','/\0\0',' ','//\0','2007-08-07 21:55:43 -0400','47.496834','-122.198166')
+ mysql_real_escape_string(&aDbConnection->mhandle,call_sign,(aStation->call_sign),strlen(aStation->call_sign));
+ // just in case, set a default value for record_type and escape it.
+ if (aStation->record_type) {
+ fprintf(stderr,"record_type: %c\n",aStation->record_type);
+ xastir_snprintf(from,2,"%c",aStation->record_type);
+ mysql_real_escape_string(&aDbConnection->mhandle,record_type,from,1);
+ } else {
+ xastir_snprintf(record_type,2,"%c",NORMAL_APRS);
+ }
+
+ if (strlen(aStation->origin) > 0) {
+ mysql_real_escape_string(&aDbConnection->mhandle,origin,(aStation->origin),strlen(aStation->origin));
+ } else {
+ xastir_snprintf(origin,2,"%c",'\0');
+ }
+ if (aStation->node_path_ptr) {
+ //mysql_real_escape_string(conn,&node_path,aStation->node_path_ptr,((strlen(aStation->node_path_ptr)*2)+1));
+ xastir_snprintf(node_path,sizeof(node_path),"%s",aStation->node_path_ptr);
+ } else {
+ xastir_snprintf(node_path,2,"%c",'\0');
+ }
+
+ xastir_snprintf(sql,sizeof(sql),"insert into simpleStation (station, symbol, overlay, aprstype, transmit_time, latitude, longitude, origin, record_type, node_path) values ('%s','%s','%s','%s','%s','%3.6f','%3.6f','%s','%s','%s')", call_sign, aprs_symbol, special_overlay, aprs_type,timestring,latitude,longitude,origin,record_type,node_path);
+
+ if (debug_level & 4096)
+ fprintf(stderr,"MySQL Query:\n%s\n",sql);
+
+ // send query
+ mysql_ping(&aDbConnection->mhandle);
+ mysqlreturn = mysql_real_query(&aDbConnection->mhandle, sql, strlen(sql)+1);
+ if (mysqlreturn!=0) {
+ // get the mysql error message
+ fprintf(stderr,mysql_error(&aDbConnection->mhandle));
+ fprintf(stderr,"\n");
+ mysql_interpret_error(mysqlreturn,aDbConnection);
+ } else {
+ // insert query was successfull, return value is ok.
+ returnvalue=1;
+ }
+ } else {
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Error converting latitude or longitude from xastir coordinates: %ld,%ld",aStation->coord_lat,aStation->coord_lon);
+ }
+ } else {
+ // set call not null error message
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Station callsign is required and was blank or null.");
+ }
+ return returnvalue;
+}
+
+
+
+
+
+/* function testXastirVersionMysql()
+ * checks the xastir database version number of a connected MySQL database against the
+ * version range supported by the running copy of xastir.
+ * @param aDbConnection pointer to a Connection struct describing the connection
+ * @returns 0 if incompatable, 1 if compatable, -1 on connection failure.
+ *
+ * db program
+ * v cs v cs compatable
+ * 1 1 1 1 1 identical
+ * 2 1 1 1 1 database newer than program (added fields, not queried)
+ * 1 1 2 1 0 program newer than database (added fields, queries fail).
+ * 3 2 2 1 0 different series
+ * 2 1 3 2 0 different series
+ *
+ * TODO: Need function to test for available schemas with mysql_list_tables()
+ */
+int testXastirVersionMysql(Connection *aDbConnection) {
+ int returnvalue = -1;
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ int version_number;
+ int compatible_series;
+ char sql[] = "select version_number, compatable_series from version order by version_number desc limit 1";
+ int ok; // to hold mysql_query return value
+ ok = mysql_query(&aDbConnection->mhandle,sql);
+ if (ok==0) {
+ result = mysql_use_result(&aDbConnection->mhandle);
+ if (result!=NULL) {
+ if ((row = mysql_fetch_row(result))) {
+ version_number = atoi((char *)row[0]);
+ if (version_number == XASTIR_SPATIAL_DB_VERSION) {
+ returnvalue = 1;
+ fprintf(stderr,"Version in schema (%d) is the same as this version of xastir (%d).\n",version_number,XASTIR_SPATIAL_DB_VERSION);
+ } else {
+ compatible_series = atoi((char *)row[1]);
+ if (version_number < XASTIR_SPATIAL_DB_VERSION && compatible_series == XASTIR_SPATIAL_DB_COMPATABLE_SERIES) {
+ returnvalue = 1;
+ fprintf(stderr,"Version in schema (%d) is compatible with this version of xastir (%d).\n",version_number,XASTIR_SPATIAL_DB_VERSION);
+ } else {
+ fprintf(stderr,"Version in schema (%d) is not compatible with this version of xastir (%d).\n",version_number,XASTIR_SPATIAL_DB_VERSION);
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Version in schema (%d) is not compatible with this version of xastir (%d).",version_number,XASTIR_SPATIAL_DB_VERSION);
+ fprintf(stderr,"%s",aDbConnection->errormessage);
+ returnvalue = 0;
+ }
+ }
+ } else {
+ // result returned, but no rows = incompatable
+ returnvalue = 0;
+ fprintf(stderr,"Version table doesn't appear to contain any rows.\n");
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Version table doesn't appear to contain any rows.");
+ }
+ } else {
+ fprintf(stderr,"Schema doesn't appear to contain a version table.\n");
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Schema doesn't appear to contain a version table.");
+ }
+ mysql_free_result(result);
+ } else {
+ fprintf(stderr,"Query failed, Schema doesn't appear to contain a version table.\n");
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "Query for version table failed.");
+ }
+ return returnvalue;
+}
+
+
+
+
+
+/* function storeStationToDbMysql()
+ */
+int storeStationToDbMysql(Connection *aDbConnection, DataRow *aStation){
+ int returnvalue = 0;
+ //ioparam *device = aDbConnection->descriptor;
+ // check type of schema to use (XASTIR simple, full or APRSWorld)
+ switch (devices[aDbConnection->interface_number].database_schema_type) {
+ case XASTIR_SCHEMA_SIMPLE :
+ returnvalue = storeStationSimplePointToDbMysql(aDbConnection,aStation);
+ break;
+ case XASTIR_SCHEMA_APRSWORLD :
+ break;
+ case XASTIR_SCHEMA_COMPLEX :
+ break;
+ // otherwise error message
+ }
+ return returnvalue;
+}
+
+
+
+
+
+/* function getAllSimplePositionsMysql()
+ * MySQL implementation of getAllSimplePositions for a MySQL database that
+ * does not include spatial support.
+ * @param aDbConnection an exastir database connection struct describing
+ * the connection.
+ * Returns 0 for failure, 1 for success.
+ * If failure, stores error message in aDbConnection->errormessage.
+ */
+int getAllSimplePositionsMysql(Connection *aDbConnection) {
+ int returnvalue = 0;
+ DataRow *p_new_station;
+ //DataRow *p_time;
+ int station_count = 0; // number of new stations retrieved
+ //unsigned long x; // xastir coordinate for longitude
+ //unsigned long y; // xastir coordinate for latitide
+ //float lat; // latitude converted from retrieved string
+ //float lon; // longitude converted from retrieved string
+ char feedback[100];
+ //struct tm time;
+ char sql[] = "select station, transmit_time, latitude, longitude, symbol, overlay, aprstype, origin, record_type, node_path from simpleStation order by station, transmit_time";
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ int ok; // to hold mysql_query return value
+ ok = mysql_query(&aDbConnection->mhandle,sql);
+ if (ok==0) {
+ result = mysql_use_result(&aDbConnection->mhandle);
+ if (result!=NULL) {
+ xastir_snprintf(feedback,100,"Retrieving MySQL records\n");
+ stderr_and_statusline(feedback);
+ // with mysql_use_result each call to mysql_fetch_row retrieves
+ // a row of data from the server. Mysql_store_result might use
+ // too much memory in retrieving a large result set all at once.
+ while ((row = mysql_fetch_row(result))) {
+ // retrieve data from the row
+ // test to see if this is a valid station
+ if (row[0]==NULL) {
+ // station is null, skip
+ } else {
+ p_new_station = NULL;
+ if (search_station_name(&p_new_station,row[0],1)) {
+ // This station is allready in present as a DataRow in the xastir db.
+ // Add data to the station's track.
+ } else {
+ // This station isn't in the xastir db.
+ // Add a datarow using the retrieved station record from the postgis database.
+ add_simple_station(p_new_station, row[0], row[7], row[4], row[5], row[6], row[2], row[3], row[8], row[9], row[1],(char*)MYSQL_TIMEFORMAT);
+
+ station_count++;
+ }
+ }
+ }
+ } else {
+ // error fetching the result set
+ fprintf(stderr,"mysql error: %s\n",mysql_error(&aDbConnection->mhandle));
+ mysql_interpret_error(mysql_errno(&aDbConnection->mhandle),aDbConnection);
+ }
+ xastir_snprintf(feedback,100,"Retreived %d new stations from MySQL\n",station_count);
+ stderr_and_statusline(feedback);
+ mysql_free_result(result);
+ } else {
+ // query didn't execute correctly
+ mysql_interpret_error(ok,aDbConnection);
+ }
+ return returnvalue;
+}
+
+
+int getAllSimplePositionsMysqlInBoundingBox(Connection *aDbConnection, char *str_e_long, char *str_w_long, char *str_n_lat, char *str_s_lat) {
+ int returnvalue = 0;
+
+ return returnvalue;
+}
+
+
+
+/* function mysql_interpret_error()
+ * given a mysql error code and an xastir connection, sets an appropriate
+ * error message in the errormessage field of the connection. Interprets
+ * numeric error codes returned by mysql functions.
+ * @param errorcode A result returned by a mysql function that can be
+ * interpreted as an error code.
+ * @param aDbConnection an xastir database connection struct describing the
+ * connection and its current state.
+ * Note - it is possible to give this function a connection on which an
+ * error has not occured along with an error code. This function does
+ * not check the connection or assess whether an error actually occured
+ * on it or not, it simply interprets an error code and writes the
+ * interpretation into the connection that was passed to it.
+ */
+void mysql_interpret_error(int errorcode, Connection *aDbConnection) {
+ fprintf(stderr,"Error communicating with MySQL database. Error code=%d\n",errorcode);
+ switch (errorcode) {
+ case CR_OUT_OF_MEMORY :
+ // insufficient memory for query
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "MySQL: Out of Memory");
+ // notify the connection status listener
+ break;
+ // mysql_query errors
+ case CR_COMMANDS_OUT_OF_SYNC :
+ // commands in improper order
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "MySQL: Commands out of sync");
+ break;
+ case CR_SERVER_GONE_ERROR :
+ // mysql server has gone away
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "MySQL: Connection to server lost");
+ // notify the connection status listener
+ break;
+ case CR_SERVER_LOST :
+ // server connection was lost during query
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "MySQL: Connection to server lost during query");
+ // notify the connection status listener
+ break;
+ case CR_UNKNOWN_ERROR :
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "MySQL: Unknown Error");
+ break;
+ default:
+ xastir_snprintf(aDbConnection->errormessage, MAX_CONNECTION_ERROR_MESSAGE, "MySQL: Unrecognized error Code [%d]", errorcode);
+ }
+ fprintf(stderr,"%s\n",aDbConnection->errormessage);
+}
+
+#endif /* HAVE_MYSQL*/
+
+// add code for a lightweight database here
+
+
+
+
+
+
+
+#endif /* HAVE_DB*/
+
+// Functions related to GIS, but not database specific ************************
+
+
+
+
+/* Function xastirCoordToLatLongPostgresPoint
+ * converts a point in xastir coordinates to a native postgres representation
+ * of a point using latitude and longitude in decimal degrees in the WGS84
+ * projection EPSG:4326. Format is similar to WKT, but without leading POINT.
+ * @param x longitude in xastir coordinates = decimal 100ths of a second.
+ * @param y latitude in xastir coordinates = decimal 100ths of a second.
+ * @param pointer to a char[ at least 24] string to hold point representation.
+ * returns 1 on success, 0 on failure.
+ */
+int xastirCoordToLatLongPostgresPoint(long x, long y, char *wkt) {
+ // 1 xastir coordinate = 1/100 of a second
+ // 100*60*60 xastir coordinates (=360000 xastir coordinates) = 1 degree
+ // 360000 xastir coordinates = 1 degree
+ // conversion to string decimal degrees handled by utility fuctions
+ int returnvalue = 0; // defaults to failure
+ float latitude;
+ float longitude;
+ int ok;
+ ok = convert_from_xastir_coordinates (&longitude,&latitude, x, y);
+ if (ok>0) {
+ xastir_snprintf(wkt, MAX_WKT, "(%3.6f, %3.6f)", latitude, longitude);
+ returnvalue = 1;
+ }
+ return returnvalue;
+}
+
+
+
+
+
+
+/* Function xastirCoordToLatLongWKT
+ * converts a point in xastir coordinates to a well known text string (WKT)
+ * representation of a point using latitude and longitude in decimal degrees
+ * in the WGS84 projection EPSG:4326
+ * @param x longitude in xastir coordinates = decimal 100ths of a second.
+ * @param y latitude in xastir coordinates = decimal 100ths of a second.
+ * @param pointer to a char[29] string to hold well known text representation.
+ * returns 1 on success, 0 on failure.
+ */
+int xastirCoordToLatLongWKT(long x, long y, char *wkt) {
+ // 1 xastir coordinate = 1/100 of a second
+ // 100*60*60 xastir coordinates (=360000 xastir coordinates) = 1 degree
+ // 360000 xastir coordinates = 1 degree
+ // conversion to string decimal degrees handled by utility fuctions
+ int returnvalue = 0; // defaults to failure
+ float latitude;
+ float longitude;
+ int ok;
+ ok = convert_from_xastir_coordinates (&longitude,&latitude, x, y);
+ if (ok>0) {
+ xastir_snprintf(wkt, MAX_WKT, "POINT(%3.6f %3.6f)", longitude, latitude);
+ returnvalue = 1;
+ }
+ return returnvalue;
+}
+
+
+
+
+
+float xastirWKTPointToLongitude(char *wkt) {
+ float returnvalue = 0.0;
+ char temp[MAX_WKT];
+ char *space = NULL;
+ int x;
+ if (wkt[0]=='P' && wkt[1]=='O' && wkt[2]=='I' && wkt[3]=='N' && wkt[4]=='T' && wkt[5]=='(') {
+ // this is a point
+ xastir_snprintf(temp, MAX_WKT, "%s", wkt);
+ // truncate at the space
+ space = strchr(temp,' ');
+ if (space != NULL) {
+ *space = '\0';
+ }
+ // remove the leading "POINT("
+ for (x=0;x<6;x++) {
+ temp[x]=' ';
+ }
+ returnvalue = atof(temp);
+ }
+ return returnvalue;
+}
+
+
+
+
+
+float xastirWKTPointToLatitude(char *wkt) {
+ float returnvalue = 0.0;
+ char temp[MAX_WKT];
+ char *paren = NULL;
+ int x;
+ if (wkt[0]=='P' && wkt[1]=='O' && wkt[2]=='I' && wkt[3]=='N' && wkt[4]=='T' && wkt[5]=='(') {
+ // this is a point
+ xastir_snprintf(temp, MAX_WKT, "%s", wkt);
+ // truncate at the trailing parenthesis
+ paren = strchr(temp,')');
+ if (paren != NULL) {
+ *paren = '\0';
+ }
+ // convert all leading characters up to the space to spaces.
+ for (x=0;x<(int)(strlen(temp));x++) {
+ if (temp[x]==' ') {
+ x = (int)(strlen(temp));
+ } else {
+ temp[x] = ' ';
+ }
+ }
+ returnvalue = atof(temp);
+ }
+ return returnvalue;
+
+}
+
diff --git a/src/db_gis.h b/src/db_gis.h
new file mode 100644
index 0000000..3ac0405
--- /dev/null
+++ b/src/db_gis.h
@@ -0,0 +1,176 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: db_gis.h,v 1.15 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 2007-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#include "xastir.h"
+#include "interface.h" // ioparam struct is used to store descriptions of databases
+ // to which to connect.
+extern int xastirCoordToLatLongWKT(long x, long y, char *wkt);
+extern int xastirCoordToLatLongPoint(long x, long y, char *wkt);
+extern float xastirWKTPointToLatitude(char *wkt);
+extern float xastirWKTPointToLongitude(char *wkt);
+
+// maximum size of a well known text representation of a geometry
+// 100 should be fine for points, will need to be longer for other geometries.
+#define MAX_WKT 100
+
+#ifdef HAVE_DB
+// maximum number of open database connections
+#define MAX_DB_CONNECTIONS 20
+
+// includes for database client libraries and
+// constants to identify database types
+// constants are used in interface_gui.c
+// where the specify order on picklist
+// *** Need to localize these and the schema types ***
+#ifdef HAVE_MYSQL
+// MySQL version 3.x and higher
+#include <mysql.h>
+// mysql error message codes
+#include <errmsg.h>
+#define DB_MYSQL 1
+#endif /* HAVE_MYSQL */
+
+#ifdef HAVE_SPATIAL_DB
+
+#ifdef HAVE_POSTGIS
+// Postgresql with postgis
+#include <libpq-fe.h>
+#define DB_POSTGIS 2
+#define POSTGRES_RESULTFORMAT_TEXT 0
+#endif /* HAVE_POSTGIS */
+
+#ifdef HAVE_MYSQL_SPATIAL
+// MySQL version 4.1 and higher
+#define DB_MYSQL_SPATIAL 3
+#endif /* HAVE_MYSQL_SPATIAL */
+
+#define MAX_DB_TYPE 3 // largest value for DB_
+ // used in load_data_or_default
+#define NODE_PATH_SIZE 56 // field size for node_path, for data_row.node_path_ptr
+
+// constants to control database schema versioning
+
+// Version of the mysql/postgresql table structures this version of xastir expects to find.
+// Any change or addition of database schema elements should trigger a version change.
+// Newer versions of xastir should require an older database to be upgraded to the
+// current version before allowing queries to run against that database.
+#define XASTIR_SPATIAL_DB_VERSION 1
+// Allow grouping of forward compatible table structures allowing an older version of xastir to
+// interact with a database created by a newer version of xastir of the same compatble series
+// addition of new tables and fields shouldn't change comapatable series, but renamed, deleted,
+// or shortened schema elements should change compatible series (changes where a select or
+// or insert query run by an older version of xastir will fail against a newer database).
+#define XASTIR_SPATIAL_DB_COMPATABLE_SERIES 1
+
+// constants to indicate schema to use in a database
+#define XASTIR_SCHEMA_SIMPLE 1 // simple station table only
+#define XASTIR_SCHEMA_CAD 2 // simple station table and cad objects
+#define XASTIR_SCHEMA_COMPLEX 3 // full aprs concept support
+#define XASTIR_SCHEMA_APRSWORLD 4 // aprs world implementaiton
+
+#define MAX_XASTIR_SCHEMA 4 // largest value for xastir_schema_
+ // used in load_data_or_default
+
+#define XASTIR_SCHEMA_DESCRIPTOR_MAX_SIZE 50 // largest allowed size of a localized schema descriptor string
+#define XASTIR_DB_DESCRIPTOR_MAX_SIZE 50 // largest allowed size of a localized dbms descriptor string
+
+
+// description of a database
+// replaced with extension of ioparam struct in interface.h
+/*
+typedef struct {
+ char name[MAX_DEVICE_NAME+1]; // name of connection to display to user - ioparam device_name
+ char host[255]; // hostname for database server - ioparam device_host_name
+ int port; // port on which to connect to database server - ioparam sp
+ char password[20]; // password to use to connect to database - ioparam device_host_password
+ char username[20]; // username to use to connect to database
+ int type; // type of dbms (posgresql, mysql, etc)
+ char schema[20]; // name of database or schema to use
+ char makeerrormessage[255]; // most recent error message from attempting to make a
+ // connection with using this descriptor.
+ int schema_type; // table structures to use in the database
+ // A database schema could contain both APRSWorld
+ // and XASTIR table structures, but a separate database
+ // descriptor should be defined for each.
+ char unix_socket[255]; // MySQL - unix socket parameter (path and filename)
+ //connection_list open_connections // list of open connections to this database
+} DbDescriptor;
+*/
+#define MAX_CONNECTION_ERROR_MESSAGE 255
+// a database connection
+typedef struct {
+ int type; // type of dbms (postgresql, mysql, etc, redundant from descriptor->type)
+ ioparam *descriptor; // connection parameters used to establish this connnection
+ // stored in ioparam struct defined in interface.h
+#ifdef HAVE_MYSQL
+ MYSQL mhandle; // mysql connection
+#endif /* HAVE_MYSQL */
+#ifdef HAVE_POSTGIS
+ PGconn *phandle; // postgres connection
+#endif /* HAVE_POSTGIS */
+ char errormessage[MAX_CONNECTION_ERROR_MESSAGE]; // most recent error message on this connection.
+ int interface_number; // number of the interface on which this connection is managed
+} Connection;
+
+
+// list of database connections
+//typedef struct{
+// Connection *conn; // a database connection
+// ioparam *iface; // interface definition for the connection
+//} ConnectionList;
+
+//extern ConnectionList connections[MAX_IFACE_DEVICES];
+extern Connection connections[MAX_IFACE_DEVICES];
+extern int connections_initialized;
+
+
+// connection management
+extern int openConnection (ioparam *aioparm, Connection *conn);
+int initAConnection(Connection *connection, int x);
+extern int closeConnection (Connection *aDbConnection, int port_number);
+extern int testConnection(Connection *aDbConnection);
+int pingConnection(Connection *aDbConnection);
+
+extern char xastir_dbms_type[4][51];
+extern char xastir_schema_type[5][51];
+
+// storing and retrieving data from a database
+extern int storeStationToGisDb(Connection *aDbConnection, DataRow *aStation);
+extern int storeCadToGisDb(Connection *aDbConnection, CADRow *aCadObject);
+extern int storeStationSimpleToGisDb(Connection *aDbConnection, DataRow *aStation);
+extern int getAllSimplePositions(Connection *aDbConnection);
+extern int getAllSimplePositionsInBoundingBox(Connection *aDbConnection, int east, int west, int north, int south);
+extern ioparam simpleDbTest(void);
+
+#endif /* HAVE_SPATIAL_DB */
+
+extern int initConnections(void);
+#endif /* HAVE_DB */
+
+// structure to hold a latutude and longitude in decimal degrees
+typedef struct {
+ float latitude;
+ float longitude;
+} Point;
+
+
diff --git a/src/dbfawk.c b/src/dbfawk.c
new file mode 100644
index 0000000..a82a793
--- /dev/null
+++ b/src/dbfawk.c
@@ -0,0 +1,498 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: dbfawk.c,v 1.38 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 2003-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ *
+ */
+/*
+ * This library glues the Awk-like functions (see awk.c) to attributes
+ * for shapefiles (contained in DBF files).
+ *
+ * Alan Crosswell, n2ygk at weca.org
+ *
+ */
+
+
+//
+// Functions which allocate memory:
+// --------------------------------
+// dbfawk_field_list
+// dbfawk_load_sigs
+// dbfawk_find_sig
+// dbfawk_parse_record (indirectly)
+//
+// Functions which free memory:
+// ----------------------------
+// dbfawk_free_info
+// dbfawk_load_sigs
+// dbfawk_free_sig
+// dbfawk_free_sigs
+// dbfawk_find_sig
+//
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#if defined(WITH_DBFAWK) && defined(HAVE_LIBSHP) && defined(HAVE_LIBPCRE)
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include "awk.h"
+#include "dbfawk.h"
+#include "snprintf.h"
+#include "maps.h"
+
+#include <sys/stat.h>
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+
+
+/*
+ * dbfawk_sig: Generate a signature for a DBF file.
+ * Fills in sig and returns number of fields.
+ */
+int dbfawk_sig(DBFHandle dbf, char *sig, int size) {
+ int nf = 0;
+
+ if (sig && size > 0 && dbf) {
+ int i;
+ char *sp;
+ int width,prec;
+
+ nf = DBFGetFieldCount(dbf);
+ for (i = 0, sp=sig; sp < &sig[size-XBASE_FLDHDR_SZ] && i < nf ; i++) {
+ DBFGetFieldInfo(dbf,i,sp,&width,&prec);
+ sp += strlen(sp);
+ *sp++ = ':'; /* field name separator */
+ }
+ if (i)
+ *--sp = '\0'; /* clobber the trailing sep */
+ }
+ return nf;
+}
+
+
+
+
+
+/* Free a field list */
+void dbfawk_free_info ( dbfawk_field_info *list) {
+ dbfawk_field_info *x, *p;
+
+ for ( p = list; p != NULL; ) {
+ x = p;
+ p = p->next;
+ free(x);
+ }
+}
+
+
+
+
+
+/*
+ * dbfawk_field_list: Generate a list of info about fields to read for
+ * a given DBFHandle and colon-separated list of fieldnames.
+ */
+dbfawk_field_info *dbfawk_field_list(DBFHandle dbf, char *dbffields) {
+ dbfawk_field_info *fi = NULL, *head = NULL, *prev;
+ int nf;
+ char *sp;
+
+ /* now build up the list of fields to read */
+ for (nf = 0, sp = dbffields, prev = NULL; *sp; nf++) {
+ char *d,*p = sp;
+ char junk[XBASE_FLDHDR_SZ];
+ int w,prec;
+
+ fi = calloc(1,sizeof(dbfawk_field_info));
+ if (!fi) {
+ fprintf(stderr,"dbfawk_field_list: first calloc failed\n");
+ return NULL;
+ }
+
+ if (prev) {
+ prev->next = fi;
+ } else { /* no prev, must be first one */
+ head = fi;
+ }
+ d = fi->name;
+ while (*p && *p != ':') *d++ = *p++;
+ if (*p == ':')
+ *p++ = '\0';
+ *d='\0';
+ fi->num = DBFGetFieldIndex(dbf, fi->name);
+ fi->type = DBFGetFieldInfo(dbf, fi->num, junk, &w, &prec);
+ sp = p;
+ prev = fi;
+ }
+
+ return head;
+}
+
+
+
+
+
+/*
+ * dbfawk_load_sigs: Load up dbfawk signature mappings
+ * Reads *.dbfawk and registers dbffields "signature".
+ * Returns head of sig_info list.
+ *
+ * TODO - consider whether it makes sense to use a private symtbl,
+ * compile and then free here or require the caller to pass in a
+ * symtbl that has dbfinfo declared.
+ */
+// Malloc's dbfawk_sig_info and returns a filled-in list
+
+dbfawk_sig_info *dbfawk_load_sigs(const char *dir, /* directory path */
+ const char *ftype) /* filetype */ {
+ DIR *d;
+ struct dirent *e;
+ struct stat nfile;
+ char fullpath[MAX_FILENAME];
+ int ftlen;
+ dbfawk_sig_info *i = NULL, *head = NULL;
+ awk_symtab *symtbl;
+ char dbfinfo[1024]; /* local copy of signature */
+
+ if (!dir || !ftype) {
+ return NULL;
+ }
+ ftlen = strlen(ftype);
+ d = opendir(dir);
+ if (!d) {
+ return NULL;
+ }
+
+ symtbl = awk_new_symtab();
+ if (!symtbl) {
+ return NULL;
+ }
+
+ awk_declare_sym(symtbl,"dbfinfo",STRING,dbfinfo,sizeof(dbfinfo));
+
+ while ((e = readdir(d)) != NULL) {
+ int len = strlen(e->d_name);
+ char *path = calloc(1,len+strlen(dir)+2);
+
+ // Check for hidden files or directories
+ if (e->d_name[0] == '.') {
+ // Hidden, skip it
+ free(path);
+ continue;
+ }
+
+ // Check for regular files
+
+ xastir_snprintf(fullpath,
+ sizeof(fullpath),
+ "%s/%s",
+ dir,
+ e->d_name);
+
+ if (stat(fullpath, &nfile) != 0) {
+ // Couldn't stat file
+ free(path);
+ continue;
+ }
+
+ if ((nfile.st_mode & S_IFMT) != S_IFREG) {
+ // Not a regular file
+ free(path);
+ continue;
+ }
+
+ if (!path) {
+ if (symtbl)
+ awk_free_symtab(symtbl);
+ fprintf(stderr,"failed to malloc in dbfawk.c!\n");
+ closedir(d);
+ return NULL;
+ }
+
+ *dbfinfo = '\0';
+ if (len > ftlen && (strcmp(&e->d_name[len-ftlen],ftype) == 0)) {
+ if (!head) {
+ i = head = calloc(1,sizeof(dbfawk_sig_info));
+
+ if (!i) {
+ fprintf(stderr,"failed to malloc in dbfawk.c!\n");
+ free(path);
+ if (symtbl)
+ awk_free_symtab(symtbl);
+ closedir(d);
+ return NULL;
+ }
+ } else {
+ i->next = calloc(1,sizeof(dbfawk_sig_info));
+
+ if (!i->next) {
+ fprintf(stderr,"failed to malloc in dbfawk.c!\n");
+ free(path);
+ if (symtbl)
+ awk_free_symtab(symtbl);
+ closedir(d);
+ return head; // Return what we were able to gather.
+ }
+
+ i = i->next;
+ }
+
+ xastir_snprintf(path,
+ len+strlen(dir)+2,
+ "%s/%s",
+ dir,
+ e->d_name);
+
+ i->prog = awk_load_program_file(path);
+
+ if (awk_compile_program(symtbl,i->prog) < 0) {
+ fprintf(stderr,"%s: failed to parse\n",e->d_name);
+ } else {
+ /* dbfinfo must be defined in BEGIN rule */
+ awk_exec_begin(i->prog);
+
+ i->sig = strdup(dbfinfo);
+
+ awk_uncompile_program(i->prog);
+ }
+ }
+ free(path);
+ }
+
+ closedir(d);
+
+ if (symtbl)
+ awk_free_symtab(symtbl);
+
+ return head;
+}
+
+
+
+
+
+void dbfawk_free_sig(dbfawk_sig_info *ptr) {
+
+ if (ptr) {
+ if (ptr->prog)
+ awk_free_program(ptr->prog);
+
+ if (ptr->sig) {
+ free(ptr->sig);
+ }
+ free(ptr);
+ }
+}
+
+
+
+
+
+void dbfawk_free_sigs(dbfawk_sig_info *list) {
+ dbfawk_sig_info *x, *p;
+
+ for (p = list; p; ) {
+ x = p;
+ p = p->next;
+ dbfawk_free_sig(x);
+ }
+}
+
+
+
+
+
+/*
+ * dbfawk_find_sig: Given a DBF file's "signature", find the appropriate
+ * awk program. If filename is not null, see if there's a per-file .dbfawk
+ * and load it.
+ */
+
+dbfawk_sig_info *dbfawk_find_sig(dbfawk_sig_info *Dbf_sigs,
+ const char *sig,
+ const char *file) {
+ dbfawk_sig_info *result = NULL;
+
+ if (file) {
+ char *dot, *perfile = calloc(1,strlen(file)+7);
+ dbfawk_sig_info *info;
+
+ if (!perfile) {
+ fprintf(stderr,"failed to malloc in dbfawk_find_sig!\n");
+ return NULL;
+ }
+
+ xastir_snprintf(perfile,
+ strlen(file)+7,
+ "%s",
+ file);
+
+ dot = strrchr(perfile,'.');
+
+ if (dot)
+ *dot = '\0';
+
+ strncat(perfile, ".dbfawk", 8);
+
+ info = calloc(1,sizeof(*info));
+
+ if (!info) {
+ fprintf(stderr,"failed to malloc in dbfawk_find_sig!\n");
+ free(perfile);
+ return NULL;
+ }
+ info->prog = awk_load_program_file(perfile);
+ /* N.B. info->sig is left NULL since it won't be searched, and
+ to flag that it's safe to free this memory when we're done with
+ it */
+ info->sig = NULL;
+ free(perfile);
+ if (info->prog) {
+
+ return info;
+ }
+ else {
+ dbfawk_free_sigs(info);
+ }
+ /* fall through and do normal signature search */
+ }
+
+ for (result = Dbf_sigs; result; result = result->next) {
+ if (strcmp(result->sig,sig) == 0) {
+ return result;
+ }
+ }
+ return NULL;
+}
+
+
+
+
+
+/*
+ * dbfawk_parse_record: Read a dbf record and parse only the fields
+ * listed in 'fi' using the program, 'rs'.
+ */
+void dbfawk_parse_record(awk_program *rs,
+ DBFHandle dbf,
+ dbfawk_field_info *fi,
+ int i) {
+ dbfawk_field_info *finfo;
+
+ awk_exec_begin_record(rs); /* execute a BEGIN_RECORD rule if any */
+
+ for (finfo = fi; finfo ; finfo = finfo->next) {
+ char qbuf[1024];
+
+ switch (finfo->type) {
+ case FTString:
+ sprintf(qbuf,"%s=%s",finfo->name,DBFReadStringAttribute(dbf,i,finfo->num));
+ break;
+ case FTInteger:
+ sprintf(qbuf,"%s=%d",finfo->name,DBFReadIntegerAttribute(dbf,i,finfo->num));
+ break;
+ case FTDouble:
+ sprintf(qbuf,"%s=%f",finfo->name,DBFReadDoubleAttribute(dbf,i,finfo->num));
+ break;
+ case FTInvalid:
+ default:
+ sprintf(qbuf,"%s=??",finfo->name);
+ break;
+ }
+ if (awk_exec_program(rs,qbuf,strlen(qbuf)) == 2)
+ break;
+ }
+ awk_exec_end_record(rs); /* execute an END_RECORD rule if any */
+}
+
+
+
+
+
+#ifndef HAVE_DBFGETFIELDINDEX
+#include <ctype.h>
+/************************************************************************/
+/* str_to_upper() */
+/************************************************************************/
+
+static void str_to_upper (char *string) {
+ int len;
+ short i = -1;
+
+ len = strlen (string);
+
+ while (++i < len)
+ if (isalpha(string[i]) && islower(string[i]))
+ string[i] = toupper ((int)string[i]);
+}
+
+
+
+
+
+/************************************************************************/
+/* DBFGetFieldIndex() */
+/* */
+/* Get the index number for a field in a .dbf file. */
+/* */
+/* Contributed by Jim Matthews. */
+/************************************************************************/
+
+int DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName) {
+ char name[12], name1[12], name2[12];
+ int i;
+
+ xastir_snprintf(name1,
+ sizeof(name1),
+ "%s",
+ pszFieldName);
+
+ str_to_upper(name1);
+
+ for( i = 0; i < DBFGetFieldCount(psDBF); i++ ) {
+ DBFGetFieldInfo( psDBF, i, name, NULL, NULL );
+ xastir_snprintf(name2,
+ sizeof(name2),
+ "%s",
+ name);
+ str_to_upper(name2);
+
+ if(!strncmp(name1,name2,10))
+ return(i);
+ }
+ return(-1);
+}
+
+
+
+#endif
+#endif /* HAVE_LIBSHP && HAVE_LIBPCRE */
+
+
diff --git a/src/dbfawk.h b/src/dbfawk.h
new file mode 100644
index 0000000..bf55a5a
--- /dev/null
+++ b/src/dbfawk.h
@@ -0,0 +1,65 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: dbfawk.h,v 1.13 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 2003-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ *
+ */
+#ifndef DBFAWK_H
+#define DBFAWK_H
+
+#ifndef _SHAPEFILE_H_INCLUDED
+#ifdef HAVE_SHAPEFIL_H
+#include <shapefil.h>
+#else
+#ifdef HAVE_LIBSHP_SHAPEFIL_H
+#include <libshp/shapefil.h>
+#else
+#error HAVE_LIBSHP defined but no corresponding include defined
+#endif // HAVE_LIBSHP_SHAPEFIL_H
+#endif // HAVE_SHAPEFIL_H
+#endif // _SHAPEFILE_H_INCLUDED
+
+typedef struct dbfawk_field_info_ {
+ struct dbfawk_field_info_ *next;
+ char name[XBASE_FLDHDR_SZ]; /* name of the field */
+ int num; /* column number */
+ DBFFieldType type; /* data type */
+} dbfawk_field_info;
+
+typedef struct dbfawk_sig_info_ {
+ struct dbfawk_sig_info_ *next;
+ char *sig; /* dbfinfo signature */
+ awk_program *prog; /* the program for this signature */
+} dbfawk_sig_info;
+
+extern int dbfawk_sig(DBFHandle dbf, char *sig, int size);
+extern dbfawk_field_info *dbfawk_field_list(DBFHandle dbf, char *dbffields);
+extern dbfawk_sig_info *dbfawk_load_sigs(const char *dir, const char *ftype);
+extern dbfawk_sig_info *dbfawk_find_sig(dbfawk_sig_info *info,
+ const char *sig,
+ const char *file);
+extern void dbfawk_free_sig(dbfawk_sig_info *sig);
+extern void dbfawk_free_sigs(dbfawk_sig_info *list);
+extern void dbfawk_free_info(dbfawk_field_info *list);
+extern void dbfawk_parse_record(awk_program *rs,
+ DBFHandle dbf,
+ dbfawk_field_info *fi,
+ int i);
+#endif /* !DBFAWK_H*/
diff --git a/src/draw_symbols.c b/src/draw_symbols.c
new file mode 100644
index 0000000..30d4842
--- /dev/null
+++ b/src/draw_symbols.c
@@ -0,0 +1,3547 @@
+/*
+ * $Id: draw_symbols.c,v 1.120 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <Xm/XmAll.h>
+
+#include "xastir.h"
+#include "database.h"
+#include "draw_symbols.h"
+#include "main.h"
+#include "util.h"
+#include "color.h"
+#include "maps.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+extern XmFontList fontlist1; // Menu/System fontlist
+
+
+#define ANGLE_UPDOWN 30 /* prefer horizontal cars if less than 45 degrees */
+
+int symbols_loaded = 0;
+int symbols_cache[5] = {0,0,0,0,0};
+Widget select_symbol_dialog = (Widget)NULL;
+static xastir_mutex select_symbol_dialog_lock;
+Pixmap select_icons[(126-32)*2]; //33 to 126 with both '/' and '\' symbols (94 * 2) or 188
+int symbol_change_requested_from = 0;
+
+
+
+
+
+void draw_symbols_init(void)
+{
+ init_critical_section( &select_symbol_dialog_lock );
+}
+
+
+
+
+
+/*** symbol data ***/
+
+void clear_symbol_data(void) {
+ int my_size;
+ int i;
+ char *data_ptr;
+
+ data_ptr = (char *)symbol_data;
+ my_size = (int)sizeof(SymbolData);
+ for (i=0;i<my_size;i++)
+ *data_ptr++ = '\0';
+ symbols_loaded = 0;
+}
+
+
+
+
+
+/*
+ * Draw nice looking text
+ */
+void draw_nice_string(Widget w, Pixmap where, int style, long x, long y, char *text, int bgcolor, int fgcolor, int length) {
+ GContext gcontext;
+ XFontStruct *xfs_ptr;
+ int font_width, font_height;
+
+
+ if (x > screen_width) return;
+ if (x < 0) return;
+ if (y > screen_height) return;
+ if (y < 0) return;
+
+ switch (style) {
+
+ case 0:
+ // make outline style
+ (void)XSetForeground(XtDisplay(w),gc,colors[bgcolor]);
+ // draw an outline 1 pixel bigger than text
+ (void)XDrawString(XtDisplay(w),where,gc,x+1,y-1,text,length);
+ (void)XDrawString(XtDisplay(w),where,gc,x+1,y,text,length);
+ (void)XDrawString(XtDisplay(w),where,gc,x+1,y+1,text,length);
+ (void)XDrawString(XtDisplay(w),where,gc,x-1,y,text,length);
+ (void)XDrawString(XtDisplay(w),where,gc,x-1,y-1,text,length);
+ (void)XDrawString(XtDisplay(w),where,gc,x-1,y+1,text,length);
+ (void)XDrawString(XtDisplay(w),where,gc,x,y+1,text,length);
+ (void)XDrawString(XtDisplay(w),where,gc,x,y-1,text,length);
+ break;
+
+ case 1:
+ // draw text the old way in a gray box
+ // Leave this next one hard-coded to 0xff. This keeps
+ // the background as gray.
+
+// With a large font, the background rectangle is too small. Need
+// to include the font metrics in this drawing algorithm.
+
+ (void)XSetForeground(XtDisplay(w),gc,colors[0xff]);
+ (void)XFillRectangle(XtDisplay(w),where,gc,x-1,(y-10),(length*6)+2,11);
+ (void)XSetForeground(XtDisplay(w),gc,colors[bgcolor]);
+ (void)XDrawString(XtDisplay(w),where,gc,x+1,y+1,text,length);
+ break;
+
+ case 2:
+ default:
+ // draw white or colored text in a black box
+
+ // With a large font, the background rectangle is too
+ // small. Need to include the font metrics in this
+ // drawing algorithm, which we do here.
+
+ gcontext = XGContextFromGC(gc);
+
+ xfs_ptr = XQueryFont(XtDisplay(w), gcontext);
+
+
+// font_width = xfs_ptr->max_bounds.width
+// + xfs_ptr->max_bounds.rbearing
+// - xfs_ptr->max_bounds.lbearing;
+// font_width = xfs_ptr->max_bounds.width;
+ font_width = (int)((xfs_ptr->max_bounds.width
+ + xfs_ptr->max_bounds.width
+ + xfs_ptr->max_bounds.width
+ + xfs_ptr->min_bounds.width) / 4);
+
+ font_height = xfs_ptr->max_bounds.ascent
+ + xfs_ptr->max_bounds.descent;
+
+ if (xfs_ptr) {
+ // This leaks memory if the last parameter is a "0"
+ XFreeFontInfo(NULL, xfs_ptr, 1);
+ }
+
+ // Normal font returns 10 & 13. Large system font
+ // returns 13 & 20 here.
+ //fprintf(stderr,
+ // "Font dimemsions: Width:%d Height:%d\n",
+ // font_width,
+ // font_height);
+
+ (void)XSetForeground( XtDisplay(w),
+ gc,
+ GetPixelByName(w,"black") );
+
+// Old:
+//(void)XFillRectangle(XtDisplay(w),where,gc,x-2,(y-11),(length*6)+3,13);
+
+// New: This one makes the black rectangle too long for smaller
+// fonts. Perhaps because they are proportional?
+ (void)XFillRectangle( XtDisplay(w),
+ where,
+ gc,
+ x-2, // X
+ y-font_height, // Y
+ (length*font_width)+3, // width
+ font_height+2); // height
+
+ break;
+
+ }
+
+ // finally draw the text
+ (void)XSetForeground(XtDisplay(w),gc,colors[fgcolor]);
+ (void)XDrawString(XtDisplay(w),where,gc,x,y,text,length);
+}
+
+
+
+
+
+/* symbol drawing routines */
+
+
+
+
+
+// Function to draw a line between a WP symbol "\/" and the
+// transmitting station. We pass it the WP symbol. It does a
+// lookup for the transmitting station callsign to get those
+// coordinates, then draws a line between the two symbols if
+// possible (both on screen).
+//
+// If the symbol was a Waypoint symbol, "\/", we need to draw a line
+// from the transmitting station to the waypoint symbol according to
+// the spec. Take care to not draw the line any longer than needed
+// (don't exercise the X11 long-line drawing bug). According to the
+// spec we also need to change the symbol to just a red dot, but
+// it's nice having the "WP" above it so we can differentiate it
+// from the other red dot symbol.
+//
+// We should skip drawing the line if the object/item is not being drawn.
+// Should we skip it if the origination station isn't being drawn?
+// Do we need to add yet another togglebutton to enable/disable this line?
+//
+// Note that this type of operation, making a relation between two
+// symbols, breaks our paradism quite a bit. Until now all symbols
+// have been independent of each other. Perhaps we should store the
+// location of one symbol in the data of the other so that we won't
+// have to compare back and forth. This won't help much if either
+// or both symbols are moving. Probably better to just do a lookup
+// of the originating station by callsign through our lists and then
+// draw the line between the two coordinates each time.
+//
+void draw_WP_line(DataRow *p_station,
+ int ambiguity_flag,
+ long ambiguity_coord_lon,
+ long ambiguity_coord_lat,
+ Pixmap where,
+ Widget w) {
+ DataRow *transmitting_station = NULL;
+ int my_course;
+ long x_long, y_lat;
+ long x_long2, y_lat2;
+ double lat_m;
+ long x, y;
+ long x2, y2;
+ double temp;
+ int color = trail_colors[p_station->trail_color];
+ float temp_latitude, temp_latitude2;
+ float temp_longitude, temp_longitude2;
+
+
+ // Compute screen position of waypoint symbol
+ if (ambiguity_flag) {
+ x_long = ambiguity_coord_lon;
+ y_lat = ambiguity_coord_lat;
+ }
+ else {
+ x_long = p_station->coord_lon;
+ y_lat = p_station->coord_lat;
+ }
+
+ // x & y are screen location of waypoint symbol
+ x = (x_long - NW_corner_longitude)/scale_x;
+ y = (y_lat - NW_corner_latitude)/scale_y;
+
+ // Find transmitting station, get it's position.
+ // p_station->origin contains the callsign for the transmitting
+ // station. Do a lookup on that callsign through our database
+ // to get the position of that station.
+
+ if (!search_station_name(&transmitting_station,p_station->origin,1)) {
+ // Can't find call,
+ return;
+ }
+
+ x_long2 = transmitting_station->coord_lon;
+ y_lat2 = transmitting_station->coord_lat;
+
+ // x2 & y2 are screen location of transmitting station
+ x2 = (x_long2 - NW_corner_longitude)/scale_x;
+ y2 = (y_lat2 - NW_corner_latitude)/scale_y;
+
+
+/*
+ if ((x2 - x) > 0) {
+ my_course = (int)( 57.29578
+ * atan( (double)((y2-(y*1.0)) / (x2-(x*1.0) ) ) ) );
+ }
+ else {
+ my_course = (int)( 57.29578
+ * atan( (double)((y2-(y*1.0)) / (x-(x2*1.0) ) ) ) );
+ }
+*/
+
+ // Use the mid-latitude formulas for calculating the rhumb line
+ // course. Modified to minimize the number of conversions we
+ // need to do.
+// lat_m = (double)( (y_lat + y_lat2) / 2.0 );
+
+ // Convert from Xastir coordinate system
+// lat_m = (double)( -((lat_m - 32400000l) / 360000.0) );
+
+ lat_m = -((y_lat - 32400000l) / 360000.0)
+ + -((y_lat2 - 32400000l) / 360000.0);
+ lat_m = lat_m / 2.0;
+
+ convert_from_xastir_coordinates(&temp_longitude2,
+ &temp_latitude2,
+ x_long2,
+ y_lat2);
+
+ convert_from_xastir_coordinates(&temp_longitude,
+ &temp_latitude,
+ x_long,
+ y_lat);
+
+ temp = (double)( (temp_longitude2 - temp_longitude)
+ / (temp_latitude2 - temp_latitude) );
+// Check for divide-by-zero here????
+
+ // Calculate course and convert to degrees
+ my_course = (int)( 57.29578 * atan( cos(lat_m) * temp) );
+
+ // The arctan function returns values between -90 and +90. To
+ // obtain the true course we apply the following rules:
+ if (temp_latitude2 > temp_latitude
+ && temp_longitude2 > temp_longitude) {
+ // Do nothing.
+ }
+ else if (temp_latitude2 < temp_latitude
+ && temp_longitude2 > temp_longitude) {
+ my_course = 180 - my_course;
+ }
+ else if (temp_latitude2 < temp_latitude
+ && temp_longitude2 < temp_longitude) {
+ my_course = 180 + my_course;
+ }
+ else if (temp_latitude2 > temp_latitude
+ && temp_longitude2 < temp_longitude) {
+ my_course = 360 - my_course;
+ }
+ else {
+ // ??
+ // Do nothing.
+ }
+
+//fprintf(stderr,"course:%d\n", my_course);
+
+ // Convert to screen angle
+// my_course = my_course + 90;
+
+ // Compute whether either of them are on-screen. If so, draw at
+ // least part of the line between them.
+ (void)XSetLineAttributes(XtDisplay(da), gc, 0, LineOnOffDash, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da),gc,color); // red3
+
+// Check that our parameters are within spec for XDrawLine. We'll
+// stick to 16-bit values here due to warnings on the man-page
+// regarding XSegment structs and the protocol only handling
+// short's/unsigned short's, just in case.
+
+ (void)XDrawLine(XtDisplay(da),where,gc,
+ l16(x), // int
+ l16(y), // int
+ l16(x2), // int
+ l16(y2)); // int
+}
+
+
+
+
+
+//draw_pod_circle(64000000l, 32400000l, 10, colors[0x44], pixmap_final);
+//
+// Probability of Detection circle: A circle around the point last
+// seen drawn at the distance that a person of that description
+// could travel since they were last seen. It helps to limit a
+// search to a reasonable area.
+//
+// It'd be nice to have some method of showing where the center of
+// the circle was as well, in case we don't have a PLS object placed
+// there also. Perhaps a small dot and/or four lines going from
+// that point to the edge of the circle?
+//
+// range is in miles
+// x_long/y_lat are in Xastir lat/lon units
+//
+void draw_pod_circle(long x_long, long y_lat, double range, int color, Pixmap where) {
+ double diameter;
+ double a,b;
+
+
+// Prevents it from being drawn when the symbol is off-screen.
+// It'd be better to check for lat/long +/- range to see if it's on the screen.
+
+// if ((x_long>NW_corner_longitude) && (x_long<SE_corner_longitude)) {
+
+// if ((y_lat>NW_corner_latitude) && (y_lat<SE_corner_latitude)) {
+
+// if ((x_long < 0) || (x_long > 129600000l))
+// return;
+
+// if ((y_lat < 0) || (y_lat > 64800000l))
+// return;
+
+ // Range is in miles. Bottom term is in meters before the 0.0006214
+ // multiplication factor which converts it to miles.
+ // Equation is: 2 * ( range(mi) / x-distance across window(mi) )
+ diameter = 2.0 * ( range/
+ (scale_x * calc_dscale_x(center_longitude,center_latitude) * 0.0006214 ) );
+
+ // If less than 4 pixels across, skip drawing it.
+ if (diameter <= 4.0)
+ return;
+
+ a = diameter;
+ b = diameter / 2;
+
+ //fprintf(stderr,"Range:%f\tDiameter:%f\n",range,diameter);
+
+ (void)XSetLineAttributes(XtDisplay(da), gc, 2, LineSolid, CapButt,JoinMiter);
+ //(void)XSetForeground(XtDisplay(da),gc,colors[0x0a]);
+ //(void)XSetForeground(XtDisplay(da),gc,colors[0x44]); // red3
+ (void)XSetForeground(XtDisplay(da),gc,color);
+
+// Check that our parameters are within spec for XDrawArc. Tricky
+// 'cuz the XArc struct has short's and unsigned short's, while
+// XDrawArc man-page says int's/unsigned int's. We'll stick to 16-bit
+// just to make sure.
+
+ (void)XDrawArc(XtDisplay(da),where,gc,
+ l16(((x_long-NW_corner_longitude)/scale_x)-(diameter/2)), // int
+ l16(((y_lat-NW_corner_latitude)/scale_y)-(diameter/2)), // int
+ lu16(diameter), // unsigned int
+ lu16(diameter), // unsigned int
+ l16(0), // int
+ l16(64*360)); // int
+
+// We may need to check for the lat/long being way too far
+// off-screen, refusing to draw the circles if so, if and only if we
+// get into X11 drawing bugs as-is.
+
+
+// }
+// }
+}
+
+
+
+
+
+// range is in centimeters (0 to 65535 representing 0 to 655.35 meters)
+// x_long/y_lat are in Xastir lat/lon units
+// lat_precision/lon-precision are in 100ths of seconds of lat/lon
+//
+void draw_precision_rectangle(long x_long,
+ long y_lat,
+ double range, // Not implemented yet
+ unsigned int lat_precision,
+ unsigned int lon_precision,
+ int color,
+ Pixmap where) {
+
+// Prevents it from being drawn when the symbol is off-screen.
+// It'd be better to check for lat/long +/- range to see if it's on the screen.
+
+ if ((x_long>NW_corner_longitude) && (x_long<SE_corner_longitude)) {
+
+ if ((y_lat>NW_corner_latitude) && (y_lat<SE_corner_latitude)) {
+ long x2, y2;
+
+
+// if ((x_long < 0) || (x_long > 129600000l))
+// return;
+
+// if ((y_lat < 0) || (y_lat > 64800000l))
+// return;
+
+ (void)XSetLineAttributes(XtDisplay(da), gc, 2, LineSolid, CapButt,JoinMiter);
+ //(void)XSetForeground(XtDisplay(da),gc,colors[0x0a]);
+ //(void)XSetForeground(XtDisplay(da),gc,colors[0x44]); // red3
+ (void)XSetForeground(XtDisplay(da),gc,color);
+
+ if (x_long > 64800000L) {
+ // Eastern hemisphere, add X's (go further east)
+ x2 = x_long + lon_precision;
+ }
+ else {
+ // Western hemisphere, subtract X's (go further west)
+ x2 = x_long - lon_precision;
+ }
+
+ if (y_lat > 32400000L) {
+ // Southern hemisphere, add Y's (go further north)
+ y2 = y_lat + lat_precision;
+ }
+ else {
+ // Northern hemisphere, subtract Y's (go further south)
+ y2 = y_lat - lat_precision;
+ }
+
+ draw_vector(da, x_long, y_lat, x_long, y2, gc, where, 0); // x_long constant
+ draw_vector(da, x_long, y2, x2, y2, gc, where, 0); // y2 constant
+ draw_vector(da, x2, y2, x2, y_lat, gc, where, 0); // x2 constant
+ draw_vector(da, x2, y_lat, x_long, y_lat, gc, where, 0); // y_lat constant
+ }
+ }
+}
+
+
+
+
+
+void draw_phg_rng(long x_long, long y_lat, char *phg, time_t sec_heard, Pixmap where) {
+ double range, diameter;
+ int offx,offy;
+ long xx,yy,xx1,yy1,fxx,fyy;
+ double tilt;
+ double a,b;
+ char is_rng;
+ char *strp;
+
+
+ if ( ((sec_old+sec_heard)>sec_now()) || Select_.old_data ) {
+
+// Prevents it from being drawn when the symbol is off-screen.
+// It'd be better to check for lat/long +/- range to see if it's on the screen.
+
+// if ((x_long>NW_corner_longitude) && (x_long<SE_corner_longitude)) {
+
+// if ((y_lat>NW_corner_latitude) && (y_lat<SE_corner_latitude)) {
+
+ xx=0l;
+ yy=0l;
+ xx1=0l;
+ yy1=0l;
+ fxx=0l;
+ fyy=0l;
+ tilt=0.0;
+ is_rng=0;
+ offx=0;
+ offy=0;
+
+ if (phg[0] == 'R' && phg[1] == 'N' && phg[2] == 'G')
+ is_rng = 1;
+
+// if ((x_long < 0) || (x_long > 129600000l))
+// return;
+
+// if ((y_lat < 0) || (y_lat > 64800000l))
+// return;
+
+ if (is_rng) {
+ strp = &phg[3];
+ range = atof(strp);
+ }
+ else {
+ range = phg_range(phg[3],phg[4],phg[5]);
+ }
+
+ // Range is in miles. Bottom term is in meters before the 0.0006214
+ // multiplication factor which converts it to miles.
+ // Equation is: 2 * ( range(mi) / x-distance across window(mi) )
+ diameter = 2.0 * ( range/
+ (scale_x * calc_dscale_x(center_longitude,center_latitude) * 0.0006214 ) );
+
+ // If less than 4 pixels across, skip drawing it.
+ if (diameter <= 4.0)
+ return;
+
+ //fprintf(stderr,"PHG: %s, Diameter: %f\n", phg, diameter);
+
+ a = diameter;
+ b = diameter / 2;
+
+ if (!is_rng) { // Figure out the directivity, if outside range of 0-8 it's declared to be an omni
+
+ switch (phg[6]-'0') {
+
+ case(0):
+ offx=0;
+ offy=0;
+ break;
+
+ case(1): // 45
+ offx=-1*(diameter/6);
+ offy=diameter/6;
+ tilt=5.49778;
+ break;
+
+ case(2): // 90
+ offx=-1*(diameter/6);
+ offy=0;
+ tilt=0;
+ break;
+
+ case(3): // 135
+ offx=-1*(diameter/6);
+ offy=-1*(diameter/6);
+ tilt=.78539;
+ break;
+
+ case(4): // 180
+ offx=0;
+ offy=-1*(diameter/6);
+ tilt=1.5707;
+ break;
+
+ case(5): // 225
+ offx=diameter/6;
+ offy=-1*(diameter/6);
+ tilt=2.3561;
+ break;
+
+ case(6): // 270
+ offx=diameter/6;
+ offy=0;
+ tilt=3.14159;
+ break;
+
+ case(7): // 315
+ offx=diameter/6;
+ offy=diameter/6;
+ tilt=3.92699;
+ break;
+
+ case(8): // 360
+ offx=0;
+ offy=diameter/6;
+ tilt=4.71238;
+ break;
+
+ default:
+ offx=0;
+ offy=0;
+ break;
+ } // End of switch
+ }
+
+ //fprintf(stderr,"PHG=%02f %0.2f %0.2f %0.2f pix %0.2f\n",range,power,height,gain,diameter);
+
+ (void)XSetLineAttributes(XtDisplay(da), gc, 1, LineSolid, CapButt,JoinMiter);
+
+ if ((sec_old+sec_heard)>sec_now())
+ (void)XSetForeground(XtDisplay(da),gc,colors[0x0a]);
+ else
+ (void)XSetForeground(XtDisplay(da),gc,colors[0x52]);
+
+ if (is_rng || phg[6]=='0') { // Draw circl
+
+// Check that our parameters are within spec for XDrawArc. Tricky
+// 'cuz the XArc struct has short's and unsigned short's, while
+// XDrawArc man-page says int's/unsigned int's. We'll stick to 16-bit
+// just to make sure.
+
+ (void)XDrawArc(XtDisplay(da),where,gc,
+ l16(((x_long-NW_corner_longitude)/scale_x)-(diameter/2)), // int
+ l16(((y_lat-NW_corner_latitude)/scale_y)-(diameter/2)), // int
+ lu16(diameter), // unsigned int
+ lu16(diameter), // unsigned int
+ l16(0), // int
+ l16(64*360)); // int
+ }
+ else { // Draw oval to depict beam heading
+
+ // If phg[6] != '0' we still draw a circle, but the center
+ // is offset in the indicated direction by 1/3 the radius.
+
+ // Draw Circle
+
+// Check that our parameters are within spec for XDrawArc. Tricky
+// 'cuz the XArc struct has short's and unsigned short's, while
+// XDrawArc man-page says int's/unsigned int's. We'll stick to 16-bit
+// just to make sure.
+
+ (void)XDrawArc(XtDisplay(da),where,gc,
+ l16(((x_long-NW_corner_longitude)/scale_x)-(diameter/2) - offx), // int
+ l16(((y_lat-NW_corner_latitude)/scale_y)-(diameter/2) - offy), // int
+ lu16(diameter), // unsigned int
+ lu16(diameter), // unsigned int
+ l16(0), // int
+ l16(64*360)); // int
+ }
+// }
+// }
+ }
+}
+
+
+
+
+
+// Function to draw DF circles around objects/stations for DF'ing purposes.
+//
+// We change from filled circles to open circles at zoom level 128 for speed purposes.
+//
+void draw_DF_circle(long x_long, long y_lat, char *shgd, time_t sec_heard, Pixmap where) {
+ double range, diameter;
+ int offx,offy;
+ long xx,yy,xx1,yy1,fxx,fyy;
+ double tilt;
+ double a,b;
+
+
+ if ( ((sec_old+sec_heard)>sec_now()) || Select_.old_data ) {
+
+
+// Prevents it from being drawn when the symbol is off-screen.
+// It'd be better to check for lat/long +/- range to see if it's on the screen.
+
+// if ((x_long>NW_corner_longitude) && (x_long<SE_corner_longitude)) {
+
+// if ((y_lat>NW_corner_latitude) && (y_lat<SE_corner_latitude)) {
+
+// if ((x_long < 0) || (x_long > 129600000l))
+// return;
+
+// if ((y_lat < 0) || (y_lat > 64800000l))
+// return;
+
+ xx=0l;
+ yy=0l;
+ xx1=0l;
+ yy1=0l;
+ fxx=0l;
+ fyy=0l;
+ tilt=0.0;
+ offx=0;
+ offy=0;
+
+ range = shg_range(shgd[3],shgd[4],shgd[5]);
+
+ // Range is in miles. Bottom term is in meters before the 0.0006214
+ // multiplication factor which converts it to miles.
+ // Equation is: 2 * ( range(mi) / x-distance across window(mi) )
+ //
+ diameter = 2.0 * ( range/
+ (scale_x * calc_dscale_x(center_longitude,center_latitude) * 0.0006214 ) );
+
+ // If less than 4 pixels across, skip drawing it.
+ if (diameter <= 4.0)
+ return;
+
+ //fprintf(stderr,"PHG: %s, Diameter: %f\n", shgd, diameter);
+
+ a = diameter;
+ b = diameter / 2;
+
+ // Figure out the directivity, if outside range of 0-8 it's declared to be an omni
+ switch (shgd[6]-'0') {
+ case(0):
+ offx=0;
+ offy=0;
+ break;
+
+ case(1): // 45
+ offx=-1*(diameter/6);
+ offy=diameter/6;
+ tilt=5.49778;
+ break;
+
+ case(2): // 90
+ offx=-1*(diameter/6);
+ offy=0;
+ tilt=0;
+ break;
+
+ case(3): // 135
+ offx=-1*(diameter/6);
+ offy=-1*(diameter/6);
+ tilt=.78539;
+ break;
+
+ case(4): // 180
+ offx=0;
+ offy=-1*(diameter/6);
+ tilt=1.5707;
+ break;
+
+ case(5): // 225
+ offx=diameter/6;
+ offy=-1*(diameter/6);
+ tilt=2.3561;
+ break;
+
+ case(6): // 270
+ offx=diameter/6;
+ offy=0;
+ tilt=3.14159;
+ break;
+
+ case(7): // 315
+ offx=diameter/6;
+ offy=diameter/6;
+ tilt=3.92699;
+ break;
+
+ case(8): // 360
+ offx=0;
+ offy=diameter/6;
+ tilt=4.71238;
+ break;
+
+ default:
+ offx=0;
+ offy=0;
+ break;
+ }
+ //fprintf(stderr,"PHG=%02f %0.2f %0.2f %0.2f pix %0.2f\n",range,power,height,gain,diameter);
+
+ //fprintf(stderr,"scale_y: %u\n",scale_y);
+
+ if (scale_y > 128) { // Don't fill in circle if zoomed in too far (too slow!)
+ (void)XSetLineAttributes(XtDisplay(da), gc_stipple, 1, LineSolid, CapButt,JoinMiter);
+ }
+ else {
+ (void)XSetLineAttributes(XtDisplay(da), gc_stipple, 8, LineSolid, CapButt,JoinMiter);
+ }
+
+ // Stipple the area instead of obscuring the map underneath
+ (void)XSetStipple(XtDisplay(da), gc_stipple, pixmap_50pct_stipple);
+ (void)XSetFillStyle(XtDisplay(da), gc_stipple, FillStippled);
+
+ // Choose the color for the DF'ing circle
+ // We try to choose similar colors to those used in DOSaprs,
+ // which are qbasic or gwbasic colors.
+ switch (shgd[3]) {
+
+ case '9': // Light Red
+ if ((sec_old+sec_heard)>sec_now()) // New
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x25]);
+ else // Old
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x25]);
+ break;
+
+ case '8': // Red
+ if ((sec_old+sec_heard)>sec_now()) // New
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x2d]);
+ else // Old
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x2d]);
+ break;
+
+ case '7': // Light Magenta
+ if ((sec_old+sec_heard)>sec_now()) // New
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x26]);
+ else // Old
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x26]);
+ break;
+
+ case '6': // Magenta
+ if ((sec_old+sec_heard)>sec_now()) // New
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x2e]);
+ else // Old
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x2e]);
+ break;
+
+ case '5': // Light Cyan
+ if ((sec_old+sec_heard)>sec_now()) // New
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x24]);
+ else // Old
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x24]);
+ break;
+
+ case '4': // Cyan
+ if ((sec_old+sec_heard)>sec_now()) // New
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x2c]);
+ else // Old
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x2c]);
+ break;
+
+ case '3': // White
+ if ((sec_old+sec_heard)>sec_now()) // New
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x0f]);
+ else // Old
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x0f]);
+ break;
+
+ case '2': // Light Blue
+ if ((sec_old+sec_heard)>sec_now()) // New
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x22]);
+ else // Old
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x22]);
+ break;
+
+ case '1': // Blue
+ if ((sec_old+sec_heard)>sec_now()) // New
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x2a]);
+ else // Old
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x2a]);
+ break;
+
+ case '0': // DarkGray (APRSdos) or Black (looks better). We use Black.
+ default:
+ if ((sec_old+sec_heard)>sec_now()) // New (was 0x30)
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x08]);
+ else // Old
+ (void)XSetForeground(XtDisplay(da),gc_stipple,colors[0x08]);
+ break;
+ }
+
+ // If shgd[6] != '0' we still draw a circle, but the center
+ // is offset in the indicated direction by 1/3 the radius.
+
+ // Draw Circle
+
+// Check that our parameters are within spec for XDrawArc. Tricky
+// 'cuz the XArc struct has short's and unsigned short's, while
+// XDrawArc man-page says int's/unsigned int's. We'll stick to 16-bit
+// just to make sure.
+
+ (void)XDrawArc(XtDisplay(da),where,gc_stipple,
+ l16(((x_long-NW_corner_longitude)/scale_x)-(diameter/2) - offx), // int
+ l16(((y_lat-NW_corner_latitude)/scale_y)-(diameter/2) - offy), // int
+ lu16(diameter), // unsigned int
+ lu16(diameter), // unsigned int
+ l16(0), // int
+ l16(64*360)); // int
+
+ if (scale_y > 128) { // Don't fill in circle if zoomed in too far (too slow!)
+
+ while (diameter > 1.0) {
+ diameter = diameter - 1.0;
+
+// Check that our parameters are within spec for XDrawArc. Tricky
+// 'cuz the XArc struct has short's and unsigned short's, while
+// XDrawArc man-page says int's/unsigned int's. We'll stick to 16-bit
+// just to make sure.
+
+ (void)XDrawArc(XtDisplay(da),where,gc_stipple,
+ l16(((x_long-NW_corner_longitude)/scale_x)-(diameter/2) - offx), // int
+ l16(((y_lat-NW_corner_latitude)/scale_y)-(diameter/2) - offy), // int
+ lu16(diameter), // unsigned int
+ lu16(diameter), // unsigned int
+ l16(0), // int
+ l16(64*360)); // int
+ }
+ }
+// }
+// }
+ }
+ // Change back to non-stipple for whatever drawing occurs after this
+ (void)XSetFillStyle(XtDisplay(da), gc_stipple, FillSolid);
+}
+
+
+
+
+
+// Draw the ALOHA circle
+// Identical to draw_pod_circle when this was first written, but separated
+// just in case that POD functionality ever changes per the comments in it
+void draw_aloha_circle(long x_long, long y_lat, double range, int color, Pixmap where) {
+ double diameter;
+ double a,b;
+ long width, height;
+
+
+ // Range is in miles. Bottom term is in meters before the
+ // 0.0006214 multiplication factor which converts it to miles.
+ // Equation is: 2 * ( range(mi) / x-distance across window(mi) )
+ diameter = 2.0 * ( range/
+ (scale_x * calc_dscale_x(center_longitude,center_latitude) * 0.0006214 ) );
+
+ // If less than 4 pixels across, skip drawing it.
+ if (diameter <= 4.0)
+ return;
+
+ a = diameter;
+ b = diameter / 2;
+
+
+ // Check for the center of the circle being off the edge of the
+ // earth (that's _our_ station position by the way!).
+ //
+// if ((x_long < 0) || (x_long > 129600000l))
+// return;
+
+// if ((y_lat < 0) || (y_lat > 64800000l))
+// return;
+
+ //fprintf(stderr,"Range:%f\tDiameter:%f\n",range,diameter);
+
+ width = (((x_long-NW_corner_longitude)/scale_x)-(diameter/2));
+ height = (((y_lat-NW_corner_latitude)/scale_y)-(diameter/2));
+
+// if (width < 0 || width > 32767 || height < 0 || height > 32767) {
+// return;
+// }
+
+ (void)XSetLineAttributes(XtDisplay(da), gc, 2, LineSolid, CapButt,JoinMiter);
+ //(void)XSetForeground(XtDisplay(da),gc,colors[0x0a]);
+ //(void)XSetForeground(XtDisplay(da),gc,colors[0x44]); // red3
+ (void)XSetForeground(XtDisplay(da),gc,color);
+
+// Check that our parameters are within spec for XDrawArc. Tricky
+// 'cuz the XArc struct has short's and unsigned short's, while
+// XDrawArc man-page says int's/unsigned int's. We'll stick to 16-bit
+// just to make sure.
+
+ (void)XDrawArc(XtDisplay(da),where,gc,
+ l16(width), // int
+ l16(height), // int
+ lu16(diameter), // unsigned int
+ lu16(diameter), // unsigned int
+ l16(0), // int
+ l16(64*360)); // int
+}
+
+
+
+
+
+static int barb_len;
+static int barb_spacing;
+
+
+
+
+
+// Change barb parameters based on our current zoom level, so the
+// barbs don't get too long as we zoom out.
+void set_barb_parameters(void) {
+ float factor = 1.0;
+
+ // Initial settings
+ barb_len = 16;
+ barb_spacing = 16;
+
+ // Scale factor
+ if (scale_y > 80000)
+ factor = 3.0;
+ else if (scale_y > 40000)
+ factor = 2.5;
+ else if (scale_y > 20000)
+ factor = 2.0;
+ else if (scale_y > 10000)
+ factor = 1.5;
+
+ // Scale them, plus use poor man's rounding
+ barb_len = (int)((barb_len / factor) + 0.5);
+ barb_spacing = (int)((barb_spacing / factor) + 0.5);;
+}
+
+
+
+
+
+void draw_half_barbs(int *i, int quantity, float bearing_radians, long x, long y, char *course, Pixmap where) {
+ float barb_radians = bearing_radians + ( (45/360.0) * 2.0 * M_PI);
+ int j;
+ long start_x, start_y, off_x, off_y;
+
+
+ for (j = 0; j < quantity; j++) {
+ // Starting point for barb is (*i * barb_spacing) pixels
+ // along bearing_radians vector
+ *i = *i + barb_spacing;
+ off_x = *i * cos(bearing_radians);
+ off_y = *i * sin(bearing_radians);
+ start_y = y + off_y;
+ start_x = x + off_x;
+
+ // Set off in the barb direction now
+ off_y = (long)( (barb_len / 2) * sin(barb_radians) );
+ off_x = (long)( (barb_len / 2) * cos(barb_radians) );
+
+ (void)XSetLineAttributes(XtDisplay(da), gc, 0, LineSolid, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da),gc,colors[0x44]); // red3
+
+// Check that our parameters are within spec for XDrawLine. We'll
+// stick to 16-bit values here due to warnings on the man-page
+// regarding XSegment structs and the protocol only handling
+// short's/unsigned short's, just in case.
+
+ (void)XDrawLine(XtDisplay(da),where,gc,
+ l16(start_x), // int
+ l16(start_y), // int
+ l16(start_x + off_x), // int
+ l16(start_y + off_y)); // int
+ }
+}
+
+
+
+
+
+void draw_full_barbs(int *i, int quantity, float bearing_radians, long x, long y, char *course, Pixmap where) {
+ float barb_radians = bearing_radians + ( (45/360.0) * 2.0 * M_PI);
+ int j;
+ long start_x, start_y, off_x, off_y;
+
+
+ for (j = 0; j < quantity; j++) {
+ // Starting point for barb is (*i * barb_spacing) pixels
+ // along bearing_radians vector
+ *i = *i + barb_spacing;
+ off_x = *i * cos(bearing_radians);
+ off_y = *i * sin(bearing_radians);
+ start_y = y + off_y;
+ start_x = x + off_x;
+
+ // Set off in the barb direction now
+ off_y = (long)( barb_len * sin(barb_radians) );
+ off_x = (long)( barb_len * cos(barb_radians) );
+
+ (void)XSetLineAttributes(XtDisplay(da), gc, 0, LineSolid, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da),gc,colors[0x44]); // red3
+
+// Check that our parameters are within spec for XDrawLine. We'll
+// stick to 16-bit values here due to warnings on the man-page
+// regarding XSegment structs and the protocol only handling
+// short's/unsigned short's, just in case.
+
+ (void)XDrawLine(XtDisplay(da),where,gc,
+ l16(start_x), // int
+ l16(start_y), // int
+ l16(start_x + off_x), // int
+ l16(start_y + off_y)); // int
+ }
+}
+
+
+
+
+
+void draw_triangle_flags(int *i, int quantity, float bearing_radians, long x, long y, char *course, Pixmap where) {
+ float barb_radians = bearing_radians + ( (45/360.0) * 2.0 * M_PI);
+ int j;
+ long start_x, start_y, off_x, off_y, off_x2, off_y2;
+ XPoint points[3];
+
+
+ for (j = 0; j < quantity; j++) {
+ // Starting point for barb is (*i * barb_spacing) pixels
+ // along bearing_radians vector
+ *i = *i + barb_spacing;
+ off_x = *i * cos(bearing_radians);
+ off_y = *i * sin(bearing_radians);
+ start_y = y + off_y;
+ start_x = x + off_x;
+
+ // Calculate 2nd point along staff
+ off_x2 = (barb_spacing/2) * cos(bearing_radians);
+ off_y2 = (barb_spacing/2) * sin(bearing_radians);
+
+ // Set off in the barb direction now
+ off_y = (long)( barb_len * sin(barb_radians) );
+ off_x = (long)( barb_len * cos(barb_radians) );
+
+ (void)XSetLineAttributes(XtDisplay(da), gc, 0, LineSolid, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da),gc,colors[0x44]); // red3
+
+ points[0].x = start_x; points[0].y = start_y;
+ points[1].x = start_x + off_x; points[1].y = start_y + off_y;
+ points[2].x = start_x + off_x2; points[2].y = start_y + off_y2;
+
+ // Number of points is always 3 here, so we don't need to
+ // check first before calling XFillPolygon().
+ (void)XFillPolygon(XtDisplay(da), where, gc, points, 3, Convex, CoordModeOrigin);
+ }
+}
+
+
+
+
+
+void draw_square_flags(int *i, int quantity, float bearing_radians, long x, long y, char *course, Pixmap where) {
+ float barb_radians = bearing_radians + ( (90/360.0) * 2.0 * M_PI);
+ int j;
+ long start_x, start_y, off_x, off_y, off_x2, off_y2;
+ XPoint points[4];
+
+
+ for (j = 0; j < quantity; j++) {
+ // Starting point for barb is (*i * barb_spacing) pixels
+ // along bearing_radians vector
+ *i = *i + barb_spacing;
+ off_x = *i * cos(bearing_radians);
+ off_y = *i * sin(bearing_radians);
+ start_y = y + off_y;
+ start_x = x + off_x;
+
+ // Calculate 2nd point along staff
+ off_x2 = (barb_spacing/2) * cos(bearing_radians);
+ off_y2 = (barb_spacing/2) * sin(bearing_radians);
+
+ // Set off in the barb direction now
+ off_y = (long)( barb_len * sin(barb_radians) );
+ off_x = (long)( barb_len * cos(barb_radians) );
+
+ (void)XSetLineAttributes(XtDisplay(da), gc, 0, LineSolid, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da),gc,colors[0x44]); // red3
+
+ points[0].x = start_x; points[0].y = start_y;
+ points[1].x = start_x + off_x; points[1].y = start_y + off_y;
+ points[2].x = start_x + off_x + off_x2; points[2].y = start_y + off_y + off_y2;
+ points[3].x = start_x + off_x2; points[3].y = start_y + off_y2;
+
+ // Number of points is always 4 here, so we don't need to
+ // check first before calling XFillPolygon().
+ (void)XFillPolygon(XtDisplay(da), where, gc, points, 4, Convex, CoordModeOrigin);
+ }
+}
+
+
+
+
+
+// Function to draw wind barbs. Use speed in knots to determine the
+// flags and barbs to draw along the shaft. Course is in true
+// degrees, in the direction that the wind is coming from.
+//
+// Square flag = 100 knots
+// Triangle flag = 50 knots
+// Full barb = 10 knots
+// Half barb = 5 knots
+//
+void draw_wind_barb(long x_long, long y_lat, char *speed,
+ char *course, time_t sec_heard, Pixmap where) {
+ int square_flags = 0;
+ int triangle_flags = 0;
+ int full_barbs = 0;
+ int half_barbs = 0;
+ int shaft_length = 0;
+ int my_speed = atoi(speed); // In mph (so far)
+ int my_course = atoi(course); // In � true
+ float bearing_radians;
+ long off_x,off_y;
+ long x,y;
+ int i;
+
+
+// Ghost the wind barb if sec_heard is too long.
+// (TBD)
+
+
+// What to do if my_speed is zero? Blank out any wind barbs
+// that were written before?
+
+
+ // Prevents it from being drawn when the symbol is off-screen.
+ // It'd be better to check for lat/long +/- range to see if it's
+ // on the screen.
+
+ if ((x_long>NW_corner_longitude) && (x_long<SE_corner_longitude)) {
+
+ if ((y_lat>NW_corner_latitude) && (y_lat<SE_corner_latitude)) {
+
+// if ((x_long < 0) || (x_long > 129600000l))
+// return;
+
+// if ((y_lat < 0) || (y_lat > 64800000l))
+// return;
+
+ // Ok to draw wind barb
+
+ }
+ else {
+ return;
+ }
+ }
+ else {
+ return;
+ }
+
+ // Set up the constants for our zoom level
+ set_barb_parameters();
+
+ // Convert from mph to knots for wind speed.
+ my_speed = my_speed * 0.8689607;
+
+ //fprintf(stderr,"mph:%s, knots:%d\n",speed,my_speed);
+
+ // Adjust so that it fits our screen angles. We're off by
+ // 90 degrees.
+ my_course = (my_course - 90) % 360;
+
+ square_flags = (int)(my_speed / 100);
+ my_speed = my_speed % 100;
+
+ triangle_flags = (int)(my_speed / 50);
+ my_speed = my_speed % 50;
+
+ full_barbs = (int)(my_speed / 10);
+ my_speed = my_speed % 10;
+
+ half_barbs = (int)(my_speed / 5);
+
+ shaft_length = barb_spacing * (square_flags + triangle_flags + full_barbs
+ + half_barbs + 1);
+
+ // Set a minimum length for the shaft?
+ if (shaft_length < 2)
+ shaft_length = 2;
+
+ if (debug_level & 128) {
+ fprintf(stderr,"Course:%d,\tL:%d,\tsq:%d,\ttr:%d,\tfull:%d,\thalf:%d\n",
+ atoi(course),
+ shaft_length,
+ square_flags,
+ triangle_flags,
+ full_barbs,
+ half_barbs);
+ }
+
+ // Draw shaft at proper angle.
+ bearing_radians = (my_course/360.0) * 2.0 * M_PI;
+
+ off_y = (long)( shaft_length * sin(bearing_radians) );
+ off_x = (long)( shaft_length * cos(bearing_radians) );
+
+ x = (x_long - NW_corner_longitude)/scale_x;
+ y = (y_lat - NW_corner_latitude)/scale_y;
+
+ (void)XSetLineAttributes(XtDisplay(da), gc, 0, LineSolid, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da),gc,colors[0x44]); // red3
+
+// Check that our parameters are within spec for XDrawLine. We'll
+// stick to 16-bit values here due to warnings on the man-page
+// regarding XSegment structs and the protocol only handling
+// short's/unsigned short's, just in case.
+
+ (void)XDrawLine(XtDisplay(da),where,gc,
+ l16(x), // int
+ l16(y), // int
+ l16(x + off_x), // int
+ l16(y + off_y)); // int
+
+ // Increment along shaft and draw filled polygons at:
+ // "(angle + 45) % 360" degrees to create flags.
+
+ i = barb_spacing;
+ // Draw half barbs if any
+ if (half_barbs)
+ draw_half_barbs(&i,
+ half_barbs,
+ bearing_radians,
+ x,
+ y,
+ course,
+ where);
+
+ // Draw full barbs if any
+ if (full_barbs)
+ draw_full_barbs(&i,
+ full_barbs,
+ bearing_radians,
+ x,
+ y,
+ course,
+ where);
+
+ // Draw triangle flags if any
+ if (triangle_flags)
+ draw_triangle_flags(&i,
+ triangle_flags,
+ bearing_radians,
+ x,
+ y,
+ course,
+ where);
+
+ // Draw rectangle flags if any
+ if (square_flags)
+ draw_square_flags(&i,
+ square_flags,
+ bearing_radians,
+ x,
+ y,
+ course,
+ where);
+}
+
+
+
+
+
+// Function to draw beam headings for DF'ing purposes. Separates NRQ into its
+// components, which are Number/Range/Quality.
+//
+// If N is 0, then the NRQ value is meaningless. 1 through 8 are hits per period
+// of time (auto-DF'ing equipment). A value of 8 means all samples possible got
+// a hit. A value of 9 means that the report is manual.
+//
+// Range limits the length of the line to the original map's scale of the sending
+// station. The range is 2**R, so for R=4 the range would be 16 miles.
+//
+// Q is a single digit from 0-9 and provides indication of bearing accuracy:
+// 0 Useless
+// 1 <240 deg (worst)
+// 2 <120 deg
+// 3 <64 deg
+// 4 <32 deg
+// 5 <16 deg
+// 6 <8 deg
+// 7 <4 deg
+// 8 <2 deg
+// 9 <1 deg (best)
+//
+//
+// TODO: Should we draw with XOR for this function? Would appear on
+// most maps that way, and we wouldn't have to worry much about
+// color.
+//
+// TODO: If Q between 1 and 8, shade the entire area to show the
+// beam width?
+//
+//
+// Latest: We ignore the color parameter and draw everything using
+// red3.
+//
+// The distance calculations below use nautical miles. Here we
+// ignore the difference between nautical and statute miles as it
+// really doesn't make much difference how long we draw the vectors:
+// The angle is what is important here.
+//
+void draw_bearing(long x_long, long y_lat, char *course,
+ char *bearing, char *NRQ, int color, int draw_beamwidth,
+ int draw_bearing,
+ time_t sec_heard, Pixmap where) {
+ double range = 0;
+ double real_bearing = 0.0;
+ double real_bearing_min = 0.0;
+ double real_bearing_max = 0.0;
+ int width = 0;
+ long x_long2, x_long3, x_long4, y_lat2, y_lat3, y_lat4;
+ double screen_miles;
+
+
+ if ( ((sec_old+sec_heard)>sec_now()) || Select_.old_data ) {
+
+ // Check for a zero value for N. If found, the NRQ value is meaningless
+ // and we need to assume some working default values.
+ if (NRQ[0] != '0') {
+
+ // "range" as used below is in nautical miles.
+ range = (double)( pow(2.0,NRQ[1] - '0') );
+
+ switch (NRQ[2]) {
+ case('1'):
+ width = 240; // Degrees of beam width. What's the point?
+ break;
+ case('2'):
+ width = 120; // Degrees of beam width. What's the point?
+ break;
+ case('3'):
+ width = 64; // Degrees of beam width. What's the point?
+ break;
+ case('4'):
+ width = 32; // Degrees of beam width. Starting to be usable.
+ break;
+ case('5'):
+ width = 16; // Degrees of beam width. Usable.
+ break;
+ case('6'):
+ width = 8; // Degrees of beam width. Usable.
+ break;
+ case('7'):
+ width = 4; // Degrees of beam width. Nice!
+ break;
+ case('8'):
+ width = 2; // Degrees of beam width. Nice!
+ break;
+ case('9'):
+ width = 1; // Degrees of beam width. Very Nice!
+ break;
+ case('0'): // "Useless" beam width according to spec
+ default:
+ return; // Exit routine without drawing vectors
+ break;
+ }
+ }
+ else { // Assume some default values.
+ range = 512.0; // Assume max range of 512 nautical miles
+ width = 8; // Assume 8 degrees for beam width
+ }
+
+ // We have the course of the vehicle and the bearing from the
+ // vehicle. Now we need the real bearing.
+ //
+ if (atoi(course) != 0) {
+ real_bearing = atoi(course) + atoi(bearing);
+ real_bearing_min = real_bearing + 360.0 - (width/2.0);
+ real_bearing_max = real_bearing + (width/2.0);
+ }
+ else {
+ real_bearing = atoi(bearing);
+ real_bearing_min = real_bearing + 360.0 - (width/2.0);
+ real_bearing_max = real_bearing + (width/2.0);
+ }
+
+ while (real_bearing > 360.0)
+ real_bearing -= 360.0;
+
+ while (real_bearing_min > 360.0)
+ real_bearing_min -= 360.0;
+
+ while (real_bearing_max > 360.0)
+ real_bearing_max -= 360.0;
+
+ // want this in nautical miles
+ screen_miles = scale_x * calc_dscale_x(center_longitude,center_latitude)
+ * .5400;
+
+ // Shorten range to more closely fit the screen
+ if ( range > (3.0 * screen_miles) )
+ range = 3.0 * screen_miles;
+
+ // We now have a distance and a bearing for each vector.
+ // Compute the end points via dead-reckoning here. It will give
+ // us points between which we can draw a vector and makes the
+ // rest of the code much easier. Need to skip adding 270
+ // degrees if we use that method.
+ //
+ if (draw_beamwidth) {
+ compute_DR_position(x_long, // input (long)
+ y_lat, // input (long)
+ range, // input in nautical miles (double)
+ real_bearing_min, // input in � true (double)
+ &x_long2, // output (*long)
+ &y_lat2); // output (*long)
+
+ compute_DR_position(x_long, // input (long)
+ y_lat, // input (long)
+ range, // input in nautical miles (double)
+ real_bearing_max, // input in � true (double)
+ &x_long3, // output (*long)
+ &y_lat3); // output (*long)
+ }
+
+ if (draw_bearing) {
+ compute_DR_position(x_long, // input (long)
+ y_lat, // input (long)
+ range, // input in nautical miles (double)
+ real_bearing, // input in � true (double)
+ &x_long4, // output (*long)
+ &y_lat4); // output (*long)
+ }
+
+ (void)XSetLineAttributes(XtDisplay(da), gc, 2, LineSolid, CapButt,JoinMiter);
+ //(void)XSetForeground(XtDisplay(da),gc,colors[0x0a]);
+ if (draw_beamwidth) {
+ (void)XSetForeground(XtDisplay(da),gc,colors[0x4a]); // red2
+ draw_vector(da, x_long, y_lat, x_long2, y_lat2, gc, where, 0);
+ draw_vector(da, x_long, y_lat, x_long3, y_lat3, gc, where, 0);
+ }
+
+ if (draw_bearing) {
+ (void)XSetForeground(XtDisplay(da),gc,colors[0x44]); // red3
+ draw_vector(da, x_long, y_lat, x_long4, y_lat4, gc, where, 0);
+ }
+ }
+
+ // Change back to non-stipple for whatever drawing occurs after this
+// (void)XSetFillStyle(XtDisplay(da), gc_tint, FillSolid);
+}
+
+
+
+
+
+// TODO: Pass back the modified x_long/y_lat to the calling routine
+// and use the new lat/long to place the symbol. This will knock
+// off the digits on the right that the ambiguity specifies. We
+// then add 1/2 the rectangle offsets in order to get the symbol
+// placed in the middle of the rectangle.
+//
+void draw_ambiguity(long x_long, long y_lat, char amb, long *amb_x_long, long *amb_y_lat, time_t sec_heard, Pixmap where) {
+ unsigned long left, right, top, bottom;
+ long offset_lat, offset_long;
+ int scale_limit;
+
+
+ // Assign these first in case we do a sudden return from the
+ // function.
+ *amb_x_long = x_long;
+ *amb_y_lat = y_lat;
+
+// if ((x_long < 0) || (x_long > 129600000l))
+// return;
+
+// if ((y_lat < 0) || (y_lat > 64800000l))
+// return;
+
+ switch (amb) {
+ case 1: // +- 1/10th minute
+ offset_lat = offset_long = 600;
+ scale_limit = 256;
+
+ // Truncate digits off the right
+ x_long = (long)(x_long / 600);
+ x_long = x_long * 600;
+ y_lat = (long)(y_lat / 600);
+ y_lat = y_lat * 600;
+ break;
+
+ case 2: // +- 1 minute
+ offset_lat = offset_long = 6000;
+ scale_limit = 2048;
+
+ // Truncate digits off the right
+ x_long = (long)(x_long / 6000);
+ x_long = x_long * 6000;
+ y_lat = (long)(y_lat / 6000);
+ y_lat = y_lat * 6000;
+ break;
+
+ case 3: // +- 10 minutes
+ offset_lat = offset_long = 60000;
+ scale_limit = 16384;
+
+ // Truncate digits off the right
+ x_long = (long)(x_long / 60000);
+ x_long = x_long * 60000;
+ y_lat = (long)(y_lat / 60000);
+ y_lat = y_lat * 60000;
+ break;
+
+ case 4: // +- 1 degree
+ offset_lat = offset_long = 360000;
+ scale_limit = 65536;
+
+ // Truncate digits off the right
+ x_long = (long)(x_long / 360000);
+ x_long = x_long * 360000;
+ y_lat = (long)(y_lat / 360000);
+ y_lat = y_lat * 360000;
+ break;
+
+// TODO: The last two cases need fixing up like the above
+
+ case 5: // grid square: 2.5min lat x 5min lon
+ offset_lat = 360000.0 * 1.25 / 60.0;
+ offset_long = 360000.0 * 2.50 / 60.0;
+ scale_limit = 1024;
+ break;
+
+ case 6: // grid square: 1deg lat x 2deg lon
+ offset_lat = 360000.0 * 0.5;
+ offset_long = 360000.0 * 1.0;
+ scale_limit = 16384;
+ break;
+
+ case 0:
+ default:
+ return; // if no ambiguity, do nothing
+ break;
+
+ }
+
+ // Re-assign them here as they should have been truncated on the
+ // right by the above code. We'll use these new values
+ // to draw the symbols and the other associated symbol data
+ // (external to this function).
+ //
+ *amb_x_long = x_long + (offset_long/2);
+ *amb_y_lat = y_lat + (offset_lat / 2);
+
+
+ if (scale_y > scale_limit) {
+ // Ambiguity box will be smaller than smallest symbol so
+ // don't draw it.
+//fprintf(stderr,"scale_y > scale_limit\n");
+ return;
+ }
+
+ if ( ((sec_old+sec_heard)<=sec_now()) && !Select_.old_data ) {
+ return;
+ }
+
+ left = x_long;
+ top = y_lat;
+ right = x_long + offset_long;
+ bottom = y_lat + offset_lat;
+
+
+ (void)XSetForeground(XtDisplay(da), gc, colors[0x08]);
+
+ // Draw rectangle (unfilled) plus vectors from symbol to
+ // corners.
+
+ (void)XSetLineAttributes(XtDisplay(da), gc,
+ 2, LineOnOffDash, CapButt,JoinMiter);
+
+ // Top line of rectangle
+ draw_vector(da,left,top,right,top,gc,pixmap_final, 0);
+
+ // Bottom line of rectangle
+ draw_vector(da,left,bottom,right,bottom,gc,pixmap_final, 1);
+
+ // Left line of rectangle
+ draw_vector(da,left,top,left,bottom,gc,pixmap_final, 1);
+
+ // Right line of rectangle
+ draw_vector(da,right,top,right,bottom,gc,pixmap_final, 1);
+
+ // Diagonal lines
+ draw_vector(da,left,top,right,bottom,gc,pixmap_final, 1);
+ draw_vector(da,right,top,left,bottom,gc,pixmap_final, 1);
+}
+
+
+
+
+
+// Function which specifies whether any part of a bounding box fits
+// on the screen, using screen coordinates as inputs.
+//
+static __inline__ int onscreen(long left, long right, long top, long bottom) {
+ // This checks to see if any part of a box is on the screen.
+ if (left > screen_width || right < 0 || top > screen_height || bottom < 0)
+ return 0;
+ else
+ return 1;
+}
+
+
+
+
+
+// According to the spec, the lat/long point is the upper left
+// corner of the object, and the offsets are down and to the right
+// (except for one line type where it's down and to the left). This
+// doesn't appear to be the case in dos/winAPRS. Matching what they
+// do:
+//
+// Type 0 Circle: Tie = center, offsets = vert/horiz. sizes.
+// Type 1 Line: Tie = bottom right, offsets = left and up.
+// Type 2 Ellipse: Tie = center, offsets = vert/horiz. sizes.
+// Type 3 Triangle: Tie = bottom right, offsets = height/width.
+// Type 4 Rectangle: Tie = lower right, offsets = left and up.
+// Type 5 Circle: Tie = center, offsets = vert/horiz. sizes.
+// Type 6 Line: Tie = bottom left, offsets = right and up.
+// Type 7 Ellipse: Tie = center, offsets = vert/horiz. sizes.
+// Type 8 Triangle: Tie = bottom right, offsets = height/width.
+// Type 9 Rectangle: Tie = lower right, offsets = left and up.
+//
+// Exceptions to this are the triangle, ellipse, and circle. The
+// ellipse and circle have the lat/long as the center point. The
+// triangle is an isosceles triangle with the lat/long point being
+// the bottom right and the bottom of the triangle being horizontal.
+//
+void draw_area(long x_long, long y_lat, char type, char color,
+ char sqrt_lat_off, char sqrt_lon_off, unsigned int width, time_t sec_heard, Pixmap where) {
+ long left, top, right, bottom, xoff, yoff;
+ int c;
+ XPoint points[4];
+
+
+// if ((x_long < 0) || (x_long > 129600000l) ||
+// (y_lat < 0) || (y_lat > 64800000l))
+// return;
+
+ xoff = 360000.0 / 1500.0 * (sqrt_lon_off * sqrt_lon_off) / scale_x;
+ yoff = 360000.0 / 1500.0 * (sqrt_lat_off * sqrt_lat_off) / scale_y;
+
+ right = (x_long - NW_corner_longitude) / scale_x;
+ bottom = (y_lat - NW_corner_latitude) / scale_y;
+ left = right - xoff;
+ top = bottom - yoff;
+
+ // colors[0x21] is the first in the list of area object colors in main.c
+ c = colors[0x21 + color];
+
+ (void)XSetForeground(XtDisplay(da), gc, c);
+ if (xoff < 20 || yoff < 20)
+ (void)XSetLineAttributes(XtDisplay(da), gc, 1, LineSolid, CapButt,JoinMiter);
+ else
+ (void)XSetLineAttributes(XtDisplay(da), gc, 2, LineSolid, CapButt,JoinMiter);
+ (void)XSetFillStyle(XtDisplay(da), gc, FillSolid); // just in case
+ (void)XSetStipple(XtDisplay(da), gc, pixmap_50pct_stipple);
+
+ switch (type) {
+ case AREA_OPEN_BOX:
+ if (onscreen(left, right, top, bottom)) {
+
+// Check that our parameters are within spec for XDrawRectangle
+// Tricky 'cuz the XRectangle struct has short's and unsigned short's,
+// while XDrawRectangle man-page says int's/unsigned int's. We'll
+// stick to 16-bit just to make sure.
+
+ (void)XDrawRectangle(XtDisplay(da), where, gc,
+ l16(left), // int
+ l16(top), // int
+ lu16(xoff), // unsigned int
+ lu16(yoff)); // unsigned int
+ }
+ break;
+ case AREA_FILLED_BOX:
+ if (onscreen(left, right, top, bottom)) {
+ (void)XSetFillStyle(XtDisplay(da), gc, FillStippled);
+ (void)XFillRectangle(XtDisplay(da), where, gc, l16(left), l16(top), l16(xoff), l16(yoff));
+ }
+ break;
+ /* For the rest of the objects, the l16 limiting of the values is inadequate because the
+ shapes will still be draw wrong if the value actually was limited down.
+ However, this is slightly better than passing long or int values that would just be
+ used as 16bit by X (i.e.: truncated) until I/we come up with some sort of clipping algorithm.
+ In real use, what I'm talking about will occur based on two things: the size of the area and
+ the zoom level being used. The more the extents of the area go beyond the edges of the screen,
+ the more this will happen. N7TAP */
+ case AREA_OPEN_CIRCLE:
+ case AREA_OPEN_ELLIPSE:
+ right += xoff;
+ bottom += yoff;
+ if (onscreen(left, right, top, bottom)) {
+
+// Check that our parameters are within spec for XDrawArc. Tricky
+// 'cuz the XArc struct has short's and unsigned short's, while
+// XDrawArc man-page says int's/unsigned int's. We'll stick to 16-bit
+// just to make sure.
+
+ (void)XDrawArc(XtDisplay(da), where, gc,
+ l16(left), // int
+ l16(top), // int
+ lu16(2*xoff), // unsigned int
+ lu16(2*yoff), // unsigned int
+ l16(0), // int
+ l16(64 * 360)); // int
+ }
+ break;
+ case AREA_FILLED_CIRCLE:
+ case AREA_FILLED_ELLIPSE:
+ right += xoff;
+ bottom += yoff;
+ if (onscreen(left, right, top, bottom)) {
+ (void)XSetFillStyle(XtDisplay(da), gc, FillStippled);
+ (void)XFillArc(XtDisplay(da), where, gc, l16(left), l16(top), l16(2*xoff), l16(2*yoff), 0, 64 * 360);
+ }
+ break;
+ case AREA_LINE_RIGHT:
+ left += xoff;
+ right += xoff;
+ if (width > 0) {
+ double angle = atan((float)xoff/(float)yoff);
+// Check for divide-by-zero here???
+
+ int conv_width = width/(scale_x*calc_dscale_x(center_longitude,center_latitude)*0.0006214);
+ points[0].x = l16(left-(conv_width * cos(angle))+xoff);
+ points[0].y = l16(top -(conv_width * sin(angle)));
+ points[1].x = l16(left-(conv_width * cos(angle)));
+ points[1].y = l16(top -(conv_width * sin(angle))+yoff);
+ points[2].x = l16(left+(conv_width * cos(angle)));
+ points[2].y = l16(top +(conv_width * sin(angle))+yoff);
+ points[3].x = l16(left+(conv_width * cos(angle))+xoff);
+ points[3].y = l16(top +(conv_width * sin(angle)));
+ if (onscreen(points[1].x, points[3].x, points[0].y, points[2].y)) {
+ (void)XSetFillStyle(XtDisplay(da), gc, FillStippled);
+
+ // Number of points is always 4 here, so we don't
+ // need to check first before calling
+ // XFillPolygon().
+ (void)XFillPolygon(XtDisplay(da), where, gc, points, 4, Convex, CoordModeOrigin);
+ }
+ }
+ if (onscreen(left, right, top, bottom)) {
+ (void)XSetFillStyle(XtDisplay(da), gc, FillSolid);
+
+// Check that our parameters are within spec for XDrawLine. We'll
+// stick to 16-bit values here due to warnings on the man-page
+// regarding XSegment structs and the protocol only handling
+// short's/unsigned short's, just in case.
+
+ (void)XDrawLine(XtDisplay(da), where, gc,
+ l16(left), // int
+ l16(bottom), // int
+ l16(right), // int
+ l16(top)); // int
+ }
+ break;
+ case AREA_LINE_LEFT:
+ if (width > 0) {
+ double angle = atan((float)xoff/(float)yoff);
+// Check for divide-by-zero here???
+
+ int conv_width = width/(scale_x*calc_dscale_x(center_longitude,center_latitude)*0.0006214);
+ points[0].x = l16(left+(conv_width * cos(angle)));
+ points[0].y = l16(top -(conv_width * sin(angle)));
+ points[1].x = l16(left+(conv_width * cos(angle))+xoff);
+ points[1].y = l16(top -(conv_width * sin(angle))+yoff);
+ points[2].x = l16(left-(conv_width * cos(angle))+xoff);
+ points[2].y = l16(top +(conv_width * sin(angle))+yoff);
+ points[3].x = l16(left-(conv_width * cos(angle)));
+ points[3].y = l16(top +(conv_width * sin(angle)));
+ if (onscreen(points[3].x, points[1].x, points[0].y, points[2].y)) {
+ (void)XSetFillStyle(XtDisplay(da), gc, FillStippled);
+
+ // Number of points is always 4 here, so we don't
+ // need to check first before calling
+ // XFillPolygon().
+ (void)XFillPolygon(XtDisplay(da), where, gc, points, 4, Convex, CoordModeOrigin);
+ }
+ }
+ if (onscreen(left, right, top, bottom)) {
+ (void)XSetFillStyle(XtDisplay(da), gc, FillSolid);
+
+// Check that our parameters are within spec for XDrawLine. We'll
+// stick to 16-bit values here due to warnings on the man-page
+// regarding XSegment structs and the protocol only handling
+// short's/unsigned short's, just in case.
+
+ (void)XDrawLine(XtDisplay(da), where, gc,
+ l16(right), // int
+ l16(bottom), // int
+ l16(left), // int
+ l16(top)); // int
+ }
+ break;
+ case AREA_OPEN_TRIANGLE:
+ left -= xoff;
+ points[0].x = l16(right); points[0].y = l16(bottom);
+ points[1].x = l16(left+xoff); points[1].y = l16(top);
+ points[2].x = l16(left); points[2].y = l16(bottom);
+ points[3].x = l16(right); points[3].y = l16(bottom);
+ if (onscreen(left, right, top, bottom)) {
+
+// Check that our parameters are within spec for XDrawLines. We'll
+// stick to 16-bit values here due to warnings on the man-page
+// regarding XSegment structs and the protocol only handling
+// short's/unsigned short's, just in case.
+
+ (void)XDrawLines(XtDisplay(da), where, gc,
+ points, // XPoint *
+ l16(4), // int
+ CoordModeOrigin); // int
+ }
+ break;
+ case AREA_FILLED_TRIANGLE:
+ left -= xoff;
+ points[0].x = l16(right); points[0].y = l16(bottom);
+ points[1].x = l16(left+xoff); points[1].y = l16(top);
+ points[2].x = l16(left); points[2].y = l16(bottom);
+ if (onscreen(left, right, top, bottom)) {
+ (void)XSetFillStyle(XtDisplay(da), gc, FillStippled);
+
+ // Number of points is always 3 here, so we don't need
+ // to check first before calling XFillPolygon().
+ (void)XFillPolygon(XtDisplay(da), where, gc, points, 3, Convex, CoordModeOrigin);
+ }
+ break;
+ default:
+ break;
+ }
+ (void)XSetFillStyle(XtDisplay(da), gc, FillSolid);
+}
+
+
+
+
+
+/* DK7IN: Statistics for colors in all symbols (as of 16.03.2001)
+60167 .
+ 6399 q
+ 3686 m
+ 3045 c
+ 2034 j
+ 1903 h
+ 1726 l
+ 1570 k
+ 1063 g
+ 1051 #
+ 840 p
+ 600 ~
+ 477 i
+ 443 n
+ 430 a
+ 403 o
+ 337 f
+ 250 b
+ 207 e
+ 169 d
+*/
+
+
+
+
+
+// read pixels from file, speeding it up by smart ordering of switches
+void read_symbol_from_file(FILE *f, char *pixels, char table_char) {
+ int x,y;
+ int color;
+ char line[100];
+ char pixels_copy[400];
+ char *p,*q;
+ unsigned char a, b, c;
+
+ for (y=0;y<20;y++) {
+ (void)get_line(f,line,100);
+ for (x=0;x<20;x++) {
+ switch (line[x]) {
+ case('.'): // transparent
+ color=0xff;
+ break;
+ case('q'): // #000000 black 0%
+ color=0x51;
+ break;
+ case('m'): // #FFFFFF white 100%
+ color=0x4d;
+ break;
+ case('c'): // #CCCCCC gray80 80%
+ color=0x43;
+ break;
+ case('j'): // #EE0000 red2
+ color=0x4a;
+ break;
+ case('h'): // #00BFFF Deep sky blue
+ color=0x48;
+ break;
+ case('l'): // #0000CD mediumblue
+ color=0x4c;
+ break;
+ case('k'): // #00CD00 green3
+ color=0x4b;
+ break;
+ case('g'): // #00008B blue4
+ color=0x47;
+ break;
+ case('#'): // #FFFF00 yellow
+ color=0x40;
+ break;
+ case('p'): // #454545 gray27 27%
+ color=0x50;
+ break;
+ case('~'): // used in the last two symbols in the file
+ color=0xff; // what should it be? was transparent before...
+ break;
+ case('i'): // #006400 Dark Green
+ color=0x49;
+ break;
+ case('n'): // #878787 gray53 52%
+ color=0x4e;
+ break;
+ case('a'): // #CD6500 darkorange2
+ color=0x41;
+ break;
+ case('o'): // #5A5A5A gray59 35%
+ color=0x4f;
+ break;
+ case('f'): // #CD3333 brown3
+ color=0x46;
+ break;
+ case('b'): // #A020F0 purple
+ color=0x42;
+ break;
+ case('e'): // #FF4040 brown1
+ color=0x45;
+ break;
+ case('d'): // #CD0000 red3
+ color=0x44;
+ break;
+ case('r'): // LimeGreen DK7IN: saw this in the color definitions...
+ color=0x52; // so we could use it
+ break;
+ default:
+ color=0xff;
+ break;
+ }
+ pixels[y*20+x] = (char)(color);
+ }
+ }
+
+ // Create outline on icons, if needed
+ // Do not change the overlays and "number" tables
+ if((icon_outline_style != 0) && (table_char != '~') && (table_char != '#'))
+ {
+ switch(icon_outline_style) {
+ case 1: color = 0x51; // Black
+ break;
+ //case 2: color = 0x43; // Grey 80%
+ case 2: color = 0x4e; // Grey 52%
+ break;
+ case 3: color = 0x4d; // White
+ break;
+ default: color = 0xff; // Transparent
+ break;
+ }
+
+ p = pixels;
+ q = &pixels_copy[0];
+
+ for (y=0;y<20;y++) {
+ for (x=0;x<20;x++) {
+ *q = *p; // copy current color
+
+ // If transparent see if the pixel is on the edge
+ if(*q == (char) 0xff)
+ {
+ //check if left or right is none transparent
+ b = c = 0xff;
+
+ // left (left only possible if x > 0)
+ if(x > 0)
+ b = p[-1];
+ // right (right only possible if x < 19)
+ if(x < 19)
+ c = p[+1];
+
+ // if non-transparent color is found change pixel
+ // to outline color
+ if((b != (unsigned char) 0xff)
+ || (c != (unsigned char) 0xff)) {
+ // change to icon outline color
+ *q = color;
+ }
+
+ if((y > 0) && (*q == (char) 0xff)) {
+ //check if left-up, up or right-up is none transparent
+ //"up" only possible if y > 0
+ a = b = c = 0xff;
+
+ // left-up (left only possible if x > 0)
+ if(x > 0)
+ a = p[-21];
+ // up
+ b = p[-20];
+ // right-up (right only possible if x < 19)
+ if(x < 19)
+ c = p[-19];
+
+ // if non-transparent color is found change pixel
+ // to outline color
+ if((a != (unsigned char) 0xff)
+ || (b != (unsigned char) 0xff)
+ || (c != (unsigned char) 0xff)) {
+ // change to icon outline color
+ *q = color;
+ }
+ }
+
+ if((y < 19) && (*q == (char) 0xff)) {
+ //check if left-down, down or right-down is none transparent
+ //"down" only possible if y < 19
+ a = b = c = 0xff;
+
+ // left-down (left only possible if x > 0)
+ if(x > 0)
+ a = p[+19];
+ // down
+ b = p[+20];
+ // right-down (right only possible if x < 19)
+ if(x < 19)
+ c = p[+21];
+
+ // if non-transparent color is found change pixel
+ // to outline color
+ if((a != (unsigned char) 0xff)
+ || (b != (unsigned char) 0xff)
+ || (c != (unsigned char) 0xff)) {
+ // change to icon outline color
+ *q = color;
+ }
+ }
+ }
+
+ p++;
+ q++;
+ }
+ }
+ memcpy(pixels, pixels_copy, 400);
+ }
+}
+
+
+
+
+
+/* read in symbol table */
+void load_pixmap_symbol_file(char *filename, int reloading) {
+ FILE *f;
+ char filen[500];
+ char line[100];
+ char table_char;
+ char symbol_char;
+ int done;
+ char pixels[400];
+ char orient;
+
+ busy_cursor(appshell);
+ symbols_loaded = 0;
+ table_char = '\0';
+ symbol_char = '\0';
+ done = 0;
+ xastir_snprintf(filen, sizeof(filen), "%s/%s", SYMBOLS_DIR, filename);
+ f = fopen(filen,"r");
+ if (f!=NULL) {
+ while (!feof(f) && !done) {
+ (void)get_line(f,line,100);
+ if (strncasecmp("TABLE ",line,6)==0) {
+ table_char=line[6];
+ /*fprintf(stderr,"TABLE %c\n",table_char);*/
+ } else {
+ if (strncasecmp("DONE",line,4)==0) {
+ done=1;
+ /*fprintf(stderr,"DONE\n");*/
+ } else {
+ if (strncasecmp("APRS ",line,5)==0) {
+ symbol_char=line[5];
+ if (strlen(line)>=20 && line[19] == 'l') // symbol with orientation ?
+ orient = 'l'; // should be 'l' for left
+ else
+ orient = ' ';
+ read_symbol_from_file(f, pixels, table_char); // read pixels for one symbol
+ insert_symbol(table_char,symbol_char,pixels,270,orient,reloading); // always have normal orientation
+ if (orient == 'l') {
+ insert_symbol(table_char,symbol_char,pixels, 0,'u',reloading); // create other orientations
+ insert_symbol(table_char,symbol_char,pixels, 90,'r',reloading);
+ insert_symbol(table_char,symbol_char,pixels,180,'d',reloading);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ fprintf(stderr,"Error opening symbol file %s\n",filen);
+ popup_message("Error opening symbol file","Error opening symbol file");
+ }
+
+ if (f != NULL)
+ (void)fclose(f);
+}
+
+
+
+
+
+// add a symbol to the end of the symbol table.
+//
+// Here we actually draw the pixels into the SymbolData struct,
+// which contains separate Pixmap's for the icon, the transparent
+// background, and the ghost image.
+//
+void insert_symbol(char table, char symbol, char *pixel, int deg, char orient, int reloading) {
+ int x,y,idx,old_next,color,last_color,last_gc2;
+
+ if (symbols_loaded < MAX_SYMBOLS) {
+ // first time loading, -> create pixmap...
+ // when reloading -> reuse already created pixmaps...
+ if(reloading == 0) {
+ symbol_data[symbols_loaded].pix=XCreatePixmap(XtDisplay(appshell),
+ RootWindowOfScreen(XtScreen(appshell)),
+ 20,
+ 20,
+ DefaultDepthOfScreen(XtScreen(appshell)));
+
+ symbol_data[symbols_loaded].pix_mask=XCreatePixmap(XtDisplay(appshell),
+ RootWindowOfScreen(XtScreen(appshell)),
+ 20,
+ 20,
+ 1);
+
+ symbol_data[symbols_loaded].pix_mask_old=XCreatePixmap(XtDisplay(appshell),
+ RootWindowOfScreen(XtScreen(appshell)),
+ 20,
+ 20,
+ 1);
+ }
+
+ old_next=0;
+ last_color = -1; // Something bogus
+ last_gc2 = -1; // Also bogus
+
+ for (y=0;y<20;y++) {
+ for (x=0;x<20;x++) {
+ switch (deg) {
+ case(0):
+ idx = 20* (19-x) + y;
+ break;
+ case(90):
+ idx = 20* y + (19-x);
+ break;
+ case(180):
+ idx = 20* (19-x) + (19-y);
+ break;
+ default:
+ idx = 20* y + x;
+ break;
+ }
+ color = (int)(pixel[idx]);
+ if (color<0)
+ color = 0xff;
+
+// Change to new color only when necessary. We use two different
+// GC's here, one for the main icon pixmap, and one for the symbol
+// mask and ghost layer.
+
+
+ // DK7IN: is (da) correct or should this be (appshell) ?
+ if (color != last_color) {
+ (void)XSetForeground(XtDisplay(da),gc,colors[color]);
+ last_color = color;
+ }
+
+// Check that our parameters are within spec for XDrawPoint. Tricky
+// 'cuz the XPoint struct uses short's, while XDrawPoint manpage
+// specifies int's. We'll stick to 16-bit numbers just to make
+// sure.
+
+ (void)XDrawPoint(XtDisplay(da),
+ symbol_data[symbols_loaded].pix,
+ gc,
+ l16(x), // int
+ l16(y)); // int
+ // DK7IN
+
+
+ // Create symbol mask
+ if (color != 0xff) {
+ if (last_gc2 != 1) {
+ (void)XSetForeground(XtDisplay(appshell),gc2,1); // active bit
+ last_gc2 = 1;
+ }
+ }
+ else {
+ if (last_gc2 != 0) {
+ (void)XSetForeground(XtDisplay(appshell),gc2,0); // transparent.
+ last_gc2 = 0;
+ }
+ }
+
+// Check that our parameters are within spec for XDrawPoint. Tricky
+// 'cuz the XPoint struct uses short's, while XDrawPoint manpage
+// specifies int's. We'll stick to 16-bit numbers just to make
+// sure.
+
+ (void)XDrawPoint(XtDisplay(appshell),
+ symbol_data[symbols_loaded].pix_mask,
+ gc2,
+ l16(x), // int
+ l16(y)); // int
+
+
+ // Create ghost symbol mask by setting every 2nd bit
+ // to transparent
+ old_next++;
+ if (old_next>1) {
+ old_next=0;
+ if (last_gc2 != 0) {
+ (void)XSetForeground(XtDisplay(appshell),gc2,0);
+ last_gc2 = 0;
+ }
+ }
+
+// Check that our parameters are within spec for XDrawPoint. Tricky
+// 'cuz the XPoint struct uses short's, while XDrawPoint manpage
+// specifies int's. We'll stick to 16-bit numbers just to make
+// sure.
+
+ (void)XDrawPoint(XtDisplay(appshell),
+ symbol_data[symbols_loaded].pix_mask_old,
+ gc2,
+ l16(x), // int
+ l16(y)); // int
+ }
+ old_next++; // shift one bit every scan line for ghost image
+ if (old_next>1)
+ old_next=0;
+ }
+ symbol_data[symbols_loaded].active = SYMBOL_ACTIVE;
+ symbol_data[symbols_loaded].table = table;
+ symbol_data[symbols_loaded].symbol = symbol;
+ symbol_data[symbols_loaded].orient = orient;
+ symbols_loaded++;
+ }
+}
+
+
+
+
+
+/* calculate symbol orientation from course */
+char symbol_orient(char *course) {
+ char orient;
+ float mydir;
+
+ orient = ' ';
+ if (strlen(course)) {
+ mydir = (float)atof(course);
+ if (mydir > 0) {
+ if (mydir < (float)( 180+ANGLE_UPDOWN ) )
+ orient = 'd';
+ if (mydir < (float)( 180-ANGLE_UPDOWN ) )
+ orient = 'r';
+ if (mydir < (float)ANGLE_UPDOWN || mydir > (float)( 360-ANGLE_UPDOWN) )
+ orient = 'u';
+ }
+ }
+ return(orient);
+}
+
+
+
+
+
+// Storage for an index into the symbol table that we may need
+// later.
+int nosym_index = -1;
+
+
+// Look through our symbol table for a match.
+//
+void symbol(Widget w, int ghost, char symbol_table, char symbol_id, char symbol_overlay, Pixmap where,
+ int mask, long x_offset, long y_offset, char orient) {
+ int i;
+ int found;
+ int alphanum_index = -1;
+
+
+ if (x_offset > screen_width) return;
+ if (x_offset < 0) return;
+ if (y_offset > screen_height) return;
+ if (y_offset < 0) return;
+
+ /* DK7IN: orient is ' ','l','r','u','d' for left/right/up/down symbol orientation */
+ // if symbol could be rotated, normal symbol orientation in symbols.dat is to the left
+
+
+ // Find the nosymbol index if we haven't filled it in by now.
+ // This "for" loop should get run only once during Xastir's
+ // entire runtime, so it shouldn't contribute much to CPU
+ // loading.
+ if (nosym_index == -1) {
+ for ( i = 0; i < symbols_loaded; i++ ) {
+ if (symbol_data[i].active == SYMBOL_ACTIVE) {
+ if (symbol_data[i].table == '!'
+ && symbol_data[i].symbol == '#') {
+ nosym_index = i; // index of special symbol (if none available)
+ break;
+ }
+ }
+ }
+ }
+
+
+ // Handle the overlay character. The "for" loop below gets run
+ // once every time we encounter an overlay character, which
+ // isn't all that often.
+ if (symbol_overlay == '\0' || symbol_overlay == ' ') {
+ alphanum_index = 0; // we don't want an overlay
+ }
+ else { // Find the overlay character index
+ for ( i = 0; i < symbols_loaded; i++ ) {
+ if (symbol_data[i].active == SYMBOL_ACTIVE) {
+ if (symbol_data[i].table == '#'
+ && symbol_data[i].symbol == symbol_overlay) {
+ alphanum_index = i; // index of symbol for character overlay
+ break;
+ }
+ }
+ }
+ }
+
+
+ found = -1;
+
+ // Check last few symbols we used to see if we can shortcut
+ // looking through the entire index. The symbols array really
+ // should be turned into a hash to save time. Basically we've
+ // implemented a very short cache here, but it keeps us from
+ // looking through the entire symbol array sometimes.
+ //
+ for ( i = 0; i < 5; i++ ) {
+//fprintf(stderr,"Checking symbol cache\n");
+ if (symbol_data[symbols_cache[i]].table == symbol_table
+ && symbol_data[symbols_cache[i]].symbol == symbol_id) {
+ // We found the matching symbol in the cache
+ found = symbols_cache[i]; // index of symbol
+//fprintf(stderr,"Symbol cache hit:%d\n",found);
+ break;
+ }
+ }
+
+ if (found == -1) { // Not found in symbols cache
+
+ for ( i = 0; i < symbols_loaded; i++ ) {
+ if (symbol_data[i].active == SYMBOL_ACTIVE) {
+ if (symbol_data[i].table == symbol_table
+ && symbol_data[i].symbol == symbol_id) {
+ // We found the matching symbol
+ found = i; // index of symbol
+
+ // Save newly found symbol in cache, shift other
+ // cache entries down by one so that newest is
+ // at the beginning for the cache search.
+//fprintf(stderr,"Saving in cache\n");
+ symbols_cache[4] = symbols_cache[3];
+ symbols_cache[3] = symbols_cache[2];
+ symbols_cache[2] = symbols_cache[1];
+ symbols_cache[1] = symbols_cache[0];
+ symbols_cache[0] = i;
+
+ break;
+ }
+ }
+ }
+ }
+
+ if (found == -1) { // Didn't find a matching symbol
+ found = nosym_index;
+ if (symbol_table && symbol_id && debug_level & 128)
+ fprintf(stderr,"No Symbol Yet! %2x:%2x\n", (unsigned int)symbol_table, (unsigned int)symbol_id);
+ } else { // maybe we want a rotated symbol
+
+
+// It looks like we originally did not want to rotate the symbol if
+// it was ghosted? Why? For dead-reckoning we do want it to be
+// rotated when ghosted.
+// if (!(orient == ' ' || orient == 'l' || symbol_data[found].orient == ' ' || ghost)) {
+ if (!(orient == ' ' || orient == 'l' || symbol_data[found].orient == ' ')) {
+ for (i = found; i < symbols_loaded; i++) {
+ if (symbol_data[i].active == SYMBOL_ACTIVE) {
+ if (symbol_data[i].table == symbol_table && symbol_data[i].symbol == symbol_id
+ && symbol_data[i].orient == orient) {
+ found=i; // index of rotated symbol
+ break;
+ }
+ }
+ }
+ }
+ }
+
+
+ if (mask) {
+ if (ghost)
+ (void)XSetClipMask(XtDisplay(w),gc,symbol_data[found].pix_mask_old);
+ else
+ (void)XSetClipMask(XtDisplay(w),gc,symbol_data[found].pix_mask);
+ }
+ (void)XSetClipOrigin(XtDisplay(w),gc,x_offset,y_offset);
+ (void)XCopyArea(XtDisplay(w),symbol_data[found].pix,where,gc,0,0,20,20,x_offset,y_offset);
+
+
+ if(alphanum_index > 0) {
+ if (ghost)
+ (void)XSetClipMask(XtDisplay(w),gc,symbol_data[alphanum_index].pix_mask_old);
+ else
+ (void)XSetClipMask(XtDisplay(w),gc,symbol_data[alphanum_index].pix_mask);
+
+ (void)XSetClipOrigin(XtDisplay(w),gc,x_offset,y_offset);
+ (void)XCopyArea(XtDisplay(w),symbol_data[alphanum_index].pix,where,gc,0,0,20,20,x_offset,y_offset); // rot
+ }
+
+ (void)XSetClipMask(XtDisplay(w),gc,None);
+}
+
+
+
+
+
+// Speed is in converted units by this point (kph or mph)
+void draw_symbol(Widget w, char symbol_table, char symbol_id, char symbol_overlay,
+ long x_long,long y_lat, char *callsign_text, char *alt_text, char *course_text,
+ char *speed_text, char *my_distance, char *my_course, char *wx_temp,
+ char* wx_wind, time_t sec_heard, int temp_show_last_heard, Pixmap where,
+ char orient, char area_type, char *signpost, char *gauge_data, int bump_count) {
+
+ long x_offset,y_offset;
+ int length;
+ int ghost;
+ int posyl;
+ int posyr;
+
+
+ if ((x_long>NW_corner_longitude) && (x_long<SE_corner_longitude)) {
+
+ if ((y_lat>NW_corner_latitude) && (y_lat<SE_corner_latitude)) {
+
+// if ((x_long+10 < 0) || (x_long-10 > 129600000l)) // 360 deg
+// return;
+
+// if ((y_lat+10 < 0) || (y_lat-10 > 64800000l)) // 180 deg
+// return;
+
+ x_offset=((x_long-NW_corner_longitude)/scale_x)-(10);
+ y_offset=((y_lat -NW_corner_latitude) /scale_y)-(10);
+ ghost = (int)(((sec_old+sec_heard)) < sec_now());
+
+ if (bump_count)
+ currently_selected_stations++;
+
+ if (Display_.symbol)
+ symbol(w,ghost,symbol_table,symbol_id,symbol_overlay,where,1,x_offset,y_offset,orient);
+
+ posyr = 10; // align symbols vertically centered to the right
+ if ( (!ghost || Select_.old_data) && strlen(alt_text)>0)
+ posyr -= 7;
+ if (strlen(callsign_text)>0)
+ posyr -= 7;
+ if ( (!ghost || Select_.old_data) && strlen(speed_text)>0)
+ posyr -= 7;
+ if ( (!ghost || Select_.old_data) && strlen(course_text)>0)
+ posyr -= 7;
+ if (area_type == AREA_LINE_RIGHT)
+ posyr += 9;
+ if (signpost[0] != '\0') // Signpost data?
+ posyr -=7;
+ // we may eventually have more adjustments for different types of areas
+
+ length=(int)strlen(alt_text);
+ if ( (!ghost || Select_.old_data) && length>0) {
+ x_offset=((x_long-NW_corner_longitude)/scale_x)+12;
+ y_offset=((y_lat -NW_corner_latitude) /scale_y)+posyr;
+ draw_nice_string(w,where,letter_style,x_offset,y_offset,alt_text,0x08,0x48,length);
+ posyr += 13;
+ }
+
+ length=(int)strlen(callsign_text);
+ if (length>0) {
+ x_offset=((x_long-NW_corner_longitude)/scale_x)+12;
+ y_offset=((y_lat -NW_corner_latitude) /scale_y)+posyr;
+ draw_nice_string(w,where,letter_style,x_offset,y_offset,callsign_text,0x08,0x0f,length);
+ posyr += 13;
+ }
+
+ length=(int)strlen(speed_text);
+ if ( (!ghost || Select_.old_data) && length>0) {
+ x_offset=((x_long-NW_corner_longitude)/scale_x)+12;
+ y_offset=((y_lat -NW_corner_latitude) /scale_y)+posyr;
+ draw_nice_string(w,where,letter_style,x_offset,y_offset,speed_text,0x08,0x4a,length);
+ posyr += 13;
+ }
+
+ length=(int)strlen(course_text);
+ if ( (!ghost || Select_.old_data) && length>0) {
+ x_offset=((x_long-NW_corner_longitude)/scale_x)+12;
+ y_offset=((y_lat -NW_corner_latitude) /scale_y)+posyr;
+ draw_nice_string(w,where,letter_style,x_offset,y_offset,course_text,0x08,0x52,length);
+ posyr += 13;
+ }
+
+ length=(int)strlen(signpost); // Make it white like callsign?
+ if ( (!ghost || Select_.old_data) && length>0) {
+ x_offset=((x_long-NW_corner_longitude)/scale_x)+12;
+ y_offset=((y_lat -NW_corner_latitude) /scale_y)+posyr;
+ draw_nice_string(w,where,letter_style,x_offset,y_offset,signpost,0x08,0x0f,length);
+ posyr += 13;
+ }
+
+ posyl = 10; // distance and direction goes to the left.
+ // Also minutes last heard.
+ if ( (!ghost || Select_.old_data) && strlen(my_distance)>0)
+ posyl -= 7;
+ if ( (!ghost || Select_.old_data) && strlen(my_course)>0)
+ posyl -= 7;
+ if ( (!ghost || Select_.old_data) && temp_show_last_heard)
+ posyl -= 7;
+
+ length=(int)strlen(my_distance);
+ if ( (!ghost || Select_.old_data) && length>0) {
+ x_offset=(((x_long-NW_corner_longitude)/scale_x)-(length*6))-12;
+ y_offset=((y_lat -NW_corner_latitude) /scale_y)+posyl;
+ draw_nice_string(w,where,letter_style,x_offset,y_offset,my_distance,0x08,0x0f,length);
+ posyl += 13;
+ }
+ length=(int)strlen(my_course);
+ if ( (!ghost || Select_.old_data) && length>0) {
+ x_offset=(((x_long-NW_corner_longitude)/scale_x)-(length*6))-12;
+ y_offset=((y_lat -NW_corner_latitude) /scale_y)+posyl;
+ draw_nice_string(w,where,letter_style,x_offset,y_offset,my_course,0x08,0x0f,length);
+ posyl += 13;
+ }
+ if ( (!ghost || Select_.old_data) && temp_show_last_heard) {
+ char age[20];
+ float minutes;
+ float hours;
+ int fgcolor;
+
+
+ // Color code the time string based on
+ // time since last heard:
+ // Green: 0-29 minutes
+ // Yellow: 30-59 minutes
+ // Red: 60 minutes to 1 day
+ // White: 1 day or later
+
+ minutes = (float)( (sec_now() - sec_heard) / 60.0);
+ hours = minutes / 60.0;
+
+ // Heard from this station within the
+ // last 30 minutes?
+ if (minutes < 30.0) {
+ xastir_snprintf(age,
+ sizeof(age),
+ "%d%s",
+ (int)minutes,
+ langcode("UNIOP00034")); // min
+ fgcolor = 0x52; // green
+ }
+ // 30 to 59 minutes?
+ else if (minutes < 60.0) {
+ xastir_snprintf(age,
+ sizeof(age),
+ "%d%s",
+ (int)minutes,
+ langcode("UNIOP00034")); // min
+ fgcolor = 0x40; // yellow
+ }
+ // 1 hour to 1 day old?
+ else if (hours <= 24.0) {
+ xastir_snprintf(age,
+ sizeof(age),
+ "%.1f%s",
+ hours,
+ langcode("UNIOP00035")); // hr
+ fgcolor = 0x4a; // red
+ }
+ // More than a day old
+ else {
+ xastir_snprintf(age,
+ sizeof(age),
+ "%.1f%s",
+ hours / 24.0,
+ langcode("UNIOP00036")); // day
+ fgcolor = 0x0f; // white
+ }
+
+ length = strlen(age);
+ x_offset=(((x_long-NW_corner_longitude)/scale_x)-(length*6))-12;
+ y_offset=((y_lat -NW_corner_latitude) /scale_y)+posyl;
+ draw_nice_string(w,where,letter_style,x_offset,y_offset,age,0x08,fgcolor,length);
+ posyl += 13;
+ }
+
+ // weather goes to the bottom, centered horizontally.
+ if (posyr < posyl)
+ posyr = posyl;
+ if (posyr < 18)
+ posyr = 18;
+
+ length=(int)strlen(wx_temp);
+ if ( (!ghost || Select_.old_data) && length>0) {
+ x_offset=((x_long-NW_corner_longitude)/scale_x)-(length*3);
+ y_offset=((y_lat -NW_corner_latitude) /scale_y)+posyr;
+ draw_nice_string(w,where,letter_style,x_offset,y_offset,wx_temp,0x08,0x40,length);
+ posyr += 13;
+ }
+
+ length=(int)strlen(wx_wind);
+ if ( (!ghost || Select_.old_data) && length>0) {
+ x_offset=((x_long-NW_corner_longitude)/scale_x)-(length*3);
+ y_offset=((y_lat -NW_corner_latitude) /scale_y)+posyr;
+ draw_nice_string(w,where,letter_style,x_offset,y_offset,wx_wind,0x08,0x40,length);
+ }
+
+ if (gauge_data != NULL) {
+ // Gauge data goes on the bottom, centered
+ // horizontally. White.
+ if (posyr < posyl)
+ posyr = posyl;
+ if (posyr < 22)
+ posyr = 22;
+
+ length=(int)strlen(gauge_data);
+ if ( (!ghost || Select_.old_data) && length>0) {
+ x_offset=((x_long-NW_corner_longitude)/scale_x)-(length*3);
+ y_offset=((y_lat -NW_corner_latitude) /scale_y)+posyr;
+ draw_nice_string(w,where,letter_style,x_offset,y_offset,gauge_data,0x08,0x0f,length);
+ }
+ }
+ }
+ }
+}
+
+
+
+
+
+/*
+ * Looks at the style to determine what color to use.
+ * KG4NBB
+ */
+static int getLineColor(char styleChar) {
+ int color;
+
+ switch (styleChar) {
+ case 'a':
+ case 'b':
+ case 'c':
+ color = colors[0x0c]; // red
+ break;
+
+ case 'd':
+ case 'e':
+ case 'f':
+ color = colors[0x0e]; // yellow
+ break;
+
+ case 'g':
+ case 'h':
+ case 'i':
+ color = colors[0x09]; // blue
+ break;
+
+ case 'j':
+ case 'k':
+ case 'l':
+ color = colors[0x0a]; // green
+ break;
+
+ default:
+ color = colors[0x0a]; // green
+ break;
+ }
+
+ return color;
+}
+
+
+
+
+
+/*
+ * Looks at the style to determine what line type to use.
+ * KG4NBB
+ */
+static int getLineStyle(char styleChar) {
+ int style;
+
+ switch (styleChar) {
+ case 'a':
+ case 'd':
+ case 'g':
+ case 'j':
+ style = LineSolid;
+ break;
+
+ case 'b':
+ case 'e':
+ case 'h':
+ case 'k':
+ style = LineOnOffDash;
+ break;
+
+ case 'c':
+ case 'f':
+ case 'i':
+ case 'l':
+ style = LineDoubleDash;
+ break;
+
+ default:
+ style = LineSolid;
+ break;
+ }
+
+ return style;
+}
+
+
+
+
+
+/*
+ * Draw the other points associated with the station.
+ * KG4NBB
+ */
+void draw_multipoints(long x_long, long y_lat, int numpoints, long mypoints[][2], char type, char style, time_t sec_heard, Pixmap where) {
+ int ghost;
+ int skip_duplicates;
+
+
+ // See if we should draw multipoints for this station. This only happens
+ // if there are points to draw and the object has not been cleared (or
+ // we're supposed to show old data).
+
+ // Per Dale Huguley in e-mail 07/10/2003, a good interval for
+ // the severe weather polygons to disappear is 10 minutes. We
+ // hard-code it here so the user can't mess it up too badly with
+ // the ghosting interval.
+// ghost = (int)(((sec_old+sec_heard)) < sec_now());
+ ghost = (int)( ( sec_heard + (10 * 60) ) < sec_now() );
+
+ // We don't want to draw them if the ghost interval is up, no
+ // matter whether Include Expired Data is checked.
+ //if ( (!ghost || Select_.old_data) && (numpoints > 0) ) {
+ if ( !ghost && (numpoints > 0) ) {
+
+ //long x_offset, y_offset;
+ int i;
+// XPoint xpoints[MAX_MULTIPOINTS + 1];
+
+#if 0
+ long mostNorth, mostSouth, mostWest, mostEast;
+
+ // Check to see if the object is onscreen.
+ // Look for the coordinates that are farthest north, farthest south,
+ // farthest west, and farthest east. Then check to see if any of that
+ // box is onscreen. If so, proceed with drawing. This is all done in
+ // Xastir coordinates.
+
+ mostNorth = mostSouth = y_lat;
+ mostWest = mostEast = x_long;
+
+ for (i = 0; i < numpoints; ++i) {
+ if (mypoints[i][0] < mostNorth)
+ mostNorth = mypoints[i][0];
+ if (mypoints[i][0] > mostSouth)
+ mostSouth = mypoints[i][0];
+ if (mypoints[i][1] < mostWest)
+ mostWest = mypoints[i][1];
+ if (mypoints[i][1] > mostEast)
+ mostEast = mypoints[i][1];
+ }
+
+ if (onscreen(mostWest, mostEast, mostNorth, mostSouth))
+#else // 0
+
+ // See if the station icon is on the screen. If so, draw the associated
+ // points. The drawback to this approach is that if the station icon is
+ // scrolled off the edge of the display the points aren't drawn even if
+ // one or more of them is on the display.
+
+// if( (x_long > NW_corner_longitude) && (x_long < SE_corner_longitude)
+// && (y_lat > NW_corner_latitude) && (y_lat < SE_corner_latitude) )
+#endif // 0
+ {
+ //x_offset = (x_long - NW_corner_longitude) / scale_x;
+ //y_offset = (y_lat - NW_corner_latitude) / scale_y;
+
+ // Convert each of the points from Xastir coordinates to
+ // screen coordinates and fill in the xpoints array.
+
+// for (i = 0; i < numpoints; ++i) {
+// xpoints[i].x = (mypoints[i][0] - NW_corner_longitude) / scale_x;
+// xpoints[i].y = (mypoints[i][1] - NW_corner_latitude) / scale_y;
+// // fprintf(stderr," %d: %d,%d\n", i, xpoints[i].x, xpoints[i].y);
+// }
+
+ // The type parameter determines how the points will be used.
+ // After determining the type, use the style parameter to
+ // get the color and line style.
+
+ switch (type) {
+
+ case '0': // closed polygon
+ default:
+ // Repeat the first point so the polygon will be closed.
+
+// xpoints[numpoints].x = xpoints[0].x;
+// xpoints[numpoints].y = xpoints[0].y;
+
+ // First draw a wider black line.
+ (void)XSetForeground(XtDisplay(da), gc, colors[0x08]); // black
+ (void)XSetLineAttributes(XtDisplay(da), gc, 4, LineSolid, CapButt, JoinMiter);
+
+ skip_duplicates = 0;
+ for (i = 0; i < numpoints-1; i++) {
+// (void)XDrawLines(XtDisplay(da), where, gc, xpoints, numpoints+1, CoordModeOrigin);
+ draw_vector(da, mypoints[i][0],
+ mypoints[i][1],
+ mypoints[i+1][0],
+ mypoints[i+1][1],
+ gc,
+ where,
+ skip_duplicates);
+
+ skip_duplicates = 1;
+ }
+ // Close the polygon
+ draw_vector(da,
+ mypoints[i][0],
+ mypoints[i][1],
+ mypoints[0][0],
+ mypoints[0][1],
+ gc,
+ where,
+ skip_duplicates);
+
+ // Then draw the appropriate colored line on top of it.
+ (void)XSetForeground(XtDisplay(da), gc, getLineColor(style));
+ (void)XSetLineAttributes(XtDisplay(da), gc, 2, getLineStyle(style), CapButt, JoinMiter);
+
+ skip_duplicates = 0;
+ for (i = 0; i < numpoints-1; i++) {
+// (void)XDrawLines(XtDisplay(da), where, gc, xpoints, numpoints+1, CoordModeOrigin);
+ draw_vector(da, mypoints[i][0],
+ mypoints[i][1],
+ mypoints[i+1][0],
+ mypoints[i+1][1],
+ gc,
+ where,
+ skip_duplicates);
+
+ skip_duplicates = 1;
+ }
+ // Close the polygon
+ draw_vector(da,
+ mypoints[i][0],
+ mypoints[i][1],
+ mypoints[0][0],
+ mypoints[0][1],
+ gc,
+ where,
+ skip_duplicates);
+
+ break;
+
+ case '1': // line segments
+
+ (void)XSetForeground(XtDisplay(da), gc, getLineColor(style));
+ (void)XSetLineAttributes(XtDisplay(da), gc, 2, getLineStyle(style), CapButt, JoinMiter);
+
+ skip_duplicates = 0;
+ for (i = 0; i < numpoints-1; i++) {
+// (void)XDrawLines(XtDisplay(da), where, gc, xpoints, numpoints, CoordModeOrigin);
+ draw_vector(da, mypoints[i][0],
+ mypoints[i][1],
+ mypoints[i+1][0],
+ mypoints[i+1][1],
+ gc,
+ where,
+ skip_duplicates);
+
+ skip_duplicates = 1;
+ }
+
+ break;
+
+ // Other types have yet to be implemented.
+ }
+ }
+ }
+}
+
+
+
+
+
+void Select_symbol_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ int i;
+
+ XtPopdown(shell);
+
+ // Free all 188 symbol pixmaps
+ for ( i = 0; i < (126-32)*2; i++ ) {
+ (void)XFreePixmap(XtDisplay(appshell),select_icons[i]);
+ }
+
+begin_critical_section(&select_symbol_dialog_lock, "draw_symbols.c:Select_symbol_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ select_symbol_dialog = (Widget)NULL;
+
+end_critical_section(&select_symbol_dialog_lock, "draw_symbols.c:Select_symbol_destroy_shell" );
+
+}
+
+
+
+
+
+void Select_symbol_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ char table[2];
+ char symbol[2];
+ int i = XTPOINTER_TO_INT(clientData);
+
+ //fprintf(stderr,"Selected a symbol: %d\n", clientData);
+
+ if ( i > 0) {
+ //fprintf(stderr,"Symbol is from primary symbol table: /%c\n",(char)i);
+ table[0] = '/';
+ symbol[0] = (char)i;
+ }
+ else {
+ //fprintf(stderr,"Symbol is from secondary symbol table: \\%c\n",(char)(-i));
+ table[0] = '\\';
+ symbol[0] = (char)(-i);
+ }
+ table[1] = '\0';
+ symbol[1] = '\0';
+
+
+ if (symbol_change_requested_from == 1) { // Configure->Station Dialog
+ symbol_change_requested_from = 0;
+ //fprintf(stderr,"Updating Configure->Station Dialog\n");
+
+ XmTextFieldSetString(station_config_group_data,table);
+ XmTextFieldSetString(station_config_symbol_data,symbol);
+ updateSymbolPictureCallback(widget,clientData,callData);
+ }
+ else if (symbol_change_requested_from == 2) { // Create->Object/Item Dialog
+ symbol_change_requested_from = 0;
+ //fprintf(stderr,"Updating Create->Object/Item Dialog\n");
+
+ XmTextFieldSetString(object_group_data,table);
+ XmTextFieldSetString(object_symbol_data,symbol);
+ updateObjectPictureCallback(widget,clientData,callData);
+ }
+ else { // Do nothing. We shouldn't be here.
+ symbol_change_requested_from = 0;
+ }
+
+ Select_symbol_destroy_shell(widget,select_symbol_dialog,callData);
+}
+
+
+
+
+
+void Select_symbol( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, my_form, my_form2, my_form3, button_cancel,
+ frame, frame2, label1, label2, b1;
+ int i;
+ Atom delw;
+
+
+ if (!select_symbol_dialog) {
+
+
+begin_critical_section(&select_symbol_dialog_lock, "draw_symbols.c:Select_symbol" );
+
+
+ select_symbol_dialog = XtVaCreatePopupShell(langcode("SYMSEL0001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Select_symbol pane",
+ xmPanedWindowWidgetClass,
+ select_symbol_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Select_symbol my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ frame = XtVaCreateManagedWidget("Select_symbol frame",
+ xmFrameWidgetClass,
+ my_form,
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset,10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ label1 = XtVaCreateManagedWidget(langcode("SYMSEL0002"),
+ xmLabelWidgetClass,
+ frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ frame2 = XtVaCreateManagedWidget("Select_symbol frame",
+ xmFrameWidgetClass,
+ my_form,
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset,10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, frame,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ label2 = XtVaCreateManagedWidget(langcode("SYMSEL0003"),
+ xmLabelWidgetClass,
+ frame2,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ my_form2 = XtVaCreateWidget("Select_symbol my_form2",
+ xmRowColumnWidgetClass,
+ frame,
+ XmNorientation, XmHORIZONTAL,
+ XmNpacking, XmPACK_COLUMN,
+ XmNnumColumns, 10,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form3 = XtVaCreateWidget("Select_symbol my_form3",
+ xmRowColumnWidgetClass,
+ frame2,
+ XmNorientation, XmHORIZONTAL,
+ XmNpacking, XmPACK_COLUMN,
+ XmNnumColumns, 10,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Symbols: 33 to 126, for both '/' and '\' tables (94 * 2)
+ // 33 = start of icons in ASCII table, 126 = end
+
+ // Draw the primary symbol set
+ for ( i = 33; i < 127; i++ ) {
+
+ select_icons[i-33] = XCreatePixmap(XtDisplay(appshell),
+ RootWindowOfScreen(XtScreen(appshell)),
+ 20,
+ 20,
+ DefaultDepthOfScreen(XtScreen(appshell)));
+
+ b1 = XtVaCreateManagedWidget("symbol button",
+ xmPushButtonWidgetClass,
+ my_form2,
+ XmNlabelType, XmPIXMAP,
+ XmNlabelPixmap, select_icons[i-33],
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ symbol(b1,0,'/',(char)i,' ',select_icons[i-33],0,0,0,' '); // create icon
+
+ // Here we send back the ascii number of the symbol. We need to keep it within
+ // the range of short int's.
+ XtAddCallback(b1,
+ XmNactivateCallback,
+ Select_symbol_change_data,
+ INT_TO_XTPOINTER(i) );
+ }
+
+ // Draw the alternate symbol set
+ for ( i = 33+94; i < 127+94; i++ ) {
+
+ select_icons[i-33] = XCreatePixmap(XtDisplay(appshell),
+ RootWindowOfScreen(XtScreen(appshell)),
+ 20,
+ 20,
+ DefaultDepthOfScreen(XtScreen(appshell)));
+
+ b1 = XtVaCreateManagedWidget("symbol button",
+ xmPushButtonWidgetClass,
+ my_form3,
+ XmNlabelType, XmPIXMAP,
+ XmNlabelPixmap, select_icons[i-33],
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ symbol(b1,0,'\\',(char)i-94,' ',select_icons[i-33],0,0,0,' '); // create icon
+
+ // Here we send back the ascii number of the symbol negated. We need to keep it
+ // within the range of short int's.
+ XtAddCallback(b1,
+ XmNactivateCallback,
+ Select_symbol_change_data,
+ INT_TO_XTPOINTER(-(i-94)) );
+ }
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_cancel, XmNactivateCallback, Select_symbol_destroy_shell, select_symbol_dialog);
+
+ pos_dialog(select_symbol_dialog);
+
+ delw = XmInternAtom(XtDisplay(select_symbol_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(select_symbol_dialog, delw, Select_symbol_destroy_shell, (XtPointer)select_symbol_dialog);
+ XtManageChild(my_form3);
+ XtManageChild(my_form2);
+ XtManageChild(my_form);
+ XtManageChild(pane);
+
+ XtPopup(select_symbol_dialog,XtGrabNone);
+ fix_dialog_size(select_symbol_dialog);
+
+ // Move focus to the Close button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(select_symbol_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+
+end_critical_section(&select_symbol_dialog_lock, "draw_symbols.c:Select_symbol" );
+
+
+ } else
+ (void)XRaiseWindow(XtDisplay(select_symbol_dialog), XtWindow(select_symbol_dialog));
+}
+
+
+
+
+
+// Function to draw dead-reckoning symbols.
+//
+void draw_deadreckoning_features(DataRow *p_station,
+ Pixmap where,
+ Widget w) {
+ double my_course;
+ long x_long, y_lat;
+ long x_long2, y_lat2;
+ long x, y;
+ long x2, y2;
+ double diameter;
+ int color = trail_colors[p_station->trail_color];
+// int symbol_on_screen = 0;
+ int ghosted_symbol_on_screen = 0;
+
+
+// This function takes a bit of CPU if we are zoomed out. It'd be
+// best to check first whether the zoom level and the speed make it
+// worth computing DR at all for this station. As a first
+// approximation, we could turn off DR if we're at zoom 8000 or
+// higher:
+//
+// if (scale_y > 8000)
+// return;
+
+
+ x_long = p_station->coord_lon;
+ y_lat = p_station->coord_lat;
+
+ // x/y are screen locations for start position
+ x = (x_long - NW_corner_longitude)/scale_x;
+ y = (y_lat - NW_corner_latitude)/scale_y;
+
+ y_lat2 = y_lat;
+ x_long2 = x_long;
+
+ // Compute the latest DR'ed position for the object
+ compute_current_DR_position(p_station,
+ &x_long2,
+ &y_lat2);
+
+ // x2/y2 are screen location for ghost symbol (DR'ed position)
+ x2 = (x_long2 - NW_corner_longitude)/scale_x;
+ y2 = (y_lat2 - NW_corner_latitude)/scale_y;
+
+
+ // Check DR'ed symbol position
+ if ( (x_long2>NW_corner_longitude) &&
+ (x_long2<SE_corner_longitude) &&
+ (y_lat2>NW_corner_latitude) &&
+ (y_lat2<SE_corner_latitude) &&
+ ((x_long>=0) && (x_long<=129600000l)) &&
+ ((y_lat>=0) && (y_lat<=64800000l))) {
+
+ ghosted_symbol_on_screen++;
+ }
+
+
+ // Draw the DR arc
+ //
+ if (Display_.dr_arc && ghosted_symbol_on_screen) {
+
+ double xdiff, ydiff;
+
+
+ xdiff = (x2-x) * 1.0;
+ ydiff = (y2-y) * 1.0;
+
+ // a squared + b squared = c squared
+ diameter = 2.0 * sqrt( (double)( (ydiff*ydiff) + (xdiff*xdiff) ) );
+
+ //fprintf(stderr,"Range:%f\tDiameter:%f\n",range,diameter);
+
+ if (diameter > 10.0) {
+ int arc_degrees = (sec_now() - p_station->sec_heard) * 90 / (5*60);
+
+ if (arc_degrees > 360) {
+ arc_degrees = 360;
+ }
+
+ (void)XSetLineAttributes(XtDisplay(da), gc, 1, LineOnOffDash, CapButt,JoinMiter);
+ //(void)XSetForeground(XtDisplay(da),gc,colors[0x0a]);
+ //(void)XSetForeground(XtDisplay(da),gc,colors[0x44]); // red3
+ (void)XSetForeground(XtDisplay(da),gc,color);
+
+
+ // Compute angle from the two screen positions.
+ //
+ if (xdiff != 0) {
+//We should guard against divide-by-zero here!
+ my_course = 57.29578 * atan(xdiff/ ydiff);
+ }
+ else {
+ if (ydiff >= 0) {
+ my_course = 180.0;
+ }
+ else {
+ my_course = 0.0;
+ }
+ }
+
+
+//fprintf(stderr,"my_course:%f\n", my_course);
+ // The arctan function returns values between -90 and +90. To
+ // obtain the true course we apply the following rules:
+ if (ydiff > 0 && xdiff > 0) {
+//fprintf(stderr,"1\n"); // Lower-right quadrant
+ my_course = 360.0 - my_course;
+ }
+ else if (ydiff < 0.0 && xdiff > 0.0) {
+//fprintf(stderr,"2\n"); // Upper-right quadrant
+ my_course = 180.0 - my_course;
+ }
+ else if (ydiff < 0.0 && xdiff < 0.0) {
+//fprintf(stderr,"3\n"); // Upper-left quadrant
+ my_course = 180.0 - my_course;
+ }
+ else if (ydiff > 0.0 && xdiff < 0.0) {
+//fprintf(stderr,"4\n"); // Lower-left quadrant
+ my_course = 360.0 - my_course;
+ }
+ else { // 0/90/180/270
+//fprintf(stderr,"5\n");
+ my_course = 180.0 + my_course;
+ }
+
+
+ // Convert to screen angle for XDrawArc routines:
+ my_course = my_course + 90.0;
+
+ if (my_course > 360.0)
+ my_course = my_course - 360.0;
+
+//fprintf(stderr,"\tmy_course2:%f\n", my_course);
+
+// Check that our parameters are within spec for XDrawArc. Tricky
+// 'cuz the XArc struct has short's and unsigned short's, while
+// XDrawArc man-page says int's/unsigned int's. We'll stick to 16-bit
+// just to make sure.
+
+ (void)XDrawArc(XtDisplay(da),where,gc,
+ l16(x-(diameter/2)), // int
+ l16(y-(diameter/2)), // int
+ lu16(diameter), // unsigned int
+ lu16(diameter), // unsigned int
+ l16(-64*my_course), // int
+ l16(64/2*arc_degrees)); // int
+
+// Check that our parameters are within spec for XDrawArc. Tricky
+// 'cuz the XArc struct has short's and unsigned short's, while
+// XDrawArc man-page says int's/unsigned int's. We'll stick to 16-bit
+// just to make sure.
+
+ (void)XDrawArc(XtDisplay(da),where,gc,
+ l16(x-(diameter/2)), // int
+ l16(y-(diameter/2)), // int
+ lu16(diameter), // unsigned int
+ lu16(diameter), // unsigned int
+ l16(-64*my_course), // int
+ l16(-64/2*arc_degrees)); // int
+ }
+ }
+
+
+// Note that for the DR course, if we're in the middle of the symbol
+// and the DR'ed symbol (ghosted symbol), but neither of them are
+// on-screen, the DR'ed course won't display.
+//
+ // Draw the DR'ed course if either the symbol or the DR'ed
+ // symbol (ghosted symbol) are on-screen.
+ //
+ if (Display_.dr_course) {
+
+ (void)XSetLineAttributes(XtDisplay(da), gc, 0, LineOnOffDash, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da),gc,color); // red3
+
+ // This one changes the angle as the vector gets longer, by
+ // about 10 degrees (A test at 133 degrees -> 143 degrees).
+ // draw_vector() needs to truncate the line in this case,
+ // maintaining the same slope. This behavior is _much_
+ // better than the XDrawLine above though!
+ //
+ draw_vector(w,
+ x_long,
+ y_lat,
+ x_long2,
+ y_lat2,
+ gc,
+ where,
+ 0);
+ }
+
+
+ // Draw the DR'ed symbol (ghosted symbol) if enabled and if
+ // on-screen.
+ //
+ if (Display_.dr_symbol && ghosted_symbol_on_screen) {
+
+ draw_symbol(w,
+ p_station->aprs_symbol.aprs_type,
+ p_station->aprs_symbol.aprs_symbol,
+ p_station->aprs_symbol.special_overlay,
+ x_long2,
+ y_lat2,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ p_station->sec_heard-sec_old, // Always draw it ghosted
+ 0,
+ where,
+ symbol_orient(p_station->course),
+ p_station->aprs_symbol.area_object.type,
+ p_station->signpost,
+ (char) 0x00,
+ 0); // Don't bump the station count
+ }
+}
+
+
diff --git a/src/draw_symbols.h b/src/draw_symbols.h
new file mode 100644
index 0000000..25a3318
--- /dev/null
+++ b/src/draw_symbols.h
@@ -0,0 +1,77 @@
+/*
+ * $Id: draw_symbols.h,v 1.33 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifndef __XASTIR_DRAW_SYMBOLS_H
+#define __XASTIR_DRAW_SYMBOLS_H
+
+#define SYMBOL_ACTIVE 'A'
+#define SYMBOL_NOTACTIVE 'N'
+
+#define MAX_SYMBOLS 400
+
+typedef struct {
+ char active; // ??
+ char table; // table character
+ char symbol; // symbol character
+ char orient; // orientation of the symbol, one of ' ', 'l','r','u','d'
+ Pixmap pix; // icon picture
+ Pixmap pix_mask; // mask for transparent background
+ Pixmap pix_mask_old; // mask for ghost symbols, half transparent icons
+} SymbolData;
+
+extern SymbolData symbol_data[];
+
+extern void draw_nice_string(Widget w, Pixmap where, int style, long x, long y, char *text, int bgcolor, int fgcolor, int length);
+extern void clear_symbol_data(void);
+extern void read_symbol_from_file(FILE *f, char *pixels, char table_char);
+extern void load_pixmap_symbol_file(char *filename, int reloading);
+extern void insert_symbol(char table, char symbol, char *pixel, int deg, char orient, int reloading);
+extern char symbol_orient(char *course);
+extern void symbol(Widget w, int ghost,char symbol_table, char symbol_id, char symbol_overlay, Pixmap where, int mask, long x_offset, long y_offset, char rotate);
+
+extern void draw_WP_line(DataRow *p_station, int ambiguity_flag, long ambiguity_coord_lon, long ambiguity_coord_lat, Pixmap where, Widget w);
+
+extern void draw_symbol(Widget w, char symbol_table, char symbol_id, char symbol_overlay, long x_lon, long y_lat,char *callsign_text, char *alt_text, char *course_text, char *speed_text, char *my_distance, char *my_course, char *wx_temp, char* wx_wind, time_t sec_heard, int temp_show_last_heard, Pixmap where, char rotate, char area_type, char *signpost, char *gauge_data, int bump_count );
+
+extern void draw_pod_circle(long x_long, long y_lat, double range, int color, Pixmap where);
+extern void draw_precision_rectangle(long x_long, long y_lat, double range, unsigned int lat_precision, unsigned int lon_precision, int color, Pixmap where);
+extern void draw_aloha_circle(long x_long, long y_lat, double range, int color, Pixmap where);
+extern void draw_phg_rng(long x_long, long y_lat, char *phg, time_t sec_heard, Pixmap where);
+extern void draw_DF_circle(long x_long, long y_lat, char *shgd, time_t sec_heard, Pixmap where);
+extern void draw_wind_barb(long x_long, long y_lat, char *speed, char *course, time_t sec_heard, Pixmap where);
+extern void draw_bearing(long x_long, long y_lat, char *course, char *bearing, char *NRQ, int color, int draw_beamwidth, int draw_bearing, time_t sec_heard, Pixmap where);
+extern void draw_ambiguity(long x_long, long y_lat, char amb, long *amb_x_long, long *amb_y_lat, time_t sec_heard, Pixmap where);
+extern void draw_area(long x_long, long y_lat, char type, char color, char sqrt_lat_off, char sqrt_lon_off, unsigned int width, time_t sec_heard, Pixmap where);
+extern void draw_multipoints(long x_long, long y_lat, int numpoints, long points[][2], char type, char style, time_t sec_heard, Pixmap where); // KG4NBB
+extern void Select_symbol( Widget w, XtPointer clientData, XtPointer callData);
+extern int symbol_change_requested_from;
+extern Widget select_symbol_dialog;
+extern void Select_symbol_destroy_shell( Widget widget, XtPointer clientData, XtPointer callData);
+extern void draw_symbols_init(void);
+extern void draw_deadreckoning_features(DataRow *p_station, Pixmap where, Widget w);
+
+#endif // __XASTIR_DRAW_SYMBOLS_H
+
+
diff --git a/src/fcc_data.c b/src/fcc_data.c
new file mode 100644
index 0000000..76f76db
--- /dev/null
+++ b/src/fcc_data.c
@@ -0,0 +1,503 @@
+/*
+ * $Id: fcc_data.c,v 1.25 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+#include <Xm/XmAll.h>
+
+#include "xastir.h"
+#include "fcc_data.h"
+#include "xa_config.h"
+#include "main.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+
+
+char *call_only(char *callsign) {
+ int i, len;
+
+ len = strlen(callsign);
+ for (i = 0; i < len; i++) {
+ if (!isalnum((int)callsign[i])) {
+ callsign[i]='\0';
+ i=len;
+ }
+ }
+ return(callsign);
+}
+
+
+
+
+
+/* ==================================================================== */
+/* build a new (or newer if I check the file date) index file */
+/* check for current ic index file */
+/* FG: added a date check in case the FCC file has been updated. */
+/* appl.dat must have a time stamp newer than the index file time */
+/* stamp. Use the touch command on the appl.dat file to make the */
+/* time current if necessary. */
+// How this works: The index file contains a few callsigns and their
+// offsets into the large database file. The code uses these as
+// jump-off points to look for a particular call, to speed things up.
+/* ******************************************************************** */
+int build_fcc_index(int type){
+ FILE *fdb;
+ FILE *fndx;
+ unsigned long call_offset = 0;
+ unsigned long x = 0;
+ char fccdata[FCC_DATA_LEN+8];
+ char database_name[100];
+ int found,i,num;
+ char appl_file_path[MAX_VALUE];
+
+ if (type==1)
+ xastir_snprintf(database_name, sizeof(database_name), "fcc/appl.dat");
+ else
+ xastir_snprintf(database_name, sizeof(database_name), "fcc/EN.dat");
+
+ /* ==================================================================== */
+ /* If the index file is there, exit */
+ /* */
+ get_user_base_dir("data/appl.ndx", appl_file_path,
+ sizeof(appl_file_path));
+ if (filethere(appl_file_path)) {
+ /* if file is there make sure the index date is newer */
+ if (file_time(get_data_base_dir(database_name))<=file_time(appl_file_path))
+ return(1);
+ else {
+ // FCC index old, rebuilding
+ statusline(langcode("STIFCC0100"),1);
+
+ fprintf(stderr,"FCC index is old. Rebuilding index.\n");
+// XmTextFieldSetString(text,"FCC index old, rebuilding");
+// XtManageChild(text);
+// XmUpdateDisplay(XtParent(text)); // DK7IN: do we need this ???
+ }
+ }
+
+ /* ==================================================================== */
+ /* Open the database and index file */
+ /* */
+ fdb=fopen(get_data_base_dir(database_name),"rb");
+ if (fdb==NULL){
+ fprintf(stderr,"Build:Could not open FCC data base: %s\n", get_data_base_dir(database_name) );
+ return(0);
+ }
+
+ fndx=fopen(appl_file_path,"w");
+ if (fndx==NULL){
+ fprintf(stderr,"Build:Could not open/create FCC data base index: %s\n", appl_file_path );
+ (void)fclose(fdb);
+ return(0);
+ }
+
+ /* ==================================================================== */
+ /* write out the current callsign and RBA of the db file */
+ /* skip (index_skip) records and do it again until no more */
+ /* */
+ xastir_snprintf(fccdata,sizeof(fccdata)," ");
+ while(!feof(fdb)) {
+ call_offset = (unsigned long)ftell(fdb);
+ (void)fgets(fccdata, (int)sizeof(fccdata), fdb);
+ found=0;
+ num=0;
+ if (type==2) {
+ for(i=0;i<14 && !found;i++) {
+ if(fccdata[i]=='|') {
+ num++;
+ if(num==4)
+ found=i+1;
+ }
+ }
+ }
+ (void)call_only(fccdata+found);
+ fprintf(fndx,"%-6.6s%li\n",fccdata+found,call_offset+found);
+ for (x=0;x<=500 && !feof(fdb);x++) {
+ if (fgets(fccdata, (int)sizeof(fccdata), fdb)==NULL)
+ break;
+ }
+ }
+ (void)fclose(fdb);
+ (void)fclose(fndx);
+
+// XmTextFieldSetString(text,"");
+// XtManageChild(text);
+
+ return(1);
+}
+
+
+
+
+
+/* ==================================================================== */
+/* Check for ic data base file */
+/* Check/build the index */
+/* */
+/* ******************************************************************** */
+int check_fcc_data(void) {
+ int fcc_data_available = 0;
+ if (filethere(get_data_base_dir("fcc/EN.dat")) && filethere(get_data_base_dir("fcc/appl.dat"))) {
+ if(file_time(get_data_base_dir("fcc/appl.dat"))<=file_time(get_data_base_dir("fcc/EN.dat"))) {
+ /*fprintf(stderr,"NEW FORMAT FCC DATA FILE is NEWER THAN OLD FCC FORMAT\n");*/
+ if (build_fcc_index(2))
+ fcc_data_available=2;
+ else {
+ fprintf(stderr,"Check:Could not build fcc data base index\n");
+ fcc_data_available=0;
+ }
+ } else {
+ /*fprintf(stderr,"OLD FORMAT FCC DATA FILE is NEWER THAN NEW FCC FORMAT\n");*/
+ if (build_fcc_index(1))
+ fcc_data_available=1;
+ else {
+ fprintf(stderr,"Check:Could not build fcc data base index\n");
+ fcc_data_available=0;
+ }
+ }
+ } else {
+ if (filethere(get_data_base_dir("fcc/EN.dat"))) {
+ /*fprintf(stderr,"NO OLD FCC, BUT NEW FORMAT FCC DATA AVAILABLE\n");*/
+ if (build_fcc_index(2))
+ fcc_data_available=2;
+ else {
+ fprintf(stderr,"Check:Could not build fcc data base index\n");
+ fcc_data_available=0;
+ }
+ } else {
+ if (filethere(get_data_base_dir("fcc/appl.dat"))) {
+ /*fprintf(stderr,"NO NEW FCC, BUT OLD FORMAT FCC DATA AVAILABLE\n");*/
+ if (build_fcc_index(1))
+ fcc_data_available=1;
+ else {
+ fprintf(stderr,"Check:Could not build fcc data base index\n");
+ fcc_data_available=0;
+ }
+ }
+ }
+ }
+ return(fcc_data_available);
+}
+
+
+
+
+
+int search_fcc_data_appl(char *callsign, FccAppl *data) {
+ FILE *f;
+ char line[200];
+ int line_pos;
+ char data_in[16385];
+ int found, xx, bytes_read;
+ char temp[15];
+ int len;
+ int which;
+ int i,ii;
+ int pos_it;
+ int llen;
+ char calltemp[8];
+ int pos,ix,num;
+ FILE *fndx;
+ long call_offset = 0;
+ char char_offset[16];
+ char index[32];
+ char appl_file_path[MAX_VALUE];
+
+ data->id_file_num[0] = '\0';
+ data->type_purpose[0] = '\0';
+ data->type_applicant=' ';
+ data->name_licensee[0] = '\0';
+ data->text_street[0] = '\0';
+ data->text_pobox[0] = '\0';
+ data->city[0] = '\0';
+ data->state[0] = '\0';
+ data->zipcode[0] = '\0';
+ data->date_issue[0] = '\0';
+ data->date_expire[0] = '\0';
+ data->date_last_change[0] = '\0';
+ data->id_examiner[0] = '\0';
+ data->renewal_notice=' ';
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ callsign);
+ (void)call_only(temp);
+
+ xastir_snprintf(calltemp, sizeof(calltemp), "%-6.6s", temp);
+// calltemp doesn't appear to get used anywhere...
+
+ /* add end of field data */
+ strncat(temp, "|", sizeof(temp) - 1 - strlen(temp));
+ len=(int)strlen(temp);
+ found=0;
+ line_pos=0;
+ /* check the database again */
+ which = check_fcc_data();
+
+ // Check for first letter of a U.S. callsign
+ if (! (callsign[0] == 'A' || callsign[0] == 'K' || callsign[0] == 'N' || callsign[0] == 'W') )
+ return(0); // Not found
+
+ // ====================================================================
+ // Search thru the index, get the RBA
+ //
+ // This gives us a jumping-off point to start looking in the right
+ // neighborhood for the callsign of interest.
+ //
+ get_user_base_dir("data/appl.ndx", appl_file_path, sizeof(appl_file_path));
+ fndx=fopen(appl_file_path,"r");
+ if (fndx!=NULL){
+ (void)fgets(index,(int)sizeof(index),fndx);
+ xastir_snprintf(char_offset,sizeof(char_offset),"%s",&index[6]);
+
+ // Search through the indexes looking for a callsign which is
+ // close to the callsign of interest. If callsign is later in
+ // the alphabet than the current index, snag the next index.
+ while (!feof(fndx) && strncmp(callsign,index,6) > 0) {
+ xastir_snprintf(char_offset,sizeof(char_offset),"%s",&index[6]);
+ (void)fgets(index,(int)sizeof(index),fndx);
+ }
+ } else {
+ fprintf(stderr,"Search:Could not open FCC data base index: %s\n", appl_file_path );
+ return (0);
+ }
+ call_offset = atol(char_offset);
+
+ (void)fclose(fndx);
+
+ /* ==================================================================== */
+ /* Continue with the original search */
+ /* */
+
+ f=NULL;
+ switch (which) {
+ case(1):
+ f=fopen(get_data_base_dir("fcc/appl.dat"),"r");
+ break;
+
+ case(2):
+ f=fopen(get_data_base_dir("fcc/EN.dat"),"r");
+ break;
+
+ default:
+ break;
+ }
+ if (f!=NULL) {
+ (void)fseek(f, call_offset,SEEK_SET);
+ while (!feof(f) && !found) {
+ bytes_read=(int)fread(data_in,1,16384,f);
+ if (bytes_read>0) {
+ for (xx=0;(xx<bytes_read) && !found;xx++) {
+ if(data_in[xx]!='\n' && data_in[xx]!='\r') {
+ if (line_pos<199) {
+ line[line_pos++]=data_in[xx];
+ line[line_pos]='\0';
+ }
+ } else {
+ line_pos=0;
+ /*fprintf(stderr,"line:%s\n",line);*/
+ pos=0;
+ num=0;
+ if (which==2) {
+ for (ix=0;ix<14 && !pos;ix++) {
+ if (line[ix]=='|') {
+ num++;
+ if (num==4)
+ pos=ix+1;
+ }
+ }
+ }
+ if (strncmp(line+pos,temp,(size_t)len)==0) {
+ found=1;
+ /*fprintf(stderr,"line:%s\n",line);*/
+ llen=(int)strlen(line);
+ /* replace "|" with 0 */
+ for (ii=pos;ii<llen;ii++) {
+ if (line[ii]=='|')
+ line[ii]='\0';
+ }
+ pos_it=pos;
+ for (i=0; i<15; i++) {
+ for (ii=pos_it;ii<llen;ii++) {
+ if (line[ii]=='\0') {
+ pos_it=ii;
+ ii=llen+1;
+ }
+ }
+ pos_it++;
+ if (line[pos_it]!='\0') {
+ /*fprintf(stderr,"DATA %d %d:%s\n",i,pos_it,line+pos_it);*/
+ switch (which) {
+ case(1):
+ switch(i) {
+ case(0):
+ xastir_snprintf(data->id_file_num,sizeof(data->id_file_num),"%s",line+pos_it);
+ break;
+
+ case(1):
+ xastir_snprintf(data->type_purpose,sizeof(data->type_purpose),"%s",line+pos_it);
+ break;
+
+ case(2):
+ data->type_applicant=line[pos_it];
+ break;
+
+ case(3):
+ xastir_snprintf(data->name_licensee,sizeof(data->name_licensee),"%s",line+pos_it);
+ break;
+
+ case(4):
+ xastir_snprintf(data->text_street,sizeof(data->text_street),"%s",line+pos_it);
+ break;
+
+ case(5):
+ xastir_snprintf(data->text_pobox,sizeof(data->text_pobox),"%s",line+pos_it);
+ break;
+
+ case(6):
+ xastir_snprintf(data->city,sizeof(data->city),"%s",line+pos_it);
+ break;
+
+ case(7):
+ xastir_snprintf(data->state,sizeof(data->state),"%s",line+pos_it);
+ break;
+
+ case(8):
+ xastir_snprintf(data->zipcode,sizeof(data->zipcode),"%s",line+pos_it);
+ break;
+
+ case(9):
+ xastir_snprintf(data->date_issue,sizeof(data->date_issue),"%s",line+pos_it);
+ break;
+
+ case(11):
+ xastir_snprintf(data->date_expire,sizeof(data->date_expire),"%s",line+pos_it);
+ break;
+
+ case(12):
+ xastir_snprintf(data->date_last_change,sizeof(data->date_last_change),"%s",line+pos_it);
+ break;
+
+ case(13):
+ xastir_snprintf(data->id_examiner,sizeof(data->id_examiner),"%s",line+pos_it);
+ break;
+
+ case(14):
+ data->renewal_notice=line[pos_it];
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case(2):
+ switch (i) {
+ case(0):
+ xastir_snprintf(data->id_file_num,sizeof(data->id_file_num),"%s",line+pos_it);
+ break;
+
+ case(2):
+ xastir_snprintf(data->name_licensee,sizeof(data->name_licensee),"%s",line+pos_it);
+ break;
+
+ case(10):
+ xastir_snprintf(data->text_street,sizeof(data->text_street),"%s",line+pos_it);
+ break;
+
+ case(11):
+ xastir_snprintf(data->city,sizeof(data->city),"%s",line+pos_it);
+ break;
+
+ case(12):
+ xastir_snprintf(data->state,sizeof(data->state),"%s",line+pos_it);
+ break;
+
+ case(13):
+ xastir_snprintf(data->zipcode,sizeof(data->zipcode),"%s",line+pos_it);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+ else {
+ // Check whether we passed the alphabetic
+ // location for the callsign. Return if so.
+ if ( (temp[0] < line[pos]) ||
+ ( (temp[0] == line[pos]) && (temp[1] < line[pos+1]) ) ) {
+
+ // "Callsign Search", "Callsign Not Found!"
+ popup_message_always(langcode("STIFCC0101"),
+ langcode("STIFCC0102") );
+
+ //fprintf(stderr,"%c%c\t%c%c\n",temp[0],temp[1],line[pos],line[pos+1]);
+ (void)fclose(f);
+ return(0);
+ }
+ }
+ }
+ }
+ }
+ }
+ (void)fclose(f);
+ } else {
+ fprintf(stderr,"Could not open FCC appl data base at: %s\n", get_data_base_dir("fcc/") );
+ }
+ return(found);
+}
+
+
diff --git a/src/fcc_data.h b/src/fcc_data.h
new file mode 100644
index 0000000..82760ea
--- /dev/null
+++ b/src/fcc_data.h
@@ -0,0 +1,90 @@
+/*
+ * $Id: fcc_data.h,v 1.10 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+/*
+ * FCC Database structures
+ *
+ */
+
+/*
+type_purpose - Indicates the reason why the application was
+ filed. Multiple codes may occur. Codes are:
+
+ A New license
+ B Change existing class
+ C Change name
+ D Change mailing address
+ E Change callsign
+ F Renewal on Form 610
+ G Add record (internal)
+ H Duplicate license request
+ I Change Issue/Expiration Date
+ J Supercede
+ K Internal correction code
+ L Delete
+ N Renewal on form 610R
+ O Renewal on form 610B
+ P Modification on form 610B
+ Q Restore both database and pending
+ R Restore database
+ S Special callsign change
+
+type_applicant - Indicates type of application. Codes are:
+
+ A Alien
+ C Club
+ I Individual
+ M Military recreation
+ R RACES
+
+*/
+
+#ifndef XASTIR_FCC_DATA_H
+#define XASTIR_FCC_DATA_H
+
+#define FCC_DATA_LEN 200
+
+typedef struct{
+ char id_callsign[11];
+ char id_file_num[11];
+ char type_purpose[9];
+ char type_applicant;
+ char name_licensee[41];
+ char text_street[36];
+ char text_pobox[21];
+ char city[30];
+ char state[3];
+ char zipcode[10];
+ char filler;
+ char date_issue[7];
+ char date_expire[7];
+ char date_last_change[7];
+ char id_examiner[4];
+ char renewal_notice;
+} FccAppl;
+
+extern int check_fcc_data(void);
+extern int search_fcc_data_appl(char *callsign, FccAppl *data);
+
+#endif /* XASTIR_FCC_DATA_H */
diff --git a/src/festival.c b/src/festival.c
new file mode 100644
index 0000000..f5a5ca5
--- /dev/null
+++ b/src/festival.c
@@ -0,0 +1,476 @@
+// Modification for Xastir CVS purposes
+//
+// Portions Copyright (C) 2000-2012 The Xastir Group
+//
+// $Id: festival.c,v 1.25 2012/08/25 16:38:29 tvrusso Exp $
+//
+// End of modification
+
+
+
+/*************************************************************************/
+/* */
+/* Centre for Speech Technology Research */
+/* University of Edinburgh, UK */
+/* Copyright (c) 1999 */
+/* All Rights Reserved. */
+/* */
+/* Permission is hereby granted, free of charge, to use and distribute */
+/* this software and its documentation without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of this work, and to */
+/* permit persons to whom this work is furnished to do so, subject to */
+/* the following conditions: */
+/* 1. The code must retain the above copyright notice, this list of */
+/* conditions and the following disclaimer. */
+/* 2. Any modifications must be clearly marked as such. */
+/* 3. Original authors' names are not deleted. */
+/* 4. The authors' names are not used to endorse or promote products */
+/* derived from this software without specific prior written */
+/* permission. */
+/* */
+/* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
+/* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
+/* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
+/* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
+/* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
+/* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
+/* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
+/* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
+/* THIS SOFTWARE. */
+/* */
+/*************************************************************************/
+/* Author : Alan W Black (awb at cstr.ed.ac.uk) */
+/* Date : March 1999 */
+/*-----------------------------------------------------------------------*/
+/* */
+/* Client end of Festival server API in C designed specifically for */
+/* Galaxy Communicator use though might be of use for other things */
+/* */
+/* This is a standalone C client, no other Festival or Speech Tools */
+/* libraries need be link with this. Thus is very small. */
+/* */
+/* Compile with (plus socket libraries if required) */
+/* cc -o festival_client -DSTANDALONE festival_client.c */
+/* */
+/* Run as */
+/* festival_client -text "hello there" -o hello.snd */
+/* */
+/* */
+/* This is provided as an example, it is quite limited in what it does */
+/* but is functional compiling without -DSTANDALONE gives you a simple */
+/* API */
+/* */
+/*************************************************************************/
+/* */
+/* Heavily modified and Hacked together to provide a general purpose */
+/* interface for use in XASTIR by: */
+/* */
+/* Ken Koster N7IPB 03/24/2001 */
+/* */
+/* */
+/* More comments added and 'do' loop that waited for 'ok' response */
+/* removed. Also cleaned up escape processing */
+/* */
+/* N7IPB 04/04/2001 */
+/* Test for errno result from 'read' operation and re-opening of */
+/* connection if it gets closed. */
+/* N7IPB 04/08/2001 */
+/* */
+/*=======================================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "xastir.h"
+#include "festival.h"
+#include "snprintf.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+FT_Info *info = NULL;
+
+static char last_speech_text[8000];
+static time_t last_speech_time = (time_t)0;
+static time_t festival_connect_attempt_time = (time_t)0;
+
+
+
+
+
+// Set up default struct
+//
+void festival_default_info(void) {
+
+ if (info == NULL) { // First time through
+
+ // Malloc storage for the struct
+ info = (FT_Info *)malloc(1 * sizeof(FT_Info));
+
+ // Fill in the struct
+ if (info != NULL) {
+ info->server_host = FESTIVAL_DEFAULT_SERVER_HOST;
+ info->server_port = FESTIVAL_DEFAULT_SERVER_PORT;
+ info->text_mode = FESTIVAL_DEFAULT_TEXT_MODE;
+ info->server_fd = -1;
+ }
+ else { // Couldn't allocate memory
+ fprintf(stderr,"festival_default_info: Couldn't malloc\n");
+ }
+ }
+
+ return;
+}
+
+
+
+
+
+// Returns a FD to a remote server
+//
+static int festival_socket_open(const char *host, int port) {
+ struct sockaddr_in serv_addr;
+ struct hostent *serverhost;
+ int fd;
+
+
+ // Delay at least 60 seconds between each socket attempt
+ if ( (festival_connect_attempt_time + 60) > sec_now() ) {
+ //fprintf(stderr,"Not time yet\n");
+ return(-1);
+ }
+ festival_connect_attempt_time = sec_now();
+
+ if ((fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ fprintf(stderr,"festival_client: can't get socket\n");
+ return(-1);
+ }
+
+ memset(&serv_addr, 0, sizeof(serv_addr));
+
+ if ((int)(serv_addr.sin_addr.s_addr = inet_addr(host)) == -1) {
+ /* its a name rather than an ipnum */
+ serverhost = gethostbyname(host);
+ if (serverhost == (struct hostent *)0) {
+ fprintf(stderr,"festival_client: gethostbyname failed\n");
+ return(-1);
+ }
+ memmove(&serv_addr.sin_addr,serverhost->h_addr, (size_t)serverhost->h_length);
+ }
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_port = htons(port);
+
+ if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
+ fprintf(stderr,"festival_client: connect to server failed\n");
+ (void)close(fd); // Close the socket
+ return(-1);
+ }
+ return(fd);
+}
+
+
+
+
+
+/***********************************************************************/
+/* Public Functions to this API */
+/***********************************************************************/
+
+
+
+// Close socket to server
+//
+int festivalClose(void) {
+
+ //fprintf(stderr,"festivalClose()\n");
+
+ if (info != NULL) { // We have a struct allocated
+
+ // Check whether we have a socket open
+ if (info->server_fd != -1) {
+ fprintf(stderr,"Closing Festival socket\n");
+ (void)close(info->server_fd); // Close the socket
+ info->server_fd = -1; // Just to be safe
+ }
+
+ // Free the struct, zero the pointer. The struct will get
+ // re-created/re-initialized later when we re-open the
+ // festival connection.
+ free(info);
+ info = NULL;
+ }
+
+ return(0);
+}
+
+
+
+
+
+// Open socket to server. Close the connection if one is already
+// open.
+//
+int festivalOpen(void) {
+
+
+ //fprintf(stderr,"festivalOpen()\n");
+
+ festival_default_info();
+
+ // Check whether we have a record to work with
+ if (info == NULL) {
+ return(-1);
+ }
+
+ // Check whether we already have a socket open (or think we do)
+ if (info->server_fd != -1) { // We have a socket open
+ (void)festivalClose(); // Close it, free struct
+ usleep(50000); // 50ms wait
+ }
+
+ info->server_fd = festival_socket_open(info->server_host, info->server_port);
+
+ if (info->server_fd == -1) { // Error occured opening socket
+ //fprintf(stderr,"festivalOpen: Error opening socket\n");
+ (void)festivalClose(); // Close, free struct
+ usleep(50000); // 50ms wait
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+
+
+
+void festivalStringToSpeech(char *text) {
+ FILE *fd;
+ char *p;
+ char ack[4];
+ int n;
+ int tmp = 0;
+ int ret;
+
+
+ //fprintf(stderr,"festivalStringToSpeech()\n");
+
+ // If we don't have a struct allocated
+ if (info == 0) {
+ if (festivalOpen() == -1) { // Allocate struct, open socket
+ //fprintf(stderr,"festivalStringToSpeech: Couldn't open socket to Festival\n");
+ return;
+ }
+ }
+
+ if (info == 0) { // If socket is still not open
+ return;
+ }
+
+ if (info->server_fd == -1) {
+ fprintf(stderr,"festival_client: server connection unopened\n");
+ (void)festivalClose();
+ return;
+ }
+
+ fd = fdopen(dup(info->server_fd),"wb");
+
+ if (fd == NULL) {
+ fprintf(stderr,"Couldn't create duplicate socket\n");
+ (void)festivalClose();
+ return;
+ }
+
+ /*
+ ** Send the mode commands to festival
+ */
+ ret = fprintf(fd,"(audio_mode `async)\n(SayText \"\n");
+
+ if (ret == 0 || ret == -1) {
+ fprintf(stderr,"Couldn't send mode commands to festival\n");
+ (void)fclose(fd);
+ (void)festivalClose();
+ return;
+ }
+
+ /*
+ ** Copy text over to server, escaping any quotes
+ */
+ for (p=text; p && (*p != '\0'); p++) {
+ if ((*p == '"') || (*p == '\\')) {
+
+ if (putc('\\',fd) == EOF) { // Error writing to socket
+ fprintf(stderr,"Error writing to socket\n");
+ (void)fclose(fd);
+ (void)festivalClose();
+ return;
+ }
+ }
+ else {
+ /*
+ ** Then convert any embedded '-' into the word 'dash'
+ ** This could cause problems with spoken text from
+ ** Weather alerts or messages. We'll deal with that
+ ** later if necessary. Making this a separate function
+ ** is probably the thing to do.
+ */
+ if (*p == '-' ) {
+
+ ret = fprintf(fd,",dash,");
+
+ if (ret == 0 || ret == -1) {
+ fprintf(stderr,"Error writing to socket\n");
+ (void)fclose(fd);
+ (void)festivalClose();
+ return;
+ }
+ }
+ else {
+
+ if (putc(*p,fd) == EOF) { // Error writing to socket
+ fprintf(stderr,"Error writing to socket\n");
+ (void)fclose(fd);
+ (void)festivalClose();
+ return;
+ }
+ }
+ }
+ }
+ /*
+ ** Complete the command to xastir, close the quotes and
+ ** set the mode to 'fundamental'
+ */
+ ret = fprintf(fd,"\" \"%s\")\n",info->text_mode);
+
+ if (ret == 0 || ret == -1) {
+ fprintf(stderr,"Error writing to socket\n");
+ (void)fclose(fd);
+ (void)festivalClose();
+ return;
+ }
+
+ /*
+ ** Close the duplicate port we used for writing
+ */
+ (void)fclose(fd);
+ /*
+ ** Read back info from server
+ **
+ ** We don't really care what we get back. If it's an error
+ ** We're just going to continue on anyway so I've removed the
+ ** check here for the 'OK' response. We still check for an ERror
+ ** but we just print the fact we got it and continue on
+ **
+ ** This could probably use some work, I need to study the
+ ** festival docs a bit more, this could block and it could
+ ** also have more than 3bytes that need to be read. It doesn't
+ ** appear to matter but should be checked into.
+ */
+ for (n=0; n < 3; ) {
+ if ( ( tmp = read(info->server_fd,ack+n,3-n)) != -1 ) {
+ n = n + tmp;
+ }
+ else {
+ if (debug_level & 2) {
+ fprintf(stderr,"Error reading festival ACK - %s\n",strerror(errno));
+ }
+ n = 3;
+ if (errno == ECONNRESET) {
+
+ fprintf(stderr,"Connection reset\n");
+ info = 0;
+
+ (void)festivalClose();
+
+ if (festivalOpen() == -1) {
+ fprintf(stderr,"festivalStringToSpeech2: Couldn't open socket to Festival\n");
+ return;
+ }
+
+ }
+ }
+ }
+
+ /*
+ ** Null terminate the string
+ */
+ ack[3] = '\0';
+ if (strcmp(ack,"ER\n") == 0) { /* server got an error */
+ fprintf(stderr,"festival_client: server returned error\n");
+ }
+ return;
+}
+
+
+
+
+
+int SayText(char *text) {
+
+ if (debug_level & 2)
+ fprintf(stderr,"SayText: %s\n",text);
+
+ // Check whether the last text was the same and it hasn't been
+ // enough time between them (30 seconds). We include our speech
+ // system test string here so that we don't have to wait 30
+ // seconds between Test button-presses.
+ if ( (strcmp(last_speech_text,text) == 0) // Strings match
+ && (strcmp(text,SPEECH_TEST_STRING) != 0)
+ && (last_speech_time + 30 > sec_now()) ) {
+
+/*
+ fprintf(stderr,
+ "Same text, skipping speech: %d seconds, %s\n",
+ (int)(sec_now() - last_speech_time),
+ text);
+*/
+
+ return(1);
+ }
+
+ //fprintf(stderr,"Speaking: %s\n",text);
+
+ xastir_snprintf(last_speech_text,
+ sizeof(last_speech_text),
+ "%s",
+ text);
+ last_speech_time = sec_now();
+
+ festivalStringToSpeech(text);
+
+ return(0);
+}
+
+
+
+
+
+int SayTextInit(void) {
+
+ if (festivalOpen() == -1) {
+ fprintf(stderr,"SayText: Couldn't open socket to Festival\n");
+ }
+
+ last_speech_text[0] = '\0';
+ last_speech_time = (time_t)0;
+
+ return(0);
+}
+
+
diff --git a/src/festival.h b/src/festival.h
new file mode 100644
index 0000000..89879e9
--- /dev/null
+++ b/src/festival.h
@@ -0,0 +1,102 @@
+// Modification for Xastir CVS purposes
+//
+// Portions Copyright (C) 2000-2012 The Xastir Group
+//
+// $Id: festival.h,v 1.12 2012/11/01 18:57:19 we7u Exp $
+//
+// End of modification
+
+
+
+/*************************************************************************/
+/* */
+/* Centre for Speech Technology Research */
+/* University of Edinburgh, UK */
+/* Copyright (c) 1999 */
+/* All Rights Reserved. */
+/* */
+/* Permission is hereby granted, free of charge, to use and distribute */
+/* this software and its documentation without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of this work, and to */
+/* permit persons to whom this work is furnished to do so, subject to */
+/* the following conditions: */
+/* 1. The code must retain the above copyright notice, this list of */
+/* conditions and the following disclaimer. */
+/* 2. Any modifications must be clearly marked as such. */
+/* 3. Original authors' names are not deleted. */
+/* 4. The authors' names are not used to endorse or promote products */
+/* derived from this software without specific prior written */
+/* permission. */
+/* */
+/* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
+/* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
+/* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
+/* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
+/* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
+/* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
+/* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
+/* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
+/* THIS SOFTWARE. */
+/* */
+/*************************************************************************/
+/* Author : Alan W Black (awb at cstr.ed.ac.uk) */
+/* Date : March 1999 */
+/*-----------------------------------------------------------------------*/
+/* */
+/* Client end of Festival server API (in C) designed specifically for */
+/* Galaxy Communicator use, though might be of use for other things */
+/* */
+/*=======================================================================*/
+#ifndef _FESTIVAL_CLIENT_H_
+#define _FESTIVAL_CLIENT_H_
+
+#define FESTIVAL_DEFAULT_SERVER_HOST "localhost"
+#define FESTIVAL_DEFAULT_SERVER_PORT 1314
+#define FESTIVAL_DEFAULT_TEXT_MODE "fundamental"
+
+typedef struct FT_Info
+{
+ int encoding;
+ char *server_host;
+ int server_port;
+ char *text_mode;
+
+ int server_fd;
+} FT_Info;
+
+typedef struct FT_Wave
+{
+ int num_samples;
+ int sample_rate;
+ short *samples;
+} FT_Wave;
+
+void delete_FT_Wave(FT_Wave *wave);
+void delete_FT_Info(FT_Info *info);
+
+#define SWAPSHORT(x) ((((unsigned)x) & 0xff) << 8 | \
+ (((unsigned)x) & 0xff00) >> 8)
+#define SWAPINT(x) ((((unsigned)x) & 0xff) << 24 | \
+ (((unsigned)x) & 0xff00) << 8 | \
+ (((unsigned)x) & 0xff0000) >> 8 | \
+ (((unsigned)x) & 0xff000000) >> 24)
+
+/* Sun, HP, SGI Mips, M68000 */
+#define FAPI_BIG_ENDIAN (((char *)&fapi_endian_loc)[0] == 0)
+/* Intel, Alpha, DEC Mips, Vax */
+#define FAPI_LITTLE_ENDIAN (((char *)&fapi_endian_loc)[0] != 0)
+
+
+/*****************************************************************/
+/* Public functions to interface */
+/*****************************************************************/
+
+/* If called with NULL will attempt to access using defaults */
+int festivalOpen(void);
+void festivalStringToWave(char *text);
+int festivalClose(void);
+
+#endif // _FESTIVAL_CLIENT_H_
+
+
diff --git a/src/fetch_remote.c b/src/fetch_remote.c
new file mode 100644
index 0000000..4477c40
--- /dev/null
+++ b/src/fetch_remote.c
@@ -0,0 +1,267 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: fetch_remote.c,v 1.4 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <math.h>
+#include <errno.h>
+
+#ifdef HAVE_LIBCURL
+#include <curl/curl.h>
+#endif // HAVE_LIBCURL
+
+// Needed for size_t
+#include <sys/types.h>
+
+
+// Must be last include file
+#include "leak_detection.h"
+
+extern int debug_level;
+extern int net_map_timeout;
+
+/* curl routines */
+#ifdef HAVE_LIBCURL
+
+struct FtpFile {
+ char *filename;
+ FILE *stream;
+};
+
+
+
+
+
+size_t curl_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) {
+ struct FtpFile *out = (struct FtpFile *)stream;
+ if (out && !out->stream) {
+ out->stream=fopen(out->filename, "wb");
+ if (!out->stream)
+ return -1;
+ }
+ return fwrite(buffer, size, nmemb, out->stream);
+}
+
+/*
+ * xastir_curl_init - create curl session with common options
+ */
+CURL *xastir_curl_init(char *errBuf) {
+ CURL *mySession;
+ char agent_string[15];
+
+ mySession = curl_easy_init();
+ if (mySession != NULL) {
+ if (debug_level & 8192) {
+ curl_easy_setopt(mySession, CURLOPT_VERBOSE, 1);
+ } else {
+ curl_easy_setopt(mySession, CURLOPT_VERBOSE, 0);
+ }
+
+
+ curl_easy_setopt(mySession, CURLOPT_ERRORBUFFER, errBuf);
+
+ xastir_snprintf(agent_string, sizeof(agent_string),"Xastir");
+ curl_easy_setopt(mySession, CURLOPT_USERAGENT, agent_string);
+
+ // write function
+ curl_easy_setopt(mySession, CURLOPT_WRITEFUNCTION, curl_fwrite);
+
+ curl_easy_setopt(mySession, CURLOPT_TIMEOUT, (long)net_map_timeout);
+ curl_easy_setopt(mySession, CURLOPT_CONNECTTIMEOUT, (long)(net_map_timeout/2));
+
+ // Added in libcurl 7.9.8
+#if (LIBCURL_VERSION_NUM >= 0x070908)
+ curl_easy_setopt(mySession, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
+#endif // LIBCURL_VERSION_NUM
+
+ // Added in libcurl 7.10.6
+#if (LIBCURL_VERSION_NUM >= 0x071006)
+ curl_easy_setopt(mySession, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+#endif // LIBCURL_VERSION_NUM
+
+ // Added in libcurl 7.10.7
+#if (LIBCURL_VERSION_NUM >= 0x071007)
+ curl_easy_setopt(mySession, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
+#endif // LIBCURL_VERSION_NUM
+
+ // Added in libcurl 7.10
+#if (LIBCURL_VERSION_NUM >= 0x070a00)
+ // This prevents a segfault for the case where we get a timeout on
+ // domain name lookup. It has to do with the ALARM signal
+ // and siglongjmp(), which we use in hostname.c already.
+ // This URL talks about it a bit more, plus see the libcurl
+ // docs:
+ //
+ // http://curl.haxx.se/mail/lib-2002-12/0103.html
+ //
+ curl_easy_setopt(mySession, CURLOPT_NOSIGNAL, 1);
+#endif // LIBCURL_VERSION_NUM
+
+ }
+
+ return(mySession);
+} // xastir_curl_init()
+
+/*
+ * fetch_remote_tile - downloads file using an open curl session
+ * Returns curl result code.
+ */
+int fetch_remote_tile(CURL *session, char *tileURL, char *tileFileName) {
+ CURLcode res;
+ struct FtpFile ftpfile;
+
+ curl_easy_setopt(session, CURLOPT_URL, tileURL);
+ ftpfile.filename = tileFileName;
+ ftpfile.stream = NULL;
+ curl_easy_setopt(session, CURLOPT_FILE, &ftpfile);
+
+ res = curl_easy_perform(session);
+
+ if (ftpfile.stream)
+ fclose(ftpfile.stream);
+
+ return(res);
+
+} // fetch_remote_tile()
+
+#endif // HAVE_LIBCURL
+
+
+/*
+ * fetch_remote_file
+ * Returns: 0 If file retrieved
+ * 1 If there was a problem getting the file
+ */
+int fetch_remote_file(char *fileimg, char *local_filename) {
+#ifdef HAVE_LIBCURL
+ CURL *curl;
+ CURLcode res;
+ char curlerr[CURL_ERROR_SIZE];
+ struct FtpFile ftpfile;
+
+//fprintf(stderr, "Fetching remote file: %s\n", fileimg);
+
+ curl = xastir_curl_init(curlerr);
+
+ if (curl) {
+
+ // download from fileimg
+ curl_easy_setopt(curl, CURLOPT_URL, fileimg);
+ ftpfile.filename = local_filename;
+ ftpfile.stream = NULL;
+ curl_easy_setopt(curl, CURLOPT_FILE, &ftpfile);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+
+ if (CURLE_OK != res) {
+ fprintf(stderr, "curl told us %d\n", res);
+ fprintf(stderr, "curlerr: %s\n", curlerr);
+ fprintf(stderr,
+ "Perhaps a timeout? Try increasing \"Internet Map Timout\".\n");
+ }
+
+ if (ftpfile.stream)
+ fclose(ftpfile.stream);
+
+ // Return error-code if we had trouble
+ if (CURLE_OK != res) {
+ return(1);
+ }
+
+ } else {
+ fprintf(stderr,"Couldn't download the file %s\n", fileimg);
+ fprintf(stderr,
+ "Perhaps a timeout? Try increasing \"Internet Map Timout\".\n");
+
+ return(1);
+ }
+ return(0); // Success!
+
+#else // HAVE_LIBCURL
+
+#ifdef HAVE_WGET
+
+ char tempfile[500];
+
+ //"%s --server-response --timestamping --user-agent=Xastir --tries=1 --timeout=%d --output-document=%s \'%s\' 2> /dev/null\n",
+ xastir_snprintf(tempfile, sizeof(tempfile),
+ "%s --server-response --user-agent=Xastir --tries=1 --timeout=%d --output-document=%s \'%s\' 2> /dev/null\n",
+ WGET_PATH,
+ net_map_timeout,
+ local_filename,
+ fileimg);
+
+ if (debug_level & 2)
+ fprintf(stderr,"%s",tempfile);
+
+ if ( system(tempfile) ) { // Go get the file
+ fprintf(stderr,"Couldn't download the file\n");
+ fprintf(stderr,
+ "Perhaps a timeout? Try increasing \"Internet Map Timout\".\n");
+
+ return(1);
+ }
+ return(0); // Success!
+
+#else // HAVE_WGET
+
+ fprintf(stderr,"libcurl or 'wget' not installed. Can't download file\n");
+ return(1);
+
+#endif // HAVE_WGET
+#endif // HAVE_LIBCURL
+
+}
diff --git a/src/fetch_remote.h b/src/fetch_remote.h
new file mode 100644
index 0000000..8f70c64
--- /dev/null
+++ b/src/fetch_remote.h
@@ -0,0 +1,40 @@
+/*
+ * $Id: fetch_remote.h,v 1.3 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifndef __XASTIR_FETCH_REMOTE_H
+#define __XASTIR_FETCH_REMOTE_H
+
+#ifdef HAVE_LIBCURL
+#include <curl/curl.h>
+CURL *xastir_curl_init(char *errBuf);
+int fetch_remote_tile(CURL *session, char *tileURL, char *tileFileName);
+#endif // HAVE_LIBCURL
+
+int fetch_remote_file(char *fileimg, char *local_filename);
+
+
+#endif // __XASTIR_FETCH_REMOTE_H
+
+
diff --git a/src/geo-find.c b/src/geo-find.c
new file mode 100644
index 0000000..e75ab99
--- /dev/null
+++ b/src/geo-find.c
@@ -0,0 +1,529 @@
+
+// $Id: geo-find.c,v 1.17 2012/08/25 16:38:29 tvrusso Exp $
+
+
+/* Copyright 2002 Daniel Egnor. See LICENSE.geocoder file.
+ * Portions Copyright (C) 2004-2012 The Xastir Group
+ *
+ * The geo_find() function defined here uses an address map built by
+ * geo-*-to-* to parse an address and convert it to geographical
+ * coordinates.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "geo.h"
+#include "io.h"
+
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+#define D(x)
+
+
+
+struct state {
+ struct io_file *index;
+
+ /* Text input */
+ int input_depth;
+ const char *input_begin,*input_end;
+ char buffer[100],*buffer_next,*buffer_end;
+ const char *next;
+
+ /* Working hypothesis */
+ int address;
+ struct { int begin,end; } range[4];
+ int range_count;
+
+ /* Answer */
+ struct geo_location *out;
+};
+
+
+
+
+
+static int is_valid(struct state *s) {
+ int i,pos[sizeof(s->range)/sizeof(*s->range)];
+
+ if (0 == s->range_count) return 0;
+
+ for (i = 0; i < s->range_count; ++i) {
+D(printf(" Metarange #%d: %d entries\n",i,(s->range[i].end - s->range[i].begin) / 8));
+ pos[i] = s->range[i].begin;
+ }
+
+ for (;;) {
+ int i_begin = 1,i_end = 1;
+ int best_begin = 1,best_end = 1;
+ char out_side = 'X';
+ int out_addr = 0,out_lat = 0,out_long = 0;
+
+D(printf("Searching ---\n"));
+ for (i = 0; i != i_begin; i = (i + 1) % s->range_count) {
+ int r_begin,r_end;
+ for (;;) {
+ int n;
+ if (pos[i] >= s->range[i].end || pos[i] < 0) {
+D(printf(" Range #%d @ %d: End\n",i,(pos[i] - s->range[i].begin) / 8));
+ return 0;
+ }
+ n = io_in_i4(s->index,
+ io_in_i4(s->index,pos[i],&r_begin),&r_end);
+ if (n < 0)
+ return 0;
+D(printf(" Range #%d @ %d: [%d,%d)\n",i,(pos[i] - s->range[i].begin) / 8,r_begin,r_end));
+ if (r_end > best_begin && r_begin < r_end)
+ break;
+ pos[i] = n;
+ }
+ if (r_begin > best_begin) {
+ best_begin = r_begin;
+ best_end = r_end;
+ i_begin = i_end = i;
+D(printf(" Best -> [%d#%d,%d#%d)\n",best_begin,i_begin,best_end,i_end));
+ }
+ else if (r_end < best_end) {
+ best_end = r_end;
+ i_end = i;
+D(printf(" Best -> [%d#%d,%d#%d)\n",best_begin,i_begin,best_end,i_end));
+ }
+ }
+
+D(printf("Address range ---\n"));
+ pos[i_end] += 8; /* hack... */
+ do {
+ int next,lon,lat,addr;
+ best_begin = io_in_i4(s->index,best_begin,&next);
+ best_begin = io_in_i4(s->index,best_begin,&lon);
+ best_begin = io_in_i4(s->index,best_begin,&lat);
+ best_begin = io_in_i4(s->index,best_begin,&addr);
+
+ /* PERF: This should be a binary search... */
+ while (best_begin >= 0 && best_begin < next) {
+ short da;
+ signed char dln,dlt;
+ char side;
+ best_begin = io_in_i2(s->index,best_begin,&da);
+ best_begin = io_in_i1(s->index,best_begin,&dln);
+ best_begin = io_in_i1(s->index,best_begin,&dlt);
+ best_begin = io_in(s->index,best_begin,&side,1);
+D(printf(" %c: %d vs. %d\n",side,addr + da,s->address / 2));
+ if (addr + da <= s->address / 2) {
+ out_side = side;
+ out_addr = addr + da;
+ out_lat = lat + dlt;
+ out_long = lon + dln;
+ } else if ('X' == out_side) {
+ best_begin = next;
+D(printf(" Not this time.\n"));
+ break;
+ }
+ else if (NULL != s->out) {
+ const int parity = s->address % 2;
+
+ s->out->before.address =
+ 2 * out_addr + parity;
+ s->out->before.latitude =
+ out_lat / 100000.0;
+ s->out->before.longitude =
+ out_long / 100000.0;
+
+ if ('X' == side) --da;
+ s->out->after.address =
+ 2 * (addr + da) + parity;
+ s->out->after.latitude =
+ (lat + dlt) / 100000.0;
+ s->out->after.longitude =
+ (lon + dln) / 100000.0;
+
+ s->out->at.address = s->address;
+ s->out->at.latitude = (out_lat +
+ (lat + dlt - out_lat) *
+ (s->address / 2 - out_addr) /
+ (addr + da - out_addr)) /
+ 100000.0;
+ s->out->at.longitude = (out_long +
+ (lon + dln - out_long) *
+ (s->address / 2 - out_addr) /
+ (addr + da - out_addr)) /
+ 100000.0;
+
+ s->out->side = out_side;
+D(printf(" Success!\n"));
+ return 1;
+ }
+ else {
+D(printf(" Success...\n"));
+ return 1;
+ }
+ }
+ }
+ while (best_begin > 0 && best_begin < best_end);
+ }
+}
+
+
+
+
+
+static int find_name(
+ struct io_file *index,int begin,int end,
+ char type,const char *name, unsigned int name_len) {
+ const int size = 45;
+ const int count = (end - begin) / size;
+ const int mid = begin + size * (count / 2);
+ char test[41];
+ if (count <= 1) return begin;
+ if (io_in(index,mid - size,test,sizeof test) < 0) return -1;
+ if (name_len > sizeof test - 1)
+ name_len = sizeof test - 1;
+ if (type > test[0]
+ || (type == test[0] && strncasecmp(name,test + 1,name_len) > 0))
+ return find_name(index,mid,end,type,name,name_len);
+ else
+ return find_name(index,begin,mid,type,name,name_len);
+}
+
+
+
+static const char *next_word(struct state *,const char *);
+
+
+
+static int get_name_at( struct state *s,
+ char type,
+ int (*f)(struct state *),
+ const char *last) {
+
+ char n[41];
+ const char *next,*save;
+ unsigned int len = last - s->next;
+ int begin,end,pos;
+
+ if (io_in_i4(s->index,
+ io_in_i4(s->index,
+ io_in_i4(s->index,0,NULL),&begin),&end) < 0
+ || (pos = find_name(s->index,begin,end,type,s->next,len)) < 0
+ || pos == end
+ || (pos = io_in_i4(s->index,io_in(s->index,pos,n,sizeof n),&begin)) < 0
+ || pos == end
+ || (pos = io_in_i4(s->index,io_in(s->index,pos,NULL,sizeof n),&end)) < 0
+ || n[0] != type
+ || strncasecmp(n + 1,s->next,len)) {
+ D(printf(" '%c' \"%.*s\" not found\n",type,len,s->next));
+ return 0;
+ }
+
+ if ('=' == n[len + 1]) { /* alias expansion */
+ char * const replace = (s->next - s->buffer) + s->buffer;
+ int delta;
+
+ begin = len + 2;
+
+ while (begin < (int)sizeof n && ' ' == n[begin]) ++begin;
+
+ end = sizeof n;
+
+ while (end > begin && ' ' == n[end - 1]) --end;
+
+ if (end < (int)sizeof n) ++end;
+
+ if (end - begin > (int)len) end = begin + len;
+
+D(printf(" Replacing '%.*s' with '%.*s'\n",len,n + 1,end - begin,&n[begin]));
+
+ memcpy(replace,n + begin,end - begin);
+ memmove(replace + (end - begin),
+ replace + len,
+ s->buffer_end - replace - len);
+
+ delta = len - (end - begin);
+ s->buffer_end -= delta;
+ s->buffer_next -= delta;
+D(printf(" Buffer is now: '%.*s'\n",s->buffer_end - s->buffer,s->buffer));
+ return 1;
+ }
+
+ next = next_word(s,last);
+ if (next != last && get_name_at(s,type,f,next)) return 1;
+
+ pos = len;
+
+ while (++pos < (int)sizeof n) if (' ' != n[pos]) return 0;
+
+ s->range[s->range_count].begin = begin;
+ s->range[s->range_count].end = end;
+ ++s->range_count;
+ save = s->next;
+ s->next = last;
+D(printf(">>> '%c' \"%.*s\" found\n",type,len - 1,n + 1));
+ if (NULL != f && f(s)) {
+ char *out = NULL;
+
+ switch (type) {
+ case 'E':
+ case 'O':
+ out = s->out ? s->out->street_name : NULL;
+ break;
+ case 'C':
+ out = s->out ? s->out->city_name : NULL;
+ break;
+ case 'S':
+ out = s->out ? s->out->state_name : NULL;
+ break;
+ }
+
+ if (NULL != out) {
+ // strncpy is dangerous as it can leave a string
+ // unterminated if the destination isn't big enough to
+ // hold the '\0' character. Must terminate the string
+ // manually in all cases, as we do here.
+ strncpy(out,n + 1,len - 1);
+ out[len - 1] = '\0';
+ }
+
+ s->next = save;
+ return 1;
+ }
+
+D(printf("<<< '%c' \"%.*s\"\n",type,len - 1,n + 1));
+ --s->range_count;
+ s->next = save;
+ return 0;
+}
+
+
+
+
+
+static const char *input_word(struct state *s,const char *pos) {
+ assert(pos >= s->buffer && pos <= s->buffer_end);
+ if (pos != s->buffer_end) {
+ while (pos < s->buffer_end && *pos != ' ') ++pos;
+ while (pos < s->buffer_end && *pos == ' ') ++pos;
+ return pos;
+ }
+
+ while (s->input_begin != s->input_end
+ && (s->input_depth > 0 || !isalnum((int)*s->input_begin))) {
+ const char ch = *s->input_begin++;
+ if ('(' == ch)
+ ++s->input_depth;
+ if (')' == ch && s->input_depth > 0)
+ --s->input_depth;
+ }
+
+ while (s->input_begin != s->input_end
+ && s->buffer_end != &s->buffer[sizeof s->buffer]
+ && isalnum((int)*s->input_begin)) {
+ if (s->buffer == s->buffer_end
+ || !isdigit((int)s->buffer_end[-1]) || !isalpha((int)*s->input_begin))
+ *s->buffer_end++ = *s->input_begin;
+ ++s->input_begin;
+ }
+
+ if (pos != s->buffer_end
+ && s->buffer_end != &s->buffer[sizeof s->buffer])
+ *s->buffer_end++ = ' ';
+ return s->buffer_end;
+}
+
+
+
+
+
+static const char *next_word(struct state *s,const char *pos) {
+ const char * const next = input_word(s,pos);
+ const char * const save = s->next;
+ assert(pos >= s->buffer && pos <= s->buffer_next);
+ if (pos != s->buffer_next || next == pos) return next;
+
+ s->next = pos;
+ s->buffer_next = s->buffer + (next - s->buffer);
+ if (get_name_at(s,'A',NULL,s->buffer_next)) {
+ s->buffer_next = s->buffer + (pos - s->buffer);
+ s->next = save;
+ return next_word(s,pos);
+ /* NOTE! make sure aliases do not form a cycle */
+ }
+
+ s->next = save;
+ return next;
+}
+
+
+
+
+
+static int get_name(struct state *s,char type,int (*f)(struct state *)) {
+ const char * const next = next_word(s,s->next);
+ if (s->next == next) return 0;
+ return get_name_at(s,type,f,next);
+}
+
+
+
+
+
+static int get_zip(struct state *s) {
+ const char * const next = next_word(s,s->next);
+ int zip,zip_offset;
+
+ if (s->next == next) return 0;
+ zip = io_strntoi(s->next,next - s->next);
+ if (zip <= 0 || zip >= 100000
+ || io_in_i4(s->index,0,&zip_offset) < 0)
+ return 0;
+
+ s->range[s->range_count].begin = zip_offset + 4 * zip;
+ s->range[s->range_count].end = zip_offset + 4 * zip + 8;
+ ++s->range_count;
+D(printf(">>> %d\n",zip));
+ if (is_valid(s)) {
+ if (NULL != s->out) s->out->zip_code = zip;
+ return 1;
+ }
+D(printf("<<< %d\n",zip));
+ --s->range_count;
+ return 0;
+}
+
+
+
+
+
+static int optional_zip(struct state *s) {
+ return get_zip(s) || is_valid(s);
+}
+
+
+
+
+
+static int get_state(struct state *s) {
+ return get_name(s,'S',optional_zip) || optional_zip(s);
+}
+
+
+
+
+
+static int get_city(struct state *s) {
+ return get_name(s,'C',get_state) || get_zip(s);
+}
+
+
+
+
+
+static int skip_stuff(struct state *s) {
+ const char * const begin = s->next;
+ int skipped;
+ for (skipped = 0; skipped < 7; ++skipped)
+ if (get_city(s)) {
+ s->next = begin;
+ return 1;
+ }
+ else {
+ const char * const next = next_word(s,s->next);
+ if (next == s->next) break;
+ s->next = next;
+ }
+
+ s->next = begin;
+ return 0;
+}
+
+
+
+
+
+static int get_street(struct state *s) {
+ return get_name(s,(s->address % 2) ? 'O' : 'E',skip_stuff);
+}
+
+
+
+
+
+static int get_address(struct state *s) {
+ const char * const begin = s->next;
+ const char * const next = next_word(s,begin);
+
+
+//fprintf(stderr,"get_address\n");
+
+ if (begin == next) {
+ return 0;
+ }
+
+ s->address = io_strntoi(begin,next - s->next);
+ if (0 == s->address) {
+ return 0;
+ }
+
+ s->next = next;
+ if (get_street(s)) {
+ s->next = begin;
+ return 1;
+ }
+
+ s->next = next_word(s,s->next);
+ if (get_street(s)) {
+ s->next = begin;
+ return 1;
+ }
+
+ s->next = next_word(s,s->next);
+ if (get_street(s)) {
+ s->next = begin;
+ return 1;
+ }
+
+ s->next = begin;
+
+ return 0;
+}
+
+
+
+
+
+int geo_find( struct io_file *index,
+ const char *str,
+ int len,
+ struct geo_location *out) {
+
+ struct state s;
+
+
+ if (NULL == index) return 0;
+
+ s.index = index;
+ s.input_depth = 0;
+ s.input_begin = str;
+ s.input_end = str + len;
+ s.next = s.buffer_end = s.buffer_next = s.buffer;
+ s.address = s.range_count = 0;
+
+ if (NULL != (s.out = out)) {
+ out->zip_code = 0;
+ out->street_name[0] = '\0';
+ out->city_name[0] = '\0';
+ out->state_name[0] = '\0';
+ }
+ return get_address(&s);
+}
+
+
diff --git a/src/geo.h b/src/geo.h
new file mode 100644
index 0000000..310a99f
--- /dev/null
+++ b/src/geo.h
@@ -0,0 +1,49 @@
+
+// $Id: geo.h,v 1.12 2012/11/01 18:57:19 we7u Exp $
+
+
+/* Copyright 2002 Daniel Egnor. See LICENSE.geocoder file.
+ * Portions Copyright (C) 2004-2012 The Xastir Group
+ *
+ * The geo_find() function is the query interface for turning addressees
+ * into geographical locations using an 'address map' built from TIGER/Line
+ * and FIPS-55 data by the geo-*-to-* programs. */
+
+#ifndef GEOCODER_GEO_H
+#define GEOCODER_GEO_H
+
+#include "io.h"
+
+extern long destination_coord_lat;
+extern long destination_coord_lon;
+extern int mark_destination;
+extern int show_destination_mark;
+
+extern char geocoder_map_filename[400];
+
+
+struct geo_corner {
+ int address;
+ double latitude,longitude;
+};
+
+/* Decoded address location. */
+struct geo_location {
+ /* "Before" and "after" are the previous and next "control point";
+ * these are the known locations, "at" is the interpolated point
+ * corresponding to the supplied address. */
+ struct geo_corner before,after,at;
+ int zip_code; /* 0 if none found in address */
+ char side; /* 'L' or 'R' */
+ char street_name[41],city_name[41],state_name[41];
+ /* Empty if none found in address */
+};
+
+/* Arguments: m = Address map file to use
+ * a = Address string to parse
+ * len = Length of address string (in characters)
+ * out = Address of location to output
+ * Returns: Nonzero iff an address was recognized and decoded. */
+int geo_find(struct io_file *m,const char *a,int len,struct geo_location *out);
+
+#endif
diff --git a/src/geocoder_gui.c b/src/geocoder_gui.c
new file mode 100644
index 0000000..78d3e86
--- /dev/null
+++ b/src/geocoder_gui.c
@@ -0,0 +1,572 @@
+/*
+ * $Id: geocoder_gui.c,v 1.27 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <Xm/XmAll.h>
+#ifdef HAVE_XBAE_MATRIX_H
+#include <Xbae/Matrix.h>
+#endif // HAVE_XBAE_MATRIX_H
+
+
+#include "xastir.h"
+#include "main.h"
+#include "lang.h"
+//#include "maps.h"
+#include "io.h"
+#include "geo.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+extern XmFontList fontlist1; // Menu/System fontlist
+
+Widget geocoder_place_dialog = (Widget)NULL;
+Widget geocoder_zip_data = (Widget)NULL;
+Widget geocoder_state_data = (Widget)NULL;
+Widget geocoder_locality_data = (Widget)NULL;
+Widget geocoder_address_data = (Widget)NULL;
+Widget geocoder_map_file_data = (Widget)NULL;
+char geocoder_zip_name[50];
+char geocoder_state_name[50];
+char geocoder_locality_name[255];
+char geocoder_address_name[255];
+char geocoder_map_filename[400];
+static xastir_mutex geocoder_place_dialog_lock;
+
+long destination_coord_lat = 0;
+long destination_coord_lon = 0;
+int mark_destination = 0;
+int show_destination_mark = 0;
+
+
+
+
+
+void geocoder_gui_init(void)
+{
+ init_critical_section( &geocoder_place_dialog_lock );
+ geocoder_zip_name[0] = '\0';
+ geocoder_state_name[0] = '\0';
+ geocoder_locality_name[0] = '\0';
+ geocoder_address_name[0] = '\0';
+}
+
+
+
+
+
+/**** GEOCODER FIND PLACE ******/
+
+void Geocoder_place_destroy_shell(/*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+
+begin_critical_section(&geocoder_place_dialog_lock, "geocoder_gui.c:Geocoder_place_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ geocoder_place_dialog = (Widget)NULL;
+
+end_critical_section(&geocoder_place_dialog_lock, "geocoder_gui.c:Geocoder_place_destroy_shell" );
+
+}
+
+
+
+
+
+/*
+ * Geocoder a place by centering the map at its position
+ */
+void Geocoder_place_now(Widget w, XtPointer clientData, XtPointer callData) {
+ struct io_file *index;
+ struct geo_location loc;
+ char input[1024];
+ char *temp_ptr;
+
+
+ /* find place and go there */
+ temp_ptr = XmTextFieldGetString(geocoder_zip_data);
+ xastir_snprintf(geocoder_zip_name,
+ sizeof(geocoder_zip_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(geocoder_state_data);
+ xastir_snprintf(geocoder_state_name,
+ sizeof(geocoder_state_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(geocoder_locality_data);
+ xastir_snprintf(geocoder_locality_name,
+ sizeof(geocoder_locality_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(geocoder_address_data);
+ xastir_snprintf(geocoder_address_name,
+ sizeof(geocoder_address_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(geocoder_map_file_data);
+ xastir_snprintf(geocoder_map_filename,
+ sizeof(geocoder_map_filename),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(geocoder_zip_name);
+ (void)remove_trailing_spaces(geocoder_state_name);
+ (void)remove_trailing_spaces(geocoder_locality_name);
+ (void)remove_trailing_spaces(geocoder_address_name);
+
+/*
+fprintf(stderr,"%s\n%s\n%s\n%s\n%s\n",
+ geocoder_zip_name,
+ geocoder_state_name,
+ geocoder_locality_name,
+ geocoder_address_name,
+ geocoder_map_filename);
+*/
+
+ index = io_open(geocoder_map_filename);
+
+ xastir_snprintf(input,
+ sizeof(input),
+ "%s %s%s%s %s",
+ geocoder_address_name,
+ geocoder_locality_name,
+ (strlen(geocoder_state_name) != 0)?",":"",
+ geocoder_state_name,
+ geocoder_zip_name);
+
+ if (debug_level & 1)
+ fprintf(stderr,"Searching for: %s\n", input);
+
+ if (geo_find(index,input,strlen(input),&loc)) {
+ long coord_lon, coord_lat;
+ char lat_str[20];
+ char long_str[20];
+ int lon, lat, lons, lats, tmp1;
+ char lond = 'E';
+ char latd = 'N';
+ double res, tmp;
+
+
+ if (loc.at.longitude < 0) {
+ loc.at.longitude = -loc.at.longitude;
+ lond = 'W';
+ }
+ if (loc.at.latitude < 0) {
+ loc.at.latitude = -loc.at.latitude;
+ latd = 'S';
+ }
+
+ lon = loc.at.longitude;
+ lat = loc.at.latitude;
+
+ res = loc.at.longitude - lon;
+ tmp = (res * 100);
+ tmp = tmp * 60 / 100;
+ tmp1 = tmp;
+ lon = (lon * 100) + tmp1;
+ lons = (tmp - tmp1) * 100;
+
+ res = loc.at.latitude - lat;
+ tmp = (res * 100);
+ tmp = tmp * 60 / 100;
+ tmp1 = tmp;
+ lat = (lat * 100) + tmp1;
+ lats = (tmp - tmp1) * 100;
+
+ xastir_snprintf(lat_str,
+ sizeof(lat_str),
+ "%d.%02d%c",
+ lat,
+ lats,
+ latd);
+
+ coord_lat = convert_lat_s2l(lat_str);
+
+ xastir_snprintf(long_str,
+ sizeof(long_str),
+ "%s%d.%02d%c",
+ (lon < 10000)?"0":"",
+ lon,
+ lons,
+ lond);
+
+ coord_lon = convert_lon_s2l(long_str);
+
+ destination_coord_lat = coord_lat;
+ destination_coord_lon = coord_lon;
+ mark_destination = 1;
+
+ popup_message_always( langcode("POPEM00029"), geocoder_address_name );
+ set_map_position(w, coord_lat, coord_lon);
+ }
+ else {
+ popup_message_always(langcode("POPEM00025"),geocoder_address_name);
+ }
+ Geocoder_place_destroy_shell(w, clientData, callData);
+}
+
+
+
+
+
+void Show_dest_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ show_destination_mark = atoi(which);
+ }
+ else {
+ show_destination_mark = 0;
+ }
+}
+
+
+
+
+
+void Geocoder_place(/*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, form, button_ok, button_cancel, sep,
+ zip, state, locality, address, map_file, show_dest_toggle;
+ Atom delw;
+
+ if (!geocoder_place_dialog) {
+
+begin_critical_section(&geocoder_place_dialog_lock, "geocoder_gui.c:Geocoder_place" );
+
+ // Find Address
+ geocoder_place_dialog = XtVaCreatePopupShell(langcode("PULDNMP029"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Geocoder_place pane",xmPanedWindowWidgetClass, geocoder_place_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Geocoder_place form",xmFormWidgetClass, pane,
+ XmNfractionBase, 2,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ // Address:
+ address = XtVaCreateManagedWidget(langcode("FEATURE007"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ geocoder_address_data = XtVaCreateManagedWidget("Geocoder_address_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 32,
+ XmNwidth, ((32*7)+2),
+ XmNmaxLength, 254,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, address,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // City:
+ locality = XtVaCreateManagedWidget(langcode("FEATURE008"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, address,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ geocoder_locality_data = XtVaCreateManagedWidget("Geocoder_address_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 32,
+ XmNwidth, ((32*7)+2),
+ XmNmaxLength, 254,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, address,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, locality,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // State/Province:
+ state = XtVaCreateManagedWidget(langcode("FEATURE002"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, locality,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ geocoder_state_data = XtVaCreateManagedWidget("Geocoder_state_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 4,
+ XmNwidth, ((4*7)+2),
+ XmNmaxLength, 2,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, locality,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, state,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Mark Destination
+ show_dest_toggle = XtVaCreateManagedWidget(langcode("FEATURE009"),xmToggleButtonGadgetClass, form,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, locality,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, geocoder_state_data,
+ XmNleftOffset, 20,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(show_dest_toggle,XmNvalueChangedCallback,Show_dest_toggle,"1");
+ if (show_destination_mark)
+ XmToggleButtonSetState(show_dest_toggle,TRUE,FALSE);
+
+
+ // Zip Code:
+ zip = XtVaCreateManagedWidget(langcode("FEATURE010"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, state,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ geocoder_zip_data = XtVaCreateManagedWidget("Geocoder_zip_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 12,
+ XmNwidth, ((12*7)+2),
+ XmNmaxLength, 10,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, state,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, zip,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Geocoding File:
+ map_file = XtVaCreateManagedWidget(langcode("FEATURE011"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, zip,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ geocoder_map_file_data = XtVaCreateManagedWidget("geocoder_map_file_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 40,
+ XmNwidth, ((40*7)+2),
+ XmNmaxLength, 254,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, zip,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, map_file,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ sep = XtVaCreateManagedWidget("Geocoder_place sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget,geocoder_map_file_data,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("WPUPLSP005"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNrightOffset, 5,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Geocoder_place_now, geocoder_place_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Geocoder_place_destroy_shell, geocoder_place_dialog);
+
+ XmTextFieldSetString(geocoder_zip_data,geocoder_zip_name);
+ XmTextFieldSetString(geocoder_state_data,geocoder_state_name);
+ XmTextFieldSetString(geocoder_locality_data,geocoder_locality_name);
+ XmTextFieldSetString(geocoder_address_data,geocoder_address_name);
+ XmTextFieldSetString(geocoder_map_file_data,geocoder_map_filename);
+
+ pos_dialog(geocoder_place_dialog);
+
+ delw = XmInternAtom(XtDisplay(geocoder_place_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(geocoder_place_dialog, delw, Geocoder_place_destroy_shell, (XtPointer)geocoder_place_dialog);
+
+ XtManageChild(form);
+ XtManageChild(pane);
+
+end_critical_section(&geocoder_place_dialog_lock, "geocoder_gui.c:Geocoder_place" );
+
+ XtPopup(geocoder_place_dialog,XtGrabNone);
+ fix_dialog_size(geocoder_place_dialog);
+
+ XmProcessTraversal(button_ok, XmTRAVERSE_CURRENT);
+
+ } else {
+ (void)XRaiseWindow(XtDisplay(geocoder_place_dialog), XtWindow(geocoder_place_dialog));
+ }
+}
+
+
diff --git a/src/gps.c b/src/gps.c
new file mode 100644
index 0000000..edc6cb2
--- /dev/null
+++ b/src/gps.c
@@ -0,0 +1,874 @@
+/*
+ * $Id: gps.c,v 1.57 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <Xm/XmAll.h>
+
+// The following files support setting the system time from the GPS
+#if TIME_WITH_SYS_TIME
+ // Define needed by some versions of Linux in order to define
+ // strptime()
+#ifndef __USE_XOPEN
+# define __USE_XOPEN
+#endif
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "gps.h"
+#include "main.h"
+#include "interface.h"
+#include "lang.h"
+#include "util.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+char gps_gprmc[MAX_GPS_STRING+1];
+char gps_gpgga[MAX_GPS_STRING+1];
+char gps_sats[4] = "";
+char gps_alt[8] = "";
+char gps_spd[10] = "";
+char gps_sunit[2] = "";
+char gps_cse[10] = "";
+int gps_valid = 0; // 0=invalid, 1=valid, 2=2D Fix, 3=3D Fix
+
+int gps_stop_now;
+
+
+
+
+
+// This function is destructive to its first parameter
+//
+// GPRMC,UTC-Time,status(A/V),lat,N/S,lon,E/W,SOG,COG,UTC-Date,Mag-Var,E/W[*CHK]
+// GPRMC,hhmmss[.sss],{A|V},ddmm.mm[mm],{N|S},dddmm.mm[mm],{E|W},[dd]d.d[ddddd],[dd]d.d[d],ddmmyy,[ddd.d],[{E|W}][,A|D|E|N|S][*CHK]
+//
+// The last field before the checksum is entirely optional, and in
+// fact first appeared in NMEA 2.3 (fairly recently). Most GPS's do
+// not currently put out that field. The field may be null or
+// nonexistent including the comma. Only "A" or "D" are considered
+// to be active and reliable fixes if this field is present.
+// Fix-Quality:
+// A: Autonomous
+// D: Differential
+// E: Estimated
+// N: Not Valid
+// S: Simulator
+//
+// $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62
+// $GPRMC,104748.821,A,4301.1492,N,08803.0374,W,0.085048,102.36,010605,,*1A
+// $GPRMC,104749.821,A,4301.1492,N,08803.0377,W,0.054215,74.60,010605,,*2D
+//
+int decode_gps_rmc( char *data,
+ char *long_pos,
+ int long_pos_length,
+ char *lat_pos,
+ int lat_pos_length,
+ char *spd,
+ char *unit,
+ int unit_length,
+ char *cse,
+ time_t *stim,
+ int *status) {
+
+ char *temp_ptr;
+ char *temp_ptr2;
+ char temp_data[MAX_LINE_SIZE+1]; // Big in case we get concatenated packets (it happens!)
+ char sampletime[7]; // We ignore fractional seconds
+ char long_pos_x[11];
+ char long_ew;
+ char lat_pos_y[10];
+ char lat_ns;
+ char speed[10];
+ char speed_unit;
+ char course[8];
+ char sampledate[7];
+
+#ifdef HAVE_STRPTIME
+ char sampledatime[15];
+ char *tzp;
+ char tzn[512];
+ struct tm stm;
+#endif // HAVE_STRPTIME
+
+
+// We should check for a minimum line length before parsing,
+// and check for end of input while tokenizing.
+
+ if ( (data == NULL) || (strlen(data) < 37) )
+ return(0); // Not enough data to parse position from.
+
+ if (strncmp(data,"$GPRMC,",7) != 0) // No GPRMC found
+ return(0);
+
+ if(strchr(data,',') == NULL) // No comma found
+ return(0);
+
+ (void)strtok(data,","); // get GPRMC and skip it
+ temp_ptr=strtok(NULL,","); // get time
+
+ if (temp_ptr == NULL) // No comma found
+ return(0);
+
+ xastir_snprintf(sampletime,
+ sizeof(sampletime),
+ "%s",
+ temp_ptr);
+
+ temp_ptr=strtok(NULL,","); // get fix status
+
+ if (temp_ptr == NULL) // No comma found
+ return(0);
+
+ if (temp_ptr[0] == 'A')
+ *status = 1;
+ else
+ *status = 0;
+
+ xastir_snprintf(temp_data,
+ sizeof(temp_data),
+ "%s",
+ temp_ptr);
+ temp_data[2] = '\0';
+
+ if (temp_data[0] != 'A') // V is a warning but we can get good data still ?
+ return(0); // Didn't find 'A' in the proper spot
+
+ temp_ptr=strtok(NULL,","); // get latitude
+
+ if (temp_ptr == NULL)
+ return(0); // Doesn't look like latitude
+
+ // Newer GPS'es appear not to zero-fill on the left. Check for
+ // the decimal point in all the possible places.
+ if (temp_ptr[1] != '.'
+ && temp_ptr[2] != '.'
+ && temp_ptr[3] != '.'
+ && temp_ptr[4] != '.') {
+ return(0); // Doesn't look like latitude
+ }
+
+// Note: Starlink Invicta shows "lllll.ll" format for latitude in
+// the GPRMC sentence, which would mean we'd need another term in
+// the above, and would need to terminate at [10] below (making sure
+// we extended the field another char as well to handle it). I'm
+// hoping it was a typo in the Starlink Invicta spec, as latitude
+// never requires three digits for degrees.
+
+ xastir_snprintf(lat_pos_y,
+ sizeof(lat_pos_y),
+ "%s",
+ temp_ptr);
+ lat_pos_y[9] = '\0';
+
+// Note that some GPS's put out latitude with extra precision, such as 4801.1234
+
+ // Check for comma char, replace with '\0'
+ temp_ptr2 = strstr(lat_pos_y, ",");
+ if (temp_ptr2)
+ temp_ptr2[0] = '\0';
+
+ temp_ptr=strtok(NULL,","); // get N-S
+
+ if (temp_ptr == NULL) // No comma found
+ return(0);
+
+ xastir_snprintf(temp_data,
+ sizeof(temp_data),
+ "%s",
+ temp_ptr);
+ temp_data[1] = '\0';
+
+ lat_ns=toupper((int)temp_data[0]);
+
+ if(lat_ns != 'N' && lat_ns != 'S')
+ return(0); // Doesn't look like latitude
+
+ temp_ptr=strtok(NULL,","); // get long
+
+ if (temp_ptr == NULL)
+ return(0); // Doesn't look like longitude
+
+ // Newer GPS'es appear not to zero-fill on the left. Check for
+ // the decimal point in all the possible places.
+ if (temp_ptr[1] != '.'
+ && temp_ptr[2] != '.'
+ && temp_ptr[3] != '.'
+ && temp_ptr[4] != '.'
+ && temp_ptr[5] != '.') {
+ return(0); // Doesn't look like longitude
+ }
+
+
+ xastir_snprintf(long_pos_x,
+ sizeof(long_pos_x),
+ "%s",
+ temp_ptr);
+ long_pos_x[10] = '\0';
+
+// Note that some GPS's put out longitude with extra precision, such as 12201.1234
+
+ // Check for comma char, replace with '\0'
+ temp_ptr2 = strstr(long_pos_x, ",");
+ if (temp_ptr2)
+ temp_ptr2[0] = '\0';
+
+ temp_ptr=strtok(NULL,","); // get E-W
+
+ if (temp_ptr == NULL) // No comma found
+ return(0);
+
+ xastir_snprintf(temp_data,
+ sizeof(temp_data),
+ "%s",
+ temp_ptr);
+ temp_data[1] = '\0';
+
+ long_ew=toupper((int)temp_data[0]);
+
+ if (long_ew != 'E' && long_ew != 'W')
+ return(0); // Doesn't look like longitude
+
+ temp_ptr=strtok(NULL,","); // Get speed
+
+ if (temp_ptr == 0) // No comma found
+ return(0);
+
+ xastir_snprintf(speed,
+ sizeof(speed),
+ "%s",
+ temp_ptr);
+ speed[9] = '\0';
+
+ speed_unit='K';
+ temp_ptr=strtok(NULL,","); // Get course
+
+ if (temp_ptr == NULL) // No comma found
+ return(0);
+
+ xastir_snprintf(course,
+ sizeof(course),
+ "%s",
+ temp_ptr);
+ course[7] = '\0';
+
+ temp_ptr=strtok(NULL,","); // get date of fix
+
+ if (temp_ptr == NULL) // No comma found
+ return(0);
+
+ xastir_snprintf(sampledate,
+ sizeof(sampledate),
+ "%s",
+ temp_ptr);
+ sampledate[6] = '\0';
+
+
+ // Data is good
+ xastir_snprintf(long_pos, long_pos_length, "%s%c", long_pos_x,long_ew);
+ xastir_snprintf(lat_pos, lat_pos_length, "%s%c", lat_pos_y, lat_ns);
+ xastir_snprintf(spd, 10, "%s", speed);
+ xastir_snprintf(unit, unit_length, "%c", speed_unit);
+ xastir_snprintf(cse, 10, "%s", course);
+
+#ifdef HAVE_STRPTIME
+ // Translate date/time into time_t GPS time is in UTC. First,
+ // save existing TZ Then set conversion to UTC, then set back to
+ // existing TZ.
+ tzp=getenv("TZ");
+ if ( tzp == NULL ) {
+ tzp = "";
+ }
+ xastir_snprintf(tzn,
+ sizeof(tzn),
+ "TZ=%s",
+ tzp);
+ putenv("TZ=UTC");
+ tzset();
+ xastir_snprintf(sampledatime,
+ sizeof(sampledatime),
+ "%s%s",
+ sampledate,
+ sampletime);
+ (void)strptime(sampledatime, "%d%m%y%H%M%S", &stm);
+ *stim=mktime(&stm);
+ putenv(tzn);
+ tzset();
+#endif // HAVE_STRPTIME
+
+ //fprintf(stderr,"Speed %s\n",spd);
+ return(1);
+}
+
+
+
+
+
+// This function is destructive to its first parameter
+//
+// GPGGA,UTC-Time,lat,N/S,long,E/W,GPS-Quality,nsat,HDOP,MSL-Meters,M,Geoidal-Meters,M,DGPS-Data-Age(seconds),DGPS-Ref-Station-ID[*CHK]
+// GPGGA,hhmmss[.sss],ddmm.mm[mm],{N|S},dddmm.mm[mm],{E|W},{0-8},dd,[d]d.d,[-dddd]d.d,M,[-ddd]d.d,M,[dddd.d],[dddd][*CHK]
+//
+// GPS-Quality:
+// 0: Invalid Fix
+// 1: GPS Fix
+// 2: DGPS Fix
+// 3: PPS Fix
+// 4: RTK Fix
+// 5: Float RTK Fix
+// 6: Estimated (dead-reckoning) Fix
+// 7: Manual Input Mode
+// 8: Simulation Mode
+//
+// $GPGGA,170834,4124.8963,N,08151.6838,W,1,05,1.5,280.2,M,-34.0,M,,,*75
+// $GPGGA,104438.833,4301.1439,N,08803.0338,W,1,05,1.8,185.8,M,-34.2,M,0.0,0000*40
+//
+int decode_gps_gga( char *data,
+ char *long_pos,
+ int long_pos_length,
+ char *lat_pos,
+ int lat_pos_length,
+ char *sats,
+ char *alt,
+ char *aunit,
+ int *status ) {
+
+ char *temp_ptr;
+ char *temp_ptr2;
+ char temp_data[MAX_LINE_SIZE+1]; // Big in case we get concatenated packets (it happens!)
+ char long_pos_x[11];
+ char long_ew;
+ char lat_pos_y[10];
+ char lat_ns;
+ char sats_visible[4];
+ char altitude[8];
+ char alt_unit;
+
+
+// We should check for a minimum line length before parsing,
+// and check for end of input while tokenizing.
+
+
+ if ( (data == NULL) || (strlen(data) < 35) ) // Not enough data to parse position from.
+ return(0);
+
+ if (strncmp(data,"$GPGGA,",7) != 0)
+ return(0);
+
+ if (strchr(data,',') == NULL)
+ return(0);
+
+ if (strtok(data,",") == NULL) // get GPGGA and skip it
+ return(0);
+
+ if(strtok(NULL,",") == NULL) // get time and skip it
+ return(0);
+
+ temp_ptr = strtok(NULL,","); // get latitude
+
+ if (temp_ptr == NULL)
+ return(0);
+
+ xastir_snprintf(lat_pos_y,
+ sizeof(lat_pos_y),
+ "%s",
+ temp_ptr);
+ lat_pos_y[9] = '\0';
+
+// Note that some GPS's put out latitude with extra precision, such as 4801.1234
+
+ // Check for comma char, replace with '\0'
+ temp_ptr2 = strstr(lat_pos_y, ",");
+ if (temp_ptr2)
+ temp_ptr2[0] = '\0';
+
+ temp_ptr = strtok(NULL,","); // get N-S
+
+ if (temp_ptr == NULL)
+ return(0);
+
+ xastir_snprintf(temp_data,
+ sizeof(temp_data),
+ "%s",
+ temp_ptr);
+ temp_data[1] = '\0';
+
+ lat_ns=toupper((int)temp_data[0]);
+
+ if(lat_ns != 'N' && lat_ns != 'S')
+ return(0);
+
+ temp_ptr = strtok(NULL,","); // get long
+
+ if(temp_ptr == NULL)
+ return(0);
+
+ xastir_snprintf(long_pos_x,
+ sizeof(long_pos_x),
+ "%s",
+ temp_ptr);
+ long_pos_x[10] = '\0';
+
+// Note that some GPS's put out longitude with extra precision, such as 12201.1234
+
+ // Check for comma char, replace with '\0'
+ temp_ptr2 = strstr(long_pos_x, ",");
+ if (temp_ptr2)
+ temp_ptr2[0] = '\0';
+
+ temp_ptr = strtok(NULL,","); // get E-W
+
+ if (temp_ptr == NULL)
+ return(0);
+
+ xastir_snprintf(temp_data,
+ sizeof(temp_data),
+ "%s",
+ temp_ptr);
+ temp_data[1] = '\0';
+
+ long_ew=toupper((int)temp_data[0]);
+
+ if (long_ew != 'E' && long_ew != 'W')
+ return(0);
+
+ temp_ptr = strtok(NULL,","); // get FIX Quality
+
+ if (temp_ptr == NULL)
+ return(0);
+
+ xastir_snprintf(temp_data,
+ sizeof(temp_data),
+ "%s",
+ temp_ptr);
+ temp_data[1] = '\0';
+
+ // '0' = bad fix, positive numbers = ok
+ if(temp_data[0] == '0')
+ return(0);
+
+ // Save the fix quality in "status"
+ *status = atoi(temp_data);
+
+ temp_ptr=strtok(NULL,","); // Get sats vis
+
+ if (temp_ptr == NULL)
+ return(0);
+
+ xastir_snprintf(sats_visible,
+ sizeof(sats_visible),
+ "%s",
+ temp_ptr);
+ sats_visible[2] = '\0';
+
+ temp_ptr=strtok(NULL,","); // get hoz dil
+
+ if (temp_ptr == NULL)
+ return(0);
+
+ temp_ptr=strtok(NULL,","); // Get altitude
+
+ if (temp_ptr == NULL)
+ return(0);
+
+ // Get altitude
+ xastir_snprintf(altitude,
+ sizeof(altitude),
+ "%s",
+ temp_ptr);
+ altitude[7] = '\0';
+
+ temp_ptr=strtok(NULL,","); // get UNIT
+
+ if (temp_ptr == NULL)
+ return(0);
+
+ // get UNIT
+ xastir_snprintf(temp_data,
+ sizeof(temp_data),
+ "%s",
+ temp_ptr);
+ temp_data[1] = '\0';
+
+ alt_unit=temp_data[0];
+
+ // Data is good
+ xastir_snprintf(long_pos, long_pos_length, "%s%c", long_pos_x, long_ew);
+ xastir_snprintf(lat_pos, lat_pos_length, "%s%c", lat_pos_y, lat_ns);
+ xastir_snprintf(sats, 4, "%s", sats_visible);
+ xastir_snprintf(alt, 8, "%s", altitude);
+ xastir_snprintf(aunit, 2, "%c", alt_unit);
+
+ return(1);
+}
+
+
+
+
+
+//
+// Note that the length of "gps_line_data" can be up to
+// MAX_DEVICE_BUFFER, which is currently set to 4096.
+//
+int gps_data_find(char *gps_line_data, int port) {
+
+ char long_pos[20],lat_pos[20],aunit[2];
+ time_t t;
+ char temp_str[MAX_GPS_STRING+1];
+ int have_valid_string = 0;
+#ifndef __CYGWIN__
+ struct timeval tv;
+ struct timezone tz;
+#endif // __CYGWIN__
+
+
+
+ if (strncmp(gps_line_data,"$GPRMC,",7)==0) {
+
+ if (debug_level & 128) {
+ char filtered_data[MAX_LINE_SIZE+1];
+
+ xastir_snprintf(filtered_data,
+ sizeof(filtered_data),
+ "%s",
+ gps_line_data);
+
+ makePrintable(filtered_data);
+ fprintf(stderr,"Got RMC %s\n", filtered_data);
+ }
+
+ if (debug_level & 128) {
+ // Got GPS RMC String
+ statusline(langcode("BBARSTA015"),0);
+ }
+
+ xastir_snprintf(gps_gprmc,
+ sizeof(gps_gprmc),
+ "%s",
+ gps_line_data);
+
+ xastir_snprintf(temp_str, sizeof(temp_str), "%s", gps_gprmc);
+ // decode_gps_rmc is destructive to its first parameter
+ if (decode_gps_rmc( temp_str,
+ long_pos,
+ sizeof(long_pos),
+ lat_pos,
+ sizeof(lat_pos),
+ gps_spd,
+ gps_sunit,
+ sizeof(gps_sunit),
+ gps_cse,
+ &t,
+ &gps_valid ) == 1) { // mod station data
+ // got GPS data
+ have_valid_string++;
+ if (debug_level & 128)
+ fprintf(stderr,"RMC <%s> <%s><%s> %c <%s>\n",
+ long_pos,lat_pos,gps_spd,gps_sunit[0],gps_cse);
+
+ if (debug_level & 128) {
+ fprintf(stderr,"Checking for Time Set on %d (%d)\n",
+ port, devices[port].set_time);
+ }
+
+// Don't set the time if it's a Cygwin system. Causes problems with
+// date, plus time can be an hour off if daylight savings time is
+// enabled on Windows.
+//
+#ifndef __CYGWIN__
+ if (devices[port].set_time) {
+ tv.tv_sec=t;
+ tv.tv_usec=0;
+ tz.tz_minuteswest=0;
+ tz.tz_dsttime=0;
+
+ if (debug_level & 128) {
+ fprintf(stderr,"Setting Time %ld EUID: %d, RUID: %d\n",
+ (long)t, (int)getuid(), (int)getuid());
+ }
+
+#ifdef HAVE_SETTIMEOFDAY
+
+ENABLE_SETUID_PRIVILEGE;
+ settimeofday(&tv, &tz);
+DISABLE_SETUID_PRIVILEGE;
+
+#endif // HAVE_SETTIMEOFDAY
+
+ }
+
+#endif // __CYGWIN__
+
+ }
+ }
+ else {
+ if (debug_level & 128) {
+ int i;
+ fprintf(stderr,"Not $GPRMC: ");
+ for (i = 0; i<7; i++)
+ fprintf(stderr,"%c", gps_line_data[i]);
+ fprintf(stderr,"\n");
+ }
+ }
+
+ if (strncmp(gps_line_data,"$GPGGA,",7)==0) {
+
+ if (debug_level & 128) {
+ char filtered_data[MAX_LINE_SIZE+1];
+
+ xastir_snprintf(filtered_data,
+ sizeof(filtered_data),
+ "%s",
+ gps_line_data);
+
+ makePrintable(filtered_data);
+ fprintf(stderr,"Got GGA %s\n", filtered_data);
+ }
+
+ if (debug_level & 128) {
+ // Got GPS GGA String
+ statusline(langcode("BBARSTA016"),0);
+ }
+
+ xastir_snprintf(gps_gpgga,
+ sizeof(gps_gpgga),
+ "%s",
+ gps_line_data);
+
+ xastir_snprintf(temp_str, sizeof(temp_str), "%s", gps_gpgga);
+
+ // decode_gps_gga is destructive to its first parameter
+ if ( decode_gps_gga( temp_str,
+ long_pos,
+ sizeof(long_pos),
+ lat_pos,
+ sizeof(lat_pos),
+ gps_sats,
+ gps_alt,
+ aunit,
+ &gps_valid ) == 1) { // mod station data
+ // got GPS data
+ have_valid_string++;
+ if (debug_level & 128)
+ fprintf(stderr,"GGA <%s> <%s> <%s> <%s> %c\n",
+ long_pos,lat_pos,gps_sats,gps_alt,aunit[0]);
+ }
+ }
+ else {
+ if (debug_level & 128) {
+ int i;
+ fprintf(stderr,"Not $GPGGA: ");
+ for (i = 0; i<7; i++)
+ fprintf(stderr,"%c",gps_line_data[i]);
+ fprintf(stderr,"\n");
+ }
+ }
+
+
+ if (have_valid_string) {
+
+ if (debug_level & 128) {
+ statusline(langcode("BBARSTA037"),0);
+ }
+
+ // Go update my screen position
+ my_station_gps_change(long_pos,lat_pos,gps_cse,gps_spd,
+ gps_sunit[0],gps_alt,gps_sats);
+
+ // gps_stop_now is how we tell main.c that we've got a valid GPS string.
+ // Only useful for HSP mode?
+ if (!gps_stop_now)
+ gps_stop_now=1;
+
+ // If HSP port, shutdown gps for timed interval
+ if (port_data[port].device_type == DEVICE_SERIAL_TNC_HSP_GPS) {
+ // return dtr to normal
+ port_dtr(port,0);
+ }
+ }
+ return(have_valid_string);
+}
+
+
+
+
+
+static char checksum[3];
+
+
+
+
+
+// Function to compute checksums for NMEA sentences
+//
+// Input: "$............*"
+// Output: Two character string containing the checksum
+//
+// Checksum is computed from the '$' to the '*', but not including
+// these two characters. It is an 8-bit Xor of the characters
+// specified, encoded in hexadecimal format.
+//
+char *nmea_checksum(char *nmea_sentence) {
+ int i;
+ int sum = 0;
+ int right;
+ int left;
+ char convert[17] = "0123456789ABCDEF";
+
+
+ for (i = 1; i < ((int)strlen(nmea_sentence) - 1); i++) {
+ sum = sum ^ nmea_sentence[i];
+ }
+
+ right = sum % 16;
+ left = (sum / 16) % 16;
+
+ xastir_snprintf(checksum, sizeof(checksum), "%c%c",
+ convert[left],
+ convert[right]);
+
+ return(checksum);
+}
+
+
+
+
+
+
+// Function which will send an NMEA sentence to a Garmin GPS which
+// will create a waypoint if the Garmin is set to NMEA-in/NMEA-out
+// mode. The sentence looks like this:
+//
+// $GPWPL,4807.038,N,01131.000,E,WPTNME*31
+//
+// $GPWPL,4849.65,N,06428.53,W,0001*54
+// $GPWPL,4849.70,N,06428.50,W,0002*50
+//
+// 4807.038,N Latitude
+// 01131.000,E Longitude
+// WPTNME Waypoint Name (stick to 6 chars for compatibility?)
+// *31 Checksum, always begins with '*'
+//
+//
+// Future implementation ideas:
+//
+// Create linked list of waypoints/location.
+// Use the list to prevent multiple writes of the same waypoint if
+// nothing has changed.
+//
+// Use the list to check distance of previously-written waypoints.
+// If we're out of range, delete the waypoint and remove it from the
+// list.
+//
+// Perhaps write the list to disk also. As we shut down, delete the
+// waypoints (self-cleaning). As we come up, load them in again?
+// We could also just continue cleaning out waypoints that are
+// out-of-range since the last time we ran the program. That's
+// probably a better solution.
+//
+void create_garmin_waypoint(long latitude,long longitude,char *call_sign) {
+ char short_callsign[10];
+ char lat_string[15];
+ char long_string[15];
+ char lat_char;
+ char long_char;
+ int i,j,len;
+ char out_string[80];
+ char out_string2[80];
+
+
+ convert_lat_l2s(latitude,
+ lat_string,
+ sizeof(lat_string),
+ CONVERT_HP_NOSP);
+ lat_char = lat_string[strlen(lat_string) - 1];
+ lat_string[strlen(lat_string) - 1] = '\0';
+
+ convert_lon_l2s(longitude,
+ long_string,
+ sizeof(long_string),
+ CONVERT_HP_NOSP);
+ long_char = long_string[strlen(long_string) - 1];
+ long_string[strlen(long_string) - 1] = '\0';
+
+ len = strlen(call_sign);
+ if (len > 9)
+ len = 9;
+
+ j = 0;
+ for (i = 0; i <= len; i++) { // Copy the '\0' as well
+ if (call_sign[i] != '-') { // We don't want the dash
+ short_callsign[j++] = call_sign[i];
+ }
+ }
+ short_callsign[6] = '\0'; // Truncate at 6 chars
+
+ // Convert to upper case. Garmin's don't seem to like lower
+ // case waypoint names
+ to_upper(short_callsign);
+
+ //fprintf(stderr,"Creating waypoint for %s:%s\n",call_sign,short_callsign);
+
+ xastir_snprintf(out_string, sizeof(out_string),
+ "$GPWPL,%s,%c,%s,%c,%s*",
+ lat_string,
+ lat_char,
+ long_string,
+ long_char,
+ short_callsign);
+
+ nmea_checksum(out_string);
+
+ xastir_snprintf(out_string2,
+ sizeof(out_string2),
+ "%s%s",
+ out_string,
+ checksum);
+
+ output_waypoint_data(out_string2);
+
+ //fprintf(stderr,"%s\n",out_string2);
+}
+
+
diff --git a/src/gps.h b/src/gps.h
new file mode 100644
index 0000000..bfbd550
--- /dev/null
+++ b/src/gps.h
@@ -0,0 +1,44 @@
+/*
+ * $Id: gps.h,v 1.16 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifndef __XASTIR_GPS_H
+#define __XASTIR_GPS_H
+
+#include "xastir.h"
+
+#define MAX_GPS_STRING 300
+
+extern char gps_sats[4];
+extern int gps_valid;
+
+extern int gps_stop_now;
+
+extern int gps_data_find(char *gps_line_data, int port);
+
+extern void create_garmin_waypoint(long latitude,long longitude,char *call_sign);
+
+#endif // __XASTIR_GPS_H
+
+
diff --git a/src/hashtable.c b/src/hashtable.c
new file mode 100644
index 0000000..9244565
--- /dev/null
+++ b/src/hashtable.c
@@ -0,0 +1,277 @@
+
+
+// $Id: hashtable.c,v 1.12 2012/08/25 16:38:29 tvrusso Exp $
+
+
+/* Copyright (C) 2004 Christopher Clark <firstname.lastname at cl.cam.ac.uk> */
+/* Portions Copyright (C) 2004-2012 The Xastir Group */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "hashtable.h"
+#include "hashtable_private.h"
+
+// Must be last include file
+#include "leak_detection.h" /* defines GC_MALLOC/GC_FREE */
+
+
+
+/*
+Credit for primes table: Aaron Krowne
+ http://br.endernet.org/~akrowne/
+ http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
+*/
+static const unsigned int primes[] = {
+53, 97, 193, 389,
+769, 1543, 3079, 6151,
+12289, 24593, 49157, 98317,
+196613, 393241, 786433, 1572869,
+3145739, 6291469, 12582917, 25165843,
+50331653, 100663319, 201326611, 402653189,
+805306457, 1610612741
+};
+const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
+const float max_load_factor = 0.65;
+
+/*****************************************************************************/
+struct hashtable *
+create_hashtable(unsigned int minsize,
+ unsigned int (*hashf) (void*),
+ int (*eqf) (void*,void*))
+{
+ struct hashtable *h;
+ unsigned int pindex, size = primes[0];
+ /* Check requested hashtable isn't too large */
+ if (minsize > (1u << 30)) return NULL;
+ /* Enforce size as prime */
+ for (pindex=0; pindex < prime_table_length; pindex++) {
+ if (primes[pindex] > minsize) { size = primes[pindex]; break; }
+ }
+ h = (struct hashtable *)malloc(sizeof(struct hashtable));
+ if (NULL == h) return NULL; /*oom*/
+ h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
+ if (NULL == h->table) { free(h); return NULL; } /*oom*/
+ memset(h->table, 0, size * sizeof(struct entry *));
+ h->tablelength = size;
+ h->primeindex = pindex;
+ h->entrycount = 0;
+ h->hashfn = hashf;
+ h->eqfn = eqf;
+ h->loadlimit = (unsigned int) ceil(size * max_load_factor);
+ return h;
+}
+
+/*****************************************************************************/
+unsigned int
+hash(struct hashtable *h, void *k)
+{
+ /* Aim to protect against poor hash functions by adding logic here
+ * - logic taken from java 1.4 hashtable source */
+ unsigned int i = h->hashfn(k);
+ i += ~(i << 9);
+ i ^= ((i >> 14) | (i << 18)); /* >>> */
+ i += (i << 4);
+ i ^= ((i >> 10) | (i << 22)); /* >>> */
+ return i;
+}
+
+/*****************************************************************************/
+static int
+hashtable_expand(struct hashtable *h)
+{
+ /* Double the size of the table to accomodate more entries */
+ struct entry **newtable;
+ struct entry *e;
+ struct entry **pE;
+ unsigned int newsize, i, index;
+ /* Check we're not hitting max capacity */
+ if (h->primeindex == (prime_table_length - 1)) return 0;
+ newsize = primes[++(h->primeindex)];
+
+ newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
+ if (NULL != newtable)
+ {
+ memset(newtable, 0, newsize * sizeof(struct entry *));
+ /* This algorithm is not 'stable'. ie. it reverses the list
+ * when it transfers entries between the tables */
+ for (i = 0; i < h->tablelength; i++) {
+ while (NULL != (e = h->table[i])) {
+ h->table[i] = e->next;
+ index = indexFor(newsize,e->h);
+ e->next = newtable[index];
+ newtable[index] = e;
+ }
+ }
+ free(h->table);
+ h->table = newtable;
+ }
+ /* Plan B: realloc instead */
+ else
+ {
+ newtable = (struct entry **)
+ realloc(h->table, newsize * sizeof(struct entry *));
+ if (NULL == newtable) { (h->primeindex)--; return 0; }
+ h->table = newtable;
+ memset(newtable[h->tablelength], 0, newsize - h->tablelength);
+ for (i = 0; i < h->tablelength; i++) {
+ for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
+ index = indexFor(newsize,e->h);
+ if (index == i)
+ {
+ pE = &(e->next);
+ }
+ else
+ {
+ *pE = e->next;
+ e->next = newtable[index];
+ newtable[index] = e;
+ }
+ }
+ }
+ }
+ h->tablelength = newsize;
+ h->loadlimit = (unsigned int) ceil(newsize * max_load_factor);
+ return -1;
+}
+
+/*****************************************************************************/
+unsigned int
+hashtable_count(struct hashtable *h)
+{
+ return h->entrycount;
+}
+
+/*****************************************************************************/
+int
+hashtable_insert(struct hashtable *h, void *k, void *v)
+{
+ /* This method allows duplicate keys - but they shouldn't be used */
+ unsigned int index;
+ struct entry *e;
+ if (++(h->entrycount) > h->loadlimit)
+ {
+ /* Ignore the return value. If expand fails, we should
+ * still try cramming just this value into the existing table
+ * -- we may not have memory for a larger table, but one more
+ * element may be ok. Next time we insert, we'll try expanding again.*/
+ hashtable_expand(h);
+ }
+ e = (struct entry *)malloc(sizeof(struct entry));
+ if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
+ e->h = hash(h,k);
+ index = indexFor(h->tablelength,e->h);
+ e->k = k;
+ e->v = v;
+ e->next = h->table[index];
+ h->table[index] = e;
+ return -1;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_search(struct hashtable *h, void *k)
+{
+ struct entry *e;
+ unsigned int hashvalue, index;
+ hashvalue = hash(h,k);
+ index = indexFor(h->tablelength,hashvalue);
+ e = h->table[index];
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
+ e = e->next;
+ }
+ return NULL;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_remove(struct hashtable *h, void *k)
+{
+ /* TODO: consider compacting the table when the load factor drops enough,
+ * or provide a 'compact' method. */
+
+ struct entry *e;
+ struct entry **pE;
+ void *v;
+ unsigned int hashvalue, index;
+
+ hashvalue = hash(h,k);
+ index = indexFor(h->tablelength,hash(h,k));
+ pE = &(h->table[index]);
+ e = *pE;
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+ {
+ *pE = e->next;
+ h->entrycount--;
+ v = e->v;
+ freekey(e->k);
+ free(e);
+ return v;
+ }
+ pE = &(e->next);
+ e = e->next;
+ }
+ return NULL;
+}
+
+/*****************************************************************************/
+/* destroy */
+void
+hashtable_destroy(struct hashtable *h, int free_values)
+{
+ unsigned int i;
+ struct entry *e, *f;
+ struct entry **table = h->table;
+ if (free_values)
+ {
+ for (i = 0; i < h->tablelength; i++)
+ {
+ e = table[i];
+ while (NULL != e)
+ { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
+ }
+ }
+ else
+ {
+ for (i = 0; i < h->tablelength; i++)
+ {
+ e = table[i];
+ while (NULL != e)
+ { f = e; e = e->next; freekey(f->k); free(f); }
+ }
+ }
+ free(h->table);
+ free(h);
+}
+
+/*
+ * Copyright (C) 2002 Christopher Clark <firstname.lastname at cl.cam.ac.uk>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * */
+
+
diff --git a/src/hashtable.h b/src/hashtable.h
new file mode 100644
index 0000000..73abcfa
--- /dev/null
+++ b/src/hashtable.h
@@ -0,0 +1,194 @@
+
+
+// $Id: hashtable.h,v 1.8 2012/11/01 18:57:19 we7u Exp $
+
+
+/* Copyright (C) 2002 Christopher Clark <firstname.lastname at cl.cam.ac.uk> */
+// Portions Copyright (C) 2004-2012 The Xastir Group
+
+
+
+#ifndef __HASHTABLE_CWC22_H__
+#define __HASHTABLE_CWC22_H__
+
+struct hashtable;
+
+/* Example of use:
+ *
+ * struct hashtable *h;
+ * struct some_key *k;
+ * struct some_value *v;
+ *
+ * static unsigned int hash_from_key_fn( void *k );
+ * static int keys_equal_fn ( void *key1, void *key2 );
+ *
+ * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
+ * k = (struct some_key *) malloc(sizeof(struct some_key));
+ * v = (struct some_value *) malloc(sizeof(struct some_value));
+ *
+ * (initialise k and v to suitable values)
+ *
+ * if (! hashtable_insert(h,k,v) )
+ * { exit(-1); }
+ *
+ * if (NULL == (found = hashtable_search(h,k) ))
+ * { printf("not found!"); }
+ *
+ * if (NULL == (found = hashtable_remove(h,k) ))
+ * { printf("Not found\n"); }
+ *
+ */
+
+/* Macros may be used to define type-safe(r) hashtable access functions, with
+ * methods specialized to take known key and value types as parameters.
+ *
+ * Example:
+ *
+ * Insert this at the start of your file:
+ *
+ * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
+ *
+ * This defines the functions 'insert_some', 'search_some' and 'remove_some'.
+ * These operate just like hashtable_insert etc., with the same parameters,
+ * but their function signatures have 'struct some_key *' rather than
+ * 'void *', and hence can generate compile time errors if your program is
+ * supplying incorrect data as a key (and similarly for value).
+ *
+ * Note that the hash and key equality functions passed to create_hashtable
+ * still take 'void *' parameters instead of 'some key *'. This shouldn't be
+ * a difficult issue as they're only defined and passed once, and the other
+ * functions will ensure that only valid keys are supplied to them.
+ *
+ * The cost for this checking is increased code size and runtime overhead
+ * - if performance is important, it may be worth switching back to the
+ * unsafe methods once your program has been debugged with the safe methods.
+ * This just requires switching to some simple alternative defines - eg:
+ * #define insert_some hashtable_insert
+ *
+ */
+
+/*****************************************************************************
+ * create_hashtable
+
+ * @name create_hashtable
+ * @param minsize minimum initial size of hashtable
+ * @param hashfunction function for hashing keys
+ * @param key_eq_fn function for determining key equality
+ * @return newly created hashtable or NULL on failure
+ */
+
+struct hashtable *
+create_hashtable(unsigned int minsize,
+ unsigned int (*hashfunction) (void*),
+ int (*key_eq_fn) (void*,void*));
+
+/*****************************************************************************
+ * hashtable_insert
+
+ * @name hashtable_insert
+ * @param h the hashtable to insert into
+ * @param k the key - hashtable claims ownership and will free on removal
+ * @param v the value - does not claim ownership
+ * @return non-zero for successful insertion
+ *
+ * This function will cause the table to expand if the insertion would take
+ * the ratio of entries to table size over the maximum load factor.
+ *
+ * This function does not check for repeated insertions with a duplicate key.
+ * The value returned when using a duplicate key is undefined -- when
+ * the hashtable changes size, the order of retrieval of duplicate key
+ * entries is reversed.
+ * If in doubt, remove before insert.
+ */
+
+int
+hashtable_insert(struct hashtable *h, void *k, void *v);
+
+#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
+int fnname (struct hashtable *h, keytype *k, valuetype *v) \
+{ \
+ return hashtable_insert(h,k,v); \
+}
+
+/*****************************************************************************
+ * hashtable_search
+
+ * @name hashtable_search
+ * @param h the hashtable to search
+ * @param k the key to search for - does not claim ownership
+ * @return the value associated with the key, or NULL if none found
+ */
+
+void *
+hashtable_search(struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
+valuetype * fnname (struct hashtable *h, keytype *k) \
+{ \
+ return (valuetype *) (hashtable_search(h,k)); \
+}
+
+/*****************************************************************************
+ * hashtable_remove
+
+ * @name hashtable_remove
+ * @param h the hashtable to remove the item from
+ * @param k the key to search for - does not claim ownership
+ * @return the value associated with the key, or NULL if none found
+ */
+
+void * /* returns value */
+hashtable_remove(struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
+valuetype * fnname (struct hashtable *h, keytype *k) \
+{ \
+ return (valuetype *) (hashtable_remove(h,k)); \
+}
+
+
+/*****************************************************************************
+ * hashtable_count
+
+ * @name hashtable_count
+ * @param h the hashtable
+ * @return the number of items stored in the hashtable
+ */
+unsigned int
+hashtable_count(struct hashtable *h);
+
+
+/*****************************************************************************
+ * hashtable_destroy
+
+ * @name hashtable_destroy
+ * @param h the hashtable
+ * @param free_values whether to call 'free' on the remaining values
+ */
+
+void
+hashtable_destroy(struct hashtable *h, int free_values);
+
+#endif /* __HASHTABLE_CWC22_H__ */
+
+/*
+ * Copyright (C) 2002 Christopher Clark <firstname.lastname at cl.cam.ac.uk>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * */
+
+
diff --git a/src/hashtable_itr.c b/src/hashtable_itr.c
new file mode 100644
index 0000000..74a12a7
--- /dev/null
+++ b/src/hashtable_itr.c
@@ -0,0 +1,212 @@
+
+
+// $Id: hashtable_itr.c,v 1.14 2012/08/25 16:38:29 tvrusso Exp $
+
+
+/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname at cl.cam.ac.uk> */
+/* Portions Copyright (C) 2004-2012 The Xastir Group */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include <stdlib.h> /* defines NULL */
+#include <stdio.h>
+//#include <string.h>
+//#include <math.h>
+
+#include "hashtable.h"
+#include "hashtable_private.h"
+#include "hashtable_itr.h"
+
+// Must be last include file
+#include "leak_detection.h" /* defines GC_MALLOC/GC_FREE */
+
+
+
+
+
+/*****************************************************************************/
+/* hashtable_iterator - iterator constructor */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h)
+{
+ unsigned int i, tablelength;
+ struct hashtable_itr *itr = (struct hashtable_itr *)
+ malloc(sizeof(struct hashtable_itr));
+ if (NULL == itr) return NULL;
+ itr->h = h;
+ itr->e = NULL;
+ itr->parent = NULL;
+ tablelength = h->tablelength;
+ itr->index = tablelength;
+ if (0 == h->entrycount) return itr;
+
+ for (i = 0; i < tablelength; i++)
+ {
+ if (NULL != h->table[i])
+ {
+ itr->e = h->table[i];
+ itr->index = i;
+ break;
+ }
+ }
+ return itr;
+}
+
+/*****************************************************************************/
+/* key - return the key of the (key,value) pair at the current position */
+/* value - return the value of the (key,value) pair at the current position */
+
+void *
+hashtable_iterator_key(struct hashtable_itr *i)
+{
+ if (!i)
+ return NULL;
+ if (i->e)
+ return i->e->k;
+ else
+ return NULL;
+}
+
+void *
+hashtable_iterator_value(struct hashtable_itr *i)
+{
+ if (!i)
+ return NULL;
+ if (i->e) {
+ return i->e->v;
+ } else {
+ return NULL;
+ }
+
+}
+
+/*****************************************************************************/
+/* advance - advance the iterator to the next element
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr)
+{
+ unsigned int j,tablelength;
+ struct entry **table;
+ struct entry *next;
+ if (NULL == itr->e) return 0; /* stupidity check */
+
+ next = itr->e->next;
+ if (NULL != next)
+ {
+ itr->parent = itr->e;
+ itr->e = next;
+ return -1;
+ }
+ tablelength = itr->h->tablelength;
+ itr->parent = NULL;
+ if (tablelength <= (j = ++(itr->index)))
+ {
+ itr->e = NULL;
+ return 0;
+ }
+ table = itr->h->table;
+ while (NULL == (next = table[j]))
+ {
+ if (++j >= tablelength)
+ {
+ itr->index = tablelength;
+ itr->e = NULL;
+ return 0;
+ }
+ }
+ itr->index = j;
+ itr->e = next;
+ return -1;
+}
+
+/*****************************************************************************/
+/* remove - remove the entry at the current iterator position
+ * and advance the iterator, if there is a successive
+ * element.
+ * If you want the value, read it before you remove:
+ * beware memory leaks if you don't.
+ * Returns zero if end of iteration. */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr)
+{
+ struct entry *remember_e, *remember_parent;
+ int ret;
+
+ /* Do the removal */
+ if (NULL == (itr->parent))
+ {
+ /* element is head of a chain */
+ itr->h->table[itr->index] = itr->e->next;
+ } else {
+ /* element is mid-chain */
+ itr->parent->next = itr->e->next;
+ }
+ /* itr->e is now outside the hashtable */
+ remember_e = itr->e;
+ itr->h->entrycount--;
+ freekey(remember_e->k);
+
+ /* Advance the iterator, correcting the parent */
+ remember_parent = itr->parent;
+ ret = hashtable_iterator_advance(itr);
+ if (itr->parent == remember_e) { itr->parent = remember_parent; }
+ free(remember_e);
+ return ret;
+}
+
+/*****************************************************************************/
+int /* returns zero if not found */
+hashtable_iterator_search(struct hashtable_itr *itr,
+ struct hashtable *h, void *k)
+{
+ struct entry *e, *parent;
+ unsigned int hashvalue, index;
+
+ hashvalue = hash(h,k);
+ index = indexFor(h->tablelength,hashvalue);
+
+ e = h->table[index];
+ parent = NULL;
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+ {
+ itr->index = index;
+ itr->e = e;
+ itr->parent = parent;
+ itr->h = h;
+ return -1;
+ }
+ parent = e;
+ e = e->next;
+ }
+ return 0;
+}
+
+
+/*
+ * Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname at cl.cam.ac.uk>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * */
+
+
diff --git a/src/hashtable_itr.h b/src/hashtable_itr.h
new file mode 100644
index 0000000..6fb46d2
--- /dev/null
+++ b/src/hashtable_itr.h
@@ -0,0 +1,123 @@
+
+
+// $Id: hashtable_itr.h,v 1.9 2012/11/01 18:57:19 we7u Exp $
+
+
+/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname at cl.cam.ac.uk> */
+// Portions Copyright (C) 2004-2012 The Xastir Group
+
+
+#ifndef __HASHTABLE_ITR_CWC22__
+#define __HASHTABLE_ITR_CWC22__
+#include "hashtable.h"
+#include "hashtable_private.h" /* needed to enable inlining */
+
+/*****************************************************************************/
+/* This struct is only concrete here to allow the inlining of two of the
+ * accessor functions. */
+struct hashtable_itr
+{
+ struct hashtable *h;
+ struct entry *e;
+ struct entry *parent;
+ unsigned int index;
+};
+
+
+/*****************************************************************************/
+/* hashtable_iterator
+ */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h);
+
+#if 0
+// BZZZZT! it is very, very wrong to be inlining this this way.
+// If one calls hashtable_iterator on a hash table from which everything
+// has been deleted, the iterator has a null for i->e.
+// It is not good to require the caller to check the internals of the iterator
+// structure just to be sure there are no null pointers inside.
+// For whatever reason, these are defined again in the hashtable_iterator.c
+// file, not inlined. I have modified the ones in hashtable_iterator so they
+// actually check for nulls and don't try to dereference them.
+/*****************************************************************************/
+/* hashtable_iterator_key
+ * - return the value of the (key,value) pair at the current position */
+
+extern inline void *
+hashtable_iterator_key(struct hashtable_itr *i)
+{
+ return i->e->k;
+}
+
+/*****************************************************************************/
+/* value - return the value of the (key,value) pair at the current position */
+
+extern inline void *
+hashtable_iterator_value(struct hashtable_itr *i)
+{
+ return i->e->v;
+}
+#else
+// SO instead of inlining, just declare. No need to be "extern"
+// The ones in the .c file check their arguments and return nulls if they
+// can't comply with the request. Much nicer for the calling routine to
+// check a return value than to monkey with the internals of the struct.
+void * hashtable_iterator_key(struct hashtable_itr *i);
+void * hashtable_iterator_value(struct hashtable_itr *i);
+#endif
+
+/*****************************************************************************/
+/* advance - advance the iterator to the next element
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* remove - remove current element and advance the iterator to the next element
+ * NB: if you need the value to free it, read it before
+ * removing. ie: beware memory leaks!
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* search - overwrite the supplied iterator, to point to the entry
+ * matching the supplied key.
+ h points to the hashtable to be searched.
+ * returns zero if not found. */
+int
+hashtable_iterator_search(struct hashtable_itr *itr,
+ struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \
+int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \
+{ \
+ return (hashtable_iterator_search(i,h,k)); \
+}
+
+
+
+#endif /* __HASHTABLE_ITR_CWC22__*/
+
+/*
+ * Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname at cl.cam.ac.uk>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * */
+
+
diff --git a/src/hashtable_private.h b/src/hashtable_private.h
new file mode 100644
index 0000000..208c155
--- /dev/null
+++ b/src/hashtable_private.h
@@ -0,0 +1,80 @@
+
+
+// $Id: hashtable_private.h,v 1.11 2012/11/01 18:57:19 we7u Exp $
+
+
+/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname at cl.cam.ac.uk> */
+/* Portions Copyright (C) 2004-2012 The Xastir Group */
+
+
+#ifndef __HASHTABLE_PRIVATE_CWC22_H__
+#define __HASHTABLE_PRIVATE_CWC22_H__
+
+#include "hashtable.h"
+
+
+/*****************************************************************************/
+struct entry
+{
+ void *k, *v;
+ unsigned int h;
+ struct entry *next;
+};
+
+struct hashtable {
+ unsigned int tablelength;
+ struct entry **table;
+ unsigned int entrycount;
+ unsigned int loadlimit;
+ unsigned int primeindex;
+ unsigned int (*hashfn) (void *k);
+ int (*eqfn) (void *k1, void *k2);
+};
+
+/*****************************************************************************/
+unsigned int
+hash(struct hashtable *h, void *k);
+
+/*****************************************************************************/
+/* indexFor */
+static inline unsigned int
+indexFor(unsigned int tablelength, unsigned int hashvalue) {
+ return (hashvalue % tablelength);
+}
+
+/* Only works if tablelength == 2^N */
+/*static inline unsigned int
+indexFor(unsigned int tablelength, unsigned int hashvalue)
+{
+ return (hashvalue & (tablelength - 1u));
+}
+*/
+
+/*****************************************************************************/
+#define freekey(X) free(X)
+/*define freekey(X) ; */
+
+
+/*****************************************************************************/
+
+#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/
+
+/*
+ * Copyright (C) 2002 Christopher Clark <firstname.lastname at cl.cam.ac.uk>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * */
+
+
diff --git a/src/hostname.c b/src/hostname.c
new file mode 100644
index 0000000..4812fe0
--- /dev/null
+++ b/src/hostname.c
@@ -0,0 +1,347 @@
+/*
+ * $Id: hostname.c,v 1.32 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <Xm/XmAll.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <signal.h>
+
+//Needed for Solaris 2.5
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <setjmp.h>
+#include <netinet/in.h>
+#include <sys/wait.h>
+
+#include "xastir.h"
+#include "main.h"
+#include "lang.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+#ifndef HAVE_SIGHANDLER_T
+ #ifdef HAVE_SIG_T
+ typedef sig_t sighandler_t;
+ #else
+ typedef void (*sighandler_t)(int);
+ #endif
+#endif
+
+
+#ifndef __LCLINT__
+ #ifndef HAVE_SIGJMP_BUF
+ jmp_buf ret_place;
+ #else // HAVE_SIGJMP_BUF
+ static sigjmp_buf ret_place; /* Jump address if alarm */
+ #endif // HAVE_SIGJMP_BUF
+#endif // __LCLINT__
+
+
+
+
+
+/*************************************************************************/
+/* Time out on connect */
+/* In case there is a problem in getting the hostname or connecting */
+/* (see setjmp below). */
+/*************************************************************************/
+
+static void host_time_out( /*@unused@*/ int sig) {
+#ifndef __LCLINT__
+ siglongjmp(ret_place,0);
+#endif // __LCLINT__
+}
+
+
+
+
+
+/*************************************************************************/
+/* do a nice host lookup (don't thread!!) */
+/* */
+/* host: name to lookup */
+/* ip: buffer for ip's must be 400 bytes at least */
+/* time: time in seconds to wait */
+/* */
+/* return the ip or ip's of the host name */
+/* or these strings: */
+/* NOHOST for no host by that name found */
+/* NOIP for host found but no ip address available */
+/* TIMEOUT for time exceeded */
+/*************************************************************************/
+
+char *host_lookup(char *host, char *ip, int ip_size, int time) {
+ /*struct sockaddr_in address;*/
+ char **names, **addrs;
+ static struct hostent *hostinfo;
+
+#ifdef RETSIGTYPE
+ RETSIGTYPE * previous_loc;
+#else
+#error RETSIGTYPE not defined
+#endif
+
+ pid_t host_pid;
+ int status;
+ char ip_addr[400];
+ char temp[40];
+ int fp[2];
+ char buf[400];
+ int ip_found;
+ int first;
+ int tm;
+ int ips;
+ int i;
+ char ttemp[60];
+ int wait_host;
+
+ if (debug_level & 1024)
+ fprintf(stderr,"Start Host lookup\n");
+
+ memset(ip_addr,(int)'\0',sizeof(ip_addr));
+ memset(buf,(int)'\0',sizeof(buf));
+
+ busy_cursor(appshell);
+
+ if (debug_level & 1024)
+ fprintf(stderr,"Creating pipe\n");
+
+ if (pipe(fp)==0) { // Create a pipe for communication
+
+ host_pid = fork(); // Fork off a child process
+
+ if (debug_level & 1024)
+ fprintf(stderr,"Host fork\n");
+
+ if (host_pid!=-1) { // If the fork was successful
+
+//---------------------------------------------------------------------------------------
+ if (host_pid==0) { // We're in the child process
+
+
+ // Go back to default signal handler instead of
+ // calling restart() on SIGHUP
+ (void) signal(SIGHUP,SIG_DFL);
+
+
+ // Change the name of the new child process. So far
+ // this only works for "ps" listings, not for "top".
+ // This code only works on Linux. For BSD use
+ // setproctitle(3), NetBSD can use setprogname(2).
+#ifdef __linux__
+ init_set_proc_title(my_argc, my_argv, my_envp);
+ set_proc_title("%s", "hostname lookup (xastir)");
+ //fprintf(stderr,"DEBUG: %s\n", Argv[0]);
+#endif // __linux__
+
+
+ // Close the end of the pipe we don't need here
+
+ if (debug_level & 1024)
+ fprintf(stderr,"Child closing read end of pipe\n");
+
+ close(fp[0]); // Read end of the pipe
+
+ if (debug_level & 1024)
+ fprintf(stderr,"Set alarm \n");
+
+#ifdef RETSIGTYPE
+ previous_loc = (RETSIGTYPE *)signal(SIGALRM, host_time_out);
+#else
+ previous_loc = signal(SIGALRM, host_time_out);
+#endif
+
+ // Set up to jump here if we time out on SIGALRM
+ if (sigsetjmp(ret_place,-1)!=0) {
+
+ // Turn off the alarm
+ (void)alarm(0);
+
+ // Reset the SIGALRM handler to its previous value
+ (void)signal(SIGALRM, (sighandler_t)previous_loc);
+
+ // Return net connection time out
+ xastir_snprintf(ip_addr, sizeof(ip_addr), "TIMEOUT");
+ (void)write(fp[1],ip_addr,strlen(ip_addr));
+
+ if (debug_level & 1024)
+ fprintf(stderr,"Child closing write end of pipe\n");
+
+ close(fp[1]); // All done writing to the pipe
+ exit(EXIT_FAILURE); // Exit from child process
+ }
+ (void)alarm(time); // Start the timer
+
+ // Make the call that may time out if no response from DNS
+ /*hostinfo = gethostbyname2(host,AF_INET); some systems don't have this*/
+ hostinfo = gethostbyname(host);
+
+ // If we get to here, we haven't timed out
+ // and we have an answer to process.
+
+ // Turn off the alarm
+ (void)alarm(0);
+ // Reset the SIGALRM handler to its previous value
+ (void)signal(SIGALRM, (sighandler_t)previous_loc);
+
+ if (hostinfo) {
+ names = hostinfo -> h_aliases;
+ ip_found=0;
+
+ /* look at all names */
+ ips=0;
+ first=0;
+ if (!*names)
+ first=1;
+
+ while (*names || first) {
+ if (hostinfo -> h_addrtype == AF_INET) {
+ ip_found=1;
+ addrs = hostinfo -> h_addr_list;
+ while (*addrs) {
+ xastir_snprintf(temp, sizeof(temp), "%s",
+ inet_ntoa(*(struct in_addr *)*addrs));
+
+ if (debug_level & 1024)
+ fprintf(stderr,"IP [%s]\n",temp);
+
+ if (strlen(temp)>7) {
+ /* IP found */
+ if((strlen(ip_addr)+strlen(temp))<sizeof(ip_addr)) {
+
+ if (ips>0) {
+ strncat(ip_addr,
+ " ",
+ sizeof(ip_addr) - 1 - strlen(ip_addr));
+ }
+
+ strncat(ip_addr,
+ temp,
+ sizeof(ip_addr) - 1 - strlen(ip_addr));
+
+ ips++;
+ }
+ }
+ addrs++;
+ }
+ }
+ if (first) {
+ *names=NULL;
+ first=0;
+ } else
+ names++;
+ }
+ if (ip_found==0) {
+ /* Host not found */
+ xastir_snprintf(ip_addr, sizeof(ip_addr), "NOIP");
+
+ if (debug_level & 1024)
+ fprintf(stderr,"Host NO IP");
+
+ }
+ }
+ else {
+ /* Host not found */
+ xastir_snprintf(ip_addr, sizeof(ip_addr), "NOHOST");
+
+ if (debug_level & 1024)
+ fprintf(stderr,"NO HOST\n");
+
+ }
+ if (debug_level & 1024)
+ fprintf(stderr,"Clear alarm 1\n");
+
+ if (debug_level & 1024)
+ fprintf(stderr,"Clear alarm 2\n");
+
+ (void)write(fp[1],ip_addr,strlen(ip_addr));
+
+ if (debug_level & 1024)
+ fprintf(stderr,"Child closing write end of pipe\n");
+
+ close(fp[1]); // All done writing to the pipe
+ exit(EXIT_FAILURE); // Exit from child process
+
+ } // End of child process
+//---------------------------------------------------------------------------------------
+ else {
+ // We're in the parent process at this point
+
+ // Close the end of the pipe we don't need here
+
+ if (debug_level & 1024)
+ fprintf(stderr,"Parent closing write end of pipe\n");
+
+ close(fp[1]); // Write end of the pipe
+
+ tm=1;
+ wait_host=1;
+ while (wait_host!=-1) {
+ xastir_snprintf(ttemp, sizeof(ttemp), langcode("BBARSTA031"), tm++);
+ statusline(ttemp,1); // Looking up hostname...
+
+ for (i=0; i < 60 && wait_host!=-1; i++) {
+ wait_host=waitpid(host_pid,&status,WNOHANG);
+ /* update display while waiting */
+// XmUpdateDisplay(XtParent(da));
+ //usleep(500);
+ sched_yield();
+ }
+ }
+ (void)read(fp[0],buf,sizeof(buf)-1);
+
+ xastir_snprintf(ip, ip_size, "%s", buf);
+
+ if (debug_level & 1024)
+ fprintf(stderr,"Parent closing read end of pipe\n");
+
+ close(fp[0]); // Close the read end of the pipe
+ }
+ }
+ else { // We didn't fork
+ // Close both ends of the pipe to make
+ // sure we've cleaned up properly
+ close(fp[0]);
+ close(fp[1]);
+ }
+ }
+ else { // No pipe created
+ }
+ return(ip);
+}
+
+
diff --git a/src/hostname.h b/src/hostname.h
new file mode 100644
index 0000000..652f15f
--- /dev/null
+++ b/src/hostname.h
@@ -0,0 +1,33 @@
+/*
+ * $Id: hostname.h,v 1.12 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifndef __XASTIR_HOSTNAME_H
+#define __XASTIR_HOSTNAME_H
+
+extern char *host_lookup(char *host, char *ip, int ip_size, int time);
+
+#endif // __XASTIR_HOSTNAME_H
+
+
diff --git a/src/icon.xbm b/src/icon.xbm
new file mode 100644
index 0000000..a4085b2
--- /dev/null
+++ b/src/icon.xbm
@@ -0,0 +1,20 @@
+#define icon_width 40
+#define icon_height 40
+static unsigned char icon_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x80,
+ 0x10, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x1f, 0x00, 0x00, 0x20, 0x20,
+ 0x10, 0x00, 0x00, 0x10, 0x20, 0x10, 0x00, 0x00, 0x08, 0x20, 0x20, 0x00,
+ 0x00, 0x04, 0x20, 0x20, 0x00, 0x00, 0x02, 0x28, 0x60, 0x00, 0x00, 0x27,
+ 0x28, 0x60, 0xfc, 0xff, 0x3f, 0x28, 0x60, 0xfe, 0xff, 0x3f, 0xe8, 0x7f,
+ 0xfe, 0xff, 0x27, 0xef, 0x7f, 0xfe, 0xff, 0x07, 0xef, 0x7f, 0xfe, 0xff,
+ 0x07, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff,
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
+ 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0f, 0x00, 0xfc, 0x0f, 0xfc, 0x0f, 0x00,
+ 0xfc, 0x0f, 0xf8, 0x07, 0x00, 0xf8, 0x07, 0xf0, 0x03, 0x00, 0xf0, 0x03,
+ 0xe0, 0x01, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/src/igate.c b/src/igate.c
new file mode 100644
index 0000000..1ca656d
--- /dev/null
+++ b/src/igate.c
@@ -0,0 +1,1443 @@
+/*
+ * $Id: igate.c,v 1.66 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <termios.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <Xm/XmAll.h>
+#include <X11/Xatom.h>
+#include <X11/Shell.h>
+
+#include "xastir.h"
+#include "igate.h"
+#include "main.h"
+#include "interface.h"
+#include "xa_config.h"
+#include "util.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+time_t last_nws_stations_file_time = 0;
+int NWS_stations = 0;
+int max_NWS_stations = 0;
+NWS_Data *NWS_station_data;
+
+
+void load_NWS_stations(char *file);
+int check_NWS_stations(char *call);
+
+
+
+// Struct for holding packet data. We use dynamically-allocated
+// singly-linked lists. The last record should have its "next"
+// pointer set to NULL.
+//
+typedef struct _DupeRecord{
+ char data[MAX_LINE_SIZE+15]; // Packet data
+ time_t time; // The time the record was inserted
+ struct _DupeRecord *next; // pointer to next record in list
+} DupeRecord;
+
+
+
+// Sent and Heard queue pointers. These are used for the dupe-checking
+// we do in the below routines. We have one Sent and one Heard queue
+// for each interface device. These pointers will point to the head of
+// each queue. We really only need these queues for each TNC interface,
+// but the user might destroy a NET interface and create a TNC interface
+// during a single runtime, so we need to populate all of the pointers
+// just in case. If people switch types, the old queue will empty out
+// (effectively anyway) within XX seconds, so we don't have to worry
+// about cleaning out the queues in this case.
+//
+DupeRecord *heard_queue[MAX_IFACE_DEVICES];
+DupeRecord *sent_queue[MAX_IFACE_DEVICES];
+
+
+
+// Types of queues for each interface
+#define HEARD 0
+#define SENT 1
+
+
+
+// Insert mode for the queues
+#define NO_FORCED_INSERT 0
+#define FORCED_INSERT 1
+
+
+
+
+
+// Initialization routine for this module which sets up the queue
+// pointers when Xastir first starts. Called from main.c:main()
+//
+void igate_init(void) {
+ int i;
+
+ for (i = 0; i < MAX_IFACE_DEVICES; i++) {
+ heard_queue[i] = NULL;
+ sent_queue[i] = NULL;
+ }
+}
+
+
+
+
+
+//
+// not_a_dupe: Function which checks for duplicate packets.
+//
+// Returns: 1 if it's _not_ a duplicate record or we have an error
+// 0 if it _is_ a duplicate record
+//
+// Since we need to run through every record checking for dupes anyway,
+// we check the timestamp on each one as we go through. If too old, we
+// delete it from the head of the chain. We add new records to the end.
+// This makes it easy to keep it as a singly-linked list, and only have
+// to deal with one record at a time.
+//
+// The way this is set up we keep a thirty second queue for each
+// interface. Any records older than this are at the head of the chain
+// and are deleted one by one whenever this routine is called again due
+// to a new packet coming through. It's ok if these records sit around
+// on the queue for a long time due to no igate activity. It doesn't
+// take long to delete them!
+//
+int not_a_dupe(int queue_type, int port, char *line, int insert_mode) {
+ DupeRecord *ptr;
+ DupeRecord *ptr_last;
+ int insert_new;
+ time_t time_cutoff;
+ int found_dupe = 0;
+ char match_line[MAX_LINE_SIZE*2];
+ char line2[MAX_LINE_SIZE+1];
+ char *c0, *c1, *c2;
+
+
+ if ( (line == NULL) || (line[0] == '\0') )
+ return(1);
+
+
+ // Figure out what's "old"
+ time_cutoff = sec_now() - (time_t)29; // 29 seconds ago
+
+
+ // Fill the destination string with zeroes. This is a nice
+ // segfault-prevention technique. Whatever strings we throw in here
+ // will be automatically terminated.
+ memset(match_line, 0, MAX_LINE_SIZE*2);
+
+
+ switch (queue_type) {
+
+ case HEARD:
+ ptr_last = ptr = heard_queue[port]; // May be NULL!
+
+ // The insert_into_heard_queue() function below (called by
+ // db.c decode routines in turn) will call this function
+ // with FORCED_INSERT. Other routines in igate.c will call
+ // it with NO_FORCED_INSERT. For the Heard queue we only
+ // want the db.c decode routines inserting records.
+ if (insert_mode == FORCED_INSERT)
+ insert_new = 1; // Insert new records.
+ else
+ insert_new = 0; // Don't insert new records.
+
+ // RF packets will have third-party headers and regular
+ // headers that must be stripped off. We only want to store
+ // 3rd party RF strings in the Heard queue as the others
+ // aren't going to be igated anyway. For matching and
+ // storage purposes the 3rd party packets should look
+ // identical to how they were originally passed on the 'net,
+ // so that we can try to find duplicates before transmitting
+ // them again.
+
+// NOTE: Below is the parsing code for an internet packet for the Sent
+// queue. Modify it to parse 3rd party packets for the Heard queue.
+
+// VE7VFM-12>APD214,VE7VAN-3*,WIDE3*:}WA7JAK>APK002,TCPIP*,VE7VFM-12*::N7WGR-7 :does{2
+
+ // Changes needed before parsing code: Get rid of first
+ // part of packet up to the '}' symbol. After this the
+ // generic parsing code will work.
+// Note that the REPLY-ACK algorithm also uses the '}' symbol.
+
+ c0 = strstr(line, ":}"); // Find start of 3rd party packet
+ if (c0 == NULL) { // Not 3rd party packet
+ if (debug_level & 1024)
+ fprintf(stderr," Not 3rd party HeardQ: %s\n",line);
+ return(1);
+ }
+
+ // Copy original packet into line2 for later parsing. We
+ // want to keep the '}' character because our own
+ // transmissions out RF have that character as well.
+// Note that the REPLY-ACK algorithm also uses the '}' symbol.
+ if (debug_level & 1024)
+ fprintf(stderr,"3rd party HeardQ: %s\n",line);
+
+ xastir_snprintf(line2,
+ sizeof(line2),
+ "%s",
+ c0+1);
+
+ break;
+
+ case SENT:
+ // For this queue we always want to insert records. Only
+ // igate.c functions call this.
+ ptr_last = ptr = sent_queue[port]; // May be NULL!
+ insert_new = 1; // Insert new records
+
+ // No extra changes needed before parsing code, Example:
+ // }VE7VFM-11>APW251,TCPIP,WE7U-14*::VE7VFM-9 :OK GOT EMAIL OK{058
+ xastir_snprintf(line2,
+ sizeof(line2),
+ "%s",
+ line);
+
+ if (debug_level & 1024)
+ fprintf(stderr," COMPLETE SENT PACKET: %s\n",line2);
+
+ break;
+
+ default:
+ // We shouldn't be here.
+ return(1);
+
+ break;
+ }
+
+
+ // Create the string we're going to compare against and that we
+ // might store in the queue. Knock off the path info and just check
+ // source/destination/info portions of the packet for a match.
+
+ c1 = strstr(line2, ","); // Find comma after destination
+ c2 = strstr(line2, ":"); // Find end of path
+
+ if ( (c1 != NULL) && (c2 != NULL) ) { // Found both separators
+
+ // Copy source/destination portion
+ xastir_snprintf(match_line,
+ sizeof(match_line),
+ "%s",
+ line2);
+ match_line[(int)(c1-line2)] = '\0'; // Terminate the substring
+
+ strncat(match_line, // Copy info portion
+ c2+1,
+ sizeof(match_line) - 1 - strlen(match_line));
+ }
+ else { // At least one separator was not found, copy entire string
+ xastir_snprintf(match_line,
+ sizeof(match_line),
+ "%s",
+ line2);
+ }
+
+
+ // Run through the selected queue from beginning to end. If the
+ // pointer is NULL, the queue is empty and we're already done.
+ while (ptr != NULL && !found_dupe) {
+
+ // Check the timestamp to determine whether to delete this
+ // record
+ if (ptr->time < time_cutoff) { // Old record, delete it
+ DupeRecord *temp;
+
+ if (debug_level & 1024) {
+ switch (queue_type) {
+ case HEARD:
+ fprintf(stderr,"HEARD Deleting record: %s\n",ptr->data);
+ break;
+ case SENT:
+ fprintf(stderr," SENT Deleting record: %s\n",ptr->data);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Delete record and free up the space
+ temp = ptr;
+ ptr = ptr->next; // May be NULL!
+ free(temp);
+
+ // Point master queue pointer to new head of queue.
+ // Make sure to carry along ptr_last as well, as this is
+ // our possible insertion point later.
+ switch (queue_type) {
+ case HEARD:
+ heard_queue[port] = ptr_last = ptr; // May be NULL!
+ break;
+ case SENT:
+ sent_queue[port] = ptr_last = ptr; // May be NULL!
+ default:
+ break;
+ }
+ }
+
+ else { // Record is current. Check for a match.
+
+ //fprintf(stderr,"\n\t\t%s\n\t\t%s\n",ptr->data,match_line);
+
+ if (strcmp(ptr->data,match_line) == 0) {
+ // We found a dupe! We're done with the loop.
+ found_dupe++;
+
+ if (debug_level & 1024) {
+ switch (queue_type) {
+ case HEARD:
+ fprintf(stderr,"HEARD* Found dupe: %s\n",match_line);
+ break;
+ case SENT:
+ fprintf(stderr,"SENT* Found dupe: %s\n",match_line);
+ default:
+ break;
+ }
+ }
+ }
+ else { // Not a dupe, skip to the next record in the
+ // queue. Keep a pointer to the last record
+ // compared so that we have a possible insertion
+ // point later. Once we hit the end (NULL), we
+ // can't back up one.
+ ptr_last = ptr; // Save pointer to last record
+ ptr = ptr->next; // Advance one. May be NULL!
+ }
+ }
+ } // End of while loop
+
+
+ if (found_dupe) {
+
+ if (debug_level & 1024) {
+ switch (port_data[port].device_type) {
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_AX25_TNC:
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ case DEVICE_NET_AGWPE:
+ fprintf(stderr," Found RF dupe: %s\n",match_line);
+ break;
+
+ default:
+ fprintf(stderr," Found NET dupe: %s\n",match_line);
+ break;
+ }
+ }
+
+ return(0); // Found a dupe, return
+ }
+
+ else {
+
+ // If insert_new == 1, insert each non-dupe record into the
+ // queue and give it a timestamp. ptr_next is currently
+ // either NULL or points to the last record in the chain.
+ if (insert_new) {
+ DupeRecord *temp;
+
+ if (debug_level & 1024) {
+ switch (queue_type) {
+ case HEARD:
+ fprintf(stderr,"HEARD Adding record: %s\n",match_line);
+ break;
+ case SENT:
+ fprintf(stderr," SENT Adding record: %s\n",match_line);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Allocate a new storage space for the record and fill
+ // it in.
+ temp = (DupeRecord *)malloc(sizeof(DupeRecord));
+
+ if (!temp) {
+ fprintf(stderr,"Couldn't allocate memory in not_a_dupe()\n");
+ return(1); // Send back "not a dupe"
+ }
+
+ temp->time = (time_t)sec_now();
+
+ xastir_snprintf(temp->data,
+ sizeof(temp->data),
+ "%s",
+ match_line);
+
+ temp->next = NULL; // Will be the end of the linked list
+
+ if (ptr_last == NULL) { // Queue is currently empty
+
+ // Add record to empty list. Point master queue pointer
+ // to new head of queue.
+ switch (queue_type) {
+ case HEARD:
+ heard_queue[port] = temp;
+ break;
+ case SENT:
+ sent_queue[port] = temp;
+ default:
+ break;
+ }
+ }
+ else { // Queue is not empty, add the record to the end of
+ // the list.
+ ptr_last->next = temp;
+ }
+ }
+ }
+ return(1); // Nope, not a dupe
+}
+
+
+
+
+
+// Function which the receive routines call to insert a received
+// packet into the HEARD queue for an interface. The packet will
+// get added to the end of the linked list if it's not a duplicate
+// record.
+//
+// Check to make sure it's an RF interface, else return
+//
+void insert_into_heard_queue(int port, char *line) {
+
+ switch (port_data[port].device_type) {
+
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_AX25_TNC:
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ case DEVICE_NET_AGWPE:
+
+ // We're not using the dupe check function, but merely the
+ // expiration and insert functions of not_a_dupe()
+
+ // Don't insert the "Tickle" lines that keep the internet
+ // sockets alive
+ if ( (strncasecmp(line,"# Tickle",8) != 0)
+ && (strncasecmp(line,"#Tickle",7) != 0) ) {
+ (void)not_a_dupe(HEARD, port, line, FORCED_INSERT);
+ }
+
+ break;
+
+ default: // Get out if not an RF interface
+ return;
+
+ break;
+ }
+}
+
+
+
+
+
+/****************************************************************/
+/* output data to inet interfaces */
+/* line: data to send out */
+/* port: port data came from */
+/****************************************************************/
+void output_igate_net(char *line, int port, int third_party) {
+ char data_txt[MAX_LINE_SIZE+5];
+ char temp[MAX_LINE_SIZE+5];
+ char *call_sign;
+ char *path;
+ char *message;
+ int len,i,x,first;
+ int igate_options;
+ char log_file_path[MAX_VALUE];
+
+ call_sign = NULL;
+ path = NULL;
+ message = NULL;
+ first = 1;
+
+ if (line == NULL)
+ return;
+
+ if (line[0] == '\0')
+ return;
+
+ // Don't igate packets read in from a log file (port -1).
+ // Packets from x_spider (port -2) are ok to igate.
+ if (port == -1)
+ return;
+
+//fprintf(stderr,"Igating: %s\n", line);
+
+ // Should we Igate from RF->NET?
+ if (operate_as_an_igate <= 0)
+ return;
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ line);
+
+ // Check for null call_sign field
+ call_sign = strtok(temp,">");
+ if (call_sign == NULL)
+ return;
+
+ // Check for null path field
+ path = strtok(NULL,":");
+ if (path == NULL)
+ return;
+
+ get_user_base_dir(LOGFILE_IGATE,log_file_path, sizeof(log_file_path));
+ // Check for "TCPIP" or "TCPXX" in the path. If found, don't
+ // gate this into the internet again, it's already been gated to
+ // RF, which means it's already been on the 'net. No looping
+ // allowed here...
+ //
+ // We also now support NOGATE and RFONLY options. If these are
+ // seen in the path, do _not_ gate those packets into the
+ // internet.
+ //
+ // Don't gate OpenTrac expanded packets to the 'net.
+ //
+ if ( (strstr(path,"TCPXX") != NULL)
+ || (strstr(path,"TCPIP") != NULL && port >= 0) // x_spider ok
+ || (strstr(path,"NOGATE") != NULL)
+ || (strstr(path,"RFONLY") != NULL)
+ || (strstr(path,"OPNTRK") != NULL) // OpenTrac Packet
+ || (strstr(path,"OPNTRC") != NULL) ) { // OpenTrac Packet
+
+ if (log_igate && (debug_level & 1024) ) {
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "IGATE RF->NET(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: Packet was gated before or shouldn't be gated!\n");
+ log_data( log_file_path, temp );
+
+ fprintf(stderr, "%s", temp);
+ }
+ return;
+ }
+
+ // Check for null message field
+ message = strtok(NULL,"");
+ if (message == NULL)
+ return;
+
+ // Check for third party messages. We don't want to gate these
+ // back onto the internet feeds
+// Note that the REPLY-ACK algorithm also uses the '}' symbol.
+ if (message[0] == '}') {
+
+ if (log_igate && (debug_level & 1024) ) {
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "IGATE RF->NET(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: Third party traffic!\n");
+ log_data( log_file_path, temp );
+
+ fprintf(stderr, "%s", temp);
+ }
+ return;
+ }
+
+ // Check for "general" queries. We don't wish to gate these in
+ // either direction. There are exactly three general query
+ // types defined in the spec.
+ //
+ if ( ( strstr(message,"?APRS?" ) != NULL)
+ || (strstr(message,"?IGATE?") != NULL)
+ || (strstr(message,"?WX?" ) != NULL) ) {
+
+ // We found a general query, don't gate it.
+
+ if (log_igate && (debug_level & 1024) ) {
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "IGATE RF->NET(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: General Query!\n");
+ log_data( log_file_path, temp );
+
+ fprintf(stderr, "%s", temp);
+ }
+ return;
+ }
+
+ len = (int)strlen(call_sign);
+ for (i=0;i<len;i++) {
+
+ // just in case we see an asterisk get rid of it
+ if (call_sign[i] == '*') {
+ call_sign[i] = '\0';
+ i = len+1;
+ }
+ }
+
+ // Check for my callsign
+ if (strcmp(call_sign,my_callsign) == 0) {
+
+ if (log_igate && (debug_level & 1024) ) {
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "IGATE RF->NET(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: From my call!\n");
+ log_data( log_file_path, temp );
+
+ fprintf(stderr, "%s", temp);
+ }
+ return;
+ }
+
+ // Should I filter out more here.. get rid of all data
+ // or Look in the path for things line "AP" "GPS" "ID" etc..?
+
+begin_critical_section(&devices_lock, "igate.c:output_igate_net" );
+
+ // If received from x_spider port or it's our own tactical call.
+ // Here are the special port numbers we might see:
+ // -1: We're reading in from a log file
+ // -2: Packet came from x_spider server port (therefore it's
+ // already authenticated)
+ // -3: We're reading in tactical calls from file
+ //
+ if (port == -1) // Packet came from a log file.
+ igate_options = 0; // Don't igate it.
+
+ else if (port == -2) // Packet came from x_spider server port
+ igate_options = 1; // Ok to igate.
+
+ else if (port == -3) // We're reading tactical call from file.
+ igate_options = 0; // Don't igate it.
+
+ else if (port < -2) // Errant port number.
+ igate_options = 0; // Don't igate it.
+
+ else // Port number is 0 or positive number. A real port.
+ // Decide whether to igate it based on the port's
+ // configuration.
+ igate_options = devices[port].igate_options;
+
+
+end_critical_section(&devices_lock, "igate.c:output_igate_net" );
+
+ if (igate_options <= 0 ) {
+
+ if (log_igate && (debug_level & 1024) ) {
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "IGATE RF->NET(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: No RF->NET from input port [%d]!\n",
+ port);
+ log_data( log_file_path, temp );
+
+ fprintf(stderr, "%s", temp);
+ }
+ return;
+ }
+
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%s%c%c",
+ line,
+ '\r',
+ '\n');
+
+ // write data out to net interfaces
+ for (x = 0; x < MAX_IFACE_DEVICES; x++) {
+
+ // Find all internet interfaces that are "up"
+ if (port_data[x].device_type == DEVICE_NET_STREAM
+ && x!=port && port_data[x].status == DEVICE_UP) {
+ int pcode;
+
+ // Check whether we have a valid callsign/password
+ // combination for this interface. If not, don't gate
+ // packets to it.
+ pcode = atoi(port_data[x].device_host_pswd);
+ if (checkHash(my_callsign, pcode)) {
+ // The pcode checks out. Allow sending the
+ // packet out to the internet.
+
+ // log traffic for the first "up" interface only
+ if (log_igate && first) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "IGATE RF->NET(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ first = 0;
+ }
+
+ // Now log the interface that each bit of traffic
+ // goes out on.
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "TRANSMIT: IGate RF->NET packet on device:%d\n",
+ x);
+
+ // log output
+ if (log_igate)
+ log_data( log_file_path, temp );
+
+ if (debug_level & 1024)
+ fprintf(stderr,"%s\n",temp);
+
+ // Write this data out to the Inet port The "1"
+ // means raw format, the last digit says to _not_
+ // use the unproto_igate path
+ output_my_data(data_txt,x,1,0,0,NULL);
+//fprintf(stderr,"Sending: %s\n", data_txt);
+ }
+ }
+ }
+}
+
+
+
+
+
+/****************************************************************/
+/* output data to tnc interfaces */
+/* from: type of port heard from (No! It's the source call!) */
+/* call: call sign heard from (No! It's the destination call!) */
+/* line: data to gate to rf */
+/* port: port data came from */
+/****************************************************************/
+void output_igate_rf(char *from, char *call, char *path, char *line,
+ int port, int third_party, char *object_name) {
+
+ char temp[MAX_LINE_SIZE+20];
+ int x;
+ int first = 1;
+ int found_in_nws_file = 0;
+ char log_file_path[MAX_VALUE];
+ char nws_file_path[MAX_VALUE];
+
+
+ if ( (from == NULL) || (call == NULL) || (path == NULL) || (line == NULL) )
+ return;
+
+ if ( (from[0] == '\0') || (call[0] == '\0') || (path[0] == '\0') || (line[0] == '\0') )
+ return;
+
+ // Should we Igate from NET->RF?
+ if (operate_as_an_igate <= 1)
+ return;
+
+
+ get_user_base_dir(LOGFILE_IGATE,log_file_path, sizeof(log_file_path));
+
+ // Don't gate anything with NOGATE in it, in either direction.
+ // Same for OpenTrac packets.
+ if ( (strstr(path,"NOGATE") != NULL)
+ || (strstr(path,"OPNTRK") != NULL) // OpenTrac Packet
+ || (strstr(path,"OPNTRC") != NULL) ) { // OpenTrac Packet
+ // "NOGATE" was found in the header. Don't gate it.
+ if (log_igate && (debug_level & 1024) ) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "IGATE NET->RF(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: NOGATE found in path or shouldn't be gated!\n");
+ log_data( log_file_path, temp );
+ fprintf(stderr, "%s", temp);
+ }
+ return;
+ }
+
+ // Don't gate "general" queries in any direction. There are
+ // exactly three general query types defined in the spec.
+ //
+ if ( (strstr(line,"?APRS?" ) != NULL)
+ || (strstr(line,"?IGATE?") != NULL)
+ || (strstr(line,"?WX?" ) != NULL) ) {
+
+ // We found a general query, don't gate it.
+
+ if (log_igate && (debug_level & 1024) ) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "IGATE NET->RF(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: General Query!\n");
+ log_data( log_file_path, temp );
+ fprintf(stderr, "%s", temp);
+ }
+ return;
+ }
+
+
+ // check to see if the nws-stations file is newer than last read
+ get_user_base_dir("data/nws-stations.txt",nws_file_path,
+ sizeof(nws_file_path));
+ if (last_nws_stations_file_time < file_time(nws_file_path)) {
+ last_nws_stations_file_time = file_time(nws_file_path);
+ load_NWS_stations(nws_file_path);
+ //fprintf(stderr,"NWS Station file time is old\n");
+ }
+
+
+ // Check whether gating of packets from this station/object/item
+ // has been specifically authorized via the nws-stations.txt
+ // mechanism.
+ //
+ if (object_name) { // It's an object or item name
+
+ if ( check_NWS_stations( object_name ) || group_active(object_name)) {
+
+ found_in_nws_file++; // Object/Item is in nws-stations.txt
+ }
+ }
+ else { // It's a station callsign
+
+ if ( check_NWS_stations( from ) || group_active(from)) {
+
+ found_in_nws_file++; // Source callsign is in nws-stations.txt
+ }
+ }
+// The above is really the same as the following code, but less
+// confusing:
+// if (check_NWS_stations( (object_name) ? object_name : from ) ) {
+// found_in_nws_file++;
+// }
+
+
+ // Check for TCPXX in string only if station wasn't found in the
+ // nws-stations.txt file. If TCPXX found, we have an
+ // unregistered net user and the packet shouldn't normally head
+ // to RF.
+ //
+ // I removed the trailing asterisk -we7u
+ //
+ // Note that we CAN now gate stations to RF that have TCPXX in
+ // the string if they are authorized via the nws-stations.txt
+ // mechanism.
+ //
+ if (!found_in_nws_file) { // Skip this check if they're always authorized via the file
+
+ if (strstr(path,"TCPXX") != NULL) {
+
+ // "TCPXX" was found in the header. We have an
+ // unregistered user.
+
+ if (log_igate && (debug_level & 1024) ) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "IGATE NET->RF(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: Unregistered net user!\n");
+ log_data( log_file_path, temp );
+ fprintf(stderr, "%s", temp);
+ }
+ return;
+ }
+ }
+
+
+
+// If we made it to this point, the packet is from an authorized net
+// user (no TCPXX found in the path), or the callsign has been
+// authorized via the nws-stations.txt file (whether or not TCPXX
+// was found in the path).
+//
+// Found in file: Gate always
+//
+// Not found: Gate if TCPXX not in path -AND- if destination
+// station was heard in last hour on RF -AND- if
+// source station was NOT heard in last hour on RF.
+
+
+
+ // Check whether the source and destination calls have been
+ // heard on local RF.
+ if ( !found_in_nws_file // Skip this check if they're always authorized via the file
+ && ( !heard_via_tnc_in_past_hour(call)==1 // Haven't heard destination call in previous hour
+ || heard_via_tnc_in_past_hour(from)) ) { // Have heard source call in previous hour
+
+ if (log_igate && (debug_level & 1024) ) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "IGATE NET->RF(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ // heard(call), heard(from) : RF-to-RF talk
+ // !heard(call), heard(from) : Destination not heard on TNC
+ // !heard(call), !heard(from) : Destination/source not heard on TNC
+
+ if (!heard_via_tnc_in_past_hour(call))
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: Destination not heard on TNC within an hour %s!\n",
+ call );
+ else
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: RF->RF talk!\n");
+ log_data( log_file_path, temp );
+ fprintf(stderr, "%s", temp);
+ }
+ return;
+ }
+
+
+
+ // Station we are going to is heard via tnc but station sending
+ // shouldn't be heard via TNC. Write data out to interfaces.
+ for (x=0; x<MAX_IFACE_DEVICES;x++) {
+
+ //fprintf(stderr,"%d\n",x);
+
+//WE7U
+ // Check here against "heard" queue for each interface.
+ // Drop the packet on the floor if it was already received
+ // on this interface within the last XX seconds. This means
+ // that some other igate beat us to the punch. The receive
+ // routines have to fill this queue. Prune outdated
+ // records.
+ //
+ // Also check here against "sent" queue for each interface.
+ // Drop the packet on the floor if already sent within the
+ // last XX seconds. Add this packet to the queue if it
+ // isn't already in it. Prune outdated records.
+ if (x != port
+ && not_a_dupe(HEARD, x, line, NO_FORCED_INSERT)
+ && not_a_dupe( SENT, x, line, NO_FORCED_INSERT) ) {
+
+ //fprintf(stderr,"output_igate_rf: Not a dupe port %d, transmitting\n",x);
+
+ switch (port_data[x].device_type) {
+
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_AX25_TNC:
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ case DEVICE_NET_AGWPE:
+
+begin_critical_section(&devices_lock, "igate.c:output_igate_rf" );
+
+ if (devices[x].igate_options>1 && port_data[x].status==DEVICE_UP) {
+
+ // log traffic for first "up" interface only
+ if (log_igate && first) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "IGATE NET->RF(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+ first = 0;
+ }
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "TRANSMIT: IGate NET->RF packet on device:%d\n",
+ x);
+
+ // log output
+ if (log_igate)
+ log_data( log_file_path, temp );
+
+ if (debug_level & 1024)
+ fprintf(stderr, "%s", temp);
+
+ // ok write this data out to the RF port
+
+end_critical_section(&devices_lock, "igate.c:output_igate_rf" );
+
+ // First "0" means "cooked"
+ // format, last digit: use
+ // unproto_igate path
+ output_my_data(line,x,0,0,1,NULL);
+
+//fprintf(stderr, "Igating->RF: %s\n", line);
+
+begin_critical_section(&devices_lock, "igate.c:output_igate_rf" );
+
+ }
+ else {
+ if (log_igate && (debug_level & 1024) ) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "IGATE NET->RF(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: NET->RF on port [%d]!\n",
+ x);
+ log_data( log_file_path, temp );
+ fprintf(stderr, "%s", temp);
+ }
+ }
+
+end_critical_section(&devices_lock, "igate.c:output_igate_rf" );
+
+ break;
+
+ default:
+ break;
+ } // End of switch
+ } // End of if
+ } // End of for
+}
+
+
+
+
+
+void add_NWS_stations(void) {
+ void *tmp_ptr;
+
+ if (NWS_stations>=max_NWS_stations) {
+ if ((tmp_ptr = realloc(NWS_station_data, sizeof(NWS_Data)*(max_NWS_stations+11)))) {
+ NWS_station_data = tmp_ptr;
+ max_NWS_stations += 10;
+ }
+ else {
+ fprintf(stderr,"Unable to allocate more space for NWS_station_data\n");
+ }
+ }
+}
+
+
+
+
+
+/****************************************************************/
+/* Load NWS stations file */
+/* file: file to read */
+/****************************************************************/
+void load_NWS_stations(char *file) {
+ FILE *f;
+ char line[40];
+
+ if (file == NULL)
+ return;
+
+ if (file[0] == '\0')
+ return;
+
+ if (NWS_station_data) {
+ free(NWS_station_data);
+ NWS_station_data = NULL;
+ }
+
+ NWS_stations = 0;
+ max_NWS_stations = 0;
+
+ f = fopen(file,"r");
+ if (f!=NULL) {
+ while (!feof(f)) {
+ if (strlen(get_line(f,line,40))>0) {
+ // look for comment
+ if (line[0] != '#' ) {
+ NWS_stations++;
+ add_NWS_stations();
+ if (NWS_station_data != NULL) {
+ // add data
+ // Note: Size of string variable is 12
+ // bytes, defined in igate.h
+ if (1 != sscanf(line,"%11s",NWS_station_data[NWS_stations-1].call)) {
+ fprintf(stderr,"load_NWS_stations: sscanf parsing error\n");
+ }
+ if (debug_level & 1024)
+ fprintf(stderr,"LINE:%s\n",line);
+ }
+ else {
+ fprintf(stderr,"Can't allocate data space for NWS station\n");
+ }
+ }
+ }
+ }
+ (void)fclose(f);
+ }
+ else
+ fprintf(stderr,"Couldn't open NWS stations file: %s\n", file);
+}
+
+
+
+
+
+// check NWS stations file
+//
+// call: call to check
+// returns 1 for found
+//
+// Both the incoming call and the stored call we're matching against
+// have to be >= 3 characters long. This routine will match only up
+// to the length of the stored string, so we now allow partial
+// matches.
+//
+int check_NWS_stations(char *call) {
+ int ok, i, length, length_incoming;
+
+
+ if (call == NULL)
+ return(0);
+
+ if (call[0] == '\0')
+ return(0);
+
+ if (NWS_station_data == NULL)
+ return(0);
+
+ if (debug_level & 1024)
+ fprintf(stderr,"igate.c::check_NWS_stations %s\n", call);
+
+ // Make sure that the incoming call is longer than three
+ // characters. If not, skip it.
+ length_incoming = strlen(call);
+ if (length_incoming < 3)
+ return(0);
+
+ ok=0;
+ for (i=0; i<NWS_stations && !ok; i++) {
+
+ // Compute length of stored string. If it's shorter than
+ // three characters, skip it and go on to the next one.
+ length = strlen(NWS_station_data[i].call);
+
+ if (length >= 3) {
+ // Compare the incoming call only up to the length of the
+ // stored call. This allows partial matches. The
+ // stored call could be significantly shorter than the
+ // incoming call, but at least three characters.
+ if (strncasecmp(call, NWS_station_data[i].call, length)==0) {
+
+ ok=1; // match found
+ if (debug_level & 1024) {
+ fprintf(stderr,"NWS-MATCH:(%s) (%s)\n",NWS_station_data[i].call,call);
+ }
+ }
+ }
+ else {
+ // Do nothing. Stored call is too short.
+ }
+ }
+ return(ok);
+}
+
+
+
+
+
+/****************************************************************/
+/* output NWS data to tnc interfaces */
+/* from: type of port heard from */
+/* call: call sign heard from */
+/* line: data to gate to rf */
+/* port: port data came from */
+/****************************************************************/
+void output_nws_igate_rf(char *from, char *path, char *line, int port, int third_party) {
+ char temp[MAX_LINE_SIZE+20];
+ int x;
+ int first = 1;
+ char log_file_path[MAX_VALUE];
+ char nws_file_path[MAX_VALUE];
+
+
+ if ( (from == NULL) || (path == NULL) || (line == NULL) )
+ return;
+
+ if ( (from[0] == '\0') || (path[0] == '\0') || (line[0] == '\0') )
+ return;
+
+ // Should we Igate from NET->RF?
+ if (operate_as_an_igate <= 1)
+ return;
+
+ get_user_base_dir(LOGFILE_IGATE,log_file_path, sizeof(log_file_path));
+ get_user_base_dir("data/nws-stations.txt",nws_file_path,
+ sizeof(nws_file_path));
+
+ // Check for TCPXX in string! If found, we have an
+ // unregistered net user.
+ // I removed the trailing asterisk --we7u
+ if (strstr(path,"TCPXX") != NULL) {
+ // "TCPXX" was found in the header. We have an
+ // unregistered user.
+ if (log_igate && (debug_level & 1024) ) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "NWS IGATE NET->RF(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: Unregistered net user!\n");
+ log_data( log_file_path, temp );
+ fprintf(stderr, "%s", temp);
+ }
+ return;
+ }
+
+ // no unregistered net user found in string. Look for NOGATE
+ // next.
+
+ if ( strstr(path,"NOGATE") != NULL ) {
+ // "NOGATE" was found in the header. Don't gate it.
+ if (log_igate && (debug_level & 1024) ) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "NWS IGATE NET->RF(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: NOGATE found in path!\n");
+ log_data( log_file_path, temp );
+ fprintf(stderr, "%s", temp);
+ }
+ return;
+ }
+
+ // see if we can gate NWS messages
+ if (!filethere(nws_file_path)) {
+ if (log_igate && (debug_level & 1024) ) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "NWS IGATE NET->RF(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: No nws-stations.txt file!\n");
+ log_data( log_file_path, temp );
+ fprintf(stderr, "%s", temp);
+ }
+ return;
+ }
+
+ // check to see if the nws-stations file is newer than last read
+ if (last_nws_stations_file_time < file_time(nws_file_path)) {
+ last_nws_stations_file_time = file_time(nws_file_path);
+ load_NWS_stations(nws_file_path);
+ //fprintf(stderr,"NWS Station file time is old\n");
+ }
+
+ // Look for NWS station in file data
+ if (!check_NWS_stations(from) || !group_active(from)){ // Couldn't find the station
+
+ if (log_igate && (debug_level & 1024) ) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "NWS IGATE NET->RF(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: No matching station in nws-stations.txt file!\n");
+ log_data( log_file_path, temp );
+ fprintf(stderr, "%s", temp);
+ }
+ return; // Match for station not found in file
+ }
+
+ //fprintf(stderr,"SENDING NWS VIA TNC!!!!\n");
+ // write data out to interfaces
+ for (x=0; x<MAX_IFACE_DEVICES;x++) {
+
+//WE7U
+ // Check here against "heard" queue for each interface.
+ // Drop the packet on the floor if it was already received
+ // on this interface within the last XX seconds. This means
+ // that some other igate beat us to the punch. The receive
+ // routines have to fill this queue. Prune outdated
+ // records.
+ //
+ // Also check here against "sent" queue for each interface.
+ // Drop the packet on the floor if already sent within the
+ // last XX seconds. Add this packet to the queue if it
+ // isn't already in it. Prune outdated records.
+ if (x != port
+ && not_a_dupe(HEARD, x, line, NO_FORCED_INSERT)
+ && not_a_dupe( SENT, x, line, NO_FORCED_INSERT) ) {
+
+ switch (port_data[x].device_type) {
+
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_AX25_TNC:
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ case DEVICE_NET_AGWPE:
+
+begin_critical_section(&devices_lock, "igate.c:output_nws_igate_rf" );
+
+ if (devices[x].igate_options>1
+ && port_data[x].status==DEVICE_UP) {
+
+ // log traffic for first "up" interface only
+ if (log_igate && first) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "NWS IGATE NET->RF(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+ first = 0;
+ }
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "TRANSMIT: IGate NET->RF packet on device:%d\n",
+ x);
+
+ // log output
+ if (log_igate)
+ log_data( log_file_path, temp );
+
+ if (debug_level & 1024)
+ fprintf(stderr, "%s", temp);
+
+ // ok write this data out to the RF port
+
+end_critical_section(&devices_lock, "igate.c:output_nws_igate_rf" );
+
+ // First "0" means "cooked"
+ // format, last digit: use
+ // unproto_igate path
+ output_my_data(line,x,0,0,1,NULL);
+
+begin_critical_section(&devices_lock, "igate.c:output_nws_igate_rf" );
+
+ }
+ else {
+ if (log_igate && (debug_level & 1024) ) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "NWS IGATE NET->RF(%c):%s\n",
+ third_party ? 'T':'N',
+ line);
+ log_data( log_file_path, temp );
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "REJECT: NET->RF on port [%d]!\n",
+ x);
+ log_data( log_file_path, temp );
+ fprintf(stderr, "%s", temp);
+ }
+ }
+
+end_critical_section(&devices_lock, "igate.c:output_nws_igate_rf" );
+
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+
diff --git a/src/igate.h b/src/igate.h
new file mode 100644
index 0000000..dee05d8
--- /dev/null
+++ b/src/igate.h
@@ -0,0 +1,41 @@
+/*
+ * $Id: igate.h,v 1.13 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifndef __XASTIR_IGATE_H
+#define __XASTIR_IGATE_H
+
+typedef struct {
+ char call[12];
+} NWS_Data;
+
+extern void igate_init(void);
+extern void insert_into_heard_queue(int port, char *line);
+extern void output_igate_net(char *line, int port, int third_party);
+extern void output_igate_rf(char *from, char *call, char *path, char *line, int port, int third_party, char *object_name);
+extern void output_nws_igate_rf(char *from, char *path, char *line, int port, int third_party);
+
+#endif // __XASTIR_IGATE_H
+
+
diff --git a/src/interface.c b/src/interface.c
new file mode 100644
index 0000000..f5d5e94
--- /dev/null
+++ b/src/interface.c
@@ -0,0 +1,10181 @@
+/*
+ * $Id: interface.c,v 1.305 2012/10/23 00:37:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+/*
+ AX.25 Parts adopted from: aprs_tty.c by Henk de Groot - PE1DNN
+*/
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <signal.h>
+#include <termios.h>
+#include <pwd.h>
+#include <termios.h>
+#include <setjmp.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+
+#include <netinet/in.h> // Moved ahead of inet.h as reports of some *BSD's not
+ // including this as they should.
+#include <arpa/inet.h>
+#include <netinet/tcp.h> // Needed for TCP_NODELAY setsockopt() (disabling Nagle algorithm)
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif // HAVE_NETDB_H
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+#include <errno.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif // HAVE_LOCALE_H
+
+#ifdef HAVE_LIBINTL_H
+#include <libintl.h>
+#define _(x) gettext(x)
+#else // HAVE_LIBINTL_H
+#define _(x) (x)
+#endif // HAVE_LIBINTL_H
+
+#include <Xm/XmAll.h>
+
+#include "xastir.h"
+#include "symbols.h"
+#include "main.h"
+#include "xa_config.h"
+//#include "maps.h"
+#include "interface.h"
+#include "util.h"
+#include "wx.h"
+#include "hostname.h"
+#include "x_spider.h"
+#include "db_gis.h"
+
+#ifdef HAVE_LIBAX25
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#endif // HAVE_LIBAX25
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+#ifndef SIGRET
+#define SIGRET void
+#endif // SIGRET
+
+
+//extern pid_t getpgid(pid_t pid);
+extern void port_write_binary(int port, unsigned char *data, int length);
+
+
+iodevices dtype[MAX_IFACE_DEVICE_TYPES]; // device names
+
+iface port_data[MAX_IFACE_DEVICES]; // shared port data
+
+int port_id[MAX_IFACE_DEVICES]; // shared port id data
+
+xastir_mutex port_data_lock; // Protects the port_data[] array of structs
+xastir_mutex data_lock; // Protects incoming_data_queue
+xastir_mutex output_data_lock; // Protects interface.c:channel_data() function only
+xastir_mutex connect_lock; // Protects port_data[].thread_status and port_data[].connect_status
+
+void port_write_string(int port, char *data);
+
+int ax25_ports_loaded = 0;
+
+
+// Incoming data queue
+typedef struct _incoming_data_record {
+ int length; // Used for binary strings such as KISS
+ int port;
+ unsigned char data[MAX_LINE_SIZE];
+} incoming_data_record;
+#define MAX_INPUT_QUEUE 1000
+static incoming_data_record incoming_data_queue[MAX_INPUT_QUEUE];
+unsigned char incoming_data_copy[MAX_LINE_SIZE]; // Used for debug
+unsigned char incoming_data_copy_previous[MAX_LINE_SIZE]; // Used for debug
+
+// interface wait time out
+int NETWORK_WAITTIME;
+
+
+
+
+
+// Read/write pointers for the circular input queue
+static int incoming_read_ptr = 0;
+static int incoming_write_ptr = 0;
+static int queue_depth = 0;
+static int push_count = 0;
+static int pop_count = 0;
+
+
+
+
+
+// Fetch a record from the circular queue.
+// Returns 0 if no records available
+// Else returns length of string, data_string and port
+// data_string variable should be of size MAX_LINE_SIZE
+//
+int pop_incoming_data(unsigned char *data_string, int *port) {
+ int length;
+ int jj;
+
+ if (begin_critical_section(&data_lock, "interface.c:pop_incoming_data" ) > 0)
+ fprintf(stderr,"data_lock\n");
+
+ // Check for queue empty
+ if (incoming_read_ptr == incoming_write_ptr) {
+ // Yep, it's empty
+
+//fprintf(stderr,"\n\t<- EMPTY!\n");
+
+ queue_depth = 0;
+
+ if (end_critical_section(&data_lock, "interface.c:pop_incoming_data" ) > 0)
+ fprintf(stderr,"data_lock\n");
+ return(0);
+ }
+
+ // Bump the read pointer
+ incoming_read_ptr = (incoming_read_ptr + 1) % MAX_INPUT_QUEUE;
+
+ *port = incoming_data_queue[incoming_read_ptr].port;
+
+ length = incoming_data_queue[incoming_read_ptr].length;
+
+ // This isn't safe for binary data. It gets truncated at the
+ // first zero byte!
+ // xastir_snprintf((char *)data_string,
+ // (length < MAX_LINE_SIZE) ? length : MAX_LINE_SIZE,
+ // "%s",
+ // incoming_data_queue[incoming_read_ptr].data);
+ //
+ // Binary safe code
+ for (jj = 0; jj < length; jj++) {
+ data_string[jj] = incoming_data_queue[incoming_read_ptr].data[jj];
+ }
+
+ // Add terminator, just in case
+ data_string[length+1] = '\0';
+
+ queue_depth--;
+ pop_count++;
+
+//if (push_count != pop_count)
+// fprintf(stderr,"Pushes:%d\tPops:%d\n", push_count, pop_count);
+//else
+// fprintf(stderr,"Pushes = \tPops\n");
+
+ // For DEBUG, to see if the queue how the queue is getting used
+// if (queue_depth > 1) {
+// fprintf(stderr,"%d\t", queue_depth);
+// }
+
+//fprintf(stderr,"\n\t<- %s",data_string);
+
+ if (end_critical_section(&data_lock, "interface.c:pop_incoming_data" ) > 0)
+ fprintf(stderr,"data_lock\n");
+
+ return(length);
+}
+
+
+
+
+
+// Add one record to the circular queue. Returns 1 if queue is
+// full, 0 if successful.
+//
+int push_incoming_data(unsigned char *data_string, int length, int port) {
+ int next_write_ptr = (incoming_write_ptr + 1) % MAX_INPUT_QUEUE;
+ int jj;
+
+
+ if (begin_critical_section(&data_lock, "interface.c:push_incoming_data" ) > 0)
+ fprintf(stderr,"data_lock\n");
+
+ // Check whether queue is full
+ if (incoming_read_ptr == next_write_ptr) {
+ // Yep, it's full!
+
+//fprintf(stderr,"\n-> FULL!");
+
+ if (end_critical_section(&data_lock, "interface.c:push_incoming_data" ) > 0)
+ fprintf(stderr,"data_lock\n");
+ return(1);
+ }
+
+//fprintf(stderr,"\n-> %s",data_string);
+
+
+ // Advance the write pointer
+ incoming_write_ptr = next_write_ptr;
+
+ incoming_data_queue[incoming_write_ptr].length = length;
+
+ incoming_data_queue[incoming_write_ptr].port = port;
+
+ // This isn't safe for binary data. It gets truncated at the
+ // first zero byte!
+ // xastir_snprintf((char *)incoming_data_queue[incoming_write_ptr].data,
+ // (length < MAX_LINE_SIZE) ? length : MAX_LINE_SIZE,
+ // "%s",
+ // data_string);
+ //
+ // Binary safe
+ for (jj = 0; jj < length; jj++) {
+ incoming_data_queue[incoming_write_ptr].data[jj] = data_string[jj];
+ }
+
+ queue_depth++;
+ push_count++;
+
+ if (end_critical_section(&data_lock, "interface.c:push_incoming_data" ) > 0)
+ fprintf(stderr,"data_lock\n");
+
+ return(0);
+}
+
+
+
+
+
+// Returns 1 if a local interface, 0 otherwise
+//
+int is_local_interface(int port) {
+
+ switch (port_data[port].device_type) {
+
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_GPS:
+ case DEVICE_SERIAL_WX:
+ case DEVICE_AX25_TNC:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ return(1); // Found a local interface
+ break;
+
+ // Could be port -1 which signifies a spider port or port
+ // -99 which signifies "All Ports" and is used for
+ // transmitting out all ports at once.
+ default:
+ return(0); // Unknown or network interface
+ break;
+ }
+}
+
+
+
+
+
+// Returns 1 if a network interface, 0 otherwise
+//
+int is_network_interface(int port) {
+
+ switch (port_data[port].device_type) {
+
+ case DEVICE_NET_STREAM:
+ case DEVICE_NET_GPSD:
+ case DEVICE_NET_WX:
+ case DEVICE_NET_DATABASE:
+ case DEVICE_NET_AGWPE:
+ return(1); // Found a network interface
+ break;
+
+ // Could be port -1 which signifies a spider port or port
+ // -99 which signifies "All Ports" and is used for
+ // transmitting out all ports at once.
+ default:
+ return(0); // Unknown or local interface
+ break;
+ }
+}
+
+
+
+
+
+
+// Create a packet and send to AGWPE for transmission.
+// Format is as follows:
+//
+// RadioPort 4 bytes (0-3)
+// DataType 4 bytes (4-7)
+// FromCall 10 bytes (8-17)
+// ToCall 10 bytes (18-27)
+// DataLength 4 bytes (28-31)
+// UserField 4 bytes (32-35)
+// Data DataLength bytes (36-?)
+//
+// Callsigns are null-terminated at end of string, but callsign
+// field width is specified to be 10 bytes in all cases.
+//
+// Path is split up into the various ViaCalls. Path may also be a
+// NULL pointer.
+//
+// If type != '\0', then we'll create the specified type of packet.
+//
+// Else if Path is not empty, we'll use packet format "V" with
+// Viacalls prepended to the Data portion of the packet, 10 chars
+// per digi, with the number of digis as the first character. The
+// packet data then follows after the last via callsign.
+//
+// Else if no Path, then put the Data directly into the Data
+// field and use "M" format packets.
+//
+// We currently use the base portion of my_callsign as the username
+// portion of the AGWPE login. This must be upper-case when you're
+// setting up the account in AGWPE, as that's what we send to
+// authenticate.
+//
+void send_agwpe_packet(int xastir_interface,// Xastir interface port
+ int RadioPort, // AGWPE RadioPort
+ unsigned char type,
+ unsigned char *FromCall,
+ unsigned char *ToCall,
+ unsigned char *Path,
+ unsigned char *Data,
+ int length) {
+ int ii;
+#define agwpe_header_size 36
+ unsigned char output_string[512+agwpe_header_size];
+ unsigned char path_string[200];
+ int full_length;
+ int data_length;
+
+
+/*
+fprintf(stderr,"Sending to AGWPE RadioPort %d, ", RadioPort);
+fprintf(stderr,"Type:%c, From:%s, To:%s, Path:%s, Data:%s\n",
+ type, FromCall, ToCall, Path, Data);
+*/
+
+ // Check size of data
+ if (length > 512)
+ return;
+
+ // Clear the output_string (set to binary zeroes)
+ for (ii = 0; ii < (int)sizeof(output_string); ii++) {
+ output_string[ii] = '\0';
+ }
+
+ if (type != 'P') {
+ // Write the port number into the frame. Note that AGWPE
+ // uses 1 for the first port in its GUI, but the programming
+ // interface starts at 0.
+ output_string[0] = (unsigned char)RadioPort;
+
+ if (FromCall) // Write the FromCall string into the frame
+ xastir_snprintf((char *)&output_string[8],
+ sizeof(output_string) - 8,
+ "%s",
+ FromCall);
+
+ if (ToCall) // Write the ToCall string into the frame
+ xastir_snprintf((char *)&output_string[18],
+ sizeof(output_string) - 18,
+ "%s",
+ ToCall);
+ }
+
+ if ( (type != '\0') && (type != 'P') ) {
+ // Type was specified, not a data frame or login frame
+
+ // Write the type character into the frame
+ output_string[4] = type;
+
+ // Send the packet to AGWPE
+ port_write_binary(xastir_interface,
+ output_string,
+ agwpe_header_size);
+ }
+
+ else if (Path == NULL) { // No ViaCalls, Data or login packet
+
+ if (type == 'P') {
+ // Login/Password frame
+ char callsign_base[15];
+ int new_length;
+
+
+ // Write the type character into the frame
+ output_string[4] = type;
+
+ // Compute the callsign base string
+ // (callsign minus SSID)
+ xastir_snprintf(callsign_base,
+ sizeof(callsign_base),
+ "%s",
+ my_callsign);
+ // Change '-' into end of string
+ strtok(callsign_base, "-");
+
+ // Length = length of each string plus the two
+ // terminating zeroes.
+ //new_length = strlen(callsign_base) + length + 2;
+ new_length = 255+255;
+
+ output_string[28] = (unsigned char)(new_length % 256);
+ output_string[29] = (unsigned char)((new_length >> 8) % 256);
+
+/*
+fprintf(stderr,"Length bytes: %02x %02x %02x %02x\n",
+ output_string[28],
+ output_string[29],
+ output_string[30],
+ output_string[31]);
+*/
+
+// Write login/password out as 255-byte strings each
+
+ // Put the login string into the buffer
+ xastir_snprintf((char *)&output_string[agwpe_header_size],
+ sizeof(output_string) - agwpe_header_size,
+ "%s",
+ callsign_base);
+
+ // Put the password string into the buffer
+ xastir_snprintf((char *)&output_string[agwpe_header_size+255],
+ sizeof(output_string) - agwpe_header_size - 255,
+ "%s",
+ Data);
+
+//fprintf(stderr,"AGWPE User:%s, Pass:%s\n",callsign_base, Data);
+
+ // Send the packet to AGWPE
+ port_write_binary(xastir_interface,
+ output_string,
+ 255+255+agwpe_header_size);
+ }
+ else { // Data frame
+ // Write the type character into the frame
+ output_string[4] = 'M'; // Unproto, no via calls
+
+ // Write the PID type into the frame
+ output_string[6] = 0xF0; // UI Frame
+
+ output_string[28] = (unsigned char)(length % 256);
+ output_string[29] = (unsigned char)((length >> 8) % 256);
+
+/*
+fprintf(stderr,"Length bytes: %02x %02x %02x %02x\n",
+ output_string[28],
+ output_string[29],
+ output_string[30],
+ output_string[31]);
+*/
+
+ // Copy Data onto the end of the string. This one
+ // doesn't have to be null-terminated, so strncpy() is
+ // ok to use here. strncpy stops at the first null byte
+ // though. Proper for a binary output routine? NOPE!
+ strncpy((char *)(&output_string[agwpe_header_size]),(char *)Data, length);
+
+ full_length = length + agwpe_header_size;
+
+ // Send the packet to AGWPE
+ port_write_binary(xastir_interface,
+ output_string,
+ full_length);
+
+//fprintf(stderr, "Sent: %s\n", Data);
+
+ }
+ }
+
+ else { // We have ViaCalls. Data packet.
+ char *ViaCall[10];
+
+ // Doesn't need to be null-terminated, so strncpy is ok to
+ // use here. strncpy stops at the first null byte though.
+ // Proper for a binary output routine? NOPE!
+ strncpy((char *)path_string, (char *)Path, sizeof(path_string));
+
+ // Convert path_string to upper-case
+ to_upper((char *)path_string);
+
+//fprintf(stderr,"path_string: %s\n", path_string);
+
+ split_string((char *)path_string, ViaCall, 10, ',');
+
+ // Write the type character into the frame
+ output_string[4] = 'V'; // Unproto, via calls present
+
+ // Write the PID type into the frame
+ output_string[6] = 0xF0; // UI Frame
+
+ // Write the number of ViaCalls into the first byte
+ if (ViaCall[7]) {
+//fprintf(stderr, "Eight viacalls\n");
+ output_string[agwpe_header_size] = 0x08;
+ }
+ else if (ViaCall[6]) {
+//fprintf(stderr, "Seven viacalls\n");
+ output_string[agwpe_header_size] = 0x07;
+ }
+ else if (ViaCall[5]) {
+//fprintf(stderr, "Six viacalls\n");
+ output_string[agwpe_header_size] = 0x06;
+ }
+ else if (ViaCall[4]) {
+//fprintf(stderr, "Five viacalls\n");
+ output_string[agwpe_header_size] = 0x05;
+ }
+ else if (ViaCall[3]) {
+//fprintf(stderr, "Four viacalls\n");
+ output_string[agwpe_header_size] = 0x04;
+ }
+ else if (ViaCall[2]) {
+//fprintf(stderr, "Three viacalls\n");
+ output_string[agwpe_header_size] = 0x03;
+ }
+ else if (ViaCall[1]) {
+//fprintf(stderr, "Two viacalls\n");
+ output_string[agwpe_header_size] = 0x02;
+ }
+ else {
+//fprintf(stderr, "One viacall\n");
+ output_string[agwpe_header_size] = 0x01;
+ }
+
+ // Write the ViaCalls into the Data field
+ switch (output_string[agwpe_header_size]) {
+ case 8:
+ if (ViaCall[7]) {
+ strncpy((char *)(&output_string[agwpe_header_size+1+70]), ViaCall[7], 10);
+//fprintf(stderr, "%s\n", ViaCall[7]);
+ }
+ else
+ return;
+ case 7:
+ if (ViaCall[6]) {
+ strncpy((char *)(&output_string[agwpe_header_size+1+60]), ViaCall[6], 10);
+//fprintf(stderr, "%s\n", ViaCall[6]);
+ }
+ else
+ return;
+ case 6:
+ if (ViaCall[5]) {
+ strncpy((char *)(&output_string[agwpe_header_size+1+50]), ViaCall[5], 10);
+//fprintf(stderr, "%s\n", ViaCall[5]);
+ }
+ else
+ return;
+ case 5:
+ if (ViaCall[4]) {
+ strncpy((char *)(&output_string[agwpe_header_size+1+40]), ViaCall[4], 10);
+//fprintf(stderr, "%s\n", ViaCall[4]);
+ }
+ else
+ return;
+ case 4:
+ if (ViaCall[3]) {
+ strncpy((char *)(&output_string[agwpe_header_size+1+30]), ViaCall[3], 10);
+//fprintf(stderr, "%s\n", ViaCall[3]);
+ }
+ else
+ return;
+ case 3:
+ if (ViaCall[2]) {
+ strncpy((char *)(&output_string[agwpe_header_size+1+20]), ViaCall[2], 10);
+//fprintf(stderr, "%s\n", ViaCall[2]);
+ }
+ else
+ return;
+ case 2:
+ if (ViaCall[1]) {
+ strncpy((char *)(&output_string[agwpe_header_size+1+10]), ViaCall[1], 10);
+//fprintf(stderr, "%s\n", ViaCall[1]);
+ }
+ else
+ return;
+ case 1:
+ default:
+ if (ViaCall[0]) {
+ strncpy((char *)(&output_string[agwpe_header_size+1+0]), ViaCall[0], 10);
+//fprintf(stderr, "%s\n", ViaCall[0]);
+ }
+ else
+ return;
+ break;
+ }
+
+ // Write the Data onto the end.
+ // Doesn't need to be null-terminated, so strncpy is ok to
+ // use here. strncpy stops at the first null byte though.
+ // Proper for a binary output routine?
+ strncpy((char *)(&output_string[((int)(output_string[agwpe_header_size]) * 10) + agwpe_header_size + 1]),
+ (char *)Data,
+ length);
+
+ //Fill in the data length field. We're assuming the total
+ //is less than 512 + 37.
+ data_length = length + ((int)(output_string[agwpe_header_size]) * 10) + 1;
+
+//fprintf(stderr, "Via calls: %d\n",
+//(int)(output_string[agwpe_header_size]));
+//fprintf(stderr, "Length: %d\n", length);
+//fprintf(stderr, "Data Length: %d\n", data_length);
+
+ if ( data_length > 512 )
+ return;
+
+ output_string[28] = (unsigned char)(data_length % 256);
+ output_string[29] = (unsigned char)((data_length >> 8) % 256);
+
+/*
+fprintf(stderr,"Length bytes: %02x %02x %02x %02x\n",
+ output_string[28],
+ output_string[29],
+ output_string[30],
+ output_string[31]);
+*/
+
+ full_length = data_length + agwpe_header_size;
+
+ // Send the packet to AGWPE
+ port_write_binary(xastir_interface,
+ output_string,
+ full_length);
+
+//fprintf(stderr, "Data: %s\n", Data);
+
+ }
+}
+
+
+
+
+
+/*
+// Here is a "monitor" UI packet
+//
+Total Length = 150
+HEX:00 00 00 00 55 00 00 00 4b 4b 31 57 00 ed 12 00 96 ed 41 50 54
+57 30 31 00 00 00 00 72 00 00 00 00 00 00 00 20 31 3a 46 6d 20 4b 4b
+31 57 20 54 6f 20 41 50 54 57 30 31 20 56 69 61 20 57 49 44 45 33 20
+3c 55 49 20 70 69 64 3d 46 30 20 4c 65 6e 3d 35 30 20 3e 5b 31 30 3a
+34 33 3a 34 33 5d 0d 5f 30 38 30 36 31 30 33 39 63 33 35 39 73 30 30
+30 67 30 30 30 74 30 36 32 72 30 30 30 70 30 30 33 50 30 39 36 68 30
+30 62 31 30 30 39 33 74 55 32 6b 0d 0d 00
+ASC:....U...KK1W......APTW01....r....... 1:Fm KK1W To APTW01 Via WIDE3 <UI pid=F0 Len=50 >[10:43:43]._08061039c359s000g000t062r000p003P096h00b10093tU2k...
+*/
+
+/*
+// And here are some "raw" UI packets
+//
+AGWPE: Got raw frame packet
+3:2e
+Bad KISS packet. Dropping it.
+Total Length = 135
+HEX:00 00 00 00 4b 00 00 00 4e 32 4c 42 54 2d 37 00 01 00 41 50 58
+31 33 33 00 00 00 00 63 00 00 00 00 00 00 00
+
+c0 82 a0 b0 62 66 66 60
+9c 64 98 84 a8 40 6e 96 82 64 a2 b2 8a f4 ae 92 88 8a 40 40 61 03 f0
+40 30 37 30 30 32 37 7a 34 32 33 39 2e 30 34 4e 5c 30 37 33 34 38 2e
+31 30 57 5f 30 30 30 2f 30 30 30 67 30 30 30 74 30 36 34 72 30 30 30
+50 30 30 30 70 30 30 30 68 35 33 62 31 30 31 32 37 58 55 32 6b 0d
+ASC:....K...N2LBT-7...APX133....c...........bff`.d... at n..d........@@a.. at 070027z4239.04N\07348.10W_000/000g000t064r000P000p000h53b10127XU2k.
+AGWPE: Got raw frame packet
+3:23
+Bad KISS packet. Dropping it.
+Total Length = 104
+HEX:00 00 00 00 4b 00 00 00 4e 31 45 44 5a 2d 37 00 01 00 54 52 31
+55 37 58 00 00 00 00 44 00 00 00 00 00 00 00
+
+c0 a8 a4 62 aa 6e b0 60
+9c 62 8a 88 b4 40 ee 96 82 62 a2 8c 8a fe ae 62 a8 9e 9a 40 fe 96 82
+64 a2 b2 8a f5 03 f0 60 64 2a 39 6c 23 22 3e 2f 3e 22 35 6b 7d 6e 31
+65 64 7a 40 61 6d 73 61 74 2e 6f 72 67 0d
+ASC:....K...N1EDZ-7...TR1U7X....D..........b.n.`.b... at ...b.....b...@...d......`d*9l#">/>"5k}n1edz at amsat.org.
+AGWPE: Got raw frame packet
+3:2e
+Bad KISS packet. Dropping it.
+Total Length = 103
+HEX:00 00 00 00 4b 00 00 00 4b 32 52 52 54 2d 39 00 01 00 41 50 54
+33 31 31 00 00 00 00 43 00 00 00 00 00 00 00
+
+c0 82 a0 a8 66 62 62 60
+96 64 a4 a4 a8 40 72 ae 82 64 aa 9a b0 e4 ae 92 88 8a 40 40 61 03 f0
+21 34 33 31 39 2e 37 39 4e 2f 30 37 33 34 30 2e 38 37 57 3e 32 36 38
+2f 30 32 30 2f 41 3d 30 30 30 34 38 35
+ASC:....K...K2RRT-9...APT311....C...........fbb`.d... at r..d........@@a..!4319.79N/07340.87W>268/020/A=000485
+AGWPE: Got raw frame packet
+3:74
+Bad KISS packet. Dropping it.
+Total Length = 82
+HEX:00 00 00 00 4b 00 00 00 4b 32 52 52 54 2d 39 00 01 00 41 50 54
+33 31 31 00 00 00 00 2e 00 00 00 00 00 00 00
+
+c0 82 a0 a8 66 62 62 60
+96 64 a4 a4 a8 40 72 ae 64 8e ae b2 40 e4 ae 82 64 aa 9a b0 e5 03 f0
+3e 6e 32 79 71 74 40 61 72 72 6c 2e 6e 65 74
+ASC:....K...K2RRT-9...APT311................fbb`.d... at r.d...@...d......>n2yqt at arrl.net
+AGWPE: Got raw frame packet
+3:2e
+Bad KISS packet. Dropping it.
+Total Length = 103
+HEX:00 00 00 00 4b 00 00 00 4b 32 52 52 54 2d 39 00 01 00 41 50 54
+33 31 31 00 00 00 00 43 00 00 00 00 00 00 00
+
+c0 82 a0 a8 66 62 62 60
+96 64 a4 a4 a8 40 72 ae 64 8e ae b2 40 e4 96 82 64 a2 b2 8a f5 03 f0
+21 34 33 31 39 2e 37 39 4e 2f 30 37 33 34 30 2e 38 37 57 3e 32 36 38
+2f 30 32 30 2f 41 3d 30 30 30 34 38 35
+ASC:....K...K2RRT-9...APT311....C...........fbb`.d... at r.d...@...d......!4319.79N/07340.87W>268/020/A=000485
+AGWPE: Got raw frame packet
+3:74
+Bad KISS packet. Dropping it.
+Total Length = 82
+HEX:00 00 00 00 4b 00 00 00 4b 32 52 52 54 2d 39 00 01 00 41 50 54
+33 31 31 00 00 00 00 2e 00 00 00 00 00 00 00
+
+c0 82 a0 a8 66 62 62 60
+96 64 a4 a4 a8 40 72 ae 64 8e ae b2 40 e4 96 82 64 a2 b2 8a f5 03 f0
+3e 6e 32 79 71 74 40 61 72 72 6c 2e 6e 65 74
+ASC:....K...K2RRT-9...APT311................fbb`.d... at r.d...@...d......>n2yqt at arrl.net
+AGWPE: Got raw frame packet
+3:2e
+Bad KISS packet. Dropping it.
+Total Length = 103
+HEX:00 00 00 00 4b 00 00 00 4b 32 52 52 54 2d 39 00 01 00 41 50 54
+33 31 31 00 00 00 00 43 00 00 00 00 00 00 00
+
+c0 82 a0 a8 66 62 62 60
+96 64 a4 a4 a8 40 72 ae 82 64 aa 9a b0 e4 96 82 64 a2 b2 8a f5 03 f0
+21 34 33 31 39 2e 37 39 4e 2f 30 37 33 34 30 2e 38 37 57 3e 32 36 38
+2f 30 32 30 2f 41 3d 30 30 30 34 38 35
+ASC:....K...K2RRT-9...APT311....C...........fbb`.d... at r..d......d......!4319.79N/07340.87W>268/020/A=000485
+*/
+
+
+// Parse an AGWPE header. Create a TAPR-2 style header out of the
+// data for feeding into the Xastir parsing code. Input format is
+// as follows:
+//
+// RadioPort 4 bytes (0-3)
+// DataType 4 bytes (4-7)
+// FromCall 10 bytes (8-17)
+// ToCall 10 bytes (18-27)
+// DataLength 4 bytes (28-31)
+// UserField 4 bytes (32-35)
+// Data xx bytes (36-??)
+//
+// Callsigns are null-terminated at end of string, but field width
+// is specified to be 10 bytes in all cases.
+//
+// output_string variable should be quite long, perhaps 1000
+// characters.
+//
+// Someday it would be nice to turn on raw packet format in AGWPE
+// which gives us the AX.25 packet format directly. We should be
+// able to use our normal KISS decoding functions to parse those
+// types of packets, instead of the mess we have below which is
+// parsing a few things out of the header, a few things out of the
+// text that AGWPE puts after the header, and then snagging the info
+// field of the packet from the tail-end.
+//
+unsigned char *parse_agwpe_packet(unsigned char *input_string,
+ int output_string_length,
+ unsigned char *output_string,
+ int *new_length) {
+ int ii, jj, kk;
+ char *info_ptr;
+ char *via_ptr;
+ char temp_str[512];
+ int special_debug = 0;
+ int data_length;
+
+
+ // Fetch the length of the data portion of the packet
+ data_length = (unsigned char)(input_string[31]);
+ data_length = (data_length << 8) + (unsigned char)(input_string[30]);
+ data_length = (data_length << 8) + (unsigned char)(input_string[29]);
+ data_length = (data_length << 8) + (unsigned char)(input_string[28]);
+
+ // Implementing some special debugging output for the case of
+ // third-party NWS messages, which so far haven't been parsed
+ // properly by this function.
+ //
+ // Check for NWS string past the header part of the AGWPE
+ // packet.
+ //
+
+// Check the data_length here to make sure we don't run off the end.
+// if (strstr(&input_string[36],"NWS-") || strstr(&input_string[36],"NWS_")) {
+// special_debug = 1;
+// }
+
+
+ // Make sure we have a terminating '\0' at the end.
+// Note that this doesn't help for binary packets (like OpenTrac),
+// but doesn't really hurt either.
+ input_string[38+data_length] = '\0';
+
+
+ // Check what sort of AGWPE packet it is.
+ switch (input_string[4]) {
+
+ case 'R':
+ //fprintf(stderr,"AGWPE: Got software version packet\n");
+ if (data_length == 8) {
+ fprintf(stderr,
+ "\nConnected to AGWPE server, version: %d.%d\n",
+ (input_string[37] << 8) + input_string[36],
+ (input_string[41] << 8) + input_string[40]);
+ }
+ return(NULL); // All done!
+ break;
+
+ case 'G':
+ //fprintf(stderr,"AGWPE: Got port information packet\n");
+
+ // Print out the data, changing all ';' characters to
+ // <CR> and a bunch of spaces to format it nicely.
+ fprintf(stderr, " Port Info, total ports = ");
+ ii = 36;
+ while (ii < data_length + 36 && input_string[ii] != '\0') {
+ if (input_string[ii] == ';')
+ fprintf(stderr, "\n ");
+ else
+ fprintf(stderr, "%c", input_string[ii]);
+ ii++;
+ }
+ fprintf(stderr,"\n");
+ return(NULL); // All done!
+ break;
+
+ case 'g':
+ //fprintf(stderr,"AGWPE: Got port capabilities packet\n");
+ return(NULL); // All done!
+ break;
+
+ case 'X':
+ //fprintf(stderr,"AGWPE: Got callsign registration results packet\n");
+ return(NULL); // All done!
+ break;
+
+ case 'y':
+ //fprintf(stderr,"AGWPE: Got outstanding frames on port packet\n");
+ return(NULL); // All done!
+ break;
+
+ case 'Y':
+ //fprintf(stderr,"AGWPE: Got outstanding frames on connection packet\n");
+ return(NULL); // All done!
+ break;
+
+ case 'H':
+ //fprintf(stderr,"AGWPE: Got heard stations on port packet\n");
+ return(NULL); // All done!
+ break;
+
+ case 'C':
+ //fprintf(stderr,"AGWPE: Got connection results packet\n");
+ return(NULL); // All done!
+ break;
+
+ case 'v':
+ //fprintf(stderr,"AGWPE: Got v packet\n");
+ return(NULL); // All done!
+ break;
+
+ case 'c':
+ //fprintf(stderr,"AGWPE: Got c packet\n");
+ return(NULL); // All done!
+ break;
+
+ case 'D':
+ //fprintf(stderr,"AGWPE: Got connected data packet\n");
+ return(NULL); // All done!
+ break;
+
+ case 'd':
+ //fprintf(stderr,"AGWPE: Got disconnection results packet\n");
+ return(NULL); // All done!
+ break;
+
+ case 'U':
+ //fprintf(stderr,"AGWPE: Got UI data packet\n");
+ // We can decode this one ok in the below code (after
+ // this switch statement), but we no longer use
+ // "monitor" mode packets in AGWPE, switching to the
+ // "raw" mode instead.
+ return(NULL); // All done!
+ break;
+
+ case 'I':
+ //fprintf(stderr,"AGWPE: Got connected information data packet\n");
+ return(NULL); // All done!
+ break;
+
+ case 'S':
+ //fprintf(stderr,"AGWPE: Got supervisory frame packet\n");
+ return(NULL); // All done!
+ break;
+
+ case 'T':
+ //fprintf(stderr,"AGWPE: Got our own transmitted packet back\n");
+ //fprintf(stderr, "%s\n", &input_string[37]);
+ // We should decode this one ok in the below code (after
+ // this switch statement), but we no longer use
+ // "monitor" mode packets in AGWPE, switching to the
+ // "raw" mode instead.
+ return(NULL); // All done!
+ break;
+
+ case 'K':
+ //fprintf(stderr,"AGWPE: Got raw frame packet\n");
+
+ // Code here processes the packet for handing to our
+ // KISS decoding routines. Chop off the header, add
+ // anything to the beginning/end that we need, then send
+ // it to decode_ax25_header().
+
+ // Try to decode header and checksum. If bad, break,
+ // else continue through to ASCII logging & decode
+ // routines. We skip the first byte as it's not part of
+ // the AX.25 packet.
+ //
+ // Note that the packet length often increases here in
+ // decode_ax25_header, as we add '*' characters and such
+ // to the header as it's decoded.
+
+ // This string already has a terminator on the end,
+ // added by the code in port_read(). If we didn't have
+ // one here, we could end up with portions of strings
+ // concatenated on the end of our string by the time
+ // we're done processing the data here.
+ //
+// input_string[data_length+36] = '\0';
+
+
+// WE7U:
+// We may need to extend input_string by a few characters before it
+// is fed to us. Something like max_callsigns * 3 or 4 characters,
+// to account for '*' and SSID characters that we might add. This
+// keeps the string from getting truncated as we add bytes to the
+// header in decode_ax25_header.
+
+
+ if ( !decode_ax25_header( (unsigned char *)&input_string[37], &data_length ) ) {
+// int zz;
+
+ // Had a problem decoding it. Drop it on the floor.
+ fprintf(stderr, "AGWPE: Bad KISS packet. Dropping it.\n");
+
+special_debug++;
+// for (zz = 0; zz < data_length; zz++) {
+// fprintf(stderr, "%02x ", input_string[zz+36]);
+// }
+// fprintf(stderr,"\n");
+
+ return(NULL);
+ }
+
+ // Good header. Compute the new length, again skipping
+ // the first byte.
+ data_length = strlen((const char *)&input_string[37]);
+
+// The above strlen() requires it to be printable ascii in the KISS
+// packet, so won't work for OpenTrac protocol or other binary
+// protocols. The decode_ax25_header() function also looks for
+// PID=0xF0, which again won't work for OpenTrac. It would be
+// better to have the decode_ax25_header routine return the new
+// length of the packet so that decoding of binary packets is still
+// possible.
+
+// Check for OpenTrac packets. If found, dump them into
+// OpenTrac-specific decode and skip the other decode below. Must
+// tweak the above stuff to allow binary-format packets to get
+// through to this point.
+
+ // Do more stuff with the packet here. The actual
+ // packet itself starts at offset 37. We can end up
+ // with 0x0d, 0x0d 0x0d, or 0x0d 0x00 0x0d on the end of
+ // it (or none of the above). Best method should be to
+ // just search for any 0x0d's or 0x0a's starting at the
+ // beginning of the string and overwrite them with
+ // 0x00's. That's what we do here.
+ //
+ for (ii = 0; ii < data_length; ii++) {
+ if (input_string[ii+37] == 0x0d
+ || input_string[ii+37] == 0x0a)
+ input_string[ii+37] = '\0';
+ }
+
+ // Compute data_length again.
+ data_length = strlen((const char *)&input_string[37]);
+
+ // Send the processed string back for decoding
+ xastir_snprintf((char *)output_string,
+ output_string_length,
+ "%s",
+ &input_string[37]);
+
+ // Send back the new length.
+ *new_length = data_length;
+
+ return(output_string);
+ break;
+
+ default:
+ fprintf(stderr,"AGWPE: Got unrecognized '%c' packet\n",input_string[4]);
+ return(NULL); // All done!
+ break;
+ }
+
+
+// NOTE: All of the code below gets used in "monitor" mode, which
+// we no longer use. We might keep this code around for a bit and
+// then delete it, as we've probably switched to "raw" mode for
+// good. "raw" mode allows us to use our KISS processing routines,
+// plus allows us to support digipeating and OpenTrac (binary)
+// protocol in the future.
+
+
+ if (special_debug) {
+ // Dump the hex & ascii representation of the whole packet
+
+ kk = data_length + 36; // Add the header length
+ fprintf(stderr, "Total Length = %d\n", kk);
+
+ fprintf(stderr, "HEX:");
+ for (ii = 0; ii < kk; ii++) {
+ fprintf(stderr, "%02x ", input_string[ii]);
+ }
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "ASC:");
+ for (ii = 0; ii < kk; ii++) {
+ if (input_string[ii] < ' ' || input_string[ii] > '~')
+ fprintf(stderr, ".");
+ else
+ fprintf(stderr, "%c", input_string[ii]);
+ }
+ fprintf(stderr, "\n");
+ }
+
+ // Clear the output_string (set to binary zeroes)
+ for (ii = 0; ii < output_string_length; ii++) {
+ output_string[ii] = '\0';
+ }
+
+ jj = 0;
+
+ // Copy the source callsign
+ ii = 8;
+ while (input_string[ii] != '\0') {
+ output_string[jj++] = input_string[ii++];
+ }
+
+ // Add a '>' character
+ output_string[jj++] = '>';
+
+ // Copy the destination callsign
+ ii = 18;
+ while (input_string[ii] != '\0') {
+ output_string[jj++] = input_string[ii++];
+ }
+
+ // Search for "]" (0x5d) which is the end of the header string,
+ // beginning of the AX.25 information field.
+ info_ptr = strstr((const char *)&input_string[36], "]");
+
+ // If not found, we can't process anymore
+ if (!info_ptr) {
+ output_string[0] = '\0';
+ new_length = 0;
+ return(NULL);
+ }
+
+ // Copy the first part of the string into a variable. We'll
+ // look for Via calls in this string, if present.
+ ii = 36;
+ temp_str[0] = '\0';
+
+ while (input_string[ii] != ']') {
+ strncat(temp_str, (char *)(&input_string[ii++]), 1);
+ }
+
+ // Make sure that the protocol ID is "F0". If not, return.
+ if (strstr(temp_str, "pid=F0") == NULL) {
+ char *pid_ptr;
+
+ // Look for the "pid=" string and print out what we can
+ // figure out about the protocol ID.
+ pid_ptr = strstr(temp_str, "pid=");
+ if (pid_ptr) {
+ pid_ptr +=4;
+ fprintf(stderr,
+ "parse_agwpe_packet: Non-APRS protocol was seen: PID=%2s. Dropping the packet.\n",
+ pid_ptr);
+ }
+ else {
+ fprintf(stderr,
+ "parse_agwpe_packet: Non-APRS protocol was seen. Dropping the packet.\n");
+ }
+ output_string[0] = '\0';
+ new_length = 0;
+ return(NULL);
+ }
+
+ // Search for "Via" in temp_str
+ via_ptr = strstr(temp_str, "Via");
+
+ if (via_ptr) {
+ // Found some Via calls. Copy them into our output string.
+
+ // Add a comma first
+ output_string[jj++] = ',';
+
+ // Skip past "Via " portion of string
+ via_ptr += 4;
+
+ // Copy the string across until we hit a space
+ while (via_ptr[0] != ' ') {
+ output_string[jj++] = via_ptr[0];
+ via_ptr++;
+ }
+ }
+
+ // Add a ':' character
+ output_string[jj++] = ':';
+
+ // Move the pointer past the "]<CR>" to the real info part of the
+ // packet.
+ info_ptr++;
+ info_ptr++;
+
+ // Copy the info field to the output string
+ while (info_ptr[0] != '\0') {
+ strncat((char *)output_string, &info_ptr[0], 1);
+ info_ptr++;
+ }
+
+ // We end up with 0x0d characters on the end. Get rid of them.
+ // The strtok() function will overwrite the first one found with
+ // a '\0' character.
+ (void)strtok((char *)output_string, "\n");
+ (void)strtok((char *)output_string, "\r");
+
+ *new_length = strlen((const char *)output_string);
+
+ if (special_debug) {
+ // Print out the resulting string
+ fprintf(stderr,"AGWPE RX: %s\n", output_string);
+ fprintf(stderr,"new_length: %d\n",*new_length);
+ for (ii = 0; ii < (int)strlen((const char *)output_string); ii++) {
+ fprintf(stderr,"%02x ",output_string[ii]);
+ }
+ fprintf(stderr,"\n");
+ }
+
+ return(output_string);
+}
+
+/*
+Found complete AGWPE packet, 93 bytes total in frame:
+00 00 00 00
+55 00 00 00 'U' Packet
+57 45 37 55 2d 33 00 00 ff ff WE7U-3
+41 50 52 53 00 20 ec e9 6c 00 APRS
+39 00 00 00 Length
+00 00 00 00
+
+20 31 .1 (36-37)
+3a 46 6d 20 :Fm (38-41)
+57 45 37 55 2d 33 WE7U-3 (42-space)
+20 54 6f .To
+20 41 50 52 53 .APRS
+20 3c 55 49 .<UI
+20 70 69 64 3d 46 30 .pid=F0
+20 4c 65 6e 3d 34 .Len=4
+20 3e 5b 32 33 3a 31 33 3a 32 30 5d 0d >[23:13:20].
+54 65 73 74 0d 0d 00 Test<CR><CR>.
+....U...WE7U-3....APRS. ..l.9....... 1:Fm WE7U-3 To APRS <UI pid=F0 Len=4 >[23:13:20].Test...
+
+1:Fm WE7U-3 To APRS Via RELAY,SAR1-1,SAR2-1,SAR3-1,SAR4-1,SAR5-1,SAR6-1,SAR7-1 <UI pid=F0 Len=26 >[23:51:46].Testing this darned thing!...
+*/
+
+
+
+
+
+//****************************************************************
+// get device name only (the portion at the end of the full path)
+// device_name current full name of device
+//****************************************************************
+
+char *get_device_name_only(char *device_name) {
+ int i,len,done;
+
+ if (device_name == NULL)
+ return(NULL);
+
+ done = 0;
+ len = (int)strlen(device_name);
+ for(i = len; i > 0 && !done; i--){
+ if(device_name[i] == '/'){
+ device_name += (i+1);
+ done = 1;
+ }
+ }
+ return(device_name);
+}
+
+
+
+
+
+//***********************************************************
+// Get Open Device
+//
+// if device is available this will return the port #
+// otherwise a -1 will be returned in error.
+//***********************************************************
+int get_open_device(void) {
+ int i, found;
+
+begin_critical_section(&devices_lock, "interface.c:get_open_device" );
+
+ found = -1;
+ for(i = 0; i < MAX_IFACE_DEVICES && found == -1; i++) {
+ if (devices[i].device_type == DEVICE_NONE){
+ found = i;
+ break;
+ }
+ }
+
+end_critical_section(&devices_lock, "interface.c:get_open_device" );
+
+ if (found == -1)
+ popup_message(langcode("POPEM00004"),langcode("POPEM00017"));
+
+ return(found);
+}
+
+
+
+
+
+//***********************************************************
+// Get Device Status
+//
+// this will return the device status for the port specified
+//***********************************************************
+int get_device_status(int port) {
+ int stat;
+
+ if (begin_critical_section(&port_data_lock, "interface.c:get_device_status(1)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ stat = port_data[port].status;
+
+ if (end_critical_section(&port_data_lock, "interface.c:get_device_status(2)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ return(stat);
+}
+
+
+
+
+
+//***********************************************************
+// channel_data()
+//
+// Takes data read in from a port and adds it to the
+// incoming_data_queue. If queue is full, waits for queue to have
+// space before continuing.
+//
+// port #
+// string is the string of data
+// length is the length of the string. If 0 then use strlen()
+// on the string itself to determine the length.
+//
+// Note that decode_ax25_header() and perhaps other routines may
+// increase the length of the string while processing. We need to
+// send a COPY of our input string off to the decoding routines for
+// this reason, and the size of the buffer must be MAX_LINE_SIZE
+// for this reason also.
+//***********************************************************
+void channel_data(int port, unsigned char *string, volatile int length) {
+ int max;
+ struct timeval tmv;
+ // Some messiness necessary because we're using xastir_mutex's
+ // instead of pthread_mutex_t's.
+ pthread_mutex_t *cleanup_mutex1;
+ pthread_mutex_t *cleanup_mutex2;
+ int process_it = 0;
+
+
+ //fprintf(stderr,"channel_data: %x %d\n",string[0],length);
+
+ // Save backup copies of the incoming string and the previous
+ // string. Used for debugging purposes. If we get a segfault,
+ // we can print out the last two messages received.
+ xastir_snprintf((char *)incoming_data_copy_previous,
+ sizeof(incoming_data_copy_previous),
+ "%s",
+ incoming_data_copy);
+ xastir_snprintf((char *)incoming_data_copy,
+ sizeof(incoming_data_copy),
+ "Port%d:%s",
+ port,
+ string);
+
+ max = 0;
+
+ if (string == NULL)
+ return;
+
+ if (string[0] == '\0')
+ return;
+
+ if (length == 0) {
+ // Compute length of string including terminator
+ length = strlen((const char *)string) + 1;
+//fprintf(stderr,"Computing length with strlen, port %d\n", port);
+ }
+
+ // Check for excessively long packets. These might be TCP/IP
+ // packets or concatenated APRS packets. In any case it's some
+ // kind of garbage that we don't want to try to parse.
+
+ // Note that for binary data (WX stations and KISS packets), the
+ // strlen() function may not work correctly.
+ if (length > MAX_LINE_SIZE) { // Too long!
+ if (debug_level & 1) {
+ fprintf(stderr,"\nchannel_data: LONG packet:%d, Dumping it:\n%s\n",
+ length,
+ string);
+ }
+
+ string[0] = '\0'; // Truncate it to zero length
+ return;
+ }
+
+
+ // Install the cleanup routine for the case where this thread
+ // gets killed while the mutex is locked. The cleanup routine
+ // initiates an unlock before the thread dies. We must be in
+ // deferred cancellation mode for the thread to have this work
+ // properly. We must first get the pthread_mutex_t address:
+ cleanup_mutex1 = &output_data_lock.lock;
+
+ // Then install the cleanup routine:
+ pthread_cleanup_push((void *)pthread_mutex_unlock, (void *)cleanup_mutex1);
+// pthread_cleanup_push(void (*pthread_mutex_unlock)(void *), (void *)cleanup_mutex1);
+
+
+ // This protects channel_data from being run by more than one
+ // thread at the same time.
+ if (begin_critical_section(&output_data_lock, "interface.c:channel_data(1)" ) > 0)
+ fprintf(stderr,"output_data_lock, Port = %d\n", port);
+
+
+ if (length > 0) {
+
+
+ // Install the cleanup routine for the case where this
+ // thread gets killed while the mutex is locked. The
+ // cleanup routine initiates an unlock before the thread
+ // dies. We must be in deferred cancellation mode for the
+ // thread to have this work properly. We must first get the
+ // pthread_mutex_t address.
+ cleanup_mutex2 = &data_lock.lock;
+
+ // Then install the cleanup routine:
+ pthread_cleanup_push((void *)pthread_mutex_unlock, (void *)cleanup_mutex2);
+// pthread_cleanup_push(void (*pthread_mutex_unlock)(void *), (void *)cleanup_mutex2);
+
+
+// if (begin_critical_section(&data_lock, "interface.c:channel_data(2)" ) > 0)
+// fprintf(stderr,"data_lock, Port = %d\n", port);
+
+
+ // If it's any of three types of GPS ports and is a GPRMC or
+ // GPGGA string, just stick it in one of two global
+ // variables for holding such strings. UpdateTime() can
+ // come along and process/clear-out those strings at the
+ // gps_time interval.
+ //
+ switch(port_data[port].device_type) {
+
+ case DEVICE_SERIAL_GPS:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_NET_GPSD:
+
+ // One of the three types of interfaces that might
+ // send in a lot of GPS data constantly. Save only
+ // GPRMC and GPGGA strings into global variables.
+ // Drop other GPS strings on the floor.
+ //
+ if ( (length > 7) && (strncmp((char *)string,"$GPRMC,",7) == 0) ) {
+ xastir_snprintf(gprmc_save_string,
+ sizeof(gprmc_save_string),
+ "%s",
+ string);
+ gps_port_save = port;
+ process_it = 0;
+ }
+ else if ( (length > 7) && (strncmp((char *)string,"$GPGGA,",7) == 0) ) {
+ xastir_snprintf(gpgga_save_string,
+ sizeof(gpgga_save_string),
+ "%s",
+ string);
+ gps_port_save = port;
+ process_it = 0;
+ }
+ else {
+ // It's not one of the GPS strings we're looking
+ // for. It could be another GPS string, a
+ // partial GPS string, or a full/partial TNC
+ // string. Drop the string on the floor unless
+ // it's an HSP interface.
+ //
+ if (port_data[port].device_type == DEVICE_SERIAL_TNC_HSP_GPS) {
+ // Decode the string normally.
+ process_it++;
+ //fprintf(stderr,"data_avail\n");
+ }
+ }
+ break;
+// We need to make sure that the variables stating that a string is
+// available are reset in any case. Look at how/where data_avail is
+// reset. We may not care if we just wait for data_avail to be
+// cleared before writing to the string again.
+
+ default: // Not one of the above three types, decode
+ // the string normally.
+ process_it++;
+ //fprintf(stderr,"data_avail\n");
+ break;
+ }
+
+
+// if (end_critical_section(&data_lock, "interface.c:channel_data(3)" ) > 0)
+// fprintf(stderr,"data_lock, Port = %d\n", port);
+
+ // Remove the cleanup routine for the case where this thread
+ // gets killed while the mutex is locked. The cleanup
+ // routine initiates an unlock before the thread dies. We
+ // must be in deferred cancellation mode for the thread to
+ // have this work properly.
+//
+// NOTE: Ignore the four \"suggest braces\" warnings you see when
+// compiling, see: http://archive.netbsd.se/?ml=gcc-help&a=2008-06&t=7730779
+//
+ pthread_cleanup_pop(0);
+
+
+ if (debug_level & 1)
+ fprintf(stderr,"Channel data on Port %d [%s]\n",port,(char *)string);
+
+ if (process_it) {
+
+ // Wait for empty space in queue
+//fprintf(stderr,"\n== %s", string);
+ while (push_incoming_data(string, length, port) && max < 5400) {
+ sched_yield(); // Yield to other threads
+ tmv.tv_sec = 0;
+ tmv.tv_usec = 2; // 2 usec
+ (void)select(0,NULL,NULL,NULL,&tmv);
+ max++;
+ }
+ }
+ }
+
+
+ if (end_critical_section(&output_data_lock, "interface.c:channel_data(4)" ) > 0)
+ fprintf(stderr,"output_data_lock, Port = %d\n", port);
+
+ // Remove the cleanup routine for the case where this thread
+ // gets killed while the mutex is locked. The cleanup routine
+ // initiates an unlock before the thread dies. We must be in
+ // deferred cancellation mode for the thread to have this work
+ // properly.
+//
+// NOTE: Ignore the four \"suggest braces\" warnings you see when
+// compiling, see: http://archive.netbsd.se/?ml=gcc-help&a=2008-06&t=7730779
+//
+ pthread_cleanup_pop(0);
+}
+
+
+
+
+
+//********************************* START AX.25 ********************************
+
+#ifdef HAVE_LIBAX25
+// stolen from libax25-0.0.9 and modified to set digipeated bit based on '*'
+int my_ax25_aton_arglist(char *call[], struct full_sockaddr_ax25 *sax)
+{
+ char *bp;
+ char *addrp;
+ int n = 0;
+ int argp = 0;
+ int len = 0;
+ int star = 0;
+
+ addrp = sax->fsa_ax25.sax25_call.ax25_call;
+
+ do {
+ /* Fetch one callsign token */
+ if ((bp = call[argp++]) == NULL)
+ break;
+
+ /* Check for the optional 'via' syntax */
+ if (n == 1 && (strcasecmp(bp, "V") == 0 || strcasecmp(bp, "VIA") == 0))
+ continue;
+
+ /* Process the token (Removes the star before the ax25_aton_entry call
+ because it would call it a bad callsign.) */
+ len = strlen(bp);
+ if (len > 1 && bp[len-1] == '*') {
+ star = 1;
+ bp[len-1] = '\0';
+ }
+ else {
+ star = 0;
+ }
+ if (ax25_aton_entry(bp, addrp) == -1) {
+ popup_message("Bad callsign!", bp);
+ return -1;
+ }
+ if (n >= 1 && star) {
+ addrp[6] |= 0x80; // set digipeated bit if we had found a star
+ }
+
+ n++;
+
+ if (n == 1)
+ addrp = sax->fsa_digipeater[0].ax25_call; /* First digipeater address */
+ else
+ addrp += sizeof(ax25_address);
+
+ } while (n < AX25_MAX_DIGIS && call[argp] != NULL);
+
+ /* Tidy up */
+ sax->fsa_ax25.sax25_ndigis = n - 1;
+ sax->fsa_ax25.sax25_family = AF_AX25;
+
+ return sizeof(struct full_sockaddr_ax25);
+}
+#endif // HAVE_LIBAX25
+
+
+
+
+
+//***********************************************************
+// ui connect: change call and proto paths and reconnect net
+// port device to work with
+//***********************************************************
+int ui_connect( int port, char *to[]) {
+ int s = -1;
+#ifdef HAVE_LIBAX25
+ int sockopt;
+ int addrlen = sizeof(struct full_sockaddr_ax25);
+ struct full_sockaddr_ax25 axbind, axconnect;
+ /* char *arg[2]; */
+ char *portcall;
+ char temp[200];
+
+ if (to == NULL)
+ return(-1);
+
+ if (to[0] == '\0')
+ return(-1);
+
+ /*
+ * Handle incoming data
+ *
+ * Parse the passed values for correctness.
+ */
+
+ axconnect.fsa_ax25.sax25_family = AF_AX25;
+ axbind.fsa_ax25.sax25_family = AF_AX25;
+ axbind.fsa_ax25.sax25_ndigis = 1;
+
+ if ((portcall = ax25_config_get_addr(port_data[port].device_name)) == NULL) {
+ xastir_snprintf(temp, sizeof(temp), langcode("POPEM00005"),
+ port_data[port].device_name);
+ popup_message(langcode("POPEM00004"),temp);
+ return -1;
+ }
+ if (ax25_aton_entry(portcall, axbind.fsa_digipeater[0].ax25_call) == -1) {
+ xastir_snprintf(temp, sizeof(temp), langcode("POPEM00006"),
+ port_data[port].device_name);
+ popup_message(langcode("POPEM00004"), temp);
+ return -1;
+ }
+
+ if (ax25_aton_entry(port_data[port].ui_call, axbind.fsa_ax25.sax25_call.ax25_call) == -1) {
+ xastir_snprintf(temp, sizeof(temp), langcode("POPEM00007"), port_data[port].ui_call);
+ popup_message(langcode("POPEM00004"),temp);
+ return -1;
+ }
+
+ if (my_ax25_aton_arglist(to, &axconnect) == -1) {
+ popup_message(langcode("POPEM00004"),langcode("POPEM00008"));
+ return -1;
+ }
+
+ /*
+ * Open the socket into the kernel.
+ */
+
+ if ((s = socket(AF_AX25, SOCK_DGRAM, 0)) < 0) {
+ xastir_snprintf(temp, sizeof(temp), langcode("POPEM00009"), strerror(errno));
+ popup_message(langcode("POPEM00004"),temp);
+ return -1;
+ }
+
+ /*
+ * Set our AX.25 callsign and AX.25 port callsign accordingly.
+ */
+ ENABLE_SETUID_PRIVILEGE;
+ if (bind(s, (struct sockaddr *)&axbind, addrlen) != 0) {
+ DISABLE_SETUID_PRIVILEGE;
+ xastir_snprintf(temp, sizeof(temp), langcode("POPEM00010"), strerror(errno));
+ popup_message(langcode("POPEM00004"),temp);
+ return -1;
+ }
+ DISABLE_SETUID_PRIVILEGE;
+
+ if (devices[port].relay_digipeat)
+ sockopt = 1;
+ else
+ sockopt = 0;
+
+ if (setsockopt(s, SOL_AX25, AX25_IAMDIGI, &sockopt, sizeof(int))) {
+ fprintf(stderr,"AX25 IAMDIGI setsockopt FAILED");
+ return -1;
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"*** Connecting to UNPROTO port for transmission...\n");
+
+ /*
+ * Lets try and connect to the far end.
+ */
+
+ if (connect(s, (struct sockaddr *)&axconnect, addrlen) != 0) {
+ xastir_snprintf(temp, sizeof(temp), langcode("POPEM00011"), strerror(errno));
+ popup_message(langcode("POPEM00004"),temp);
+ return -1;
+ }
+
+ /*
+ * We got there.
+ */
+#endif /* HAVE_LIBAX25 */
+ return s;
+}
+
+
+
+
+
+//************************************************************
+// data_out_ax25()
+//
+// Send string data out ax25 port
+//************************************************************
+
+static void data_out_ax25(int port, unsigned char *string) {
+ static char ui_mycall[10];
+ char *temp;
+ char *to[10];
+ int quantity;
+
+ if (string == NULL)
+ return;
+
+ if (string[0] == '\0')
+ return;
+
+ if (begin_critical_section(&port_data_lock, "interface.c:data_out_ax25(1)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ // Check for commands (start with Control-C)
+ if (string[0] == (unsigned char)3) { // Yes, process TNC type commands
+
+ // Look for MYCALL command
+ if (strncmp((char *)&string[1],"MYCALL", 6) == 0) {
+
+ // Found MYCALL. Snag the callsign and put it into the
+ // structure for the port
+
+ // Look for whitespace/CR/LF (end of "MYCALL")
+ temp = strtok((char *)&string[1]," \t\r\n");
+ if (temp != NULL) {
+
+ // Look for whitespace/CR/LF (after callsign)
+ temp = strtok(NULL," \t\r\n");
+ if (temp != NULL) {
+ substr(ui_mycall, temp, 9);
+ xastir_snprintf(port_data[port].ui_call,
+ sizeof(port_data[port].ui_call),
+ "%s",
+ ui_mycall);
+ if (debug_level & 2)
+ fprintf(stderr,"*** MYCALL %s\n",port_data[port].ui_call);
+ }
+ }
+ }
+
+ // Look for UNPROTO command
+ else if (strncmp((char *)&string[1],"UNPROTO", 6) == 0) {
+ quantity = 0; // Number of callsigns found
+
+ // Look for whitespace/CR/LF (end of "UNPROTO")
+ temp = strtok((char *)&string[1]," \t\r\n");
+ if (temp != NULL) { // Found end of "UNPROTO"
+
+ // Find first callsign (destination call)
+ temp = strtok(NULL," \t\r\n");
+ if (temp != NULL) {
+ to[quantity++] = temp; // Store it
+ //fprintf(stderr,"Destination call: %s\n",temp);
+
+ // Look for "via" or "v"
+ temp = strtok(NULL," \t\r\n");
+ //fprintf(stderr,"Via: %s\n",temp);
+
+ while (temp != NULL) { // Found it
+ // Look for the rest of the callsigns (up to
+ // eight of them)
+ temp = strtok(NULL," ,\t\r\n");
+ if (temp != NULL) {
+ //fprintf(stderr,"Call: %s\n",temp);
+ if (quantity < 9) {
+ to[quantity++] = temp;
+ }
+ }
+ }
+ to[quantity] = NULL;
+
+ if (debug_level & 2) {
+ int i = 1;
+
+ fprintf(stderr,"UNPROTO %s VIA ",*to);
+ while (to[i] != NULL)
+ fprintf(stderr,"%s,",to[i++]);
+ fprintf(stderr,"\n");
+ }
+
+ if (port_data[port].channel2 != -1) {
+ if (debug_level & 2)
+ fprintf(stderr,"Write DEVICE is UP! Taking it down to reconfigure UI path.\n");
+
+ (void)close(port_data[port].channel2);
+ port_data[port].channel2 = -1;
+ }
+
+ if ((port_data[port].channel2 = ui_connect(port,to)) < 0) {
+ popup_message(langcode("POPEM00004"),langcode("POPEM00012"));
+ port_data[port].errors++;
+ }
+ else { // Port re-opened and re-configured
+ if (debug_level & 2)
+ fprintf(stderr,"WRITE port re-opened after UI path change\n");
+ }
+ }
+ }
+ }
+ }
+
+ // Else not a command, write the data directly out to the port
+ else {
+ if (debug_level & 2)
+ fprintf(stderr,"*** DATA: %s\n",(char *)string);
+
+ if (port_data[port].channel2 != -1)
+ (void)write(port_data[port].channel2, string, strlen((char *)string));
+ else if (debug_level & 2)
+ fprintf(stderr,"\nPort down for writing!\n\n");
+ }
+
+ if (end_critical_section(&port_data_lock, "interface.c:data_out_ax25(2)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+}
+
+
+
+
+
+// fetch16bits
+//
+// Modifies: Nothing.
+//
+int fetch16bits(unsigned char *str) {
+ int i;
+
+
+ i = *str++;
+ i = i << 8;
+ i = i | *str++;
+ return(i);
+}
+
+
+
+
+
+// fetch32bits
+//
+// Modifies: Nothing.
+//
+int fetch32bits(unsigned char *str) {
+ int i;
+
+
+ i = *str++;
+ i = i << 8;
+ i = i | *str++;
+ i = i << 8;
+ i = i | *str++;
+ i = i << 8;
+ i = i | *str;
+ return(i);
+}
+
+
+
+
+
+// 0x00 Sequence number - 16 bit integer
+//
+// Modifies: sequence
+//
+int OpenTrac_decode_sequence(unsigned char *element,
+ int element_len,
+ unsigned int *sequence) {
+
+ if (element_len != 2 && element_len != 0)
+ return -1;
+
+ // No sequence number, increment by one
+ if (element_len == 0) {
+ *sequence = *sequence + 1;
+ }
+ else {
+ *sequence = fetch16bits(element);
+ }
+
+ fprintf(stderr,"Sequence: %d\n",*sequence);
+
+ return 0;
+}
+
+
+
+
+
+// 0x01 Originating Station - Callsign, SSID, Sequence, and Network
+//
+// Modifies: sequence
+// callsign
+// ssid
+// network
+//
+int OpenTrac_decode_origination(unsigned char *element,
+ int element_len,
+ unsigned int *sequence,
+ char *callsign,
+ unsigned char *ssid,
+ unsigned char *network) {
+ unsigned char c;
+
+
+ if (element_len < 6)
+ return -1;
+
+ if (element_len > 8)
+ return -1;
+
+ // Binary routine. strncpy is ok here as long as nulls not in
+ // data. We null-terminate it ourselves to make sure it is
+ // terminated.
+ strncpy(callsign, (char *)element, 6);
+ callsign[6]=0;
+ for (c=*ssid=0;c<6;c++) {
+ *ssid |= (callsign[c] & 0x80) >> (c+2);
+ callsign[c] &= 0x7f;
+ }
+
+ *sequence = fetch16bits(element+6);
+ if (element_len == 9) {
+ *network = *(element+8);
+
+ fprintf(stderr, "Origin: %s-%d seq %d net %d\n",
+ callsign,
+ *ssid,
+ *sequence,
+ *network);
+ }
+ else {
+ fprintf(stderr, "Origin: %s-%d seq %d direct\n",
+ callsign,
+ *ssid,
+ *sequence);
+ }
+
+ return 0;
+}
+
+
+
+
+
+// Strip the SSID from the callsign and return it
+//
+// Modifies: call (Strips top bit from each char)
+//
+int OpenTrac_extract_ssid(unsigned char *call) {
+ int c, ssid;
+
+
+ for (c=ssid=0;c<6;c++) {
+ ssid |= (call[c] & 0x80) >> (c+2);
+ call[c] &= 0x7f;
+ }
+
+ return ssid;
+}
+
+
+
+
+
+// 0x02 Entity ID
+//
+// Modifies: entity_call
+// entity_ssid
+// entity_serial
+// entity_sequence
+//
+int OpenTrac_decode_entityid(unsigned char *element,
+ int element_len,
+ unsigned char *origin_call,
+ unsigned char origin_ssid,
+ unsigned char *entity_call,
+ unsigned char *entity_ssid,
+ unsigned int *entity_serial,
+ unsigned int *entity_sequence) {
+
+ if (element_len > 10) {
+ return -1;
+ }
+ else if (element_len > 5) {
+ memcpy(entity_call, element, 6);
+ entity_call[6]=0;
+ *entity_ssid = OpenTrac_extract_ssid(entity_call);
+ }
+ else { // Not enough, so use origin_call instead
+ xastir_snprintf((char *)entity_call,
+ 10,
+ "%s",
+ origin_call);
+ *entity_ssid = origin_ssid;
+ }
+
+ switch (element_len) {
+ case 0:
+ *entity_serial = *entity_serial + 1;
+ *entity_sequence = 0;
+ break;
+ case 2:
+ *entity_serial = fetch16bits(element);
+ *entity_sequence = 0;
+ break;
+ case 4:
+ *entity_serial = fetch16bits(element);
+ *entity_sequence = fetch16bits(element+2);
+ break;
+ case 6:
+ *entity_serial = 0;
+ break;
+ case 8:
+ *entity_serial = fetch16bits(element+6);
+ *entity_sequence = 0;
+ break;
+ case 10:
+ *entity_serial = fetch16bits(element+6);
+ *entity_sequence = fetch16bits(element+8);
+ break;
+ default:
+ *entity_sequence = 0;
+ *entity_serial = *entity_serial + 1;
+ break;
+ }
+
+ fprintf(stderr, "Entity %s-%d:%04x #%d\n",
+ entity_call,
+ *entity_ssid,
+ *entity_serial,
+ *entity_sequence);
+
+ return 0;
+}
+
+
+
+
+
+// 0x10 Position Report - Lat/Lon/<Alt>
+// Lat/Lon is WGS84, 180/2^31 degrees, Alt is 1/100 meter
+//
+// Modifies: lat
+// lon
+// alt
+//
+int OpenTrac_decode_position(unsigned char *element,
+ int element_len,
+ double *lat,
+ double *lon,
+ float *alt) {
+
+ const double semicircles = 11930464.71111111111;
+
+
+ if (element_len < 8)
+ return -1; // Too short!
+
+ if (element_len > 11)
+ return -1; // Too long!
+
+ *lat = fetch32bits(element) / semicircles;
+ *lon = fetch32bits(element+4) / semicircles;
+
+ if (element_len == 11) {
+ *alt = ( (*(element+8))<<16 ) + fetch16bits(element+9);
+ *alt = (*alt / 100) - 10000;
+ }
+
+ fprintf(stderr, "Position: Lat %f Lon %f Alt %f\n",*lat,*lon,*alt);
+
+ return 0;
+}
+
+
+
+
+
+// 0x11 Timestamp - Unix format time (unsigned)
+//
+// Modifies: rawtime
+//
+int OpenTrac_decode_timestamp(unsigned char *element,
+ int element_len,
+ long *rawtime) {
+ time_t rawtime_t;
+
+
+ *rawtime = 0;
+
+ if (element_len != 4)
+ return -1;
+
+ *rawtime = fetch32bits(element);
+
+ rawtime_t = (time_t)rawtime;
+
+ fprintf(stderr, "Time: %s", ctime(&rawtime_t));
+
+ return 0;
+}
+
+
+
+
+
+// 0x12 Freeform Comment - ASCII text
+//
+// Modifies: comment
+//
+int OpenTrac_decode_comment(unsigned char *element,
+ int element_len,
+ char *comment) {
+
+ if (element_len > 126)
+ return -1; // shouldn't be possible
+
+ strncat(comment," ",1);
+ strncat(comment, (char *)element, element_len);
+ comment[element_len + 1] = 0; // Account for the space char
+
+ fprintf(stderr, "Text: %s\n", comment);
+
+ return 0;
+}
+
+
+
+
+
+// 0x13 Course and Speed - Course in degrees, speed in 1/50 m/s
+//
+// Modifies: course (degrees true)
+// speed (kph)
+//
+int OpenTrac_decode_courseandspeed(unsigned char *element,
+ int element_len,
+ int *course,
+ float *speed) {
+ int rawspeed;
+
+
+ if (element_len != 3)
+ return -1;
+
+ *course = ( (*element) << 1 ) + ( (*(element+1) & 0x80) >> 7);
+ rawspeed = fetch16bits(element+1) & 0x7fff;
+ *speed = (float)(rawspeed * 0.072); // kph
+
+ fprintf(stderr, "Course: %d Speed: %f kph\n", *course, *speed);
+
+ return 0;
+}
+
+
+
+
+
+// 0x14 Positional Ambiguity - 16 bits, in meters
+//
+// Modifies: ambiguity
+//
+int OpenTrac_decode_ambiguity(unsigned char *element,
+ int element_len,
+ int *ambiguity) {
+
+ if (element_len != 2)
+ return -1;
+
+ *ambiguity = fetch16bits(element);
+
+ fprintf(stderr, "Position +/- %d meters\n", *ambiguity);
+
+ return 0;
+}
+
+
+
+
+
+// 0x15 Country Code - ISO 3166-1 and optionally -2
+//
+// Modifies: country
+// subdivision
+//
+int OpenTrac_decode_country(unsigned char *element,
+ int element_len,
+ char *country,
+ char *subdivision) {
+
+ if (element_len < 2)
+ return -1;
+
+ if (element_len > 5)
+ return -1;
+
+ // Binary routine. strncpy is ok here as long as nulls not in
+ // data. We null-terminate it ourselves to make sure it is
+ // terminated.
+ strncpy(country, (char *)element, 2);
+ country[2] = 0;
+ if (element_len > 2) {
+ // Binary routine. strncpy is ok here as long as nulls not
+ // in data. We null-terminate it ourselves to make sure it
+ // is terminated.
+ strncpy(subdivision, (char *)(element+2), element_len-2);
+ subdivision[element_len-2] = 0;
+ fprintf(stderr, "Country Code %s-%s\n", country, subdivision);
+ }
+ else {
+ fprintf(stderr, "Country Code %s\n", country);
+ }
+ return 0;
+}
+
+
+
+
+
+// 0x16 Display Name (UTF-8 text)
+//
+// Modifies: displayname
+//
+int OpenTrac_decode_displayname(unsigned char *element,
+ int element_len,
+ char *displayname) {
+
+ if (element_len > 30 || !element_len)
+ return -1;
+
+ // Binary routine. strncpy is ok here as long as nulls not in
+ // data. We null-terminate it ourselves to make sure it is
+ // terminated.
+ strncpy(displayname, (char *)element, element_len);
+ displayname[element_len] = 0;
+
+ fprintf(stderr, "Display Name: %s\n", displayname);
+ return 0;
+}
+
+
+
+
+
+// 0x17 Waypoint Name (up to 6 chars, uppercase)
+//
+// Modifies: waypoint
+//
+int OpenTrac_decode_waypoint(unsigned char *element,
+ int element_len,
+ char *waypoint) {
+
+ if (element_len > 6 || !element_len)
+ return -1;
+
+ // Binary routine. strncpy is ok here as long as nulls not in
+ // data. We null-terminate it ourselves to make sure it is
+ // terminated.
+ strncpy(waypoint, (char *)element, element_len);
+ waypoint[element_len] = 0;
+
+ fprintf(stderr, "Waypoint Name: %s\n", waypoint);
+
+ return 0;
+}
+
+
+
+
+
+// Mapping between OpenTrac symbols and APRS symbols
+char symbol_translate[100][14] = {
+ "3 11100000 /S", // space shuttle
+ "3 12100000 \\S", // satellite
+ "1 10000000 \\S", // *** other space
+ "2 21000000 /O", // balloon
+ "4 22120000 /g", // glider
+ "3 22100000 /'", // small plane
+ "3 22200000 /^", // large aircraft
+ "3 22300000 /^", // large aircraft
+ "2 23000000 /X", // helicopter
+ "1 20000000 /'", // *** other air
+ "4 31310000 /h", // hospital
+ "4 31340000 /A", // aid station
+ "4 31350000 \\X", // pharmacy
+ "4 31410000 /d", // fire station
+ "4 31440000 /o", // EOC
+ "4 31460000 /+", // red cross
+ "4 31620000 \\h", // ham store
+ "3 31700000 /-", // house
+ "3 31800000 \\+", // church
+ "4 31910000 /H", // hotel
+ "4 31920000 \\9", // gas station
+ "4 31930000 \\R", // restaurant
+ "4 31940000 \\?", // information
+ "4 31950000 \\P", // parking
+ "4 31960000 /t", // truck stop
+ "4 31970000 \\r", // restrooms
+ "4 31980000 \\$", // bank/atm
+ "3 31a00000 /K", // school
+ "4 31c10000 /,", // boy scouts
+ "4 31c20000 \\,", // girl scouts
+ "4 31d10000 \\;", // park/picnic area
+ "4 31d20000 \\;", // park/picnic area
+ "4 31d30000 /;", // campground
+ "5 31e13000 \\V", // VORTAC
+ "5 31f12000 /$", // phone
+ "5 32111000 />", // car
+ "5 32112000 /v", // van
+ "5 32113000 /k", // truck
+ "5 32114000 /j", // jeep
+ "5 32115000 /R", // rv
+ "5 32116000 /<", // motorcycle
+ "5 32117000 /b", // bicycle
+ "5 32121000 /u", // 18-wheeler
+ "5 32122000 /U", // bus
+ "5 32131000 /=", // railroad engine
+ "5 32141000 /*", // snowmobile
+ "5 32161000 /!", // police
+ "5 32162000 /a", // ambulance
+ "5 32163000 /f", // fire truck
+ "3 33100000 /(", // sat station
+ "1 30000000 //", // *** other ground
+ "3 41200000 /s", // ship
+ "4 41510000 /C", // canoe
+ "4 41520000 /C", // canoe (kayak)
+ "4 41540000 /Y", // yacht
+ "4 41620000 \\C", // coastguard
+ "3 43100000 \\N", // nav buoy
+ "1 40000000 \\s", // *** other sea
+ "1 50000000 /.", // ***
+ "4 62110000 /[", // jogger
+ "3 64200000 /:", // fire
+ "3 65500000 \\'", // crash site
+ "3 66100000 \\Q", // earthquake
+ "3 66300000 \\w", // flooding
+ "1 60000000 /.", // *** other activities
+ "4 71610000 \\U", // sunny
+ "4 71620000 \\U", // sunny
+ "4 71630000 \\(", // cloudy
+ "4 71640000 \\(", // cloudy
+ "4 71650000 \\(", // cloudy
+ "4 71660000 \\(", // cloudy
+ "5 71711000 \\I", // rain shower
+ "5 71712000 \\F", // freezing rain
+ "5 71713000 \\D", // drizzle
+ "4 71710000 \\'", // rain
+ "5 71721000 \\G", // snow shower
+ "4 71720000 \\*", // snow
+ "4 71730000 \\:", // hail
+ "5 71812000 \\f", // funnel cloud
+ "5 71813000 \\J", // lightning
+ "4 71810000 \\T", // thunderstorm
+ "5 71822000 /@", // hurricane
+ "4 71820000 \\@", // storm
+ "4 71920000 \\{", // fog
+ "4 71950000 \\E", // smoke
+ "4 71960000 \\H", // haze
+ "4 71970000 \\b", // blowing dust/sand
+ "1 70000000 \\o", // *** other weather
+ "1 80000000 /.", // ***
+ "1 90000000 /.", // ***
+ "1 A0000000 /.", // ***
+ "1 B0000000 /.", // ***
+ "1 C0000000 /.", // ***
+ "1 D0000000 /.", // ***
+ "1 E0000000 /.", // ***
+ "1 F0000000 /.", // ***
+ "0"};
+
+
+
+
+
+// 0x18 Map Symbol - Packed 4-bit integers
+//
+// Modifies: symbol (leaves it in 4-bit packed format)
+// aprs_symbol_table
+// aprs_symbol_char
+//
+int OpenTrac_decode_symbol(unsigned char *element,
+ int element_len,
+ char *symbol,
+ char *aprs_symbol_table,
+ char *aprs_symbol_char) {
+ int c, ii, done;
+ unsigned char split[9];
+
+
+ ii = 0;
+ symbol[0] = '\0';
+
+ if (!element_len)
+ return -1;
+
+ if (element_len > 4)
+ return -1;
+
+ fprintf(stderr, "Symbol: ");
+
+ for (c = 0; c < element_len; c++) {
+
+ symbol[c] = element[c];
+
+ // Split nibbles into two bytes
+ split[ii++] = element[c] >> 4;
+ split[ii++] = element[c] & 0x0f;
+
+ if (c > 0) {
+ fprintf(stderr, ".");
+ }
+ fprintf(stderr, "%d", element[c] >> 4);
+
+ if (element[c] & 0x0f) {
+ fprintf(stderr, ".%d", element[c] & 0x0f);
+ }
+ }
+
+ symbol[element_len] = '\0'; // Terminate string
+ split[ii] = '\0'; // Terminate split integers
+
+ // Convert split string chars into hex chars
+ for (c = 0; c < element_len * 2; c++) {
+ if (split[c] < 10) {
+ split[c] += 0x30;
+ }
+ else {
+ split[c] += 0x37;
+ }
+ }
+
+//fprintf(stderr,"\n%s\n",split);
+
+ // Find the symbol from the table above that matches. Use the
+ // split[] string.
+
+ // Defaults:
+ *aprs_symbol_table = '/';
+ *aprs_symbol_char = '/'; // A dot
+
+ ii = 0;
+ done = 0;
+
+ while (!done && symbol_translate[ii][0] != '0') {
+ int len;
+
+ // Find out how many chars to compare
+ len = symbol_translate[ii][0] - 0x30;
+
+//fprintf(stderr,"%d:%s\n",len,&symbol_translate[ii][2]);
+
+ // Do a strncasecmp() for "len" chars in the hex part of the
+ // string. Once we find a match, the last two chars in the
+ // string are our symbol table and symbol. If we don't find
+ // a match, we use the default "//" symbol (a dot) instead.
+ if ( strncasecmp(&symbol_translate[ii][2],(const char *)split,len) == 0 ) {
+ // Found a match
+//fprintf(stderr,"Found a match: %s in %d", split, ii);
+ len = strlen(&symbol_translate[ii][0]);
+ *aprs_symbol_table = symbol_translate[ii][len-2];
+ *aprs_symbol_char = symbol_translate[ii][len-1];
+ done++;
+ }
+ else {
+ // No match
+ ii++;
+ }
+ }
+
+ switch (split[0]) {
+ case '1':
+ fprintf(stderr, " (Space Symbol)");
+ break;
+ case '2':
+ fprintf(stderr, " (Air Symbol)");
+ break;
+ case '3':
+ fprintf(stderr, " (Ground Symbol)");
+ break;
+ case '4':
+ fprintf(stderr, " (Sea Symbol)");
+ break;
+ case '5':
+ fprintf(stderr, " (Subsurface Symbol)");
+ break;
+ case '6':
+ fprintf(stderr, " (Activities Symbol)");
+ break;
+ case '7':
+ fprintf(stderr, " (Weather Symbol)");
+ break;
+ default:
+ fprintf(stderr, " (Unknown Symbol)");
+ break;
+ }
+ fprintf(stderr, "\n");
+
+ return 0;
+}
+
+
+
+
+
+// 0x20 Path Trace - Call/SSID, Network
+//
+// Modifies:
+//
+int OpenTrac_decode_pathtrace(unsigned char *element,
+ int element_len) {
+
+//WE7U: Need to pass back and use callsign/ssid/network.
+
+ char callsign[7];
+ int ssid, c, network;
+
+
+ if (element_len % 7)
+ return -1; // Must be multiple of 7 octets
+
+ if (!element_len) {
+ fprintf(stderr, "Empty Path\n");
+ return 0;
+ }
+
+ fprintf(stderr, "Path: ");
+ for (c=0; c<element_len; c+=7) {
+ memcpy(callsign, element+c, 6);
+ ssid = OpenTrac_extract_ssid((unsigned char *)callsign);
+ network = (int)*(element+c+6);
+ fprintf(stderr, " %s-%d (%d)", callsign, ssid, network);
+ }
+ fprintf(stderr, "\n");
+
+ return 0;
+}
+
+
+
+
+
+// 0x21 Heard-By List
+//
+// Modifies:
+//
+int OpenTrac_decode_heardby(unsigned char *element,
+ int element_len) {
+
+//WE7U: Need to pass back "Heard By" string.
+
+ int c;
+
+
+ if (!element_len)
+ return -1;
+
+ fprintf(stderr, "Heard By:");
+ for (c=0; c<element_len; c++) {
+ fprintf(stderr, " %d", (int)*(element+c));
+ }
+ fprintf(stderr, "\n");
+
+ return 0;
+}
+
+
+
+
+
+// 0x22 Available Networks
+//
+// Modifies:
+//
+int OpenTrac_decode_availablenets(unsigned char *element,
+ int element_len) {
+
+//WE7U: Need to pass back "Available Networks" string.
+
+ int c;
+
+
+ if (!element_len)
+ return -1;
+
+ fprintf(stderr, "Available Networks:");
+ for (c=0; c<element_len; c++) {
+ fprintf(stderr, " %d", (int)*(element+c));
+ }
+ fprintf(stderr, "\n");
+
+ return 0;
+}
+
+
+
+
+
+// 0x32 Maidenhead Locator (4 or 6 chars)
+//
+// Modifies: maidenhead
+//
+int OpenTrac_decode_maidenhead(unsigned char *element,
+ int element_len,
+ char *maidenhead) {
+
+ if (element_len > 6)
+ return -1;
+
+ if (element_len < 4)
+ return -1;
+
+ // Binary routine. strncpy is ok here as long as nulls not in
+ // data. We null-terminate it ourselves to make sure it is
+ // terminated.
+ strncpy(maidenhead, (char *)element, element_len);
+ maidenhead[element_len] = 0;
+
+ fprintf(stderr, "Maidenhead Grid: %s\n", maidenhead);
+ return 0;
+}
+
+
+
+
+
+// 0x33 Radio Capabilities
+//
+// Modifies: Nothing yet
+//
+int OpenTrac_decode_radio_capabilities(unsigned char *element,
+ int element_len) {
+
+//WE7U: Need to decode/pass back values. This element is still
+//being defined in the spec.
+
+ fprintf(stderr, "Radio Capabilities\n");
+
+ return 0;
+}
+
+
+
+
+
+// 0x34 GPS Data Quality - Fix, Validity, Sats, PDOP, HDOP, VDOP
+//
+// Modifies:
+//
+int OpenTrac_decode_gpsquality(unsigned char *element,
+ int element_len) {
+
+//WE7U: Need to pass back gps quality parameters/strings.
+
+ int fixtype, validity, sats;
+ const char *fixstr[] = {"Unknown Fix", "No Fix", "2D Fix", "3D Fix"};
+ const char *validstr[] = {"Invalid", "Valid SPS", "Valid DGPS", "Valid PPS"};
+
+
+ if (element_len > 4 || !element_len)
+ return -1;
+
+ fixtype = (element[0] & 0xc0) >> 6;
+ validity = (element[0] & 0x30) >> 4;
+ sats = (element[0] & 0x0f);
+ fprintf(stderr, "GPS: %s %s, %d sats", fixstr[fixtype],
+ validstr[validity], sats);
+ if (element_len > 1)
+ fprintf(stderr, " PDOP=%.1f", (float)element[1]/10);
+ if (element_len > 2)
+ fprintf(stderr, " HDOP=%.1f", (float)element[2]/10);
+ if (element_len > 3)
+ fprintf(stderr, " VDOP=%.1f", (float)element[3]/10);
+ fprintf(stderr, "\n");
+
+ return 0;
+}
+
+
+
+
+
+// 0x35 Aircraft Registration - ASCII text
+//
+// Modifies: aircraft_id
+//
+int OpenTrac_decode_acreg(unsigned char *element,
+ int element_len,
+ char *aircraft_id) {
+
+ if (element_len > 8)
+ return -1;
+
+ // Binary routine. strncpy is ok here as long as nulls not in
+ // data. We null-terminate it ourselves to make sure it is
+ // terminated.
+ strncpy(aircraft_id, (char *)element, element_len);
+ aircraft_id[element_len]=0;
+
+ fprintf(stderr, "Aircraft ID: %s\n", aircraft_id);
+
+ return 0;
+}
+
+
+
+
+
+// 0x40 Surface Observation Report
+//
+// Modifies: Nothing
+//
+int OpenTrac_surface_observation(unsigned char *element,
+ int element_len) {
+
+//WE7U: Need to decode/pass back the data. This element is still
+//being defined in the spec.
+
+ fprintf(stderr, "Surface Observation Report Element\n");
+
+ return 0;
+}
+
+
+
+
+
+// 0x41 Rainfall History
+//
+// Modifies: Nothing
+//
+int OpenTrac_rainfall_history(unsigned char *element,
+ int element_len) {
+
+//WE7U: Need to decode/pass back the data. This element is still
+//being defined in the spec.
+
+ fprintf(stderr, "Rainfall History Element\n");
+
+ return 0;
+}
+
+
+
+
+
+// 0x42 River Flow Gauge - 1/64 m^3/sec, centimeters
+//
+// Modifies: Nothing.
+//
+int OpenTrac_decode_rivergauge(unsigned char *element,
+ int element_len) {
+
+//WE7U: Need to pass back gauge indications.
+
+ unsigned int flow;
+ unsigned int height;
+ float flowm;
+ float heightm;
+
+
+ if (element_len != 4)
+ return -1;
+
+ flow = fetch16bits(element);
+ height = fetch16bits(element+2);
+ flowm = (float)flow / 64;
+ heightm = (float)height / 100;
+ fprintf(stderr, "River flow rate: %f Cu M/Sec Height: %f M\n",
+ flowm, heightm);
+
+ return 0;
+}
+
+
+
+
+
+// 0x43 Storm
+//
+// Modifies: Nothing.
+//
+int OpenTrac_decode_storm(unsigned char *element,
+ int element_len) {
+
+// WE7U: Need to decode/pass back storm info. This element is
+// still being defined in the spec.
+
+ fprintf(stderr, "Storm Report Element\n");
+ return 0;
+}
+
+
+
+
+
+// 0x50 Shape
+//
+// Modifies: Nothing.
+//
+int OpenTrac_decode_shape(unsigned char *element,
+ int element_len) {
+
+// WE7U: Need to decode/pass back Shape info. This element is
+// still being defined in the spec.
+
+ fprintf(stderr, "Shape Element\n");
+
+ return 0;
+}
+
+
+
+
+
+// 0x0100 Emergency / Distress Call
+//
+// Modifies: nothing
+//
+int OpenTrac_flag_emergency(void) {
+
+ fprintf(stderr, "* * * EMERGENCY * * *\n");
+
+ return 0;
+}
+
+
+
+
+
+// 0x0101 Attention / Ident
+//
+// Modifies: nothing
+//
+int OpenTrac_flag_attention(void) {
+
+ fprintf(stderr, " - ATTENTION - \n");
+
+ return 0;
+}
+
+
+
+
+
+// 0x0300 HAZMAT (UN ID in lower 14 bits)
+//
+// Modifies: hazmat_id
+//
+int OpenTrac_decode_hazmat(unsigned char *element,
+ int element_len,
+ int *hazmat_id,
+ char *comment,
+ int comment_size) {
+
+ if (element_len < 2) {
+ fprintf(stderr, "HAZMAT: Unknown Material\n");
+ strncat(comment,
+ " HAZMAT: Unknown Material",
+ comment_size - 1 - strlen(comment));
+ }
+ else if (element_len > 2) {
+ fprintf(stderr, "HAZMAT: Unknown Material: ID too Long\n");
+ strncat(comment,
+ " HAZMAT: Unknown Material: ID too Long",
+ comment_size - 1 - strlen(comment));
+ }
+ else {
+ char temp[200];
+
+ *hazmat_id = fetch16bits(element) & 0x3fff;
+ fprintf(stderr, "HAZMAT: UN%04d\n", *hazmat_id);
+ xastir_snprintf(temp,
+ sizeof(temp),
+ " HAZMAT: UN%04d",
+ *hazmat_id);
+ strncat(comment,
+ temp,
+ comment_size - 1 - strlen(comment));
+ }
+ return 0;
+}
+
+
+
+
+
+// 0x0500 to 0x05ff Generic Measurement Elements
+// Values may be 8-bit int, 16-bit int, single float, or double
+// float
+//
+// Modifies: Nothing.
+//
+int OpenTrac_decode_units(int unitnum,
+ unsigned char *element,
+ int element_len,
+ char *comment,
+ int comment_size) {
+
+//WE7U: Need to pass back and use units.
+
+ const char *units[]={"Volts","Amperes","Watts","Kelvins",
+ "Meters","Seconds","Meters/Second","Liters","Kilograms",
+ "Bits/Second","Bytes","Radians","Radians/Second",
+ "Square Meters","Joules","Newtons","Pascals","Hertz",
+ "Meters/Sec^2","Grays","Lumens","Cubic Meters/Second",
+ "Pascal Seconds","Kilograms/Meter^3","Radians/Second^2",
+ "Coulombs","Farads","Siemens","Counts"};
+
+ union measurement {
+ char c;
+ float f;
+ double d;
+ } *mval;
+
+ int ival; // too much variation in byte order and size for union
+ char temp[200];
+
+
+ mval = (void *)element;
+ switch (element_len) {
+ case 1:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ " %d %s",
+ mval->c,
+ units[unitnum]);
+ strncat(comment,
+ temp,
+ comment_size - 1 - strlen(comment));
+ fprintf(stderr, "%s\n",temp);
+ break;
+ case 2:
+ ival = fetch16bits(element);
+ xastir_snprintf(temp,
+ sizeof(temp),
+ " %d %s",
+ ival,
+ units[unitnum]);
+ strncat(comment,
+ temp,
+ comment_size - 1 - strlen(comment));
+ fprintf(stderr, "%s\n", temp);
+ break;
+ case 4:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ " %f %s",
+ mval->f,
+ units[unitnum]);
+ strncat(comment,
+ temp,
+ comment_size - 1 - strlen(comment));
+ fprintf(stderr, "%s\n", temp);
+ break;
+ case 8:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ " %f %s",
+ mval->d,
+ units[unitnum]);
+ strncat(comment,
+ temp,
+ comment_size - 1 - strlen(comment));
+ fprintf(stderr, "%s\n", temp);
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+
+
+// Construct a Base-91 compressed APRS-format packet out of
+// the parsed information (to attempt to represent some of
+// the better resolution available with OpenTrac). We may
+// need to construct several APRS packets out of the
+// OpenTrac packet, as there may be several entity ID's or
+// other types of info that can't fit into one APRS packet.
+// Later we'll change this so that we don't create an APRS
+// packet out of the OpenTrac packet at all, but instead
+// decode and use the OpenTrac information directly.
+//
+// Inputs: Lots!
+// Outputs: buffer
+//
+void process_opentrac_aprs(unsigned char *origin_call,
+ unsigned char origin_ssid,
+ char *buffer,
+ unsigned char *dest,
+ unsigned int digis,
+ unsigned char digi[10][10],
+ unsigned char *digi_h,
+ int have_position,
+ double latitude,
+ double longitude,
+ unsigned int entity_serial,
+ char *displayname,
+ char aprs_symbol_table,
+ char aprs_symbol_char,
+ int course,
+ float speed,
+ float altitude,
+ char *comment) {
+
+ int i;
+
+ // Note that if we got an Origination Station element, the path
+ // here is not representative of the entire path the packet
+ // took, and in fact we don't know who the transmitting station
+ // was for this packet anymore, just the originating station for
+ // the packet.
+
+fprintf(stderr,"Origin Call: %s\nOrigin SSID: %d\n",origin_call,origin_ssid);
+
+ // The passed in value includes the SSID, but the
+ // size of the char[] is 7, which is bad - overflow
+ // Either need to fix how we deal with the origin_call
+ // or fix what it means. (with ssid or without)!!
+ // For now, I changed origin_call and source_call
+ // to be 10 bytes since that is what the rest of Xastir uses
+ // FIXME: Check if all of the OpenTrac_decode functions
+ // expect callsign to have ssid already or not
+ // KJ5O
+
+ strncat(buffer,(char *)origin_call,10);
+
+ strncat(buffer,">",1);
+ strncat(buffer,(char *)dest,10);
+
+ for(i = 0; i < (int)digis; i++) {
+ strncat(buffer,",",1);
+ strncat(buffer,(char *)digi[i],10);
+ /* at the last digi always put a '*' when h_bit is set */
+ if (i == (int)(digis - 1)) {
+ if (digi_h[i] == (unsigned char)0x80) {
+ /* this digi must have transmitted the packet */
+ strncat(buffer,"*",1);
+ }
+ } else {
+ if (digi_h[i] == (unsigned char)0x80) {
+ /* only put a '*' when the next digi has no h_bit */
+ if (digi_h[i + 1] != (unsigned char)0x80) {
+ /* this digi must have transmitted the packet */
+ strncat(buffer,"*",1);
+ }
+ }
+ }
+ }
+ strncat(buffer,":",1);
+
+
+ // If we parsed a position, finish creating an APRS packet.
+ if (have_position) {
+ // We have latitude/longitude/altitude
+ // lat/lon are doubles, alt is a float
+ int ok;
+ unsigned long temp_lat, temp_lon;
+ char lat_str[20];
+ char lon_str[20];
+ char alt_str[20];
+
+
+fprintf(stderr, "Decoded this position: %f %f\n", latitude, longitude);
+
+ // Format it first in DDMM.MMMMN/DDDMM.MMMMW format
+ // lat/lon are doubles, alt is a float
+ //
+ // Convert lat/long to Xastir coordinate system first.
+ // We pass in floats and get returned longs, which
+ // represent 1/100 sec resolution lat/long.
+ ok = convert_to_xastir_coordinates (
+ &temp_lon,
+ &temp_lat,
+ (float)longitude,
+ (float)latitude);
+
+ if (ok) {
+ // Convert to a Base-91 compressed position so that
+ // we can use part of the extra resolution provided
+ // by OpenTrac.
+
+ // Convert to very high precision format, DDMM.MMMMN
+ convert_lat_l2s( temp_lat, lat_str, 20, CONVERT_VHP_NOSP);
+ convert_lon_l2s( temp_lon, lon_str, 20, CONVERT_VHP_NOSP);
+ if (entity_serial) {
+ // We have an entity that is non-zero. Create a
+ // compressed APRS "Item" from the data. NOTE:
+ // Items have to have at minimum 3, maximum 9
+ // characters for the name.
+ char entity_name[10];
+
+ if (strlen(displayname)) {
+ xastir_snprintf(entity_name,
+ sizeof(entity_name),
+ "%s",
+ displayname);
+ }
+ else {
+ xastir_snprintf(entity_name,
+ sizeof(entity_name),
+ "Ent. %04x", // Short for "Entity"
+ entity_serial);
+ }
+
+ strncat(buffer,")",1); // APRS Item packet
+ strncat(buffer,entity_name,9); // Entity name
+ strncat(buffer,"!",1);
+
+ // Convert the high-resolution lat/long data to
+ // Base-91 compressed position:
+ strncat(buffer,
+ compress_posit(lat_str,
+ aprs_symbol_table,
+ lon_str,
+ aprs_symbol_char,
+ course % 360, // Course
+ (int)(speed / 1.852), // kph -> knots
+ ""), // PHG, we don't use it here
+ 13);
+ }
+ else {
+ // Entity is zero. Create an APRS position packet.
+
+ strncat(buffer,"!",1); // APRS non-messaging position packet
+
+ // Convert the high-resolution lat/long data to
+ // Base-91 compressed position:
+ strncat(buffer,
+ compress_posit(lat_str,
+ aprs_symbol_table,
+ lon_str,
+ aprs_symbol_char,
+ course % 360, // Course
+ (int)(speed / 1.852), // kph -> knots
+ ""), // PHG, we don't use it here
+ 13);
+
+ if (strlen(displayname)) {
+ // Add displayname
+ strncat(buffer," ",1);
+ strncat(buffer,displayname,40);
+ }
+ }
+
+ // Append the comment to the end.
+
+ // We must check length here. APRS packets can't
+ // handle much.
+
+ // Altitude should be in feet "/A=001234", and placed in
+ // the comment field of an APRS packet.
+ xastir_snprintf(alt_str,
+ sizeof(alt_str),
+ " /A=%06d",
+ (int)(altitude * 3.28084)); // meters to feet
+ strncat(buffer,alt_str,10);
+
+ // We must limit the length here. APRS Item packets
+ // can handle 43 chars in the comment field, Base-91
+ // compressed position packets can handle 40.
+ //
+ // Wait a minute! We don't care how long they are
+ // as long as they fit through our APRS decoding.
+ // We're not transmitting these as APRS packets, so
+ // the max length in the APRS Spec doesn't matter
+ // here!
+ //
+ strncat(buffer,comment,126);
+ }
+ }
+
+ // Null-terminate the buffer string to make sure.
+ buffer[MAX_DEVICE_BUFFER - 1] = '\0';
+
+fprintf(stderr, "\n***** %s\n\n", buffer);
+
+ decode_ax25_line( buffer, DATA_VIA_TNC, 0, 1);
+
+ // Clear the buffer for the next round.
+ buffer[0] = '\0';
+}
+
+
+
+
+
+//WE7U: Protect "buffer" from getting overrun!!!
+//
+//***********************************************************
+// process_OpenTrac_packet()
+//
+// data raw packet data: Points to first char of info field
+// len length of info field of AX.25 packet
+// buffer buffer to write readable packet data to
+// source source callsign
+// ssid ssid of source callsign
+// dest destination callsign
+// digis number of digi's that we're being passed
+// digi[][] digi list (up to 10 digis, 10 chars each)
+// digi_h high bit of the digis (up to 10 chars)
+//
+// Function used to process an OpenTrac packet that is not in a
+// KISS frame. In other words the underlying transport protocol
+// portions have been stripped off by this point, or perhaps the
+// packet was received from an OpenTrac internet feed that didn't
+// have anything to strip off.
+//
+// This is where the majority of the OpenTrac-specific decoding gets
+// done. Much of the code for this routine and the routines above
+// that deal with OpenTrac packets was generously donated by Scott
+// Miller, N1VG. He's allowing us to put it under the GPL license.
+//
+// A new sequence or a new entityID should trigger an APRS packet to
+// be generated (with the old sequence/entityID). A packet should
+// also be generated at the end of processing. There can be
+// multiple ID's and multiple locations embedded inside an OpenTrac
+// packet.
+//
+//***********************************************************
+
+char *process_OpenTrac_packet( unsigned char *data,
+ unsigned int len,
+ char *buffer,
+ unsigned char *source_call,
+ unsigned int source_ssid,
+ unsigned char *dest,
+ unsigned int digis,
+ unsigned char digi[10][10],
+ unsigned char *digi_h) {
+
+ int elen;
+ int etype;
+ unsigned int decoded = 0;
+ unsigned char origin_call[10]; // Where the packet originated
+ unsigned char origin_ssid = 0;
+ unsigned char entity_call[10]; // What the packet is talking about
+ unsigned char entity_ssid = 0x00;
+ unsigned int entity_serial = 0;
+ unsigned int entity_sequence = 0;
+ unsigned int temp_entity_sequence = 0;
+ unsigned char network = 0;
+ long rawtime = 0;
+ int have_position = 0;
+ double latitude = 0.0;
+ double longitude = 0.0;
+ float altitude = 0;
+ int course = 0;
+ float speed = 0;
+ int ambiguity = 0;
+ char country[3];
+ char subdivision[4];
+ char aircraft_id[9];
+ int hazmat_id = 0;
+ char displayname[31];
+ char maidenhead[7];
+ char waypoint[7];
+ char symbol[5];
+ char aprs_symbol_table = '/';
+ char aprs_symbol_char = '/'; // A "dot"
+ char comment[127];
+
+
+ fprintf(stderr, "process_OpenTrac_packet()\n");
+
+ // Initialize strings
+ entity_call[0] = '\0';
+ country[0] = '\0';
+ subdivision[0] = '\0';
+ aircraft_id[0] = '\0';
+ displayname[0] = '\0';
+ maidenhead[0] = '\0';
+ waypoint[0] = '\0';
+ symbol[0] = '\0';
+ comment[0] = '\0';
+
+ // Fill origin with source-call/SSID initially.
+ xastir_snprintf((char *)origin_call,
+ sizeof(origin_call),
+ "%s",
+ source_call);
+ origin_ssid = source_ssid;
+
+
+ // OpenTrac-specific decoding code. For the moment we'll
+ // construct an APRS-format packet from it and send it through
+ // our regular decoding routines. Later we'll dissect the
+ // OpenTrac packets and store them into their own data
+ // structures, but then we'll also need code in place for
+ // _displaying_ that data.
+
+
+ fprintf(stderr, "OpenTRAC: %d bytes\n", len);
+
+
+ // Main loop. Keep decoding elements until we run out of things
+ // to process.
+ //
+ while (decoded < len) {
+ elen = (int)*data;
+ decoded += (elen & 0x7f)+1;
+ if (elen & 0x80) { // See if it's got a 16-bit ID
+ elen = (elen & 0x7f) - 2; // Strip the extid flag
+ etype = fetch16bits(++data);
+ }
+ else {
+ elen--; // Don't count the type byte
+ etype = (int)*(data+1);
+ }
+ data+=2; // Skip to the body
+ fprintf(stderr, "EID 0x%04x len %02d: ", etype, elen);
+ switch (etype) {
+ case (0x00): // Sequence
+ temp_entity_sequence = entity_sequence;
+
+ OpenTrac_decode_sequence(
+ data,
+ elen,
+ &temp_entity_sequence);
+
+ if (temp_entity_sequence != entity_sequence) {
+
+ process_opentrac_aprs(origin_call,
+ origin_ssid,
+ buffer,
+ dest,
+ digis,
+ digi,
+ digi_h,
+ have_position,
+ latitude, longitude,
+ entity_serial,
+ displayname,
+ aprs_symbol_table,
+ aprs_symbol_char,
+ course,
+ speed,
+ altitude,
+ comment);
+
+ entity_sequence = temp_entity_sequence;
+ }
+
+// Problem here: What to do for multi-sequence OpenTrac packets?
+// Generate a new APRS packet for each so that we get an entire
+// history?
+
+ break;
+ case (0x01): // Originating Station
+ temp_entity_sequence = entity_sequence;
+
+ OpenTrac_decode_origination(
+ data,
+ elen,
+ &temp_entity_sequence, // Origin sequence?
+ (char *)origin_call,
+ &origin_ssid,
+ &network);
+
+ if (temp_entity_sequence != entity_sequence) {
+
+ process_opentrac_aprs(origin_call,
+ origin_ssid,
+ buffer,
+ dest,
+ digis,
+ digi,
+ digi_h,
+ have_position,
+ latitude, longitude,
+ entity_serial,
+ displayname,
+ aprs_symbol_table,
+ aprs_symbol_char,
+ course,
+ speed,
+ altitude,
+ comment);
+
+ entity_sequence = temp_entity_sequence;
+ }
+
+ // Originating station different from transmitting
+ // station.
+
+ break;
+ case (0x02): // Entity ID
+ temp_entity_sequence = entity_sequence;
+
+ OpenTrac_decode_entityid(
+ data,
+ elen,
+ origin_call,
+ origin_ssid,
+ entity_call,
+ &entity_ssid,
+ &entity_serial,
+ &temp_entity_sequence);
+
+ if (temp_entity_sequence != entity_sequence) {
+
+ process_opentrac_aprs(origin_call,
+ origin_ssid,
+ buffer,
+ dest,
+ digis,
+ digi,
+ digi_h,
+ have_position,
+ latitude, longitude,
+ entity_serial,
+ displayname,
+ aprs_symbol_table,
+ aprs_symbol_char,
+ course,
+ speed,
+ altitude,
+ comment);
+
+ entity_sequence = temp_entity_sequence;
+ }
+
+// We're dealing with a different entity than the transmitting or
+// originating station. Need to do something different here,
+// perhaps creating an object or an item from it?
+
+ break;
+ case (0x10): // Position report
+ OpenTrac_decode_position(
+ data,
+ elen,
+ &latitude,
+ &longitude,
+ &altitude);
+ have_position++;
+ break;
+ case (0x11): // Timestamp
+ OpenTrac_decode_timestamp(
+ data,
+ elen,
+ &rawtime);
+ break;
+ case (0x12): // Comment
+ OpenTrac_decode_comment(
+ data,
+ elen,
+ comment);
+ break;
+ case (0x13): // Course and Speed
+ OpenTrac_decode_courseandspeed(
+ data,
+ elen,
+ &course, // degrees true
+ &speed); // kph
+ break;
+ case (0x14): // Positional Ambiguity
+ OpenTrac_decode_ambiguity(
+ data,
+ elen,
+ &ambiguity);
+ break;
+ case (0x15): // Country Code
+ OpenTrac_decode_country(
+ data,
+ elen,
+ country,
+ subdivision);
+ break;
+ case (0x16): // Display Name
+ OpenTrac_decode_displayname(
+ data,
+ elen,
+ displayname);
+ break;
+ case (0x17): // Waypoint Name
+ OpenTrac_decode_waypoint(
+ data,
+ elen,
+ waypoint);
+ break;
+ case (0x18): // Map Symbol
+ OpenTrac_decode_symbol(
+ data,
+ elen,
+ symbol,
+ &aprs_symbol_table,
+ &aprs_symbol_char);
+ break;
+ case (0x20): // Path Trace
+ OpenTrac_decode_pathtrace(
+ data,
+ elen);
+ break;
+ case (0x21): // Heard-By List
+ OpenTrac_decode_heardby(
+ data,
+ elen);
+ break;
+ case (0x22): // Available Networks
+ OpenTrac_decode_availablenets(
+ data,
+ elen);
+ break;
+ case (0x32): // Maidenhead Locator
+ OpenTrac_decode_maidenhead(
+ data,
+ elen,
+ maidenhead);
+ break;
+ case (0x33): // Radio Capabilities
+ OpenTrac_decode_radio_capabilities(
+ data,
+ elen);
+ break;
+ case (0x34): // GPS Data Quality
+ OpenTrac_decode_gpsquality(
+ data,
+ elen);
+ break;
+ case (0x35): // Aircraft Registration
+ OpenTrac_decode_acreg(
+ data,
+ elen,
+ aircraft_id);
+ break;
+ case (0x40): // Surface Observation Report
+ OpenTrac_surface_observation(
+ data,
+ elen);
+ break;
+ case (0x41): // Rainfall History
+ OpenTrac_rainfall_history(
+ data,
+ elen);
+ break;
+ case (0x42): // River Flow Gauge
+ OpenTrac_decode_rivergauge(
+ data,
+ elen);
+ break;
+ case (0x43): // Storm Report
+ OpenTrac_decode_storm(
+ data,
+ elen);
+ break;
+ case (0x50): // Shape
+ OpenTrac_decode_shape(
+ data,
+ elen);
+ break;
+ case (0x100): // Emergency/distress flag
+ OpenTrac_flag_emergency();
+ break;
+ case (0x101): // Attention/ident flag
+ OpenTrac_flag_attention();
+ break;
+ case (0x300): // Hazmat
+ OpenTrac_decode_hazmat(
+ data,
+ elen,
+ &hazmat_id,
+ comment,
+ sizeof(comment));
+ break;
+ case (0xffff): // Null element
+ fprintf(stderr, "Null element\n");
+ break;
+ default: // Everything else
+
+ // Check for Generic Measurement Units (0x500 to
+ // 0x5ff inclusive)
+ if ((etype & 0xff00) == 0x500) {
+ OpenTrac_decode_units(
+ etype & 0x00ff,
+ data,
+ elen,
+ comment,
+ sizeof(comment));
+ }
+ else {
+
+ // Not a measurement unit. Print out something
+ // about what we found.
+ fprintf(stderr,
+ "Unknown Element Type, ");
+
+ // Provide more data about the class of element
+ // if we can, even if we don't know the specific
+ // element type.
+ //
+ if ( (etype & 0xfff0) == 0x0000) {
+ fprintf(stderr, "Class: Stream Control\n");
+ }
+ else if ((etype & 0xfff0) == 0x0010) {
+ fprintf(stderr, "Class: Common Attribute\n");
+ }
+ else if ((etype & 0xfff0) == 0x0020) {
+ fprintf(stderr, "Class: Network Information\n");
+ }
+// else if ((etype & 0xfff0) == 0x0030) {
+// fprintf(stderr, "Class: ??\n");
+// }
+ else if ((etype & 0xfff0) == 0x0040) {
+ fprintf(stderr, "Class: Weather\n");
+ }
+// else if ((etype & 0xfff0) == 0x0050) {
+// fprintf(stderr, "Class: ??\n");
+// }
+ else if ((etype & 0xff00) == 0x0100) {
+ fprintf(stderr, "Class: Status Flags\n");
+ }
+ else if ((etype & 0xff00) == 0x0200) {
+ fprintf(stderr, "Class: Incident Command System\n");
+ }
+ else if ((etype & 0xff00) == 0xf000) {
+ // Note: 0xffff Null element is caught
+ // before we get to here.
+ fprintf(stderr, "Class: Experimental\n");
+ }
+ else {
+ fprintf(stderr, "Class: Unknown\n");
+ }
+ }
+ break;
+ }
+ data+=elen;
+ }
+
+ process_opentrac_aprs(origin_call,
+ origin_ssid,
+ buffer,
+ dest,
+ digis,
+ digi,
+ digi_h,
+ have_position,
+ latitude, longitude,
+ entity_serial,
+ displayname,
+ aprs_symbol_table,
+ aprs_symbol_char,
+ course,
+ speed,
+ altitude,
+ comment);
+
+ return( buffer );
+}
+
+
+
+
+
+//***********************************************************
+// process_ax25_packet()
+//
+// bp raw packet data
+// len length of raw packet data
+// buffer buffer to write readable packet data to
+// buffer_size max length of buffer
+//
+// Note that db.c:decode_ax25_header does much the same thing for
+// Serial KISS interface packets. Consider combining the two
+// functions. process_ax25_packet() would be the earlier and more
+// thought-out function. This function now has some OpenTrac code
+// as well.
+//***********************************************************
+
+char *process_ax25_packet(unsigned char *bp, unsigned int len, char *buffer, int buffer_size) {
+ int i,j;
+ unsigned int k,l;
+ unsigned int digis;
+ unsigned char source[10];
+ unsigned char dest[10];
+ unsigned char digi[10][10];
+ unsigned char digi_h[10];
+ unsigned int ssid;
+ unsigned char message[513];
+
+ if ( (bp == NULL) || (buffer == NULL) )
+ return(NULL);
+
+ /* clear buffer */
+ buffer[0] = '\0';
+
+ if (*bp != (unsigned char)0)
+ return(NULL); /* not a DATA packet */
+
+ // We have a KISS packet here, so we know that the first
+ // character is a flag character. Skip over it.
+ bp++;
+ len--;
+
+ // Check the length to make sure that we don't have an empty
+ // packet.
+ if (!bp || !len)
+ return(NULL);
+
+ // Check for minimum KISS frame bytes.
+ if (len < 15)
+ return(NULL);
+
+ if (bp[1] & 1) /* Compressed FlexNet Header */
+ return(NULL);
+
+ /* Destination of frame */
+ j = 0;
+ for(i = 0; i < 6; i++) {
+ if ((bp[i] &0xfe) != (unsigned char)0x40)
+ dest[j++] = bp[i] >> 1;
+ }
+ ssid = (unsigned int)( (bp[6] & 0x1e) >> 1 );
+ if (ssid != 0) {
+ dest[j++] = '-';
+ if ((ssid / 10) != 0) {
+ dest[j++] = '1';
+ }
+ ssid = (ssid % 10);
+ dest[j++] = (unsigned char)ssid + (unsigned char)'0';
+ }
+ dest[j] = '\0';
+ bp += 7;
+ len -= 7;
+
+ /* Source of frame */
+ j = 0;
+ for(i = 0; i < 6; i++) {
+ if ((bp[i] &0xfe) != (unsigned char)0x40)
+ source[j++] = bp[i] >> 1;
+ }
+ ssid = (unsigned int)( (bp[6] & 0x1e) >> 1 );
+ if (ssid != 0) {
+ source[j++] = '-';
+ if ((ssid / 10) != 0) {
+ source[j++] = '1';
+ }
+ // Commented out by Lance KJ5O. Why is this here?
+ // It destroys the ssid value. I moved the calculation
+ // to the source-construction line. But we need to be consistent
+ // in what the variables are. Is "source" including the SSID or not?
+ // This function allocatees 10 bytes, and so assumes that SSID belongs
+ // However, in process_OpenTrac_packet, origin_ssid is 7 bytes.
+ // ssid = (ssid % 10);
+
+ source[j++] = (unsigned char)(ssid % 10) + (unsigned char)'0';
+ // source[j++] = (unsigned char)ssid + (unsigned char)'0';
+ }
+ source[j] = '\0';
+ bp += 7;
+ len -= 7;
+
+ // by KJ5O - test for proper extraction of source call and ssid
+ // fprintf(stderr, "|KJ5O-test| %s-%d\n", source, ssid);
+
+ /* Digipeaters */
+ digis = 0;
+ while ((!(bp[-1] & 1)) && (len >= 7)) {
+ /* Digi of frame */
+ if (digis != 10) {
+ j = 0;
+ for (i = 0; i < 6; i++) {
+ if ((bp[i] &0xfe) != (unsigned char)0x40)
+ digi[digis][j++] = bp[i] >> 1;
+ }
+ digi_h[digis] = (bp[6] & 0x80);
+ ssid = (unsigned int)( (bp[6] & 0x1e) >> 1 );
+ if (ssid != 0) {
+ digi[digis][j++] = '-';
+ if ((ssid / 10) != 0) {
+ digi[digis][j++] = '1';
+ }
+ ssid = (ssid % 10);
+ digi[digis][j++] = (unsigned char)ssid + (unsigned char)'0';
+ }
+ digi[digis][j] = '\0';
+ digis++;
+ }
+ bp += 7;
+ len -= 7;
+ }
+ if (!len)
+ return(NULL);
+
+ /* We are now at the primitive bit */
+ i = (int)(*bp++);
+ len--;
+
+ /* strip the poll-bit from the primitive */
+ i = i & (~0x10);
+
+ /* return if this is not an UI frame (= 0x03) */
+ if(i != 0x03)
+ return(NULL);
+
+ /* no data left */
+ if (!len)
+ return(NULL);
+
+ // Check whether we're dealing with an OpenTrac KISS packet. If
+ // so, go process it and then pass through the return code that
+ // the OpenTrac functions provide.
+ if (*bp == 0x77) {
+ char* ret;
+
+ bp++;
+ len--;
+ // We have an OpenTrac packet.
+ ret = process_OpenTrac_packet(
+ bp,
+ len,
+ buffer,
+ source,
+ ssid,
+ dest,
+ digis,
+ digi,
+ digi_h);
+
+ // If we wish to process some APRS-converted OpenTrac
+ // packet:
+ return(ret);
+
+ // If we processed it in another manner and just wish to
+ // quit:
+ //return(NULL);
+
+ }
+ else if(*bp != (unsigned char)0xF0) { // APRS PID
+ // We _don't_ have an APRS packet
+ return(NULL);
+ }
+
+ // We have what looks like a valid KISS-frame containing APRS
+ // protocol data.
+
+ bp++;
+ len--;
+ k = 0;
+ l = 0;
+ while (len) {
+ i = (int)(*bp++);
+ if ((i != (int)'\n') && (i != (int)'\r')) {
+ if (l < 512)
+ message[l++] = (unsigned char)i;
+ }
+ len--;
+ }
+ /* add terminating '\0' to allow handling as a string */
+ message[l] = '\0';
+
+ xastir_snprintf(buffer,
+ buffer_size,
+ "%s",
+ source);
+
+ /*
+ * if there are no digis or the first digi has not handled the
+ * packet then this is directly from the source, mark it with
+ * a "*" in that case
+ */
+
+ /* I don't think we need this just yet, perhaps not at all? */
+ /* I think if we don't have a '*' in the path we can assume direct? -FG */
+ /*
+ if((digis == 0) || (digi_h[0] != 0x80))
+ strncat(buffer, "*", buffer_size - 1 - strlen(buffer));
+ */
+
+ strncat(buffer, ">", buffer_size - 1 - strlen(buffer));
+
+ /* destination is at the begining of the chain, because it is */
+ /* needed so MIC-E packets can be decoded correctly. */
+ /* this may be changed in the future but for now leave it here -FG */
+ strncat(buffer, (char *)dest, buffer_size - 1 - strlen(buffer));
+
+ for(i = 0; i < (int)digis; i++) {
+ strncat(buffer, ",", buffer_size - 1 - strlen(buffer));
+ strncat(buffer, (char *)digi[i], buffer_size - 1 - strlen(buffer));
+ /* at the last digi always put a '*' when h_bit is set */
+ if (i == (int)(digis - 1)) {
+ if (digi_h[i] == (unsigned char)0x80) {
+ /* this digi must have transmitted the packet */
+ strncat(buffer, "*", buffer_size - 1 - strlen(buffer));
+ }
+ } else {
+ if (digi_h[i] == (unsigned char)0x80) {
+ /* only put a '*' when the next digi has no h_bit */
+ if (digi_h[i + 1] != (unsigned char)0x80) {
+ /* this digi must have transmitted the packet */
+ strncat(buffer, "*", buffer_size - 1 - strlen(buffer));
+ }
+ }
+ }
+ }
+ strncat(buffer, ":", buffer_size - 1 - strlen(buffer));
+
+ //Copy into only the free space in buffer.
+ strncat( buffer, (char *)message, MAX_DEVICE_BUFFER - 1 - strlen(buffer));
+
+ // And null-terminate it to make sure.
+ buffer[MAX_DEVICE_BUFFER - 1] = '\0';
+
+ return(buffer);
+}
+
+
+
+
+
+//*********************************************************
+// AX25 port INIT
+//
+// port is port# used
+//*********************************************************
+
+int ax25_init(int port) {
+
+ /*
+ COMMENT:tested this Seems to work fine as ETH_P_AX25
+ on newer linux kernels (and you see your own transmissions
+ but it is not good for older linux kernels and FreeBSD -FG
+ */
+
+#ifdef HAVE_LIBAX25
+ int proto = PF_AX25;
+ char temp[200];
+ char *dev = NULL;
+#endif // HAVE_LIBAX25
+
+ if (begin_critical_section(&port_data_lock, "interface.c:ax25_init(1)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ /* clear port_channel */
+// port_data[port].channel = -1;
+
+ /* clear port active */
+ port_data[port].active = DEVICE_NOT_IN_USE;
+
+ /* clear port status */
+ port_data[port].status = DEVICE_DOWN;
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+
+#ifdef HAVE_LIBAX25
+ if (ax25_ports_loaded == 0) {
+ /* port file has not been loaded before now */
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "ERROR: problem with axports file\n");
+ popup_message(langcode("POPEM00004"),langcode("POPEM00013"));
+
+ if (end_critical_section(&port_data_lock, "interface.c:ax25_init(2)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ return -1;
+ }
+ /* we can only load the port file once!!! so do not load again */
+ ax25_ports_loaded = 1;
+ }
+
+ if (port_data[port].device_name != NULL) {
+ if ((dev = ax25_config_get_dev(port_data[port].device_name)) == NULL) {
+ xastir_snprintf(temp, sizeof(temp), langcode("POPEM00014"),
+ port_data[port].device_name);
+ popup_message(langcode("POPEM00004"),temp);
+
+ if (end_critical_section(&port_data_lock, "interface.c:ax25_init(3)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ return -1;
+ }
+ }
+
+ /* COMMENT: tested this AF_INET is CORRECT -FG */
+ // Commented out sections below. We keep the old socket number
+ // around now, so have to start a new socket in all cases to make it work.
+// if (port_data[port].channel == -1) {
+
+ ENABLE_SETUID_PRIVILEGE;
+#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 3
+ port_data[port].channel = socket(PF_INET, SOCK_DGRAM, htons(proto)); // proto = AF_AX25
+#else // __GLIBC__ >= 2 && __GLIBC_MINOR >= 3
+ port_data[port].channel = socket(PF_INET, SOCK_PACKET, htons(proto));
+#endif // __GLIBC__ >= 2 && __GLIBC_MINOR >= 3
+ DISABLE_SETUID_PRIVILEGE;
+
+ if (port_data[port].channel == -1) {
+ perror("socket");
+ if (end_critical_section(&port_data_lock, "interface.c:ax25_init(4)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ return -1;
+ }
+
+// }
+// else {
+ // Use socket number that is already defined
+// }
+
+ /* port active */
+ port_data[port].active = DEVICE_IN_USE;
+
+ /* port status */
+ port_data[port].status = DEVICE_UP;
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+
+#else /* HAVE_LIBAX25 */
+ fprintf(stderr,"AX.25 support not compiled into Xastir!\n");
+ popup_message(langcode("POPEM00004"),langcode("POPEM00021"));
+#endif /* HAVE_LIBAX25 */
+ if (end_critical_section(&port_data_lock, "interface.c:ax25_init(5)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ return(1);
+}
+
+//********************************* STOP AX.25 ********************************
+
+
+
+
+
+//*************************** START SERIAL PORT FUNCTIONS ********************************
+
+
+//******************************************************
+// command file to tnc port
+// port to send config data to
+// Filename containing the config data
+//******************************************************
+int command_file_to_tnc_port(int port, char *filename) {
+ FILE *f;
+ char line[MAX_LINE_SIZE+1];
+ char command[MAX_LINE_SIZE+5];
+ int i;
+ char cin;
+ int error;
+ struct stat file_status;
+
+
+ if (filename == NULL)
+ return(-1);
+
+ // Check file status
+ if (stat(filename, &file_status) < 0) {
+ fprintf(stderr,
+ "Couldn't stat file: %s\n",
+ filename);
+ fprintf(stderr,
+ "Skipping send to TNC\n");
+ return(-1);
+ }
+
+ // Check that it is a regular file
+ if (!S_ISREG(file_status.st_mode)) {
+ fprintf(stderr,
+ "File is not a regular file: %s\n",
+ filename);
+ fprintf(stderr,
+ "Skipping send to TNC\n");
+ return(-1);
+ }
+
+ error = 0;
+ i = 0;
+ f = fopen(filename,"r");
+ if (f != NULL) {
+ int send_ctrl_C = 1;
+
+ line[0] = (char)0;
+ while (!feof(f) && error != -1) {
+
+ if (fread(&cin,1,1,f) == 1) {
+
+ // Check for <LF>/<CR>
+ if (cin != (char)10 && cin != (char)13) {
+
+ // If NOT <LF> or <CR>
+ if (i < MAX_LINE_SIZE) {
+
+ // Add to buffer
+ line[i++] = cin;
+ line[i] = (char)0;
+ }
+ }
+
+ else { // Found a <LF> or <CR>, process line
+ i = 0;
+
+ // Check whether comment or zero-length line
+ if (line[0] != '#' && strlen(line) > 0) {
+
+ // Line looks good. Send it to the TNC.
+
+ if (send_ctrl_C) {
+ // Control-C desired
+ xastir_snprintf(command,
+ sizeof(command),
+ "%c%s\r",
+ (char)03, // Control-C
+ line);
+ }
+ else {
+ // No Control-C desired
+ xastir_snprintf(command,
+ sizeof(command),
+ "%s\r",
+ line);
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"CMD:%s\n",command);
+
+ port_write_string(port,command);
+ line[0] = (char)0;
+
+ // Set flag to default condition
+ send_ctrl_C = 1;
+ }
+ else { // Check comment to see if it is a META
+ // command
+
+ // Should we make these ignore white-space?
+
+ if (strncasecmp(line, "##META <", 8) == 0) {
+ // Found a META command, process it
+ if (strncasecmp(line+8, "delay", 5) == 0) {
+ usleep(500000); // Sleep 500ms
+ }
+ else if (strncasecmp(line+8, "no-ctrl-c", 9) == 0) {
+ // Reset the flag
+ send_ctrl_C = 0;
+ }
+ else {
+ fprintf(stderr,
+ "Unrecognized ##META command: %s\n",
+ line);
+ }
+ }
+ }
+ }
+ }
+ }
+ (void)fclose(f);
+ } else {
+ if (debug_level & 2)
+ fprintf(stderr,"Could not open TNC command file: %s\n",filename);
+ }
+
+ return(error);
+}
+
+
+
+
+
+//***********************************************************
+// port_dtr INIT
+// port is port# used
+// dtr 1 is down, 0 is normal(up)
+//***********************************************************
+void port_dtr(int port, int dtr) {
+
+// It looks like we have two methods of getting this to compile on
+// CYGWIN, getting rid of the entire procedure contents, and getting
+// rid of the TIO* code. One method or the other should work to get
+// it compiled. We shouldn't need both.
+ int sg;
+
+ /* check for 1 or 0 */
+ dtr = (dtr & 0x1);
+
+ if (begin_critical_section(&port_data_lock, "interface.c:port_dtr(1)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ if (port_data[port].active == DEVICE_IN_USE
+ && port_data[port].status == DEVICE_UP
+ && port_data[port].device_type == DEVICE_SERIAL_TNC_HSP_GPS){
+
+ port_data[port].dtr = dtr;
+ if (debug_level & 2)
+ fprintf(stderr,"DTR %d\n",port_data[port].dtr);
+
+#ifdef TIOCMGET
+ ENABLE_SETUID_PRIVILEGE;
+ (void)ioctl(port_data[port].channel, TIOCMGET, &sg);
+ DISABLE_SETUID_PRIVILEGE;
+#endif // TIOCMGET
+
+ sg &= 0xff;
+
+#ifdef TIOCM_DTR
+
+// ugly HPUX hack - n8ysz 20041206
+
+#ifndef MDTR
+#define MDTR 99999
+#if (TIOCM_DTR == 99999)
+#include <sys/modem.h>
+#endif
+#endif
+
+// end ugly hack
+
+ sg = TIOCM_DTR;
+#endif // TIOCM_DIR
+
+ if (dtr) {
+ dtr &= ~sg;
+
+#ifdef TIOCMBIC
+ ENABLE_SETUID_PRIVILEGE;
+ (void)ioctl(port_data[port].channel, TIOCMBIC, &sg);
+ DISABLE_SETUID_PRIVILEGE;
+#endif // TIOCMBIC
+
+ if (debug_level & 2)
+ fprintf(stderr,"Down\n");
+
+ // statusline(langcode("BBARSTA026"),1);
+
+ } else {
+ dtr |= sg;
+
+#ifdef TIOCMBIS
+ ENABLE_SETUID_PRIVILEGE;
+ (void)ioctl(port_data[port].channel, TIOCMBIS, &sg);
+ DISABLE_SETUID_PRIVILEGE;
+#endif // TIOCMBIS
+
+ if (debug_level & 2)
+ fprintf(stderr,"UP\n");
+
+ // statusline(langcode("BBARSTA027"),1);
+ }
+ }
+
+ if (end_critical_section(&port_data_lock, "interface.c:port_dtr(2)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+}
+
+
+
+
+
+//***********************************************************
+// port_dtr INIT
+// port is port# used
+// dtr 1 is down, 0 is normal(up)
+//***********************************************************
+void dtr_all_set(int dtr) {
+ int i;
+
+//fprintf(stderr,"dtr_all_set(%d)\t",dtr);
+ for (i = 0; i < MAX_IFACE_DEVICES; i++) {
+ if (port_data[i].device_type == DEVICE_SERIAL_TNC_HSP_GPS
+ && port_data[i].status == DEVICE_UP) {
+ port_dtr(i,dtr);
+ }
+ }
+}
+
+
+
+
+
+//***********************************************************
+// Serial port close. Remove the lockfile as well.
+// port is port# used
+//***********************************************************
+int serial_detach(int port) {
+ char fn[600];
+ int ok;
+ ok = -1;
+
+ if (begin_critical_section(&port_data_lock, "interface.c:serial_detach(1)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ if (port_data[port].active == DEVICE_IN_USE && port_data[port].status == DEVICE_UP){
+
+ // Close port first
+ (void)tcsetattr(port_data[port].channel, TCSANOW, &port_data[port].t_old);
+ if (close(port_data[port].channel) == 0) {
+ port_data[port].status = DEVICE_DOWN;
+ usleep(200);
+ port_data[port].active = DEVICE_NOT_IN_USE;
+ ok = 1;
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+ }
+ else {
+ if (debug_level & 2)
+ fprintf(stderr,"Could not close port %s\n",port_data[port].device_name);
+
+ port_data[port].status = DEVICE_DOWN;
+ usleep(200);
+ port_data[port].active = DEVICE_NOT_IN_USE;
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+ }
+
+ // Delete lockfile
+ xastir_snprintf(fn, sizeof(fn), "/var/lock/LCK..%s", get_device_name_only(port_data[port].device_name));
+ if (debug_level & 2)
+ fprintf(stderr,"Delete lock file %s\n",fn);
+
+ ENABLE_SETUID_PRIVILEGE;
+ (void)unlink(fn);
+ DISABLE_SETUID_PRIVILEGE;
+ }
+ else {
+
+ // If we didn't have the port in use, for instance we
+ // weren't able to open it, we should check whether a
+ // lockfile exists for the port and see if another running
+ // process owns the lockfile (the PID of the owner is inside
+ // the lockfile). If not, remove the lockfile 'cuz it may
+ // have been ours from this or a previous run. Note that we
+ // can now run multiple Xastir sessions from a single user,
+ // and the lockfiles must be kept straight between them. If
+ // a lockfile doesn't contain a PID from a running process,
+ // it's fair game to delete the lockfile and/or take over
+ // the port with a new lockfile.
+ //
+ // if (lockfile exists) {
+ // PID = read contents of lockfile
+ // if (PID is running) {
+ // Do nothing, leave the file alone
+ // }
+ // else {
+ // Delete the lockfile
+ // }
+ // }
+ }
+
+ if (end_critical_section(&port_data_lock, "interface.c:serial_detach(2)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ return(ok);
+}
+
+
+
+
+
+//***********************************************************
+// Serial port INIT
+// port is port# used
+//***********************************************************
+int serial_init (int port) {
+ FILE *lock;
+ int speed;
+ pid_t mypid = 0;
+ pid_t lockfile_pid = 0;
+ int lockfile_intpid;
+ char fn[600];
+ uid_t user_id;
+ struct passwd *user_info;
+ char temp[100];
+ char temp1[100];
+ pid_t status;
+ int ii;
+ int myerrno;
+
+ status = -9999;
+
+ if (begin_critical_section(&port_data_lock, "interface.c:serial_init(1)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ // clear port_channel
+ port_data[port].channel = -1;
+
+ // clear port active
+ port_data[port].active = DEVICE_NOT_IN_USE;
+
+ // clear port status
+ port_data[port].status = DEVICE_DOWN;
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+
+
+ // Check whether we have a port with the same device already
+ // open. Check all ports except this one and check for
+ // DEVICE_IN_USE. If found, check whether the device_name
+ // matches. If a match, skip initializing this port.
+ //
+ for (ii = 0; ii < MAX_IFACE_DEVICES; ii++) {
+ if (ii != port) {
+ if (port_data[ii].active == DEVICE_IN_USE) {
+ if (strcmp(port_data[ii].device_name, port_data[port].device_name) == 0) {
+ // Found a port with the same device_name which
+ // is already active. Skip bringing up another
+ // interface on the same port.
+ return(-1);
+ }
+ }
+ }
+ }
+
+
+ // check for lockfile
+ xastir_snprintf(fn, sizeof(fn), "/var/lock/LCK..%s",
+ get_device_name_only(port_data[port].device_name));
+
+ if (filethere(fn) == 1) {
+
+ // Also look for pid of other process and see if it is a valid lock
+ fprintf(stderr,"Found an existing lockfile %s for this port!\n",fn);
+
+ lock = fopen(fn,"r");
+ if (lock != NULL) { // We could open it so it must have
+ // been created by this userid
+ if (fscanf(lock,"%d %99s %99s",&lockfile_intpid,temp,temp1) == 3) {
+ //fprintf(stderr,"Current lock %d %s %s\n",lockfile_intpid,temp,temp1);
+ lockfile_pid = (pid_t)lockfile_intpid;
+
+#ifdef HAVE_GETPGRP
+ #ifdef GETPGRP_VOID
+ // Won't this one get our process group instead of
+ // the process group for the lockfile? Not of that
+ // much use to us here.
+ status = getpgrp();
+ #else // GETPGRP_VOID
+ status = getpgrp(lockfile_pid);
+ #endif // GETPGRP_VOID
+#else // HAVE_GETPGRP
+ status = getpgid(lockfile_pid);
+#endif // HAVE_GETPGRP
+
+ }
+ else {
+ // fscanf parsed the wrong number of items.
+ // lockfile is different, perhaps created by some
+ // other program.
+ }
+
+ (void)fclose(lock);
+
+ // See whether the existing lockfile is stale. Remove
+ // the file if it belongs to our process group or if the
+ // PID in the file is no longer running.
+ //
+ // The only time we _shouldn't_ delete the file and
+ // claim the port for our own is when the process that
+ // created the lockfile is still running.
+
+ // Get my process id
+ mypid = getpid();
+
+ // If status = -1, the process that created the lockfile
+ // is no longer running and of course will not match
+ // "lockfile_pid", so we can delete it.
+ //
+ // If "lockfile_pid == mypid", then this currently
+ // running instance of Xastir was the one that created
+ // the lockfile and it is again ok to delete it.
+ //
+ if (status != lockfile_pid || lockfile_pid == mypid) {
+ fprintf(stderr,"Lock is stale! Removing it.\n");
+ ENABLE_SETUID_PRIVILEGE;
+ (void)unlink(fn);
+ DISABLE_SETUID_PRIVILEGE;
+ }
+ else {
+ fprintf(stderr,"Cannot open port: Another program has the lock!\n");
+
+ if (end_critical_section(&port_data_lock, "interface.c:serial_init(2)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ return (-1);
+ }
+ }
+ else { // Couldn't open it, so the lock must have been
+ // created by another userid
+ fprintf(stderr,"Cannot open port: Lockfile cannot be opened!\n");
+
+ if (end_critical_section(&port_data_lock, "interface.c:serial_init(3)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ return (-1);
+ }
+ }
+
+ // Try to open the serial port now
+ ENABLE_SETUID_PRIVILEGE;
+ port_data[port].channel = open(port_data[port].device_name, O_RDWR|O_NOCTTY);
+ myerrno = errno;
+ DISABLE_SETUID_PRIVILEGE;
+ if (port_data[port].channel == -1){
+
+ if (end_critical_section(&port_data_lock, "interface.c:serial_init(4)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Could not open channel on port %d!\n",port);
+
+ switch (myerrno) {
+
+ case EACCES:
+ fprintf(stderr,"\tEACCESS ERROR\n");
+ break;
+
+ case EEXIST:
+ fprintf(stderr,"\tEEXIST ERROR\n");
+ break;
+
+ case EFAULT:
+ fprintf(stderr,"\tEFAULT ERROR\n");
+ break;
+
+ case EISDIR:
+ fprintf(stderr,"\tEISDIR ERROR\n");
+ break;
+
+ case ELOOP:
+ fprintf(stderr,"\tELOOP ERROR\n");
+ break;
+
+ case EMFILE:
+ fprintf(stderr,"\tEMFILE ERROR\n");
+ break;
+
+ case ENAMETOOLONG:
+ fprintf(stderr,"\tENAMETOOLONG ERROR\n");
+ break;
+
+ case ENFILE:
+ fprintf(stderr,"\tEMFILE ERROR\n");
+ break;
+
+ case ENODEV:
+ fprintf(stderr,"\tENODEV ERROR\n");
+ break;
+
+ case ENOENT:
+ fprintf(stderr,"\tENOENT ERROR\n");
+ break;
+
+ case ENOMEM:
+ fprintf(stderr,"\tENOMEM ERROR\n");
+ break;
+
+ case ENOSPC:
+ fprintf(stderr,"\tENOSPC ERROR\n");
+ break;
+
+ case ENOTDIR:
+ fprintf(stderr,"\tENOTDIR ERROR\n");
+ break;
+
+ case ENXIO:
+ fprintf(stderr,"\tENXIO ERROR\n");
+ break;
+
+ case EOVERFLOW:
+ fprintf(stderr,"\tEOVERFLOW ERROR\n");
+ break;
+
+ case EPERM:
+ fprintf(stderr,"\tEPERM ERROR\n");
+ break;
+
+ case EROFS:
+ fprintf(stderr,"\tEROFS ERROR\n");
+ break;
+
+ case ETXTBSY:
+ fprintf(stderr,"\tETXTBSY ERROR\n");
+ break;
+
+ default:
+ fprintf(stderr,"\tOTHER ERROR\n");
+ break;
+ }
+
+ return (-1);
+ }
+
+ // Attempt to create the lockfile
+ xastir_snprintf(fn, sizeof(fn), "/var/lock/LCK..%s", get_device_name_only(port_data[port].device_name));
+ if (debug_level & 2)
+ fprintf(stderr,"Create lock file %s\n",fn);
+
+ ENABLE_SETUID_PRIVILEGE;
+ lock = fopen(fn,"w");
+ DISABLE_SETUID_PRIVILEGE;
+ if (lock != NULL) {
+ // get my process id for lockfile
+ mypid = getpid();
+
+ // get user info
+ user_id = getuid();
+ user_info = getpwuid(user_id);
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ user_info->pw_name);
+
+ fprintf(lock,"%9d %s %s",(int)mypid,"xastir",temp);
+ (void)fclose(lock);
+ // We've successfully created our own lockfile
+ }
+ else {
+ // lock failed
+ if (debug_level & 2)
+ fprintf(stderr,"Warning: Failed opening LCK file! Continuing on...\n");
+
+ /* if we can't create lockfile don't fail!
+
+if (end_critical_section(&port_data_lock, "interface.c:serial_init(5)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ return (-1);*/
+ }
+
+ // get port attributes for new and old
+ if (tcgetattr(port_data[port].channel, &port_data[port].t) != 0) {
+
+ if (end_critical_section(&port_data_lock, "interface.c:serial_init(6)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Could not get t port attributes for port %d!\n",port);
+
+ // Close the port and remove the lock.
+ serial_detach(port);
+
+ return (-1);
+ }
+
+ if (tcgetattr(port_data[port].channel, &port_data[port].t_old) != 0) {
+
+ if (end_critical_section(&port_data_lock, "interface.c:serial_init(7)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Could not get t_old port attributes for port %d!\n",port);
+
+ // Close the port and remove the lock.
+ serial_detach(port);
+
+ return (-1);
+ }
+
+ // set time outs
+ port_data[port].t.c_cc[VMIN] = (cc_t)1;
+ port_data[port].t.c_cc[VTIME] = (cc_t)2;
+
+ // set port flags
+ port_data[port].t.c_iflag &= ~(BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
+ port_data[port].t.c_iflag = (tcflag_t)(IGNBRK | IGNPAR);
+
+ port_data[port].t.c_oflag = (0);
+ port_data[port].t.c_lflag = (0);
+
+#ifdef CBAUD
+ speed = (int)(port_data[port].t.c_cflag & CBAUD);
+#else // CBAUD
+ speed = 0;
+#endif // CBAUD
+ port_data[port].t.c_cflag = (tcflag_t)(HUPCL|CLOCAL|CREAD);
+ port_data[port].t.c_cflag &= ~PARENB;
+ switch (port_data[port].style){
+ case(0):
+ // No parity (8N1)
+ port_data[port].t.c_cflag &= ~CSTOPB;
+ port_data[port].t.c_cflag &= ~CSIZE;
+ port_data[port].t.c_cflag |= CS8;
+ break;
+
+ case(1):
+ // Even parity (7E1)
+ port_data[port].t.c_cflag &= ~PARODD;
+ port_data[port].t.c_cflag &= ~CSTOPB;
+ port_data[port].t.c_cflag &= ~CSIZE;
+ port_data[port].t.c_cflag |= CS7;
+ break;
+
+ case(2):
+ // Odd parity (7O1):
+ port_data[port].t.c_cflag |= PARODD;
+ port_data[port].t.c_cflag &= ~CSTOPB;
+ port_data[port].t.c_cflag &= ~CSIZE;
+ port_data[port].t.c_cflag |= CS7;
+ break;
+
+ default:
+ break;
+ }
+
+ port_data[port].t.c_cflag |= speed;
+ // set input and out put speed
+ if (cfsetispeed(&port_data[port].t, port_data[port].sp) == -1) {
+
+ if (end_critical_section(&port_data_lock, "interface.c:serial_init(8)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Could not set port input speed for port %d!\n",port);
+
+ // Close the port and remove the lock.
+ serial_detach(port);
+
+ return (-1);
+ }
+
+ if (cfsetospeed(&port_data[port].t, port_data[port].sp) == -1) {
+
+ if (end_critical_section(&port_data_lock, "interface.c:serial_init(9)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Could not set port output speed for port %d!\n",port);
+
+ // Close the port and remove the lock.
+ serial_detach(port);
+
+ return (-1);
+ }
+
+ if (tcflush(port_data[port].channel, TCIFLUSH) == -1) {
+
+ if (end_critical_section(&port_data_lock, "interface.c:serial_init(10)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Could not flush data for port %d!\n",port);
+
+ // Close the port and remove the lock.
+ serial_detach(port);
+
+ return (-1);
+ }
+
+ if (tcsetattr(port_data[port].channel,TCSANOW, &port_data[port].t) == -1) {
+
+ if (end_critical_section(&port_data_lock, "interface.c:serial_init(11)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Could not set port attributes for port %d!\n",port);
+
+ // Close the port and remove the lock.
+ serial_detach(port);
+
+ return (-1);
+ }
+
+ // clear port active
+ port_data[port].active = DEVICE_IN_USE;
+
+ // clear port status
+ port_data[port].status = DEVICE_UP;
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+
+ if (end_critical_section(&port_data_lock, "interface.c:serial_init(12)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ // return good condition
+ return (1);
+}
+
+//*************************** STOP SERIAL PORT FUNCTIONS ********************************
+
+
+
+
+
+//***************************** START NETWORK FUNCTIONS *********************************
+
+//**************************************************************
+// net_connect_thread()
+// Temporary thread used to start up a socket.
+//**************************************************************
+static void* net_connect_thread(void *arg) {
+ int port;
+ volatile int ok = -1;
+ int len;
+ int result;
+ int flag;
+ //int stat;
+ struct sockaddr_in address;
+
+ // Some messiness necessary because we're using
+ // xastir_mutex's instead of pthread_mutex_t's.
+ pthread_mutex_t *cleanup_mutex;
+
+
+ if (debug_level & 2)
+ fprintf(stderr,"net_connect_thread start\n");
+
+ port = *((int *) arg);
+ // This call means we don't care about the return code and won't
+ // use pthread_join() later. Makes threading more efficient.
+ (void)pthread_detach(pthread_self());
+
+//if (begin_critical_section(&port_data_lock, "interface.c:net_connect_thread(1)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ /* set address */
+ address.sin_addr.s_addr = (port_data[port].address);
+
+ // Create a socket if we don't have one yet for this channel
+ if (port_data[port].channel == -1) {
+ pthread_testcancel(); // Check for thread termination request
+ port_data[port].channel = socket(PF_INET, SOCK_STREAM, 0);
+ pthread_testcancel(); // Check for thread termination request
+ }
+
+ if (port_data[port].channel != -1) {
+ if (debug_level & 2)
+ fprintf(stderr,"We have a socket to use\n");
+ address.sin_family = AF_INET;
+ address.sin_port = htons(port_data[port].socket_port);
+ if (debug_level & 2)
+ fprintf(stderr,"after htons\n");
+ len = (int)sizeof(address);
+ flag = 1;
+
+ // Turn on the socket keepalive option
+ (void)setsockopt(port_data[port].channel, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int));
+
+ // Disable the Nagle algorithm (speeds things up)
+ (void)setsockopt(port_data[port].channel, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
+
+ if (debug_level & 2)
+ fprintf(stderr,"after setsockopt\n");
+ pthread_testcancel(); // Check for thread termination request
+ if (debug_level & 2)
+ fprintf(stderr,"calling connect(), port: %d\n", port_data[port].socket_port);
+ result = connect(port_data[port].channel, (struct sockaddr *)&address, len);
+ if (debug_level & 2)
+ fprintf(stderr,"connect result was: %d\n", result);
+ ok = 0;
+ pthread_testcancel(); // Check for thread termination request
+ if (result != -1){
+ /* connection up */
+ if (debug_level & 2)
+ fprintf(stderr,"net_connect_thread():Net up, port %d\n",port);
+
+ port_data[port].status = DEVICE_UP;
+ ok = 1;
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+ }
+ else { /* net connection failed */
+ ok = 0;
+ if (debug_level & 2)
+ fprintf(stderr,"net_connect_thread():net connection failed, port %d, DEVICE_ERROR ***\n",port);
+ port_data[port].status = DEVICE_ERROR;
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+
+ // Shut down and close the socket
+
+ //pthread_testcancel(); // Check for thread termination request
+ //
+ // Don't do a shutdown! The socket wasn't connected. This causes
+ // problems due to the same socket number getting recycled. It can
+ // shut down another socket.
+ //
+ //stat = shutdown(port_data[port].channel,2);
+ //pthread_testcancel(); // Check for thread termination request
+ //if (debug_level & 2)
+ // fprintf(stderr,"net_connect_thread():Net Shutdown 1 Returned %d, port %d\n",stat,port);
+
+ usleep(100000); // 100ms
+ //pthread_testcancel(); // Check for thread termination request
+ //stat = close(port_data[port].channel);
+ //pthread_testcancel(); // Check for thread termination request
+ //if (debug_level & 2)
+ // fprintf(stderr,"net_connect_thread():Net Close 1 Returned %d, port %d\n",stat,port);
+
+ //if (debug_level & 2)
+ // fprintf(stderr,"net_connect_thread():Net connection 1 failed, port %d\n",port);
+ }
+ } else { /* Could not bind socket */
+ ok = -1;
+ if (debug_level & 2)
+ fprintf(stderr,"net_connect_thread():could not bind socket, port %d, DEVICE_ERROR ***\n",port);
+ port_data[port].status = DEVICE_ERROR;
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+
+ // Shut down and close the socket
+ //pthread_testcancel(); // Check for thread termination request
+ //
+ // Don't do a shutdown! The socket wasn't connected. This causes
+ // problems due to the same socket number getting recycled. It can
+ // shut down another socket.
+ //
+ //stat = shutdown(port_data[port].channel,2);
+ //pthread_testcancel(); // Check for thread termination request
+ //if (debug_level & 2)
+ // fprintf(stderr,"net_connect_thread():Net Shutdown 2 Returned %d, port %d\n",stat,port);
+
+ usleep(100000); // 100ms
+ //pthread_testcancel(); // Check for thread termination request
+ //stat = close(port_data[port].channel);
+ //pthread_testcancel(); // Check for thread termination request
+ //if (debug_level & 2)
+ // fprintf(stderr,"net_connect_thread():Net Close 2 Returned %d, port %d\n",stat,port);
+
+ //if (debug_level & 2)
+ // fprintf(stderr,"net_connect_thread():Could not bind socket, port %d\n",port);
+ }
+
+
+ // Install the cleanup routine for the case where this thread
+ // gets killed while the mutex is locked. The cleanup routine
+ // initiates an unlock before the thread dies. We must be in
+ // deferred cancellation mode for the thread to have this work
+ // properly. We must first get the pthread_mutex_t address:
+ cleanup_mutex = &connect_lock.lock;
+
+ // Then install the cleanup routine:
+ pthread_cleanup_push((void *)pthread_mutex_unlock, (void *)cleanup_mutex);
+// pthread_cleanup_push(void (*pthread_mutex_unlock)(void *), (void *)cleanup_mutex);
+
+
+ if (begin_critical_section(&connect_lock, "interface.c:net_connect_thread(2)" ) > 0)
+ fprintf(stderr,"net_connect_thread():connect_lock, Port = %d\n", port);
+
+ port_data[port].connect_status = ok;
+ port_data[port].thread_status = 0;
+
+ if (end_critical_section(&connect_lock, "interface.c:net_connect_thread(3)" ) > 0)
+ fprintf(stderr,"net_connect_thread():connect_lock, Port = %d\n", port);
+
+ // Remove the cleanup routine for the case where this thread
+ // gets killed while the mutex is locked. The cleanup routine
+ // initiates an unlock before the thread dies. We must be in
+ // deferred cancellation mode for the thread to have this work
+ // properly.
+//
+// NOTE: Ignore the four \"suggest braces\" warnings you see when
+// compiling, see: http://archive.netbsd.se/?ml=gcc-help&a=2008-06&t=7730779
+//
+ pthread_cleanup_pop(0);
+
+
+//if (end_critical_section(&port_data_lock, "interface.c:net_connect_thread(4)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ if (debug_level & 2)
+ fprintf(stderr,"net_connect_thread terminating itself\n");
+
+ return(NULL); // This should kill the thread
+}
+
+
+
+
+
+//**************************************************************
+// net_init()
+//
+// This brings up a network connection
+//
+// returns -1 on hard error, 0 on time out, 1 if ok
+//**************************************************************
+int net_init(int port) {
+ int ok;
+ int have_address = 0;
+ char ip_addrs[400];
+ char ip_addr[40];
+ char st[200];
+ pthread_t connect_thread;
+ int stat;
+ int wait_on_connect;
+ time_t wait_time;
+ struct in_addr ip_test;
+
+ if (begin_critical_section(&port_data_lock, "interface.c:net_init(1)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ /* clear port_channel */
+// port_data[port].channel = -1;
+
+ /* set port active */
+ port_data[port].active = DEVICE_IN_USE;
+
+ /* clear port status */
+ port_data[port].status = DEVICE_DOWN;
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+
+ ok = -1;
+
+ // Check whether we were passed an IPv4/IPv6 address or a
+ // hostname. If an address, skip the host_lookup.
+ if (inet_aton(port_data[port].device_host_name, &ip_test)) {
+ // We have an IPv4 or IPv6 address already. Set a flag so
+ // that the code below can directly use it.
+ have_address = 1;
+ }
+
+ if (!have_address) {
+ xastir_snprintf(st, sizeof(st), langcode("BBARSTA019"), port_data[port].device_host_name);
+ statusline(st,1); // Looking up host
+
+ //fprintf(stderr,"Hostname Lookup\n");
+
+ // We currently give 13 seconds to look up the hostname
+ (void)host_lookup(port_data[port].device_host_name,
+ ip_addrs,
+ sizeof(ip_addrs),
+ 13);
+ }
+ else {
+ //fprintf(stderr,"Skipping Hostname Lookup\n");
+ }
+
+ if (have_address || strcmp(ip_addrs,"NOIP") != 0) {
+ if (have_address || strcmp(ip_addrs,"NOHOST") != 0) {
+ if (have_address || strcmp(ip_addrs,"TIMEOUT") != 0) { // We found an IP address
+
+ if (have_address) {
+ // Stuff the address passed to us into our
+ // working variable.
+ xastir_snprintf(ip_addr,
+ sizeof(ip_addr),
+ "%s",
+ port_data[port].device_host_name);
+ }
+ else {
+ // Get the first IP address from the lookup.
+ if (1 != sscanf(ip_addrs,"%39s",ip_addr)) {
+ fprintf(stderr,"net_init: sscanf parsing error\n");
+ }
+ }
+ if (debug_level & 2)
+ fprintf(stderr,"IP Address: %s\n",ip_addr);
+ /* set address for connection */
+ port_data[port].address = inet_addr(ip_addr);
+
+ /* ok try to connect */
+
+ if (begin_critical_section(&connect_lock, "interface.c:net_init(2)" ) > 0)
+ fprintf(stderr,"connect_lock, Port = %d\n", port);
+
+ port_data[port].thread_status = 1;
+ port_data[port].connect_status = -1;
+
+ // If channel is != -1, we have a socket remaining from a previous
+ // connect attempt. Shutdown and close that socket, then create
+ // a new one.
+ if (port_data[port].channel != -1) { // We have a socket already
+
+ // Shut down and close the socket
+ pthread_testcancel(); // Check for thread termination request
+ stat = shutdown(port_data[port].channel,2);
+ pthread_testcancel(); // Check for thread termination request
+ if (debug_level & 2)
+ fprintf(stderr,"net_connect_thread():Net Shutdown 1 Returned %d, port %d\n",stat,port);
+ usleep(100000); // 100ms
+ pthread_testcancel(); // Check for thread termination request
+ stat = close(port_data[port].channel);
+ pthread_testcancel(); // Check for thread termination request
+ if (debug_level & 2)
+ fprintf(stderr,"net_connect_thread():Net Close 1 Returned %d, port %d\n",stat,port);
+ usleep(100000); // 100ms
+ port_data[port].channel = -1;
+ }
+
+ if (end_critical_section(&connect_lock, "interface.c:net_init(3)" ) > 0)
+ fprintf(stderr,"connect_lock, Port = %d\n", port);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Creating new thread\n");
+ if (pthread_create(&connect_thread, NULL, net_connect_thread, &port)){
+ /* error starting thread*/
+ ok = -1;
+ fprintf(stderr,"Error creating net_connect thread, port %d\n",port);
+ }
+
+ busy_cursor(appshell);
+ wait_time = sec_now() + NETWORK_WAITTIME; // Set ending time for wait
+ wait_on_connect = 1;
+ while (wait_on_connect && (sec_now() < wait_time)) {
+
+ if (begin_critical_section(&connect_lock, "interface.c:net_init(4)" ) > 0)
+ fprintf(stderr,"connect_lock, Port = %d\n", port);
+
+ wait_on_connect = port_data[port].thread_status;
+
+ if (end_critical_section(&connect_lock, "interface.c:net_init(5)" ) > 0)
+ fprintf(stderr,"connect_lock, Port = %d\n", port);
+
+ xastir_snprintf(st, sizeof(st), langcode("BBARSTA025"), wait_time - sec_now() );
+ statusline(st,1); // Host found, connecting n
+ if (debug_level & 2)
+ fprintf(stderr,"%d\n", (int)(wait_time - sec_now()) );
+
+ /* update display while waiting */
+ // XmUpdateDisplay(XtParent(da));
+ usleep(250000); // 250mS
+ //sched_yield(); // Too fast!
+ }
+
+ ok = port_data[port].connect_status;
+ /* thread did not return! kill it */
+ if ( (sec_now() >= wait_time) // Timed out
+ || (ok != 1) ) { // or connection failure of another type
+ if (debug_level & 2)
+ fprintf(stderr,"Thread exceeded it's time limit or failed to connect! Port %d\n",port);
+
+ if (begin_critical_section(&connect_lock, "interface.c:net_init(6)" ) > 0)
+ fprintf(stderr,"connect_lock, Port = %d\n", port);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Killing thread\n");
+ if (pthread_cancel(connect_thread)) {
+ // The only error code we can get here is ESRCH, which means
+ // that the thread number wasn't found. The thread is already
+ // dead, so let's not print out an error code.
+ //fprintf(stderr,"Error on termination of connect thread!\n");
+ }
+
+ if (sec_now() >= wait_time) { // Timed out
+ port_data[port].connect_status = -2;
+ if (debug_level & 2)
+ fprintf(stderr,"It was a timeout.\n");
+ }
+
+ if (end_critical_section(&connect_lock, "interface.c:net_init(7)" ) > 0)
+ fprintf(stderr,"connect_lock, Port = %d\n", port);
+
+ port_data[port].status = DEVICE_ERROR;
+ if (debug_level & 2)
+ fprintf(stderr,"Thread did not return, port %d, DEVICE_ERROR ***\n",port);
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+ }
+ if (begin_critical_section(&connect_lock, "interface.c:net_init(8)" ) > 0)
+ fprintf(stderr,"connect_lock, Port = %d\n", port);
+
+ ok = port_data[port].connect_status;
+
+ if (end_critical_section(&connect_lock, "interface.c:net_init(9)" ) > 0)
+ fprintf(stderr,"connect_lock, Port = %d\n", port);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Net ok: %d, port %d\n", ok, port);
+
+ switch (ok) {
+
+ case 1: /* connection up */
+ xastir_snprintf(st, sizeof(st), langcode("BBARSTA020"), port_data[port].device_host_name);
+ statusline(st,1); // Connected to ...
+ break;
+
+ case 0:
+ xastir_snprintf(st, sizeof(st), "%s", langcode("BBARSTA021"));
+ statusline(st,1); // Net Connection Failed!
+ ok = -1;
+ break;
+
+ case -1:
+ xastir_snprintf(st, sizeof(st), "%s", langcode("BBARSTA022"));
+ statusline(st,1); // Could not bind socket
+ break;
+
+ case -2:
+ xastir_snprintf(st, sizeof(st), "%s", langcode("BBARSTA018"));
+ statusline(st,1); // Net Connection timed out
+ ok = 0;
+ break;
+
+ default:
+ break;
+ /*break;*/
+ }
+ } else { /* host lookup time out */
+ xastir_snprintf(st, sizeof(st), "%s", langcode("BBARSTA018"));
+ statusline(st,1); // Net Connection timed out
+ port_data[port].status = DEVICE_ERROR;
+ if (debug_level & 2)
+ fprintf(stderr,"Host lookup timeout, port %d, DEVICE_ERROR ***\n",port);
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+
+ ok = 0;
+ }
+ } else { /* Host ip look up failure (no ip address for that host) */
+ xastir_snprintf(st, sizeof(st), "%s", langcode("BBARSTA023"));
+ statusline(st,1); // No IP for Host
+ port_data[port].status = DEVICE_ERROR;
+ if (debug_level & 2)
+ fprintf(stderr,"Host IP lookup failure, port %d, DEVICE_ERROR ***\n",port);
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+ }
+ }
+ else { /* Host look up failure (no host by that name) */
+ xastir_snprintf(st, sizeof(st), "%s", langcode("BBARSTA023"));
+ statusline(st,1); // No IP for Host
+ port_data[port].status = DEVICE_ERROR;
+ if (debug_level & 2)
+ fprintf(stderr,"Host lookup failure, port %d, DEVICE_ERROR ***\n",port);
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+ }
+
+ if (end_critical_section(&port_data_lock, "interface.c:net_init(10)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ if (debug_level & 2)
+ fprintf(stderr,"*** net_init is returning a %d ***\n",ok);
+
+ return(ok);
+}
+
+
+
+
+
+//**************************************************************
+// This shuts down a network connection
+//
+//**************************************************************
+int net_detach(int port) {
+ int ok;
+ int max;
+ int stat;
+ char quiti[2];
+
+ if (debug_level & 2)
+ fprintf(stderr,"Net detach Start, port %d\n",port);
+
+ ok = -1;
+ max = 0;
+
+ if (begin_critical_section(&port_data_lock, "interface.c:net_detach(1)" ) > 0)
+ fprintf(stderr,"net_detach():port_data_lock, Port = %d\n", port);
+
+ if (port_data[port].active == DEVICE_IN_USE) {
+ if (port_data[port].status == DEVICE_UP && port_data[port].device_type == DEVICE_NET_STREAM){
+
+ if (debug_level & 2)
+ fprintf(stderr,"net_detach():Found port %d up, shutting it down\n",port);
+
+ quiti[0] = (char)4;
+ quiti[1] = (char)0;
+ if (port_data[port].status == DEVICE_UP) {
+ port_write_string(port,quiti);
+ usleep(100000); // 100ms
+ }
+ /* wait to write */
+ while (port_data[port].status == DEVICE_UP && port_data[port].write_in_pos != port_data[port].write_out_pos && max < 25) {
+ if (debug_level & 2)
+ fprintf(stderr,"net_detach():Waiting to finish writing data to port %d\n",port);
+
+ //(void)sleep(1);
+ usleep(100000); // 100ms
+ max++;
+ }
+ }
+ /*
+ Shut down and Close were separated but this would cause sockets to
+ just float around
+ */
+
+ // It doesn't matter whether we _think_ the device is up. It might
+ // be in some other state, but the socket still needs to be closed.
+ //if (port_data[port].status == DEVICE_UP) {
+
+ /* we don't need to do a shut down on AX_25 devices */
+ if ( (port_data[port].status == DEVICE_UP)
+ && (port_data[port].device_type != DEVICE_AX25_TNC) ) {
+ stat = shutdown(port_data[port].channel,2);
+ if (debug_level & 2)
+ fprintf(stderr,"net_detach():Net Shutdown Returned %d, port %d\n",stat,port);
+ }
+
+ usleep(100000); // 100ms
+ // We wish to close down the socket (so both ends of the darn thing
+ // go away), but we want to keep the number on those systems that
+ // re-assign the same file descriptor again. This is to prevent
+ // cross-connects from one interface to another in Xastir (big pain!).
+
+ // Close it
+ stat = close(port_data[port].channel);
+ if (debug_level & 2)
+ fprintf(stderr,"net_detach():Net Close Returned %d, port %d\n",stat,port);
+
+ usleep(100000); // 100ms
+
+ // Snag a socket again. We'll use it next time around.
+ port_data[port].channel = socket(PF_INET, SOCK_STREAM, 0);
+
+ ok = 1;
+ }
+ /* close down no matter what */
+ port_data[port].status = DEVICE_DOWN;
+ //usleep(300);
+ port_data[port].active = DEVICE_NOT_IN_USE;
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+
+ if (end_critical_section(&port_data_lock, "interface.c:net_detach(2)" ) > 0)
+ fprintf(stderr,"net_detach():port_data_lock, Port = %d\n", port);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Net detach stop, port %d\n",port);
+
+ return(ok);
+}
+
+
+
+
+
+//***************************** STOP NETWORK FUNCTIONS **********************************
+
+
+
+// This routine changes callsign chars to proper uppercase chars or
+// numerals, fixes the callsign to six bytes, shifts the letters left by
+// one bit, and puts the SSID number into the proper bits in the seventh
+// byte. The callsign as processed is ready for inclusion in an
+// AX.25 header.
+//
+void fix_up_callsign(unsigned char *data, int data_size) {
+ unsigned char new_call[8] = " "; // Start with seven spaces
+ int ssid = 0;
+ int i;
+ int j = 0;
+ int digipeated_flag = 0;
+
+
+ // Check whether we've digipeated through this callsign yet.
+ if (strstr((const char *)data,"*") != 0) {
+ digipeated_flag++;
+ }
+
+ // Change callsign to upper-case and pad out to six places with
+ // space characters.
+ for (i = 0; i < (int)strlen((const char *)data); i++) {
+ toupper(data[i]);
+
+ if (data[i] == '-') { // Stop at '-'
+ break;
+ }
+ else if (data[i] == '*') {
+ }
+ else {
+ new_call[j++] = data[i];
+ }
+ }
+ new_call[7] = '\0';
+
+ //fprintf(stderr,"new_call:(%s)\n",new_call);
+
+ // Handle SSID. 'i' should now be pointing at a dash or at the
+ // terminating zero character.
+ if ( (i < (int)strlen((const char *)data)) && (data[i++] == '-') ) { // We might have an SSID
+ if (data[i] != '\0')
+ ssid = atoi((const char *)&data[i]);
+// ssid = data[i++] - 0x30; // Convert from ascii to int
+// if (data[i] != '\0')
+// ssid = (ssid * 10) + (data[i] - 0x30);
+ }
+
+//fprintf(stderr,"SSID:%d\t",ssid);
+
+ if (ssid >= 0 && ssid <= 15) {
+ new_call[6] = ssid | 0x30; // Set 2 reserved bits
+ }
+ else { // Whacko SSID. Set it to zero
+ new_call[6] = 0x30; // Set 2 reserved bits
+ }
+
+ if (digipeated_flag) {
+ new_call[6] = new_call[6] | 0x40; // Set the 'H' bit
+ }
+
+ // Shift each byte one bit to the left
+ for (i = 0; i < 7; i++) {
+ new_call[i] = new_call[i] << 1;
+ new_call[i] = new_call[i] & 0xfe;
+ }
+
+//fprintf(stderr,"Last:%0x\n",new_call[6]);
+
+ // Write over the top of the input string with the newly
+ // formatted callsign
+ xastir_snprintf((char *)data,
+ data_size,
+ "%s",
+ new_call);
+}
+
+
+
+
+
+//-------------------------------------------------------------------
+// Had to snag code from port_write_string() below because our string
+// needs to have 0x00 chars inside it. port_write_string() can't
+// handle that case. It's a good thing the transmit queue stuff
+// could handle it.
+//-------------------------------------------------------------------
+//
+//WE7U
+// Modify the other routines that needed binary output so that they
+// use this routine.
+//
+void port_write_binary(int port, unsigned char *data, int length) {
+ int ii,erd;
+ int write_in_pos_hold;
+
+
+//fprintf(stderr,"Sending to AGWPE:\n");
+
+ erd = 0;
+
+ if (begin_critical_section(&port_data[port].write_lock, "interface.c:port_write_binary(1)" ) > 0)
+ fprintf(stderr,"write_lock, Port = %d\n", port);
+
+ // Save the current position, just in case we have trouble
+ write_in_pos_hold = port_data[port].write_in_pos;
+
+ for (ii = 0; ii < length && !erd; ii++) {
+
+//fprintf(stderr,"%02x ",data[ii]);
+
+ // Put character into write buffer and advance pointer
+ port_data[port].device_write_buffer[port_data[port].write_in_pos++] = data[ii];
+
+ // Check whether we need to wrap back to the start of the
+ // circular buffer
+ if (port_data[port].write_in_pos >= MAX_DEVICE_BUFFER)
+ port_data[port].write_in_pos = 0;
+
+ // Check whether we just filled our buffer (read/write
+ // pointers are equal). If so, exit gracefully, dumping
+ // this string and resetting the write pointer.
+ if (port_data[port].write_in_pos == port_data[port].write_out_pos) {
+ if (debug_level & 2)
+ fprintf(stderr,"Port %d Buffer overrun\n",port);
+
+ // Restore original write_in pos and dump this string
+ port_data[port].write_in_pos = write_in_pos_hold;
+ port_data[port].errors++;
+ erd = 1;
+ }
+ }
+
+// Check that the data got placed in the buffer ok
+//for (ii = write_in_pos_hold; ii < port_data[port].write_in_pos; ii++) {
+// fprintf(stderr,"%02x ",port_data[port].device_write_buffer[ii]);
+//}
+//fprintf(stderr,"\n");
+
+
+ if (end_critical_section(&port_data[port].write_lock, "interface.c:port_write_binary(2)" ) > 0)
+ fprintf(stderr,"write_lock, Port = %d\n", port);
+
+//fprintf(stderr,"\n");
+
+}
+
+
+
+
+
+// Create an AX25 frame and then turn it into a KISS packet. Dump
+// it into the transmit queue.
+//
+void send_ax25_frame(int port, char *source, char *destination, char *path, char *data) {
+ unsigned char temp_source[15];
+ unsigned char temp_dest[15];
+ unsigned char temp[15];
+ unsigned char control[2], pid[2];
+ unsigned char transmit_txt[MAX_LINE_SIZE*2];
+ unsigned char transmit_txt2[MAX_LINE_SIZE*2];
+ unsigned char c;
+ int i, j;
+ int erd;
+ int write_in_pos_hold;
+
+
+//fprintf(stderr,"KISS String:%s>%s,%s:%s\n",source,destination,path,data);
+
+ // Check whether transmits are disabled globally
+ if (transmit_disable) {
+ return;
+ }
+
+ // Check whether transmit has been enabled for this interface.
+ // If not, get out while the gettin's good.
+ if (devices[port].transmit_data != 1) {
+ return;
+ }
+
+ transmit_txt[0] = '\0';
+
+ // Format the destination callsign
+ xastir_snprintf((char *)temp_dest,
+ sizeof(temp_dest),
+ "%s",
+ destination);
+ fix_up_callsign(temp_dest, sizeof(temp_dest));
+ xastir_snprintf((char *)transmit_txt,
+ sizeof(transmit_txt),
+ "%s",
+ temp_dest);
+
+ // Format the source callsign
+ xastir_snprintf((char *)temp_source,
+ sizeof(temp_source),
+ "%s",
+ source);
+ fix_up_callsign(temp_source, sizeof(temp_source));
+ strncat((char *)transmit_txt,
+ (char *)temp_source,
+ sizeof(transmit_txt) - 1 - strlen((char *)transmit_txt));
+
+ // Break up the path into individual callsigns and send them one
+ // by one to fix_up_callsign(). If we get passed an empty path,
+ // we merely skip this section and no path gets added to
+ // "transmit_txt".
+ j = 0;
+ temp[0] = '\0'; // Start with empty path
+ if ( (path != NULL) && (strlen(path) != 0) ) {
+ while (path[j] != '\0') {
+ i = 0;
+ while ( (path[j] != ',') && (path[j] != '\0') ) {
+ temp[i++] = path[j++];
+ }
+ temp[i] = '\0';
+
+ if (path[j] == ',') { // Skip over comma
+ j++;
+ }
+
+//fprintf(stderr,"%s\n",temp);
+
+ fix_up_callsign(temp, sizeof(temp));
+ strncat((char *)transmit_txt,
+ (char *)temp,
+ sizeof(transmit_txt) - 1 - strlen((char *)transmit_txt));
+ }
+ }
+
+ // Set the end-of-address bit on the last callsign in the
+ // address field
+ transmit_txt[strlen((const char *)transmit_txt) - 1] |= 0x01;
+
+ // Add the Control byte
+ control[0] = 0x03;
+ control[1] = '\0';
+ strncat((char *)transmit_txt,
+ (char *)control,
+ sizeof(transmit_txt) - 1 - strlen((char *)transmit_txt));
+
+ // Add the PID byte
+ pid[0] = 0xf0;
+ pid[1] = '\0';
+ strncat((char *)transmit_txt,
+ (char *)pid,
+ sizeof(transmit_txt) - 1 - strlen((char *)transmit_txt));
+
+ // Append the information chars
+ strncat((char *)transmit_txt,
+ data,
+ sizeof(transmit_txt) - 1 - strlen((char *)transmit_txt));
+
+ //fprintf(stderr,"%s\n",transmit_txt);
+
+ // Add the KISS framing characters and do the proper escapes.
+ j = 0;
+ transmit_txt2[j++] = KISS_FEND;
+
+ // Note: This byte is where different interfaces would be
+ // specified:
+ transmit_txt2[j++] = 0x00;
+
+ for (i = 0; i < (int)strlen((const char *)transmit_txt); i++) {
+ c = transmit_txt[i];
+ if (c == KISS_FEND) {
+ transmit_txt2[j++] = KISS_FESC;
+ transmit_txt2[j++] = KISS_TFEND;
+ }
+ else if (c == KISS_FESC) {
+ transmit_txt2[j++] = KISS_FESC;
+ transmit_txt2[j++] = KISS_TFESC;
+ }
+ else {
+ transmit_txt2[j++] = c;
+ }
+ }
+ transmit_txt2[j++] = KISS_FEND;
+
+ // Terminate the string, but don't increment the 'j' counter.
+ // We don't want to send the NULL byte out the KISS interface,
+ // just make sure the string is terminated in all cases.
+ //
+ transmit_txt2[j] = '\0';
+
+//-------------------------------------------------------------------
+// Had to snag code from port_write_string() below because our string
+// needs to have 0x00 chars inside it. port_write_string() can't
+// handle that case. It's a good thing the transmit queue stuff
+// could handle it.
+//-------------------------------------------------------------------
+
+ erd = 0;
+
+ if (begin_critical_section(&port_data[port].write_lock, "interface.c:send_ax25_frame(1)" ) > 0)
+ fprintf(stderr,"write_lock, Port = %d\n", port);
+
+ write_in_pos_hold = port_data[port].write_in_pos;
+
+ for (i = 0; i < j && !erd; i++) {
+ port_data[port].device_write_buffer[port_data[port].write_in_pos++] = transmit_txt2[i];
+ if (port_data[port].write_in_pos >= MAX_DEVICE_BUFFER)
+ port_data[port].write_in_pos = 0;
+
+ if (port_data[port].write_in_pos == port_data[port].write_out_pos) {
+ if (debug_level & 2)
+ fprintf(stderr,"Port %d Buffer overrun\n",port);
+
+ /* clear this restore original write_in pos and dump this string */
+ port_data[port].write_in_pos = write_in_pos_hold;
+ port_data[port].errors++;
+ erd = 1;
+ }
+ }
+
+
+
+// DEBUG. Dump out the hex codes for the KISS packet we just
+// created.
+/*
+ for (i = 0; i< j; i++) {
+ fprintf(stderr,"%02x ", transmit_txt2[i]);
+ }
+ fprintf(stderr,"\n\n");
+*/
+
+
+
+ if (end_critical_section(&port_data[port].write_lock, "interface.c:send_ax25_frame(2)" ) > 0)
+ fprintf(stderr,"write_lock, Port = %d\n", port);
+}
+
+
+
+
+
+// Send a KISS configuration command to the selected port.
+// The KISS spec allows up to 16 devices to be configured. We
+// support that here with the "device" input, which should be
+// between 0 and 15. The commands accepted are integer values:
+//
+// 0x01 TXDELAY
+// 0x02 P-Persistence
+// 0x03 SlotTime
+// 0x04 TxTail
+// 0x05 FullDuplex
+// 0x06 SetHardware
+// 0xff Exit from KISS mode (not implemented yet)
+//
+void send_kiss_config(int port, int device, int command, int value) {
+ unsigned char transmit_txt[MAX_LINE_SIZE+1];
+ int i, j;
+ int erd;
+ int write_in_pos_hold;
+
+
+ if (device < 0 || device > 15) {
+ fprintf(stderr,"send_kiss_config: out-of-range value for device\n");
+ return;
+ }
+
+ if (command < 1 || command > 6) {
+ fprintf(stderr,"send_kiss_config: out-of-range value for command\n");
+ return;
+ }
+
+ if (value < 0 || value > 255) {
+ fprintf(stderr,"send_kiss_config: out-of-range value for value\n");
+ return;
+ }
+
+ // Add the KISS framing characters and do the proper escapes.
+ j = 0;
+ transmit_txt[j++] = KISS_FEND;
+
+ transmit_txt[j++] = (device << 4) | (command & 0x0f);
+
+ transmit_txt[j++] = value & 0xff;
+
+ transmit_txt[j++] = KISS_FEND;
+
+ // Terminate the string, but don't increment the 'j' counter.
+ // We don't want to send the NULL byte out the KISS interface,
+ // just make sure the string is terminated in all cases.
+ //
+ transmit_txt[j] = '\0';
+
+
+
+
+//-------------------------------------------------------------------
+// Had to snag code from port_write_string() below because our string
+// needs to have 0x00 chars inside it. port_write_string() can't
+// handle that case. It's a good thing the transmit queue stuff
+// could handle it.
+//-------------------------------------------------------------------
+
+ erd = 0;
+
+ if (begin_critical_section(&port_data[port].write_lock, "interface.c:send_kiss_config(1)" ) > 0)
+ fprintf(stderr,"write_lock, Port = %d\n", port);
+
+ write_in_pos_hold = port_data[port].write_in_pos;
+
+ for (i = 0; i < j && !erd; i++) {
+ port_data[port].device_write_buffer[port_data[port].write_in_pos++] = transmit_txt[i];
+ if (port_data[port].write_in_pos >= MAX_DEVICE_BUFFER)
+ port_data[port].write_in_pos = 0;
+
+ if (port_data[port].write_in_pos == port_data[port].write_out_pos) {
+ if (debug_level & 2)
+ fprintf(stderr,"Port %d Buffer overrun\n",port);
+
+ /* clear this restore original write_in pos and dump this string */
+ port_data[port].write_in_pos = write_in_pos_hold;
+ port_data[port].errors++;
+ erd = 1;
+ }
+ }
+
+ if (end_critical_section(&port_data[port].write_lock, "interface.c:send_kiss_config(2)" ) > 0)
+ fprintf(stderr,"write_lock, Port = %d\n", port);
+}
+
+
+
+
+
+//***********************************************************
+// port_write_string()
+//
+// port is port# used
+// data is the string to write
+//***********************************************************
+
+void port_write_string(int port, char *data) {
+ int i,erd;
+ int write_in_pos_hold;
+
+ if (data == NULL)
+ return;
+
+ if (data[0] == '\0')
+ return;
+
+ erd = 0;
+
+ if (debug_level & 2)
+ fprintf(stderr,"CMD:%s\n",data);
+
+ if (begin_critical_section(&port_data[port].write_lock, "interface.c:port_write_string(1)" ) > 0)
+ fprintf(stderr,"write_lock, Port = %d\n", port);
+
+ write_in_pos_hold = port_data[port].write_in_pos;
+
+ // Normal Serial/Net output?
+ if (port_data[port].device_type != DEVICE_AX25_TNC) {
+ for (i = 0; i < (int)strlen(data) && !erd; i++) {
+ port_data[port].device_write_buffer[port_data[port].write_in_pos++] = data[i];
+ if (port_data[port].write_in_pos >= MAX_DEVICE_BUFFER)
+ port_data[port].write_in_pos = 0;
+
+ if (port_data[port].write_in_pos == port_data[port].write_out_pos){
+ if (debug_level & 2)
+ fprintf(stderr,"Port %d Buffer overrun\n",port);
+
+ /* clear this restore original write_in pos and dump this string */
+ port_data[port].write_in_pos = write_in_pos_hold;
+ port_data[port].errors++;
+ erd = 1;
+ }
+ }
+ }
+
+ // AX.25 port output
+ else {
+ port_data[port].bytes_output += strlen(data);
+ data_out_ax25(port,(unsigned char *)data);
+ /* do for interface indicators */
+ if (port_data[port].write_in_pos >= MAX_DEVICE_BUFFER)
+ port_data[port].write_in_pos = 0;
+ }
+
+ if (end_critical_section(&port_data[port].write_lock, "interface.c:port_write_string(2)" ) > 0)
+ fprintf(stderr,"write_lock, Port = %d\n", port);
+}
+
+
+
+
+
+//***********************************************************
+// port_read()
+//
+// port is port# used
+//
+// This function becomes the long-running thread that snags
+// characters from an interface and passes them off to the
+// decoding routines. One copy of this is run for each read
+// thread for each interface.
+//***********************************************************
+
+void port_read(int port) {
+ unsigned char cin, last;
+ unsigned char buffer[MAX_DEVICE_BUFFER]; // Only used for AX.25 packets
+ int i;
+ struct timeval tmv;
+ fd_set rd;
+ int group;
+ int binary_wx_data = 0;
+ int max;
+ /*
+ * Some local variables used for checking AX.25 data - PE1DNN
+ *
+ * "from" is used to look up where the data comes from
+ * "from_len" is used to keep the size of sockaddr structure
+ * "dev" is used to keep the name of the interface that
+ * belongs to our port/device_name
+ */
+ struct sockaddr from;
+ socklen_t from_len;
+
+#ifdef HAVE_LIBAX25
+ char *dev;
+#endif /* USE_AX25 */
+
+ if (debug_level & 2)
+ fprintf(stderr,"Port %d read start\n",port);
+
+// init_critical_section(&port_data[port].read_lock);
+
+ group = 0;
+ max = MAX_DEVICE_BUFFER - 1;
+ cin = (unsigned char)0;
+ last = (unsigned char)0;
+
+ // We stay in this read loop until the port is shut down
+ while(port_data[port].active == DEVICE_IN_USE){
+
+ if (port_data[port].status == DEVICE_UP){
+
+ port_data[port].read_in_pos = 0;
+ port_data[port].scan = 1;
+
+ while (port_data[port].scan
+ && (port_data[port].read_in_pos < (MAX_DEVICE_BUFFER - 1) )
+ && (port_data[port].status == DEVICE_UP) ) {
+
+ int skip = 0;
+
+// pthread_testcancel(); // Check for thread termination request
+
+ // Handle all EXCEPT AX25_TNC interfaces here
+ if (port_data[port].device_type != DEVICE_AX25_TNC) {
+ // Get one character
+ port_data[port].scan = (int)read(port_data[port].channel,&cin,1);
+//fprintf(stderr," in:%02x ",cin);
+ }
+
+ else { // Handle AX25_TNC interfaces
+ /*
+ * Use recvfrom on a network socket to know from
+ * which interface the packet came - PE1DNN
+ */
+
+#ifdef __solaris__
+ from_len = (unsigned int)sizeof(from);
+#else // __solaris__
+ from_len = (socklen_t)sizeof(from);
+#endif // __solaris__
+
+ port_data[port].scan = recvfrom(port_data[port].channel,buffer,
+ sizeof(buffer) - 1,
+ 0,
+ &from,
+ &from_len);
+ }
+
+
+ // Below is code for ALL types of interfaces
+ if (port_data[port].scan > 0 && port_data[port].status == DEVICE_UP ) {
+
+ if (port_data[port].device_type != DEVICE_AX25_TNC)
+ port_data[port].bytes_input += port_data[port].scan; // Add character to read buffer
+
+
+// Somewhere between these lock statements the read_lock got unlocked. How?
+// if (begin_critical_section(&port_data[port].read_lock, "interface.c:port_read(1)" ) > 0)
+// fprintf(stderr,"read_lock, Port = %d\n", port);
+
+
+ // Handle all EXCEPT AX25_TNC interfaces here
+ if (port_data[port].device_type != DEVICE_AX25_TNC){
+
+
+ // Do special KISS packet processing here.
+ // We save the last character in
+ // port_data[port].channel2, as it is
+ // otherwise only used for AX.25 ports.
+
+ if ( (port_data[port].device_type == DEVICE_SERIAL_KISS_TNC)
+ || (port_data[port].device_type == DEVICE_SERIAL_MKISS_TNC) ) {
+
+
+ if (port_data[port].channel2 == KISS_FESC) { // Frame Escape char
+ if (cin == KISS_TFEND) { // Transposed Frame End char
+
+ // Save this char for next time
+ // around
+ port_data[port].channel2 = cin;
+
+ cin = KISS_FEND;
+ }
+ else if (cin == KISS_TFESC) { // Transposed Frame Escape char
+
+ // Save this char for next time
+ // around
+ port_data[port].channel2 = cin;
+
+ cin = KISS_FESC;
+ }
+ else {
+ port_data[port].channel2 = cin;
+ }
+ }
+ else if (port_data[port].channel2 == KISS_FEND) { // Frame End char
+ // Frame start or frame end. Drop
+ // the next character which should
+ // either be another frame end or a
+ // type byte.
+
+// Note this "type" byte is where it specifies which KISS interface
+// the packet came from. We may want to use this later for
+// multi-drop KISS or other types of KISS protocols.
+
+ // Save this char for next time
+ // around
+ port_data[port].channel2 = cin;
+//fprintf(stderr,"Byte: %02x\n", cin);
+ skip++;
+ }
+ else if (cin == KISS_FESC) { // Frame Escape char
+ port_data[port].channel2 = cin;
+ skip++;
+ }
+ else {
+ port_data[port].channel2 = cin;
+ }
+ } // End of first special KISS processing
+
+
+
+
+
+// AGWPE
+// Process AGWPE packets here. Massage the frames so that they look
+// like normal serial packets to the Xastir decoding functions?
+//
+// We turn on monitoring of packets when we first connect. We now
+// need to throw away all but the "U" packets, which are unconnected
+// information packets.
+//
+// Check for enough bytes to complete a header (36 bytes). If
+// enough, check the datalength to see if an entire packet has been
+// read. If so, run that packet through a conversion routine to
+// convert it to a TAPR2-style packet.
+//
+// Right now we're not taking into account multiple radio ports that
+// AGWPE is capable of. Just assume that we'll receive from all
+// radio ports, but transmit out port 0.
+//
+ if (port_data[port].device_type == DEVICE_NET_AGWPE) {
+ int bytes_available = 0;
+ long frame_length = 0;
+
+
+ skip = 1; // Keeps next block of code from
+ // trying to process this data.
+
+ // Add it to the buffer
+ if (port_data[port].read_in_pos < (MAX_DEVICE_BUFFER - 1) ) {
+ port_data[port].device_read_buffer[port_data[port].read_in_pos] = (char)cin;
+ port_data[port].read_in_pos++;
+ port_data[port].device_read_buffer[port_data[port].read_in_pos] = (char)0;
+ } else {
+ if (debug_level & 2)
+ fprintf(stderr,"Port read overrun (1) on %d\n",port);
+
+ port_data[port].read_in_pos = 0;
+ }
+
+ bytes_available = port_data[port].read_in_pos - port_data[port].read_out_pos;
+ if (bytes_available < 0)
+ bytes_available = (bytes_available + MAX_DEVICE_BUFFER) % MAX_DEVICE_BUFFER;
+
+//fprintf(stderr," bytes_avail:%d ",bytes_available);
+
+ if (bytes_available >= 36) {
+ // We have a full AGWPE header,
+ // which means we can compute the
+ // frame length.
+ unsigned char count[4];
+ int my_pointer;
+
+ // Snag bytes 28-32 of the buffer and compute frame_length
+ my_pointer = (port_data[port].read_out_pos + 28) % MAX_DEVICE_BUFFER;
+ count[0] = (unsigned char)port_data[port].device_read_buffer[my_pointer];
+ my_pointer = (my_pointer + 1) % MAX_DEVICE_BUFFER;
+ count[1] = (unsigned char)port_data[port].device_read_buffer[my_pointer];
+ my_pointer = (my_pointer + 1) % MAX_DEVICE_BUFFER;
+ count[2] = (unsigned char)port_data[port].device_read_buffer[my_pointer];
+ my_pointer = (my_pointer + 1) % MAX_DEVICE_BUFFER;
+ count[3] = (unsigned char)port_data[port].device_read_buffer[my_pointer];
+
+ frame_length = 0;
+ frame_length = frame_length | (count[0] );
+ frame_length = frame_length | (count[1] << 8);
+ frame_length = frame_length | (count[2] << 16);
+ frame_length = frame_length | (count[3] << 24);
+
+//fprintf(stderr,"Found complete AGWPE header: DataLength: %d\n",frame_length);
+
+ // Have a complete AGWPE packet? If
+ // so, convert it to a more standard
+ // packet format then feed it to our
+ // decoding routines.
+ //
+ if (bytes_available >= (frame_length+36)) {
+ char input_string[MAX_DEVICE_BUFFER];
+ char output_string[MAX_DEVICE_BUFFER];
+ int ii,jj,new_length;
+
+//fprintf(stderr,"Found complete AGWPE packet, %d bytes total in frame:\n",frame_length+36);
+
+ my_pointer = port_data[port].read_out_pos;
+ jj = 0;
+ for (ii = 0; ii < frame_length+36; ii++) {
+ input_string[jj++] = (unsigned char)port_data[port].device_read_buffer[my_pointer];
+ my_pointer = (my_pointer + 1) % MAX_DEVICE_BUFFER;
+ }
+
+ // Add a terminator. We need
+ // this for the raw packets so
+ // that we don't end up getting
+ // portions of strings
+ // concatenated onto the end of
+ // our current packet during
+ // later processing.
+ input_string[jj] = '\0';
+
+ my_pointer = port_data[port].read_out_pos;
+
+ if ( parse_agwpe_packet((unsigned char *)input_string,
+ frame_length+36,
+ (unsigned char *)output_string,
+ &new_length) ) {
+ channel_data(port,
+ (unsigned char *)output_string,
+ new_length+1); // include terminator
+ }
+
+ for (i = 0; i <= port_data[port].read_in_pos; i++)
+ port_data[port].device_read_buffer[i] = (char)0;
+
+ port_data[port].read_in_pos = 0;
+ }
+ }
+ else {
+ // Not enough for a full header so
+ // we can't compute frame length
+ // yet. Do nothing until we have
+ // more data.
+ }
+ }
+// End of new AGWPE code
+
+
+
+ // We shouldn't see any AX.25 flag
+ // characters on a KISS interface because
+ // they are stripped out by the KISS code.
+ // What we should see though are KISS_FEND
+ // characters at the beginning of each
+ // packet. These characters are where we
+ // should break the data apart in order to
+ // send strings to the decode routines. It
+ // may be just fine to still break it on \r
+ // or \n chars, as the KISS_FEND should
+ // appear immediately afterwards in
+ // properly formed packets.
+
+
+ if ( (!skip)
+ && (cin == (unsigned char)'\r'
+ || cin == (unsigned char)'\n'
+ || port_data[port].read_in_pos >= (MAX_DEVICE_BUFFER - 1)
+ || ( (cin == KISS_FEND) && (port_data[port].device_type == DEVICE_SERIAL_KISS_TNC) )
+ || ( (cin == KISS_FEND) && (port_data[port].device_type == DEVICE_SERIAL_MKISS_TNC) ) )
+ && port_data[port].data_type == 0) { // If end-of-line
+
+// End serial/net type data send it to the decoder Put a terminating
+// zero at the end of the read-in data
+
+ port_data[port].device_read_buffer[port_data[port].read_in_pos] = (char)0;
+
+ if (port_data[port].status == DEVICE_UP && port_data[port].read_in_pos > 0) {
+ int length;
+
+ // Compute length of string in
+ // circular queue
+
+ //fprintf(stderr,"%d\t%d\n",port_data[port].read_in_pos,port_data[port].read_out_pos);
+
+ // KISS TNC sends binary data
+ if ( (port_data[port].device_type == DEVICE_SERIAL_KISS_TNC)
+ || (port_data[port].device_type == DEVICE_SERIAL_MKISS_TNC) ) {
+
+ length = port_data[port].read_in_pos - port_data[port].read_out_pos;
+ if (length < 0)
+ length = (length + MAX_DEVICE_BUFFER) % MAX_DEVICE_BUFFER;
+
+length++;
+ }
+ else { // ASCII data
+ length = 0;
+ }
+
+ channel_data(port,
+ (unsigned char *)port_data[port].device_read_buffer,
+ length); // Length of string
+ }
+
+ for (i = 0; i <= port_data[port].read_in_pos; i++)
+ port_data[port].device_read_buffer[i] = (char)0;
+
+ port_data[port].read_in_pos = 0;
+ }
+ else if (!skip) {
+
+ // Check for binary WX station data
+ if (port_data[port].data_type == 1 && (port_data[port].device_type == DEVICE_NET_WX ||
+ port_data[port].device_type == DEVICE_SERIAL_WX)) {
+
+ /* BINARY DATA input (WX data ?) */
+ /* check RS WX200 */
+ switch (cin) {
+
+ case 0x8f:
+ case 0x9f:
+ case 0xaf:
+ case 0xbf:
+ case 0xcf:
+
+ if (group == 0) {
+ port_data[port].read_in_pos = 0;
+ group = (int)cin;
+ switch (cin) {
+
+ case 0x8f:
+ max = 35;
+ binary_wx_data = 1;
+ break;
+
+ case 0x9f:
+ max = 34;
+ binary_wx_data = 1;
+ break;
+
+ case 0xaf:
+ max = 31;
+ binary_wx_data = 1;
+ break;
+
+ case 0xbf:
+ max = 14;
+ binary_wx_data = 1;
+ break;
+
+ case 0xcf:
+ max = 27;
+ binary_wx_data = 1;
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ if (port_data[port].read_in_pos < (MAX_DEVICE_BUFFER - 1) ) {
+ port_data[port].device_read_buffer[port_data[port].read_in_pos] = (char)cin;
+ port_data[port].read_in_pos++;
+ port_data[port].device_read_buffer[port_data[port].read_in_pos] = (char)0;
+ } else {
+ if (debug_level & 2)
+ fprintf(stderr,"Port read overrun (1) on %d\n",port);
+
+ port_data[port].read_in_pos = 0;
+ }
+ if (port_data[port].read_in_pos >= max) {
+ if (group != 0) { /* ok try to decode it */
+ int length = 0;
+//int jj;
+ if (binary_wx_data) {
+ length = port_data[port].read_in_pos - port_data[port].read_out_pos;
+ if (length < 0)
+ length = (length + MAX_DEVICE_BUFFER) % MAX_DEVICE_BUFFER;
+ length++;
+ }
+//fprintf(stderr,"\n\n3, length: %d ", length);
+//for (jj = 0; jj < (length-1); jj++) {
+// fprintf(stderr, "%02x ", 0x0ff & port_data[port].device_read_buffer[jj]);
+//}
+//fprintf(stderr,"\n");
+
+
+ channel_data(port,
+ (unsigned char *)port_data[port].device_read_buffer,
+ length);
+ }
+ max = MAX_DEVICE_BUFFER - 1;
+ group = 0;
+
+ port_data[port].read_in_pos = 0;
+ }
+ }
+ else { /* Normal Data input */
+
+ if (cin == '\0') // OWW WX daemon sends 0x00's!
+ cin = '\n';
+
+ if (port_data[port].read_in_pos < (MAX_DEVICE_BUFFER - 1) ) {
+ port_data[port].device_read_buffer[port_data[port].read_in_pos] = (char)cin;
+ port_data[port].read_in_pos++;
+ port_data[port].device_read_buffer[port_data[port].read_in_pos] = (char)0;
+ }
+ else {
+ if (debug_level & 2)
+ fprintf(stderr,"Port read overrun (2) on %d\n",port);
+
+ port_data[port].read_in_pos = 0;
+ }
+ }
+ }
+
+ // Ascii WX station data but no line-ends?
+ if (port_data[port].read_in_pos > MAX_DEVICE_BUFFER_UNTIL_BINARY_SWITCH &&
+ (port_data[port].device_type == DEVICE_NET_WX
+ || port_data[port].device_type == DEVICE_SERIAL_WX)) {
+
+ /* normal data on WX not found do look at data for binary WX */
+ port_data[port].data_type++;
+ port_data[port].data_type &= 1;
+ port_data[port].read_in_pos = 0;
+ }
+ } // End of non-AX.25 interface code block
+
+
+ else { // Process ax25 interface data and send to the decoder
+ /*
+ * Only accept data from our own interface (recvfrom will get
+ * data from all AX.25 interfaces!) - PE1DNN
+ */
+#ifdef HAVE_LIBAX25
+ if (port_data[port].device_name != NULL) {
+ if ((dev = ax25_config_get_dev(port_data[port].device_name)) != NULL) {
+ /* if the data is not from our interface, ignore it! PE1DNN */
+ if(strcmp(dev, from.sa_data) == 0) {
+ /* Received data from our interface! - process data */
+ if (process_ax25_packet(buffer,
+ port_data[port].scan,
+ port_data[port].device_read_buffer,
+ sizeof(port_data[port].device_read_buffer)) != NULL) {
+ port_data[port].bytes_input += strlen(port_data[port].device_read_buffer);
+
+ channel_data(port,
+ (unsigned char *)port_data[port].device_read_buffer,
+ 0);
+ }
+ /*
+ do this for interface indicator in this case we only do it for,
+ data from the correct AX.25 port
+ */
+ if (port_data[port].read_in_pos < (MAX_DEVICE_BUFFER - 1) ) {
+ port_data[port].read_in_pos += port_data[port].scan;
+ } else {
+
+ /* no buffer over runs writing a line at a time */
+ port_data[port].read_in_pos = 0;
+ }
+ }
+ }
+ }
+#endif /* HAVE_LIBAX25 */
+ } // End of AX.25 interface code block
+
+
+//if (end_critical_section(&port_data[port].read_lock, "interface.c:port_read(2)" ) > 0)
+// fprintf(stderr,"read_lock, Port = %d\n", port);
+
+ }
+ else if (port_data[port].status == DEVICE_UP) { /* error or close on read */
+ port_data[port].errors++;
+ if (port_data[port].scan == 0) {
+ // Should not get this unless the device is down. NOT TRUE!
+ // We seem to also be able to get here if we're closing/restarting
+ // another interface. For that reason I commented out the below
+ // statement so that this interface won't go down. The inactivity
+ // timer solves that issue now anyway. --we7u.
+ port_data[port].status = DEVICE_ERROR;
+
+ // If the below statement is enabled, it causes an immediate reconnect
+ // after one time-period of inactivity, currently 7.5 minutes, as set in
+ // main.c:UpdateTime(). This means the symbol will never change from green
+ // to red on the status bar, so the operator might not know about a
+ // connection that is being constantly reconnected. By leaving it commented
+ // out we get one time period of red, and then it will reconnect at the 2nd
+ // time period. This means we can reconnect within 15 minutes if a line
+ // goes dead.
+ //
+ port_data[port].reconnects = -1; // Causes an immediate reconnect
+
+ if (debug_level & 2)
+ fprintf(stderr,"end of file on read, or signal interrupted the read, port %d\n",port);
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+
+ } else {
+ if (port_data[port].scan == -1) {
+ /* Should only get this if an real error occurs */
+ port_data[port].status = DEVICE_ERROR;
+
+ // If the below statement is enabled, it causes an immediate reconnect
+ // after one time-period of inactivity, currently 7.5 minutes, as set in
+ // main.c:UpdateTime(). This means the symbol will never change from green
+ // to red on the status bar, so the operator might not know about a
+ // connection that is being constantly reconnected. By leaving it commented
+ // out we get one time period of red, and then it will reconnect at the 2nd
+ // time period. This means we can reconnect within 15 minutes if a line
+ // goes dead.
+ //
+ port_data[port].reconnects = -1; // Causes an immediate reconnect
+
+ // Show the latest status in the
+ // interface control dialog
+ update_interface_list();
+
+ if (debug_level & 2) {
+ fprintf(stderr,"error on read with error no %d, or signal interrupted the read, port %d, DEVICE_ERROR ***\n",
+ errno,port);
+ switch (errno) {
+
+ case EINTR:
+ fprintf(stderr,"EINTR ERROR\n");
+ break;
+
+ case EAGAIN:
+ fprintf(stderr,"EAGAIN ERROR\n");
+ break;
+
+ case EIO:
+ fprintf(stderr,"EIO ERROR\n");
+ break;
+
+ case EISDIR:
+ fprintf(stderr,"EISDIR ERROR\n");
+ break;
+
+ case EBADF: // Get this one when we terminate nearby threads
+ fprintf(stderr,"EBADF ERROR\n");
+ break;
+
+ case EINVAL:
+ fprintf(stderr,"EINVAL ERROR\n");
+ break;
+
+ case EFAULT:
+ fprintf(stderr,"EFAULT ERROR\n");
+ break;
+
+ default:
+ fprintf(stderr,"OTHER ERROR\n");
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (port_data[port].active == DEVICE_IN_USE) {
+
+ // We need to delay here so that the thread doesn't use
+ // high amounts of CPU doing nothing.
+
+// This select that waits on data and a timeout, so that if data
+// doesn't come in within a certain period of time, we wake up to
+// check whether the socket has gone down. Else, we go back into
+// the select to wait for more data or a timeout. FreeBSD has a
+// problem if this is less than 1ms. Linux works ok down to 100us.
+// We don't need it anywhere near that short though. We just need
+// to check whether the main thread has requested the interface be
+// closed, and so need to have this short enough to have reasonable
+// response time to the user.
+
+//sched_yield(); // Yield to other threads
+
+ // Set up the select to block until data ready or 100ms
+ // timeout, whichever occurs first.
+ FD_ZERO(&rd);
+ FD_SET(port_data[port].channel, &rd);
+ tmv.tv_sec = 0;
+ tmv.tv_usec = 100000; // 100 ms
+ (void)select(0,&rd,NULL,NULL,&tmv);
+ }
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"Thread for port %d read down!\n",port);
+}
+
+
+
+
+
+//***********************************************************
+// port_write()
+//
+// port is port# used
+//
+// This function becomes the long-running thread that sends
+// characters to an interface. One copy of this is run for
+// each write thread for each interface.
+//***********************************************************
+void port_write(int port) {
+ int retval;
+ struct timeval tmv;
+ fd_set wd;
+ int wait_max;
+ unsigned long bytes_input;
+ char write_buffer[MAX_DEVICE_BUFFER];
+ int quantity;
+
+
+ if (debug_level & 2)
+ fprintf(stderr,"Port %d write start\n",port);
+
+ init_critical_section(&port_data[port].write_lock);
+
+ while(port_data[port].active == DEVICE_IN_USE) {
+
+ if (port_data[port].status == DEVICE_UP) {
+ // Some messiness necessary because we're using
+ // xastir_mutex's instead of pthread_mutex_t's.
+ pthread_mutex_t *cleanup_mutex;
+
+
+ // Install the cleanup routine for the case where this
+ // thread gets killed while the mutex is locked. The
+ // cleanup routine initiates an unlock before the thread
+ // dies. We must be in deferred cancellation mode for
+ // the thread to have this work properly. We must first
+ // get the pthread_mutex_t address:
+ cleanup_mutex = &port_data[port].write_lock.lock;
+
+ // Then install the cleanup routine:
+ pthread_cleanup_push((void *)pthread_mutex_unlock, (void *)cleanup_mutex);
+// pthread_cleanup_push(void (*pthread_mutex_unlock)(void *), (void *)cleanup_mutex);
+
+
+
+ if (begin_critical_section(&port_data[port].write_lock, "interface.c:port_write(1)" ) > 0)
+ fprintf(stderr,"write_lock, Port = %d\n", port);
+
+ if ( (port_data[port].write_in_pos != port_data[port].write_out_pos)
+ && port_data[port].status == DEVICE_UP) {
+ // We have something in the buffer to transmit!
+
+
+// Handle control-C delay
+ switch (port_data[port].device_type) {
+
+ // Use this block for serial interfaces where we
+ // need special delays for control-C character
+ // processing in the TNC.
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ case DEVICE_SERIAL_TNC:
+
+ // Are we trying to send a control-C? If so, wait a
+ // special amount of time _before_ we send
+ // it out the serial port.
+ if (port_data[port].device_write_buffer[port_data[port].write_out_pos] == (char)0x03) {
+ // Sending control-C.
+
+ if (debug_level & 128) {
+ fprintf(stderr,"Writing command [%x] on port %d, at pos %d\n",
+ *(port_data[port].device_write_buffer +
+ port_data[port].write_out_pos),
+ port, port_data[port].write_out_pos);
+ }
+
+ wait_max = 0;
+ bytes_input = port_data[port].bytes_input + 40;
+ while ( (port_data[port].bytes_input != bytes_input)
+ && (port_data[port].status == DEVICE_UP)
+ && (wait_max < 100) ) {
+ bytes_input = port_data[port].bytes_input;
+ /*sleep(1);*/
+
+ /*wait*/
+ FD_ZERO(&wd);
+ FD_SET(port_data[port].channel, &wd);
+ tmv.tv_sec = 0;
+ tmv.tv_usec = 80000l; // Delay 80ms
+ (void)select(0,NULL,&wd,NULL,&tmv);
+ wait_max++;
+ /*fprintf(stderr,"Bytes in %ld %ld\n",bytes_input,port_data[port].bytes_input);*/
+ }
+ /*fprintf(stderr,"Wait_max %d\n",wait_max);*/
+ } // End of command byte wait
+ break;
+
+ // Use this block for all other interfaces.
+ default:
+ // Do nothing (no delays for control-C's)
+ break;
+
+ } // End of switch
+// End of control-C delay code
+
+
+ pthread_testcancel(); // Check for thread termination request
+
+
+// Handle method of sending data (1 or multiple chars per TX)
+ switch (port_data[port].device_type) {
+
+ // Use this block for serial interfaces where we
+ // need character pacing and so must send one
+ // character per write.
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_SERIAL_GPS:
+ case DEVICE_SERIAL_WX:
+ // Do the actual write here, one character
+ // at a time for these types of interfaces.
+
+ retval = (int)write(port_data[port].channel,
+ &port_data[port].device_write_buffer[port_data[port].write_out_pos],
+ 1);
+
+//fprintf(stderr,"%02x ", (unsigned char)port_data[port].device_write_buffer[port_data[port].write_out_pos]);
+
+ pthread_testcancel(); // Check for thread termination request
+
+ if (retval == 1) { // We succeeded in writing one byte
+
+ port_data[port].bytes_output++;
+
+ port_data[port].write_out_pos++;
+ if (port_data[port].write_out_pos >= MAX_DEVICE_BUFFER)
+ port_data[port].write_out_pos = 0;
+
+ } else {
+ /* error of some kind */
+ port_data[port].errors++;
+ port_data[port].status = DEVICE_ERROR;
+
+ // If the below statement is enabled, it causes an immediate reconnect
+ // after one time-period of inactivity, currently 7.5 minutes, as set in
+ // main.c:UpdateTime(). This means the symbol will never change from green
+ // to red on the status bar, so the operator might not know about a
+ // connection that is being constantly reconnected. By leaving it commented
+ // out we get one time period of red, and then it will reconnect at the 2nd
+ // time period. This means we can reconnect within 15 minutes if a line
+ // goes dead.
+ //
+ port_data[port].reconnects = -1; // Causes an immediate reconnect
+
+ if (retval == 0) {
+ /* Should not get this unless the device is down */
+ if (debug_level & 2)
+ fprintf(stderr,"no data written %d, DEVICE_ERROR ***\n",port);
+ } else {
+ if (retval == -1) {
+ /* Should only get this if an real error occurs */
+ if (debug_level & 2)
+ fprintf(stderr,"error on write with error no %d, or port %d\n",errno,port);
+ }
+ }
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+ }
+//fprintf(stderr,"Char pacing ");
+// usleep(25000); // character pacing, 25ms per char. 20ms doesn't work for PicoPacket.
+ if (serial_char_pacing > 0) {
+ // Character pacing. Delay in between
+ // each character in milliseconds.
+ // Convert to microseconds for this
+ // usleep() call .
+ usleep(serial_char_pacing * 1000);
+ }
+ break;
+
+ // Use this block for all other interfaces where
+ // we don't need character pacing and we can
+ // send blocks of data in one write.
+ default:
+ // Do the actual write here, one buffer's
+ // worth at a time.
+
+ // Copy the data to a linear write buffer so
+ // that we can send it all in one shot.
+
+// Need to handle the case where only a portion of the data was
+// written by the write() function. Perhaps just write out an error
+// message?
+ quantity = 0;
+ while (port_data[port].write_in_pos != port_data[port].write_out_pos) {
+
+ write_buffer[quantity] = port_data[port].device_write_buffer[port_data[port].write_out_pos];
+
+ port_data[port].write_out_pos++;
+ if (port_data[port].write_out_pos >= MAX_DEVICE_BUFFER)
+ port_data[port].write_out_pos = 0;
+
+//fprintf(stderr,"%02x ",(unsigned char)write_buffer[quantity]);
+
+ quantity++;
+ }
+
+//fprintf(stderr,"\nWriting %d bytes\n\n", quantity);
+
+ retval = (int)write(port_data[port].channel,
+ write_buffer,
+ quantity);
+
+//fprintf(stderr,"%02x ", (unsigned char)port_data[port].device_write_buffer[port_data[port].write_out_pos]);
+
+ pthread_testcancel(); // Check for thread termination request
+
+ if (retval == quantity) { // We succeeded in writing one byte
+ port_data[port].bytes_output++;
+ } else {
+ /* error of some kind */
+ port_data[port].errors++;
+ port_data[port].status = DEVICE_ERROR;
+
+ // If the below statement is enabled, it causes an immediate reconnect
+ // after one time-period of inactivity, currently 7.5 minutes, as set in
+ // main.c:UpdateTime(). This means the symbol will never change from green
+ // to red on the status bar, so the operator might not know about a
+ // connection that is being constantly reconnected. By leaving it commented
+ // out we get one time period of red, and then it will reconnect at the 2nd
+ // time period. This means we can reconnect within 15 minutes if a line
+ // goes dead.
+ //
+ port_data[port].reconnects = -1; // Causes an immediate reconnect
+
+ if (retval == 0) {
+ /* Should not get this unless the device is down */
+ if (debug_level & 2)
+ fprintf(stderr,"no data written %d, DEVICE_ERROR ***\n",port);
+ } else {
+ if (retval == -1) {
+ /* Should only get this if an real error occurs */
+ if (debug_level & 2)
+ fprintf(stderr,"error on write with error no %d, or port %d\n",errno,port);
+ }
+ }
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+ }
+ break;
+
+ } // End of switch
+// End of handling method of sending data (1 or multiple char per TX)
+
+
+ }
+
+ if (end_critical_section(&port_data[port].write_lock, "interface.c:port_write(2)" ) > 0)
+ fprintf(stderr,"write_lock, Port = %d\n", port);
+
+ // Remove the cleanup routine for the case where this
+ // thread gets killed while the mutex is locked. The
+ // cleanup routine initiates an unlock before the thread
+ // dies. We must be in deferred cancellation mode for
+ // the thread to have this work properly.
+//
+// NOTE: Ignore the four \"suggest braces\" warnings you see when
+// compiling, see: http://archive.netbsd.se/?ml=gcc-help&a=2008-06&t=7730779
+//
+ pthread_cleanup_pop(0);
+
+ }
+
+ if (port_data[port].active == DEVICE_IN_USE) {
+
+ // Delay here so that the thread doesn't use high
+ // amounts of CPU doing _nothing_. Take this delay out
+ // and the thread will take lots of CPU time.
+
+// Try to change this to a select that waits on data and a timeout,
+// so that if data doesn't come in within a certain period of time,
+// we wake up to check whether the socket has gone down. Else, we
+// go back into the select to wait for more data or a timeout.
+// FreeBSD has a problem if this is less than 1ms. Linux works ok
+// down to 100us. Theoretically we don't need it anywhere near that
+// short, we just need to check whether the main thread has
+// requested the interface be closed, and so need to have this short
+// enough to have reasonable response time to the user.
+// Unfortunately it has been reported that having this at 100ms
+// causes about 9 seconds of delay when transmitting to a KISS TNC,
+// so it's good to keep this short also.
+
+ FD_ZERO(&wd);
+ FD_SET(port_data[port].channel, &wd);
+ tmv.tv_sec = 0;
+ tmv.tv_usec = 2000; // Delay 2ms
+ (void)select(0,NULL,&wd,NULL,&tmv);
+ }
+ }
+ if (debug_level & 2)
+ fprintf(stderr,"Thread for port %d write down!\n",port);
+}
+
+
+
+
+
+//***********************************************************
+// read_access_port_thread()
+//
+// Port read thread.
+// port is port# used
+//
+// open threads for reading data from this port.
+//***********************************************************
+static void* read_access_port_thread(void *arg) {
+ int port;
+
+ port = *((int *) arg);
+ // This call means we don't care about the return code and won't
+ // use pthread_join() later. Makes threading more efficient.
+ (void)pthread_detach(pthread_self());
+ port_read(port);
+
+ return(NULL);
+}
+
+
+
+
+
+//***********************************************************
+// write_access_port_thread()
+//
+// Port write thread.
+// port is port# used
+//
+// open threads for writing data to this port.
+//***********************************************************
+static void* write_access_port_thread(void *arg) {
+ int port;
+
+ port = *((int *) arg);
+ // This call means we don't care about the return code and won't
+ // use pthread_join() later. Makes threading more efficient.
+ (void)pthread_detach(pthread_self());
+ port_write(port);
+
+ return(NULL);
+}
+
+
+
+
+
+//***********************************************************
+// Start port read & write threads
+// port is port# used
+//
+// open threads for reading and writing data to and from this
+// port.
+//***********************************************************
+int start_port_threads(int port) {
+ int ok;
+
+ port_id[port] = port;
+ if (debug_level & 2)
+ fprintf(stderr,"Start port %d threads\n",port);
+
+ ok = 1;
+ if (port_data[port].active == DEVICE_IN_USE && port_data[port].status == DEVICE_UP){
+ if (debug_level & 2)
+ fprintf(stderr,"*** Startup of read/write threads for port %d ***\n",port);
+
+ /* start the two threads */
+ if (pthread_create(&port_data[port].read_thread, NULL, read_access_port_thread, &port_id[port])) {
+ /* error starting read thread*/
+ fprintf(stderr,"Error starting read thread, port %d\n",port);
+ port_data[port].read_thread = 0;
+ ok = -1;
+ }
+ else if (pthread_create(&port_data[port].write_thread, NULL, write_access_port_thread, &port_id[port])) {
+ /* error starting write thread*/
+ fprintf(stderr,"Error starting write thread, port %d\n",port);
+ port_data[port].write_thread = 0;
+ ok = -1;
+ }
+
+ }
+ else if (debug_level & 2) {
+ fprintf(stderr,"*** Skipping startup of read/write threads for port %d ***\n",port);
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"End port %d threads\n",port);
+
+ return(ok);
+}
+
+
+
+
+
+//***********************************************************
+// Clear Port Data
+// int port to be cleared
+//***********************************************************
+void clear_port_data(int port, int clear_more) {
+
+ if (begin_critical_section(&port_data_lock, "interface.c:clear_port_data(1)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ port_data[port].device_type = -1;
+ port_data[port].active = DEVICE_NOT_IN_USE;
+ port_data[port].status = DEVICE_DOWN;
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+
+ port_data[port].device_name[0] = '\0';
+ port_data[port].device_host_name[0] = '\0';
+
+ if (begin_critical_section(&connect_lock, "interface.c:clear_port_data(2)" ) > 0)
+ fprintf(stderr,"connect_lock, Port = %d\n", port);
+
+ port_data[port].thread_status = -1;
+ port_data[port].connect_status = -1;
+ port_data[port].read_thread = 0;
+ port_data[port].write_thread = 0;
+
+ if (end_critical_section(&connect_lock, "interface.c:clear_port_data(3)" ) > 0)
+ fprintf(stderr,"connect_lock, Port = %d\n", port);
+
+ port_data[port].decode_errors = 0;
+ port_data[port].data_type = 0;
+ port_data[port].socket_port = -1;
+ port_data[port].device_host_pswd[0] = '\0';
+
+ if (clear_more)
+ port_data[port].channel = -1;
+
+ port_data[port].channel2 = -1;
+ port_data[port].ui_call[0] = '\0';
+ port_data[port].dtr = 0;
+ port_data[port].sp = -1;
+ port_data[port].style = -1;
+ port_data[port].errors = 0;
+ port_data[port].bytes_input = 0l;
+ port_data[port].bytes_output = 0l;
+ port_data[port].bytes_input_last = 0l;
+ port_data[port].bytes_output_last = 0l;
+ port_data[port].port_activity = 1; // First time-period is a freebie
+ port_data[port].read_in_pos = 0;
+ port_data[port].read_out_pos = 0;
+ port_data[port].write_in_pos = 0;
+ port_data[port].write_out_pos = 0;
+
+ if (end_critical_section(&port_data_lock, "interface.c:clear_port_data(4)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+}
+
+
+
+
+
+//***********************************************************
+// Clear All Port Data
+//***********************************************************
+void clear_all_port_data(void) {
+ int i;
+
+ for (i = 0; i < MAX_IFACE_DEVICES; i++)
+ clear_port_data(i,1);
+}
+
+
+
+
+
+//***********************************************************
+// INIT Device names Data
+//***********************************************************
+void init_device_names(void) {
+ xastir_snprintf(dtype[DEVICE_NONE].device_name,
+ sizeof(dtype[DEVICE_NONE].device_name),
+ "%s",
+ langcode("IFDNL00000"));
+ xastir_snprintf(dtype[DEVICE_SERIAL_TNC].device_name,
+ sizeof(dtype[DEVICE_SERIAL_TNC].device_name),
+ "%s",
+ langcode("IFDNL00001"));
+ xastir_snprintf(dtype[DEVICE_SERIAL_TNC_HSP_GPS].device_name,
+ sizeof(dtype[DEVICE_SERIAL_TNC_HSP_GPS].device_name),
+ "%s",
+ langcode("IFDNL00002"));
+ xastir_snprintf(dtype[DEVICE_SERIAL_GPS].device_name,
+ sizeof(dtype[DEVICE_SERIAL_GPS].device_name),
+ "%s",
+ langcode("IFDNL00003"));
+ xastir_snprintf(dtype[DEVICE_SERIAL_WX].device_name,
+ sizeof(dtype[DEVICE_SERIAL_WX].device_name),
+ "%s",
+ langcode("IFDNL00004"));
+ xastir_snprintf(dtype[DEVICE_NET_STREAM].device_name,
+ sizeof(dtype[DEVICE_NET_STREAM].device_name),
+ "%s",
+ langcode("IFDNL00005"));
+ xastir_snprintf(dtype[DEVICE_AX25_TNC].device_name,
+ sizeof(dtype[DEVICE_AX25_TNC].device_name),
+ "%s",
+ langcode("IFDNL00006"));
+ xastir_snprintf(dtype[DEVICE_NET_GPSD].device_name,
+ sizeof(dtype[DEVICE_NET_GPSD].device_name),
+ "%s",
+ langcode("IFDNL00007"));
+ xastir_snprintf(dtype[DEVICE_NET_WX].device_name,
+ sizeof(dtype[DEVICE_NET_WX].device_name),
+ "%s",
+ langcode("IFDNL00008"));
+ xastir_snprintf(dtype[DEVICE_SERIAL_TNC_AUX_GPS].device_name,
+ sizeof(dtype[DEVICE_SERIAL_TNC_AUX_GPS].device_name),
+ "%s",
+ langcode("IFDNL00009"));
+ xastir_snprintf(dtype[DEVICE_SERIAL_KISS_TNC].device_name,
+ sizeof(dtype[DEVICE_SERIAL_KISS_TNC].device_name),
+ "%s",
+ langcode("IFDNL00010"));
+ xastir_snprintf(dtype[DEVICE_NET_DATABASE].device_name,
+ sizeof(dtype[DEVICE_NET_DATABASE].device_name),
+ "%s",
+ langcode("IFDNL00011"));
+ xastir_snprintf(dtype[DEVICE_NET_AGWPE].device_name,
+ sizeof(dtype[DEVICE_NET_AGWPE].device_name),
+ "%s",
+ langcode("IFDNL00012"));
+ xastir_snprintf(dtype[DEVICE_SERIAL_MKISS_TNC].device_name,
+ sizeof(dtype[DEVICE_SERIAL_MKISS_TNC].device_name),
+ "%s",
+ langcode("IFDNL00013"));
+
+#ifdef HAVE_DB
+ // SQL Database (experimental)
+ xastir_snprintf(dtype[DEVICE_SQL_DATABASE].device_name,
+ sizeof(dtype[DEVICE_SQL_DATABASE].device_name),
+ "%s",
+ langcode("IFDNL00014"));
+#endif /* HAVE_DB */
+
+}
+
+
+
+
+
+//***********************************************************
+// Delete Device. Shuts down active port/ports.
+//***********************************************************
+int del_device(int port) {
+ int ok;
+ char temp[300];
+ long wait_time = 0;
+
+
+ if (debug_level & 2)
+ fprintf(stderr,"Delete Device start\n");
+
+ ok = -1;
+ switch (port_data[port].device_type) {
+
+ case(DEVICE_SERIAL_TNC):
+ case(DEVICE_SERIAL_KISS_TNC):
+ case(DEVICE_SERIAL_MKISS_TNC):
+ case(DEVICE_SERIAL_GPS):
+ case(DEVICE_SERIAL_WX):
+ case(DEVICE_SERIAL_TNC_HSP_GPS):
+ case(DEVICE_SERIAL_TNC_AUX_GPS):
+
+ switch (port_data[port].device_type){
+
+ case DEVICE_SERIAL_TNC:
+
+ if (debug_level & 2)
+ fprintf(stderr,"Close a Serial TNC device\n");
+
+begin_critical_section(&devices_lock, "interface.c:del_device" );
+
+ xastir_snprintf(temp, sizeof(temp), "config/%s", devices[port].tnc_down_file);
+
+end_critical_section(&devices_lock, "interface.c:del_device" );
+
+ (void)command_file_to_tnc_port(port,get_data_base_dir(temp));
+ break;
+
+ case DEVICE_SERIAL_KISS_TNC:
+ if (debug_level & 2)
+ fprintf(stderr,"Close a Serial KISS TNC device\n");
+ break;
+
+ case DEVICE_SERIAL_MKISS_TNC:
+ if (debug_level & 2)
+ fprintf(stderr,"Close a Serial MKISS TNC device\n");
+ break;
+
+ case DEVICE_SERIAL_GPS:
+ if (debug_level & 2)
+ fprintf(stderr,"Close a Serial GPS device\n");
+ if (using_gps_position) {
+ using_gps_position--;
+ }
+ break;
+
+ case DEVICE_SERIAL_WX:
+ if (debug_level & 2)
+ fprintf(stderr,"Close a Serial WX device\n");
+
+ break;
+
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ if (debug_level & 2)
+ fprintf(stderr,"Close a Serial TNC w/HSP GPS\n");
+ if (using_gps_position) {
+ using_gps_position--;
+ }
+
+begin_critical_section(&devices_lock, "interface.c:del_device" );
+
+ xastir_snprintf(temp, sizeof(temp), "config/%s", devices[port].tnc_down_file);
+
+end_critical_section(&devices_lock, "interface.c:del_device" );
+
+ (void)command_file_to_tnc_port(port,get_data_base_dir(temp));
+ break;
+
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ if (debug_level & 2)
+ fprintf(stderr,"Close a Serial TNC w/AUX GPS\n");
+ if (using_gps_position) {
+ using_gps_position--;
+ }
+
+begin_critical_section(&devices_lock, "interface.c:del_device");
+
+ sprintf(temp, "config/%s", devices[port].tnc_down_file);
+
+end_critical_section(&devices_lock, "interface.c:del_device");
+
+ (void)command_file_to_tnc_port(port,
+ get_data_base_dir(temp));
+ break;
+
+ default:
+ break;
+ } // End of switch
+
+
+ // Let the write queue empty before we return, to make
+ // sure all of the data gets written out.
+ while ( (port_data[port].write_in_pos != port_data[port].write_out_pos)
+ && port_data[port].status == DEVICE_UP) {
+
+ // Check whether we're hung waiting on the device
+ if (wait_time > SERIAL_MAX_WAIT)
+ break; // Break out of the while loop
+
+ sched_yield();
+ usleep(25000); // 25ms
+ wait_time = wait_time + 25000;
+ }
+
+
+ if (debug_level & 2)
+ fprintf(stderr,"Serial detach\n");
+
+ ok = serial_detach(port);
+ break;
+
+ case(DEVICE_NET_STREAM):
+ case(DEVICE_AX25_TNC):
+ case(DEVICE_NET_GPSD):
+ case(DEVICE_NET_WX):
+ case(DEVICE_NET_DATABASE):
+ case(DEVICE_NET_AGWPE):
+
+ switch (port_data[port].device_type){
+
+ case DEVICE_NET_STREAM:
+ if (debug_level & 2)
+ fprintf(stderr,"Close a Network stream\n");
+ break;
+
+ case DEVICE_AX25_TNC:
+ if (debug_level & 2)
+ fprintf(stderr,"Close a AX25 TNC device\n");
+ break;
+
+ case DEVICE_NET_GPSD:
+ if (debug_level & 2)
+ fprintf(stderr,"Close a Network GPSd stream\n");
+ if (using_gps_position) {
+ using_gps_position--;
+ }
+ break;
+
+ case DEVICE_NET_WX:
+ if (debug_level & 2)
+ fprintf(stderr,"Close a Network WX stream\n");
+ break;
+
+ case DEVICE_NET_DATABASE:
+ if (debug_level & 2)
+ fprintf(stderr,"Close a Network Database stream\n");
+ break;
+
+ case DEVICE_NET_AGWPE:
+ if (debug_level & 2)
+ fprintf(stderr,"Close a Network AGWPE stream\n");
+ break;
+
+ default:
+ break;
+ }
+ if (debug_level & 2)
+ fprintf(stderr,"Net detach\n");
+
+ ok = net_detach(port);
+ break;
+
+#ifdef HAVE_DB
+ case DEVICE_SQL_DATABASE:
+ if (debug_level & 2)
+ fprintf(stderr,"Close connection to database on device %d\n",port);
+ if (port_data[port].status==DEVICE_UP) {
+ ok = closeConnection(&connections[port],port);
+ }
+ // remove the connection from the list of open connections
+ /* clear port active */
+ port_data[port].active = DEVICE_NOT_IN_USE;
+ /* clear port status */
+ port_data[port].active = DEVICE_DOWN;
+ update_interface_list();
+fprintf(stderr,"Closed connection to database on device %d\n",port);
+ break;
+#endif /* HAVE_DB */
+
+ default:
+ break;
+ }
+
+ if (ok) {
+ int retvalue;
+
+ if (debug_level & 2)
+ fprintf(stderr,"port detach OK\n");
+
+ usleep(100000); // 100ms
+ if (debug_level & 2)
+ fprintf(stderr,"Cancel threads\n");
+
+ if (begin_critical_section(&port_data_lock, "interface.c:del_device(1)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ if (begin_critical_section(&connect_lock, "interface.c:del_device(2)" ) > 0)
+ fprintf(stderr,"connect_lock, Port = %d\n", port);
+
+ if (port_data[port].read_thread != 0) { // If we have a thread defined
+ retvalue = pthread_cancel(port_data[port].read_thread);
+ if (retvalue == ESRCH) {
+ //fprintf(stderr,"ERROR: Could not cancel read thread on port %d\n", port);
+ //fprintf(stderr,"No thread found with that thread ID\n");
+ }
+ }
+
+ if (port_data[port].write_thread != 0) { // If we have a thread defined
+ retvalue = pthread_cancel(port_data[port].write_thread);
+ if (retvalue == ESRCH) {
+ //fprintf(stderr,"ERROR: Could not cancel write thread on port %d\n", port);
+ //fprintf(stderr,"No thread found with that thread ID\n");
+ }
+ }
+
+ if (end_critical_section(&connect_lock, "interface.c:del_device(3)" ) > 0)
+ fprintf(stderr,"connect_lock, Port = %d\n", port);
+
+ if (end_critical_section(&port_data_lock, "interface.c:del_device(4)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ usleep(100000); // 100ms
+ } else {
+ if (debug_level & 2)
+ fprintf(stderr,"Port %d could not be closed\n",port);
+ }
+ usleep(10);
+
+ // Cover the case where someone plays with a GPS interface or
+ // three and then turns it/them off again: They won't send a
+ // posit again until the next restart or whenever they enable a
+ // GPS interface again that has good data, unless we set this
+ // variable again for them.
+ if (!using_gps_position) {
+ my_position_valid = 1;
+ }
+
+ return(ok);
+}
+
+
+#ifdef HAVE_DB
+/* Add a device, passing it a pointer to the ioparam
+ * that describes the interface to start up, rather than passing
+ * an extracted list of elements
+ *
+ * temporary addition for testing sql_database_functionality
+ * when working, needs to be integrated into add_device
+ */
+int add_device_by_ioparam(int port_avail, ioparam *device) {
+ int ok;
+ int got_conn;
+ int done = 0;
+ DataRow *dr;
+ ok = -1;
+
+ if (port_avail >= 0){
+
+ switch (device->device_type) {
+ case DEVICE_SQL_DATABASE:
+ if (debug_level & 4096)
+ fprintf(stderr,"Opening a sql db connection to %s\n",device->device_host_name);
+ clear_port_data(port_avail,0);
+
+ port_data[port_avail].device_type = DEVICE_SQL_DATABASE;
+ xastir_snprintf(port_data[port_avail].device_host_name,
+ sizeof(port_data[port_avail].device_host_name),
+ "%s",
+ device->device_host_name);
+ if (connections_initialized==0) {
+ if (debug_level & 4096)
+ fprintf(stderr,"Calling initConnections in add_device_by_ioparam\n");
+fprintf(stderr,"adddevice, initializing connections");
+ connections_initialized = initConnections();
+ }
+ if (debug_level & 4096) {
+ fprintf(stderr,"Opening (in interfaces) device on port [%d] with connection [%p]\n",port_avail,&connections[port_avail]);
+ fprintf(stderr,"device [%p][%p] device_type=%d\n",device,&device,device->device_type);
+ }
+ got_conn = 0;
+ got_conn=openConnection(device, &connections[port_avail]);
+ if (debug_level & 4096) {
+ fprintf(stderr,"got_conn connections[%d] [%p] result=%d\n",port_avail,&connections[port_avail],got_conn);
+ if (got_conn==1)
+ fprintf(stderr,"got_conn connection type %d\n",connections[port_avail].type);
+ }
+ if ((got_conn == 1) && (!(connections[port_avail].type==NULL))) {
+ if (debug_level & 4096)
+ fprintf(stderr, "Opened connection [%d] type=[%d]\n",port_avail,connections[port_avail].type);
+ ok = 1;
+ port_data[port_avail].active = DEVICE_IN_USE;
+ port_data[port_avail].status = DEVICE_UP;
+ } else {
+ port_data[port_avail].active = DEVICE_IN_USE;
+ port_data[port_avail].status = DEVICE_ERROR;
+ }
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+ if (ok == 1) {
+ /* if connected save top of call list */
+ ok = storeStationSimpleToGisDb(&connections[port_avail], n_first);
+ if (ok==1) {
+ if (debug_level & 4096)
+ fprintf(stderr,"Stored station n_first\n");
+ // iterate through station_pointers and write all stations currently known
+ dr = n_first->n_next;
+ if (dr!=NULL) {
+ while (done==0) {
+ if (debug_level & 4096)
+ fprintf(stderr,"storing additional stations\n");
+ // Need to check that stations aren't from the database
+ // preventing creation of duplicate round trip records.
+ ok = storeStationSimpleToGisDb(&connections[port_avail], dr);
+ if (ok==1) {
+ dr = dr->n_next;
+ if (dr==NULL) {
+ done = 1;
+ }
+ } else {
+ done = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return ok;
+}
+#endif /* HAVE_DB */
+
+
+//***********************************************************
+// Add Device. Starts up ports (makes them active).
+// dev_type is the device type to add
+// dev_num is the device name
+// dev_hst is the host name to connect to (network only)
+// dev_sck_p is the socket port to connect to (network only)
+// dev_sp is the baud rate of the port (serial only)
+// dev_sty is the port style (serial only)
+//
+// this will return the port # if one is available
+// otherwise it will return -1 if there is an error
+//***********************************************************
+int add_device(int port_avail,int dev_type,char *dev_nm,char *passwd,int dev_sck_p,
+ int dev_sp,int dev_sty,int reconnect, char *filter_string) {
+ char logon_txt[600];
+ char init_kiss_string[5]; // KISS-mode on startup
+ int ok;
+ char temp[300];
+ char verstr[15];
+
+ if ( (dev_nm == NULL) || (passwd == NULL) )
+ return(-1);
+
+ if (dev_nm[0] == '\0')
+ return(-1);
+
+ xastir_snprintf(verstr,
+ sizeof(verstr),
+ "XASTIR %s",
+ VERSION);
+
+ ok = -1;
+ if (port_avail >= 0){
+ if (debug_level & 2)
+ fprintf(stderr,"Port Available %d\n",port_avail);
+
+ switch(dev_type){
+
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ case DEVICE_SERIAL_GPS:
+ case DEVICE_SERIAL_WX:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+
+ switch (dev_type) {
+
+ case DEVICE_SERIAL_TNC:
+ if (debug_level & 2)
+ fprintf(stderr,"Opening a Serial TNC device\n");
+
+ break;
+
+ case DEVICE_SERIAL_KISS_TNC:
+ if (debug_level & 2)
+ fprintf(stderr,"Opening a Serial KISS TNC device\n");
+
+ break;
+
+ case DEVICE_SERIAL_MKISS_TNC:
+ if (debug_level & 2)
+ fprintf(stderr,"Opening a Serial MKISS TNC device\n");
+
+ break;
+
+ case DEVICE_SERIAL_GPS:
+ if (debug_level & 2)
+ fprintf(stderr,"Opening a Serial GPS device\n");
+ // Must wait for valid GPS parsing after
+ // sending one posit.
+ my_position_valid = 1;
+ using_gps_position++;
+ statusline(langcode("BBARSTA041"),1);
+//fprintf(stderr,"my_position_valid = 1, using_gps_position:%d\n",using_gps_position);
+
+ break;
+
+ case DEVICE_SERIAL_WX:
+ if (debug_level & 2)
+ fprintf(stderr,"Opening a Serial WX device\n");
+
+ break;
+
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ if (debug_level & 2)
+ fprintf(stderr,"Opening a Serial TNC w/HSP GPS device\n");
+ // Must wait for valid GPS parsing after
+ // sending one posit.
+ my_position_valid = 1;
+ using_gps_position++;
+ statusline(langcode("BBARSTA041"),1);
+//fprintf(stderr,"my_position_valid = 1, using_gps_position:%d\n",using_gps_position);
+
+ break;
+
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ if (debug_level & 2)
+ fprintf(stderr,"Opening a Serial TNC w/AUX GPS device\n");
+ // Must wait for valid GPS parsing after
+ // sending one posit.
+ my_position_valid = 1;
+ using_gps_position++;
+ statusline(langcode("BBARSTA041"),1);
+//fprintf(stderr,"my_position_valid = 1, using_gps_position:%d\n",using_gps_position);
+
+ break;
+
+ default:
+ break;
+ }
+ clear_port_data(port_avail,0);
+
+//if (begin_critical_section(&port_data_lock, "interface.c:add_device(1)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port_avail);
+
+ port_data[port_avail].device_type = dev_type;
+ xastir_snprintf(port_data[port_avail].device_name,
+ sizeof(port_data[port_avail].device_name),
+ "%s",
+ dev_nm);
+ port_data[port_avail].sp = dev_sp;
+ port_data[port_avail].style = dev_sty;
+ if (dev_type == DEVICE_SERIAL_WX) {
+ if (strcmp("1",passwd) == 0)
+ port_data[port_avail].data_type = 1;
+ }
+
+//if (end_critical_section(&port_data_lock, "interface.c:add_device(2)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port_avail);
+
+ ok = serial_init(port_avail);
+ break;
+
+ case DEVICE_NET_STREAM:
+ if (debug_level & 2)
+ fprintf(stderr,"Opening a Network stream\n");
+
+ clear_port_data(port_avail,0);
+
+//if (begin_critical_section(&port_data_lock, "interface.c:add_device(3)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port_avail);
+
+ port_data[port_avail].device_type = DEVICE_NET_STREAM;
+ xastir_snprintf(port_data[port_avail].device_host_name,
+ sizeof(port_data[port_avail].device_host_name),
+ "%s",
+ dev_nm);
+ xastir_snprintf(port_data[port_avail].device_host_pswd,
+ sizeof(port_data[port_avail].device_host_pswd),
+ "%s",
+ passwd);
+ port_data[port_avail].socket_port = dev_sck_p;
+ port_data[port_avail].reconnect = reconnect;
+
+//if (end_critical_section(&port_data_lock, "interface.c:add_device(4)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port_avail);
+
+ ok = net_init(port_avail);
+
+ if (ok == 1) {
+
+ /* if connected now send password */
+ if (strlen(passwd)) {
+
+ if (filter_string != NULL
+ && strlen(filter_string) > 0) { // Filter specified
+
+ // Please note that "filter" must be the 8th
+ // parameter on the line in order to be
+ // parsed properly by the servers.
+ xastir_snprintf(logon_txt,
+ sizeof(logon_txt),
+ "user %s pass %s vers %s filter %s%c%c",
+ my_callsign,
+ passwd,
+ verstr,
+ filter_string,
+ '\r',
+ '\n');
+ }
+ else { // No filter specified
+ xastir_snprintf(logon_txt,
+ sizeof(logon_txt),
+ "user %s pass %s vers %s%c%c",
+ my_callsign,
+ passwd,
+ verstr,
+ '\r',
+ '\n');
+ }
+ }
+ else {
+ xastir_snprintf(logon_txt,
+ sizeof(logon_txt),
+ "user %s pass -1 vers %s %c%c",
+ my_callsign,
+ verstr,
+ '\r',
+ '\n');
+ }
+
+//fprintf(stderr,"Sending this string: %s\n", logon_txt);
+
+ port_write_string(port_avail,logon_txt);
+ }
+ break;
+
+ case DEVICE_AX25_TNC:
+ if (debug_level & 2)
+ fprintf(stderr,"Opening a network AX25 TNC\n");
+
+ clear_port_data(port_avail,0);
+
+//if (begin_critical_section(&port_data_lock, "interface.c:add_device(5)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port_avail);
+
+ port_data[port_avail].device_type = DEVICE_AX25_TNC;
+ xastir_snprintf(port_data[port_avail].device_name,
+ sizeof(port_data[port_avail].device_name),
+ "%s",
+ dev_nm);
+
+//if (end_critical_section(&port_data_lock, "interface.c:add_device(6)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port_avail);
+
+ ok = ax25_init(port_avail);
+ break;
+
+ case DEVICE_NET_GPSD:
+ if (debug_level & 2)
+ fprintf(stderr,"Opening a network GPS using gpsd\n");
+
+ clear_port_data(port_avail,0);
+
+//if (begin_critical_section(&port_data_lock, "interface.c:add_device(7)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port_avail);
+
+ port_data[port_avail].device_type = DEVICE_NET_GPSD;
+ xastir_snprintf(port_data[port_avail].device_host_name,
+ sizeof(port_data[port_avail].device_host_name),
+ "%s",
+ dev_nm);
+ port_data[port_avail].socket_port = dev_sck_p;
+ port_data[port_avail].reconnect = reconnect;
+
+//if (end_critical_section(&port_data_lock, "interface.c:add_device(8)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port_avail);
+
+ ok = net_init(port_avail);
+ if (ok == 1) {
+
+ // Pre-2.90 GPSD protocol
+ xastir_snprintf(logon_txt, sizeof(logon_txt), "R\r\n");
+ port_write_string(port_avail,logon_txt);
+
+ // Moved the below section to near the bottom of
+ // the routine, after the read/write threads are
+ // started. The net effect is that the above
+ // string gets sent, then the below string,
+ // kick-starting either protocol into sending us
+ // NMEA strings.
+ //
+// // Post-2.90 GPSD protocol
+// xastir_snprintf(logon_txt, sizeof(logon_txt), "?WATCH={\"enable\":true,\"nmea\":true}\r\n");
+// port_write_string(port_avail,logon_txt);
+
+ // Must wait for valid GPS parsing after sending
+ // one posit.
+ my_position_valid = 1;
+ using_gps_position++;
+ statusline(langcode("BBARSTA041"),1);
+//fprintf(stderr,"my_position_valid = 1, using_gps_position:%d\n",using_gps_position);
+ }
+ break;
+
+ case DEVICE_NET_WX:
+ if (debug_level & 2)
+ fprintf(stderr,"Opening a network WX\n");
+
+ clear_port_data(port_avail,0);
+
+//if (begin_critical_section(&port_data_lock, "interface.c:add_device(9)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port_avail);
+
+ port_data[port_avail].device_type = DEVICE_NET_WX;
+ xastir_snprintf(port_data[port_avail].device_host_name,
+ sizeof(port_data[port_avail].device_host_name),
+ "%s",
+ dev_nm);
+ port_data[port_avail].socket_port = dev_sck_p;
+ port_data[port_avail].reconnect = reconnect;
+ if (strcmp("1",passwd) == 0)
+ port_data[port_avail].data_type = 1;
+
+//if (end_critical_section(&port_data_lock, "interface.c:add_device(10)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port_avail);
+
+ ok = net_init(port_avail);
+ if (ok == 1) {
+ /* if connected now send call and program version */
+ xastir_snprintf(logon_txt, sizeof(logon_txt), "%s %s%c%c", my_callsign, VERSIONTXT, '\r', '\n');
+ port_write_string(port_avail,logon_txt);
+ }
+ break;
+
+ case DEVICE_NET_DATABASE:
+ if (debug_level & 2)
+ fprintf(stderr,"Opening a network database stream\n");
+
+ clear_port_data(port_avail,0);
+
+//if (begin_critical_section(&port_data_lock, "interface.c:add_device(11)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port_avail);
+
+ port_data[port_avail].device_type = DEVICE_NET_DATABASE;
+ xastir_snprintf(port_data[port_avail].device_host_name,
+ sizeof(port_data[port_avail].device_host_name),
+ "%s",
+ dev_nm);
+ port_data[port_avail].socket_port = dev_sck_p;
+ port_data[port_avail].reconnect = reconnect;
+ if (strcmp("1",passwd) == 0)
+ port_data[port_avail].data_type = 1;
+
+//if (end_critical_section(&port_data_lock, "interface.c:add_device(12)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port_avail);
+
+ ok = net_init(port_avail);
+ if (ok == 1) {
+ /* if connected now send call and program version */
+ xastir_snprintf(logon_txt, sizeof(logon_txt), "%s %s%c%c", my_callsign, VERSIONTXT, '\r', '\n');
+ port_write_string(port_avail,logon_txt);
+ }
+ break;
+
+ case DEVICE_NET_AGWPE:
+ if (debug_level & 2)
+ fprintf(stderr,"Opening a network AGWPE stream");
+
+ clear_port_data(port_avail,0);
+
+//if (begin_critical_section(&port_data_lock, "interface.c:add_device(13)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port_avail);
+
+ port_data[port_avail].device_type = DEVICE_NET_AGWPE;
+ xastir_snprintf(port_data[port_avail].device_host_name,
+ sizeof(port_data[port_avail].device_host_name),
+ "%s",
+ dev_nm);
+ port_data[port_avail].socket_port = dev_sck_p;
+ port_data[port_avail].reconnect = reconnect;
+ if (strcmp("1",passwd) == 0)
+ port_data[port_avail].data_type = 1;
+
+//if (end_critical_section(&port_data_lock, "interface.c:add_device(14)" ) > 0)
+// fprintf(stderr,"port_data_lock, Port = %d\n", port_avail);
+
+ ok = net_init(port_avail);
+
+ if (ok == 1) {
+
+ // If password isn't empty, send login
+ // information
+ //
+ if (strlen(passwd) != 0) {
+
+ // Send the login packet
+ send_agwpe_packet(port_avail,
+ 0, // AGWPE RadioPort
+ 'P', // Login/Password Frame
+ NULL, // FromCall
+ NULL, // ToCall
+ NULL, // Path
+ (unsigned char *)passwd, // Data
+ strlen(passwd)); // Length
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (ok == 1) { // If port is connected...
+
+ if (debug_level & 2)
+ fprintf(stderr,"*** add_device: ok: %d ***\n",ok);
+
+ /* if all is ok check and start read write threads */
+ (void)start_port_threads(port_avail);
+ usleep(100000); // 100ms
+
+ switch (dev_type) {
+
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+
+ if (ok == 1) {
+
+// We already have the lock by the time add_device() is called!
+//begin_critical_section(&devices_lock, "interface.c:add_device" );
+
+ xastir_snprintf(temp, sizeof(temp), "config/%s", devices[port_avail].tnc_up_file);
+
+//end_critical_section(&devices_lock, "interface.c:add_device" );
+
+ (void)command_file_to_tnc_port(port_avail,get_data_base_dir(temp));
+ }
+ break;
+
+ case DEVICE_SERIAL_KISS_TNC:
+
+ // Initialize KISS-Mode at startup
+ if (devices[port_avail].init_kiss) {
+ xastir_snprintf(init_kiss_string,
+ sizeof(init_kiss_string),
+ "\x1B at k\r"); // [ESC at K sets tnc from terminal- into kissmode
+ port_write_string(port_avail,init_kiss_string);
+ usleep(100000); // wait a little bit...
+ }
+
+ // Send the KISS parameters to the TNC
+ send_kiss_config(port_avail,0,0x01,atoi(devices[port_avail].txdelay));
+ send_kiss_config(port_avail,0,0x02,atoi(devices[port_avail].persistence));
+ send_kiss_config(port_avail,0,0x03,atoi(devices[port_avail].slottime));
+ send_kiss_config(port_avail,0,0x04,atoi(devices[port_avail].txtail));
+ send_kiss_config(port_avail,0,0x05,devices[port_avail].fullduplex);
+ break;
+
+//WE7U
+ case DEVICE_SERIAL_MKISS_TNC:
+ // Send the KISS parameters to the TNC. We'll
+ // need to send them to the correct port for
+ // this MKISS device.
+ send_kiss_config(port_avail,0,0x01,atoi(devices[port_avail].txdelay));
+ send_kiss_config(port_avail,0,0x02,atoi(devices[port_avail].persistence));
+ send_kiss_config(port_avail,0,0x03,atoi(devices[port_avail].slottime));
+ send_kiss_config(port_avail,0,0x04,atoi(devices[port_avail].txtail));
+ send_kiss_config(port_avail,0,0x05,devices[port_avail].fullduplex);
+ break;
+
+ case DEVICE_NET_AGWPE:
+
+ // Query for the AGWPE version
+ //
+ send_agwpe_packet(port_avail,
+ 0, // AGWPE RadioPort
+ 'R', // Request SW Version Frame
+ NULL, // FromCall
+ NULL, // ToCall
+ NULL, // Path
+ NULL, // Data
+ 0); // Length
+
+
+ // Query for port information
+ //
+ send_agwpe_packet(port_avail,
+ 0, // AGWPE RadioPort
+ 'G', // Request Port Info Frame
+ NULL, // FromCall
+ NULL, // ToCall
+ NULL, // Path
+ NULL, // Data
+ 0); // Length
+
+
+/*
+ // Ask to receive "Monitor" frames. Once we
+ // switch to "raw" mode for decoding, we won't
+ // need this one anymore.
+ //
+ send_agwpe_packet(port_avail,
+ 0, // AGWPE RadioPort
+ 'm', // Monitor Packets Frame
+ NULL, // FromCall
+ NULL, // ToCall
+ NULL, // Path
+ NULL, // Data
+ 0); // Length
+*/
+
+
+ // Ask to receive "raw" frames
+ //
+ send_agwpe_packet(port_avail,
+ 0, // AGWPE RadioPort
+ 'k', // Request Raw Packets Frame
+ NULL, // FromCall
+ NULL, // ToCall
+ NULL, // Path
+ NULL, // Data
+ 0); // Length
+
+
+/*
+ // Send a dummy UI frame for testing purposes.
+ //
+ send_agwpe_packet(port_avail,
+ atoi(devices[port_avail].device_host_filter_string) - 1, // AGWPE radio port
+ '\0', // type
+ "TEST-3", // FromCall
+ "APRS", // ToCall
+ NULL, // Path
+ "Test", // Data
+ 4); // length
+
+
+ // Send another dummy UI frame.
+ //
+ send_agwpe_packet(port_avail,
+ atoi(devices[port_avail].device_host_filter_string) - 1, // AGWPE radio port
+ '\0', // type
+ "TEST-3", // FromCall
+ "APRS", // ToCall
+ "RELAY,SAR1-1,SAR2-1,SAR3-1,SAR4-1,SAR5-1,SAR6-1,SAR7-1", // Path
+ "Testing this darned thing!", // Data
+ 26); // length
+*/
+
+ break;
+
+ case DEVICE_NET_GPSD:
+
+ // Post-2.90 GPSD protocol
+ xastir_snprintf(logon_txt, sizeof(logon_txt), "?WATCH={\"enable\":true,\"nmea\":true}\r\n");
+ port_write_string(port_avail,logon_txt);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (ok == -1) {
+ xastir_snprintf(temp, sizeof(temp), langcode("POPEM00015"), port_avail);
+ popup_message(langcode("POPEM00004"),temp);
+ port_avail = -1;
+ } else {
+ if (ok == 0) {
+ xastir_snprintf(temp, sizeof(temp), langcode("POPEM00016"), port_avail);
+ popup_message(langcode("POPEM00004"),temp);
+ port_avail = -1;
+ }
+ }
+ } else
+ popup_message(langcode("POPEM00004"),langcode("POPEM00017"));
+
+ return(port_avail);
+}
+
+
+
+
+
+//***********************************************************
+// port status
+// port is the port to get status on
+//***********************************************************
+void port_stats(int port) {
+ if (port >= 0) {
+ fprintf(stderr,"Port %d %s Status\n\n",port,dtype[port_data[port].device_type].device_name);
+ fprintf(stderr,"Errors %d\n",port_data[port].errors);
+ fprintf(stderr,"Reconnects %d\n",port_data[port].reconnects);
+ fprintf(stderr,"Bytes in: %ld out: %ld\n",(long)port_data[port].bytes_input,(long)port_data[port].bytes_output);
+ fprintf(stderr,"\n");
+ }
+}
+
+
+
+
+
+//***********************************************************
+// startup defined ports
+//
+// port = -2: Start all defined interfaces
+// port = -1: Start all interfaces with "Activate on Startup"
+// port = 0 - MAX: Start only the one port specified
+//***********************************************************
+void startup_all_or_defined_port(int port) {
+ int i, override;
+ int start;
+
+ override = 0;
+
+ switch (port) {
+
+ case -1: // Start if "Activate on Startup" enabled
+ start = 0;
+ break;
+
+ case -2: // Start all interfaces, period!
+ start = 0;
+ override = 1;
+ break;
+
+ default: // Start only the interface specified in "port"
+ start = port;
+ override = 1;
+ break;
+ }
+
+begin_critical_section(&devices_lock, "interface.c:startup_all_or_defined_port" );
+
+ for (i = start; i < MAX_IFACE_DEVICES; i++){
+
+ // Only start ports that aren't already up
+ if ( (port_data[i].active != DEVICE_IN_USE)
+ || (port_data[i].status != DEVICE_UP) ) {
+
+ switch (devices[i].device_type) {
+
+ case DEVICE_NET_STREAM:
+ if (devices[i].connect_on_startup == 1 || override) {
+
+//end_critical_section(&devices_lock, "interface.c:startup_all_or_defined_port" );
+ //(void)del_device(i); // Disconnect old port if it exists
+//begin_critical_section(&devices_lock, "interface.c:startup_all_or_defined_port" );
+
+ (void)add_device(i,
+ DEVICE_NET_STREAM,
+ devices[i].device_host_name,
+ devices[i].device_host_pswd,
+ devices[i].sp,
+ 0,
+ 0,
+ devices[i].reconnect,
+ devices[i].device_host_filter_string);
+ }
+ break;
+
+ case DEVICE_NET_DATABASE:
+ if (devices[i].connect_on_startup == 1 || override) {
+
+//end_critical_section(&devices_lock, "interface.c:startup_all_or_defined_port" );
+ //(void)del_device(i); // Disconnect old port if it exists
+//begin_critical_section(&devices_lock, "interface.c:startup_all_or_defined_port" );
+
+ (void)add_device(i,
+ DEVICE_NET_DATABASE,
+ devices[i].device_host_name,
+ devices[i].device_host_pswd,
+ devices[i].sp,
+ 0,
+ 0,
+ devices[i].reconnect,
+ devices[i].device_host_filter_string);
+ }
+ break;
+
+ case DEVICE_NET_AGWPE:
+ if (devices[i].connect_on_startup == 1 || override) {
+
+//end_critical_section(&devices_lock, "interface.c:startup_all_or_defined_port" );
+ //(void)del_device(i); // Disconnect old port if it exists
+//begin_critical_section(&devices_lock, "interface.c:startup_all_or_defined_port" );
+
+ (void)add_device(i,
+ DEVICE_NET_AGWPE,
+ devices[i].device_host_name,
+ devices[i].device_host_pswd,
+ devices[i].sp,
+ 0,
+ 0,
+ devices[i].reconnect,
+ devices[i].device_host_filter_string);
+ }
+ break;
+
+ case DEVICE_NET_GPSD:
+ if (devices[i].connect_on_startup == 1 || override) {
+
+//end_critical_section(&devices_lock, "interface.c:startup_all_or_defined_port" );
+// (void)del_device(i); // Disconnect old port if it exists
+//begin_critical_section(&devices_lock, "interface.c:startup_all_or_defined_port" );
+
+ (void)add_device(i,
+ DEVICE_NET_GPSD,
+ devices[i].device_host_name,
+ "",
+ devices[i].sp,
+ 0,
+ 0,
+ devices[i].reconnect,
+ "");
+ }
+ break;
+
+ case DEVICE_SERIAL_WX:
+ if (devices[i].connect_on_startup == 1 || override) {
+ (void)add_device(i,
+ DEVICE_SERIAL_WX,
+ devices[i].device_name,
+ devices[i].device_host_pswd,
+ -1,
+ devices[i].sp,
+ devices[i].style,
+ 0,
+ "");
+ }
+ break;
+
+ case DEVICE_NET_WX:
+ if (devices[i].connect_on_startup == 1 || override) {
+
+//end_critical_section(&devices_lock, "interface.c:startup_all_or_defined_port" );
+// (void)del_device(i); // Disconnect old port if it exists
+//begin_critical_section(&devices_lock, "interface.c:startup_all_or_defined_port" );
+
+ (void)add_device(i,
+ DEVICE_NET_WX,
+ devices[i].device_host_name,
+ devices[i].device_host_pswd,
+ devices[i].sp,
+ 0,
+ 0,
+ devices[i].reconnect,
+ "");
+ }
+ break;
+
+ case DEVICE_SERIAL_GPS:
+ if (devices[i].connect_on_startup == 1 || override) {
+ (void)add_device(i,
+ DEVICE_SERIAL_GPS,
+ devices[i].device_name,
+ "",
+ -1,
+ devices[i].sp,
+ devices[i].style,
+ 0,
+ "");
+ }
+ break;
+
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+
+ if (devices[i].connect_on_startup == 1 || override) {
+ (void)add_device(i,
+ devices[i].device_type,
+ devices[i].device_name,
+ "",
+ -1,
+ devices[i].sp,
+ devices[i].style,
+ 0,
+ "");
+ }
+ break;
+
+ case DEVICE_AX25_TNC:
+ if (devices[i].connect_on_startup == 1 || override) {
+ (void)add_device(i,
+ DEVICE_AX25_TNC,
+ devices[i].device_name,
+ "",
+ -1,
+ -1,
+ -1,
+ 0,
+ "");
+ }
+ break;
+#ifdef HAVE_DB
+ case DEVICE_SQL_DATABASE:
+ if (debug_level & 4096)
+ fprintf(stderr,"Device %d Connect_on_startup=%d\n",i,devices[i].connect_on_startup);
+ if (devices[i].connect_on_startup == 1 || override) {
+ ioparam *d = &devices[i];
+ if (debug_level & 4096)
+ fprintf(stderr,"Opening a sql db with device type %d\n",d->device_type);
+ (void)add_device_by_ioparam(i, &devices[i]);
+ if (debug_level & 4096)
+ fprintf(stderr, "added device by ioparam [%d] type=[%d]\n",i,connections[i].type);
+ }
+ break;
+#endif /* HAVE_DB */
+
+ default:
+ break;
+ } // End of switch
+ }
+ else if (debug_level & 2) {
+ fprintf(stderr,"Skipping port %d, it's already running\n",i);
+ }
+
+ if (port != -1 && port != -2) {
+ // We're doing a specific port #, so stop the loop
+ i = MAX_IFACE_DEVICES+1;
+ }
+ }
+
+end_critical_section(&devices_lock, "interface.c:startup_all_or_defined_port" );
+
+}
+
+
+
+
+
+//***********************************************************
+// shutdown active ports
+//
+// port = -1: Shut down all active ports
+// port = 0 to max: Shut down the specified port if active
+//***********************************************************
+void shutdown_all_active_or_defined_port(int port) {
+ int i;
+ int start;
+
+ if (debug_level & 2)
+ fprintf(stderr,"\nshutdown_all_active_or_defined_port: %d\n\n",port);
+
+ if (port == -1)
+ start = 0;
+ else
+ start = port;
+
+ for( i = start; i < MAX_IFACE_DEVICES; i++ ){
+ if ( (port_data[i].active == DEVICE_IN_USE)
+ && ( (port_data[i].status == DEVICE_UP)
+ || (port_data[i].status == DEVICE_ERROR) ) ) {
+ if (debug_level & 2)
+ fprintf(stderr,"Shutting down port %d \n",i);
+
+ (void)del_device(i);
+ }
+ if (port != -1) // Stop after one iteration if port specified
+ i = MAX_IFACE_DEVICES+1;
+ }
+}
+
+
+
+
+
+//*************************************************************
+// check ports
+//
+// Called periodically by main.c:UpdateTime() function.
+// Attempts to reconnect interfaces that are down.
+//*************************************************************
+void check_ports(void) {
+ int i;
+ int temp;
+
+ for (i = 0; i < MAX_IFACE_DEVICES; i++){
+
+ switch (port_data[i].device_type){
+ case(DEVICE_NET_STREAM):
+ //case(DEVICE_AX25_TNC):
+ case(DEVICE_NET_GPSD):
+ case(DEVICE_NET_WX):
+ if (port_data[i].port_activity == 0) {
+ // We've seen no activity for one time period. This variable
+ // is updated in interface_gui.c
+
+ if (port_data[i].status == DEVICE_ERROR) {
+ // We're already in the error state, so force a reconnect
+ port_data[i].reconnects = -1;
+ }
+ else if (port_data[i].status == DEVICE_UP) {
+ // No activity on a port that's being used.
+ // Cause a reconnect at the next iteration
+ if (debug_level & 2)
+ fprintf(stderr,"check_ports(): Inactivity on port %d, DEVICE_ERROR ***\n",i);
+ port_data[i].status = DEVICE_ERROR; // No activity, so force a shutdown
+
+ // Show the latest status in the interface control dialog
+ update_interface_list();
+
+
+ // If the below statement is enabled, it causes an immediate reconnect
+ // after one time-period of inactivity, currently 7.5 minutes, as set in
+ // main.c:UpdateTime(). This means the symbol will never change from green
+ // to red on the status bar, so the operator might not know about a
+ // connection that is being constantly reconnected. By leaving it commented
+ // out we get one time period of red, and then it will reconnect at the 2nd
+ // time period. This means we can reconnect within 15 minutes if a line
+ // goes dead.
+ //
+ port_data[i].reconnects = -1; // Causes an immediate reconnect
+ }
+
+ }
+ else { // We saw activity on this port.
+ port_data[i].port_activity = 0; // Reset counter for next time
+ }
+ break;
+ }
+
+ if (port_data[i].active == DEVICE_IN_USE && port_data[i].status == DEVICE_ERROR) {
+ if (debug_level & 2)
+ fprintf(stderr,"Found device error on port %d\n",i);
+
+ if (port_data[i].reconnect == 1) {
+ port_data[i].reconnects++;
+ temp = port_data[i].reconnects;
+ if (temp < 1) {
+ if (debug_level & 2)
+ fprintf(stderr,"Device asks for reconnect count now at %d\n",temp);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Shutdown device %d\n",i);
+
+ shutdown_all_active_or_defined_port(i);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Starting device %d\n",i);
+
+ startup_all_or_defined_port(i);
+
+ /* if error on startup */
+ if (port_data[i].status == DEVICE_ERROR)
+ port_data[i].reconnects = temp;
+ } else {
+ if (debug_level & 2)
+ fprintf(stderr,"Device has either too many errors, or no activity at all!\n");
+
+ port_data[i].reconnects = temp - 2;
+ }
+ }
+ }
+ }
+}
+
+
+
+
+
+static char unproto_path_txt[MAX_LINE_SIZE+5];
+
+
+
+
+
+// Function which selects an unproto path in round-robin fashion.
+// Once we select a path, we save the number selected back to
+// devices[port].unprotonum so that the next time around we select
+// the next in the sequence. If we don't come up with a valid
+// unproto path, we use the unproto path: "WIDE2-2".
+//
+// Input: Port number
+// Ouput: String pointer containing unproto path
+//
+// WE7U: Should we check to make sure that there are printable
+// characters in the path?
+//
+unsigned char *select_unproto_path(int port) {
+ int count;
+ int done;
+ int temp;
+ int bump_up;
+
+
+ // Set unproto path:
+ // We look for a non-null path entry starting at the current
+ // value of "unprotonum". The first non-null path wins.
+ count = 0;
+ done = 0;
+ bump_up = 0;
+
+
+ while (!done && (count < 3)) {
+ temp = (devices[port].unprotonum + count) % 3;
+ switch (temp) {
+
+ case 0:
+ if (strlen(devices[port].unproto1) > 0) {
+ xastir_snprintf(unproto_path_txt,
+ sizeof(unproto_path_txt),
+ "%s",
+ devices[port].unproto1);
+ done++;
+ }
+ else {
+ // No path entered here. Skip this path in the
+ // rotation for next time.
+ bump_up++;
+ }
+ break;
+
+ case 1:
+ if (strlen(devices[port].unproto2) > 0) {
+ xastir_snprintf(unproto_path_txt,
+ sizeof(unproto_path_txt),
+ "%s",
+ devices[port].unproto2);
+ done++;
+ }
+ else {
+ // No path entered here. Skip this path in
+ // the rotation for next time.
+ bump_up++;
+ }
+ break;
+
+ case 2:
+ if (strlen(devices[port].unproto3) > 0) {
+ xastir_snprintf(unproto_path_txt,
+ sizeof(unproto_path_txt),
+ "%s",
+ devices[port].unproto3);
+ done++;
+ }
+ else {
+ // No path entered here. Skip this path in
+ // the rotation for next time.
+ bump_up++;
+ }
+ break;
+ } // End of switch
+ count++;
+ } // End of while loop
+
+ if (done) {
+ // We found an unproto path. Check it for accepted values.
+ // Output a warning message if it is beyond normal ranges,
+ // but still allow it to be used.
+ //
+ if(check_unproto_path(unproto_path_txt)) {
+ popup_message_always(langcode("WPUPCFT045"),
+ langcode("WPUPCFT043"));
+ }
+ }
+ else {
+ // We found no entries in the unproto fields for the
+ // interface. Set a default path of "WIDE2-2".
+
+ xastir_snprintf(unproto_path_txt,
+ sizeof(unproto_path_txt),
+ "WIDE2-2");
+ }
+
+ // Increment the path number for the next round of
+ // transmissions. This will round-robin the paths so that all
+ // entered paths get used.
+ devices[port].unprotonum = (devices[port].unprotonum + 1 + bump_up) % 3;
+
+ // Make sure the path is in upper-case
+ (void)to_upper(unproto_path_txt);
+
+ return((unsigned char *)unproto_path_txt);
+}
+
+
+
+
+
+//***********************************************************
+// output_my_aprs_data
+// This is the function responsible for sending out my own
+// posits. The next function below this one handles objects,
+// messages and the like (output_my_data).
+//***********************************************************
+void output_my_aprs_data(void) {
+ char header_txt[MAX_LINE_SIZE+5];
+ char header_txt_save[MAX_LINE_SIZE+5];
+ char data_txt[MAX_LINE_SIZE+5];
+ char data_txt_save[MAX_LINE_SIZE+5];
+ char temp[MAX_LINE_SIZE+5];
+ char path_txt[MAX_LINE_SIZE+5];
+ char *unproto_path = "";
+ char data_txt2[5];
+ struct tm *day_time;
+ time_t sec;
+ char my_pos[256];
+ char my_output_lat[MAX_LAT];
+ char my_output_long[MAX_LONG];
+ char output_net[256];
+ char wx_data[200];
+ char output_phg[10];
+ char output_cs[10];
+ char output_alt[20];
+ char output_brk[3];
+ int ok;
+ int port;
+ char my_comment_tx[MAX_COMMENT+1];
+ int interfaces_ok_for_transmit = 0;
+ char logfile_tmp_path[MAX_VALUE];
+
+ // Check whether transmits are disabled globally
+ if (transmit_disable) {
+
+ if (emergency_beacon) {
+
+ // Notify the operator because emergency_beacon mode is on but
+ // nobody will know it 'cuz global transmit is disabled.
+ //
+ // "Warning"
+ // "Global transmit is DISABLED. Emergency beacons are NOT going out!"
+ popup_message_always( langcode("POPEM00035"),
+ langcode("POPEM00047") );
+ }
+ return;
+ }
+
+ header_txt_save[0] = '\0';
+ data_txt_save[0] = '\0';
+ sec = sec_now();
+
+
+ // Check whether we're in emergency beacon mode. If so, add
+ // "EMERGENCY" at the beginning of the comment field we'll
+ // transmit.
+ if (emergency_beacon) {
+ xastir_snprintf(my_comment_tx,
+ sizeof(my_comment_tx),
+ "EMERGENCY %s",
+ my_comment);
+ }
+ else {
+ xastir_snprintf(my_comment_tx,
+ sizeof(my_comment_tx),
+ "%s",
+ my_comment);
+ }
+
+
+ // Format latitude string for transmit later
+ if (transmit_compressed_posit) { // High res version
+ xastir_snprintf(my_output_lat,
+ sizeof(my_output_lat),
+ "%s",
+ my_lat);
+ }
+ else { // Create a low-res version of the latitude string
+ long my_temp_lat;
+ char temp_data[20];
+
+ // Convert to long
+ my_temp_lat = convert_lat_s2l(my_lat);
+
+ // Convert to low-res string
+ convert_lat_l2s(my_temp_lat,
+ temp_data,
+ sizeof(temp_data),
+ CONVERT_LP_NORMAL);
+
+//fprintf(stderr," Latitude temp_data:%s\n", temp_data);
+
+ xastir_snprintf(my_output_lat,
+ sizeof(my_output_lat),
+ "%c%c%c%c.%c%c%c",
+ temp_data[0],
+ temp_data[1],
+ temp_data[3],
+ temp_data[4],
+ temp_data[6],
+ temp_data[7],
+ temp_data[8]);
+ }
+
+ (void)output_lat(my_output_lat,transmit_compressed_posit);
+ if (debug_level & 128)
+ fprintf(stderr,"OUT LAT <%s>\n",my_output_lat);
+
+ // Format longitude string for transmit later
+ if (transmit_compressed_posit) { // High res version
+ xastir_snprintf(my_output_long,
+ sizeof(my_output_long),
+ "%s",
+ my_long);
+ }
+ else { // Create a low-res version of the longitude string
+ long my_temp_long;
+ char temp_data[20];
+
+ // Convert to long
+ my_temp_long = convert_lon_s2l(my_long);
+
+ // Convert to low-res string
+ convert_lon_l2s(my_temp_long,
+ temp_data,
+ sizeof(temp_data),
+ CONVERT_LP_NORMAL);
+
+//fprintf(stderr,"Longitude temp_data:%s\n", temp_data);
+
+ xastir_snprintf(my_output_long,
+ sizeof(my_output_long),
+ "%c%c%c%c%c.%c%c%c",
+ temp_data[0],
+ temp_data[1],
+ temp_data[2],
+ temp_data[4],
+ temp_data[5],
+ temp_data[7],
+ temp_data[8],
+ temp_data[9]);
+ }
+
+ (void)output_long(my_output_long,transmit_compressed_posit);
+ if (debug_level & 128)
+ fprintf(stderr,"OUT LONG <%s>\n",my_output_long);
+
+begin_critical_section(&devices_lock, "interface.c:output_my_aprs_data" );
+
+ // Iterate across the ports, set up each device's headers/paths/handshakes,
+ // then transmit the posit if the port is open and tx is enabled.
+ for (port = 0; port < MAX_IFACE_DEVICES; port++) {
+
+ // First send any header/path info we might need out the port,
+ // set up TNC's to the proper mode, etc.
+ ok = 1;
+ switch (port_data[port].device_type) {
+
+// case DEVICE_NET_DATABASE:
+
+ case DEVICE_NET_AGWPE:
+
+ output_net[0] = '\0'; // We don't need this header for AGWPE
+ break;
+
+ case DEVICE_NET_STREAM:
+
+ xastir_snprintf(output_net,
+ sizeof(output_net),
+ "%s>%s,TCPIP*:",
+ my_callsign,
+ VERSIONFRM);
+ break;
+
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+
+ /* make dtr normal (talk to TNC) */
+ if (port_data[port].status == DEVICE_UP) {
+ port_dtr(port,0);
+ }
+
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_AX25_TNC:
+
+ /* clear this for a TNC */
+ output_net[0] = '\0';
+
+ /* Set my call sign */
+ xastir_snprintf(header_txt,
+ sizeof(header_txt),
+ "%c%s %s\r",
+ '\3',
+ "MYCALL",
+ my_callsign);
+
+ // Send the callsign out to the TNC only if the interface is up and tx is enabled???
+ // We don't set it this way for KISS TNC interfaces.
+ if ( (port_data[port].device_type != DEVICE_SERIAL_KISS_TNC)
+ && (port_data[port].device_type != DEVICE_SERIAL_MKISS_TNC)
+ && (port_data[port].status == DEVICE_UP)
+ && (devices[port].transmit_data == 1)
+ && !transmit_disable
+ && !posit_tx_disable) {
+ port_write_string(port,header_txt);
+ }
+
+ // Set unproto path: Get next unproto path in
+ // sequence.
+ unproto_path = (char *)select_unproto_path(port);
+
+ xastir_snprintf(header_txt,
+ sizeof(header_txt),
+ "%c%s %s VIA %s\r",
+ '\3',
+ "UNPROTO",
+ VERSIONFRM,
+ unproto_path);
+
+ xastir_snprintf(header_txt_save,
+ sizeof(header_txt_save),
+ "%s>%s,%s:",
+ my_callsign,
+ VERSIONFRM,
+ unproto_path);
+
+ xastir_snprintf(path_txt,
+ sizeof(path_txt),
+ "%s",
+ unproto_path);
+
+
+ // Send the header data to the TNC. This sets the
+ // unproto path that'll be used by the next packet.
+ // We don't set it this way for KISS TNC interfaces.
+ if ( (port_data[port].device_type != DEVICE_SERIAL_KISS_TNC)
+ && (port_data[port].device_type != DEVICE_SERIAL_MKISS_TNC)
+ && (port_data[port].status == DEVICE_UP)
+ && (devices[port].transmit_data == 1)
+ && !transmit_disable
+ && !posit_tx_disable) {
+ port_write_string(port,header_txt);
+ }
+
+
+ // Set converse mode. We don't need to do this for
+ // KISS TNC interfaces. One european TNC (tnc2-ui)
+ // doesn't accept "conv" but does accept the 'k'
+ // command. A Kantronics KPC-2 v2.71 TNC accepts
+ // the "conv" command but not the 'k' command.
+ // Figures! The choice of whether to send "k" or "conv"
+ // is made by the user in the Serial TNC interface properties
+ // dialog. Older versions of Xastir had this hardcoded here.
+ //
+ xastir_snprintf(header_txt, sizeof(header_txt), "%c%s\r", '\3', devices[port].device_converse_string);
+//fprintf(stderr,"%s\n", header_txt);
+
+ if ( (port_data[port].device_type != DEVICE_SERIAL_KISS_TNC)
+ && (port_data[port].device_type != DEVICE_SERIAL_MKISS_TNC)
+ && (port_data[port].status == DEVICE_UP)
+ && (devices[port].transmit_data == 1)
+ && !transmit_disable
+ && !posit_tx_disable) {
+ port_write_string(port,header_txt);
+ }
+ // Delay a bit if the user clicked on the "Add Delay"
+ // togglebutton in the port's interface properties dialog.
+ // This is primarily needed for KAM TNCs, which will fail to
+ // go into converse mode if there is no delay here.
+ if (devices[port].tnc_extra_delay != 0) {
+ usleep(devices[port].tnc_extra_delay);
+ }
+ break;
+
+ default: /* port has unknown device_type */
+ ok = 0;
+ break;
+
+ } // End of switch
+
+
+ // Set up some more strings for later transmission
+
+ /* send station info */
+ output_cs[0] = '\0';
+ output_phg[0] = '\0';
+ output_alt[0] = '\0';
+ output_brk[0] = '\0';
+
+
+ if (transmit_compressed_posit)
+ xastir_snprintf(my_pos,
+ sizeof(my_pos),
+ "%s",
+ compress_posit(my_output_lat,
+ my_group,
+ my_output_long,
+ my_symbol,
+ my_last_course,
+ my_last_speed, // In knots
+ my_phg));
+ else { /* standard non compressed mode */
+ xastir_snprintf(my_pos,
+ sizeof(my_pos),
+ "%s%c%s%c",
+ my_output_lat,
+ my_group,
+ my_output_long,
+ my_symbol);
+ /* get PHG, if used for output */
+ if (strlen(my_phg) >= 6)
+ xastir_snprintf(output_phg,
+ sizeof(output_phg),
+ "%s",
+ my_phg);
+
+ /* get CSE/SPD, Always needed for output even if 0 */
+ xastir_snprintf(output_cs,
+ sizeof(output_cs),
+ "%03d/%03d/",
+ my_last_course,
+ my_last_speed); // Speed in knots
+
+ /* get altitude */
+ if (my_last_altitude_time > 0)
+ xastir_snprintf(output_alt,
+ sizeof(output_alt),
+ "A=%06ld/",
+ my_last_altitude);
+ }
+
+
+ // And set up still more strings for later transmission
+ switch (output_station_type) {
+ case(1):
+ /* APRS_MOBILE LOCAL TIME */
+
+ if((strlen(output_cs) < 8) && (my_last_altitude_time > 0) &&
+ (strlen(output_alt) > 0)) {
+ xastir_snprintf(output_brk,
+ sizeof(output_brk),
+ "/");
+ }
+
+ day_time = localtime(&sec);
+
+ xastir_snprintf(data_txt_save,
+ sizeof(data_txt_save),
+ "@%02d%02d%02d/%s%s%s%s%s",
+ day_time->tm_mday,
+ day_time->tm_hour,
+ day_time->tm_min,
+ my_pos,
+ output_cs,
+ output_brk,
+ output_alt,
+ my_comment_tx);
+
+//WE7U2:
+ // Truncate at max length for this type of APRS
+ // packet.
+ if (transmit_compressed_posit) {
+ if (strlen(data_txt_save) > 61) {
+ data_txt_save[61] = '\0';
+ }
+ }
+ else { // Uncompressed lat/long
+ if (strlen(data_txt_save) > 70) {
+ data_txt_save[70] = '\0';
+ }
+ }
+
+ // Add '\r' onto end.
+ strncat(data_txt_save, "\r", 1);
+
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%s%s",
+ output_net,
+ data_txt_save);
+
+ break;
+
+ case(2):
+ /* APRS_MOBILE ZULU DATE-TIME */
+
+ if((strlen(output_cs) < 8) && (my_last_altitude_time > 0) &&
+ (strlen(output_alt) > 0)) {
+ xastir_snprintf(output_brk,
+ sizeof(output_brk),
+ "/");
+ }
+
+ day_time = gmtime(&sec);
+
+ xastir_snprintf(data_txt_save,
+ sizeof(data_txt_save),
+ "@%02d%02d%02dz%s%s%s%s%s",
+ day_time->tm_mday,
+ day_time->tm_hour,
+ day_time->tm_min,
+ my_pos,
+ output_cs,
+ output_brk,
+ output_alt,
+ my_comment_tx);
+
+//WE7U2:
+ // Truncate at max length for this type of APRS
+ // packet.
+ if (transmit_compressed_posit) {
+ if (strlen(data_txt_save) > 61) {
+ data_txt_save[61] = '\0';
+ }
+ }
+ else { // Uncompressed lat/long
+ if (strlen(data_txt_save) > 70) {
+ data_txt_save[70] = '\0';
+ }
+ }
+
+ // Add '\r' onto end.
+ strncat(data_txt_save, "\r", 1);
+
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%s%s",
+ output_net,
+ data_txt_save);
+
+ break;
+
+ case(3):
+ /* APRS_MOBILE ZULU TIME w/SEC */
+
+ if((strlen(output_cs) < 8) && (my_last_altitude_time > 0) &&
+ (strlen(output_alt) > 0)) {
+ xastir_snprintf(output_brk,
+ sizeof(output_brk),
+ "/");
+ }
+
+ day_time = gmtime(&sec);
+
+ xastir_snprintf(data_txt_save,
+ sizeof(data_txt_save),
+ "@%02d%02d%02dh%s%s%s%s%s",
+ day_time->tm_hour,
+ day_time->tm_min,
+ day_time->tm_sec,
+ my_pos,
+ output_cs,
+ output_brk,
+ output_alt,
+ my_comment_tx);
+
+//WE7U2:
+ // Truncate at max length for this type of APRS
+ // packet.
+ if (transmit_compressed_posit) {
+ if (strlen(data_txt_save) > 61) {
+ data_txt_save[61] = '\0';
+ }
+ }
+ else { // Uncompressed lat/long
+ if (strlen(data_txt_save) > 70) {
+ data_txt_save[70] = '\0';
+ }
+ }
+
+ // Add '\r' onto end.
+ strncat(data_txt_save, "\r", 1);
+
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%s%s",
+ output_net,
+ data_txt_save);
+
+ break;
+
+ case(4):
+ /* APRS position with WX data, no timestamp */
+ sec = wx_tx_data1(wx_data, sizeof(wx_data));
+ if (sec != 0) {
+
+ xastir_snprintf(data_txt_save,
+ sizeof(data_txt_save),
+ "%c%s%s",
+ aprs_station_message_type,
+ my_pos,
+ wx_data);
+
+// WE7U2:
+// There's no limit on the max size for this kind of packet except
+// for the AX.25 limit of 256 bytes!
+ //
+ // Truncate at max length for this type of APRS
+ // packet. Left the compressed/uncompressed
+ // "if" statement here in case we need to change
+ // this in the future due to spec changes.
+ // Consistent with the rest of the code in this
+ // function which does similar things.
+ //
+ if (transmit_compressed_posit) {
+ if (strlen(data_txt_save) > 256) {
+ data_txt_save[256] = '\0';
+ }
+ }
+ else { // Uncompressed lat/long
+ if (strlen(data_txt_save) > 256) {
+ data_txt_save[256] = '\0';
+ }
+ }
+
+ // Add '\r' onto end.
+ strncat(data_txt_save, "\r", 1);
+
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%s%s",
+ output_net,
+ data_txt_save);
+ }
+ else {
+ /* default to APRS FIXED if no wx data. No timestamp */
+
+ if ((strlen(output_phg) < 6) && (my_last_altitude_time > 0) &&
+ (strlen(output_alt) > 0)) {
+ xastir_snprintf(output_brk,
+ sizeof(output_brk),
+ "/");
+ }
+
+ xastir_snprintf(data_txt_save,
+ sizeof(data_txt_save),
+ "%c%s%s%s%s%s",
+ aprs_station_message_type,
+ my_pos,
+ output_phg,
+ output_brk,
+ output_alt,
+ my_comment_tx);
+
+// WE7U2:
+ // Truncate at max length for this type of APRS
+ // packet.
+ if (transmit_compressed_posit) {
+ if (strlen(data_txt_save) > 54) {
+ data_txt_save[54] = '\0';
+ }
+ }
+ else { // Uncompressed lat/long
+ if (strlen(data_txt_save) > 63) {
+ data_txt_save[63] = '\0';
+ }
+ }
+
+ // Add '\r' onto end.
+ strncat(data_txt_save, "\r", 1);
+
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%s%s",
+ output_net,
+ data_txt_save);
+ }
+
+ break;
+
+ case(5):
+ /* APRS position with ZULU DATE-TIME and WX data */
+ sec = wx_tx_data1(wx_data,sizeof(wx_data));
+ if (sec != 0) {
+ day_time = gmtime(&sec);
+
+ xastir_snprintf(data_txt_save,
+ sizeof(data_txt_save),
+ "@%02d%02d%02dz%s%s",
+ day_time->tm_mday,
+ day_time->tm_hour,
+ day_time->tm_min,
+ my_pos,
+ wx_data);
+
+// WE7U2:
+ // Truncate at max length for this type of APRS
+ // packet.
+ if (transmit_compressed_posit) {
+ if (strlen(data_txt_save) > 61) {
+ data_txt_save[61] = '\0';
+ }
+ }
+ else { // Uncompressed lat/long
+ if (strlen(data_txt_save) > 70) {
+ data_txt_save[70] = '\0';
+ }
+ }
+
+ // Add '\r' onto end.
+ strncat(data_txt_save, "\r", 1);
+
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%s%s",
+ output_net,
+ data_txt_save);
+ }
+ else {
+ /* default to APRS FIXED if no wx data */
+
+ if((strlen(output_phg) < 6) && (my_last_altitude_time > 0) &&
+ (strlen(output_alt) > 0)) {
+ xastir_snprintf(output_brk,
+ sizeof(output_brk),
+ "/");
+ }
+
+ xastir_snprintf(data_txt_save,
+ sizeof(data_txt_save),
+ "%c%s%s%s%s%s",
+ aprs_station_message_type,
+ my_pos,
+ output_phg,
+ output_brk,
+ output_alt,
+ my_comment_tx);
+
+// WE7U2:
+ // Truncate at max length for this type of APRS
+ // packet.
+ if (transmit_compressed_posit) {
+ if (strlen(data_txt_save) > 54) {
+ data_txt_save[54] = '\0';
+ }
+ }
+ else { // Uncompressed lat/long
+ if (strlen(data_txt_save) > 63) {
+ data_txt_save[63] = '\0';
+ }
+ }
+
+ // Add '\r' onto end.
+ strncat(data_txt_save, "\r", 1);
+
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%s%s",
+ output_net,
+ data_txt_save);
+ }
+ break;
+
+ /* default to APRS FIXED if no wx data */
+ case(0):
+
+ default:
+ /* APRS_FIXED */
+
+ if ((strlen(output_phg) < 6) && (my_last_altitude_time > 0) &&
+ (strlen(output_alt) > 0)) {
+ xastir_snprintf(output_brk,
+ sizeof(output_brk),
+ "/");
+ }
+
+ xastir_snprintf(data_txt_save,
+ sizeof(data_txt_save),
+ "%c%s%s%s%s%s",
+ aprs_station_message_type,
+ my_pos,
+ output_phg,
+ output_brk,
+ output_alt,
+ my_comment_tx);
+
+// WE7U2:
+ // Truncate at max length for this type of APRS
+ // packet.
+ if (transmit_compressed_posit) {
+ if (strlen(data_txt_save) > 54) {
+ data_txt_save[54] = '\0';
+ }
+ }
+ else { // Uncompressed lat/long
+ if (strlen(data_txt_save) > 63) {
+ data_txt_save[63] = '\0';
+ }
+ }
+
+ // Add '\r' onto end.
+ strncat(data_txt_save, "\r", 1);
+
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%s%s",
+ output_net,
+ data_txt_save);
+
+ break;
+ }
+
+
+//fprintf(stderr,"data_txt_save: %s\n",data_txt_save);
+
+
+ if (ok) {
+ // Here's where the actual transmit of the posit occurs. The
+ // transmit string has been set up in "data_txt" by this point.
+
+ // If transmit or posits have been turned off, don't transmit posit
+ if ( (port_data[port].status == DEVICE_UP)
+ && (devices[port].transmit_data == 1)
+ && !transmit_disable
+ && !posit_tx_disable) {
+
+ interfaces_ok_for_transmit++;
+
+// WE7U: Change so that path is passed as well for KISS TNC
+// interfaces: header_txt_save would probably be the one to pass,
+// or create a new string just for KISS TNC's.
+
+ if ( (port_data[port].device_type == DEVICE_SERIAL_KISS_TNC)
+ || (port_data[port].device_type == DEVICE_SERIAL_MKISS_TNC) ) {
+
+// Note: This one has callsign & destination in the string
+
+ // Transmit the posit out the KISS interface
+ send_ax25_frame(port,
+ my_callsign, // source
+ VERSIONFRM, // destination
+ path_txt, // path
+ data_txt); // data
+ }
+
+//WE7U:AGWPE
+ else if (port_data[port].device_type == DEVICE_NET_AGWPE) {
+
+ // Set unproto path: Get next unproto path in
+ // sequence.
+ unproto_path = (char *)select_unproto_path(port);
+
+// We need to remove the complete AX.25 header from data_txt before
+// we call this routine! Instead put the digipeaters into the
+// ViaCall fields. We do this above by setting output_net to '\0'
+// before creating the data_txt string.
+ send_agwpe_packet(port, // Xastir interface port
+ atoi(devices[port].device_host_filter_string) - 1, // AGWPE RadioPort
+ '\0', // Type of frame
+ (unsigned char *)my_callsign, // source
+ (unsigned char *)VERSIONFRM, // destination
+ (unsigned char *)unproto_path, // Path,
+ (unsigned char *)data_txt, // Data
+ strlen(data_txt) - 1); // Skip \r
+
+//fprintf(stderr,"Sending this string: \n%s\n", data_txt);
+//fprintf(stderr,"Length was %d\n", strlen(data_txt) - 1);
+
+ }
+
+ else { // Not a Serial KISS TNC interface
+
+//fprintf(stderr,"Sending this string: \n%s\n\n", data_txt);
+
+ port_write_string(port, data_txt); // Transmit the posit
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"TX:%d<%s>\n",port,data_txt);
+
+ /* add new line on network data */
+ if (port_data[port].device_type == DEVICE_NET_STREAM) {
+ xastir_snprintf(data_txt2, sizeof(data_txt2), "\n"); // Transmit a newline
+ port_write_string(port, data_txt2);
+ }
+
+
+ // Put our transmitted packet into the Incoming Data
+ // window as well. This way we can see both sides of a
+ // conversation. data_port == -1 for x_spider port,
+ // normal interface number otherwise. -99 to get a "**"
+ // display meaning all ports.
+ //
+ // For packets that we're igating we end up with a CR or
+ // LF on the end of them. Remove that so the display
+ // looks nice.
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s>%s,%s:%s",
+ my_callsign,
+ VERSIONFRM,
+ unproto_path,
+ data_txt);
+ makePrintable(temp);
+ packet_data_add("TX ", temp, port);
+//fprintf(stderr,"%s\n", temp);
+
+ }
+ else {
+ }
+ } // End of posit transmit: "if (ok)"
+ } // End of big loop
+
+end_critical_section(&devices_lock, "interface.c:output_my_aprs_data" );
+
+
+ // Check the interfaces_ok_for_transmit variable if we're in
+ // emergency_beacon mode. If we didn't transmit out any interfaces, alert
+ // the operator so that they can either enable interfaces or get emergency
+ // help in some other manner.
+ //
+ if (emergency_beacon) {
+
+ if (interfaces_ok_for_transmit) {
+
+ // Beacons are going out in emergency beacon mode. Alert the
+ // operator so that he/she knows they've enabled that mode.
+ //
+ // "Emergency Beacon Mode"
+ // "EMERGENCY BEACON MODE, transmitting every 60 seconds!"
+ popup_message_always( langcode("POPEM00048"),
+ langcode("POPEM00049") );
+ }
+
+ else { // Emergency beacons are not going out for some reason
+
+ // Notify the operator because emergency_beacon mode is on but
+ // nobody will know it 'cuz there are no interfaces enabled for
+ // transmit.
+ //
+ // "Warning"
+ // "Interfaces or posits/transmits DISABLED. Emergency beacons are NOT going out!"
+ popup_message_always( langcode("POPEM00035"),
+ langcode("POPEM00050") );
+ }
+ }
+
+
+ // This will log a posit in the general format for a network interface
+ // whether or not any network interfaces are currently up.
+ if (log_net_data) {
+ xastir_snprintf(data_txt, sizeof(data_txt), "%s>%s,TCPIP*:%s", my_callsign,
+ VERSIONFRM, data_txt_save);
+ log_data( get_user_base_dir(LOGFILE_NET, logfile_tmp_path,
+ sizeof(logfile_tmp_path)),
+ (char *)data_txt );
+ }
+
+
+ if (enable_server_port && !transmit_disable && !posit_tx_disable) {
+// Send data to the x_spider server
+
+ xastir_snprintf(data_txt, sizeof(data_txt), "%s>%s,TCPIP*:%s", my_callsign,
+ VERSIONFRM, data_txt_save);
+
+ if (writen(pipe_xastir_to_tcp_server,
+ data_txt,
+ strlen(data_txt)) != (int)strlen(data_txt)) {
+ fprintf(stderr,
+ "my_aprs_data: Writen error: %d\n",
+ errno);
+ }
+ // Terminate it with a linefeed
+ if (writen(pipe_xastir_to_tcp_server, "\n", 1) != 1) {
+ fprintf(stderr,
+ "my_aprs_data: Writen error: %d\n",
+ errno);
+ }
+ }
+// End of x_spider server send code
+
+
+ // Note that this will only log one TNC line per transmission now matter
+ // how many TNC's are defined. It's a representative sample of what we're
+ // sending out. At least one TNC interface must be enabled in order to
+ // have anything output to the log file here.
+ if (log_tnc_data) {
+ if (header_txt_save[0] != '\0') {
+ xastir_snprintf(data_txt, sizeof(data_txt), "%s%s", header_txt_save, data_txt_save);
+ log_data( get_user_base_dir(LOGFILE_TNC, logfile_tmp_path,
+ sizeof(logfile_tmp_path)),
+ (char *)data_txt );
+ }
+ }
+
+//fprintf(stderr,"Data_txt:%s\n", data_txt);
+}
+
+
+
+
+
+//*****************************************************************************
+// output_my_data()
+//
+// 1) Used to send local messages/objects/items. Cooked mode.
+// 2) Used from output_igate_net(), igating from RF to the 'net. Raw mode.
+// 3) Used from output_igate_rf() to igate from the 'net to RF. Cooked mode.
+// 4) Used from output_nws_igate_rf() to send NWS packets out RF. Cooked mode.
+// 5) Used for queries and responses. Cooked mode.
+//
+// Parameters:
+// message: the message data to send
+// port: the port transmitting through, or -1 for all
+// type: 0 for my data, 1 for raw data (Cooked/Raw)
+// loopback_only: 0 for transmit/loopback, 1 for loopback only
+// use_igate_path: 0 for standard unproto paths, 1 for igate path
+// path: Set to non-NULL if special path selected for messaging
+//
+// This function sends out messages/objects/bulletins/etc.
+// This one currently tries to do local logging even if
+// transmit is disabled.
+//*****************************************************************************
+void output_my_data(char *message, int incoming_port, int type, int loopback_only, int use_igate_path, char *path) {
+ char data_txt[MAX_LINE_SIZE+5];
+ char data_txt_save[MAX_LINE_SIZE+5];
+ char temp[MAX_LINE_SIZE+5];
+ char path_txt[MAX_LINE_SIZE+5];
+ char *unproto_path = "";
+ char output_net[256];
+ int ok, start, finish, port;
+ int done;
+ char logfile_tmp_path[MAX_VALUE];
+
+ // Check whether transmits are disabled globally
+ if (transmit_disable && !loopback_only) {
+ return;
+ }
+
+ //// cbell- if path is null, strlen/printf segv in solaris
+ if (path == NULL) {
+ path = "";
+ }
+
+ if (debug_level & 1) {
+ fprintf(stderr,
+ "Sending out port: %d, type: %d, path: %s\n",
+ incoming_port,
+ type,
+ path);
+ }
+
+ if (message == NULL)
+ return;
+
+ if (message[0] == '\0')
+ return;
+
+ data_txt_save[0] = '\0';
+
+ if (incoming_port == -1) { // Send out all of the interfaces
+ start = 0;
+ finish = MAX_IFACE_DEVICES;
+ }
+ else { // Only send out the chosen interface
+ start = incoming_port;
+ finish = incoming_port + 1;
+ }
+
+
+begin_critical_section(&devices_lock, "interface.c:output_my_data" );
+
+ for (port = start; port < finish; port++) {
+
+ ok = 1;
+ if (type == 0) { // my data
+ switch (port_data[port].device_type) {
+
+// case DEVICE_NET_DATABASE:
+
+ case DEVICE_NET_AGWPE:
+//fprintf(stderr,"DEVICE_NET_AGWPE\n");
+ output_net[0] = '\0'; // Clear header
+ break;
+
+ case DEVICE_NET_STREAM:
+ if (debug_level & 1)
+ fprintf(stderr,"%d Net\n",port);
+ xastir_snprintf(output_net,
+ sizeof(output_net),
+ "%s>%s,TCPIP*:",
+ my_callsign,
+ VERSIONFRM);
+ break;
+
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ if (port_data[port].status == DEVICE_UP && !loopback_only && !transmit_disable) {
+ port_dtr(port,0); // make DTR normal (talk to TNC)
+ }
+
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_AX25_TNC:
+
+ if (debug_level & 1)
+ fprintf(stderr,"%d AX25 TNC\n",port);
+ output_net[0] = '\0'; // clear this for a TNC
+
+ /* Set my call sign */
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%c%s %s\r",
+ '\3',
+ "MYCALL",
+ my_callsign);
+
+ if ( (port_data[port].device_type != DEVICE_SERIAL_KISS_TNC)
+ && (port_data[port].device_type != DEVICE_SERIAL_MKISS_TNC)
+ && (port_data[port].status == DEVICE_UP)
+ && (devices[port].transmit_data == 1)
+ && !transmit_disable
+ && !loopback_only) {
+ port_write_string(port,data_txt);
+ usleep(10000); // 10ms
+ }
+
+ done = 0;
+
+ // Set unproto path. First check whether we're
+ // to use the igate path. If so and the path
+ // isn't empty, skip the rest of the path selection:
+ if ( (use_igate_path)
+ && (strlen(devices[port].unproto_igate) > 0) ) {
+
+// WE7U: Should we check here and in the following path
+// selection code to make sure that there are printable characters
+// in the path? Also: Output_my_aprs_data() has nearly identical
+// path selection code. Fix it in one place, fix it in the other.
+
+ // Check whether igate path is socially
+ // acceptable. Output warning if not, but
+ // still allow the transmit.
+ if(check_unproto_path(devices[port].unproto_igate)) {
+ popup_message_always(langcode("WPUPCFT046"),
+ langcode("WPUPCFT043"));
+ }
+
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%c%s %s VIA %s\r",
+ '\3',
+ "UNPROTO",
+ VERSIONFRM,
+ devices[port].unproto_igate);
+
+ xastir_snprintf(data_txt_save,
+ sizeof(data_txt_save),
+ "%s>%s,%s:",
+ my_callsign,
+ VERSIONFRM,
+ devices[port].unproto_igate);
+
+ xastir_snprintf(path_txt,
+ sizeof(path_txt),
+ "%s",
+ devices[port].unproto_igate);
+
+ done++;
+ }
+
+
+ // Check whether a path was passed to us as a
+ // parameter:
+ if ( (path != NULL) && (strlen(path) != 0) ) {
+
+ if (strncmp(path, "DIRECT PATH", 11) == 0) {
+ // The user has requested a direct path
+
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%c%s %s\r",
+ '\3',
+ "UNPROTO",
+ VERSIONFRM);
+
+ xastir_snprintf(data_txt_save,
+ sizeof(data_txt_save),
+ "%s>%s:",
+ my_callsign,
+ VERSIONFRM);
+ }
+ else {
+
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%c%s %s VIA %s\r",
+ '\3',
+ "UNPROTO",
+ VERSIONFRM,
+ path);
+
+ xastir_snprintf(data_txt_save,
+ sizeof(data_txt_save),
+ "%s>%s,%s:",
+ my_callsign,
+ VERSIONFRM,
+ path);
+ }
+
+ if (strncmp(path, "DIRECT PATH", 11) == 0) {
+ // The user has requested a direct path
+ path_txt[0] = '\0'; // Empty path
+ }
+ else {
+ xastir_snprintf(path_txt,
+ sizeof(path_txt),
+ "%s",
+ path);
+ }
+
+ done++;
+
+ // If "DEFAULT PATH" was passed to us, then
+ // we're not done yet.
+ //
+ if (strncmp(path, "DEFAULT PATH", 12) == 0) {
+ done = 0;
+ }
+ }
+
+ if (!done) {
+
+ // Set unproto path: Get next unproto path
+ // in sequence.
+ unproto_path = (char *)select_unproto_path(port);
+
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%c%s %s VIA %s\r",
+ '\3',
+ "UNPROTO",
+ VERSIONFRM,
+ unproto_path);
+
+ xastir_snprintf(data_txt_save,
+ sizeof(data_txt_save),
+ "%s>%s,%s:",
+ my_callsign,
+ VERSIONFRM,
+ unproto_path);
+
+ xastir_snprintf(path_txt,
+ sizeof(path_txt),
+ "%s",
+ unproto_path);
+
+ done++;
+ }
+
+
+ if ( (port_data[port].device_type != DEVICE_SERIAL_KISS_TNC)
+ && (port_data[port].device_type != DEVICE_SERIAL_MKISS_TNC)
+ && (port_data[port].status == DEVICE_UP)
+ && (devices[port].transmit_data == 1)
+ && !transmit_disable
+ && !loopback_only) {
+ port_write_string(port,data_txt);
+ usleep(10000); // 10ms
+ }
+
+ // Set converse mode. One european TNC
+ // (tnc2-ui) doesn't accept "conv" but does
+ // accept the 'k' command. A Kantronics KPC-2
+ // v2.71 TNC accepts the "conv" command but not
+ // the 'k' command. Figures!
+ //
+// xastir_snprintf(data_txt, sizeof(data_txt), "%c%s\r", '\3', "CONV");
+// xastir_snprintf(data_txt, sizeof(data_txt), "%c%s\r", '\3', "k");
+// xastir_snprintf(data_txt, sizeof(data_txt), "%c%s\r", '\3', CONVERSE_MODE);
+ xastir_snprintf(data_txt, sizeof(data_txt), "%c%s\r", '\3', devices[port].device_converse_string);
+
+
+
+ if ( (port_data[port].device_type != DEVICE_SERIAL_KISS_TNC)
+ && (port_data[port].device_type != DEVICE_SERIAL_MKISS_TNC)
+ && (port_data[port].status == DEVICE_UP)
+ && (devices[port].transmit_data == 1)
+ && !transmit_disable
+ && !loopback_only) {
+ port_write_string(port,data_txt);
+ usleep(20000); // 20ms
+ }
+ break;
+
+ default: /* unknown */
+ ok = 0;
+ break;
+ } // End of switch
+ } else { // Type == 1, raw data. Probably igating something...
+ output_net[0] = '\0';
+ }
+
+
+ if (ok) {
+ /* send data */
+ xastir_snprintf(data_txt, sizeof(data_txt), "%s%s\r", output_net, message);
+
+//fprintf(stderr,"%s\n",data_txt);
+
+ if ( (port_data[port].status == DEVICE_UP)
+ && (devices[port].transmit_data == 1)
+ && !transmit_disable
+ && !loopback_only) {
+
+// WE7U: Change so that path is passed as well for KISS TNC
+// interfaces: data_txt_save would probably be the one to pass,
+// or create a new string just for KISS TNC's.
+
+ if ( (port_data[port].device_type == DEVICE_SERIAL_KISS_TNC)
+ || (port_data[port].device_type == DEVICE_SERIAL_MKISS_TNC) ) {
+
+ // Transmit
+ send_ax25_frame(port,
+ my_callsign, // source
+ VERSIONFRM, // destination
+ path_txt, // path
+ data_txt); // data
+ }
+
+//WE7U:AGWPE
+ else if (port_data[port].device_type == DEVICE_NET_AGWPE) {
+
+ // Set unproto path. First check whether we're
+ // to use the igate path. If so and the path
+ // isn't empty, skip the rest of the path selection:
+ if ( (use_igate_path)
+ && (strlen(devices[port].unproto_igate) > 0) ) {
+
+ // Check whether igate path is socially
+ // acceptable. Output warning if not, but
+ // still allow the transmit.
+ if(check_unproto_path(devices[port].unproto_igate)) {
+ popup_message_always(langcode("WPUPCFT046"),
+ langcode("WPUPCFT043"));
+ }
+
+ xastir_snprintf(path_txt,
+ sizeof(path_txt),
+ "%s",
+ devices[port].unproto_igate);
+ }
+ // Check whether a path was passed to us as a
+ // parameter:
+ else if ( (path != NULL) && (strlen(path) != 0) ) {
+
+ if (strncmp(path, "DEFAULT PATH", 12) == 0) {
+ unproto_path = (char *)select_unproto_path(port);
+
+//fprintf(stderr,"unproto_path: %s\n", unproto_path);
+ xastir_snprintf(path_txt,
+ sizeof(path_txt),
+ "%s",
+ unproto_path);
+ }
+
+ else if (strncmp(path, "DIRECT PATH", 11) == 0) {
+ // The user has requested a direct path
+ path_txt[0] = '\0'; // Empty string
+
+// WE7U
+// TEST THIS TO SEE IF IT WORKS ON AGWPE TO HAVE NO PATH
+
+ }
+ else {
+ xastir_snprintf(path_txt,
+ sizeof(path_txt),
+ "%s",
+ path);
+ }
+ }
+ else {
+ // Set unproto path: Get next unproto path in
+ // sequence.
+
+ unproto_path = (char *)select_unproto_path(port);
+
+//fprintf(stderr,"unproto_path: %s\n", unproto_path);
+ xastir_snprintf(path_txt,
+ sizeof(path_txt),
+ "%s",
+ unproto_path);
+ }
+//fprintf(stderr,"path_txt: %s\n", path_txt);
+
+
+// We need to remove the complete AX.25 header from data_txt before
+// we call this routine! Instead put the digipeaters into the
+// ViaCall fields. We do this above by setting output_net to '\0'
+// before creating the data_txt string.
+
+//fprintf(stderr,"send_agwpe_packet\n");
+
+ send_agwpe_packet(port, // Xastir interface port
+ atoi(devices[port].device_host_filter_string) - 1, // AGWPE RadioPort
+ '\0', // Type of frame
+ (unsigned char *)my_callsign, // source
+ (unsigned char *)VERSIONFRM, // destination
+ (unsigned char *)path_txt, // Path,
+ (unsigned char *)data_txt, // Data
+ strlen(data_txt) - 1); // Skip \r
+ }
+
+ else { // Not a Serial KISS TNC interface
+
+//fprintf(stderr,"Sending this string: %s\n", data_txt);
+
+ port_write_string(port, data_txt); // Transmit
+ }
+
+ if (debug_level & 1)
+ fprintf(stderr,"Sending to interface:%d, %s\n",
+ port,
+ data_txt);
+
+
+ // Put our transmitted packet into the Incoming Data
+ // window as well. This way we can see both sides of a
+ // conversation. data_port == -1 for x_spider port,
+ // normal interface number otherwise. -99 to get a "**"
+ // display meaning all ports.
+ //
+ // For packets that we're igating we end up with a CR or
+ // LF on the end of them. Remove that so the display
+ // looks nice.
+ //
+ // Check whether a path was passed to us as a
+ // parameter:
+
+ if ( (path != NULL) && (strlen(path) != 0) ) {
+
+ if (strncmp(path, "DEFAULT PATH", 12) == 0) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s>%s,%s:%s",
+ my_callsign,
+ VERSIONFRM,
+ unproto_path,
+ message);
+ }
+ else if (strncmp(path, "DIRECT PATH", 11) == 0) {
+ // The user has requested a direct path
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s>%s:%s",
+ my_callsign,
+ VERSIONFRM,
+ message);
+ }
+ else {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s>%s,%s:%s",
+ my_callsign,
+ VERSIONFRM,
+ path,
+ message);
+ }
+ }
+ else {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s>%s,%s:%s",
+ my_callsign,
+ VERSIONFRM,
+ unproto_path,
+ message);
+ }
+ makePrintable(temp);
+ packet_data_add("TX ", temp, port);
+//fprintf(stderr,"%s\n", temp);
+
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"TX:%d<%s>\n",port,data_txt);
+
+ /* add newline on network data */
+ if (port_data[port].device_type == DEVICE_NET_STREAM) {
+ xastir_snprintf(data_txt, sizeof(data_txt), "\n");
+
+ if ( (port_data[port].status == DEVICE_UP)
+ && (devices[port].transmit_data == 1)
+ && !transmit_disable
+ && !loopback_only) {
+ port_write_string(port,data_txt);
+ }
+ }
+ else {
+ }
+ }
+// if (incoming_port != -1)
+// port = MAX_IFACE_DEVICES+1; // process only one port
+ }
+
+end_critical_section(&devices_lock, "interface.c:output_my_data" );
+
+ // This will log a posit in the general format for a network interface
+ // whether or not any network interfaces are currently up.
+ xastir_snprintf(data_txt, sizeof(data_txt), "%s>%s,TCPIP*:%s", my_callsign,
+ VERSIONFRM, message);
+ if (debug_level & 2)
+ fprintf(stderr,"output_my_data: Transmitting and decoding: %s\n", data_txt);
+
+ if (log_net_data)
+ log_data( get_user_base_dir(LOGFILE_NET, logfile_tmp_path,
+ sizeof(logfile_tmp_path)),
+ (char *)data_txt );
+
+
+ // Note that this will only log one TNC line per transmission now matter
+ // how many TNC's are defined. It's a representative sample of what we're
+ // sending out. At least one TNC interface must be enabled in order to
+ // have anything output to the log file here.
+ if (data_txt_save[0] != '\0') {
+ xastir_snprintf(data_txt, sizeof(data_txt), "%s%s", data_txt_save, message);
+ if (log_tnc_data)
+ log_data( get_user_base_dir(LOGFILE_TNC, logfile_tmp_path,
+ sizeof(logfile_tmp_path)),
+ (char *)data_txt );
+ }
+
+
+ if (enable_server_port && !loopback_only && !transmit_disable) {
+// Send data to the x_spider server
+
+ if (type == 0) { // My data, add a header
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%s>%s,TCPIP*:%s",
+ my_callsign,
+ VERSIONFRM,
+ message);
+ }
+ else { // Not my data, don't add a header
+ xastir_snprintf(data_txt,
+ sizeof(data_txt),
+ "%s",
+ message);
+ }
+
+//fprintf(stderr,"To 2023:%s", data_txt);
+//fprintf(stderr,"\tport:%d type:%d loopback_only:%d use_igate_path:%d\n",
+// incoming_port, type, loopback_only, use_igate_path);
+
+ if (writen(pipe_xastir_to_tcp_server,
+ data_txt,
+ strlen(data_txt)) != (int)strlen(data_txt)) {
+ fprintf(stderr,
+ "output_my_data: Writen error: %d\n",
+ errno);
+ }
+ // Terminate it with a linefeed
+ if (writen(pipe_xastir_to_tcp_server, "\n", 1) != 1) {
+ fprintf(stderr,
+ "output_my_data: Writen error: %d\n",
+ errno);
+ }
+ }
+// End of x_spider server send code
+
+
+ // Decode our own transmitted packets.
+ // Note that this function call is destructive to the first parameter.
+ // This is why we call it _after_ we call the log_data functions.
+ //
+ // This must be the "L" packet we see in the View->Messages
+ // dialog. We don't see a "T" packet (for TNC) and we only see
+ // "I" packets if we re-receive our own packet from the internet
+ // feeds.
+ if (incoming_port == -1) { // We were sending to all ports
+ // Pretend we received it from port 1
+//fprintf(stderr,"output_my_data 1:%s\n", data_txt);
+ decode_ax25_line( data_txt, DATA_VIA_LOCAL, 1, 1);
+ }
+ else { // We were sending to a specific port
+//fprintf(stderr,"output_my_data 2:%s\n", data_txt);
+ decode_ax25_line( data_txt, DATA_VIA_LOCAL, incoming_port, 1);
+ }
+
+//fprintf(stderr,"Data_txt:%s\n", data_txt);
+}
+
+
+
+
+
+//*****************************************************************************
+// output_waypoint_data()
+//
+// message: the message data to send
+//
+// This function sends out waypoint creation strings to GPS
+// interfaces capable of dealing with it.
+//
+//*****************************************************************************
+void output_waypoint_data(char *message) {
+ char data_txt[MAX_LINE_SIZE+5];
+ char data_txt_save[MAX_LINE_SIZE+5];
+ int ok, start, finish, i;
+
+ if (message == NULL)
+ return;
+
+ if (message[0] == '\0')
+ return;
+
+ if (debug_level & 1)
+ fprintf(stderr,"Sending to GPS interfaces: %s\n", message);
+
+ data_txt_save[0] = '\0';
+
+ start = 0;
+ finish = MAX_IFACE_DEVICES;
+
+begin_critical_section(&devices_lock, "interface.c:output_waypoint_data" );
+
+ for (i = start; i < finish; i++) {
+ ok = 1;
+ switch (port_data[i].device_type) {
+
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ port_dtr(i,1); // make DTR active (select GPS)
+ break;
+
+ case DEVICE_SERIAL_GPS:
+ break;
+
+ default: /* unknown */
+ ok = 0;
+ break;
+ } // End of switch
+
+ if (ok) { // Found a GPS interface
+ /* send data */
+ xastir_snprintf(data_txt, sizeof(data_txt), "%s\r\n", message);
+
+ if (port_data[i].status == DEVICE_UP) {
+ port_write_string(i,data_txt);
+ usleep(250000); // 0.25 secs
+
+ if (debug_level & 1)
+ fprintf(stderr,"Sending to interface:%d, %s\n",i,data_txt);
+ }
+
+ if (debug_level & 2)
+ fprintf(stderr,"TX:%d<%s>\n",i,data_txt);
+
+ if (port_data[i].device_type == DEVICE_SERIAL_TNC_HSP_GPS) {
+ port_dtr(i,0); // make DTR inactive (select TNC data)
+ }
+ }
+ }
+
+end_critical_section(&devices_lock, "interface.c:output_waypoint_data" );
+
+}
+
+
+
+
+
+// Added by KB6MER for KAM XL(SERIAL_TNC_AUX_GPS) support
+// buf is a null terminated string
+// returns buf as a null terminated string after cleaning.
+// Currently:
+// removes leading 'cmd:' prompts from TNC if needed
+// Can be used to add any additional data cleaning functions desired.
+// Currently only called for SERIAL_TNC_AUX_GPS, but could be added
+// to other device routines to improve packet decode on other devices.
+//
+// Note that the length of "buf" can be up to MAX_DEVICE_BUFFER,
+// which is currently set to 4096.
+//
+void tnc_data_clean(char *buf) {
+
+ if (debug_level & 1) {
+ char filtered_data[MAX_LINE_SIZE+1];
+
+ // strncpy is ok here as long as nulls not in data. We
+ // null-terminate it ourselves to make sure it is terminated.
+ strncpy(filtered_data, buf, MAX_LINE_SIZE);
+ filtered_data[MAX_LINE_SIZE] = '\0'; // Terminate it
+
+ makePrintable(filtered_data);
+ fprintf(stderr,"tnc_data_clean: called to clean %s\n", filtered_data);
+ }
+
+ while (!strncmp(buf,"cmd:",4)) {
+ int ii;
+
+ // We're _shortening_ the string here, so we don't need to
+ // know the length of the buffer unless it has no '\0'
+ // terminator to begin with! In that one case we could run
+ // off the end of the string and get a segfault or cause
+ // other problems.
+ for (ii = 0; ; ii++) {
+ buf[ii] = buf[ii+4];
+ if (buf[ii] == '\0')
+ break;
+ }
+ }
+
+ if (debug_level & 1) {
+ char filtered_data[MAX_LINE_SIZE+1];
+
+ // Binary routine. strncpy is ok here as long as nulls not
+ // in data. We null-terminate it ourselves to make sure it
+ // is terminated.
+ strncpy(filtered_data, buf, MAX_LINE_SIZE);
+ filtered_data[MAX_LINE_SIZE] = '\0'; // Terminate it
+
+ makePrintable(filtered_data);
+ fprintf(stderr,"tnc_data_clean: clean result %s\n", filtered_data);
+ }
+}
+
+
+
+
+
+// Added by KB6MER for KAM XL (SERIAL_TNC_AUX_GPS) support
+// buf is a null terminated string.
+// port is integer offset into port_data[] array of iface data (see interface.h)
+// returns int 0=AX25, 1=GPS
+// Tries to guess from the contents of buf whether it represents data from
+// the GPS or data from an AX25 packet.
+//
+// Note that the length of "buf" can be up to MAX_DEVICE_BUFFER,
+// which is currently set to 4096.
+//
+int tnc_get_data_type(char *buf, int port) {
+ register int i;
+ int type=1; // Don't know what it is yet. Assume NMEA for now.
+
+ if (debug_level & 1) {
+ char filtered_data[MAX_LINE_SIZE+1];
+
+ // Binary routine. strncpy is ok here as long as nulls not
+ // in data. We null-terminate it ourselves to make sure it
+ // is terminated.
+ strncpy(filtered_data, buf, MAX_LINE_SIZE);
+ filtered_data[MAX_LINE_SIZE] = '\0'; // Terminate it
+
+ makePrintable(filtered_data);
+ fprintf(stderr,"tnc_get_data_type: parsing %s\n", filtered_data);
+ }
+
+ // First, let's look for NMEA-ish things.
+ if (buf[0]=='$') {
+ //This looks kind of NMEA-ish, let's check for known message type
+ //headers ($P[A-Z][A-Z][A-Z][A-Z] or $GP[A-Z][A-Z][A-Z])
+ if(buf[1]=='P') {
+ for(i=2; i<=5; i++) {
+ if (buf[i]<'A' || buf[i]>'Z') {
+ type=0; // Disqualified, not valid NMEA-0183
+ if (debug_level & 1) {
+ char filtered_data[MAX_LINE_SIZE+1];
+
+ // Binary routine. strncpy is ok here as
+ // long as nulls not in data. We
+ // null-terminate it ourselves to make
+ // sure it is terminated.
+ strncpy(filtered_data, buf, MAX_LINE_SIZE);
+ filtered_data[MAX_LINE_SIZE] = '\0'; // Terminate it
+
+ makePrintable(filtered_data);
+ fprintf(stderr,"tnc_get_data_type: Not NMEA %s\n",
+ filtered_data);
+ }
+ }
+ }
+ }
+ else if(buf[1]=='G' && buf[2]=='P') {
+ for(i=3; i<=5; i++) {
+ if (buf[i]<'A' || buf[i]>'Z') {
+ type=0; // Disqualified, not valid NMEA-0183
+ if (debug_level & 1) {
+ char filtered_data[MAX_LINE_SIZE+1];
+
+ // Binary routine. strncpy is ok here as
+ // long as nulls not in data. We
+ // null-terminate it ourselves to make
+ // sure it is terminated.
+ strncpy(filtered_data, buf, MAX_LINE_SIZE);
+ filtered_data[MAX_LINE_SIZE] = '\0'; // Terminate it
+
+ makePrintable(filtered_data);
+ fprintf(stderr,"tnc_get_data_type: Not NMEA %s\n",
+ filtered_data);
+ }
+ }
+ }
+ }
+ }
+ else { // Must be APRS data
+ type = 0;
+ }
+
+ if (debug_level & 1) {
+ if (type == 0)
+ fprintf(stderr,"APRS data\n");
+ else
+ fprintf(stderr,"NMEA data\n");
+ }
+
+ return(type);
+}
+
+
diff --git a/src/interface.h b/src/interface.h
new file mode 100644
index 0000000..7a948de
--- /dev/null
+++ b/src/interface.h
@@ -0,0 +1,276 @@
+/*
+ * $Id: interface.h,v 1.48 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifndef __XASTIR_INTERFACE_H
+#define __XASTIR_INTERFACE_H
+
+#include <termios.h>
+#include <unistd.h>
+#include "util.h"
+#include "xastir.h"
+
+
+#define MAX_DEVICE_NAME 128
+#define MAX_DEVICE_BUFFER 4096
+#define MAX_DEVICE_BUFFER_UNTIL_BINARY_SWITCH 700
+#define MAX_DEVICE_HOSTNM 40
+#define MAX_DEVICE_HOSTPW 40
+
+#define MAX_IFACE_DEVICES 15
+
+#define NET_CONNECT_TIMEOUT 20
+
+#define DEFAULT_GPS_RETR 0x05 /* CTRL-E */
+
+// Define a 60 second max wait on a serial port (in microseconds)
+#define SERIAL_MAX_WAIT 60000000
+
+// KISS Protocol Special Characters & Commands:
+#define KISS_FEND 0xc0 // Frame End
+#define KISS_FESC 0xdb // Frame Escape
+#define KISS_TFEND 0xdc // Transposed Frame End
+#define KISS_TFESC 0xdd // Transposed Frame Escape
+#define KISS_DATA 0x00
+#define KISS_TXDELAY 0x01
+#define KISS_PERSISTENCE 0x02
+#define KISS_SLOTTIME 0x03
+#define KISS_TXTAIL 0x04
+#define KISS_FULLDUPLEX 0x05
+#define KISS_SETHARDWARE 0x06
+#define KISS_RETURN 0xff
+
+
+
+#define MAX_IFACE_DEVICE_TYPES 15
+
+/* Define Device Types */
+enum Device_Types {
+ DEVICE_NONE,
+ DEVICE_SERIAL_TNC,
+ DEVICE_SERIAL_TNC_HSP_GPS,
+ DEVICE_SERIAL_GPS,
+ DEVICE_SERIAL_WX,
+ DEVICE_NET_STREAM,
+ DEVICE_AX25_TNC,
+ DEVICE_NET_GPSD,
+ DEVICE_NET_WX,
+ DEVICE_SERIAL_TNC_AUX_GPS, // KB6MER -> KAM XL or other TNC w/GPS on AUX port
+ DEVICE_SERIAL_KISS_TNC, // KISS TNC on serial port (not ax.25 kernel device)
+ DEVICE_NET_DATABASE,
+ DEVICE_NET_AGWPE,
+ DEVICE_SERIAL_MKISS_TNC, // Multi-port KISS TNC, like the Kantronics KAM
+ DEVICE_SQL_DATABASE // SQL server (MySQL/Postgis) database
+};
+
+enum Device_Active {
+ DEVICE_NOT_IN_USE,
+ DEVICE_IN_USE
+};
+
+enum Device_Status {
+ DEVICE_DOWN,
+ DEVICE_UP,
+ DEVICE_ERROR
+};
+
+
+typedef struct {
+ int device_type; /* device type */
+ int active; /* channel in use */
+ int status; /* current status (up or down) */
+ char device_name[MAX_DEVICE_NAME+1]; /* device name */
+ char device_host_name[MAX_DEVICE_HOSTNM+1]; /* device host name for network */
+ unsigned long int address; /* socket address for network */
+ int thread_status; /* thread status for connect thread */
+ int connect_status; /* connect status for connect thread */
+ int decode_errors; /* decode error count, used for data type */
+ int data_type; /* 0=normal 1=wx_binary */
+ int socket_port; /* socket port# for network */
+ char device_host_pswd[MAX_DEVICE_HOSTPW+1]; /* host password */
+ int channel; /* for serial and net ports */
+ int channel2; /* for AX25 ports */
+ char ui_call[30]; /* current call for this port */
+ struct termios t,t_old; /* terminal struct for serial port */
+ int dtr; /* dtr signal for HSP cable (status) */
+ int sp; /* serial port speed */
+ int style; /* serial port style */
+ int scan; /* data read available */
+ int errors; /* errors for this port */
+ int reconnect; /* reconnect on net failure */
+ int reconnects; /* total number of reconnects by this port */
+ unsigned long bytes_input; /* total bytes read by this port */
+ unsigned long bytes_output; /* total bytes written by this port */
+ unsigned long bytes_input_last; /* total bytes read last check */
+ unsigned long bytes_output_last; /* total bytes read last check */
+ int port_activity; /* 0 if no activity between checks */
+ pthread_t read_thread; /* read thread */
+ int read_in_pos; /* current read buffer input pos */
+ int read_out_pos; /* current read buffer output pos */
+ char device_read_buffer[MAX_DEVICE_BUFFER]; /* read buffer for this port */
+ xastir_mutex read_lock; /* Lock for reading the port data */
+ pthread_t write_thread; /* write thread */
+ int write_in_pos; /* current write buffer input pos */
+ int write_out_pos; /* current write buffer output pos */
+ xastir_mutex write_lock; /* Lock for writing the port data */
+ char device_write_buffer[MAX_DEVICE_BUFFER];/* write buffer for this port */
+} iface;
+
+typedef struct {
+ char device_name[100];
+} iodevices;
+
+
+typedef struct {
+ int device_type; /* device type */
+ char device_name[MAX_DEVICE_NAME+1]; /* device name */
+ char radio_port[3]; /* port for multi-port TNC's */
+ char device_host_name[MAX_DEVICE_HOSTNM+1]; /* device host name for network */
+ char device_host_pswd[MAX_DEVICE_HOSTPW+1]; /* host password also WX device data type */
+ char device_host_filter_string[201]; /* host filter string */
+ char device_converse_string[10+1]; /* string used to enter converse mode */
+ char comment[50]; /* Local comment or name for port */
+ char unproto1[50]; /* unproto path 1 for this port */
+ char unproto2[50]; /* unproto path 2 for this port */
+ char unproto3[50]; /* unproto path 3 for this port */
+ char unproto_igate[50]; /* unproto igate path for this port */
+ int unprotonum; /* unproto path selection */
+ char tnc_up_file[100]; /* file for setting up TNC on this port */
+ char tnc_down_file[100]; /* file for shutting down TNC on this port */
+ int sp; /* serial port speed/Net port */
+ int style; /* serial port style */
+ int igate_options; /* Igate options (0=none,1=input,2=in/out) */
+ int transmit_data; /* Data transmit out of this port */
+ int reconnect; /* reconnect on net failure */
+ int connect_on_startup; /* connect to this device on startup */
+ int gps_retrieve; /* Character to cause SERIAL_TNC_AUX_GPS to spit out current GPS data */
+ int tnc_extra_delay; /* Introduces fixed delay when talking to TNC in command-mode */
+ int set_time; /* Set System Time from GPS on this port */
+ char txdelay[4]; /* KISS parameter */
+ char persistence[4]; /* KISS parameter */
+ char slottime[4]; /* KISS parameter */
+ char txtail[4]; /* KISS parameter */
+ int fullduplex; /* KISS parameter */
+ int relay_digipeat; /* If 1: interface should RELAY digipeat */
+ int init_kiss; /* Initialize KISS-Mode on startup */
+#ifdef HAVE_DB
+ // to support connections to sql server databases for db_gis.c
+ char database_username[20]; /* Username to use to connect to database */
+ int database_type; /* Type of dbms (posgresql, mysql, etc) */
+ char database_schema[20]; /* Name of database or schema to use */
+ char database_errormessage[255]; /* Most recent error message from
+ attempting to make a
+ connection with using this descriptor. */
+ int database_schema_type; /* table structures to use in the database
+ A database schema could contain both
+ APRSWorld and XASTIR table structures,
+ but a separate database descriptor
+ needs to be defined for each. */
+ char database_unix_socket[255]; /* MySQL - unix socket parameter (path and
+ filename) */
+ // Need a pointer here, and one in connection pointing back here. How to do????
+ //Connection *database_connection;
+ /* Pointer to database connection that
+ contains database handle (with type
+ of handle being dependent on type of
+ database. */
+ int query_on_startup; /* Load stations from this database on
+ startup. */
+ // Use of other ioparam variables for sql server database connections:
+ // device_host_name = hostname for database server
+ // sp = port on which to connect to database server
+ // device_host_pswd = password to use to connect to database -- security issue needs to be addressed
+#endif // HAVE_DB
+} ioparam;
+
+
+extern iodevices dtype[];
+
+extern xastir_mutex port_data_lock; // Protects the port_data[] array of structs
+extern xastir_mutex devices_lock; // Protects the devices[] array
+
+extern iface port_data[];
+extern int port_id[];
+extern int get_device_status(int port);
+extern int del_device(int port);
+extern int get_open_device(void);
+extern int add_device(int port_avail,int dev_type,
+ char *dev_nm,
+ char *passwd,
+ int dev_sck_p, int dev_sp,
+ int dev_sty,
+ int reconnect,
+ char *filter_string);
+
+extern xastir_mutex data_lock; // Protects incoming_data_queue
+extern xastir_mutex output_data_lock; // Protects interface.c:channel_data() function only
+extern xastir_mutex connect_lock; // Protects port_data[].thread_status and port_data[].connect_status
+
+extern ioparam devices[];
+
+#if !HAVE_SOCKLEN_T
+typedef unsigned int socklen_t;
+#endif
+
+/* from interface_gui.c */
+extern void interface_gui_init(void);
+extern void Configure_interface_destroy_shell(Widget widget, XtPointer clientData, XtPointer callData);
+extern void Configure_interface(Widget w, XtPointer clientData, XtPointer callData);
+extern void output_my_aprs_data(void);
+extern void control_interface(Widget w, XtPointer clientData, XtPointer callData);
+extern void dtr_all_set(int dtr);
+extern void interface_status(Widget w);
+extern void update_interface_list(void);
+extern int WX_rain_gauge_type;
+
+/* interface.c */
+extern int is_local_interface(int port);
+extern int is_network_interface(int port);
+extern void send_agwpe_packet(int xastir_interface, int RadioPort, unsigned char type, unsigned char *FromCall, unsigned char *ToCall, unsigned char *Path, unsigned char *Data, int length);
+
+extern int pop_incoming_data(unsigned char *data_string, int *port);
+extern int push_incoming_data(unsigned char *data_string, int length, int port);
+
+extern unsigned char incoming_data_copy[MAX_LINE_SIZE];
+extern unsigned char incoming_data_copy_previous[MAX_LINE_SIZE];
+extern int NETWORK_WAITTIME;
+extern void startup_all_or_defined_port(int port);
+extern void shutdown_all_active_or_defined_port(int port);
+extern void check_ports(void);
+extern void clear_all_port_data(void);
+extern char aprs_station_message_type;
+extern void port_dtr(int port, int dtr);
+extern void send_kiss_config(int port, int device, int command, int value);
+void port_write_string(int port, char *data);
+extern void init_device_names(void);
+extern void output_my_data(char *message, int port, int type, int loopback_only, int use_igate_path, char *path);
+int tnc_get_data_type(char *buf, int port);
+void tnc_data_clean(char *buf);
+extern void output_waypoint_data(char *message);
+extern void send_ax25_frame(int port, char *source, char *destination, char *path, char *data);
+
+extern pid_t getpgid(pid_t pid);
+
+
+#endif /* XASTIR_INTERFACE_H */
+
diff --git a/src/interface_gui.c b/src/interface_gui.c
new file mode 100644
index 0000000..cbbd16f
--- /dev/null
+++ b/src/interface_gui.c
@@ -0,0 +1,9146 @@
+/*
+ * $Id: interface_gui.c,v 1.127 2012/10/22 23:59:55 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <termios.h>
+#include <Xm/XmAll.h>
+
+#include "xastir.h"
+#include "main.h"
+#include "xa_config.h"
+#include "interface.h"
+#include "wx.h"
+#include "draw_symbols.h"
+#include "util.h"
+#include "db_gis.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+extern XmFontList fontlist1; // Menu/System fontlist
+
+// lesstif (at least as of version 0.94 in 2008), doesn't
+// have full implementation of combo boxes.
+#ifndef USE_COMBO_BOX
+#if (XmVERSION >= 2 && !defined(LESSTIF_VERSION))
+# define USE_COMBO_BOX 1
+#endif
+#endif // USE_COMBO_BOX
+
+Widget configure_interface_dialog = NULL;
+Widget choose_interface_dialog = NULL;
+Widget interface_type_list = NULL;
+Widget control_interface_dialog = NULL;
+Widget control_iface_list = NULL;
+
+
+static xastir_mutex control_interface_dialog_lock;
+
+ioparam devices[MAX_IFACE_DEVICES];
+xastir_mutex devices_lock;
+
+void Choose_interface_destroy_shell(Widget widget, XtPointer clientData, XtPointer callData);
+void modify_device_list(int option, int port);
+
+
+
+
+
+void interface_gui_init(void)
+{
+ init_critical_section( &control_interface_dialog_lock );
+ init_critical_section( &devices_lock );
+}
+
+
+
+
+
+/*****************************************************/
+/* Universal Serial GUI */
+/*****************************************************/
+int device_speed;
+int device_style;
+int device_igate_options;
+int device_data_type;
+
+
+
+
+
+void speed_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+ if (state->set)
+ device_speed = atoi(which);
+ else
+ device_speed = 0;
+}
+
+
+
+
+
+void style_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ device_style = atoi(which);
+ else
+ device_style = 0;
+}
+
+
+
+
+
+void data_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ device_data_type = atoi(which);
+ else
+ device_data_type = 0;
+}
+
+
+
+
+
+void rain_gauge_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ WX_rain_gauge_type = atoi(which);
+ else
+ WX_rain_gauge_type = 0;
+}
+
+
+
+
+
+void igate_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ device_igate_options = atoi(which);
+ else
+ device_igate_options = 0;
+}
+
+
+
+
+
+void set_port_speed(int port) {
+
+ switch (device_speed){
+ case(1):
+ devices[port].sp=B300;
+ break;
+
+ case(2):
+ devices[port].sp=B1200;
+ break;
+
+ case(3):
+ devices[port].sp=B2400;
+ break;
+
+ case(4):
+ devices[port].sp=B4800;
+ break;
+
+ case(5):
+ devices[port].sp=B9600;
+ break;
+
+ case(6):
+ devices[port].sp=B19200;
+ break;
+
+ case(7):
+ devices[port].sp=B38400;
+ break;
+
+#ifndef __LSB__
+ case(8):
+ devices[port].sp=B57600;
+ break;
+
+ case(9):
+ devices[port].sp=B115200;
+ break;
+
+ case(10):
+#ifndef B230400
+ devices[port].sp=B115200;
+#else // B230400
+ devices[port].sp=B230400;
+#endif // B230400
+ break;
+#endif // __LSB__
+
+ default:
+ break;
+ }
+}
+
+
+
+
+
+
+
+/*****************************************************/
+/* Configure Serial TNC GUI */
+/*****************************************************/
+
+/**** TNC CONFIGURE ******/
+int TNC_port;
+int TNC_device;
+Widget config_TNC_dialog = (Widget)NULL;
+Widget TNC_active_on_startup;
+Widget TNC_transmit_data;
+Widget TNC_device_name_data;
+Widget TNC_radio_port_data; // Used only for Multi-Port TNC's
+Widget TNC_converse_string;
+Widget TNC_comment;
+Widget TNC_unproto1_data;
+Widget TNC_unproto2_data;
+Widget TNC_unproto3_data;
+Widget TNC_igate_data;
+Widget TNC_up_file_data;
+Widget TNC_down_file_data;
+Widget TNC_txdelay;
+Widget TNC_persistence;
+Widget TNC_slottime;
+Widget TNC_txtail;
+Widget TNC_init_kiss; // Used to initialize KISS-Mode
+Widget TNC_fullduplex;
+Widget TNC_extra_delay;
+Widget TNC_GPS_set_time;
+Widget TNC_AUX_GPS_Retrieve_Needed;
+Widget TNC_relay_digipeat;
+
+
+
+
+
+void Config_TNC_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ config_TNC_dialog = (Widget)NULL;
+ if (choose_interface_dialog != NULL)
+ Choose_interface_destroy_shell(choose_interface_dialog,choose_interface_dialog,NULL);
+ choose_interface_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Config_TNC_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ int type;
+ int was_up;
+ char *temp_ptr;
+
+
+ busy_cursor(appshell);
+
+ was_up=0;
+ if (get_device_status(TNC_port) == DEVICE_IN_USE) {
+ /* if active shutdown before changes are made */
+ /*fprintf(stderr,"Device is up, shutting down\n");*/
+
+//WE7U: Modify for MKISS?
+ (void)del_device(TNC_port);
+
+ was_up=1;
+ usleep(1000000); // Wait for one second
+ }
+
+ /* device type */
+ type=DEVICE_SERIAL_TNC; // Default in case not defined next
+ if (TNC_device)
+ type=TNC_device; // Modified to support more than two types
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_TNC_change_data" );
+
+ temp_ptr = XmTextFieldGetString(TNC_device_name_data);
+ xastir_snprintf(devices[TNC_port].device_name,
+ sizeof(devices[TNC_port].device_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[TNC_port].device_name);
+
+ temp_ptr = XmTextFieldGetString(TNC_converse_string);
+ xastir_snprintf(devices[TNC_port].device_converse_string,
+ sizeof(devices[TNC_port].device_converse_string),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[TNC_port].device_converse_string);
+
+ temp_ptr = XmTextFieldGetString(TNC_comment);
+ xastir_snprintf(devices[TNC_port].comment,
+ sizeof(devices[TNC_port].comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[TNC_port].comment);
+
+ if (devices[TNC_port].device_type == DEVICE_SERIAL_MKISS_TNC) {
+
+ // If MKISS, fetch "radio_port". If empty, store a zero.
+ temp_ptr = XmTextFieldGetString(TNC_radio_port_data);
+ xastir_snprintf(devices[TNC_port].radio_port,
+ sizeof(devices[TNC_port].radio_port),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[TNC_port].radio_port);
+
+ if (strcmp(devices[TNC_port].radio_port,"") == 0) {
+ xastir_snprintf(devices[TNC_port].radio_port,
+ sizeof(devices[TNC_port].radio_port),
+ "0");
+ }
+//fprintf(stderr,"Radio Port: %s\n",devices[TNC_port].radio_port);
+ }
+
+ if (XmToggleButtonGetState(TNC_active_on_startup))
+ devices[TNC_port].connect_on_startup=1;
+ else
+ devices[TNC_port].connect_on_startup=0;
+
+ if(XmToggleButtonGetState(TNC_transmit_data)) {
+ devices[TNC_port].transmit_data=1;
+ if ( (devices[TNC_port].device_type == DEVICE_SERIAL_KISS_TNC)
+ || (devices[TNC_port].device_type == DEVICE_SERIAL_MKISS_TNC) ) {
+
+#ifdef SERIAL_KISS_RELAY_DIGI
+ XtSetSensitive(TNC_relay_digipeat, TRUE);
+#else
+ XtSetSensitive(TNC_relay_digipeat, FALSE);
+#endif // SERIAL_KISS_RELAY_DIGI
+
+ }
+
+ }
+ else {
+ devices[TNC_port].transmit_data=0;
+ if ( (devices[TNC_port].device_type == DEVICE_SERIAL_KISS_TNC)
+ || (devices[TNC_port].device_type == DEVICE_SERIAL_MKISS_TNC) ) {
+ XtSetSensitive(TNC_relay_digipeat, FALSE);
+ }
+ }
+
+ if ( (type == DEVICE_SERIAL_KISS_TNC)
+ || (type == DEVICE_SERIAL_MKISS_TNC) ) {
+
+ if (XmToggleButtonGetState(TNC_relay_digipeat))
+ devices[TNC_port].relay_digipeat=1;
+ else
+ devices[TNC_port].relay_digipeat=0;
+ }
+
+ switch(type) {
+
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ if (XmToggleButtonGetState(TNC_extra_delay))
+ devices[TNC_port].tnc_extra_delay=1000000; // 1,000,000 us
+ else
+ devices[TNC_port].tnc_extra_delay=0;
+ break;
+ default:
+ break;
+ }
+
+ switch(type) {
+
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ if (XmToggleButtonGetState(TNC_GPS_set_time))
+ devices[TNC_port].set_time=1;
+ else
+ devices[TNC_port].set_time=0;
+
+ if (type == DEVICE_SERIAL_TNC_AUX_GPS) {
+ if (XmToggleButtonGetState(TNC_AUX_GPS_Retrieve_Needed))
+ devices[TNC_port].gps_retrieve=DEFAULT_GPS_RETR;
+ else
+ devices[TNC_port].gps_retrieve=0;
+ }
+
+ break;
+
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ default:
+ break;
+ }
+
+ set_port_speed(TNC_port);
+
+ devices[TNC_port].style=device_style;
+ devices[TNC_port].igate_options=device_igate_options;
+
+ temp_ptr = XmTextFieldGetString(TNC_unproto1_data);
+ xastir_snprintf(devices[TNC_port].unproto1,
+ sizeof(devices[TNC_port].unproto1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[TNC_port].unproto1);
+
+ if(check_unproto_path(devices[TNC_port].unproto1)) {
+ popup_message_always(langcode("WPUPCFT042"),
+ langcode("WPUPCFT043"));
+ }
+
+ temp_ptr = XmTextFieldGetString(TNC_unproto2_data);
+ xastir_snprintf(devices[TNC_port].unproto2,
+ sizeof(devices[TNC_port].unproto2),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[TNC_port].unproto2);
+
+ if(check_unproto_path(devices[TNC_port].unproto2)) {
+ popup_message_always(langcode("WPUPCFT042"),
+ langcode("WPUPCFT043"));
+ }
+
+ temp_ptr = XmTextFieldGetString(TNC_unproto3_data);
+ xastir_snprintf(devices[TNC_port].unproto3,
+ sizeof(devices[TNC_port].unproto3),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[TNC_port].unproto3);
+
+ if(check_unproto_path(devices[TNC_port].unproto3)) {
+ popup_message_always(langcode("WPUPCFT042"),
+ langcode("WPUPCFT043"));
+ }
+
+ temp_ptr = XmTextFieldGetString(TNC_igate_data);
+ xastir_snprintf(devices[TNC_port].unproto_igate,
+ sizeof(devices[TNC_port].unproto_igate),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[TNC_port].unproto_igate);
+
+ if(check_unproto_path(devices[TNC_port].unproto_igate)) {
+ popup_message_always(langcode("WPUPCFT044"),
+ langcode("WPUPCFT043"));
+ }
+
+
+ if ( (type == DEVICE_SERIAL_KISS_TNC)
+ || (type == DEVICE_SERIAL_MKISS_TNC) ) {
+
+ // KISS TNC, no up/down files for this one!
+ devices[TNC_port].tnc_up_file[0] = '\0';
+ devices[TNC_port].tnc_down_file[0] = '\0';
+
+ // Instead we have KISS parameters to set
+
+// We really should do some validation of these strings
+
+//WE7U: Modify for MKISS: Must send to the proper Radio Port.
+ temp_ptr = XmTextFieldGetString(TNC_txdelay);
+ xastir_snprintf(devices[TNC_port].txdelay,
+ sizeof(devices[TNC_port].txdelay),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ send_kiss_config(TNC_port,0,0x01,atoi(devices[TNC_port].txdelay));
+
+ temp_ptr = XmTextFieldGetString(TNC_persistence);
+ xastir_snprintf(devices[TNC_port].persistence,
+ sizeof(devices[TNC_port].persistence),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ send_kiss_config(TNC_port,0,0x02,atoi(devices[TNC_port].persistence));
+
+ temp_ptr = XmTextFieldGetString(TNC_slottime);
+ xastir_snprintf(devices[TNC_port].slottime,
+ sizeof(devices[TNC_port].slottime),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ send_kiss_config(TNC_port,0,0x03,atoi(devices[TNC_port].slottime));
+
+ temp_ptr = XmTextFieldGetString(TNC_txtail);
+ xastir_snprintf(devices[TNC_port].txtail,
+ sizeof(devices[TNC_port].txtail),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ send_kiss_config(TNC_port,0,0x04,atoi(devices[TNC_port].txtail));
+
+ if (XmToggleButtonGetState(TNC_fullduplex))
+ devices[TNC_port].fullduplex=1;
+ else
+ devices[TNC_port].fullduplex=0;
+ send_kiss_config(TNC_port,0,0x05,devices[TNC_port].fullduplex);
+
+ // For KISS-mode
+ if (XmToggleButtonGetState(TNC_init_kiss))
+ devices[TNC_port].init_kiss=1;
+ else
+ devices[TNC_port].init_kiss=0;
+ }
+ else {
+ temp_ptr = XmTextFieldGetString(TNC_up_file_data);
+ xastir_snprintf(devices[TNC_port].tnc_up_file,
+ sizeof(devices[TNC_port].tnc_up_file),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[TNC_port].tnc_up_file);
+
+ temp_ptr = XmTextFieldGetString(TNC_down_file_data);
+ xastir_snprintf(devices[TNC_port].tnc_down_file,
+ sizeof(devices[TNC_port].tnc_down_file),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[TNC_port].tnc_down_file);
+ }
+
+//WE7U: Modify for MKISS?
+ /* reopen port*/
+ if (was_up) {
+ (void)add_device(TNC_port,
+ type,
+ devices[TNC_port].device_name,
+ "",
+ -1,
+ devices[TNC_port].sp,
+ devices[TNC_port].style,
+ 0,
+ "");
+ }
+
+ /* delete list */
+// modify_device_list(4,0);
+
+
+ /* add device type */
+ devices[TNC_port].device_type=type;
+
+ /* rebuild list */
+// modify_device_list(3,0);
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_TNC_change_data" );
+
+ // Rebuild the interface control list
+ update_interface_list();
+
+ Config_TNC_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void Config_TNC( /*@unused@*/ Widget w, int device_type, int config_type, int port) {
+ static Widget pane, form, form2, button_ok, button_cancel,
+ frame, frame2, frame3, frame4,
+ setup, setup1, setup2, setup3, setup4,
+ device, converse, comment, speed, speed_box,
+ speed_300, speed_1200, speed_2400, speed_4800, speed_9600,
+ speed_19200, speed_38400;
+#ifndef __LSB__
+ static Widget speed_57600, speed_115200, speed_230400;
+#endif // __LSB__
+ static Widget style, style_box,
+ style_8n1, style_7e1, style_7o1,
+ igate, igate_box,
+ igate_o_0, igate_o_1, igate_o_2,
+ igate_label,
+ proto, proto1, proto2, proto3,
+ radio_port_label;
+ char temp[50];
+ Atom delw;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+ register char *tmp;
+
+ tmp=(char *)NULL;
+
+ if(!config_TNC_dialog) {
+ TNC_port=port;
+ TNC_device=device_type;
+/* config_TNC_dialog = XtVaCreatePopupShell(device_type ? langcode("WPUPCFT023"):langcode("WPUPCFT001"),
+ -- replaced by KB6MER with the lines below for adding AUX GPS type TNC
+*/
+ switch(device_type) {
+ case DEVICE_SERIAL_TNC:
+ tmp=langcode("WPUPCFT001");
+ break;
+
+ case DEVICE_SERIAL_KISS_TNC:
+ tmp=langcode("WPUPCFT030");
+ break;
+
+ case DEVICE_SERIAL_MKISS_TNC:
+ tmp=langcode("WPUPCFT040");
+ break;
+
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ tmp=langcode("WPUPCFT023");
+ break;
+
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ tmp=langcode("WPUPCFT028");
+ break;
+
+ default:
+ sprintf(tmp, langcode("WPUPCFT029"), (int)device_type);
+ break;
+ }
+
+ config_TNC_dialog = XtVaCreatePopupShell(
+ tmp,
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Config_TNC pane",xmPanedWindowWidgetClass, config_TNC_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Config_TNC form",xmFormWidgetClass, pane,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ TNC_active_on_startup = XtVaCreateManagedWidget(langcode("UNIOP00011"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_transmit_data = XtVaCreateManagedWidget(langcode("UNIOP00010"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, TNC_active_on_startup,
+ XmNleftOffset ,35,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ switch(device_type) {
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ TNC_extra_delay = XtVaCreateManagedWidget(langcode("UNIOP00038"), xmToggleButtonWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, TNC_transmit_data,
+ XmNleftOffset ,35,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ }
+
+ switch(device_type) {
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ TNC_GPS_set_time = XtVaCreateManagedWidget(langcode("UNIOP00029"), xmToggleButtonWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, TNC_extra_delay,
+ XmNleftOffset ,35,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+// We can only set the time properly on Linux systems
+#ifndef HAVE_SETTIMEOFDAY
+ XtSetSensitive(TNC_GPS_set_time,FALSE);
+#endif // HAVE_SETTIMEOFDAY
+#ifdef __CYGWIN__
+ XtSetSensitive(TNC_GPS_set_time,FALSE);
+#endif // __CYGWIN__
+
+ // Let the user turn off the Control-E thing
+ // that only SOME "tnc-with-gps" devices actually
+ // require, and that confuse the heck out of others.
+ // D700 is among the confused, by the way. TVR -- 14 Aug 2012
+ if (device_type == DEVICE_SERIAL_TNC_AUX_GPS) {
+ TNC_AUX_GPS_Retrieve_Needed = XtVaCreateManagedWidget(langcode("UNIOP00037"), xmToggleButtonWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, TNC_GPS_set_time,
+ XmNleftOffset ,35,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ }
+
+ break;
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ // Add a "RELAY Digipeat?" button for KISS/MKISS TNC's
+ TNC_relay_digipeat = XtVaCreateManagedWidget(langcode("UNIOP00030"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, TNC_transmit_data,
+ XmNleftOffset ,35,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+#ifdef SERIAL_KISS_RELAY_DIGI
+ XtSetSensitive(TNC_relay_digipeat, TRUE);
+#else
+ XtSetSensitive(TNC_relay_digipeat, FALSE);
+#endif // SERIAL_KISS_RELAY_DIGIPEAT
+
+ break;
+
+ case DEVICE_SERIAL_TNC:
+ default:
+ break;
+ }
+
+ device = XtVaCreateManagedWidget(langcode("WPUPCFT003"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, TNC_active_on_startup,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_device_name_data = XtVaCreateManagedWidget("Config_TNC device_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNwidth, ((15*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, TNC_active_on_startup,
+ XmNtopOffset, 2,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, device,
+ XmNleftOffset, 12,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+// converse = XtVaCreateManagedWidget(langcode("WPUPCFS017"),xmLabelWidgetClass, form,
+ converse = XtVaCreateManagedWidget("Converse CMD:",xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, TNC_active_on_startup,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, TNC_device_name_data,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_converse_string = XtVaCreateManagedWidget("Config_TNC comment", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNwidth, ((15*7)+2),
+ XmNmaxLength, 49,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, TNC_active_on_startup,
+ XmNtopOffset, 2,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, converse,
+ XmNleftOffset, 12,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ comment = XtVaCreateManagedWidget(langcode("WPUPCFS017"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, TNC_active_on_startup,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, TNC_converse_string,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_comment = XtVaCreateManagedWidget("Config_TNC comment", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNwidth, ((15*7)+2),
+ XmNmaxLength, 49,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, TNC_active_on_startup,
+ XmNtopOffset, 2,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, comment,
+ XmNleftOffset, 12,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ if (device_type == DEVICE_SERIAL_MKISS_TNC) {
+ // "Radio Port" field for Multi-Port KISS TNC's.
+
+ radio_port_label = XtVaCreateManagedWidget(langcode("WPUPCFT041"),
+ xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, TNC_active_on_startup,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, TNC_comment,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_radio_port_data = XtVaCreateManagedWidget("Config_TNC device_data",
+ xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 5,
+ XmNwidth, ((5*7)+2),
+ XmNmaxLength, 2,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, TNC_active_on_startup,
+ XmNtopOffset, 2,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, radio_port_label,
+ XmNleftOffset, 12,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ }
+
+ frame = XtVaCreateManagedWidget("Config_TNC frame", xmFrameWidgetClass, form,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopOffset, 10,
+ XmNtopWidget, device,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ speed = XtVaCreateManagedWidget(langcode("WPUPCFT004"),xmLabelWidgetClass, frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ /*set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNbackground, colors[0xff]); ac++;
+
+ speed_box = XmCreateRadioBox(frame,"Config_TNC Speed_box",al,ac);
+ XtVaSetValues(speed_box,XmNnumColumns,5,NULL);
+
+ speed_300 = XtVaCreateManagedWidget(langcode("WPUPCFT005"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(speed_300,XmNvalueChangedCallback,speed_toggle,"1");
+
+ speed_1200 = XtVaCreateManagedWidget(langcode("WPUPCFT006"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_1200,XmNvalueChangedCallback,speed_toggle,"2");
+
+
+ speed_2400 = XtVaCreateManagedWidget(langcode("WPUPCFT007"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_2400,XmNvalueChangedCallback,speed_toggle,"3");
+
+
+ speed_4800 = XtVaCreateManagedWidget(langcode("WPUPCFT008"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_4800,XmNvalueChangedCallback,speed_toggle,"4");
+
+ speed_9600 = XtVaCreateManagedWidget(langcode("WPUPCFT009"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_9600,XmNvalueChangedCallback,speed_toggle,"5");
+
+ speed_19200 = XtVaCreateManagedWidget(langcode("WPUPCFT010"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_19200,XmNvalueChangedCallback,speed_toggle,"6");
+
+ speed_38400 = XtVaCreateManagedWidget(langcode("WPUPCFT019"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_38400,XmNvalueChangedCallback,speed_toggle,"7");
+
+#ifndef __LSB__
+ speed_57600 = XtVaCreateManagedWidget(langcode("WPUPCFT020"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_57600,XmNvalueChangedCallback,speed_toggle,"8");
+
+ speed_115200 = XtVaCreateManagedWidget(langcode("WPUPCFT021"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_115200,XmNvalueChangedCallback,speed_toggle,"9");
+
+ speed_230400 = XtVaCreateManagedWidget(langcode("WPUPCFT022"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_230400,XmNvalueChangedCallback,speed_toggle,"10");
+#endif // __LSB__
+
+ switch(device_type) {
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ break;
+ default:
+ frame2 = XtVaCreateManagedWidget("Config_TNC frame2", xmFrameWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ style = XtVaCreateManagedWidget(langcode("WPUPCFT015"),xmLabelWidgetClass, frame2,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ style_box = XmCreateRadioBox(frame2,"Config_TNC Style box",al,ac);
+
+ XtVaSetValues(style_box,XmNorientation, XmHORIZONTAL,NULL);
+
+ style_8n1 = XtVaCreateManagedWidget(langcode("WPUPCFT016"),xmToggleButtonGadgetClass,
+ style_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(style_8n1,XmNvalueChangedCallback,style_toggle,"0");
+
+ style_7e1 = XtVaCreateManagedWidget(langcode("WPUPCFT017"),xmToggleButtonGadgetClass,
+ style_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(style_7e1,XmNvalueChangedCallback,style_toggle,"1");
+
+ style_7o1 = XtVaCreateManagedWidget(langcode("WPUPCFT018"),xmToggleButtonGadgetClass,
+ style_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(style_7o1,XmNvalueChangedCallback,style_toggle,"2");
+ break;
+ }
+
+ frame4 = XtVaCreateManagedWidget("Config_TNC frame4", xmFrameWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+XmNtopWidget, (device_type == DEVICE_SERIAL_KISS_TNC || device_type == DEVICE_SERIAL_MKISS_TNC) ? frame : frame2,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ igate = XtVaCreateManagedWidget(langcode("IGPUPCF000"),xmLabelWidgetClass, frame4,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ igate_box = XmCreateRadioBox(frame4,"Config_TNC IGate box",al,ac);
+
+ XtVaSetValues(igate_box,XmNorientation, XmVERTICAL,XmNnumColumns,2,NULL);
+
+ igate_o_0 = XtVaCreateManagedWidget(langcode("IGPUPCF001"),xmToggleButtonGadgetClass,
+ igate_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(igate_o_0,XmNvalueChangedCallback,igate_toggle,"0");
+
+ igate_o_1 = XtVaCreateManagedWidget(langcode("IGPUPCF002"),xmToggleButtonGadgetClass,
+ igate_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(igate_o_1,XmNvalueChangedCallback,igate_toggle,"1");
+
+ igate_o_2 = XtVaCreateManagedWidget(langcode("IGPUPCF003"),xmToggleButtonGadgetClass,
+ igate_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(igate_o_2,XmNvalueChangedCallback,igate_toggle,"2");
+
+ proto = XtVaCreateManagedWidget(langcode("WPUPCFT011"), xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, frame4,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPCFT012"), VERSIONFRM);
+
+ proto1 = XtVaCreateManagedWidget(temp, xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto,
+ XmNtopOffset, 12,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 15,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_unproto1_data = XtVaCreateManagedWidget("Config_TNC protopath1", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, proto1,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPCFT013"), VERSIONFRM);
+
+ proto2 = XtVaCreateManagedWidget(temp, xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto,
+ XmNtopOffset, 12,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, TNC_unproto1_data,
+ XmNleftOffset, 15,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_unproto2_data = XtVaCreateManagedWidget("Config_TNC protopath2", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, proto2,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 15,
+ XmNfontList, fontlist1,
+ NULL);
+
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPCFT014"), VERSIONFRM);
+
+ proto3 = XtVaCreateManagedWidget(temp, xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto1,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 15,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_unproto3_data = XtVaCreateManagedWidget("Config_TNC protopath3", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, TNC_unproto1_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, proto3,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("IGPUPCF004"));
+ igate_label = XtVaCreateManagedWidget(temp, xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto2,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, TNC_unproto3_data,
+ XmNleftOffset, 15,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_igate_data = XtVaCreateManagedWidget("Config_TNC igate_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, TNC_unproto2_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, igate_label,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+// Draw a different frame3 for Serial KISS/MKISS TNC interfaces
+ switch(device_type) {
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ frame3 = XtVaCreateManagedWidget("Config_TNC frame3", xmFrameWidgetClass, form,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopOffset,10,
+ XmNtopWidget, TNC_igate_data,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ // KISS Parameters
+ setup = XtVaCreateManagedWidget(langcode("WPUPCFT034"),xmLabelWidgetClass, frame3,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ form2 = XtVaCreateWidget("Config_TNC form2",xmFormWidgetClass, frame3,
+ XmNfractionBase, 6,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ // TXDelay (10 ms units)
+ setup1 = XtVaCreateManagedWidget(langcode("WPUPCFT035"), xmLabelWidgetClass, form2,
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_txdelay = XtVaCreateManagedWidget("Config_TNC TNC_txdelay", xmTextFieldWidgetClass, form2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 3,
+ XmNwidth, ((6*7)+2),
+ XmNmaxLength, 3,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Persistence (0 to 255)
+ setup2 = XtVaCreateManagedWidget(langcode("WPUPCFT036"), xmLabelWidgetClass, form2,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, setup1,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_persistence = XtVaCreateManagedWidget("Config_TNC persistence", xmTextFieldWidgetClass, form2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 3,
+ XmNwidth, ((6*7)+2),
+ XmNmaxLength, 3,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, setup1,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // SlotTime (10 ms units)
+ setup3 = XtVaCreateManagedWidget(langcode("WPUPCFT037"), xmLabelWidgetClass, form2,
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_slottime = XtVaCreateManagedWidget("Config_TNC slottime", xmTextFieldWidgetClass, form2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 3,
+ XmNwidth, ((6*7)+2),
+ XmNmaxLength, 3,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_POSITION,
+ XmNleftPosition, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // TxTail (10 ms units)
+ setup4 = XtVaCreateManagedWidget(langcode("WPUPCFT038"), xmLabelWidgetClass, form2,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, setup3,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_txtail = XtVaCreateManagedWidget("Config_TNC TxTail", xmTextFieldWidgetClass, form2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 3,
+ XmNwidth, ((6*7)+2),
+ XmNmaxLength, 3,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, setup3,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_POSITION,
+ XmNleftPosition, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Full Duplex
+ TNC_fullduplex = XtVaCreateManagedWidget(langcode("WPUPCFT039"),xmToggleButtonWidgetClass,form2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, setup4,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Button to enable KISS-mode at startup
+ TNC_init_kiss = XtVaCreateManagedWidget(langcode("WPUPCFT047"),xmToggleButtonWidgetClass,form2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, setup4,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 135,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ break;
+ default:
+ frame3 = XtVaCreateManagedWidget("Config_TNC frame3", xmFrameWidgetClass, form,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopOffset,10,
+ XmNtopWidget, TNC_igate_data,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ setup = XtVaCreateManagedWidget(langcode("WPUPCFT031"),xmLabelWidgetClass, frame3,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ form2 = XtVaCreateWidget("Config_TNC form2",xmFormWidgetClass, frame3,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ setup1 = XtVaCreateManagedWidget(langcode("WPUPCFT032"), xmLabelWidgetClass, form2,
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_up_file_data = XtVaCreateManagedWidget("Config_TNC up_file", xmTextFieldWidgetClass, form2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 80,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ setup2 = XtVaCreateManagedWidget(langcode("WPUPCFT033"), xmLabelWidgetClass, form2,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, setup1,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ TNC_down_file_data = XtVaCreateManagedWidget("Config_TNC down_file", xmTextFieldWidgetClass, form2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 80,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, setup1,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ break;
+ }
+
+
+//------------------------------------------------------------
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame3,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame3,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Config_TNC_change_data, config_TNC_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Config_TNC_destroy_shell, config_TNC_dialog);
+
+ pos_dialog(config_TNC_dialog);
+
+ delw = XmInternAtom(XtDisplay(config_TNC_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(config_TNC_dialog, delw, Config_TNC_destroy_shell, (XtPointer)config_TNC_dialog);
+
+ if (config_type==0) {
+ /* first time port */
+ devices[TNC_port].gps_retrieve=DEFAULT_GPS_RETR;
+ if (debug_level & 128) {
+ fprintf(stderr,"Storing %d to gps_retrieve for %d\n",
+ DEFAULT_GPS_RETR, port);
+ }
+
+ XmTextFieldSetString(TNC_device_name_data,TNC_PORT);
+
+ XmTextFieldSetString(TNC_converse_string,"k");
+
+ XmTextFieldSetString(TNC_comment,"");
+
+ if (device_type == DEVICE_SERIAL_MKISS_TNC) {
+ XmTextFieldSetString(TNC_radio_port_data,"0");
+//fprintf(stderr,"Assigning default '0' to radio port\n");
+ }
+
+ XmToggleButtonSetState(TNC_active_on_startup,TRUE,FALSE);
+ XmToggleButtonSetState(TNC_transmit_data,TRUE,FALSE);
+
+ switch(device_type) {
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ XmToggleButtonSetState(TNC_extra_delay, FALSE, FALSE);
+ break;
+ default:
+ break;
+ }
+
+ switch(device_type) {
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ XmToggleButtonSetState(TNC_GPS_set_time, FALSE, FALSE);
+ if (device_type == DEVICE_SERIAL_TNC_AUX_GPS)
+ XmToggleButtonSetState(TNC_AUX_GPS_Retrieve_Needed,
+ TRUE, FALSE);
+ break;
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ XmToggleButtonSetState(TNC_relay_digipeat, FALSE, FALSE);
+ XmToggleButtonSetState(TNC_fullduplex, FALSE, FALSE);
+ XmToggleButtonSetState(TNC_init_kiss, FALSE, FALSE); // For KISS-Mode
+ break;
+ case DEVICE_SERIAL_TNC:
+ default:
+ break;
+ }
+
+ XmToggleButtonSetState(speed_4800,TRUE,FALSE);
+ device_speed=4;
+
+ if ( (device_type != DEVICE_SERIAL_KISS_TNC)
+ && (device_type != DEVICE_SERIAL_MKISS_TNC) ) {
+ XmToggleButtonSetState(style_8n1,TRUE,FALSE);
+ }
+
+ device_style=0;
+
+ device_igate_options=0;
+ XmToggleButtonSetState(igate_o_0,TRUE,FALSE);
+ XmTextFieldSetString(TNC_unproto1_data,"WIDE2-2");
+ XmTextFieldSetString(TNC_unproto2_data,"");
+ XmTextFieldSetString(TNC_unproto3_data,"");
+ XmTextFieldSetString(TNC_igate_data,"");
+
+//WE7U
+ if ( (device_type == DEVICE_SERIAL_KISS_TNC)
+ || (device_type == DEVICE_SERIAL_MKISS_TNC) ) {
+ // We don't allow changing the selection for KISS
+ // TNC's, as they require 8N1
+ device_style = 0;
+ XmTextFieldSetString(TNC_txdelay,"40");
+ XmTextFieldSetString(TNC_persistence,"63");
+ XmTextFieldSetString(TNC_slottime,"20");
+ XmTextFieldSetString(TNC_txtail,"30");
+ }
+ else {
+ XmTextFieldSetString(TNC_up_file_data,"tnc-startup.sys");
+ XmTextFieldSetString(TNC_down_file_data,"tnc-stop.sys");
+ }
+
+ } else {
+ /* reconfig */
+
+ if (debug_level & 128)
+ fprintf(stderr,"Reconfiguring interface\n");
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_TNC" );
+
+ XmTextFieldSetString(TNC_device_name_data,devices[TNC_port].device_name);
+
+ XmTextFieldSetString(TNC_converse_string,devices[TNC_port].device_converse_string);
+
+ XmTextFieldSetString(TNC_comment,devices[TNC_port].comment);
+
+ if (device_type == DEVICE_SERIAL_MKISS_TNC) {
+ XmTextFieldSetString(TNC_radio_port_data, devices[TNC_port].radio_port);
+//fprintf(stderr,"Reconfig: %s\n", devices[TNC_port].radio_port);
+ }
+
+ if (devices[TNC_port].connect_on_startup)
+ XmToggleButtonSetState(TNC_active_on_startup,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(TNC_active_on_startup,FALSE,FALSE);
+
+ if (devices[TNC_port].transmit_data)
+ XmToggleButtonSetState(TNC_transmit_data,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(TNC_transmit_data,FALSE,FALSE);
+
+ switch(device_type) {
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ if (devices[TNC_port].tnc_extra_delay)
+ XmToggleButtonSetState(TNC_extra_delay, TRUE, FALSE);
+ else
+ XmToggleButtonSetState(TNC_extra_delay, FALSE, FALSE);
+ break;
+ default:
+ break;
+ }
+
+ switch(device_type) {
+
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ if (devices[TNC_port].set_time)
+ XmToggleButtonSetState(TNC_GPS_set_time, TRUE, FALSE);
+ else
+ XmToggleButtonSetState(TNC_GPS_set_time, FALSE, FALSE);
+
+ if (device_type == DEVICE_SERIAL_TNC_AUX_GPS) {
+ if (devices[TNC_port].gps_retrieve != 0)
+ XmToggleButtonSetState(TNC_AUX_GPS_Retrieve_Needed,
+ TRUE, FALSE);
+ else
+ XmToggleButtonSetState(TNC_AUX_GPS_Retrieve_Needed,
+ FALSE, FALSE);
+ }
+
+ break;
+
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+
+ if (devices[TNC_port].relay_digipeat)
+ XmToggleButtonSetState(TNC_relay_digipeat, TRUE, FALSE);
+ else
+ XmToggleButtonSetState(TNC_relay_digipeat, FALSE, FALSE);
+
+ if (devices[TNC_port].fullduplex)
+ XmToggleButtonSetState(TNC_fullduplex, TRUE, FALSE);
+ else
+ XmToggleButtonSetState(TNC_fullduplex, FALSE, FALSE);
+
+ // For KISS-Mode
+ if (devices[TNC_port].init_kiss)
+ XmToggleButtonSetState(TNC_init_kiss, TRUE, FALSE);
+ else
+ XmToggleButtonSetState(TNC_init_kiss, FALSE, FALSE);
+
+ if (devices[TNC_port].transmit_data) {
+
+#ifdef SERIAL_KISS_RELAY_DIGI
+ XtSetSensitive(TNC_relay_digipeat, TRUE);
+#else
+ XtSetSensitive(TNC_relay_digipeat, FALSE);
+#endif // SERIAL_KISS_RELAY_DIGI
+
+ }
+ else
+ XtSetSensitive(TNC_relay_digipeat, FALSE);
+ break;
+
+ case DEVICE_SERIAL_TNC:
+ default:
+ break;
+ }
+
+ switch (devices[TNC_port].sp) {
+ case(B300):
+ XmToggleButtonSetState(speed_300,TRUE,FALSE);
+ device_speed=1;
+ break;
+
+ case(B1200):
+ XmToggleButtonSetState(speed_1200,TRUE,FALSE);
+ device_speed=2;
+ break;
+
+ case(B2400):
+ XmToggleButtonSetState(speed_2400,TRUE,FALSE);
+ device_speed=3;
+ break;
+
+ case(B4800):
+ XmToggleButtonSetState(speed_4800,TRUE,FALSE);
+ device_speed=4;
+ break;
+
+ case(B9600):
+ XmToggleButtonSetState(speed_9600,TRUE,FALSE);
+ device_speed=5;
+ break;
+
+ case(B19200):
+ XmToggleButtonSetState(speed_19200,TRUE,FALSE);
+ device_speed=6;
+ break;
+
+ case(B38400):
+ XmToggleButtonSetState(speed_38400,TRUE,FALSE);
+ device_speed=7;
+ break;
+
+#ifndef __LSB__
+ case(B57600):
+ XmToggleButtonSetState(speed_57600,TRUE,FALSE);
+ device_speed=8;
+ break;
+
+ case(B115200):
+ XmToggleButtonSetState(speed_115200,TRUE,FALSE);
+ device_speed=9;
+ break;
+
+#ifdef B230400
+ case(B230400):
+ XmToggleButtonSetState(speed_230400,TRUE,FALSE);
+ device_speed=10;
+ break;
+#endif // B230400
+#endif // __LSB__
+
+ default:
+ XmToggleButtonSetState(speed_4800,TRUE,FALSE);
+ device_speed=4;
+ break;
+ }
+
+ if ( (device_type == DEVICE_SERIAL_KISS_TNC)
+ || (device_type == DEVICE_SERIAL_MKISS_TNC) ) {
+ // We don't allow changing the selection for KISS
+ // TNC's, as they require 8N1
+ device_style = 0;
+ }
+ else {
+ switch (devices[TNC_port].style) {
+ case(0):
+ XmToggleButtonSetState(style_8n1,TRUE,FALSE);
+ device_style=0;
+ break;
+
+ case(1):
+ XmToggleButtonSetState(style_7e1,TRUE,FALSE);
+ device_style=1;
+ break;
+
+ case(2):
+ XmToggleButtonSetState(style_7o1,TRUE,FALSE);
+ device_style=2;
+ break;
+
+ default:
+ XmToggleButtonSetState(style_8n1,TRUE,FALSE);
+ device_style=0;
+ break;
+ }
+ }
+
+ switch (devices[TNC_port].igate_options) {
+ case(0):
+ XmToggleButtonSetState(igate_o_0,TRUE,FALSE);
+ device_igate_options=0;
+ break;
+
+ case(1):
+ XmToggleButtonSetState(igate_o_1,TRUE,FALSE);
+ device_igate_options=1;
+ break;
+
+ case(2):
+ XmToggleButtonSetState(igate_o_2,TRUE,FALSE);
+ device_igate_options=2;
+ break;
+
+ default:
+ XmToggleButtonSetState(igate_o_0,TRUE,FALSE);
+ device_igate_options=0;
+ break;
+ }
+ XmTextFieldSetString(TNC_unproto1_data,devices[TNC_port].unproto1);
+ XmTextFieldSetString(TNC_unproto2_data,devices[TNC_port].unproto2);
+ XmTextFieldSetString(TNC_unproto3_data,devices[TNC_port].unproto3);
+ XmTextFieldSetString(TNC_igate_data,devices[TNC_port].unproto_igate);
+
+ if ( (device_type == DEVICE_SERIAL_KISS_TNC)
+ || (device_type == DEVICE_SERIAL_MKISS_TNC) ) {
+ XmTextFieldSetString(TNC_txdelay,devices[TNC_port].txdelay);
+ XmTextFieldSetString(TNC_persistence,devices[TNC_port].persistence);
+ XmTextFieldSetString(TNC_slottime,devices[TNC_port].slottime);
+ XmTextFieldSetString(TNC_txtail,devices[TNC_port].txtail);
+ }
+ else {
+ XmTextFieldSetString(TNC_up_file_data,devices[TNC_port].tnc_up_file);
+ XmTextFieldSetString(TNC_down_file_data,devices[TNC_port].tnc_down_file);
+ }
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_TNC" );
+
+ }
+
+ XtManageChild(form);
+
+ XtManageChild(form2);
+
+ XtManageChild(speed_box);
+
+ if ( (device_type != DEVICE_SERIAL_KISS_TNC)
+ && (device_type != DEVICE_SERIAL_MKISS_TNC) ) {
+ XtManageChild(style_box);
+ }
+
+ XtManageChild(igate_box);
+ XtManageChild(pane);
+
+ XtPopup(config_TNC_dialog,XtGrabNone);
+ fix_dialog_size(config_TNC_dialog);
+ }
+ else {
+ (void)XRaiseWindow(XtDisplay(config_TNC_dialog), XtWindow(config_TNC_dialog));
+ }
+}
+
+
+
+
+
+/*****************************************************/
+/* Configure Serial GPS GUI */
+/*****************************************************/
+
+/**** GPS CONFIGURE ******/
+int GPS_port;
+Widget config_GPS_dialog = (Widget)NULL;
+Widget GPS_device_name_data;
+Widget GPS_comment;
+Widget GPS_active_on_startup;
+Widget GPS_set_time;
+
+
+
+
+
+void Config_GPS_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ config_GPS_dialog = (Widget)NULL;
+ if (choose_interface_dialog != NULL)
+ Choose_interface_destroy_shell(choose_interface_dialog,choose_interface_dialog,NULL);
+ choose_interface_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Config_GPS_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ int was_up;
+ char *temp_ptr;
+
+
+ busy_cursor(appshell);
+ was_up=0;
+ if (get_device_status(GPS_port) == DEVICE_IN_USE) {
+ /* if active shutdown before changes are made */
+ /*fprintf(stderr,"Device is up, shutting down\n");*/
+ (void)del_device(GPS_port);
+ was_up=1;
+ usleep(1000000); // Wait for one second
+ }
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_GPS_change_data" );
+
+ temp_ptr = XmTextFieldGetString(GPS_device_name_data);
+ xastir_snprintf(devices[GPS_port].device_name,
+ sizeof(devices[GPS_port].device_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[GPS_port].device_name);
+
+ temp_ptr = XmTextFieldGetString(GPS_comment);
+ xastir_snprintf(devices[GPS_port].comment,
+ sizeof(devices[GPS_port].comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[GPS_port].comment);
+
+ if(XmToggleButtonGetState(GPS_active_on_startup))
+ devices[GPS_port].connect_on_startup=1;
+ else
+ devices[GPS_port].connect_on_startup=0;
+
+ if (XmToggleButtonGetState(GPS_set_time))
+ devices[GPS_port].set_time=1;
+ else
+ devices[GPS_port].set_time=0;
+
+ set_port_speed(GPS_port);
+ devices[GPS_port].style=device_style;
+ /* reopen */
+ if ( was_up ) {
+ (void)add_device(GPS_port,
+ DEVICE_SERIAL_GPS,
+ devices[GPS_port].device_name,
+ "",
+ -1,
+ devices[GPS_port].sp,
+ devices[GPS_port].style,
+ 0,
+ "");
+ }
+
+ /* delete list */
+// modify_device_list(4,0);
+
+
+ /* add device type */
+ devices[GPS_port].device_type=DEVICE_SERIAL_GPS;
+
+ /* rebuild list */
+// modify_device_list(3,0);
+
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_GPS_change_data" );
+
+ // Rebuild the interface control list
+ update_interface_list();
+
+ Config_GPS_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void Config_GPS( /*@unused@*/ Widget w, int config_type, int port) {
+ static Widget pane, form, button_ok, button_cancel,
+ frame, frame2,
+ device, comment, speed, speed_box,
+ speed_300, speed_1200, speed_2400, speed_4800, speed_9600,
+ speed_19200, speed_38400;
+#ifndef __LSB__
+ static Widget speed_57600, speed_115200, speed_230400;
+#endif // __LSB__
+ static Widget style, style_box,
+ style_8n1, style_7e1, style_7o1,
+ sep;
+ Atom delw;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+
+ if(!config_GPS_dialog) {
+ GPS_port=port;
+ config_GPS_dialog = XtVaCreatePopupShell(langcode("WPUPCFG001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Config_GPS pane",xmPanedWindowWidgetClass, config_GPS_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Config_GPS form",xmFormWidgetClass, pane,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ device = XtVaCreateManagedWidget(langcode("WPUPCFG003"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ GPS_device_name_data = XtVaCreateManagedWidget("Config_GPS device_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, device,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ comment = XtVaCreateManagedWidget(langcode("WPUPCFS017"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, device,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 15,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ GPS_comment = XtVaCreateManagedWidget("Config_GPS comment", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 49,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, device,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, comment,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ GPS_active_on_startup = XtVaCreateManagedWidget(langcode("UNIOP00011"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, comment,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ GPS_set_time = XtVaCreateManagedWidget(langcode("UNIOP00029"), xmToggleButtonWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, GPS_active_on_startup,
+ XmNtopOffset, 7,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+// We can only set the time properly on Linux systems
+#ifndef HAVE_SETTIMEOFDAY
+ XtSetSensitive(GPS_set_time,FALSE);
+#endif // HAVE_SETTIMEOFDAY
+#ifdef __CYGWIN__
+ XtSetSensitive(GPS_set_time,FALSE);
+#endif // __CYGWIN__
+
+
+
+ frame = XtVaCreateManagedWidget("Config_GPS frame", xmFrameWidgetClass, form,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopOffset,10,
+ XmNtopWidget, GPS_set_time,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ speed = XtVaCreateManagedWidget(langcode("WPUPCFT004"),xmLabelWidgetClass, frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ /*set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNbackground, colors[0xff]); ac++;
+
+
+ speed_box = XmCreateRadioBox(frame,"Config_GPS Speed_box",al,ac);
+
+ XtVaSetValues(speed_box,XmNnumColumns,3,NULL);
+
+ speed_300 = XtVaCreateManagedWidget(langcode("WPUPCFT005"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_300,XmNvalueChangedCallback,speed_toggle,"1");
+
+ speed_1200 = XtVaCreateManagedWidget(langcode("WPUPCFT006"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_1200,XmNvalueChangedCallback,speed_toggle,"2");
+
+ speed_2400 = XtVaCreateManagedWidget(langcode("WPUPCFT007"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_2400,XmNvalueChangedCallback,speed_toggle,"3");
+
+ speed_4800 = XtVaCreateManagedWidget(langcode("WPUPCFT008"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_4800,XmNvalueChangedCallback,speed_toggle,"4");
+
+ speed_9600 = XtVaCreateManagedWidget(langcode("WPUPCFT009"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_9600,XmNvalueChangedCallback,speed_toggle,"5");
+
+ speed_19200 = XtVaCreateManagedWidget(langcode("WPUPCFT010"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_19200,XmNvalueChangedCallback,speed_toggle,"6");
+
+ speed_38400 = XtVaCreateManagedWidget(langcode("WPUPCFT019"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_38400,XmNvalueChangedCallback,speed_toggle,"7");
+
+#ifndef __LSB__
+ speed_57600 = XtVaCreateManagedWidget(langcode("WPUPCFT020"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_57600,XmNvalueChangedCallback,speed_toggle,"8");
+
+ speed_115200 = XtVaCreateManagedWidget(langcode("WPUPCFT021"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_115200,XmNvalueChangedCallback,speed_toggle,"9");
+
+ speed_230400 = XtVaCreateManagedWidget(langcode("WPUPCFT022"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_230400,XmNvalueChangedCallback,speed_toggle,"10");
+#endif // __LSB__
+
+ frame2 = XtVaCreateManagedWidget("Config_GPS frame2", xmFrameWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ style = XtVaCreateManagedWidget(langcode("WPUPCFT015"),xmLabelWidgetClass, frame2,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ style_box = XmCreateRadioBox(frame2,"Config_GPS Style box",al,ac);
+
+ XtVaSetValues(style_box,
+ XmNorientation, XmHORIZONTAL,
+ NULL);
+
+ style_8n1 = XtVaCreateManagedWidget(langcode("WPUPCFT016"),xmToggleButtonGadgetClass,
+ style_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(style_8n1,XmNvalueChangedCallback,style_toggle,"0");
+
+ style_7e1 = XtVaCreateManagedWidget(langcode("WPUPCFT017"),xmToggleButtonGadgetClass,
+ style_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(style_7e1,XmNvalueChangedCallback,style_toggle,"1");
+
+ style_7o1 = XtVaCreateManagedWidget(langcode("WPUPCFT018"),xmToggleButtonGadgetClass,
+ style_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(style_7o1,XmNvalueChangedCallback,style_toggle,"2");
+
+ sep = XtVaCreateManagedWidget("Config_GPS sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, frame2,
+ XmNtopOffset, 20,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Config_GPS_change_data, config_GPS_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Config_GPS_destroy_shell, config_GPS_dialog);
+
+ pos_dialog(config_GPS_dialog);
+
+ delw = XmInternAtom(XtDisplay(config_GPS_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(config_GPS_dialog, delw, Config_GPS_destroy_shell, (XtPointer)config_GPS_dialog);
+
+ if (config_type==0) {
+ /* first time port */
+ XmTextFieldSetString(GPS_device_name_data,GPS_PORT);
+ XmTextFieldSetString(GPS_comment,"");
+ XmToggleButtonSetState(GPS_active_on_startup,TRUE,FALSE);
+ XmToggleButtonSetState(GPS_set_time, FALSE, FALSE);
+ XmToggleButtonSetState(speed_4800,TRUE,FALSE);
+ device_speed=4;
+ XmToggleButtonSetState(style_8n1,TRUE,FALSE);
+ device_style=0;
+ } else {
+ /* reconfig */
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_GPS" );
+
+ XmTextFieldSetString(GPS_device_name_data,devices[GPS_port].device_name);
+ XmTextFieldSetString(GPS_comment,devices[GPS_port].comment);
+
+ if (devices[GPS_port].connect_on_startup)
+ XmToggleButtonSetState(GPS_active_on_startup,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(GPS_active_on_startup,FALSE,FALSE);
+
+ if (devices[GPS_port].set_time)
+ XmToggleButtonSetState(GPS_set_time,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(GPS_set_time,FALSE,FALSE);
+
+ switch (devices[GPS_port].sp) {
+ case(B300):
+ XmToggleButtonSetState(speed_300,TRUE,FALSE);
+ device_speed=1;
+ break;
+
+ case(B1200):
+ XmToggleButtonSetState(speed_1200,TRUE,FALSE);
+ device_speed=2;
+ break;
+
+ case(B2400):
+ XmToggleButtonSetState(speed_2400,TRUE,FALSE);
+ device_speed=3;
+ break;
+
+ case(B4800):
+ XmToggleButtonSetState(speed_4800,TRUE,FALSE);
+ device_speed=4;
+ break;
+
+ case(B9600):
+ XmToggleButtonSetState(speed_9600,TRUE,FALSE);
+ device_speed=5;
+ break;
+
+ case(B19200):
+ XmToggleButtonSetState(speed_19200,TRUE,FALSE);
+ device_speed=6;
+ break;
+
+ case(B38400):
+ XmToggleButtonSetState(speed_38400,TRUE,FALSE);
+ device_speed=7;
+ break;
+
+#ifndef __LSB__
+ case(B57600):
+ XmToggleButtonSetState(speed_57600,TRUE,FALSE);
+ device_speed=8;
+ break;
+
+ case(B115200):
+ XmToggleButtonSetState(speed_115200,TRUE,FALSE);
+ device_speed=9;
+ break;
+
+#ifdef B230400
+ case(B230400):
+ XmToggleButtonSetState(speed_230400,TRUE,FALSE);
+ device_speed=10;
+ break;
+#endif // B230400
+#endif // __LSB__
+
+ default:
+ XmToggleButtonSetState(speed_4800,TRUE,FALSE);
+ device_speed=4;
+ break;
+ }
+ switch (devices[GPS_port].style) {
+ case(0):
+ XmToggleButtonSetState(style_8n1,TRUE,FALSE);
+ device_style=0;
+ break;
+
+ case(1):
+ XmToggleButtonSetState(style_7e1,TRUE,FALSE);
+ device_style=1;
+ break;
+
+ case(2):
+ XmToggleButtonSetState(style_7o1,TRUE,FALSE);
+ device_style=2;
+ break;
+
+ default:
+ XmToggleButtonSetState(style_8n1,TRUE,FALSE);
+ device_style=0;
+ break;
+ }
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_GPS" );
+
+ }
+ XtManageChild(form);
+ XtManageChild(speed_box);
+ XtManageChild(style_box);
+ XtManageChild(pane);
+
+ XtPopup(config_GPS_dialog,XtGrabNone);
+ fix_dialog_size(config_GPS_dialog);
+ } else
+ (void)XRaiseWindow(XtDisplay(config_GPS_dialog), XtWindow(config_GPS_dialog));
+}
+
+
+
+
+
+/*****************************************************/
+/* Configure Serial WX GUI */
+/*****************************************************/
+
+/**** WX CONFIGURE ******/
+int WX_port;
+int WX_rain_gauge_type;
+Widget config_WX_dialog = (Widget)NULL;
+Widget WX_transmit_data;
+Widget WX_device_name_data;
+Widget WX_comment;
+Widget WX_active_on_startup;
+Widget WX_tenths, WX_hundredths, WX_millimeters;
+
+
+
+
+
+void Config_WX_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ config_WX_dialog = (Widget)NULL;
+ if (choose_interface_dialog != NULL)
+ Choose_interface_destroy_shell(choose_interface_dialog,choose_interface_dialog,NULL);
+
+ choose_interface_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Config_WX_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ int was_up;
+ char *temp_ptr;
+
+
+ busy_cursor(appshell);
+ was_up=0;
+ if (get_device_status(WX_port) == DEVICE_IN_USE) {
+ /* if active shutdown before changes are made */
+ /*fprintf(stderr,"Device is up, shutting down\n");*/
+ (void)del_device(WX_port);
+ was_up=1;
+ usleep(1000000); // Wait for one second
+ }
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_WX_change_data" );
+
+ temp_ptr = XmTextFieldGetString(WX_device_name_data);
+ xastir_snprintf(devices[WX_port].device_name,
+ sizeof(devices[WX_port].device_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[WX_port].device_name);
+
+ temp_ptr = XmTextFieldGetString(WX_comment);
+ xastir_snprintf(devices[WX_port].comment,
+ sizeof(devices[WX_port].comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[WX_port].comment);
+
+ if(XmToggleButtonGetState(WX_active_on_startup))
+ devices[WX_port].connect_on_startup=1;
+ else
+ devices[WX_port].connect_on_startup=0;
+
+ set_port_speed(WX_port);
+ devices[WX_port].style=device_style;
+
+ xastir_snprintf(devices[WX_port].device_host_pswd,
+ sizeof( devices[WX_port].device_host_pswd), "%d", device_data_type);
+
+ /* reopen */
+ if ( was_up) {
+ (void)add_device(WX_port,
+ DEVICE_SERIAL_WX,
+ devices[WX_port].device_name,
+ devices[WX_port].device_host_pswd,
+ -1,
+ devices[WX_port].sp,
+ devices[WX_port].style,
+ 0,
+ "");
+ }
+
+ /* delete list */
+// modify_device_list(4,0);
+
+
+ /* add device type */
+ devices[WX_port].device_type=DEVICE_SERIAL_WX;
+
+ /* rebuild list */
+// modify_device_list(3,0);
+
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_WX_change_data" );
+
+ // Rebuild the interface control list
+ update_interface_list();
+
+ Config_WX_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void Config_WX( /*@unused@*/ Widget w, int config_type, int port) {
+ static Widget pane, form, button_ok, button_cancel,
+ frame, frame2, frame3, frame4, WX_none,
+ device, comment, speed, speed_box,
+ speed_300, speed_1200, speed_2400, speed_4800, speed_9600,
+ speed_19200, speed_38400;
+#ifndef __LSB__
+ static Widget speed_57600, speed_115200, speed_230400;
+#endif // __LSB__
+ static Widget style, style_box,
+ style_8n1, style_7e1, style_7o1,
+ data_type, data_box,
+ data_auto, data_bin, data_ascii,
+ gauge_type, gauge_box,
+ sep;
+ Atom delw;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+
+ if(!config_WX_dialog) {
+ WX_port=port;
+ config_WX_dialog = XtVaCreatePopupShell(langcode("WPUPCFWX01"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Config_WX pane",xmPanedWindowWidgetClass, config_WX_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Config_WX form",xmFormWidgetClass, pane,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ device = XtVaCreateManagedWidget(langcode("WPUPCFWX02"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_device_name_data = XtVaCreateManagedWidget("Config_WX device_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNwidth, ((15*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, device,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ comment = XtVaCreateManagedWidget(langcode("WPUPCFS017"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, device,
+ XmNtopOffset, 15,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_comment = XtVaCreateManagedWidget("Config_WX comment", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNwidth, ((15*7)+2),
+ XmNmaxLength, 49,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, device,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, comment,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_active_on_startup = XtVaCreateManagedWidget(langcode("UNIOP00011"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, comment,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ frame = XtVaCreateManagedWidget("Config_WX frame", xmFrameWidgetClass, form,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopOffset,10,
+ XmNtopWidget, WX_active_on_startup,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ speed = XtVaCreateManagedWidget(langcode("WPUPCFT004"),xmLabelWidgetClass, frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ /*set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNbackground, colors[0xff]); ac++;
+
+
+ speed_box = XmCreateRadioBox(frame,"Config_WX Speed_box",al,ac);
+
+ XtVaSetValues(speed_box,
+ XmNnumColumns,3,
+ NULL);
+
+ speed_300 = XtVaCreateManagedWidget(langcode("WPUPCFT005"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_300,XmNvalueChangedCallback,speed_toggle,"1");
+
+ speed_1200 = XtVaCreateManagedWidget(langcode("WPUPCFT006"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_1200,XmNvalueChangedCallback,speed_toggle,"2");
+
+ speed_2400 = XtVaCreateManagedWidget(langcode("WPUPCFT007"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_2400,XmNvalueChangedCallback,speed_toggle,"3");
+
+ speed_4800 = XtVaCreateManagedWidget(langcode("WPUPCFT008"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_4800,XmNvalueChangedCallback,speed_toggle,"4");
+
+ speed_9600 = XtVaCreateManagedWidget(langcode("WPUPCFT009"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_9600,XmNvalueChangedCallback,speed_toggle,"5");
+
+ speed_19200 = XtVaCreateManagedWidget(langcode("WPUPCFT010"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_19200,XmNvalueChangedCallback,speed_toggle,"6");
+
+ speed_38400 = XtVaCreateManagedWidget(langcode("WPUPCFT019"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_38400,XmNvalueChangedCallback,speed_toggle,"7");
+
+#ifndef __LSB__
+ speed_57600 = XtVaCreateManagedWidget(langcode("WPUPCFT020"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_57600,XmNvalueChangedCallback,speed_toggle,"8");
+
+ speed_115200 = XtVaCreateManagedWidget(langcode("WPUPCFT021"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_115200,XmNvalueChangedCallback,speed_toggle,"9");
+
+ speed_230400 = XtVaCreateManagedWidget(langcode("WPUPCFT022"),xmToggleButtonGadgetClass,
+ speed_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(speed_230400,XmNvalueChangedCallback,speed_toggle,"10");
+#endif // __LSB__
+
+ frame2 = XtVaCreateManagedWidget("Config_WX frame2", xmFrameWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ style = XtVaCreateManagedWidget(langcode("WPUPCFT015"),xmLabelWidgetClass, frame2,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ style_box = XmCreateRadioBox(frame2,"Config_WX Style box",al,ac);
+
+ XtVaSetValues(style_box,
+ XmNorientation, XmHORIZONTAL,
+ NULL);
+
+ style_8n1 = XtVaCreateManagedWidget(langcode("WPUPCFT016"),xmToggleButtonGadgetClass,
+ style_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(style_8n1,XmNvalueChangedCallback,style_toggle,"0");
+
+ style_7e1 = XtVaCreateManagedWidget(langcode("WPUPCFT017"),xmToggleButtonGadgetClass,
+ style_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(style_7e1,XmNvalueChangedCallback,style_toggle,"1");
+
+ style_7o1 = XtVaCreateManagedWidget(langcode("WPUPCFT018"),xmToggleButtonGadgetClass,
+ style_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(style_7o1,XmNvalueChangedCallback,style_toggle,"2");
+
+ frame3 = XtVaCreateManagedWidget("Config_WX frame3", xmFrameWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame2,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ data_type= XtVaCreateManagedWidget(langcode("WPUPCFT024"),xmLabelWidgetClass, frame3,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ data_box = XmCreateRadioBox(frame3,"Config_WX data box",al,ac);
+
+ XtVaSetValues(data_box,
+ XmNorientation, XmHORIZONTAL,
+ NULL);
+
+ data_auto = XtVaCreateManagedWidget(langcode("WPUPCFT025"),xmToggleButtonGadgetClass,
+ data_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(data_auto,XmNvalueChangedCallback,data_toggle,"0");
+
+ data_bin = XtVaCreateManagedWidget(langcode("WPUPCFT026"),xmToggleButtonGadgetClass,
+ data_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(data_bin,XmNvalueChangedCallback,data_toggle,"1");
+
+ data_ascii = XtVaCreateManagedWidget(langcode("WPUPCFT027"),xmToggleButtonGadgetClass,
+ data_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(data_ascii,XmNvalueChangedCallback,data_toggle,"2");
+
+ frame4 = XtVaCreateManagedWidget("Config_WX frame4", xmFrameWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame3,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ // Rain Gauge Type
+ gauge_type= XtVaCreateManagedWidget(langcode("WPUPCFWX03"),xmLabelWidgetClass, frame4,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ gauge_box = XmCreateRadioBox(frame4,"Config_WX gauge box",al,ac);
+
+ XtVaSetValues(gauge_box,
+ XmNorientation, XmHORIZONTAL,
+ NULL);
+
+ WX_none = XtVaCreateManagedWidget(langcode("WPUPCFWX07"),xmToggleButtonGadgetClass,
+ gauge_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ WX_tenths = XtVaCreateManagedWidget(langcode("WPUPCFWX04"),xmToggleButtonGadgetClass,
+ gauge_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ WX_hundredths = XtVaCreateManagedWidget(langcode("WPUPCFWX05"),xmToggleButtonGadgetClass,
+ gauge_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ WX_millimeters = XtVaCreateManagedWidget(langcode("WPUPCFWX06"),xmToggleButtonGadgetClass,
+ gauge_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(WX_none,XmNvalueChangedCallback,rain_gauge_toggle,"0");
+ XtAddCallback(WX_tenths,XmNvalueChangedCallback,rain_gauge_toggle,"1");
+ XtAddCallback(WX_hundredths,XmNvalueChangedCallback,rain_gauge_toggle,"2");
+ XtAddCallback(WX_millimeters,XmNvalueChangedCallback,rain_gauge_toggle,"3");
+
+ sep = XtVaCreateManagedWidget("Config_WX sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, frame4,
+ XmNtopOffset, 20,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Config_WX_change_data, config_WX_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Config_WX_destroy_shell, config_WX_dialog);
+
+ pos_dialog(config_WX_dialog);
+
+ delw = XmInternAtom(XtDisplay(config_WX_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(config_WX_dialog, delw, Config_WX_destroy_shell, (XtPointer)config_WX_dialog);
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_WX" );
+
+ if (config_type==0) {
+ /* first time port */
+ XmTextFieldSetString(WX_device_name_data,GPS_PORT);
+ XmTextFieldSetString(WX_comment,"");
+ XmToggleButtonSetState(WX_active_on_startup,TRUE,FALSE);
+ XmToggleButtonSetState(speed_2400,TRUE,FALSE);
+ device_speed=3;
+ XmToggleButtonSetState(style_8n1,TRUE,FALSE);
+ device_style=0;
+ device_data_type=0;
+ XmToggleButtonSetState(data_auto,TRUE,FALSE);
+ } else {
+ /* reconfig */
+ XmTextFieldSetString(WX_device_name_data,devices[WX_port].device_name);
+ XmTextFieldSetString(WX_comment,devices[WX_port].comment);
+
+ if (devices[WX_port].connect_on_startup)
+ XmToggleButtonSetState(WX_active_on_startup,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(WX_active_on_startup,FALSE,FALSE);
+
+ switch (devices[WX_port].sp) {
+ case(B300):
+ XmToggleButtonSetState(speed_300,TRUE,FALSE);
+ device_speed=1;
+ break;
+
+ case(B1200):
+ XmToggleButtonSetState(speed_1200,TRUE,FALSE);
+ device_speed=2;
+ break;
+
+ case(B2400):
+ XmToggleButtonSetState(speed_2400,TRUE,FALSE);
+ device_speed=3;
+ break;
+
+ case(B4800):
+ XmToggleButtonSetState(speed_4800,TRUE,FALSE);
+ device_speed=4;
+ break;
+
+ case(B9600):
+ XmToggleButtonSetState(speed_9600,TRUE,FALSE);
+ device_speed=5;
+ break;
+
+ case(B19200):
+ XmToggleButtonSetState(speed_19200,TRUE,FALSE);
+ device_speed=6;
+ break;
+
+ case(B38400):
+ XmToggleButtonSetState(speed_38400,TRUE,FALSE);
+ device_speed=7;
+ break;
+
+#ifndef __LSB__
+ case(B57600):
+ XmToggleButtonSetState(speed_57600,TRUE,FALSE);
+ device_speed=8;
+ break;
+
+ case(B115200):
+ XmToggleButtonSetState(speed_115200,TRUE,FALSE);
+ device_speed=9;
+ break;
+
+#ifdef B230400
+ case(B230400):
+ XmToggleButtonSetState(speed_230400,TRUE,FALSE);
+ device_speed=10;
+ break;
+#endif // B230400
+#endif // __LSB__
+
+ default:
+ XmToggleButtonSetState(speed_4800,TRUE,FALSE);
+ device_speed=4;
+ break;
+ }
+ switch (devices[WX_port].style) {
+ case(0):
+ XmToggleButtonSetState(style_8n1,TRUE,FALSE);
+ device_style=0;
+ break;
+
+ case(1):
+ XmToggleButtonSetState(style_7e1,TRUE,FALSE);
+ device_style=1;
+ break;
+
+ case(2):
+ XmToggleButtonSetState(style_7o1,TRUE,FALSE);
+ device_style=2;
+ break;
+
+ default:
+ XmToggleButtonSetState(style_8n1,TRUE,FALSE);
+ device_style=0;
+ break;
+ }
+ switch (atoi(devices[WX_port].device_host_pswd)) {
+ case(0):
+ XmToggleButtonSetState(data_auto,TRUE,FALSE);
+ device_data_type=0;
+ break;
+
+ case(1):
+ XmToggleButtonSetState(data_bin,TRUE,FALSE);
+ device_data_type=1;
+ break;
+
+ case(2):
+ XmToggleButtonSetState(data_ascii,TRUE,FALSE);
+ device_data_type=2;
+ break;
+
+ default:
+ device_data_type=0;
+ break;
+ }
+ }
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_WX" );
+
+ XmToggleButtonSetState(WX_none,FALSE,FALSE);
+ XmToggleButtonSetState(WX_tenths,FALSE,FALSE);
+ XmToggleButtonSetState(WX_hundredths,FALSE,FALSE);
+ XmToggleButtonSetState(WX_millimeters,FALSE,FALSE);
+ switch (WX_rain_gauge_type) {
+ case(1):
+ XmToggleButtonSetState(WX_tenths,TRUE,FALSE);
+ break;
+ case(2):
+ XmToggleButtonSetState(WX_hundredths,TRUE,FALSE);
+ break;
+ case(3):
+ XmToggleButtonSetState(WX_millimeters,TRUE,FALSE);
+ break;
+ default:
+ XmToggleButtonSetState(WX_none,TRUE,FALSE);
+ break;
+ }
+
+ XtManageChild(form);
+ XtManageChild(speed_box);
+ XtManageChild(style_box);
+ XtManageChild(data_box);
+ XtManageChild(gauge_box);
+ XtManageChild(pane);
+
+ XtPopup(config_WX_dialog,XtGrabNone);
+ fix_dialog_size(config_WX_dialog);
+ } else
+ (void)XRaiseWindow(XtDisplay(config_WX_dialog), XtWindow(config_WX_dialog));
+
+}
+
+
+
+
+
+/**** net WX CONFIGURE ******/
+int NWX_port;
+Widget config_NWX_dialog = (Widget)NULL;
+Widget NWX_host_name_data;
+Widget NWX_host_port_data;
+Widget NWX_comment;
+Widget NWX_active_on_startup;
+Widget NWX_host_reconnect_data;
+
+
+
+
+
+void Config_NWX_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ config_NWX_dialog = (Widget)NULL;
+
+ if (choose_interface_dialog != NULL)
+ Choose_interface_destroy_shell(choose_interface_dialog,choose_interface_dialog,NULL);
+
+ choose_interface_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Config_NWX_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ int was_up;
+ char *temp_ptr;
+
+
+ busy_cursor(appshell);
+
+ was_up=0;
+ if (get_device_status(NWX_port) == DEVICE_IN_USE) {
+ /* if active shutdown before changes are made */
+ /*fprintf(stderr,"Device is up, shutting down\n");*/
+ (void)del_device(NWX_port);
+ was_up=1;
+ usleep(1000000); // Wait for one second
+ }
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_NWX_change_data" );
+
+ temp_ptr = XmTextFieldGetString(NWX_host_name_data);
+ xastir_snprintf(devices[NWX_port].device_host_name,
+ sizeof(devices[NWX_port].device_host_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[NWX_port].device_host_name);
+
+ temp_ptr = XmTextFieldGetString(NWX_host_port_data);
+ devices[NWX_port].sp=atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(NWX_comment);
+ xastir_snprintf(devices[NWX_port].comment,
+ sizeof(devices[NWX_port].comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[NWX_port].comment);
+
+ if (XmToggleButtonGetState(NWX_active_on_startup))
+ devices[NWX_port].connect_on_startup=1;
+ else
+ devices[NWX_port].connect_on_startup=0;
+
+ if(XmToggleButtonGetState(NWX_host_reconnect_data))
+ devices[NWX_port].reconnect=1;
+ else
+ devices[NWX_port].reconnect=0;
+
+ xastir_snprintf(devices[NWX_port].device_host_pswd,
+ sizeof(devices[NWX_port].device_host_pswd), "%d", device_data_type);
+
+ /* reopen if was up*/
+ if ( was_up) {
+ (void)add_device(NWX_port,
+ DEVICE_NET_WX,
+ devices[NWX_port].device_host_name,
+ devices[NWX_port].device_host_pswd,
+ devices[NWX_port].sp,
+ 0,
+ 0,
+ devices[NWX_port].reconnect,
+ "");
+ }
+
+
+ /* delete list */
+// modify_device_list(4,0);
+
+
+ /* add device type */
+ devices[NWX_port].device_type=DEVICE_NET_WX;
+
+ /* rebuild list */
+// modify_device_list(3,0);
+
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_NWX_change_data" );
+
+ // Rebuild the interface control list
+ update_interface_list();
+
+ Config_NWX_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void Config_NWX( /*@unused@*/ Widget w, int config_type, int port) {
+ static Widget pane, form, frame3, frame4, WX_none,
+ button_ok, button_cancel,
+ hostn, portn, comment,
+ data_type, data_box,
+ data_auto, data_bin, data_ascii,
+ gauge_type, gauge_box,
+ sep;
+ char temp[20];
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+ Atom delw;
+
+ if(!config_NWX_dialog) {
+ NWX_port=port;
+ config_NWX_dialog = XtVaCreatePopupShell(langcode("WPUPCFG021"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Config_NWX pane",xmPanedWindowWidgetClass, config_NWX_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Config_NWX form",xmFormWidgetClass, pane,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ hostn = XtVaCreateManagedWidget(langcode("WPUPCFG022"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ NWX_host_name_data = XtVaCreateManagedWidget("Config_NWX host_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, hostn,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ portn = XtVaCreateManagedWidget(langcode("WPUPCFG023"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, hostn,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ NWX_host_port_data = XtVaCreateManagedWidget("Config_NWX port_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, hostn,
+ XmNtopOffset, 8,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, portn,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ comment = XtVaCreateManagedWidget(langcode("WPUPCFS017"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, portn,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ NWX_comment = XtVaCreateManagedWidget("Config_NWX comment", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 49,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, portn,
+ XmNtopOffset, 8,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, comment,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ NWX_active_on_startup = XtVaCreateManagedWidget(langcode("UNIOP00011"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, comment,
+ XmNtopOffset, 15,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ NWX_host_reconnect_data = XtVaCreateManagedWidget(langcode("WPUPCFG020"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, NWX_active_on_startup,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ /*set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNbackground, colors[0xff]); ac++;
+
+
+ frame3 = XtVaCreateManagedWidget("Config_NWX frame3", xmFrameWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, NWX_host_reconnect_data,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ data_type= XtVaCreateManagedWidget(langcode("WPUPCFT024"),xmLabelWidgetClass, frame3,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ data_box = XmCreateRadioBox(frame3,"Config_NWX data box",al,ac);
+
+ XtVaSetValues(data_box,
+ XmNorientation, XmHORIZONTAL,
+ NULL);
+
+ data_auto = XtVaCreateManagedWidget(langcode("WPUPCFT025"),xmToggleButtonGadgetClass,
+ data_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(data_auto,XmNvalueChangedCallback,data_toggle,"0");
+
+ data_bin = XtVaCreateManagedWidget(langcode("WPUPCFT026"),xmToggleButtonGadgetClass,
+ data_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(data_bin,XmNvalueChangedCallback,data_toggle,"1");
+
+ data_ascii = XtVaCreateManagedWidget(langcode("WPUPCFT027"),xmToggleButtonGadgetClass,
+ data_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(data_ascii,XmNvalueChangedCallback,data_toggle,"2");
+
+ frame4 = XtVaCreateManagedWidget("Config_WX frame4", xmFrameWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame3,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ // Rain Gauge Type
+ gauge_type= XtVaCreateManagedWidget(langcode("WPUPCFWX03"),xmLabelWidgetClass, frame4,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ gauge_box = XmCreateRadioBox(frame4,"Config_WX gauge box",al,ac);
+
+ XtVaSetValues(gauge_box,
+ XmNorientation, XmHORIZONTAL,
+ NULL);
+
+ WX_none = XtVaCreateManagedWidget(langcode("WPUPCFWX07"),xmToggleButtonGadgetClass,
+ gauge_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ WX_tenths = XtVaCreateManagedWidget(langcode("WPUPCFWX04"),xmToggleButtonGadgetClass,
+ gauge_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ WX_hundredths = XtVaCreateManagedWidget(langcode("WPUPCFWX05"),xmToggleButtonGadgetClass,
+ gauge_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ WX_millimeters = XtVaCreateManagedWidget(langcode("WPUPCFWX06"),xmToggleButtonGadgetClass,
+ gauge_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(WX_none,XmNvalueChangedCallback,rain_gauge_toggle,"0");
+ XtAddCallback(WX_tenths,XmNvalueChangedCallback,rain_gauge_toggle,"1");
+ XtAddCallback(WX_hundredths,XmNvalueChangedCallback,rain_gauge_toggle,"2");
+ XtAddCallback(WX_millimeters,XmNvalueChangedCallback,rain_gauge_toggle,"3");
+
+
+ sep = XtVaCreateManagedWidget("Config_NWX sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, frame4,
+ XmNtopOffset, 20,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Config_NWX_change_data, config_NWX_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Config_NWX_destroy_shell, config_NWX_dialog);
+
+ pos_dialog(config_NWX_dialog);
+
+ delw = XmInternAtom(XtDisplay(config_NWX_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(config_NWX_dialog, delw, Config_NWX_destroy_shell, (XtPointer)config_NWX_dialog);
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_NWX" );
+
+ if (config_type==0) {
+ /* first time port */
+ XmTextFieldSetString(NWX_host_name_data,"localhost");
+ XmTextFieldSetString(NWX_host_port_data,"1234");
+ XmTextFieldSetString(NWX_comment,"");
+ XmToggleButtonSetState(NWX_active_on_startup,TRUE,FALSE);
+ XmToggleButtonSetState(NWX_host_reconnect_data,TRUE,FALSE);
+ device_data_type=0;
+ XmToggleButtonSetState(data_auto,TRUE,FALSE);
+ } else {
+ /* reconfig */
+
+ XmTextFieldSetString(NWX_host_name_data,devices[NWX_port].device_host_name);
+ xastir_snprintf(temp, sizeof(temp), "%d", devices[NWX_port].sp); /* port number */
+ XmTextFieldSetString(NWX_host_port_data,temp);
+
+ XmTextFieldSetString(NWX_comment,devices[NWX_port].comment);
+
+ if (devices[NWX_port].connect_on_startup)
+ XmToggleButtonSetState(NWX_active_on_startup,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(NWX_active_on_startup,FALSE,FALSE);
+
+ if (devices[NWX_port].reconnect)
+ XmToggleButtonSetState(NWX_host_reconnect_data,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(NWX_host_reconnect_data,FALSE,FALSE);
+
+ switch (atoi(devices[NWX_port].device_host_pswd)) {
+ case(0):
+ XmToggleButtonSetState(data_auto,TRUE,FALSE);
+ device_data_type=0;
+ break;
+
+ case(1):
+ XmToggleButtonSetState(data_bin,TRUE,FALSE);
+ device_data_type=1;
+ break;
+
+ case(2):
+ XmToggleButtonSetState(data_ascii,TRUE,FALSE);
+ device_data_type=2;
+ break;
+
+ default:
+ device_data_type=0;
+ break;
+ }
+ }
+
+ XmToggleButtonSetState(WX_none,FALSE,FALSE);
+ XmToggleButtonSetState(WX_tenths,FALSE,FALSE);
+ XmToggleButtonSetState(WX_hundredths,FALSE,FALSE);
+ XmToggleButtonSetState(WX_millimeters,FALSE,FALSE);
+ switch (WX_rain_gauge_type) {
+ case(1):
+ XmToggleButtonSetState(WX_tenths,TRUE,FALSE);
+ break;
+ case(2):
+ XmToggleButtonSetState(WX_hundredths,TRUE,FALSE);
+ break;
+ case(3):
+ XmToggleButtonSetState(WX_millimeters,TRUE,FALSE);
+ break;
+ default:
+ XmToggleButtonSetState(WX_none,TRUE,FALSE);
+ break;
+ }
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_NWX" );
+
+ XtManageChild(form);
+ XtManageChild(data_box);
+ XtManageChild(frame3);
+ XtManageChild(gauge_box);
+ XtManageChild(pane);
+
+ XtPopup(config_NWX_dialog,XtGrabNone);
+ fix_dialog_size(config_NWX_dialog);
+ } else {
+ (void)XRaiseWindow(XtDisplay(config_NWX_dialog), XtWindow(config_NWX_dialog));
+ }
+}
+
+
+
+
+
+/*****************************************************/
+/* Configure net GPS GUI */
+/*****************************************************/
+
+/**** net GPS CONFIGURE ******/
+int NGPS_port;
+Widget config_NGPS_dialog = (Widget)NULL;
+Widget NGPS_host_name_data;
+Widget NGPS_host_port_data;
+Widget NGPS_comment;
+Widget NGPS_active_on_startup;
+Widget NGPS_host_reconnect_data;
+Widget NGPS_set_time;
+
+
+
+
+
+
+void Config_NGPS_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ config_NGPS_dialog = (Widget)NULL;
+ if (choose_interface_dialog != NULL)
+ Choose_interface_destroy_shell(choose_interface_dialog,choose_interface_dialog,NULL);
+
+ choose_interface_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Config_NGPS_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ int was_up;
+ char *temp_ptr;
+
+
+ busy_cursor(appshell);
+ was_up=0;
+ if (get_device_status(NGPS_port) == DEVICE_IN_USE) {
+ /* if active shutdown before changes are made */
+ /*fprintf(stderr,"Device is up, shutting down\n");*/
+ (void)del_device(NGPS_port);
+ was_up=1;
+ usleep(1000000); // Wait for one second
+ }
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_NGPS_change_data" );
+
+ temp_ptr = XmTextFieldGetString(NGPS_host_name_data);
+ xastir_snprintf(devices[NGPS_port].device_host_name,
+ sizeof(devices[NGPS_port].device_host_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[NGPS_port].device_host_name);
+
+ temp_ptr = XmTextFieldGetString(NGPS_host_port_data);
+ devices[NGPS_port].sp=atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(NGPS_comment);
+ xastir_snprintf(devices[NGPS_port].comment,
+ sizeof(devices[NGPS_port].comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[NGPS_port].comment);
+
+ if(XmToggleButtonGetState(NGPS_active_on_startup))
+ devices[NGPS_port].connect_on_startup=1;
+ else
+ devices[NGPS_port].connect_on_startup=0;
+
+ if (XmToggleButtonGetState(NGPS_host_reconnect_data))
+ devices[NGPS_port].reconnect=1;
+ else
+ devices[NGPS_port].reconnect=0;
+
+ if (XmToggleButtonGetState(NGPS_set_time))
+ devices[NGPS_port].set_time=1;
+ else
+ devices[NGPS_port].set_time=0;
+
+ /* reopen */
+ if ( was_up ) {
+ (void)add_device(NGPS_port,
+ DEVICE_NET_GPSD,
+ devices[NGPS_port].device_host_name,
+ "",
+ devices[NGPS_port].sp,
+ 0,
+ 0,
+ devices[NGPS_port].reconnect,
+ "");
+ }
+
+
+ /* delete list */
+// modify_device_list(4,0);
+
+
+ /* add device type */
+ devices[NGPS_port].device_type=DEVICE_NET_GPSD;
+
+ /* rebuild list */
+// modify_device_list(3,0);
+
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_NGPS_change_data" );
+
+ // Rebuild the interface control list
+ update_interface_list();
+
+ Config_NGPS_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void Config_NGPS( /*@unused@*/ Widget w, int config_type, int port) {
+ static Widget pane, form, button_ok, button_cancel,
+ hostn, portn, comment,
+ sep;
+ char temp[20];
+ Atom delw;
+
+ if (!config_NGPS_dialog) {
+ NGPS_port=port;
+ config_NGPS_dialog = XtVaCreatePopupShell(langcode("WPUPCFG019"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Config_NGPS pane",xmPanedWindowWidgetClass, config_NGPS_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Config_NGPS form",xmFormWidgetClass, pane,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ hostn = XtVaCreateManagedWidget(langcode("WPUPCFG017"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ NGPS_host_name_data = XtVaCreateManagedWidget("Config_NGPS host_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, hostn,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ portn = XtVaCreateManagedWidget(langcode("WPUPCFG018"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, hostn,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ NGPS_host_port_data = XtVaCreateManagedWidget("Config_NGPS port_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, hostn,
+ XmNtopOffset, 8,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, portn,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ comment = XtVaCreateManagedWidget(langcode("WPUPCFS017"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, portn,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ NGPS_comment = XtVaCreateManagedWidget("Config_NGPS comment", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 49,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, portn,
+ XmNtopOffset, 8,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, comment,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ NGPS_active_on_startup = XtVaCreateManagedWidget(langcode("UNIOP00011"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, comment,
+ XmNtopOffset, 15,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ NGPS_host_reconnect_data = XtVaCreateManagedWidget(langcode("WPUPCFG020"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, NGPS_active_on_startup,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ NGPS_set_time = XtVaCreateManagedWidget(langcode("UNIOP00029"), xmToggleButtonWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, NGPS_host_reconnect_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+// We can only set the time properly on Linux systems
+#ifndef HAVE_SETTIMEOFDAY
+ XtSetSensitive(NGPS_set_time,FALSE);
+#endif // HAVE_SETTIMEOFDAY
+#ifdef __CYGWIN__
+ XtSetSensitive(NGPS_set_time,FALSE);
+#endif // __CYGWIN__
+
+
+
+ sep = XtVaCreateManagedWidget("Config_NGPS sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, NGPS_set_time,
+ XmNtopOffset, 20,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Config_NGPS_change_data, config_NGPS_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Config_NGPS_destroy_shell, config_NGPS_dialog);
+
+ pos_dialog(config_NGPS_dialog);
+
+ delw = XmInternAtom(XtDisplay(config_NGPS_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(config_NGPS_dialog, delw, Config_NGPS_destroy_shell, (XtPointer)config_NGPS_dialog);
+
+ if (config_type==0) {
+ /* first time port */
+ XmTextFieldSetString(NGPS_host_name_data,"localhost");
+ XmTextFieldSetString(NGPS_host_port_data,"2947");
+ XmTextFieldSetString(NGPS_comment,"");
+ XmToggleButtonSetState(NGPS_active_on_startup,TRUE,FALSE);
+ XmToggleButtonSetState(NGPS_host_reconnect_data,TRUE,FALSE);
+ XmToggleButtonSetState(NGPS_set_time, FALSE, FALSE);
+ } else {
+ /* reconfig */
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_NGPS" );
+
+ XmTextFieldSetString(NGPS_host_name_data,devices[NGPS_port].device_host_name);
+ xastir_snprintf(temp, sizeof(temp), "%d", devices[NGPS_port].sp); /* port number */
+ XmTextFieldSetString(NGPS_host_port_data,temp);
+ XmTextFieldSetString(NGPS_comment,devices[NGPS_port].comment);
+
+ if (devices[NGPS_port].connect_on_startup)
+ XmToggleButtonSetState(NGPS_active_on_startup,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(NGPS_active_on_startup,FALSE,FALSE);
+
+ if (devices[NGPS_port].reconnect)
+ XmToggleButtonSetState(NGPS_host_reconnect_data,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(NGPS_host_reconnect_data,FALSE,FALSE);
+
+ if (devices[NGPS_port].set_time)
+ XmToggleButtonSetState(NGPS_set_time, TRUE, FALSE);
+ else
+ XmToggleButtonSetState(NGPS_set_time, FALSE, FALSE);
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_NGPS" );
+
+ }
+ XtManageChild(form);
+ XtManageChild(pane);
+
+ XtPopup(config_NGPS_dialog,XtGrabNone);
+ fix_dialog_size(config_NGPS_dialog);
+ } else
+ (void)XRaiseWindow(XtDisplay(config_NGPS_dialog), XtWindow(config_NGPS_dialog));
+}
+
+
+
+
+
+/*****************************************************/
+/* Configure AX.25 TNC GUI */
+/*****************************************************/
+
+/**** AX.25 CONFIGURE ******/
+int AX25_port;
+Widget config_AX25_dialog = (Widget)NULL;
+Widget AX25_device_name_data;
+Widget AX25_comment;
+Widget AX25_unproto1_data;
+Widget AX25_unproto2_data;
+Widget AX25_unproto3_data;
+Widget AX25_igate_data;
+Widget AX25_active_on_startup;
+Widget AX25_transmit_data;
+Widget AX25_relay_digipeat;
+
+
+
+
+
+void Config_AX25_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ config_AX25_dialog = (Widget)NULL;
+ if (choose_interface_dialog != NULL)
+ Choose_interface_destroy_shell(choose_interface_dialog,choose_interface_dialog,NULL);
+
+ choose_interface_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Config_AX25_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ int was_up;
+ char *temp_ptr;
+
+ busy_cursor(appshell);
+
+ was_up=0;
+ if (get_device_status(AX25_port) == DEVICE_IN_USE) {
+ /* if active shutdown before changes are made */
+ /*fprintf(stderr,"Device is up, shutting down\n");*/
+ (void)del_device(AX25_port);
+ was_up=1;
+ usleep(1000000); // Wait for one second
+ }
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_AX25_change_data" );
+
+ temp_ptr = XmTextFieldGetString(AX25_device_name_data);
+ xastir_snprintf(devices[AX25_port].device_name,
+ sizeof(devices[AX25_port].device_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[AX25_port].device_name);
+
+ temp_ptr = XmTextFieldGetString(AX25_comment);
+ xastir_snprintf(devices[AX25_port].comment,
+ sizeof(devices[AX25_port].comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[AX25_port].comment);
+
+ if(XmToggleButtonGetState(AX25_active_on_startup))
+ devices[AX25_port].connect_on_startup=1;
+ else
+ devices[AX25_port].connect_on_startup=0;
+
+ if(XmToggleButtonGetState(AX25_transmit_data)) {
+ devices[AX25_port].transmit_data=1;
+ XtSetSensitive(AX25_relay_digipeat, TRUE);
+ }
+ else {
+ devices[AX25_port].transmit_data=0;
+ XtSetSensitive(AX25_relay_digipeat, FALSE);
+ }
+
+ if(XmToggleButtonGetState(AX25_relay_digipeat))
+ devices[AX25_port].relay_digipeat=1;
+ else
+ devices[AX25_port].relay_digipeat=0;
+
+ devices[AX25_port].igate_options=device_igate_options;
+
+ temp_ptr = XmTextFieldGetString(AX25_unproto1_data);
+ xastir_snprintf(devices[AX25_port].unproto1,
+ sizeof(devices[AX25_port].unproto1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[AX25_port].unproto1);
+
+ if(check_unproto_path(devices[AX25_port].unproto1)) {
+ popup_message_always(langcode("WPUPCFT042"),
+ langcode("WPUPCFT043"));
+ }
+
+ temp_ptr = XmTextFieldGetString(AX25_unproto2_data);
+ xastir_snprintf(devices[AX25_port].unproto2,
+ sizeof(devices[AX25_port].unproto2),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[AX25_port].unproto2);
+
+ if(check_unproto_path(devices[AX25_port].unproto2)) {
+ popup_message_always(langcode("WPUPCFT042"),
+ langcode("WPUPCFT043"));
+ }
+
+ temp_ptr = XmTextFieldGetString(AX25_unproto3_data);
+ xastir_snprintf(devices[AX25_port].unproto3,
+ sizeof(devices[AX25_port].unproto3),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[AX25_port].unproto3);
+
+ if(check_unproto_path(devices[AX25_port].unproto3)) {
+ popup_message_always(langcode("WPUPCFT042"),
+ langcode("WPUPCFT043"));
+ }
+
+ temp_ptr = XmTextFieldGetString(AX25_igate_data);
+ xastir_snprintf(devices[AX25_port].unproto_igate,
+ sizeof(devices[AX25_port].unproto_igate),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[AX25_port].unproto_igate);
+
+ if(check_unproto_path(devices[AX25_port].unproto_igate)) {
+ popup_message_always(langcode("WPUPCFT044"),
+ langcode("WPUPCFT043"));
+ }
+
+
+ devices[AX25_port].reconnect=1;
+
+// reopen if open before - n8ysz 20041213
+// if (devices[AX25_port].connect_on_startup==1 || was_up) {
+ if ( was_up) {
+ (void)add_device(AX25_port,
+ DEVICE_AX25_TNC,
+ devices[AX25_port].device_name,
+ "",
+ -1,
+ -1,
+ -1,
+ 0,
+ "");
+ }
+
+
+ /* delete list */
+// modify_device_list(4,0);
+
+
+ /* add device type */
+ devices[AX25_port].device_type=DEVICE_AX25_TNC;
+
+ /* rebuild list */
+// modify_device_list(3,0);
+
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_AX25_change_data" );
+
+ // Rebuild the interface control list
+ update_interface_list();
+
+ Config_AX25_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void Config_AX25( /*@unused@*/ Widget w, int config_type, int port) {
+ static Widget pane, form, button_ok, button_cancel, frame,
+ devn, comment,
+ proto, proto1, proto2, proto3,
+ igate, igate_box,
+ igate_o_0, igate_o_1, igate_o_2,
+ igate_label,
+ sep;
+
+ char temp[50];
+ Atom delw;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+
+ if(!config_AX25_dialog) {
+ AX25_port=port;
+ config_AX25_dialog = XtVaCreatePopupShell(langcode("WPUPCAX001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Config_AX25 pane",xmPanedWindowWidgetClass, config_AX25_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Config_AX25 form",xmFormWidgetClass, pane,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ AX25_active_on_startup = XtVaCreateManagedWidget(langcode("UNIOP00011"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AX25_transmit_data = XtVaCreateManagedWidget(langcode("UNIOP00010"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, AX25_active_on_startup,
+ XmNleftOffset ,35,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AX25_relay_digipeat = XtVaCreateManagedWidget(langcode("UNIOP00030"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, AX25_transmit_data,
+ XmNleftOffset ,35,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ devn = XtVaCreateManagedWidget(langcode("WPUPCAX002"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, AX25_active_on_startup,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AX25_device_name_data = XtVaCreateManagedWidget("Config_AX25 device_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNwidth, ((15*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, AX25_active_on_startup,
+ XmNtopOffset, 2,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, devn,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ comment = XtVaCreateManagedWidget(langcode("WPUPCFS017"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, AX25_active_on_startup,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, AX25_device_name_data,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AX25_comment = XtVaCreateManagedWidget("Config_AX25 comment", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNwidth, ((15*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, AX25_active_on_startup,
+ XmNtopOffset, 2,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, comment,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ frame = XtVaCreateManagedWidget("Config_AX25 frame", xmFrameWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, devn,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ igate = XtVaCreateManagedWidget(langcode("IGPUPCF000"),xmLabelWidgetClass, frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ /* set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNbackground, colors[0xff]); ac++;
+
+
+ igate_box = XmCreateRadioBox(frame,"Config_AX25 IGate box",al,ac);
+
+ XtVaSetValues(igate_box,
+ XmNorientation, XmVERTICAL,
+ XmNnumColumns,2,
+ NULL);
+
+ igate_o_0 = XtVaCreateManagedWidget(langcode("IGPUPCF001"),xmToggleButtonGadgetClass,
+ igate_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(igate_o_0,XmNvalueChangedCallback,igate_toggle,"0");
+
+ igate_o_1 = XtVaCreateManagedWidget(langcode("IGPUPCF002"),xmToggleButtonGadgetClass,
+ igate_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(igate_o_1,XmNvalueChangedCallback,igate_toggle,"1");
+
+ igate_o_2 = XtVaCreateManagedWidget(langcode("IGPUPCF003"),xmToggleButtonGadgetClass,
+ igate_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(igate_o_2,XmNvalueChangedCallback,igate_toggle,"2");
+
+ proto = XtVaCreateManagedWidget(langcode("WPUPCFT011"), xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, frame,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset,5,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset,5,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPCFT012"), VERSIONFRM);
+
+ proto1 = XtVaCreateManagedWidget(temp, xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto,
+ XmNtopOffset, 12,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 60,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AX25_unproto1_data = XtVaCreateManagedWidget("Config_AX25 protopath1", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, proto1,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPCFT013"), VERSIONFRM);
+
+ proto2 = XtVaCreateManagedWidget(temp, xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto1,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 60,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AX25_unproto2_data = XtVaCreateManagedWidget("Config_AX25 protopath2", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, AX25_unproto1_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, proto2,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPCFT014"), VERSIONFRM);
+
+ proto3 = XtVaCreateManagedWidget(temp, xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto2,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 60,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AX25_unproto3_data = XtVaCreateManagedWidget("Config_AX25 protopath3", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, AX25_unproto2_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, proto3,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("IGPUPCF004"));
+ igate_label = XtVaCreateManagedWidget(temp, xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto3,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 60,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AX25_igate_data = XtVaCreateManagedWidget("Config_TNC igate_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, AX25_unproto3_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, igate_label,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sep = XtVaCreateManagedWidget("Config_AX25 sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, igate_label,
+ XmNtopOffset, 20,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+#ifdef HAVE_LIBAX25
+ XtAddCallback(button_ok, XmNactivateCallback, Config_AX25_change_data, config_AX25_dialog);
+#endif /* USE_AX25 */
+ XtAddCallback(button_cancel, XmNactivateCallback, Config_AX25_destroy_shell, config_AX25_dialog);
+
+ pos_dialog(config_AX25_dialog);
+
+ delw = XmInternAtom(XtDisplay(config_AX25_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(config_AX25_dialog, delw, Config_AX25_destroy_shell, (XtPointer)config_AX25_dialog);
+
+ if (config_type==0) {
+ /* first time port */
+ XmToggleButtonSetState(AX25_active_on_startup,TRUE,FALSE);
+ XmToggleButtonSetState(AX25_transmit_data,TRUE,FALSE);
+ XmToggleButtonSetState(AX25_relay_digipeat,FALSE,FALSE);
+ XmTextFieldSetString(AX25_device_name_data,"");
+ XmTextFieldSetString(AX25_comment,"");
+ device_igate_options=0;
+ XmToggleButtonSetState(igate_o_0,TRUE,FALSE);
+ XmTextFieldSetString(AX25_unproto1_data,"WIDE2-2");
+ XmTextFieldSetString(AX25_unproto2_data,"");
+ XmTextFieldSetString(AX25_unproto3_data,"");
+ XmTextFieldSetString(AX25_igate_data,"");
+ } else {
+ /* reconfig */
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_AX25" );
+
+ if (devices[AX25_port].connect_on_startup)
+ XmToggleButtonSetState(AX25_active_on_startup,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(AX25_active_on_startup,FALSE,FALSE);
+
+ switch (devices[AX25_port].igate_options) {
+ case(0):
+ XmToggleButtonSetState(igate_o_0,TRUE,FALSE);
+ device_igate_options=0;
+ break;
+
+ case(1):
+ XmToggleButtonSetState(igate_o_1,TRUE,FALSE);
+ device_igate_options=1;
+ break;
+
+ case(2):
+ XmToggleButtonSetState(igate_o_2,TRUE,FALSE);
+ device_igate_options=2;
+ break;
+
+ default:
+ XmToggleButtonSetState(igate_o_0,TRUE,FALSE);
+ device_igate_options=0;
+ break;
+ }
+ if (devices[AX25_port].transmit_data)
+ XmToggleButtonSetState(AX25_transmit_data,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(AX25_transmit_data,FALSE,FALSE);
+
+ if (devices[AX25_port].relay_digipeat)
+ XmToggleButtonSetState(AX25_relay_digipeat,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(AX25_relay_digipeat,FALSE,FALSE);
+
+ XmTextFieldSetString(AX25_device_name_data,devices[AX25_port].device_name);
+ XmTextFieldSetString(AX25_comment,devices[AX25_port].comment);
+ XmTextFieldSetString(AX25_unproto1_data,devices[AX25_port].unproto1);
+ XmTextFieldSetString(AX25_unproto2_data,devices[AX25_port].unproto2);
+ XmTextFieldSetString(AX25_unproto3_data,devices[AX25_port].unproto3);
+ XmTextFieldSetString(AX25_igate_data,devices[AX25_port].unproto_igate);
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_AX25" );
+
+ }
+ XtManageChild(form);
+ XtManageChild(igate_box);
+ XtManageChild(pane);
+
+ XtPopup(config_AX25_dialog,XtGrabNone);
+ fix_dialog_size(config_AX25_dialog);
+ } else {
+ (void)XRaiseWindow(XtDisplay(config_AX25_dialog), XtWindow(config_AX25_dialog));
+ }
+}
+
+
+
+
+
+/*****************************************************/
+/* Configure Network server GUI */
+/*****************************************************/
+
+/**** INTERNET CONFIGURE ******/
+Widget config_Inet_dialog = (Widget)NULL;
+Widget Inet_active_on_startup;
+Widget Inet_host_data;
+Widget Inet_port_data;
+Widget Inet_comment;
+Widget Inet_password_data;
+Widget Inet_filter_data;
+Widget Inet_transmit_data;
+Widget Inet_reconnect_data;
+int Inet_port;
+
+
+
+
+
+void Inet_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ config_Inet_dialog = (Widget)NULL;
+ if (choose_interface_dialog != NULL)
+ Choose_interface_destroy_shell(choose_interface_dialog,choose_interface_dialog,NULL);
+
+ choose_interface_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Inet_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ int was_up;
+ char *temp_ptr;
+
+
+ busy_cursor(appshell);
+ was_up=0;
+ if (get_device_status(Inet_port) == DEVICE_IN_USE) {
+ /* if active shutdown before changes are made */
+ /*fprintf(stderr,"Device is up, shutting down\n");*/
+ (void)del_device(Inet_port);
+ was_up=1;
+ usleep(1000000); // Wait for one second
+ }
+
+begin_critical_section(&devices_lock, "interface_gui.c:Inet_change_data" );
+
+ temp_ptr = XmTextFieldGetString(Inet_host_data);
+ xastir_snprintf(devices[Inet_port].device_host_name,
+ sizeof(devices[Inet_port].device_host_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[Inet_port].device_host_name);
+
+ temp_ptr = XmTextFieldGetString(Inet_password_data);
+ xastir_snprintf(devices[Inet_port].device_host_pswd,
+ sizeof(devices[Inet_port].device_host_pswd),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[Inet_port].device_host_pswd);
+
+ temp_ptr = XmTextFieldGetString(Inet_filter_data);
+ xastir_snprintf(devices[Inet_port].device_host_filter_string,
+ sizeof(devices[Inet_port].device_host_filter_string),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[Inet_port].device_host_filter_string);
+
+ temp_ptr = XmTextFieldGetString(Inet_comment);
+ xastir_snprintf(devices[Inet_port].comment,
+ sizeof(devices[Inet_port].comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[Inet_port].comment);
+
+ temp_ptr = XmTextFieldGetString(Inet_port_data);
+ devices[Inet_port].sp=atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ if(XmToggleButtonGetState(Inet_active_on_startup))
+ devices[Inet_port].connect_on_startup=1;
+ else
+ devices[Inet_port].connect_on_startup=0;
+
+ if(XmToggleButtonGetState(Inet_transmit_data))
+ devices[Inet_port].transmit_data=1;
+ else
+ devices[Inet_port].transmit_data=0;
+
+ if(XmToggleButtonGetState(Inet_reconnect_data))
+ devices[Inet_port].reconnect=1;
+ else
+ devices[Inet_port].reconnect=0;
+
+// Changed 20041213 per emails with we7u - n8ysz
+// if (devices[Inet_port].connect_on_startup==1 || was_up) {
+
+ if ( was_up) {
+ (void)add_device(Inet_port,
+ DEVICE_NET_STREAM,
+ devices[Inet_port].device_host_name,
+ devices[Inet_port].device_host_pswd,
+ devices[Inet_port].sp,
+ 0,
+ 0,
+ devices[Inet_port].reconnect,
+ devices[Inet_port].device_host_filter_string);
+ }
+
+ /* delete list */
+// modify_device_list(4,0);
+
+
+ /* add device type */
+ devices[Inet_port].device_type=DEVICE_NET_STREAM;
+
+ /* rebuild list */
+// modify_device_list(3,0);
+
+
+end_critical_section(&devices_lock, "interface_gui.c:Inet_change_data" );
+
+ // Rebuild the interface control list
+ update_interface_list();
+
+ Inet_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void Config_Inet( /*@unused@*/ Widget w, int config_type, int port) {
+ static Widget pane, form, button_ok, button_cancel,
+ ihost, iport, password, password_fl,
+ filter, comment, sep;
+
+ Atom delw;
+ char temp[40];
+
+ if(!config_Inet_dialog) {
+ Inet_port=port;
+ config_Inet_dialog = XtVaCreatePopupShell(langcode("WPUPCFI001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Config_Inet pane",xmPanedWindowWidgetClass, config_Inet_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Config_Inet form",xmFormWidgetClass, pane,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ Inet_active_on_startup = XtVaCreateManagedWidget(langcode("UNIOP00011"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Inet_transmit_data = XtVaCreateManagedWidget(langcode("UNIOP00010"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Inet_active_on_startup,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ ihost = XtVaCreateManagedWidget(langcode("WPUPCFI002"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Inet_transmit_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Inet_host_data = XtVaCreateManagedWidget("Config_Inet host_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 30,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, Inet_transmit_data,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ihost,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ iport = XtVaCreateManagedWidget(langcode("WPUPCFI003"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget,Inet_transmit_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget,Inet_host_data,
+ XmNleftOffset, 20,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Inet_port_data = XtVaCreateManagedWidget("Config_Inet port_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 5,
+ XmNmaxLength, 6,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Inet_transmit_data,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, iport,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset,10,
+ XmNfontList, fontlist1,
+ NULL);
+
+ password = XtVaCreateManagedWidget(langcode("WPUPCFI009"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ihost,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Inet_password_data = XtVaCreateManagedWidget("Config_Inet password_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 20,
+ XmNmaxLength, 20,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, password,
+ XmNleftOffset, 10,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, ihost,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ password_fl = XtVaCreateManagedWidget(langcode("WPUPCFI010"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ihost,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget,Inet_password_data,
+ XmNleftOffset,20,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ filter = XtVaCreateManagedWidget(langcode("WPUPCFI015"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, password,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Inet_filter_data = XtVaCreateManagedWidget("Config_Inet filter_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 30,
+ XmNmaxLength, 190,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, filter,
+ XmNleftOffset, 10,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, password,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ comment = XtVaCreateManagedWidget(langcode("WPUPCFS017"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Inet_filter_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Inet_comment = XtVaCreateManagedWidget("Config_Inet comment", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 49,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, Inet_filter_data,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, comment,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ Inet_reconnect_data = XtVaCreateManagedWidget(langcode("WPUPCFI011"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, comment,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ sep = XtVaCreateManagedWidget("Config_Inet sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, Inet_reconnect_data,
+ XmNtopOffset, 14,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Inet_change_data, config_Inet_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Inet_destroy_shell, config_Inet_dialog);
+
+ pos_dialog(config_Inet_dialog);
+
+ delw = XmInternAtom(XtDisplay(config_Inet_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(config_Inet_dialog, delw, Inet_destroy_shell, (XtPointer)config_Inet_dialog);
+
+ if (config_type==0) {
+ /* first time port */
+ XmToggleButtonSetState(Inet_active_on_startup,TRUE,FALSE);
+ XmToggleButtonSetState(Inet_transmit_data,TRUE,FALSE);
+
+ // Core APRS-IS Servers
+ XmTextFieldSetString(Inet_host_data,"rotate.aprs.net");
+
+ // Filtered port
+ XmTextFieldSetString(Inet_port_data,"14580");
+
+ // Filter of 500 miles around my location. But only if I
+ // enable transmit on that interface and globally!
+ XmTextFieldSetString(Inet_filter_data,"m/500");
+
+ XmTextFieldSetString(Inet_comment,"Core INET Servers");
+ XmToggleButtonSetState(Inet_reconnect_data,TRUE,FALSE);
+ } else {
+ /* reconfig */
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_Inet" );
+
+ if (devices[Inet_port].connect_on_startup)
+ XmToggleButtonSetState(Inet_active_on_startup,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(Inet_active_on_startup,FALSE,FALSE);
+
+ if (devices[Inet_port].transmit_data)
+ XmToggleButtonSetState(Inet_transmit_data,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(Inet_transmit_data,FALSE,FALSE);
+
+ XmTextFieldSetString(Inet_host_data,devices[Inet_port].device_host_name);
+ xastir_snprintf(temp, sizeof(temp), "%d", devices[Inet_port].sp);
+ XmTextFieldSetString(Inet_port_data,temp);
+ XmTextFieldSetString(Inet_password_data,devices[Inet_port].device_host_pswd);
+ XmTextFieldSetString(Inet_filter_data,devices[Inet_port].device_host_filter_string);
+ XmTextFieldSetString(Inet_comment,devices[Inet_port].comment);
+
+ if (devices[Inet_port].reconnect)
+ XmToggleButtonSetState(Inet_reconnect_data,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(Inet_reconnect_data,FALSE,FALSE);
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_Inet" );
+
+ }
+ XtManageChild(form);
+ XtManageChild(pane);
+
+ XtPopup(config_Inet_dialog,XtGrabNone);
+ fix_dialog_size(config_Inet_dialog);
+ } else {
+ (void)XRaiseWindow(XtDisplay(config_Inet_dialog), XtWindow(config_Inet_dialog));
+ }
+}
+
+
+
+
+
+//WE7U-DATABASE
+/*****************************************************/
+/* Configure Database Server GUI */
+/*****************************************************/
+
+/**** DATABASE CONFIGURE ******/
+Widget config_Database_dialog = (Widget)NULL;
+Widget Database_active_on_startup;
+Widget Database_host_data;
+Widget Database_port_data;
+Widget Database_comment;
+Widget Database_password_data;
+Widget Database_filter_data;
+Widget Database_transmit_data;
+Widget Database_reconnect_data;
+int Database_port;
+
+
+
+
+
+void Database_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ config_Database_dialog = (Widget)NULL;
+ if (choose_interface_dialog != NULL)
+ Choose_interface_destroy_shell(choose_interface_dialog,choose_interface_dialog,NULL);
+
+ choose_interface_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Database_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ int was_up;
+ char *temp_ptr;
+
+
+ busy_cursor(appshell);
+ was_up=0;
+ if (get_device_status(Database_port) == DEVICE_IN_USE) {
+ /* if active shutdown before changes are made */
+ /*fprintf(stderr,"Device is up, shutting down\n");*/
+ (void)del_device(Database_port);
+ was_up=1;
+ usleep(1000000); // Wait for one second
+ }
+
+begin_critical_section(&devices_lock, "interface_gui.c:Database_change_data" );
+
+ temp_ptr = XmTextFieldGetString(Database_host_data);
+ xastir_snprintf(devices[Database_port].device_host_name,
+ sizeof(devices[Database_port].device_host_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[Database_port].device_host_name);
+
+ temp_ptr = XmTextFieldGetString(Database_password_data);
+ xastir_snprintf(devices[Database_port].device_host_pswd,
+ sizeof(devices[Database_port].device_host_pswd),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[Database_port].device_host_pswd);
+
+ temp_ptr = XmTextFieldGetString(Database_filter_data);
+ xastir_snprintf(devices[Database_port].device_host_filter_string,
+ sizeof(devices[Database_port].device_host_filter_string),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[Database_port].device_host_filter_string);
+
+ temp_ptr = XmTextFieldGetString(Database_comment);
+ xastir_snprintf(devices[Database_port].comment,
+ sizeof(devices[Database_port].comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[Database_port].comment);
+
+ temp_ptr = XmTextFieldGetString(Database_port_data);
+ devices[Database_port].sp=atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ if(XmToggleButtonGetState(Database_active_on_startup))
+ devices[Database_port].connect_on_startup=1;
+ else
+ devices[Database_port].connect_on_startup=0;
+
+ if(XmToggleButtonGetState(Database_transmit_data))
+ devices[Database_port].transmit_data=1;
+ else
+ devices[Database_port].transmit_data=0;
+
+ if(XmToggleButtonGetState(Database_reconnect_data))
+ devices[Database_port].reconnect=1;
+ else
+ devices[Database_port].reconnect=0;
+
+// n8ysz 20041213
+// if (devices[Database_port].connect_on_startup==1 || was_up) {
+ if ( was_up) {
+ (void)add_device(Database_port,
+ DEVICE_NET_DATABASE,
+ devices[Database_port].device_host_name,
+ devices[Database_port].device_host_pswd,
+ devices[Database_port].sp,
+ 0,
+ 0,
+ devices[Database_port].reconnect,
+ devices[Database_port].device_host_filter_string);
+ }
+
+ /* delete list */
+// modify_device_list(4,0);
+
+
+ /* add device type */
+ devices[Database_port].device_type=DEVICE_NET_DATABASE;
+
+ /* rebuild list */
+// modify_device_list(3,0);
+
+
+end_critical_section(&devices_lock, "interface_gui.c:Database_change_data" );
+
+ // Rebuild the interface control list
+ update_interface_list();
+
+ Database_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void Config_Database( /*@unused@*/ Widget w, int config_type, int port) {
+ static Widget pane, form, button_ok, button_cancel,
+ ihost, iport, password, password_fl,
+ filter, sep, comment;
+
+ Atom delw;
+ char temp[40];
+
+ if(!config_Database_dialog) {
+ Database_port=port;
+ config_Database_dialog = XtVaCreatePopupShell(langcode("WPUPCFID01"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Config_Database pane",xmPanedWindowWidgetClass, config_Database_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Config_Database form",xmFormWidgetClass, pane,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ Database_active_on_startup = XtVaCreateManagedWidget(langcode("UNIOP00011"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Database_transmit_data = XtVaCreateManagedWidget(langcode("UNIOP00010"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Database_active_on_startup,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ ihost = XtVaCreateManagedWidget(langcode("WPUPCFID02"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Database_transmit_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Database_host_data = XtVaCreateManagedWidget("Config_Database host_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 30,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, Database_transmit_data,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ihost,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ iport = XtVaCreateManagedWidget(langcode("WPUPCFID03"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget,Database_transmit_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget,Database_host_data,
+ XmNleftOffset, 20,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Database_port_data = XtVaCreateManagedWidget("Config_Database port_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 5,
+ XmNmaxLength, 6,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Database_transmit_data,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, iport,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset,10,
+ XmNfontList, fontlist1,
+ NULL);
+
+ password = XtVaCreateManagedWidget(langcode("WPUPCFID09"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ihost,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Database_password_data = XtVaCreateManagedWidget("Config_Database password_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 20,
+ XmNmaxLength, 20,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, password,
+ XmNleftOffset, 10,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, ihost,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ password_fl = XtVaCreateManagedWidget(langcode("WPUPCFID10"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ihost,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget,Database_password_data,
+ XmNleftOffset,20,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ filter = XtVaCreateManagedWidget(langcode("WPUPCFID15"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, password,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Database_filter_data = XtVaCreateManagedWidget("Config_Database filter_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 30,
+ XmNmaxLength, 190,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, filter,
+ XmNleftOffset, 10,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, password,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ comment = XtVaCreateManagedWidget(langcode("WPUPCFS017"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, filter,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Database_comment = XtVaCreateManagedWidget("Config_Database comment", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 49,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, filter,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, comment,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ Database_reconnect_data = XtVaCreateManagedWidget(langcode("WPUPCFID11"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, comment,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ sep = XtVaCreateManagedWidget("Config_Database sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, Database_reconnect_data,
+ XmNtopOffset, 14,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Database_change_data, config_Database_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Database_destroy_shell, config_Database_dialog);
+
+ pos_dialog(config_Database_dialog);
+
+ delw = XmInternAtom(XtDisplay(config_Database_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(config_Database_dialog, delw, Database_destroy_shell, (XtPointer)config_Database_dialog);
+
+ if (config_type==0) {
+ /* first time port */
+ XmToggleButtonSetState(Database_active_on_startup,TRUE,FALSE);
+ XmToggleButtonSetState(Database_transmit_data,TRUE,FALSE);
+ //XmTextFieldSetString(Database_host_data,"first.aprs.net");
+ XmTextFieldSetString(Database_host_data,"");
+ XmTextFieldSetString(Database_port_data,"");
+ XmTextFieldSetString(Database_filter_data,"");
+ XmTextFieldSetString(Database_comment,"");
+ XmToggleButtonSetState(Database_reconnect_data,FALSE,FALSE);
+ } else {
+ /* reconfig */
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_Database" );
+
+ if (devices[Database_port].connect_on_startup)
+ XmToggleButtonSetState(Database_active_on_startup,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(Database_active_on_startup,FALSE,FALSE);
+
+ if (devices[Database_port].transmit_data)
+ XmToggleButtonSetState(Database_transmit_data,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(Database_transmit_data,FALSE,FALSE);
+
+ XmTextFieldSetString(Database_host_data,devices[Database_port].device_host_name);
+ xastir_snprintf(temp, sizeof(temp), "%d", devices[Database_port].sp);
+ XmTextFieldSetString(Database_port_data,temp);
+ XmTextFieldSetString(Database_password_data,devices[Database_port].device_host_pswd);
+ XmTextFieldSetString(Database_filter_data,devices[Database_port].device_host_filter_string);
+ XmTextFieldSetString(Database_comment,devices[Database_port].comment);
+
+ if (devices[Database_port].reconnect)
+ XmToggleButtonSetState(Database_reconnect_data,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(Database_reconnect_data,FALSE,FALSE);
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_Database" );
+
+ }
+ XtManageChild(form);
+ XtManageChild(pane);
+
+ XtPopup(config_Database_dialog,XtGrabNone);
+ fix_dialog_size(config_Database_dialog);
+ } else {
+ (void)XRaiseWindow(XtDisplay(config_Database_dialog), XtWindow(config_Database_dialog));
+ }
+}
+
+
+#ifdef HAVE_DB
+//AA3SD-SQL SERVER DATABASE, for db_gis spatial databases
+/*****************************************************/
+/* Configure SQL Database Server GUI */
+/*****************************************************/
+
+/**** DATABASE CONFIGURE ******/
+Widget config_Sql_Database_dialog = (Widget)NULL; // dialog for sql server database connections used in db_gis.c
+Widget Sql_Database_active_on_startup;
+Widget Sql_Database_query_on_startup_data;
+Widget Sql_Database_host_data;
+Widget Sql_Database_iport_data; // = sp, tcp port number on which to connect to database server
+Widget Sql_Database_comment;
+Widget Sql_Database_password_data;
+Widget Sql_Database_transmit_data;
+Widget Sql_Database_reconnect_data;
+int Sql_Database_port; // xastir interface port number, not tcp/ip port
+Widget Sql_Database_username_data;
+Widget Sql_Database_schema_name_data;
+
+// lesstif combo boxes are not fully implemented.
+// replace combo box with a fake combo box made out of a menu when only lesstif is available
+#ifdef USE_COMBO_BOX
+Widget Sql_Database_dbms_data;
+#else
+int sddd_value; // integer value of the currently selected item (replicating ordinal position in picklist)
+Widget sddd_button; // button to bring up the picklist
+Widget sddd_buttons[3];
+Widget sddd_menuPane; /// menu that acts as the picklist of dbms types
+Widget sddd_menu; /// menu top level
+#endif // USE_COMBO_BOX
+Widget sddd_widget; // widget used to bind next control in either use combo box or not cases.
+
+Widget Sql_Database_unix_socket_data;
+Widget Sql_Database_schema_type_data;
+Widget Sql_Database_errormessage_data; // display most recent error message on connection
+
+
+
+
+
+#ifdef HAVE_MYSQL
+// Set the values on the user interface to an appropriate set
+// of defaults for connecting to a mysql database.
+void Sql_Database_set_defaults_mysql(/*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ XmString cb_item;
+ //cb_item = XmStringCreateLtoR("MySQL (lat/long)", XmFONTLIST_DEFAULT_TAG);
+ cb_item = XmStringCreateLtoR(&xastir_dbms_type[DB_MYSQL][0], XmFONTLIST_DEFAULT_TAG);
+ //cb_item = XmStringCreateLtoR("MySQL (spatial)", XmFONTLIST_DEFAULT_TAG);
+#ifdef HAVE_MYSQL_SPATIAL
+ cb_item = XmStringCreateLtoR(&xastir_dbms_type[DB_MYSQL_SPATIAL][0], XmFONTLIST_DEFAULT_TAG);
+#endif /* HAVE_MYSQL_SPATIAL */
+#ifdef USE_COMBO_BOX
+ XmComboBoxSelectItem(Sql_Database_dbms_data,cb_item);
+#else
+ XtVaSetValues(sddd_menu, XmNmenuHistory, sddd_buttons[DB_MYSQL_SPATIAL], NULL);
+ sddd_value = DB_MYSQL_SPATIAL;
+#endif // USE_COMBO_BOX
+ XmStringFree(cb_item);
+ //cb_item = XmStringCreateLtoR("Xastir - simple", XmFONTLIST_DEFAULT_TAG);
+ cb_item = XmStringCreateLtoR(&xastir_schema_type[XASTIR_SCHEMA_SIMPLE][0], XmFONTLIST_DEFAULT_TAG);
+ XmComboBoxSelectItem(Sql_Database_schema_type_data,cb_item);
+ XmStringFree(cb_item);
+ XmToggleButtonSetState(Sql_Database_active_on_startup,TRUE,FALSE);
+ XmToggleButtonSetState(Sql_Database_transmit_data,TRUE,FALSE);
+ XmTextFieldSetString(Sql_Database_host_data,"localhost");
+ XmTextFieldSetString(Sql_Database_iport_data,"3306");
+ XmTextFieldSetString(Sql_Database_username_data,"xastir_user");
+ XmTextFieldSetString(Sql_Database_schema_name_data,"xastir");
+ // ** get default from mysql_config at configure time
+ XmTextFieldSetString(Sql_Database_unix_socket_data,"/var/lib/mysql/mysql.sock");
+ XmTextFieldSetString(Sql_Database_comment,"");
+ XmToggleButtonSetState(Sql_Database_reconnect_data,FALSE,FALSE);
+ // don't set Sql_Database_errormessage_data - leave most recent error message visible
+}
+#endif /* HAVE_MYSQL */
+
+
+
+
+
+#ifdef HAVE_POSTGIS
+// Set the values on the user interface to an appropriate set
+// of defaults for connecting to a postgresql database.
+void Sql_Database_set_defaults_postgis(/*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ XmString cb_item;
+ //cb_item = XmStringCreateLtoR("Postgres/Postgis", XmFONTLIST_DEFAULT_TAG);
+ cb_item = XmStringCreateLtoR(&xastir_dbms_type[DB_POSTGIS][0], XmFONTLIST_DEFAULT_TAG);
+#ifdef USE_COMBO_BOX
+ XmComboBoxSelectItem(Sql_Database_dbms_data,cb_item);
+#else
+ XtVaSetValues(sddd_menu, XmNmenuHistory, sddd_buttons[DB_POSTGIS], NULL);
+ sddd_value = DB_POSTGIS;
+#endif // USE_COMBO_BOX
+ XmStringFree(cb_item);
+ //cb_item = XmStringCreateLtoR("Xastir - simple", XmFONTLIST_DEFAULT_TAG);
+ cb_item = XmStringCreateLtoR(&xastir_schema_type[XASTIR_SCHEMA_SIMPLE][0], XmFONTLIST_DEFAULT_TAG);
+ XmComboBoxSelectItem(Sql_Database_schema_type_data,cb_item);
+ XmStringFree(cb_item);
+ XmToggleButtonSetState(Sql_Database_active_on_startup,TRUE,FALSE);
+ XmToggleButtonSetState(Sql_Database_transmit_data,TRUE,FALSE);
+ XmTextFieldSetString(Sql_Database_host_data,"localhost");
+ XmTextFieldSetString(Sql_Database_iport_data,"5432");
+ XmTextFieldSetString(Sql_Database_username_data,"xastir_user");
+ XmTextFieldSetString(Sql_Database_schema_name_data,"xastir");
+ // ** get default from mysql_config at configure time
+ XmTextFieldSetString(Sql_Database_unix_socket_data,"");
+ XmTextFieldSetString(Sql_Database_comment,"");
+ XmToggleButtonSetState(Sql_Database_reconnect_data,FALSE,FALSE);
+ // don't set Sql_Database_errormessage_data - leave most recent error message visible
+}
+#endif /* HAVE_POSTGIS */
+
+
+
+
+
+// Destroy the dialog used to set properties for a SQL database interface.
+void Sql_Database_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ config_Sql_Database_dialog = (Widget)NULL;
+ if (choose_interface_dialog != NULL)
+ Choose_interface_destroy_shell(choose_interface_dialog,choose_interface_dialog,NULL);
+
+ choose_interface_dialog = (Widget)NULL;
+}
+
+
+
+
+
+
+/* Callback for OK button on SQL database interface properties dialog.
+ Creates a new interface with the parameters provided in the dialog, or
+ alters the values of the selected interface that was displayed in the
+ dialog.
+ Differs from other interfaces in that an active database connection needs
+ to be started from the interface parameters.
+*/
+void Sql_Database_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ int was_up; // flag to restart connection with new parameters
+ char *temp_ptr; // temporary variable for retrieving string data from XmTextFields
+ int cb_selected; // temporary variable for retrieving combo box selections
+
+ // change to use code from db_gis.c
+
+ busy_cursor(appshell);
+ was_up=0;
+
+ if (debug_level & 2)
+ fprintf(stderr,"Storing SQL Database interface on port %d\n",Sql_Database_port);
+ // determine if there is an active connection based on this interface,
+ // if so, stop it and restart after changes have been made.
+ if (get_device_status(Sql_Database_port) == DEVICE_IN_USE) {
+ /* if active shutdown before changes are made */
+ fprintf(stderr,"Device is up, disconnecting from database \n");
+ was_up=1;
+
+ // close connection
+
+ }
+
+// This needs to be a unitary transaction for other interfaces as we don't
+// want to read/write data from an interface while its configuration is in an
+// inconsistent state. In this case (SQL databases, we still need this to be
+// a unitary transaction in case a new connection is created while the
+// configuration is in an inconsistent state.
+begin_critical_section(&devices_lock, "interface_gui.c:Sql_Database_change_data" );
+
+ // ** set the interface values needed to make a connection to a database **
+
+ // hostname
+ temp_ptr = XmTextFieldGetString(Sql_Database_host_data);
+ xastir_snprintf(devices[Sql_Database_port].device_host_name,
+ sizeof(devices[Sql_Database_port].device_host_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+ (void)remove_trailing_spaces(devices[Sql_Database_port].device_host_name);
+
+ //port
+ temp_ptr = XmTextFieldGetString(Sql_Database_iport_data);
+ devices[Sql_Database_port].sp=atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ //username
+ temp_ptr = XmTextFieldGetString(Sql_Database_username_data);
+ xastir_snprintf(devices[Sql_Database_port].database_username,
+ sizeof(devices[Sql_Database_port].database_username),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+ (void)remove_trailing_spaces(devices[Sql_Database_port].device_host_pswd);
+
+ //password
+ temp_ptr = XmTextFieldGetString(Sql_Database_password_data);
+ xastir_snprintf(devices[Sql_Database_port].device_host_pswd,
+ sizeof(devices[Sql_Database_port].device_host_pswd),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+ (void)remove_trailing_spaces(devices[Sql_Database_port].device_host_pswd);
+
+ // schema name
+ temp_ptr = XmTextFieldGetString(Sql_Database_schema_name_data);
+ xastir_snprintf(devices[Sql_Database_port].database_schema,
+ sizeof(devices[Sql_Database_port].database_schema),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+ (void)remove_trailing_spaces(devices[Sql_Database_port].database_schema);
+
+ // database type
+ cb_selected = FALSE;
+#ifdef USE_COMBO_BOX
+ XtVaGetValues(Sql_Database_dbms_data,XmNselectedPosition, &cb_selected, NULL);
+#else
+ // find out the value of the latest selection from the Sql_Databas_dbms_data_menu
+ cb_selected = sddd_value;
+#endif
+
+ if (cb_selected) {
+ devices[Sql_Database_port].database_type = cb_selected;
+ } else {
+ // If no selection,
+ // default to mysql non-spatial, unless postgis is available.
+#ifdef HAVE_POSTGIS
+ devices[Sql_Database_port].database_type = DB_POSTGIS;
+#endif /* HAVE_POSTGIS */
+#ifdef HAVE_MYSQL
+ devices[Sql_Database_port].database_type = DB_MYSQL;
+#endif /* HAVE_MYSQL */
+ }
+
+ // schema type
+ cb_selected = FALSE;
+ XtVaGetValues(Sql_Database_schema_type_data,XmNselectedPosition, &cb_selected, NULL);
+
+ if (cb_selected) {
+ devices[Sql_Database_port].database_schema_type = cb_selected;
+ } else {
+ // If no selection, default to simple schema.
+ devices[Sql_Database_port].database_schema_type = XASTIR_SCHEMA_SIMPLE;
+ }
+
+ // unix socket
+ temp_ptr = XmTextFieldGetString(Sql_Database_unix_socket_data);
+ xastir_snprintf(devices[Sql_Database_port].database_unix_socket,
+ sizeof(devices[Sql_Database_port].database_unix_socket),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+ (void)remove_trailing_spaces(devices[Sql_Database_port].database_unix_socket);
+
+ // reset the error message to a blank
+ xastir_snprintf(devices[Sql_Database_port].database_errormessage,
+ sizeof(devices[Sql_Database_port].database_errormessage),
+ " ");
+
+ // ** set additional interface values **
+
+ // comment to display on interface list
+ temp_ptr = XmTextFieldGetString(Sql_Database_comment);
+ xastir_snprintf(devices[Sql_Database_port].comment,
+ sizeof(devices[Sql_Database_port].comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+ (void)remove_trailing_spaces(devices[Sql_Database_port].comment);
+
+ // activate on startup
+ if(XmToggleButtonGetState(Sql_Database_active_on_startup))
+ devices[Sql_Database_port].connect_on_startup=1;
+ else
+ devices[Sql_Database_port].connect_on_startup=0;
+
+ // query on startup
+ if(XmToggleButtonGetState(Sql_Database_query_on_startup_data))
+ devices[Sql_Database_port].query_on_startup=1;
+ else
+ devices[Sql_Database_port].query_on_startup=0;
+
+ // allow saving data
+ if(XmToggleButtonGetState(Sql_Database_transmit_data))
+ devices[Sql_Database_port].transmit_data=1;
+ else
+ devices[Sql_Database_port].transmit_data=0;
+
+ // reconnect on database connection failure
+ if(XmToggleButtonGetState(Sql_Database_reconnect_data))
+ devices[Sql_Database_port].reconnect=1;
+ else
+ devices[Sql_Database_port].reconnect=0;
+
+ if (was_up) {
+ // If the connection was allready open when we started then reconnect
+ // and reopen the database connection with the new parameters.
+ if (openConnection(&devices[Sql_Database_port],&connections[Sql_Database_port])==1) {
+ port_data[Sql_Database_port].status = DEVICE_UP;
+ } else {
+ port_data[Sql_Database_port].status = DEVICE_ERROR;
+ }
+ }
+
+ /* add device type */
+ devices[Sql_Database_port].device_type=DEVICE_SQL_DATABASE;
+
+end_critical_section(&devices_lock, "interface_gui.c:Sql_Database_change_data" );
+
+ // Rebuild the interface control list
+ update_interface_list();
+
+ // close the dialog
+ Sql_Database_destroy_shell(widget,clientData,callData);
+ if (debug_level & 2)
+ fprintf(stderr,"Done storing sql interface parameters\n");
+}
+
+
+
+#ifndef USE_COMBO_BOX
+void sddd_menuCallback(Widget widget, XtPointer ptr, XtPointer callData) {
+ XtPointer userData;
+
+ XtVaGetValues(widget, XmNuserData, &userData, NULL);
+ //sddd_menu is zero based, constants for database types are one based.
+ sddd_value = (int)userData + 1;
+ if (debug_level & 4096)
+ fprintf(stderr,"Selected value on dbms pulldown: %d\n",sddd_value);
+}
+#endif // USE_COMBO_BOX
+
+
+
+
+
+/* dialog to obtain connection parameters for a SQL server (MySQL/Postgresql)
+ * database for spatialy enabled database support
+ */
+void Config_sql_Database( /*@unused@*/ Widget w, int config_type, int port) {
+ static Widget pane, form, button_ok, button_cancel, label_dbms, label_schema_type,
+ ihost, iport, password, unix_socket, error_message,
+ sep, comment, username, schema_name;
+ static Widget button_mysql_defaults; // set form values to defaults for mysql
+ static Widget button_postgis_defaults; // set form values to deaults for postgresql/postgis
+ int defaults_set; // Have defaults been set on form for new interface?
+ // Used to make only a single set defaults call when
+ // support for multiple types of dbms are available.
+
+ Atom delw;
+ char temp[40];
+ XmString cb_item;
+ XmString *cb_items[2];
+ int x;
+#ifndef USE_COMBO_BOX
+ int i; // loop counter
+ Arg args[12]; // available for XtSetArguments
+ char buf[18];
+ char *tmp;
+#endif // !USE_COMBO_BOX
+ /*
+ // configuration parameters for a sql server database
+ char database_username[20]; // username to use to connect to database
+ // default xastir
+ int database_type; // type of dbms (posgresql, mysql, etc)
+ // default mysql
+ char database_schema[20]; // name of database or schema to use
+ // default xastir
+ char database_errormessage[255]; // most recent error message from
+ attempting to make a
+ connection with using this descriptor.
+ int database_schema_type; // table structures to use in the database
+ A database schema could contain both APRSWorld
+ and XASTIR table structures, but a separate database
+ descriptor should be defined for each.
+ // default simple
+ char database_unix_socket[255]; // MySQL - unix socket parameter (path and
+ filename)
+ // device_host_name = hostname for database server
+ // sp = port on which to connect to database server (Not database_port)
+ // device_host_password = password to use to connect to database -- security issue needs to be addressed
+ */
+
+ if(!config_Sql_Database_dialog) {
+ // port is position in xastir interface list, not tcp port on which to connect
+ Sql_Database_port=port;
+
+ // SQL Server Database
+ config_Sql_Database_dialog = XtVaCreatePopupShell("SQL Server Database",
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Config_Database pane",xmPanedWindowWidgetClass, config_Sql_Database_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Config_Database form",xmFormWidgetClass, pane,
+ XmNfractionBase, 13,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ // Activate on startup
+ Sql_Database_active_on_startup = XtVaCreateManagedWidget(langcode("UNIOP00011"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ // DMBS
+ label_dbms = XtVaCreateManagedWidget("Database:",xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 15,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, Sql_Database_active_on_startup,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ // Combo box to pick dbms
+ cb_items [0] = (XmString *) XtMalloc ( sizeof (XmString) * 4 );
+ // Combo box items are defined by xastir_dbms_type, defined in db_gis.c
+ cb_items[0][0] = XmStringCreateLtoR( &xastir_dbms_type[1][0] , XmFONTLIST_DEFAULT_TAG);
+ cb_items[0][1] = XmStringCreateLtoR( &xastir_dbms_type[2][0] , XmFONTLIST_DEFAULT_TAG);
+ cb_items[0][2] = XmStringCreateLtoR( &xastir_dbms_type[3][0] , XmFONTLIST_DEFAULT_TAG);
+ // mysql
+ //cb_items[0][0] = XmStringCreateLtoR("MySQL (lat/long)", XmFONTLIST_DEFAULT_TAG);
+ // postgresql
+ //cb_items[0][1] = XmStringCreateLtoR("Postgres/Postgis", XmFONTLIST_DEFAULT_TAG);
+ // mysql with spatial extensions
+ //cb_items[0][2] = XmStringCreateLtoR("MySQL (spatial)", XmFONTLIST_DEFAULT_TAG);
+ cb_items[0][3] = NULL;
+#ifdef USE_COMBO_BOX
+ Sql_Database_dbms_data = XtVaCreateManagedWidget("select dbms", xmComboBoxWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, label_dbms,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNitems, cb_items[0],
+ XmNitemCount, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNcomboBoxType, XmDROP_DOWN_LIST,
+ XmNpositionMode, XmONE_BASED,
+ XmNmatchBehavior, XmQUICK_NAVIGATE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ sddd_widget = Sql_Database_dbms_data;
+#else
+ // lesstif, at least as of version 0.95 in 2008, doesn't fully support combo boxes.
+ //
+ // lesstif 0.94 doesn't support adding items to the list on creation through XmNitems
+ // lesstif 0.94 combo boxes don't have means to set currently selected value
+ // or to retrieve currently selected value.
+ //
+ // Need to replace combo boxes with a pull down menu when lesstif is used.
+ // See xpdf's XPDFViewer.cc/XPDFViewer.h for an example.
+ //
+ // Fake a combo box with a menu, as done by xpdf in in XPDFViewer.cc
+ //
+ // create widgets and populate menu
+ // sddd_ abbreviates name of single control that is being replaced: Sql_Database_dbms_data
+ // sddd_value // numberic value for the database dbms type
+ // sddd_button // picklist item
+ // sddd_menu // menu that acts as the picklist of dbms types
+ x = 0;
+ XtSetArg(args[x], XmNmarginWidth, 0); ++x;
+ XtSetArg(args[x], XmNmarginHeight, 0); ++x;
+ sddd_menuPane = XmCreatePulldownMenu(form,"sddd_menuPane", args, x);
+ //sddd_menu is zero based, constants for database types are one based.
+ //sddd_value is set to match constants in callback.
+ for (i=0;i<3;i++) {
+ x = 0;
+ XmStringGetLtoR(cb_items[0][i],XmFONTLIST_DEFAULT_TAG,&tmp);
+ XtSetArg(args[x], XmNlabelString, cb_items[0][i]); x++;
+ XtSetArg(args[x], XmNuserData, (XtPointer)i); x++;
+ XtSetArg(args[x], XmNfontList, fontlist1); x++;
+ sprintf(buf,"button%d",i);
+ sddd_button = XmCreatePushButton(sddd_menuPane, buf, args, x);
+ XtManageChild(sddd_button);
+ XtAddCallback(sddd_button, XmNactivateCallback, sddd_menuCallback, config_Sql_Database_dialog);
+ sddd_buttons[i] = sddd_button;
+ }
+ x = 0;
+ XtSetArg(args[x], XmNleftAttachment, XmATTACH_WIDGET); ++x;
+ XtSetArg(args[x], XmNleftWidget, label_dbms); ++x;
+ XtSetArg(args[x], XmNtopAttachment, XmATTACH_FORM); ++x;
+ XtSetArg(args[x], XmNmarginWidth, 0); ++x;
+ XtSetArg(args[x], XmNmarginHeight, 0); ++x;
+ XtSetArg(args[x], XmNtopOffset, 7); ++x;
+ XtSetArg(args[x], XmNleftOffset, 1); ++x;
+ XtSetArg(args[x], XmNsubMenuId, sddd_menuPane); ++x;
+ sddd_menu = XmCreateOptionMenu(form, "sddd_Menu", args, x);
+ XtManageChild(sddd_menu);
+ sddd_widget = sddd_menu;
+#endif
+ // free up the XmStrings used to create the picklist
+ x=0;
+ while ( cb_items[0][x] )
+ XmStringFree ( cb_items[0][x++] );
+ x=0;
+ XtFree ( (char *) cb_items[0] );
+
+ // *** when localizing these strings propagate the localizations to
+ // the set default functions above and to constants for picklist
+ // selection recognition. ***
+ //cb_item = XmStringCreateLtoR(&xastir_dbms_type[DB_MYSQL][0], XmFONTLIST_DEFAULT_TAG);
+ //XmComboBoxAddItem(Sql_Database_dbms_data,cb_item,1,1);
+ //XmStringFree(cb_item);
+ //cb_item = XmStringCreateLtoR(&xastir_dbms_type[DB_POSTGIS][0], XmFONTLIST_DEFAULT_TAG);
+ //XmComboBoxAddItem(Sql_Database_dbms_data,cb_item,2,1);
+ //XmStringFree(cb_item);
+ //cb_item = XmStringCreateLtoR(&xastir_dbms_type[DB_MYSQL_SPATIAL][0], XmFONTLIST_DEFAULT_TAG);
+ //XmComboBoxAddItem(Sql_Database_dbms_data,cb_item,3,1);
+ //XmStringFree(cb_item);
+
+ // Schema Type
+ label_schema_type = XtVaCreateManagedWidget("With Tables for",xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 15,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, sddd_widget,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ // Combo box to pick schema
+ Sql_Database_schema_type_data = XtVaCreateManagedWidget("Tables to use", xmComboBoxWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, label_schema_type,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNcomboBoxType, XmDROP_DOWN_LIST,
+ XmNpositionMode, XmONE_BASED,
+ XmNvisibleItemCount, 3,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // *** need to add constants for order and localization ***
+ // ? use an array - schm_typ[XASTIR_SCHEMA_SIMPLE]=langcode("codeforxastirsimple").... ?
+ // ?or some other form of key-value pairs?
+
+ // simple
+ //cb_item = XmStringCreateLtoR("Xastir - simple", XmFONTLIST_DEFAULT_TAG);
+ cb_item = XmStringCreateLtoR(&xastir_schema_type[XASTIR_SCHEMA_SIMPLE][0], XmFONTLIST_DEFAULT_TAG);
+ XmComboBoxAddItem(Sql_Database_schema_type_data,cb_item,1,1);
+ XmStringFree(cb_item);
+
+/* not yet implemented
+ // aprs world
+ cb_item = XmStringCreateLtoR("APRSWorld", XmFONTLIST_DEFAULT_TAG);
+ XmComboBoxAddItem(cad_line_style_data,cb_item,2,1);
+ XmStringFree(cb_item);
+
+ // full
+ cb_item = XmStringCreateLtoR("Xastir - full", XmFONTLIST_DEFAULT_TAG);
+ XmComboBoxAddItem(cad_line_style_data,cb_item,2,1);
+ XmStringFree(cb_item);
+
+ // cad
+ cb_item = XmStringCreateLtoR("Xastir - CAD", XmFONTLIST_DEFAULT_TAG);
+ XmComboBoxAddItem(cad_line_style_data,cb_item,2,1);
+ XmStringFree(cb_item);
+*/
+
+ // Store data
+ Sql_Database_transmit_data = XtVaCreateManagedWidget("Store incoming data",xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sddd_widget,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Retrieve data on start
+ Sql_Database_query_on_startup_data = XtVaCreateManagedWidget("Load data on start",xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sddd_widget,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, Sql_Database_transmit_data,
+ XmNleftOffset, 15,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ // put retieve now button here.
+
+ // hostname
+ ihost = XtVaCreateManagedWidget(langcode("WPUPCFID02"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_transmit_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ Sql_Database_host_data = XtVaCreateManagedWidget("Config_Database host_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 55,
+ XmNmaxLength, 255,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_transmit_data,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ihost,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // tcp port for server, not xastir interface port
+ // port
+ iport = XtVaCreateManagedWidget(langcode("WPUPCFID03"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_transmit_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, Sql_Database_host_data,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Sql_Database_iport_data = XtVaCreateManagedWidget("Config_Database port_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 5,
+ XmNmaxLength, 6,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_transmit_data,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, iport,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Username
+ username = XtVaCreateManagedWidget("Username",xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_host_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Sql_Database_username_data = XtVaCreateManagedWidget("Config_Database username_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNmaxLength, 25,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_host_data,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, username,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ // Password
+ password = XtVaCreateManagedWidget("Password",xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_host_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, Sql_Database_username_data,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Sql_Database_password_data = XtVaCreateManagedWidget("Config_Database password_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNmaxLength, 20,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, password,
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_host_data,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ // Schema/Database name
+ schema_name = XtVaCreateManagedWidget("Schema/Database name",xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_username_data,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Sql_Database_schema_name_data= XtVaCreateManagedWidget("Config_Database schema_name_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNmaxLength, 50,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, schema_name,
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_username_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // MySQL unix socket
+ unix_socket = XtVaCreateManagedWidget("MySQL unix socket",xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_username_data,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, Sql_Database_schema_name_data,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ Sql_Database_unix_socket_data = XtVaCreateManagedWidget("Config_Database unix_socket_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 30,
+ XmNmaxLength, 190,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, unix_socket,
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_username_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // comment
+ comment = XtVaCreateManagedWidget(langcode("WPUPCFS017"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_schema_name_data,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ Sql_Database_comment = XtVaCreateManagedWidget("Config_Database comment", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 49,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_schema_name_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, comment,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // reconnect on network failure
+ Sql_Database_reconnect_data = XtVaCreateManagedWidget(langcode("WPUPCFID11"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_comment,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ // most recent error
+ error_message = XtVaCreateManagedWidget("Most Recent Error:",xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_reconnect_data,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ // error message isn't editable and isn't saved
+ Sql_Database_errormessage_data = XtVaCreateManagedWidget("Config_Database error_message", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 79,
+ XmNwidth, ((79*7)+2),
+ XmNmaxLength, 255,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_reconnect_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, error_message,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // separator line
+ sep = XtVaCreateManagedWidget("Config_Database sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, Sql_Database_errormessage_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ // button: MySQL Defaults
+ button_mysql_defaults = XtVaCreateManagedWidget("MySQL Defaults",xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ // button: Postgis Defaults
+ button_postgis_defaults = XtVaCreateManagedWidget("Postgis Defaults",xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 4,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 6,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ // button: OK
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 7,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 9,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ // button: Cancel
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 12,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtSetSensitive(button_mysql_defaults,FALSE);
+#ifdef HAVE_MYSQL
+ XtSetSensitive(button_mysql_defaults,TRUE);
+ XtAddCallback(button_mysql_defaults,
+ XmNactivateCallback, Sql_Database_set_defaults_mysql, config_Sql_Database_dialog);
+#endif /* HAVE_MYSQL */
+ XtSetSensitive(button_postgis_defaults,FALSE);
+#ifdef HAVE_POSTGIS
+ XtSetSensitive(button_postgis_defaults,TRUE);
+ XtAddCallback(button_postgis_defaults,
+ XmNactivateCallback, Sql_Database_set_defaults_postgis, config_Sql_Database_dialog);
+#endif /* HAVE_POSTGIS */
+ XtAddCallback(button_ok,
+ XmNactivateCallback, Sql_Database_change_data, config_Sql_Database_dialog);
+ XtAddCallback(button_cancel,
+ XmNactivateCallback, Sql_Database_destroy_shell, config_Sql_Database_dialog);
+
+ pos_dialog(config_Sql_Database_dialog);
+
+ delw = XmInternAtom(XtDisplay(config_Sql_Database_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(config_Sql_Database_dialog,
+ delw, Sql_Database_destroy_shell, (XtPointer)config_Sql_Database_dialog);
+
+ if (config_type==0) {
+ /* first time port */
+ // Default settings for a new interface.
+ defaults_set = 0;
+#ifdef HAVE_MYSQL
+ Sql_Database_set_defaults_mysql(config_Sql_Database_dialog,NULL,NULL);
+ defaults_set = 1;
+#endif /* HAVE_MYSQL */
+#ifdef HAVE_POSTGIS
+ if (defaults_set==0) {
+ // mysql support not available, use postgis
+ Sql_Database_set_defaults_postgis(config_Sql_Database_dialog,NULL,NULL);
+ }
+#endif /* HAVE_POSTGIS */
+ } else {
+ /* reconfigure an existing interface */
+
+// why critical section here? We are reading data from an existing configuration,
+// not changing the configuration while the interface might be in use.
+begin_critical_section(&devices_lock, "interface_gui.c:Config_sql_Database" );
+
+ // *** need to look up localized string for database_type ***
+ cb_item = XmStringCreateLtoR(&xastir_dbms_type[devices[Sql_Database_port].database_type][0], XmFONTLIST_DEFAULT_TAG);
+#ifdef USE_COMBO_BOX
+ XmComboBoxSelectItem(Sql_Database_dbms_data,cb_item);
+ XmComboBoxSetItem(Sql_Database_dbms_data,cb_item);
+#else
+ //sddd_menu is zero based, constants for database types are one based.
+ //sddd_value matches constants.
+ XtVaSetValues(sddd_menu, XmNmenuHistory,
+ sddd_buttons[devices[Sql_Database_port].database_type - 1 ], NULL);
+ sddd_value = devices[Sql_Database_port].database_type;
+#endif
+ XmStringFree(cb_item);
+
+ cb_item = XmStringCreateLtoR(&xastir_schema_type[devices[Sql_Database_port].database_schema_type][0], XmFONTLIST_DEFAULT_TAG);
+ XmComboBoxSelectItem(Sql_Database_schema_type_data,cb_item);
+ XmComboBoxSetItem(Sql_Database_schema_type_data,cb_item);
+ XmStringFree(cb_item);
+
+ if (devices[Sql_Database_port].connect_on_startup)
+ XmToggleButtonSetState(Sql_Database_active_on_startup,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(Sql_Database_active_on_startup,FALSE,FALSE);
+
+ if (devices[Sql_Database_port].query_on_startup)
+ XmToggleButtonSetState(Sql_Database_query_on_startup_data,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(Sql_Database_query_on_startup_data,FALSE,FALSE);
+
+
+ if (devices[Sql_Database_port].transmit_data)
+ XmToggleButtonSetState(Sql_Database_transmit_data,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(Sql_Database_transmit_data,FALSE,FALSE);
+
+ XmTextFieldSetString(Sql_Database_host_data,devices[Sql_Database_port].device_host_name);
+ XmTextFieldSetString(Sql_Database_schema_name_data,devices[Sql_Database_port].database_schema);
+ xastir_snprintf(temp, sizeof(temp), "%d", devices[Sql_Database_port].sp);
+ XmTextFieldSetString(Sql_Database_iport_data,temp);
+ XmTextFieldSetString(Sql_Database_username_data,devices[Sql_Database_port].database_username);
+ XmTextFieldSetString(Sql_Database_password_data,devices[Sql_Database_port].device_host_pswd);
+ XmTextFieldSetString(Sql_Database_unix_socket_data,devices[Sql_Database_port].database_unix_socket);
+ XmTextFieldSetString(Sql_Database_comment,devices[Sql_Database_port].comment);
+ // display most recent error message
+ XmTextFieldSetString(Sql_Database_errormessage_data,devices[Sql_Database_port].database_errormessage);
+
+ if (devices[Sql_Database_port].reconnect)
+ XmToggleButtonSetState(Sql_Database_reconnect_data,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(Sql_Database_reconnect_data,FALSE,FALSE);
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_sql_Database" );
+
+ }
+ XtManageChild(form);
+ XtManageChild(pane);
+
+ XtPopup(config_Sql_Database_dialog,XtGrabNone);
+ fix_dialog_size(config_Sql_Database_dialog);
+ } else {
+ (void)XRaiseWindow(XtDisplay(config_Sql_Database_dialog), XtWindow(config_Sql_Database_dialog));
+ }
+}
+#endif /* HAVE_DB */
+
+
+
+
+/*****************************************************/
+/* Configure AGWPE Server GUI */
+/*****************************************************/
+
+/**** AGWPE CONFIGURE ******/
+Widget config_AGWPE_dialog = (Widget)NULL;
+Widget AGWPE_active_on_startup;
+Widget AGWPE_host_data;
+Widget AGWPE_port_data;
+Widget AGWPE_comment;
+Widget AGWPE_password_data;
+Widget AGWPE_transmit_data;
+Widget AGWPE_igate_data;
+Widget AGWPE_reconnect_data;
+Widget AGWPE_unproto1_data;
+Widget AGWPE_unproto2_data;
+Widget AGWPE_unproto3_data;
+Widget AGWPE_relay_digipeat;
+Widget AGWPE_radioport_data;
+int AGWPE_port;
+
+
+
+
+
+void AGWPE_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ config_AGWPE_dialog = (Widget)NULL;
+ if (choose_interface_dialog != NULL)
+ Choose_interface_destroy_shell(choose_interface_dialog,choose_interface_dialog,NULL);
+
+ choose_interface_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void AGWPE_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ int was_up;
+ char *temp_ptr;
+
+
+ busy_cursor(appshell);
+ was_up=0;
+ if (get_device_status(AGWPE_port) == DEVICE_IN_USE) {
+ /* if active shutdown before changes are made */
+ /*fprintf(stderr,"Device is up, shutting down\n");*/
+ (void)del_device(AGWPE_port);
+ was_up=1;
+ usleep(1000000); // Wait for one second
+ }
+
+begin_critical_section(&devices_lock, "interface_gui.c:AGWPE_change_data" );
+
+ devices[AGWPE_port].igate_options=device_igate_options;
+
+ temp_ptr = XmTextFieldGetString(AGWPE_host_data);
+ xastir_snprintf(devices[AGWPE_port].device_host_name,
+ sizeof(devices[AGWPE_port].device_host_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[AGWPE_port].device_host_name);
+
+ temp_ptr = XmTextFieldGetString(AGWPE_password_data);
+ xastir_snprintf(devices[AGWPE_port].device_host_pswd,
+ sizeof(devices[AGWPE_port].device_host_pswd),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[AGWPE_port].device_host_pswd);
+
+ temp_ptr = XmTextFieldGetString(AGWPE_comment);
+ xastir_snprintf(devices[AGWPE_port].comment,
+ sizeof(devices[AGWPE_port].comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[AGWPE_port].comment);
+
+ temp_ptr = XmTextFieldGetString(AGWPE_port_data);
+ devices[AGWPE_port].sp=atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(AGWPE_unproto1_data);
+ xastir_snprintf(devices[AGWPE_port].unproto1,
+ sizeof(devices[AGWPE_port].unproto1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[AGWPE_port].unproto1);
+
+ if(check_unproto_path(devices[AGWPE_port].unproto1)) {
+ popup_message_always(langcode("WPUPCFT042"),
+ langcode("WPUPCFT043"));
+ }
+
+ temp_ptr = XmTextFieldGetString(AGWPE_unproto2_data);
+ xastir_snprintf(devices[AGWPE_port].unproto2,
+ sizeof(devices[AGWPE_port].unproto2),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[AGWPE_port].unproto2);
+
+ if(check_unproto_path(devices[AGWPE_port].unproto2)) {
+ popup_message_always(langcode("WPUPCFT042"),
+ langcode("WPUPCFT043"));
+ }
+
+ temp_ptr = XmTextFieldGetString(AGWPE_unproto3_data);
+ xastir_snprintf(devices[AGWPE_port].unproto3,
+ sizeof(devices[AGWPE_port].unproto3),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[AGWPE_port].unproto3);
+
+ if(check_unproto_path(devices[AGWPE_port].unproto3)) {
+ popup_message_always(langcode("WPUPCFT042"),
+ langcode("WPUPCFT043"));
+ }
+
+ temp_ptr = XmTextFieldGetString(AGWPE_igate_data);
+ xastir_snprintf(devices[AGWPE_port].unproto_igate,
+ sizeof(devices[AGWPE_port].unproto_igate),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[AGWPE_port].unproto_igate);
+
+ if(check_unproto_path(devices[AGWPE_port].unproto_igate)) {
+ popup_message_always(langcode("WPUPCFT044"),
+ langcode("WPUPCFT043"));
+ }
+
+
+ temp_ptr = XmTextFieldGetString(AGWPE_radioport_data);
+ xastir_snprintf(devices[AGWPE_port].device_host_filter_string,
+ sizeof(devices[AGWPE_port].device_host_filter_string),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(devices[AGWPE_port].device_host_filter_string);
+
+ if(XmToggleButtonGetState(AGWPE_active_on_startup))
+ devices[AGWPE_port].connect_on_startup=1;
+ else
+ devices[AGWPE_port].connect_on_startup=0;
+
+ if(XmToggleButtonGetState(AGWPE_transmit_data))
+ devices[AGWPE_port].transmit_data=1;
+ else
+ devices[AGWPE_port].transmit_data=0;
+
+//WE7U
+// if(XmToggleButtonGetState(AGWPE_relay_digipeat))
+// devices[AGWPE_port].relay_digipeat=1;
+// else
+ devices[AGWPE_port].relay_digipeat=0;
+
+ if(XmToggleButtonGetState(AGWPE_reconnect_data))
+ devices[AGWPE_port].reconnect=1;
+ else
+ devices[AGWPE_port].reconnect=0;
+
+// n8ysz 20041213
+// if (devices[AGWPE_port].connect_on_startup==1 || was_up) {
+ if ( was_up) {
+ (void)add_device(AGWPE_port,
+ DEVICE_NET_AGWPE,
+ devices[AGWPE_port].device_host_name,
+ devices[AGWPE_port].device_host_pswd,
+ devices[AGWPE_port].sp,
+ 0,
+ 0,
+ devices[AGWPE_port].reconnect,
+ "");
+ }
+
+ /* delete list */
+// modify_device_list(4,0);
+
+
+ /* add device type */
+ devices[AGWPE_port].device_type=DEVICE_NET_AGWPE;
+
+ /* rebuild list */
+// modify_device_list(3,0);
+
+
+end_critical_section(&devices_lock, "interface_gui.c:AGWPE_change_data" );
+
+ // Rebuild the interface control list
+ update_interface_list();
+
+ AGWPE_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void Config_AGWPE( /*@unused@*/ Widget w, int config_type, int port) {
+ static Widget pane, form, button_ok, button_cancel,
+ ihost, iport, password, password_fl, sep,
+ igate, igate_box, igate_o_0, igate_o_1, igate_o_2,
+ igate_label, frame, proto, proto1, proto2, proto3,
+ radioport_label, comment;
+ Atom delw;
+ char temp[40];
+ Arg al[50]; // Arg list
+ register unsigned int ac = 0; // Arg Count
+
+ if(!config_AGWPE_dialog) {
+ AGWPE_port=port;
+ config_AGWPE_dialog = XtVaCreatePopupShell(langcode("WPUPCFIA01"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Config_AGWPE pane",xmPanedWindowWidgetClass, config_AGWPE_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Config_AGWPE form",xmFormWidgetClass, pane,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ AGWPE_active_on_startup = XtVaCreateManagedWidget(langcode("UNIOP00011"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AGWPE_transmit_data = XtVaCreateManagedWidget(langcode("UNIOP00010"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, AGWPE_active_on_startup,
+ XmNleftOffset ,35,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AGWPE_relay_digipeat = XtVaCreateManagedWidget(langcode("UNIOP00030"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, AGWPE_transmit_data,
+ XmNleftOffset ,35,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ ihost = XtVaCreateManagedWidget(langcode("WPUPCFIA02"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, AGWPE_transmit_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AGWPE_host_data = XtVaCreateManagedWidget("Config_AGWPE host_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 30,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, AGWPE_transmit_data,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ihost,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ iport = XtVaCreateManagedWidget(langcode("WPUPCFIA03"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget,AGWPE_transmit_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget,AGWPE_host_data,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AGWPE_port_data = XtVaCreateManagedWidget("Config_AGWPE port_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 5,
+ XmNwidth, ((5*7)+2),
+ XmNmaxLength, 6,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, AGWPE_transmit_data,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, iport,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ comment = XtVaCreateManagedWidget(langcode("WPUPCFS017"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, AGWPE_transmit_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, AGWPE_port_data,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AGWPE_comment = XtVaCreateManagedWidget("Config_AGWPE comment", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 49,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, AGWPE_transmit_data,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, comment,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ password = XtVaCreateManagedWidget(langcode("WPUPCFIA09"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ihost,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AGWPE_password_data = XtVaCreateManagedWidget("Config_AGWPE password_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 20,
+ XmNmaxLength, 20,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, password,
+ XmNleftOffset, 10,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, ihost,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ password_fl = XtVaCreateManagedWidget(langcode("WPUPCFIA10"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ihost,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget,AGWPE_password_data,
+ XmNleftOffset,20,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ AGWPE_reconnect_data = XtVaCreateManagedWidget(langcode("WPUPCFIA11"),xmToggleButtonWidgetClass,form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, password,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ radioport_label = XtVaCreateManagedWidget(langcode("WPUPCFIA15"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, password,
+ XmNtopOffset, 25,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, AGWPE_reconnect_data,
+ XmNleftOffset, 50,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AGWPE_radioport_data = XtVaCreateManagedWidget("Config_AGWPE radioport_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 3,
+ XmNmaxLength, 3 ,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, radioport_label,
+ XmNleftOffset, 10,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, password,
+ XmNtopOffset, 20,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ frame = XtVaCreateManagedWidget("Config_AGWPE frame", xmFrameWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, AGWPE_reconnect_data,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ igate = XtVaCreateManagedWidget(langcode("IGPUPCF000"),xmLabelWidgetClass, frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Set args for color
+ ac=0;
+ XtSetArg(al[ac], XmNbackground, colors[0xff]); ac++;
+
+
+ igate_box = XmCreateRadioBox(frame,"Config_AGWPE IGate box",al,ac);
+
+ XtVaSetValues(igate_box,XmNorientation, XmVERTICAL,XmNnumColumns,2,NULL);
+
+ igate_o_0 = XtVaCreateManagedWidget(langcode("IGPUPCF001"),xmToggleButtonGadgetClass,
+ igate_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(igate_o_0,XmNvalueChangedCallback,igate_toggle,"0");
+
+ igate_o_1 = XtVaCreateManagedWidget(langcode("IGPUPCF002"),xmToggleButtonGadgetClass,
+ igate_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(igate_o_1,XmNvalueChangedCallback,igate_toggle,"1");
+
+ igate_o_2 = XtVaCreateManagedWidget(langcode("IGPUPCF003"),xmToggleButtonGadgetClass,
+ igate_box,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(igate_o_2,XmNvalueChangedCallback,igate_toggle,"2");
+
+ proto = XtVaCreateManagedWidget(langcode("WPUPCFT011"), xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, frame,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPCFT012"), VERSIONFRM);
+
+ proto1 = XtVaCreateManagedWidget(temp, xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto,
+ XmNtopOffset, 12,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 45,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AGWPE_unproto1_data = XtVaCreateManagedWidget("Config_AGWPE protopath1", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, proto1,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPCFT013"), VERSIONFRM);
+
+ proto2 = XtVaCreateManagedWidget(temp, xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto1,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 45,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AGWPE_unproto2_data = XtVaCreateManagedWidget("Config_AGWPE protopath2", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, AGWPE_unproto1_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, proto2,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ xastir_snprintf(temp, sizeof(temp), langcode("WPUPCFT014"), VERSIONFRM);
+
+ proto3 = XtVaCreateManagedWidget(temp, xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto2,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 45,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ AGWPE_unproto3_data = XtVaCreateManagedWidget("Config_AGWPE protopath3", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, AGWPE_unproto2_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, proto3,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("IGPUPCF004"));
+ igate_label = XtVaCreateManagedWidget(temp, xmLabelWidgetClass, form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, proto3,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 45,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ AGWPE_igate_data = XtVaCreateManagedWidget("Config_AGWPE igate_data", xmTextFieldWidgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 40,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, AGWPE_unproto3_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, igate_label,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ sep = XtVaCreateManagedWidget("Config_AGWPE sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, AGWPE_igate_data,
+ XmNtopOffset, 14,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, AGWPE_change_data, config_AGWPE_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, AGWPE_destroy_shell, config_AGWPE_dialog);
+
+ pos_dialog(config_AGWPE_dialog);
+
+ delw = XmInternAtom(XtDisplay(config_AGWPE_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(config_AGWPE_dialog, delw, AGWPE_destroy_shell, (XtPointer)config_AGWPE_dialog);
+
+ if (config_type==0) {
+ /* first time port */
+ XmToggleButtonSetState(AGWPE_active_on_startup,TRUE,FALSE);
+ XmToggleButtonSetState(AGWPE_transmit_data,TRUE,FALSE);
+ //XmTextFieldSetString(AGWPE_host_data,"first.aprs.net");
+ XmTextFieldSetString(AGWPE_host_data,"localhost");
+ XmTextFieldSetString(AGWPE_port_data,"8000");
+ XmTextFieldSetString(AGWPE_comment,"");
+ XmToggleButtonSetState(AGWPE_reconnect_data,FALSE,FALSE);
+ XmToggleButtonSetState(AGWPE_relay_digipeat, FALSE, FALSE);
+ device_igate_options=0;
+ XmToggleButtonSetState(igate_o_0,TRUE,FALSE);
+ XmTextFieldSetString(AGWPE_unproto1_data,"WIDE2-2");
+ XmTextFieldSetString(AGWPE_unproto2_data,"");
+ XmTextFieldSetString(AGWPE_unproto3_data,"");
+ XmTextFieldSetString(AGWPE_igate_data,"");
+ XmTextFieldSetString(AGWPE_radioport_data,"1");
+
+//WE7U
+// Keep this statement until we get relay digipeating functional for
+// this interface.
+XtSetSensitive(AGWPE_relay_digipeat, FALSE);
+
+ }
+ else {
+ /* reconfig */
+
+begin_critical_section(&devices_lock, "interface_gui.c:Config_AGWPE" );
+
+ if (devices[AGWPE_port].connect_on_startup)
+ XmToggleButtonSetState(AGWPE_active_on_startup,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(AGWPE_active_on_startup,FALSE,FALSE);
+
+ if (devices[AGWPE_port].transmit_data)
+ XmToggleButtonSetState(AGWPE_transmit_data,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(AGWPE_transmit_data,FALSE,FALSE);
+
+// if (devices[AGWPE_port].relay_digipeat)
+// XmToggleButtonSetState(AGWPE_relay_digipeat, TRUE, FALSE);
+// else
+ XmToggleButtonSetState(AGWPE_relay_digipeat, FALSE, FALSE);
+
+// if (devices[AGWPE_port].transmit_data) {
+// XtSetSensitive(AGWPE_relay_digipeat, TRUE);
+// }
+// else
+ XtSetSensitive(AGWPE_relay_digipeat, FALSE);
+
+ XmTextFieldSetString(AGWPE_host_data,devices[AGWPE_port].device_host_name);
+ xastir_snprintf(temp, sizeof(temp), "%d", devices[AGWPE_port].sp);
+ XmTextFieldSetString(AGWPE_port_data,temp);
+ XmTextFieldSetString(AGWPE_password_data,devices[AGWPE_port].device_host_pswd);
+ XmTextFieldSetString(AGWPE_comment,devices[AGWPE_port].comment);
+
+ if (devices[AGWPE_port].reconnect)
+ XmToggleButtonSetState(AGWPE_reconnect_data,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(AGWPE_reconnect_data,FALSE,FALSE);
+
+ XmTextFieldSetString(AGWPE_radioport_data,devices[AGWPE_port].device_host_filter_string);
+
+ switch (devices[AGWPE_port].igate_options) {
+ case(0):
+ XmToggleButtonSetState(igate_o_0,TRUE,FALSE);
+ device_igate_options=0;
+ break;
+
+ case(1):
+ XmToggleButtonSetState(igate_o_1,TRUE,FALSE);
+ device_igate_options=1;
+ break;
+
+ case(2):
+ XmToggleButtonSetState(igate_o_2,TRUE,FALSE);
+ device_igate_options=2;
+ break;
+
+ default:
+ XmToggleButtonSetState(igate_o_0,TRUE,FALSE);
+ device_igate_options=0;
+ break;
+ }
+
+ XmTextFieldSetString(AGWPE_unproto1_data,devices[AGWPE_port].unproto1);
+ XmTextFieldSetString(AGWPE_unproto2_data,devices[AGWPE_port].unproto2);
+ XmTextFieldSetString(AGWPE_unproto3_data,devices[AGWPE_port].unproto3);
+ XmTextFieldSetString(AGWPE_igate_data,devices[AGWPE_port].unproto_igate);
+
+end_critical_section(&devices_lock, "interface_gui.c:Config_AGWPE" );
+
+ }
+ XtManageChild(igate_box);
+ XtManageChild(form);
+ XtManageChild(pane);
+
+ XtPopup(config_AGWPE_dialog,XtGrabNone);
+ fix_dialog_size(config_AGWPE_dialog);
+ } else {
+ (void)XRaiseWindow(XtDisplay(config_AGWPE_dialog), XtWindow(config_AGWPE_dialog));
+ }
+}
+
+
+
+
+
+/*****************************************************/
+/* Configure Interface GUI */
+/*****************************************************/
+
+int are_shells_up(void) {
+ int up;
+
+ up=1;
+ if (config_TNC_dialog) {
+ (void)XRaiseWindow(XtDisplay(config_TNC_dialog), XtWindow(config_TNC_dialog));
+ } else {
+ if (config_GPS_dialog) {
+ (void)XRaiseWindow(XtDisplay(config_GPS_dialog), XtWindow(config_GPS_dialog));
+ } else {
+ if (config_WX_dialog) {
+ (void)XRaiseWindow(XtDisplay(config_WX_dialog), XtWindow(config_WX_dialog));
+ } else {
+ if (config_NGPS_dialog) {
+ (void)XRaiseWindow(XtDisplay(config_NGPS_dialog), XtWindow(config_NGPS_dialog));
+ } else {
+ if (config_AX25_dialog) {
+ (void)XRaiseWindow(XtDisplay(config_AX25_dialog), XtWindow(config_AX25_dialog));
+ } else {
+ if (config_Inet_dialog) {
+ (void)XRaiseWindow(XtDisplay(config_Inet_dialog), XtWindow(config_Inet_dialog));
+ } else {
+ if (config_NWX_dialog) {
+ (void)XRaiseWindow(XtDisplay(config_NWX_dialog), XtWindow(config_NWX_dialog));
+ } else {
+ if (config_Database_dialog) {
+ (void)XRaiseWindow(XtDisplay(config_Database_dialog), XtWindow(config_Database_dialog));
+ } else {
+#ifdef HAVE_DB
+ if (config_Sql_Database_dialog) {
+ (void)XRaiseWindow(XtDisplay(config_Sql_Database_dialog), XtWindow(config_Sql_Database_dialog));
+ } else {
+
+#endif /* HAVE_DB */
+ if (config_AGWPE_dialog) {
+ (void)XRaiseWindow(XtDisplay(config_AGWPE_dialog), XtWindow(config_AGWPE_dialog));
+ } else up=0;
+#ifdef HAVE_DB
+ }
+#endif /* HAVE_DB */
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return(up);
+}
+
+
+
+
+
+void Choose_interface_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ if (are_shells_up()==0) {
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ choose_interface_dialog = (Widget)NULL;
+ }
+}
+
+
+
+
+
+void modify_device_list(int option, int port) {
+ int i,n;
+ char temp[150];
+ char temp2[150];
+ XmString str_ptr;
+
+
+ n=1;
+ for (i=0; i < MAX_IFACE_DEVICES; i++) {
+ if (devices[i].device_type!=DEVICE_NONE) {
+ switch (option) {
+ case 0 :
+ /* delete entire list available */
+ XmListDeleteAllItems(control_iface_list);
+ return; // Exit routine
+ break;
+
+ case 1 :
+ /* delete item pointed to by port */
+ if (i==port)
+ XmListDeletePos(control_iface_list,n);
+ n++;
+ break;
+
+ case 2 :
+ /* create item list */
+ /* format list for device modify*/
+ switch (devices[i].device_type) {
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_GPS:
+ case DEVICE_SERIAL_WX:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ langcode("IFDIN00000"),
+ langcode("UNIOP00006"),
+ i,
+ dtype[devices[i].device_type].device_name,
+ devices[i].device_name,
+ devices[i].comment);
+ strncat(temp,
+ " ",
+ sizeof(temp) - 1 - strlen(temp));
+ break;
+
+ case DEVICE_SERIAL_MKISS_TNC:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ langcode("IFDIN00001"),
+ langcode("UNIOP00006"),
+ i,
+ dtype[devices[i].device_type].device_name,
+ devices[i].device_name,
+ atoi(devices[i].radio_port),
+ devices[i].comment);
+ strncat(temp,
+ " ",
+ sizeof(temp) - 1 - strlen(temp));
+ break;
+
+ case DEVICE_NET_DATABASE:
+ case DEVICE_SQL_DATABASE:
+ case DEVICE_NET_STREAM:
+ case DEVICE_NET_GPSD:
+ case DEVICE_NET_WX:
+ case DEVICE_NET_AGWPE:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ langcode("IFDIN00001"),
+ langcode("UNIOP00006"),
+ i,
+ dtype[devices[i].device_type].device_name,
+ devices[i].device_host_name,
+ devices[i].sp,
+ devices[i].comment);
+ strncat(temp,
+ " ",
+ sizeof(temp) - 1 - strlen(temp));
+ break;
+
+ case DEVICE_AX25_TNC:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ langcode("IFDIN00002"),
+ langcode("UNIOP00006"),
+ i,
+ dtype[devices[i].device_type].device_name,
+ devices[i].device_name,
+ devices[i].comment);
+ strncat(temp,
+ " ",
+ sizeof(temp) - 1 - strlen(temp));
+ break;
+
+ default:
+ break;
+ }
+ /* look at list data (Must be "Device" port#) */
+ XmListAddItem(control_iface_list, str_ptr = XmStringCreateLtoR(temp,XmFONTLIST_DEFAULT_TAG),n++);
+
+ XmStringFree(str_ptr);
+ break;
+
+ case 3 :
+ /* create item list */
+ /* format list for device control*/
+ if (port_data[i].active==DEVICE_IN_USE) {
+ switch (port_data[i].status) {
+ case DEVICE_DOWN:
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ langcode("IFDIN00006"));
+ break;
+
+ case DEVICE_UP:
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ langcode("IFDIN00007"));
+ break;
+
+ case DEVICE_ERROR:
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ langcode("IFDIN00008"));
+ break;
+
+ default:
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ langcode("IFDIN00009"));
+ break;
+ }
+ } else {
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ langcode("IFDIN00006"));
+ }
+ switch (devices[i].device_type) {
+ case DEVICE_SERIAL_TNC:
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ case DEVICE_SERIAL_GPS:
+ case DEVICE_SERIAL_WX:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ langcode("IFDIN00003"),
+ langcode("UNIOP00006"),
+ i,
+ temp2,
+ dtype[devices[i].device_type].device_name,
+ devices[i].device_name,
+ devices[i].comment);
+ strncat(temp,
+ " ",
+ sizeof(temp) - 1 - strlen(temp));
+ break;
+
+ case DEVICE_SERIAL_MKISS_TNC:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ langcode("IFDIN00004"),
+ langcode("UNIOP00006"),
+ i,
+ temp2,
+ dtype[devices[i].device_type].device_name,
+ devices[i].device_name,
+ atoi(devices[i].radio_port),
+ devices[i].comment);
+ strncat(temp,
+ " ",
+ sizeof(temp) - 1 - strlen(temp));
+ break;
+
+ case DEVICE_NET_DATABASE:
+ case DEVICE_SQL_DATABASE:
+ case DEVICE_NET_STREAM:
+ case DEVICE_NET_GPSD:
+ case DEVICE_NET_WX:
+ case DEVICE_NET_AGWPE:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ langcode("IFDIN00004"),
+ langcode("UNIOP00006"),
+ i,
+ temp2,
+ dtype[devices[i].device_type].device_name,
+ devices[i].device_host_name,
+ devices[i].sp,
+ devices[i].comment);
+ strncat(temp,
+ " ",
+ sizeof(temp) - 1 - strlen(temp));
+ break;
+
+ case DEVICE_AX25_TNC:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ langcode("IFDIN00005"),
+ langcode("UNIOP00006"),
+ i,
+ temp2,
+ dtype[devices[i].device_type].device_name,
+ devices[i].device_name,
+ devices[i].comment);
+ strncat(temp,
+ " ",
+ sizeof(temp) - 1 - strlen(temp));
+ break;
+
+ default:
+ break;
+ }
+ /* look at list data (Must be "Device" port#) */
+ XmListAddItem(control_iface_list, str_ptr = XmStringCreateLtoR(temp,XmFONTLIST_DEFAULT_TAG),n++);
+ XmStringFree(str_ptr);
+ break;
+
+ case 4 :
+ /* delete entire list available */
+ XmListDeleteAllItems(control_iface_list);
+ return; // Exit routine
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+
+
+
+
+// Rebuild the list in the interface control dialog so that the
+// current status of each interface is shown.
+//
+void update_interface_list(void) {
+
+ // If the interface control dialog exists
+ if (control_interface_dialog) {
+
+ // Delete the entire list
+ modify_device_list(4,0);
+
+ // Create the list again with updated values
+ modify_device_list(3,0);
+ }
+}
+
+
+
+
+
+void interface_setup(Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char *what = (char *)clientData;
+ int x,i,do_w;
+ char *temp;
+ /*char temp2[100];*/
+ XmString *list;
+ int port;
+ int found;
+
+ port=-1;
+ found=0;
+ do_w=atoi(what);
+
+ /* get option selected */
+ XtVaGetValues(interface_type_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ for (x=1; x<=i;x++) {
+ if (XmListPosSelected(interface_type_list,x)) {
+ found=x;
+ if (XmStringGetLtoR(list[(x-1)],XmFONTLIST_DEFAULT_TAG,&temp))
+ x=i+1;
+ }
+ }
+
+ /* if selection was made */
+ if (found) {
+ if (do_w==0) { // Add an interface
+ /* add */
+ /*fprintf(stderr,"ADD DEVICE\n");*/
+
+ /* delete list */
+
+begin_critical_section(&devices_lock, "interface_gui.c:interface_setup" );
+ modify_device_list(0,0);
+end_critical_section(&devices_lock, "interface_gui.c:interface_setup" );
+
+ port=get_open_device(); // Find an unused port number
+ /*fprintf(stderr,"Open_port %d\n",port);*/
+
+ if(port!=-1) {
+ /*devices[port].device_type=found;*/
+ /*fprintf(stderr,"adding device %s on port %d\n",dtype[found].device_name,port);*/
+
+ switch (found) {
+
+//WE7U: Set up for new KISS device type
+ case DEVICE_SERIAL_KISS_TNC:
+ // configure this port
+ if (debug_level & 1)
+ fprintf(stderr,"ADD SERIAL KISS TNC\n");
+ Config_TNC(w, DEVICE_SERIAL_KISS_TNC, 0, port);
+ break;
+
+ case DEVICE_SERIAL_MKISS_TNC:
+ // configure this port
+ if (debug_level & 1)
+ fprintf(stderr,"ADD SERIAL MKISS TNC\n");
+ Config_TNC(w, DEVICE_SERIAL_MKISS_TNC, 0, port);
+ break;
+
+ case DEVICE_SERIAL_TNC:
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"ADD SERIAL TNC\n");
+ Config_TNC(w, DEVICE_SERIAL_TNC, 0, port);
+ break;
+
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"ADD SERIAL TNC w HSP GPS\n");
+ Config_TNC(w, DEVICE_SERIAL_TNC_HSP_GPS, 0, port);
+ break;
+
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"ADD SERIAL TNC w AUX GPS\n");
+ Config_TNC(w, DEVICE_SERIAL_TNC_AUX_GPS, 0, port);
+ break;
+
+ case DEVICE_SERIAL_GPS:
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"ADD SERIAL GPS\n");
+ Config_GPS(w, 0, port);
+ break;
+
+ case DEVICE_SERIAL_WX:
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"ADD SERIAL WX\n");
+ Config_WX(w, 0, port);
+ break;
+
+ case DEVICE_NET_WX:
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"ADD Network WX\n");
+ Config_NWX(w, 0, port);
+ break;
+
+ case DEVICE_NET_GPSD:
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"ADD Network GPS\n");
+ Config_NGPS(w, 0, port);
+ break;
+
+ case DEVICE_AX25_TNC:
+ /* configure this port */
+ if (debug_level & 1)
+#ifdef HAVE_LIBAX25
+ fprintf(stderr,"ADD AX.25 TNC\n");
+ Config_AX25(w, 0, port);
+#else // HAVE_LIBAX25
+ fprintf(stderr,"AX.25 support not compiled into Xastir!\n");
+ popup_message(langcode("POPEM00004"),langcode("POPEM00021"));
+
+#endif // HAVE_LIBAX25
+ break;
+
+ case DEVICE_NET_STREAM:
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"ADD NET STREAM\n");
+ Config_Inet(w, 0, port);
+ break;
+
+ case DEVICE_NET_DATABASE:
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"ADD NET DATABASE\n");
+ Config_Database(w, 0, port);
+ break;
+#ifdef HAVE_DB
+ case DEVICE_SQL_DATABASE:
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"ADD SQL DATABASE\n");
+ Config_sql_Database(w, 0, port);
+ break;
+#endif /* HAVE_DB */
+ case DEVICE_NET_AGWPE:
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"ADD NET AGWPE\n");
+ Config_AGWPE(w, 0, port);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* rebuild list */
+
+begin_critical_section(&devices_lock, "interface_gui.c:interface_setup" );
+ modify_device_list(2,0);
+end_critical_section(&devices_lock, "interface_gui.c:interface_setup" );
+
+ }
+ /*fprintf(stderr,"SELECTION is %s\n",temp);*/
+ XtFree(temp);
+ }
+}
+
+
+
+
+
+// clientData:
+// 0 = Add
+// 1 = Delete
+// 2 = Properties
+//
+void interface_option(Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget pane, form, label, button_add, button_cancel;
+ char *what = (char *)clientData;
+ int i,x,n,do_w;
+ char *temp;
+ char temp2[50];
+ int port;
+ XmString *list;
+ int data_on,pos;
+ int found;
+ Atom delw;
+ XmString str_ptr;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+
+ data_on=0;
+ pos=0;
+ found=0;
+ do_w=atoi(what);
+ switch (do_w) {
+ case 0:/* add interface */
+ if (!choose_interface_dialog) {
+ choose_interface_dialog = XtVaCreatePopupShell(langcode("WPUPCIF002"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNresize, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("interface_option pane",xmPanedWindowWidgetClass, choose_interface_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("interface_option form",xmFormWidgetClass, pane,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ label = XtVaCreateManagedWidget(langcode("WPUPCIF002"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ /*set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNbackground, colors[0xff]); ac++;
+ XtSetArg(al[ac], XmNvisibleItemCount, MAX_IFACE_DEVICE_TYPES); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNshadowThickness, 3); ac++;
+ XtSetArg(al[ac], XmNselectionPolicy, XmSINGLE_SELECT); ac++;
+ XtSetArg(al[ac], XmNscrollBarPlacement, XmBOTTOM_RIGHT); ac++;
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopWidget, label); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 5); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 5); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 5); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ interface_type_list = XmCreateScrolledList(form,"interface_option list",al,ac);
+ n=1;
+ for (i=1; i<MAX_IFACE_DEVICE_TYPES; i++) {
+ XmListAddItem(interface_type_list, str_ptr = XmStringCreateLtoR(dtype[i].device_name,XmFONTLIST_DEFAULT_TAG),n++);
+ XmStringFree(str_ptr);
+ }
+ button_add = XtVaCreateManagedWidget(langcode("UNIOP00007"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, XtParent(interface_type_list),
+ XmNtopOffset,10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, XtParent(interface_type_list),
+ XmNtopOffset,10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_cancel, XmNactivateCallback, Choose_interface_destroy_shell, choose_interface_dialog);
+ XtAddCallback(button_add, XmNactivateCallback, interface_setup, "0");
+
+ pos_dialog(choose_interface_dialog);
+
+ delw = XmInternAtom(XtDisplay(choose_interface_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(choose_interface_dialog, delw, Choose_interface_destroy_shell, (XtPointer)configure_interface_dialog);
+
+ XtManageChild(form);
+ XtManageChild(interface_type_list);
+ XtVaSetValues(interface_type_list, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(pane);
+
+ XtPopup(choose_interface_dialog,XtGrabNone);
+ fix_dialog_size(choose_interface_dialog);
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(choose_interface_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else {
+ (void)XRaiseWindow(XtDisplay(choose_interface_dialog), XtWindow(choose_interface_dialog));
+ }
+ break;
+
+ case 1:/* delete interface */
+
+ case 2:/* interface properties */
+ /* get option selected */
+ XtVaGetValues(control_iface_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ for (x=1; x<=i;x++) {
+ if(XmListPosSelected(control_iface_list,x)) {
+ found=1;
+ if (XmStringGetLtoR(list[(x-1)],XmFONTLIST_DEFAULT_TAG,&temp))
+ x=i+1;
+ }
+ }
+
+ /* if selection was made */
+ if (found) {
+ /* look at list data (Must be "Device" port#) */
+ if (2 != sscanf(temp,"%49s %d",temp2,&port)) {
+ fprintf(stderr,"interface_option:sscanf parsing error\n");
+ }
+ if(do_w==1) {
+ /* delete interface */
+ /*fprintf(stderr,"delete interface port %d\n",port);*/
+
+ if (port_data[port].active==DEVICE_IN_USE) {
+ /* shut down and delete port */
+ /*fprintf(stderr,"Shutting down port %d\n",port);*/
+ (void)del_device(port);
+ }
+
+begin_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* delete item at that port */
+ modify_device_list(1,port);
+ /* Clear device */
+ devices[port].device_type=DEVICE_NONE;
+ devices[port].device_name[0] = '\0';
+ devices[port].radio_port[0] = '\0';
+ devices[port].device_converse_string[0] = '\0';
+ devices[port].device_host_name[0] = '\0';
+ devices[port].device_host_pswd[0] = '\0';
+ devices[port].device_host_filter_string[0] = '\0';
+ devices[port].comment[0] = '\0';
+ devices[port].unproto1[0] = '\0';
+ devices[port].unproto2[0] = '\0';
+ devices[port].unproto3[0] = '\0';
+ devices[port].unproto_igate[0] = '\0';
+ devices[port].style=0;
+ devices[port].igate_options=0;
+ devices[port].transmit_data=0;
+ devices[port].reconnect=0;
+ devices[port].connect_on_startup=0;
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ } else {
+ /* Properties */
+
+begin_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ if (debug_level & 1) {
+ fprintf(stderr,"Changing device %s on port %d\n",
+ dtype[devices[port].device_type].device_name,port);
+ }
+ switch (devices[port].device_type) {
+ case DEVICE_SERIAL_TNC:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"Modify SERIAL TNC\n");
+ Config_TNC(w, DEVICE_SERIAL_TNC, 1, port);
+ break;
+
+ case DEVICE_SERIAL_KISS_TNC:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"Modify SERIAL KISS TNC\n");
+ Config_TNC(w, DEVICE_SERIAL_KISS_TNC, 1, port);
+ break;
+
+ case DEVICE_SERIAL_MKISS_TNC:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"Modify SERIAL MKISS TNC\n");
+ Config_TNC(w, DEVICE_SERIAL_MKISS_TNC, 1, port);
+ break;
+
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"Modify SERIAL TNC with HSP GPS\n");
+ Config_TNC(w, DEVICE_SERIAL_TNC_HSP_GPS, 1, port);
+ break;
+
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"Modify SERIAL TNC with AUX GPS\n");
+ Config_TNC(w, DEVICE_SERIAL_TNC_AUX_GPS, 1, port);
+ break;
+
+ case DEVICE_SERIAL_GPS:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"Modify SERIAL GPS\n");
+ Config_GPS(w, 1, port);
+ break;
+
+ case DEVICE_SERIAL_WX:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"Modify SERIAL WX\n");
+ Config_WX(w, 1, port);
+ break;
+
+ case DEVICE_NET_WX:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"Modify Network WX\n");
+ Config_NWX(w, 1, port);
+ break;
+
+ case DEVICE_NET_GPSD:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"Modify Network GPS\n");
+ Config_NGPS(w, 1, port);
+ break;
+
+ case DEVICE_AX25_TNC:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"Modify AX.25 TNC\n");
+ Config_AX25(w, 1, port);
+ break;
+
+ case DEVICE_NET_STREAM:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"Modify NET STREAM\n");
+ Config_Inet(w, 1, port);
+ break;
+
+ case DEVICE_NET_DATABASE:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"Modify NET DATABASE\n");
+ Config_Database(w, 1, port);
+ break;
+#ifdef HAVE_DB
+ case DEVICE_SQL_DATABASE:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"Modify SQL DATABASE\n");
+ Config_sql_Database(w, 1, port);
+ break;
+#endif /* HAVE_DB */
+ case DEVICE_NET_AGWPE:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ /* configure this port */
+ if (debug_level & 1)
+ fprintf(stderr,"Modify NET AGWPE\n");
+ Config_AGWPE(w, 1, port);
+ break;
+
+ default:
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+ break;
+ }
+ }
+ /*fprintf(stderr,"interface - %s\n",temp);*/
+ XtFree(temp);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+
+
+
+/*****************************************************/
+/* Control Interface GUI */
+/*****************************************************/
+extern void startup_all_or_defined_port(int port);
+extern void shutdown_all_active_or_defined_port(int port);
+
+
+
+
+
+void start_stop_interface( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char *which = (char *)clientData;
+ int do_w;
+ char temp2[50];
+ int i,x;
+ char *temp;
+ int port;
+ XmString *list;
+ int found;
+
+ busy_cursor(appshell);
+
+ found=0;
+ /* get option selected */
+ XtVaGetValues(control_iface_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ for (x=1; x<=i;x++) {
+ if (XmListPosSelected(control_iface_list,x)) {
+ found=1;
+ if (XmStringGetLtoR(list[(x-1)],XmFONTLIST_DEFAULT_TAG,&temp))
+ x=i+1;
+ }
+ }
+
+ /* if selection was made */
+ if (found) {
+
+ /* delete list */
+
+//begin_critical_section(&devices_lock, "interface_gui.c:start_stop_interface" );
+// modify_device_list(4,0);
+//end_critical_section(&devices_lock, "interface_gui.c:start_stop_interface" );
+
+ /* look at list data (Must be "Device" port#) */
+ if (2 != sscanf(temp,"%49s %d",temp2,&port)) {
+ fprintf(stderr,"start_stop_interface:sscanf parsing error\n");
+ }
+ /*fprintf(stderr,"Port to change %d\n",port);*/
+ do_w = atoi(which);
+ if (do_w) {
+ shutdown_all_active_or_defined_port(port);
+ } else {
+ /*fprintf(stderr,"DO port up\n");*/
+ if (port_data[port].active==DEVICE_IN_USE) {
+ /*fprintf(stderr,"Device was up, Shutting down\n");*/
+ shutdown_all_active_or_defined_port(port);
+ }
+ /* now start port */
+ startup_all_or_defined_port(port);
+ }
+ /* rebuild list */
+
+//begin_critical_section(&devices_lock, "interface_gui.c:start_stop_interface" );
+// modify_device_list(3,0);
+//end_critical_section(&devices_lock, "interface_gui.c:start_stop_interface" );
+
+ // Rebuild the interface control list
+ update_interface_list();
+
+ XtFree(temp);
+ }
+}
+
+
+
+
+
+void start_stop_all_interfaces( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char *which = (char *)clientData; // Whether to start or stop the interfaces
+ int do_w;
+
+ busy_cursor(appshell);
+
+//begin_critical_section(&devices_lock, "interface_gui.c:start_stop_all_interfaces" );
+// modify_device_list(4,0);
+//end_critical_section(&devices_lock, "interface_gui.c:start_stop_all_interfaces" );
+
+ do_w = atoi(which);
+ if (do_w) { // We wish to shut down all ports
+ shutdown_all_active_or_defined_port(-1);
+ }
+ else { // We wish to start up all ports
+ startup_all_or_defined_port(-2);
+ }
+ /* rebuild list */
+
+//begin_critical_section(&devices_lock, "interface_gui.c:start_stop_all_interfaces" );
+// modify_device_list(3,0);
+//end_critical_section(&devices_lock, "interface_gui.c:start_stop_all_interfaces" );
+
+ // Rebuild the interface control list
+ update_interface_list();
+
+}
+
+
+
+
+
+void Control_interface_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+
+begin_critical_section(&control_interface_dialog_lock, "interface_gui.c:Control_interface_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ control_interface_dialog = (Widget)NULL;
+
+end_critical_section(&control_interface_dialog_lock, "interface_gui.c:Control_interface_destroy_shell" );
+
+}
+
+
+
+
+
+void control_interface( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget rowcol, form, button_start, button_stop, button_start_all, button_stop_all, button_cancel;
+ static Widget button_add, button_delete, button_properties;
+ Atom delw;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+
+
+ if(!control_interface_dialog) {
+
+begin_critical_section(&control_interface_dialog_lock, "interface_gui.c:control_interface" );
+
+ control_interface_dialog = XtVaCreatePopupShell(langcode("IFPUPCT000"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNresize, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ rowcol = XtVaCreateWidget("control_interface rowcol",xmRowColumnWidgetClass, control_interface_dialog,
+ XmNorientation, XmVERTICAL,
+ XmNnumColumns, 1,
+ XmNpacking, XmPACK_TIGHT,
+ XmNisAligned, TRUE,
+ XmNentryAlignment, XmALIGNMENT_CENTER,
+ XmNkeyboardFocusPolicy, XmEXPLICIT,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ /*set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNbackground, colors[0xff]); ac++;
+ XtSetArg(al[ac], XmNvisibleItemCount, MAX_IFACE_DEVICES); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNshadowThickness, 3); ac++;
+ XtSetArg(al[ac], XmNselectionPolicy, XmSINGLE_SELECT); ac++;
+ XtSetArg(al[ac], XmNscrollBarPlacement, XmBOTTOM_RIGHT); ac++;
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 5); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 5); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 5); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ control_iface_list = XmCreateScrolledList(rowcol,"control_interface list",al,ac);
+
+ /* build device list */
+
+begin_critical_section(&devices_lock, "interface_gui.c:control_interface" );
+ modify_device_list(3,0);
+end_critical_section(&devices_lock, "interface_gui.c:control_interface" );
+
+ form = XtVaCreateWidget("control_interface form",xmFormWidgetClass, rowcol,
+ XmNfractionBase, 4,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ button_start = XtVaCreateManagedWidget(langcode("IFPUPCT001"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_start_all = XtVaCreateManagedWidget(langcode("IFPUPCT003"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_add = XtVaCreateManagedWidget(langcode("UNIOP00007"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_delete = XtVaCreateManagedWidget(langcode("UNIOP00008"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_stop = XtVaCreateManagedWidget(langcode("IFPUPCT002"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, button_start,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_stop_all = XtVaCreateManagedWidget(langcode("IFPUPCT004"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, button_start,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_properties = XtVaCreateManagedWidget(langcode("UNIOP00009"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, button_start,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),xmPushButtonGadgetClass, form,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, button_start,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_add, XmNactivateCallback, interface_option, "0");
+ XtAddCallback(button_delete, XmNactivateCallback, interface_option, "1");
+ XtAddCallback(button_properties, XmNactivateCallback, interface_option, "2");
+
+ XtAddCallback(button_cancel, XmNactivateCallback, Control_interface_destroy_shell, control_interface_dialog);
+ XtAddCallback(button_start, XmNactivateCallback, start_stop_interface, "0");
+ XtAddCallback(button_stop, XmNactivateCallback, start_stop_interface, "1");
+
+ XtAddCallback(button_start_all, XmNactivateCallback, start_stop_all_interfaces, "0");
+ XtAddCallback(button_stop_all, XmNactivateCallback, start_stop_all_interfaces, "1");
+
+ delw = XmInternAtom(XtDisplay(control_interface_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(control_interface_dialog, delw, Control_interface_destroy_shell, (XtPointer)control_interface_dialog);
+
+ XtVaSetValues(control_iface_list, XmNbackground, colors[0x0f], NULL);
+
+ pos_dialog(control_interface_dialog);
+
+ XtManageChild(control_iface_list);
+ XtManageChild(form);
+ XtManageChild(rowcol);
+
+end_critical_section(&control_interface_dialog_lock, "interface_gui.c:control_interface" );
+
+ XtPopup(control_interface_dialog,XtGrabNone);
+ fix_dialog_size(control_interface_dialog);
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(control_interface_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else {
+ (void)XRaiseWindow(XtDisplay(control_interface_dialog), XtWindow(control_interface_dialog));
+ }
+}
+
+
+
+
+
+void interface_status(Widget w) {
+ int i;
+ char s;
+ char opt;
+ int read_data;
+ int write_data;
+
+ read_data=0;
+ write_data=0;
+ s='\0';
+
+begin_critical_section(&devices_lock, "interface_gui.c:interface_status" );
+
+ for (i=0; i < MAX_IFACE_DEVICES; i++) {
+ read_data=0;
+ write_data=0;
+ opt='\0';
+
+ if (devices[i].device_type!=DEVICE_NONE) {
+ switch(devices[i].device_type) {
+ case DEVICE_SERIAL_TNC:
+ s='0'; // Select icon for status bar
+ break;
+
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ s='1'; // Select icon for status bar
+ break;
+
+ case DEVICE_SERIAL_GPS:
+ s='2'; // Select icon for status bar
+ break;
+
+ case DEVICE_SERIAL_WX:
+ case DEVICE_NET_WX:
+ s='3'; // Select icon for status bar
+ break;
+
+ case DEVICE_SQL_DATABASE:
+ s='8'; // Select icon for status bar
+ break;
+
+ case DEVICE_NET_DATABASE:
+ case DEVICE_NET_STREAM:
+ case DEVICE_NET_AGWPE:
+ s='4'; // Select icon for status bar
+ break;
+
+ case DEVICE_AX25_TNC:
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+ s='5'; // Select icon for status bar
+ break;
+
+ case DEVICE_NET_GPSD:
+ s='6'; // Select icon for status bar
+ break;
+
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ s='7'; // Select icon for status bar
+ break;
+
+ default:
+ break;
+ }
+ if (port_data[i].active==DEVICE_IN_USE) {
+ if (port_data[i].status==DEVICE_UP) {
+ if (port_data[i].bytes_input_last != port_data[i].bytes_input) {
+if (begin_critical_section(&port_data_lock, "interface_gui.c:interface_status(1)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", i);
+ port_data[i].bytes_input_last = port_data[i].bytes_input;
+ port_data[i].port_activity = 1;
+if (end_critical_section(&port_data_lock, "interface_gui.c:interface_status(2)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", i);
+ read_data=1;
+ }
+ if (port_data[i].bytes_output_last != port_data[i].bytes_output) {
+if (begin_critical_section(&port_data_lock, "interface_gui.c:interface_status(3)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", i);
+ port_data[i].bytes_output_last = port_data[i].bytes_output;
+ port_data[i].port_activity = 1;
+if (end_critical_section(&port_data_lock, "interface_gui.c:interface_status(4)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", i);
+ write_data=1;
+ }
+ if (write_data)
+ opt='>';
+ else {
+ if (read_data)
+ opt='<';
+ else
+ opt='^';
+ }
+ } else
+ opt='*';
+ } else
+ opt='\0';
+ symbol(w,0,'~',s,opt,XtWindow(iface_da),0,(i*10),0,' ');
+ } else
+ symbol(w,0,'~','#','\0',XtWindow(iface_da),0,(i*10),0,' ');
+ }
+
+end_critical_section(&devices_lock, "interface_gui.c:interface_option" );
+
+}
+
+
diff --git a/src/io-common.c b/src/io-common.c
new file mode 100644
index 0000000..d7d734a
--- /dev/null
+++ b/src/io-common.c
@@ -0,0 +1,70 @@
+
+// $Id: io-common.c,v 1.11 2012/08/25 16:38:29 tvrusso Exp $
+
+
+/* Copyright 2002 Daniel Egnor. See LICENSE.geocoder file.
+ * Portions Copyright (C) 2004-2012 The Xastir Group
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "io.h"
+#include <ctype.h>
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+
+
+int io_out_i4(struct io_file *f,int pos,int o) {
+ unsigned char x[4];
+ x[0] = o >> 24;
+ x[1] = o >> 16;
+ x[2] = o >> 8;
+ x[3] = o;
+ return io_out(f,pos,x,sizeof x);
+}
+
+int io_out_i2(struct io_file *f,int pos,short int o) {
+ unsigned char x[2];
+ x[0] = o >> 8;
+ x[1] = o;
+ return io_out(f,pos,x,sizeof x);
+}
+
+int io_out_i1(struct io_file *f,int pos,signed char o) {
+ return io_out(f,pos,&o,sizeof o);
+}
+
+int io_in_i4(struct io_file *f,int pos,int *i) {
+ unsigned char x[4];
+ const int r = io_in(f,pos,x,sizeof x);
+ if (i) *i = (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3];
+ return r;
+}
+
+int io_in_i2(struct io_file *f,int pos,short *i) {
+ unsigned char x[2];
+ const int r = io_in(f,pos,x,sizeof x);
+ if (i) *i = (x[0] << 8) | x[1];
+ return r;
+}
+
+int io_in_i1(struct io_file *f,int pos,signed char *i) {
+ return io_in(f,pos,i,sizeof *i);
+}
+
+int io_strntoi(const char *str,int len) {
+ int r = 0;
+ int sign = 1;
+ const char * const end = str + len;
+ while (end != str && isspace((int)*str)) ++str;
+ if (end != str && *str == '-') (sign *= -1),++str;
+ if (end != str && *str == '+') ++str;
+ while (end != str && isdigit((int)*str)) r = *str++ - '0' + 10 * r;
+ return r * sign;
+}
diff --git a/src/io-mmap.c b/src/io-mmap.c
new file mode 100644
index 0000000..ab561fc
--- /dev/null
+++ b/src/io-mmap.c
@@ -0,0 +1,218 @@
+
+// $Id: io-mmap.c,v 1.12 2012/08/25 16:38:29 tvrusso Exp $
+
+
+/* Copyright 2002 Daniel Egnor. See LICENSE.geocoder file.
+ * Portions Copyright (C) 2004-2012 The Xastir Group
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "io.h"
+#include <stdio.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <string.h>
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+struct io_file {
+ int fd;
+ int prot;
+ off_t file_size;
+ void *map;
+ off_t map_offset;
+ size_t map_size,map_page;
+ char buffer[4096];
+ off_t buffer_offset;
+ size_t buffer_size;
+};
+
+/* Writes any buffered append data.
+ Returns nonzero iff failed. */
+static int unbuffer(struct io_file *f) {
+ int r;
+ if (!f->buffer_size) return 0;
+ r = write(f->fd,f->buffer,f->buffer_size);
+ if (r > 0) {
+ f->buffer_offset += r;
+ f->buffer_size -= r;
+ if (f->buffer_offset > f->file_size)
+ f->file_size = f->buffer_offset;
+ }
+
+ if (0 != f->buffer_size) {
+ perror("write");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Resets f->file_size to the actual size of the file.
+ Returns nonzero iff failed. */
+static int checksize(struct io_file *f) {
+ struct stat buf;
+ if (unbuffer(f)) return -1;
+ if (fstat(f->fd,&buf)) {
+ perror("fstat");
+ return -1;
+ }
+
+ f->file_size = buf.st_size;
+ return 0;
+}
+
+struct io_file *io_open(const char *fname) {
+ struct io_file * const f = malloc(sizeof *f);
+
+ if (NULL == f) return NULL;
+ f->fd = open(fname,O_RDWR|O_CREAT,0666);
+ f->prot = PROT_READ|PROT_WRITE;
+ if (f->fd < 0) {
+ f->fd = open(fname,O_RDONLY);
+ f->prot = PROT_READ;
+ }
+ if (f->fd < 0) {
+ perror(fname);
+ free(f);
+ return NULL;
+ }
+
+ f->map = NULL;
+ f->map_offset = 0;
+ f->map_size = 0;
+ f->map_page = getpagesize();
+ f->file_size = 0;
+ f->buffer_offset = 0;
+ f->buffer_size = 0;
+ if (checksize(f)) {
+ close(f->fd);
+ free(f);
+ return NULL;
+ }
+
+ return f;
+}
+
+void io_close(struct io_file *f) {
+ if (NULL != f) {
+ unbuffer(f);
+ close(f->fd);
+ if (NULL != f->map) munmap(f->map,f->map_size);
+ free(f);
+ }
+}
+
+/* Attempts to make the mapping cover [pos,pos+len), or at least [pos].
+ Returns nonzero iff failed. */
+static int remap(struct io_file *f,int pos,int len) {
+ if (pos < (int)f->map_offset || pos >= (int)(f->map_offset + f->map_size) ) {
+ const int flags = MAP_SHARED;
+
+ const off_t b1 = pos / f->map_page * f->map_page;
+ const off_t e1 = b1 + f->map_page;
+
+ off_t b2 = f->map_offset;
+ off_t e2 = b2 + f->map_size;
+ if (b2 > b1) b2 = b1 - (b2 - b1);
+ if (b2 < 0) b2 = 0;
+ if (e2 < e1) e2 = e1 + (e1 - e2);
+
+ if (NULL != f->map) munmap(f->map,f->map_size);
+ if (MAP_FAILED != (f->map = mmap(NULL,e2 - b2,f->prot,flags,f->fd,b2))) {
+ f->map_size = e2 - b2;
+ f->map_offset = b2;
+ }
+ else if (MAP_FAILED != (f->map = mmap(NULL,e1 - b1,f->prot,flags,f->fd,b1))) {
+ f->map_size = e1 - b1;
+ f->map_offset = b1;
+ }
+ else {
+ perror("mmap");
+ f->map = NULL;
+ f->map_size = 0;
+ f->map_offset = 0;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int io_out(struct io_file *f,int pos,const void *o,int len) {
+ int end = pos + len;
+ if (0 == len) return pos;
+ if (NULL == f || -1 == pos) return -1;
+ if (NULL == o) return pos + len;
+ if (remap(f,pos,len)) return -1;
+
+ if (pos < f->file_size) {
+ assert(pos >= f->map_offset);
+ if (pos >= f->buffer_offset && unbuffer(f))
+ return -1;
+ if (end > (int)(f->map_offset + f->map_size))
+ end = f->map_offset + f->map_size;
+ if (end > f->file_size)
+ end = f->file_size;
+ memcpy(pos - f->map_offset + (char *) f->map,o,end - pos);
+ }
+ else {
+ if (pos < f->buffer_offset
+ || pos > (int)(f->buffer_offset + f->buffer_size)) {
+ if (unbuffer(f)) return -1;
+ if (lseek(f->fd,pos,SEEK_SET) == (off_t) -1) {
+ perror("lseek");
+ return -1;
+ }
+
+ assert(0 == f->buffer_size);
+ f->buffer_offset = pos;
+ }
+ else if (pos == (int)(f->buffer_offset + sizeof f->buffer))
+ if (unbuffer(f)) return -1;
+
+ assert(pos >= f->buffer_offset
+ && pos <= (int)(f->buffer_offset + f->buffer_size));
+ if (end > (int)(f->buffer_offset + sizeof f->buffer))
+ end = f->buffer_offset + sizeof f->buffer;
+ memcpy(&f->buffer[pos - f->buffer_offset],o,end - pos);
+ if ((int)(end - f->buffer_offset) > (int)f->buffer_size)
+ f->buffer_size = end - f->buffer_offset;
+ }
+
+ return io_out(f,end,end - pos + (char *) o,len + pos - end);
+}
+
+int io_in(struct io_file *f,int pos,void *i,int len) {
+ int end = pos + len;
+ if (0 == len) return pos;
+ if (NULL == f || -1 == pos) return -1;
+ if (NULL == i) return pos + len;
+ if (remap(f,pos,len)) return -1;
+ if (unbuffer(f)) return -1;
+
+ if (pos >= f->file_size && checksize(f)) return -1;
+ if (pos >= f->file_size) {
+/* TODO: fill with zeroes instead */
+ fputs("read: EOF\n",stderr);
+ return -1;
+ }
+
+ if (end > (int)(f->map_offset + f->map_size))
+ end = f->map_offset + f->map_size;
+ if (end > f->file_size)
+ end = f->file_size;
+ memcpy(i,pos - f->map_offset + (char *) f->map,end - pos);
+ return io_in(f,end,end - pos + (char *) i,len + pos - end);
+}
diff --git a/src/io.h b/src/io.h
new file mode 100644
index 0000000..4c6a155
--- /dev/null
+++ b/src/io.h
@@ -0,0 +1,54 @@
+
+// $Id: io.h,v 1.8 2012/11/01 18:57:19 we7u Exp $
+
+
+/* Copyright 2002 Daniel Egnor. See LICENSE.geocoder file.
+ * Portions Copyright (C) 2004-2012 The Xastir Group
+ *
+ * This file defines the I/O interface used for access to index files.
+ * There are two implementations of this interface; io-mmap.c uses Unix
+ * mmap() and is quite efficient, and io-stdio.c uses C stdio and is slower
+ * but more portable. Which one is used depends on which file is compiled. */
+
+#ifndef GEOCODER_IO_H
+#define GEOCODER_IO_H
+
+struct io_file;
+
+/* Open a file. The file will be created if it did not exist.
+ * It will be opened R/W if possible, R/O otherwise.
+ * Returns NULL on error.*/
+
+struct io_file *io_open(const char *fname);
+void io_close(struct io_file *);
+
+/* In general, all I/O is done with an offset ("pos") directly. There is
+ * no "current position" associated with the file handle. This is really
+ * a lot more convenient for random access.
+ *
+ * Functions almost always return the position just after the data that was
+ * read or written, so they may be easily "chained" to read or write several
+ * contiguous items; this makes it almost as easy to do this as it would be
+ * with a file pointer, which keeping things more flexible.
+ *
+ * If an error occurs, the return value will be -1. If the input "pos"
+ * is -1, these functions will silently return -1, so you can safely wait
+ * until the end of a "chain" to check for errors, if you want.
+ *
+ * Integer values are written in byte-order-independent fashion. */
+
+int io_out(struct io_file *,int pos,const void *o,int len); /* Write data */
+int io_out_i4(struct io_file *,int pos,int o); /* Write an int */
+int io_out_i2(struct io_file *,int pos,short o); /* Write a short */
+int io_out_i1(struct io_file *,int pos,signed char o); /* Write a char */
+
+int io_in(struct io_file *,int pos,void *i,int len); /* Read data */
+int io_in_i4(struct io_file *,int pos,int *i); /* Read an int */
+int io_in_i2(struct io_file *,int pos,short *i); /* Read a short */
+int io_in_i1(struct io_file *,int pos,signed char *i); /* Read a char */
+
+/* Convert a string to integer. Like strtol(), only with a count.
+ * Kept here, 'cuz ... where else? */
+int io_strntoi(const char *str,int len);
+
+#endif
diff --git a/src/lang.c b/src/lang.c
new file mode 100644
index 0000000..e8ea176
--- /dev/null
+++ b/src/lang.c
@@ -0,0 +1,255 @@
+/*
+ * $Id: lang.c,v 1.20 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+#include <Xm/XmAll.h>
+
+#include "xastir.h"
+#include "lang.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+char lang_code[MAX_LANG_ENTRIES][MAX_LANG_CODE+1];
+char *lang_code_ptr[MAX_LANG_ENTRIES];
+char lang_buffer[MAX_LANG_BUFFER];
+char lang_hotkey[MAX_LANG_ENTRIES];
+
+int lang_code_number;
+long buffer_len;
+char invalid_code[50];
+
+
+
+
+
+char *langcode(char *code) {
+ int i;
+
+ // Create an invalid code string to return in case we can't find the proper string
+ if (strlen(code) <= MAX_LANG_CODE) { // Code is ok
+ xastir_snprintf(invalid_code, sizeof(invalid_code), "IC>%s", code);
+ }
+ else { // Code is too long
+ xastir_snprintf(invalid_code, sizeof(invalid_code), "IC>TOO LONG:%s",code);
+ fprintf(stderr,"IC>TOO LONG:%s\n",code);
+ return(invalid_code);
+ }
+
+ if(lang_code_number>0) {
+ for(i=0;i<lang_code_number;i++) {
+ if(strcmp(code,lang_code[i])==0) { // Found a match
+ if (strlen(lang_code[i]) < MAX_LANG_LINE_SIZE) {
+ return(lang_code_ptr[i]); // Found it, length ok
+ }
+ else {
+ fprintf(stderr,"String size: %d, Max size: %d, %s\n",
+ (int)strlen(lang_code[i]),
+ MAX_LANG_LINE_SIZE,code);
+ return(invalid_code); // Found it, but string too long
+ }
+ }
+ }
+ fprintf(stderr,"Language String not found:%s\n",code);
+ return(invalid_code);
+ }
+
+ fprintf(stderr,"No language strings loaded:%s\n",code);
+ return(invalid_code); // No strings loaded in language file
+}
+
+
+
+
+
+char langcode_hotkey(char *code) {
+ int i;
+
+ if(lang_code_number>0) {
+ for(i=0;i<lang_code_number;i++) {
+ if(strcmp(code,lang_code[i])==0) {
+ return(lang_hotkey[i]); // Found it
+ }
+ }
+ }
+
+ fprintf(stderr,"No hotkey for:%s\n",code);
+ return(' '); // No strings loaded in language file
+}
+
+
+
+
+
+int load_language_file(char *filename) {
+ FILE *f;
+ char line[MAX_LANG_LINE_SIZE+1];
+ char *temp_ptr;
+ int i,lt,lcok;
+ char cin;
+ int ok;
+ int line_num;
+ int data_len;
+
+ lang_code_number=0;
+ buffer_len=0l;
+ ok=1;
+ line_num=1;
+ i=0;
+ f=fopen(filename,"r");
+ if(f != NULL) {
+ line[0]='\0';
+ while(!feof(f)) {
+ if(fread(&cin,1,1,f)==1) {
+ if(cin != (char)10 && cin != (char)13) {
+ if(i<MAX_LANG_LINE_SIZE) {
+ line[i++]=cin;
+ line[i]='\0';
+ } else {
+ ok=0;
+ fprintf(stderr,"Error! Line %d too long in language file\n",line_num);
+ }
+ } else {
+ i=0;
+ if (line[0]!='#' && strlen(line)>0) {
+ /* data line */
+ if(lang_code_number < MAX_LANG_ENTRIES) {
+ if(buffer_len < MAX_LANG_BUFFER) {
+ if(strchr(line,'|')!=NULL) {
+ temp_ptr=strtok(line,"|"); /* get code */
+ if (temp_ptr!=NULL) {
+ if(strlen(temp_ptr)<=MAX_LANG_CODE) {
+ lcok=1;
+ for (lt=0; lt <lang_code_number && lcok; lt++) {
+ if(strcmp(lang_code[lt],temp_ptr)==0) {
+ lcok=0;
+ break;
+ }
+ }
+ if(lcok) {
+ xastir_snprintf(lang_code[lang_code_number],
+ MAX_LANG_CODE+1,
+ "%s",
+ temp_ptr);
+ temp_ptr=strtok(NULL,"|"); /* get string */
+ if (temp_ptr!=NULL) {
+ data_len=(int)strlen(temp_ptr);
+ if ((buffer_len+data_len+1)< MAX_LANG_BUFFER) {
+ lang_code_ptr[lang_code_number]=lang_buffer+buffer_len;
+ xastir_snprintf(lang_buffer+buffer_len,
+ MAX_LANG_BUFFER-buffer_len,
+ "%s",
+ temp_ptr);
+ lang_buffer[buffer_len+data_len]='\0';
+ buffer_len+=data_len+1;
+ temp_ptr=strtok(NULL,"|"); /* get hotkey */
+ if (temp_ptr!=NULL) {
+ lang_hotkey[lang_code_number]=temp_ptr[0];
+ /*fprintf(stderr,"HOTKEY %c\n",lang_hotkey[lang_code_number]);*/
+ }
+ } else {
+ ok=0;
+ fprintf(stderr,"Language data buffer full error on line %d\n",line_num);
+ }
+ } else {
+ ok=0;
+ fprintf(stderr,"Language string parse error on line %d\n",line_num);
+ }
+ } else {
+ ok=0;
+ fprintf(stderr,"Duplicate code! <%s> on line %d\n",temp_ptr,line_num);
+ }
+ } else {
+ ok=0;
+ fprintf(stderr,"Language code on line %d is too long\n",line_num);
+ }
+ } else {
+ ok=0;
+ fprintf(stderr,"Missing Language code data on line %d\n",line_num);
+ }
+ } else {
+ ok=0;
+ fprintf(stderr,"Language code parse error on line %d\n",line_num);
+ }
+ } else {
+ ok=0;
+ fprintf(stderr,"Language data buffer full error on line %d\n",line_num);
+ }
+ } else {
+ ok=0;
+ fprintf(stderr,"Too many Language codes error on line %d\n",line_num);
+ }
+ if (ok) {
+ if (debug_level & 32)
+ fprintf(stderr,"Code #%d <%s> data <%s> hotkey <%c>\n",lang_code_number,
+ lang_code[lang_code_number],lang_code_ptr[lang_code_number],
+ lang_hotkey[lang_code_number]);
+ lang_code_number++;
+ }
+ line[0]='\0';
+ }
+ line_num++;
+ }
+ }
+ }
+ (void)fclose(f);
+ } else {
+ ok=0;
+ fprintf(stderr,"Could not read Language file: %s!\n",filename);
+ }
+ if (debug_level & 32)
+ fprintf(stderr,"LANG %d\n",lang_code_number);
+
+ return(ok);
+}
+
+
diff --git a/src/lang.h b/src/lang.h
new file mode 100644
index 0000000..ba57aea
--- /dev/null
+++ b/src/lang.h
@@ -0,0 +1,39 @@
+/*
+ * $Id: lang.h,v 1.11 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifndef XASTIR_LANG_H
+#define XASTIR_LANG_H
+
+#define MAX_LANG_LINE_SIZE 800
+#define MAX_LANG_CODE 10
+#define MAX_LANG_ENTRIES 3000
+#define MAX_LANG_BUFFER 30000
+
+extern int load_language_file(char *filename);
+extern char *langcode(char *code);
+extern char langcode_hotkey(char *code);
+
+
+
+#endif /* XASTIR_LANG_H */
diff --git a/src/leak_detection.h b/src/leak_detection.h
new file mode 100644
index 0000000..08f2604
--- /dev/null
+++ b/src/leak_detection.h
@@ -0,0 +1,101 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: leak_detection.h,v 1.9 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 2005-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+/* All of the misc entry points to be included for all packages */
+
+#ifndef _LEAK_DETECTION_H
+#define _LEAK_DETECTION_H
+
+
+// If libgc is installed, uncomment this next line to enable memory
+// leak detection:
+#define DETECT_MEMORY_LEAKS
+
+
+// Defines for including the libgc garbage collection library.
+// This enables automatic garbage collection of unused memory,
+// very similar to the garbage collection in Java. Get libgc from
+// here: http://www.hpl.hp.com/personal/Hans_Boehm/gc/
+//
+// This will cause stats to be printed every 60 seconds, 'cuz we
+// call GC_collect via a macro from UpdateTime() once per minute:
+// export GC_PRINT_STATS=1; xastir &
+//
+// Compile libgc with this option for more debugging output. I
+// didn't do so: --enable-full_debug
+//
+// If we enable these thread options, Xastir won't link with the
+// library. Since we don't allocate dynamic memory in the child
+// threads anyway, skip them.
+// --enable-threads=posix --enable-thread-local-alloc --enable-parallel-mark
+//
+// Call GC_gcollect at appropriate points to check for leaks. We do
+// this via the CHECK_LEAKS macro called from main.c:UpdateTime.
+//
+//
+// Note: The thread includes must be done before the libgc includes
+// as libgc redefines some thread stuff so that it cooperates with
+// the garbage collector routines. Any code module that does
+// malloc's/free's or thread operations should include
+// leak_detection.h as the last include if at all possible, and
+// should not include pthread.h themselves.
+//
+#include <pthread.h>
+#include <stdlib.h> /* Where malloc/free definitions reside */
+#ifdef HAVE_DMALLOC
+#include <dmalloc.h>
+#endif // HAVE_DMALLOC
+//
+#ifdef HAVE_GC_H
+ #ifdef HAVE_LIBGC
+
+ // We use this define to enable code in *.c files
+ #define USING_LIBGC
+
+ // Set up for threads
+ #define GC_THREADS
+
+ #ifdef __LINUX__
+ #define GC_LINUX_THREADS
+ #endif // __LINUX__
+
+// #define _REENTRANT
+
+ // Ask for more debugging
+ #define GC_DEBUG
+
+ #include <gc.h>
+ #define malloc(n) GC_MALLOC(n)
+ #define calloc(m,n) GC_MALLOC((m)*(n))
+ #define free(p) GC_FREE(p)
+ #define realloc(p,n) GC_REALLOC((p),(n))
+ #define CHECK_LEAKS() GC_gcollect()
+
+ #endif // HAVE_LIBGC
+#endif // HAVE_GC_H
+
+
+
+#endif /* LEAK_DETECTION_H */
+
+
diff --git a/src/list_gui.c b/src/list_gui.c
new file mode 100644
index 0000000..3067392
--- /dev/null
+++ b/src/list_gui.c
@@ -0,0 +1,2489 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: list_gui.c,v 1.57 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif // HAVE_LOCALE_H
+
+#ifdef HAVE_LIBINTL_H
+#include <libintl.h>
+#define _(x) gettext(x)
+#else // HAVE_LIBINTL_H
+#define _(x) (x)
+#endif // HAVE_LIBINTL_H
+
+#include <Xm/XmAll.h>
+
+#ifdef HAVE_XBAE_MATRIX_H
+#include <Xbae/Matrix.h>
+#endif // HAVE_XBAE_MATRIX_H
+
+#include "xastir.h"
+#include "main.h"
+#include "messages.h"
+#include "draw_symbols.h"
+#include "list_gui.h"
+#include "database.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+// Must be last include file
+#include "leak_detection.h"
+
+extern XmFontList fontlist1; // Menu/System fontlist
+
+#define SL_MAX 20
+#define ROWS 17
+
+// List Numbers (defined in list_gui.h)
+// 0: LST_ALL - all stations list
+// 1: LST_MOB - mobile stations list
+// 2: LST_WX - WX stations list
+// 3: LST_TNC - local stations list
+// 4: LST_TIM - last stations
+// 5: LST_OBJ - Objects/Items
+// 6: LST_MYOBJ - My Objects/Items
+// 7: LST_NUM - Number of lists; for use in array definitions below
+
+Widget station_list_dialog[LST_NUM]; // store list definitions
+static xastir_mutex station_list_dialog_lock; // Mutex lock for above
+
+Widget SL_list[LST_NUM][SL_MAX];
+Widget SL_da[LST_NUM][SL_MAX];
+Widget SL_call[LST_NUM][SL_MAX];
+char * SL_callback[LST_NUM][SL_MAX];
+Pixmap SL_icon[LST_NUM][SL_MAX]; // icons for different lists and list rows
+Pixmap blank_icon; // holds an empty icon
+Widget SL_scroll[LST_NUM];
+Widget SL_wx_wind_course[LST_NUM][SL_MAX];
+Widget SL_wx_wind_speed[LST_NUM][SL_MAX];
+Widget SL_wx_wind_gust[LST_NUM][SL_MAX];
+Widget SL_wx_temp[LST_NUM][SL_MAX];
+Widget SL_wx_hum[LST_NUM][SL_MAX];
+Widget SL_wx_baro[LST_NUM][SL_MAX];
+Widget SL_wx_rain_h[LST_NUM][SL_MAX];
+Widget SL_wx_rain_00[LST_NUM][SL_MAX];
+Widget SL_wx_rain_24[LST_NUM][SL_MAX];
+Widget SL_course[LST_NUM][SL_MAX];
+Widget SL_speed[LST_NUM][SL_MAX];
+Widget SL_alt[LST_NUM][SL_MAX];
+Widget SL_lat_long[LST_NUM][SL_MAX];
+Widget SL_packets[LST_NUM][SL_MAX];
+Widget SL_sats[LST_NUM][SL_MAX];
+Widget SL_my_course[LST_NUM][SL_MAX];
+Widget SL_my_distance[LST_NUM][SL_MAX];
+Widget SL_pos_time[LST_NUM][SL_MAX];
+Widget SL_node_path[LST_NUM][SL_MAX];
+Widget SL_power_gain[LST_NUM][SL_MAX];
+Widget SL_comments[LST_NUM][SL_MAX];
+int station_list_first = 1;
+int list_size_h[LST_NUM]; // height of entire list widget
+int list_size_w[LST_NUM]; // width of entire list widget
+int list_size_i[LST_NUM]; // size initialized, dirty hack, but works...
+
+int last_offset[LST_NUM];
+char top_call[LST_NUM][MAX_CALLSIGN+1]; // call of first list entry or empty string for always first call
+time_t top_time; // time of first list entry or 0 for always newest station
+int top_sn; // serial number for unique time index
+time_t last_list_upd; // time of last list update
+int units_last;
+
+#define LIST_UPDATE_CYCLE 2 /* Minimum time between list updates in seconds, we want */
+ /* immediate update, but not in high traffic situations */
+
+
+
+
+
+void list_gui_init(void)
+{
+ init_critical_section( &station_list_dialog_lock );
+}
+
+
+
+
+
+// get a valid list member, starting from current station in the desired direction
+// returns pointer to found member or NULL
+void get_list_member(int type, DataRow **p_station, int skip, int forward) {
+ char found;
+
+ if ((*p_station) == NULL) { // default start value
+ if (type == LST_TIM)
+ (*p_station) = t_newest;
+ else
+ (*p_station) = n_first;
+ }
+
+ if (skip == 1) { // skip before searching
+ if (type != LST_TIM) {
+ if (forward == 1)
+ (void)next_station_name(p_station);
+ else
+ (void)prev_station_name(p_station);
+ } else {
+ if (forward == 1)
+ (void)prev_station_time(p_station);
+ else
+ (void)next_station_time(p_station);
+ }
+ }
+
+ found = (char)FALSE;
+ switch (type) { // DK7IN: here I'm trading code size for speed...
+ case LST_ALL:
+ if (forward == 1)
+ while (!found && (*p_station) != NULL) {
+ if (((*p_station)->flag & ST_ACTIVE) != 0) // ignore deleted objects
+ found = (char)TRUE;
+ else
+ (*p_station) = (*p_station)->n_next;
+ }
+ else
+ while (!found && (*p_station) != NULL) {
+ if (((*p_station)->flag & ST_ACTIVE) != 0)
+ found = (char)TRUE;
+ else
+ (*p_station) = (*p_station)->n_prev;
+ }
+ break;
+ case LST_MOB:
+ if (forward == 1)
+ while (!found && (*p_station) != NULL) {
+ if (((*p_station)->flag & ST_ACTIVE) != 0 && (*p_station)->newest_trackpoint != NULL)
+ found = (char)TRUE;
+ else
+ (*p_station) = (*p_station)->n_next;
+ }
+ else
+ while (!found && (*p_station) != NULL) {
+ if (((*p_station)->flag & ST_ACTIVE) != 0 && (*p_station)->newest_trackpoint != NULL)
+ found = (char)TRUE;
+ else
+ (*p_station) = (*p_station)->n_prev;
+ }
+ break;
+ case LST_WX:
+ if (forward == 1)
+ while (!found && (*p_station) != NULL) {
+ if (((*p_station)->flag & ST_ACTIVE) != 0 && (*p_station)->weather_data != NULL)
+ found = (char)TRUE;
+ else
+ (*p_station) = (*p_station)->n_next;
+ }
+ else
+ while (!found && (*p_station) != NULL) {
+ if (((*p_station)->flag & ST_ACTIVE) != 0 && (*p_station)->weather_data != NULL)
+ found = (char)TRUE;
+ else
+ (*p_station) = (*p_station)->n_prev;
+ }
+ break;
+ case LST_TNC:
+ if (forward == 1)
+ while (!found && (*p_station) != NULL) {
+ if (((*p_station)->flag & ST_ACTIVE) != 0
+ && ((*p_station)->flag & ST_VIATNC) != 0)
+ found = (char)TRUE;
+ else
+ (*p_station) = (*p_station)->n_next;
+ }
+ else
+ while (!found && (*p_station) != NULL) {
+ if (((*p_station)->flag & ST_ACTIVE) != 0
+ && ((*p_station)->flag & ST_VIATNC) != 0)
+ found = (char)TRUE;
+ else
+ (*p_station) = (*p_station)->n_prev;
+ }
+ break;
+ case LST_TIM:
+ if (forward == 1) // forward in list, backward in time
+ while (!found && (*p_station) != NULL) {
+ if (((*p_station)->flag & ST_ACTIVE) != 0) // ignore deleted objects
+ found = (char)TRUE;
+ else
+ (*p_station) = (*p_station)->t_older;
+ }
+ else
+ while (!found && (*p_station) != NULL) {
+ if (((*p_station)->flag & ST_ACTIVE) != 0)
+ found = (char)TRUE;
+ else
+ (*p_station) = (*p_station)->t_newer;
+ }
+ break;
+ case LST_OBJ:
+ if (forward == 1)
+ while (!found && (*p_station) != NULL) {
+ // Show deleted objects/items as well
+ if ( ( (((*p_station)->flag & ST_OBJECT) != 0)
+ || (((*p_station)->flag & ST_ITEM) != 0) ) )
+ found = (char)TRUE;
+ else
+ (*p_station) = (*p_station)->n_next;
+ }
+ else
+ while (!found && (*p_station) != NULL) {
+ if (((*p_station)->flag & ST_ACTIVE) != 0
+ && ( (((*p_station)->flag & ST_VIATNC) != 0)
+ || (((*p_station)->flag & ST_ITEM) != 0) ) )
+ found = (char)TRUE;
+ else
+ (*p_station) = (*p_station)->n_prev;
+ }
+ break;
+ case LST_MYOBJ:
+
+// We should really show the active AND inactive objects. This is
+// so that inactive ones can be resurrected. Probably should do
+// this for all objects, not just ones we own.
+
+ if (forward == 1)
+ while (!found && (*p_station) != NULL) {
+ // Show deleted objects/items as well
+ if ( ( (((*p_station)->flag & ST_OBJECT) != 0)
+ || (((*p_station)->flag & ST_ITEM) != 0) )
+// && ( is_my_call( (*p_station)->origin,1)) ) // Exact match include SSID
+ && ( is_my_object_item(*p_station)) ) // Exact match include SSID
+
+ found = (char)TRUE;
+ else
+ (*p_station) = (*p_station)->n_next;
+ }
+ else
+ while (!found && (*p_station) != NULL) {
+ if (((*p_station)->flag & ST_ACTIVE) != 0
+ && ( (((*p_station)->flag & ST_VIATNC) != 0)
+ || (((*p_station)->flag & ST_ITEM) != 0) )
+// && ( is_my_call( (*p_station)->origin,1)) ) // Exact match includes SSID
+ && ( is_my_object_item(*p_station)) ) // Exact match include SSID
+
+ found = (char)TRUE;
+ else
+ (*p_station) = (*p_station)->n_prev;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+
+
+
+// initialization of station list at very first Station List call
+void init_station_lists(void) {
+ int type,i;
+
+ blank_icon = XCreatePixmap(XtDisplay(appshell),RootWindowOfScreen(XtScreen(appshell)),20,20,
+ DefaultDepthOfScreen(XtScreen(appshell)));
+
+begin_critical_section(&station_list_dialog_lock, "list_gui.c:init_station_lists" );
+
+ for (type=0;type<LST_NUM;type++) {
+ station_list_dialog[type] = NULL; // set list to undefined
+ for (i=0;i<ROWS;i++) {
+ SL_icon[type][i] = XCreatePixmap(XtDisplay(appshell),RootWindowOfScreen(XtScreen(appshell)),20,20,
+ DefaultDepthOfScreen(XtScreen(appshell)));
+ }
+ }
+ memset(SL_callback, 0, sizeof(SL_callback));
+
+end_critical_section(&station_list_dialog_lock, "list_gui.c:init_station_lists" );
+
+}
+
+
+
+
+
+// check if there is at least one station of a specific type now used only in db.c
+int stations_types(int type) {
+ int st;
+ DataRow *p_station;
+
+ st=0;
+ for (p_station=n_first;p_station != NULL;p_station=p_station->n_next) {
+ if ((p_station->flag & ST_ACTIVE) != 0) { // ignore deleted objects
+ switch (type) {
+ case 0: // all stations list
+ case 4: // last stations
+ st++;
+ break;
+ case 1: // mobile stations list
+ if (p_station->newest_trackpoint != NULL)
+ st++;
+ break;
+ case 2: // WX stations list
+ if (p_station->weather_data != NULL)
+ st++;
+ break;
+ case 3: // local stations list
+ if ((p_station->flag & ST_VIATNC) != 0)
+ st++;
+ break;
+ case 5: // Object/Item list
+ if ( ((p_station->flag & ST_OBJECT) != 0) ||
+ ((p_station->flag & ST_ITEM) != 0) )
+ st++;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ if (st==0)
+ st=1;
+ return(st);
+}
+
+
+
+
+
+void station_list_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ int type;
+ int i;
+
+ type = atoi((char *)clientData);
+ XtPopdown(station_list_dialog[type]);
+
+ begin_critical_section(&station_list_dialog_lock, "list_gui.c:station_list_destroy_shell" );
+
+ for (i = 0; i < ROWS; i++) {
+ if (SL_callback[type][i]) {
+ XtFree(SL_callback[type][i]);
+ SL_callback[type][i] = NULL;
+ }
+ }
+
+ XtDestroyWidget(station_list_dialog[type]);
+ station_list_dialog[type] = (Widget)NULL; // clear list definition
+
+ end_critical_section(&station_list_dialog_lock, "list_gui.c:station_list_destroy_shell" );
+
+}
+
+
+
+/*
+ * Callback for station icon in list.
+ * Calls a function to center the map on the selected station from the list.
+ */
+void Call_locate_station(/*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ if (clientData != NULL && strlen(clientData) > 0) {
+ locate_station(w, clientData, 1,1,1);
+ }
+}
+
+
+
+/*
+ * *** This callback is not linked to a control on list yet. ***
+ * Invokes the station information dialog for the selected station from the list.
+ */
+void Call_Station_data(/*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ if (clientData != NULL && strlen(clientData) > 0) {
+ Station_data(w, clientData, NULL);
+ }
+}
+
+
+
+/*
+ * Fill list with new data
+ */
+void Station_List_fill(int type, int new_offset) {
+ int row;
+ char temp[8];
+ char *temp_ptr;
+ Dimension w,h; // size of scrollbar in pixel
+ Dimension ww,wh; // size of entire widget in pixel
+ Dimension new_h; // overall height in pixel
+ char stemp[400];
+ char stemp1[60];
+ char stemp2[60];
+ char temp_call[MAX_CALLSIGN+1];
+ long l_lat, l_lon;
+ float value;
+ WeatherRow *weather;
+ DataRow *p_station;
+ DataRow *p_name;
+ int cur_offset;
+ Dimension count, inview;
+ int to_move, rows;
+ int strwid;
+
+ assert(ROWS <= SL_MAX);
+#define HGT 26
+#define FUDGE 78
+ // type 0 all, 1: mobile, 2: WX, 3: local, 4: time, 5: Objects/Items
+ // offset is the entry that should be displayed in the first line
+
+ w = h = ww = wh = 0;
+ if (station_list_dialog[type] != NULL) { // if list is defined
+ // the list is first drawn very big then gets initialized to the correct size
+ // I don't want the first wrong draw but don't know how to avoid it. DK7IN
+
+ // there are wrong icons drawn on the first time... ????
+ if (list_size_i[type]) { // we are initialized...
+ // ww, wh get width and height of entire widget:
+ XtVaGetValues(station_list_dialog[type], XmNwidth, &ww, XmNheight, &wh, NULL);
+ // w, h get width and height of scrollbar:
+ XtVaGetValues(SL_scroll[type], XmNwidth, &w, XmNheight, &h, NULL);
+ rows = (h+10) / HGT; // number of rows we can display, HGT pixel per row
+// fprintf(stderr,"fill: %d %d %d\n",wh, h, rows);
+ } else {
+ if (list_size_w[type] > 0 && list_size_h[type] > 0) {
+ wh = list_size_h[type]; // restore size
+ ww = list_size_w[type];
+ rows = (wh -FUDGE+10) / HGT; // Fudge Factor ???
+// fprintf(stderr,"load: %d %d\n",wh, rows);
+ } else {
+ wh = 500; // start with this... ???
+ ww = 700;
+ rows = (wh -FUDGE+10) / HGT; // Fudge Factor ???
+// fprintf(stderr,"set: %d %d\n",wh, rows);
+ }
+ XtVaSetValues(station_list_dialog[type], XmNwidth, ww, NULL); // set widget width
+ }
+ if (rows > ROWS) // limit vertical size to data structure size for widgets
+ rows = ROWS;
+ if (rows < 1)
+ rows = 1;
+ // new_h = (rows*HGT) + (wh-h); // (rows + border) in pixel
+ new_h = (rows*HGT) + FUDGE; // (rows + border) in pixel
+ XtVaSetValues(station_list_dialog[type], XmNheight, new_h, NULL); // correct widget height
+
+ list_size_h[type] = new_h; // remember current size
+ list_size_w[type] = ww;
+ list_size_i[type] = (int)TRUE; // don't init next time
+
+ // look for the station to display on the first row...
+ p_station = NULL;
+ if (type == LST_TIM)
+ (void)search_station_time(&p_station,top_time,top_sn); // gives match or next station
+ else
+ (void)search_station_name(&p_station,top_call[type],1); // gives match or next station
+ get_list_member(type, &p_station, 0, 1); // get member in list for first row
+
+ // get updated statistics, database may have changed since last call
+ count = 0;
+ cur_offset = 0;
+ p_name = NULL;
+ get_list_member(type, &p_name, 0, 1); // get first member in list
+
+ while (p_name != NULL) {
+ if (p_name == p_station)
+ cur_offset = count; // got offset of first row entry
+ count++; // count valid list member
+ get_list_member(type, &p_name, 1, 1); // get next member in list
+ }
+
+ // check boundaries
+ new_offset += cur_offset - last_offset[type]; // adjust for database changes
+
+ if (count == 0) count = 1; // empty
+ if (count - new_offset < rows) // bottom
+ new_offset = count - rows; // keep page filled, if possible
+ if (new_offset < 0) // top
+ new_offset = 0;
+ inview = rows; // number of stations in view
+ if (inview > count) // partially filled
+ inview = count;
+
+ // update scrollbar parameters
+ XtVaSetValues(SL_scroll[type],
+ XmNmaximum, count,
+ XmNpageIncrement, inview,
+ XmNvalue, new_offset,
+ XmNsliderSize, inview,
+ NULL);
+
+ if (new_offset == 0) { // stay at first member
+ p_station = NULL;
+ get_list_member(type, &p_station, 0, 1); // get first member in list
+ } else {
+ // if database changed, adjust first entry accordingly
+ to_move = new_offset - cur_offset;
+ while (to_move > 0) { // move down, if neccessary
+ if (p_station != 0)
+ get_list_member(type, &p_station, 1, 1); // gets next member in list
+ to_move--;
+ }
+ while (to_move < 0) { // move up, if neccessary
+ if (p_station != 0)
+ get_list_member(type, &p_station, 1, 0); // gets previous member in list
+ to_move++;
+ }
+ }
+
+ // store current start position, we need a unique index for this to work (time?)
+ if (new_offset == 0 || p_station == NULL) { // keep it at top
+ if (type != LST_TIM)
+ top_call[type][0] = '\0';
+ else {
+ top_time = 0;
+ top_sn = -1;
+ }
+ } else {
+ if (type != LST_TIM) {
+ xastir_snprintf(top_call[type],
+ MAX_CALLSIGN+1,
+ "%s",
+ p_station->call_sign); // remember call at list top
+ }
+ else {
+ top_time = p_station->sec_heard; // remember time station was heard
+ top_sn = p_station->time_sn; // remember time serial number
+ }
+ }
+ last_offset[type] = new_offset;
+
+ // now fill the list rows
+ xastir_snprintf(temp, sizeof(temp), "%d", (rows+new_offset)); // calculate needed string width
+ strwid = (int)strlen(temp); // to keep it right justified
+
+begin_critical_section(&station_list_dialog_lock, "list_gui.c:Station_List_fill" );
+
+ // Start filling in the rows of the widget
+ for (row=0; row<rows; row++) { // loop over display lines
+ if (p_station != NULL) { // we have data...
+ int ghost;
+
+ // icon
+ XtVaSetValues(SL_da[type][row],XmNlabelPixmap, blank_icon,NULL);
+ XtManageChild(SL_da[type][row]);
+
+ if (type == LST_OBJ || type == LST_MYOBJ) {
+ if (p_station->flag & ST_ACTIVE) {
+ ghost = 0; // Active object/item
+ }
+ else {
+ ghost = 1; // Deleted object/item
+ }
+ }
+ else {
+ ghost = 0; // Not an object
+ }
+
+ // Blank out the icon first
+ XtVaSetValues(SL_da[type][row],XmNlabelPixmap, blank_icon,NULL);
+ XtManageChild(SL_da[type][row]);
+ symbol(SL_da[type][row],0,'~','$','\0',SL_icon[type][row],0,0,0,' ');
+ XtVaSetValues(SL_da[type][row],XmNlabelPixmap, SL_icon[type][row],NULL);
+ XtManageChild(SL_da[type][row]);
+
+ // Now redraw it
+ symbol(SL_da[type][row],ghost,p_station->aprs_symbol.aprs_type,
+ p_station->aprs_symbol.aprs_symbol,
+ p_station->aprs_symbol.special_overlay,SL_icon[type][row],ghost,0,0,' ');
+
+ XtVaSetValues(SL_da[type][row],XmNlabelPixmap, SL_icon[type][row],NULL);
+ XtManageChild(SL_da[type][row]);
+
+ if (SL_callback[type][row]) XtFree(SL_callback[type][row]);
+ SL_callback[type][row] = XmTextFieldGetString(SL_call[type][row]);
+
+ // Pressing the icon button centers the map on the station.
+ XtAddCallback( (XtPointer)SL_da[type][row],
+ XmNactivateCallback,
+ Call_locate_station,
+ SL_callback[type][row]
+ );
+
+ // number in list
+ xastir_snprintf(temp, sizeof(temp), "%*d", strwid, (row+1+new_offset));
+ XmTextFieldSetString(SL_list[type][row],temp);
+ XtManageChild(SL_list[type][row]);
+
+ // call (or object/item name)
+ /* check to see if string changed and over write */
+ temp_ptr = XmTextFieldGetString(SL_call[type][row]);
+ xastir_snprintf(temp_call, sizeof(temp_call), "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ if (strcmp(temp_call,p_station->call_sign) !=0 ) {
+ XmTextFieldSetString(SL_call[type][row],p_station->call_sign);
+ if (ghost)
+ XtSetSensitive(SL_call[type][row],FALSE);
+ else
+ XtSetSensitive(SL_call[type][row],TRUE);
+ XtManageChild(SL_call[type][row]);
+ }
+
+ switch (type) {
+ case LST_TNC: // local stations list
+ case LST_TIM: // last stations list
+ case LST_ALL: // stations list
+ case LST_OBJ: // objects/items
+ case LST_MYOBJ: // my objects/items
+ xastir_snprintf(stemp, sizeof(stemp), "%5d",
+ (int)p_station->num_packets);
+ XmTextFieldSetString(SL_packets[type][row],stemp);
+ XtManageChild(SL_packets[type][row]);
+
+ if (strlen(p_station->pos_time) > 13) {
+ xastir_snprintf(stemp, sizeof(stemp), "%c%c/%c%c %c%c:%c%c",
+ //sprintf(stemp,"%c%c/%c%c/%c%c%c%c %c%c:%c%c",
+ p_station->pos_time[0],
+ p_station->pos_time[1],
+ p_station->pos_time[2],
+ p_station->pos_time[3],
+ //p_station->pos_time[4],
+ //p_station->pos_time[5],
+ //p_station->pos_time[6],
+ //p_station->pos_time[7],
+ p_station->pos_time[8],
+ p_station->pos_time[9],
+ p_station->pos_time[10],
+ p_station->pos_time[11]);
+ } else
+ xastir_snprintf(stemp, sizeof(stemp), " ");
+
+ XmTextFieldSetString(SL_pos_time[type][row],stemp);
+ XtManageChild(SL_pos_time[type][row]);
+
+ xastir_snprintf(stemp, sizeof(stemp), "%s", p_station->node_path_ptr);
+ XmTextFieldSetString(SL_node_path[type][row],stemp);
+ XtManageChild(SL_node_path[type][row]);
+
+ xastir_snprintf(stemp, sizeof(stemp), "%s", p_station->power_gain);
+ XmTextFieldSetString(SL_power_gain[type][row],stemp);
+ XtManageChild(SL_power_gain[type][row]);
+
+// Should we display only the first comment field we have stored, or
+// concatenate all of them up to the limit of stemp?
+ //xastir_snprintf(stemp, sizeof(stemp), "%s", p_station->comments);
+ if ( (p_station->comment_data != NULL)
+ && (p_station->comment_data->text_ptr != NULL) )
+ xastir_snprintf(stemp, sizeof(stemp), "%s", p_station->comment_data->text_ptr);
+ else
+ stemp[0] = '\0'; // Empty string
+
+ XmTextFieldSetString(SL_comments[type][row],stemp);
+ XtManageChild(SL_comments[type][row]);
+
+ break;
+
+ case LST_MOB: // mobile stations list
+ if (strlen(p_station->course)>0)
+ XmTextFieldSetString(SL_course[type][row],p_station->course);
+ else
+ XmTextFieldSetString(SL_course[type][row],"");
+
+ XtManageChild(SL_course[type][row]);
+ if (strlen(p_station->speed)>0) {
+ if (!english_units)
+ xastir_snprintf(stemp, sizeof(stemp), "%.1f",
+ atof(p_station->speed)*1.852);
+ else
+ xastir_snprintf(stemp, sizeof(stemp), "%.1f",
+ atof(p_station->speed)*1.1508);
+
+ XmTextFieldSetString(SL_speed[type][row],stemp);
+ } else
+ XmTextFieldSetString(SL_speed[type][row],"");
+
+ XtManageChild(SL_speed[type][row]);
+
+ if (strlen(p_station->altitude)>0) {
+ if (!english_units)
+ xastir_snprintf(stemp, sizeof(stemp), "%s", p_station->altitude);
+ else
+ xastir_snprintf(stemp, sizeof(stemp), "%.1f", atof(p_station->altitude)*3.28084);
+
+ XmTextFieldSetString(SL_alt[type][row],stemp);
+ } else
+ XmTextFieldSetString(SL_alt[type][row],"");
+
+ XtManageChild(SL_alt[type][row]);
+
+ if (coordinate_system == USE_UTM
+ || coordinate_system == USE_UTM_SPECIAL) {
+ // Create a UTM string from coordinates
+ // in Xastir coordinate system.
+ convert_xastir_to_UTM_str(stemp, sizeof(stemp), p_station->coord_lon, p_station->coord_lat);
+ XmTextFieldSetString(SL_lat_long[type][row],stemp);
+ XtManageChild(SL_lat_long[type][row]);
+ }
+ else if (coordinate_system == USE_MGRS) {
+ // Create an MGRS string from
+ // coordinates in Xastir coordinate
+ // system.
+ convert_xastir_to_MGRS_str(stemp,
+ sizeof(stemp),
+ p_station->coord_lon,
+ p_station->coord_lat,
+ 0);
+ XmTextFieldSetString(SL_lat_long[type][row],stemp);
+ XtManageChild(SL_lat_long[type][row]);
+ }
+ else {
+ // Create lat/lon strings from coordinates
+ // in Xastir coordinate system.
+ if (coordinate_system == USE_DDDDDD) {
+ convert_lat_l2s(p_station->coord_lat, stemp1, sizeof(stemp1), CONVERT_DEC_DEG);
+ convert_lon_l2s(p_station->coord_lon, stemp2, sizeof(stemp2), CONVERT_DEC_DEG);
+ } else if (coordinate_system == USE_DDMMSS) {
+ convert_lat_l2s(p_station->coord_lat, stemp1, sizeof(stemp1), CONVERT_DMS_NORMAL);
+ convert_lon_l2s(p_station->coord_lon, stemp2, sizeof(stemp2), CONVERT_DMS_NORMAL);
+ } else { // Assume coordinate_system == USE_DDMMMM
+ convert_lat_l2s(p_station->coord_lat, stemp1, sizeof(stemp1), CONVERT_HP_NORMAL);
+ convert_lon_l2s(p_station->coord_lon, stemp2, sizeof(stemp2), CONVERT_HP_NORMAL);
+ }
+ xastir_snprintf(stemp, sizeof(stemp), "%s %s", stemp1, stemp2);
+ XmTextFieldSetString(SL_lat_long[type][row],stemp);
+ XtManageChild(SL_lat_long[type][row]);
+ }
+
+ xastir_snprintf(stemp, sizeof(stemp), "%d",
+ (int)p_station->num_packets);
+ XmTextFieldSetString(SL_packets[type][row],stemp);
+ XtManageChild(SL_packets[type][row]);
+
+ if (strlen(p_station->sats_visible)>0){
+ xastir_snprintf(stemp, sizeof(stemp), "%d", atoi(p_station->sats_visible));
+ XmTextFieldSetString(SL_sats[type][row],stemp);
+ } else
+ XmTextFieldSetString(SL_sats[type][row],"");
+
+ XtManageChild(SL_sats[type][row]);
+
+ l_lat = convert_lat_s2l(my_lat);
+ l_lon = convert_lon_s2l(my_long);
+
+ // Get distance in nautical miles
+ value = (float)calc_distance_course(l_lat,l_lon,
+ p_station->coord_lat,p_station->coord_lon,stemp,sizeof(stemp));
+
+ if (english_units)
+ xastir_snprintf(stemp1, sizeof(stemp1), "%0.1f", (value * 1.15078));
+ else
+ xastir_snprintf(stemp1, sizeof(stemp1), "%0.1f", (value * 1.852));
+
+ XmTextFieldSetString(SL_my_course[type][row],stemp);
+ XtManageChild(SL_my_course[type][row]);
+ XmTextFieldSetString(SL_my_distance[type][row],stemp1);
+ XtManageChild(SL_my_distance[type][row]);
+
+ break;
+
+ case LST_WX: // weather stations list
+
+ weather = p_station->weather_data;
+
+ if ((int)(((sec_old + weather->wx_sec_time)) < sec_now()))
+ break; // Weather data is too old
+
+ if (strlen(weather->wx_course) > 0)
+ XmTextFieldSetString(SL_wx_wind_course[type][row],weather->wx_course);
+ else
+ XmTextFieldSetString(SL_wx_wind_course[type][row],"");
+
+ XtManageChild(SL_wx_wind_course[type][row]);
+
+ if (strlen(weather->wx_speed) > 0) {
+ if (english_units)
+ xastir_snprintf(stemp, sizeof(stemp), "%d", (int)atoi(weather->wx_speed));
+ else
+ xastir_snprintf(stemp, sizeof(stemp), "%d", (int)(atof(weather->wx_speed)*1.6094));
+
+ XmTextFieldSetString(SL_wx_wind_speed[type][row],stemp);
+ } else
+ XmTextFieldSetString(SL_wx_wind_speed[type][row],"");
+
+ XtManageChild(SL_wx_wind_speed[type][row]);
+
+ if (strlen(weather->wx_gust) > 0) {
+ if (english_units)
+ xastir_snprintf(stemp, sizeof(stemp), "%d", atoi(weather->wx_gust));
+ else
+ xastir_snprintf(stemp, sizeof(stemp), "%d", (int)(atof(weather->wx_gust)*1.6094));
+
+ XmTextFieldSetString(SL_wx_wind_gust[type][row],stemp);
+ } else
+ XmTextFieldSetString(SL_wx_wind_gust[type][row],"");
+
+ XtManageChild(SL_wx_wind_gust[type][row]);
+
+ if (strlen(weather->wx_temp) > 0) {
+ if (english_units)
+ xastir_snprintf(stemp, sizeof(stemp), "%d", atoi(weather->wx_temp));
+ else
+ xastir_snprintf(stemp, sizeof(stemp), "%d", (int)(((atof(weather->wx_temp)-32)*5.0)/9.0));
+
+ XmTextFieldSetString(SL_wx_temp[type][row],stemp);
+ } else
+ XmTextFieldSetString(SL_wx_temp[type][row],"");
+
+ XtManageChild(SL_wx_temp[type][row]);
+
+ if (strlen(weather->wx_hum) > 0)
+ XmTextFieldSetString(SL_wx_hum[type][row],weather->wx_hum);
+ else
+ XmTextFieldSetString(SL_wx_hum[type][row],"");
+
+ XtManageChild(SL_wx_hum[type][row]);
+
+//WE7U
+// Change this to inches mercury when English Units is selected
+ if (strlen(weather->wx_baro) > 0) {
+ if (!english_units) { // hPa
+ XmTextFieldSetString(SL_wx_baro[type][row],
+ weather->wx_baro);
+ }
+ else { // Inches Mercury
+ float temp;
+ char temp2[15];
+
+ temp = atof(weather->wx_baro)*0.02953;
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%0.2f",
+ temp);
+ XmTextFieldSetString(SL_wx_baro[type][row],
+ temp2);
+ }
+ }
+ else {
+ XmTextFieldSetString(SL_wx_baro[type][row],"");
+ }
+
+ XtManageChild(SL_wx_baro[type][row]);
+
+ if (strlen(weather->wx_rain) > 0) {
+ if (english_units)
+ xastir_snprintf(stemp, sizeof(stemp), "%0.2f", atof(weather->wx_rain)/100.0);
+ else
+ xastir_snprintf(stemp, sizeof(stemp), "%0.2f", atof(weather->wx_rain)*.254);
+
+ XmTextFieldSetString(SL_wx_rain_h[type][row],stemp);
+ } else
+ XmTextFieldSetString(SL_wx_rain_h[type][row],"");
+
+ XtManageChild(SL_wx_rain_h[type][row]);
+
+ if (strlen(weather->wx_prec_00) > 0) {
+ if (english_units)
+ xastir_snprintf(stemp, sizeof(stemp), "%0.2f", atof(weather->wx_prec_00)/100.0);
+ else
+ xastir_snprintf(stemp, sizeof(stemp), "%0.2f", atof(weather->wx_prec_00)*.254);
+
+ XmTextFieldSetString(SL_wx_rain_00[type][row],stemp);
+ } else
+ XmTextFieldSetString(SL_wx_rain_00[type][row],"");
+
+ XtManageChild(SL_wx_rain_00[type][row]);
+
+ if (strlen(weather->wx_prec_24) > 0) {
+ if (english_units)
+ xastir_snprintf(stemp, sizeof(stemp), "%0.2f", atof(weather->wx_prec_24)/100.0);
+ else
+ xastir_snprintf(stemp, sizeof(stemp), "%0.2f", atof(weather->wx_prec_24)*.254);
+
+ XmTextFieldSetString(SL_wx_rain_24[type][row],stemp);
+ } else
+ XmTextFieldSetString(SL_wx_rain_24[type][row],"");
+
+ XtManageChild(SL_wx_rain_24[type][row]);
+ break;
+
+ default:
+ break;
+ }
+ } else { // no data, empty row
+ XtVaSetValues(SL_da[type][row],XmNlabelPixmap, blank_icon,NULL);
+ XtManageChild(SL_da[type][row]);
+ symbol(SL_da[type][row],0,'~','$','\0',SL_icon[type][row],0,0,0,' ');
+ XtVaSetValues(SL_da[type][row],XmNlabelPixmap, SL_icon[type][row],NULL);
+ XtManageChild(SL_da[type][row]);
+
+ xastir_snprintf(temp, sizeof(temp), "%*d", strwid, (row+1+new_offset));
+ XmTextFieldSetString(SL_list[type][row],temp);
+ XtManageChild(SL_list[type][row]);
+
+ XmTextFieldSetString(SL_call[type][row],"");
+ XtManageChild(SL_call[type][row]);
+
+ switch (type) {
+ case LST_TNC: // local stations list
+ case LST_TIM:
+ case LST_ALL: // stations list
+ case LST_OBJ: // Objects/Items list
+ case LST_MYOBJ: // My objects/Items
+ XmTextFieldSetString(SL_packets[type][row],"");
+ XtManageChild(SL_packets[type][row]);
+ XmTextFieldSetString(SL_pos_time[type][row],"");
+ XtManageChild(SL_pos_time[type][row]);
+ XmTextFieldSetString(SL_node_path[type][row],"");
+ XtManageChild(SL_node_path[type][row]);
+ XmTextFieldSetString(SL_power_gain[type][row],"");
+ XtManageChild(SL_power_gain[type][row]);
+ XmTextFieldSetString(SL_comments[type][row],"");
+ XtManageChild(SL_comments[type][row]);
+ break;
+
+ case LST_MOB: // mobile stations list
+ XmTextFieldSetString(SL_course[type][row],"");
+ XtManageChild(SL_course[type][row]);
+ XmTextFieldSetString(SL_speed[type][row],"");
+ XtManageChild(SL_speed[type][row]);
+ XmTextFieldSetString(SL_alt[type][row],"");
+ XtManageChild(SL_alt[type][row]);
+ XmTextFieldSetString(SL_lat_long[type][row],"");
+ XtManageChild(SL_lat_long[type][row]);
+ XmTextFieldSetString(SL_packets[type][row],"");
+ XtManageChild(SL_packets[type][row]);
+ XmTextFieldSetString(SL_sats[type][row],"");
+ XtManageChild(SL_sats[type][row]);
+ XmTextFieldSetString(SL_my_course[type][row],"");
+ XtManageChild(SL_my_course[type][row]);
+ XmTextFieldSetString(SL_my_distance[type][row],"");
+ XtManageChild(SL_my_distance[type][row]);
+ break;
+
+ case LST_WX: /*WX stations list */
+ XmTextFieldSetString(SL_wx_wind_course[type][row],"");
+ XtManageChild(SL_wx_wind_course[type][row]);
+ XmTextFieldSetString(SL_wx_wind_speed[type][row],"");
+ XtManageChild(SL_wx_wind_speed[type][row]);
+ XmTextFieldSetString(SL_wx_wind_gust[type][row],"");
+ XtManageChild(SL_wx_wind_gust[type][row]);
+ XmTextFieldSetString(SL_wx_temp[type][row],"");
+ XtManageChild(SL_wx_temp[type][row]);
+ XmTextFieldSetString(SL_wx_hum[type][row],"");
+ XtManageChild(SL_wx_hum[type][row]);
+ XmTextFieldSetString(SL_wx_baro[type][row],"");
+ XtManageChild(SL_wx_baro[type][row]);
+ XmTextFieldSetString(SL_wx_rain_h[type][row],"");
+ XtManageChild(SL_wx_rain_h[type][row]);
+ XmTextFieldSetString(SL_wx_rain_00[type][row],"");
+ XtManageChild(SL_wx_rain_00[type][row]);
+ XmTextFieldSetString(SL_wx_rain_24[type][row],"");
+ XtManageChild(SL_wx_rain_24[type][row]);
+ break;
+
+ default:
+ break;
+ }
+ } // empty line
+ if (p_station != NULL)
+ get_list_member(type, &p_station, 1, 1); // get next member in list
+ } // loop over display lines
+
+end_critical_section(&station_list_dialog_lock, "list_gui.c:Station_List_fill" );
+
+ } // if list is defined
+}
+
+
+
+
+
+/*
+ * Check if we have to update an active list, do it if necessary
+ */
+void update_station_scroll_list(void) { // called from UpdateTime() [main.c] in timing loop
+ int i;
+ int pos;
+ Dimension last_h, last_w;
+ int last;
+ int ok;
+
+ last_h = last_w = 0;
+ ok = 0;
+ for (i=0;i<LST_NUM;i++) { // update all active lists
+ if (station_list_dialog[i] != NULL) {
+ XtVaGetValues(station_list_dialog[i], XmNheight, &last_h, XmNwidth, &last_w, NULL);
+ XtVaGetValues(SL_scroll[i], XmNmaximum,&last,XmNvalue, &pos, NULL);
+ if ((redo_list && (sec_now() - last_list_upd > LIST_UPDATE_CYCLE))
+ || (last_h!=list_size_h[i]) || (last_w!=list_size_w[i])
+ || units_last!=english_units) {
+ Station_List_fill(i,pos); // update list contents
+ ok = 1;
+ }
+ }
+ }
+ if (ok == 1) {
+ last_list_upd = sec_now();
+ redo_list = FALSE;
+ }
+ units_last = english_units;
+}
+
+
+
+
+
+void dragCallback(/*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ int i;
+
+ XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
+ i = atoi((char *)clientData);
+ // DK7IN:
+ // todo: We should only do the update if no other list navigation command is
+ // waiting, otherwise we only should update the offset value.
+ // Same with all other callbacks below...
+ Station_List_fill(i,cbs->value);
+}
+
+
+
+
+
+void decrementCallback(/*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ int i;
+
+ XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
+ i = atoi((char *)clientData);
+ Station_List_fill(i,cbs->value);
+}
+
+
+
+
+
+void incrementCallback(/*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ int i;
+
+ XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
+ i = atoi((char *)clientData);
+ Station_List_fill(i,cbs->value);
+}
+
+
+
+
+
+void pageDecrementCallback(/*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ int i;
+
+ XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
+ i = atoi((char *)clientData);
+ Station_List_fill(i,cbs->value);
+}
+
+
+
+
+
+void pageIncrementCallback(/*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ int i;
+
+ XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
+ i = atoi((char *)clientData);
+ Station_List_fill(i,cbs->value);
+}
+
+
+
+
+
+void mouseScrollHandler(Widget w, XtPointer clientData, XButtonEvent* event, Boolean* continueToDispatch) {
+ int i = atoi((char*)clientData);
+ int lines = 2;
+ // no modifier moves 2 lines
+ // shift moves 1 line
+ // control moves 10 lines
+
+ if (event->type == ButtonRelease) {
+ if (event->state & ControlMask)
+ lines = 10;
+ else if (event->state & ShiftMask)
+ lines = 1;
+
+ if (event->button == Button4) { // Scroll up
+ if (last_offset[i] > 0) {
+ if ((last_offset[i] - lines) < 0)
+ Station_List_fill(i, 0);
+ else
+ Station_List_fill(i, last_offset[i] - lines);
+ }
+ }
+ else if (event->button == Button5) { // Scroll down
+ Station_List_fill(i, last_offset[i] + lines);
+ }
+ }
+}
+
+
+
+
+
+void valueChangedCallback(/*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ int i;
+
+ XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
+ i = atoi((char *)clientData);
+ Station_List_fill(i,cbs->value);
+}
+
+
+
+
+
+/*
+ * Setup the various list layouts
+ */
+void Station_List(/*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ int i;
+ Widget pane, form, win_list, form2, button_close;
+ Widget numl,call,sep,sep2;
+ Widget it1, it2, it3, it4, it5, it6, it7, it8, it9;
+ Widget seps[40];
+ Atom delw;
+ int type;
+ char temp[400];
+
+ if (station_list_first) {
+ memset(&SL_scroll, 0, sizeof(SL_scroll));
+ init_station_lists(); // init icons at very first list call
+ station_list_first=0;
+ }
+ type=atoi((char *)clientData);
+ switch(type) {
+ case LST_ALL:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ langcode("LHPUPNI000")); // All Stations
+ break;
+
+ case LST_MOB:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ langcode("LHPUPNI001")); // Mobile Stations
+ break;
+
+ case LST_WX:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ langcode("LHPUPNI002")); // Weather Stations
+ break;
+
+ case LST_TNC:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ langcode("LHPUPNI003")); // Local Stations
+ break;
+
+ case LST_TIM:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ langcode("LHPUPNI004")); // Last Stations
+ break;
+
+ case LST_OBJ:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ langcode("LHPUPNI005")); // Objects/Items
+ break;
+
+ case LST_MYOBJ:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ langcode("LHPUPNI006")); // My Objects/Items
+ break;
+
+ default:
+ return;
+ }
+
+ if (!station_list_dialog[type]) { // setup list area if not previously done
+ // DK7IN: we should destroy those Widgets to get the
+ // memory back, and rebuild it on the next call. ????
+ // I don't exactly know what's going on, but we lose memory
+ // every time we call it.
+
+begin_critical_section(&station_list_dialog_lock, "list_gui.c:Station_List" );
+
+ station_list_dialog[type]= XtVaCreatePopupShell(temp,
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNminWidth, 274,
+ XmNmaxHeight, ROWS*HGT+FUDGE,
+ XmNminHeight, 95,
+// XmNheight, 230,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Station_List pane",xmPanedWindowWidgetClass, station_list_dialog[type],
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Station_List form",xmFormWidgetClass, pane,
+ XmNfractionBase, 5,
+ XmNshadowType, XmSHADOW_OUT,
+ XmNshadowThickness, 1,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ // station number in list
+ numl = XtVaCreateManagedWidget(langcode("LHPUPNI010"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 3,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XmTextFieldSetString(numl,langcode("LHPUPNI010")); // #
+
+ // icon
+
+ // call
+ call = XtVaCreateManagedWidget(langcode("LHPUPNI011"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 9, // 12,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, numl,
+ XmNleftOffset, 23, // 22,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XmTextFieldSetString(call,langcode("LHPUPNI011")); // Call Sign
+
+ switch (type) {
+ case LST_ALL: // All Stations
+ case LST_TNC: // Local Stations [via TNC]
+ case LST_TIM: // Last Stations
+ case LST_OBJ: // Objects/Item
+ case LST_MYOBJ: // My objects/items
+
+ // number of packets heard
+ it1 = XtVaCreateManagedWidget(langcode("LHPUPNI012"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, call,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XmTextFieldSetString(it1,langcode("LHPUPNI012")); // #Pack
+
+ // Last time of position
+ it2 = XtVaCreateManagedWidget(langcode("LHPUPNI013"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 11, //16, //17,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it1,
+ XmNleftOffset, 0, // 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XmTextFieldSetString(it2,langcode("LHPUPNI013")); // Last Position Time
+
+ // Path
+ it3 = XtVaCreateManagedWidget(langcode("LHPUPNI014"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 30,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it2,
+ XmNleftOffset, 0, // 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XmTextFieldSetString(it3,langcode("LHPUPNI014")); // Path
+
+ // PHG
+ it4 = XtVaCreateManagedWidget(langcode("LHPUPNI015"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 7,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it3,
+ XmNleftOffset, 0, // 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XmTextFieldSetString(it4,langcode("LHPUPNI015")); // PHG
+
+ // Comments
+ it5 = XtVaCreateManagedWidget(langcode("LHPUPNI016"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 40,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it4,
+ XmNleftOffset, 0, // 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XmTextFieldSetString(it5,langcode("LHPUPNI016")); // Comments
+ break;
+
+ case LST_MOB: /*mobile list */
+ it1 = XtVaCreateManagedWidget(langcode("LHPUPNI100"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 3,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, call,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it1,langcode("LHPUPNI100")); // CSE
+
+ it2 = XtVaCreateManagedWidget(langcode("LHPUPNI101"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 4,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it1,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it2,langcode("LHPUPNI101")); // SPD
+
+ it3 = XtVaCreateManagedWidget(langcode("LHPUPNI102"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 8,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it2,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it3,langcode("LHPUPNI102")); // ALT.
+
+ it4 = XtVaCreateManagedWidget(langcode("LHPUPNI103"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 25,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it3,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it4,langcode("LHPUPNI209")); // Lat/Lon or UTM
+
+ it6 = XtVaCreateManagedWidget(langcode("LHPUPNI105"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it4,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it6,langcode("LHPUPNI105")); // #Pack
+
+ it7 = XtVaCreateManagedWidget(langcode("LHPUPNI106"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 3,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it6,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it7,langcode("LHPUPNI106")); // LSV
+
+ it8 = XtVaCreateManagedWidget(langcode("LHPUPNI107"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it7,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it8,langcode("LHPUPNI107")); // CFMS
+
+ it9 = XtVaCreateManagedWidget(langcode("LHPUPNI108"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 6,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it8,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it9,langcode("LHPUPNI108")); // DFMS
+
+ break;
+
+ case LST_WX: /*wx list */
+ it1 = XtVaCreateManagedWidget(langcode("LHPUPNI200"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 3,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, call,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it1,langcode("LHPUPNI200")); // CSE
+
+ it2 = XtVaCreateManagedWidget(langcode("LHPUPNI201"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 3,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it1,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it2,langcode("LHPUPNI201")); // SPD
+
+ it3 = XtVaCreateManagedWidget(langcode("LHPUPNI202"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 3,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it2,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it3,langcode("LHPUPNI202")); // GST
+
+ it4 = XtVaCreateManagedWidget(langcode("LHPUPNI203"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 4,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it3,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it4,langcode("LHPUPNI203")); // Temp
+
+ it5 = XtVaCreateManagedWidget(langcode("LHPUPNI204"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 3,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it4,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it5,langcode("LHPUPNI204")); // Hum
+
+ it6 = XtVaCreateManagedWidget(langcode("LHPUPNI205"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 6,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it5,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it6,langcode("LHPUPNI205")); // Baro
+
+ it7 = XtVaCreateManagedWidget(langcode("LHPUPNI206"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it6,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it7,langcode("LHPUPNI206")); // RN-H
+
+ it8 = XtVaCreateManagedWidget(langcode("LHPUPNI207"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNtraversalOn, FALSE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it7,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it8,langcode("LHPUPNI207")); // RNSM
+
+ it9 = XtVaCreateManagedWidget(langcode("LHPUPNI208"), xmTextFieldWidgetClass, form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset,2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, it8,
+ XmNleftOffset, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XmTextFieldSetString(it9,langcode("LHPUPNI208")); // RN24
+
+ break;
+
+ default:
+ break;
+ } // if (!station_list_dialog[type])... from some kilometers above... ;-)
+
+ sep = XtVaCreateManagedWidget("Station_List sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, numl,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNfontList, fontlist1,
+ NULL);
+
+ SL_scroll[type] = XtVaCreateManagedWidget("Station_List SL_scroll", xmScrollBarWidgetClass,form,
+ XmNorientation, XmVERTICAL,
+ XmNtraversalOn, TRUE,
+ XmNmaximum, 10,
+// XmNmaximum, stations_types(type),
+// XmNsliderSize, rows, //
+// XmNpageIncrement, rows, // was 18
+ XmNheight, 145, // test
+ XmNsliderSize, 10, //
+ XmNpageIncrement, 10, // was 18
+ XmNprocessingDirection, XmMAX_ON_BOTTOM,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 42,
+ XmNleftAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_scroll[type], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ win_list = XtVaCreateWidget("Station_List win_list",xmFormWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 42,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 2,
+ XmNrightAttachment, XmATTACH_WIDGET,
+ XmNrightWidget, SL_scroll[type],
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(win_list, ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ for (i=0; i<ROWS;i++) { // setup widgets for maximum number of rows
+ if (i != 0) { // not first row
+
+ seps[i] = XtVaCreateManagedWidget("Station_List seps", xmSeparatorGadgetClass, win_list,
+ XmNorientation, XmHORIZONTAL,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, SL_list[type][i-1],
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ // line
+ SL_list[type][i]= XtVaCreateManagedWidget("Station_List line data", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNalignment, XmALIGNMENT_END,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 2,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, seps[i],
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ } else { // all except first row
+ // station number in list
+ SL_list[type][i]= XtVaCreateManagedWidget("Station_List line data", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNalignment, XmALIGNMENT_END,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 2,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ }
+ XtAddEventHandler(SL_list[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ // station symbol graphics
+ SL_da[type][i] = XtVaCreateManagedWidget("Station_List icon", xmPushButtonWidgetClass, win_list,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNtopOffset, -5, // Align with top of row, not top of text.
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, SL_list[type][i],
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNlabelType, XmPIXMAP,
+ XmNlabelPixmap, SL_icon[type][i],
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+ //XtAddEventHandler(SL_da[type][i], ButtonReleaseMask, FALSE,
+ // (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ // call sign
+ SL_call[type][i]= XtVaCreateManagedWidget("Station_List call data", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 9, // 12,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, SL_da[type][i],
+ XmNleftOffset, 0, // 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_da[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ switch (type) {
+ case LST_ALL: // station list
+ case LST_TNC: // local station list
+ case LST_TIM:
+ case LST_OBJ: // Objects/Items
+ case LST_MYOBJ: // My objects/items
+ // number of packets received
+ SL_packets[type][i] = XtVaCreateManagedWidget("Station_List packets", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, SL_call[type][i],
+ XmNleftOffset, 0, //1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_packets[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ // Last time of position report
+ SL_pos_time[type][i] = XtVaCreateManagedWidget("Station_List pos_time", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 11, //16, // 17,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, SL_packets[type][i],
+ XmNleftOffset, 0, // 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_pos_time[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ // path
+ SL_node_path[type][i] = XtVaCreateManagedWidget("Station_List node_path", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 30,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, SL_pos_time[type][i],
+ XmNleftOffset, 0, // 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_node_path[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ // PHG
+ SL_power_gain[type][i] = XtVaCreateManagedWidget("Station_List packets", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 7,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, SL_node_path[type][i],
+ XmNleftOffset, 0, // 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_power_gain[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ // Comment
+ SL_comments[type][i] = XtVaCreateManagedWidget("Station_List comments", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 40,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, SL_power_gain[type][i],
+ XmNleftOffset, 0, // 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_comments[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+ break;
+
+ case LST_MOB: /*mobile list */
+ SL_course[type][i] = XtVaCreateManagedWidget("Station_List course", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 3,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_call[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_course[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ SL_speed[type][i] = XtVaCreateManagedWidget("Station_List speed", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 4,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_course[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_speed[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ SL_alt[type][i] = XtVaCreateManagedWidget("Station_List alt", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 8,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_speed[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_alt[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ SL_lat_long[type][i] = XtVaCreateManagedWidget("Station_List lat/lon", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 25,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_alt[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_lat_long[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ SL_packets[type][i] = XtVaCreateManagedWidget("Station_List packets", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_lat_long[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_packets[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ SL_sats[type][i] = XtVaCreateManagedWidget("Station_List sats", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 3,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_packets[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_sats[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ SL_my_course[type][i] = XtVaCreateManagedWidget("Station_List my course", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_sats[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_my_course[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ SL_my_distance[type][i] = XtVaCreateManagedWidget("Station_List my distance", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 6,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_my_course[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_my_distance[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ break;
+
+ case LST_WX: /*wx list */
+ SL_wx_wind_course[type][i] = XtVaCreateManagedWidget("Station_List wind course", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 3,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_call[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_wx_wind_course[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ SL_wx_wind_speed[type][i] = XtVaCreateManagedWidget("Station_List wind speed", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 3,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_wx_wind_course[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_wx_wind_speed[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+
+ SL_wx_wind_gust[type][i] = XtVaCreateManagedWidget("Station_List wind gust", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 3,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_wx_wind_speed[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_wx_wind_gust[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ SL_wx_temp[type][i] = XtVaCreateManagedWidget("Station_List temp", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 4,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_wx_wind_gust[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_wx_temp[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ SL_wx_hum[type][i] = XtVaCreateManagedWidget("Station_List humidity", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 3,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_wx_temp[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_wx_hum[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ SL_wx_baro[type][i] = XtVaCreateManagedWidget("Station_List wx baro", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 6,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_wx_hum[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_wx_baro[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ SL_wx_rain_h[type][i] = XtVaCreateManagedWidget("Station_List rain hour", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_wx_baro[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_wx_rain_h[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ SL_wx_rain_00[type][i] = XtVaCreateManagedWidget("Station_List rain since mid", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_wx_rain_h[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_wx_rain_00[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ SL_wx_rain_24[type][i] = XtVaCreateManagedWidget("Station_List rain last 24", xmTextFieldWidgetClass, win_list,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns, 5,
+ XmNbackground, colors[0x0f],
+ XmNalignment, XmALIGNMENT_END,
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, SL_wx_rain_00[type][i],
+ XmNleftOffset, 1,
+ XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNtopWidget, SL_list[type][i],
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddEventHandler(SL_wx_rain_24[type][i], ButtonReleaseMask, FALSE,
+ (XtEventHandler)mouseScrollHandler, (char*)clientData);
+
+ break;
+
+ default:
+ break;
+ }
+ } // each row
+
+ form2 = XtVaCreateWidget("Station_List form2",xmFormWidgetClass, form,
+ XmNfractionBase, 5,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, SL_scroll[type],
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ sep2 = XtVaCreateManagedWidget("Station_List sep2", xmSeparatorGadgetClass,form2,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_close = XtVaCreateManagedWidget(langcode("UNIOP00003"),xmPushButtonGadgetClass,form2,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep2,
+ XmNtopOffset, 4,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 2,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ pos_dialog(station_list_dialog[type]); // calculate position
+ delw = XmInternAtom(XtDisplay(station_list_dialog[type]), "WM_DELETE_WINDOW", FALSE);
+
+ /* call backs */
+ XtAddCallback(SL_scroll[type], XmNdecrementCallback, decrementCallback, (char *)clientData);
+ XtAddCallback(SL_scroll[type], XmNdragCallback, dragCallback, (char *)clientData);
+ XtAddCallback(SL_scroll[type], XmNincrementCallback, incrementCallback, (char *)clientData);
+ XtAddCallback(SL_scroll[type], XmNpageDecrementCallback, pageDecrementCallback, (char *)clientData);
+ XtAddCallback(SL_scroll[type], XmNpageIncrementCallback, pageIncrementCallback, (char *)clientData);
+ XtAddCallback(SL_scroll[type], XmNvalueChangedCallback, valueChangedCallback, (char *)clientData);
+
+ XtAddCallback(button_close, XmNactivateCallback, station_list_destroy_shell, (char *)clientData);
+ XmAddWMProtocolCallback(station_list_dialog[type], delw, station_list_destroy_shell, (char *)clientData);
+
+ XtManageChild(form);
+ XtManageChild(win_list);
+ XtManageChild(form2);
+ XtManageChild(pane);
+
+end_critical_section(&station_list_dialog_lock, "list_gui.c:Station_List" );
+
+ XtPopup(station_list_dialog[type], XtGrabNone);
+
+ // Move focus to the Close button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(station_list_dialog[type]);
+ XmProcessTraversal(button_close, XmTRAVERSE_CURRENT);
+
+
+// Note: If adding new lists, make sure to tweak xa_config.c to
+// increment the number. If not, you'll get an X-Windows error at
+// this point when trying to resize the window:
+
+ /* set last size if there was one */ // done in list_fill
+ if (list_size_w[type] > 0 && list_size_h[type] > 0)
+ XtVaSetValues(station_list_dialog[type],
+ XmNwidth, list_size_w[type],
+ XmNheight, list_size_h[type],
+ NULL);
+
+ if (type != LST_TIM)
+ top_call[type][0] = '\0'; // start at top
+ else {
+ top_time = 0;
+ top_sn = -1;
+ }
+ last_offset[type] = 0;
+ last_list_upd = sec_now();
+ list_size_i[type] = FALSE;
+ redo_list = (int)TRUE;
+
+ Station_List_fill(type,0); // start with top of list
+
+ } else // if (!station_list_dialog[type])
+ // we already have an initialized widget
+ (void)XRaiseWindow(XtDisplay(station_list_dialog[type]), XtWindow(station_list_dialog[type]));
+}
+
+
diff --git a/src/list_gui.h b/src/list_gui.h
new file mode 100644
index 0000000..38d64cf
--- /dev/null
+++ b/src/list_gui.h
@@ -0,0 +1,50 @@
+/*
+ * $Id: list_gui.h,v 1.13 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifndef __XASTIR_LIST_GUI_H
+#define __XASTIR_LIST_GUI_H
+
+// different list types:
+#define LST_ALL 0
+#define LST_MOB 1
+#define LST_WX 2
+#define LST_TNC 3
+#define LST_TIM 4
+#define LST_OBJ 5
+#define LST_MYOBJ 6
+#define LST_NUM 7
+
+extern int list_size_h[];
+extern int list_size_w[];
+
+/* from list_gui.c */
+extern void list_gui_init(void);
+extern void update_station_scroll_list(void);
+extern int stations_types(int type);
+extern void Station_List_fill(int type, int new_offset);
+
+#endif // __XASTIR_LIST_GUI_H
+
+
diff --git a/src/locate_gui.c b/src/locate_gui.c
new file mode 100644
index 0000000..de5a6a9
--- /dev/null
+++ b/src/locate_gui.c
@@ -0,0 +1,1220 @@
+/*
+ * $Id: locate_gui.c,v 1.32 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+
+#include <Xm/XmAll.h>
+#ifdef HAVE_XBAE_MATRIX_H
+#include <Xbae/Matrix.h>
+#endif // HAVE_XBAE_MATRIX_H
+
+#include "xastir.h"
+#include "main.h"
+#include "lang.h"
+#include "maps.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+extern XmFontList fontlist1; // Menu/System fontlist
+
+Widget locate_station_dialog = (Widget)NULL;
+Widget locate_station_data = (Widget)NULL;
+
+char locate_station_call[30];
+static xastir_mutex locate_station_dialog_lock;
+
+Widget locate_place_dialog = (Widget)NULL;
+Widget locate_place_data = (Widget)NULL;
+Widget locate_state_data = (Widget)NULL;
+Widget locate_county_data = (Widget)NULL;
+Widget locate_quad_data = (Widget)NULL;
+Widget locate_type_data = (Widget)NULL;
+Widget locate_gnis_file_data = (Widget)NULL;
+char locate_place_name[50];
+char locate_state_name[50];
+char locate_county_name[50];
+char locate_quad_name[50];
+char locate_type_name[50];
+char locate_gnis_filename[200];
+static xastir_mutex locate_place_dialog_lock;
+
+
+/* locate station values */
+Widget locate_case_data, locate_match_data;
+
+/* locate place values */
+Widget locate_place_case_data, locate_place_match_data;
+Widget locate_place_list;
+Widget locate_place_chooser = (Widget)NULL;
+static xastir_mutex locate_place_chooser_lock;
+char match_array_name[50][200];
+long match_array_lat[50];
+long match_array_long[50];
+int match_quantity = 0;
+
+
+
+
+
+void locate_gui_init(void)
+{
+ init_critical_section( &locate_station_dialog_lock );
+ init_critical_section( &locate_place_dialog_lock );
+ init_critical_section( &locate_place_chooser_lock );
+ locate_station_call[0] = '\0';
+ locate_place_name[0] = '\0';
+ locate_state_name[0] = '\0';
+ locate_county_name[0] = '\0';
+ locate_quad_name[0] = '\0';
+ locate_type_name[0] = '\0';
+}
+
+
+
+
+
+/**** LOCATE STATION ******/
+
+void Locate_station_destroy_shell(/*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+
+begin_critical_section(&locate_station_dialog_lock, "locate_gui.c:Locate_station_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ locate_station_dialog = (Widget)NULL;
+
+end_critical_section(&locate_station_dialog_lock, "locate_gui.c:Locate_station_destroy_shell" );
+
+}
+
+
+
+
+
+/*
+ * Look up detailed FCC/RAC info about the station
+ */
+
+// Determine whether it is a U.S. or Canadian callsign then search
+// through the appropriate database and present the results.
+
+void fcc_rac_lookup(Widget w, XtPointer clientData, XtPointer callData) {
+ char station_call[200];
+ char temp[1000];
+ char temp2[300];
+ char *temp_ptr;
+ FccAppl my_fcc_data;
+ rac_record my_rac_data;
+
+
+ // Snag station call
+ temp_ptr = XmTextFieldGetString(locate_station_data);
+ xastir_snprintf(station_call,
+ sizeof(station_call),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(station_call);
+ (void)remove_trailing_dash_zero(station_call);
+
+ to_upper(station_call);
+
+ switch (station_call[0]) {
+ case 'A':
+ case 'K':
+ case 'N':
+ case 'W':
+ if (search_fcc_data_appl(station_call, &my_fcc_data) == 1) {
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s\n%s %s\n%s %s %s\n%s %s, %s %s, %s %s\n\n",
+ langcode("STIFCC0001"),
+ langcode("STIFCC0003"),
+ my_fcc_data.name_licensee,
+ langcode("STIFCC0004"),
+ my_fcc_data.text_street,
+ my_fcc_data.text_pobox,
+ langcode("STIFCC0005"),
+ my_fcc_data.city,
+ langcode("STIFCC0006"),
+ my_fcc_data.state,
+ langcode("STIFCC0007"),
+ my_fcc_data.zipcode);
+
+ popup_message_always(langcode("WPUPLSP007"),temp);
+ }
+ else {
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "Callsign Not Found!\n");
+ popup_message_always(langcode("POPEM00001"),temp2);
+ }
+ break;
+ case 'V':
+ if (search_rac_data(station_call, &my_rac_data) == 1) {
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s\n%s %s\n%s\n%s, %s\n%s\n",
+ langcode("STIFCC0002"),
+ my_rac_data.first_name,
+ my_rac_data.last_name,
+ my_rac_data.address,
+ my_rac_data.city,
+ my_rac_data.province,
+ my_rac_data.postal_code);
+
+ if (my_rac_data.qual_a[0] == 'A')
+ strncat(temp,
+ langcode("STIFCC0008"),
+ sizeof(temp) - 1 - strlen(temp));
+
+ if (my_rac_data.qual_d[0] == 'D')
+ strncat(temp,
+ langcode("STIFCC0009"),
+ sizeof(temp) - 1 - strlen(temp));
+
+ if (my_rac_data.qual_b[0] == 'B' && my_rac_data.qual_c[0] != 'C')
+ strncat(temp,
+ langcode("STIFCC0010"),
+ sizeof(temp) - 1 - strlen(temp));
+
+ if (my_rac_data.qual_c[0] == 'C')
+ strncat(temp,
+ langcode("STIFCC0011"),
+ sizeof(temp) - 1 - strlen(temp));
+
+ strncat(temp,
+ "\n",
+ sizeof(temp) - 1 - strlen(temp));
+
+ if (strlen(my_rac_data.club_name) > 1) {
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s\n%s\n%s, %s\n%s\n",
+ my_rac_data.club_name,
+ my_rac_data.club_address,
+ my_rac_data.club_city,
+ my_rac_data.club_province,
+ my_rac_data.club_postal_code);
+ strncat(temp,
+ temp2,
+ sizeof(temp) - 1 - strlen(temp));
+ }
+
+
+ popup_message_always(langcode("WPUPLSP007"),temp);
+ }
+ else {
+ // RAC code does its own popup in this case?
+ //fprintf(stderr, "Callsign not found\n");
+ }
+ break;
+ default:
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "Not an FCC or RAC callsign!\n");
+ popup_message_always(langcode("POPEM00001"),temp2);
+ break;
+ }
+
+ // Don't enable this as then we can't click on the Locate button
+ // later.
+ //Locate_station_destroy_shell(w, clientData, callData);
+}
+
+
+
+
+
+/*
+ * Locate a station by centering the map at its position
+ */
+void Locate_station_now(Widget w, XtPointer clientData, XtPointer callData) {
+ char temp2[200];
+ char *temp_ptr;
+
+
+ /* find station and go there */
+ temp_ptr = XmTextFieldGetString(locate_station_data);
+ xastir_snprintf(locate_station_call,
+ sizeof(locate_station_call),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(locate_station_call);
+ (void)remove_trailing_dash_zero(locate_station_call);
+
+ /*fprintf(stderr,"looking for %s\n",locate_station_call);*/
+ if (locate_station(da, locate_station_call, (int)XmToggleButtonGetState(locate_case_data),
+ (int)XmToggleButtonGetState(locate_match_data),1) ==0) {
+ xastir_snprintf(temp2, sizeof(temp2), langcode("POPEM00002"), locate_station_call);
+ popup_message_always(langcode("POPEM00001"),temp2);
+ }
+
+ // Don't enable this as then we can't click on the FCC/RAC
+ // button later, and we'll lose the callsign info if we want to
+ // see it again.
+ //Locate_station_destroy_shell(w, clientData, callData);
+}
+
+
+
+
+
+// Here we pass in a 1 in callData if it's an emergency locate,
+// for when we've received a Mic-E emergency packet.
+//
+void Locate_station(/*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, XtPointer callData) {
+ static Widget pane, form, button_locate, button_cancel, call,
+ button_lookup, sep;
+ Atom delw;
+ int emergency_flag = XTPOINTER_TO_INT(callData);
+
+
+ if (!locate_station_dialog) {
+
+begin_critical_section(&locate_station_dialog_lock, "locate_gui.c:Locate_station" );
+
+ // Check whether it is an emergency locate function
+ if (emergency_flag == 1) {
+ locate_station_dialog = XtVaCreatePopupShell(langcode("WPUPLSP006"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+ }
+ else { // Non-emergency locate
+ locate_station_dialog = XtVaCreatePopupShell(langcode("WPUPLSP001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+ }
+
+
+ pane = XtVaCreateWidget("Locate_station pane",xmPanedWindowWidgetClass, locate_station_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Locate_station form",xmFormWidgetClass, pane,
+ XmNfractionBase, 3,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ call = XtVaCreateManagedWidget(langcode("WPUPLSP002"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ locate_station_data = XtVaCreateManagedWidget("Locate_station data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNwidth, ((15*7)+2),
+ XmNmaxLength, 15,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, call,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ locate_case_data = XtVaCreateManagedWidget(langcode("WPUPLSP003"),xmToggleButtonWidgetClass,form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, call,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ locate_match_data = XtVaCreateManagedWidget(langcode("WPUPLSP004"),xmToggleButtonWidgetClass,form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, call,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget,locate_case_data,
+ XmNleftOffset ,20,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sep = XtVaCreateManagedWidget("Locate_station sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget,locate_case_data,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_lookup = XtVaCreateManagedWidget(langcode("WPUPLSP007"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_locate = XtVaCreateManagedWidget(langcode("WPUPLSP005"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNrightOffset, 5,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_lookup, XmNactivateCallback, fcc_rac_lookup, locate_station_dialog);
+ XtAddCallback(button_locate, XmNactivateCallback, Locate_station_now, locate_station_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Locate_station_destroy_shell, locate_station_dialog);
+
+ XmToggleButtonSetState(locate_case_data,FALSE,FALSE);
+ XmToggleButtonSetState(locate_match_data,TRUE,FALSE);
+
+ XmTextFieldSetString(locate_station_data,locate_station_call);
+
+ pos_dialog(locate_station_dialog);
+
+ delw = XmInternAtom(XtDisplay(locate_station_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(locate_station_dialog, delw, Locate_station_destroy_shell, (XtPointer)locate_station_dialog);
+
+ XtManageChild(form);
+ XtManageChild(pane);
+
+end_critical_section(&locate_station_dialog_lock, "locate_gui.c:Locate_station" );
+
+ XtPopup(locate_station_dialog,XtGrabNone);
+ fix_dialog_size(locate_station_dialog);
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(locate_station_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ }
+ else {
+ (void)XRaiseWindow(XtDisplay(locate_station_dialog), XtWindow(locate_station_dialog));
+ }
+}
+
+
+
+
+
+/*******************************************************************/
+/* Locate Place Chooser routines */
+
+
+
+/*
+ * Locate Place Chooser PopUp window: Cancelled
+ */
+void Locate_place_chooser_destroy_shell(Widget widget, XtPointer clientData, XtPointer callData) {
+ Widget shell = (Widget) clientData;
+
+begin_critical_section(&locate_place_chooser_lock, "locate_gui.c:Locate_place_chooser_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ locate_place_chooser = (Widget)NULL;
+
+end_critical_section(&locate_place_chooser_lock, "locate_gui.c:Locate_place_chooser_destroy_shell" );
+
+}
+
+
+
+
+
+/*
+ * Locate Place Selection PopUp window: Map selected place
+ */
+void Locate_place_chooser_select(Widget widget,
+ XtPointer clientData,
+ XtPointer callData) {
+
+ int ii, xx;
+ char *temp;
+ XmString *list;
+ int found = 0;
+ int index = 0;
+
+begin_critical_section(&locate_place_chooser_lock, "locate_gui.c:Locate_place_chooser_select" );
+
+ if (locate_place_chooser) {
+ XtVaGetValues(locate_place_list,
+ XmNitemCount,
+ &ii,
+ XmNitems,
+ &list,
+ NULL);
+
+ for (xx=1; xx<=ii; xx++) {
+ if (XmListPosSelected(locate_place_list, xx)) {
+ found = 1;
+ index = xx;
+ if (XmStringGetLtoR(list[(xx-1)], XmFONTLIST_DEFAULT_TAG, &temp))
+ xx=ii+1;
+ }
+ }
+
+ if (found) {
+
+ // Center the map at the chosen location
+ set_map_position(widget,
+ match_array_lat[index-1],
+ match_array_long[index-1]);
+
+ XtFree(temp);
+ }
+ }
+
+end_critical_section(&locate_place_chooser_lock, "locate_gui.c:Locate_place_chooser_select" );
+
+}
+
+
+
+
+
+void Locate_place_chooser(/*@unused@*/ Widget widget,
+ XtPointer clientData,
+ /*@unused@*/ XtPointer callData) {
+
+ Widget pane, form, button_ok, button_cancel;
+ Arg al[50];
+ register unsigned int ac = 0;
+ int ii, nn;
+ XmString str_ptr;
+ Atom delw;
+
+
+ if (locate_place_chooser != NULL)
+ Locate_place_chooser_destroy_shell(locate_place_chooser, locate_place_chooser, NULL);
+
+begin_critical_section(&locate_place_chooser_lock, "locate_gui.c:Locate_place_chooser");
+
+ if (locate_place_chooser == NULL) {
+
+ // Set up a selection box:
+ locate_place_chooser = XtVaCreatePopupShell(langcode("WPUPCFS028"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Locate_place_chooser pane",xmPanedWindowWidgetClass, locate_place_chooser,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Locate_place_chooser form",xmFormWidgetClass, pane,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+
+ // Attach buttons first to the bottom of the form,
+ // so that we'll be able to stretch this thing
+ // vertically to see all of the entries.
+ //
+ button_ok = XtVaCreateManagedWidget(langcode("WPUPCFS028"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok,
+ XmNactivateCallback,
+ Locate_place_chooser_select,
+ locate_place_chooser);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_cancel,
+ XmNactivateCallback,
+ Locate_place_chooser_destroy_shell,
+ locate_place_chooser);
+
+ // set args for color
+ ac = 0;
+ XtSetArg(al[ac], XmNbackground, colors[0xff]); ac++;
+ XtSetArg(al[ac], XmNvisibleItemCount, 6); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNshadowThickness, 3); ac++;
+ XtSetArg(al[ac], XmNselectionPolicy, XmSINGLE_SELECT); ac++;
+ XtSetArg(al[ac], XmNscrollBarPlacement, XmBOTTOM_RIGHT); ac++;
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 5); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, button_ok); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 5); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 5); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 5); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ locate_place_list = XmCreateScrolledList(form,"Locate_place_chooser list",al,ac);
+
+ nn = 1;
+ for (ii = 0; ii < match_quantity; ii++) {
+ XmListAddItem(locate_place_list,
+ str_ptr = XmStringCreateLtoR(match_array_name[ii],
+ XmFONTLIST_DEFAULT_TAG),
+ (int)nn++);
+ XmStringFree(str_ptr);
+ }
+
+ pos_dialog(locate_place_chooser);
+
+ delw = XmInternAtom(XtDisplay(locate_place_chooser),
+ "WM_DELETE_WINDOW",
+ FALSE);
+
+ XmAddWMProtocolCallback(locate_place_chooser,
+ delw,
+ Locate_place_chooser_destroy_shell,
+ (XtPointer)locate_place_chooser);
+
+ XtManageChild(form);
+ XtManageChild(locate_place_list);
+ XtVaSetValues(locate_place_list, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(pane);
+
+ XtPopup(locate_place_chooser,XtGrabNone);
+
+ // Move focus to the Cancel button. This appears to
+ // highlight t
+ // button fine, but we're not able to hit the
+ // <Enter> key to
+ // have that default function happen. Note: We
+ // _can_ hit the
+ // <SPACE> key, and that activates the option.
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+ }
+
+end_critical_section(&locate_place_chooser_lock, "locate_gui.c:Locate_place_chooser" );
+
+}
+/*******************************************************************/
+
+
+
+
+
+/**** LOCATE PLACE ******/
+
+void Locate_place_destroy_shell(/*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+
+begin_critical_section(&locate_place_dialog_lock, "locate_gui.c:Locate_place_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ locate_place_dialog = (Widget)NULL;
+
+end_critical_section(&locate_place_dialog_lock, "locate_gui.c:Locate_place_destroy_shell" );
+
+}
+
+
+
+
+
+/*
+ * Locate a place by centering the map at its position
+ */
+void Locate_place_now(Widget w, XtPointer clientData, XtPointer callData) {
+ char *temp_ptr;
+// int ii;
+
+
+ /* find place and go there */
+ temp_ptr = XmTextFieldGetString(locate_place_data);
+ xastir_snprintf(locate_place_name,
+ sizeof(locate_place_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(locate_state_data);
+ xastir_snprintf(locate_state_name,
+ sizeof(locate_state_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(locate_county_data);
+ xastir_snprintf(locate_county_name,
+ sizeof(locate_county_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(locate_quad_data);
+ xastir_snprintf(locate_quad_name,
+ sizeof(locate_quad_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(locate_type_data);
+ xastir_snprintf(locate_type_name,
+ sizeof(locate_type_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(locate_gnis_file_data);
+ xastir_snprintf(locate_gnis_filename,
+ sizeof(locate_gnis_filename),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(locate_place_name);
+ (void)remove_trailing_spaces(locate_state_name);
+ (void)remove_trailing_spaces(locate_county_name);
+ (void)remove_trailing_spaces(locate_quad_name);
+ (void)remove_trailing_spaces(locate_type_name);
+
+ /*fprintf(stderr,"looking for %s\n",locate_place_name);*/
+
+ match_quantity = gnis_locate_place(da, locate_place_name,
+ locate_state_name, locate_county_name, locate_quad_name,
+ locate_type_name, locate_gnis_filename,
+ (int)XmToggleButtonGetState(locate_place_case_data),
+ (int)XmToggleButtonGetState(locate_place_match_data),
+ match_array_name, match_array_lat, match_array_long);
+
+ if (0 == match_quantity) // Try population centers.
+ match_quantity = pop_locate_place(da, locate_place_name,
+ locate_state_name, locate_county_name, locate_quad_name,
+ locate_type_name, locate_gnis_filename,
+ (int)XmToggleButtonGetState(locate_place_case_data),
+ (int)XmToggleButtonGetState(locate_place_match_data),
+ match_array_name, match_array_lat, match_array_long);
+
+ if (match_quantity) {
+ // Found some matches!
+
+ // Have a Chooser dialog if more than one match is found,
+ // plus the associated callbacks. Don't center the map
+ // unless the user chooses one of the matches. Leave the
+ // chooser dialog up so that the user can click on the
+ // matches one at a time until the correct one is found,
+ // then he/she can hit the Close button on that dialog to
+ // make it go away.
+
+ // Bring up a chooser dialog with the results from the
+ // match_array and a close button. Allow the user to choose
+ // which one to center the map to. Could also allow the
+ // user to find out more about each match if we fill the
+ // array with more data from the GNIS file.
+
+// Debug: Print out the contents of the match arrays.
+//fprintf(stderr,"Found %d matches!\n", match_quantity);
+
+/*
+set_dangerous("printing");
+for (ii = 0; ii < match_quantity; ii++) {
+ fprintf(stderr,
+ "%d, %s, %ld, %ld\n",
+ ii,
+ match_array_name[ii],
+ match_array_lat[ii],
+ match_array_long[ii]);
+}
+clear_dangerous();
+*/
+
+ // This one pops up the names of whatever we found.
+ // "Found It!"
+ //popup_message_always( langcode("POPEM00029"), match_array_name[0]);
+
+ // Bring up the new Chooser dialog
+ (void)Locate_place_chooser(w, clientData, callData);
+ }
+ else {
+ // No matches found.
+ popup_message_always(langcode("POPEM00025"),locate_place_name);
+ }
+
+ Locate_place_destroy_shell(w, clientData, callData);
+}
+
+
+
+
+
+void Locate_place(/*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, form, button_ok, button_cancel, sep,
+ place, state, county, quad, place_type, gnis_file;
+ Atom delw;
+
+ if (!locate_place_dialog) {
+
+begin_critical_section(&locate_place_dialog_lock, "locate_gui.c:Locate_place" );
+
+ locate_place_dialog = XtVaCreatePopupShell(langcode("PULDNMP014"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Locate_place pane",xmPanedWindowWidgetClass, locate_place_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ form = XtVaCreateWidget("Locate_place form",xmFormWidgetClass, pane,
+ XmNfractionBase, 2,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ place = XtVaCreateManagedWidget(langcode("FEATURE001"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ locate_place_data = XtVaCreateManagedWidget("Locate_place_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 32,
+ XmNwidth, ((32*7)+2),
+ XmNmaxLength, 30,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, place,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ state = XtVaCreateManagedWidget(langcode("FEATURE002"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, place,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ locate_state_data = XtVaCreateManagedWidget("Locate_state_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 4,
+ XmNwidth, ((4*7)+2),
+ XmNmaxLength, 2,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, place,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, state,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ county = XtVaCreateManagedWidget(langcode("FEATURE003"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, state,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ locate_county_data = XtVaCreateManagedWidget("Locate_county_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 32,
+ XmNwidth, ((32*7)+2),
+ XmNmaxLength, 30,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, state,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, county,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ quad = XtVaCreateManagedWidget(langcode("FEATURE004"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, county,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ locate_quad_data = XtVaCreateManagedWidget("Locate_quad_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 32,
+ XmNwidth, ((32*7)+2),
+ XmNmaxLength, 30,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, county,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, quad,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ place_type = XtVaCreateManagedWidget(langcode("FEATURE005"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, quad,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ locate_type_data = XtVaCreateManagedWidget("Locate_type_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 32,
+ XmNwidth, ((32*7)+2),
+ XmNmaxLength, 30,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, quad,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, place_type,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ gnis_file = XtVaCreateManagedWidget(langcode("FEATURE006"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, place_type,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ locate_gnis_file_data = XtVaCreateManagedWidget("locate_gnis_file_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 40,
+ XmNwidth, ((40*7)+2),
+ XmNmaxLength, 199,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, place_type,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, gnis_file,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ locate_place_case_data = XtVaCreateManagedWidget(langcode("WPUPLSP003"),xmToggleButtonWidgetClass,form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, gnis_file,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ locate_place_match_data = XtVaCreateManagedWidget(langcode("WPUPLSP004"),xmToggleButtonWidgetClass,form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, gnis_file,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget,locate_place_case_data,
+ XmNleftOffset ,20,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sep = XtVaCreateManagedWidget("Locate_place sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget,locate_place_case_data,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("WPUPLSP005"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNrightOffset, 5,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Locate_place_now, locate_place_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Locate_place_destroy_shell, locate_place_dialog);
+
+ XmToggleButtonSetState(locate_place_case_data,FALSE,FALSE);
+ XmToggleButtonSetState(locate_place_match_data,FALSE,FALSE);
+// XtSetSensitive(locate_place_match_data,FALSE);
+
+ XmTextFieldSetString(locate_place_data,locate_place_name);
+ XmTextFieldSetString(locate_state_data,locate_state_name);
+ XmTextFieldSetString(locate_county_data,locate_county_name);
+ XmTextFieldSetString(locate_quad_data,locate_quad_name);
+ XmTextFieldSetString(locate_type_data,locate_type_name);
+ XmTextFieldSetString(locate_gnis_file_data,locate_gnis_filename);
+
+ pos_dialog(locate_place_dialog);
+
+ delw = XmInternAtom(XtDisplay(locate_place_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(locate_place_dialog, delw, Locate_place_destroy_shell, (XtPointer)locate_place_dialog);
+
+ XtManageChild(form);
+ XtManageChild(pane);
+
+end_critical_section(&locate_place_dialog_lock, "locate_gui.c:Locate_place" );
+
+ XtPopup(locate_place_dialog,XtGrabNone);
+ fix_dialog_size(locate_place_dialog);
+
+ // Move focus to the Locate Now! button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(locate_place_dialog);
+ XmProcessTraversal(button_ok, XmTRAVERSE_CURRENT);
+
+ } else {
+ (void)XRaiseWindow(XtDisplay(locate_place_dialog), XtWindow(locate_place_dialog));
+ }
+}
+
+
diff --git a/src/location.c b/src/location.c
new file mode 100644
index 0000000..5321dd3
--- /dev/null
+++ b/src/location.c
@@ -0,0 +1,104 @@
+/*
+ * $Id: location.c,v 1.16 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <netinet/in.h>
+
+#include <Xm/XmAll.h>
+
+#include "xastir.h"
+#include "main.h"
+#include "track_gui.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+static long last_center_longitude; // remember last screen settings
+static long last_center_latitude;
+static long last_scale_x;
+static long last_scale_y;
+
+
+/***********************************************************/
+/* set last map position */
+/* store lat long and zoom */
+/***********************************************************/
+void set_last_position(void) {
+ last_center_longitude=center_longitude;
+ last_center_latitude=center_latitude;
+ last_scale_x = scale_x; // we don't restore this...
+ last_scale_y = scale_y;
+}
+
+
+
+/***********************************************************/
+/* reset map to last position */
+/* */
+/***********************************************************/
+void map_pos_last_position(void) {
+
+ map_pos(last_center_latitude,last_center_longitude,last_scale_y);
+}
+
+
+
+/***********************************************************/
+/* Jump map to position */
+/* */
+/***********************************************************/
+void map_pos(long mid_y, long mid_x, long sz) {
+ // see also set_map_position() in db.c
+
+ // Set interrupt_drawing_now because conditions have changed
+ // (new map center).
+ interrupt_drawing_now++;
+
+ set_last_position();
+ center_longitude = mid_x;
+ center_latitude = mid_y;
+ scale_y = sz;
+ scale_x = get_x_scale(mid_x,mid_y,scale_y);
+ setup_in_view(); // flag all stations in screen view
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(da)) {
+// // We don't care whether or not this succeeds?
+// (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// display_zoom_status();
+// }
+}
+
diff --git a/src/location_gui.c b/src/location_gui.c
new file mode 100644
index 0000000..fffc64e
--- /dev/null
+++ b/src/location_gui.c
@@ -0,0 +1,592 @@
+/*
+ * $Id: location_gui.c,v 1.26 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <Xm/XmAll.h>
+
+#include "xastir.h"
+#include "main.h"
+#include "xa_config.h"
+#include "util.h"
+#include "lang.h"
+#include "snprintf.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+extern XmFontList fontlist1; // Menu/System fontlist
+
+Widget location_dialog = (Widget)NULL;
+Widget location_list;
+
+static xastir_mutex location_dialog_lock;
+
+
+
+
+
+void location_gui_init(void)
+{
+ init_critical_section( &location_dialog_lock );
+}
+
+
+
+
+
+/************************************************/
+/* button fuction for last location */
+/************************************************/
+void Last_location(/*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ map_pos_last_position();
+}
+
+
+
+
+
+/************************************************/
+/* manage jump locations */
+/************************************************/
+void location_destroy_shell(/*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+
+begin_critical_section(&location_dialog_lock, "location_gui.c:location_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ location_dialog = (Widget)NULL;
+
+end_critical_section(&location_dialog_lock, "location_gui.c:location_destroy_shell" );
+
+}
+
+
+
+
+
+/************************************************/
+/* jump to chosen location/zoom */
+/************************************************/
+void location_view(/*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ int i,x;
+ char *location;
+ XmString *list;
+ int found,done;
+ FILE *f;
+ char temp[200];
+ char name[100];
+ char pos[100];
+ char *temp_ptr;
+ char s_lat[20];
+ char s_long[20];
+ char s_sz[10];
+ char location_file_path[MAX_VALUE];
+
+ found=0;
+ XtVaGetValues(location_list,XmNitemCount,&i,XmNitems,&list,NULL);
+
+ for (x=1; x<=i;x++) {
+ if (XmListPosSelected(location_list,x)) {
+ found=1;
+ if (XmStringGetLtoR(list[(x-1)],XmFONTLIST_DEFAULT_TAG,&location))
+ x=i+1;
+ }
+ }
+ get_user_base_dir("config/locations.sys", location_file_path,
+ sizeof(location_file_path));
+ if (found) {
+ f=fopen(location_file_path,"r");
+ if (f!=NULL) {
+ done=0;
+ while (!feof(f) & !done) {
+ (void)get_line(f,temp,200);
+ if (!feof(f) && strlen(temp)>8) {
+ temp_ptr=strtok(temp,"|"); /* get the name */
+ if (temp_ptr!=NULL) {
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ temp);
+ temp_ptr=strtok(NULL,"|"); /* get the pos */
+ xastir_snprintf(pos,
+ sizeof(pos),
+ "%s",
+ temp_ptr);
+ if (strcmp(location,name)==0) {
+ if (3 != sscanf(pos,"%19s %19s %9s", s_lat, s_long, s_sz)) {
+ fprintf(stderr,"location_view:sscanf parsing error\n");
+ }
+ map_pos(convert_lat_s2l(s_lat),convert_lon_s2l(s_long),atol(s_sz));
+ done=1;
+ }
+ }
+ }
+ }
+ (void)fclose(f);
+ }
+ else {
+ fprintf(stderr,"Couldn't open file: %s\n", location_file_path );
+ }
+ XtFree(location);
+ }
+}
+
+
+
+
+
+/************************************************/
+/* sort and jump locations */
+/************************************************/
+void jump_sort(void) {
+ char temp[200];
+ char name[100];
+ char *temp_ptr;
+ FILE *f;
+ char location_file_path[MAX_VALUE];
+ char location_db_file_path[MAX_VALUE];
+
+ get_user_base_dir("config/locations.sys", location_file_path,
+ sizeof(location_file_path));
+ get_user_base_dir("data/locations_db.dat", location_db_file_path,
+ sizeof(location_db_file_path));
+ f=fopen(location_file_path,"r");
+ if (f!=NULL) {
+ while (!feof(f)) {
+ (void)get_line(f,temp,200);
+ if (!feof(f) && strlen(temp)>8) {
+ temp_ptr=strtok(temp,"|"); /* get the name */
+ if (temp_ptr!=NULL) {
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ temp);
+ (void)sort_input_database(location_db_file_path,name,200);
+ }
+ }
+ }
+ (void)fclose(f);
+ }
+ else
+ fprintf(stderr,"Couldn't open file: %s\n", location_file_path );
+}
+
+
+
+
+
+/************************************************/
+/* delete location/zoom */
+/************************************************/
+void location_delete(/*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ int i,x;
+ char *location;
+ XmString *list;
+ int found,ok;
+ FILE *f,*fout;
+ char temp[200];
+ char name[100];
+ char pos[100];
+ char *temp_ptr;
+ char filen[400];
+ char filen_bak[400];
+ char location_file_path[MAX_VALUE];
+ char location_sys_path[MAX_VALUE];
+
+ get_user_base_dir("config/locations.sys", location_file_path,
+ sizeof(location_file_path));
+ get_user_base_dir("config/locations.sys-tmp", location_sys_path,
+ sizeof(location_sys_path));
+
+ found=0;
+ ok=0;
+ XtVaGetValues(location_list,XmNitemCount,&i,XmNitems,&list,NULL);
+
+ for (x=1; x<=i;x++) {
+ if (XmListPosSelected(location_list,x)) {
+ found=1;
+ if (XmStringGetLtoR(list[(x-1)],XmFONTLIST_DEFAULT_TAG,&location)) {
+ XmListDeletePos(location_list,x);
+ x=i+1;
+ }
+ }
+ }
+ if(found) {
+ f=fopen(location_file_path,"r");
+ if (f!=NULL) {
+ fout=fopen(location_sys_path,"a");
+ if (fout!=NULL) {
+ while (!feof(f)) {
+ (void)get_line(f,temp,200);
+ if (!feof(f) && strlen(temp)>8) {
+ temp_ptr=strtok(temp,"|"); /* get the name */
+ if (temp_ptr!=NULL) {
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ temp);
+ temp_ptr=strtok(NULL,"|"); /* get the pos */
+ xastir_snprintf(pos,
+ sizeof(pos),
+ "%s",
+ temp_ptr);
+ if (strcmp(location,name)!=0) {
+ fprintf(fout,"%s|%s\n",name,pos);
+ }
+ }
+ }
+ }
+ (void)fclose(fout);
+ ok=1;
+ }
+ else
+ fprintf(stderr,"Couldn't open file: %s\n", location_sys_path );
+
+ (void)fclose(f);
+ }
+ else {
+ fprintf(stderr,"Couldn't open file: %s\n", location_file_path );
+ }
+ XtFree(location);
+ }
+
+ if (ok==1){
+
+ xastir_snprintf(filen,
+ sizeof(filen),
+ "%s",
+ location_file_path);
+
+ xastir_snprintf(filen_bak,
+ sizeof(filen_bak),
+ "%s",
+ location_sys_path);
+
+ (void)unlink(filen);
+ (void)rename(filen_bak,filen);
+ }
+
+}
+
+
+
+
+
+/************************************************/
+/* add location/zoom */
+/************************************************/
+void location_add(/*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char name[100];
+ char s_long[20];
+ char s_lat[20];
+ FILE *f, *fout;
+ char temp[200];
+ char *temp_ptr;
+ Widget my_text = (Widget) clientData;
+ int len,n,found;
+ char location_file_path[MAX_VALUE];
+ char location_db_path[MAX_VALUE];
+
+ get_user_base_dir("config/locations.sys", location_file_path,
+ sizeof(location_file_path));
+
+ get_user_base_dir("data/locations_db.dat", location_db_path,
+ sizeof(location_db_path));
+
+
+ temp_ptr = XmTextFieldGetString(my_text);
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(name);
+ XmTextFieldSetString(my_text,"");
+ /* should check for name used already */
+ found=0;
+ f=fopen(location_file_path,"r");
+ if (f!=NULL) {
+ while (!feof(f) && !found) {
+ (void)get_line(f,temp,200);
+ if (!feof(f) && strlen(temp)>8) {
+ temp_ptr=strtok(temp,"|"); /* get the name */
+ if (temp_ptr!=NULL) {
+ if (strcmp(name,temp)==0)
+ found=1;
+ }
+ }
+ }
+ (void)fclose(f);
+ }
+ else
+ fprintf(stderr,"Couldn't open file: %s\n", location_file_path );
+
+ if (!found) {
+ /* delete entire list available */
+ XmListDeleteAllItems(location_list);
+ len = (int)strlen(name);
+ if (len>0 && len<100){
+ fout = fopen(location_file_path,"a");
+ if (fout!=NULL) {
+ convert_lat_l2s(center_latitude, s_lat, sizeof(s_lat), CONVERT_HP_NOSP);
+ convert_lon_l2s(center_longitude, s_long, sizeof(s_long), CONVERT_HP_NOSP);
+ fprintf(fout,"%s|%s %s %ld\n",name,s_lat,s_long,scale_y);
+ (void)fclose(fout);
+ }
+ else
+ fprintf(stderr,"Couldn't open file: %s\n", location_file_path );
+ } else
+ popup_message_always(langcode("POPEM00022"),langcode("POPEM00023"));
+
+ /* resort the list and put it back up */
+ n=1;
+ clear_sort_file(location_db_path);
+ jump_sort();
+ sort_list(location_db_path,200,location_list,&n);
+ } else
+ popup_message_always(langcode("POPEM00022"),langcode("POPEM00024")); /* dupe name */
+}
+
+
+
+
+
+/************************************************/
+/* manage jump locations */
+/************************************************/
+void Jump_location(/*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane,form, button_ok, button_add, button_delete, button_cancel, locdata, location_name;
+ int n;
+ Arg al[50]; /* Arg List */
+ unsigned int ac = 0; /* Arg Count */
+ Atom delw;
+ char location_db_path[MAX_VALUE];
+
+ get_user_base_dir("data/locations_db.dat", location_db_path,
+ sizeof(location_db_path));
+
+ if(!location_dialog) {
+
+begin_critical_section(&location_dialog_lock, "location_gui.c:Jump_location" );
+
+ location_dialog = XtVaCreatePopupShell(langcode("JMLPO00001"),
+ xmDialogShellWidgetClass,
+ appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNresize, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Jump_location pane",
+ xmPanedWindowWidgetClass,
+ location_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ form = XtVaCreateWidget("Jump_location form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ /*set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNvisibleItemCount, 11); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNshadowThickness, 3); ac++;
+ XtSetArg(al[ac], XmNbackground, colors[0x0ff]); ac++;
+ XtSetArg(al[ac], XmNselectionPolicy, XmSINGLE_SELECT); ac++;
+ XtSetArg(al[ac], XmNscrollBarPlacement, XmBOTTOM_RIGHT); ac++;
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 5); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 5); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 5); ac++;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ location_list = XmCreateScrolledList(form,
+ "Jump_location list",
+ al,
+ ac);
+
+ n=1;
+ clear_sort_file(location_db_path);
+ jump_sort();
+ sort_list(location_db_path,200,location_list,&n);
+
+ locdata = XtVaCreateManagedWidget(langcode("JMLPO00003"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, XtParent(location_list),
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ location_name = XtVaCreateManagedWidget("Jump_location Location_name",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns,21,
+ XmNwidth,((21*7)+2),
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, XtParent(location_list),
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget,locdata,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("JMLPO00002"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, locdata,
+ XmNtopOffset,15,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_add = XtVaCreateManagedWidget(langcode("UNIOP00007"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, locdata,
+ XmNtopOffset,15,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_delete = XtVaCreateManagedWidget(langcode("UNIOP00008"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, locdata,
+ XmNtopOffset,15,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, locdata,
+ XmNtopOffset,15,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 4,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 5,
+ XmNrightOffset, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_cancel, XmNactivateCallback, location_destroy_shell, location_dialog);
+ XtAddCallback(button_ok, XmNactivateCallback, location_view, NULL);
+ XtAddCallback(button_add, XmNactivateCallback, location_add, location_name);
+ XtAddCallback(button_delete, XmNactivateCallback, location_delete, NULL);
+
+ pos_dialog(location_dialog);
+
+ delw = XmInternAtom(XtDisplay(location_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(location_dialog, delw, location_destroy_shell, (XtPointer)location_dialog);
+
+ XtManageChild(form);
+ XtManageChild(location_list);
+ XtVaSetValues(location_list, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(pane);
+
+end_critical_section(&location_dialog_lock, "location_gui.c:location_destroy_shell" );
+
+ XtPopup(location_dialog,XtGrabNone);
+ fix_dialog_size(location_dialog);
+
+ // Move focus to the Close button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(location_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else {
+ XtPopup(location_dialog,XtGrabNone);
+ (void)XRaiseWindow(XtDisplay(location_dialog), XtWindow(location_dialog));
+ }
+}
+
+
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..90b7513
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,28028 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: main.c,v 1.810 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+
+// This is for debug. If defined to 1, Xastir will display
+// coordinates in the Xastir coordinate system inside the text2
+// widget.
+//
+static int DISPLAY_XASTIR_COORDINATES = 0;
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <math.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <signal.h>
+#include <termios.h>
+#include <pwd.h>
+#include <locale.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <sys/wait.h>
+#include <errno.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+// TVR -- stupid, stupid ImageMagick
+char *xastir_package=PACKAGE;
+char *xastir_version=VERSION;
+#undef PACKAGE
+#undef VERSION
+
+#ifdef HAVE_MAGICK
+#include <sys/types.h>
+#undef RETSIGTYPE
+/* JMT - stupid ImageMagick */
+#define XASTIR_PACKAGE_BUGREPORT PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#define XASTIR_PACKAGE_NAME PACKAGE_NAME
+#undef PACKAGE_NAME
+#define XASTIR_PACKAGE_STRING PACKAGE_STRING
+#undef PACKAGE_STRING
+#define XASTIR_PACKAGE_TARNAME PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#define XASTIR_PACKAGE_VERSION PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#include <magick/api.h>
+#undef PACKAGE_BUGREPORT
+#define PACKAGE_BUGREPORT XASTIR_PACKAGE_BUGREPORT
+#undef XASTIR_PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#define PACKAGE_NAME XASTIR_PACKAGE_NAME
+#undef XASTIR_PACKAGE_NAME
+#undef PACKAGE_STRING
+#define PACKAGE_STRING XASTIR_PACKAGE_STRING
+#undef XASTIR_PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#define PACKAGE_TARNAME XASTIR_PACKAGE_TARNAME
+#undef XASTIR_PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#define PACKAGE_VERSION XASTIR_PACKAGE_VERSION
+#undef XASTIR_PACKAGE_VERSION
+#endif // HAVE_MAGICK
+
+#ifdef HAVE_LIBINTL_H
+#include <libintl.h>
+#define _(x) gettext(x)
+#else // HAVE_LIBINTL_H
+#define _(x) (x)
+#endif // HAVE_LIBINTL_H
+
+//#ifdef HAVE_NETAX25_AXLIB_H
+//#include <netax25/axlib.h>
+//#endif // HAVE_NETAX25_AXLIB_H
+
+#ifdef HAVE_LIBCURL
+#include <curl/curl.h>
+#endif
+
+#ifdef HAVE_LIBGDAL
+// WE7U - stupid ImageMagick
+#define XASTIR_PACKAGE_BUGREPORT PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#define XASTIR_PACKAGE_NAME PACKAGE_NAME
+#undef PACKAGE_NAME
+#define XASTIR_PACKAGE_STRING PACKAGE_STRING
+#undef PACKAGE_STRING
+#define XASTIR_PACKAGE_TARNAME PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#define XASTIR_PACKAGE_VERSION PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#include <ogr_api.h>
+#undef PACKAGE_BUGREPORT
+#define PACKAGE_BUGREPORT XASTIR_PACKAGE_BUGREPORT
+#undef XASTIR_PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#define PACKAGE_NAME XASTIR_PACKAGE_NAME
+#undef XASTIR_PACKAGE_NAME
+#undef PACKAGE_STRING
+#define PACKAGE_STRING XASTIR_PACKAGE_STRING
+#undef XASTIR_PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#define PACKAGE_TARNAME XASTIR_PACKAGE_TARNAME
+#undef XASTIR_PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#define PACKAGE_VERSION XASTIR_PACKAGE_VERSION
+#undef XASTIR_PACKAGE_VERSION
+#include <gdal.h>
+#endif
+
+#include "xastir.h"
+#include "draw_symbols.h"
+#include "main.h"
+#include "xa_config.h"
+#include "maps.h"
+#include "alert.h"
+#include "interface.h"
+#include "wx.h"
+#include "popup.h"
+#include "track_gui.h"
+#include "list_gui.h"
+#include "util.h"
+#include "color.h"
+#include "gps.h"
+#include "bulletin_gui.h"
+#include "rotated.h"
+#include "datum.h"
+#include "igate.h"
+#include "objects.h"
+#include "db_gis.h"
+
+#include "map_OSM.h"
+
+#ifdef HAVE_LIBSHP
+ #include "shp_hash.h"
+#endif // HAVE_LIBSHP
+
+#include "x_spider.h"
+#include "map_cache.h"
+
+#include <Xm/XmAll.h>
+#include <X11/cursorfont.h>
+#include <Xm/ComboBox.h>
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+// Copyright 2008.
+// Added the above "Copyright" just so that grep would find these
+// lines and we could update the years in the Help->About message
+// each time. Otherwise it often gets missed when we're updating
+// the years.
+#define ABOUT_MSG "X Amateur Station Tracking and Information Reporting\n\n http://www.xastir.org\n\nCopyright (C) 1999-2000 Frank Giannandrea\nCopyright (C) 1999-2012 The Xastir Group\nSee the \"LICENSE\" file for other applicable copyrights"
+
+// OpenStreetMap attribution
+#define ABOUT_OSM "Maps, tiles, and data from the OpenStreetMap project are\nCopyright OpenStreetMap and contributors, CC-BY-SA.\nMaps and tiles from CloudMade are Copyright CloudMade, CC-BY-SA.\n http://www.openstreetmap.org/\n http://creativecommons.org/licenses/by-sa/2.0/\n http://www.cloudmade.com/\n"
+
+
+// Define this if you want an xastir.pid file created in the
+// ~/.xastir directory and want to check that there's not another
+// copy of Xastir running before a new one starts up. You can also
+// use this to send SIGHUP or SIGUSR1 signals to a running Xastir
+// from scripts.
+#define USE_PID_FILE_CHECK 1
+
+
+#define DOS_HDR_LINES 8
+
+#define STATUSLINE_ACTIVE 10 /* status line is cleared after 10 seconds */
+#define REPLAY_DELAY 0 /* delay between replayed packets in sec, 0 is ok */
+#define REDRAW_WAIT 3 /* delay between consecutive redraws in seconds (file load) */
+
+
+
+// FONTS FONTS FONTS FONTS FONTS
+//
+// NOTE: See the main() function at the bottom of this module for
+// the default font definition. xa_config.c is where fonts get
+// saved/restored for user-defined fonts.
+// This one is not used anymore:
+//#define XmFONTLIST_DEFAULT_MY "-misc-fixed-*-r-*-*-10-*-*-*-*-*-*-*"
+
+
+// This one goes right along with smaller system fonts on fixed-size
+// LCD screens. Fix new dialogs to the upper left of the main
+// window, don't have them cycle through multiple possible positions
+// as each new dialog is drawn.
+//
+//#define FIXED_DIALOG_STARTUP
+
+// Yet another useful item: Puts the mouse menu on button 1 instead
+// of button3. Useful for one-button devices like touchscreens.
+//
+//#define SWAP_MOUSE_BUTTONS
+
+// If next line uncommented, Xastir will display the status line
+// in 2 rows instead of the normal single row. Formatted especially
+// for 640 pixel wide screens. It also gives a little extra room for
+// the number of stations and the Zoom factor.
+// #define USE_TWO_STATUS_LINES
+
+// Enable this next line to set all flags properly for a 640x480
+// touch-screen: Makes the main window smaller due to the reduced
+// font sizes, makes all dialogs come up at the upper-left of the
+// main Xastir screen, reverses buttons 1 and 3 so that the more
+// important mouse menus are accessible via the touch-screen, and
+// sets it for 2 status lines. Make sure to change the system font
+// size smaller than the default.
+//
+//#define LCD640x480TOUCH
+//
+#ifdef LCD640x480TOUCH
+ #define FIXED_DIALOG_STARTUP
+ #define SWAP_MOUSE_BUTTONS
+ #define USE_TWO_STATUS_LINES
+#endif
+
+
+#define LINE_WIDTH 1
+
+#define ARROWS 1 // Arrow buttons on menubar
+
+// TVR 26 July 2005
+// Moved this magic number to a #define --- there were numerous places
+// where this constant was hard coded, making it difficult to change the
+// map properties line format without breaking something. Now it can live
+// in one place that needs to be updated when the properties line is changed.
+// At the time of writing, the properties line had the followign format:
+// min max lyr fil drg amap name
+// %5d %5d %5d %5c %5c %5c %s
+// placing the name at offset 37
+#define MPD_FILENAME_OFFSET 37
+
+
+// Define the ICON, created with the "bitmap" editor:
+#include "icon.xbm"
+
+// lesstif (at least as of version 0.94 in 2008), doesn't
+// have full implementation of combo boxes.
+#ifndef USE_COMBO_BOX
+#if (XmVERSION >= 2 && !defined(LESSTIF_VERSION))
+# define USE_COMBO_BOX 1
+#endif
+#endif // USE_COMBO_BOX
+
+int geometry_x, geometry_y;
+unsigned int geometry_width, geometry_height;
+int geometry_flags;
+
+static int initial_load = 1;
+int first_time_run = 0;
+
+/* JMT - works under FreeBSD */
+uid_t euid;
+gid_t egid;
+
+
+int my_argc;
+char **my_argv;
+char **my_envp;
+int restart_xastir_now = 0;
+
+
+// A count of the stations currently on the screen. Counted by
+// db.c:display_file() routine.
+int currently_selected_stations = 0;
+int currently_selected_stations_save = 0;
+
+// If my_trail_diff_color is 0, all my calls (SSIDs) will use MY_TRAIL_COLOR.
+// If my_trail_diff_color = 1 then each different ssid for my callsign will use a different color.
+int my_trail_diff_color = 0;
+
+
+// Used in segfault handler
+char dangerous_operation[200];
+
+FILE *file_wx_test;
+
+int tcp_server_pid = 0;
+int udp_server_pid = 0;
+
+int serial_char_pacing; // Inter-char delay in ms for serial ports.
+int dtr_on = 1;
+time_t sec_last_dtr = (time_t)0;
+
+time_t last_updatetime = (time_t)0;
+int time_went_backwards = 0;
+
+/* language in use */
+char lang_to_use[30];
+
+/* version info in main.h */
+int altnet;
+char altnet_call[MAX_CALLSIGN+1];
+
+static void Window_Quit(Widget w, XtPointer client, XtPointer call);
+static void save_state(Widget w, XtPointer client, XtPointer call);
+
+void da_input(Widget w, XtPointer client_data, XtPointer call_data);
+void da_resize(Widget w, XtPointer client_data, XtPointer call_data);
+void da_expose(Widget w, XtPointer client_data, XtPointer call_data);
+
+void BuildPredefinedSARMenu_UI(Widget *parent_menu);
+Widget *predefined_object_menu_parent;
+Widget sar_object_sub;
+Widget predefined_object_menu_items[MAX_NUMBER_OF_PREDEFINED_OBJECTS];
+
+int debug_level;
+
+//Widget hidden_shell;
+Widget appshell;
+Widget form;
+Widget da;
+Widget text;
+Widget text2;
+Widget text3;
+Widget text4;
+Widget log_indicator;
+Widget iface_da;
+Widget menubar;
+Widget toolbar;
+
+Widget configure_station_dialog = (Widget)NULL;
+Widget right_menu_popup = (Widget)NULL; // Button one or left mouse button
+//Widget middle_menu_popup=(Widget)NULL; // Button two or middle mouse button
+//Widget right_menu_popup=(Widget)NULL; // Button three or right mouse button
+Widget trackme_button;
+Widget measure_button;
+Widget move_button;
+Widget cad_draw_button;
+
+Widget CAD_close_polygon_menu_item;
+
+int Station_transmit_type;
+int Igate_type;
+
+Widget Display_data_dialog = (Widget)NULL;
+Widget Display_data_text;
+int Display_packet_data_type;
+int show_only_station_capabilities = 0;
+int Display_packet_data_mine_only = 0;
+
+Widget configure_defaults_dialog = (Widget)NULL;
+Widget configure_timing_dialog = (Widget)NULL;
+Widget configure_coordinates_dialog = (Widget)NULL;
+Widget coordinate_calc_button_ok = (Widget)NULL;
+Widget change_debug_level_dialog = (Widget)NULL;
+
+
+Widget coordinate_calc_dialog = (Widget)NULL;
+Widget coordinate_calc_zone = (Widget)NULL;
+Widget coordinate_calc_latitude_easting = (Widget)NULL;
+Widget coordinate_calc_longitude_northing = (Widget)NULL;
+Widget coordinate_calc_result_text = (Widget)NULL;
+static char coordinate_calc_lat_deg[5];
+static char coordinate_calc_lat_min[15];
+static char coordinate_calc_lat_dir[5];
+static char coordinate_calc_lon_deg[5];
+static char coordinate_calc_lon_min[15];
+static char coordinate_calc_lon_dir[5];
+coordinate_calc_array_type coordinate_calc_array;
+
+
+
+// --------------------------- help menu -----------------------------
+Widget help_list;
+Widget help_index_dialog = (Widget)NULL;
+Widget help_view_dialog = (Widget)NULL;
+Widget emergency_beacon_toggle;
+int emergency_beacon = 0;
+static void Help_About(Widget w, XtPointer clientData, XtPointer callData);
+static void Help_Index(Widget w, XtPointer clientData, XtPointer callData);
+void Emergency_beacon_toggle( Widget widget, XtPointer clientData, XtPointer callData);
+
+// ----------------------------- map ---------------------------------
+Widget map_list;
+Widget map_properties_list;
+void map_index_update_temp_select(char *filename, map_index_record **current);
+void map_index_temp_select_clear(void);
+
+void map_chooser_fill_in (void);
+int map_chooser_expand_dirs = 0;
+
+void map_chooser_init (void);
+
+Widget map_chooser_dialog = (Widget)NULL;
+Widget map_chooser_button_ok = (Widget)NULL;
+Widget map_chooser_button_cancel = (Widget)NULL;
+
+Widget map_properties_dialog = (Widget)NULL;
+static void Map_chooser(Widget w, XtPointer clientData, XtPointer callData);
+Widget map_chooser_maps_selected_data = (Widget)NULL;
+int re_sort_maps = 1;
+
+#ifdef HAVE_MAGICK
+static void Config_tiger(Widget w, XtPointer clientData, XtPointer callData);
+#endif // HAVE_MAGICK
+
+#ifdef HAVE_LIBGEOTIFF
+static void Config_DRG(Widget w, XtPointer clientData, XtPointer callData);
+#endif // HAVE_LIBGEOTIFF
+
+Widget grid_on, grid_off;
+static void Grid_toggle( Widget w, XtPointer clientData, XtPointer calldata);
+int long_lat_grid; // Switch for Map Lat and Long grid display
+
+void Map_border_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData);
+int draw_labeled_grid_border = FALSE; // Toggle labeled border around map.
+
+
+static void CAD_draw_toggle( Widget w, XtPointer clientData, XtPointer calldata);
+
+int map_lock_pan_zoom = 0;
+static void Map_lock_pan_zoom_toggle( Widget w, XtPointer clientData, XtPointer calldata);
+
+int disable_all_maps = 0;
+static void Map_disable_toggle( Widget w, XtPointer clientData, XtPointer calldata);
+
+static void Map_auto_toggle( Widget w, XtPointer clientData, XtPointer calldata);
+int map_auto_maps; /* toggle use of auto_maps */
+static void Map_auto_skip_raster_toggle( Widget w, XtPointer clientData, XtPointer calldata);
+int auto_maps_skip_raster;
+Widget map_auto_skip_raster_button;
+Widget map_border_button;
+
+Widget map_levels_on, map_levels_off;
+static void Map_levels_toggle( Widget w, XtPointer clientData, XtPointer calldata);
+int map_color_levels; /* toggle use of map_color_levels */
+
+Widget map_labels_on, map_labels_off;
+static void Map_labels_toggle( Widget w, XtPointer clientData, XtPointer calldata);
+int map_labels; // toggle use of map_labels */
+
+Widget map_fill_on, map_fill_off;
+static void Map_fill_toggle( Widget w, XtPointer clientData, XtPointer calldata);
+int map_color_fill; /* Whether or not to fill in map polygons with solid color */
+
+int index_maps_on_startup; // Index maps on startup
+static void Index_maps_on_startup_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+Widget map_bgcolor[12];
+static void Map_background(Widget w, XtPointer clientData, XtPointer calldata);
+int map_background_color; /* Background color for maps */
+
+#if !defined(NO_GRAPHICS)
+Widget raster_intensity[11];
+static void Raster_intensity(Widget w, XtPointer clientData, XtPointer calldata);
+#if defined(HAVE_MAGICK)
+Widget gamma_adjust_dialog = (Widget)NULL;
+Widget gamma_adjust_text;
+#endif // HAVE_MAGICK
+#endif // NO_GRAPHICS
+
+Widget map_font_dialog = (Widget)NULL;
+Widget map_font_text[FONT_MAX];
+
+
+Widget map_station_label0,map_station_label1,map_station_label2;
+static void Map_station_label(Widget w, XtPointer clientData, XtPointer calldata);
+int letter_style; /* Station Letter style */
+
+Widget map_icon_outline0,map_icon_outline1,map_icon_outline2,map_icon_outline3;
+static void Map_icon_outline(Widget w, XtPointer clientData, XtPointer calldata);
+int icon_outline_style; /* Icon Outline style */
+
+Widget map_wx_alerts_0,map_wx_alerts_1;
+static void Map_wx_alerts_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+int wx_alert_style; /* WX alert map style */
+time_t map_refresh_interval = 0; /* how often to refresh maps, seconds */
+time_t map_refresh_time = 0; /* when to refresh maps next, seconds */
+
+// ------------------------ Filter and Display menus -----------------------------
+Selections Select_ = { 0, // none
+ 1, // mine
+ 1, // tnc
+ 1, // direct
+ 1, // via_digi
+ 1, // net
+ 0, // tactical only
+ 1, // old_data
+
+ 1, // stations
+ 1, // fixed_stations
+ 1, // moving_stations
+ 1, // weather_stations
+ 1, // CWOP_wx_stations
+ 1, // objects
+ 1, // weather_objects
+ 1, // gauge_objects
+ 1, // other_objects
+};
+
+What_to_display Display_ = { 1, // callsign
+ 1, // label_all_trackpoints
+ 1, // symbol
+ 1, // symbol_rotate
+ 1, // trail
+
+ 1, // course
+ 1, // speed
+ 1, // speed_short
+ 1, // altitude
+
+ 1, // weather
+ 1, // weather_text
+ 1, // temperature_only
+ 1, // wind_barb
+
+ 1, // aloha_circle
+ 1, // ambiguity
+ 1, // phg
+ 1, // default_phg
+ 1, // phg_of_moving
+
+ 1, // df_data
+ 1, // df_beamwidth_data
+ 1, // df_bearing_data
+ 1, // dr_data
+ 1, // dr_arc
+ 1, // dr_course
+ 1, // dr_symbol
+
+ 1, // dist_bearing
+ 1, // last_heard
+};
+
+Widget select_none_button;
+Widget select_mine_button;
+Widget select_tnc_button;
+Widget select_direct_button;
+Widget select_via_digi_button;
+Widget select_net_button;
+Widget select_tactical_button;
+Widget select_old_data_button;
+
+Widget select_stations_button;
+Widget select_fixed_stations_button;
+Widget select_moving_stations_button;
+Widget select_weather_stations_button;
+Widget select_CWOP_wx_stations_button;
+Widget select_objects_button;
+Widget select_weather_objects_button;
+Widget select_gauge_objects_button;
+Widget select_other_objects_button;
+
+
+Widget display_callsign_button;
+Widget display_label_all_trackpoints_button;
+Widget display_symbol_button;
+Widget display_symbol_rotate_button;
+Widget display_trail_button;
+
+Widget display_course_button;
+Widget display_speed_button;
+Widget display_speed_short_button;
+Widget display_altitude_button;
+
+Widget display_weather_button;
+Widget display_weather_text_button;
+Widget display_temperature_only_button;
+Widget display_wind_barb_button;
+
+Widget display_aloha_circle_button;
+Widget display_ambiguity_button;
+Widget display_phg_button;
+Widget display_default_phg_button;
+Widget display_phg_of_moving_button;
+
+Widget display_df_data_button;
+Widget display_df_beamwidth_data_button;
+Widget display_df_bearing_data_button;
+Widget display_dr_data_button;
+Widget display_dr_arc_button;
+Widget display_dr_course_button;
+Widget display_dr_symbol_button;
+
+Widget display_dist_bearing_button;
+Widget display_last_heard_button;
+
+
+static void Select_none_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_mine_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_tnc_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_direct_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_via_digi_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_net_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_tactical_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_old_data_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+static void Select_stations_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_fixed_stations_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_moving_stations_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_weather_stations_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_CWOP_wx_stations_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_objects_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_weather_objects_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_other_objects_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Select_gauge_objects_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+
+static void Display_callsign_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_label_all_trackpoints_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_symbol_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_symbol_rotate_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_trail_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+static void Display_course_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_speed_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_speed_short_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_altitude_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+static void Display_weather_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_weather_text_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_temperature_only_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_wind_barb_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+static void Display_aloha_circle_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_ambiguity_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_phg_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_default_phg_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_phg_of_moving_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+static void Display_df_data_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_df_beamwidth_data_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_df_bearing_data_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_dr_data_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_dr_arc_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_dr_course_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_dr_symbol_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+static void Display_dist_bearing_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void Display_last_heard_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+
+// ------------------------ Interfaces --------------------------
+static void Transmit_disable_toggle( Widget widget, XtPointer clientData, XtPointer callData);
+static void Posit_tx_disable_toggle( Widget widget, XtPointer clientData, XtPointer callData);
+static void Object_tx_disable_toggle( Widget widget, XtPointer clientData, XtPointer callData);
+static void Server_port_toggle( Widget widget, XtPointer clientData, XtPointer callData);
+int transmit_disable;
+int posit_tx_disable;
+int object_tx_disable;
+int enable_server_port = 0;
+Widget iface_transmit_now, posit_tx_disable_toggle, object_tx_disable_toggle;
+Widget server_port_toggle;
+
+#ifdef HAVE_GPSMAN
+Widget Fetch_gps_track, Fetch_gps_route, Fetch_gps_waypoints;
+Widget Fetch_RINO_waypoints;
+Widget Send_gps_track, Send_gps_route, Send_gps_waypoints;
+int gps_got_data_from = 0; // We got data from a GPS
+int gps_operation_pending = 0; // A GPS transfer is happening
+int gps_details_selected = 0; // Whether name/color have been selected yet
+Widget gpsfilename_text; // Short name of gps map (no color/type)
+char gps_map_filename[MAX_FILENAME];// Chosen name of gps map (including color)
+char gps_map_filename_base[MAX_FILENAME]; // Same minus ".shp"
+char gps_map_filename_base2[MAX_FILENAME]; // Same minus ".shp" and color
+char gps_temp_map_filename[MAX_FILENAME];
+char gps_temp_map_filename_base[MAX_FILENAME]; // Same minus ".shp"
+char gps_dbfawk_format[]="BEGIN_RECORD {key=\"\"; lanes=3; color=%d; name=\"%s\"; filled=0; pattern=1; display_level=65536; label_level=128; label_color=8; symbol=\"\"}\n";
+int gps_map_color = 0; // Chosen color of gps map
+int gps_map_color_offset; // offset into colors array of that color.
+char gps_map_type[30]; // Type of GPS download
+void check_for_new_gps_map(int curr_sec);
+Widget GPS_operations_dialog = (Widget)NULL;
+#endif // HAVE_GPSMAN
+
+// ------------------------ unit conversion --------------------------
+static void Units_choice_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+// 0: metric, 1: english, (2: nautical, not fully implemented)
+int english_units;
+
+char un_alt[2+1]; // m / ft
+char un_dst[2+1]; // mi / km (..nm)
+char un_spd[4+1]; // mph / km/h (..kn)
+double cvt_m2len; // from meter
+double cvt_kn2len; // from knots
+double cvt_mi2len; // from miles
+double cvt_dm2len; // from decimeter
+double cvt_hm2len; // from hectometer
+
+void update_units(void);
+
+// dist/bearing on status line
+static void Dbstatus_choice_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+int do_dbstatus;
+
+
+// Coordinate System
+int coordinate_system = USE_DDMMMM; // Default, used for most APRS systems
+
+
+// ------------------------- audio alarms ----------------------------
+Widget configure_audio_alarm_dialog = (Widget)NULL;
+Widget audio_alarm_config_play_data,
+ audio_alarm_config_play_on_new_station, audio_alarm_config_play_ons_data,
+ audio_alarm_config_play_on_new_message, audio_alarm_config_play_onm_data,
+ audio_alarm_config_play_on_prox, audio_alarm_config_play_onpx_data,
+ audio_alarm_config_play_on_bando, audio_alarm_config_play_onbo_data,
+ prox_min_data, prox_max_data, bando_min_data, bando_max_data,
+ audio_alarm_config_play_on_wx_alert, audio_alarm_config_wx_alert_data;
+static void Configure_audio_alarms(Widget w, XtPointer clientData, XtPointer callData);
+
+// ---------------------------- speech -------------------------------
+Widget configure_speech_dialog = (Widget)NULL;
+Widget speech_config_play_on_new_station,
+ speech_config_play_on_new_message_alert,
+ speech_config_play_on_new_message_body,
+ speech_config_play_on_prox,
+ speech_config_play_on_trak,
+ speech_config_play_on_bando,
+ speech_config_play_on_new_wx_alert;
+
+static void Configure_speech(Widget w, XtPointer clientData, XtPointer callData);
+
+//#ifdef HAVE_FESTIVAL
+/* WARNING - new station is initialized to FALSE for a reason */
+/* If you're tempted to make it something that can be saved and restored */
+/* beware, Speech cannot keep up with the initial flow of data from an */
+/* Internet connection that has buffered data. An unbuffered connection */
+/* yes, but not a buffered one. Ken, N7IPB */
+int festival_speak_new_station = FALSE;
+int festival_speak_proximity_alert;
+int festival_speak_tracked_proximity_alert;
+int festival_speak_band_opening;
+int festival_speak_new_message_alert;
+int festival_speak_new_message_body;
+int festival_speak_new_weather_alert;
+int festival_speak_ID;
+//#endif // HAVE_FESTIVAL
+int ATV_screen_ID;
+
+#ifdef HAVE_MAGICK //N0VH
+Widget configure_tiger_dialog = (Widget) NULL;
+Widget tiger_cities,
+ tiger_grid,
+ tiger_counties,
+ tiger_majroads,
+ tiger_places,
+ tiger_railroad,
+ tiger_streets,
+ tiger_interstate,
+ tiger_statehwy,
+ tiger_states,
+ tiger_ushwy,
+ tiger_water,
+ tiger_lakes,
+ tiger_misc;
+
+int tiger_show_grid = TRUE;
+int tiger_show_counties = TRUE;
+int tiger_show_cities = TRUE;
+int tiger_show_places = TRUE;
+int tiger_show_majroads = TRUE;
+int tiger_show_streets = FALSE;
+int tiger_show_railroad = TRUE;
+int tiger_show_states = FALSE;
+int tiger_show_interstate = TRUE;
+int tiger_show_ushwy = TRUE;
+int tiger_show_statehwy = TRUE;
+int tiger_show_water = TRUE;
+int tiger_show_lakes = TRUE;
+int tiger_show_misc = TRUE;
+#endif // HAVE_MAGICK
+
+
+#ifdef HAVE_LIBGEOTIFF
+Widget configure_DRG_dialog = (Widget) NULL;
+Widget DRG_XOR,
+ DRG_color0,
+ DRG_color1,
+ DRG_color2,
+ DRG_color3,
+ DRG_color4,
+ DRG_color5,
+ DRG_color6,
+ DRG_color7,
+ DRG_color8,
+ DRG_color9,
+ DRG_color10,
+ DRG_color11,
+ DRG_color12;
+
+int DRG_XOR_colors = 0;
+int DRG_show_colors[13];
+#endif // HAVE_LIBGEOTIFF
+
+
+// -------------------------------------------------------------------
+
+
+Widget read_selection_dialog = (Widget)NULL;
+
+// config station values
+Widget station_config_call_data, station_config_slat_data_deg, station_config_slat_data_min,
+ station_config_slat_data_ns, station_config_slong_data_deg, station_config_slong_data_min,
+ station_config_slong_data_ew, station_config_group_data, station_config_symbol_data,
+ station_config_icon, station_config_comment_data;
+Pixmap CS_icon0, CS_icon;
+
+/* defaults*/
+#ifdef TRANSMIT_RAW_WX
+Widget raw_wx_tx;
+#endif // TRANSMIT_RAW_WX
+Widget compressed_posit_tx;
+Widget compressed_objects_items_tx;
+Widget new_bulletin_popup_enable;
+Widget zero_bulletin_popup_enable;
+Widget warn_about_mouse_modifiers_enable;
+Widget my_trail_diff_color_enable;
+Widget load_predefined_objects_menu_from_file_enable;
+#ifdef USE_COMBO_BOX
+Widget load_predefined_objects_menu_from_file; // combo box widget
+#else
+int lpomff_value; // replacement value for predefined menu file combo box
+#endif // USE_COMBO_BOX
+int pop_up_new_bulletins = 0;
+int view_zero_distance_bulletins = 0;
+int warn_about_mouse_modifiers = 1;
+Widget altnet_active;
+Widget altnet_text;
+Widget disable_dupe_check;
+Widget new_map_layer_text = (Widget)NULL;
+Widget new_max_zoom_text = (Widget)NULL;
+Widget new_min_zoom_text = (Widget)NULL;
+Widget debug_level_text;
+static int sec_last_dr_update = 0;
+
+
+FILE *f_xfontsel_pipe[FONT_MAX];
+int xfontsel_query = 0;
+
+
+// -------------------------------------------------------------------
+static void UpdateTime( XtPointer clientData, XtIntervalId id );
+void pos_dialog(Widget w);
+
+static void Zoom_in(Widget w, XtPointer clientData, XtPointer calldata);
+static void Zoom_in_no_pan(Widget w, XtPointer clientData, XtPointer calldata);
+static void Zoom_out(Widget w, XtPointer clientData, XtPointer calldata);
+static void Zoom_out_no_pan(Widget w, XtPointer clientData, XtPointer calldata);
+static void Zoom_level(Widget w, XtPointer clientData, XtPointer calldata);
+static void display_zoom_image(int recenter);
+static void Track_Me( Widget w, XtPointer clientData, XtPointer calldata);
+static void Measure_Distance( Widget w, XtPointer clientData, XtPointer calldata);
+
+static void SetMyPosition( Widget w, XtPointer clientData, XtPointer calldata);
+
+static void Pan_ctr(Widget w, XtPointer clientData, XtPointer calldata);
+static void Pan_up(Widget w, XtPointer clientData, XtPointer calldata);
+static void Pan_up_less(Widget w, XtPointer clientData, XtPointer calldata);
+static void Pan_down(Widget w, XtPointer clientData, XtPointer calldata);
+static void Pan_down_less(Widget w, XtPointer clientData, XtPointer calldata);
+static void Pan_left(Widget w, XtPointer clientData, XtPointer calldata);
+static void Pan_left_less(Widget w, XtPointer clientData, XtPointer calldata);
+static void Pan_right(Widget w, XtPointer clientData, XtPointer calldata);
+static void Pan_right_less(Widget w, XtPointer clientData, XtPointer calldata);
+void Center_Zoom(Widget w, XtPointer clientData, XtPointer calldata);
+void Go_Home(Widget w, XtPointer clientData, XtPointer calldata);
+int center_zoom_override = 0;
+Widget center_zoom_dialog = (Widget)NULL;
+Widget custom_zoom_dialog = (Widget)NULL;
+
+static void Menu_Quit(Widget w, XtPointer clientData, XtPointer calldata);
+
+static void TNC_Logging_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+static void TNC_Transmit_now(Widget w, XtPointer clientData, XtPointer calldata);
+
+#ifdef HAVE_GPSMAN
+static void GPS_operations(Widget w, XtPointer clientData, XtPointer calldata);
+#endif // HAVE_GPSMAN
+
+static void Net_Logging_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+static void IGate_Logging_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+static void Message_Logging_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+static void WX_Logging_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+static void WX_Alert_Logging_toggle(Widget w, XtPointer clientData, XtPointer calldata);
+
+void on_off_switch(int switchpos, Widget first, Widget second);
+void sel3_switch(int switchpos, Widget first, Widget second, Widget third);
+void sel4_switch(int switchpos, Widget first, Widget second, Widget third, Widget fourth);
+
+static void Configure_station(Widget w, XtPointer clientData, XtPointer callData);
+
+static void Configure_defaults(Widget w, XtPointer clientData, XtPointer callData);
+
+static void Configure_timing(Widget w, XtPointer clientData, XtPointer callData);
+
+static void Configure_coordinates(Widget w, XtPointer clientData, XtPointer callData);
+
+static void Stations_Clear(Widget w, XtPointer clientData, XtPointer callData);
+
+static void Test(Widget w, XtPointer clientData, XtPointer callData);
+
+static void Save_Config(Widget w, XtPointer clientData, XtPointer callData);
+
+static void Read_File_Selection(Widget w, XtPointer clientData, XtPointer callData);
+
+static void Display_data(Widget w, XtPointer clientData, XtPointer callData);
+
+static void Auto_msg_toggle( Widget widget, XtPointer clientData, XtPointer callData);
+static void Satellite_msg_ack_toggle( Widget widget, XtPointer clientData, XtPointer callData);
+
+Widget auto_msg_toggle;
+Widget satellite_msg_ack_toggle;
+Widget posamb0,posamb1,posamb2,posamb3,posamb4;
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/* GLOBAL DEFINES */
+GC gc=0; // Used for drawing maps
+GC gc2=0; // Used for drawing symbols
+GC gc_tint=0; // Used for tinting maps & symbols
+GC gc_stipple=0; // Used for drawing symbols
+GC gc_bigfont=0;
+Pixmap pixmap;
+Pixmap pixmap_alerts;
+Pixmap pixmap_final;
+
+// Global variable, so we can set it up once check it from then on,
+// preventing memory leaks from repeatedly setting up the same
+// XFontStruct.
+XFontStruct *station_font = NULL; // Station font
+XFontStruct *font1; // Menu/System font
+XmFontList fontlist1; // Menu/System fontlist
+
+Pixmap pixmap_50pct_stipple; // 50% pixels used for position ambiguity, DF circle, etc.
+Pixmap pixmap_25pct_stipple; // 25% pixels used for large position ambiguity
+Pixmap pixmap_13pct_stipple; // 12.5% pixels used for larger position ambiguity
+Pixmap pixmap_wx_stipple; // Used for weather alerts
+
+int interrupt_drawing_now = 0; // Flag used to interrupt map drawing
+int request_resize = 0; // Flag used to request a resize operation
+int request_new_image = 0; // Flag used to request a create_image operation
+//time_t last_input_event = (time_t)0; // Time of last mouse/keyboard event
+void new_image(Widget da);
+
+
+typedef struct XastirGlobal {
+ Widget top; // top level shell
+} XastirGlobal;
+XastirGlobal Global;
+
+
+char *database_ptr; /* database pointers */
+
+
+//---------------------------------------------------------------------------------------------
+//
+// These describe the current map window. They must be kept
+// up-to-date when we zoom/pan/resize the window.
+//
+float f_center_longitude; // Floating point map center longitude, updated by new_image()
+float f_center_latitude; // Floating point map center latitude , updated by new_image()
+float f_NW_corner_longitude; // longitude of NW corner, updated by create_image(), refresh_image()
+float f_NW_corner_latitude; // latitude of NW corner, updated by create_image(), refresh_image()
+float f_SE_corner_longitude; // longitude of SE corner, updated by create_image(), refresh_image()
+float f_SE_corner_latitude; // latitude of SE corner, updated by create_image(), refresh_image()
+
+long center_longitude; // Longitude at center of map, updated by display_zoom_image()
+long center_latitude; // Latitude at center of map, updated by display_zoom_image()
+long NW_corner_longitude; // Longitude at NW corner, updated by create_image(), refresh_image()
+long NW_corner_latitude; // Latitude at NW corner, updated by create_image(), refresh_image()
+long SE_corner_longitude; // Longitude at SE corner, updated by create_image(), refresh_image()
+long SE_corner_latitude; // Latitude at SE corner, updated by create_image(), refresh_image()
+
+long scale_x; // x scaling in 1/100 sec per pixel, calculated from scale_y
+long scale_y; // y scaling in 1/100 sec per pixel
+
+long new_mid_x, new_mid_y; // Check values used before applying real change
+long new_scale_x;
+long new_scale_y;
+long screen_width; // Screen width, map area without border (in pixels)
+long screen_height; // Screen height, map area without border (in pixels)
+Position screen_x_offset;
+Position screen_y_offset;
+float d_screen_distance; // Diag screen distance
+float x_screen_distance; // x screen distance
+//---------------------------------------------------------------------------------------------
+
+char user_dir[1000]; /* user directory file */
+int delay_time; /* used to delay display data */
+time_t last_weather_cycle; // Time of last call to cycle_weather()
+Pixel colors[256]; /* screen colors */
+Pixel trail_colors[MAX_TRAIL_COLORS]; /* station trail colors, duh */
+int current_trail_color; /* what color to draw station trails with */
+Pixel_Format visual_type = NOT_TRUE_NOR_DIRECT;
+int install_colormap; /* if visual_type == NOT_TRUE..., should we install priv cmap */
+Colormap cmap; /* current colormap */
+
+int redo_list; // Station List update request
+int redraw_on_new_data; // Station redraw request
+int wait_to_redraw; /* wait to redraw until system is up */
+int display_up = 0; /* display up? */
+int display_up_first = 0; /* display up first */
+
+time_t max_transmit_time; /* max time between transmits */
+time_t last_alert_redraw; /* last time alert caused a redraw */
+time_t sec_next_gps; /* next gps check */
+time_t gps_time; /* gps delay time */
+char gprmc_save_string[MAX_LINE_SIZE+1];
+char gpgga_save_string[MAX_LINE_SIZE+1];
+int gps_port_save;
+time_t POSIT_rate; // Posit TX rate timer
+time_t OBJECT_rate; // Object/Item TX rate timer
+time_t update_DR_rate; // How often to call draw_symbols if DR enabled
+time_t remove_ID_message_time; // Time to get rid of large msg on screen.
+int pending_ID_message = 0; // Variable turning on/off this function
+
+
+// SmartBeaconing(tm) stuff. If enabled, POSIT_rate won't be used
+// for timing posits. sb_POSIT_rate computed via SmartBeaconing(tm)
+// will be used instead.
+int smart_beaconing; // Master enable/disable for SmartBeaconing(tm) mode
+int sb_POSIT_rate = 30 * 60; // Computed SmartBeaconing(tm) posit rate (secs)
+int sb_last_heading = -1; // Heading at time of last posit
+int sb_current_heading = -1; // Most recent heading parsed from GPS sentence
+int sb_turn_min = 20; // Min threshold for corner pegging (degrees)
+int sb_turn_slope = 25; // Threshold slope for corner pegging (degrees/mph)
+int sb_turn_time = 5; // Time between other beacon & turn beacon (secs)
+int sb_posit_fast = 90; // Fast beacon rate (secs)
+int sb_posit_slow = 30; // Slow beacon rate (mins)
+int sb_low_speed_limit = 2; // Speed below which SmartBeaconing(tm) is disabled &
+ // we'll beacon at the POSIT_slow rate (mph)
+int sb_high_speed_limit = 60; // Speed above which we'll beacon at the
+ // POSIT_fast rate (mph)
+Widget smart_beacon_dialog = (Widget)NULL;
+Widget smart_beacon_enable = (Widget)NULL;
+Widget sb_hi_rate_data = (Widget)NULL;
+Widget sb_hi_mph_data = (Widget)NULL;
+Widget sb_lo_rate_data = (Widget)NULL;
+Widget sb_lo_mph_data = (Widget)NULL;
+Widget sb_min_turn_data = (Widget)NULL;
+Widget sb_turn_slope_data = (Widget)NULL;
+Widget sb_wait_time_data = (Widget)NULL;
+
+
+Widget ghosting_time = (Widget)NULL;
+Widget clearing_time = (Widget)NULL;
+Widget removal_time = (Widget)NULL;
+Widget posit_interval = (Widget)NULL;
+Widget gps_interval = (Widget)NULL;
+Widget dead_reckoning_time = (Widget)NULL;
+Widget object_item_interval = (Widget)NULL;
+Widget serial_pacing_time = (Widget)NULL;
+Widget trail_segment_timeout = (Widget)NULL;
+Widget trail_segment_distance_max = (Widget)NULL;
+Widget RINO_download_timeout = (Widget)NULL;
+Widget net_map_slider = (Widget)NULL;
+Widget snapshot_interval_slider = (Widget)NULL;
+int net_map_timeout = 120;
+
+
+
+time_t GPS_time; /* gps time out */
+time_t last_statusline; // last update of statusline or 0 if inactive
+time_t last_id_time; // Time of last ID message to statusline
+time_t sec_old; /* station old after */
+time_t sec_clear; /* station cleared after */
+time_t sec_remove; /* Station removed after */
+int trail_segment_time; // Segment missing if above this time (mins)
+int trail_segment_distance; // Segment missing if greater distance
+int RINO_download_interval; // Interval at which to download RINO waypoints,
+ // creating APRS Objects from them.
+time_t last_RINO_download = (time_t)0;
+time_t sec_next_raw_wx; /* raw wx transmit data */
+int dead_reckoning_timeout = 60 * 10; // 10 minutes;
+
+#ifdef TRANSMIT_RAW_WX
+int transmit_raw_wx; /* transmit raw wx data? */
+#endif // TRANSMIT_RAW_WX
+
+int transmit_compressed_posit; // transmit location in compressed format?
+int transmit_compressed_objects_items; // Same for objects & items
+
+int output_station_type; /* Broadcast station type */
+
+int Configure_station_pos_amb; /* Broadcast station position ambiguity */
+
+long max_vectors_allowed; /* max map vectors allowed */
+long max_text_labels_allowed; /* max map text labels allowed */
+long max_symbol_labels_allowed; /* max map symbol labels allowed */
+
+time_t net_last_time; /* reconnect last time in seconds */
+time_t net_next_time; /* reconnect Next update delay time */
+
+#ifdef USING_LIBGC
+time_t gc_next_time = 0L; // Garbage collection next time
+#endif // USING_LIBGC
+
+time_t posit_last_time;
+time_t posit_next_time; /* time at which next posit TX will occur */
+
+time_t last_time; /* last time in seconds */
+time_t next_time; /* Next update delay time */
+
+time_t next_redraw; /* Next update time */
+time_t last_redraw; /* Time of last redraw */
+
+char aprs_station_message_type = '='; // station message-capable or not
+
+int transmit_now; /* set to transmit now (push on moment) */
+int my_position_valid = 1; /* Don't send posits if this is zero */
+int using_gps_position = 0; /* Set to one if a GPS port is active */
+int operate_as_an_igate; /* toggle igate operations for net connections */
+unsigned igate_msgs_tx; /* current total of igate messages transmitted */
+
+int log_tnc_data; /* log data */
+int log_net_data; /* log data */
+int log_igate; /* toggle to allow igate logging */
+int log_wx; /* toggle to allow wx logging */
+int log_message_data; /* toggle to allow message logging */
+int log_wx_alert_data; /* toggle to allow wx alert logging */
+
+
+int snapshots_enabled = 0; // toggle to allow creating .png snapshots on a regular basis
+int kmlsnapshots_enabled = 0; // toggle to allow creating .kml snapshots on a regular basis
+
+time_t WX_ALERTS_REFRESH_TIME; /* Minimum WX alert map refresh time in seconds */
+
+/* button zoom */
+int menu_x;
+int menu_y;
+int possible_zoom_function = 0;
+int zoom_box_x1 = -1; // Stores one corner of zoom box
+int zoom_box_y1 = -1;
+int zoom_box_x2 = -1; // Stores one corner of zoom box
+int zoom_box_y2 = -1;
+int mouse_zoom = 0;
+
+// log file replay
+int read_file;
+FILE *read_file_ptr;
+time_t next_file_read;
+
+// Data for own station
+char my_callsign[MAX_CALLSIGN+1];
+char my_lat[MAX_LAT];
+char my_long[MAX_LONG];
+char my_group;
+char my_symbol;
+char my_phg[MAX_PHG+1];
+char my_comment[MAX_COMMENT+1];
+int my_last_course;
+int my_last_speed;
+long my_last_altitude;
+time_t my_last_altitude_time;
+
+/* Symbols */
+SymbolData symbol_data[MAX_SYMBOLS];
+
+/* sound run */
+pid_t last_sound_pid;
+
+/* Default directories */
+
+char AUTO_MAP_DIR[400];
+char ALERT_MAP_DIR[400];
+char SELECTED_MAP_DIR[400];
+char SELECTED_MAP_DATA[400];
+char MAP_INDEX_DATA[400];
+char SYMBOLS_DIR[400];
+char HELP_FILE[400];
+char SOUND_DIR[400];
+
+char LOGFILE_TNC[400];
+char LOGFILE_NET[400];
+char LOGFILE_IGATE[400];
+char LOGFILE_MESSAGE[400];
+char LOGFILE_WX[400];
+char LOGFILE_WX_ALERT[400];
+
+/* sound data */
+char sound_command[90];
+int sound_play_new_station;
+char sound_new_station[90];
+int sound_play_new_message;
+char sound_new_message[90];
+
+int sound_play_prox_message;
+char sound_prox_message[90];
+char prox_min[30];
+char prox_max[30];
+int sound_play_band_open_message;
+char sound_band_open_message[90];
+char bando_min[30];
+char bando_max[30];
+int sound_play_wx_alert_message;
+char sound_wx_alert_message[90];
+
+
+int input_x = 0;
+int input_y = 0;
+
+XtAppContext app_context;
+Display *display; /* Display */
+
+/* dialog popup last */
+int last_popup_x;
+int last_popup_y;
+
+int disable_all_popups = 0;
+char temp_tracking_station_call[30] = "";
+
+time_t program_start_time;
+int measuring_distance = 0;
+int moving_object = 0;
+
+
+
+
+/////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+void Smart_Beacon_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ smart_beacon_dialog = (Widget)NULL;
+}
+
+
+
+
+
+// Still need to do some bounds checking on the values here.
+//
+// If the user enters 0's or non-numeric data, this function sets the
+// values to reasonable defaults.
+//
+// Another thing that'd be good to do is to recalculate the next
+// beacon time if one of the posit rates is shortened. Otherwise we
+// might be waiting a while to get into the "right rhythm".
+//
+void Smart_Beacon_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+
+ // Snag the XmTextString data and write it into the variables
+ if (smart_beacon_dialog != NULL) {
+ char *str_ptr1;
+ int i;
+
+ smart_beaconing = (int)XmToggleButtonGetState(smart_beacon_enable);
+
+ str_ptr1 = XmTextGetString(sb_hi_rate_data);
+ i = atoi(str_ptr1);
+ if (i == 0)
+ i = 90;
+ sb_posit_fast = i;
+ // Free the space.
+ XtFree(str_ptr1);
+
+ str_ptr1 = XmTextGetString(sb_hi_mph_data);
+ i = atoi(str_ptr1);
+ switch (english_units) {
+ case 0: // Metric: Convert from KPH to MPH for storage
+ i = (int)((i * 0.62137) + 0.5);
+ break;
+ case 1: // English
+ case 2: // Nautical
+ default: // No conversion necessary
+ break;
+ }
+ if (i == 0)
+ i = 60;
+ sb_high_speed_limit = i;
+ // Free the space.
+ XtFree(str_ptr1);
+
+ str_ptr1 = XmTextGetString(sb_lo_rate_data);
+ i = atoi(str_ptr1);
+ if (i == 0)
+ i = 30;
+ sb_posit_slow = i;
+ // Free the space.
+ XtFree(str_ptr1);
+
+ str_ptr1 = XmTextGetString(sb_lo_mph_data);
+ i = atoi(str_ptr1);
+ switch (english_units) {
+ case 0: // Metric: Convert from KPH to MPH for storage
+ i = (int)((i * 0.62137) + 0.5);
+ break;
+ case 1: // English
+ case 2: // Nautical
+ default: // No conversion necessary
+ break;
+ }
+ if (i == 0)
+ i = 2;
+ sb_low_speed_limit = i;
+ // Free the space.
+ XtFree(str_ptr1);
+
+ str_ptr1 = XmTextGetString(sb_min_turn_data);
+ i = atoi(str_ptr1);
+ if (i == 0)
+ i = 20;
+ sb_turn_min = i;
+ // Free the space.
+ XtFree(str_ptr1);
+
+ str_ptr1 = XmTextGetString(sb_turn_slope_data);
+ i = atoi(str_ptr1);
+ if (i == 0)
+ i = 25;
+ sb_turn_slope = i;
+ // Free the space.
+ XtFree(str_ptr1);
+
+ str_ptr1 = XmTextGetString(sb_wait_time_data);
+ i = atoi(str_ptr1);
+ if (i == 0)
+ i = 5;
+ sb_turn_time = i;
+ // Free the space.
+ XtFree(str_ptr1);
+
+ Smart_Beacon_destroy_shell(widget,clientData,callData);
+ }
+}
+
+
+
+
+
+void Smart_Beacon(Widget w, XtPointer clientData, XtPointer callData) {
+ static Widget pane, form, label1, label2, label3,
+ label4, label5, label6, label7,
+ button_ok, button_cancel;
+
+ Atom delw;
+ char temp_string[10];
+ char temp_label_string[100];
+
+
+ // Destroy the dialog if it exists. This is to make sure the
+ // title is correct based on the last dialog that called us.
+ if (smart_beacon_dialog) {
+ Smart_Beacon_destroy_shell( w, smart_beacon_dialog, callData);
+ }
+
+ if (!smart_beacon_dialog) {
+
+ smart_beacon_dialog = XtVaCreatePopupShell(langcode("SMARTB001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Smart_Beacon pane",
+ xmPanedWindowWidgetClass,
+ smart_beacon_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ form = XtVaCreateWidget("Smart_Beacon form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 2,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ smart_beacon_enable = XtVaCreateManagedWidget(langcode("SMARTB011"),
+ xmToggleButtonWidgetClass,form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset,5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ label1 = XtVaCreateManagedWidget(langcode("SMARTB002"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, smart_beacon_enable,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sb_hi_rate_data = XtVaCreateManagedWidget("Smart_Beacon hi_rate_data",
+ xmTextWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNwidth, ((6*7)+2),
+ XmNmaxLength, 5,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, smart_beacon_enable,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ switch (english_units) {
+ case 0: // Metric
+ xastir_snprintf(temp_label_string,
+ sizeof(temp_label_string),
+ "%s",
+ langcode("SMARTB004") );
+ break;
+ case 1: // English
+ case 2: // Nautical
+ default:
+ xastir_snprintf(temp_label_string,
+ sizeof(temp_label_string),
+ "%s",
+ langcode("SMARTB003") );
+ break;
+ }
+
+ // High Speed (mph) / (kph)
+ label2 = XtVaCreateManagedWidget(temp_label_string,
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, label1,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sb_hi_mph_data = XtVaCreateManagedWidget("Smart_Beacon hi_mph_data",
+ xmTextWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNwidth, ((6*7)+2),
+ XmNmaxLength, 3,
+ XmNbackground, colors[0x0f],
+ XmNtopOffset, 5,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, label1,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ label3 = XtVaCreateManagedWidget(langcode("SMARTB005"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, label2,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sb_lo_rate_data = XtVaCreateManagedWidget("Smart_Beacon lo_rate_data",
+ xmTextWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNwidth, ((6*7)+2),
+ XmNmaxLength, 3,
+ XmNbackground, colors[0x0f],
+ XmNtopOffset, 5,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, label2,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ switch (english_units) {
+ case 0: // Metric
+ xastir_snprintf(temp_label_string,
+ sizeof(temp_label_string),
+ "%s",
+ langcode("SMARTB007") );
+ break;
+ case 1: // English
+ case 2: // Nautical
+ default:
+ xastir_snprintf(temp_label_string,
+ sizeof(temp_label_string),
+ "%s",
+ langcode("SMARTB006") );
+ break;
+ }
+
+ // Low Speed (mph) / (kph)
+ label4 = XtVaCreateManagedWidget(temp_label_string,
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, label3,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sb_lo_mph_data = XtVaCreateManagedWidget("Smart_Beacon lo_mph_data",
+ xmTextWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNwidth, ((6*7)+2),
+ XmNmaxLength, 3,
+ XmNbackground, colors[0x0f],
+ XmNtopOffset, 5,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, label3,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ label5 = XtVaCreateManagedWidget(langcode("SMARTB008"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, label4,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sb_min_turn_data = XtVaCreateManagedWidget("Smart_Beacon min_turn_data",
+ xmTextWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNwidth, ((6*7)+2),
+ XmNmaxLength, 3,
+ XmNbackground, colors[0x0f],
+ XmNtopOffset, 5,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, label4,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ label6 = XtVaCreateManagedWidget(langcode("SMARTB009"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, label5,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sb_turn_slope_data = XtVaCreateManagedWidget("Smart_Beacon turn_slope_data",
+ xmTextWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNwidth, ((6*7)+2),
+ XmNmaxLength, 5,
+ XmNbackground, colors[0x0f],
+ XmNtopOffset, 5,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, label5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ label7 = XtVaCreateManagedWidget(langcode("SMARTB010"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, label6,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sb_wait_time_data = XtVaCreateManagedWidget("Smart_Beacon wait_time_data",
+ xmTextWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNwidth, ((6*7)+2),
+ XmNmaxLength, 3,
+ XmNbackground, colors[0x0f],
+ XmNtopOffset, 5,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, label6,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sb_wait_time_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_ok, XmNactivateCallback, Smart_Beacon_change_data, smart_beacon_dialog);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sb_wait_time_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_cancel, XmNactivateCallback, Smart_Beacon_destroy_shell, smart_beacon_dialog);
+
+ pos_dialog(smart_beacon_dialog);
+
+ delw = XmInternAtom(XtDisplay(smart_beacon_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(smart_beacon_dialog, delw, Smart_Beacon_destroy_shell, (XtPointer)smart_beacon_dialog);
+
+ XtManageChild(form);
+ XtManageChild(pane);
+ XtPopup(smart_beacon_dialog,XtGrabNone);
+ fix_dialog_size(smart_beacon_dialog);
+
+ // Move focus to the Close button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(smart_beacon_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else {
+ (void)XRaiseWindow(XtDisplay(smart_beacon_dialog), XtWindow(smart_beacon_dialog));
+ }
+
+ // Fill in the current values
+ if (smart_beacon_dialog != NULL) {
+
+ if(smart_beaconing)
+ XmToggleButtonSetState(smart_beacon_enable,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(smart_beacon_enable,FALSE,FALSE);
+
+ xastir_snprintf(temp_string, sizeof(temp_string), "%d", sb_posit_fast);
+ XmTextSetString(sb_hi_rate_data, temp_string);
+
+ switch (english_units) {
+ case 0: // Metric: Convert from MPH to KPH for display
+ xastir_snprintf(temp_string,
+ sizeof(temp_string),
+ "%d",
+ (int)((sb_high_speed_limit * 1.6094) + 0.5) );
+ break;
+ case 1: // English
+ case 2: // Nautical
+ default: // No conversion necessary
+ xastir_snprintf(temp_string,
+ sizeof(temp_string),
+ "%d",
+ sb_high_speed_limit);
+ break;
+ }
+ XmTextSetString(sb_hi_mph_data, temp_string);
+
+ xastir_snprintf(temp_string, sizeof(temp_string), "%d", sb_posit_slow);
+ XmTextSetString(sb_lo_rate_data, temp_string);
+
+ switch (english_units) {
+ case 0: // Metric: Convert from MPH to KPH for display
+ xastir_snprintf(temp_string,
+ sizeof(temp_string),
+ "%d",
+ (int)((sb_low_speed_limit * 1.6094) + 0.5) );
+ break;
+ case 1: // English
+ case 2: // Nautical
+ default: // No conversion necessary
+ xastir_snprintf(temp_string,
+ sizeof(temp_string),
+ "%d",
+ sb_low_speed_limit);
+ break;
+ }
+ XmTextSetString(sb_lo_mph_data, temp_string);
+
+ xastir_snprintf(temp_string, sizeof(temp_string), "%d", sb_turn_min);
+ XmTextSetString(sb_min_turn_data, temp_string);
+
+ xastir_snprintf(temp_string, sizeof(temp_string), "%d", sb_turn_slope);
+ XmTextSetString(sb_turn_slope_data, temp_string);
+
+ xastir_snprintf(temp_string, sizeof(temp_string), "%d", sb_turn_time);
+ XmTextSetString(sb_wait_time_data, temp_string);
+ }
+}
+
+
+
+
+
+/////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+// Causes the current set of internet-based maps to be snagged from
+// the 'net instead of from cache. Once downloaded they get written
+// to the cache, overwriting possibly corrupted maps already in the
+// cache (why else would you invoke this function?). This is a
+// method of getting rid of corrupted maps without having to wipe
+// out the entire cache.
+//
+void Re_Download_Maps_Now(Widget w, XtPointer clientData, XtPointer callData) {
+
+#ifdef USE_MAP_CACHE
+ // Disable reads from the map cache
+ map_cache_fetch_disable = 1;
+#endif
+
+ // Show a busy cursor while the map is being downloaded
+ busy_cursor(appshell);
+
+ // Cause maps to be refreshed
+ new_image(da);
+
+#ifdef USE_MAP_CACHE
+ //Enable reads from the map cache
+ map_cache_fetch_disable = 0;
+#endif
+}
+
+
+
+
+
+// Removes all files in the ~/.xastir/map_cache directory. Does not
+// recurse down into subdirectories, but it shouldn't have to.
+//
+void Flush_Entire_Map_Queue(Widget w, XtPointer clientData, XtPointer callData) {
+ struct dirent *dl = NULL;
+ DIR *dm;
+ char fullpath[MAX_FILENAME];
+ char dir[MAX_FILENAME];
+ struct stat nfile;
+
+
+ get_user_base_dir("map_cache", dir, sizeof(dir));
+
+ dm = opendir(dir);
+ if (!dm) { // Couldn't open directory
+ fprintf(stderr,"Flush_Entire_Map_Queue: Couldn't open directory\n");
+ return;
+ }
+
+ // Read the directory contents, delete each file found, skip
+ // directories.
+ //
+ while ((dl = readdir(dm))) {
+
+ //Construct the entire path/filename
+ xastir_snprintf(fullpath,
+ sizeof(fullpath),
+ "%s/%s",
+ dir,
+ dl->d_name);
+
+ if (stat(fullpath, &nfile) == 0) {
+ if ((nfile.st_mode & S_IFMT) == S_IFREG) {
+ // It's a regular file
+
+ // Remove the file
+ if (debug_level & 512)
+ fprintf(stderr,"Deleting file: %s\n", fullpath);
+
+ unlink(fullpath);
+ }
+ }
+ }
+ (void)closedir(dm);
+}
+
+
+
+
+
+// Find the extents of every map we have. This is the callback for
+// the "Re-Index Maps" button.
+//
+// If passed a NULL in the callback, we do a smart reindexing: Only
+// reindex the files that are new or have changed.
+// If passed a "1" in the callback, we do a full reindexing: Delete
+// the in-memory index and start indexing from scratch.
+//
+void Index_Maps_Now(Widget w, XtPointer clientData, XtPointer callData) {
+ int parameter = 0; // Default: Smart timestamp-checking indexing
+
+
+ if (clientData != NULL) {
+
+ parameter = atoi((char *)clientData);
+
+ if (parameter != 1) { // Our only option
+ parameter = 0;
+ }
+ }
+
+ // Update the list and write it to file.
+ map_indexer(parameter);
+}
+
+
+
+
+
+void check_weather_symbol(void) {
+ // Check for weather station, if so, make sure symbol is proper type
+ if ( (output_station_type == 4) || (output_station_type == 5) ) {
+ // Need one of these symbols if a weather station: /_ \_ /W \W
+ if ( ( (my_symbol != '_') && (my_symbol != 'W') )
+ || ( (my_group != '\\') && (my_group != '/') ) ) {
+
+ // Force it to '/_'
+ my_group = '/';
+ my_symbol = '_';
+
+ // Update my station data with the new symbol
+ my_station_add(my_callsign,my_group,my_symbol,my_long,my_lat,my_phg,my_comment,(char)position_amb_chars);
+ redraw_on_new_data=2;
+
+ // Notify the operator that the symbol has been changed
+ // "Weather Station", "Changed to WX symbol '/_', other option is '\\_'"
+ popup_message_always( langcode("POPEM00030"), langcode("POPEM00031") );
+ }
+ }
+}
+
+
+
+
+
+void check_nws_weather_symbol(void) {
+ if ( (my_symbol == 'W')
+ && ( (my_group == '\\') || (my_group == '/') ) ) {
+
+ // Notify the operator that they're trying to be an NWS
+ // weather station.
+ popup_message_always( langcode("POPEM00030"), langcode("POPEM00032") );
+ }
+}
+
+
+
+
+
+void Coordinate_calc_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ coordinate_calc_dialog = (Widget)NULL;
+}
+
+
+
+
+
+// Clears out the dialog's input textFields
+void Coordinate_calc_clear_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ XmTextSetString(coordinate_calc_zone, "");
+ XmTextSetString(coordinate_calc_latitude_easting, "");
+ XmTextSetString(coordinate_calc_longitude_northing, "");
+ XmTextSetString(coordinate_calc_result_text, "");
+ XtSetSensitive(coordinate_calc_button_ok,FALSE);
+}
+
+
+
+
+
+// Computes all five coordinate representations for displaying in
+// the "result" textField. Also fills in the global variables for
+// possible later use when passing results back to the calling
+// dialog. We can't use the util.c:*_l2s routines for the
+// conversions here because the util.c routines use Xastir
+// coordinate system as inputs instead of normal lat/lon. Had to
+// home-grow our solution here.
+//
+// Inputs: full_zone, northing, easting, latitude, longitude. UTM
+// inputs are output directly. Latitude/longitude are converted to
+// the various different lat/lon representations.
+//
+// Outputs: global variables and "result" textField, full_zone.
+// full_zone should be a string of at least size 4.
+//
+void Coordinate_calc_output(char *full_zone, long northing,
+ long easting, double latitude, double longitude) {
+ char temp_string[1024];
+ int south = 0;
+ int west = 0;
+ double lat_min,lon_min,lat_sec,lon_sec;
+ int lat_deg_int,lat_min_int;
+ int lon_deg_int,lon_min_int;
+ char maidenhead_grid[50];
+ long temp;
+ long xastir_lat;
+ long xastir_lon;
+ char MGRS_str[50];
+ double double_easting, double_northing;
+
+
+ // Latitude: Switch to integer arithmetic to avoid
+ // floating-point rounding errors.
+ // We _do_ need to round it first though so that we don't lose
+ // accuracy.
+ xastir_snprintf(temp_string,sizeof(temp_string),"%8.0f",latitude * 100000.0);
+ temp = atol(temp_string);
+ if (temp < 0) {
+ south++;
+ temp = labs(temp);
+ }
+ lat_deg_int = (int)temp / 100000;
+ lat_min = (temp % 100000) * 60.0 / 100000.0;
+
+ // Again switch to integer arithmetic to avoid floating-point
+ // rounding errors.
+ temp = (long)(lat_min * 1000);
+ lat_min_int = (int)(temp / 1000);
+ lat_sec = (temp % 1000) * 60.0 / 1000.0;
+
+
+ // Longitude: Switch to integer arithmetic to avoid
+ // floating-point rounding errors.
+ // We _do_ need to round it first though so that we don't lose
+ // accuracy.
+ xastir_snprintf(temp_string,sizeof(temp_string),"%9.0f",longitude * 100000.0);
+ temp = atol(temp_string);
+ if (temp < 0) {
+ west++;
+ temp = labs(temp);
+ }
+ lon_deg_int = (int)temp / 100000;
+ lon_min = (temp % 100000) * 60.0 / 100000.0;
+
+ // Again switch to integer arithmetic to avoid floating-point
+ // rounding errors.
+ temp = (long)(lon_min * 1000);
+ lon_min_int = (int)(temp / 1000);
+ lon_sec = (temp % 1000) * 60.0 / 1000.0;
+
+
+ double_easting = (double)easting;
+ double_northing = (double)northing;
+ convert_UTM_to_xastir(double_easting,
+ double_northing,
+ full_zone,
+ &xastir_lon,
+ &xastir_lat);
+
+//fprintf(stderr,"%s %f %f\t\t%lu %lu\n",
+//full_zone,
+//double_easting,
+//double_northing,
+//xastir_lat,
+//xastir_lon);
+
+
+ // Compute MGRS coordinates.
+ convert_xastir_to_MGRS_str(MGRS_str,
+ sizeof(MGRS_str),
+ xastir_lon,
+ xastir_lat,
+ 1); // Format with leading spaces plus spaces between
+ // easting and northing, so that it lines up with UTM
+ // strings.
+
+
+ // Compute Maidenhead Grid Locator. Note that the sec_to_loc()
+ // function expects lat/lon in Xastir coordinate system.
+ xastir_snprintf(maidenhead_grid,
+ sizeof(maidenhead_grid),
+ "%s",
+ sec_to_loc( xastir_lon, xastir_lat ) );
+
+
+ if (strlen(full_zone) == 1) {
+ xastir_snprintf(temp_string,
+ sizeof(temp_string),
+ " %s",
+ full_zone);
+ xastir_snprintf(full_zone,
+ 4,
+ "%s",
+ temp_string);
+ }
+ else if (strlen(full_zone) == 2) {
+ xastir_snprintf(temp_string,
+ sizeof(temp_string),
+ " %s",
+ full_zone);
+ xastir_snprintf(full_zone,
+ 4,
+ "%s",
+ temp_string);
+ }
+
+
+ // Put the four different representations of the coordinate into
+ // the "result" textField.
+ xastir_snprintf(temp_string,
+ sizeof(temp_string),
+ "%s%8.5f%c %9.5f%c\n%s%02d %06.3f%c %03d %06.3f%c\n%s%02d %02d %04.1f%c %03d %02d %04.1f%c\n%s%3s %07lu %07lu\n%s%s\n%s%s",
+ langcode("COORD011"), // "Decimal Degrees:",
+ lat_deg_int+lat_min/60.0, (south) ? 'S':'N',
+ lon_deg_int+lon_min/60.0, (west) ? 'W':'E',
+ langcode("COORD012"), // "Degrees/Decimal Minutes:",
+ lat_deg_int, lat_min, (south) ? 'S':'N',
+ lon_deg_int, lon_min, (west) ? 'W':'E',
+ langcode("COORD013"), // "Degrees/Minutes/Dec. Seconds:",
+ lat_deg_int, lat_min_int, lat_sec, (south) ? 'S':'N',
+ lon_deg_int, lon_min_int, lon_sec, (west) ? 'W':'E',
+ langcode("COORD014"), // "Universal Transverse Mercator:",
+ full_zone, easting, northing,
+ langcode("COORD015"), // "Military Grid Reference System:",
+ MGRS_str,
+ langcode("COORD016"), // "Maidenhead Grid Locator:",
+ maidenhead_grid);
+ XmTextSetString(coordinate_calc_result_text, temp_string);
+
+ // Fill in the global dd mm.mmm values in case we wish to write
+ // the result back to the calling dialog.
+ xastir_snprintf(coordinate_calc_lat_deg, sizeof(coordinate_calc_lat_deg),
+ "%02d", lat_deg_int);
+ xastir_snprintf(coordinate_calc_lat_min, sizeof(coordinate_calc_lat_min),
+ "%06.3f", lat_min);
+ xastir_snprintf(coordinate_calc_lat_dir, sizeof(coordinate_calc_lat_dir),
+ "%c", (south) ? 'S':'N');
+ xastir_snprintf(coordinate_calc_lon_deg, sizeof(coordinate_calc_lon_deg),
+ "%03d", lon_deg_int);
+ xastir_snprintf(coordinate_calc_lon_min, sizeof(coordinate_calc_lon_min),
+ "%06.3f", lon_min);
+ xastir_snprintf(coordinate_calc_lon_dir, sizeof(coordinate_calc_lon_dir),
+ "%c", (west) ? 'W':'E');
+}
+
+
+
+
+
+// Coordinate_calc_compute
+//
+// Inputs: coordinate_calc_zone textField
+// coordinate_calc_latitude_easting textField
+// coordinate_calc_longitude_northing textField
+//
+// Output: coordinate_calc_result_text only if the inputs are not
+// recognized, then it outputs help text to the textField. If
+// inputs are good it calls Coordinate_calc_output() to format and
+// save/output the results.
+//
+void Coordinate_calc_compute(Widget widget, XtPointer clientData, XtPointer callData) {
+ char *str_ptr;
+ char zone_letter;
+ int zone_number = 0;
+ char full_zone[5];
+ int i;
+ int have_utm;
+ int have_lat_lon;
+ long easting = 0;
+ long northing = 0;
+ double double_easting;
+ double double_northing;
+ double latitude;
+ double longitude;
+ char temp_string[1024];
+
+
+ // Goal is to suck in the format provided, figure out what
+ // format it is, then convert to the four major formats we
+ // support and put all four into the output window, each on a
+ // different line.
+
+ // These are the formats that I'd like to be able to
+ // auto-recognize and support:
+
+ // ddN dddW IMPLEMENTED
+ // dd N ddd W IMPLEMENTED
+ // -dd -ddd IMPLEMENTED
+
+ // dd.ddddN ddd.ddddW IMPLEMENTED
+ // dd.dddd N ddd.dddd W IMPLEMENTED
+ // -dd.dddd -ddd.dddd IMPLEMENTED
+
+ // dd mmN ddd mmW IMPLEMENTED
+ // dd mm N ddd mm W IMPLEMENTED
+ // -dd mm -ddd mm IMPLEMENTED
+
+ // dd mm.mmmN ddd mm.mmmW IMPLEMENTED
+ // dd mm.mmm N ddd mm.mmm W IMPLEMENTED
+ // -dd mm.mmm -ddd mm.mmm IMPLEMENTED
+
+ // dd mm ssN ddd mm ssW IMPLEMENTED
+ // dd mm ss N ddd mm ss W IMPLEMENTED
+ // -dd mm ss -ddd mm ss IMPLEMENTED
+
+ // dd mm ss.sN ddd mm ss.sW IMPLEMENTED
+ // dd mm ss.s N ddd mm ss.s W IMPLEMENTED
+ // -dd mm ss.s -ddd mm ss.s IMPLEMENTED
+
+ // 10T 0123456 1234567 IMPLEMENTED
+ // 10T 123456 1234567 IMPLEMENTED
+ // 10T 012 3456 123 4567
+ // 10T 12 3456 123 4567
+
+ // Once the four major formats are created and written to the
+ // output test widget, the dd mm.mmmN/ddd mm.mmmW formatted
+ // output should also be saved for later pasting into the
+ // calling dialog's input fields. DONE!
+ //
+ // Must also make sure that the calling dialog is still up and
+ // active before we try to write to it's widgets. DONE!
+
+
+ // Check for something in the zone field that looks like a valid
+ // UTM zone.
+ str_ptr = XmTextGetString(coordinate_calc_zone);
+ i = strlen(str_ptr);
+ have_utm = 1; // Wishful thinking. We'll zero it later if not.
+ if ( (i >= 1) && (i <= 3) ) {
+ // String is the correct length. Can have just A/B/Y/Z, or
+ // else one or two digits plus one letter.
+ int j;
+
+ for (j = 0; j < (i-1); j++) {
+ if ( (str_ptr[j] < '0') && (str_ptr[j] > '9') ) {
+ // Not UTM, need either one or two digits first if
+ // we have 2 or 3 chars.
+ have_utm = 0;
+ }
+ }
+ if ( ( (str_ptr[i-1] < 'A') || (str_ptr[i-1] > 'Z') )
+ && ( (str_ptr[i-1] < 'a') || (str_ptr[i-1] > 'z') ) ) {
+ // Not UTM, zone character isn't correct
+ have_utm = 0;
+ }
+ }
+ else { // Not a valid UTM zone, wrong length.
+ have_utm = 0;
+ }
+
+ // If we've made it to this point and have_utm == 1, then zone looks
+ // like a UTM zone.
+ if (have_utm) {
+ zone_letter = toupper(str_ptr[i-1]);
+ zone_number = atoi(str_ptr);
+ //fprintf(stderr,"Zone Number: %d, Zone Letter: %c\n", zone_number, zone_letter);
+ // Save it away for later use
+ if (zone_number == 0) { // We're in a UPS area
+ xastir_snprintf(full_zone,
+ sizeof(full_zone),
+ " %c",
+ zone_letter);
+ }
+ else { // UTM area
+ xastir_snprintf(full_zone,
+ sizeof(full_zone),
+ "%02d%c",
+ zone_number,
+ zone_letter);
+ }
+ have_lat_lon = 0;
+ }
+ else {
+ //fprintf(stderr,"Bad zone, not a UTM coordinate\n");
+ // Skip zone widget for lat/lon, it's not used.
+ have_lat_lon = 1; // Wishful thinking. We'll zero it later if not.
+ }
+ // We're done with that variable. Free the space.
+ XtFree(str_ptr);
+
+
+ str_ptr = XmTextGetString(coordinate_calc_latitude_easting);
+ i = strlen(str_ptr);
+ // Check for exactly six or seven chars. If seven, first one must
+ // be a zero (Not true! UPS coordinates have digits there!).
+ if ( have_utm && (i != 6) && (i != 7) ) {
+ have_utm = 0;
+ //fprintf(stderr,"Bad Easting value: Not 6 or 7 chars\n");
+ }
+// if ( have_utm && (i == 7) && (str_ptr[0] != '0') ) {
+// have_utm = 0;
+// //fprintf(stderr,"Bad Easting value: 7 chars but first one not 0\n");
+// }
+ if (have_utm) {
+ int j;
+
+ // Might be good to get rid of spaces at this point as we think
+ // it's a UTM number. Might have to put it in our own string
+ // first though to do that.
+
+ for (j = 0; j < i; j++) {
+ if ( (str_ptr[j] < '0') || (str_ptr[j] > '9') ) {
+ // Not UTM, found a non-number
+ have_utm = 0;
+ }
+ }
+
+ if (have_utm) { // If we still think it's a valid UTM number
+ easting = atol(str_ptr);
+ //fprintf(stderr,"Easting: %lu\n",easting);
+ }
+ else {
+ //fprintf(stderr,"Bad Easting value\n");
+ }
+ }
+ else if (have_lat_lon) {
+ // Process the string to see if it's a valid latitude value.
+ // Convert it into a double if so and store it in
+ // "latitude".
+ int j, substring;
+ int south = 0;
+ int temp[10]; // indexes to substrings
+ char *ptr;
+ char temp_string[30];
+ int piece;
+
+ // Copy the string so we can change it.
+ xastir_snprintf(temp_string,sizeof(temp_string),"%s",str_ptr);
+
+ for (j = 0; j < i; j++) {
+ temp_string[j] = toupper(temp_string[j]);
+ }
+
+ // Search for 'N' or 'S'.
+ ptr = rindex(temp_string, 'N');
+ if (ptr != NULL) { // Found an 'N'
+ *ptr = ' '; // Convert it to a space
+ //fprintf(stderr,"Found an 'N', converted to %s\n", temp_string);
+ }
+ ptr = rindex(temp_string, 'S');
+ if (ptr != NULL) { // Found an 'S'
+ *ptr = ' '; // Convert it to a space
+ south++;
+ //fprintf(stderr,"Found an 'S', converted to %s\n", temp_string);
+ }
+ ptr = rindex(temp_string, '-');
+ if (ptr != NULL) { // Found an '-'
+ *ptr = ' '; // Convert it to a space
+ south++;
+ //fprintf(stderr,"Found an '-', converted to %s\n", temp_string);
+ }
+
+ // Tokenize the string
+
+ // Find the space characters
+ temp[0] = 0; // First index is to start of entire string
+ substring = 1;
+ for (j = 1; j < i; j++) {
+ if (temp_string[j] == ' ') { // Found a space
+ temp_string[j] = '\0'; // Terminate the substring
+ if ( (j + 1) < i) { // If not at the end
+ temp[substring++] = j + 1; // Save an index to the new substring
+ //fprintf(stderr,"%s",&temp_string[j+1]);
+ }
+ }
+ }
+
+ // temp[] array now contains indexes into all of the
+ // substrings. Some may contain empty strings.
+
+ //fprintf(stderr,"Substrings: %d\n", substring);
+ //fprintf(stderr,"temp_string: %s\n",temp_string);
+
+
+ //for (j = 0; j < substring; j++) {
+ // if (strlen(&temp_string[temp[j]]) > 0) {
+ // fprintf(stderr,"%s\n", &temp_string[temp[j]]);
+ // }
+ //}
+
+ piece = 0;
+ have_lat_lon = 0;
+
+ for (j = 0; j < substring; j++) {
+ if (strlen(&temp_string[temp[j]]) > 0) {
+ double kk;
+
+ piece++; // Found the next piece
+ kk = atof(&temp_string[temp[j]]);
+
+ switch (piece) {
+ case (1) : // Degrees
+ latitude = kk;
+ have_lat_lon = 1;
+ break;
+ case (2) : // Minutes
+ if ( (kk < 0.0) || (kk >= 60.0) ) {
+ fprintf(stderr,"Warning: Bad latitude minutes value\n");
+ // Set variables so that we'll get error output.
+ have_lat_lon = 0;
+ have_utm = 0;
+ }
+ else {
+ latitude = latitude + ( kk / 60.0 );
+ }
+ break;
+ case (3) : // Seconds
+ if ( (kk < 0.0) || (kk >= 60.0)) {
+ fprintf(stderr,"Warning: Bad latitude seconds value\n");
+ // Set variables so that we'll get error output.
+ have_lat_lon = 0;
+ have_utm = 0;
+ }
+ else {
+ latitude = latitude + ( kk / 3600.0 );
+ }
+ break;
+ default :
+ break;
+ }
+ }
+ }
+
+ if (south) {
+ latitude = -latitude;
+ }
+ //fprintf(stderr,"%f\n", latitude);
+
+ // Test for valid values of latitude
+ if ( have_lat_lon && ((latitude < -90.0) || (latitude > 90.0)) ) {
+ have_lat_lon = 0;
+ }
+ if (strlen(str_ptr) == 0) {
+ have_lat_lon = 0;
+ }
+ }
+ // We're done with that variable. Free the space.
+ XtFree(str_ptr);
+
+
+ str_ptr = XmTextGetString(coordinate_calc_longitude_northing);
+ i = strlen(str_ptr);
+ // Check for exactly seven chars.
+ if (have_utm && (i != 7) ) {
+ have_utm = 0;
+ //fprintf(stderr,"Bad Northing value: Not 7 chars\n");
+ }
+ if (have_utm) {
+ int j;
+
+ // Might be good to get rid of spaces at this point as we think
+ // it's a UTM number. Might have to put it in our own string
+ // first though to do that.
+
+ for (j = 0; j< i; j++) {
+ if ( (str_ptr[j] < '0') || (str_ptr[j] > '9') ) {
+ // Not UTM, found a non-number
+ have_utm = 0;
+ }
+ }
+ if (have_utm) { // If we still think it's a valid UTM number
+ northing = atol(str_ptr);
+ //fprintf(stderr,"Northing: %lu\n",northing);
+ }
+ else {
+ //fprintf(stderr,"Bad Northing value\n");
+ }
+ }
+ else if (have_lat_lon) {
+ // Process the string to see if it's a valid longitude
+ // value. Convert it into a double if so and store it in
+ // "longitude".
+ int j, substring;
+ int west = 0;
+ int temp[10]; // indexes to substrings
+ char *ptr;
+ char temp_string[30];
+ int piece;
+
+ // Copy the string so we can change it.
+ xastir_snprintf(temp_string,sizeof(temp_string),"%s",str_ptr);
+
+ for (j = 0; j < i; j++) {
+ temp_string[j] = toupper(temp_string[j]);
+ }
+
+ // Search for 'W' or 'E'.
+ ptr = rindex(temp_string, 'W');
+ if (ptr != NULL) { // Found an 'W'
+ *ptr = ' '; // Convert it to a space
+ west++;
+ //fprintf(stderr,"Found an 'W', converted to %s\n", temp_string);
+ }
+ ptr = rindex(temp_string, 'E');
+ if (ptr != NULL) { // Found an 'E'
+ *ptr = ' '; // Convert it to a space
+ //fprintf(stderr,"Found an 'E', converted to %s\n", temp_string);
+ }
+ ptr = index(temp_string, '-');
+ if (ptr != NULL) { // Found an '-'
+ *ptr = ' '; // Convert it to a space
+ west++;
+ //fprintf(stderr,"Found an '-', converted to %s\n", temp_string);
+ }
+
+ // Tokenize the string
+
+ // Find the space characters
+ temp[0] = 0; // First index is to start of entire string
+ substring = 1;
+ for (j = 1; j < i; j++) {
+ if (temp_string[j] == ' ') { // Found a space
+ temp_string[j] = '\0'; // Terminate the substring
+ if ( (j + 1) < i) { // If not at the end
+ temp[substring++] = j + 1; // Save an index to the new substring
+ //fprintf(stderr,"%s",&temp_string[j+1]);
+ }
+ }
+ }
+
+ // temp[] array now contains indexes into all of the
+ // substrings. Some may contain empty strings.
+
+ //fprintf(stderr,"Substrings: %d\n", substring);
+ //fprintf(stderr,"temp_string: %s\n",temp_string);
+
+
+ //for (j = 0; j < substring; j++) {
+ // if (strlen(&temp_string[temp[j]]) > 0) {
+ // fprintf(stderr,"%s\n", &temp_string[temp[j]]);
+ // }
+ //}
+ piece = 0;
+ have_lat_lon = 0;
+
+ for (j = 0; j < substring; j++) {
+ if (strlen(&temp_string[temp[j]]) > 0) {
+ double kk;
+
+ piece++; // Found the next piece
+ kk = atof(&temp_string[temp[j]]);
+
+ switch (piece) {
+ case (1) : // Degrees
+ longitude = kk;
+ have_lat_lon = 1;
+ break;
+ case (2) : // Minutes
+ if ( (kk < 0.0) || (kk >= 60.0) ) {
+ fprintf(stderr,"Warning: Bad longitude minutes value\n");
+ // Set variables so that we'll get error output.
+ have_lat_lon = 0;
+ have_utm = 0;
+ }
+ else {
+ longitude = longitude + ( kk / 60.0 );
+ }
+ break;
+ case (3) : // Seconds
+ if ( (kk < 0.0) || (kk >= 60.0) ) {
+ fprintf(stderr,"Warning: Bad longitude seconds value\n");
+ // Set variables so that we'll get error output.
+ have_lat_lon = 0;
+ have_utm = 0;
+ }
+ else {
+ longitude = longitude + ( kk / 3600.0 );
+ }
+ break;
+ default :
+ break;
+ }
+ }
+ }
+
+ if (west) {
+ longitude = -longitude;
+ }
+ //fprintf(stderr,"%f\n", longitude);
+
+
+ // Test for valid values of longitude
+ if (have_lat_lon && ((longitude < -180.0) || (longitude > 180.0)) ) {
+ have_lat_lon = 0;
+ }
+ if (strlen(str_ptr) == 0) {
+ have_lat_lon = 0;
+ }
+ }
+ // We're done with that variable. Free the space.
+ XtFree(str_ptr);
+
+ // If we get to this point and have_utm == 1, then we're fairly sure
+ // we have a good value and can convert it to the other formats for
+ // display.
+ if (have_utm) {
+//fprintf(stderr,"Processing 'good' UTM values\n");
+ // Process UTM values
+ utm_ups_to_ll(E_WGS_84,
+ (double)northing,
+ (double)easting,
+ full_zone,
+ &latitude,
+ &longitude);
+ if (debug_level & 1)
+ fprintf(stderr,"Latitude: %f, Longitude: %f\n",latitude,longitude);
+ Coordinate_calc_output(full_zone,
+ northing,
+ easting,
+ latitude,
+ longitude);
+ XtSetSensitive(coordinate_calc_button_ok,TRUE);
+ }
+ else if (have_lat_lon) {
+ // Process lat/lon values
+ double_northing = (double)northing;
+ double_easting = (double)easting;
+ ll_to_utm_ups(E_WGS_84,
+ (double)latitude,
+ (double)longitude,
+ &double_northing,
+ &double_easting,
+ full_zone,
+ sizeof(full_zone));
+ if (debug_level & 1)
+ fprintf(stderr,"Zone: %s, Easting: %f, Northing: %f\n", full_zone, double_easting, double_northing);
+ // Round the UTM values as we convert them to longs
+ xastir_snprintf(temp_string,sizeof(temp_string),"%7.0f",double_northing);
+ northing = (long)(atof(temp_string));
+ xastir_snprintf(temp_string,sizeof(temp_string),"%7.0f",double_easting);
+ easting = (long)(atof(temp_string));
+ Coordinate_calc_output(full_zone,
+ (long)northing,
+ (long)easting,
+ latitude,
+ longitude);
+ XtSetSensitive(coordinate_calc_button_ok,TRUE);
+ }
+ else { // Dump out some helpful text
+ xastir_snprintf(temp_string,
+ sizeof(temp_string),
+ "%s\n%s\n%s\n%s",
+// " ** Sorry, your input was not recognized! **",
+ langcode("COORD017"),
+// " ** Please use one of the following input formats: **",
+ langcode("COORD018"),
+ " ** 47.99999N 121.99999W, 47 59.999N 121 59.999W **",
+ " ** 10T 0574599 5316887, 47 59 59.9N 121 59 59.9W **");
+ XmTextSetString(coordinate_calc_result_text, temp_string);
+ XtSetSensitive(coordinate_calc_button_ok,FALSE);
+ }
+}
+
+
+
+
+
+// Input: Values from the coordinate_calc_array struct.
+//
+// Output: Writes data back to the calling dialog's input fields if
+// the calling dialog still exists at this point.
+//
+// Make sure that if an error occurs during computation we don't
+// write a bad value back to the calling widget. DONE.
+//
+void Coordinate_calc_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+
+ // Write output directly to the XmTextStrings pointed to by our array
+ if ( (coordinate_calc_array.calling_dialog != NULL)
+ && (coordinate_calc_array.input_lat_deg != NULL) )
+ XmTextSetString(coordinate_calc_array.input_lat_deg, coordinate_calc_lat_deg);
+ //fprintf(stderr,"%s\n",coordinate_calc_lat_deg);
+
+ if ( (coordinate_calc_array.calling_dialog != NULL)
+ && (coordinate_calc_array.input_lat_min != NULL) )
+ XmTextSetString(coordinate_calc_array.input_lat_min, coordinate_calc_lat_min);
+ //fprintf(stderr,"%s\n",coordinate_calc_lat_min);
+
+ if ( (coordinate_calc_array.calling_dialog != NULL)
+ && (coordinate_calc_array.input_lat_dir != NULL) )
+ XmTextSetString(coordinate_calc_array.input_lat_dir, coordinate_calc_lat_dir);
+ //fprintf(stderr,"%s\n",coordinate_calc_lat_dir);
+
+ if ( (coordinate_calc_array.calling_dialog != NULL)
+ && (coordinate_calc_array.input_lon_deg != NULL) )
+ XmTextSetString(coordinate_calc_array.input_lon_deg, coordinate_calc_lon_deg);
+ //fprintf(stderr,"%s\n",coordinate_calc_lon_deg);
+
+ if ( (coordinate_calc_array.calling_dialog != NULL)
+ && (coordinate_calc_array.input_lon_min != NULL) )
+ XmTextSetString(coordinate_calc_array.input_lon_min, coordinate_calc_lon_min);
+ //fprintf(stderr,"%s\n",coordinate_calc_lon_min);
+
+ if ( (coordinate_calc_array.calling_dialog != NULL)
+ && (coordinate_calc_array.input_lon_dir != NULL) )
+ XmTextSetString(coordinate_calc_array.input_lon_dir, coordinate_calc_lon_dir);
+ //fprintf(stderr,"%s\n",coordinate_calc_lon_dir);
+
+ Coordinate_calc_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+// Coordinate Calculator
+//
+// Change the title based on what dialog is calling us?
+//
+// We want all four possible coordinate formats displayed
+// simultaneously. DONE.
+//
+// Hitting enter or "Calculate" will cause all of the fields to be
+// updated. DONE (for Calculate button).
+//
+// The fields should be filled in when this is first called.
+// When done, this routine will pass back values via a static array
+// of Widget pointers to the calling dialog's fields. DONE.
+//
+// We could grey-out the OK button until we have a successful
+// calculation, and when the "Clear" button is pressed. This
+// would make sure that an invalid location doesn't
+// get written to the calling dialog. Would have to have a
+// successful conversion before we could write the value back.
+//
+void Coordinate_calc(Widget w, XtPointer clientData, XtPointer callData) {
+ static Widget pane, form, label1, label2, label3,
+ label4, label5, label6,
+ button_clear, button_calculate, button_cancel;
+ Atom delw;
+ Arg args[50]; // Arg List
+ register unsigned int n = 0; // Arg Count
+ char temp_string[50];
+
+ // Destroy the dialog if it exists. This is to make sure the
+ // title is correct based on the last dialog that called us.
+ if (coordinate_calc_dialog) {
+ Coordinate_calc_destroy_shell( w, coordinate_calc_dialog, callData);
+ }
+
+ if (!coordinate_calc_dialog) {
+
+ // We change the title based on who's calling us.
+ // clientData supplies the string we use for the label, and
+ // is sent to us by the calling dialog.
+ xastir_snprintf( temp_string, sizeof(temp_string), "%s %s", (char *)clientData, langcode("COORD001") );
+
+ coordinate_calc_dialog = XtVaCreatePopupShell(temp_string,
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ NULL);
+
+ pane = XtVaCreateWidget("Coordinate_calc pane",
+ xmPanedWindowWidgetClass,
+ coordinate_calc_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ form = XtVaCreateWidget("Coordinate_calc form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 4,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ label1 = XtVaCreateManagedWidget(langcode("COORD005"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ label2 = XtVaCreateManagedWidget(langcode("COORD006"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 70,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ label3 = XtVaCreateManagedWidget(langcode("COORD007"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 200,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ label4 = XtVaCreateManagedWidget(langcode("COORD008"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, label1,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ label5 = XtVaCreateManagedWidget(langcode("COORD009"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, label1,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 70,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ label6 = XtVaCreateManagedWidget(langcode("COORD010"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, label1,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 200,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ /*set args for color */
+ n=0;
+ XtSetArg(args[n], XmNforeground, MY_FG_COLOR); n++;
+ XtSetArg(args[n], XmNbackground, MY_BG_COLOR); n++;
+
+
+ coordinate_calc_zone = XtVaCreateManagedWidget("Coordinate_calc zone",
+ xmTextWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 4,
+ XmNwidth, ((5*7)+2),
+ XmNmaxLength, 3,
+ XmNbackground, colors[0x0f],
+ XmNtopOffset, 5,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, label4,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ coordinate_calc_latitude_easting = XtVaCreateManagedWidget("Coordinate_calc lat",
+ xmTextWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 13,
+ XmNwidth, ((13*7)+2),
+ XmNmaxLength, 12,
+ XmNbackground, colors[0x0f],
+ XmNtopOffset, 5,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, label4,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 65,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ coordinate_calc_longitude_northing = XtVaCreateManagedWidget("Coordinate_calc lon",
+ xmTextWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 13,
+ XmNwidth, ((14*7)+2),
+ XmNmaxLength, 13,
+ XmNbackground, colors[0x0f],
+ XmNtopOffset, 5,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, label4,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 195,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+// xastir_snprintf(temp_string, sizeof(temp_string), "%d", temp);
+// XmTextSetString(coordinate_calc_text, temp_string);
+
+ coordinate_calc_result_text = NULL;
+ coordinate_calc_result_text = XtVaCreateManagedWidget("Coordinate_calc results",
+ xmTextWidgetClass,
+ form,
+ XmNrows, 6,
+ XmNcolumns, 58,
+ XmNeditable, FALSE,
+ XmNtraversalOn, FALSE,
+ XmNeditMode, XmMULTI_LINE_EDIT,
+ XmNwordWrap, TRUE,
+// XmNscrollHorizontal, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNautoShowCursorPosition, True,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, coordinate_calc_zone,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 5,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_clear = XtVaCreateManagedWidget(langcode("COORD004"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, coordinate_calc_result_text,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_clear, XmNactivateCallback, Coordinate_calc_clear_data, coordinate_calc_dialog);
+
+ button_calculate = XtVaCreateManagedWidget(langcode("COORD003"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, coordinate_calc_result_text,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_calculate, XmNactivateCallback, Coordinate_calc_compute, coordinate_calc_dialog);
+
+ coordinate_calc_button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, coordinate_calc_result_text,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coordinate_calc_button_ok, XmNactivateCallback, Coordinate_calc_change_data, coordinate_calc_dialog);
+ XtSetSensitive(coordinate_calc_button_ok,FALSE);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, coordinate_calc_result_text,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_cancel, XmNactivateCallback, Coordinate_calc_destroy_shell, coordinate_calc_dialog);
+
+ pos_dialog(coordinate_calc_dialog);
+
+ delw = XmInternAtom(XtDisplay(coordinate_calc_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(coordinate_calc_dialog, delw, Coordinate_calc_destroy_shell, (XtPointer)coordinate_calc_dialog);
+
+ XtManageChild(form);
+ XtManageChild(pane);
+ XtPopup(coordinate_calc_dialog,XtGrabNone);
+ fix_dialog_size(coordinate_calc_dialog);
+
+ // Move focus to the Close button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(coordinate_calc_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else {
+ (void)XRaiseWindow(XtDisplay(coordinate_calc_dialog), XtWindow(coordinate_calc_dialog));
+ }
+
+ // Fill in the latitude values if they're available
+ if ( (coordinate_calc_array.calling_dialog != NULL)
+ && (coordinate_calc_array.input_lat_deg != NULL)
+ && (coordinate_calc_array.input_lat_min != NULL)
+ && (coordinate_calc_array.input_lat_dir != NULL) )
+ {
+ char *str_ptr1;
+ char *str_ptr2;
+ char *str_ptr3;
+
+ str_ptr1 = XmTextGetString(coordinate_calc_array.input_lat_deg);
+ str_ptr2 = XmTextGetString(coordinate_calc_array.input_lat_min);
+ str_ptr3 = XmTextGetString(coordinate_calc_array.input_lat_dir);
+
+ xastir_snprintf(temp_string, sizeof(temp_string), "%s %s%s",
+ str_ptr1, str_ptr2, str_ptr3);
+ XmTextSetString(coordinate_calc_latitude_easting, temp_string);
+ //fprintf(stderr,"String: %s\n", temp_string);
+ // We're done with these variables. Free the space.
+ XtFree(str_ptr1);
+ XtFree(str_ptr2);
+ XtFree(str_ptr3);
+ }
+
+ // Fill in the longitude values if they're available
+ if ( (coordinate_calc_array.calling_dialog != NULL)
+ && (coordinate_calc_array.input_lon_deg != NULL)
+ && (coordinate_calc_array.input_lon_min != NULL)
+ && (coordinate_calc_array.input_lon_dir != NULL) )
+ {
+ char *str_ptr1;
+ char *str_ptr2;
+ char *str_ptr3;
+
+ str_ptr1 = XmTextGetString(coordinate_calc_array.input_lon_deg);
+ str_ptr2 = XmTextGetString(coordinate_calc_array.input_lon_min);
+ str_ptr3 = XmTextGetString(coordinate_calc_array.input_lon_dir);
+
+ xastir_snprintf(temp_string, sizeof(temp_string), "%s %s%s",
+ str_ptr1, str_ptr2, str_ptr3);
+ XmTextSetString(coordinate_calc_longitude_northing, temp_string);
+ //fprintf(stderr,"String: %s\n", temp_string);
+ // We're done with these variables. Free the space.
+ XtFree(str_ptr1);
+ XtFree(str_ptr2);
+ XtFree(str_ptr3);
+ }
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+void HandlePendingEvents( XtAppContext app) {
+ XEvent event;
+
+ while(XtAppPending(app)) {
+ XtAppNextEvent(app,&event);
+ (void)XtDispatchEvent(&event);
+ }
+}
+
+
+
+
+
+Boolean unbusy_cursor(XtPointer clientdata) {
+ Widget w = (Widget)clientdata;
+
+ (void)XUndefineCursor(XtDisplay(w),XtWindow(w));
+ return((Boolean)TRUE);
+}
+
+
+
+
+static Cursor cs = (Cursor)NULL;
+
+void busy_cursor(Widget w) {
+
+ if(!cs) {
+ cs=XCreateFontCursor(XtDisplay(w),XC_watch);
+ }
+
+ (void)XDefineCursor(XtDisplay(w),XtWindow(w),cs);
+ (void)XFlush(XtDisplay(w));
+
+ // This X11 function gets invoked when X11 decides that it has
+ // some free time. We use that to advantage in making the busy
+ // cursor go away "magically" when we're not so busy.
+ //
+ (void)XtAppAddWorkProc(XtWidgetToApplicationContext(w),unbusy_cursor,(XtPointer)w);
+}
+
+
+
+
+
+// This function:
+// Draws the map data into "pixmap", copies "pixmap" to
+// "pixmap_alerts", draws alerts into "pixmap_alerts", copies
+// "pixmap_alerts" to "pixmap_final", draws symbols/tracks into
+// "pixmap_final" via a call to display_file().
+//
+// Other functions which call this function are responsible for
+// copying the image from pixmap_final() to the screen's drawing
+// area.
+//
+// We check for interrupt_drawing_now flag being set, and exit
+// nicely if so. That flag means that some other drawing operation
+// needs to happen.
+//
+// Returns 0 if it gets interrupted, 1 if it completes.
+//
+int create_image(Widget w) {
+ Dimension width, height, margin_width, margin_height;
+ long lat_offset_temp;
+ long long_offset_temp;
+ char temp_course[20];
+ unsigned char unit_type;
+ char medium_dashed[2] = {(char)5,(char)5};
+ long pos1_lat, pos1_lon, pos2_lat, pos2_lon;
+
+
+ //busy_cursor(w);
+ busy_cursor(appshell);
+
+ if (debug_level & 4)
+ fprintf(stderr,"Create image start\n");
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return(0);
+
+ // If we're in the middle of ID'ing, wait a bit.
+ if (ATV_screen_ID && pending_ID_message)
+ usleep(2000000); // 2 seconds
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return(0);
+
+ /* First get the various dimensions */
+ XtVaGetValues(w,
+ XmNwidth, &width,
+ XmNheight, &height,
+ XmNmarginWidth, &margin_width,
+ XmNmarginHeight, &margin_height,
+ XmNunitType, &unit_type,
+ NULL);
+
+ (void)XSetDashes(XtDisplay(w), gc, 0, medium_dashed , 2);
+
+ screen_width = (long)width;
+ screen_height = (long)height;
+ long_offset_temp = NW_corner_longitude = center_longitude - (screen_width * scale_x / 2); // NW corner
+ lat_offset_temp = NW_corner_latitude = center_latitude - (screen_height * scale_y / 2);
+
+ SE_corner_longitude = center_longitude + (screen_width * scale_x / 2);
+ SE_corner_latitude = center_latitude + (screen_height * scale_y / 2);
+
+ // Set up floating point lat/long values to match Xastir
+ // coordinates.
+ convert_from_xastir_coordinates(&f_NW_corner_longitude,
+ &f_NW_corner_latitude,
+ NW_corner_longitude,
+ NW_corner_latitude);
+ convert_from_xastir_coordinates(&f_SE_corner_longitude,
+ &f_SE_corner_latitude,
+ SE_corner_longitude,
+ SE_corner_latitude);
+
+ /* map default background color */
+ switch (map_background_color){
+ case 0 :
+ colors[0xfd] = GetPixelByName(appshell,"gray73");
+ break;
+
+ case 1 :
+ colors[0xfd] = GetPixelByName(w,"MistyRose");
+ break;
+
+ case 2 :
+ colors[0xfd] = GetPixelByName(w,"NavyBlue");
+ break;
+
+ case 3 :
+ colors[0xfd] = GetPixelByName(w,"SteelBlue");
+ break;
+
+ case 4 :
+ colors[0xfd] = GetPixelByName(w,"MediumSeaGreen");
+ break;
+
+ case 5 :
+ colors[0xfd] = GetPixelByName(w,"PaleGreen");
+ break;
+
+ case 6 :
+ colors[0xfd] = GetPixelByName(w,"PaleGoldenrod");
+ break;
+
+ case 7 :
+ colors[0xfd] = GetPixelByName(w,"LightGoldenrodYellow");
+ break;
+
+ case 8 :
+ colors[0xfd] = GetPixelByName(w,"RosyBrown");
+ break;
+
+ case 9 :
+ colors[0xfd] = GetPixelByName(w,"firebrick");
+ break;
+
+ case 10 :
+ colors[0xfd] = GetPixelByName(w,"white");
+ break;
+
+ case 11 :
+ colors[0xfd] = GetPixelByName(w, "black");
+ break;
+
+ default:
+ colors[0xfd] = GetPixelByName(appshell,"gray73");
+ map_background_color=0;
+ break;
+ }
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return(0);
+
+ (void)XSetForeground(XtDisplay(w),gc,colors[0xfd]);
+ (void)XSetBackground(XtDisplay(w),gc,colors[0xfd]);
+
+ (void)XFillRectangle(XtDisplay(w),
+ pixmap,
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height);
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return(0);
+
+ statusline(langcode("BBARSTA003"),1); // Loading Maps
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return(0);
+
+ if (display_up_first != 0) {
+ // clear the OSM function keys. If an OSM
+ // map is selected they will get re-initialized when
+ // the map is loaded.
+ init_OSM_values();
+ if (map_auto_maps && !disable_all_maps)
+ load_auto_maps(w,AUTO_MAP_DIR);
+ else if (!disable_all_maps)
+ load_maps(w);
+ }
+
+ if (!wx_alert_style)
+ statusline(langcode("BBARSTA034"),1);
+
+ // Update to screen
+// (void)XCopyArea(XtDisplay(da),pixmap,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return(0);
+
+ /* copy map data to alert pixmap */
+ (void)XCopyArea(XtDisplay(w),pixmap,pixmap_alerts,gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return(0);
+
+ if (!wx_alert_style && !disable_all_maps)
+ load_alert_maps(w, ALERT_MAP_DIR); // These write onto pixmap_alerts
+
+ // Update to screen
+// (void)XCopyArea(XtDisplay(da),pixmap_alerts,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return(0);
+
+ /* copy map and alert data to final pixmap */
+ (void)XCopyArea(XtDisplay(w),pixmap_alerts,pixmap_final,gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return(0);
+
+ wx_alert_update_list();
+
+ /* Compute distance */
+ if (lat_offset_temp<0l)
+ lat_offset_temp=0l; // max 90�N
+ else
+ if (lat_offset_temp>64800000l)
+ lat_offset_temp=64800000l; // max 90�S
+
+ if(long_offset_temp<0l)
+ long_offset_temp=0l; // max 180�W
+ else
+ if (long_offset_temp>129600000l)
+ long_offset_temp=129600000l; // max 180�E
+
+ pos1_lat = lat_offset_temp;
+ pos1_lon = long_offset_temp;
+ pos2_lat = lat_offset_temp; // ??
+ pos2_lon = long_offset_temp+(50.0*scale_x);
+
+// long_offset_temp = long_offset_temp+(50*scale_x); // ??
+
+ if(pos2_lat < 0l) // ??
+ pos2_lat = 0l;
+ else
+ if (pos2_lat > 64799999l)
+ pos2_lat = 64799999l;
+
+ if (pos2_lon < 0l)
+ pos2_lon = 0l;
+ else
+ if (pos2_lon > 129599999l)
+ pos2_lon = 129599999l;
+
+ // Get distance in nautical miles
+ x_screen_distance = (float)calc_distance_course(pos1_lat,
+ pos1_lon,
+ pos2_lat,
+ pos2_lon,
+ temp_course,
+ sizeof(temp_course) );
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return(0);
+
+ draw_grid(w); // Draw grid if enabled
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return(0);
+
+ display_file(w); // display stations (symbols, info, trails)
+
+ last_alert_redraw=sec_now(); // set last time of screen redraw
+
+ if (debug_level & 4)
+ fprintf(stderr,"Create image stop\n");
+
+ return(1);
+}
+
+
+
+
+
+// Routine used to refresh image WITHOUT reading regular map files
+// from disk. It starts with the map data already in "pixmap",
+// copies "pixmap" to "pixmap_alerts", draws alerts into
+// "pixmap_alerts", copies "pixmap_alerts" to "pixmap_final", draws
+// symbols/tracks into "pixmap_final" via a call to display_file().
+//
+// Other functions which call this function are responsible for
+// copying the image from pixmap_final() to the screen's drawing
+// area.
+//
+void refresh_image(Widget w) {
+ Dimension width, height, margin_width, margin_height;
+ long lat_offset_temp;
+ long long_offset_temp;
+ char temp_course[20];
+ unsigned char unit_type;
+ char medium_dashed[2] = {(char)5,(char)5};
+ long pos1_lat, pos1_lon, pos2_lat, pos2_lon;
+
+
+ //busy_cursor(w);
+ busy_cursor(appshell);
+
+ if (debug_level & 4)
+ fprintf(stderr,"Refresh image start\n");
+
+ // If we're in the middle of ID'ing, wait a bit.
+ if (ATV_screen_ID && pending_ID_message)
+ usleep(2000000); // 2 seconds
+
+ /* First get the various dimensions */
+ XtVaGetValues(w,
+ XmNwidth, &width,
+ XmNheight, &height,
+ XmNmarginWidth, &margin_width,
+ XmNmarginHeight, &margin_height,
+ XmNunitType, &unit_type,
+ NULL);
+
+ (void)XSetDashes(XtDisplay(w), gc, 0, medium_dashed , 2);
+
+ screen_width = (long)width;
+ screen_height = (long)height;
+
+ long_offset_temp = NW_corner_longitude = center_longitude - (screen_width * scale_x / 2);
+ NW_corner_latitude = center_latitude - (screen_height * scale_y / 2);
+ lat_offset_temp = center_latitude;
+
+ SE_corner_longitude = center_longitude + (screen_width * scale_x / 2);
+ SE_corner_latitude = center_latitude + (screen_height * scale_y / 2);
+
+ // Set up floating point lat/long values to match Xastir
+ // coordinates.
+ convert_from_xastir_coordinates(&f_NW_corner_longitude,
+ &f_NW_corner_latitude,
+ NW_corner_longitude,
+ NW_corner_latitude);
+ convert_from_xastir_coordinates(&f_SE_corner_longitude,
+ &f_SE_corner_latitude,
+ SE_corner_longitude,
+ SE_corner_latitude);
+
+ (void)XSetForeground(XtDisplay(w),gc,colors[0xfd]);
+ (void)XSetBackground(XtDisplay(w),gc,colors[0xfd]);
+
+ /* copy over map data to alert pixmap */
+ (void)XCopyArea(XtDisplay(w),pixmap,pixmap_alerts,gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+
+ if (!wx_alert_style && !disable_all_maps) {
+ statusline(langcode("BBARSTA034"),1);
+ load_alert_maps(w, ALERT_MAP_DIR); // These write onto pixmap_alerts
+ }
+
+ /* copy over map and alert data to final pixmap */
+ (void)XCopyArea(XtDisplay(w),pixmap_alerts,pixmap_final,gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+
+// statusline("Weather Alert Maps Loaded",1);
+
+ wx_alert_update_list();
+
+ /* Compute distance */
+ if (lat_offset_temp<0l)
+ lat_offset_temp=0l; // max 90�N
+ else
+ if (lat_offset_temp>64800000l)
+ lat_offset_temp=64800000l; // max 90�S
+
+ if(long_offset_temp<0l)
+ long_offset_temp=0l; // max 180�W
+ else
+ if (long_offset_temp>129600000l)
+ long_offset_temp=129600000l; // max 180�E
+
+ pos1_lat = lat_offset_temp;
+ pos1_lon = long_offset_temp;
+ pos2_lat = lat_offset_temp; // ??
+ pos2_lon = long_offset_temp+(50.0*scale_x);
+
+// long_offset_temp = long_offset_temp+(50*scale_x); // ??
+
+ if(pos2_lat < 0l) // ??
+ pos2_lat = 0l;
+ else
+ if (pos2_lat > 64799999l)
+ pos2_lat = 64799999l;
+
+ if (pos2_lon < 0l)
+ pos2_lon = 0l;
+ else
+ if (pos2_lon > 129599999l)
+ pos2_lon = 129599999l;
+
+ // Get distance in nautical miles
+ x_screen_distance = (float)calc_distance_course(pos1_lat,
+ pos1_lon,
+ pos2_lat,
+ pos2_lon,
+ temp_course,
+ sizeof(temp_course) );
+
+ // Draw grid if enabled
+ draw_grid(w);
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return;
+
+ /* display icons */
+ display_file(w);
+
+ /* set last time of screen redraw*/
+ last_alert_redraw=sec_now();
+
+ // We just refreshed the screen, so don't try to erase any
+ // zoom-in boxes via XOR.
+ zoom_box_x1 = -1;
+
+ if (debug_level & 4)
+ fprintf(stderr,"Refresh image stop\n");
+}
+
+
+
+
+
+// And this function is even faster yet. It snags "pixmap_alerts",
+// which already has map and alert data drawn into it, copies it to
+// pixmap_final, then draws symbols and tracks on top of it. When
+// done it copies the image to the drawing area, making it visible.
+void redraw_symbols(Widget w) {
+
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return;
+
+ // If we're in the middle of ID'ing, wait a bit.
+ if (ATV_screen_ID && pending_ID_message)
+ usleep(2000000); // 2 seconds
+
+ /* copy over map and alert data to final pixmap */
+ if(!wait_to_redraw) {
+
+ (void)XCopyArea(XtDisplay(w),pixmap_alerts,pixmap_final,gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+
+ draw_grid(w); // draw grid if enabled
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return;
+
+ display_file(w); // display stations (symbols, info, trails)
+
+ (void)XCopyArea(XtDisplay(w),pixmap_final,XtWindow(w),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+ }
+ else {
+ fprintf(stderr,"wait_to_redraw\n");
+ }
+
+ // We just refreshed the screen, so don't try to erase any
+ // zoom-in boxes via XOR.
+ zoom_box_x1 = -1;
+}
+
+
+
+
+
+static void TrackMouse( /*@unused@*/ Widget w, XtPointer clientData, XEvent *event, /*@unused@*/ Boolean *flag) {
+ char my_text[70];
+ char str_lat[20];
+ char str_long[20];
+ long x, y;
+ //beg
+ char temp_my_distance[20];
+ char temp_my_course[20];
+ char temp1_my_course[20];
+ long ml_lat, ml_lon;
+ float value;
+ //end
+
+
+ Widget textarea = (Widget) clientData;
+
+ x = (center_longitude - ((screen_width * scale_x)/2) + (event->xmotion.x * scale_x));
+ y = (center_latitude - ((screen_height * scale_y)/2) + (event->xmotion.y * scale_y));
+
+ if (x < 0)
+// x = 0l; // 180�W
+ return;
+
+ if (x > 129600000l)
+// x = 129600000l; // 180�E
+ return;
+
+ if (y < 0)
+// y = 0l; // 90�N
+ return;
+
+ if (y > 64800000l)
+// y = 64800000l; // 90�S
+ return;
+
+ if (DISPLAY_XASTIR_COORDINATES) {
+ xastir_snprintf(my_text, sizeof(my_text), "%ld %ld", y, x);
+ }
+ else if (coordinate_system == USE_UTM
+ || coordinate_system == USE_UTM_SPECIAL) {
+ // Create a UTM string from coordinate in Xastir coordinate
+ // system.
+ convert_xastir_to_UTM_str(my_text, sizeof(my_text), x, y);
+ }
+ else if (coordinate_system == USE_MGRS) {
+ // Create an MGRS string from coordinate in Xastir
+ // coordinate system.
+ convert_xastir_to_MGRS_str(my_text, sizeof(my_text), x, y, 0);
+ }
+ else {
+ // Create a lat/lon string from coordinate in Xastir
+ // coordinate system.
+ if (coordinate_system == USE_DDDDDD) {
+ convert_lat_l2s(y, str_lat, sizeof(str_lat), CONVERT_DEC_DEG);
+ convert_lon_l2s(x, str_long, sizeof(str_long), CONVERT_DEC_DEG);
+ } else if (coordinate_system == USE_DDMMSS) {
+ convert_lat_l2s(y, str_lat, sizeof(str_lat), CONVERT_DMS_NORMAL_FORMATED);
+ convert_lon_l2s(x, str_long, sizeof(str_long), CONVERT_DMS_NORMAL_FORMATED);
+ //str_lat[2]='�'; str_long[3]='�';
+ //str_lat[5]='\''; str_long[6]='\'';
+ } else { // Assume coordinate_system == USE_DDMMMM
+ convert_lat_l2s(y, str_lat, sizeof(str_lat), CONVERT_HP_NORMAL_FORMATED);
+ convert_lon_l2s(x, str_long, sizeof(str_long), CONVERT_HP_NORMAL_FORMATED);
+ //str_lat[2]='�'; str_long[3]='�';
+ }
+ xastir_snprintf(my_text, sizeof(my_text), "%s %s", str_lat, str_long);
+ }
+
+ strncat(my_text,
+ " ",
+ sizeof(my_text) - 1 - strlen(my_text));
+
+ strncat(my_text,
+ sec_to_loc(x,y),
+ sizeof(my_text) - 1 - strlen(my_text));
+
+ // begin dist/bearing
+ if ( do_dbstatus ) {
+ ml_lat = convert_lat_s2l(my_lat);
+ ml_lon = convert_lon_s2l(my_long);
+
+ // Get distance in nautical miles.
+ value = (float)calc_distance_course(ml_lat,ml_lon,y,x,
+ temp1_my_course,sizeof(temp1_my_course));
+
+ // n7tap: This is a quick hack to get some more useful values for
+ // distance to near ojects.
+ // (copied from db.c:station_data_fill_in)
+ if (english_units) {
+ if (value*1.15078 < 0.99) {
+ xastir_snprintf(temp_my_distance,
+ sizeof(temp_my_distance),
+ "%d %s",
+ (int)(value*1.15078*1760),
+ langcode("SPCHSTR004")); // yards
+ }
+ else {
+ xastir_snprintf(temp_my_distance,
+ sizeof(temp_my_distance),
+ langcode("WPUPSTI020"), // miles
+ value*1.15078);
+ }
+ }
+ else {
+ if (value*1.852 < 0.99) {
+ xastir_snprintf(temp_my_distance,
+ sizeof(temp_my_distance),
+ "%d %s",
+ (int)(value*1.852*1000),
+ langcode("UNIOP00031")); // 'm' as in meters
+ }
+ else {
+ xastir_snprintf(temp_my_distance,
+ sizeof(temp_my_distance),
+ langcode("WPUPSTI021"), // km
+ value*1.852);
+ }
+ }
+ xastir_snprintf(temp_my_course, sizeof(temp_my_course), "%s�",temp1_my_course);
+
+
+ strncat(my_text,
+ " ",
+ sizeof(my_text) - 1 - strlen(my_text));
+
+ strncat(my_text,
+ temp_my_distance,
+ sizeof(my_text) - 1 - strlen(my_text));
+
+ strncat(my_text,
+ " ",
+ sizeof(my_text) - 1 - strlen(my_text));
+
+ strncat(my_text,
+ temp_my_course,
+ sizeof(my_text) - 1 - strlen(my_text));
+ }
+
+ XmTextFieldSetString(textarea, my_text);
+ XtManageChild(textarea);
+}
+
+
+
+
+
+static void ClearTrackMouse( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XEvent *event, /*@unused@*/ Boolean *flag) {
+// N7TAP: In my opinion, it is handy to have the cursor position still displayed
+// in the xastir window when I switch to another (like to write it down...)
+// Widget textarea = (Widget) clientData;
+// XmTextFieldSetString(textarea," ");
+// XtManageChild(textarea);
+}
+
+
+
+
+
+/*
+ * Delete tracks of all stations
+ */
+void Tracks_All_Clear( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ DataRow *p_station;
+
+ p_station = n_first;
+ while (p_station != 0) {
+ if (delete_trail(p_station))
+ redraw_on_new_data=2;
+ p_station = p_station->n_next;
+ }
+}
+
+
+
+
+
+// Get a pointer to the first station record. Loop through all
+// station records and clear out the tactical_call_sign fields in
+// each.
+//
+void clear_all_tactical(void) {
+ DataRow *p_station = n_first;
+
+ // Run through the name-ordered list of records
+ while (p_station != 0) {
+ if (p_station->tactical_call_sign) {
+ // One found. Free it.
+ free(p_station->tactical_call_sign);
+ p_station->tactical_call_sign = NULL;
+ }
+ p_station = p_station->n_next;
+ }
+ fprintf(stderr,"Cleared all tactical calls\n");
+}
+
+
+
+
+
+/*
+ * Clear all tactical callsigns from the station records. Comment
+ * out the active records in the log file.
+ */
+void Tactical_Callsign_Clear( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char *ptr;
+ char file[200];
+ char file_temp[200];
+ FILE *f;
+ FILE *f_temp;
+ char line[300];
+ int ret;
+
+
+ // Loop through all station records and clear out the
+ // tactical_call_sign fields in each.
+ clear_all_tactical();
+
+ // Get rid of the tactical callsign hash here
+ destroy_tactical_hash();
+
+ get_user_base_dir("config/tactical_calls.log", file, sizeof(file));
+
+ get_user_base_dir("config/tactical_calls-temp.log", file_temp,
+ sizeof(file_temp));
+
+ // Our own internal function from util.c
+ ret = copy_file(file, file_temp);
+ if (ret) {
+ fprintf(stderr,"\n\nCouldn't create temp file %s!\n\n\n",
+ file_temp);
+ return;
+ }
+
+ // Comment out all active lines in the log file via a '#' mark.
+ // Read one line at a time from the temp file. Add a '#'
+ // mark to the line if it doesn't already have it, then write
+ // that line to the original file.
+ f_temp=fopen(file_temp,"r");
+ f=fopen(file,"w");
+
+ if (f == NULL) {
+ fprintf(stderr,"Couldn't open %s\n",file);
+ return;
+ }
+ if (f_temp == NULL) {
+ fprintf(stderr,"Couldn't open %s\n",file_temp);
+ return;
+ }
+
+ // Read lines from the temp file and write them to the standard
+ // file, modifying them as necessary.
+ while (fgets(line, 300, f_temp) != NULL) {
+
+ if (line[0] != '#') {
+ fprintf(f,"#%s",line);
+ }
+ else {
+ fprintf(f,"%s",line);
+ }
+ }
+ fclose(f);
+ fclose(f_temp);
+}
+
+
+
+
+
+/*
+ * Clear out tactical callsign log file
+ */
+void Tactical_Callsign_History_Clear( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char file[MAX_VALUE];
+ FILE *f;
+
+ // Loop through all station records and clear out the
+ // tactical_call_sign fields in each.
+ clear_all_tactical();
+
+ // Get rid of the tactical callsign hash here
+ destroy_tactical_hash();
+
+ // Wipe out the log file.
+ get_user_base_dir("config/tactical_calls.log", file, sizeof(file));
+
+ f=fopen(file,"w");
+ if (f!=NULL) {
+ (void)fclose(f);
+
+ if (debug_level & 1)
+ fprintf(stderr,"Clearing tactical callsign file...\n");
+ }
+ else {
+ fprintf(stderr,"Couldn't open file for writing: %s\n", file);
+ }
+
+ fprintf(stderr,"Cleared tactical call history file\n");
+}
+
+
+
+
+
+/*
+ * Display text in the status line, text is removed after timeout
+ */
+void statusline(char *status_text,int update) {
+
+ XmTextFieldSetString (text, status_text);
+ last_statusline = sec_now(); // Used for auto-ID timeout
+// if (update != 0)
+// XmUpdateDisplay(text); // do an immediate update
+}
+
+
+
+
+
+/* print a message on standard error and display the same message
+ * on the status line of the user interface.
+*/
+void stderr_and_statusline(char *message) {
+ fprintf(stderr,"%s",message);
+ if (message[strlen(message)-1]=='\n') {
+ // if there is a terminal new line character remove it.
+ message[strlen(message)-1]='\0';
+ }
+ statusline(message,1);
+ XmUpdateDisplay(text); // force an immediate update
+}
+
+
+
+
+
+//
+// Check for statusline timeout and replace statusline text with a
+// station identification message.
+//
+// ID was requested so that Xastir could be used for a live fast-scan
+// TV display over amateur radio without having to identify the
+// station in some other manner. As long as we guarantee that we'll
+// see this line for a few seconds each 10 minutes (30 minutes for
+// Canada), we should be within the ID rules.
+//
+void check_statusline_timeout(int curr_sec) {
+ char status_text[100];
+ int id_interval = (int)(9.5 * 60);
+// int id_interval = (int)(1 * 5); // Debug
+
+
+ if ( (last_statusline != 0
+ && (last_statusline < curr_sec - STATUSLINE_ACTIVE))
+ || (last_id_time < curr_sec - id_interval) ) {
+
+
+ // We save last_id_time and identify for a few seconds if
+ // we haven't identified for the last nine minutes or so.
+
+ xastir_snprintf(status_text,
+ sizeof(status_text),
+ langcode ("BBARSTA040"),
+ my_callsign);
+
+ XmTextFieldSetString(text, status_text);
+
+ if (last_id_time < curr_sec - id_interval) {
+ popup_ID_message(langcode("BBARSTA040"),status_text);
+#ifdef HAVE_FESTIVAL
+ if (festival_speak_ID) {
+ char my_speech_callsign[100];
+
+ xastir_snprintf(my_speech_callsign,
+ sizeof(my_speech_callsign),
+ "%s",
+ my_callsign);
+ spell_it_out(my_speech_callsign, 100);
+ xastir_snprintf(status_text,
+ sizeof(status_text),
+ langcode ("BBARSTA040"),
+ my_speech_callsign);
+ SayText(status_text);
+ }
+#endif // HAVE_FESTIVAL
+ }
+
+ last_statusline = 0; // now inactive
+
+ // Guarantee that the ID text will be viewable for a few
+ // seconds if we haven't identified recently. Note that the
+ // sleep statement puts the entire main thread to sleep for
+ // that amount of time. The application will be unresponsive
+ // during that time.
+
+ if (last_id_time < (curr_sec - (9 * 60))) {
+ //fprintf(stderr,"Identifying at nine minutes\n");
+ //sleep(1);
+ }
+
+ last_id_time = curr_sec;
+ }
+}
+
+
+
+
+
+/*
+ * Display current zoom factor
+ *
+ * DK7IN: we should find a new measure, we now have different x/y scaling!
+ * I now only use the y value
+ */
+void display_zoom_status(void) {
+ char zoom[30];
+ char siz_str[6];
+
+ if (scale_y < 9000)
+ xastir_snprintf(siz_str, sizeof(siz_str), "%ld", scale_y);
+ else
+ xastir_snprintf(siz_str, sizeof(siz_str), "%ldk", scale_y/1024);
+
+ if (track_station_on == 1)
+ xastir_snprintf(zoom, sizeof(zoom), langcode("BBARZM0002"), siz_str);
+ else
+ xastir_snprintf(zoom, sizeof(zoom), langcode("BBARZM0001"), siz_str);
+
+ XmTextFieldSetString(text4,zoom);
+}
+
+
+
+
+
+void Change_debug_level_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ change_debug_level_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Change_debug_level_reset(Widget widget, XtPointer clientData, XtPointer callData) {
+ debug_level = 0;
+ XmTextSetString(debug_level_text, "0");
+// Change_debug_level_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void Change_debug_level_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ char *temp;
+ char temp_string[10];
+
+ temp = XmTextGetString(debug_level_text);
+
+ debug_level = atoi(temp);
+ if ( (debug_level < 0) || (debug_level > 32767) )
+ debug_level = 0;
+
+ XtFree(temp);
+
+ // Fill in the current value of debug_level
+ xastir_snprintf(temp_string, sizeof(temp_string), "%d", debug_level);
+ XmTextSetString(debug_level_text, temp_string);
+
+// Change_debug_level_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void Change_Debug_Level(Widget w, XtPointer clientData, XtPointer callData) {
+ static Widget pane, my_form, button_ok, button_close,
+ button_reset;
+ Atom delw;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+ char temp_string[10];
+
+ if (!change_debug_level_dialog) {
+ change_debug_level_dialog = XtVaCreatePopupShell(langcode("PULDNFI007"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ NULL);
+
+ pane = XtVaCreateWidget("Change Debug Level pane",
+ xmPanedWindowWidgetClass,
+ change_debug_level_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Change Debug Level my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 3,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ /*set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+
+
+ debug_level_text = XtVaCreateManagedWidget("Change_Debug_Level debug text",
+ xmTextWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 4,
+ XmNwidth, ((5*7)+2),
+ XmNmaxLength, 4,
+ XmNbackground, colors[0x0f],
+ XmNtopOffset, 5,
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Fill in the current value of debug_level
+ xastir_snprintf(temp_string, sizeof(temp_string), "%d", debug_level);
+ XmTextSetString(debug_level_text, temp_string);
+
+ button_reset = XtVaCreateManagedWidget(langcode("UNIOP00033"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, debug_level_text,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, debug_level_text,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ button_close = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, debug_level_text,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_reset, XmNactivateCallback, Change_debug_level_reset, change_debug_level_dialog);
+ XtAddCallback(button_ok, XmNactivateCallback, Change_debug_level_change_data, change_debug_level_dialog);
+ XtAddCallback(button_close, XmNactivateCallback, Change_debug_level_destroy_shell, change_debug_level_dialog);
+
+ pos_dialog(change_debug_level_dialog);
+
+ delw = XmInternAtom(XtDisplay(change_debug_level_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(change_debug_level_dialog, delw, Change_debug_level_destroy_shell, (XtPointer)change_debug_level_dialog);
+
+ XtManageChild(my_form);
+ XtManageChild(pane);
+
+ XtPopup(change_debug_level_dialog,XtGrabNone);
+ fix_dialog_size(change_debug_level_dialog);
+
+ // Move focus to the Close button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(change_debug_level_dialog);
+ XmProcessTraversal(button_close, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(change_debug_level_dialog), XtWindow(change_debug_level_dialog));
+}
+
+
+
+
+
+#if !defined(NO_GRAPHICS) && defined(HAVE_MAGICK)
+void Gamma_adjust_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ gamma_adjust_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Gamma_adjust_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ char *temp;
+ char temp_string[10];
+
+ temp = XmTextGetString(gamma_adjust_text);
+
+ imagemagick_gamma_adjust = atof(temp);
+ if (imagemagick_gamma_adjust < -9.9)
+ imagemagick_gamma_adjust = -9.9;
+ else if (imagemagick_gamma_adjust > 9.9)
+ imagemagick_gamma_adjust = 9.9;
+
+ XtFree(temp);
+
+ xastir_snprintf(temp_string, sizeof(temp_string), "%+.1f", imagemagick_gamma_adjust);
+ XmTextSetString(gamma_adjust_text, temp_string);
+
+ // Set interrupt_drawing_now because conditions have changed
+ // (new map center).
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(da)) {
+// XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+}
+
+
+
+
+
+void Gamma_adjust(Widget w, XtPointer clientData, XtPointer callData) {
+ static Widget pane, my_form, button_ok, button_close;
+ Atom delw;
+ char temp_string[10];
+
+ if (!gamma_adjust_dialog) {
+ // Gamma Correction
+ gamma_adjust_dialog = XtVaCreatePopupShell(langcode("GAMMA002"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ NULL);
+
+ pane = XtVaCreateWidget("Adjust Gamma pane",
+ xmPanedWindowWidgetClass, gamma_adjust_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Adjust Gamma my_form",
+ xmFormWidgetClass, pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ gamma_adjust_text = XtVaCreateManagedWidget("Adjust Gamma text",
+ xmTextWidgetClass, my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 4,
+ XmNwidth, 4*10,
+ XmNmaxLength, 4,
+ XmNbackground, colors[0x0f],
+ XmNtopOffset, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ xastir_snprintf(temp_string, sizeof(temp_string), "%+.1f", imagemagick_gamma_adjust);
+ XmTextSetString(gamma_adjust_text, temp_string);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass, my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, gamma_adjust_text,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_close = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass, my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, gamma_adjust_text,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok,
+ XmNactivateCallback, Gamma_adjust_change_data, gamma_adjust_dialog);
+ XtAddCallback(button_close,
+ XmNactivateCallback, Gamma_adjust_destroy_shell, gamma_adjust_dialog);
+
+ pos_dialog(gamma_adjust_dialog);
+
+ delw = XmInternAtom(XtDisplay(gamma_adjust_dialog), "WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(gamma_adjust_dialog,
+ delw, Gamma_adjust_destroy_shell, (XtPointer)gamma_adjust_dialog);
+
+ XtManageChild(my_form);
+ XtManageChild(pane);
+
+ XtPopup(gamma_adjust_dialog, XtGrabNone);
+ fix_dialog_size(gamma_adjust_dialog);
+
+ // Move focus to the Close button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(gamma_adjust_dialog);
+ XmProcessTraversal(button_close, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(gamma_adjust_dialog), XtWindow(gamma_adjust_dialog));
+}
+#endif // NO_GRAPHICS && HAVE_MAGICK
+
+
+
+
+
+void Load_station_font(void) {
+ // Assign a font (or a different font) to the GC
+
+ // Free any old font first. If we fail to assign a new font in
+ // the code here, can we get in a sitation where we are trying
+ // to draw without a font?
+ if (station_font != NULL) {
+ XFreeFont(XtDisplay(da), station_font);
+ }
+
+ // Load the new font from the FONT_STATION string
+ station_font = (XFontStruct *)XLoadQueryFont(XtDisplay(da), rotated_label_fontname[FONT_STATION]);
+
+ if (station_font == NULL) { // Couldn't get the font!!!
+ char tempy[100];
+
+ fprintf(stderr,"Map_font_change_data: Couldn't load station font %s. ",
+ rotated_label_fontname[FONT_STATION]);
+ fprintf(stderr,"Loading default station font instead.\n");
+
+ xastir_snprintf(tempy,
+ sizeof(tempy),
+ "Couldn't get font %s. Loading default font instead.",
+ rotated_label_fontname[FONT_STATION]);
+ popup_message_always(langcode("POPEM00035"), tempy);
+
+ station_font = (XFontStruct *)XLoadQueryFont(XtDisplay(da), "fixed");
+ if (station_font == NULL) { // Couldn't get the font!!!
+ fprintf(stderr,"Map_font_change_data: Couldn't load default station font.\n");
+
+ popup_message_always(langcode("POPEM00035"),
+ "Couldn't load default station font.");
+ }
+ }
+
+ // Assign the font to the GC.
+ if (station_font != NULL) {
+ XSetFont(XtDisplay(da), gc, station_font->fid);
+ }
+}
+
+
+
+
+
+// chose map label font
+void Map_font_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+
+ xfontsel_query = 0;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ map_font_dialog = (Widget)NULL;
+}
+
+
+
+
+
+// Function called by UpdateTime when xfontsel_query is non-zero.
+// Checks the pipe to see if xfontsel has sent anything to us yet.
+// If we get anything from the read, we should wait a small amount
+// of time and try another read, to make sure we don't get a partial
+// read the first time and quit.
+//
+void Query_xfontsel_pipe (void) {
+ char xfontsel_font[FONT_MAX][sizeof(rotated_label_fontname[0])];
+ struct timeval tmv;
+ fd_set rd;
+ int retval;
+ int fd;
+ int i;
+
+ for (i = 0; i < FONT_MAX; i++) {
+
+ // if (fgets(xfontsel_font,sizeof(xfontsel_font),f_xfontsel_pipe)) {
+
+ // Find out the file descriptor associated with our pipe.
+ if (!f_xfontsel_pipe[i])
+ continue;
+ fd = fileno(f_xfontsel_pipe[i]);
+
+ FD_ZERO(&rd);
+ FD_SET(fd, &rd);
+ tmv.tv_sec = 0;
+ tmv.tv_usec = 1; // 1 usec
+
+ // Do a non-blocking check of the read end of the pipe.
+ retval = select(fd+1,&rd,NULL,NULL,&tmv);
+
+ //fprintf(stderr,"1\n");
+
+ if (retval) {
+ int l = strlen(xfontsel_font[i]);
+
+ // We have something to process. Wait a bit, then snag the
+ // data.
+ usleep(250000); // 250ms
+
+ fgets(xfontsel_font[i],sizeof(xfontsel_font[0]),f_xfontsel_pipe[i]);
+
+ if (xfontsel_font[i][l-1] == '\n')
+ xfontsel_font[i][l-1] = '\0';
+ if (map_font_text[i] != NULL) {
+ XmTextSetString(map_font_text[i], xfontsel_font[i]);
+ }
+ pclose(f_xfontsel_pipe[i]);
+ f_xfontsel_pipe[i] = 0;
+ //fprintf(stderr,"Resetting xfontset_query\n");
+ xfontsel_query = 0;
+ }
+ else {
+ // Read nothing. Let UpdateTime run this function again
+ // shortly.
+ }
+ }
+}
+
+
+
+
+
+void Map_font_xfontsel(Widget widget, XtPointer clientData, XtPointer callData) {
+
+#if defined(HAVE_XFONTSEL)
+
+ int fontsize = XTPOINTER_TO_INT(clientData);
+ char xfontsel[50];
+
+ /* invoke xfontsel -print and stick into map_font_text */
+ sprintf(xfontsel,
+ "%s -print -title \"xfontsel %d\"",
+ XFONTSEL_PATH,
+ fontsize);
+ if ((f_xfontsel_pipe[fontsize] = popen(xfontsel,"r"))) {
+
+ // Request UpdateTime to keep checking the pipe periodically
+ // using non-blocking reads.
+//fprintf(stderr,"Setting xfontsel_query\n");
+ xfontsel_query++;
+
+ } else {
+ perror("xfontsel");
+ }
+#endif // HAVE_XFONTSEL
+}
+
+
+
+
+
+void Map_font_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ char *temp;
+ Widget shell = (Widget) clientData;
+ int i;
+
+
+ xfontsel_query = 0;
+
+ for (i = 0; i < FONT_MAX; i++) {
+ temp = XmTextGetString(map_font_text[i]);
+
+ xastir_snprintf(rotated_label_fontname[i],
+ sizeof(rotated_label_fontname[i]),
+ "%s",
+ temp);
+
+ XtFree(temp);
+ XmTextSetString(map_font_text[i], rotated_label_fontname[i]);
+ }
+
+ // Load a new font into the GC for the station font
+ Load_station_font();
+
+ // Set interrupt_drawing_now because conditions have changed
+ // (new map center).
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ map_font_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Map_font(Widget w, XtPointer clientData, XtPointer callData) {
+ static Widget pane, my_form, fontname[FONT_MAX], button_ok,
+ button_cancel,button_xfontsel[FONT_MAX];
+ Atom delw;
+ int i;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+
+
+ if (!map_font_dialog) {
+ map_font_dialog = XtVaCreatePopupShell(langcode("MAPFONT002"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Choose map labels font",
+ xmPanedWindowWidgetClass, map_font_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Map font my_form",
+ xmFormWidgetClass, pane,
+ XmNfractionBase, 3,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // ac=0;
+ // XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ // XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+
+
+ for (i = 0; i < FONT_MAX; i++) {
+ char *fonttitle[FONT_MAX] = {"MAPFONT009","MAPFONT010","MAPFONT003",
+ "MAPFONT004","MAPFONT005","MAPFONT006",
+ "MAPFONT007","MAPFONT008","MAPFONT011"};
+ ac = 0;
+ if (i == 0) {
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 10); ac++;
+ } else {
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopWidget, fontname[i-1]); ac++;
+ }
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 5); ac++;
+ XtSetArg(al[ac], XmNwidth, 150); ac++;
+ XtSetArg(al[ac], XmNheight, 40); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNforeground,colors[0x08]); ac++;
+ XtSetArg(al[ac], XmNbackground,colors[0xff]); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ fontname[i] = XtCreateManagedWidget(langcode(fonttitle[i]),
+ xmLabelWidgetClass,
+ my_form,
+ al, ac);
+ ac = 0;
+ if (i == 0) {
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 10); ac++;
+ } else {
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopWidget, map_font_text[i-1]); ac++;
+ }
+ XtSetArg(al[ac], XmNeditable, TRUE); ac++;
+ XtSetArg(al[ac], XmNcursorPositionVisible, TRUE); ac++;
+ XtSetArg(al[ac], XmNsensitive, TRUE); ac++;
+ XtSetArg(al[ac], XmNshadowThickness, 1); ac++;
+ XtSetArg(al[ac], XmNcolumns, 60); ac++;
+ XtSetArg(al[ac], XmNwidth, (60*7)+2); ac++;
+ XtSetArg(al[ac], XmNmaxLength, 128); ac++;
+ XtSetArg(al[ac], XmNbackground, colors[0x0f]); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftWidget, fontname[i]); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 10); ac++;
+ XtSetArg(al[ac], XmNheight, 40); ac++;
+ XtSetArg(al[ac], XmNrightAttachment,XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ map_font_text[i] = XtCreateManagedWidget("Map font text",
+ xmTextFieldWidgetClass, my_form,
+ al, ac);
+
+ XmTextSetString(map_font_text[i], rotated_label_fontname[i]);
+
+ // Xfontsel
+ ac = 0;
+ if (i == 0) {
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 10); ac++;
+ } else {
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopWidget, button_xfontsel[i-1]); ac++;
+ }
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftWidget, map_font_text[i]); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 10); ac++;
+ XtSetArg(al[ac], XmNheight, 40); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNforeground,colors[0x08]); ac++;
+ XtSetArg(al[ac], XmNbackground,colors[0xff]); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ button_xfontsel[i] = XtCreateManagedWidget(langcode("PULDNMP015"),
+ xmPushButtonGadgetClass, my_form,
+ al,ac);
+
+#if defined(HAVE_XFONTSEL)
+ XtSetSensitive(button_xfontsel[i],TRUE);
+#else // HAVE_FONTSEL
+ XtSetSensitive(button_xfontsel[i],FALSE);
+#endif // HAVE_FONTSEL
+
+ XtAddCallback(button_xfontsel[i],
+ XmNactivateCallback,
+ Map_font_xfontsel,
+ INT_TO_XTPOINTER(i) );
+
+ }
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass, my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, map_font_text[FONT_MAX-1],
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),
+ xmPushButtonGadgetClass, my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, map_font_text[FONT_MAX-1],
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok,
+ XmNactivateCallback, Map_font_change_data, map_font_dialog);
+ XtAddCallback(button_cancel,
+ XmNactivateCallback, Map_font_destroy_shell, map_font_dialog);
+
+ pos_dialog(map_font_dialog);
+
+ delw = XmInternAtom(XtDisplay(map_font_dialog), "WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(map_font_dialog,
+ delw, Map_font_destroy_shell, (XtPointer)map_font_dialog);
+
+ XtManageChild(my_form);
+ XtManageChild(pane);
+
+ XtPopup(map_font_dialog, XtGrabNone);
+ fix_dialog_size(map_font_dialog);
+
+ // Move focus to the Close button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(map_font_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(map_font_dialog), XtWindow(map_font_dialog));
+}
+
+
+
+
+
+// Used by view_gps_status() function below. We must either expire
+// this data or associate a time with it on the display.
+char gps_status_save[100];
+time_t gps_status_save_time = 0;
+
+
+
+
+
+char *report_gps_status(void) {
+ static char gps_temp[100];
+ char temp2[20];
+
+ switch (gps_valid) {
+
+ case 8: // Simulation Mode
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ langcode("GPSS008") ); // "Simulation"
+ break;
+
+ case 7: // Manual Input Mode
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ langcode("GPSS009") ); // "Manual"
+ break;
+
+ case 6: // Estimated Fix (dead reckoning)
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ langcode("GPSS010") ); // "Estimated"
+ break;
+
+ case 5: // Float RTK
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ langcode("GPSS011") ); // "Float RTK"
+ break;
+
+ case 4: // RTK
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ langcode("GPSS012") ); // "RTK"
+ break;
+
+ case 3: // WAAS or PPS Fix
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ langcode("GPSS001") ); // "WAAS or PPS"
+ break;
+
+ case 2: // DGPS Fix
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ langcode("GPSS002") ); // "DGPS"
+ break;
+
+ case 1: // Valid SPS Fix
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ langcode("GPSS003") ); // "Valid SPS"
+ break;
+
+ case 0: // Invalid
+ default:
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ langcode("GPSS004") ); // "Invalid"
+ break;
+ }
+
+ xastir_snprintf(gps_temp,
+ sizeof(gps_temp),
+ "%s:%s %s:%s",
+ langcode("GPSS005"), // "Sats/View"
+ gps_sats,
+ langcode("GPSS006"), // "Fix"
+ temp2);
+
+ // Save it in global variable in case we request status via the
+ // menus.
+ xastir_snprintf(gps_status_save,
+ sizeof(gps_status_save),
+ "%s",
+ gps_temp);
+
+ gps_status_save_time = sec_now();
+
+ // Reset the variables.
+ xastir_snprintf(gps_sats, sizeof(gps_sats), "00");
+ gps_valid = 0;
+
+ return(gps_temp);
+}
+
+
+
+
+
+void view_gps_status(Widget w, XtPointer clientData, XtPointer callData) {
+
+ // GPS status data too old?
+ if ((gps_status_save_time + 30) >= sec_now()) {
+ // Nope, within 30 seconds
+ popup_message_always(langcode("PULDNVI015"),
+ gps_status_save);
+ }
+ else {
+ // Yes, GPS status data is old
+ popup_message_always(langcode("PULDNVI015"),
+ langcode("GPSS007") );
+ // "!GPS data is older than 30 seconds!"
+ }
+}
+
+
+
+
+
+void Compute_Uptime(Widget w, XtPointer clientData, XtPointer callData) {
+ char temp[200];
+ unsigned long runtime;
+ int days, hours, minutes, seconds;
+ char Days[6];
+ char Hours[7];
+ char Minutes[9];
+ char Seconds[9];
+
+ runtime = sec_now() - program_start_time;
+ days = runtime / 86400;
+ runtime = runtime - (days * 86400);
+ hours = runtime / 3600;
+ runtime = runtime - (hours * 3600);
+ minutes = runtime / 60;
+ seconds = runtime - (minutes * 60);
+
+ if (days == 1)
+ xastir_snprintf(Days,sizeof(Days),"%s",langcode("TIME001")); // Day
+ else
+ xastir_snprintf(Days,sizeof(Days),"%s",langcode("TIME002")); // Days
+
+
+ if (hours == 1)
+ xastir_snprintf(Hours,sizeof(Hours),"%s",langcode("TIME003")); // Hour
+ else
+ xastir_snprintf(Hours,sizeof(Hours),"%s",langcode("TIME004")); // Hours
+
+
+ if (minutes == 1)
+ xastir_snprintf(Minutes,sizeof(Minutes),"%s",langcode("TIME005")); // Minute
+ else
+ xastir_snprintf(Minutes,sizeof(Minutes),"%s",langcode("TIME006")); // Minutes
+
+
+ if (seconds == 1)
+ xastir_snprintf(Seconds,sizeof(Seconds),"%s",langcode("TIME007")); // Second
+ else
+ xastir_snprintf(Seconds,sizeof(Seconds),"%s",langcode("TIME008")); // Seconds
+
+
+ if (days != 0) {
+ xastir_snprintf(temp, sizeof(temp), "%d %s, %d %s, %d %s, %d %s",
+ days, Days, hours, Hours, minutes, Minutes, seconds, Seconds);
+ } else if (hours != 0) {
+ xastir_snprintf(temp, sizeof(temp), "%d %s, %d %s, %d %s",
+ hours, Hours, minutes, Minutes, seconds, Seconds);
+ } else if (minutes != 0) {
+ xastir_snprintf(temp, sizeof(temp), "%d %s, %d %s", minutes, Minutes, seconds, Seconds);
+ } else {
+ xastir_snprintf(temp, sizeof(temp), "%d %s", seconds, Seconds);
+ }
+ popup_message_always(langcode("PULDNVI014"),temp);
+}
+
+
+
+
+
+void Mouse_button_handler (Widget w, Widget popup, XButtonEvent *event) {
+
+ // Snag the current pointer position
+ input_x = event->x;
+ input_y = event->y;
+
+ if (event->type == ButtonPress) {
+ //fprintf(stderr,"Mouse_button_handler, button pressed %d\n", event->button);
+ }
+
+ if (event->type == ButtonRelease) {
+ //fprintf(stderr,"Mouse_button_handler, button released %d\n", event->button);
+ return;
+ }
+
+#ifdef SWAP_MOUSE_BUTTONS
+ if (event->button != Button1) {
+ //fprintf(stderr,"Pressed a mouse button, but not Button1: %x\n",event->button);
+#else // SWAP_MOUSE_BUTTONS
+ if (event->button != Button3) {
+ //fprintf(stderr,"Pressed a mouse button, but not Button3: %x\n",event->button);
+#endif // SWAP_MOUSE_BUTTONS
+ return;
+ }
+
+ // Right mouse button press
+ menu_x=input_x;
+ menu_y=input_y;
+ if (right_menu_popup != NULL) { // If popup menu defined
+
+#ifdef SWAP_MOUSE_BUTTONS
+ // This gets the menus out of the way that are on pointer
+ // button1 if SWAP_MOUSE_BUTTONS is enabled. If it's not
+ // enabled, they don't interfere with each other anyway.
+ if (!measuring_distance && !moving_object) {
+#else // SWAP_MOUSE_BUTTONS
+ if (1) { // Always bring up the menu if SWAP is disabled
+#endif // SWAP_MOUSE_BUTTONS
+
+ // Bring up the popup menu
+ XmMenuPosition(right_menu_popup,(XButtonPressedEvent *)event);
+ XtManageChild(right_menu_popup);
+
+ // Check whether any modifiers are pressed.
+ // If so, pop up a warning message.
+ if ( (event->state != 0) && warn_about_mouse_modifiers) {
+ popup_message_always(langcode("POPUPMA023"),langcode("POPUPMA024"));
+ }
+ }
+ }
+}
+
+
+
+
+
+void menu_link_for_mouse_menu(Widget w, XtPointer clientData, XtPointer callData) {
+ if (right_menu_popup!=NULL) {
+ //XmMenuPosition(right_menu_popup,(XButtonPressedEvent *)event);
+ XtManageChild(right_menu_popup);
+ }
+}
+
+
+
+
+
+void store_all_kml_callback(/*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ export_trail_as_kml(NULL);
+ last_kmlsnapshot = sec_now();
+}
+
+
+
+
+void KML_Snapshots_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ // Whether we're setting or unsetting it, set the timer such
+ // that a snapshot will occur immediately once the button is set
+ // again.
+ last_kmlsnapshot = 0;
+
+ if(state->set)
+ kmlsnapshots_enabled = atoi(which);
+ else
+ kmlsnapshots_enabled = 0;
+}
+
+
+
+
+
+void Snapshots_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ // Whether we're setting or unsetting it, set the timer such
+ // that a snapshot will occur immediately once the button is set
+ // again.
+ last_snapshot = 0;
+
+ if(state->set)
+ snapshots_enabled = atoi(which);
+ else
+ snapshots_enabled = 0;
+}
+
+
+
+
+
+inline int no_data_selected(void)
+{
+ return (
+ Select_.none || (
+ !Select_.mine &&
+ !Select_.net && (
+ !Select_.tnc || (
+ !Select_.direct && !Select_.via_digi
+ )
+ )
+ )
+ );
+}
+
+
+
+
+
+#ifdef ARROWS
+Widget pan_up_menu, pan_down_menu,
+ pan_left_menu, pan_right_menu,
+ zoom_in_menu, zoom_out_menu;
+#endif // ARROWS
+
+
+
+
+
+void create_appshell( /*@unused@*/ Display *display, char *app_name, /*@unused@*/ int app_argc, char ** app_argv) {
+ Pixmap icon_pixmap;
+ Atom WM_DELETE_WINDOW;
+ Widget children[9]; /* Children to manage */
+ Arg al[100]; /* Arg List */
+ register unsigned int ac; /* Arg Count */
+ /*popup menu widgets */
+ Widget zoom_in, zoom_out, zoom_sub, zoom_level, zl1, zl2, zl3,
+ zl4, zl5, zl6, zl7, zl8, zl9, zlC;
+ Widget sar_object_menu;
+ Widget CAD_sub, CAD1, CAD3, CAD4;
+ Widget pan_sub, pan_menu;
+ Widget move_my_sub, move_my_menu;
+ Widget pan_ctr, last_loc, station_info, send_message_to;
+ Widget set_object, modify_object;
+ Widget setmyposition, pan_up, pan_down, pan_left, pan_right;
+ /*menu widgets */
+ Widget sep;
+ Widget filepane, configpane, exitpane, mappane, viewpane,
+ stationspane, messagepane, ifacepane, helppane,
+ filter_data_pane, filter_display_pane, map_config_pane,
+ station_config_pane,
+ help_emergency_pane, help_emergency_button;
+
+ Widget display_button,
+ track_button, download_trail_button, station_clear_button,
+ tracks_clear_button, object_history_refresh_button,
+ object_history_clear_button, tactical_clear_button,
+ tactical_history_clear_button, uptime_button, aloha_button,
+ save_button,
+ file_button, open_file_button, exit_button,
+ view_button, view_messages_button, gps_status_button,
+ bullet_button, packet_data_button, mobile_button,
+ stations_button, localstations_button, laststations_button,
+ objectstations_button, objectmystations_button,
+ weather_button, wx_station_button, locate_button, geocode_place_button,
+ locate_place_button, jump_button, jump_button2, alert_button,
+ config_button, defaults_button, timing_button,
+ coordinates_button, station_button, map_lock_pan_zoom_button, map_disable_button,
+ map_button, map_auto_button, map_chooser_button,
+ map_grid_button, map_levels_button, map_labels_button,
+ map_fill_button, coordinate_calculator_button,
+ center_zoom_button,
+ Map_background_color_Pane, map_background_button,
+ map_pointer_menu_button, map_config_button,
+ station_config_button,
+ cad_draw_button, cad_show_label_button,
+ cad_show_probability_button, cad_show_area_button,
+ cad_show_comment_button,
+#if !defined(NO_GRAPHICS)
+ Raster_intensity_Pane, raster_intensity_button,
+#if defined(HAVE_MAGICK)
+ gamma_adjust_button, tiger_config_button,
+#endif // HAVE_MAGICK
+#ifdef HAVE_LIBGEOTIFF
+ drg_config_button,
+#endif // HAVE_LIBGEOTIFF
+#endif // NO_GRAPHICS
+ font_button,
+ Map_station_label_Pane, map_station_label_button,
+ Map_icon_outline_Pane, map_icon_outline_button,
+ map_wx_alerts_button, index_maps_on_startup_button,
+ redownload_maps_button, flush_map_cache_button,
+ units_choice_button, dbstatus_choice_button,
+ iface_button, iface_connect_button,
+ tnc_logging, transmit_disable_toggle, net_logging,
+ igate_logging, wx_logging, message_logging,
+ wx_alert_logging, enable_snapshots, print_button,
+ test_button, debug_level_button, aa_button, speech_button,
+ smart_beacon_button, map_indexer_button,
+ map_all_indexer_button, auto_msg_set_button,
+ message_button, send_message_to_button,
+ show_pending_messages_button, enable_kmlsnapshots,
+ open_messages_group_button, clear_messages_button,
+ General_q_button, IGate_q_button, WX_q_button,
+ filter_data_button, filter_display_button,
+ draw_CAD_objects_menu,
+ store_data_pane, store_data_button, store_all_kml_button,
+#ifdef HAVE_DB
+ store_all_db_button,
+#endif // HAVE_DB
+ help_button, help_about, help_help;
+
+ char *title, *t;
+ int t_size;
+// XWMHints *wm_hints; // Used for window manager hints
+ Dimension my_appshell_width, my_appshell_height;
+ Dimension da_width, da_height;
+ static XmFontListEntry font_entry;
+
+
+ if(debug_level & 8)
+ fprintf(stderr,"Create appshell start\n");
+
+/*
+ wm_hints = XAllocWMHints();
+ if (!wm_hints) {
+ fprintf(stderr,"Failure allocating memory: wm_hints\n");
+ exit(0);
+ }
+
+ // Set up the wm_hints struct
+ wm_hints->initial_state = NormalState;
+ wm_hints->input = True;
+ wm_hints->flags = StateHint | InputHint;
+*/
+
+
+ t = _("X Amateur Station Tracking and Information Reporting");
+ title = (char *)malloc(t_size = (strlen(t) + 42 + strlen(xastir_package)));
+ if (!title) {
+ fprintf(stderr,"Couldn't allocate memory for title\n");
+ }
+ else {
+ xastir_snprintf(title, t_size, "XASTIR");
+ strncat(title, " - ", t_size - 1 - strlen(title));
+ strncat(title, t, t_size - 1 - strlen(title));
+ strncat(title, " @ ", t_size - 1 - strlen(title));
+ (void)gethostname(&title[strlen(title)], 28);
+ }
+
+ // Allocate a couple of colors that we'll need before we get
+ // around to calling create_gc(), which creates the rest.
+ //
+ colors[0x08] = GetPixelByName(appshell,"black");
+ colors[0x0c] = GetPixelByName(appshell,"red");
+ colors[0xff] = GetPixelByName(appshell,"gray73");
+
+
+ ac = 0;
+
+
+
+// Snag border widths so that we can use them in the calculations
+// below. If we fail to do this the size and offsets will be off by
+// the width of the borders added by the window manager.
+//
+// if (XGetGeometry(XtDisplay(da),
+// XtWindow(appshell),
+// &root_return,
+// &x_return,
+// &y_return,
+// &width_return,
+// &height_return,
+// &border_width_return,
+// &depth_return) ) == False) {
+// fprintf(stderr,"Couldn't get window attributes\n");
+// }
+//
+// Another method:
+//
+// XWindowAttributes windowattr; // Defined in Xlib.h
+// Struct has x/y/width/height/border_width/depth fields.
+// if (XGetWindowAttributes(display,XtWindow(appshell),&windowattr) == 0) {
+// fprintf(stderr,"Couldn't get window attributes\n")
+// }
+
+
+
+ // Set up the main window X/Y sizes and the minimum sizes
+ // allowable.
+ //
+ if ( (WidthValue|HeightValue) & geometry_flags ) {
+ //
+ // Size of Xastir was specified with a -geometry setting.
+ // Set up the window size.
+ //
+
+ my_appshell_width = (Dimension)geometry_width; // Used in offset equations below
+ my_appshell_height = (Dimension)geometry_height; // Used in offset equations below
+//fprintf(stderr,"gW:%d gH:%d\n", geometry_width, geometry_height);
+//fprintf(stderr,"tW:%d tH:%d\n", (int)my_appshell_width, (int)my_appshell_height);
+ if (my_appshell_width < 61)
+ my_appshell_width = 61;
+ if (my_appshell_height < 61)
+ my_appshell_height = 61;
+//fprintf(stderr,"tW:%d tH:%d\n", (int)my_appshell_width, (int)my_appshell_height);
+ XtSetArg(al[ac], XmNwidth, my_appshell_width); ac++;
+ XtSetArg(al[ac], XmNheight, my_appshell_height); ac++;
+// XtSetArg(al[ac], XmNminWidth, 61); ac++;
+// XtSetArg(al[ac], XmNminHeight, 61); ac++;
+// Lock the min size to the specified initial size for now, release
+// later after creating initial window. Snagged this idea from the
+// Lincity project where they do similar things in "lcx11.c"
+// XtSetArg(al[ac], XmNminWidth, my_appshell_width); ac++;
+// XtSetArg(al[ac], XmNminHeight, my_appshell_height); ac++;
+ }
+ else {
+ // Size was NOT specified in a -geometry string. Set to the
+ // size specified in the config file instead.
+ //
+ my_appshell_width = (Dimension)screen_width;
+ my_appshell_height = (Dimension)(screen_height + 60);
+ XtSetArg(al[ac], XmNwidth, my_appshell_width); ac++;
+ XtSetArg(al[ac], XmNheight, my_appshell_height); ac++;
+// XtSetArg(al[ac], XmNminWidth, 61); ac++;
+// XtSetArg(al[ac], XmNminHeight, 61); ac++;
+// Lock the min size to the specified initial size for now, release
+// later after creating initial window. Got this idea from the
+// Lincity project where they do the similar things in "lcx11.c"
+// XtSetArg(al[ac], XmNminWidth, my_appshell_width); ac++;
+// XtSetArg(al[ac], XmNminHeight, my_appshell_height); ac++;
+ }
+
+
+// Set up default font
+ font1 = XLoadQueryFont(display, rotated_label_fontname[FONT_SYSTEM]);
+
+ if (font1 == NULL) { // Couldn't get the font!!!
+ fprintf(stderr,"create_appshell: Couldn't load system font %s. ",
+ rotated_label_fontname[FONT_SYSTEM]);
+ fprintf(stderr,"Loading default system font instead.\n");
+ font1 = XLoadQueryFont(display, "fixed");
+ if (font1 == NULL) { // Couldn't get the font!!!
+ fprintf(stderr,"create_appshell: Couldn't load default system font, exiting.\n");
+ exit(1);
+ }
+ else {
+ // _Now_ we can do a popup message about the first error
+ // as we have a font to work with!
+ char tempy[100];
+
+ xastir_snprintf(tempy,
+ sizeof(tempy),
+ "Couldn't get font %s. Loading default font instead.",
+ rotated_label_fontname[FONT_SYSTEM]);
+ popup_message_always(langcode("POPEM00035"), tempy);
+ }
+ }
+
+ font_entry = XmFontListEntryCreate(XmFONTLIST_DEFAULT_TAG, XmFONT_IS_FONT, font1);
+ fontlist1 = XmFontListAppendEntry(NULL, font_entry);
+ XmFontListEntryFree(&font_entry);
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ // Set up the X/Y offsets for the main window
+ //
+ if ( (XValue|YValue) & geometry_flags ) {
+ Position my_x, my_y;
+
+ //
+ // Position of Xastir was specified with a -geometry setting.
+ //
+ if (XNegative & geometry_flags) {
+ geometry_x = DisplayWidth(display, DefaultScreen(display) )
+ + geometry_x - (int)my_appshell_width;
+ }
+ if (YNegative & geometry_flags) {
+ geometry_y = DisplayHeight(display, DefaultScreen(display) )
+ + geometry_y - (int)my_appshell_height;
+ }
+ my_x = (Position)geometry_x;
+ my_y = (Position)geometry_y;
+ XtSetArg(al[ac], XmNx, my_x); ac++;
+ XtSetArg(al[ac], XmNy, my_y); ac++;
+ }
+ else {
+ //
+ // Position of Xastir was not specified. Use the values
+ // from the config file
+ //
+/*
+// This doesn't position the widget in fvwm2. Would hate to go back
+// to XSizeHints in order to make this work.
+fprintf(stderr,"Setting up widget's X/Y position at X:%d Y:%d\n",
+ (int)screen_x_offset,
+ (int)screen_y_offset);
+
+ XtSetArg(al[ac], XmNx, screen_x_offset); ac++; // Doesn't work here
+ XtSetArg(al[ac], XmNy, screen_y_offset); ac++; // Doesn't work here
+*/
+ }
+
+
+ XtSetArg(al[ac], XmNallowShellResize, TRUE); ac++;
+
+ if (title)
+ XtSetArg(al[ac], XmNtitle, title); ac++;
+
+ XtSetArg(al[ac], XmNdefaultPosition, FALSE); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ //
+ // Set the above values into the appshell widget
+ //
+ XtSetValues(appshell, al, ac);
+
+
+ // Make at least one Motif call so that the next function won't
+ // result in this problem: 'Error: atttempt to add non-widget
+ // child "DropSiteManager" to parent "xastir"'.
+ //
+ (void) XmIsMotifWMRunning(appshell);
+
+
+ form = XtVaCreateWidget("create_appshell form",
+ xmFormWidgetClass,
+ appshell,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ /* Menu Bar */
+ ac = 0;
+ XtSetArg(al[ac], XmNshadowThickness, 1); ac++;
+ XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ menubar = XmCreateMenuBar(form,
+ "create_appshell menubar",
+ al,
+ ac);
+
+ /*set args for color */
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ /* menu bar */
+ filepane = XmCreatePulldownMenu(menubar,"filepane", al, ac);
+ viewpane = XmCreatePulldownMenu(menubar,"viewpane", al, ac);
+ mappane = XmCreatePulldownMenu(menubar,"mappane", al, ac);
+ stationspane= XmCreatePulldownMenu(menubar,"stationspane",al, ac);
+ messagepane = XmCreatePulldownMenu(menubar,"messagepane", al, ac);
+ ifacepane = XmCreatePulldownMenu(menubar,"ifacepane", al, ac);
+ helppane = XmCreatePulldownMenu(menubar,"helppane", al, ac);
+
+ file_button = XtVaCreateManagedWidget(langcode("MENUTB0001"),
+ xmCascadeButtonGadgetClass,
+ menubar,
+ XmNsubMenuId, filepane,
+ XmNmnemonic,langcode_hotkey("MENUTB0001"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ view_button = XtVaCreateManagedWidget(langcode("MENUTB0002"),
+ xmCascadeButtonGadgetClass,
+ menubar,
+ XmNsubMenuId,viewpane,
+ XmNmnemonic,langcode_hotkey("MENUTB0002"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_button = XtVaCreateManagedWidget(langcode("MENUTB0004"),
+ xmCascadeButtonGadgetClass,
+ menubar,
+ XmNsubMenuId,mappane,
+ XmNmnemonic,langcode_hotkey("MENUTB0004"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ display_button = XtVaCreateManagedWidget(langcode("MENUTB0005"),
+ xmCascadeButtonGadgetClass,
+ menubar,
+ XmNsubMenuId,stationspane,
+ XmNmnemonic,langcode_hotkey("MENUTB0005"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ message_button = XtVaCreateManagedWidget(langcode("MENUTB0006"),
+ xmCascadeButtonGadgetClass,
+ menubar,
+ XmNsubMenuId,messagepane,
+ XmNmnemonic,langcode_hotkey("MENUTB0006"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ iface_button = XtVaCreateManagedWidget(langcode("MENUTB0010"),
+ xmCascadeButtonGadgetClass,
+ menubar,
+ XmNsubMenuId,ifacepane,
+ XmNmnemonic,langcode_hotkey("MENUTB0010"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ help_button = XtVaCreateManagedWidget(langcode("MENUTB0009"),
+ xmCascadeButtonGadgetClass,
+ menubar,
+ XmNsubMenuId,helppane,
+ XmNmnemonic,langcode_hotkey("MENUTB0009"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtVaSetValues (menubar,XmNmenuHelpWidget,help_button,NULL);
+ /* end bar */
+
+ /* File */
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ configpane = XmCreatePulldownMenu(filepane,
+ "configpane",
+ al,
+ ac);
+
+ // Print button
+ print_button = XtVaCreateManagedWidget(langcode("PULDNFI015"),
+ xmPushButtonWidgetClass,
+ filepane,
+ XmNmnemonic, langcode_hotkey("PULDNFI015"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback( print_button, XmNactivateCallback, Print_Postscript, NULL );
+
+ config_button = XtVaCreateManagedWidget(langcode("PULDNFI001"),
+ xmCascadeButtonGadgetClass,
+ filepane,
+ XmNsubMenuId,configpane,
+ XmNmnemonic,langcode_hotkey("PULDNFI001"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ (void)XtVaCreateManagedWidget("create_appshell sep1",
+ xmSeparatorGadgetClass,
+ filepane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ open_file_button = XtVaCreateManagedWidget(langcode("PULDNFI002"),
+ xmPushButtonGadgetClass,
+ filepane,
+ XmNmnemonic,langcode_hotkey("PULDNFI002"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ tnc_logging = XtVaCreateManagedWidget(langcode("PULDNFI010"),
+ xmToggleButtonGadgetClass,
+ filepane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(tnc_logging,XmNvalueChangedCallback,TNC_Logging_toggle,"1");
+ if (log_tnc_data)
+ XmToggleButtonSetState(tnc_logging,TRUE,FALSE);
+
+
+
+ net_logging = XtVaCreateManagedWidget(langcode("PULDNFI011"),
+ xmToggleButtonGadgetClass,
+ filepane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(net_logging,XmNvalueChangedCallback,Net_Logging_toggle,"1");
+ if (log_net_data)
+ XmToggleButtonSetState(net_logging,TRUE,FALSE);
+
+
+ igate_logging = XtVaCreateManagedWidget(langcode("PULDNFI012"),
+ xmToggleButtonGadgetClass,
+ filepane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(igate_logging,XmNvalueChangedCallback,IGate_Logging_toggle,"1");
+ if (log_igate)
+ XmToggleButtonSetState(igate_logging,TRUE,FALSE);
+
+// message_logging = XtVaCreateManagedWidget(langcode("PULDNFI012"),
+ message_logging = XtVaCreateManagedWidget("Message Logging",
+ xmToggleButtonGadgetClass,
+ filepane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(message_logging,XmNvalueChangedCallback,Message_Logging_toggle,"1");
+ if (log_message_data)
+ XmToggleButtonSetState(message_logging,TRUE,FALSE);
+
+ wx_logging = XtVaCreateManagedWidget(langcode("PULDNFI013"),
+ xmToggleButtonGadgetClass,
+ filepane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(wx_logging,XmNvalueChangedCallback,WX_Logging_toggle,"1");
+ if (log_wx)
+ XmToggleButtonSetState(wx_logging,TRUE,FALSE);
+
+// wx_alert_logging = XtVaCreateManagedWidget(langcode("PULDNFI013"),
+ wx_alert_logging = XtVaCreateManagedWidget("WX Alert Logging",
+ xmToggleButtonGadgetClass,
+ filepane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(wx_alert_logging,XmNvalueChangedCallback,WX_Alert_Logging_toggle,"1");
+ if (log_wx_alert_data)
+ XmToggleButtonSetState(wx_alert_logging,TRUE,FALSE);
+
+ enable_snapshots = XtVaCreateManagedWidget(langcode("PULDNFI014"),
+ xmToggleButtonGadgetClass,
+ filepane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(enable_snapshots,XmNvalueChangedCallback,Snapshots_toggle,"1");
+ if (snapshots_enabled)
+ XmToggleButtonSetState(enable_snapshots,TRUE,FALSE);
+
+ // enable kml snapshots
+ enable_kmlsnapshots = XtVaCreateManagedWidget(langcode("PULDNFI016"),
+ xmToggleButtonGadgetClass,
+ filepane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(enable_kmlsnapshots,XmNvalueChangedCallback,KML_Snapshots_toggle,"1");
+ if (kmlsnapshots_enabled)
+ XmToggleButtonSetState(enable_kmlsnapshots,TRUE,FALSE);
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep1a",
+ xmSeparatorGadgetClass,
+ filepane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep1b",
+ xmSeparatorGadgetClass,
+ filepane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ exitpane = XmCreatePulldownMenu(filepane,
+ "exitpane",
+ al,
+ ac);
+
+ exit_button = XtVaCreateManagedWidget(langcode("PULDNFI004"),
+ xmPushButtonWidgetClass,
+ filepane,
+ XmNmnemonic,langcode_hotkey("PULDNFI004"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ /* View */
+ packet_data_button = XtVaCreateManagedWidget(langcode("PULDNVI002"),
+ xmPushButtonGadgetClass,
+ viewpane,
+ XmNmnemonic,langcode_hotkey("PULDNVI002"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ view_messages_button = XtVaCreateManagedWidget(langcode("PULDNVI011"),
+ xmPushButtonGadgetClass,
+ viewpane,
+ XmNmnemonic,langcode_hotkey("PULDNVI011"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ bullet_button = XtVaCreateManagedWidget(langcode("PULDNVI001"),
+ xmPushButtonGadgetClass,
+ viewpane,
+ XmNmnemonic,langcode_hotkey("PULDNVI001"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ (void)XtVaCreateManagedWidget("create_appshell sep?",
+ xmSeparatorGadgetClass,
+ viewpane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ mobile_button = XtVaCreateManagedWidget(langcode("PULDNVI003"),
+ xmPushButtonGadgetClass,
+ viewpane,
+ XmNmnemonic,langcode_hotkey("PULDNVI003"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ stations_button = XtVaCreateManagedWidget(langcode("PULDNVI004"),
+ xmPushButtonGadgetClass,
+ viewpane,
+ XmNmnemonic,langcode_hotkey("PULDNVI004"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ localstations_button = XtVaCreateManagedWidget(langcode("PULDNVI009"),
+ xmPushButtonGadgetClass,
+ viewpane,
+ XmNmnemonic,langcode_hotkey("PULDNVI009"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ laststations_button = XtVaCreateManagedWidget(langcode("PULDNVI012"),
+ xmPushButtonGadgetClass,
+ viewpane,
+ XmNmnemonic,langcode_hotkey("PULDNVI012"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ (void)XtVaCreateManagedWidget("create_appshell sep1?",
+ xmSeparatorGadgetClass,
+ viewpane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ objectstations_button = XtVaCreateManagedWidget(langcode("LHPUPNI005"),
+ xmPushButtonGadgetClass,
+ viewpane,
+ XmNmnemonic,langcode_hotkey("LHPUPNI005"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ objectmystations_button = XtVaCreateManagedWidget(langcode("LHPUPNI006"),
+ xmPushButtonGadgetClass,
+ viewpane,
+ XmNmnemonic,langcode_hotkey("LHPUPNI006"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // "List All CAD Polygons"
+ CAD1 = XtVaCreateManagedWidget(langcode("POPUPMA046"),
+ xmPushButtonGadgetClass,
+ viewpane,
+ XmNmnemonic,langcode_hotkey("POPUPMA046"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ (void)XtVaCreateManagedWidget("create_appshell sep2?",
+ xmSeparatorGadgetClass,
+ viewpane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ weather_button = XtVaCreateManagedWidget(langcode("PULDNVI005"),
+ xmPushButtonGadgetClass,
+ viewpane,
+ XmNmnemonic,langcode_hotkey("PULDNVI005"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ wx_station_button = XtVaCreateManagedWidget(langcode("PULDNVI008"),
+ xmPushButtonGadgetClass,
+ viewpane,
+ XmNmnemonic,langcode_hotkey("PULDNVI008"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ alert_button = XtVaCreateManagedWidget(langcode("PULDNVI007"),
+ xmPushButtonGadgetClass,
+ viewpane,
+ XmNmnemonic,langcode_hotkey("PULDNVI007"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ (void)XtVaCreateManagedWidget("create_appshell sep3?",
+ xmSeparatorGadgetClass,
+ viewpane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ gps_status_button = XtVaCreateManagedWidget(langcode("PULDNVI015"),
+ xmPushButtonGadgetClass,
+ viewpane,
+ XmNmnemonic,langcode_hotkey("PULDNVI015"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ uptime_button = XtVaCreateManagedWidget(langcode("PULDNVI013"),
+ xmPushButtonWidgetClass,
+ viewpane,
+ XmNmnemonic, langcode_hotkey("PULDNVI013"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ aloha_button = XtVaCreateManagedWidget(langcode("PULDNVI016"),
+ xmPushButtonWidgetClass,
+ viewpane,
+ XmNmnemonic, langcode_hotkey("PULDNVI016"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ /* Configure */
+ station_button = XtVaCreateManagedWidget(langcode("PULDNCF004"),
+ xmPushButtonGadgetClass,
+ configpane,
+ XmNmnemonic,langcode_hotkey("PULDNCF004"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ defaults_button = XtVaCreateManagedWidget(langcode("PULDNCF001"),
+ xmPushButtonGadgetClass,
+ configpane,
+ XmNmnemonic,langcode_hotkey("PULDNCF001"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ timing_button = XtVaCreateManagedWidget(langcode("PULDNCF003"),
+ xmPushButtonGadgetClass,
+ configpane,
+ XmNmnemonic,langcode_hotkey("PULDNCF003"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ coordinates_button = XtVaCreateManagedWidget(langcode("PULDNCF002"),
+ xmPushButtonGadgetClass,
+ configpane,
+ XmNmnemonic,langcode_hotkey("PULDNCF002"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ aa_button = XtVaCreateManagedWidget(langcode("PULDNCF006"),
+ xmPushButtonGadgetClass,
+ configpane,
+ XmNmnemonic,langcode_hotkey("PULDNCF006"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ speech_button = XtVaCreateManagedWidget(langcode("PULDNCF007"),
+ xmPushButtonGadgetClass,
+ configpane,
+ XmNmnemonic,langcode_hotkey("PULDNCF007"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ smart_beacon_button = XtVaCreateManagedWidget(langcode("SMARTB001"),
+ xmPushButtonGadgetClass,
+ configpane,
+ XmNmnemonic,langcode_hotkey("SMARTB001"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // map label font select
+ font_button = XtVaCreateManagedWidget(langcode("PULDNMP025"),
+ xmPushButtonWidgetClass, configpane,
+ XmNmnemonic,langcode_hotkey("PULDNMP025"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(font_button, XmNactivateCallback, Map_font, NULL);
+
+ test_button = XtVaCreateManagedWidget(langcode("PULDNFI003"),
+ xmPushButtonWidgetClass,
+ configpane,
+ XmNmnemonic, langcode_hotkey("PULDNFI003"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ debug_level_button = XtVaCreateManagedWidget(langcode("PULDNFI007"),
+ xmPushButtonWidgetClass,
+ configpane,
+ XmNmnemonic, langcode_hotkey("PULDNFI007"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ units_choice_button = XtVaCreateManagedWidget(langcode("PULDNUT001"),
+ xmToggleButtonGadgetClass,
+ configpane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(units_choice_button,XmNvalueChangedCallback,Units_choice_toggle,"1");
+ if (english_units)
+ XmToggleButtonSetState(units_choice_button,TRUE,FALSE);
+
+ dbstatus_choice_button = XtVaCreateManagedWidget(langcode("PULDNDB001"),
+ xmToggleButtonGadgetClass,
+ configpane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(dbstatus_choice_button,XmNvalueChangedCallback,Dbstatus_choice_toggle,"1");
+ if (do_dbstatus)
+ XmToggleButtonSetState(dbstatus_choice_button,TRUE,FALSE);
+
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep1d",
+ xmSeparatorGadgetClass,
+ configpane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ save_button = XtVaCreateManagedWidget(langcode("PULDNCF008"),
+ xmPushButtonGadgetClass,
+ configpane,
+ XmNmnemonic, langcode_hotkey("PULDNCF008"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+
+//- Maps -------------------------------------------------------------
+
+ map_chooser_button = XtVaCreateManagedWidget(langcode("PULDNMP001"),
+ xmPushButtonGadgetClass,
+ mappane,
+ XmNmnemonic,langcode_hotkey("PULDNMP001"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(map_chooser_button, XmNactivateCallback,Map_chooser,NULL);
+
+ // Map Display Bookmarks
+ jump_button = XtVaCreateManagedWidget(langcode("PULDNMP012"),
+ xmPushButtonGadgetClass,
+ mappane,
+ XmNmnemonic,langcode_hotkey("PULDNMP012"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ locate_place_button = XtVaCreateManagedWidget(langcode("PULDNMP014"),
+ xmPushButtonGadgetClass,
+ mappane,
+ XmNmnemonic,langcode_hotkey("PULDNMP014"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ geocode_place_button = XtVaCreateManagedWidget(langcode("PULDNMP029"),
+ xmPushButtonGadgetClass,
+ mappane,
+ XmNmnemonic,langcode_hotkey("PULDNMP029"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ coordinate_calculator_button = XtVaCreateManagedWidget(langcode("COORD001"),
+ xmPushButtonGadgetClass,mappane,
+ XmNmnemonic, langcode_hotkey("COORD001"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ center_zoom_button=XtVaCreateManagedWidget(langcode("POPUPMA026"),
+ xmPushButtonGadgetClass, mappane,
+ XmNmnemonic, langcode_hotkey("POPUPMA026"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(center_zoom_button,XmNactivateCallback,Center_Zoom,NULL);
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ CAD_sub=XmCreatePulldownMenu(mappane,
+ "create_appshell CAD sub",
+ al,
+ ac);
+
+ // "Draw CAD Objects"
+ draw_CAD_objects_menu=XtVaCreateManagedWidget(langcode("POPUPMA029"),
+ xmCascadeButtonGadgetClass,
+ mappane,
+ XmNsubMenuId,CAD_sub,
+// XmNmnemonic,langcode_hotkey("POPUPMA029"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // "Draw Mode"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+// XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA031")); ac++;
+
+ // "Close Polygon"
+ CAD_close_polygon_menu_item=XtCreateManagedWidget(langcode("POPUPMA031"),
+ xmPushButtonGadgetClass,
+ CAD_sub,
+ al,
+ ac);
+ XtAddCallback(CAD_close_polygon_menu_item,XmNactivateCallback,Draw_CAD_Objects_close_polygon,NULL);
+ // disable the close polygon menu item if not in draw mode
+ if (draw_CAD_objects_flag==1)
+ XtSetSensitive(CAD_close_polygon_menu_item,TRUE);
+ if (draw_CAD_objects_flag==0)
+ XtSetSensitive(CAD_close_polygon_menu_item,FALSE);
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+// XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA032")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ // "Erase CAD Polygons"
+ CAD3=XtCreateManagedWidget(langcode("POPUPMA032"),
+ xmPushButtonGadgetClass,
+ CAD_sub,
+ al,
+ ac);
+ XtAddCallback(CAD3,XmNactivateCallback,Draw_CAD_Objects_erase_dialog,NULL);
+
+ // "List All CAD Polygons"
+ CAD4 = XtVaCreateManagedWidget(langcode("POPUPMA046"),
+ xmPushButtonGadgetClass,
+ CAD_sub,
+ XmNmnemonic,langcode_hotkey("POPUPMA046"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(CAD4,XmNactivateCallback,Draw_CAD_Objects_list_dialog,NULL);
+
+ // Toggles for CAD object information display on map
+ // Draw CAD Objects
+ cad_draw_button = XtVaCreateManagedWidget(langcode("POPUPMA047"),
+ xmToggleButtonGadgetClass,
+ CAD_sub,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(cad_draw_button,XmNvalueChangedCallback,CAD_draw_toggle,"CAD_draw_objects");
+ if (CAD_draw_objects==TRUE)
+ XmToggleButtonSetState(cad_draw_button,TRUE,FALSE);
+
+ // Draw CAD Labels
+ cad_show_label_button = XtVaCreateManagedWidget(langcode("POPUPMA048"),
+ xmToggleButtonGadgetClass,
+ CAD_sub,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(cad_show_label_button,XmNvalueChangedCallback,CAD_draw_toggle,"CAD_show_label");
+ if (CAD_show_label==TRUE)
+ XmToggleButtonSetState(cad_show_label_button,TRUE,FALSE);
+
+ // Draw CAD Probability
+ cad_show_probability_button = XtVaCreateManagedWidget(langcode("POPUPMA050"),
+ xmToggleButtonGadgetClass,
+ CAD_sub,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(cad_show_probability_button,XmNvalueChangedCallback,CAD_draw_toggle,"CAD_show_raw_probability");
+ if (CAD_show_raw_probability==TRUE)
+ XmToggleButtonSetState(cad_show_probability_button,TRUE,FALSE);
+
+ // Draw CAD Comments
+ cad_show_comment_button = XtVaCreateManagedWidget(langcode("POPUPMA049"),
+ xmToggleButtonGadgetClass,
+ CAD_sub,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(cad_show_comment_button,XmNvalueChangedCallback,CAD_draw_toggle,"CAD_show_comment");
+ if (CAD_show_comment==TRUE)
+ XmToggleButtonSetState(cad_show_comment_button,TRUE,FALSE);
+
+ // Draw CAD Size of Area
+ cad_show_area_button = XtVaCreateManagedWidget(langcode("POPUPMA051"),
+ xmToggleButtonGadgetClass,
+ CAD_sub,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(cad_show_area_button,XmNvalueChangedCallback,CAD_draw_toggle,"CAD_show_area");
+ if (CAD_show_area==TRUE)
+ XmToggleButtonSetState(cad_show_area_button,TRUE,FALSE);
+
+ (void)XtVaCreateManagedWidget("create_appshell sep2",
+ xmSeparatorGadgetClass,
+ mappane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ map_lock_pan_zoom_button = XtVaCreateManagedWidget(langcode("PULDNMP016"),
+ xmToggleButtonGadgetClass,
+ mappane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(map_lock_pan_zoom_button, XmNvalueChangedCallback, Map_lock_pan_zoom_toggle, "1");
+ if (map_lock_pan_zoom)
+ XmToggleButtonSetState(map_lock_pan_zoom_button, TRUE, FALSE);
+
+
+ map_disable_button = XtVaCreateManagedWidget(langcode("PULDNMP013"),
+ xmToggleButtonGadgetClass,
+ mappane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(map_disable_button, XmNvalueChangedCallback, Map_disable_toggle, "1");
+ if (disable_all_maps)
+ XmToggleButtonSetState(map_disable_button, TRUE, FALSE);
+
+
+ map_auto_button = XtVaCreateManagedWidget(langcode("PULDNMP002"),
+ xmToggleButtonGadgetClass,
+ mappane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(map_auto_button,XmNvalueChangedCallback,Map_auto_toggle,"1");
+ if (map_auto_maps)
+ XmToggleButtonSetState(map_auto_button,TRUE,FALSE);
+
+
+ map_auto_skip_raster_button = XtVaCreateManagedWidget(langcode("PULDNMP021"),
+ xmToggleButtonGadgetClass,
+ mappane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(map_auto_skip_raster_button,XmNvalueChangedCallback,Map_auto_skip_raster_toggle,"1");
+ if (auto_maps_skip_raster)
+ XmToggleButtonSetState(map_auto_skip_raster_button,TRUE,FALSE);
+ if (!map_auto_maps)
+ XtSetSensitive(map_auto_skip_raster_button,FALSE);
+
+
+ map_grid_button = XtVaCreateManagedWidget(langcode("PULDNMP003"),
+ xmToggleButtonGadgetClass,
+ mappane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(map_grid_button,XmNvalueChangedCallback,Grid_toggle,"1");
+ if (long_lat_grid)
+ XmToggleButtonSetState(map_grid_button,TRUE,FALSE);
+
+ // Enable Map Border
+ map_border_button = XtVaCreateManagedWidget(langcode("PULDNMP031"),
+ xmToggleButtonGadgetClass,
+ mappane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(map_border_button,XmNvalueChangedCallback,Map_border_toggle,"1");
+ if (draw_labeled_grid_border)
+ XmToggleButtonSetState(map_border_button,TRUE,FALSE);
+ if (!long_lat_grid)
+ XtSetSensitive(map_border_button,FALSE);
+ else
+ XtSetSensitive(map_border_button,TRUE);
+
+
+ map_levels_button = XtVaCreateManagedWidget(langcode("PULDNMP004"),
+ xmToggleButtonGadgetClass,
+ mappane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(map_levels_button,XmNvalueChangedCallback,Map_levels_toggle,"1");
+ if (map_color_levels)
+ XmToggleButtonSetState(map_levels_button,TRUE,FALSE);
+
+
+ map_labels_button = XtVaCreateManagedWidget(langcode("PULDNMP010"),
+ xmToggleButtonGadgetClass,
+ mappane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(map_labels_button,XmNvalueChangedCallback,Map_labels_toggle,"1");
+ if (map_labels)
+ XmToggleButtonSetState(map_labels_button,TRUE,FALSE);
+
+
+ map_fill_button = XtVaCreateManagedWidget(langcode("PULDNMP009"),
+ xmToggleButtonGadgetClass,
+ mappane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(map_fill_button,XmNvalueChangedCallback,Map_fill_toggle,"1");
+ if (map_color_fill)
+ XmToggleButtonSetState(map_fill_button,TRUE,FALSE);
+
+
+ map_wx_alerts_button = XtVaCreateManagedWidget(langcode("PULDNMP007"),
+ xmToggleButtonGadgetClass,
+ mappane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(map_wx_alerts_button,XmNvalueChangedCallback,Map_wx_alerts_toggle,"1");
+ if (!wx_alert_style)
+ XmToggleButtonSetState(map_wx_alerts_button,TRUE,FALSE);
+#ifndef HAVE_LIBSHP
+ // If we don't have Shapelib compiled in, grey-out the weather
+ // alerts button.
+ XtSetSensitive(map_wx_alerts_button, FALSE);
+#endif // HAVE_LIBSHP
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep2b",
+ xmSeparatorGadgetClass,
+ mappane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ (void)XtVaCreateManagedWidget("create_appshell sep2c",
+ xmSeparatorGadgetClass,
+ mappane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ map_config_pane = XmCreatePulldownMenu(mappane,
+ "map_config_pane",
+ al,
+ ac);
+
+ map_config_button = XtVaCreateManagedWidget(langcode("PULDNFI001"),
+ xmCascadeButtonGadgetClass,
+ mappane,
+ XmNsubMenuId,map_config_pane,
+ XmNmnemonic,langcode_hotkey("PULDNFI001"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ // These go into the map config submenu
+ Map_background_color_Pane = XmCreatePulldownMenu(map_config_pane,
+ "create_appshell map_background_color",
+ al,
+ ac);
+
+ map_background_button = XtVaCreateManagedWidget(langcode("PULDNMP005"),
+ xmCascadeButtonWidgetClass,
+ map_config_pane,
+ XmNsubMenuId, Map_background_color_Pane,
+ XmNmnemonic, langcode_hotkey("PULDNMP005"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_bgcolor[10] = XtVaCreateManagedWidget(langcode("PULDNMBC11"),
+ xmPushButtonGadgetClass,
+ Map_background_color_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMBC11"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_bgcolor[11] = XtVaCreateManagedWidget(langcode("PULDNMBC12"),
+ xmPushButtonGadgetClass,
+ Map_background_color_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMBC12"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_bgcolor[0] = XtVaCreateManagedWidget(langcode("PULDNMBC01"),
+ xmPushButtonGadgetClass,
+ Map_background_color_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMBC01"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_bgcolor[1] = XtVaCreateManagedWidget(langcode("PULDNMBC02"),
+ xmPushButtonGadgetClass,
+ Map_background_color_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMBC02"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_bgcolor[2] = XtVaCreateManagedWidget(langcode("PULDNMBC03"),
+ xmPushButtonGadgetClass,
+ Map_background_color_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMBC03"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_bgcolor[3] = XtVaCreateManagedWidget(langcode("PULDNMBC04"),
+ xmPushButtonGadgetClass,
+ Map_background_color_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMBC04"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_bgcolor[4] = XtVaCreateManagedWidget(langcode("PULDNMBC05"),
+ xmPushButtonGadgetClass,
+ Map_background_color_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMBC05"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_bgcolor[5] = XtVaCreateManagedWidget(langcode("PULDNMBC06"),
+ xmPushButtonGadgetClass,
+ Map_background_color_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMBC06"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_bgcolor[6] = XtVaCreateManagedWidget(langcode("PULDNMBC07"),
+ xmPushButtonGadgetClass,
+ Map_background_color_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMBC07"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_bgcolor[7] = XtVaCreateManagedWidget(langcode("PULDNMBC08"),
+ xmPushButtonGadgetClass,
+ Map_background_color_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMBC08"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_bgcolor[8] = XtVaCreateManagedWidget(langcode("PULDNMBC09"),
+ xmPushButtonGadgetClass,
+ Map_background_color_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMBC09"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_bgcolor[9] = XtVaCreateManagedWidget(langcode("PULDNMBC10"),
+ xmPushButtonGadgetClass,
+ Map_background_color_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMBC10"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtSetSensitive(map_bgcolor[map_background_color],FALSE);
+ XtAddCallback(map_bgcolor[10], XmNactivateCallback,Map_background,"10");
+ XtAddCallback(map_bgcolor[11], XmNactivateCallback,Map_background,"11");
+ XtAddCallback(map_bgcolor[0], XmNactivateCallback,Map_background,"0");
+ XtAddCallback(map_bgcolor[1], XmNactivateCallback,Map_background,"1");
+ XtAddCallback(map_bgcolor[2], XmNactivateCallback,Map_background,"2");
+ XtAddCallback(map_bgcolor[3], XmNactivateCallback,Map_background,"3");
+ XtAddCallback(map_bgcolor[4], XmNactivateCallback,Map_background,"4");
+ XtAddCallback(map_bgcolor[5], XmNactivateCallback,Map_background,"5");
+ XtAddCallback(map_bgcolor[6], XmNactivateCallback,Map_background,"6");
+ XtAddCallback(map_bgcolor[7], XmNactivateCallback,Map_background,"7");
+ XtAddCallback(map_bgcolor[8], XmNactivateCallback,Map_background,"8");
+ XtAddCallback(map_bgcolor[9], XmNactivateCallback,Map_background,"9");
+
+#if !defined(NO_GRAPHICS)
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ Raster_intensity_Pane = XmCreatePulldownMenu(map_config_pane,
+ "create_appshell raster_intensity",
+ al,
+ ac);
+
+ raster_intensity_button = XtVaCreateManagedWidget(langcode("PULDNMP008"),
+ xmCascadeButtonWidgetClass,
+ map_config_pane,
+ XmNsubMenuId,
+ Raster_intensity_Pane,
+ XmNmnemonic, langcode_hotkey("PULDNMP008"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ raster_intensity[0] = XtVaCreateManagedWidget("0%",
+ xmPushButtonGadgetClass,
+ Raster_intensity_Pane,
+ XmNmnemonic,"0%",
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ raster_intensity[1] = XtVaCreateManagedWidget("10%",
+ xmPushButtonGadgetClass,
+ Raster_intensity_Pane,
+ XmNmnemonic,"10%",
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ raster_intensity[2] = XtVaCreateManagedWidget("20%",
+ xmPushButtonGadgetClass,
+ Raster_intensity_Pane,
+ XmNmnemonic,"20%",
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ raster_intensity[3] = XtVaCreateManagedWidget("30%",
+ xmPushButtonGadgetClass,
+ Raster_intensity_Pane,
+ XmNmnemonic,"30%",
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ raster_intensity[4] = XtVaCreateManagedWidget("40%",
+ xmPushButtonGadgetClass,
+ Raster_intensity_Pane,
+ XmNmnemonic,"40%",
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ raster_intensity[5] = XtVaCreateManagedWidget("50%",
+ xmPushButtonGadgetClass,
+ Raster_intensity_Pane,
+ XmNmnemonic,"50%",
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ raster_intensity[6] = XtVaCreateManagedWidget("60%",
+ xmPushButtonGadgetClass,
+ Raster_intensity_Pane,
+ XmNmnemonic,"60%",
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ raster_intensity[7] = XtVaCreateManagedWidget("70%",
+ xmPushButtonGadgetClass,
+ Raster_intensity_Pane,
+ XmNmnemonic,"70%",
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ raster_intensity[8] = XtVaCreateManagedWidget("80%",
+ xmPushButtonGadgetClass,
+ Raster_intensity_Pane,
+ XmNmnemonic,"80%",
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ raster_intensity[9] = XtVaCreateManagedWidget("90%",
+ xmPushButtonGadgetClass,
+ Raster_intensity_Pane,
+ XmNmnemonic,"90%",
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ raster_intensity[10] = XtVaCreateManagedWidget("100%",
+ xmPushButtonGadgetClass,
+ Raster_intensity_Pane,
+ XmNmnemonic,"100%",
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtSetSensitive(raster_intensity[(int)(raster_map_intensity * 10.0)],FALSE);
+
+ //fprintf(stderr,"raster index = %d\n",
+ // (int)(raster_map_intensity * 10.01) );
+
+ XtAddCallback(raster_intensity[0], XmNactivateCallback,Raster_intensity,"0.0");
+ XtAddCallback(raster_intensity[1], XmNactivateCallback,Raster_intensity,"0.1");
+ XtAddCallback(raster_intensity[2], XmNactivateCallback,Raster_intensity,"0.2");
+ XtAddCallback(raster_intensity[3], XmNactivateCallback,Raster_intensity,"0.3");
+ XtAddCallback(raster_intensity[4], XmNactivateCallback,Raster_intensity,"0.4");
+ XtAddCallback(raster_intensity[5], XmNactivateCallback,Raster_intensity,"0.5");
+ XtAddCallback(raster_intensity[6], XmNactivateCallback,Raster_intensity,"0.6");
+ XtAddCallback(raster_intensity[7], XmNactivateCallback,Raster_intensity,"0.7");
+ XtAddCallback(raster_intensity[8], XmNactivateCallback,Raster_intensity,"0.8");
+ XtAddCallback(raster_intensity[9], XmNactivateCallback,Raster_intensity,"0.9");
+ XtAddCallback(raster_intensity[10], XmNactivateCallback,Raster_intensity,"1.0");
+#if defined(HAVE_MAGICK)
+ // Adjust Gamma Correction
+ gamma_adjust_button = XtVaCreateManagedWidget(langcode("GAMMA001"),
+ xmPushButtonWidgetClass, map_config_pane,
+ XmNmnemonic,langcode_hotkey("GAMMA001"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(gamma_adjust_button, XmNactivateCallback, Gamma_adjust, NULL);
+#endif // HAVE_MAGICK
+#endif // NO_GRAPHICS
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ Map_station_label_Pane = XmCreatePulldownMenu(map_config_pane,
+ "create_appshell map_station_label",
+ al,
+ ac);
+ map_station_label_button = XtVaCreateManagedWidget(langcode("PULDNMP006"),
+ xmCascadeButtonWidgetClass,
+ map_config_pane,
+ XmNsubMenuId, Map_station_label_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMP006"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_station_label0 = XtVaCreateManagedWidget(langcode("PULDNMSL01"),
+ xmPushButtonGadgetClass,
+ Map_station_label_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMSL01"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_station_label1 = XtVaCreateManagedWidget(langcode("PULDNMSL02"),
+ xmPushButtonGadgetClass,
+ Map_station_label_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMSL02"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_station_label2 = XtVaCreateManagedWidget(langcode("PULDNMSL03"),
+ xmPushButtonGadgetClass,
+ Map_station_label_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMSL03"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ sel3_switch(letter_style,map_station_label2,map_station_label1,map_station_label0);
+ XtAddCallback(map_station_label0, XmNactivateCallback,Map_station_label,"0");
+ XtAddCallback(map_station_label1, XmNactivateCallback,Map_station_label,"1");
+ XtAddCallback(map_station_label2, XmNactivateCallback,Map_station_label,"2");
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ Map_icon_outline_Pane = XmCreatePulldownMenu(map_config_pane,
+ "create_appshell map_icon_outline",
+ al,
+ ac);
+ map_icon_outline_button = XtVaCreateManagedWidget(langcode("PULDNMP026"),
+ xmCascadeButtonWidgetClass,
+ map_config_pane,
+ XmNsubMenuId, Map_icon_outline_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMP026"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_icon_outline0 = XtVaCreateManagedWidget(langcode("PULDNMIO01"),
+ xmPushButtonGadgetClass,
+ Map_icon_outline_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMIO01"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_icon_outline1 = XtVaCreateManagedWidget(langcode("PULDNMIO02"),
+ xmPushButtonGadgetClass,
+ Map_icon_outline_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMIO02"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_icon_outline2 = XtVaCreateManagedWidget(langcode("PULDNMIO03"),
+ xmPushButtonGadgetClass,
+ Map_icon_outline_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMIO03"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ map_icon_outline3 = XtVaCreateManagedWidget(langcode("PULDNMIO04"),
+ xmPushButtonGadgetClass,
+ Map_icon_outline_Pane,
+ XmNmnemonic,langcode_hotkey("PULDNMIO04"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ sel4_switch(icon_outline_style,map_icon_outline3,map_icon_outline2,map_icon_outline1,map_icon_outline0);
+ XtAddCallback(map_icon_outline0, XmNactivateCallback,Map_icon_outline,"0");
+ XtAddCallback(map_icon_outline1, XmNactivateCallback,Map_icon_outline,"1");
+ XtAddCallback(map_icon_outline2, XmNactivateCallback,Map_icon_outline,"2");
+ XtAddCallback(map_icon_outline3, XmNactivateCallback,Map_icon_outline,"3");
+
+
+#if defined(HAVE_MAGICK)
+ tiger_config_button= XtVaCreateManagedWidget(langcode("PULDNMP020"),
+ xmPushButtonGadgetClass,
+ map_config_pane,
+ XmNmnemonic,langcode_hotkey("PULDNMP020"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(tiger_config_button, XmNactivateCallback,Config_tiger,NULL);
+#endif // HAVE_MAGICK
+
+#ifdef HAVE_LIBGEOTIFF
+ drg_config_button= XtVaCreateManagedWidget(langcode("PULDNMP030"),
+ xmPushButtonGadgetClass,
+ map_config_pane,
+ XmNmnemonic,langcode_hotkey("PULDNMP030"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(drg_config_button, XmNactivateCallback,Config_DRG,NULL);
+#endif // HAVE_LIBGEOTIFF
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep2d",
+ xmSeparatorGadgetClass,
+ map_config_pane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+// Re-download Maps (Not from cache)
+ redownload_maps_button = XtVaCreateManagedWidget(langcode("PULDNMP027"),
+ xmPushButtonGadgetClass,
+ map_config_pane,
+ XmNmnemonic,langcode_hotkey("PULDNMP027"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(redownload_maps_button, XmNactivateCallback,Re_Download_Maps_Now,NULL);
+
+
+// Flush Entire Map Cache!
+ flush_map_cache_button = XtVaCreateManagedWidget(langcode("PULDNMP028"),
+ xmPushButtonGadgetClass,
+ map_config_pane,
+ XmNmnemonic,langcode_hotkey("PULDNMP028"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(flush_map_cache_button, XmNactivateCallback,Flush_Entire_Map_Queue,NULL);
+
+
+ //Index Maps on startup
+ index_maps_on_startup_button = XtVaCreateManagedWidget(langcode("PULDNMP022"),
+ xmToggleButtonGadgetClass,
+ map_config_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(index_maps_on_startup_button,XmNvalueChangedCallback,Index_maps_on_startup_toggle,"1");
+ if (index_maps_on_startup)
+ XmToggleButtonSetState(index_maps_on_startup_button,TRUE,FALSE);
+
+
+ map_indexer_button = XtVaCreateManagedWidget(langcode("PULDNMP023"),
+ xmPushButtonGadgetClass,
+ map_config_pane,
+ XmNmnemonic,langcode_hotkey("PULDNMP023"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ map_all_indexer_button = XtVaCreateManagedWidget(langcode("PULDNMP024"),
+ xmPushButtonGadgetClass,
+ map_config_pane,
+ XmNmnemonic,langcode_hotkey("PULDNMP024"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep2e",
+ xmSeparatorGadgetClass,
+ mappane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ map_pointer_menu_button = XtVaCreateManagedWidget(langcode("PULDNMP011"),
+ xmPushButtonGadgetClass,
+ mappane,
+ XmNmnemonic,langcode_hotkey("PULDNMP011"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+//- Stations Menu -----------------------------------------------------
+ locate_button = XtVaCreateManagedWidget(langcode("PULDNDP014"),
+ xmPushButtonGadgetClass,
+ stationspane,
+ XmNmnemonic,langcode_hotkey("PULDNDP014"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ track_button = XtVaCreateManagedWidget(langcode("PULDNDP001"),
+ xmPushButtonGadgetClass,
+ stationspane,
+ XmNmnemonic,langcode_hotkey("PULDNDP001"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(track_button, XmNactivateCallback,Track_station,NULL);
+
+ download_trail_button = XtVaCreateManagedWidget(langcode("PULDNDP022"),
+ xmPushButtonGadgetClass,
+ stationspane,
+ XmNmnemonic,langcode_hotkey("PULDNDP022"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(download_trail_button, XmNactivateCallback,Download_findu_trail,NULL);
+
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+
+ // Store Data pulldown/tearoff
+ store_data_pane = XmCreatePulldownMenu(stationspane,
+ "store_data_pane",
+ al,
+ ac);
+
+ // Export all >
+ store_data_button = XtVaCreateManagedWidget(langcode("PULDNDP055"),
+ xmCascadeButtonGadgetClass,
+ stationspane,
+ XmNsubMenuId, store_data_pane,
+ XmNmnemonic, langcode_hotkey("PULDNDP055"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Export to KML file
+ store_all_kml_button = XtVaCreateManagedWidget(langcode("PULDNDP056"),
+ xmPushButtonGadgetClass,
+ store_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(store_all_kml_button, XmNactivateCallback, store_all_kml_callback, NULL);
+
+#ifdef HAVE_DB
+ // store to open databases
+ store_all_db_button = XtVaCreateManagedWidget("Store to open databases",
+ xmPushButtonGadgetClass,
+ store_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ //XtAddCallback(store_all_db_button, XmNvalueChangedCallback, store_all_db_button_callback, "1");
+ XtSetSensitive(store_all_db_button,FALSE);
+#endif // HAVE_DB
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep3",
+ xmSeparatorGadgetClass,
+ stationspane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ // Filter Data pulldown/tearoff
+ filter_data_pane = XmCreatePulldownMenu(stationspane,
+ "filter_data_pane",
+ al,
+ ac);
+
+ filter_data_button = XtVaCreateManagedWidget(langcode("PULDNDP032"),
+ xmCascadeButtonGadgetClass,
+ stationspane,
+ XmNsubMenuId, filter_data_pane,
+ XmNmnemonic, langcode_hotkey("PULDNDP032"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ select_none_button = XtVaCreateManagedWidget(langcode("PULDNDP040"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_none_button, XmNvalueChangedCallback, Select_none_toggle, "1");
+ if (Select_.none)
+ XmToggleButtonSetState(select_none_button, TRUE, FALSE);
+
+
+ select_mine_button = XtVaCreateManagedWidget(langcode("PULDNDP041"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_mine_button, XmNvalueChangedCallback, Select_mine_toggle, "1");
+ if (Select_.mine)
+ XmToggleButtonSetState(select_mine_button, TRUE, FALSE);
+ if (Select_.none)
+ XtSetSensitive(select_mine_button, FALSE);
+
+
+ select_tnc_button = XtVaCreateManagedWidget(langcode("PULDNDP042"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_tnc_button, XmNvalueChangedCallback, Select_tnc_toggle, "1");
+ if (Select_.tnc)
+ XmToggleButtonSetState(select_tnc_button, TRUE, FALSE);
+ if (Select_.none)
+ XtSetSensitive(select_tnc_button, FALSE);
+
+
+ select_direct_button = XtVaCreateManagedWidget(langcode("PULDNDP027"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_direct_button, XmNvalueChangedCallback, Select_direct_toggle, "1");
+ if (Select_.direct)
+ XmToggleButtonSetState(select_direct_button, TRUE, FALSE);
+ if (!Select_.tnc || Select_.none)
+ XtSetSensitive(select_direct_button, FALSE);
+
+
+ select_via_digi_button = XtVaCreateManagedWidget(langcode("PULDNDP043"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_via_digi_button, XmNvalueChangedCallback, Select_via_digi_toggle, "1");
+ if (Select_.via_digi)
+ XmToggleButtonSetState(select_via_digi_button, TRUE, FALSE);
+ if (!Select_.tnc || Select_.none)
+ XtSetSensitive(select_via_digi_button, FALSE);
+
+
+ select_net_button = XtVaCreateManagedWidget(langcode("PULDNDP034"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_net_button, XmNvalueChangedCallback, Select_net_toggle, "1");
+ if (Select_.net)
+ XmToggleButtonSetState(select_net_button, TRUE, FALSE);
+ if (Select_.none)
+ XtSetSensitive(select_net_button, FALSE);
+
+
+ // "Select Tactical Calls Only"
+ select_tactical_button = XtVaCreateManagedWidget(langcode("PULDNDP051"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_tactical_button, XmNvalueChangedCallback, Select_tactical_toggle, "1");
+ if (Select_.tactical)
+ XmToggleButtonSetState(select_tactical_button, TRUE, FALSE);
+ if (Select_.none)
+ XtSetSensitive(select_tactical_button, FALSE);
+
+
+ select_old_data_button = XtVaCreateManagedWidget(langcode("PULDNDP019"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_old_data_button, XmNvalueChangedCallback, Select_old_data_toggle, "1");
+ if (Select_.old_data)
+ XmToggleButtonSetState(select_old_data_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(select_old_data_button, FALSE);
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep3a",
+ xmSeparatorGadgetClass,
+ filter_data_pane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ select_stations_button = XtVaCreateManagedWidget(langcode("PULDNDP044"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_stations_button, XmNvalueChangedCallback,
+ Select_stations_toggle, "1");
+ if (Select_.stations)
+ XmToggleButtonSetState(select_stations_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(select_stations_button, FALSE);
+
+
+ select_fixed_stations_button = XtVaCreateManagedWidget(langcode("PULDNDP028"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_fixed_stations_button, XmNvalueChangedCallback,
+ Select_fixed_stations_toggle, "1");
+ if (Select_.fixed_stations)
+ XmToggleButtonSetState(select_fixed_stations_button, TRUE, FALSE);
+ if (!Select_.stations || no_data_selected())
+ XtSetSensitive(select_fixed_stations_button, FALSE);
+
+
+ select_moving_stations_button = XtVaCreateManagedWidget(langcode("PULDNDP029"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_moving_stations_button, XmNvalueChangedCallback,
+ Select_moving_stations_toggle, "1");
+ if (Select_.moving_stations)
+ XmToggleButtonSetState(select_moving_stations_button, TRUE, FALSE);
+ if (!Select_.stations || no_data_selected())
+ XtSetSensitive(select_moving_stations_button, FALSE);
+
+
+ select_weather_stations_button = XtVaCreateManagedWidget(langcode("PULDNDP030"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_weather_stations_button, XmNvalueChangedCallback,
+ Select_weather_stations_toggle, "1");
+ if (Select_.weather_stations)
+ XmToggleButtonSetState(select_weather_stations_button, TRUE, FALSE);
+ if (!Select_.stations || no_data_selected())
+ XtSetSensitive(select_weather_stations_button, FALSE);
+
+
+ select_CWOP_wx_stations_button = XtVaCreateManagedWidget(langcode("PULDNDP053"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_CWOP_wx_stations_button, XmNvalueChangedCallback,
+ Select_CWOP_wx_stations_toggle, "1");
+ if (Select_.CWOP_wx_stations)
+ XmToggleButtonSetState(select_CWOP_wx_stations_button, TRUE, FALSE);
+ if (!Select_.stations || no_data_selected() || !Select_.weather_stations)
+ XtSetSensitive(select_CWOP_wx_stations_button, FALSE);
+ else
+ XtSetSensitive(select_CWOP_wx_stations_button, TRUE);
+
+
+ select_objects_button = XtVaCreateManagedWidget(langcode("PULDNDP045"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_objects_button, XmNvalueChangedCallback,
+ Select_objects_toggle, "1");
+ if (Select_.objects)
+ XmToggleButtonSetState(select_objects_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(select_objects_button, FALSE);
+
+
+ select_weather_objects_button = XtVaCreateManagedWidget(langcode("PULDNDP026"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_weather_objects_button, XmNvalueChangedCallback,
+ Select_weather_objects_toggle, "1");
+ if (Select_.weather_objects)
+ XmToggleButtonSetState(select_weather_objects_button, TRUE, FALSE);
+ if (!Select_.objects || no_data_selected())
+ XtSetSensitive(select_weather_objects_button, FALSE);
+
+
+ select_gauge_objects_button = XtVaCreateManagedWidget(langcode("PULDNDP039"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_gauge_objects_button, XmNvalueChangedCallback,
+ Select_gauge_objects_toggle, "1");
+ if (Select_.gauge_objects)
+ XmToggleButtonSetState(select_gauge_objects_button, TRUE, FALSE);
+ if (!Select_.objects || no_data_selected())
+ XtSetSensitive(select_gauge_objects_button, FALSE);
+
+
+ select_other_objects_button = XtVaCreateManagedWidget(langcode("PULDNDP031"),
+ xmToggleButtonGadgetClass,
+ filter_data_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(select_other_objects_button, XmNvalueChangedCallback,
+ Select_other_objects_toggle, "1");
+ if (Select_.other_objects)
+ XmToggleButtonSetState(select_other_objects_button, TRUE, FALSE);
+ if (!Select_.objects || no_data_selected())
+ XtSetSensitive(select_other_objects_button, FALSE);
+
+
+ // End of Data Filtering
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ // Displayed Info Filtering
+ filter_display_pane = XmCreatePulldownMenu(stationspane,
+ "filter_display_pane",
+ al,
+ ac);
+
+ filter_display_button = XtVaCreateManagedWidget(langcode("PULDNDP033"),
+ xmCascadeButtonGadgetClass,
+ stationspane,
+ XmNsubMenuId, filter_display_pane,
+ XmNmnemonic, langcode_hotkey("PULDNDP033"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ display_callsign_button = XtVaCreateManagedWidget(langcode("PULDNDP010"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_callsign_button, XmNvalueChangedCallback, Display_callsign_toggle, "1");
+ if (Display_.callsign)
+ XmToggleButtonSetState(display_callsign_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(display_callsign_button, FALSE);
+
+ display_label_all_trackpoints_button = XtVaCreateManagedWidget(langcode("PULDNDP052"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_label_all_trackpoints_button, XmNvalueChangedCallback, Display_label_all_trackpoints_toggle, "1");
+ if (Display_.label_all_trackpoints)
+ XmToggleButtonSetState(display_label_all_trackpoints_button, TRUE, FALSE);
+ if (!Display_.callsign || no_data_selected())
+ XtSetSensitive(display_label_all_trackpoints_button, FALSE);
+
+ display_symbol_button = XtVaCreateManagedWidget(langcode("PULDNDP012"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_symbol_button, XmNvalueChangedCallback, Display_symbol_toggle, "1");
+ if (Display_.symbol)
+ XmToggleButtonSetState(display_symbol_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(display_symbol_button, FALSE);
+
+
+ display_symbol_rotate_button = XtVaCreateManagedWidget(langcode("PULDNDP011"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_symbol_rotate_button, XmNvalueChangedCallback, Display_symbol_rotate_toggle, "1");
+ if (Display_.symbol_rotate)
+ XmToggleButtonSetState(display_symbol_rotate_button, TRUE, FALSE);
+ if (!Display_.symbol || no_data_selected())
+ XtSetSensitive(display_symbol_rotate_button, FALSE);
+
+
+ display_trail_button = XtVaCreateManagedWidget(langcode("PULDNDP007"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_trail_button, XmNvalueChangedCallback, Display_trail_toggle, "1");
+ if (Display_.trail)
+ XmToggleButtonSetState(display_trail_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(display_trail_button, FALSE);
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep3b",
+ xmSeparatorGadgetClass,
+ filter_display_pane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ display_course_button = XtVaCreateManagedWidget(langcode("PULDNDP003"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_course_button, XmNvalueChangedCallback, Display_course_toggle, "1");
+ if (Display_.course)
+ XmToggleButtonSetState(display_course_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(display_course_button, FALSE);
+
+
+ display_speed_button = XtVaCreateManagedWidget(langcode("PULDNDP004"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_speed_button, XmNvalueChangedCallback, Display_speed_toggle, "1");
+ if (Display_.speed)
+ XmToggleButtonSetState(display_speed_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(display_speed_button, FALSE);
+
+
+ display_speed_short_button = XtVaCreateManagedWidget(langcode("PULDNDP017"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_speed_short_button, XmNvalueChangedCallback, Display_speed_short_toggle, "1");
+ if (Display_.speed_short)
+ XmToggleButtonSetState(display_speed_short_button, TRUE, FALSE);
+ if (!Display_.speed || no_data_selected())
+ XtSetSensitive(display_speed_short_button, FALSE);
+
+
+ display_altitude_button = XtVaCreateManagedWidget(langcode("PULDNDP002"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_altitude_button, XmNvalueChangedCallback, Display_altitude_toggle, "1");
+ if (Display_.altitude)
+ XmToggleButtonSetState(display_altitude_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(display_altitude_button, FALSE);
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep3c",
+ xmSeparatorGadgetClass,
+ filter_display_pane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ display_weather_button = XtVaCreateManagedWidget(langcode("PULDNDP009"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_weather_button, XmNvalueChangedCallback, Display_weather_toggle, "1");
+ if (Display_.weather)
+ XmToggleButtonSetState(display_weather_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(display_weather_button, FALSE);
+
+
+ display_weather_text_button = XtVaCreateManagedWidget(langcode("PULDNDP046"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_weather_text_button, XmNvalueChangedCallback, Display_weather_text_toggle, "1");
+ if (Display_.weather_text)
+ XmToggleButtonSetState(display_weather_text_button, TRUE, FALSE);
+ if (!Display_.weather || no_data_selected())
+ XtSetSensitive(display_weather_text_button, FALSE);
+
+
+ display_temperature_only_button = XtVaCreateManagedWidget(langcode("PULDNDP018"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_temperature_only_button, XmNvalueChangedCallback, Display_temperature_only_toggle, "1");
+ if (Display_.temperature_only)
+ XmToggleButtonSetState(display_temperature_only_button, TRUE, FALSE);
+ if (!Display_.weather || !Display_.weather_text || no_data_selected())
+ XtSetSensitive(display_temperature_only_button, FALSE);
+
+
+ display_wind_barb_button = XtVaCreateManagedWidget(langcode("PULDNDP047"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_wind_barb_button, XmNvalueChangedCallback, Display_wind_barb_toggle, "1");
+ if (Display_.wind_barb)
+ XmToggleButtonSetState(display_wind_barb_button, TRUE, FALSE);
+ if (!Display_.weather || no_data_selected())
+ XtSetSensitive(display_wind_barb_button, FALSE);
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep3d",
+ xmSeparatorGadgetClass,
+ filter_display_pane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ display_aloha_circle_button = XtVaCreateManagedWidget(langcode("PULDNDP054"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_aloha_circle_button, XmNvalueChangedCallback, Display_aloha_circle_toggle, "1");
+ if (Display_.aloha_circle)
+ XmToggleButtonSetState(display_aloha_circle_button, TRUE, FALSE);
+
+
+ display_ambiguity_button = XtVaCreateManagedWidget(langcode("PULDNDP013"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_ambiguity_button, XmNvalueChangedCallback, Display_ambiguity_toggle, "1");
+ if (Display_.ambiguity)
+ XmToggleButtonSetState(display_ambiguity_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(display_ambiguity_button, FALSE);
+
+
+ display_phg_button = XtVaCreateManagedWidget(langcode("PULDNDP008"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_phg_button, XmNvalueChangedCallback, Display_phg_toggle, "1");
+ if (Display_.phg)
+ XmToggleButtonSetState(display_phg_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(display_phg_button, FALSE);
+
+
+ display_default_phg_button = XtVaCreateManagedWidget(langcode("PULDNDP021"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_default_phg_button, XmNvalueChangedCallback, Display_default_phg_toggle, "1");
+ if (Display_.default_phg)
+ XmToggleButtonSetState(display_default_phg_button, TRUE, FALSE);
+ if (!Display_.phg || no_data_selected())
+ XtSetSensitive(display_default_phg_button, FALSE);
+
+
+ display_phg_of_moving_button = XtVaCreateManagedWidget(langcode("PULDNDP020"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_phg_of_moving_button, XmNvalueChangedCallback, Display_phg_of_moving_toggle, "1");
+ if (Display_.phg_of_moving)
+ XmToggleButtonSetState(display_phg_of_moving_button, TRUE, FALSE);
+ if (!Display_.phg || no_data_selected())
+ XtSetSensitive(display_phg_of_moving_button, FALSE);
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep3e",
+ xmSeparatorGadgetClass,
+ filter_display_pane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ display_df_data_button = XtVaCreateManagedWidget(langcode("PULDNDP023"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_df_data_button, XmNvalueChangedCallback, Display_df_data_toggle, "1");
+ if (Display_.df_data)
+ XmToggleButtonSetState(display_df_data_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(display_df_data_button, FALSE);
+
+ display_df_beamwidth_data_button = XtVaCreateManagedWidget(langcode("PULDNDP123"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_df_beamwidth_data_button, XmNvalueChangedCallback, Display_df_beamwidth_data_toggle, "1");
+ if (Display_.df_beamwidth_data)
+ XmToggleButtonSetState(display_df_beamwidth_data_button, TRUE, FALSE);
+ if (!Display_.df_data || no_data_selected())
+ XtSetSensitive(display_df_beamwidth_data_button, FALSE);
+
+ display_df_bearing_data_button = XtVaCreateManagedWidget(langcode("PULDNDP223"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_df_bearing_data_button, XmNvalueChangedCallback, Display_df_bearing_data_toggle, "1");
+ if (Display_.df_bearing_data)
+ XmToggleButtonSetState(display_df_bearing_data_button, TRUE, FALSE);
+ if (!Display_.df_data || no_data_selected())
+ XtSetSensitive(display_df_bearing_data_button, FALSE);
+
+ (void)XtVaCreateManagedWidget("create_appshell sep3e",
+ xmSeparatorGadgetClass,
+ filter_display_pane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ display_dr_data_button = XtVaCreateManagedWidget(langcode("PULDNDP035"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_dr_data_button, XmNvalueChangedCallback, Display_dr_data_toggle, "1");
+ if (Display_.dr_data)
+ XmToggleButtonSetState(display_dr_data_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(display_dr_data_button, FALSE);
+
+
+ display_dr_arc_button = XtVaCreateManagedWidget(langcode("PULDNDP036"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_dr_arc_button, XmNvalueChangedCallback, Display_dr_arc_toggle, "1");
+ if (Display_.dr_arc)
+ XmToggleButtonSetState(display_dr_arc_button, TRUE, FALSE);
+ if (!Display_.dr_data || no_data_selected())
+ XtSetSensitive(display_dr_arc_button, FALSE);
+
+
+ display_dr_course_button = XtVaCreateManagedWidget(langcode("PULDNDP037"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_dr_course_button, XmNvalueChangedCallback, Display_dr_course_toggle, "1");
+ if (Display_.dr_course)
+ XmToggleButtonSetState(display_dr_course_button, TRUE, FALSE);
+ if (!Display_.dr_data || no_data_selected())
+ XtSetSensitive(display_dr_course_button, FALSE);
+
+
+ display_dr_symbol_button = XtVaCreateManagedWidget(langcode("PULDNDP038"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_dr_symbol_button, XmNvalueChangedCallback, Display_dr_symbol_toggle, "1");
+ if (Display_.dr_symbol)
+ XmToggleButtonSetState(display_dr_symbol_button, TRUE, FALSE);
+ if (!Display_.dr_data || no_data_selected())
+ XtSetSensitive(display_dr_symbol_button, FALSE);
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep3f",
+ xmSeparatorGadgetClass,
+ filter_display_pane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ display_dist_bearing_button = XtVaCreateManagedWidget(langcode("PULDNDP005"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_dist_bearing_button, XmNvalueChangedCallback, Display_dist_bearing_toggle, "1");
+ if (Display_.dist_bearing)
+ XmToggleButtonSetState(display_dist_bearing_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(display_dist_bearing_button, FALSE);
+
+
+ display_last_heard_button = XtVaCreateManagedWidget(langcode("PULDNDP024"),
+ xmToggleButtonGadgetClass,
+ filter_display_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(display_last_heard_button, XmNvalueChangedCallback, Display_last_heard_toggle, "1");
+ if (Display_.last_heard)
+ XmToggleButtonSetState(display_last_heard_button, TRUE, FALSE);
+ if (no_data_selected())
+ XtSetSensitive(display_last_heard_button, FALSE);
+
+
+ // End of Displayed Info Filtering
+
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep3g",
+ xmSeparatorGadgetClass,
+ stationspane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ (void)XtVaCreateManagedWidget("create_appshell sep3h",
+ xmSeparatorGadgetClass,
+ stationspane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ station_config_pane = XmCreatePulldownMenu(stationspane,
+ "stations_config_pane",
+ al,
+ ac);
+
+ station_config_button = XtVaCreateManagedWidget(langcode("PULDNFI001"),
+ xmCascadeButtonGadgetClass,
+ stationspane,
+ XmNsubMenuId,station_config_pane,
+ XmNmnemonic,langcode_hotkey("PULDNFI001"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ object_history_refresh_button = XtVaCreateManagedWidget(langcode("PULDNDP048"),
+ xmPushButtonGadgetClass,
+ station_config_pane,
+ XmNmnemonic,langcode_hotkey("PULDNDP048"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ object_history_clear_button = XtVaCreateManagedWidget(langcode("PULDNDP025"),
+ xmPushButtonGadgetClass,
+ station_config_pane,
+ XmNmnemonic,langcode_hotkey("PULDNDP025"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // "Clear All Tactical Calls"
+ tactical_clear_button = XtVaCreateManagedWidget(langcode("PULDNDP049"),
+ xmPushButtonGadgetClass,
+ station_config_pane,
+// XmNmnemonic,langcode_hotkey("PULDNDP049"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ // "Clear Tactical Call History"
+ tactical_history_clear_button = XtVaCreateManagedWidget(langcode("PULDNDP050"),
+ xmPushButtonGadgetClass,
+ station_config_pane,
+// XmNmnemonic,langcode_hotkey("PULDNDP050"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ tracks_clear_button = XtVaCreateManagedWidget(langcode("PULDNDP016"),
+ xmPushButtonGadgetClass,
+ station_config_pane,
+ XmNmnemonic,langcode_hotkey("PULDNDP016"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ station_clear_button = XtVaCreateManagedWidget(langcode("PULDNDP015"),
+ xmPushButtonGadgetClass,
+ station_config_pane,
+ XmNmnemonic,langcode_hotkey("PULDNDP015"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+//--------------------------------------------------------------------
+
+ /* Messages */
+ send_message_to_button = XtVaCreateManagedWidget(langcode("PULDNMG001"),
+ xmPushButtonGadgetClass,
+ messagepane,
+ XmNmnemonic,langcode_hotkey("PULDNMG001"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ show_pending_messages_button = XtVaCreateManagedWidget(langcode("PULDNMG007"),
+ xmPushButtonGadgetClass,
+ messagepane,
+ XmNmnemonic,langcode_hotkey("PULDNMG007"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ open_messages_group_button = XtVaCreateManagedWidget(langcode("PULDNMG002"),
+ xmPushButtonGadgetClass,
+ messagepane,
+ XmNmnemonic,langcode_hotkey("PULDNMG002"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ clear_messages_button= XtVaCreateManagedWidget(langcode("PULDNMG003"),
+ xmPushButtonGadgetClass,
+ messagepane,
+ XmNmnemonic,langcode_hotkey("PULDNMG003"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ (void)XtVaCreateManagedWidget("create_appshell sep4",
+ xmSeparatorGadgetClass,
+ messagepane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ General_q_button = XtVaCreateManagedWidget(langcode("PULDQUS001"),
+ xmPushButtonGadgetClass,
+ messagepane,
+ XmNmnemonic,langcode_hotkey("PULDQUS001"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ IGate_q_button = XtVaCreateManagedWidget(langcode("PULDQUS002"),
+ xmPushButtonGadgetClass,
+ messagepane,
+ XmNmnemonic,langcode_hotkey("PULDQUS002"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ WX_q_button = XtVaCreateManagedWidget(langcode("PULDQUS003"),
+ xmPushButtonGadgetClass,
+ messagepane,
+ XmNmnemonic,langcode_hotkey("PULDQUS003"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ (void)XtVaCreateManagedWidget("create_appshell sep4a",
+ xmSeparatorGadgetClass,
+ messagepane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ auto_msg_set_button = XtVaCreateManagedWidget(langcode("PULDNMG004"),
+ xmPushButtonGadgetClass,
+ messagepane,
+ XmNmnemonic,langcode_hotkey("PULDNMG004"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ auto_msg_toggle = XtVaCreateManagedWidget(langcode("PULDNMG005"),
+ xmToggleButtonGadgetClass,
+ messagepane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(auto_msg_toggle,XmNvalueChangedCallback,Auto_msg_toggle,"1");
+
+ (void)XtVaCreateManagedWidget("create_appshell sep5",
+ xmSeparatorGadgetClass,
+ messagepane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ satellite_msg_ack_toggle = XtVaCreateManagedWidget(langcode("PULDNMG006"),
+ xmToggleButtonGadgetClass,
+ messagepane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(satellite_msg_ack_toggle,XmNvalueChangedCallback,Satellite_msg_ack_toggle,"1");
+
+
+
+ /* Interface */
+ iface_connect_button = XtVaCreateManagedWidget(langcode("PULDNTNT04"),
+ xmPushButtonGadgetClass,
+ ifacepane,
+ XmNmnemonic,langcode_hotkey("PULDNTNT04"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ (void)XtVaCreateManagedWidget("create_appshell sep5a",
+ xmSeparatorGadgetClass,
+ ifacepane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ transmit_disable_toggle = XtVaCreateManagedWidget(langcode("PULDNTNT03"),
+ xmToggleButtonGadgetClass,
+ ifacepane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(transmit_disable_toggle,XmNvalueChangedCallback,Transmit_disable_toggle,"1");
+ if (transmit_disable)
+ XmToggleButtonSetState(transmit_disable_toggle,TRUE,FALSE);
+
+
+ posit_tx_disable_toggle = XtVaCreateManagedWidget(langcode("PULDNTNT05"),
+ xmToggleButtonGadgetClass,
+ ifacepane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(posit_tx_disable_toggle,XmNvalueChangedCallback,Posit_tx_disable_toggle,"1");
+ if (posit_tx_disable)
+ XmToggleButtonSetState(posit_tx_disable_toggle,TRUE,FALSE);
+ if (transmit_disable)
+ XtSetSensitive(posit_tx_disable_toggle,FALSE);
+
+
+ object_tx_disable_toggle = XtVaCreateManagedWidget(langcode("PULDNTNT06"),
+ xmToggleButtonGadgetClass,
+ ifacepane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(object_tx_disable_toggle,XmNvalueChangedCallback,Object_tx_disable_toggle,"1");
+ if (object_tx_disable)
+ XmToggleButtonSetState(object_tx_disable_toggle,TRUE,FALSE);
+ if (transmit_disable)
+ XtSetSensitive(object_tx_disable_toggle,FALSE);
+
+
+ server_port_toggle = XtVaCreateManagedWidget(langcode("PULDNTNT11"),
+ xmToggleButtonGadgetClass,
+ ifacepane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(server_port_toggle,XmNvalueChangedCallback,Server_port_toggle,"1");
+ if (enable_server_port)
+ XmToggleButtonSetState(server_port_toggle,TRUE,FALSE);
+
+
+ (void)XtVaCreateManagedWidget("create_appshell sep5b",
+ xmSeparatorGadgetClass,
+ ifacepane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ iface_transmit_now = XtVaCreateManagedWidget(langcode("PULDNTNT01"),
+ xmPushButtonGadgetClass,
+ ifacepane,
+ XmNmnemonic,langcode_hotkey("PULDNTNT01"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ if (transmit_disable)
+ XtSetSensitive(iface_transmit_now,FALSE);
+
+#ifdef HAVE_GPSMAN
+ Fetch_gps_track = XtVaCreateManagedWidget(langcode("PULDNTNT07"),
+ xmPushButtonGadgetClass,
+ ifacepane,
+ XmNmnemonic,langcode_hotkey("PULDNTNT07"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ Fetch_gps_route = XtVaCreateManagedWidget(langcode("PULDNTNT08"),
+ xmPushButtonGadgetClass,
+ ifacepane,
+ XmNmnemonic,langcode_hotkey("PULDNTNT08"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ Fetch_gps_waypoints = XtVaCreateManagedWidget(langcode("PULDNTNT09"),
+ xmPushButtonGadgetClass,
+ ifacepane,
+ XmNmnemonic,langcode_hotkey("PULDNTNT09"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+/*
+ Send_gps_track = XtVaCreateManagedWidget(langcode("Send_Tr"),
+ xmPushButtonGadgetClass,
+ ifacepane,
+ XmNmnemonic,langcode_hotkey("Send_Tr"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ Send_gps_route = XtVaCreateManagedWidget(langcode("Send_Rt"),
+ xmPushButtonGadgetClass,
+ ifacepane,
+ XmNmnemonic,langcode_hotkey("Send_Rt"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ Send_gps_waypoints = XtVaCreateManagedWidget(langcode("Send_Wp"),
+ xmPushButtonGadgetClass,
+ ifacepane,
+ XmNmnemonic,langcode_hotkey("Send_Wp"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+*/
+
+ Fetch_RINO_waypoints = XtVaCreateManagedWidget(langcode("PULDNTNT10"),
+ xmPushButtonGadgetClass,
+ ifacepane,
+ XmNmnemonic,langcode_hotkey("PULDNTNT10"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+#endif // HAVE_GPSMAN
+
+ /* Help*/
+ help_about = XtVaCreateManagedWidget(langcode("PULDNHEL01"),
+ xmPushButtonGadgetClass,
+ helppane,
+ XmNmnemonic,langcode_hotkey("PULDNHEL01"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ help_help = XtVaCreateManagedWidget(langcode("PULDNHEL02"),
+ xmPushButtonGadgetClass,
+ helppane,
+ XmNmnemonic,langcode_hotkey("PULDNHEL02"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ (void)XtVaCreateManagedWidget("create_appshell sephelp",
+ xmSeparatorGadgetClass,
+ helppane,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ help_emergency_pane = XmCreatePulldownMenu(helppane,
+ "help_emergency_pane",
+ al,
+ ac);
+
+ help_emergency_button = XtVaCreateManagedWidget(langcode("PULDNHEL03"),
+ xmCascadeButtonGadgetClass,
+ helppane,
+ XmNsubMenuId,help_emergency_pane,
+ XmNmnemonic,langcode_hotkey("PULDNHEL03"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ emergency_beacon_toggle = XtVaCreateManagedWidget(langcode("PULDNHEL04"),
+ xmToggleButtonGadgetClass,
+ help_emergency_pane,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(emergency_beacon_toggle,XmNvalueChangedCallback,Emergency_beacon_toggle,"1");
+ if (emergency_beacon)
+ XmToggleButtonSetState(emergency_beacon_toggle,TRUE,FALSE);
+
+
+ /* view */
+ XtAddCallback(stations_button, XmNactivateCallback,Station_List,"0");
+ XtAddCallback(mobile_button, XmNactivateCallback,Station_List,"1");
+ XtAddCallback(weather_button, XmNactivateCallback,Station_List,"2");
+ XtAddCallback(localstations_button, XmNactivateCallback,Station_List,"3");
+ XtAddCallback(laststations_button, XmNactivateCallback,Station_List,"4");
+ XtAddCallback(objectstations_button,XmNactivateCallback,Station_List,"5");
+ XtAddCallback(objectmystations_button,XmNactivateCallback,Station_List,"6");
+ XtAddCallback(CAD1,XmNactivateCallback,Draw_CAD_Objects_list_dialog,NULL);
+
+ /* button callbacks */
+ XtAddCallback(General_q_button, XmNactivateCallback,General_query,"");
+ XtAddCallback(IGate_q_button, XmNactivateCallback,IGate_query,NULL);
+ XtAddCallback(WX_q_button, XmNactivateCallback,WX_query,NULL);
+ XtAddCallback(station_clear_button, XmNactivateCallback,Stations_Clear,NULL);
+ XtAddCallback(tracks_clear_button, XmNactivateCallback,Tracks_All_Clear,NULL);
+ XtAddCallback(object_history_refresh_button, XmNactivateCallback,Object_History_Refresh,NULL);
+ XtAddCallback(object_history_clear_button, XmNactivateCallback,Object_History_Clear,NULL);
+ XtAddCallback(tactical_clear_button, XmNactivateCallback,Tactical_Callsign_Clear,NULL);
+ XtAddCallback(tactical_history_clear_button, XmNactivateCallback,Tactical_Callsign_History_Clear,NULL);
+ XtAddCallback(exit_button, XmNactivateCallback,Menu_Quit,NULL);
+
+ XtAddCallback(defaults_button, XmNactivateCallback,Configure_defaults,NULL);
+ XtAddCallback(timing_button, XmNactivateCallback,Configure_timing,NULL);
+ XtAddCallback(coordinates_button, XmNactivateCallback,Configure_coordinates,NULL);
+ XtAddCallback(aa_button, XmNactivateCallback,Configure_audio_alarms,NULL);
+ XtAddCallback(speech_button, XmNactivateCallback,Configure_speech,NULL);
+ XtAddCallback(smart_beacon_button, XmNactivateCallback,Smart_Beacon,NULL);
+ XtAddCallback(map_indexer_button, XmNactivateCallback,Index_Maps_Now,NULL);
+ XtAddCallback(map_all_indexer_button,XmNactivateCallback,Index_Maps_Now,"1");
+ XtAddCallback(station_button, XmNactivateCallback,Configure_station,NULL);
+
+ XtAddCallback(help_about, XmNactivateCallback,Help_About,NULL);
+ XtAddCallback(help_help, XmNactivateCallback,Help_Index,NULL);
+
+ /* TNC */
+ XtAddCallback(iface_transmit_now, XmNactivateCallback,TNC_Transmit_now,NULL);
+
+#ifdef HAVE_GPSMAN
+ XtAddCallback(Fetch_gps_track, XmNactivateCallback,GPS_operations,"1");
+ XtAddCallback(Fetch_gps_route, XmNactivateCallback,GPS_operations,"2");
+ XtAddCallback(Fetch_gps_waypoints, XmNactivateCallback,GPS_operations,"3");
+// XtAddCallback(Send_gps_track, XmNactivateCallback,GPS_operations,"4");
+// XtAddCallback(Send_gps_route, XmNactivateCallback,GPS_operations,"5");
+// XtAddCallback(Send_gps_waypoints, XmNactivateCallback,GPS_operations,"6");
+ XtAddCallback(Fetch_RINO_waypoints, XmNactivateCallback,GPS_operations,"7");
+#endif // HAVE_GPSMAN
+
+ XtAddCallback(auto_msg_set_button,XmNactivateCallback,Auto_msg_set,NULL);
+
+ XtAddCallback(iface_connect_button, XmNactivateCallback,control_interface,NULL);
+
+ XtAddCallback(open_file_button, XmNactivateCallback,Read_File_Selection,NULL);
+
+ XtAddCallback(bullet_button, XmNactivateCallback,Bulletins,NULL);
+ XtAddCallback(packet_data_button, XmNactivateCallback,Display_data,NULL);
+ XtAddCallback(locate_button, XmNactivateCallback,Locate_station,NULL);
+ XtAddCallback(alert_button, XmNactivateCallback,Display_Wx_Alert,NULL);
+ XtAddCallback(view_messages_button, XmNactivateCallback,view_all_messages,NULL);
+ XtAddCallback(gps_status_button,XmNactivateCallback,view_gps_status,NULL);
+
+ XtAddCallback(map_pointer_menu_button, XmNactivateCallback,menu_link_for_mouse_menu,NULL);
+
+ XtAddCallback(wx_station_button, XmNactivateCallback,WX_station,NULL);
+ XtAddCallback(jump_button, XmNactivateCallback, Jump_location, NULL);
+ XtAddCallback(locate_place_button, XmNactivateCallback,Locate_place,NULL);
+ XtAddCallback(geocode_place_button, XmNactivateCallback,Geocoder_place,NULL);
+ XtAddCallback(coordinate_calculator_button, XmNactivateCallback,Coordinate_calc,"");
+
+ XtAddCallback(send_message_to_button, XmNactivateCallback,Send_message,NULL);
+ XtAddCallback(show_pending_messages_button, XmNactivateCallback,Show_pending_messages,NULL);
+ XtAddCallback(open_messages_group_button, XmNactivateCallback,Send_message,"*");
+ XtAddCallback(clear_messages_button,XmNactivateCallback,Clear_messages,NULL);
+ XtAddCallback(save_button, XmNactivateCallback,Save_Config,NULL);
+ XtAddCallback(test_button, XmNactivateCallback,Test,NULL);
+ if (!debug_level) {
+ XtSetSensitive(test_button, False);
+ }
+
+ XtAddCallback(debug_level_button, XmNactivateCallback, Change_Debug_Level,NULL);
+// XtSetSensitive(debug_level_button, False);
+
+ XtAddCallback(uptime_button, XmNactivateCallback, Compute_Uptime,NULL);
+ XtAddCallback(aloha_button, XmNactivateCallback, Show_Aloha_Stats,NULL);
+ //XtSetSensitive(uptime_button, False);
+
+
+
+ // Toolbar
+ toolbar = XtVaCreateWidget("Toolbar form",
+ xmFormWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, menubar,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ trackme_button=XtVaCreateManagedWidget(langcode("POPUPMA022"),
+ xmToggleButtonGadgetClass,
+ toolbar,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, -5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNbottomOffset, 0,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNrightOffset, 0,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(trackme_button,XmNvalueChangedCallback,Track_Me,"1");
+
+ measure_button=XtVaCreateManagedWidget(langcode("POPUPMA020"),
+ xmToggleButtonGadgetClass,
+ toolbar,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, trackme_button,
+ XmNtopOffset, -7,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, -5,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNrightOffset, 0,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(measure_button,XmNvalueChangedCallback,Measure_Distance,"1");
+
+ cad_draw_button=XtVaCreateManagedWidget(langcode("POPUPMA030"),
+ xmToggleButtonGadgetClass,
+ toolbar,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, -5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNbottomOffset, 0,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, trackme_button,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNrightOffset, 0,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(cad_draw_button,XmNvalueChangedCallback,Draw_CAD_Objects_mode,NULL);
+
+ move_button=XtVaCreateManagedWidget(langcode("POPUPMA021"),
+ xmToggleButtonGadgetClass,
+ toolbar,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, cad_draw_button,
+ XmNtopOffset, -7,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, -5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, trackme_button,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNrightOffset, 0,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(move_button,XmNvalueChangedCallback,Move_Object,"1");
+
+
+
+#ifdef ARROWS
+ zoom_in_menu=XtVaCreateManagedWidget(langcode("POPUPMA002"),
+ xmPushButtonWidgetClass,
+ toolbar,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, cad_draw_button,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(zoom_in_menu,XmNactivateCallback,Zoom_in_no_pan,NULL);
+ if (map_lock_pan_zoom) XtSetSensitive(zoom_in_menu, FALSE);
+
+ zoom_out_menu=XtVaCreateManagedWidget(langcode("POPUPMA003"),
+ xmPushButtonWidgetClass,
+ toolbar,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, zoom_in_menu,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ XtAddCallback(zoom_out_menu,XmNactivateCallback,Zoom_out_no_pan,NULL);
+ if (map_lock_pan_zoom) XtSetSensitive(zoom_out_menu, FALSE);
+
+ pan_left_menu=XtVaCreateManagedWidget("create_appshell arrow1_menu",
+ xmArrowButtonGadgetClass,
+ toolbar,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, zoom_out_menu,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNarrowDirection, XmARROW_LEFT,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ NULL);
+ XtAddCallback(pan_left_menu,XmNactivateCallback,Pan_left,NULL);
+ if (map_lock_pan_zoom) XtSetSensitive(pan_left_menu, FALSE);
+
+ pan_up_menu=XtVaCreateManagedWidget("create_appshell arrow2_menu",
+ xmArrowButtonGadgetClass,
+ toolbar,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, pan_left_menu,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNarrowDirection, XmARROW_UP,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ NULL);
+ XtAddCallback(pan_up_menu,XmNactivateCallback,Pan_up,NULL);
+ if (map_lock_pan_zoom) XtSetSensitive(pan_up_menu, FALSE);
+
+ pan_down_menu=XtVaCreateManagedWidget("create_appshell arrow3_menu",
+ xmArrowButtonGadgetClass,
+ toolbar,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, pan_up_menu,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNarrowDirection, XmARROW_DOWN,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ NULL);
+ XtAddCallback(pan_down_menu,XmNactivateCallback,Pan_down,NULL);
+ if (map_lock_pan_zoom) XtSetSensitive(pan_down_menu, FALSE);
+
+ pan_right_menu=XtVaCreateManagedWidget("create_appshell arrow4_menu",
+ xmArrowButtonGadgetClass,
+ toolbar,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, pan_down_menu,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNarrowDirection, XmARROW_RIGHT,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ NULL);
+ XtAddCallback(pan_right_menu,XmNactivateCallback,Pan_right,NULL);
+ if (map_lock_pan_zoom) XtSetSensitive(pan_right_menu, FALSE);
+#endif // ARROWS
+
+
+
+#define FONT_WIDTH 9
+
+ // Create bottom text area
+ //
+#ifdef USE_TWO_STATUS_LINES
+
+ // Quantity of stations box, Bottom left corner
+ text3 = XtVaCreateWidget("create_appshell text_output3",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 14,
+ XmNwidth, ((22*FONT_WIDTH)+2),
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Zoom level box, Bottom second from left
+ text4 = XtVaCreateWidget("create_appshell text_output4",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 10,
+ XmNwidth, ((15*FONT_WIDTH)+2),
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, text3,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Log indicator box, Bottom second from right
+ log_indicator = XtVaCreateWidget(langcode("BBARSTA043"),
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 8,
+ XmNwidth, ((8*FONT_WIDTH)),
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, text4,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Interface status indicators, Bottom right corner
+ iface_da = XtVaCreateWidget("create_appshell iface",
+ xmDrawingAreaWidgetClass,
+ form,
+ XmNwidth, 22*(MAX_IFACE_DEVICES/2),
+ XmNheight, 20,
+ XmNunitType, XmPIXELS,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, log_indicator,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Message box, on Top left
+ text = XtVaCreateWidget("create_appshell text_output",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 30,
+ XmNwidth, ((29*FONT_WIDTH)+2),
+ XmNtopOffset, 4,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, text3,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Coordinate display box, Top right
+ text2 = XtVaCreateWidget("create_appshell text_output2",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 35,
+ XmNwidth, do_dbstatus?((37*FONT_WIDTH)+2):((24*FONT_WIDTH)+2),
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, text3,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, text,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+#else
+
+ // Message box, on left
+ text = XtVaCreateWidget("create_appshell text_output",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 30,
+ XmNwidth, ((29*FONT_WIDTH)+2),
+ XmNtopOffset, 4,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Coordinate display box, 2nd from left
+ text2 = XtVaCreateWidget("create_appshell text_output2",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 35,
+ XmNwidth, do_dbstatus?((37*FONT_WIDTH)+2):((24*FONT_WIDTH)+2),
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, text,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Quantity of stations box, 3rd from left
+ text3 = XtVaCreateWidget("create_appshell text_output3",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 14,
+ XmNwidth, ((10*FONT_WIDTH)+2),
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, text2,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Zoom level box, 3rd from right
+ text4 = XtVaCreateWidget("create_appshell text_output4",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 10,
+ XmNwidth, ((8*FONT_WIDTH)+2),
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, text3,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Log indicator box, 2nd from right
+ log_indicator = XtVaCreateWidget(langcode("BBARSTA043"),
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 8,
+ XmNwidth, ((8*FONT_WIDTH)),
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, text4,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Interface status indicators, on right
+ iface_da = XtVaCreateWidget("create_appshell iface",
+ xmDrawingAreaWidgetClass,
+ form,
+ XmNwidth, 22*(MAX_IFACE_DEVICES/2),
+ XmNheight, 20,
+ XmNunitType, XmPIXELS,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, log_indicator,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+#endif // USE_TWO_STATUS_LINES
+
+ // The separator goes on top of the text box no matter how
+ // many lines the status bar is, so I'm putting if after the
+ // endif statement - DCR
+ sep = XtVaCreateManagedWidget("create_appshell sep6",
+ xmSeparatorGadgetClass,
+ form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, text,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Map drawing area
+ da_width = (Dimension)screen_width;
+ da_height = (Dimension)screen_height;
+ da = XtVaCreateWidget("create_appshell da",
+ xmDrawingAreaWidgetClass,
+ form,
+ XmNwidth, da_width,
+ XmNheight, da_height,
+ XmNunitType, XmPIXELS,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, menubar,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, sep,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+//-------------------------------------------------------------------------
+
+
+ // Create the mouse menus here
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+
+#ifdef SWAP_MOUSE_BUTTONS
+ //
+ // Motif 2.2.2 (and perhaps earlier, back to version 2.0) has a
+ // problem where the XmNmenuPost doesn't work properly for
+ // modifiers (CapsLock/ScrollLock/NumLock/etc). We're reverting
+ // back to the Motif 1.x method of doing things. It works!
+ //
+ //XtSetArg(al[ac], XmNmenuPost, "<Btn1Down>"); ac++; // Set for popup menu on button 1
+ XtSetArg(al[ac], XmNwhichButton, 1); ac++; // Enable popup menu on button 1
+
+#else // SWAP_MOUSE_BUTTONS
+ //
+ // Motif 2.2.2 (and perhaps earlier, back to version 2.0) has a
+ // problem where the XmNmenuPost doesn't work properly for
+ // modifiers (CapsLock/ScrollLock/NumLock/etc). We're reverting
+ // back to the Motif 1.x method of doing things. It works!
+ //
+ //XtSetArg(al[ac], XmNmenuPost, "<Btn3Down>"); ac++; // Set for popup menu on button 3
+ XtSetArg(al[ac], XmNwhichButton, 3); ac++; // Enable popup menu on button 3
+#endif // SWAP_MOUSE_BUTTONS
+
+
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+
+ // Right menu popup (right mouse button or button 3)
+ right_menu_popup = XmCreatePopupMenu(da,
+ "create_appshell Menu Popup",
+ al,
+ ac);
+#ifdef XASTIR_XORG_SERVER_175_BUG
+ // This hack is to deal with a bug that was introduced in Xorg server
+ // version 1.7.5 and promptly fixed right after several distros adopted
+ // that version as their long-term supported version. This server version
+ // was common in 2010, but should no longer be in the wild much.
+
+#if XmVersion >= 2000
+ XtVaSetValues(right_menu_popup, XmNpopupEnabled, XmPOPUP_DISABLED, NULL);
+ XtUngrabButton(da, AnyButton, AnyModifier);
+#else
+ XtVaSetValues(right_menu_popup, XmNpopupEnabled, False, NULL);
+#endif
+#endif
+ //XtVaSetValues(right_menu_popup, XmNwhichButton, 3, NULL);
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+
+ // "Options"
+ (void)XtCreateManagedWidget(langcode("POPUPMA001"),
+ xmLabelWidgetClass,
+ right_menu_popup,
+ al,
+ ac);
+ (void)XtCreateManagedWidget("create_appshell sep7",
+ xmSeparatorWidgetClass,
+ right_menu_popup,
+ al,
+ ac);
+
+ // "Center"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA00c")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ pan_ctr=XtCreateManagedWidget(langcode("POPUPMA00c"),
+ xmPushButtonGadgetClass,
+ right_menu_popup,
+ al,
+ ac);
+ XtAddCallback(pan_ctr,XmNactivateCallback,Pan_ctr,NULL);
+
+ // "Station info"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA015")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ station_info=XtCreateManagedWidget(langcode("POPUPMA015"),
+ xmPushButtonGadgetClass,
+ right_menu_popup,
+ al,
+ ac);
+ XtAddCallback(station_info,XmNactivateCallback,Station_info,NULL);
+
+ // Send Message To
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("PULDNMG001")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ send_message_to=XtCreateManagedWidget(langcode("PULDNMG001"),
+ xmPushButtonGadgetClass,
+ right_menu_popup,
+ al,
+ ac);
+ XtAddCallback(send_message_to,XmNactivateCallback,Station_info,"4");
+
+ // Map Bookmarks
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("PULDNMP012")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ jump_button2=XtCreateManagedWidget(langcode("PULDNMP012"),
+ xmPushButtonGadgetClass,
+ right_menu_popup,
+ al,
+ ac);
+ XtAddCallback(jump_button2,XmNactivateCallback,Jump_location, NULL);
+
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ zoom_sub=XmCreatePulldownMenu(right_menu_popup,
+ "create_appshell zoom sub",
+ al,
+ ac);
+
+ // "Zoom level"
+ zoom_level=XtVaCreateManagedWidget(langcode("POPUPMA004"),
+ xmCascadeButtonGadgetClass,
+ right_menu_popup,
+ XmNsubMenuId,zoom_sub,
+ XmNmnemonic,langcode_hotkey("POPUPMA004"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Zoom in"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA002")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ zoom_in=XtCreateManagedWidget(langcode("POPUPMA002"),
+ xmPushButtonGadgetClass,
+ zoom_sub,
+ al,
+ ac);
+ XtAddCallback(zoom_in,XmNactivateCallback,Zoom_in,NULL);
+
+ // Zoom out"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA003")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ zoom_out=XtCreateManagedWidget(langcode("POPUPMA003"),
+ xmPushButtonGadgetClass,
+ zoom_sub,
+ al,
+ ac);
+ XtAddCallback(zoom_out,XmNactivateCallback,Zoom_out,NULL);
+
+ // "1"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA005")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ zl1=XtCreateManagedWidget(langcode("POPUPMA005"),
+ xmPushButtonGadgetClass,
+ zoom_sub,
+ al,
+ ac);
+ XtAddCallback(zl1,XmNactivateCallback,Zoom_level,"1");
+
+ // "16"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA006")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ zl2=XtCreateManagedWidget(langcode("POPUPMA006"),
+ xmPushButtonGadgetClass,
+ zoom_sub,
+ al,
+ ac);
+ XtAddCallback(zl2,XmNactivateCallback,Zoom_level,"2");
+
+ // "64"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA007")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ zl3=XtCreateManagedWidget(langcode("POPUPMA007"),
+ xmPushButtonGadgetClass,
+ zoom_sub,
+ al,
+ ac);
+ XtAddCallback(zl3,XmNactivateCallback,Zoom_level,"3");
+
+ // "256"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA008")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ zl4=XtCreateManagedWidget(langcode("POPUPMA008"),
+ xmPushButtonGadgetClass,
+ zoom_sub,
+ al,
+ ac);
+ XtAddCallback(zl4,XmNactivateCallback,Zoom_level,"4");
+
+ // "1024"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA009")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ zl5=XtCreateManagedWidget(langcode("POPUPMA009"),
+ xmPushButtonGadgetClass,
+ zoom_sub,
+ al,
+ ac);
+ XtAddCallback(zl5,XmNactivateCallback,Zoom_level,"5");
+
+ // "8192"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA010")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ zl6=XtCreateManagedWidget(langcode("POPUPMA010"),
+ xmPushButtonGadgetClass,
+ zoom_sub,
+ al,
+ ac);
+ XtAddCallback(zl6,XmNactivateCallback,Zoom_level,"6");
+
+ // "Entire World"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA017")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ zl7=XtCreateManagedWidget(langcode("POPUPMA017"),
+ xmPushButtonGadgetClass,
+ zoom_sub,
+ al,
+ ac);
+ XtAddCallback(zl7,XmNactivateCallback,Zoom_level,"7");
+
+ // "10% out"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, 'o'); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ zl8=XtCreateManagedWidget(langcode("POPUPMA035"), // 10% out
+ xmPushButtonGadgetClass,
+ zoom_sub,
+ al,
+ ac);
+ XtAddCallback(zl8,XmNactivateCallback,Zoom_level,"8");
+
+ // "10% in"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, 'i'); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ zl9=XtCreateManagedWidget(langcode("POPUPMA036"), // 10% in
+ xmPushButtonGadgetClass,
+ zoom_sub,
+ al,
+ ac);
+ XtAddCallback(zl9,XmNactivateCallback,Zoom_level,"9");
+
+ // "Custom Zoom Level"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, 'i'); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ zlC=XtCreateManagedWidget(langcode("POPUPMA034"),
+ xmPushButtonGadgetClass,
+ zoom_sub,
+ al,
+ ac);
+ XtAddCallback(zlC,XmNactivateCallback,Zoom_level,"10");
+
+ // "Last map pos/zoom"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA016")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ last_loc=XtCreateManagedWidget(langcode("POPUPMA016"),
+ xmPushButtonGadgetClass,
+ right_menu_popup,
+ al,
+ ac);
+ XtAddCallback(last_loc,XmNactivateCallback,Last_location,NULL);
+
+ (void)XtCreateManagedWidget("create_appshell sep7a",
+ xmSeparatorWidgetClass,
+ right_menu_popup,
+ al,
+ ac);
+
+ // "Object -> Create"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA018")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ set_object=XtCreateManagedWidget(langcode("POPUPMA018"),
+ xmPushButtonGadgetClass,
+ right_menu_popup,
+ al,
+ ac);
+ XtAddCallback(set_object,XmNactivateCallback,Set_Del_Object,NULL);
+
+ // "Object -> Modify"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA019")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ modify_object=XtCreateManagedWidget(langcode("POPUPMA019"),
+ xmPushButtonGadgetClass,
+ right_menu_popup,
+ al,
+ ac);
+ XtAddCallback(modify_object,XmNactivateCallback,Station_info,"1");
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ // Display a list of predefined SAR or Public service event objects.
+ sar_object_sub=XmCreatePulldownMenu(right_menu_popup,
+ "create_appshell sar_object_sub",
+ al,
+ ac);
+
+ // "Predefined Objects"
+ sar_object_menu=XtVaCreateManagedWidget(langcode("POPUPMA045"),
+ xmCascadeButtonGadgetClass,
+ right_menu_popup,
+ XmNsubMenuId,sar_object_sub,
+// XmNmnemonic,langcode_hotkey("POPUPMA045"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ BuildPredefinedSARMenu_UI(&sar_object_sub);
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ XtCreateManagedWidget("create_appshell sep7b",
+ xmSeparatorWidgetClass,
+ right_menu_popup,
+ al,
+ ac);
+
+ XtCreateManagedWidget("create_appshell sep7c",
+ xmSeparatorWidgetClass,
+ right_menu_popup,
+ al,
+ ac);
+
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNtearOffModel, XmTEAR_OFF_ENABLED); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ pan_sub=XmCreatePulldownMenu(right_menu_popup,
+ "create_appshell pan sub",
+ al,
+ ac);
+
+ // "Pan"
+// pan_menu=XtVaCreateManagedWidget(langcode(""),
+ pan_menu=XtVaCreateManagedWidget("Pan",
+ xmCascadeButtonGadgetClass,
+ right_menu_popup,
+ XmNsubMenuId,pan_sub,
+// XmNmnemonic,langcode_hotkey("POPUPMA004"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // "Pan Up"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA011")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ pan_up=XtCreateManagedWidget(langcode("POPUPMA011"),
+ xmPushButtonGadgetClass,
+ pan_sub,
+ al,
+ ac);
+ //pan_up=XtVaCreateManagedWidget("create_appshell arrow1",
+ // xmArrowButtonGadgetClass,
+ // right_menu_popup,
+ // XmNarrowDirection, XmARROW_UP,
+ // NULL);
+ XtAddCallback(pan_up,XmNactivateCallback,Pan_up,NULL);
+
+ // "Pan Left"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA013")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ pan_left=XtCreateManagedWidget(langcode("POPUPMA013"),
+ xmPushButtonGadgetClass,
+ pan_sub,
+ al,
+ ac);
+ //pan_left=XtVaCreateManagedWidget("create_appshell arrow3",
+ // xmArrowButtonGadgetClass,
+ // right_menu_popup,
+ // XmNarrowDirection, XmARROW_LEFT,
+ // NULL);
+ XtAddCallback(pan_left,XmNactivateCallback,Pan_left,NULL);
+
+ // "Pan Right"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA014")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ pan_right=XtCreateManagedWidget(langcode("POPUPMA014"),
+ xmPushButtonGadgetClass,
+ pan_sub,
+ al,
+ ac);
+ //pan_right=XtVaCreateManagedWidget("create_appshell arrow4",
+ // xmArrowButtonGadgetClass,
+ // right_menu_popup,
+ // XmNarrowDirection, XmARROW_RIGHT,
+ // NULL);
+ XtAddCallback(pan_right,XmNactivateCallback,Pan_right,NULL);
+
+ // "Pan Down"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA012")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ pan_down=XtCreateManagedWidget(langcode("POPUPMA012"),
+ xmPushButtonGadgetClass,
+ pan_sub,
+ al,
+ ac);
+ //pan_down=XtVaCreateManagedWidget("create_appshell arrow2",
+ // xmArrowButtonGadgetClass,
+ // right_menu_popup,
+ // XmNarrowDirection, XmARROW_DOWN,
+ // NULL);
+ XtAddCallback(pan_down,XmNactivateCallback,Pan_down,NULL);
+
+ XtCreateManagedWidget("create_appshell sep7d",
+ xmSeparatorWidgetClass,
+ right_menu_popup,
+ al,
+ ac);
+
+ move_my_sub=XmCreatePulldownMenu(right_menu_popup,
+ "create_appshell move_my sub",
+ al,
+ ac);
+
+ move_my_menu=XtVaCreateManagedWidget(langcode("POPUPMA025"),
+ xmCascadeButtonGadgetClass,
+ right_menu_popup,
+ XmNsubMenuId,move_my_sub,
+ XmNmnemonic,langcode_hotkey("POPUPMA025"),
+ XmNfontList, fontlist1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // "Move my station here"
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNmnemonic, langcode_hotkey("POPUPMA025")); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ setmyposition=XtCreateManagedWidget(langcode("POPUPMA025"),
+ xmPushButtonGadgetClass,
+ move_my_sub,
+ al,
+ ac);
+ XtAddCallback(setmyposition,XmNactivateCallback,SetMyPosition,"1");
+
+
+//-------------------------------------------------------------------------
+
+
+ /* mouse tracking */
+ XtAddEventHandler(da,LeaveWindowMask,FALSE,ClearTrackMouse,(XtPointer)text2);
+ XtAddEventHandler(da,PointerMotionMask,FALSE,TrackMouse,(XtPointer)text2);
+
+ // Popup menus
+ XtAddEventHandler(da, ButtonPressMask, FALSE, (XtEventHandler)Mouse_button_handler, NULL);
+ //XtAddEventHandler(da,ButtonReleaseMask,FALSE,(XtEventHandler)Mouse_button_handler,NULL);
+
+
+ // If adding any more widgets here, increase the size of the
+ // children[] array above.
+ ac = 0;
+ children[ac++] = text;
+ children[ac++] = text2;
+ children[ac++] = text3;
+ children[ac++] = text4;
+ children[ac++] = log_indicator;
+ children[ac++] = iface_da;
+ children[ac++] = menubar;
+ children[ac++] = toolbar;
+ children[ac++] = da;
+
+ XtManageChildren(children, ac);
+ ac = 0;
+
+ // This one needs to be done after all of
+ // the above 'cuz it contains all of them.
+ XtManageChild(form);
+
+ WM_DELETE_WINDOW = XmInternAtom(XtDisplay(appshell),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(appshell, WM_DELETE_WINDOW, Window_Quit, (XtPointer) NULL);
+ XtAddCallback(appshell,XtNsaveCallback, save_state, (XtPointer) NULL);
+ XtAddCallback(appshell,XtNdieCallback, Window_Quit, (XtPointer) NULL);
+
+ XmTextFieldSetString(text,"");
+ XtManageChild(text);
+
+ display_zoom_status();
+
+ XtManageChild(text);
+
+// We get this error on some systems if XtRealizeWidget() is called
+// without setting width/height values first:
+// "Error: Shell widget xastir has zero width and/or height"
+
+ XtRealizeWidget (appshell);
+
+
+ // Flush all pending requests to the X server.
+ XFlush(display);
+
+
+ create_gc(da);
+
+ // Fill the drawing area with the background color.
+ (void)XSetForeground(XtDisplay(da),gc,MY_BG_COLOR); // Not a mistake!
+ (void)XSetBackground(XtDisplay(da),gc,MY_BG_COLOR);
+ (void)XFillRectangle(XtDisplay(appshell),
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height);
+
+
+ XtAddCallback (da, XmNinputCallback, da_input,NULL);
+ XtAddCallback (da, XmNresizeCallback, da_resize,NULL);
+ XtAddCallback (da, XmNexposeCallback, da_expose,(XtPointer)text);
+
+
+ // Don't discard events in X11 queue, but wait for the X11
+ // server to catch up.
+ (void)XSync(XtDisplay(appshell), False);
+
+
+ // Send the window manager hints
+// XSetWMHints(display, XtWindow(appshell), wm_hints);
+
+
+ // Set up the icon
+ icon_pixmap = XCreateBitmapFromData(display,
+ XtWindow(appshell),
+ (char *)icon_bits,
+ icon_width, // icon_bitmap_width,
+ icon_height); // icon_bitmap_height
+
+ XSetStandardProperties(display,
+ XtWindow(appshell),
+ title ? title: "Xastir", // window name
+ "Xastir", // icon name
+ icon_pixmap, // pixmap for icon
+ 0, 0, // argv and argc for restarting
+ NULL); // size hints
+
+ if (title) {
+ free(title);
+ title = NULL;
+ }
+
+ if (track_me)
+ XmToggleButtonSetState(trackme_button,TRUE,TRUE);
+ else
+ XmToggleButtonSetState(trackme_button,FALSE,TRUE);
+
+
+
+ // Flush all pending requests to the X server.
+ XFlush(display);
+
+ // Don't discard events in X11 queue, but wait for the X11
+ // server to catch up.
+ (void)XSync(XtDisplay(appshell), False);
+
+
+
+ // Reset the minimum window size so that we can adjust the
+ // window downwards again, but only down to size 61. If we go
+ // any smaller height-wise then we end up getting segfaults,
+ // probably because we're trying to update some widgets that
+ // aren't visible at that point.
+ //
+ XtVaSetValues(appshell,
+ XmNminWidth, 61,
+ XmNminHeight, 61,
+ XmNwidth, my_appshell_width,
+ XmNheight, my_appshell_height,
+// XmNx, screen_x_offset, // Doesn't work here
+// XmNy, screen_y_offset, // Doesn't work here
+ NULL);
+// Lincity method of locking down the min_width/height when
+// instantiating the window, then releasing it later:
+// http://pingus.seul.org/~grumbel/tmp/lincity-source/lcx11_8c-source.html
+
+
+
+ // Actually show the draw and show the window on the display
+ XMapRaised(XtDisplay(appshell), XtWindow(appshell));
+
+
+ // Free the allocated struct. We won't need it again.
+// XFree(wm_hints); // We're not currently using this struct
+
+ if(debug_level & 8)
+ fprintf(stderr,"Create appshell stop\n");
+} // end of create_appshell()
+
+
+
+
+
+void BuildPredefinedSARMenu_UI(Widget *parent_menu) {
+ int i; // number of items in menu
+ int ac; // number of arguments
+ Arg al[100]; // arguments
+
+
+ // Set standard menu item arguments to use with each widget.
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ // Before building menu, make sure that any existing menu items are removed
+ // this allows the menu to be changed on the fly while the program is running.
+ //
+ for (i = 0; i < MAX_NUMBER_OF_PREDEFINED_OBJECTS; i++) {
+ if (predefined_object_menu_items[i] != NULL) {
+ XtDestroyWidget(predefined_object_menu_items[i]);
+ predefined_object_menu_items[i] = NULL;
+ }
+ }
+ // Now build a menu item for each entry in the predefinedObjects array.
+ for (i = 0; i < number_of_predefined_objects; i++) {
+
+ // Walk through array of predefined objects and
+ // build a menu item for each predefined object.
+ //
+ if (predefinedObjects[i].show_on_menu == 1) {
+
+ // Some predefined objects are hidden to allow construction
+ // of two predefined objects in the same place at the same
+ // time with one menu item.
+
+ if(debug_level & 1)
+ fprintf(stderr,
+ "Menu item with name: %s and index_of_child=%d\n",
+ predefinedObjects[i].menu_call, predefinedObjects[i].index_of_child);
+
+ predefined_object_menu_items[i]=XtCreateManagedWidget(predefinedObjects[i].menu_call,
+ xmPushButtonGadgetClass,
+ *parent_menu,
+ al,
+ ac);
+
+ XtAddCallback(predefined_object_menu_items[i],
+ XmNactivateCallback,
+ Create_SAR_Object,
+ (intptr_t *)predefinedObjects[i].index);
+
+ if (predefinedObjects[i].index_of_child > -1) {
+
+ // This second callback allows stacking of two
+ // objects such as a PLS with 0.25 and 0.5 and a
+ // PLS_ with 0.75 and 1.0 mile probability circles.
+ //
+ if (predefinedObjects[i].index_of_child < number_of_predefined_objects) {
+ XtAddCallback(predefined_object_menu_items[i],
+ XmNactivateCallback,
+ Create_SAR_Object,
+ (intptr_t *)predefinedObjects[predefinedObjects[i].index_of_child].index);
+ }
+ }
+ }
+ }
+}
+
+
+
+
+
+void create_gc(Widget w) {
+ XGCValues values;
+ Display *my_display = XtDisplay(w);
+ int mask = 0;
+ Pixmap pix;
+ unsigned int _w, _h;
+ int _xh, _yh;
+ char xbm_path[500];
+ int ret_val;
+
+
+ if (debug_level & 8)
+ fprintf(stderr,"Create gc start\n");
+
+ if (gc != 0)
+ return;
+
+ memset(&values, 0, sizeof(values));
+
+ // Allocate colors
+ // Note that the names here are the ones given in xastir.rgb
+ colors[0x00] = GetPixelByName(w,"DarkGreen"); // was darkgreen (same)
+ colors[0x01] = GetPixelByName(w,"purple");
+ colors[0x02] = GetPixelByName(w,"DarkGreen"); // was darkgreen (same)
+ colors[0x03] = GetPixelByName(w,"cyan");
+ colors[0x04] = GetPixelByName(w,"brown");
+ colors[0x05] = GetPixelByName(w,"plum"); // light magenta
+ colors[0x06] = GetPixelByName(w,"orange");
+ colors[0x07] = GetPixelByName(w,"darkgray");
+ colors[0x08] = GetPixelByName(w,"black"); // Foreground font color
+ colors[0x09] = GetPixelByName(w,"blue");
+ colors[0x0a] = GetPixelByName(w,"green"); // PHG (old)
+ colors[0x0b] = GetPixelByName(w,"mediumorchid"); // light purple
+ colors[0x0c] = GetPixelByName(w,"red");
+ colors[0x0d] = GetPixelByName(w,"magenta");
+ colors[0x0e] = GetPixelByName(w,"yellow");
+ colors[0x0f] = GetPixelByName(w,"white"); //
+ colors[0x10] = GetPixelByName(w,"black");
+ colors[0x11] = GetPixelByName(w,"black");
+ colors[0x12] = GetPixelByName(w,"black");
+ colors[0x13] = GetPixelByName(w,"black");
+ colors[0x14] = GetPixelByName(w,"lightgray");
+ colors[0x15] = GetPixelByName(w,"magenta");
+ colors[0x16] = GetPixelByName(w,"mediumorchid"); // light purple
+ colors[0x17] = GetPixelByName(w,"lightblue");
+ colors[0x18] = GetPixelByName(w,"purple");
+ colors[0x19] = GetPixelByName(w,"orange2"); // light orange
+ colors[0x1a] = GetPixelByName(w,"SteelBlue");
+ colors[0x20] = GetPixelByName(w,"white");
+
+ // Area object colors. Order must not be changed. If beginning moves,
+ // update draw_area and draw_map.
+ // High
+ colors[0x21] = GetPixelByName(w,"black"); // AREA_BLACK_HI
+ colors[0x22] = GetPixelByName(w,"blue"); // AREA_BLUE_HI
+ colors[0x23] = GetPixelByName(w,"green"); // AREA_GREEN_HI
+ colors[0x24] = GetPixelByName(w,"cyan3"); // AREA_CYAN_HI
+ colors[0x25] = GetPixelByName(w,"red"); // AREA_RED_HI
+ colors[0x26] = GetPixelByName(w,"magenta"); // AREA_VIOLET_HI
+ colors[0x27] = GetPixelByName(w,"yellow"); // AREA_YELLOW_HI
+ colors[0x28] = GetPixelByName(w,"gray35"); // AREA_GRAY_HI
+ // Low
+ colors[0x29] = GetPixelByName(w,"gray27"); // AREA_BLACK_LO
+ colors[0x2a] = GetPixelByName(w,"blue4"); // AREA_BLUE_LO
+ colors[0x2b] = GetPixelByName(w,"green4"); // AREA_GREEN_LO
+ colors[0x2c] = GetPixelByName(w,"cyan4"); // AREA_CYAN_LO
+ colors[0x2d] = GetPixelByName(w,"red4"); // AREA_RED_LO
+ colors[0x2e] = GetPixelByName(w,"magenta4"); // AREA_VIOLET_LO
+ colors[0x2f] = GetPixelByName(w,"yellow4"); // AREA_YELLOW_LO
+ colors[0x30] = GetPixelByName(w,"gray53"); // AREA_GRAY_LO
+
+ colors[0x40] = GetPixelByName(w,"yellow"); // symbols ...
+ colors[0x41] = GetPixelByName(w,"DarkOrange3");
+ colors[0x42] = GetPixelByName(w,"purple");
+ colors[0x43] = GetPixelByName(w,"gray80");
+ colors[0x44] = GetPixelByName(w,"red3");
+ colors[0x45] = GetPixelByName(w,"brown1");
+ colors[0x46] = GetPixelByName(w,"brown3");
+ colors[0x47] = GetPixelByName(w,"blue4");
+ colors[0x48] = GetPixelByName(w,"DeepSkyBlue");
+ colors[0x49] = GetPixelByName(w,"DarkGreen");
+ colors[0x4a] = GetPixelByName(w,"red2");
+ colors[0x4b] = GetPixelByName(w,"green3");
+ colors[0x4c] = GetPixelByName(w,"MediumBlue");
+ colors[0x4d] = GetPixelByName(w,"white");
+ colors[0x4e] = GetPixelByName(w,"gray53");
+ colors[0x4f] = GetPixelByName(w,"gray35");
+ colors[0x50] = GetPixelByName(w,"gray27");
+ colors[0x51] = GetPixelByName(w,"black"); // ... symbols
+
+ colors[0x52] = GetPixelByName(w,"LimeGreen"); // PHG, symbols
+
+ colors[0xfe] = GetPixelByName(w,"pink");
+
+ // map solid colors
+ colors[0x60] = GetPixelByName(w,"HotPink");
+ colors[0x61] = GetPixelByName(w,"RoyalBlue");
+ colors[0x62] = GetPixelByName(w,"orange3");
+ colors[0x63] = GetPixelByName(w,"yellow3");
+ colors[0x64] = GetPixelByName(w,"ForestGreen");
+ colors[0x65] = GetPixelByName(w,"DodgerBlue");
+ colors[0x66] = GetPixelByName(w,"cyan2");
+ colors[0x67] = GetPixelByName(w,"plum2");
+ colors[0x68] = GetPixelByName(w,"MediumBlue"); // was blue3 (the same!)
+ colors[0x69] = GetPixelByName(w,"gray86");
+
+ // These colors added to make it possible to color local shapefile tiger
+ // maps similar to on-line ones.
+ colors[0x70] = GetPixelByName(w,"RosyBrown2");
+ colors[0x71] = GetPixelByName(w,"gray81");
+ colors[0x72] = GetPixelByName(w,"tgr_park_1");
+ colors[0x73] = GetPixelByName(w,"tgr_city_1");
+ colors[0x74] = GetPixelByName(w,"tgr_forest_1");
+ colors[0x75] = GetPixelByName(w,"tgr_water_1");
+
+ // tracking trail colors
+ // set color for your own station with #define MY_TRAIL_COLOR in db.c
+ trail_colors[0x00] = GetPixelByName(w,"yellow");
+ trail_colors[0x01] = GetPixelByName(w,"blue");
+ trail_colors[0x02] = GetPixelByName(w,"green");
+ trail_colors[0x03] = GetPixelByName(w,"red");
+ trail_colors[0x04] = GetPixelByName(w,"magenta");
+ trail_colors[0x05] = GetPixelByName(w,"black");
+ trail_colors[0x06] = GetPixelByName(w,"white");
+ trail_colors[0x07] = GetPixelByName(w,"DarkOrchid");
+ trail_colors[0x08] = GetPixelByName(w,"purple"); // very similar to DarkOrchid...
+ trail_colors[0x09] = GetPixelByName(w,"OrangeRed");
+ trail_colors[0x0a] = GetPixelByName(w,"brown");
+ trail_colors[0x0b] = GetPixelByName(w,"DarkGreen"); // was darkgreen (same)
+ trail_colors[0x0c] = GetPixelByName(w,"MediumBlue");
+ trail_colors[0x0d] = GetPixelByName(w,"ForestGreen");
+ trail_colors[0x0e] = GetPixelByName(w,"chartreuse");
+ trail_colors[0x0f] = GetPixelByName(w,"cornsilk");
+ trail_colors[0x10] = GetPixelByName(w,"LightCyan");
+ trail_colors[0x11] = GetPixelByName(w,"cyan");
+ trail_colors[0x12] = GetPixelByName(w,"DarkSlateGray");
+ trail_colors[0x13] = GetPixelByName(w,"NavyBlue");
+ trail_colors[0x14] = GetPixelByName(w,"DarkOrange3");
+ trail_colors[0x15] = GetPixelByName(w,"gray27");
+ trail_colors[0x16] = GetPixelByName(w,"RoyalBlue");
+ trail_colors[0x17] = GetPixelByName(w,"yellow2");
+ trail_colors[0x18] = GetPixelByName(w,"DodgerBlue");
+ trail_colors[0x19] = GetPixelByName(w,"cyan2");
+ trail_colors[0x1a] = GetPixelByName(w,"MediumBlue"); // was blue3 (the same!)
+ trail_colors[0x1b] = GetPixelByName(w,"gray86");
+ trail_colors[0x1c] = GetPixelByName(w,"SteelBlue");
+ trail_colors[0x1d] = GetPixelByName(w,"PaleGreen");
+ trail_colors[0x1e] = GetPixelByName(w,"RosyBrown");
+ trail_colors[0x1f] = GetPixelByName(w,"DeepSkyBlue");
+
+ values.background=GetPixelByName(w,"darkgray");
+
+ gc = XCreateGC(my_display, XtWindow(w), mask, &values);
+
+ // Load a new font into the GC for the station font
+ Load_station_font();
+
+ gc_tint = XCreateGC(my_display, XtWindow(w), mask, &values);
+
+ gc_stipple = XCreateGC(my_display, XtWindow(w), mask, &values);
+
+ gc_bigfont = XCreateGC(my_display, XtWindow(w), mask, &values);
+
+ pix = XCreatePixmap(XtDisplay(w), RootWindowOfScreen(XtScreen(w)), 20, 20, 1);
+ values.function = GXcopy;
+ gc2 = XCreateGC(XtDisplay(w), pix,GCForeground|GCBackground|GCFunction, &values);
+
+ pixmap=XCreatePixmap(XtDisplay(w),
+ DefaultRootWindow(XtDisplay(w)),
+ (unsigned int)screen_width,(unsigned int)screen_height,
+ DefaultDepthOfScreen(XtScreen(w)));
+
+ pixmap_final=XCreatePixmap(XtDisplay(w),
+ DefaultRootWindow(XtDisplay(w)),
+ (unsigned int)screen_width,(unsigned int)screen_height,
+ DefaultDepthOfScreen(XtScreen(w)));
+
+ pixmap_alerts=XCreatePixmap(XtDisplay(w),
+ DefaultRootWindow(XtDisplay(w)),
+ (unsigned int)screen_width,(unsigned int)screen_height,
+ DefaultDepthOfScreen(XtScreen(w)));
+
+ xastir_snprintf(xbm_path, sizeof(xbm_path), "%s/%s", SYMBOLS_DIR, "2x2.xbm");
+ ret_val = XReadBitmapFile(XtDisplay(w), DefaultRootWindow(XtDisplay(w)),
+ xbm_path, &_w, &_h, &pixmap_50pct_stipple, &_xh, &_yh);
+
+ if (ret_val != 0) {
+ fprintf(stderr,"XReadBitmapFile() failed: Bitmap not found? %s\n",xbm_path);
+ exit(1); // 2x2.xbm couldn't be loaded
+ }
+
+ xastir_snprintf(xbm_path, sizeof(xbm_path), "%s/%s", SYMBOLS_DIR, "25pct.xbm");
+ ret_val = XReadBitmapFile(XtDisplay(w), DefaultRootWindow(XtDisplay(w)),
+ xbm_path, &_w, &_h, &pixmap_25pct_stipple, &_xh, &_yh);
+
+ if (ret_val != 0) {
+ fprintf(stderr,"XReadBitmapFile() failed: Bitmap not found? %s\n",xbm_path);
+ exit(1); // 25pct.xbm couldn't be loaded
+ }
+
+ xastir_snprintf(xbm_path, sizeof(xbm_path), "%s/%s", SYMBOLS_DIR, "13pct.xbm");
+ ret_val = XReadBitmapFile(XtDisplay(w), DefaultRootWindow(XtDisplay(w)),
+ xbm_path, &_w, &_h, &pixmap_13pct_stipple, &_xh, &_yh);
+
+ if (ret_val != 0) {
+ fprintf(stderr,"XReadBitmapFile() failed: Bitmap not found? %s\n",xbm_path);
+ exit(1); // 13pct.xbm couldn't be loaded
+ }
+
+ xastir_snprintf(xbm_path, sizeof(xbm_path), "%s/%s", SYMBOLS_DIR, "alert.xbm");
+ ret_val = XReadBitmapFile(XtDisplay(w), DefaultRootWindow(XtDisplay(w)),
+ xbm_path, &_w, &_h, &pixmap_wx_stipple, &_xh, &_yh);
+
+ if (ret_val != 0) {
+ fprintf(stderr,"XReadBitmapFile() failed: Bitmap not found? %s\n",xbm_path);
+ exit(1); // alert.xbm couldn't be loaded
+ }
+
+ display_up=1;
+
+ wait_to_redraw=0;
+
+ if (debug_level & 8)
+ fprintf(stderr,"Create gc stop\n");
+} // create_gc()
+
+
+
+
+
+// This routine just copies an area from pixmap_final to the
+// display, so we won't go through all the trouble of making this
+// interruptable. Just get on with it, perform the operation, and
+// return to X. If it did any map drawing, we'd make it
+// interruptable.
+//
+void da_expose(Widget w, /*@unused@*/ XtPointer client_data, XtPointer call_data) {
+ Dimension width, height, margin_width, margin_height;
+ XmDrawingAreaCallbackStruct *db = (XmDrawingAreaCallbackStruct *)call_data;
+ XExposeEvent *event = (XExposeEvent *) db->event;
+ unsigned char unit_type;
+
+ //fprintf(stderr,"Expose event\n");*/
+
+ /* Call a routine to create a Graphics Context */
+ create_gc(w);
+
+ /* First get the various dimensions */
+ XtVaGetValues(w,
+ XmNwidth, &width,
+ XmNheight, &height,
+ XmNmarginWidth, &margin_width,
+ XmNmarginHeight, &margin_height,
+ XmNunitType, &unit_type,
+ NULL);
+
+ (void)XCopyArea(XtDisplay(w),
+ pixmap_final,
+ XtWindow(w),
+ gc,
+ event->x,
+ event->y,
+ event->width,
+ event->height,
+ event->x,
+ event->y);
+
+ // We just refreshed the screen, so don't try to erase any
+ // zoom-in boxes via XOR.
+ zoom_box_x1 = -1;
+}
+
+
+
+
+
+// The work function for resizing. This one will be called by
+// UpdateTime if certain flags have been set my da_resize. This
+// function and the functions it calls that are CPU intensive should
+// be made interruptable: They should check interrupt_drawing_now
+// flag periodically and exit nicely if it is set.
+//
+void da_resize_execute(Widget w) {
+ Dimension width, height;
+
+
+ busy_cursor(appshell);
+
+ // Reset the flags that may have brought us here.
+ interrupt_drawing_now = 0;
+ request_resize = 0;
+
+ if (XtIsRealized(w)){
+ /* First get the various dimensions */
+ XtVaGetValues(w,
+ XmNwidth, &width,
+ XmNheight, &height,
+ NULL);
+
+ screen_width = (long)width;
+ screen_height = (long)height;
+ XtVaSetValues(w,
+ XmNwidth, width,
+ XmNheight, height,
+ NULL);
+
+ /* fprintf(stderr,"Size x:%ld, y:%ld\n",screen_width,screen_height);*/
+ if (pixmap)
+ (void)XFreePixmap(XtDisplay(w),pixmap);
+
+ if(pixmap_final)
+ (void)XFreePixmap(XtDisplay(w),pixmap_final);
+
+ if(pixmap_alerts)
+ (void)XFreePixmap(XtDisplay(w),pixmap_alerts);
+
+ pixmap=XCreatePixmap(XtDisplay(w),
+ DefaultRootWindow(XtDisplay(w)),
+ (unsigned int)width,(unsigned int)height,
+ DefaultDepthOfScreen(XtScreen(w)));
+
+ pixmap_final=XCreatePixmap(XtDisplay(w),
+ DefaultRootWindow(XtDisplay(w)),
+ (unsigned int)width,(unsigned int)height,
+ DefaultDepthOfScreen(XtScreen(w)));
+
+ pixmap_alerts=XCreatePixmap(XtDisplay(w),
+ DefaultRootWindow(XtDisplay(w)),
+ (unsigned int)width,(unsigned int)height,
+ DefaultDepthOfScreen(XtScreen(w)));
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return;
+
+ setup_in_view(); // flag stations that are in screen view
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return;
+
+ // Reload maps
+ // Set interrupt_drawing_now because conditions have
+ // changed.
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(w)) {
+// (void)XCopyArea(XtDisplay(w),pixmap_final,XtWindow(w),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+ }
+}
+
+
+
+
+
+// We got a resize callback. Set flags. UpdateTime will come
+// along in a bit and perform the resize. With this method, the
+// resize can be made interruptable. We merely need to check for
+// the interrupt_drawing_now flag periodically while doing the
+// resize drawing.
+//
+void da_resize(Widget w, /*@unused@*/ XtPointer client_data, /*@unused@*/ XtPointer call_data) {
+
+ // Set the interrupt_drawing_now flag
+ interrupt_drawing_now++;
+
+ // Set the request_resize flag
+ request_resize++;
+// last_input_event = sec_now() + 2;
+}
+
+
+
+
+
+// We got a mouse or keyboard callback. Set flags. UpdateTime
+// will come along in a bit and perform the screen redraw. With
+// this method, the redraw can be made interruptable. We merely
+// need to check for the interrupt_drawing_now flag periodically
+// while doing the redraw.
+//
+void da_input(Widget w, XtPointer client_data, XtPointer call_data) {
+ XEvent *event = ((XmDrawingAreaCallbackStruct *) call_data)->event;
+ Dimension width, height;
+ int redraw;
+ char buffer[20];
+ int bufsize = 20;
+ char temp[200];
+ char temp_course[20];
+ KeySym key;
+ XComposeStatus compose;
+ int x_center;
+ int y_center;
+ int x_distance;
+ int y_distance;
+ float x_distance_real;
+ float y_distance_real;
+ float full_distance;
+ double area;
+ float area_acres; // area in acres
+ long a_x, a_y, b_x, b_y;
+ char str_lat[20];
+ char str_long[20];
+ long x,y;
+ int done = 0;
+ long lat, lon;
+
+
+ XtVaGetValues(w,
+ XmNwidth, &width,
+ XmNheight, &height,
+ NULL);
+
+ /*fprintf(stderr,"input event %d %d\n",event->type,ButtonPress);*/
+ redraw=0;
+
+ // Snag the current pointer position
+ input_x = event->xbutton.x;
+ input_y = event->xbutton.y;
+
+
+/////////////////
+// CAD OBJECTS //
+/////////////////
+
+ // Start of CAD Objects code. We have both ButtonPress and
+ // ButtonRelease code handlers here, for this mode only.
+ // Check whether we're in CAD Object draw mode first
+ if (draw_CAD_objects_flag && event->xbutton.button == Button2) {
+
+ if (event->type == ButtonRelease) {
+ // We don't want to do anything for ButtonRelease. Most
+ // of all, we don't want another point drawn for both
+ // press and release, and we don't want other GUI
+ // actions performed on release when in CAD Draw mode.
+ done++;
+ }
+ else { // ButtonPress for Button2
+
+ // We need to check to see whether we're dragging the
+ // pointer, and then need to save the points away (in
+ // Xastir lat/long format), drawing lines between the
+ // points whenever we do a pixmap_final refresh to the
+ // screen.
+
+ // Check whether we just did the first mouse button down
+ // while in CAD draw mode. If so, save away the mouse
+ // pointer and get out. We'll use that mouse pointer
+ // the next time a mouse button gets pressed in order to
+ // draw a line.
+
+ // We're going to use gc_tint with an XOR bitblit here
+ // to make sure that any lines we draw will be easily
+ // seen, no matter what colors we're drawing on top of.
+ //
+
+ // If we have a valid saved position already from our
+ // first click, then we must be on the 2nd or later
+ // click. Draw a line.
+ if (polygon_last_x != -1 && polygon_last_y != -1) {
+
+ // Convert from screen coordinates to Xastir
+ // coordinate system and save in the object->vertice
+ // list.
+ convert_screen_to_xastir_coordinates(input_x,
+ input_y,
+ &lat,
+ &lon);
+ CAD_vertice_allocate(lat, lon);
+ // Reload symbols/tracks/CAD objects
+ redraw_symbols(da);
+ }
+ else { // First point of a polygon. Save it.
+
+ // Figure out the real lat/long from the screen
+ // coordinates. Create a new object to hold the
+ // point.
+ convert_screen_to_xastir_coordinates(input_x,
+ input_y,
+ &lat,
+ &lon);
+ CAD_object_allocate(lat, lon);
+ }
+
+ // Save current point away for the next draw.
+ polygon_last_x = input_x;
+ polygon_last_y = input_y;
+
+ done++;
+ }
+ }
+// End of CAD Objects code.
+
+
+/////////////////////////////////
+// Start of ButtonRelease code //
+/////////////////////////////////
+
+ if (!done && event->type == ButtonRelease) {
+ //fprintf(stderr,"ButtonRelease %d %d\n",event->xbutton.button,Button3);
+
+#ifdef SWAP_MOUSE_BUTTONS
+ if (event->xbutton.button == Button3) {
+ // Right mouse button release
+#else // SWAP_MOUSE_BUTTONS
+ if (event->xbutton.button == Button1) {
+ // Left mouse button release
+#endif // SWAP_MOUSE_BUTTONS
+
+ // If no drag, Center the map on the mouse pointer
+ // If drag, compute new zoom factor/center and redraw
+ // -OR- measure distances.
+
+
+/////////////////////////
+// CENTER MAP FUNCTION //
+/////////////////////////
+
+ // Check for "Center Map" function. Must be within 15
+ // pixels of where the button press occurred to qualify.
+ if ( mouse_zoom && !measuring_distance && !moving_object
+ && (abs(menu_x - input_x) < 15)
+ && (abs(menu_y - input_y) < 15) ) {
+ /* if(display_up) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height,NULL);
+ new_mid_x = center_longitude - ((width *scale_x)/2) + (menu_x*scale_x);
+ new_mid_y = center_latitude - ((height*scale_y)/2) + (menu_y*scale_y);
+ new_scale_y = scale_y; // keep size
+ display_zoom_image(1); // check range and do display, recenter
+ }
+ */
+ // Reset the zoom-box variables
+ possible_zoom_function = 0;
+ zoom_box_x1 = -1;
+ }
+ // It's not the center function because the mouse moved more than 15 pixels.
+ // It must be either the "Compute new zoom/center" -OR- the "Measure distance"
+ // -OR- "Move distance" functions.. The "measuring_distance" or "moving_object"
+ // variables will tell us.
+
+ else {
+ // At this stage we have menu_x/menu_y where the button press occurred,
+ // and input_x/input_y where the button release occurred.
+
+
+//////////////////////
+// MEASURE DISTANCE //
+//////////////////////
+
+ if (measuring_distance) { // Measure distance function
+ double R = EARTH_RADIUS_METERS;
+
+
+ // Check whether we already have a box on screen
+ // that we need to erase.
+ if (zoom_box_x1 != -1) {
+//fprintf(stderr,"erasing\n");
+ // Remove the last box drawn via the XOR
+ // function.
+ XDrawLine(XtDisplay(da),
+ XtWindow(da),
+ gc_tint,
+ l16(zoom_box_x1), // Keep x constant
+ l16(zoom_box_y1),
+ l16(zoom_box_x1),
+ l16(zoom_box_y2));
+ XDrawLine(XtDisplay(da),
+ XtWindow(da),
+ gc_tint,
+ l16(zoom_box_x1),
+ l16(zoom_box_y1), // Keep y constant
+ l16(zoom_box_x2),
+ l16(zoom_box_y1));
+ XDrawLine(XtDisplay(da),
+ XtWindow(da),
+ gc_tint,
+ l16(zoom_box_x2), // Keep x constant
+ l16(zoom_box_y1),
+ l16(zoom_box_x2),
+ l16(zoom_box_y2));
+ XDrawLine(XtDisplay(da),
+ XtWindow(da),
+ gc_tint,
+ l16(zoom_box_x1),
+ l16(zoom_box_y2), // Keep y constant
+ l16(zoom_box_x2),
+ l16(zoom_box_y2));
+ }
+
+ // Reset the zoom-box variables
+ possible_zoom_function = 0;
+ zoom_box_x1 = -1;
+
+ x_distance = abs(menu_x - input_x);
+ y_distance = abs(menu_y - input_y);
+
+ // Here we need to convert to either English or Metric units of distance.
+
+ //(temp,"Distance x:%d pixels, y:%d pixels\n",x_distance,y_distance);
+ //popup_message_always(langcode("POPUPMA020"),temp);
+
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height,NULL);
+ a_x = center_longitude - ((width *scale_x)/2) + (menu_x*scale_x);
+ a_y = center_latitude - ((height*scale_y)/2) + (menu_y*scale_y);
+
+ b_x = center_longitude - ((width *scale_x)/2) + (input_x*scale_x);
+ b_y = center_latitude - ((height*scale_y)/2) + (input_y*scale_y);
+
+ // Keep y constant to get x distance. Convert
+ // to the current measurement units for display.
+ x_distance_real = cvt_kn2len * calc_distance_course(a_y,a_x,a_y,b_x,temp_course,sizeof(temp_course));
+ // Keep x constant to get y distance. Convert
+ // to the current measurement units for display.
+ y_distance_real = cvt_kn2len * calc_distance_course(a_y,a_x,b_y,a_x,temp_course,sizeof(temp_course));
+ // Compute the total distance and course.
+ // Convert to the current measurement units for
+ // display.
+ full_distance = cvt_kn2len * calc_distance_course(a_y,a_x,b_y,b_x,temp_course,sizeof(temp_course));
+
+ if (full_distance < 1.0) {
+ switch (english_units) {
+ case 1: // English
+ full_distance = full_distance * 5280; // convert from miles to feet
+ x_distance_real = x_distance_real * 5280; // convert from miles to feet
+ y_distance_real = y_distance_real * 5280; // convert from miles to feet
+ break;
+ case 2: // Nautical miles and knots
+ full_distance = full_distance * 6076; // convert from miles to feet
+ x_distance_real = x_distance_real * 6076; // convert from miles to feet
+ y_distance_real = y_distance_real * 6076; // convert from miles to feet
+ break;
+ default: // Metric
+ full_distance = full_distance * 1000; // convert from kilometers to meters
+ x_distance_real = x_distance_real * 1000; // convert from kilometers to meters
+ y_distance_real = y_distance_real * 1000; // convert from kilometers to meters
+ break;
+ }
+
+// See this URL for a method of calculating the area of a lat/long
+// rectangle on a sphere:
+// http://mathforum.org/library/drmath/view/63767.html
+// area = (pi/180)*R^2 * abs(sin(lat1)-sin(lat2)) * abs(lon1-lon2)
+//
+// Their formula is incorrect due to the mistake of mixing radians
+// and degrees. The correct formula is (WE7U):
+// area = R^2 * abs(sin(lat1)-sin(lat2)) * abs(lon1-lon2)
+
+ // Compute correct units
+ switch (english_units) {
+ case 1: // English
+ R = EARTH_RADIUS_MILES * 5280.0; // feet
+ break;
+ case 2: // Nautical miles and knots
+ R = EARTH_RADIUS_MILES * 5280.0; // feet
+ break;
+ default: // Metric
+ R = EARTH_RADIUS_METERS; // Meters
+ break;
+ }
+
+ // Compute the total area in feet or meters
+
+ // New method using area on a sphere:
+ area = R*R
+ * fabs( sin(convert_lat_l2r(a_y)) - sin(convert_lat_l2r(b_y)) )
+ * fabs( convert_lon_l2r(a_x) - convert_lon_l2r(b_x) );
+
+ // Old method using planar geometry:
+ //area = x_distance_real * y_distance_real;
+
+ // calculate area in acres
+ switch (english_units) {
+ case 1:
+ case 2:
+ area_acres = area * 2.2956749e-05;
+ break;
+ default: // Metric
+ area_acres = area * 2.4710439e-04;
+ break;
+ }
+ //if (area_acres<0.1)
+ // area_acres = 0;
+
+//fprintf(stderr,"Old method: %f\nNew method: %f\n\n",
+// x_distance_real * y_distance_real,
+// area);
+
+
+
+// NOTE: Angles currently change at zoom==1, so we purposely don't
+// give an angle in that measurement instance below.
+//
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%0.2f %s, x=%0.2f %s, y=%0.2f %s, %0.2f %s %s (%0.2f %s), %s: %s %s",
+ full_distance, un_alt, // feet/meters
+ x_distance_real, un_alt, // feet/meters
+ y_distance_real, un_alt, // feet/meters
+ area,
+ langcode("POPUPMA038"), // square
+ un_alt,
+ area_acres,
+ "acres",
+ langcode("POPUPMA041"), // Bearing
+ (scale_y == 1) ? "??" : temp_course, // Fix for zoom==1
+ langcode("POPUPMA042") ); // degrees
+ }
+ else {
+ // Compute the total area in miles or
+ // kilometers
+
+ // Compute correct units
+ switch (english_units) {
+ case 1: // English
+ R = EARTH_RADIUS_MILES; // Statute miles
+ break;
+ case 2: // Nautical miles and knots
+ R = EARTH_RADIUS_KILOMETERS/1.852; // Nautical miles
+ break;
+ default: // Metric
+ R = EARTH_RADIUS_KILOMETERS; // kilometers
+ break;
+ }
+
+ // New method, area on a sphere:
+ area = R*R
+ * fabs(sin(convert_lat_l2r(a_y))-sin(convert_lat_l2r(b_y)))
+ * fabs(convert_lon_l2r(a_x)-convert_lon_l2r(b_x));
+
+ // Old method using planar geometry:
+ //area = x_distance_real * y_distance_real;
+
+//fprintf(stderr,"Old method: %f\nNew method: %f\n\n",
+// x_distance_real * y_distance_real,
+// area);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%0.2f %s, x=%0.2f %s, y=%0.2f %s, %0.2f %s %s, %s: %s %s",
+ full_distance, un_dst, // miles/kilometers
+ x_distance_real, un_dst, // miles/kilometers
+ y_distance_real, un_dst, // miles/kilometers
+ area,
+ langcode("POPUPMA038"), // square
+ un_dst,
+ langcode("POPUPMA041"), // Bearing
+ temp_course,
+ langcode("POPUPMA042") ); // degrees
+ }
+ popup_message_always(langcode("POPUPMA020"),temp);
+ }
+
+
+///////////////////
+// MOVING OBJECT //
+///////////////////
+
+ else if (moving_object) { // Move function
+ // For this function we need to:
+ // Determine which icon is closest to the mouse pointer press position.
+ // We'll use Station_info to select the icon for us.
+ // Determine whether it is our object. If not, force
+ // the user to "adopt" the object before moving it.
+ // Compute the lat/lon of the mouse pointer release position.
+ // Put the new value of lat/lon into the object data.
+ // Cause symbols to get redrawn.
+
+ // Reset the zoom-box variables
+ possible_zoom_function = 0;
+ zoom_box_x1 = -1;
+
+ x = (center_longitude - ((screen_width * scale_x)/2) + (event->xmotion.x * scale_x));
+ y = (center_latitude - ((screen_height * scale_y)/2) + (event->xmotion.y * scale_y));
+
+ if (x < 0)
+ x = 0l; // 180�W
+
+ if (x > 129600000l)
+ x = 129600000l; // 180�E
+
+ if (y < 0)
+ y = 0l; // 90�N
+
+ if (y > 64800000l)
+ y = 64800000l; // 90�S
+
+ if (debug_level & 1) {
+ // This math is only used for the debug mode printf below.
+ if (coordinate_system == USE_DDDDDD) {
+ convert_lat_l2s(y, str_lat, sizeof(str_lat), CONVERT_DEC_DEG);
+ convert_lon_l2s(x, str_long, sizeof(str_long), CONVERT_DEC_DEG);
+ } else if (coordinate_system == USE_DDMMSS) {
+ convert_lat_l2s(y, str_lat, sizeof(str_lat), CONVERT_DMS_NORMAL);
+ convert_lon_l2s(x, str_long, sizeof(str_long), CONVERT_DMS_NORMAL);
+ } else { // Assume coordinate_system == USE_DDMMMM
+ convert_lat_l2s(y, str_lat, sizeof(str_lat), CONVERT_HP_NORMAL);
+ convert_lon_l2s(x, str_long, sizeof(str_long), CONVERT_HP_NORMAL);
+ }
+ //fprintf(stderr,"%s %s\n", str_lat, str_long);
+ }
+
+ // Effect the change in the object/item's
+ // position.
+ //
+ doing_move_operation++;
+ Station_info(w, "2", NULL);
+ doing_move_operation = 0;
+ }
+
+
+/////////////////////////////
+// COMPUTE NEW CENTER/ZOOM //
+/////////////////////////////
+
+ else { // Must be "Compute new center/zoom" function
+ float ratio;
+
+ if (!map_lock_pan_zoom) {
+
+ // We need to compute a new center and a new scale, then
+ // cause the new image to be created.
+ // Compute new center. It'll be the average of the two points
+ x_center = (menu_x + input_x) /2;
+ y_center = (menu_y + input_y) /2;
+
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height,NULL);
+ new_mid_x = center_longitude - ((width *scale_x)/2) + (x_center*scale_x);
+ new_mid_y = center_latitude - ((height*scale_y)/2) + (y_center*scale_y);
+
+ //
+ // What Rolf had to say:
+ //
+ // Calculate center of mouse-marked area and get the scaling relation
+ // between x and y for that position. This position will be the new
+ // center, so that lattitude-dependent relation does not change with
+ // a zoom-in. For both x and y calculate a new zoom factor necessary
+ // to fit that screen direction. Select the one that allows both x
+ // and y part to fall into the screen area. Draw the new screen with
+ // new center and new zoom factor.
+ //
+
+ // Compute the new scale, or as close to it as we can get
+ //new_scale_y = scale_y / 2; // Zoom in by a factor of 2
+ new_scale_y = (long)( (((float)abs(menu_y - input_y) / (float)height ) * (float)scale_y ) + 0.5);
+ new_scale_x = (long)( (((float)abs(menu_x - input_x) / (float)width ) * (float)scale_x ) + 0.5);
+
+ if (new_scale_y < 1)
+ new_scale_y = 1; // Don't go further in than zoom 1
+
+ if (new_scale_x < 1)
+ new_scale_x = 1; // Don't go further in than zoom 1
+
+ // We now know approximately the scales we need
+ // in order to view all of the pixels just
+ // selected in the drag operation. Now set
+ // new_scale_y to the highest number of the two,
+ // which will make sure the entire drag
+ // selection will be seen at the new zoom level.
+ // Use the new ratio between scales to compute
+ // this, computed from the new midpoint.
+ //
+ //fprintf(stderr,"scale_x:%ld\tscale_y:%ld\n", get_x_scale(new_mid_x, new_mid_y, scale_y), scale_y );
+ ratio = ((float)get_x_scale(new_mid_x,new_mid_y,scale_y) / (float)scale_y);
+
+ //fprintf(stderr,"Ratio: %f\n", ratio);
+ //fprintf(stderr,"x:%ld\ty:%ld\n", new_scale_x, new_scale_y);
+ if ( new_scale_y < (long)((new_scale_x / ratio) + 0.5) ) {
+ new_scale_y = (long)((new_scale_x / ratio) + 0.5);
+ //fprintf(stderr,"Changed y\n");
+ }
+ //fprintf(stderr,"x:%ld\ty:%ld\n", new_scale_x, new_scale_y);
+
+ display_zoom_image(1); // Check range and do display, recenter
+
+ menu_x = input_x;
+ menu_y = input_y;
+ //fprintf(stderr,"Drag/zoom/center happened\n");
+
+ // Reset the zoom-box variables
+ possible_zoom_function = 0;
+ zoom_box_x1 = -1;
+ }
+ }
+ }
+ mouse_zoom = 0;
+ } // End of Button1 release code
+
+
+//////////////
+// ZOOM OUT //
+//////////////
+
+ else if (event->xbutton.button == Button2 && !map_lock_pan_zoom) {
+ // Middle mouse button release
+
+ // Zoom out 2x with panning
+ menu_x=input_x;
+ menu_y=input_y;
+ Zoom_out( w, client_data, call_data );
+
+ // Simple zoom out, keeping map center at current position
+ //Zoom_out_no_pan( w, client_data, call_data );
+ mouse_zoom = 0;
+ } // End of Button2 release code
+
+
+////////////////////////////////
+// THIRD MOUSE BUTTON RELEASE //
+////////////////////////////////
+
+#ifdef SWAP_MOUSE_BUTTONS
+ else if (event->xbutton.button == Button1) {
+ // Left mouse button release
+#else // SWAP_MOUSE_BUTTONS
+ else if (event->xbutton.button == Button3) {
+ // Right mouse button release
+#endif // SWAP_MOUSE_BUTTONS
+
+ // Do nothing. We have a popup tied into the button press anyway.
+ // (Mouse_button_handler & right_menu_popup).
+ // Leave the button release alone in this case.
+ mouse_zoom = 0;
+ } // End of Button3 release code
+
+
+///////////////
+// SCROLL UP //
+///////////////
+
+ else if (event->xbutton.button == Button4 && !map_lock_pan_zoom) {
+// Scroll up
+ menu_x=input_x;
+ menu_y=input_y;
+ Pan_up(w, client_data, call_data);
+ } // End of Button4 release code
+
+
+/////////////////
+// SCROLL DOWN //
+/////////////////
+
+ else if (event->xbutton.button == Button5 && !map_lock_pan_zoom) {
+// Scroll down
+ menu_x=input_x;
+ menu_y=input_y;
+ Pan_down(w, client_data, call_data);
+ } // End of Button5 release code
+
+
+////////////////////////////////////
+// YET MORE MOUSE BUTTON RELEASES //
+////////////////////////////////////
+
+ else if (event->xbutton.button == 6 && !map_lock_pan_zoom) {
+// Mouse button 6 release
+ menu_x=input_x;
+ menu_y=input_y;
+ Zoom_out_no_pan(w, client_data, call_data);
+ mouse_zoom = 0;
+ } // End of Button6 code
+
+ else if (event->xbutton.button == 7 && !map_lock_pan_zoom) {
+// Mouse button 7 release
+ menu_x=input_x;
+ menu_y=input_y;
+ Zoom_in_no_pan(w, client_data, call_data);
+ mouse_zoom = 0;
+ } // End of Button7 release code
+ }
+// End of ButtonRelease code
+
+
+
+///////////////////////////////
+// Start of ButtonPress code //
+///////////////////////////////
+
+ else if (!done && event->type == ButtonPress) {
+ //fprintf(stderr,"ButtonPress %d %d\n",event->xbutton.button,Button3);
+
+#ifdef SWAP_MOUSE_BUTTONS
+ if (event->xbutton.button == Button3) {
+// Right mouse button press
+#else // SWAP_MOUSE_BUTTONS
+ if (event->xbutton.button == Button1) {
+// Left mouse button press
+#endif // SWAP_MOUSE_BUTTONS
+
+ // Mark the position for possible drag function
+ menu_x=input_x;
+ menu_y=input_y;
+ mouse_zoom = 1;
+
+ if (!moving_object) { // Can be "Measure" or "Zoom-in"
+ if (!map_lock_pan_zoom || (map_lock_pan_zoom && measuring_distance)) {
+ // Not moving an object/item, so allow the
+ // zoom-in box to display.
+ possible_zoom_function++;
+ }
+ }
+ } // End of Button1 Press code
+
+ else if (event->xbutton.button == Button2) {
+// Middle mouse button or both right/left mouse buttons press
+
+ // Nothing attached here.
+ mouse_zoom = 0;
+ } // End of Button2 Press code
+
+#ifdef SWAP_MOUSE_BUTTONS
+ else if (event->xbutton.button == Button1) {
+// Left mouse button press
+#else // SWAP_MOUSE_BUTTONS
+ else if (event->xbutton.button == Button3) {
+// Right mouse button press
+#endif // SWAP_MOUSE_BUTTONS
+
+ // Nothing attached here.
+ mouse_zoom = 0;
+ } // End of Button3 Press code
+ }
+// End of ButtonPress code
+
+
+////////////////////////////
+// Start of KeyPress code //
+////////////////////////////
+
+ else if (!done && event->type == KeyPress) {
+
+ // We want to branch from the keysym instead of the keycode
+ (void)XLookupString( (XKeyEvent *)event, buffer, bufsize, &key, &compose );
+ //fprintf(stderr,"main.c:da_input():keycode %d\tkeysym %ld\t%s\n", event->xkey.keycode, key, buffer);
+
+ // keycode ??, keysym 65360 is Home (0x???? on sun kbd)
+// if ((key == 65360) || (key == 0x????)) {
+ if (key == 65360) {
+ if (!map_lock_pan_zoom) {
+ Go_Home(w, NULL, NULL);
+ }
+ }
+
+ // keycode 99, keysym 65365 is PageUp (0xffda on sun kbd)
+ if ((key == 65365) || (key == 0xffda)) {
+ menu_x=input_x;
+ menu_y=input_y;
+ Zoom_out_no_pan( w, client_data, call_data );
+ TrackMouse(w, (XtPointer)text2, event, NULL);
+ }
+
+ // keycode 105, keysym 65366 is PageDown (0xffe0 on sun kbd)
+ if ((key == 65366) || (key == 0xffe0)) {
+ menu_x=input_x;
+ menu_y=input_y;
+ Zoom_in_no_pan( w, client_data, call_data );
+ TrackMouse(w, (XtPointer)text2, event, NULL);
+ }
+
+ // keycode 100, keysym 65361 is left-arrow
+ if ( (key == 65361)
+ || ( (key == 65361) && (event->xkey.state & ShiftMask) ) ) { // Doesn't work yet.
+ if (!map_lock_pan_zoom) {
+ menu_x=input_x;
+ menu_y=input_y;
+ if (event->xbutton.state & ShiftMask) // This doesn't work yet
+ Pan_left_less( w, client_data, call_data);
+ else
+ Pan_left( w, client_data, call_data );
+ TrackMouse(w, (XtPointer)text2, event, NULL);
+ }
+ }
+
+ // keycode 102, keysym 65363 is right-arrow
+ if ( (key == 65363)
+ || ( (key == 65363) && (event->xkey.state & ShiftMask) ) ) { // Doesn't work yet.
+ if (!map_lock_pan_zoom) {
+ menu_x=input_x;
+ menu_y=input_y;
+ if (event->xbutton.state & ShiftMask) // This doesn't work yet
+ Pan_right_less( w, client_data, call_data);
+ else
+ Pan_right( w, client_data, call_data );
+ TrackMouse(w, (XtPointer)text2, event, NULL);
+ }
+ }
+
+ // keycode 98, keysym 65362 is up-arrow
+ if ( (key == 65362)
+ || ( (key == 65362) && (event->xkey.state & ShiftMask) ) ) { // Doesn't work yet.
+ if (!map_lock_pan_zoom) {
+ menu_x=input_x;
+ menu_y=input_y;
+ if (event->xbutton.state & ShiftMask) // This doesn't work yet
+ Pan_up_less( w, client_data, call_data);
+ else
+ Pan_up( w, client_data, call_data );
+ TrackMouse(w, (XtPointer)text2, event, NULL);
+ }
+ }
+
+ // keycode 105, keysym 65364 is down-arrow
+ if ( (key == 65364)
+ || ( (key == 65364) && (event->xkey.state & ShiftMask) ) ) { // Doesn't work yet.
+ if (!map_lock_pan_zoom) {
+ menu_x=input_x;
+ menu_y=input_y;
+ if (event->xbutton.state & ShiftMask) // This doesn't work yet
+ Pan_down_less( w, client_data, call_data);
+ else
+ Pan_down( w, client_data, call_data );
+ TrackMouse(w, (XtPointer)text2, event, NULL);
+ }
+ }
+
+ // keycode 35, keysym 61 is Equals
+ // keycode 35, keysim 43 is Plus
+ // keycode 86, keysim 65451 is KP_Add
+ if (key == 61 || key == 43 || key == 65451) {
+ grid_size++;
+ redraw = 1;
+ }
+
+ // keycode 48, keysym 45 is Minus
+ // keycode 82, keysym 65453 is KP_Subtract
+ if (key == 45 || key == 65453) {
+ grid_size--;
+ redraw = 1;
+ }
+
+ // Adjust map scale, execpt when pan/zoom locked
+ if (!map_lock_pan_zoom && OSM_optimize_key(key)) {
+ if (debug_level & 512) {
+ fprintf(stderr, "Initial scale, before adjustment sx/sy = %li/%li\n", scale_x, scale_y);
+ }
+
+ adj_to_OSM_level(&scale_x, &scale_y);
+
+ if (debug_level & 512) {
+ fprintf(stderr, "Scale adjusted for OSM, sx/sy = %li/%li\n", scale_x, scale_y);
+ }
+ redraw = 1;
+ }
+
+ if ((debug_level & 512) && OSM_report_scale_key(key)) {
+ fprintf(stderr, "scale_x = %li, scale_y = %li, OSM zoom = %i\n",
+ scale_x, scale_y, osm_zoom_level(scale_x));
+ }
+ }
+// End of KeyPress code
+
+
+//////////////////////////////////
+// START OF SOMETHING ELSE CODE //
+//////////////////////////////////
+ else if (!done) { // Something else
+ if (event->type == MotionNotify) {
+ input_x = event->xmotion.x;
+ input_y = event->xmotion.y;
+//fprintf(stderr,"da_input2 x %d y %d\n",input_x,input_y);
+ }
+ } // End of SomethingElse code
+
+
+
+ if (redraw) {
+ /*fprintf(stderr,"Current x %ld y * %ld\n",center_longitude,center_latitude);*/
+
+ // Set the interrupt_drawing_now flag
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+// last_input_event = sec_now() + 2;
+ }
+}
+
+
+
+
+
+
+
+// DK7IN: this function is unused...
+//void wait_sec(int dt) {
+// time_t ct;
+//
+// ct = sec_now() + dt;
+// while (ct < sec_now()) {
+// }
+//}
+
+
+
+
+
+// This function snags the current pointer information and tries to
+// determine whether we're doing some sort of draw or zoom function.
+// If so, draws the appropriate temporary squares or lines that the
+// operator expects.
+//
+void check_pointer_position(void) {
+ Window root_return, child_return;
+ int rootx_return, rooty_return;
+ int win_x_return, win_y_return;
+ unsigned int mask_return;
+ Bool ret;
+ int x_return;
+ int y_return;
+ unsigned int width_return;
+ unsigned int height_return;
+ unsigned int border_width_return;
+ unsigned int depth_return;
+
+
+ // If this variable has not been set, we should not display the
+ // box.
+ if (!possible_zoom_function) {
+ return;
+ }
+
+ // Snag the current pointer info
+ ret = XQueryPointer(XtDisplay(da),
+ XtWindow(da), // Window we are interested in
+ &root_return, // Root window that pointer is in
+ &child_return, // Child windows that pointer is in, if any
+ &rootx_return, // Pointer coord. relative to root window
+ &rooty_return, // Pointer coord. relative to root window
+ &win_x_return, // Pointer coord. relative to specified window
+ &win_y_return, // Pointer coord. relative to specified window
+ &mask_return); // State of modifier keys and pointer buttons
+
+ switch (ret) {
+
+ case True:
+ // If we made it here, we're on the same screen as the
+ // specified window. It's a good start anyway.
+//fprintf(stderr, "x:%d y:%d ", win_x_return, win_y_return);
+//fprintf(stderr, "root:%lx child:%lx ", root_return, child_return);
+//fprintf(stderr, "mask:%03x ret:%02x\n", mask_return, ret);
+
+ // Check mask_return to see if button one is being
+ // pressed down (a drag operation). If so, we're doing
+ // a zoom-in operation and need to draw a box. 0x100
+
+ // Check if button two (middle button) is being pressed
+ // down (a drag operation). If so, we're doing a CAD
+ // Object draw and need to draw a line. 0x200
+
+ // Figure out how to erase previous lines/boxes so that
+ // only the current object is shown. We might need to
+ // keep track of earlier vectors and then redraw them
+ // with an XOR function to erase.
+
+ // Get the dimensions for the drawing area
+ // XGetGeometry(Display *display,
+ // Drawable d,
+ // Window *root_return,
+ // int *x_return,
+ // int *y_return,
+ // unsigned int *width_return,
+ // unsigned int *height_return,
+ // unsigned int *border_width_return,
+ // unsigned int *depth_return);
+ XGetGeometry(XtDisplay(da),
+ XtWindow(da),
+ &root_return,
+ &x_return,
+ &y_return,
+ &width_return,
+ &height_return,
+ &border_width_return,
+ &depth_return);
+
+ // Check that X/Y are positive and below the max size of
+ // the child window.
+ if ( win_x_return >= (int)width_return
+ || win_y_return >= (int)height_return) {
+
+ /*
+ fprintf(stderr, "Out of bounds: %d:%d %d:%d\n",
+ win_x_return,
+ width_return,
+ win_y_return,
+ height_return);
+ */
+ return;
+ }
+ else {
+ // Draw what we need to.
+ // For CAD objects, polygon_last_x and
+ // polygon_last_y contain the last position.
+ // For the zoom-in function, menu_x and menu_y
+ // contain the last position.
+
+ if (draw_CAD_objects_flag) {
+ // Check if button two (middle button) is being
+ // pressed down (a drag operation). If so,
+ // we're doing a CAD Object draw and need to
+ // draw a line. 0x200
+ if ( (mask_return & 0x200) == 0) {
+ return;
+ }
+
+ // Remove the last line drawn (if any). Draw a
+ // line from polygon_last_x and polygon_last_y
+ // to the current pointer position.
+/*
+ (void)XSetLineAttributes(XtDisplay(da), gc_tint, 0, LineSolid, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da), gc_tint, colors[(int)0x0e]); // yellow
+ XDrawLine(XtDisplay(da),
+ XtWindow(da),
+ gc_tint,
+ l16(polygon_last_x),
+ l16(polygon_last_y),
+ l16(win_x_return),
+ l16(win_y_return));
+*/
+ return;
+ }
+ else { // Zoom-in function?
+ // Check mask_return to see if button one is
+ // being pressed down (a drag operation). If
+ // so, we're doing a zoom-in operation and need
+ // to draw a box. 0x100
+#ifdef SWAP_MOUSE_BUTTONS
+ if ( (mask_return & 0x400) == 0) { // Button3
+#else // SWAP_MOUSE_BUTTONS
+ if ( (mask_return & 0x100) == 0) { // Button1
+#endif // SWAP_MOUSE_BUTTONS
+ return;
+ }
+
+ (void)XSetLineAttributes(XtDisplay(da), gc_tint, 1, LineSolid, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da), gc_tint, colors[(int)0x0e]); // yellow
+ (void)XSetFunction(XtDisplay(da), gc_tint, GXxor);
+
+ // Check whether we already have a box on screen
+ // that we need to erase.
+ if (zoom_box_x1 != -1) {
+//fprintf(stderr,"erasing\n");
+ // Remove the last box drawn via the XOR
+ // function.
+ XDrawLine(XtDisplay(da),
+ XtWindow(da),
+ gc_tint,
+ l16(zoom_box_x1), // Keep x constant
+ l16(zoom_box_y1),
+ l16(zoom_box_x1),
+ l16(zoom_box_y2));
+ XDrawLine(XtDisplay(da),
+ XtWindow(da),
+ gc_tint,
+ l16(zoom_box_x1),
+ l16(zoom_box_y1), // Keep y constant
+ l16(zoom_box_x2),
+ l16(zoom_box_y1));
+ XDrawLine(XtDisplay(da),
+ XtWindow(da),
+ gc_tint,
+ l16(zoom_box_x2), // Keep x constant
+ l16(zoom_box_y1),
+ l16(zoom_box_x2),
+ l16(zoom_box_y2));
+ XDrawLine(XtDisplay(da),
+ XtWindow(da),
+ gc_tint,
+ l16(zoom_box_x1),
+ l16(zoom_box_y2), // Keep y constant
+ l16(zoom_box_x2),
+ l16(zoom_box_y2));
+ }
+
+ // Draw a box around the current zoom area.
+ XDrawLine(XtDisplay(da),
+ XtWindow(da),
+ gc_tint,
+ l16(menu_x), // Keep x constant
+ l16(menu_y),
+ l16(menu_x),
+ l16(win_y_return));
+ XDrawLine(XtDisplay(da),
+ XtWindow(da),
+ gc_tint,
+ l16(menu_x),
+ l16(menu_y), // Keep y constant
+ l16(win_x_return),
+ l16(menu_y));
+ XDrawLine(XtDisplay(da),
+ XtWindow(da),
+ gc_tint,
+ l16(win_x_return), // Keep x constant
+ l16(menu_y),
+ l16(win_x_return),
+ l16(win_y_return));
+ XDrawLine(XtDisplay(da),
+ XtWindow(da),
+ gc_tint,
+ l16(menu_x),
+ l16(win_y_return), // Keep y constant
+ l16(win_x_return),
+ l16(win_y_return));
+
+ // Save the values away so that we can erase the
+ // box later.
+ zoom_box_x1 = menu_x;
+ zoom_box_y1 = menu_y;
+ zoom_box_x2 = win_x_return;
+ zoom_box_y2 = win_y_return;
+
+ return;
+ }
+
+ }
+
+ break;
+
+ case BadWindow: // A window passed to the function was no
+ // good.
+ fprintf(stderr, "check_pointer_position: BadWindow\n");
+ return;
+ break;
+
+ case False: // Pointer is not on the same screen as the
+ // specified window.
+ default:
+ return;
+ break;
+
+ }
+} // End of check_pointer_position()
+
+
+
+
+
+// Release ApplicationContext when we are asked to leave
+//
+void clear_application_context(void)
+{
+ if (app_context)
+ XtDestroyApplicationContext(app_context);
+ app_context = NULL;
+}
+
+
+
+time_t stations_status_time = 0;
+static int last_alert_on_screen = -1;
+
+
+// This is the periodic process that updates the maps/symbols/tracks.
+// At the end of the function it schedules itself to be run again.
+void UpdateTime( XtPointer clientData, /*@unused@*/ XtIntervalId id ) {
+ Widget w = (Widget) clientData;
+ time_t nexttime;
+ int do_time;
+ int max;
+ int i;
+ char station_num[30];
+ char line[MAX_LINE_SIZE+1];
+ int line_offset = 0;
+ int n;
+ time_t current_time;
+ int data_length;
+ int data_port;
+ unsigned char data_string[MAX_LINE_SIZE];
+#ifdef HAVE_DB
+ int got_conn; // holds result from openConnection()
+#endif // HAVE_DB
+
+ char temp_file_name[MAX_VALUE];
+
+ do_time = 0;
+
+ // Start UpdateTime again 10 milliseconds after we've completed.
+ // Note: Setting this too low can cause // some systems
+ // (RedHat/FreeBSD) to spin their wheels a lot, using up great
+ // amounts of CPU time. This is heavily dependent on the true
+ // value of the "HZ" value, which is reported as "100" on some
+ // systems even if the kernel is using another value.
+#ifdef __CYGWIN__
+ // Cygwin performance is abysmal if nexttime is lower than 50, almost
+ // acceptable at 200.
+ nexttime = 200;
+#else
+ // Changed from 2 to 10 to fix high CPU usage problems on
+ // FreeBSD.
+ nexttime = 10;
+#endif // __CYGWIN__
+
+
+
+ if (restart_xastir_now) {
+ char bin_path[250];
+
+ clear_application_context();
+ // Restart Xastir in this process space. This is triggered
+ // by receiving a SIGHUP signal to the main process, which
+ // causes the signal handler restart() to run. restart()
+ // shuts down most things nicely and then sets the
+ // restart_xastir_now global variable.
+ //
+ // We need to snag the path to the executable from somewhere
+ // so that we can start up again on a variety of systems.
+ // Trying to get it from argv[0] doesn't work as that ends
+ // up as "xastir" with no path. We therefore get it from
+ // XASTIR_BIN_PATH which we define in configure.ac
+ //
+// execve("/usr/local/bin/xastir", my_argv, my_envp);
+ xastir_snprintf(bin_path,
+ sizeof(bin_path),
+ "%s/bin/xastir",
+ XASTIR_BIN_PATH);
+
+ // Restart this Xastir instance
+ execve(bin_path, my_argv, my_envp);
+ }
+
+
+
+ current_time = sec_now();
+
+ if (last_updatetime > current_time) {
+ // Time just went in the wrong direction. Sleep for a bit
+ // so that we don't use massive CPU until the time catches
+ // up again.
+ //
+ if (time_went_backwards == 0) {
+ char temp[110];
+
+ // This is our first time through UpdateTime() since the
+ // time went in the wrong direction. Dump out a
+ // message to the user.
+ time_went_backwards++;
+ get_timestamp(temp);
+
+ fprintf(stderr,"\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+ fprintf(stderr, "!! System time jumped backwards %d seconds!\n",
+ (int)(last_updatetime - current_time) );
+ fprintf(stderr, "!! Xastir sleeping, else will use excessive CPU\n");
+ fprintf(stderr, "!! %s\n",
+ temp);
+ fprintf(stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n");
+ time_went_backwards++;
+ }
+ usleep(1); // Sleep for 1uS.
+ }
+ else {
+ // Time is behaving normally.
+ last_updatetime = current_time;
+ if (time_went_backwards) {
+ fprintf(stderr,
+ "Xastir is done sleeping due to time reversal.\n\n");
+ }
+ time_went_backwards = 0;
+ }
+
+
+ (void)sound_done();
+
+ if(display_up) {
+
+ if(display_up_first == 0) { // very first call, do initialization
+
+ display_up_first = 1;
+ statusline(langcode("BBARSTA045"), 1); // Loading symbols...
+ load_pixmap_symbol_file("symbols.dat", 0);
+ statusline(langcode("BBARSTA047"), 1); // Initialize my station...
+ my_station_add(my_callsign,my_group,my_symbol,my_long,my_lat,my_phg,my_comment,(char)position_amb_chars);
+ da_resize(w, NULL,NULL); // make sure the size is right after startup & create image
+ set_last_position(); // init last map position
+
+#ifdef HAVE_DB
+//uncomment to enable hardcoded test of writing station to db
+//simpleDbTest();
+#endif /* HAVE_DB */
+ // Restore weather alerts so that we have a clear
+ // picture of the current state. Do this before we
+ // start the interfaces.
+ load_wx_alerts_from_log();
+
+ statusline(langcode("BBARSTA048"), 1); // Start interfaces...
+ startup_all_or_defined_port(-1); // start interfaces
+ }
+
+ else { // Not the first time UpdateTime was called.
+ // Perform the regular updates.
+
+ if (first_time_run) {
+ first_time_run = 0;
+ Configure_station(NULL, NULL, NULL);
+ }
+
+ popup_time_out_check(current_time); // clear popup windows after timeout
+ check_statusline_timeout(current_time); // clear statusline after timeout
+ check_station_remove(current_time); // remove old stations
+ check_message_remove(current_time); // remove old messages
+
+#ifdef USE_RTREE
+ #ifdef HAVE_LIBSHP
+ purge_shp_hash(current_time); // purge stale rtrees
+ #endif // HAVE_LIBSHP
+#endif // USE_RTREE
+
+
+ // We need to always calculate the Aloha circle so that
+ // if it is turned on by the user it will be accurate.
+ calc_aloha(current_time);
+
+
+ //if ( (new_message_data > 0) && ( (delay_time % 2) == 0) )
+ //update_messages(0); // Check Messages, no forced update
+
+
+ // Check whether it's time to expire some weather
+ // alerts. This function will set redraw_on_new_data
+ // and alert_redraw_on_update if any alerts are expired
+ // from the list.
+ (void)alert_expire(current_time);
+
+
+#ifdef HAVE_GPSMAN
+ // Check whether we've just completed a GPS transfer and
+ // have new maps to draw because of it. This function
+ // can cause a complete redraw of the maps.
+ check_for_new_gps_map(current_time);
+
+
+ // Check whether it is time to snag RINO waypoints
+ // again, creating APRS Objects out of them. "0" for
+ // the download interval disables this function.
+ if (RINO_download_interval > 0) {
+ int rino_time = RINO_download_interval * 60;
+
+ if (last_RINO_download + rino_time < current_time) {
+ last_RINO_download = current_time;
+ GPS_operations(NULL, "7", NULL);
+ }
+ }
+#endif // HAVE_GPSMAN
+
+
+ if (xfontsel_query) {
+ Query_xfontsel_pipe();
+ }
+
+
+ // Check on resize requests
+ if (request_resize) {
+// if (last_input_event < current_time) {
+ da_resize_execute(w);
+// }
+ }
+
+
+ if (request_new_image) {
+// if (last_input_event < current_time) {
+ new_image(w);
+// }
+ }
+
+
+ // check on Redraw requests
+ if ( ( (redraw_on_new_data > 1)
+ || (redraw_on_new_data && (current_time > last_redraw + REDRAW_WAIT))
+ || (current_time > next_redraw)
+ || (pending_ID_message && (current_time > remove_ID_message_time)) )
+ && !wait_to_redraw) {
+
+ int temp_alert_count;
+
+
+ //fprintf(stderr,"Redraw on new data\n");
+
+ // Cause refresh_image() to happen if no other
+ // triggers occurred, but enough time has passed.
+ if (current_time > next_redraw) {
+ alert_redraw_on_update++;
+ }
+
+ // check if alert_redraw_on_update is set and it has been at least xx seconds since
+ // last weather alert redraw.
+ if ( (alert_redraw_on_update
+ && !pending_ID_message
+ && ( current_time > ( last_alert_redraw + WX_ALERTS_REFRESH_TIME ) ))
+ || (pending_ID_message && (current_time > remove_ID_message_time)) ) {
+
+
+ // If we got here because of the ID_message
+ // stuff, clear the variable.
+ if (pending_ID_message && (current_time > remove_ID_message_time)) {
+ pending_ID_message = 0;
+ }
+
+ //if (alert_redraw_on_update) {
+ //fprintf(stderr,"Alert redraw on update: %ld\t%ld\t%ld\n",
+ // current_time, last_alert_redraw, WX_ALERTS_REFRESH_TIME);
+
+ if (!pending_ID_message) {
+ refresh_image(da); // Much faster than create_image.
+ (void)XCopyArea(XtDisplay(da),
+ pixmap_final,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+
+ // We just refreshed the screen, so don't
+ // try to erase any zoom-in boxes via XOR.
+ zoom_box_x1 = -1;
+ }
+
+ // Here we use temp_alert_count as a temp holding place for the
+ // count of active alerts. Sound alarm if new alerts are displayed.
+ if ((temp_alert_count = alert_on_screen()) > last_alert_on_screen) {
+ if (sound_play_wx_alert_message)
+ play_sound(sound_command, sound_wx_alert_message);
+#ifdef HAVE_FESTIVAL
+ if (festival_speak_new_weather_alert) {
+ char station_id[50];
+ xastir_snprintf(station_id,
+ sizeof(station_id), "%s, %d",
+ langcode("SPCHSTR009"),
+ temp_alert_count);
+ SayText(station_id);
+ }
+#endif // HAVE_FESTIVAL
+ }
+ last_alert_on_screen = temp_alert_count;
+ alert_redraw_on_update = 0;
+ } else {
+ if (!pending_ID_message)
+ redraw_symbols(w);
+ }
+
+ redraw_on_new_data = 0;
+ next_redraw = current_time+60; // redraw every minute
+ last_redraw = current_time;
+
+ // This assures that we periodically check for expired alerts
+ // and schedule a screen update if we find any.
+ if (alert_display_request()) // should nor be placed in redraw loop !!???
+ alert_redraw_on_update = redraw_on_new_data = 1; // ????
+
+ }
+
+
+ if (initial_load) {
+
+ // Reload saved objects and items from previous runs.
+ // This implements persistent objects.
+ reload_object_item();
+
+#ifdef HAVE_DB
+ // load data from SQL database connections
+ // step through interface list
+ for (i = 0; i < MAX_IFACE_DEVICES; i++){
+ // if interface is a database and is set to load on start then load
+ if (connections_initialized==0) {
+fprintf(stderr,"main, initializing connections");
+ connections_initialized = initConnections();
+ }
+ if (devices[i].device_type == DEVICE_SQL_DATABASE && devices[i].query_on_startup && port_data[i].status==DEVICE_UP) {
+ // load data
+ if (devices[i].connect_on_startup == 1) {
+ // there should be an open connection already
+ if (debug_level & 4096)
+ fprintf(stderr,"Opening (in main) connection [%d] with existing connection [%p]",i,&connections[i]);
+ if (pingConnection(&connections[i])==True) {
+ got_conn = 1;
+ } else {
+ // if (debug_level & 4096)
+ fprintf(stderr,"Ping failed opening new connection [%p]",&connections[i]);
+ got_conn = openConnection(&devices[i],&connections[i]);
+ }
+ } else {
+ if (debug_level & 4096)
+ fprintf(stderr,"Opening (in main) connection [%d] with new connection [%p]",i,&connections[i]);
+ got_conn = openConnection(&devices[i],&connections[i]);
+ }
+ if ((got_conn == 1) && (!(connections[i].type==0))) {
+ getAllSimplePositions(&connections[i]);
+ // if connection worked, it is a oneshot upload of data, so we don't
+ // need to set port_data[].active and .status values here.
+ } else {
+ // report error on this port
+ port_data[i].active = DEVICE_IN_USE;
+ port_data[i].status = DEVICE_ERROR;
+ update_interface_list();
+ }
+ }
+ }
+#endif /* HAVE_DB */
+
+ // Reload any CAD objects from file. This implements
+ // persistent objects.
+ Restore_CAD_Objects_from_file();
+
+ initial_load = 0; // All done!
+ }
+
+
+ if (Display_.dr_data
+ && ((current_time - sec_last_dr_update) > update_DR_rate) ) {
+
+//WE7U: Possible slow-down here w.r.t. dead-reckoning? If
+//update_DR_rate is too quick, we end up looking through all of the
+//stations in station list much too often and using a lot of CPU.
+
+ redraw_on_new_data = 1;
+ sec_last_dr_update = current_time;
+ }
+
+
+ // Look for packet data and check port status
+ display_packet_data();
+ if (delay_time > 15) {
+ interface_status(w);
+ delay_time = 0;
+ // check station lists
+ update_station_scroll_list(); // maybe update lists
+ }
+ delay_time++;
+
+
+ // If active HSP ports, check whether we've been sitting
+ // for longer than XX seconds waiting for GPS data. If
+ // so, the GPS is powered-down, lost lock, or become
+ // disconnected. Go back to listening on the TNC port.
+ //
+ if (current_time > (sec_last_dtr + 2)) { // 2-3 secs
+
+ if (!gps_stop_now) { // No GPS strings parsed
+
+ // GPS listen timeout! Pop us out of GPS listen
+ // mode on all HSP ports. Listen to the TNC for
+ // a while.
+//fprintf(stderr,"1:calling dtr_all_set(0)\n");
+ dtr_all_set(0);
+ sec_last_dtr = current_time;
+ }
+ }
+
+
+ // If we parsed valid GPS data, bring all DTR lines back
+ // to normal for all HSP interfaces (set to receive from
+ // TNC now).
+ if (gps_stop_now) {
+//fprintf(stderr,"2:calling dtr_all_set(0)\n");
+ dtr_all_set(0); // Go back to TNC listen mode
+ sec_last_dtr = current_time;
+ }
+
+
+ // Start the GPS listening process again
+
+ // check gps start up, GPS on GPSPORT
+ if(current_time > sec_next_gps) {
+
+ // Reset the gps good-data flag
+ if (gps_stop_now) {
+ gps_stop_now = 0;
+ }
+
+ //fprintf(stderr,"Check GPS\n");
+
+ // Set dtr lines down
+ // works for SERIAL_GPS and SERIAL_TNC_HSP_GPS?
+
+ // HSP interfaces: Set DTR line for all. DTR will
+ // get reset for each line as valid GPS data gets
+ // parsed on that interface.
+//fprintf(stderr,"3:calling dtr_all_set(1)\n");
+ dtr_all_set(1);
+ sec_last_dtr = current_time; // GPS listen timeout
+
+ for(i=0; i<MAX_IFACE_DEVICES; i++) {
+ if (port_data[i].status) {
+ char tmp[3];
+ int ret1 = 0;
+ int ret2 = 0;
+
+ switch (port_data[i].device_type) {
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ if (devices[i].gps_retrieve != 0) {
+ // Tell TNC to send GPS data
+
+ // Device is correct type and is UP
+ // (or ERROR). Send character to
+ // device (prefixed with CTRL-C so
+ // that we exit CONV if necessary).
+ //
+ if (debug_level & 128) {
+ fprintf(stderr,"Retrieving GPS AUX port %d\n", i);
+ }
+ sprintf(tmp, "%c%c",
+ '\3',
+ devices[i].gps_retrieve);
+
+ if (debug_level & 1) {
+ fprintf(stderr,"Using 0x%02x 0x%02x to retrieve GPS\n",
+ '\3',
+ devices[i].gps_retrieve);
+ }
+ port_write_string(i, tmp);
+ }
+
+ // GPS strings are processed in
+ // UpdateTime function via
+ // gps_data_find(), if the incoming
+ // data is GPS data instead of TNC
+ // data. We need to do nothing
+ // further here.
+
+ break;
+
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ // Check for GPS timing being too
+ // short for HSP interfaces. If to
+ // short, we'll never receive any
+ // TNC data, just GPS data.
+ if (gps_time < 3) {
+ gps_time = 3;
+ popup_message_always(langcode("POPEM00036"),
+ langcode("POPEM00037"));
+ }
+
+ // GPS strings are processed in
+ // UpdateTime function via
+ // gps_data_find(), if the incoming
+ // data is GPS data instead of TNC
+ // data. We need to do nothing
+ // further here.
+
+ break;
+
+ case DEVICE_SERIAL_GPS:
+ case DEVICE_NET_GPSD:
+
+// For each of these we wish to dump their queue to be processed at
+// the gps_time interval. At other times they should be overwriting
+// old data with new and not processing the strings.
+
+ // Process the GPS strings saved by
+ // the channel_data() function.
+ if (gprmc_save_string[0] != '\0')
+ ret1 = gps_data_find(gprmc_save_string,
+ gps_port_save);
+ if (gpgga_save_string[0] != '\0')
+ ret2 = gps_data_find(gpgga_save_string,
+ gps_port_save);
+
+ // Blank out the global variables
+ // (we just processed them).
+ gprmc_save_string[0] = '\0';
+ gpgga_save_string[0] = '\0';
+
+ if (ret1 && ret2) {
+ char temp[200];
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "GPS:GPRMC,GPGGA ");
+ strncat(temp,
+ report_gps_status(),
+ sizeof(temp) - 1 - strlen(temp));
+ statusline(temp, 0);
+ }
+ else if (ret1) {
+ char temp[200];
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "GPS:GPRMC ");
+ strncat(temp,
+ report_gps_status(),
+ sizeof(temp) - 1 - strlen(temp));
+ statusline(temp, 0);
+ }
+ else if (ret2) {
+ char temp[200];
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "GPS:GPGGA ");
+ strncat(temp,
+ report_gps_status(),
+ sizeof(temp) - 1 - strlen(temp));
+ statusline(temp, 0);
+ }
+ else {
+ char temp[200];
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "GPS: ");
+ strncat(temp,
+ report_gps_status(),
+ sizeof(temp) - 1 - strlen(temp));
+ statusline(temp, 0);
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ sec_next_gps = current_time+gps_time;
+ }
+
+ // Check to reestablish a connection
+ if(current_time > net_next_time) {
+ net_last_time = current_time;
+ net_next_time = net_last_time + 300; // Check every five minutes
+ //net_next_time = net_last_time + 30; // This statement is for debug
+
+ //fprintf(stderr,"Checking for reconnects\n");
+ check_ports();
+ }
+
+#ifdef USING_LIBGC
+ // Check for leaks?
+ if(current_time > gc_next_time) {
+ gc_next_time = current_time + 60; // Check every minute
+//fprintf(stderr,"Checking for leaks\n");
+ CHECK_LEAKS();
+ }
+#endif // USING_LIBGC
+
+ // Check to see if it is time to spit out data
+ if(!wait_to_redraw) {
+ if (last_time == 0) {
+ // first update
+ next_time = 120;
+ last_time = current_time;
+ do_time = 1;
+ } else {
+ // check for update
+ //fprintf(stderr,"Checking --- time %ld time to update %ld\n",current_time,last_time+next_time);
+ if(current_time >= (last_time + next_time)) {
+ next_time += next_time;
+ if (next_time > max_transmit_time)
+ next_time = max_transmit_time;
+
+ last_time = current_time;
+ do_time = 1;
+ }
+ }
+ }
+
+ // Time to spit out a posit? If emergency_beacon is enabled
+ // change to a relatively fast fixed beacon rate. Should be
+ // more than a 30-second interval though to avoid digipeater
+ // dupe intervals of 30 seconds.
+ //
+ if ( my_position_valid
+ && ( transmit_now
+ || (emergency_beacon && (current_time > (posit_last_time + 60) ) )
+ || (current_time > posit_next_time && POSIT_rate) ) ) {
+
+ //fprintf(stderr,"Transmitting posit\n");
+
+ // Check for proper symbol in case we're a weather station
+ (void)check_weather_symbol();
+
+ posit_last_time = current_time;
+
+ if (smart_beaconing) {
+ // Schedule next computed posit time based on
+ // speed/turns, etc.
+ posit_next_time = posit_last_time + sb_POSIT_rate;
+ sb_last_heading = sb_current_heading;
+ //fprintf(stderr,"Sending Posit\n");
+ }
+ else {
+ // Schedule next fixed posit time, set in
+ // Configure->Defaults dialog
+ posit_next_time = posit_last_time + POSIT_rate;
+ }
+
+ transmit_now = 0;
+ // Output to ALL net/tnc ports that are enabled & have tx enabled
+//fprintf(stderr,"Sending posit\n");
+ output_my_aprs_data();
+
+ // Decrement the my_position_valid variable if we're
+ // using GPS. This will make sure that positions
+ // are valid, as we'll only get four positions out
+ // maximum per valid GPS position. If the GPS
+ // position goes stale, we'll stop sending posits.
+ // We initialize it to one if we turn on a GPS
+ // interface, so we'll get at the very most one
+ // posit sent out with a stale position, each time
+ // we open a GPS interface.
+ if (using_gps_position && my_position_valid) {
+ my_position_valid--;
+//fprintf(stderr,"my_position_valid:%d\n",my_position_valid);
+
+ if (!my_position_valid) { // We just went to zero!
+ // Waiting for GPS data..
+ statusline(langcode("BBARSTA041"),1);
+
+ // If the user intends to send posits, GPS
+ // interface is enabled, and we're not
+ // getting GPS data, warn the user that
+ // posits are disabled.
+ if (!transmit_disable && !posit_tx_disable) {
+ popup_message_always(langcode("POPEM00033"),
+ langcode("POPEM00034"));
+ }
+//fprintf(stderr,"my_position_valid just went to zero!\n");
+ }
+ }
+ }
+// if (do_time || transmit_now) {
+// transmit_now = 0;
+// // output to ALL net/tnc ports
+// //fprintf(stderr,"Output data\n");
+// output_my_aprs_data();
+// }
+
+ // Must compute rain on a periodic basis, as some
+ // weather daemons don't put out data often enough
+ // to rotate through our queues.
+ // We also refresh the Station_info dialog here if
+ // it is currently drawn.
+ if (current_time >= (last_weather_cycle + 30)) { // Every 30 seconds
+ // Note that we also write timestamps out to all of the log files
+ // from this routine. It works out well with the 30 second update
+ // rate of cycle_weather().
+ (void)cycle_weather();
+ last_weather_cycle = current_time;
+
+ if (station_data_auto_update)
+ update_station_info(w); // Go refresh the Station Info display
+
+ // Time to put out raw WX data ?
+ if (current_time > sec_next_raw_wx) {
+ sec_next_raw_wx = current_time+600;
+
+#ifdef TRANSMIT_RAW_WX
+ if (transmit_raw_wx)
+ tx_raw_wx_data();
+#endif // TRANSMIT_RAW_WX
+
+ // check wx data last received
+ wx_last_data_check();
+ }
+ }
+
+ // is it time to spit out messages?
+ check_and_transmit_messages(current_time);
+
+ // Is it time to spit out any delayed ack's?
+ check_delayed_transmit_queue(current_time);
+
+ // Is it time to spit out objects/items?
+ check_and_transmit_objects_items(current_time);
+
+ // Do we have any new bulletins to display?
+ check_for_new_bulletins(current_time);
+
+ // Is it time to create a JPG snapshot?
+ if (snapshots_enabled)
+ (void)Snapshot();
+
+ // Is it time to create a kml dump of all current stations
+ if (kmlsnapshots_enabled) {
+ if (sec_now() > (last_kmlsnapshot + (snapshot_interval * 60)) ) {
+ last_kmlsnapshot = sec_now(); // Set up timer for next time
+ export_trail_as_kml(NULL);
+ }
+ }
+
+ // Is it time to refresh maps?
+ if ( map_refresh_interval && (current_time > map_refresh_time) ) {
+
+ // Reload maps
+ // Set interrupt_drawing_now because conditions have
+ // changed.
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls
+ // create_image, XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(da)) {
+// (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+
+ map_refresh_time = current_time + map_refresh_interval;
+ }
+
+ // get data from interfaces
+ max=0;
+ // Allow multiple packets to be processed inside this
+ // loop. Well, it was a nice idea anyway. See the
+ // below note.
+
+// CAREFUL HERE: If we try to send to the Spider pipes faster than
+// it's reading from the pipes we corrupt the data out our server
+// ports. Having too high of a number here or putting too small of
+// a delay down lower causes our server port to server up junk!
+
+ while (max < 1 && !XtAppPending(app_context)) {
+ struct timeval tmv;
+
+
+// Check the x_spider server for incoming data
+ if (enable_server_port) {
+ // Check whether the x_spider server pipes have
+ // any data for us. Process if found.
+
+
+// Check the TCP pipe
+ n = readline(pipe_tcp_server_to_xastir, line, MAX_LINE_SIZE);
+ if (n == 0) {
+ // Do nothing, empty packet
+ }
+ else if (n < 0) {
+ //fprintf(stderr,"UpdateTime: Readline error: %d\n",errno);
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ // This is normal if we have no data to read
+ //fprintf(stderr,"EAGAIN or EWOULDBLOCK\n");
+ }
+ else { // Non-normal error. Report it.
+ fprintf(stderr,"UpdateTime: Readline error: %d\n",errno);
+ }
+ }
+ else { // We have a good packet
+ // Knock off the linefeed at the end
+ line[n-1] = '\0';
+
+ if (log_net_data)
+ log_data( get_user_base_dir(LOGFILE_NET,
+ temp_file_name,
+ sizeof(temp_file_name)),
+ (char *)line);
+
+//fprintf(stderr,"TCP server data:%d: %s\n", n, line);
+
+ packet_data_add(langcode("WPUPDPD006"),
+ (char *)line,
+ -1); // data_port -1 signifies x_spider
+
+ // Set port to -2 here to designate that it
+ // came from x_spider. -1 = from a log
+ // file, 0 - 14 = from normal interfaces.
+ decode_ax25_line((char *)line,
+ 'I',
+ -2, // Port -2 signifies x_spider data
+ 1);
+
+ max++; // Count the number of packets processed
+ }
+
+
+// Check the UDP pipe
+ n = readline(pipe_udp_server_to_xastir, line, MAX_LINE_SIZE);
+ if (n == 0) {
+ // Do nothing, empty packet
+ }
+ else if (n < 0) {
+ //fprintf(stderr,"UpdateTime: Readline error: %d\n",errno);
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ // This is normal if we have no data to read
+ //fprintf(stderr,"EAGAIN or EWOULDBLOCK\n");
+ }
+ else { // Non-normal error. Report it.
+ fprintf(stderr,"UpdateTime: Readline error: %d\n",errno);
+ }
+ }
+ else { // We have a good packet
+ char temp_call[10];
+ int skip_decode = 0;
+
+
+ // Knock off the linefeed at the end
+ line[n-1] = '\0';
+
+ // Check for "TO_INET," prefix, then check
+ // for "TO_RF," prefix. Set appropriate
+ // flags and remove the prefixes if found.
+ // x_spider.c will always put them in that
+ // order if both flags are present, so we
+ // don't need to check for the reverse
+ // order.
+
+ // Check for "TO_INET," string
+ if (strncmp(line, "TO_INET,", 8) == 0) {
+// fprintf(stderr,"Xastir received UDP packet with \"TO_INET,\" prefix\n");
+ line_offset += 8;
+//
+// "TO_INET" found.
+// This packet should be gated to the internet if and only if
+// igating is enabled. This may happen automatically as-is, due to
+// the decode_ax25_line() call below. Check whether that's true.
+//
+// We can always add "NOGATE" or "RFONLY" to the path before we dump
+// it to decode_ax25_line() in order to stop this igating...
+//
+ }
+
+ // Check for "TO_RF," string
+ if (strncmp((char *)(line+line_offset), "TO_RF,", 6) == 0) {
+// fprintf(stderr,"Xastir received UDP packet with \"TO_RF,\" prefix\n");
+ line_offset += 6;
+//
+// "TO_RF" found.
+// This packet should be sent out the local RF ports. If the
+// callsign matches Xastir's (without the SSID), then send it out
+// first-person format. If it doesn't, send it out third-party
+// format?
+//
+ // Snag FROM callsign and do a non-exact
+ // match on it against "my_callsign"
+ xastir_snprintf(temp_call,
+ sizeof(temp_call),
+ "%s",
+ (char *)(line+line_offset));
+ if (strchr(temp_call,'>')) {
+ *strchr(temp_call,'>') = '\0';
+ }
+
+// if (is_my_call(temp_call, 0)) { // Match ignoring SSID
+// exact match
+ // Send to RF as direct packet
+//fprintf(stderr,"\tBase callsigns Match! Send to RF as direct packet\n");
+//fprintf(stderr,"\t%s\n", line);
+
+// Change this to go out only RF interfaces so we don't double-up on
+// the INET interfaces? This would require looping on the
+// interfaces and checking type and transmit_enable for each, as is
+// done in output_igate_rf(). If we change to that method,
+// re-enable the decode_ax25_line() call below.
+//
+
+// Change to a third-party packet. In this case we know we have a
+// line_offset, so backing up one to insert a char is ok.
+*(line + line_offset - 1) = '}';
+
+ output_my_data(
+ (char *)(line + line_offset - 1), // Raw data line
+ -1, // ports, -1=send out all interfaces
+ 0, // type: 0=cooked, 1=raw
+ 0, // loopback_only
+ 0, // use_igate_path
+ NULL); // path
+
+//skip_decode++;
+
+ igate_msgs_tx++;
+// }
+// else { // Send to RF as 3rd party packet
+//fprintf(stderr,
+// "\tBase callsigns don't match. Could send to RF as 3rd party packet, but dropping packet for now...\n");
+//fprintf(stderr,"\t%s\n", line);
+
+// Drop the packet for now, until we get more code added to turn it
+// into a 3rd party packet
+
+/*
+ output_igate_rf(temp_call,
+ addr,
+ path,
+ (char *)(line + line_offset),
+ port,
+ 1,
+ NULL);
+
+ igate_msgs_tx++;
+*/
+//continue;
+// }
+ }
+
+ if (log_net_data)
+ log_data( get_user_base_dir(LOGFILE_NET,
+ temp_file_name,
+ sizeof(temp_file_name)),
+ (char *)(line + line_offset));
+
+//fprintf(stderr,"UDP server data: %s\n", line);
+//fprintf(stderr,"\tUDP server data2: %s\n\n", (char *)(line + line_offset));
+
+ packet_data_add(langcode("WPUPDPD006"),
+ (char *)(line + line_offset),
+ -1); // data_port -1 signifies x_spider
+
+// We don't need the below if we call output_my_data with -1 for the
+// port, as in that case it calls decode_ax25_line directly.
+
+if (!skip_decode) {
+
+ // Set port to -2 here to designate that it
+ // came from x_spider. -1 = from a log
+ // file, 0 - 14 = from normal interfaces.
+ decode_ax25_line((char *)(line + line_offset),
+ 'I',
+ -2, // Port -2 signifies x_spider data
+ 1);
+
+ max++; // Count the number of packets processed
+}
+
+ }
+
+
+ }
+// End of x_spider server check code
+
+
+//if (begin_critical_section(&data_lock, "main.c:UpdateTime(1)" ) > 0)
+// fprintf(stderr,"data_lock\n");
+
+
+// Check the rest of the ports for incoming data. Process up to
+// 1000 packets here in a loop.
+
+ data_length = pop_incoming_data(data_string, &data_port);
+
+ if (data_length != 0) {
+ int data_type; // 0=AX25, 1=GPS
+
+ // Terminate the string
+ data_string[data_length] = '\0';
+
+ //fprintf(stderr,"device_type: %d\n",port_data[data_port].device_type);
+
+ switch (port_data[data_port].device_type) {
+ // NET Data stream
+ case DEVICE_NET_STREAM:
+
+ if (log_net_data)
+ log_data(get_user_base_dir(LOGFILE_NET,
+ temp_file_name,
+ sizeof(temp_file_name)),
+ (char *)data_string);
+
+ packet_data_add(langcode("WPUPDPD006"),
+ (char *)data_string,
+ data_port);
+
+//fprintf(stderr,"\n-1 %s", data_string);
+
+ if (enable_server_port) {
+ char new_string[MAX_LINE_SIZE+1];
+
+ // Terminate it with a linefeed
+ xastir_snprintf(new_string,
+ data_length+1,
+ "%s\n",
+ data_string);
+
+//fprintf(stderr,"\n-2 %s", new_string);
+
+ // Send data to the x_spider server
+ if (writen(pipe_xastir_to_tcp_server,
+ new_string,
+ data_length+1) != data_length+1) {
+ if (errno != EPIPE) {
+ fprintf(stderr,
+ "UpdateTime: Writen error (Net send x_spider): %d\n",
+ errno);
+ }
+ }
+//fprintf(stderr,"\n-3 %s", new_string);
+
+ }
+ // End of x_spider server send code
+
+ decode_ax25_line((char *)data_string,
+ 'I',
+ data_port,
+ 1);
+ break;
+
+ // TNC Devices
+ case DEVICE_SERIAL_KISS_TNC:
+ case DEVICE_SERIAL_MKISS_TNC:
+
+ // Try to decode header and checksum. If
+ // bad, break, else continue through to
+ // ASCII logging & decode routines.
+ // Note that the length of data_string
+ // can increase within decode_ax25_header().
+ if ( !decode_ax25_header( (unsigned char *)data_string,
+ &data_length ) ) {
+ // Had a problem decoding it. Drop
+ // it on the floor.
+ break;
+ }
+ else {
+ // Good decode. Drop through to the
+ // next block to log and decode the
+ // packet.
+ }
+
+ case DEVICE_SERIAL_TNC:
+ tnc_data_clean((char *)data_string);
+
+ case DEVICE_AX25_TNC:
+ case DEVICE_NET_AGWPE:
+ if (log_tnc_data)
+ log_data( get_user_base_dir(LOGFILE_TNC,
+ temp_file_name,
+ sizeof(temp_file_name)),
+ (char *)data_string);
+
+ packet_data_add(langcode("WPUPDPD005"),
+ (char *)data_string,
+ data_port);
+
+ if (enable_server_port) {
+ char new_string[MAX_LINE_SIZE+1];
+
+ // Terminate it with a linefeed
+ xastir_snprintf(new_string,
+ MAX_LINE_SIZE+1,
+ "%s\n",
+ data_string);
+
+ // Send data to the x_spider server
+ if (writen(pipe_xastir_to_tcp_server,
+ new_string,
+ data_length+1) != data_length+1) {
+ fprintf(stderr,
+ "UpdateTime: Writen error (TNC Send x_spider): %d\n",
+ errno);
+ }
+ }
+ // End of x_spider server send code
+
+ decode_ax25_line((char *)data_string,
+ 'T',
+ data_port,
+ 1);
+ break;
+
+ case DEVICE_SERIAL_TNC_HSP_GPS:
+ if (port_data[data_port].dtr==1) { // get GPS data
+ char temp[200];
+
+ (void)gps_data_find((char *)data_string,
+ data_port);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "GPS: ");
+ strncat(temp,
+ report_gps_status(),
+ sizeof(temp) - 1 - strlen(temp));
+ statusline(temp, 0);
+ }
+ else {
+ // get TNC data
+ if (log_tnc_data)
+ log_data( get_user_base_dir(LOGFILE_TNC,
+ temp_file_name,
+ sizeof(temp_file_name)),
+ (char *)data_string);
+
+ packet_data_add(langcode("WPUPDPD005"),
+ (char *)data_string,
+ data_port);
+
+ if (enable_server_port) {
+ char new_string[MAX_LINE_SIZE+1];
+
+ // Terminate it with a linefeed
+ xastir_snprintf(new_string,
+ MAX_LINE_SIZE+1,
+ "%s\n",
+ data_string);
+
+ // Send data to the x_spider server
+ if (writen(pipe_xastir_to_tcp_server,
+ new_string,
+ data_length+1) != data_length+1) {
+ fprintf(stderr,
+ "UpdateTime: Writen error(HSP data): %d\n",
+ errno);
+ }
+ }
+ // End of x_spider server send code
+
+ decode_ax25_line((char *)data_string,
+ 'T',
+ data_port,
+ 1);
+ }
+ break;
+
+ case DEVICE_SERIAL_TNC_AUX_GPS:
+ tnc_data_clean((char *)data_string);
+ data_type=tnc_get_data_type((char *)data_string,
+ data_port);
+ if (data_type) { // GPS Data
+ char temp[200];
+
+ (void)gps_data_find((char *)data_string,
+ data_port);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "GPS: ");
+ strncat(temp,
+ report_gps_status(),
+ sizeof(temp) - 1 - strlen(temp));
+ statusline(temp, 0);
+ }
+ else { // APRS Data
+ if (log_tnc_data)
+ log_data( get_user_base_dir(LOGFILE_TNC,
+ temp_file_name,
+ sizeof(temp_file_name)),
+ (char *)data_string);
+
+ packet_data_add(langcode("WPUPDPD005"),
+ (char *)data_string,
+ data_port);
+
+ if (enable_server_port) {
+ char new_string[MAX_LINE_SIZE+1];
+
+ // Terminate it with a linefeed
+ xastir_snprintf(new_string,
+ MAX_LINE_SIZE+1,
+ "%s\n",
+ data_string);
+
+ // Send data to the x_spider server
+ if (writen(pipe_xastir_to_tcp_server,
+ new_string,
+ data_length+1) != data_length+1) {
+ fprintf(stderr,
+ "UpdateTime: Writen error(TNC/GPS data): %d\n",
+ errno);
+ }
+ }
+ // End of x_spider server send code
+
+ decode_ax25_line((char *)data_string,
+ 'T',
+ data_port,
+ 1);
+ }
+ break;
+
+ // GPS Devices
+ case DEVICE_SERIAL_GPS:
+
+ case DEVICE_NET_GPSD:
+ //fprintf(stderr,"GPS Data <%s>\n",data_string);
+ (void)gps_data_find((char *)data_string,
+ data_port);
+ {
+ char temp[200];
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "GPS: ");
+ strncat(temp,
+ report_gps_status(),
+ sizeof(temp) - 1 - strlen(temp));
+ statusline(temp, 0);
+ }
+ break;
+
+ // WX Devices
+ case DEVICE_SERIAL_WX:
+
+ case DEVICE_NET_WX:
+ if (log_wx)
+// TODO: Probably only logs to the first 0x00 byte... Need another
+// logging function that accepts a size, perhaps converting it to
+// 0x00 or similar as it writes to file.
+ log_data( get_user_base_dir(LOGFILE_WX,
+ temp_file_name,
+ sizeof(temp_file_name)),
+ (char *)data_string);
+
+ wx_decode(data_string, data_length, data_port);
+ break;
+
+ default:
+ fprintf(stderr,"Data from unknown source\n");
+ break;
+ }
+ max++; // Count the number of packets processed
+ } else {
+ max=1000; // Go straight to "max": Exit loop
+ }
+
+//if (end_critical_section(&data_lock, "main.c:UpdateTime(2)" ) > 0)
+// fprintf(stderr,"data_lock\n");
+
+ // Do a usleep() here to give the interface threads
+ // time to put something in the queue if they still
+ // have data to process. We also need a delay here
+ // to allow the x_spider code to process packets
+ // we've sent to it.
+
+// NOTE: There's a very delicate balance here between x_spider
+// server, sched_yield(), the delay below, and nexttime. If we feed
+// packets to the x_spider server faster than it gets to process
+// them, we end up with blank lines and corrupted lines going to the
+// connected clients.
+
+ sched_yield(); // Yield to the other threads
+
+ if (enable_server_port) {
+ tmv.tv_sec = 0;
+ tmv.tv_usec = 2000; // Delay 2ms
+ (void)select(0,NULL,NULL,NULL,&tmv);
+ }
+
+ } // End of packet processing loop
+
+ // END- get data from interface
+ // READ FILE IF OPENED
+ if (read_file) {
+ if (current_time >= next_file_read) {
+ read_file_line(read_file_ptr);
+ next_file_read = current_time + REPLAY_DELAY;
+ }
+ }
+ // END- READ FILE IF OPENED
+ }
+
+ // If number of stations has changed, update the status
+ // line, but only once per second max.
+ if (station_count != station_count_save
+ && stations_status_time != current_time) {
+ // show number of stations in status line
+ xastir_snprintf(station_num,
+ sizeof(station_num),
+ langcode("BBARSTH001"),
+ currently_selected_stations,
+ station_count);
+ XmTextFieldSetString(text3, station_num);
+
+ // Set up for next time
+ station_count_save = station_count;
+ stations_status_time = current_time;
+ }
+
+ check_pointer_position();
+ }
+
+ sched_yield(); // Yield the processor to another thread
+
+ (void)XtAppAddTimeOut(XtWidgetToApplicationContext(w),
+ nexttime,
+ (XtTimerCallbackProc)UpdateTime,
+ (XtPointer)w);
+}
+
+
+
+
+
+void shut_down_server(void) {
+
+ // Shut down the server if it was enabled
+ if (tcp_server_pid || udp_server_pid) {
+
+ // Send a kill to the main server process
+ if (tcp_server_pid)
+ kill(tcp_server_pid, SIGHUP);
+
+ if (udp_server_pid)
+ kill(udp_server_pid, SIGHUP);
+
+ wait(NULL); // Reap the status of the process
+
+ // Send to all processes in our process group. This will
+ // cause the server and all of its children to die. Also
+ // causes Xastir to die! Don't do it!
+ //kill(0, 1);
+
+ sleep(1);
+
+ // Send a more forceful kill signal in case the "nice" kill
+ // signal didn't work.
+ if (tcp_server_pid)
+ kill(tcp_server_pid, SIGKILL);
+
+ if (udp_server_pid)
+ kill(udp_server_pid, SIGKILL);
+ }
+}
+
+
+
+
+
+// This is the SIGHUP handler. We restart Xastir if we receive a
+// SIGHUP, hopefully with the same environment that the original
+// Xastir had. We set a global variable, then UpdateTime() is the
+// process that actually calls execve() in order to replace our
+// current process with the new one. This assures that the signal
+// handler gets reset. We can't call execve() from inside the
+// signal handler and have the restart work more than once.
+//
+// This function should be nearly identical to the quit() function
+// below.
+//
+// One strangeness is that this routine gets called when any of the
+// spawned processes get a SIGHUP also, which means when we shut
+// down the TCP/UDP servers or similar. For some reason it still
+// appears to work, even though restart() gets called multiple
+// times when we shut down Xastir or the servers. We probably need
+// to call signal() from outside any signal handlers to tell it to
+// ignore further SIGHUP's.
+//
+static void restart(int sig) {
+
+ char temp_file_name[MAX_VALUE];
+
+// if (debug_level & 1)
+ fprintf(stderr,"Shutting down Xastir...\n");
+
+ save_data();
+
+ // shutdown all interfaces
+ shutdown_all_active_or_defined_port(-1);
+
+ shut_down_server();
+
+#ifdef USE_PID_FILE_CHECK
+ // remove the PID file
+ unlink(get_user_base_dir("xastir.pid", temp_file_name,
+ sizeof(temp_file_name)));
+#endif
+
+#ifdef HAVE_LIBCURL
+ curl_global_cleanup();
+#endif
+
+#ifdef USING_LIBGC
+ CHECK_LEAKS();
+#endif // USING LIBGC
+
+// if (debug_level & 1)
+ fprintf(stderr,"Attempting to restart Xastir...\n");
+
+ // Set the global variable which tells UpdateTime() to do a
+ // restart.
+ //
+ restart_xastir_now++;
+}
+
+
+
+
+
+static void quit(int sig) {
+
+ char temp_file_name[MAX_VALUE];
+
+ if(debug_level & 15)
+ fprintf(stderr,"Caught %d\n",sig);
+
+ save_data();
+
+ // shutdown all interfaces
+ shutdown_all_active_or_defined_port(-1);
+
+ shut_down_server();
+
+
+#ifdef USE_PID_FILE_CHECK
+ // remove the PID file
+ unlink(get_user_base_dir("xastir.pid",temp_file_name,
+ sizeof(temp_file_name)));
+#endif
+
+ if (debug_level & 1)
+ fprintf(stderr,"Exiting Xastir...\n");
+
+#ifdef HAVE_LIBCURL
+ curl_global_cleanup();
+#endif
+
+ clear_application_context();
+#ifdef USING_LIBGC
+ CHECK_LEAKS();
+#endif // USING LIBGC
+
+ exit(sig); // Main exit from the program
+}
+
+
+
+
+
+#ifdef USE_PID_FILE_CHECK
+
+static int pid_file_check(int hold){
+
+ int killret=0;
+ int other_pid=0;
+ char temp[32] ;
+ FILE * PIDFILE ;
+ char temp_file_name[MAX_VALUE];
+
+ /* Save our PID */
+
+ char pidfile_name[MAX_FILENAME];
+
+ xastir_snprintf(pidfile_name, sizeof(pidfile_name),
+ "%s",
+ get_user_base_dir("xastir.pid", temp_file_name,
+ sizeof(temp_file_name)));
+
+ if (filethere(pidfile_name)){
+ fprintf(stderr,"Found pid file: %s\n",pidfile_name);
+ PIDFILE=fopen(pidfile_name,"r");
+ if (PIDFILE!=NULL) {
+ if(!feof(PIDFILE)) {
+ (void)get_line(PIDFILE,temp,32);
+ }
+ (void)fclose(PIDFILE);
+ other_pid=atoi(temp);
+ } else {
+ fprintf(stderr,"Couldn't open file: %s\n", pidfile_name);
+ }
+
+ // send a ping
+ killret = kill(other_pid,0);
+
+#ifdef N8YSZ
+ fprintf(stderr, "other_pid = <%d> killret == <%d> errno == <%d>\n",
+ other_pid,killret,errno);
+#endif
+ if ((killret == -1) && (errno == ESRCH ) && !hold){
+ fprintf(stderr,
+ "Other Xastir process, pid: %d does not appear be running. \n",
+ other_pid);
+ // nuke from orbit
+ if (unlink(pidfile_name)) {
+ fprintf(stderr,"Error unlinking pid file: %s, %d\n",
+ pidfile_name,errno);
+ }
+ } else {
+ fprintf(stderr,
+ "Other Xastir process, pid: %d may be running. Exiting..\n",
+ other_pid);
+
+#ifdef USING_LIBGC
+ CHECK_LEAKS();
+#endif // USING LIBGC
+ exit(-1); // Quick exit from the program
+ }
+
+ } else {
+
+ // if we're here - ok to truncate & open pidfile.
+
+#ifdef N8YSZ
+ fprintf(stderr, "other_pid = <%d> killret == <%d> errno == <%d>\n",
+ other_pid,killret,errno);
+#endif
+
+ PIDFILE = fopen(pidfile_name,"w");
+ if(PIDFILE != NULL){
+ fprintf(PIDFILE, "%d",getpid());
+ (void) fclose (PIDFILE);
+ return(0);
+ } else {
+ fprintf(stderr, "Error opening pidfile: %s\n", strerror(errno) );
+ return(errno);
+ }
+ return(0);
+ }
+ return(0);
+} // end pid_file_check
+
+#endif
+
+
+/* handle segfault signal */
+void segfault(/*@unused@*/ int sig) {
+ fprintf(stderr, "Caught Segfault! Xastir will terminate\n");
+ fprintf(stderr, "Previous incoming line was: %s\n", incoming_data_copy_previous);
+ fprintf(stderr, " Last incoming line was: %s\n", incoming_data_copy);
+ if (dangerous_operation[0] != '\0')
+ fprintf(stderr, "Possibly died at: %s\n", dangerous_operation);
+ fprintf(stderr, "%02d:%02d:%02d\n", get_hours(), get_minutes(), get_seconds() );
+
+ shut_down_server();
+
+ quit(-1);
+}
+
+
+
+
+
+/*
+ Added by KB4AMA
+ Handle USR1 signal. This will cause
+ a snapshot to be generated.
+*/
+#ifndef OLD_PTHREADS
+void usr1sig(int sig) {
+ if (debug_level & 512)
+ fprintf(stderr, "Caught Signal USR1, Doing a snapshot! Signal No %d\n", sig);
+
+ last_snapshot = 0;
+ (void)Snapshot();
+}
+void usr2sig(int sig) {
+ if (debug_level & 512)
+ fprintf(stderr, "Caught Signal USR2, Transmitting now! Signal No %d\n", sig);
+
+ transmit_now = 1;
+}
+#endif // OLD_PTHREADS
+
+
+
+
+
+/********************* dialog position *************************/
+
+void pos_dialog(Widget w) {
+ static Position x,y;
+ Dimension wd, ht;
+ int max_x, max_y;
+
+ XtVaGetValues(appshell, XmNx, &x, XmNy, &y, NULL);
+ XtVaGetValues(appshell, XmNwidth, &wd, XmNheight, &ht, NULL);
+
+ if (x > 1280) // We sometimes get strange values for X/Y
+ x = 300;
+
+ if (y > 1024) // We sometimes get strange values for X/Y
+ y = 200;
+
+ if (wd > 1280) // And for width and height
+ wd = 640;
+
+ if (ht > 1024) // And for width and height
+ ht = 480;
+
+ max_x = x + wd - (wd / 5);
+// max_y = y + ht - (ht / 5);
+ max_y = y + ht/3;
+
+ // Check for proper values for last stored position
+ if ( (last_popup_x < x)
+ || (last_popup_y < y)
+ || (last_popup_x > max_x)
+ || (last_popup_y > max_y) ) {
+ last_popup_x = x + 20; // Go to initial position again
+ last_popup_y = y + 30; // Go to initial position again
+ } else {
+ last_popup_x += 10; // Increment slightly for next dialog
+ last_popup_y += 20; // Increment slightly for next dialog
+ }
+
+ if ((last_popup_y+50) > max_y) {
+ last_popup_x = x + 20; // Go to initial position again
+ last_popup_y = y + 30; // Go to initial position again
+ }
+
+ if ((last_popup_x+50) > max_x) {
+ last_popup_x = x + 20; // Go to initial position again
+ last_popup_y = y + 30; // Go to initial position again
+ }
+
+#ifdef FIXED_DIALOG_STARTUP
+ XtVaSetValues(w,XmNx,x,XmNy,y,NULL);
+#else
+ XtVaSetValues(w,XmNx,last_popup_x,XmNy,last_popup_y,NULL);
+#endif // FIXED_DIALOG_STARTUP
+
+ //fprintf(stderr,"max_x:%d max_y:%d x:%d y:%d wd:%d ht:%d last_x:%d last_y:%d\n",
+ //max_x,max_y,x,y,wd,ht,last_popup_x,last_popup_y);
+}
+
+
+
+/********************* fix dialog size *************************/
+
+void fix_dialog_size(Widget w) {
+ Dimension wd, ht;
+
+ if (XtIsRealized(w)){
+ XtVaGetValues(w,
+ XmNwidth, &wd,
+ XmNheight, &ht,
+ NULL);
+
+ XtVaSetValues(w,
+ XmNminWidth,wd,
+ XmNminHeight,ht,
+ XmNmaxWidth,wd,
+ XmNmaxHeight,ht,
+ NULL);
+ }
+}
+
+
+
+/******************** fix dialog size vertically only *************/
+
+void fix_dialog_vsize(Widget w) {
+ Dimension ht;
+
+ if (XtIsRealized(w)){
+ XtVaGetValues(w,
+ XmNheight, &ht,
+ NULL);
+
+ XtVaSetValues(w,
+ XmNminHeight,ht,
+ XmNmaxHeight,ht,
+ NULL);
+ }
+}
+
+
+
+/**************************************** Button CallBacks *************************************/
+/***********************************************************************************************/
+
+
+/*
+ * Button callback for 1 out of 2 selection
+ */
+void on_off_switch(int switchpos, Widget first, Widget second) {
+ if(switchpos) {
+ XtSetSensitive(first, FALSE);
+ XtSetSensitive(second,TRUE);
+ } else {
+ XtSetSensitive(first, TRUE);
+ XtSetSensitive(second,FALSE);
+ }
+}
+
+
+
+
+
+/*
+ * Button callback for 1 out of 3 selection
+ */
+void sel3_switch(int switchpos, Widget first, Widget second, Widget third) {
+ if(switchpos == 2) {
+ XtSetSensitive(first, FALSE);
+ XtSetSensitive(second,TRUE);
+ XtSetSensitive(third, TRUE);
+ } else if(switchpos == 1) {
+ XtSetSensitive(first, TRUE);
+ XtSetSensitive(second,FALSE);
+ XtSetSensitive(third, TRUE);
+ } else {
+ XtSetSensitive(first, TRUE);
+ XtSetSensitive(second,TRUE);
+ XtSetSensitive(third, FALSE);
+ }
+}
+
+
+/*
+ * Button callback for 1 out of 4 selection
+ */
+void sel4_switch(int switchpos, Widget first, Widget second, Widget third, Widget fourth) {
+ if(switchpos == 3) {
+ XtSetSensitive(first, FALSE);
+ XtSetSensitive(second,TRUE);
+ XtSetSensitive(third, TRUE);
+ XtSetSensitive(fourth, TRUE);
+ } else if(switchpos == 2) {
+ XtSetSensitive(first, TRUE);
+ XtSetSensitive(second,FALSE);
+ XtSetSensitive(third, TRUE);
+ XtSetSensitive(fourth, TRUE);
+ } else if(switchpos == 1) {
+ XtSetSensitive(first, TRUE);
+ XtSetSensitive(second,TRUE);
+ XtSetSensitive(third, FALSE);
+ XtSetSensitive(fourth, TRUE);
+ } else {
+ XtSetSensitive(first, TRUE);
+ XtSetSensitive(second,TRUE);
+ XtSetSensitive(third, TRUE);
+ XtSetSensitive(fourth, FALSE);
+ }
+}
+
+
+
+
+
+// Called by UpdateTime when request_new_image flag is set.
+void new_image(Widget da) {
+
+
+ busy_cursor(appshell);
+
+ // Reset flags
+ interrupt_drawing_now = 0;
+ request_new_image = 0;
+
+
+ // Set up floating point lat/long values to match Xastir
+ // coordinates (speeds things up when dealing with lat/long
+ // values later).
+ convert_from_xastir_coordinates(&f_center_longitude,
+ &f_center_latitude,
+ center_longitude,
+ center_latitude);
+
+ if (create_image(da)) {
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return;
+
+ (void)XCopyArea(XtDisplay(da),
+ pixmap_final,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+
+ // We just refreshed the screen, so don't try to erase any
+ // zoom-in boxes via XOR.
+ zoom_box_x1 = -1;
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now)
+ return;
+
+ display_zoom_status();
+ }
+}
+
+
+
+
+
+/*
+ * Keep map in real world space, readjust center and scaling if neccessary
+ */
+void check_range(void) {
+ Dimension width, height;
+
+
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+
+ // Check the window itself to see if our new y-scale fits it
+ //
+ if ((height*new_scale_y) > 64800000l) {
+
+ // Center between 90�N and 90�S
+ new_mid_y = 64800000l/2;
+
+ // Adjust y-scaling so that we fit perfectly in the window
+ new_scale_y = 64800000l / height;
+ }
+
+ if ((new_mid_y < (height*new_scale_y)/2))
+ new_mid_y = (height*new_scale_y)/2; // upper border max 90�N
+
+ if ((new_mid_y + (height*new_scale_y)/2) > 64800000l)
+ new_mid_y = 64800000l-((height*new_scale_y)/2); // lower border max 90�S
+
+ // Adjust scaling based on latitude of new center
+ new_scale_x = get_x_scale(new_mid_x,new_mid_y,new_scale_y); // recalc x scaling depending on position
+
+ if (debug_level & 512) {
+ fprintf(stderr,"checkrange- x:%ld\ty:%ld\n\n",new_scale_x,new_scale_y);
+ }
+
+// // scale_x will always be bigger than scale_y, so no problem here...
+// if ((width*new_scale_x) > 129600000l) {
+// // Center between 180�W and 180�E
+// new_mid_x = 129600000l/2;
+// }
+
+
+// The below code causes the map image to snap to the left or right
+// of the display. I'd rather see the scale factor changed so that
+// the map fits perfectly left/right in the display, so that we
+// cannot go past the edges of the earth. Change the code to work
+// this way later. We'll have to compute new_y_scale from the
+// new_x_scale once we scale X appropriately, then will probably
+// have to test the y scaling again?
+
+
+/*
+ // Check against left border
+ if ((new_mid_x < (width*new_scale_x)/2)) {
+ // This will cause the map image to snap to the left of the
+ // display.
+ new_mid_x = (width*new_scale_x)/2; // left border max 180�W
+ }
+ else {
+ // Check against right border
+ if ((new_mid_x + (width*new_scale_x)/2) > 129600000l)
+ // This will cause the map image to snap to the right of
+ // the display.
+ new_mid_x = 129600000l-((width*new_scale_x)/2); // right border max 180�E
+ }
+*/
+
+
+// long NW_corner_longitude; // Longitude at top NW corner of map screen
+// long NW_corner_latitude; // Latitude at top NW corner of map screen
+
+/*
+if (NW_corner_longitude < 0l) {
+// fprintf(stderr,"left\n");
+ NW_corner_longitude = 0l; // New left viewpoint edge
+ new_mid_x = 0l + ((width*new_scale_x) / 2); // New midpoint
+}
+if ( (NW_corner_longitude + (width*new_scale_x) ) > 129600000l) {
+// fprintf(stderr,"right\n");
+ NW_corner_longitude = 129600000l - (width*new_scale_x); // New left viewpoint edge
+ new_mid_x = 129600000l - ((width*new_scale_x) / 2); // New midpoint
+}
+*/
+
+// Find the four corners of the map in the new scale system. Make
+// sure they are on the display, but not well inside the borders of
+// the display.
+
+// We keep getting center_longitude out of range when zooming out
+// and having the edge of the world map to the right of the middle
+// of the window. This shows up in new_image() above during the
+// convert_from_xastir_coordinates() call. new_mid_x is the data of
+// interest in this routine.
+
+}
+
+
+
+
+
+/*
+ * Display a new map view after checking the view and scaling
+ */
+void display_zoom_image(int recenter) {
+ Dimension width, height;
+
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+//fprintf(stderr,"Before, x: %lu, y: %lu\n",new_scale_x,new_scale_y);
+ check_range(); // keep map inside world and calc x scaling
+//fprintf(stderr,"After, x: %lu, y: %lu\n\n",new_scale_x,new_scale_y);
+ if (new_mid_x != center_longitude
+ || new_mid_y != center_latitude
+ || new_scale_x != scale_x
+ || new_scale_y != scale_y) { // If there's been a change in zoom or center
+
+ set_last_position();
+
+ if (recenter) {
+ center_longitude = new_mid_x; // new map center
+ center_latitude = new_mid_y;
+ }
+ scale_x = new_scale_x;
+ scale_y = new_scale_y;
+
+ setup_in_view(); // update "in view" flag for all stations
+
+ // Set the interrupt_drawing_now flag
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+// last_input_event = sec_now() + 2;
+
+ } else { // No change in zoom or center. Don't update ANYTHING.
+ }
+}
+
+
+
+
+
+void Zoom_in( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ Dimension width, height;
+
+ if(display_up) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ new_mid_x = center_longitude - ((width *scale_x)/2) + (menu_x*scale_x);
+ new_mid_y = center_latitude - ((height*scale_y)/2) + (menu_y*scale_y);
+ new_scale_y = scale_y / 2;
+ if (new_scale_y < 1)
+ new_scale_y = 1; // don't go further in
+ display_zoom_image(1); // check range and do display, recenter
+ }
+}
+
+
+
+
+
+void Zoom_in_no_pan( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ Dimension width, height;
+
+ if(display_up && !map_lock_pan_zoom) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ new_mid_x = center_longitude;
+ new_mid_y = center_latitude;
+ new_scale_y = scale_y / 2;
+ if (new_scale_y < 1)
+ new_scale_y = 1; // don't go further in, scale_x always bigger than scale_y
+ display_zoom_image(0); // check range and do display, keep center
+ }
+}
+
+
+
+
+
+void Zoom_out( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ Dimension width, height;
+
+ if(display_up) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ new_mid_x = center_longitude - ((width *scale_x)/2) + (menu_x*scale_x);
+ new_mid_y = center_latitude - ((height*scale_y)/2) + (menu_y*scale_y);
+ if (width*scale_x < 129600000l || height*scale_y < 64800000l)
+ new_scale_y = scale_y * 2;
+ else
+ new_scale_y = scale_y; // don't zoom out if whole world could be shown
+ display_zoom_image(1); // check range and do display, recenter
+ }
+}
+
+
+
+
+
+void Zoom_out_no_pan( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ Dimension width, height;
+
+ if(display_up && !map_lock_pan_zoom) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ new_mid_x = center_longitude;
+ new_mid_y = center_latitude;
+ if (width*scale_x < 129600000l || height*scale_y < 64800000l)
+ new_scale_y = scale_y * 2;
+ else
+ new_scale_y = scale_y; // don't zoom out if whole world could be shown
+ display_zoom_image(0); // check range and do display, keep center
+ }
+}
+
+
+
+
+
+void Custom_Zoom_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ custom_zoom_dialog = (Widget)NULL;
+}
+
+
+
+
+
+static Widget custom_zoom_zoom_level;
+
+
+
+
+
+void Custom_Zoom_do_it( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char *temp_ptr;
+
+ temp_ptr = XmTextFieldGetString(custom_zoom_zoom_level);
+ scale_y = atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ new_scale_y = scale_y;
+ display_zoom_image(1);
+}
+
+
+
+
+
+// Function to bring up a dialog. User can then select zoom for the
+// display directly.
+//
+void Custom_Zoom( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ static Widget pane,form, button_ok, button_cancel, zoom_label;
+// Arg al[50]; /* Arg List */
+// unsigned int ac = 0; /* Arg Count */
+ Atom delw;
+ char temp[50];
+
+ if(!custom_zoom_dialog) {
+
+ // "Custom Zoom"
+ custom_zoom_dialog = XtVaCreatePopupShell(langcode("POPUPMA034"),
+ xmDialogShellWidgetClass,
+ appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNresize, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Jump_location pane",
+ xmPanedWindowWidgetClass,
+ custom_zoom_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ form = XtVaCreateWidget("Jump_location form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 2,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // "Zoom Level"
+ zoom_label = XtVaCreateManagedWidget(langcode("POPUPMA004"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ custom_zoom_zoom_level = XtVaCreateManagedWidget("Custom_Zoom zoom_level",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns,6,
+ XmNwidth,((6*7)+2),
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, zoom_label,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("JMLPO00002"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, zoom_label,
+ XmNtopOffset,15,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, zoom_label,
+ XmNtopOffset,15,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNrightOffset, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_cancel, XmNactivateCallback, Custom_Zoom_destroy_shell, custom_zoom_dialog);
+ XtAddCallback(button_ok, XmNactivateCallback, Custom_Zoom_do_it, NULL);
+
+ pos_dialog(custom_zoom_dialog);
+
+ delw = XmInternAtom(XtDisplay(custom_zoom_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(custom_zoom_dialog, delw, Custom_Zoom_destroy_shell, (XtPointer)custom_zoom_dialog);
+
+
+ // Snag the current zoom value, convert them to
+ // displayable values, and fill in the fields.
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%ld",
+ scale_y);
+ XmTextFieldSetString(custom_zoom_zoom_level, temp);
+
+
+ XtManageChild(form);
+ XtManageChild(pane);
+
+ XtPopup(custom_zoom_dialog,XtGrabNone);
+ fix_dialog_size(custom_zoom_dialog);
+
+ // Move focus to the Close button. This appears to
+ // highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit
+ // the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(custom_zoom_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else {
+ XtPopup(custom_zoom_dialog,XtGrabNone);
+ (void)XRaiseWindow(XtDisplay(custom_zoom_dialog), XtWindow(custom_zoom_dialog));
+ }
+}
+
+
+
+
+
+void Zoom_level( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ Dimension width, height;
+ int level;
+
+ level=atoi((char *)clientData);
+ if(display_up) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ new_mid_x = center_longitude - ((width *scale_x)/2) + (menu_x*scale_x);
+ new_mid_y = center_latitude - ((height*scale_y)/2) + (menu_y*scale_y);
+ switch(level) {
+ case(1):
+ new_scale_y = 1;
+ break;
+
+ case(2):
+ new_scale_y = 16;
+ break;
+
+ case(3):
+ new_scale_y = 64;
+ break;
+
+ case(4):
+ new_scale_y = 256;
+ break;
+
+ case(5):
+ new_scale_y = 1024;
+ break;
+
+ case(6):
+ new_scale_y = 8192;
+ break;
+
+ case(7):
+
+//WE7U
+// Here it'd be good to calculate what zoom level the entire world
+// would best fit in, instead of fixing the scale to a particular
+// amount. Figure out which zoom level would fit in the X and the Y
+// direction, and then pick the higher zoom level of the two (to
+// make sure the world fits in both). We should probably center at
+// 0.0N/0.0W as well.
+
+ new_scale_y = 500000;
+
+ // Center on Earth (0/0)
+// new_mid_x = 12900000l / 2;
+// new_mid_y = 6480000l / 2;
+ break;
+
+ case(8): // 10% out
+ new_scale_y = (int)(scale_y * 1.1);
+ if (new_scale_y == scale_y)
+ new_scale_y++;
+ break;
+
+ case(9): // 10% in
+ new_scale_y = (int)(scale_y * 0.9);
+ // Don't allow the user to go in further than zoom 1
+ if (new_scale_y < 1)
+ new_scale_y = 1;
+ break;
+
+ // Pop up a new dialog that allows the user to select
+ // the zoom level, then causes that zoom level and the
+ // right-click mouse location to take effect on the map
+ // window. Similar to the Center_Zoom function but with
+ // the mouse coordinates instead of the center of the
+ // screen.
+ case(10): // Custom Zoom Level
+
+ // Pop up a new dialog that allows the user to
+ // select the zoom level, then causes that zoom
+ // level and the right-click mouse location to take
+ // effect on the map window. Similar to the
+ // Center_Zoom function but with the mouse
+ // coordinates instead of the center of the screen.
+
+ // Set up new_scale_y for whatever custom zoom level
+ // the user has chosen, then call
+ // display_zoom_image() from the callback there.
+ //
+ Custom_Zoom( w, clientData, calldata);
+ return;
+ break;
+
+ default:
+ break;
+ }
+ display_zoom_image(1); // check range and do display, recenter
+ }
+}
+
+
+
+
+
+void Pan_ctr( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ Dimension width, height;
+
+ if(display_up) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ new_mid_x = center_longitude - ((width *scale_x)/2) + (menu_x*scale_x);
+ new_mid_y = center_latitude - ((height*scale_y)/2) + (menu_y*scale_y);
+ new_scale_y = scale_y; // keep size
+ display_zoom_image(1); // check range and do display, recenter
+ }
+}
+
+
+
+
+
+void Pan_up( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ Dimension width, height;
+
+ if(display_up) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ new_mid_x = center_longitude;
+ new_mid_y = center_latitude - (height*scale_y/4);
+ new_scale_y = scale_y; // keep size
+ display_zoom_image(1); // check range and do display, recenter
+ }
+}
+
+
+
+
+
+void Pan_up_less( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ Dimension width, height;
+
+ if(display_up && !map_lock_pan_zoom) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ new_mid_x = center_longitude;
+ new_mid_y = center_latitude - (height*scale_y/10);
+ new_scale_y = scale_y; // keep size
+ display_zoom_image(1); // check range and do display, recenter
+ }
+}
+
+
+
+
+
+void Pan_down( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ Dimension width, height;
+
+ if(display_up) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ new_mid_x = center_longitude;
+ new_mid_y = center_latitude + (height*scale_y/4);
+ new_scale_y = scale_y; // keep size
+ display_zoom_image(1); // check range and do display, recenter
+ }
+}
+
+
+
+
+
+void Pan_down_less( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ Dimension width, height;
+
+ if(display_up && !map_lock_pan_zoom) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ new_mid_x = center_longitude;
+ new_mid_y = center_latitude + (height*scale_y/10);
+ new_scale_y = scale_y; // keep size
+ display_zoom_image(1); // check range and do display, recenter
+ }
+}
+
+
+
+
+
+void Pan_left( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ Dimension width, height;
+
+ if(display_up) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ new_mid_x = center_longitude - (width*scale_x/4);
+ new_mid_y = center_latitude;
+ new_scale_y = scale_y; // keep size
+ display_zoom_image(1); // check range and do display, recenter
+ }
+}
+
+
+
+
+
+void Pan_left_less( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ Dimension width, height;
+
+ if(display_up && !map_lock_pan_zoom) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ new_mid_x = center_longitude - (width*scale_x/10);
+ new_mid_y = center_latitude;
+ new_scale_y = scale_y; // keep size
+ display_zoom_image(1); // check range and do display, recenter
+ }
+}
+
+
+
+
+
+void Pan_right( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ Dimension width, height;
+
+ if(display_up) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ new_mid_x = center_longitude + (width*scale_x/4);
+ new_mid_y = center_latitude;
+ new_scale_y = scale_y; // keep size
+ display_zoom_image(1); // check range and do display, recenter
+ }
+}
+
+
+
+
+
+void Pan_right_less( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ Dimension width, height;
+
+ if(display_up && !map_lock_pan_zoom) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ new_mid_x = center_longitude + (width*scale_x/10);
+ new_mid_y = center_latitude;
+ new_scale_y = scale_y; // keep size
+ display_zoom_image(1); // check range and do display, recenter
+ }
+}
+
+
+
+
+
+void Center_Zoom_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ center_zoom_dialog = (Widget)NULL;
+}
+
+
+
+
+
+static Widget center_zoom_latitude,
+ center_zoom_longitude,
+ center_zoom_zoom_level;
+
+
+
+
+
+void Center_Zoom_do_it( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ unsigned long x, y;
+ char *temp_ptr;
+
+
+ temp_ptr = XmTextFieldGetString(center_zoom_latitude);
+ f_center_latitude = atof(temp_ptr);
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(center_zoom_longitude);
+ f_center_longitude = atof(temp_ptr);
+ XtFree(temp_ptr);
+
+ //Convert to Xastir coordinate system for lat/long
+ convert_to_xastir_coordinates(&x,
+ &y,
+ f_center_longitude,
+ f_center_latitude);
+
+ temp_ptr = XmTextFieldGetString(center_zoom_zoom_level);
+ scale_y = atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ new_mid_x = x;
+ new_mid_y = y;
+ new_scale_y = scale_y;
+ display_zoom_image(1);
+}
+
+
+
+
+
+void Go_Home( Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ DataRow *p_station;
+
+ if (!map_lock_pan_zoom) {
+ if (search_station_name(&p_station,my_callsign,1)) {
+ set_map_position(w, p_station->coord_lat, p_station->coord_lon);
+ }
+ }
+}
+
+
+
+
+
+// Function to bring up a dialog. User can then select the center
+// and zoom for the display directly.
+//
+// Later it would be nice to have a "Calc" button so that the user
+// could input lat/long in any of the supported formats. Right now
+// it is DD.DDDD format only.
+//
+void Center_Zoom( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ static Widget pane,form, button_ok, button_cancel,
+ lat_label, lon_label, zoom_label;
+// Arg al[50]; /* Arg List */
+// unsigned int ac = 0; /* Arg Count */
+ Atom delw;
+ char temp[50];
+
+ if(!center_zoom_dialog) {
+
+ // "Center & Zoom"
+ center_zoom_dialog = XtVaCreatePopupShell(langcode("POPUPMA026"),
+ xmDialogShellWidgetClass,
+ appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNresize, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Jump_location pane",
+ xmPanedWindowWidgetClass,
+ center_zoom_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ form = XtVaCreateWidget("Jump_location form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 2,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // "Latitude"
+ lat_label = XtVaCreateManagedWidget(langcode("POPUPMA027"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ center_zoom_latitude = XtVaCreateManagedWidget("Center_Zoom latitude",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns,21,
+ XmNwidth,((21*7)+2),
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, lat_label,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Longitude"
+ lon_label = XtVaCreateManagedWidget(langcode("POPUPMA028"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, lat_label,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ center_zoom_longitude = XtVaCreateManagedWidget("Center_Zoom longitude",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns,21,
+ XmNwidth,((21*7)+2),
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, lat_label,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, lon_label,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Zoom Level"
+ zoom_label = XtVaCreateManagedWidget(langcode("POPUPMA004"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, lon_label,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ center_zoom_zoom_level = XtVaCreateManagedWidget("Center_Zoom zoom_level",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns,21,
+ XmNwidth,((21*7)+2),
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, lon_label,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, zoom_label,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("JMLPO00002"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, zoom_label,
+ XmNtopOffset,15,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, zoom_label,
+ XmNtopOffset,15,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNrightOffset, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_cancel, XmNactivateCallback, Center_Zoom_destroy_shell, center_zoom_dialog);
+ XtAddCallback(button_ok, XmNactivateCallback, Center_Zoom_do_it, NULL);
+
+ pos_dialog(center_zoom_dialog);
+
+ delw = XmInternAtom(XtDisplay(center_zoom_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(center_zoom_dialog, delw, Center_Zoom_destroy_shell, (XtPointer)center_zoom_dialog);
+
+
+ if (center_zoom_override) { // We've found a Map View
+ // "eyeball" object and are
+ // doing a center/zoom based on
+ // that object's info. Grab the
+ // pointer to the object which
+ // is in calldata.
+ DataRow *p_station = (DataRow *)calldata;
+ float f_latitude, f_longitude;
+ int range;
+ Dimension width, height;
+ long x, x0, y, y0;
+ double x_miles, y_miles, distance;
+ char temp_course[10];
+ double scale_factor;
+ long my_scale_y;
+ int fell_off = 0;
+
+
+//fprintf(stderr,"Map View Object: %s\n",p_station->call_sign);
+
+ center_zoom_override = 0;
+
+
+ // Snag the objects values, convert them to displayable
+ // values, and fill in the fields.
+ convert_from_xastir_coordinates(&f_longitude,
+ &f_latitude,
+ p_station->coord_lon,
+ p_station->coord_lat);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%f",
+ f_latitude);
+ XmTextFieldSetString(center_zoom_latitude, temp);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%f",
+ f_longitude);
+ XmTextFieldSetString(center_zoom_longitude, temp);
+
+ // Compute the approximate zoom level we need from the
+ // range value in the object. Range is in miles.
+ range = atoi(&p_station->power_gain[3]);
+
+ // We should be able to compute the distance across the
+ // screen that we currently have, then compute an
+ // accurate zoom level that will give us the range we
+ // want.
+
+ // Find out the screen values
+ XtVaGetValues(da,XmNwidth, &width, XmNheight, &height, NULL);
+
+ // Convert points to Xastir coordinate system
+
+ // X
+ x = center_longitude - ((width *scale_x)/2);
+
+ // Check for the edge of the earth
+ if (x < 0) {
+ x = 0;
+ fell_off++; // Fell off the edge of the earth
+ }
+
+ x0 = center_longitude; // Center of screen
+
+ // Y
+ y = center_latitude - ((height*scale_y)/2);
+
+ // Check for the edge of the earth
+ if (y < 0) {
+ y = 0;
+ fell_off++; // Fell off the edge of the earth
+ }
+
+ y0 = center_latitude; // Center of screen
+
+ // Compute distance from center to each edge
+
+ // X distance. Keep Y constant.
+ x_miles = cvt_kn2len
+ * calc_distance_course(y0,
+ x0,
+ y0,
+ x,
+ temp_course,
+ sizeof(temp_course));
+
+ // Y distance. Keep X constant.
+ y_miles = cvt_kn2len
+ * calc_distance_course(y0,
+ x0,
+ y,
+ x0,
+ temp_course,
+ sizeof(temp_course));
+
+ // Choose the smaller distance
+ if (x_miles < y_miles) {
+ distance = x_miles;
+ }
+ else {
+ distance = y_miles;
+ }
+//fprintf(stderr,"Current screen range: %f\n", distance);
+//fprintf(stderr,"Desired screen range: %d\n", range);
+
+// Note that these numbers will be off if we're zoomed out way too
+// far (edges of the earth are inside the screen view).
+
+ // Now we know the range of the current screen
+ // (distance) in miles. Compute what we need from
+ // "distance" (screen) and "range" (object) in order to
+ // get a scale factor we can apply to our zoom numbers.
+ if (distance < range) {
+//fprintf(stderr,"Zooming out\n");
+ scale_factor = (range * 1.0)/distance;
+// fprintf(stderr,"Scale Factor: %f\n", scale_factor);
+ my_scale_y = (long)(scale_y * scale_factor);
+ }
+ else { // distance > range
+//fprintf(stderr,"Zooming in\n");
+ scale_factor = distance/(range * 1.0);
+//fprintf(stderr,"Scale Factor: %f\n", scale_factor);
+ my_scale_y = (long)(scale_y / scale_factor);
+ }
+
+ if (my_scale_y < 1)
+ my_scale_y = 1;
+
+//fprintf(stderr,"my_scale_y: %ld\n", my_scale_y);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%ld",
+ my_scale_y);
+ XmTextFieldSetString(center_zoom_zoom_level, temp);
+ }
+ else {
+ // Normal user-initiated center/zoom function
+
+ // Snag the current lat/long/center values, convert them to
+ // displayable values, and fill in the fields.
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%f",
+ f_center_latitude);
+ XmTextFieldSetString(center_zoom_latitude, temp);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%f",
+ f_center_longitude);
+ XmTextFieldSetString(center_zoom_longitude, temp);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%ld",
+ scale_y);
+ XmTextFieldSetString(center_zoom_zoom_level, temp);
+ }
+
+
+ XtManageChild(form);
+ XtManageChild(pane);
+
+ XtPopup(center_zoom_dialog,XtGrabNone);
+ fix_dialog_size(center_zoom_dialog);
+
+ // Move focus to the Close button. This appears to
+ // highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit
+ // the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(center_zoom_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else {
+ XtPopup(center_zoom_dialog,XtGrabNone);
+ (void)XRaiseWindow(XtDisplay(center_zoom_dialog), XtWindow(center_zoom_dialog));
+ }
+}
+
+
+
+
+
+void SetMyPosition( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+
+ Dimension width, height;
+ long my_new_latl, my_new_lonl;
+
+ // check for fixed station
+ //if ( (output_station_type == 0) || (output_station_type > 3)) {
+ // popup_message( "Modify fixed position", "Are you sure you want to modify your position?");
+ //}
+ // check for position abiguity
+ if ( position_amb_chars > 0 ) { // popup warning that ambiguity is on
+ popup_message_always(langcode("POPUPMA043"), // "Modify ambiguous position"
+ langcode("POPUPMA044") ); // "Position abiguity is on, your new position may appear to jump."
+ }
+
+ if(display_up) {
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ my_new_lonl = (center_longitude - ((width *scale_x)/2) + (menu_x*scale_x));
+ my_new_latl = (center_latitude - ((height*scale_y)/2) + (menu_y*scale_y));
+ // Check if we are still on the planet...
+ if ( my_new_latl > 64800000l ) my_new_latl = 64800000l;
+ if ( my_new_latl < 0 ) my_new_latl = 0;
+ if ( my_new_lonl > 129600000l ) my_new_lonl = 129600000l;
+ if ( my_new_lonl < 0 ) my_new_lonl = 0;
+
+ convert_lon_l2s( my_new_lonl, my_long, sizeof(my_long), CONVERT_HP_NOSP);
+ convert_lat_l2s( my_new_latl, my_lat, sizeof(my_lat), CONVERT_HP_NOSP);
+
+ // Update my station data with the new lat/lon
+ my_station_add(my_callsign,my_group,my_symbol,my_long,my_lat,my_phg,my_comment,(char)position_amb_chars);
+ redraw_on_new_data=2;
+ }
+}
+
+
+
+
+
+void Window_Quit( /*@unused@*/ Widget w, /*@unused@*/ XtPointer client, /*@unused@*/ XtPointer calldata) {
+ quit(0);
+}
+
+
+
+
+
+void Menu_Quit( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ quit(0);
+}
+
+
+
+
+
+void save_state( /*@unused@*/ Widget w, /*@unused@*/ XtPointer client, /*@unused@*/ XtPointer calldata) {
+ if (((XtCheckpointToken)calldata)->shutdown) {
+ save_data();
+
+ // shutdown all interfaces
+ shutdown_all_active_or_defined_port(-1);
+
+ shut_down_server();
+ }
+
+}
+
+
+
+
+
+// Turn on or off map border, callback from map_border_button.
+void Map_border_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ draw_labeled_grid_border = TRUE;
+ else
+ draw_labeled_grid_border = FALSE;
+
+ redraw_symbols(da);
+}
+
+
+
+void Grid_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ long_lat_grid = atoi(which);
+ else
+ long_lat_grid = 0;
+
+ if (long_lat_grid) {
+ statusline(langcode("BBARSTA005"),1); // Map Lat/Long Grid On
+ XtSetSensitive(map_border_button,TRUE);
+ }
+ else {
+ statusline(langcode("BBARSTA006"),2); // Map Lat/Long Grid Off
+ XtSetSensitive(map_border_button,FALSE);
+ }
+
+ redraw_symbols(da);
+ (void)XCopyArea(XtDisplay(da),
+ pixmap_final,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+}
+
+
+
+
+// Callback from menu buttons that allow user to turn on or off the
+// global display of CAD objects and their metadata on the map.
+void CAD_draw_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ // turn on or off display of cad objects
+ if (strcmp(which,"CAD_draw_objects")==0) {
+ CAD_draw_objects = state->set;
+ }
+
+ // turn on or off display of standard metadata
+ if (strcmp(which,"CAD_show_label")==0) {
+ CAD_show_label = state->set;
+ }
+ if (strcmp(which,"CAD_show_raw_probability")==0) {
+ CAD_show_raw_probability = state->set;
+ }
+ if (strcmp(which,"CAD_show_comment")==0) {
+ CAD_show_comment = state->set;
+ }
+ if (strcmp(which,"CAD_show_area")==0) {
+ CAD_show_area = state->set;
+ }
+
+ // redraw objects on the current base maps
+ redraw_symbols(da);
+}
+
+
+
+
+
+void Map_lock_pan_zoom_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ map_lock_pan_zoom = atoi(which);
+ XtSetSensitive(zoom_in_menu, FALSE);
+ XtSetSensitive(zoom_out_menu, FALSE);
+ XtSetSensitive(pan_left_menu, FALSE);
+ XtSetSensitive(pan_up_menu, FALSE);
+ XtSetSensitive(pan_down_menu, FALSE);
+ XtSetSensitive(pan_right_menu, FALSE);
+ }
+ else {
+ map_lock_pan_zoom = 0;
+ XtSetSensitive(zoom_in_menu, TRUE);
+ XtSetSensitive(zoom_out_menu, TRUE);
+ XtSetSensitive(pan_left_menu, TRUE);
+ XtSetSensitive(pan_up_menu, TRUE);
+ XtSetSensitive(pan_down_menu, TRUE);
+ XtSetSensitive(pan_right_menu, TRUE);
+ }
+}
+
+
+
+
+
+void Map_disable_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ disable_all_maps = atoi(which);
+ }
+ else {
+ disable_all_maps = 0;
+ }
+
+ request_new_image++;
+
+// if (create_image(da)) {
+// (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+}
+
+
+
+
+
+void Map_auto_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ map_auto_maps = atoi(which);
+ XtSetSensitive(map_auto_skip_raster_button,TRUE);
+ }
+ else {
+ map_auto_maps = 0;
+ XtSetSensitive(map_auto_skip_raster_button,FALSE);
+ }
+
+ re_sort_maps = 1;
+
+ // Set interrupt_drawing_now because conditions have changed.
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(da)) {
+// (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+
+ if (map_auto_maps)
+ statusline(langcode("BBARSTA007"),1); // The use of Auto Maps is now on
+ else
+ statusline(langcode("BBARSTA008"),2); // The use of Auto Maps is now off
+}
+
+
+
+
+
+void Map_auto_skip_raster_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ auto_maps_skip_raster = atoi(which);
+ else
+ auto_maps_skip_raster = 0;
+
+ re_sort_maps = 1;
+
+ // Set interrupt_drawing_now because conditions have changed.
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(da)) {
+// (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+}
+
+
+
+
+
+void Map_levels_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ map_color_levels = atoi(which);
+ else
+ map_color_levels = 0;
+
+ if (map_color_levels)
+ statusline(langcode("BBARSTA009"),1); // The use of Auto Maps is now on
+ else
+ statusline(langcode("BBARSTA010"),2); // The use of Auto Maps is now off
+
+ // Set interrupt_drawing_now because conditions have changed.
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(da)) {
+// (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+}
+
+
+
+
+
+void Map_labels_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ map_labels = atoi(which);
+ else
+ map_labels = 0;
+
+ // Set interrupt_drawing_now because conditions have changed.
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(da)) {
+// (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+}
+
+
+
+
+
+void Map_fill_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ map_color_fill = atoi(which);
+ else
+ map_color_fill = 0;
+
+ if (map_color_fill)
+ statusline(langcode("BBARSTA009"),1); // The use of Map Color Fill is now On
+ else
+ statusline(langcode("BBARSTA010"),1); // The use of Map Color Fill is now Off
+
+ // Set interrupt_drawing_now because conditions have changed.
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(da)) {
+// (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+}
+
+
+
+
+
+void Map_background( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ int bgcolor;
+ int i;
+
+ bgcolor=atoi((char *)clientData);
+
+ if(display_up){
+ for (i=0;i<12;i++){
+ if (i == bgcolor)
+ XtSetSensitive(map_bgcolor[i],FALSE);
+ else
+ XtSetSensitive(map_bgcolor[i],TRUE);
+ }
+ map_background_color=bgcolor;
+
+ // Set interrupt_drawing_now because conditions have changed.
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(da)) {
+// (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+ }
+}
+
+
+
+
+
+#if !defined(NO_GRAPHICS)
+void Raster_intensity(Widget w, XtPointer clientData, XtPointer calldata) {
+ float my_intensity;
+ int i;
+
+ my_intensity=atof((char *)clientData);
+
+ if(display_up){
+ for (i=0;i<11;i++){
+ if (i == (int)((float)(my_intensity * 10.01)) )
+ XtSetSensitive(raster_intensity[i],FALSE);
+ else
+ XtSetSensitive(raster_intensity[i],TRUE);
+
+ //fprintf(stderr,"Change to index: %d\n", (int)((float)(my_intensity * 10.01)));
+ }
+
+ raster_map_intensity=my_intensity;
+ //fprintf(stderr,"raster_map_intensity = %f\n", raster_map_intensity);
+
+ // Set interrupt_drawing_now because conditions have changed.
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(da)) {
+// XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+ }
+}
+#endif // NO_GRAPHICS
+
+
+
+
+
+void Map_station_label( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ int style;
+
+ style=atoi((char *)clientData);
+
+ if(display_up){
+ letter_style = style;
+ sel3_switch(letter_style,map_station_label2,map_station_label1,map_station_label0);
+ redraw_symbols(da);
+ (void)XCopyArea(XtDisplay(da),
+ pixmap_final,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ }
+}
+
+
+
+
+
+void Map_icon_outline( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ int style;
+
+ style=atoi((char *)clientData);
+
+ if(display_up){
+ icon_outline_style = style;
+ sel4_switch(icon_outline_style,map_icon_outline3,map_icon_outline2,map_icon_outline1,map_icon_outline0);
+ redraw_symbols(da);
+ (void)XCopyArea(XtDisplay(da),
+ pixmap_final,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ }
+ statusline( langcode("BBARSTA046"), 1); // Reloading symbols...
+ load_pixmap_symbol_file("symbols.dat", 1);
+ redraw_symbols(da);
+ (void)XCopyArea(XtDisplay(da),
+ pixmap_final,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+}
+
+
+
+
+
+void Map_wx_alerts_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ wx_alert_style = !(atoi(which));
+ else
+ wx_alert_style = 1;
+
+ if (display_up) {
+ refresh_image(da);
+ (void)XCopyArea(XtDisplay(da),
+ pixmap_final,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ }
+}
+
+
+
+
+
+void Index_maps_on_startup_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ index_maps_on_startup = 1;
+ else
+ index_maps_on_startup = 0;
+}
+
+
+
+
+
+void TNC_Transmit_now( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ transmit_now = 1; /* toggle transmission of station now*/
+}
+
+
+
+
+
+/////////////////////////////////////////////////////////////////////
+// GPS operations
+/////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#ifdef HAVE_GPSMAN
+
+// Function to process the RINO.gpstrans file. We'll create APRS
+// objects out of them as if our own callsign created them. Lines
+// in the file look like this (spaces removed):
+//
+// W N3EG3 20-JUN-02 17:55 07/08/2004 13:03:29 46.1141682 -122.9384817
+// W N3JGI 20-JUN-02 18:29 07/08/2004 13:03:29 48.0021644 -116.0118324
+//
+// Fields are:
+// W name Comment Date/Time Latitude Longitude
+//
+void process_RINO_waypoints(void) {
+ FILE *f;
+ char temp[MAX_FILENAME * 2];
+ char line[301];
+ float UTC_Offset;
+ char temp_file_name[MAX_VALUE];
+
+// char datum[50];
+
+
+ // Just to be safe
+ line[300] = '\0';
+
+ // Create the full path/filename
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s/RINO.gpstrans",
+ get_user_base_dir("gps", temp_file_name, sizeof(temp_file_name)));
+
+ f=fopen(temp,"r"); // Open for reading
+
+ if (f == NULL) {
+ fprintf(stderr,
+ "Couldn't open %s file for reading\n",
+ temp);
+ return;
+ }
+
+ // Process the file line-by-line here. The format for gpstrans
+ // files as written by GPSMan appears to be:
+ //
+ // "W"
+ // Waypoint name
+ // Comment field (Date/Time is default on Garmins)
+ // Date/Time
+ // Decimal latitude
+ // Decimal longitude
+ //
+ while (fgets(line, 300, f) != NULL) {
+
+ // Snag the "Format:" line at the top of the file:
+ // Format: DDD UTC Offset: -8.00 hrs Datum[100]: WGS 84
+ //
+ if (strncmp(line,"Format:",7) == 0) {
+ int i = 7;
+ char temp2[50];
+
+
+ // Find the ':' after "UTC Offset"
+ while (line[i] != ':'
+ && line[i] != '\0'
+ && line[i] != '\n'
+ && line[i] != '\r') {
+ i++;
+ }
+ i++;
+
+ // Skip white space
+ while (line[i] == ' '
+ && line[i] != '\0'
+ && line[i] != '\n'
+ && line[i] != '\r') {
+ i++;
+ }
+
+ // Copy UTC offset chars into temp2
+ temp2[0] = '\0';
+ while (line[i] != '\t'
+ && line[i] != ' '
+ && line[i] != '\0'
+ && line[i] != '\n'
+ && line[i] != '\r') {
+ strncat(temp2,&line[i],1);
+ i++;
+ }
+
+ UTC_Offset = atof(temp2);
+
+//fprintf(stderr,"UTC Offset: %f\n", UTC_Offset);
+
+// NOTE: This would be the place to snag the datum as well.
+
+ }
+
+ // Check for a waypoint entry
+ else if (line[0] == 'W') {
+ char name[50];
+ char datetime[50];
+ char lat_c[20];
+ char lon_c[20];
+ int i = 1;
+
+
+// NOTE: We should check for the end of the string, skipping this
+// iteration of the loop if we haven't parsed enough fields.
+
+ // Find non-white-space character
+ while ((line[i] == '\t' || line[i] == ' ')
+ && line[i] != '\0'
+ && line[i] != '\n'
+ && line[i] != '\r') {
+ i++;
+ }
+
+ // Copy into name until tab or whitespace char. We're
+ // assuming that a waypoint name can't have spaces in
+ // it.
+ name[0] = '\0';
+ while (line[i] != '\t'
+ && line[i] != ' '
+ && line[i] != '\0'
+ && line[i] != '\n'
+ && line[i] != '\r') {
+ strncat(name,&line[i],1);
+ i++;
+ }
+
+ // Find tab character at end of name field
+ while (line[i] != '\t'
+ && line[i] != '\0'
+ && line[i] != '\n'
+ && line[i] != '\r') {
+ i++;
+ }
+ i++;
+
+ // We skip the comment field, doing nothing with the
+ // data.
+ //
+ // Find tab character at end of comment field
+ while (line[i] != '\t'
+ && line[i] != '\0'
+ && line[i] != '\n'
+ && line[i] != '\r') {
+ i++;
+ }
+ i++;
+
+ // Find non-white-space character
+ while ((line[i] == '\t' || line[i] == ' ')
+ && line[i] != '\0'
+ && line[i] != '\n'
+ && line[i] != '\r') {
+ i++;
+ }
+
+// Snag date/time. Use it in the object date/time field.
+ // Copy into datetime until tab char. Include the space
+ // between the time and date portions.
+ datetime[0] = '\0';
+ while (line[i] != '\t'
+ && line[i] != '\0'
+ && line[i] != '\n'
+ && line[i] != '\r') {
+ strncat(datetime,&line[i],1);
+ i++;
+ }
+
+ // Find tab character at end of date/time field
+ while (line[i] != '\t'
+ && line[i] != '\0'
+ && line[i] != '\n'
+ && line[i] != '\r') {
+ i++;
+ }
+ i++;
+
+ // Find non-white-space character
+ while ((line[i] == '\t' || line[i] == ' ')
+ && line[i] != '\0'
+ && line[i] != '\n'
+ && line[i] != '\r') {
+ i++;
+ }
+
+ // Copy into lat_c until white space char
+ lat_c[0] = '\0';
+ while (line[i] != '\t'
+ && line[i] != ' '
+ && line[i] != '\0'
+ && line[i] != '\n'
+ && line[i] != '\r') {
+ strncat(lat_c,&line[i],1);
+ i++;
+ }
+
+ // Find non-white-space character
+ while ((line[i] == '\t' || line[i] == ' ')
+ && line[i] != '\0'
+ && line[i] != '\n'
+ && line[i] != '\r') {
+ i++;
+ }
+
+ // Copy into lon_c until tab character
+ lon_c[0] = '\0';
+ while (line[i] != '\t'
+ && line[i] != ' '
+ && line[i] != '\0'
+ && line[i] != '\n'
+ && line[i] != '\r') {
+ strncat(lon_c,&line[i],1);
+ i++;
+ }
+ i++;
+
+/*
+ fprintf(stderr,
+ "%s\t%f\t%f\n",
+ name,
+ atof(lat_c),
+ atof(lon_c));
+*/
+
+
+// For now we're hard-coding the RINO group to "APRS". Any RINO
+// waypoints that begin with these four characters will have those
+// four characters chopped and will be turned into our own APRS
+// object, which we will then attempt to transmit.
+
+ if (strncmp(name,"APRS",4) == 0) {
+ // We have a match. Turn this into an APRS Object
+ char line2[100];
+ int lat_deg, lon_deg;
+ float lat_min, lon_min;
+ char lat_dir, lon_dir;
+ char temp2[50];
+ int date;
+ int hour;
+ int minute;
+// Three variables used for Base-91 compressed strings. We have a
+// bug in this code at the moment so the Base-91 compressed code in
+// this routine is commented out.
+// char *compressed_string;
+// char lat_s[50];
+// char lon_s[50];
+
+
+ // Strip off the "APRS" at the beginning of the
+ // name. Add spaces to flush out the length of an
+ // APRS object name.
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s ",
+ &name[4]);
+
+ // Copy it back to the "name" variable.
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ temp2);
+
+ // Truncate the name at nine characters.
+ name[9] = '\0';
+
+ // We can either snag the UTC Offset from the top of
+ // the file, or we can put the date/time format into
+ // local time. The spec suggests using zulu time
+ // for all future implementations, so we snagged the
+ // UTC Offset earlier in this routine.
+
+ // 07/09/2004 09:22:28
+//fprintf(stderr,"%s %s", name, datetime);
+
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ &datetime[3]);
+ temp2[2] = '\0';
+ date = atoi(temp2);
+//fprintf(stderr, "%02d\n", date);
+
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ &datetime[11]);
+ temp2[2] = '\0';
+ hour = atoi(temp2);
+
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ &datetime[14]);
+ temp2[2] = '\0';
+ minute = atoi(temp2);
+//fprintf(stderr,"\t\t%02d%02d%02d/\n", date, hour, minute);
+
+ // We need to remember to bump the date up if we go
+ // past midnight adding the UTC offset. In that
+ // case we may need to bump the day as well if we're
+ // near the end of the month. Use the Unix time
+ // facilities for this?
+
+ // Here we're assuming that the UTC offset is
+ // divisible by one hour. Always correct?
+
+// hour = (int)(hour - UTC_Offset);
+
+
+ lat_deg = atoi(lat_c);
+ if (lat_deg < 0)
+ lat_deg = -lat_deg;
+
+ lon_deg = atoi(lon_c);
+ if (lon_deg < 0)
+ lon_deg = -lon_deg;
+
+ lat_min = atof(lat_c);
+ if (lat_min < 0.0)
+ lat_min = -lat_min;
+ lat_min = (lat_min - lat_deg) * 60.0;
+
+ lon_min = atof(lon_c);
+ if (lon_min < 0.0)
+ lon_min = -lon_min;
+ lon_min = (lon_min - lon_deg) * 60.0;
+
+ if (lat_c[0] == '-')
+ lat_dir = 'S';
+ else
+ lat_dir = 'N';
+
+ if (lon_c[0] == '-')
+ lon_dir = 'W';
+ else
+ lon_dir = 'E';
+
+ // Non-Compressed version
+ xastir_snprintf(line2,
+ sizeof(line2),
+ ";%-9s*%02d%02d%02d/%02d%05.2f%c%c%03d%05.2f%c%c",
+ name,
+ date,
+ hour,
+ minute,
+ lat_deg, // Degrees
+ lat_min, // Minutes
+ lat_dir, // N/S
+ '/', // Primary symbol table
+ lon_deg, // Degrees
+ lon_min, // Minutes
+ lon_dir, // E/W
+ '['); // Hiker symbol
+
+/*
+ // Compressed version. Gives us more of the
+ // resolution inherent in the RINO waypoints.
+ // Doesn't have an affect on whether we transmit
+ // compressed objects from Xastir over RF. That is
+ // selected from the File->Configure->Defaults
+ // dialog.
+ //
+ // compress_posit expects its lat/long in //
+ // APRS-like format:
+ // "%2d%lf%c", °, &minutes, &ext
+
+ xastir_snprintf(lat_s,
+ sizeof(lat_s),
+ "%02d%8.5f%c",
+ lat_deg,
+ lat_min,
+ lat_dir);
+
+ xastir_snprintf(lon_s,
+ sizeof(lon_s),
+ "%02d%8.5f%c",
+ lon_deg,
+ lon_min,
+ lon_dir);
+
+ compressed_string = compress_posit(lat_s,
+ '/', // group character
+ lon_s,
+ '[', // symbol,
+ 0, // course,
+ 0, // speed,
+ ""); // phg
+
+//fprintf(stderr, "compressed: %s\n", compressed_string);
+
+ xastir_snprintf(line2,
+ sizeof(line2),
+ ";%-9s*%02d%02d%02d/%s",
+ name,
+ date,
+ hour,
+ minute,
+ compressed_string);
+*/
+
+/*
+ fprintf(stderr,
+ "%-9s\t%f\t%f\t\t\t\t\t\t",
+ name,
+ atof(lat_c),
+ atof(lon_c));
+ fprintf(stderr,"%s\n",line2);
+*/
+
+ // Update this object in our save file
+ log_object_item(line2,0,name);
+
+ if (object_tx_disable)
+ output_my_data(line2,-1,0,1,0,NULL); // Local loopback only, not igating
+ else
+ output_my_data(line2,-1,0,0,0,NULL); // Transmit/loopback object data, not igating
+ }
+ }
+ }
+
+//fprintf(stderr,"\n");
+
+ (void)fclose(f);
+}
+
+
+
+
+
+void GPS_operations_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ GPS_operations_dialog = (Widget)NULL;
+}
+
+
+
+
+
+// Set up gps_map_filename based on user preferences for filename
+// and map color.
+void GPS_operations_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ char *temp;
+ char short_filename[MAX_FILENAME];
+ char color_text[50];
+
+
+ temp = XmTextGetString(gpsfilename_text);
+ xastir_snprintf(short_filename,
+ sizeof(short_filename),
+ "%s",
+ temp);
+ XtFree(temp);
+
+ // Add date/time to filename if no filename is given
+ if (strlen(short_filename) == 0) {
+ int ii;
+
+ // Compute the date/time and put in string
+ get_timestamp(short_filename);
+
+ // Change spaces to underlines
+ // Wed Mar 5 15:24:48 PST 2003
+ for (ii = 0; ii < (int)strlen(short_filename); ii++) {
+ if (short_filename[ii] == ' ')
+ short_filename[ii] = '_';
+ }
+ }
+
+ (void)remove_trailing_spaces(short_filename);
+
+ switch (gps_map_color) {
+ case 0: {
+ xastir_snprintf(color_text,sizeof(color_text),"Red");
+ gps_map_color_offset=0x0c;
+ break;
+ }
+ case 1: {
+ xastir_snprintf(color_text,sizeof(color_text),"Green");
+ gps_map_color_offset=0x23;
+ break;
+ }
+ case 2: {
+ xastir_snprintf(color_text,sizeof(color_text),"Black");
+ gps_map_color_offset=0x08;
+ break;
+ }
+ case 3: {
+ xastir_snprintf(color_text,sizeof(color_text),"White");
+ gps_map_color_offset=0x0f;
+ break;
+ }
+ case 4: {
+ xastir_snprintf(color_text,sizeof(color_text),"Orange");
+ gps_map_color_offset=0x62;
+ break;
+ }
+ case 5: {
+ xastir_snprintf(color_text,sizeof(color_text),"Blue");
+ gps_map_color_offset=0x03;
+ break;
+ }
+ case 6: {
+ xastir_snprintf(color_text,sizeof(color_text),"Yellow");
+ gps_map_color_offset=0x0e;
+ break;
+ }
+ case 7: {
+ xastir_snprintf(color_text,sizeof(color_text),"Purple");
+ gps_map_color_offset=0x0b;
+ break;
+ }
+ default: {
+ xastir_snprintf(color_text,sizeof(color_text),"Red");
+ gps_map_color_offset=0x0c;
+ break;
+ }
+ }
+
+ // If doing waypoints, don't add the color onto the end
+ if (strcmp("Waypoints",gps_map_type) == 0) {
+ xastir_snprintf(gps_map_filename,
+ sizeof(gps_map_filename),
+ "%s_%s.shp",
+ short_filename,
+ gps_map_type);
+
+ // Same without ".shp"
+ xastir_snprintf(gps_map_filename_base,
+ sizeof(gps_map_filename_base),
+ "%s_%s",
+ short_filename,
+ gps_map_type);
+ }
+ else { // Doing Tracks/Routes
+ xastir_snprintf(gps_map_filename,
+ sizeof(gps_map_filename),
+ "%s_%s_%s.shp",
+ short_filename,
+ gps_map_type,
+ color_text);
+
+ // Same without ".shp"
+ xastir_snprintf(gps_map_filename_base,
+ sizeof(gps_map_filename_base),
+ "%s_%s_%s",
+ short_filename,
+ gps_map_type,
+ color_text);
+
+ // Same without ".shp" *or* color
+ xastir_snprintf(gps_map_filename_base2,
+ sizeof(gps_map_filename_base2),
+ "%s_%s",
+ short_filename,
+ gps_map_type);
+ }
+
+//fprintf(stderr,"%s\t%s\n",gps_map_filename,gps_map_filename_base);
+
+ // Signify that the user has selected the filename and color for
+ // the downloaded file.
+ gps_details_selected++;
+
+ GPS_operations_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void GPS_operations_cancel(Widget widget, XtPointer clientData, XtPointer callData) {
+
+ // Destroy the GPS selection dialog
+ GPS_operations_destroy_shell(widget,clientData,callData);
+
+ // Wait for the GPS operation to be finished, then clear out all
+ // of the variables.
+ while (!gps_got_data_from && gps_operation_pending) {
+ usleep(1000000); // 1 second
+ }
+
+ gps_details_selected = 0;
+ gps_got_data_from = 0;
+ gps_operation_pending = 0;
+}
+
+
+
+
+
+void GPS_operations_color_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ gps_map_color = atoi(which);
+ else
+ gps_map_color = 0;
+}
+
+
+
+
+
+// This routine should be called while the transfer is progressing,
+// or perhaps just after it ends. If we can do it while the
+// transfer is ocurring we can save time overall. Here we'll select
+// the color and name for the resulting file, then cause it to be
+// selected and displayed on the map screen.
+//
+void GPS_transfer_select( void ) {
+ static Widget pane, my_form, button_select, button_cancel,
+ frame, color_type, type_box, ctyp0, ctyp1,
+ ctyp2, ctyp3, ctyp4, ctyp5, ctyp6, ctyp7,
+ gpsfilename_label;
+ Atom delw;
+ Arg al[50]; // Arg List
+ register unsigned int ac = 0; // Arg Count
+
+
+ if (!GPS_operations_dialog) {
+
+ // Set args for color
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ GPS_operations_dialog = XtVaCreatePopupShell(
+ langcode("GPS001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget(
+ "GPS_transfer_select pane",
+ xmPanedWindowWidgetClass,
+ GPS_operations_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget(
+ "GPS_transfer_select my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ gpsfilename_label = XtVaCreateManagedWidget( // Filename
+ langcode("GPS002"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ gpsfilename_text = XtVaCreateManagedWidget(
+ "GPS_transfer_select gpsfilename_text",
+ xmTextWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 20,
+ XmNwidth, ((20*7)+2),
+ XmNmaxLength, 200,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, gpsfilename_label,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ frame = XtVaCreateManagedWidget(
+ "GPS_transfer_select frame",
+ xmFrameWidgetClass,
+ my_form,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, gpsfilename_label,
+ XmNtopOffset,15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ color_type = XtVaCreateManagedWidget( // Select Color
+ langcode("GPS003"),
+ xmLabelWidgetClass,
+ frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ type_box = XmCreateRadioBox(
+ frame,
+ "GPS_transfer_select Transmit Options box",
+ al,
+ ac);
+
+ XtVaSetValues(type_box,
+ XmNnumColumns,2,
+ NULL);
+
+ ctyp0 = XtVaCreateManagedWidget( // Red
+ langcode("GPS004"),
+ xmToggleButtonGadgetClass,
+ type_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ctyp0,XmNvalueChangedCallback,GPS_operations_color_toggle,"0");
+
+ ctyp1 = XtVaCreateManagedWidget( // Green
+ langcode("GPS005"),
+ xmToggleButtonGadgetClass,
+ type_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ctyp1,XmNvalueChangedCallback,GPS_operations_color_toggle,"1");
+
+ ctyp2 = XtVaCreateManagedWidget( // Black
+ langcode("GPS006"),
+ xmToggleButtonGadgetClass,
+ type_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ctyp2,XmNvalueChangedCallback,GPS_operations_color_toggle,"2");
+
+ ctyp3 = XtVaCreateManagedWidget( // White
+ langcode("GPS007"),
+ xmToggleButtonGadgetClass,
+ type_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ctyp3,XmNvalueChangedCallback,GPS_operations_color_toggle,"3");
+
+ ctyp4 = XtVaCreateManagedWidget( // Orange
+ langcode("GPS008"),
+ xmToggleButtonGadgetClass,
+ type_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ctyp4,XmNvalueChangedCallback,GPS_operations_color_toggle,"4");
+
+ ctyp5 = XtVaCreateManagedWidget( // Blue
+ langcode("GPS009"),
+ xmToggleButtonGadgetClass,
+ type_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ctyp5,XmNvalueChangedCallback,GPS_operations_color_toggle,"5");
+
+ ctyp6 = XtVaCreateManagedWidget( // Yellow
+ langcode("GPS010"),
+ xmToggleButtonGadgetClass,
+ type_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ctyp6,XmNvalueChangedCallback,GPS_operations_color_toggle,"6");
+
+ ctyp7 = XtVaCreateManagedWidget( // Violet
+ langcode("GPS011"),
+ xmToggleButtonGadgetClass,
+ type_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ctyp7,XmNvalueChangedCallback,GPS_operations_color_toggle,"7");
+
+
+ button_select = XtVaCreateManagedWidget(
+ langcode("WPUPCFS028"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ button_cancel = XtVaCreateManagedWidget(
+ langcode("UNIOP00002"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_select,
+ XmNactivateCallback,
+ GPS_operations_change_data,
+ GPS_operations_dialog);
+
+ XtAddCallback(button_cancel,
+ XmNactivateCallback,
+ GPS_operations_cancel,
+ GPS_operations_dialog);
+
+ // Set default color to first selection
+ XmToggleButtonSetState(ctyp0,TRUE,FALSE);
+ gps_map_color = 0;
+
+ // De-sensitize the color selections if we're doing
+ // waypoints.
+ if (strcmp("Waypoints",gps_map_type) == 0) {
+ XtSetSensitive(frame, FALSE);
+ }
+
+ pos_dialog(GPS_operations_dialog);
+
+ delw = XmInternAtom(
+ XtDisplay(GPS_operations_dialog),
+ "WM_DELETE_WINDOW",
+ FALSE);
+
+ XmAddWMProtocolCallback(
+ GPS_operations_dialog,
+ delw,
+ GPS_operations_destroy_shell,
+ (XtPointer)GPS_operations_dialog);
+
+ XtManageChild(my_form);
+ XtManageChild(type_box);
+ XtManageChild(pane);
+
+ XtPopup(GPS_operations_dialog,XtGrabNone);
+ fix_dialog_size(GPS_operations_dialog);
+
+ // Move focus to the Select button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(GPS_operations_dialog);
+ XmProcessTraversal(button_select, XmTRAVERSE_CURRENT);
+
+ } else {
+ (void)XRaiseWindow(
+ XtDisplay(GPS_operations_dialog),
+ XtWindow(GPS_operations_dialog));
+ }
+}
+
+
+
+
+time_t check_gps_map_time = (time_t)0;
+
+
+// Function called by UpdateTime periodically. Checks whether
+// we've just completed a GPS transfer and need to redraw maps as a
+// result.
+//
+void check_for_new_gps_map(int curr_sec) {
+
+ // Only check once per second
+ if (check_gps_map_time == curr_sec) {
+ return; // Skip it, we already checked once this second.
+ }
+ check_gps_map_time = curr_sec;
+
+
+ if ( (gps_operation_pending || gps_got_data_from)
+ && !gps_details_selected) {
+
+ // A transfer is underway or has just completed. The user
+ // hasn't selected the filename/color yet. Bring up the
+ // selection dialog so that the user can do so.
+ GPS_transfer_select();
+ }
+ else if (gps_details_selected
+ && gps_got_data_from
+ && !gps_operation_pending) {
+ FILE *f;
+ char temp[MAX_FILENAME * 2];
+ char gps_base_dir[MAX_VALUE];
+ char temp_file_name[MAX_VALUE];
+
+ get_user_base_dir("gps",gps_base_dir, sizeof(gps_base_dir));
+//fprintf(stderr,"check_for_new_gps_map()\n");
+
+
+ // We have new data from a GPS! Add the file to the
+ // selected maps file, cause a reload of the maps to occur,
+ // and then re-index maps (so that map may be deselected by
+ // the user).
+
+//
+// It would be good to verify that we're not duplicating entries.
+// Add code here to read through the file first looking for a
+// match before attempting to append any new lines.
+//
+
+ // We don't rename if Garmin RINO waypoint file
+ if (strcmp(gps_map_type,"RINO") != 0) {
+ // Rename the temporary file to the new filename. We must
+ // do this three times, once for each piece of the Shapefile
+ // map.
+#if defined(HAVE_MV)
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s %s/%s %s/%s",
+ MV_PATH,
+ gps_base_dir,
+ gps_temp_map_filename,
+ gps_base_dir,
+ gps_map_filename);
+
+ if ( system(temp) ) {
+ fprintf(stderr,"Couldn't rename the downloaded GPS map file\n");
+ fprintf(stderr,"%s\n",temp);
+ gps_got_data_from = 0;
+ gps_details_selected = 0;
+ return;
+ }
+ // Done for the ".shp" file. Now repeat for the ".shx" and
+ // ".dbf" files.
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s %s/%s.shx %s/%s.shx",
+ MV_PATH,
+ gps_base_dir,
+ gps_temp_map_filename_base,
+ gps_base_dir,
+ gps_map_filename_base);
+
+ if ( system(temp) ) {
+ fprintf(stderr,"Couldn't rename the downloaded GPS map file\n");
+ fprintf(stderr,"%s\n",temp);
+ gps_got_data_from = 0;
+ gps_details_selected = 0;
+ return;
+ }
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s %s/%s.dbf %s/%s.dbf",
+ MV_PATH,
+ gps_base_dir,
+ gps_temp_map_filename_base,
+ gps_base_dir,
+ gps_map_filename_base);
+
+ if ( system(temp) ) {
+ fprintf(stderr,"Couldn't rename the downloaded GPS map file\n");
+ fprintf(stderr,"%s\n",temp);
+ gps_got_data_from = 0;
+ gps_details_selected = 0;
+ return;
+ }
+#endif // HAVE_MV
+
+
+ // Write out a WKT in a .prj file to go with this shapefile.
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s/%s.prj",
+ gps_base_dir,
+ gps_map_filename_base);
+ xastirWriteWKT(temp);
+
+ if (strcmp(gps_map_type,"Waypoints") != 0) {
+ // KM5VY: Create a really, really simple dbfawk file to
+ // go with the shapefile. This is a dbfawk file of the
+ // "per file" type, with the color hardcoded into it.
+ // This will enable downloaded gps shapefiles to have
+ // the right color even when they're not placed in the
+ // GPS directory.
+ // We don't do this for waypoint files, because all we need to
+ // do for those is associate the name with the waypoint, and
+ // that can be done by a generic signature-based file.
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s/%s.dbfawk",
+ gps_base_dir,
+ gps_map_filename_base);
+ f=fopen(temp,"w"); // open for write
+ if (f != NULL) {
+ fprintf(f,gps_dbfawk_format,gps_map_color_offset,
+ gps_map_filename_base2);
+ fclose(f);
+ }
+ }
+ // Add the new gps map to the list of selected maps
+ f=fopen( get_user_base_dir(SELECTED_MAP_DATA, temp_file_name,
+ sizeof(temp_file_name)), "a" ); // Open for appending
+ if (f!=NULL) {
+
+//WE7U: Change this:
+ fprintf(f,"GPS/%s\n",gps_map_filename);
+
+ (void)fclose(f);
+
+ // Reindex maps. Use the smart timestamp-checking indexing.
+ map_indexer(0); // Have to have the new map in the index first before we can select it
+ map_chooser_init(); // Re-read the selected_maps.sys file
+ re_sort_maps = 1; // Creates a new sorted list from the selected maps
+
+//
+// We should set some flags here instead of doing the map redraw
+// ourselves, so that multiple map reloads don't occur sometimes in
+// UpdateTime.
+//
+
+ // Reload maps
+ // Set interrupt_drawing_now because conditions have changed.
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(da)) {
+// (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+ }
+ else {
+ fprintf(stderr,"Couldn't open file: %s\n", get_user_base_dir(SELECTED_MAP_DATA, temp_file_name, sizeof(temp_file_name)) );
+ }
+ }
+ else {
+ // We're dealing with Garmin RINO waypoints. Go process
+ // the RINO.gpstrans file, creating objects out of them.
+ process_RINO_waypoints();
+ }
+
+ // Set up for the next GPS run
+ gps_got_data_from = 0;
+ gps_details_selected = 0;
+ }
+}
+
+
+
+
+
+// This is the separate execution thread that transfers the data
+// to/from the GPS. The thread is started up by the
+// GPS_operations() function below.
+//
+static void* gps_transfer_thread(void *arg) {
+ int input_param;
+ char temp[500];
+ char prefix[100];
+ char postfix[100];
+ char gps_base_dir[MAX_VALUE];
+
+ get_user_base_dir("gps", gps_base_dir, sizeof(gps_base_dir));
+
+ // Set up the prefix string. Note that we depend on the correct
+ // setup of serial ports and such in GPSMan's configs.
+ xastir_snprintf(prefix, sizeof(prefix),
+ "%s",
+ GPSMAN_PATH);
+
+ // Set up the postfix string. The files will be created in the
+ // "~/.xastir/gps/" directory.
+ xastir_snprintf(postfix, sizeof(postfix),
+ "Shapefile dim=2 %s/",
+ gps_base_dir);
+
+ input_param = atoi((char *)arg);
+
+ // The pthread_detach() call means we don't care about the
+ // return code and won't use pthread_join() later. Makes
+ // threading more efficient.
+ (void)pthread_detach(pthread_self());
+
+ switch (input_param) {
+
+ case 1: // Fetch track from GPS
+ // gpsman.tcl -dev /dev/ttyS0 getwrite TR Shapefile dim=2 track.date
+
+// fprintf(stderr,"Fetch track from GPS\n");
+
+ xastir_snprintf(gps_temp_map_filename,
+ sizeof(gps_temp_map_filename),
+ "Unnamed_Track_Red.shp");
+ xastir_snprintf(gps_temp_map_filename_base,
+ sizeof(gps_temp_map_filename_base),
+ "Unnamed_Track_Red");
+
+
+ xastir_snprintf(gps_map_type,
+ sizeof(gps_map_type),
+ "Track");
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s getwrite TR %s%s",
+ prefix,
+ postfix,
+ gps_temp_map_filename);
+
+ if ( system(temp) ) {
+ fprintf(stderr,"Couldn't download the gps track\n");
+ gps_operation_pending = 0; // We're done
+ return(NULL);
+ }
+ // Set the got_data flag
+ gps_got_data_from++;
+ break;
+
+ case 2: // Fetch route from GPS
+ // gpsman.tcl -dev /dev/ttyS0 getwrite RT Shapefile dim=2 routes.date
+
+// fprintf(stderr,"Fetch routes from GPS\n");
+
+ xastir_snprintf(gps_temp_map_filename,
+ sizeof(gps_temp_map_filename),
+ "Unnamed_Routes_Red.shp");
+ xastir_snprintf(gps_temp_map_filename_base,
+ sizeof(gps_temp_map_filename_base),
+ "Unnamed_Routes_Red");
+
+ xastir_snprintf(gps_map_type,
+ sizeof(gps_map_type),
+ "Routes");
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s getwrite RT %s%s",
+ prefix,
+ postfix,
+ gps_temp_map_filename);
+
+ if ( system(temp) ) {
+ fprintf(stderr,"Couldn't download the gps routes\n");
+ gps_operation_pending = 0; // We're done
+ return(NULL);
+ }
+ // Set the got_data flag
+ gps_got_data_from++;
+ break;
+
+ case 3: // Fetch waypoints from GPS
+ // gpsman.tcl -dev /dev/ttyS0 getwrite WP Shapefile dim=2 waypoints.date
+
+// fprintf(stderr,"Fetch waypoints from GPS\n");
+
+ xastir_snprintf(gps_temp_map_filename,
+ sizeof(gps_temp_map_filename),
+ "Unnamed_Waypoints.shp");
+ xastir_snprintf(gps_temp_map_filename_base,
+ sizeof(gps_temp_map_filename_base),
+ "Unnamed_Waypoints");
+
+ xastir_snprintf(gps_map_type,
+ sizeof(gps_map_type),
+ "Waypoints");
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s getwrite WP %s%s",
+ prefix,
+ postfix,
+ gps_temp_map_filename);
+
+ if ( system(temp) ) {
+ fprintf(stderr,"Couldn't download the gps waypoints\n");
+ gps_operation_pending = 0; // We're done
+ return(NULL);
+ }
+ // Set the got_data flag
+ gps_got_data_from++;
+ break;
+
+ case 4: // Send track to GPS
+ // gpsman.tcl -dev /dev/ttyS0 readput Shapefile dim=2 track.date TR
+
+ fprintf(stderr,"Send track to GPS\n");
+ fprintf(stderr,"Not implemented yet\n");
+ gps_operation_pending = 0; // We're done
+ return(NULL);
+ break;
+
+ case 5: // Send route to GPS
+ // gpsman.tcl -dev /dev/ttyS0 readput Shapefile dim=2 routes.date RT
+
+ fprintf(stderr,"Send route to GPS\n");
+ fprintf(stderr,"Not implemented yet\n");
+ gps_operation_pending = 0; // We're done
+ return(NULL);
+ break;
+
+ case 6: // Send waypoints to GPS
+ // gpsman.tcl -dev /dev/ttyS0 readput Shapefile dim=2 waypoints.date WP
+
+ fprintf(stderr,"Send waypoints to GPS\n");
+ fprintf(stderr,"Not implemented yet\n");
+ gps_operation_pending = 0; // We're done
+ return(NULL);
+ break;
+
+ case 7: // Fetch waypoints from GPS in GPSTrans format
+ // gpsman.tcl -dev /dev/ttyS0 getwrite WP GPStrans waypoints.date
+
+// fprintf(stderr,"Fetch Garmin RINO waypoints\n");
+
+ // The files will be created in the "~/.xastir/gps/"
+ // directory.
+
+ xastir_snprintf(gps_temp_map_filename,
+ sizeof(gps_temp_map_filename),
+ "RINO.gpstrans");
+
+ xastir_snprintf(gps_temp_map_filename_base,
+ sizeof(gps_temp_map_filename_base),
+ "RINO");
+
+ xastir_snprintf(gps_map_type,
+ sizeof(gps_map_type),
+ "RINO");
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "(%s getwrite WP GPStrans %s/%s 2>&1) >/dev/null",
+ prefix,
+ gps_base_dir,
+ gps_temp_map_filename);
+
+// Execute the command
+system(temp);
+// if ( system(temp) ) {
+// fprintf(stderr,"Couldn't download the gps waypoints\n");
+// gps_operation_pending = 0; // We're done
+// return(NULL);
+// }
+ // Set the got_data flag
+ gps_got_data_from++;
+ break;
+
+ default:
+ fprintf(stderr,"Illegal parameter %d passed to gps_transfer_thread!\n",
+ input_param);
+ gps_operation_pending = 0; // We're done
+ break;
+ } // End of switch
+
+
+ // Signal to the main thread that we're all done with the
+ // GPS operation.
+ gps_operation_pending = 0; // We're done
+
+ // End the thread
+ return(NULL);
+}
+
+
+
+
+
+// GPSMan can't handle multiple '.'s in the filename. It chops at
+// the first one.
+//
+// Note that the permissions on the "~/.xastir/gps/" directory have to be
+// set so that this user (or the root user?) can create files in
+// that directory. The permissions on the resulting files may need
+// to be tweaked.
+//
+// When creating files, we should warn the user of a conflict if the
+// filename already exists, then if the user wishes to overwrite it,
+// delete the old set of files before downloading the new ones. We
+// should also make sure we're not adding the filename to the
+// selected_maps.sys more than once.
+//
+// Set up default filenames for each, with an autoincrementing
+// number at the end? That'd be one way of getting a maps
+// downloaded in a hurry. Could also ask for a filename after the
+// download is complete instead of at the start of the download. In
+// that case, download to a temporary filename and then rename it
+// later and reload maps.
+//
+// Dialog should ask the user to put the unit into Garmin-Garmin
+// mode before proceeding.
+//
+// We could de-sensitize the GPS transfer menu items during a
+// transfer operation, to make sure we're not called again until the
+// first operation is over.
+//
+void GPS_operations( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ pthread_t gps_operations_thread;
+ int parameter;
+
+
+ if (clientData != NULL) {
+
+ // Check whether we're already doing a GPS operation.
+ // Return if so.
+ if (gps_operation_pending) {
+ fprintf(stderr,"GPS Operation is already pending, can't start another one!\n");
+ return;
+ }
+
+ parameter = atoi((char *)clientData);
+
+ if ( ((parameter < 1) || (parameter > 3)) && parameter != 7) {
+ fprintf(stderr,"GPS_operations: Parameter out-of-range: %d",parameter);
+ return;
+ }
+
+
+ gps_operation_pending++;
+ gps_got_data_from = 0;
+
+ // We don't need to select filename/color if option 7
+ if (parameter == 7) {
+ gps_details_selected++;
+ }
+
+
+//----- Start New Thread -----
+
+ // Here we start a new thread. We'll communicate with the
+ // main thread via global variables. Use mutex locks if
+ // there might be a conflict as to when/how we're updating
+ // those variables.
+ //
+ if (pthread_create(&gps_operations_thread, NULL, gps_transfer_thread, clientData)) {
+ fprintf(stderr,"Error creating gps transfer thread\n");
+ gps_got_data_from = 0; // No data to present
+ gps_operation_pending = 0; // We're done
+ }
+ else {
+ // We're off and running with the new thread!
+ }
+ }
+}
+#endif // HAVE_GPSMAN
+
+
+
+
+
+/////////////////////////////////////////////////////////////////////
+// End of GPS operations
+/////////////////////////////////////////////////////////////////////
+
+
+
+
+
+void Set_Log_Indicator(void) {
+ if ( (1==log_tnc_data)
+ || (1==log_net_data)
+ || (1==log_wx)
+ || (1==log_igate)
+ || (1==log_wx_alert_data)
+ || (1==log_message_data) ) {
+ XmTextFieldSetString(log_indicator, langcode("BBARSTA043")); // Logging
+ XtVaSetValues(log_indicator,
+ XmNbackground, GetPixelByName(appshell,"RosyBrown"),
+ NULL);
+ } else {
+ XmTextFieldSetString(log_indicator, NULL);
+ XtVaSetValues(log_indicator, MY_BACKGROUND_COLOR, NULL);
+ }
+}
+
+
+
+
+
+void TNC_Logging_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ log_tnc_data = atoi(which);
+ else
+ log_tnc_data = 0;
+ Set_Log_Indicator();
+}
+
+
+
+
+
+void Net_Logging_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ log_net_data = atoi(which);
+ else
+ log_net_data = 0;
+ Set_Log_Indicator();
+}
+
+
+
+
+
+void IGate_Logging_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ log_igate = atoi(which);
+ else
+ log_igate = 0;
+ Set_Log_Indicator();
+}
+
+
+
+
+
+void Message_Logging_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ log_message_data = atoi(which);
+ else
+ log_message_data = 0;
+ Set_Log_Indicator();
+}
+
+
+
+
+
+void WX_Logging_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ log_wx = atoi(which);
+ else
+ log_wx = 0;
+ Set_Log_Indicator();
+}
+
+
+
+
+
+void WX_Alert_Logging_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ log_wx_alert_data = atoi(which);
+ else
+ log_wx_alert_data = 0;
+ Set_Log_Indicator();
+}
+
+
+
+
+
+// Filter Data Menu button callbacks
+
+// support functions
+void set_sensitive_select_sources(int sensitive)
+{
+ XtSetSensitive(select_mine_button, sensitive);
+ XtSetSensitive(select_tnc_button, sensitive);
+ if (!Select_.tnc) {
+ XtSetSensitive(select_direct_button, FALSE);
+ XtSetSensitive(select_via_digi_button, FALSE);
+ }
+ else {
+ XtSetSensitive(select_direct_button, sensitive);
+ XtSetSensitive(select_via_digi_button, sensitive);
+ }
+ XtSetSensitive(select_net_button, sensitive);
+ if (no_data_selected())
+ XtSetSensitive(select_old_data_button, FALSE);
+ else
+ XtSetSensitive(select_old_data_button, sensitive);
+}
+
+void set_sensitive_select_types(int sensitive)
+{
+ XtSetSensitive(select_stations_button, sensitive);
+ if (!Select_.stations) {
+ XtSetSensitive(select_fixed_stations_button, FALSE);
+ XtSetSensitive(select_moving_stations_button, FALSE);
+ XtSetSensitive(select_weather_stations_button, FALSE);
+ XtSetSensitive(select_CWOP_wx_stations_button, FALSE);
+ }
+ else {
+ XtSetSensitive(select_fixed_stations_button, sensitive);
+ XtSetSensitive(select_moving_stations_button, sensitive);
+ XtSetSensitive(select_weather_stations_button, sensitive);
+ if (Select_.weather_stations) {
+ XtSetSensitive(select_CWOP_wx_stations_button, sensitive);
+ }
+ }
+
+ XtSetSensitive(select_objects_button, sensitive);
+
+ if (!Select_.objects) {
+ XtSetSensitive(select_weather_objects_button, FALSE);
+ XtSetSensitive(select_gauge_objects_button, FALSE);
+ XtSetSensitive(select_other_objects_button, FALSE);
+ }
+ else {
+ XtSetSensitive(select_weather_objects_button, sensitive);
+ XtSetSensitive(select_gauge_objects_button, sensitive);
+ XtSetSensitive(select_other_objects_button, sensitive);
+ }
+}
+
+
+
+
+
+void set_sensitive_display(int sensitive)
+{
+ XtSetSensitive(display_callsign_button, sensitive);
+
+ if (!Display_.callsign) {
+ XtSetSensitive(display_label_all_trackpoints_button, FALSE);
+ }
+ else {
+ XtSetSensitive(display_label_all_trackpoints_button, sensitive);
+ }
+
+ XtSetSensitive(display_symbol_button, sensitive);
+
+ if (!Display_.symbol) {
+ XtSetSensitive(display_symbol_rotate_button, FALSE);
+ }
+ else {
+ XtSetSensitive(display_symbol_rotate_button, sensitive);
+ }
+
+ XtSetSensitive(display_phg_button, sensitive);
+
+ if (!Display_.phg) {
+ XtSetSensitive(display_default_phg_button, FALSE);
+ XtSetSensitive(display_phg_of_moving_button, FALSE);
+ }
+ else {
+ XtSetSensitive(display_default_phg_button, sensitive);
+ XtSetSensitive(display_phg_of_moving_button, sensitive);
+ }
+ XtSetSensitive(display_altitude_button, sensitive);
+ XtSetSensitive(display_course_button, sensitive);
+ XtSetSensitive(display_speed_button, sensitive);
+ if (!Display_.speed) {
+ XtSetSensitive(display_speed_short_button, FALSE);
+ }
+ else {
+ XtSetSensitive(display_speed_short_button, sensitive);
+ }
+ XtSetSensitive(display_dist_bearing_button, sensitive);
+ XtSetSensitive(display_weather_button, sensitive);
+ if (!Display_.weather) {
+ XtSetSensitive(display_weather_text_button, FALSE);
+ XtSetSensitive(display_temperature_only_button, FALSE);
+ XtSetSensitive(display_wind_barb_button, FALSE);
+ }
+ else {
+ XtSetSensitive(display_weather_text_button, sensitive);
+ if (!Display_.weather_text) {
+ XtSetSensitive(display_temperature_only_button, FALSE);
+ }
+ else {
+ XtSetSensitive(display_temperature_only_button, sensitive);
+ }
+ XtSetSensitive(display_wind_barb_button, sensitive);
+ }
+ XtSetSensitive(display_trail_button, sensitive);
+ XtSetSensitive(display_last_heard_button, sensitive);
+ XtSetSensitive(display_ambiguity_button, sensitive);
+ XtSetSensitive(display_df_data_button, sensitive);
+ if (!Display_.df_data) {
+ XtSetSensitive(display_df_beamwidth_data_button, FALSE);
+ XtSetSensitive(display_df_bearing_data_button, FALSE);
+ }
+ else {
+ XtSetSensitive(display_df_beamwidth_data_button, sensitive);
+ XtSetSensitive(display_df_bearing_data_button, sensitive);
+ }
+
+ XtSetSensitive(display_dr_data_button, sensitive);
+ if (!Display_.dr_data) {
+ XtSetSensitive(display_dr_arc_button, FALSE);
+ XtSetSensitive(display_dr_course_button, FALSE);
+ XtSetSensitive(display_dr_symbol_button, FALSE);
+ }
+ else {
+ XtSetSensitive(display_dr_arc_button, sensitive);
+ XtSetSensitive(display_dr_course_button, sensitive);
+ XtSetSensitive(display_dr_symbol_button, sensitive);
+ }
+}
+
+
+
+
+
+void Select_none_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Select_.none = atoi(which);
+ set_sensitive_select_sources(FALSE);
+ set_sensitive_select_types(FALSE);
+ set_sensitive_display(FALSE);
+ }
+ else {
+ Select_.none = 0;
+ set_sensitive_select_sources(TRUE);
+ if (no_data_selected()) {
+ set_sensitive_select_types(FALSE);
+ set_sensitive_display(FALSE);
+ }
+ else {
+ set_sensitive_select_types(TRUE);
+ set_sensitive_display(TRUE);
+ }
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+
+void Select_mine_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Select_.mine = atoi(which);
+ XtSetSensitive(select_old_data_button, TRUE);
+ set_sensitive_select_types(TRUE);
+ set_sensitive_display(TRUE);
+ }
+ else {
+ Select_.mine = 0;
+ if (no_data_selected()) {
+ XtSetSensitive(select_old_data_button, FALSE);
+ set_sensitive_select_types(FALSE);
+ set_sensitive_display(FALSE);
+ }
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_tnc_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Select_.tnc = atoi(which);
+ XtSetSensitive(select_direct_button, TRUE);
+ XtSetSensitive(select_via_digi_button, TRUE);
+
+ if (!no_data_selected()) {
+ XtSetSensitive(select_old_data_button, TRUE);
+ set_sensitive_select_types(TRUE);
+ set_sensitive_display(TRUE);
+ }
+ }
+ else {
+ Select_.tnc = 0;
+ XtSetSensitive(select_direct_button, FALSE);
+ XtSetSensitive(select_via_digi_button, FALSE);
+ if (no_data_selected()) {
+ XtSetSensitive(select_old_data_button, FALSE);
+ set_sensitive_select_types(FALSE);
+ set_sensitive_display(FALSE);
+ }
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_direct_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Select_.direct = atoi(which);
+ XtSetSensitive(select_old_data_button, TRUE);
+ set_sensitive_select_types(TRUE);
+ set_sensitive_display(TRUE);
+ }
+ else {
+ Select_.direct = 0;
+ if (no_data_selected()) {
+ XtSetSensitive(select_old_data_button, FALSE);
+ set_sensitive_select_types(FALSE);
+ set_sensitive_display(FALSE);
+ }
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_via_digi_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Select_.via_digi = atoi(which);
+ XtSetSensitive(select_old_data_button, TRUE);
+ set_sensitive_select_types(TRUE);
+ set_sensitive_display(TRUE);
+ }
+ else {
+ Select_.via_digi = 0;
+ if (no_data_selected()) {
+ XtSetSensitive(select_old_data_button, FALSE);
+ set_sensitive_select_types(FALSE);
+ set_sensitive_display(FALSE);
+ }
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_net_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Select_.net = atoi(which);
+ XtSetSensitive(select_old_data_button, TRUE);
+ set_sensitive_select_types(TRUE);
+ set_sensitive_display(TRUE);
+ }
+ else {
+ Select_.net = 0;
+ if (no_data_selected()) {
+ XtSetSensitive(select_old_data_button, FALSE);
+ set_sensitive_select_types(FALSE);
+ set_sensitive_display(FALSE);
+ }
+ }
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_tactical_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Select_.tactical = atoi(which);
+ XtSetSensitive(select_old_data_button, TRUE);
+ set_sensitive_select_types(TRUE);
+ set_sensitive_display(TRUE);
+ }
+ else {
+ Select_.tactical = 0;
+ if (no_data_selected()) {
+ XtSetSensitive(select_old_data_button, FALSE);
+ set_sensitive_select_types(FALSE);
+ set_sensitive_display(FALSE);
+ }
+ }
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_old_data_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Select_.old_data = atoi(which);
+ else
+ Select_.old_data = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_stations_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Select_.stations = atoi(which);
+ XtSetSensitive(select_fixed_stations_button, TRUE);
+ XtSetSensitive(select_moving_stations_button, TRUE);
+ XtSetSensitive(select_weather_stations_button, TRUE);
+ if (Select_.weather_stations) {
+ XtSetSensitive(select_CWOP_wx_stations_button, TRUE);
+ }
+ }
+ else {
+ Select_.stations = 0;
+ XtSetSensitive(select_fixed_stations_button, FALSE);
+ XtSetSensitive(select_moving_stations_button, FALSE);
+ XtSetSensitive(select_weather_stations_button, FALSE);
+ XtSetSensitive(select_CWOP_wx_stations_button, FALSE);
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_fixed_stations_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Select_.fixed_stations = atoi(which);
+ else
+ Select_.fixed_stations = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_moving_stations_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Select_.moving_stations = atoi(which);
+ else
+ Select_.moving_stations = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_weather_stations_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Select_.weather_stations = atoi(which);
+ XtSetSensitive(select_CWOP_wx_stations_button, atoi(which));
+ }
+ else {
+ Select_.weather_stations = 0;
+ XtSetSensitive(select_CWOP_wx_stations_button, FALSE);
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_CWOP_wx_stations_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Select_.CWOP_wx_stations = atoi(which);
+ else
+ Select_.CWOP_wx_stations = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_objects_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Select_.objects = atoi(which);
+ XtSetSensitive(select_weather_objects_button, TRUE);
+ XtSetSensitive(select_gauge_objects_button, TRUE);
+ XtSetSensitive(select_other_objects_button, TRUE);
+ }
+ else {
+ Select_.objects = 0;
+ XtSetSensitive(select_weather_objects_button, FALSE);
+ XtSetSensitive(select_gauge_objects_button, FALSE);
+ XtSetSensitive(select_other_objects_button, FALSE);
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_weather_objects_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Select_.weather_objects = atoi(which);
+ else
+ Select_.weather_objects = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_gauge_objects_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Select_.gauge_objects = atoi(which);
+ else
+ Select_.gauge_objects = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Select_other_objects_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Select_.other_objects = atoi(which);
+ else
+ Select_.other_objects = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+// Display Menu button callbacks
+
+void Display_callsign_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Display_.callsign = atoi(which);
+ XtSetSensitive(display_label_all_trackpoints_button, TRUE);
+ }
+ else {
+ Display_.callsign = 0;
+ XtSetSensitive(display_label_all_trackpoints_button, FALSE);
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_label_all_trackpoints_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.label_all_trackpoints = atoi(which);
+ else
+ Display_.label_all_trackpoints = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_symbol_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Display_.symbol = atoi(which);
+ XtSetSensitive(display_symbol_rotate_button, TRUE);
+ }
+ else {
+ Display_.symbol = 0;
+ XtSetSensitive(display_symbol_rotate_button, FALSE);
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_symbol_rotate_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.symbol_rotate = atoi(which);
+ else
+ Display_.symbol_rotate = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_trail_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.trail = atoi(which);
+ else
+ Display_.trail = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_course_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.course = atoi(which);
+ else
+ Display_.course = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_speed_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Display_.speed = atoi(which);
+ XtSetSensitive(display_speed_short_button, TRUE);
+ }
+ else {
+ Display_.speed = 0;
+ XtSetSensitive(display_speed_short_button, FALSE);
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_speed_short_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.speed_short = atoi(which);
+ else
+ Display_.speed_short = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_altitude_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.altitude = atoi(which);
+ else
+ Display_.altitude = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_weather_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Display_.weather = atoi(which);
+ XtSetSensitive(display_weather_text_button, TRUE);
+ XtSetSensitive(display_temperature_only_button, TRUE);
+ XtSetSensitive(display_wind_barb_button, TRUE);
+ }
+ else {
+ Display_.weather = 0;
+ XtSetSensitive(display_weather_text_button, FALSE);
+ XtSetSensitive(display_temperature_only_button, FALSE);
+ XtSetSensitive(display_wind_barb_button, FALSE);
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_weather_text_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Display_.weather_text = atoi(which);
+ XtSetSensitive(display_temperature_only_button, TRUE);
+ }
+ else {
+ Display_.weather_text = 0;
+ XtSetSensitive(display_temperature_only_button, FALSE);
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_temperature_only_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.temperature_only = atoi(which);
+ else
+ Display_.temperature_only = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_wind_barb_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.wind_barb = atoi(which);
+ else
+ Display_.wind_barb = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_aloha_circle_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.aloha_circle = atoi(which);
+ else
+ Display_.aloha_circle = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_ambiguity_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.ambiguity = atoi(which);
+ else
+ Display_.ambiguity = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_phg_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Display_.phg = atoi(which);
+ XtSetSensitive(display_default_phg_button, TRUE);
+ XtSetSensitive(display_phg_of_moving_button, TRUE);
+ }
+ else {
+ Display_.phg = 0;
+ XtSetSensitive(display_default_phg_button, FALSE);
+ XtSetSensitive(display_phg_of_moving_button, FALSE);
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_default_phg_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.default_phg = atoi(which);
+ else
+ Display_.default_phg = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_phg_of_moving_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.phg_of_moving = atoi(which);
+ else
+ Display_.phg_of_moving = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_df_data_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Display_.df_data = atoi(which);
+ XtSetSensitive(display_df_beamwidth_data_button, TRUE);
+ XtSetSensitive(display_df_bearing_data_button, TRUE);
+ }
+ else {
+ Display_.df_data = 0;
+ XtSetSensitive(display_df_beamwidth_data_button, FALSE);
+ XtSetSensitive(display_df_bearing_data_button, FALSE);
+ }
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+void Display_df_beamwidth_data_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.df_beamwidth_data = atoi(which);
+ else
+ Display_.df_beamwidth_data = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+void Display_df_bearing_data_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.df_bearing_data = atoi(which);
+ else
+ Display_.df_bearing_data = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_dr_data_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set) {
+ Display_.dr_data = atoi(which);
+ XtSetSensitive(display_dr_arc_button, TRUE);
+ XtSetSensitive(display_dr_course_button, TRUE);
+ XtSetSensitive(display_dr_symbol_button, TRUE);
+ }
+ else {
+ Display_.dr_data = 0;
+ XtSetSensitive(display_dr_arc_button, FALSE);
+ XtSetSensitive(display_dr_course_button, FALSE);
+ XtSetSensitive(display_dr_symbol_button, FALSE);
+ }
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_dr_arc_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.dr_arc = atoi(which);
+ else
+ Display_.dr_arc = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_dr_course_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.dr_course = atoi(which);
+ else
+ Display_.dr_course = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_dr_symbol_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.dr_symbol = atoi(which);
+ else
+ Display_.dr_symbol = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_dist_bearing_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.dist_bearing = atoi(which);
+ else
+ Display_.dist_bearing = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+void Display_last_heard_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ Display_.last_heard = atoi(which);
+ else
+ Display_.last_heard = 0;
+
+ redraw_on_new_data = 2; // Immediate screen update
+}
+
+
+
+
+
+/*
+ * Toggle unit system (button callbacks)
+ */
+void Units_choice_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ english_units = atoi(which);
+ else
+ english_units = 0;
+
+ redraw_on_new_data=2;
+ update_units(); // setup conversion
+ fill_wx_data();
+}
+
+
+
+
+
+/*
+ * Toggle dist/bearing status (button callbacks)
+ */
+void Dbstatus_choice_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ do_dbstatus = atoi(which);
+ else
+ do_dbstatus = 0;
+ // we need to rebuild main window now???
+ XtVaSetValues(text2, XmNwidth, do_dbstatus?((37*FONT_WIDTH)+2):((24*FONT_WIDTH)+2), NULL);
+
+ redraw_on_new_data=2;
+}
+
+
+
+
+
+
+/*
+ * Update global variables for unit conversion
+ *
+ * Be careful using these, as they change based on the value of
+ * english_units! These variable should only be used when
+ * DISPLAYING data, not when converting numbers for use in internal
+ * storage or equations.
+ *
+ */
+void update_units(void) {
+
+ switch (english_units) {
+ case 1: // English
+ xastir_snprintf(un_alt,sizeof(un_alt),"ft");
+ xastir_snprintf(un_dst,sizeof(un_dst),"mi");
+ xastir_snprintf(un_spd,sizeof(un_spd),"mph");
+ cvt_m2len = 3.28084; // m to ft
+ cvt_dm2len = 0.328084; // dm to ft
+ cvt_hm2len = 0.0621504; // hm to mi
+ cvt_kn2len = 1.1508; // knots to mph
+ cvt_mi2len = 1.0; // mph to mph
+ break;
+ case 2: // Nautical
+ // add nautical miles and knots for future use
+ xastir_snprintf(un_alt,sizeof(un_alt),"ft");
+ xastir_snprintf(un_dst,sizeof(un_dst),"nm");
+ xastir_snprintf(un_spd,sizeof(un_spd),"kn");
+ cvt_m2len = 3.28084; // m to ft
+ cvt_dm2len = 0.328084; // dm to ft
+ cvt_hm2len = 0.0539957; // hm to nm
+ cvt_kn2len = 1.0; // knots to knots
+ cvt_mi2len = 0.8689607; // mph to knots / mi to nm
+ break;
+ default: // Metric
+ xastir_snprintf(un_alt,sizeof(un_alt),"m");
+ xastir_snprintf(un_dst,sizeof(un_dst),"km");
+ xastir_snprintf(un_spd,sizeof(un_spd),"km/h");
+ cvt_m2len = 1.0; // m to m
+ cvt_dm2len = 0.1; // dm to m
+ cvt_hm2len = 0.1; // hm to km
+ cvt_kn2len = 1.852; // knots to km/h
+ cvt_mi2len = 1.609; // mph to km/h
+ break;
+ }
+}
+
+
+
+
+
+void Auto_msg_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ auto_reply = atoi(which);
+ else
+ auto_reply = 0;
+}
+
+
+
+
+
+void Satellite_msg_ack_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ satellite_ack_mode = atoi(which);
+ else
+ satellite_ack_mode = 0;
+}
+
+
+
+
+
+void Transmit_disable_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ transmit_disable = atoi(which);
+ XtSetSensitive(iface_transmit_now,FALSE);
+ XtSetSensitive(object_tx_disable_toggle,FALSE);
+ XtSetSensitive(posit_tx_disable_toggle,FALSE);
+ }
+ else {
+ transmit_disable = 0;
+ XtSetSensitive(iface_transmit_now,TRUE);
+ XtSetSensitive(object_tx_disable_toggle,TRUE);
+ XtSetSensitive(posit_tx_disable_toggle,TRUE);
+ }
+}
+
+
+
+
+
+void Posit_tx_disable_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ posit_tx_disable = atoi(which);
+ else
+ posit_tx_disable = 0;
+}
+
+
+
+
+
+void Object_tx_disable_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ object_tx_disable = atoi(which);
+ else
+ object_tx_disable = 0;
+}
+
+
+
+
+
+void Emergency_beacon_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ emergency_beacon = atoi(which);
+
+//WE7U
+// We need to send a posit or two immediately, shorten the interval
+// between posits, and add the string "EMERGENCY" to the posit
+// before anything else in the comment field.
+
+ transmit_now = 1;
+
+ }
+ else {
+ emergency_beacon = 0;
+ }
+}
+
+
+
+
+
+void Server_port_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ // Start the listening socket. If we fork it early we end
+ // up with much smaller process memory allocated for it and
+ // all its children. The server will authenticate each
+ // client that connects. We'll share all of our data with
+ // the server, which will send it to all
+ // connected/authenticated clients. Anything transmitted by
+ // the clients will come back to us and standard igating
+ // rules should apply from there.
+ //
+ enable_server_port = atoi(which);
+ tcp_server_pid = Fork_TCP_server(my_argc, my_argv, my_envp);
+ udp_server_pid = Fork_UDP_server(my_argc, my_argv, my_envp);
+ }
+ else {
+ enable_server_port = 0;
+ shut_down_server();
+ }
+}
+
+
+
+
+void Help_About( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget d;
+ Widget child;
+ XmString xms, xa, xb;
+ Arg al[400];
+ unsigned int ac;
+ float version;
+ char string1[200];
+ char string2[200];
+ extern char compiledate[];
+
+ xastir_snprintf(string2, sizeof(string2),"\nXastir V%s \n",xastir_version);
+ xb = XmStringCreateLocalized(string2);
+ xa = XmStringCreateLocalized(compiledate);
+ xms = XmStringConcat(xb, xa);
+ XmStringFree(xa);
+ XmStringFree(xb);
+ //xms is still defined
+
+ xa = XmStringCreateLocalized("\n\n" ABOUT_MSG "\n\nLibraries used: " XASTIR_INSTALLED_LIBS "\n\n" ABOUT_OSM); // Add some newlines
+ xb = XmStringConcat(xms, xa);
+ XmStringFree(xa);
+ XmStringFree(xms);
+ //xb is still defined
+
+ xa = XmStringCreateLocalized("\n" XmVERSION_STRING); // Add the Motif version string
+ xms = XmStringConcat(xb, xa);
+ XmStringFree(xa);
+ XmStringFree(xb);
+ //xms is still defined
+
+ xa = XmStringCreateLocalized("\n"); // Add a newline
+ xb = XmStringConcat(xms, xa);
+ XmStringFree(xa);
+ XmStringFree(xms);
+ //xb is still defined
+
+ xms = XmStringCopy(xb);
+ XmStringFree(xb);
+ //xms is still defined
+
+#ifdef HAVE_NETAX25_AXLIB_H
+ //if (libax25_version != NULL) {
+ xb = XmStringCreateLocalized("\n");
+ xa = XmStringConcat(xb, xms);
+ XmStringFree(xb);
+ XmStringFree(xms);
+ xb = XmStringCreateLocalized("@(#)LibAX25 (ax25lib_version is broken. Complain to the authors.)\n");
+ xms = XmStringConcat(xa, xb);
+ XmStringFree(xa);
+ XmStringFree(xb);
+ //}
+#endif // AVE_NETAX25_AXLIB_H
+
+#ifdef HAVE_MAGICK
+ xb = XmStringCreateLocalized("\n"); // Add a newline
+ xa = XmStringConcat(xb, xms);
+ XmStringFree(xb);
+ XmStringFree(xms);
+ //xa is still defined
+
+ xb = XmStringCreateLocalized( MagickVersion); // Add ImageMagick version string
+ xms = XmStringConcat(xa, xb);
+ XmStringFree(xa);
+ XmStringFree(xb);
+ //xms is still defined
+#endif // HAVE_MAGICK
+ xb = XmStringCreateLocalized("\n"); // Add a newline
+ xa = XmStringConcat(xb, xms);
+ XmStringFree(xb);
+ XmStringFree(xms);
+ //xa is still defined
+
+ version = XRotVersion( string1, 99 );
+ xastir_snprintf(string2, sizeof(string2), "\n%s, Version %0.2f", string1, version);
+ xb = XmStringCreateLocalized( string2); // Add Xvertext version string
+ xms = XmStringConcat(xa, xb);
+ XmStringFree(xa);
+ XmStringFree(xb);
+ //xms is still defined
+
+ ac = 0;
+ XtSetArg(al[ac], XmNmessageString, xms); ac++;
+ // "About Xastir"
+ XtSetArg(al[ac], XmNtitle, langcode("PULDNHEL05") ); ac++;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ // "About Xastir"
+ d = XmCreateInformationDialog(appshell, langcode("PULDNHEL05"), al, ac);
+ XmStringFree(xms);
+ XtDestroyWidget(XmMessageBoxGetChild(d, (unsigned char)XmDIALOG_CANCEL_BUTTON));
+ XtDestroyWidget(XmMessageBoxGetChild(d, (unsigned char)XmDIALOG_HELP_BUTTON));
+
+ child = XmMessageBoxGetChild(d, XmDIALOG_MESSAGE_LABEL);
+ XtVaSetValues(child, XmNfontList, fontlist1, NULL);
+
+ XtManageChild(d);
+ pos_dialog(d);
+ fix_dialog_size(d);
+}
+
+
+
+
+
+Widget GetTopShell(Widget w) {
+ while(w && !XtIsWMShell(w))
+ w = XtParent(w);
+
+ return(w);
+}
+
+
+
+
+
+/*********************** Display incoming data*******************************/
+/****************************************************************************/
+
+void Display_data_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ Display_data_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Display_packet_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ Display_packet_data_type = atoi(which);
+ else
+ Display_packet_data_type = 0;
+
+ redraw_on_new_packet_data=1;
+}
+
+
+
+
+
+// Turn on or off "Station Capabilities", callback for capabilities
+// button.
+//
+void Capabilities_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ show_only_station_capabilities = TRUE;
+ else
+ show_only_station_capabilities = FALSE;
+}
+
+
+
+
+
+// Turn on or off "Mine Only"
+//
+void Display_packet_mine_only_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ Display_packet_data_mine_only = TRUE;
+ else
+ Display_packet_data_mine_only = FALSE;
+}
+
+
+
+
+
+void Display_data( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget pane, my_form, button_close, option_box, tnc_data,
+ net_data, tnc_net_data, capabilities_button,
+ mine_only_button;
+ unsigned int n;
+ Arg args[50];
+ Atom delw;
+
+ if (!Display_data_dialog) {
+ Display_data_dialog = XtVaCreatePopupShell(langcode("WPUPDPD001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Display_data pane",
+ xmPanedWindowWidgetClass,
+ Display_data_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Display_data my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ /* set colors */
+ n=0;
+ XtSetArg(args[n],XmNforeground, MY_FG_COLOR); n++;
+ XtSetArg(args[n],XmNbackground, MY_BG_COLOR); n++;
+ XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNtopOffset, 5); n++;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_NONE); n++;
+ XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNleftOffset, 5); n++;
+ XtSetArg(args[n], XmNrightAttachment, XmATTACH_NONE); n++;
+ XtSetArg(args[n], XmNfontList, fontlist1); n++;
+
+ option_box = XmCreateRadioBox(my_form,
+ "Display_data option box",
+ args,
+ n);
+
+ XtVaSetValues(option_box,
+ XmNpacking, XmPACK_TIGHT,
+ XmNorientation, XmHORIZONTAL,
+ NULL);
+
+ tnc_data = XtVaCreateManagedWidget(langcode("WPUPDPD002"),
+ xmToggleButtonGadgetClass,
+ option_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(tnc_data,XmNvalueChangedCallback,Display_packet_toggle,"1");
+
+ net_data = XtVaCreateManagedWidget(langcode("WPUPDPD003"),
+ xmToggleButtonGadgetClass,
+ option_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(net_data,XmNvalueChangedCallback,Display_packet_toggle,"2");
+
+ tnc_net_data = XtVaCreateManagedWidget(langcode("WPUPDPD004"),
+ xmToggleButtonGadgetClass,
+ option_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(tnc_net_data,XmNvalueChangedCallback,Display_packet_toggle,"0");
+
+ capabilities_button = XtVaCreateManagedWidget(langcode("WPUPDPD007"),
+ xmToggleButtonGadgetClass,
+ my_form,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, option_box,
+ XmNleftOffset, 20,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(capabilities_button, XmNvalueChangedCallback,Capabilities_toggle,"1");
+
+ mine_only_button = XtVaCreateManagedWidget(langcode("WPUPDPD008"),
+ xmToggleButtonGadgetClass,
+ my_form,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, capabilities_button,
+ XmNleftOffset, 20,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(mine_only_button, XmNvalueChangedCallback,Display_packet_mine_only_toggle,"1");
+
+ n=0;
+ XtSetArg(args[n], XmNrows, 15); n++;
+ XtSetArg(args[n], XmNcolumns, 100); n++;
+ XtSetArg(args[n], XmNeditable, FALSE); n++;
+ XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
+ XtSetArg(args[n], XmNwordWrap, TRUE); n++;
+ XtSetArg(args[n], XmNforeground, MY_FG_COLOR); n++;
+ XtSetArg(args[n], XmNbackground, MY_BG_COLOR); n++;
+ XtSetArg(args[n], XmNscrollHorizontal, TRUE); n++;
+ XtSetArg(args[n], XmNscrollVertical, TRUE); n++;
+ XtSetArg(args[n], XmNcursorPositionVisible, FALSE); n++;
+ XtSetArg(args[n], XmNtraversalOn, FALSE); n++;
+ XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
+ XtSetArg(args[n], XmNtopWidget, option_box); n++;
+ XtSetArg(args[n], XmNtopOffset, 5); n++;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNbottomOffset, 30); n++;
+ XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNleftOffset, 5); n++;
+ XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNrightOffset, 5); n++;
+ XtSetArg(args[n], XmNfontList, fontlist1); n++;
+
+
+// XtSetArg(args[n], XmNnavigationType, XmTAB_GROUP); n++;
+ Display_data_text=NULL;
+ Display_data_text = XmCreateScrolledText(my_form,
+ "Display_data text",
+ args,
+ n);
+
+
+ button_close = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_close, XmNactivateCallback, Display_data_destroy_shell, Display_data_dialog);
+
+
+// I haven't figured out how to get the scrollbars to allow keyboard traversal.
+// When the ScrolledText widget is in the tab group, once you get there you can't
+// get out and it beeps at you when you try. Frustrating. For this dialog it's
+// probably not important enough to worry about.
+// I now have it set to allow TAB'ing into the ScrolledText widget, but to get
+// out you must do a <Shift><TAB>. This sucks. Even if you enable the
+// ScrolledText widget in the tab group, the scrollbars don't work with the
+// arrow keys.
+// ScrolledList works. I need to convert to ScrolledList if
+// possible for output-only windows.
+
+
+ pos_dialog(Display_data_dialog);
+
+ delw = XmInternAtom(XtDisplay(Display_data_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(Display_data_dialog,
+ delw,
+ Display_data_destroy_shell,
+ (XtPointer)Display_data_dialog);
+
+ switch (Display_packet_data_type) {
+ case(0):
+ XmToggleButtonSetState(tnc_net_data,TRUE,FALSE);
+ break;
+
+ case(1):
+ XmToggleButtonSetState(tnc_data,TRUE,FALSE);
+ break;
+
+ case(2):
+ XmToggleButtonSetState(net_data,TRUE,FALSE);
+ break;
+
+ default:
+ XmToggleButtonSetState(tnc_net_data,TRUE,FALSE);
+ break;
+ }
+
+ if (show_only_station_capabilities)
+ XmToggleButtonSetState(capabilities_button,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(capabilities_button,FALSE,FALSE);
+
+ if (Display_packet_data_mine_only)
+ XmToggleButtonSetState(mine_only_button,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(mine_only_button,FALSE,FALSE);
+
+ XtManageChild(option_box);
+ XtManageChild(Display_data_text);
+ XtVaSetValues(Display_data_text, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(my_form);
+ XtManageChild(pane);
+
+ redraw_on_new_packet_data=1;
+ XtPopup(Display_data_dialog,XtGrabNone);
+
+// fix_dialog_vsize(Display_data_dialog);
+
+ // Move focus to the Close button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(Display_data_dialog);
+ XmProcessTraversal(button_close, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(Display_data_dialog), XtWindow(Display_data_dialog));
+
+}
+
+
+
+
+
+/****************************** Help menu ***********************************/
+/****************************************************************************/
+
+void help_view_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ help_view_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void help_index_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+
+ if (help_view_dialog)
+ help_view_destroy_shell(help_view_dialog, help_view_dialog, NULL);
+
+ help_view_dialog = (Widget)NULL;
+
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ help_index_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void help_view( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget pane, my_form, button_close,help_text;
+ int i;
+ Position x, y;
+ unsigned int n;
+ char *temp = NULL;
+ char title[200];
+ char temp2[200];
+ char temp3[200];
+ FILE *f;
+ XmString *list;
+ int open;
+ Arg args[50];
+ int data_on,pos;
+ int found;
+ Atom delw;
+ char help_file_path[MAX_VALUE];
+
+ data_on=0;
+ pos=0;
+ found=0;
+
+ XtVaGetValues(help_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ for (x=1; x<=i;x++) {
+ if (XmListPosSelected(help_list,x)) {
+ found=1;
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_BEGINNING);
+ x=i+1;
+ }
+ }
+ open=0;
+
+ if (found) {
+ if (help_view_dialog) {
+ XtVaGetValues(help_view_dialog, XmNx, &x, XmNy, &y, NULL);
+ help_view_destroy_shell(help_view_dialog, help_view_dialog, NULL);
+ help_view_dialog = (Widget)NULL;
+ open=1;
+ }
+ if (!help_view_dialog) {
+ xastir_snprintf(title, sizeof(title), "%s - %s", langcode("MENUTB0009"), temp);
+ help_view_dialog = XtVaCreatePopupShell(title,
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+ pane = XtVaCreateWidget("help_view pane",
+ xmPanedWindowWidgetClass,
+ help_view_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("help_view my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ n=0;
+ XtSetArg(args[n], XmNrows, 20); n++;
+ XtSetArg(args[n], XmNcolumns, 80); n++;
+ XtSetArg(args[n], XmNeditable, FALSE); n++;
+ XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
+ XtSetArg(args[n], XmNwordWrap, TRUE); n++;
+ XtSetArg(args[n], XmNscrollHorizontal, FALSE); n++;
+ XtSetArg(args[n], XmNcursorPositionVisible, FALSE); n++;
+ XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNtopOffset, 5); n++;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_NONE); n++;
+ XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNleftOffset, 5); n++;
+ XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNrightOffset, 5); n++;
+ XtSetArg(args[n], XmNforeground, MY_FG_COLOR); n++;
+ XtSetArg(args[n], XmNbackground, MY_BG_COLOR); n++;
+ XtSetArg(args[n], XmNfontList, fontlist1); n++;
+
+ help_text=NULL;
+ help_text = XmCreateScrolledText(my_form,
+ "help_view help text",
+ args,
+ n);
+
+ get_user_base_dir(HELP_FILE, help_file_path, sizeof(help_file_path));
+
+ f=fopen( help_file_path , "r" );
+ if (f!=NULL) {
+ while(!feof(f)) {
+ (void)get_line(f,temp2,200);
+ if (strncmp(temp2,"HELP-INDEX>",11)==0) {
+ if(strcmp((temp2+11),temp)==0)
+ data_on=1;
+ else
+ data_on=0;
+ } else {
+ if (data_on) {
+ xastir_snprintf(temp3, sizeof(temp3), "%s\n", temp2);
+ XmTextInsert(help_text,pos,temp3);
+ pos += strlen(temp3);
+ XmTextShowPosition(help_text,0);
+ }
+ }
+ }
+ (void)fclose(f);
+ }
+ else
+ fprintf(stderr,"Couldn't open file: %s\n", help_file_path);
+
+ button_close = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, XtParent(help_text),
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_close, XmNactivateCallback, help_view_destroy_shell, help_view_dialog);
+
+ if (!open)
+ pos_dialog(help_view_dialog);
+ else
+ XtVaSetValues(help_view_dialog, XmNx, x, XmNy, y, NULL);
+
+ delw = XmInternAtom(XtDisplay(help_view_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(help_view_dialog, delw, help_view_destroy_shell, (XtPointer)help_view_dialog);
+
+ XtManageChild(my_form);
+ XtManageChild(help_text);
+ XtVaSetValues(help_text, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(pane);
+
+ XtPopup(help_view_dialog,XtGrabNone);
+ fix_dialog_size(help_view_dialog);
+ XmTextShowPosition(help_text,0);
+ }
+ XtFree(temp); // Free up the space allocated
+ }
+
+}
+
+
+
+
+
+void Help_Index( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, my_form, button_ok, button_cancel;
+ int n;
+ char temp[600];
+ FILE *f;
+ Arg al[50]; /* Arg List */
+ unsigned int ac = 0; /* Arg Count */
+ Atom delw;
+ XmString str_ptr;
+ char help_file_path[MAX_VALUE];
+
+ if(!help_index_dialog) {
+ help_index_dialog = XtVaCreatePopupShell(langcode("WPUPHPI001"),
+ xmDialogShellWidgetClass,
+ appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNresize, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Help_Index pane",
+ xmPanedWindowWidgetClass,
+ help_index_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Help_Index my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ /*set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNvisibleItemCount, 11); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNshadowThickness, 3); ac++;
+ XtSetArg(al[ac], XmNbackground, colors[0x0ff]); ac++;
+ XtSetArg(al[ac], XmNselectionPolicy, XmSINGLE_SELECT); ac++;
+ XtSetArg(al[ac], XmNscrollBarPlacement, XmBOTTOM_RIGHT); ac++;
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 5); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 5); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 5); ac++;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ help_list = XmCreateScrolledList(my_form,
+ "Help_Index list",
+ al,
+ ac);
+
+ n=1;
+
+ get_user_base_dir(HELP_FILE, help_file_path, sizeof(help_file_path));
+
+ f=fopen( help_file_path, "r" );
+ if (f!=NULL) {
+ while (!feof(f)) {
+ (void)get_line(f,temp,600);
+ if (strncmp(temp,"HELP-INDEX>",11)==0) {
+ XmListAddItem(help_list, str_ptr = XmStringCreateLocalized((temp+11)),n++);
+ XmStringFree(str_ptr);
+ }
+ }
+ (void)fclose(f);
+ }
+ else
+ fprintf(stderr,"Couldn't open file: %s\n", help_file_path );
+
+ button_ok = XtVaCreateManagedWidget(langcode("WPUPHPI002"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, XtParent(help_list),
+ XmNtopOffset,5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, XtParent(help_list),
+ XmNtopOffset,5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_cancel, XmNactivateCallback, help_index_destroy_shell, help_index_dialog);
+ XtAddCallback(button_ok, XmNactivateCallback, help_view, NULL);
+
+ pos_dialog(help_index_dialog);
+
+ delw = XmInternAtom(XtDisplay(help_index_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(help_index_dialog, delw, help_index_destroy_shell, (XtPointer)help_index_dialog);
+
+ XtManageChild(my_form);
+ XtManageChild(help_list);
+ XtVaSetValues(help_list, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(pane);
+
+ XtPopup(help_index_dialog,XtGrabNone);
+ fix_dialog_size(help_index_dialog);
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(help_index_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else {
+ XtPopup(help_index_dialog,XtGrabNone);
+ (void)XRaiseWindow(XtDisplay(help_index_dialog), XtWindow(help_index_dialog));
+ }
+}
+
+
+
+
+
+/************************** Clear stations *******************************/
+/*************************************************************************/
+
+void Stations_Clear( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+
+ delete_all_stations();
+
+ my_station_add(my_callsign,my_group,my_symbol,my_long,my_lat,my_phg,my_comment,(char)position_amb_chars);
+
+ current_trail_color = 0x00; // restart
+
+ // Reload saved objects and items from previous runs.
+ // This implements persistent objects.
+ reload_object_item();
+
+ redraw_on_new_data=2;
+}
+
+
+
+
+
+/************************* Map Properties*********************************/
+/*************************************************************************/
+
+// Destroys the Map Properties dialog
+void map_properties_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ map_properties_dialog = (Widget)NULL;
+ re_sort_maps = 1;
+
+ if (map_chooser_dialog) {
+ XtSetSensitive(map_chooser_button_ok, TRUE);
+ XtSetSensitive(map_chooser_button_cancel, TRUE);
+ }
+}
+
+
+
+
+
+//WE7U
+// Possible changes:
+// *) Save/restore the map selections while changing properties.
+// Malloc a char array the size of the map_properties_list and
+// fill it in based on the current highlighting. Free it when
+// we're done.
+// *) Change the labels at the top into buttons? Zoom/Layer buttons
+// would pop up a dialog asking for the number. Others would
+// just toggle the feature.
+// *) Change to a single "Apply" button. This won't allow us to
+// easily change only some parameters unless we skip input fields
+// that are blank. Run through highlighted items, fill in input
+// fields if the parameter is the same for all. If different for
+// some, leave input field blank.
+// *) Bring up an "Abandon Changes?" confirmation dialog if input
+// fields are filled in but "Cancel" was pressed instead of
+// "Apply".
+
+
+
+// Fills in the map properties file entries.
+//
+void map_properties_fill_in (void) {
+ int n,i;
+ XmString str_ptr;
+ map_index_record *current = map_index_head;
+ int top_position;
+
+
+ busy_cursor(appshell);
+
+ i=0;
+ if (map_properties_dialog) {
+ char *current_selections = NULL;
+ int kk, mm;
+
+
+ // Save our current place in the dialog
+ XtVaGetValues(map_properties_list,
+ XmNtopItemPosition, &top_position,
+ NULL);
+
+ // Get the list count from the dialog
+ XtVaGetValues(map_properties_list,
+ XmNitemCount,&kk,
+ NULL);
+
+ if (kk) { // If list is not empty
+ // Allocate enough chars to hold the highlighting info
+ current_selections = (char *)malloc(sizeof(char) * kk);
+//fprintf(stderr,"List entries:%d\n", kk);
+
+ // Iterate over the list, saving the highlighting values
+ for (mm = 0; mm < kk; mm++) {
+ if (XmListPosSelected(map_properties_list, mm))
+ current_selections[mm] = 1;
+ else
+ current_selections[mm] = 0;
+ }
+ }
+
+// fprintf(stderr,"Top Position: %d\n",top_position);
+
+ // Empty the map_properties_list widget first
+ XmListDeleteAllItems(map_properties_list);
+
+ // Put all the map files/dirs in the map_index into the Map
+ // Properties dialog list (map_properties_list). Include
+ // the map_layer and draw_filled variables on the line.
+ n=1;
+
+
+//
+// We wish to only show the files that are currently selected in the
+// map_chooser_dialog's map_list widget. We'll need to run down
+// that widget's entries, checking whether each line is selected,
+// and only display it in the map_properties_list widget if selected
+// and a match with our string.
+//
+// One method would be to make the Map Chooser selections set a bit
+// in the in-memory index, so that we can tell which ones are
+// selected without a bunch of string compares. The bit would need
+// to be tweaked on starting up the map chooser (setting the
+// selected entries that match the selected_maps.sys file), and when
+// the user tweaked a selection.
+//
+// What we don't want to get into is an n*n set of string compares
+// between two lists, which would be very slow. If they're both
+// ordered lists though, we'll end up with at most a 2n multiplier,
+// which is much better. If we can pass the info between the lists
+// with a special entry in the record, we don't slow down at all.
+//
+// Reasonably fast method: Create a new list that contains only the
+// selected items from map_list. Run through this list as we
+// populate map_properties_list from the big linked list.
+//
+// Actually, it's probably just as fast to run down through
+// map_list, looking up records for every line that's selected.
+// Just keep the pointers incrementing for each list instead of
+// running through the entire in-memory linked list for every
+// selected item in map_list.
+//
+// For selected directories, we need to add each file that has that
+// initial directory name. We should be able to do this with a
+// match that stops at the end of the directory name.
+//
+// We need to grey-out the buttons in the Map Chooser until the
+// Properties dialog closes. Otherwise we might not able to get to
+// to the map_list widget to re-do the Properties list when a button
+// is pressed in the Properties dialog (if the user closes the Map
+// Chooser).
+//
+
+
+ // Set all of the temp_select bits to zero in the in-memory
+ // map index.
+ map_index_temp_select_clear();
+
+ if (map_chooser_dialog) {
+ map_index_record *ptr = map_index_head;
+ int jj, x;
+ XmString *list;
+ char *temp;
+
+ // Get the list and list count from the Map Chooser
+ // dialog.
+ XtVaGetValues(map_list,
+ XmNitemCount,&jj,
+ XmNitems,&list,
+ NULL);
+
+ // Find all selected files/directories in the Map
+ // Chooser. Set the "temp_select" bits in the in-memory
+ // map index to correspond.
+ //
+ for(x=1; x<=jj; x++)
+ {
+ if (XmListPosSelected(map_list,x)) {
+ // Snag the filename portion from the line
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_BEGINNING);
+ if (temp) {
+
+ // Update this file or directory in the in-memory
+ // map index, setting the "temp_select" field to 1.
+ map_index_update_temp_select(temp, &ptr);
+ XtFree(temp);
+ }
+ }
+ }
+ }
+
+ // We should now have all of the files/directories marked in
+ // the in-memory map index. Files underneath selected
+ // directories should also be marked by this point, as the
+ // map_index_update_temp_select() routine should assure
+ // this.
+
+ while (current != NULL) {
+
+if (current->temp_select) {
+
+ //fprintf(stderr,"%s\n",current->filename);
+
+ // Make sure it's a file and not a directory
+ if (current->filename[strlen(current->filename)-1] != '/') {
+ char temp[MAX_FILENAME];
+ char temp_layer[10];
+ char temp_max_zoom[10];
+ char temp_min_zoom[10];
+ char temp_filled[20];
+ char temp_drg[20];
+ char temp_auto[20];
+ int len, start;
+
+
+ // We have a file. Construct the line that we wish
+ // to place in the list
+
+ // JMT - this is a guess
+ if (current->max_zoom == 0) {
+ xastir_snprintf(temp_max_zoom,
+ sizeof(temp_max_zoom),
+ " - ");
+ }
+ else {
+ xastir_snprintf(temp_max_zoom,
+ sizeof(temp_max_zoom),
+ "%5d",
+ current->max_zoom);
+ }
+
+ if (current->min_zoom == 0) {
+ xastir_snprintf(temp_min_zoom,
+ sizeof(temp_min_zoom),
+ " - ");
+ }
+ else {
+ xastir_snprintf(temp_min_zoom,
+ sizeof(temp_min_zoom),
+ "%5d",
+ current->min_zoom);
+ }
+
+ if (current->map_layer == 0) {
+ xastir_snprintf(temp_layer,
+ sizeof(temp_layer),
+ " - ");
+ }
+ else {
+ xastir_snprintf(temp_layer,
+ sizeof(temp_layer),
+ "%5d",
+ current->map_layer);
+ }
+
+ xastir_snprintf(temp_filled,
+ sizeof(temp_filled),
+ " ");
+
+ switch (current->draw_filled) {
+
+ case 0: // Global No-Fill (vector)
+
+ // Center the string in the column
+ len = strlen(langcode("MAPP007"));
+ start = (int)( (5 - len) / 2 + 0.5);
+
+ if (start < 0)
+ start = 0;
+
+ // Insert the string. Fill with spaces
+ // on the end.
+ xastir_snprintf(&temp_filled[start],
+ sizeof(temp_filled)-start,
+ "%s ",
+ langcode("MAPP007")); // "No"
+
+ break;
+
+ case 1: // Global Fill
+
+ // Center the string in the column
+ len = strlen(langcode("MAPP006"));
+ start = (int)( (5 - len) / 2 + 0.5);
+
+ if (start < 0)
+ start = 0;
+
+ // Insert the string. Fill with spaces
+ // on the end.
+ xastir_snprintf(&temp_filled[start],
+ sizeof(temp_filled)-start,
+ "%s ",
+ langcode("MAPP006")); // "Yes"
+
+ break;
+
+ case 2: // Auto
+ default:
+
+ // Center the string in the column
+ len = strlen(langcode("MAPP011"));
+ start = (int)( (5 - len) / 2 + 1.5);
+
+ if (start < 0)
+ start = 0;
+
+ // Insert the string. Fill with spaces
+ // on the end.
+ xastir_snprintf(&temp_filled[start],
+ sizeof(temp_filled)-start,
+ "%s ",
+ langcode("MAPP011")); // "Auto"
+
+ break;
+
+ } // End of switch
+
+ // Truncate it so it fits our column width.
+ temp_filled[5] = '\0';
+
+ xastir_snprintf(temp_drg,
+ sizeof(temp_drg),
+ " ");
+
+ switch (current->usgs_drg) {
+
+ case 0: // No
+
+ // Center the string in the column
+ len = strlen(langcode("MAPP007"));
+ start = (int)( (5 - len) / 2 + 0.5);
+
+ if (start < 0)
+ start = 0;
+
+ // Insert the string. Fill with spaces
+ // on the end.
+ xastir_snprintf(&temp_drg[start],
+ sizeof(temp_drg)-start,
+ "%s ",
+ langcode("MAPP007")); // "No"
+
+ break;
+
+ case 1: // Yes
+
+ // Center the string in the column
+ len = strlen(langcode("MAPP006"));
+ start = (int)( (5 - len) / 2 + 0.5);
+
+ if (start < 0)
+ start = 0;
+
+ // Insert the string. Fill with spaces
+ // on the end.
+ xastir_snprintf(&temp_drg[start],
+ sizeof(temp_drg)-start,
+ "%s ",
+ langcode("MAPP006")); // "Yes"
+
+ break;
+
+ case 2: // Auto
+ default:
+
+ // Center the string in the column
+ len = strlen(langcode("MAPP011"));
+ start = (int)( (5 - len) / 2 + 1.5);
+
+ if (start < 0)
+ start = 0;
+
+ // Insert the string. Fill with spaces
+ // on the end.
+ xastir_snprintf(&temp_drg[start],
+ sizeof(temp_drg)-start,
+ "%s ",
+ langcode("MAPP011")); // "Auto"
+
+ break;
+
+ } // End of switch
+
+ // Truncate it so it fits our column width.
+ temp_drg[5] = '\0';
+
+ xastir_snprintf(temp_auto,
+ sizeof(temp_auto),
+ " ");
+
+ if (current->auto_maps) {
+ int len, start;
+
+ // Center the string in the column
+ len = strlen(langcode("MAPP006"));
+ start = (int)( (5 - len) / 2 + 0.5);
+
+ if (start < 0)
+ start = 0;
+
+ // Insert the string. Fill with spaces on the
+ // end.
+ xastir_snprintf(&temp_auto[start],
+ sizeof(temp_filled)-start,
+ "%s ",
+ langcode("MAPP006"));
+
+ // Truncate it so it fits our column width.
+ temp_auto[5] = '\0';
+ }
+
+ //WARNING WARNING WARNING --- changing this format string
+ // REQUIRES changing the defined constant MPD_FILENAME_OFFSET
+ // at the top of this file, or all the routines that try
+ // to decode the string will be wrong!
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s %s %s %s %s %s %s",
+ temp_max_zoom,
+ temp_min_zoom,
+ temp_layer,
+ temp_filled,
+ temp_drg,
+ temp_auto,
+ current->filename);
+
+ str_ptr = XmStringCreateLocalized(temp);
+ XmListAddItem(map_properties_list, str_ptr, n);
+ n++;
+ XmStringFree(str_ptr);
+ }
+}
+
+ current = current->next;
+ }
+
+ if (kk) { // If list is not empty
+ // Restore the highlighting values
+ for (mm = 0; mm < kk; mm++) {
+ if (current_selections[mm])
+ XmListSelectPos(map_properties_list,mm,TRUE);
+ }
+ // Free the highlighting array we allocated
+ free(current_selections);
+ }
+
+ // Restore our place in the dialog
+ XtVaSetValues(map_properties_list,
+ XmNtopItemPosition, top_position,
+ NULL);
+ }
+}
+
+
+
+
+
+// Removes the highlighting for maps in the current view of the map
+// properties list.
+//
+void map_properties_deselect_maps(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x;
+ XmString *list;
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_properties_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the widget's list, deselecting every line
+ for(x=1; x<=i;x++) {
+ if (XmListPosSelected(map_properties_list,x)) {
+ XmListDeselectPos(map_properties_list,x);
+ }
+ }
+}
+
+
+
+
+
+// Selects all maps in the current view of the map properties list.
+//
+void map_properties_select_all_maps(Widget widget, XtPointer clientData, XtPointer
+ callData) {
+ int i, x;
+ XmString *list;
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_properties_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the widget's list, selecting every line
+ for(x=1; x<=i;x++) {
+ // Deselect each one first, in case already selected
+ XmListDeselectPos(map_properties_list,x);
+
+ // Select/highlight that position
+ XmListSelectPos(map_properties_list,x,TRUE);
+ }
+}
+
+
+
+
+
+// Change the "draw_filled" field in the in-memory map_index to a
+// two.
+void map_index_update_filled_auto(char *filename) {
+ map_index_record *current = map_index_head;
+
+ while (current != NULL) {
+ if (strcmp(current->filename,filename) == 0) {
+ // Found a match. Update the field and return.
+ current->draw_filled = 2;
+ break;
+ }
+ current = current->next;
+ }
+}
+
+
+
+
+
+// Change the "draw_filled" field in the in-memory map_index to a
+// one.
+void map_index_update_filled_yes(char *filename) {
+ map_index_record *current = map_index_head;
+
+ while (current != NULL) {
+ if (strcmp(current->filename,filename) == 0) {
+ // Found a match. Update the field and return.
+ current->draw_filled = 1;
+ break;
+ }
+ current = current->next;
+ }
+}
+
+
+
+
+
+// Change the "draw_filled" field in the in-memory map_index to a
+// zero.
+void map_index_update_filled_no(char *filename) {
+ map_index_record *current = map_index_head;
+
+ while (current != NULL) {
+ if (strcmp(current->filename,filename) == 0) {
+ // Found a match. Update the field and return.
+ current->draw_filled = 0;
+ break;
+ }
+ current = current->next;
+ }
+}
+
+
+
+
+
+void map_properties_filled_auto(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x;
+ XmString *list;
+ char *temp;
+
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_properties_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the widget's list, changing the filled field on
+ // every one that is selected.
+ for(x=1; x<=i;x++)
+ {
+ // If the line was selected
+ if ( XmListPosSelected(map_properties_list,x) ) {
+
+ // Snag the filename portion from the line
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_END);
+ if (temp) {
+ // Update this file or directory in the in-memory
+ // map index, setting the "draw_filled" field to 2.
+ map_index_update_filled_auto(&temp[MPD_FILENAME_OFFSET]);
+ XtFree(temp);
+ }
+ }
+ }
+
+ // Delete all entries in the list and re-create anew.
+ map_properties_fill_in();
+
+ // Save the updated index to the file
+ index_save_to_file();
+}
+
+
+
+
+
+void map_properties_filled_yes(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x;
+ XmString *list;
+ char *temp;
+
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_properties_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the widget's list, changing the filled field on
+ // every one that is selected.
+ for(x=1; x<=i;x++)
+ {
+ // If the line was selected
+ if ( XmListPosSelected(map_properties_list,x) ) {
+
+ // Snag the filename portion from the line
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_END);
+ if (temp) {
+ // Update this file or directory in the in-memory
+ // map index, setting the "draw_filled" field to 1.
+ map_index_update_filled_yes(&temp[MPD_FILENAME_OFFSET]);
+ XtFree(temp);
+ }
+ }
+ }
+
+ // Delete all entries in the list and re-create anew.
+ map_properties_fill_in();
+
+ // Save the updated index to the file
+ index_save_to_file();
+}
+
+
+
+
+
+void map_properties_filled_no(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x;
+ XmString *list;
+ char *temp;
+
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_properties_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the widget's list, changing the filled field on
+ // every one that is selected.
+ for(x=1; x<=i;x++)
+ {
+ // If the line was selected
+ if ( XmListPosSelected(map_properties_list,x) ) {
+
+ // Snag the filename portion from the line
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_END);
+ if (temp) {
+ // Update this file or directory in the in-memory
+ // map index, setting the "draw_filled" field to 0.
+ map_index_update_filled_no(&temp[MPD_FILENAME_OFFSET]);
+ XtFree(temp);
+ }
+ }
+ }
+
+ // Delete all entries in the list and re-create anew.
+ map_properties_fill_in();
+
+ // Save the updated index to the file
+ index_save_to_file();
+}
+
+
+
+// Change the "usgs_drg" field in the in-memory map_index to a
+// specified value.
+void map_index_update_usgs_drg(char *filename, int drg_setting) {
+ map_index_record *current = map_index_head;
+
+ while (current != NULL) {
+ if (strcmp(current->filename,filename) == 0) {
+ // Found a match. Update the field and return.
+ current->usgs_drg = drg_setting;
+ break;
+ }
+ current = current->next;
+ }
+}
+
+
+
+
+// common functionality of all the callbacks. Probably don't even need
+// all the X data here, either
+void map_properties_usgs_drg(Widget widget, XtPointer clientData, XtPointer callData, int drg_setting) {
+ int i, x;
+ XmString *list;
+ char *temp;
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_properties_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the widget's list, changing the usgs_drg field on
+ // every one that is selected.
+ for(x=1; x<=i;x++)
+ {
+ // If the line was selected
+ if ( XmListPosSelected(map_properties_list,x) ) {
+
+ // Snag the filename portion from the line
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_END);
+ if (temp) {
+ // Update this file or directory in the in-memory
+ // map index, setting the "usgs_drg" field to drg_setting.
+ map_index_update_usgs_drg(&temp[MPD_FILENAME_OFFSET],drg_setting);
+ XtFree(temp);
+ }
+ }
+ }
+
+ // Delete all entries in the list and re-create anew.
+ map_properties_fill_in();
+
+ // Save the updated index to the file
+ index_save_to_file();
+}
+
+// the real callbacks
+void map_properties_usgs_drg_auto(Widget widget, XtPointer clientData, XtPointer callData) {
+ map_properties_usgs_drg(widget, clientData, callData, 2);
+}
+void map_properties_usgs_drg_yes(Widget widget, XtPointer clientData, XtPointer callData) {
+ map_properties_usgs_drg(widget, clientData, callData, 1);
+}
+void map_properties_usgs_drg_no(Widget widget, XtPointer clientData, XtPointer callData) {
+ map_properties_usgs_drg(widget, clientData, callData, 0);
+}
+
+
+
+
+
+// Change the "auto_maps" field in the in-memory map_index to a one.
+void map_index_update_auto_maps_yes(char *filename) {
+ map_index_record *current = map_index_head;
+
+ while (current != NULL) {
+ if (strcmp(current->filename,filename) == 0) {
+ // Found a match. Update the field and return.
+ current->auto_maps = 1;
+ return;
+ }
+ current = current->next;
+ }
+}
+
+
+
+
+
+// Change the "auto_maps" field in the in-memory map_index to a
+// zero.
+void map_index_update_auto_maps_no(char *filename) {
+ map_index_record *current = map_index_head;
+
+ while (current != NULL) {
+ if (strcmp(current->filename,filename) == 0) {
+ // Found a match. Update the field and return.
+ current->auto_maps = 0;
+ return;
+ }
+ current = current->next;
+ }
+}
+
+
+
+
+
+void map_properties_auto_maps_yes(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x;
+ XmString *list;
+ char *temp;
+
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_properties_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the widget's list, changing the auto_maps field
+ // on every one that is selected.
+ for(x=1; x<=i;x++)
+ {
+ // If the line was selected
+ if ( XmListPosSelected(map_properties_list,x) ) {
+
+ // Snag the filename portion from the line
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_END);
+ if (temp) {
+ // Update this file or directory in the in-memory
+ // map index, setting the "auto_maps" field to 1.
+ map_index_update_auto_maps_yes(&temp[MPD_FILENAME_OFFSET]);
+ XtFree(temp);
+ }
+ }
+ }
+
+ // Delete all entries in the list and re-create anew.
+ map_properties_fill_in();
+
+ // Save the updated index to the file
+ index_save_to_file();
+}
+
+
+
+
+
+void map_properties_auto_maps_no(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x;
+ XmString *list;
+ char *temp;
+
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_properties_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the widget's list, changing the auto_maps field
+ // on every one that is selected.
+ for(x=1; x<=i;x++)
+ {
+ // If the line was selected
+ if ( XmListPosSelected(map_properties_list,x) ) {
+
+ // Snag the filename portion from the line
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_END);
+ if (temp) {
+ // Update this file or directory in the in-memory
+ // map index, setting the "auto_maps" field to 0.
+ map_index_update_auto_maps_no(&temp[MPD_FILENAME_OFFSET]);
+ XtFree(temp);
+ }
+ }
+ }
+
+ // Delete all entries in the list and re-create anew.
+ map_properties_fill_in();
+
+ // Save the updated index to the file
+ index_save_to_file();
+}
+
+
+
+
+
+// Update the "map_layer" field in the in-memory map_index based on
+// the "map_layer" input parameter.
+void map_index_update_layer(char *filename, int map_layer) {
+ map_index_record *current = map_index_head;
+
+ while (current != NULL) {
+ if (strcmp(current->filename,filename) == 0) {
+ // Found a match. Update the field and return.
+ current->map_layer = map_layer;
+ return;
+ }
+ current = current->next;
+ }
+}
+
+
+
+
+
+void map_properties_layer_change(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x, new_layer;
+ XmString *list;
+ char *temp;
+
+
+ // Get new layer selection in the form of an int
+ temp = XmTextGetString(new_map_layer_text);
+ new_layer = atoi(temp);
+ XtFree(temp);
+
+//fprintf(stderr,"New layer selected is: %d\n", new_layer);
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_properties_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the widget's list, changing the layer on every
+ // one that is selected.
+ for(x=1; x<=i;x++)
+ {
+ // If the line was selected
+ if ( XmListPosSelected(map_properties_list,x) ) {
+
+ // Snag the filename portion from the line
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_END);
+ if (temp) {
+ // Update this file or directory in the in-memory
+ // map index, setting/resetting the "selected" field
+ // as appropriate.
+ map_index_update_layer(&temp[MPD_FILENAME_OFFSET], new_layer);
+ XtFree(temp);
+ }
+ }
+ }
+
+ // Delete all entries in the list and re-create anew.
+ map_properties_fill_in();
+
+ // Save the updated index to the file
+ index_save_to_file();
+}
+
+
+
+
+
+// Update the "max_zoom" field in the in-memory map_index based on
+// the "max_zoom" input parameter.
+void map_index_update_max_zoom(char *filename, int max_zoom) {
+ map_index_record *current = map_index_head;
+
+ while (current != NULL) {
+ if (strcmp(current->filename,filename) == 0) {
+ // Found a match. Update the field and return.
+ current->max_zoom = max_zoom;
+ return;
+ }
+ current = current->next;
+ }
+}
+
+
+
+
+
+void map_properties_max_zoom_change(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x, new_max_zoom;
+ XmString *list;
+ char *temp;
+
+
+ // Get new layer selection in the form of an int
+ temp = XmTextGetString(new_max_zoom_text);
+ new_max_zoom = atoi(temp);
+ XtFree(temp);
+
+// fprintf(stderr,"New max_zoom selected is: %d\n", new_max_zoom);
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_properties_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the widget's list, changing the layer on every
+ // one that is selected.
+ for(x=1; x<=i;x++)
+ {
+ // If the line was selected
+ if ( XmListPosSelected(map_properties_list,x) ) {
+
+ // Snag the filename portion from the line
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_END);
+ if (temp) {
+ // Update this file or directory in the in-memory
+ // map index, setting/resetting the "selected" field
+ // as appropriate.
+ map_index_update_max_zoom(&temp[MPD_FILENAME_OFFSET], new_max_zoom);
+ XtFree(temp);
+ }
+ }
+ }
+
+ // Delete all entries in the list and re-create anew.
+ map_properties_fill_in();
+
+ // Save the updated index to the file
+ index_save_to_file();
+}
+
+
+
+
+
+// Update the "min_zoom" field in the in-memory map_index based on
+// the "min_zoom" input parameter.
+void map_index_update_min_zoom(char *filename, int min_zoom) {
+ map_index_record *current = map_index_head;
+
+ while (current != NULL) {
+ if (strcmp(current->filename,filename) == 0) {
+ // Found a match. Update the field and return.
+ current->min_zoom = min_zoom;
+ return;
+ }
+ current = current->next;
+ }
+}
+
+
+
+
+
+void map_properties_min_zoom_change(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x, new_min_zoom;
+ XmString *list;
+ char *temp;
+
+
+ // Get new layer selection in the form of an int
+ temp = XmTextGetString(new_min_zoom_text);
+ new_min_zoom = atoi(temp);
+ XtFree(temp);
+
+//fprintf(stderr,"New layer selected is: %d\n", new_layer);
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_properties_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the widget's list, changing the layer on every
+ // one that is selected.
+ for(x=1; x<=i;x++)
+ {
+ // If the line was selected
+ if ( XmListPosSelected(map_properties_list,x) ) {
+
+ // Snag the filename portion from the line
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_END);
+ if (temp) {
+ // Update this file or directory in the in-memory
+ // map index, setting/resetting the "selected" field
+ // as appropriate.
+ map_index_update_min_zoom(&temp[MPD_FILENAME_OFFSET], new_min_zoom);
+ XtFree(temp);
+ }
+ }
+ }
+
+ // Delete all entries in the list and re-create anew.
+ map_properties_fill_in();
+
+ // Save the updated index to the file
+ index_save_to_file();
+}
+
+
+
+
+
+// JMT -- now supports max and min zoom levels
+
+// Allows setting map layer and filled polygon properties for maps
+// selected in the map chooser. Show a warning or bring up a
+// confirmation dialog if more than one map is selected when this
+// function is entered. This is the callback function for the
+// Properties button in the Map Chooser.
+//
+// If the map_layer is a range of values, inform the user here
+// via a popup, so that they don't make a mistake and change too
+// many different types of maps to the same map layer.
+//
+// We could either show all maps here and allow changing each
+// one, or just show min/max map_layer draw_filled properties
+// for the maps selected in the Map Chooser.
+//
+// Create the properties dialog. Show the map_layer and
+// draw_filled properties for the maps.
+//
+// Could still create Cancel and OK buttons. Cancel would wipe the
+// in-memory list and fetch it from file again. OK would write the
+// in-memory list to disk.
+//
+void map_properties( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ int i;
+// int x;
+// char *temp;
+// XmString *list;
+ static Widget pane, my_form, button_clear, button_close,
+ rowcol1, rowcol2, rowcol3, label1, label2, label3, label4, label5,
+ button_filled_auto, button_filled_yes, button_filled_no,
+ button_usgs_drg_auto, button_usgs_drg_yes, button_usgs_drg_no,
+ button_layer_change,
+ button_auto_maps_yes, button_auto_maps_no,
+ button_max_zoom_change, button_min_zoom_change,
+ button_select_all;
+ Atom delw;
+ Arg al[50]; // Arg List
+ register unsigned int ac = 0; // Arg Count
+
+
+ busy_cursor(appshell);
+
+ if (map_chooser_dialog) {
+ XtSetSensitive(map_chooser_button_ok, FALSE);
+ XtSetSensitive(map_chooser_button_cancel, FALSE);
+ }
+
+ i=0;
+ if (!map_properties_dialog) {
+
+ map_properties_dialog = XtVaCreatePopupShell(langcode("MAPP001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Map_properties pane",
+ xmPanedWindowWidgetClass,
+ map_properties_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Map_properties my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 7,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ /*set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNvisibleItemCount, 13); ac++;
+ XtSetArg(al[ac], XmNshadowThickness, 3); ac++;
+ XtSetArg(al[ac], XmNselectionPolicy, XmMULTIPLE_SELECT); ac++;
+ XtSetArg(al[ac], XmNscrollBarPlacement, XmBOTTOM_RIGHT); ac++;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ map_properties_list = XmCreateScrolledList(my_form,
+ "Map_properties list",
+ al,
+ ac);
+
+ // Find the names of all the map files on disk and put them
+ // into map_properties_list
+ map_properties_fill_in();
+
+ // Attach a rowcolumn manager widget to my_form to handle
+ // the third button row. Attach it to the bottom of the
+ // form.
+ rowcol3 = XtVaCreateManagedWidget("Map properties rowcol3",
+ xmRowColumnWidgetClass,
+ my_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNkeyboardFocusPolicy, XmEXPLICIT,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Attach a rowcolumn manager widget to my_form to handle
+ // the second button row. Attach it to the top of rowcol3.
+ rowcol2 = XtVaCreateManagedWidget("Map properties rowcol2",
+ xmRowColumnWidgetClass,
+ my_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, rowcol3,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNkeyboardFocusPolicy, XmEXPLICIT,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Attach a rowcolumn manager widget to my_form to handle
+ // the first button row.
+ rowcol1 = XtVaCreateManagedWidget("Map properties rowcol1",
+ xmRowColumnWidgetClass,
+ my_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, rowcol2,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNkeyboardFocusPolicy, XmEXPLICIT,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ label1 = XtVaCreateManagedWidget(langcode("MAPP002"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ label2 = XtVaCreateManagedWidget(langcode("MAPP003"),
+
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, label1,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtVaSetValues(XtParent(map_properties_list),
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, label2,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, rowcol1,
+ XmNbottomOffset, 2,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // JMT -- this is a guess
+// "Max Zoom" stolen from "Change Layer"
+ button_max_zoom_change = XtVaCreateManagedWidget(langcode("MAPP009"),
+ xmPushButtonGadgetClass,
+ rowcol1,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ new_max_zoom_text = XtVaCreateManagedWidget("Map Properties max zoom number",
+ xmTextWidgetClass,
+ rowcol1,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNwidth, ((7*7)+2),
+ XmNmaxLength, 5,
+ XmNbackground, colors[0x0f],
+ XmNrightOffset, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "Min Zoom" stolen from "Change Layer"
+ button_min_zoom_change = XtVaCreateManagedWidget(langcode("MAPP010"),
+ xmPushButtonGadgetClass,
+ rowcol1,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ new_min_zoom_text = XtVaCreateManagedWidget("Map Properties min zoom number",
+ xmTextWidgetClass,
+ rowcol1,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNwidth, ((7*7)+2),
+ XmNmaxLength, 5,
+ XmNbackground, colors[0x0f],
+ XmNrightOffset, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+// "Change Layer"
+ button_layer_change = XtVaCreateManagedWidget(langcode("MAPP004"),
+ xmPushButtonGadgetClass,
+ rowcol1,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ new_map_layer_text = XtVaCreateManagedWidget("Map Properties new layer number",
+ xmTextWidgetClass,
+ rowcol1,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNwidth, ((7*7)+2),
+ XmNmaxLength, 5,
+ XmNbackground, colors[0x0f],
+ XmNrightOffset, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ label3 = XtVaCreateManagedWidget(langcode("MAPP005"),
+ xmLabelWidgetClass,
+ rowcol2,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "Filled-Auto"
+ button_filled_auto = XtVaCreateManagedWidget(langcode("MAPP011"),
+ xmPushButtonGadgetClass,
+ rowcol2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "Filled-Yes"
+ button_filled_yes = XtVaCreateManagedWidget(langcode("MAPP006"),
+ xmPushButtonGadgetClass,
+ rowcol2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "Filled-No"
+ button_filled_no = XtVaCreateManagedWidget(langcode("MAPP007"),
+ xmPushButtonGadgetClass,
+ rowcol2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// Automaps
+ label4 = XtVaCreateManagedWidget(langcode("MAPP008"),
+ xmLabelWidgetClass,
+ rowcol2,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "Automaps-Yes"
+ button_auto_maps_yes = XtVaCreateManagedWidget(langcode("MAPP006"),
+ xmPushButtonGadgetClass,
+ rowcol2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "Automaps-No"
+ button_auto_maps_no = XtVaCreateManagedWidget(langcode("MAPP007"),
+ xmPushButtonGadgetClass,
+ rowcol2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// USGS DRG->
+ label5 = XtVaCreateManagedWidget(langcode("MAPP012"),
+ xmLabelWidgetClass,
+ rowcol2,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "USGS DRG Auto"
+ button_usgs_drg_auto = XtVaCreateManagedWidget(langcode("MAPP011"),
+ xmPushButtonGadgetClass,
+ rowcol2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "USGS DRG Yes"
+ button_usgs_drg_yes = XtVaCreateManagedWidget(langcode("MAPP006"),
+ xmPushButtonGadgetClass,
+ rowcol2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "USGS DRG No"
+ button_usgs_drg_no = XtVaCreateManagedWidget(langcode("MAPP007"),
+ xmPushButtonGadgetClass,
+ rowcol2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "Select All"
+ button_select_all = XtVaCreateManagedWidget(langcode("PULDNMMC09"),
+ xmPushButtonGadgetClass,
+ rowcol3,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "Clear"
+ button_clear = XtVaCreateManagedWidget(langcode("PULDNMMC01"),
+ xmPushButtonGadgetClass,
+ rowcol3,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "Close"
+ button_close = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ rowcol3,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_close, XmNactivateCallback, map_properties_destroy_shell, map_properties_dialog);
+ XtAddCallback(button_clear, XmNactivateCallback, map_properties_deselect_maps, map_properties_dialog);
+ XtAddCallback(button_select_all, XmNactivateCallback, map_properties_select_all_maps, map_properties_dialog);
+ XtAddCallback(button_filled_auto, XmNactivateCallback, map_properties_filled_auto, map_properties_dialog);
+ XtAddCallback(button_filled_yes, XmNactivateCallback, map_properties_filled_yes, map_properties_dialog);
+ XtAddCallback(button_filled_no, XmNactivateCallback, map_properties_filled_no, map_properties_dialog);
+ XtAddCallback(button_usgs_drg_auto, XmNactivateCallback, map_properties_usgs_drg_auto, map_properties_dialog);
+ XtAddCallback(button_usgs_drg_yes, XmNactivateCallback, map_properties_usgs_drg_yes, map_properties_dialog);
+ XtAddCallback(button_usgs_drg_no, XmNactivateCallback, map_properties_usgs_drg_no, map_properties_dialog);
+ XtAddCallback(button_max_zoom_change, XmNactivateCallback, map_properties_max_zoom_change, map_properties_dialog);
+ XtAddCallback(button_min_zoom_change, XmNactivateCallback, map_properties_min_zoom_change, map_properties_dialog);
+ XtAddCallback(button_layer_change, XmNactivateCallback, map_properties_layer_change, map_properties_dialog);
+ XtAddCallback(button_auto_maps_yes, XmNactivateCallback, map_properties_auto_maps_yes, map_properties_dialog);
+ XtAddCallback(button_auto_maps_no, XmNactivateCallback, map_properties_auto_maps_no, map_properties_dialog);
+
+ pos_dialog(map_properties_dialog);
+
+ delw = XmInternAtom(XtDisplay(map_properties_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(map_properties_dialog, delw, map_properties_destroy_shell, (XtPointer)map_properties_dialog);
+
+ XtManageChild(rowcol1);
+ XtManageChild(rowcol2);
+ XtManageChild(rowcol3);
+ XtManageChild(my_form);
+ XtManageChild(map_properties_list);
+ XtVaSetValues(map_properties_list, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(pane);
+
+ XmTextSetString(new_map_layer_text, "0");
+
+ XtPopup(map_properties_dialog,XtGrabNone);
+
+ // Move focus to the OK button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(map_properties_dialog);
+ XmProcessTraversal(button_close, XmTRAVERSE_CURRENT);
+
+ } else {
+ (void)XRaiseWindow(XtDisplay(map_properties_dialog), XtWindow(map_properties_dialog));
+ }
+}
+
+
+
+
+
+/************************* Map Chooser ***********************************/
+/*************************************************************************/
+
+// Destroys the Map Chooser dialog
+void map_chooser_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ map_chooser_dialog = (Widget)NULL;
+}
+
+
+
+
+
+// Update the "selected" field in the in-memory map_index based on
+// the "selected" input parameter.
+void map_index_update_selected(char *filename, int selected, map_index_record **current) {
+
+ // If we're passed a NULL pointer, start at the head of the
+ // in-memory linked list.
+ //
+ if ( (*current) == NULL) {
+ (*current) = map_index_head;
+ }
+
+ // Start searching through the list at the pointer we were
+ // given.
+ //
+ while ( (*current) != NULL) {
+ if (strcmp( (*current)->filename,filename) == 0) {
+ // Found a match. Update the field and return.
+ (*current)->selected = selected;
+ return;
+ }
+ (*current) = (*current)->next;
+ }
+}
+
+
+
+
+
+// Update the "temp_select" field in the in-memory map_index.
+void map_index_update_temp_select(char *filename, map_index_record **current) {
+ int result;
+
+ // If we're passed a NULL pointer, start at the head of the
+ // in-memory linked list.
+ //
+ if ( (*current) == NULL) {
+ (*current) = map_index_head;
+ }
+
+ // Start searching through the list at the pointer we were
+ // given. We need to do a loose match here for directories. If
+ // a selected directory is contained in a filepath, select that
+ // file as well. For the directory case, once we find a match
+ // in the file path, keep walking down the list until we get a
+ // non-match.
+ //
+ while ( (*current) != NULL) {
+
+ result = strncmp( (*current)->filename,filename,strlen(filename));
+
+ if (result == 0) {
+ // Found a match. Update the field.
+ (*current)->temp_select = 1;
+ }
+ else if (result > 0) { // We passsed the relevant area.
+ // All done for now.
+ return;
+ }
+ (*current) = (*current)->next;
+ }
+}
+
+
+
+
+
+// Clear all of the temp_select bits in the in-memory map index
+void map_index_temp_select_clear(void) {
+ map_index_record *current;
+
+ current = map_index_head;
+ while (current != NULL) {
+ current->temp_select = 0;
+ current = current->next;
+ }
+}
+
+
+
+
+
+// Gets the list of selected maps out of the dialog, writes them to
+// the selected maps disk file, destroys the dialog, then calls
+// create_image() with the newly selected map set in place. This
+// should be the _only_ routine in this set of functions that
+// actually changes the selected maps disk file. The others should
+// merely manipulate the list in the map chooser dialog. This
+// function is attached to the "OK" button in the Map Chooser dialog.
+//
+// What we'll do here is set/reset the "selected" field in the
+// in-memory map_index list, then write the info out to the
+// selected_maps.sys file. Only set the file entries if in file
+// mode, dir entries if in dir mode. When writing out to file,
+// write them both out.
+//
+// In order to make this fast, we'll send a start pointer to
+// map_index_update_selected() which is the "next" pointer from the
+// previous hit. We're relying on the fact that the Map Chooser
+// list and the in-memory linked list are in the same search order,
+// so this way we don't search through the entire linked list for
+// each update. With 30,000 maps, it ended up being up to 30,000 *
+// 30,000 for the loop iterations, which was unwieldy.
+//
+void map_chooser_select_maps(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x;
+ char *temp;
+ XmString *list;
+ FILE *f;
+ map_index_record *ptr = map_index_head;
+ char selected_map_path[MAX_VALUE];
+
+ get_user_base_dir(SELECTED_MAP_DATA, selected_map_path,
+ sizeof(selected_map_path));
+
+// It'd be nice to turn off auto-maps here, or better perhaps would
+// be if any button were chosen other than "Cancel".
+
+ // reset map_refresh in case we no longer have a refreshed map selected
+ map_refresh_interval = 0;
+
+ // Cause load_maps() and load_automaps() to re-sort the selected
+ // maps by layer.
+ re_sort_maps = 1;
+
+ // Get the list and the list count from the dialog
+ XtVaGetValues(map_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the list, updating the equivalent entries in the
+ // in-memory map index. If we're in "directory" mode we'll only
+ // update the directory entries. In "Expanded dirs" mode, we'll
+ // update both file and directory entries.
+ // The end result is that both directories and files may be
+ // selected, not either/or as the code was written earlier.
+ //
+ // Here we basically walk both lists together, the List widget
+ // and the in-memory linked list, as they're both in the same
+ // sort order. We do this by passing "ptr" back and forth, and
+ // updating it to point to one after the last one found each
+ // time. That turns and N*N search into an N search and is a
+ // big speed improvement when you have 1000's of maps.
+ //
+ for(x=1; x<=i;x++) {
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_BEGINNING);
+ if (temp) {
+ // Update this file or directory in the in-memory map
+ // index, setting/resetting the "selected" field as
+ // appropriate.
+ map_index_update_selected(temp,
+ XmListPosSelected(map_list,x),
+ &ptr);
+ XtFree(temp);
+ }
+ //fprintf(stderr,"Passed back: %s\n", ptr->filename);
+ ptr = ptr->next;
+ }
+
+ // Now we have all of the updates done to the in-memory map
+ // index. Write out the selected maps to disk, overwriting
+ // whatever was there before.
+
+ ptr = map_index_head;
+ f=fopen( selected_map_path , "w+" );
+ if (f!=NULL) {
+
+ while (ptr != NULL) {
+ // Write only selected files/directories out to the disk
+ // file.
+ if (ptr->selected) {
+ fprintf(f,"%s\n",ptr->filename);
+ }
+ ptr = ptr->next;
+ }
+ (void)fclose(f);
+ }
+ else
+ fprintf(stderr,"Couldn't open file: %s\n", selected_map_path );
+
+ map_chooser_destroy_shell(widget,clientData,callData);
+
+ // Set interrupt_drawing_now because conditions have changed.
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(da)) {
+// (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0;
+// }
+}
+
+
+
+
+
+// Same as map_chooser_select_maps, but doesn't destroy the Map
+// Chooser dialog.
+void map_chooser_apply_maps(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x;
+ char *temp;
+ XmString *list;
+ FILE *f;
+ map_index_record *ptr = map_index_head;
+ char selected_map_path[MAX_VALUE];
+
+ get_user_base_dir(SELECTED_MAP_DATA, selected_map_path,
+ sizeof(selected_map_path));
+
+// It'd be nice to turn off auto-maps here, or better perhaps would
+// be if any button were chosen other than "Cancel".
+
+ // reset map_refresh in case we no longer have a refreshed map selected
+ map_refresh_interval = 0;
+
+ // Cause load_maps() and load_automaps() to re-sort the selected
+ // maps by layer.
+ re_sort_maps = 1;
+
+ // Get the list and the list count from the dialog
+ XtVaGetValues(map_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the list, updating the equivalent entries in the
+ // in-memory map index. If we're in "directory" mode we'll only
+ // update the directory entries. In "Expanded dirs" mode, we'll
+ // update both file and directory entries.
+ // The end result is that both directories and files may be
+ // selected, not either/or as the code was written earlier.
+ //
+ // Here we basically walk both lists together, the List widget
+ // and the in-memory linked list, as they're both in the same
+ // sort order. We do this by passing "ptr" back and forth, and
+ // updating it to point to one after the last one found each
+ // time. That turns and N*N search into an N search and is a
+ // big speed improvement when you have 1000's of maps.
+ //
+ for(x=1; x<=i;x++) {
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_BEGINNING);
+ if (temp) {
+ // Update this file or directory in the in-memory map
+ // index, setting/resetting the "selected" field as
+ // appropriate.
+ map_index_update_selected(temp,
+ XmListPosSelected(map_list,x),
+ &ptr);
+ XtFree(temp);
+ }
+//fprintf(stderr,"Passed back: %s\n", ptr->filename);
+ ptr = ptr->next;
+ }
+
+ // Now we have all of the updates done to the in-memory map
+ // index. Write out the selected maps to disk, overwriting
+ // whatever was there before.
+
+ ptr = map_index_head;
+
+ f=fopen( selected_map_path, "w+" );
+ if (f!=NULL) {
+
+ while (ptr != NULL) {
+ // Write only selected files/directories out to the disk
+ // file.
+ if (ptr->selected) {
+ fprintf(f,"%s\n",ptr->filename);
+ }
+ ptr = ptr->next;
+ }
+ (void)fclose(f);
+ }
+ else
+ fprintf(stderr,"Couldn't open file: %s\n", selected_map_path );
+
+// map_chooser_destroy_shell(widget,clientData,callData);
+
+ // Set interrupt_drawing_now because conditions have changed.
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(da)) {
+// (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+}
+
+
+
+
+
+// Counts the number of "selected" fields with a value of 1 in the
+// in-memory map index. Updates the "Dirs/Maps Selected" count in
+// the map chooser.
+void map_chooser_update_quantity(void) {
+ int dir_quantity = 0;
+ int map_quantity = 0;
+ static char str_quantity[100];
+ map_index_record *current = map_index_head;
+ XmString x_str;
+
+ // Count the "selected" fields in the map index with value of 1
+ while (current != NULL) {
+ if (current->selected) {
+
+ if (current->filename[strlen(current->filename)-1] == '/') {
+ // It's a directory
+ dir_quantity++;
+ }
+ else {
+ // It's a map
+ map_quantity++;
+ }
+ }
+ current = current->next;
+ }
+
+ // Update the "Dirs/Maps Selected" label in the Map Chooser
+ xastir_snprintf(str_quantity,
+ sizeof(str_quantity),
+ "%d/%d",
+ dir_quantity,
+ map_quantity);
+ x_str = XmStringCreateLocalized(str_quantity);
+ XtVaSetValues(map_chooser_maps_selected_data,
+ XmNlabelString, x_str,
+ NULL);
+ XmStringFree(x_str);
+}
+
+
+
+
+
+void map_chooser_select_vector_maps(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x;
+ char *temp;
+ char *ext;
+ XmString *list;
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the list looking for matching file extensions
+ for(x=1; x<=i;x++) {
+
+// // Deselect all currently selected maps
+// if (XmListPosSelected(map_list,x)) {
+// XmListDeselectPos(map_list,x);
+// }
+
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_BEGINNING);
+ if(temp) {
+ ext = get_map_ext (temp);
+ if ( (ext != NULL)
+ && ( (strcasecmp(ext,"map") == 0)
+ || (strcasecmp(ext,"shp") == 0)
+ || (strcasecmp(ext,"pdb") == 0)
+ || (strcasecmp(ext,"gnis") == 0)
+ || (strcasecmp(ext,"rt1") == 0)
+ || (strcasecmp(ext,"rt2") == 0)
+ || (strcasecmp(ext,"rt4") == 0)
+ || (strcasecmp(ext,"rt5") == 0)
+ || (strcasecmp(ext,"rt6") == 0)
+ || (strcasecmp(ext,"rt7") == 0)
+ || (strcasecmp(ext,"rt8") == 0)
+ || (strcasecmp(ext,"rta") == 0)
+ || (strcasecmp(ext,"rtc") == 0)
+ || (strcasecmp(ext,"rth") == 0)
+ || (strcasecmp(ext,"rti") == 0)
+ || (strcasecmp(ext,"rtp") == 0)
+ || (strcasecmp(ext,"rtr") == 0)
+ || (strcasecmp(ext,"rts") == 0)
+ || (strcasecmp(ext,"rtt") == 0)
+ || (strcasecmp(ext,"rtz") == 0)
+ || (strcasecmp(ext,"tab") == 0) ) ) {
+ XmListSelectPos(map_list,x,TRUE);
+ }
+ XtFree(temp);
+ }
+ }
+
+ map_chooser_update_quantity();
+}
+
+
+
+
+
+void map_chooser_select_250k_maps(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x, length;
+ char *temp;
+ char *ext;
+ XmString *list;
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the list looking for matching file extensions
+ for(x=1; x<=i;x++) {
+
+// // Deselect all currently selected maps
+// if (XmListPosSelected(map_list,x)) {
+// XmListDeselectPos(map_list,x);
+// }
+
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_BEGINNING);
+ if(temp) {
+ ext = get_map_ext (temp);
+ length = (int)strlen(temp);
+ if ( (ext != NULL) && (strcasecmp (ext, "tif") == 0)
+ && (length >= 12) // "o48122h3.tif", we might have subdirectories also
+ && ( (temp[length - 12] == 'c') || (temp[length - 12] == 'C') ) ) {
+ XmListSelectPos(map_list,x,TRUE);
+ }
+ XtFree(temp);
+ }
+ }
+
+ map_chooser_update_quantity();
+}
+
+
+
+
+
+void map_chooser_select_100k_maps(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x, length;
+ char *temp;
+ char *ext;
+ XmString *list;
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the list looking for matching file extensions
+ for(x=1; x<=i;x++) {
+
+// // Deselect all currently selected maps
+// if (XmListPosSelected(map_list,x)) {
+// XmListDeselectPos(map_list,x);
+// }
+
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_BEGINNING);
+ if(temp) {
+ ext = get_map_ext (temp);
+ length = (int)strlen(temp);
+ if ( (ext != NULL) && (strcasecmp (ext, "tif") == 0)
+ && (length >= 12) // "o48122h3.tif", we might have subdirectories also
+ && ( (temp[length - 12] == 'f') || (temp[length - 12] == 'F') ) ) {
+ XmListSelectPos(map_list,x,TRUE);
+ }
+ XtFree(temp);
+ }
+ }
+
+ map_chooser_update_quantity();
+}
+
+
+
+
+
+void map_chooser_select_24k_maps(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x, length;
+ char *temp;
+ char *ext;
+ XmString *list;
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the list looking for matching file extensions
+ for(x=1; x<=i;x++) {
+
+// // Deselect all currently selected maps
+// if (XmListPosSelected(map_list,x)) {
+// XmListDeselectPos(map_list,x);
+// }
+
+ temp = XmStringUnparse(list[(x-1)], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_BEGINNING);
+ if(temp) {
+ ext = get_map_ext (temp);
+ length = (int)strlen(temp);
+ if ( (ext != NULL) && (strcasecmp (ext, "tif") == 0)
+ && (length >= 12) // "o48122h3.tif", we might have subdirectories also
+ && ( (temp[length - 12] == 'o') || (temp[length - 12] == 'O')
+ || (temp[length - 12] == 'k') || (temp[length - 12] == 'K') ) ) {
+ XmListSelectPos(map_list,x,TRUE);
+ }
+ XtFree(temp);
+ }
+ }
+
+ map_chooser_update_quantity();
+}
+
+
+
+
+
+// Removes the highlighting for maps in the current view of the map
+// chooser. In order to de-select all maps, must flip through both
+// map chooser views and hit the "none" button each time, then hit
+// the "ok" button.
+//
+// Changed the code to clear all of the "selected" bits in the
+// in-memory map index as well. The "None" and "OK" buttons take
+// immediate effect, all others do not (until the "OK" button is
+// pressed). Decided that this was too inconsistent, so changed it
+// back and changed "None" to "Clear", which means to clear the
+// currently seen selections, but not the selections in the other
+// mode.
+//
+void map_chooser_deselect_maps(Widget widget, XtPointer clientData, XtPointer callData) {
+ int i, x;
+ XmString *list;
+// map_index_record *current = map_index_head;
+
+ // Get the list and the count from the dialog
+ XtVaGetValues(map_list,
+ XmNitemCount,&i,
+ XmNitems,&list,
+ NULL);
+
+ // Run through the widget's list, deselecting every line
+ for(x=1; x<=i;x++)
+ {
+ if (XmListPosSelected(map_list,x)) {
+ XmListDeselectPos(map_list,x);
+ }
+ }
+
+/*
+ // Run through the in-memory map list, deselecting every line
+ while (current != NULL) {
+ current->selected = 0; // Not Selected
+ current = current->next;
+ }
+*/
+
+ map_chooser_update_quantity();
+}
+
+
+
+
+
+void sort_list(char *filename,int size, Widget list, int *item) {
+ FILE *f_data;
+ FILE *f_pointer;
+ char fill[2000];
+ long file_ptr;
+ long ptr;
+ char ptr_filename[400];
+ XmString str_ptr;
+
+ // Clear the list widget first
+ XmListDeleteAllItems(list);
+
+ xastir_snprintf(ptr_filename, sizeof(ptr_filename), "%s-ptr", filename);
+ f_pointer=fopen(ptr_filename,"r");
+ f_data=fopen(filename,"r");
+ if (f_pointer!=NULL && f_data !=NULL) {
+ while (!feof(f_pointer)) {
+ ptr=ftell(f_pointer);
+ if (fread(&file_ptr,sizeof(file_ptr),1,f_pointer)==1) {
+ (void)fseek(f_data,file_ptr,SEEK_SET);
+ if (fread(fill,(size_t)size,1,f_data)==1) {
+ str_ptr = XmStringCreateLocalized(fill);
+ XmListAddItem(list, str_ptr,*item);
+ XmStringFree(str_ptr);
+ (*item)++;
+ }
+ }
+ }
+ }
+ if(f_pointer!=NULL)
+ (void)fclose(f_pointer);
+ else
+ fprintf(stderr,"Couldn't open file: %s\n", ptr_filename);
+
+
+ if(f_data!=NULL)
+ (void)fclose(f_data);
+ else
+ fprintf(stderr,"Couldn't open file: %s\n", filename);
+}
+
+
+
+
+
+// Mark the "selected" field in the in-memory map index based on the
+// contents of the selected_maps.sys file. Called from main() right
+// after map_indexer() is called on startup.
+void map_chooser_init (void) {
+ FILE *f;
+ char temp[600];
+ map_index_record *current;
+ char selected_map_path[MAX_VALUE];
+
+ get_user_base_dir(SELECTED_MAP_DATA, selected_map_path,
+ sizeof(selected_map_path));
+
+
+ busy_cursor(appshell);
+
+ // First run through our in-memory map index, clearing all of
+ // the selected bits.
+ current = map_index_head;
+ while (current != NULL) {
+ current->selected = 0;
+ current = current->next;
+ }
+
+ (void)filecreate( selected_map_path ); // Create empty file if it doesn't exist
+
+ f=fopen( selected_map_path, "r" );
+ if (f!=NULL) {
+ while(!feof(f)) {
+ int done;
+
+ (void)get_line(f,temp,600);
+
+ // We have a line from the file. Find the matching line
+ // in the in-memory map index.
+ current = map_index_head;
+ done = 0;
+ while (current != NULL && !done) {
+ //fprintf(stderr,"%s\n",current->filename);
+
+ if (strcmp(temp,current->filename) == 0) {
+ current->selected = 1;
+ done++;
+ }
+ current = current->next;
+ }
+ }
+ (void)fclose(f);
+ }
+ else {
+ fprintf(stderr,"Couldn't open file: %s\n", selected_map_path );
+ }
+}
+
+
+
+
+
+// Fills in the map chooser file/directory entries based on the
+// current view and whether the "selected" field in the in-memory
+// map_index is set for each file/directory.
+//
+// We also check the XmStringPtr field in the map index records. If
+// NULL, then we call XmStringCreateLocalized() to allocate and fill in
+// the XmString value corresponding to the filename. We use that to
+// speed up Map Chooser later.
+//
+void map_chooser_fill_in (void) {
+ int n,i;
+ map_index_record *current = map_index_head;
+
+
+ busy_cursor(appshell);
+
+ i=0;
+ if (map_chooser_dialog) {
+
+ // Empty the map_list widget first
+ XmListDeleteAllItems(map_list);
+
+ // Put all the map files/dirs in the map_index into the Map
+ // Chooser dialog list (map_list).
+ n=1;
+
+ while (current != NULL) {
+
+ //fprintf(stderr,"%s\n",current->filename);
+
+ // Check whether we're supposed to show dirs and files or
+ // just dirs. Directories are always shown.
+ if (map_chooser_expand_dirs // Show all
+ || current->filename[strlen(current->filename)-1] == '/') {
+
+
+// Try XmListAddItems() here? Could also create XmString's for each
+// filename and keep them in the map index. Then we wouldn't have to
+// free that malloc/free that storage space all the time.
+// XmListAddItems()
+// XmListAddItemsUnselected()
+// XmListReplaceItems()
+// XmListReplaceItemsUnselected()
+
+
+ // If pointer is NULL, malloc and create the
+ // XmString corresponding to the filename, attach it
+ // to the record. The 2nd and succeeding times we
+ // bring up Map Chooser, things will be faster.
+ if (current->XmStringPtr == NULL) {
+ current->XmStringPtr = XmStringCreateLocalized(current->filename);
+ }
+
+ XmListAddItem(map_list,
+ current->XmStringPtr,
+ n);
+
+ // If a selected map, hilight it in the list
+ if (current->selected) {
+ XmListSelectPos(map_list,i,TRUE);
+ }
+
+ n++;
+ }
+ current = current->next;
+ }
+ }
+}
+
+
+
+
+
+/////////////////////////////////////// Configure Tigermaps Dialog //////////////////////////////////////////////
+//N0VH
+#if defined(HAVE_MAGICK)
+
+
+
+void Configure_tiger_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ configure_tiger_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Configure_tiger_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+
+ if(XmToggleButtonGetState(tiger_grid))
+ tiger_show_grid=TRUE;
+ else
+ tiger_show_grid=FALSE;
+
+ if(XmToggleButtonGetState(tiger_counties))
+ tiger_show_counties=TRUE;
+ else
+ tiger_show_counties=FALSE;
+
+ if(XmToggleButtonGetState(tiger_cities))
+ tiger_show_cities=TRUE;
+ else
+ tiger_show_cities=FALSE;
+
+ if(XmToggleButtonGetState(tiger_places))
+ tiger_show_places=TRUE;
+ else
+ tiger_show_places=FALSE;
+
+ if(XmToggleButtonGetState(tiger_majroads))
+ tiger_show_majroads=TRUE;
+ else
+ tiger_show_majroads=FALSE;
+
+ if(XmToggleButtonGetState(tiger_streets))
+ tiger_show_streets=TRUE;
+ else
+ tiger_show_streets=FALSE;
+
+ if(XmToggleButtonGetState(tiger_railroad))
+ tiger_show_railroad=TRUE;
+ else
+ tiger_show_railroad=FALSE;
+
+ if(XmToggleButtonGetState(tiger_water))
+ tiger_show_water=TRUE;
+ else
+ tiger_show_water=FALSE;
+
+ if(XmToggleButtonGetState(tiger_lakes))
+ tiger_show_lakes=TRUE;
+ else
+ tiger_show_lakes=FALSE;
+
+ if(XmToggleButtonGetState(tiger_misc))
+ tiger_show_misc=TRUE;
+ else
+ tiger_show_misc=FALSE;
+
+ if(XmToggleButtonGetState(tiger_states))
+ tiger_show_states=TRUE;
+ else
+ tiger_show_states=FALSE;
+
+ if(XmToggleButtonGetState(tiger_interstate))
+ tiger_show_interstate=TRUE;
+ else
+ tiger_show_interstate=FALSE;
+
+ if(XmToggleButtonGetState(tiger_ushwy))
+ tiger_show_ushwy=TRUE;
+ else
+ tiger_show_ushwy=FALSE;
+
+ if(XmToggleButtonGetState(tiger_statehwy))
+ tiger_show_statehwy=TRUE;
+ else
+ tiger_show_statehwy=FALSE;
+
+ Configure_tiger_destroy_shell(widget,clientData,callData);
+
+ // Reload maps
+ // Set interrupt_drawing_now because conditions have
+ // changed.
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls
+ // create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+// if (create_image(da)) {
+// (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+// }
+}
+
+
+
+
+
+////////////////////////////////////////////// Config_tiger//////////////////////////////////////////////////////
+//
+//
+void Config_tiger( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget tiger_pane, tiger_form, button_ok, button_cancel, tiger_label1, sep;
+
+ Atom delw;
+
+ if (!configure_tiger_dialog) {
+
+ configure_tiger_dialog = XtVaCreatePopupShell(langcode("PULDNMP020"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_pane = XtVaCreateWidget("Configure_tiger pane",
+ xmPanedWindowWidgetClass,
+ configure_tiger_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ tiger_form = XtVaCreateWidget("Configure_tiger tiger_form",
+ xmFormWidgetClass,
+ tiger_pane,
+ XmNfractionBase, 3,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ tiger_label1 = XtVaCreateManagedWidget(langcode("MPUPTGR012"),
+ xmLabelWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_grid = XtVaCreateManagedWidget(langcode("MPUPTGR001"),
+ xmToggleButtonWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tiger_label1,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_counties = XtVaCreateManagedWidget(langcode("MPUPTGR002"),
+ xmToggleButtonWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tiger_label1,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_states = XtVaCreateManagedWidget(langcode("MPUPTGR008"),
+ xmToggleButtonWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tiger_label1,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_cities = XtVaCreateManagedWidget(langcode("MPUPTGR003"),
+ xmToggleButtonWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tiger_grid,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_places = XtVaCreateManagedWidget(langcode("MPUPTGR004"),
+ xmToggleButtonWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tiger_grid,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_interstate = XtVaCreateManagedWidget(langcode("MPUPTGR009"),
+ xmToggleButtonWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tiger_grid,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_majroads = XtVaCreateManagedWidget(langcode("MPUPTGR005"),
+ xmToggleButtonWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tiger_cities,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_streets = XtVaCreateManagedWidget(langcode("MPUPTGR006"),
+ xmToggleButtonWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tiger_cities,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_ushwy = XtVaCreateManagedWidget(langcode("MPUPTGR010"),
+ xmToggleButtonWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tiger_cities,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_railroad = XtVaCreateManagedWidget(langcode("MPUPTGR007"),
+ xmToggleButtonWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tiger_majroads,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_water = XtVaCreateManagedWidget(langcode("MPUPTGR013"),
+ xmToggleButtonWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tiger_majroads,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_statehwy = XtVaCreateManagedWidget(langcode("MPUPTGR011"),
+ xmToggleButtonWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tiger_majroads,
+ XmNtopOffset, 4,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_lakes = XtVaCreateManagedWidget(langcode("MPUPTGR014"),
+ xmToggleButtonWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tiger_railroad,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ tiger_misc = XtVaCreateManagedWidget(langcode("MPUPTGR015"),
+ xmToggleButtonWidgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, tiger_railroad,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sep = XtVaCreateManagedWidget("Config Tigermap sep",
+ xmSeparatorGadgetClass,
+ tiger_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, tiger_lakes,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNrightOffset, 0,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),
+ xmPushButtonGadgetClass,
+ tiger_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Configure_tiger_change_data, configure_tiger_dialog);
+
+ XtAddCallback(button_cancel, XmNactivateCallback, Configure_tiger_destroy_shell, configure_tiger_dialog);
+
+ pos_dialog(configure_tiger_dialog);
+
+ delw = XmInternAtom(XtDisplay(configure_tiger_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(configure_tiger_dialog, delw, Configure_tiger_destroy_shell,
+ (XtPointer)configure_tiger_dialog);
+
+ if(tiger_show_grid)
+ XmToggleButtonSetState(tiger_grid,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(tiger_grid,FALSE,FALSE);
+
+ if(tiger_show_counties)
+ XmToggleButtonSetState(tiger_counties,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(tiger_counties,FALSE,FALSE);
+
+ if(tiger_show_cities)
+ XmToggleButtonSetState(tiger_cities,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(tiger_cities,FALSE,FALSE);
+
+ if(tiger_show_places)
+ XmToggleButtonSetState(tiger_places,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(tiger_places,FALSE,FALSE);
+
+ if(tiger_show_majroads)
+ XmToggleButtonSetState(tiger_majroads,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(tiger_majroads,FALSE,FALSE);
+
+ if(tiger_show_streets)
+ XmToggleButtonSetState(tiger_streets,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(tiger_streets,FALSE,FALSE);
+
+ if(tiger_show_railroad)
+ XmToggleButtonSetState(tiger_railroad,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(tiger_railroad,FALSE,FALSE);
+
+ if(tiger_show_water)
+ XmToggleButtonSetState(tiger_water,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(tiger_water,FALSE,FALSE);
+
+ if(tiger_show_lakes)
+ XmToggleButtonSetState(tiger_lakes,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(tiger_lakes,FALSE,FALSE);
+
+ if(tiger_show_misc)
+ XmToggleButtonSetState(tiger_misc,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(tiger_misc,FALSE,FALSE);
+
+ if(tiger_show_states)
+ XmToggleButtonSetState(tiger_states,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(tiger_states,FALSE,FALSE);
+
+ if(tiger_show_interstate)
+ XmToggleButtonSetState(tiger_interstate,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(tiger_interstate,FALSE,FALSE);
+
+ if(tiger_show_ushwy)
+ XmToggleButtonSetState(tiger_ushwy,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(tiger_ushwy,FALSE,FALSE);
+
+ if(tiger_show_statehwy)
+ XmToggleButtonSetState(tiger_statehwy,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(tiger_statehwy,FALSE,FALSE);
+
+ XtManageChild(tiger_form);
+ XtManageChild(tiger_pane);
+
+ XtPopup(configure_tiger_dialog,XtGrabNone);
+ fix_dialog_size(configure_tiger_dialog);
+
+ XmProcessTraversal(button_ok, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(configure_tiger_dialog), XtWindow(configure_tiger_dialog));
+}
+#endif // HAVE_MAGICK
+///////////////////////// End of Configure Tiger code ///////////////////////////////////
+
+
+
+
+
+/////////////////////////////////////// Configure DRG Dialog //////////////////////////////////////////////
+#if defined(HAVE_LIBGEOTIFF)
+void Configure_DRG_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+
+ if (configure_DRG_dialog) {
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ configure_DRG_dialog = (Widget)NULL;
+ }
+}
+
+
+
+
+
+void Configure_DRG_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+
+ if (configure_DRG_dialog) {
+
+ if(XmToggleButtonGetState(DRG_XOR))
+ DRG_XOR_colors=TRUE;
+ else
+ DRG_XOR_colors=FALSE;
+
+ if(XmToggleButtonGetState(DRG_color0))
+ DRG_show_colors[0]=TRUE;
+ else
+ DRG_show_colors[0]=FALSE;
+
+ if(XmToggleButtonGetState(DRG_color1))
+ DRG_show_colors[1]=TRUE;
+ else
+ DRG_show_colors[1]=FALSE;
+
+ if(XmToggleButtonGetState(DRG_color2))
+ DRG_show_colors[2]=TRUE;
+ else
+ DRG_show_colors[2]=FALSE;
+
+ if(XmToggleButtonGetState(DRG_color3))
+ DRG_show_colors[3]=TRUE;
+ else
+ DRG_show_colors[3]=FALSE;
+
+ if(XmToggleButtonGetState(DRG_color4))
+ DRG_show_colors[4]=TRUE;
+ else
+ DRG_show_colors[4]=FALSE;
+
+ if(XmToggleButtonGetState(DRG_color5))
+ DRG_show_colors[5]=TRUE;
+ else
+ DRG_show_colors[5]=FALSE;
+
+ if(XmToggleButtonGetState(DRG_color6))
+ DRG_show_colors[6]=TRUE;
+ else
+ DRG_show_colors[6]=FALSE;
+
+ if(XmToggleButtonGetState(DRG_color7))
+ DRG_show_colors[7]=TRUE;
+ else
+ DRG_show_colors[7]=FALSE;
+
+ if(XmToggleButtonGetState(DRG_color8))
+ DRG_show_colors[8]=TRUE;
+ else
+ DRG_show_colors[8]=FALSE;
+
+ if(XmToggleButtonGetState(DRG_color9))
+ DRG_show_colors[9]=TRUE;
+ else
+ DRG_show_colors[9]=FALSE;
+
+ if(XmToggleButtonGetState(DRG_color10))
+ DRG_show_colors[10]=TRUE;
+ else
+ DRG_show_colors[10]=FALSE;
+
+ if(XmToggleButtonGetState(DRG_color11))
+ DRG_show_colors[11]=TRUE;
+ else
+ DRG_show_colors[11]=FALSE;
+
+ if(XmToggleButtonGetState(DRG_color12))
+ DRG_show_colors[12]=TRUE;
+ else
+ DRG_show_colors[12]=FALSE;
+
+ Configure_DRG_destroy_shell(widget,clientData,callData);
+
+ // Reload maps
+ // Set interrupt_drawing_now because conditions have
+ // changed.
+ interrupt_drawing_now++;
+
+ // Request that a new image be created. Calls
+ // create_image,
+ // XCopyArea, and display_zoom_status.
+ request_new_image++;
+
+ // if (create_image(da)) {
+ // (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+ // }
+
+ }
+}
+
+
+
+
+
+void Configure_DRG_all(Widget widget, XtPointer clientData, XtPointer callData) {
+
+ if (configure_DRG_dialog) {
+ XmToggleButtonSetState(DRG_color0,TRUE,FALSE);
+ XmToggleButtonSetState(DRG_color1,TRUE,FALSE);
+ XmToggleButtonSetState(DRG_color2,TRUE,FALSE);
+ XmToggleButtonSetState(DRG_color3,TRUE,FALSE);
+ XmToggleButtonSetState(DRG_color4,TRUE,FALSE);
+ XmToggleButtonSetState(DRG_color5,TRUE,FALSE);
+ XmToggleButtonSetState(DRG_color6,TRUE,FALSE);
+ XmToggleButtonSetState(DRG_color7,TRUE,FALSE);
+ XmToggleButtonSetState(DRG_color8,TRUE,FALSE);
+ XmToggleButtonSetState(DRG_color9,TRUE,FALSE);
+ XmToggleButtonSetState(DRG_color10,TRUE,FALSE);
+ XmToggleButtonSetState(DRG_color11,TRUE,FALSE);
+ XmToggleButtonSetState(DRG_color12,TRUE,FALSE);
+ }
+}
+
+
+
+
+
+void Configure_DRG_none(Widget widget, XtPointer clientData, XtPointer callData) {
+
+ if (configure_DRG_dialog) {
+ XmToggleButtonSetState(DRG_color0,FALSE,FALSE);
+ XmToggleButtonSetState(DRG_color1,FALSE,FALSE);
+ XmToggleButtonSetState(DRG_color2,FALSE,FALSE);
+ XmToggleButtonSetState(DRG_color3,FALSE,FALSE);
+ XmToggleButtonSetState(DRG_color4,FALSE,FALSE);
+ XmToggleButtonSetState(DRG_color5,FALSE,FALSE);
+ XmToggleButtonSetState(DRG_color6,FALSE,FALSE);
+ XmToggleButtonSetState(DRG_color7,FALSE,FALSE);
+ XmToggleButtonSetState(DRG_color8,FALSE,FALSE);
+ XmToggleButtonSetState(DRG_color9,FALSE,FALSE);
+ XmToggleButtonSetState(DRG_color10,FALSE,FALSE);
+ XmToggleButtonSetState(DRG_color11,FALSE,FALSE);
+ XmToggleButtonSetState(DRG_color12,FALSE,FALSE);
+ }
+}
+
+
+
+
+
+void Config_DRG( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget DRG_pane, DRG_form, button_ok, button_cancel,
+ DRG_label1, sep1, sep2, button_all, button_none;
+
+ Atom delw;
+
+ if (!configure_DRG_dialog) {
+
+ configure_DRG_dialog = XtVaCreatePopupShell(langcode("PULDNMP030"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ DRG_pane = XtVaCreateWidget("Configure_DRG pane",
+ xmPanedWindowWidgetClass,
+ configure_DRG_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ DRG_form = XtVaCreateWidget("Configure_DRG DRG_form",
+ xmFormWidgetClass,
+ DRG_pane,
+ XmNfractionBase, 3,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ DRG_XOR = XtVaCreateManagedWidget(langcode("MPUPDRG002"),
+ xmToggleButtonWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sep1 = XtVaCreateManagedWidget("Config Tigermap sep1",
+ xmSeparatorGadgetClass,
+ DRG_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, DRG_XOR,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ DRG_label1 = XtVaCreateManagedWidget(langcode("MPUPDRG001"),
+ xmLabelWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep1,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+// Column 1
+ // Black
+ DRG_color0 = XtVaCreateManagedWidget(langcode("MPUPDRG003"),
+ xmToggleButtonWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, DRG_label1,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Blue
+ DRG_color2 = XtVaCreateManagedWidget(langcode("MPUPDRG005"),
+ xmToggleButtonWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, DRG_color0,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Red
+ DRG_color3 = XtVaCreateManagedWidget(langcode("MPUPDRG006"),
+ xmToggleButtonWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, DRG_color2,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Brown
+ DRG_color4 = XtVaCreateManagedWidget(langcode("MPUPDRG007"),
+ xmToggleButtonWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, DRG_color3,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Purple
+ DRG_color6 = XtVaCreateManagedWidget(langcode("MPUPDRG009"),
+ xmToggleButtonWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, DRG_color4,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// Column 2
+ // Light Gray
+ DRG_color11 = XtVaCreateManagedWidget(langcode("MPUPDRG014"),
+ xmToggleButtonWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, DRG_label1,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Light Blue
+ DRG_color8 = XtVaCreateManagedWidget(langcode("MPUPDRG011"),
+ xmToggleButtonWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, DRG_color11,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Light Red
+ DRG_color9 = XtVaCreateManagedWidget(langcode("MPUPDRG012"),
+ xmToggleButtonWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, DRG_color8,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Light Brown
+ DRG_color12 = XtVaCreateManagedWidget(langcode("MPUPDRG015"),
+ xmToggleButtonWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, DRG_color9,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Light Purple
+ DRG_color10 = XtVaCreateManagedWidget(langcode("MPUPDRG013"),
+ xmToggleButtonWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, DRG_color12,
+ XmNtopOffset, 4,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// Column 3
+ // White
+ DRG_color1 = XtVaCreateManagedWidget(langcode("MPUPDRG004"),
+ xmToggleButtonWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, DRG_label1,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Green
+ DRG_color5 = XtVaCreateManagedWidget(langcode("MPUPDRG008"),
+ xmToggleButtonWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, DRG_color1,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Yellow
+ DRG_color7 = XtVaCreateManagedWidget(langcode("MPUPDRG010"),
+ xmToggleButtonWidgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, DRG_color5,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sep2 = XtVaCreateManagedWidget("Config Tigermap sep2",
+ xmSeparatorGadgetClass,
+ DRG_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, DRG_color6,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_all = XtVaCreateManagedWidget(langcode("PULDNMMC09"),
+ xmPushButtonGadgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep2,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_none = XtVaCreateManagedWidget(langcode("PULDNDP040"),
+ xmPushButtonGadgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep2,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, button_all,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep2,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, button_none,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),
+ xmPushButtonGadgetClass,
+ DRG_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep2,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, button_ok,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_all,
+ XmNactivateCallback,
+ Configure_DRG_all,
+ configure_DRG_dialog);
+
+ XtAddCallback(button_none,
+ XmNactivateCallback,
+ Configure_DRG_none,
+ configure_DRG_dialog);
+
+ XtAddCallback(button_ok,
+ XmNactivateCallback,
+ Configure_DRG_change_data,
+ configure_DRG_dialog);
+
+ XtAddCallback(button_cancel,
+ XmNactivateCallback,
+ Configure_DRG_destroy_shell,
+ configure_DRG_dialog);
+
+ pos_dialog(configure_DRG_dialog);
+
+ delw = XmInternAtom(XtDisplay(configure_DRG_dialog),
+ "WM_DELETE_WINDOW",
+ FALSE);
+ XmAddWMProtocolCallback(configure_DRG_dialog,
+ delw,
+ Configure_DRG_destroy_shell,
+ (XtPointer)configure_DRG_dialog);
+
+ if(DRG_XOR_colors)
+ XmToggleButtonSetState(DRG_XOR,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(DRG_XOR,FALSE,FALSE);
+
+ if(DRG_show_colors[0])
+ XmToggleButtonSetState(DRG_color0,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(DRG_color0,FALSE,FALSE);
+
+ if(DRG_show_colors[1])
+ XmToggleButtonSetState(DRG_color1,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(DRG_color1,FALSE,FALSE);
+
+ if(DRG_show_colors[2])
+ XmToggleButtonSetState(DRG_color2,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(DRG_color2,FALSE,FALSE);
+
+ if(DRG_show_colors[3])
+ XmToggleButtonSetState(DRG_color3,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(DRG_color3,FALSE,FALSE);
+
+ if(DRG_show_colors[4])
+ XmToggleButtonSetState(DRG_color4,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(DRG_color4,FALSE,FALSE);
+
+ if(DRG_show_colors[5])
+ XmToggleButtonSetState(DRG_color5,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(DRG_color5,FALSE,FALSE);
+
+ if(DRG_show_colors[6])
+ XmToggleButtonSetState(DRG_color6,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(DRG_color6,FALSE,FALSE);
+
+ if(DRG_show_colors[7])
+ XmToggleButtonSetState(DRG_color7,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(DRG_color7,FALSE,FALSE);
+
+ if(DRG_show_colors[8])
+ XmToggleButtonSetState(DRG_color8,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(DRG_color8,FALSE,FALSE);
+
+ if(DRG_show_colors[9])
+ XmToggleButtonSetState(DRG_color9,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(DRG_color9,FALSE,FALSE);
+
+ if(DRG_show_colors[10])
+ XmToggleButtonSetState(DRG_color10,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(DRG_color10,FALSE,FALSE);
+
+ if(DRG_show_colors[11])
+ XmToggleButtonSetState(DRG_color11,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(DRG_color11,FALSE,FALSE);
+
+ if(DRG_show_colors[12])
+ XmToggleButtonSetState(DRG_color12,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(DRG_color12,FALSE,FALSE);
+
+ XtManageChild(DRG_form);
+ XtManageChild(DRG_pane);
+
+ XtPopup(configure_DRG_dialog,XtGrabNone);
+ fix_dialog_size(configure_DRG_dialog);
+
+ XmProcessTraversal(button_ok, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(configure_DRG_dialog),
+ XtWindow(configure_DRG_dialog));
+}
+#endif // HAVE_LIBGEOTIFF
+///////////////////////// End of Configure DRG code ///////////////////////////////////
+
+
+
+
+
+void Expand_Dirs_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ map_chooser_expand_dirs = atoi(which);
+ else
+ map_chooser_expand_dirs = 0;
+
+ // Kill/resurrect the Map Chooser so that the changes take
+ // effect.
+ map_chooser_destroy_shell( w, map_chooser_dialog, (XtPointer) NULL);
+ Map_chooser( w, (XtPointer)NULL, (XtPointer) NULL);
+
+ map_chooser_update_quantity();
+}
+
+
+
+
+
+void Map_chooser( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, my_form, button_clear, button_V,
+ button_C, button_F, button_O,
+ rowcol, expand_dirs_button, button_properties,
+ maps_selected_label, button_apply;
+ Atom delw;
+ int i;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+
+
+ busy_cursor(appshell);
+
+ i=0;
+ if (!map_chooser_dialog) {
+ map_chooser_dialog = XtVaCreatePopupShell(langcode("WPUPMCP001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Map_chooser pane",
+ xmPanedWindowWidgetClass,
+ map_chooser_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Map_chooser my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 7,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ /*set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNvisibleItemCount, 13); ac++;
+ XtSetArg(al[ac], XmNshadowThickness, 3); ac++;
+ XtSetArg(al[ac], XmNselectionPolicy, XmMULTIPLE_SELECT); ac++;
+ XtSetArg(al[ac], XmNscrollBarPlacement, XmBOTTOM_RIGHT); ac++;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ map_list = XmCreateScrolledList(my_form,
+ "Map_chooser list",
+ al,
+ ac);
+
+ // Find the names of all the map files on disk and put them into map_list
+ map_chooser_fill_in();
+
+ expand_dirs_button = XtVaCreateManagedWidget(langcode("PULDNMMC06"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNsensitive, TRUE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(expand_dirs_button,XmNvalueChangedCallback,Expand_Dirs_toggle,"1");
+ if(map_chooser_expand_dirs)
+ XmToggleButtonSetState(expand_dirs_button,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(expand_dirs_button,FALSE,FALSE);
+
+ maps_selected_label = XtVaCreateManagedWidget(langcode("PULDNMMC07"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, expand_dirs_button,
+ XmNleftOffset, 15,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ map_chooser_maps_selected_data = XtVaCreateManagedWidget("0/0",
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, maps_selected_label,
+ XmNleftOffset, 2,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Button for configuring properties
+ button_properties = XtVaCreateManagedWidget(langcode("UNIOP00009"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNsensitive, TRUE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_properties, XmNactivateCallback, map_properties, map_chooser_dialog);
+
+ // Attach a rowcolumn manager widget to my_form to handle all of the buttons
+ rowcol = XtVaCreateManagedWidget("Map Chooser rowcol",
+ xmRowColumnWidgetClass,
+ my_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNkeyboardFocusPolicy, XmEXPLICIT,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtVaSetValues(XtParent(map_list),
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, expand_dirs_button,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, rowcol,
+ XmNbottomOffset, 2,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "Clear"
+ if(map_chooser_expand_dirs) { // "Clear"
+ button_clear = XtVaCreateManagedWidget(langcode("PULDNMMC01"),
+ xmPushButtonGadgetClass,
+ rowcol,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ }
+ else { // "Clear Dirs"
+ button_clear = XtVaCreateManagedWidget(langcode("PULDNMMC08"),
+ xmPushButtonGadgetClass,
+ rowcol,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ }
+
+
+// "Vector Maps"
+ button_V = XtVaCreateManagedWidget(langcode("PULDNMMC02"),
+ xmPushButtonGadgetClass,
+ rowcol,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "250k Topos"
+ button_C = XtVaCreateManagedWidget(langcode("PULDNMMC03"),
+ xmPushButtonGadgetClass,
+ rowcol,
+ XmNnavigationType, XmTAB_GROUP,
+#ifndef HAVE_LIBGEOTIFF
+ XmNsensitive, FALSE,
+#endif /* HAVE_LIBGEOTIFF */
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "100k Topos"
+ button_F = XtVaCreateManagedWidget(langcode("PULDNMMC04"),
+ xmPushButtonGadgetClass,
+ rowcol,
+ XmNnavigationType, XmTAB_GROUP,
+#ifndef HAVE_LIBGEOTIFF
+ XmNsensitive, FALSE,
+#endif /* HAVE_LIBGEOTIFF */
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "24k Topos"
+ button_O = XtVaCreateManagedWidget(langcode("PULDNMMC05"),
+ xmPushButtonGadgetClass,
+ rowcol,
+ XmNnavigationType, XmTAB_GROUP,
+#ifndef HAVE_LIBGEOTIFF
+ XmNsensitive, FALSE,
+#endif /* HAVE_LIBGEOTIFF */
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "Apply"
+ button_apply = XtVaCreateManagedWidget(langcode("UNIOP00032"),
+ xmPushButtonGadgetClass,
+ rowcol,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "OK"
+ map_chooser_button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass,
+ rowcol,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// "Cancel"
+ map_chooser_button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),
+ xmPushButtonGadgetClass,
+ rowcol,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_apply, XmNactivateCallback, map_chooser_apply_maps, map_chooser_dialog);
+ XtAddCallback(map_chooser_button_cancel, XmNactivateCallback, map_chooser_destroy_shell, map_chooser_dialog);
+ XtAddCallback(map_chooser_button_ok, XmNactivateCallback, map_chooser_select_maps, map_chooser_dialog);
+ XtAddCallback(button_clear, XmNactivateCallback, map_chooser_deselect_maps, map_chooser_dialog);
+ XtAddCallback(button_V, XmNactivateCallback, map_chooser_select_vector_maps, map_chooser_dialog);
+#ifdef HAVE_LIBGEOTIFF
+ XtAddCallback(button_C, XmNactivateCallback, map_chooser_select_250k_maps, map_chooser_dialog);
+ XtAddCallback(button_F, XmNactivateCallback, map_chooser_select_100k_maps, map_chooser_dialog);
+ XtAddCallback(button_O, XmNactivateCallback, map_chooser_select_24k_maps, map_chooser_dialog);
+#endif /* HAVE_LIBGEOTIFF */
+
+ if(!map_chooser_expand_dirs) {
+ XtSetSensitive(button_V, FALSE);
+ XtSetSensitive(button_C, FALSE);
+ XtSetSensitive(button_F, FALSE);
+ XtSetSensitive(button_O, FALSE);
+ }
+
+ pos_dialog(map_chooser_dialog);
+
+ delw = XmInternAtom(XtDisplay(map_chooser_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(map_chooser_dialog, delw, map_chooser_destroy_shell, (XtPointer)map_chooser_dialog);
+
+ XtManageChild(rowcol);
+ XtManageChild(my_form);
+ XtManageChild(map_list);
+ XtVaSetValues(map_list, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(pane);
+
+ XtPopup(map_chooser_dialog,XtGrabNone);
+
+ // Fix the dialog height only, allow the width to vary.
+// fix_dialog_vsize(map_chooser_dialog);
+
+ // Move focus to the OK button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(map_chooser_dialog);
+ XmProcessTraversal(map_chooser_button_ok, XmTRAVERSE_CURRENT);
+
+ } else {
+ (void)XRaiseWindow(XtDisplay(map_chooser_dialog), XtWindow(map_chooser_dialog));
+ }
+
+ map_chooser_update_quantity();
+}
+
+
+
+
+
+/****** Read in file **********/
+
+void read_file_selection_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtDestroyWidget(shell);
+ read_selection_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void read_file_selection_now(Widget w, XtPointer clientData, XtPointer callData) {
+ char *file;
+ XmFileSelectionBoxCallbackStruct *cbs =(XmFileSelectionBoxCallbackStruct*)callData;
+
+ file = XmStringUnparse(cbs->value, NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_BEGINNING);
+ if(file) {
+ // fprintf(stderr,"FILE is %s\n",file);
+
+ // Make sure we're not already reading a file and the user actually
+ // selected a file (if not, the last character will be a '/').
+ if ( (!read_file) && (file[strlen(file) - 1] != '/') ) {
+
+ /* do read file start */
+ read_file_ptr = fopen(file,"r");
+ if (read_file_ptr != NULL)
+ read_file = 1;
+ else
+ fprintf(stderr,"Couldn't open file: %s\n", file);
+
+ }
+ XtFree(file);
+ }
+ read_file_selection_destroy_shell(w, clientData, callData);
+
+ // Note that we leave the file in the "open" state. UpdateTime
+ // comes along shortly and reads the file.
+}
+
+
+
+
+
+void Read_File_Selection( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+ Widget fs;
+ Widget child;
+ char temp_base_dir[MAX_VALUE];
+
+ if (read_selection_dialog!=NULL)
+ read_file_selection_destroy_shell(read_selection_dialog, read_selection_dialog, NULL);
+
+ if(read_selection_dialog==NULL) {
+
+ // This is necessary because the resources for setting the
+ // directory in the FileSelectionDialog aren't working in Lesstif.
+ chdir( get_user_base_dir("logs", temp_base_dir, sizeof(temp_base_dir)) );
+
+ /*set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNtitle, langcode("PULDNFI002")); ac++; // Open Log File
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ //XtSetArg(al[ac], XmNdirMask, "/home/hacker/.xastir/logs/*"); ac++;
+ //XtSetArg(al[ac], XmNdirectory, "/home/hacker/.xastir/logs/"); ac++;
+ //XtSetArg(al[ac], XmNpattern, "*"); ac++;
+ //XtSetArg(al[ac], XmNdirMask, ".xastir/logs/*"); ac++;
+ read_selection_dialog = XmCreateFileSelectionDialog(appshell,
+ "filesb",
+ al,
+ ac);
+
+ // Change back to the base directory
+ chdir( get_user_base_dir("", temp_base_dir, sizeof(temp_base_dir)) );
+
+ fs=XmFileSelectionBoxGetChild(read_selection_dialog,(unsigned char)XmDIALOG_TEXT);
+ XtVaSetValues(fs,XmNbackground, colors[0x0f],NULL);
+ XtVaSetValues(fs,XmNfontList,fontlist1,NULL);
+
+ fs=XmFileSelectionBoxGetChild(read_selection_dialog,(unsigned char)XmDIALOG_FILTER_TEXT);
+ XtVaSetValues(fs,XmNbackground, colors[0x0f],NULL);
+ XtVaSetValues(fs,XmNfontList,fontlist1,NULL);
+
+ fs=XmFileSelectionBoxGetChild(read_selection_dialog,(unsigned char)XmDIALOG_DIR_LIST);
+ XtVaSetValues(fs,XmNbackground, colors[0x0f],NULL);
+ XtVaSetValues(fs,XmNfontList,fontlist1,NULL);
+
+ fs=XmFileSelectionBoxGetChild(read_selection_dialog,(unsigned char)XmDIALOG_LIST);
+ XtVaSetValues(fs,XmNbackground, colors[0x0f],NULL);
+ XtVaSetValues(fs,XmNfontList,fontlist1,NULL);
+
+ //XtVaSetValues(read_selection_dialog, XmNdirMask, "/home/hacker/.xastir/logs/*", NULL);
+
+ child = XmFileSelectionBoxGetChild(read_selection_dialog, XmDIALOG_FILTER_LABEL);
+ XtVaSetValues(child,XmNfontList,fontlist1,NULL);
+
+ child = XmFileSelectionBoxGetChild(read_selection_dialog, XmDIALOG_DIR_LIST_LABEL);
+ XtVaSetValues(child,XmNfontList,fontlist1,NULL);
+
+ child = XmFileSelectionBoxGetChild(read_selection_dialog, XmDIALOG_LIST_LABEL);
+ XtVaSetValues(child,XmNfontList,fontlist1,NULL);
+
+ child = XmFileSelectionBoxGetChild(read_selection_dialog, XmDIALOG_SELECTION_LABEL);
+ XtVaSetValues(child,XmNfontList,fontlist1,NULL);
+
+ child = XmFileSelectionBoxGetChild(read_selection_dialog, XmDIALOG_OK_BUTTON);
+ XtVaSetValues(child,XmNfontList,fontlist1,NULL);
+
+ child = XmFileSelectionBoxGetChild(read_selection_dialog, XmDIALOG_APPLY_BUTTON);
+ XtVaSetValues(child,XmNfontList,fontlist1,NULL);
+
+ child = XmFileSelectionBoxGetChild(read_selection_dialog, XmDIALOG_CANCEL_BUTTON);
+ XtVaSetValues(child,XmNfontList,fontlist1,NULL);
+
+ child = XmFileSelectionBoxGetChild(read_selection_dialog, XmDIALOG_HELP_BUTTON);
+ XtVaSetValues(child,XmNfontList,fontlist1,NULL);
+
+ XtAddCallback(read_selection_dialog, XmNcancelCallback,read_file_selection_destroy_shell,read_selection_dialog);
+ XtAddCallback(read_selection_dialog, XmNokCallback,read_file_selection_now,read_selection_dialog);
+
+ XtAddCallback(read_selection_dialog, XmNhelpCallback, Help_Index, read_selection_dialog);
+
+ XtManageChild(read_selection_dialog);
+ pos_dialog(read_selection_dialog);
+ }
+}
+
+
+
+
+
+void Test(Widget w, XtPointer clientData, XtPointer callData) {
+// static char temp[256];
+// int port = 7;
+
+
+ mdisplay_file(0);
+// mem_display();
+ alert_print_list();
+
+/*
+ draw_wind_barb(50000000l, // long x_long,
+ 32000000l, // long y_lat,
+ "169", // char *speed,
+ "005", // char *course,
+ sec_now(), // time_t sec_heard,
+ pixmap_final); // Pixmap where);
+
+ draw_wind_barb(60000000l, // long x_long,
+ 32000000l, // long y_lat,
+ "009", // char *speed,
+ "123", // char *course,
+ sec_now(), // time_t sec_heard,
+ pixmap_final); // Pixmap where);
+
+ draw_wind_barb(70000000l, // long x_long,
+ 32000000l, // long y_lat,
+ "109", // char *speed,
+ "185", // char *course,
+ sec_now(), // time_t sec_heard,
+ pixmap_final); // Pixmap where);
+
+ draw_wind_barb(80000000l, // long x_long,
+ 32000000l, // long y_lat,
+ "079", // char *speed,
+ "275", // char *course,
+ sec_now(), // time_t sec_heard,
+ pixmap_final); // Pixmap where);
+*/
+
+// fprintf(stderr,"view_zero_distance_bulletins = %d\n",
+// view_zero_distance_bulletins);
+
+
+/*
+ // Simulate data coming in from a TNC in order to test igating.
+ // Port 7 in this case is a serial TNC port (in my current test
+ // configuration).
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "WE7U-4>APOT01,SUMAS*,WIDE2-2:!4757.28N/12212.00Wv178/057/A=000208 14.0V 30C\r");
+
+ if (begin_critical_section(&data_lock, "main.c" ) > 0)
+ fprintf(stderr,"data_lock, Port = %d\n", port);
+
+ incoming_data=temp;
+ incoming_data_length = strlen(temp);
+ data_port = port;
+ data_avail = 1;
+
+ if (end_critical_section(&data_lock, "main.c" ) > 0)
+ fprintf(stderr,"data_lock, Port = %d\n", port);
+
+ fprintf(stderr, "Sent: %s\n", temp);
+*/
+
+
+// (void)XCopyArea(XtDisplay(da),pixmap_final,XtWindow(da),gc,0,0,(unsigned int)screen_width,(unsigned int)screen_height,0,0);
+}
+
+
+
+
+
+/****** Save Config data **********/
+
+void Save_Config( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ save_data();
+}
+
+
+
+
+
+/////////////////////////////////// Configure Defaults Dialog //////////////////////////////////
+
+
+void Configure_defaults_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ configure_defaults_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Configure_defaults_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ char *temp;
+ int load_predefined_cb_selected;
+ XmString load_predefined_cb_selection;
+
+
+ output_station_type = Station_transmit_type;
+ if ((output_station_type >= 1) && (output_station_type <= 3)) {
+ next_time = 60;
+ max_transmit_time = (time_t)120l; // shorter beacon interval for mobile stations
+ }
+ else {
+ max_transmit_time = (time_t)900l;
+ }
+
+ // Check for proper symbol in case we're a weather station
+ (void)check_weather_symbol();
+
+ // Check for NWS symbol and print warning if so
+ (void)check_nws_weather_symbol();
+
+#ifdef TRANSMIT_RAW_WX
+ transmit_raw_wx = (int)XmToggleButtonGetState(raw_wx_tx);
+#endif // TRANSMIT_RAW_WX
+
+ transmit_compressed_objects_items = (int)XmToggleButtonGetState(compressed_objects_items_tx);
+
+ pop_up_new_bulletins = (int)XmToggleButtonGetState(new_bulletin_popup_enable);
+ view_zero_distance_bulletins = (int)XmToggleButtonGetState(zero_bulletin_popup_enable);
+
+ // user interface refers to all my trails in one color
+ // my trail diff color as 0 means my trails in one color, so select
+ // button when my trail diff color is 0 rather than 1.
+ my_trail_diff_color = !(int)XmToggleButtonGetState(my_trail_diff_color_enable);
+
+ // Predefined (SAR/EVENT) objects menu loading (default hardcoded SAR objects or objects from file)
+ predefined_menu_from_file = (int)XmToggleButtonGetState(load_predefined_objects_menu_from_file_enable);
+
+ // Use the file specified on the picklist if one is selected.
+ load_predefined_cb_selected = 0;
+#ifdef USE_COMBO_BOX
+ XtVaGetValues(load_predefined_objects_menu_from_file,
+ XmNselectedPosition,
+ &load_predefined_cb_selected,
+ NULL);
+#else
+ load_predefined_cb_selected = lpomff_value;
+#endif //USE_COMBO_BOX
+
+ // Use the file specified on the picklist if one is selected.
+ if (load_predefined_cb_selected > 0) {
+
+ // XtVaGetValues() expects to be able to write into
+ // allocated memory.
+ //
+ load_predefined_cb_selection = (XmString)malloc(MAX_FILENAME);
+
+#ifdef USE_COMBO_BOX
+ XtVaGetValues(load_predefined_objects_menu_from_file,
+ XmNselectedItem,
+ &load_predefined_cb_selection,
+ NULL);
+#else
+ switch (load_predefined_cb_selected) {
+ case 1:
+ load_predefined_cb_selection = XmStringCreateLocalized("predefined_SAR.sys");
+ break;
+ case 2:
+ load_predefined_cb_selection = XmStringCreateLocalized("predefined_EVENT.sys");
+ break;
+ case 3:
+ load_predefined_cb_selection = XmStringCreateLocalized("predefined_USER.sys");
+ break;
+ case 4:
+ load_predefined_cb_selection = XmStringCreateLocalized(predefined_object_definition_filename);
+ break;
+ default:
+ load_predefined_cb_selection = XmStringCreateLocalized("predefined_SAR.sys");
+ }
+#endif //USE_COMBO_BOX
+ }
+ else {
+
+ load_predefined_cb_selection = XmStringCreateLocalized("predefined_SAR.sys");
+ }
+
+ xastir_snprintf(predefined_object_definition_filename,
+ sizeof(predefined_object_definition_filename),
+ "%s",
+ temp = XmStringUnparse(load_predefined_cb_selection,
+ NULL,
+ XmCHARSET_TEXT,
+ XmCHARSET_TEXT,
+ NULL,
+ 0,
+ XmOUTPUT_ALL) );
+
+ XtFree(temp);
+ XmStringFree(load_predefined_cb_selection);
+
+ // Repopulate the predefined object (SAR/Public service) struct
+ Populate_predefined_objects(predefinedObjects);
+
+ // Rebuild the predefined objects SAR/Public service menu.
+ BuildPredefinedSARMenu_UI(&sar_object_sub);
+
+ warn_about_mouse_modifiers = (int)XmToggleButtonGetState(warn_about_mouse_modifiers_enable);
+
+ altnet = (int)(XmToggleButtonGetState(altnet_active));
+
+ skip_dupe_checking = (int)(XmToggleButtonGetState(disable_dupe_check));
+
+ temp = XmTextGetString(altnet_text);
+ xastir_snprintf(altnet_call,
+ sizeof(altnet_call),
+ "%s",
+ temp);
+ XtFree(temp);
+
+ (void)remove_trailing_spaces(altnet_call);
+ if (strlen(altnet_call)==0) {
+ altnet = FALSE;
+ xastir_snprintf(altnet_call,
+ sizeof(altnet_call),
+ "XASTIR");
+ }
+
+ operate_as_an_igate=Igate_type;
+
+ redraw_on_new_data=2;
+ Configure_defaults_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+/* Station_transmit type radio buttons */
+void station_type_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ Station_transmit_type = atoi(which);
+ else
+ Station_transmit_type = 0;
+
+}
+
+
+
+
+
+/* Igate type radio buttons */
+void igate_type_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ Igate_type = atoi(which);
+ else
+ Igate_type = 0;
+}
+
+
+#ifndef USE_COMBO_BOX
+void lpomff_menuCallback(Widget widget, XtPointer ptr, XtPointer callData) {
+ XtPointer userData;
+
+ XtVaGetValues(widget, XmNuserData, &userData, NULL);
+ //clsd_menu is zero based, cad_line_style_data constants are one based.
+ lpomff_value = (int)userData + 1;
+ if (debug_level & 1)
+ fprintf(stderr,"Selected value on cad line type pulldown: %d\n",lpomff_value);
+}
+#endif // !USE_COMBO_BOX
+
+
+
+
+
+void Configure_defaults( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, my_form, button_ok, button_cancel,
+ frame4, frame5,
+ station_type, type_box,
+ styp1, styp2, styp3, styp4, styp5, styp6,
+ igate_option, igate_box,
+ igtyp0, igtyp1, igtyp2, altnet_label;
+ Atom delw;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+#ifndef USE_COMBO_BOX
+ Widget lpomff_menuPane;
+ Widget lpomff_button;
+ Widget lpomff_buttons[4];
+ Widget lpomff_menu;
+ char buf[18];
+ int x;
+#endif // !USE_COMBO_BOX
+ Widget lpomff_widget;
+ int i;
+ XmString cb_items[4];
+ char temp_base_dir[MAX_VALUE];
+
+
+
+ if (!configure_defaults_dialog) {
+ char loadfrom[300];
+
+ // Set args for color
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ configure_defaults_dialog = XtVaCreatePopupShell(langcode("WPUPCFD001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Configure_defaults pane",
+ xmPanedWindowWidgetClass,
+ configure_defaults_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Configure_defaults my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Transmit Station Options
+ frame4 = XtVaCreateManagedWidget("Configure_defaults frame4",
+ xmFrameWidgetClass,
+ my_form,
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset,10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ station_type = XtVaCreateManagedWidget(langcode("WPUPCFD015"),
+ xmLabelWidgetClass,
+ frame4,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ type_box = XmCreateRadioBox(frame4,
+ "Configure_defaults Transmit Options box",
+ al,
+ ac);
+
+ XtVaSetValues(type_box,
+ XmNnumColumns,2,
+ NULL);
+
+ styp1 = XtVaCreateManagedWidget(langcode("WPUPCFD016"),
+ xmToggleButtonGadgetClass,
+ type_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(styp1,XmNvalueChangedCallback,station_type_toggle,"0");
+
+ styp2 = XtVaCreateManagedWidget(langcode("WPUPCFD017"),
+ xmToggleButtonGadgetClass,
+ type_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(styp2,XmNvalueChangedCallback,station_type_toggle,"1");
+
+ styp3 = XtVaCreateManagedWidget(langcode("WPUPCFD018"),
+ xmToggleButtonGadgetClass,
+ type_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(styp3,XmNvalueChangedCallback,station_type_toggle,"2");
+
+ styp4 = XtVaCreateManagedWidget(langcode("WPUPCFD019"),
+ xmToggleButtonGadgetClass,
+ type_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(styp4,XmNvalueChangedCallback,station_type_toggle,"3");
+
+ styp5 = XtVaCreateManagedWidget(langcode("WPUPCFD021"),
+ xmToggleButtonGadgetClass,
+ type_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(styp5,XmNvalueChangedCallback,station_type_toggle,"4");
+
+ styp6 = XtVaCreateManagedWidget(langcode("WPUPCFD022"),
+ xmToggleButtonGadgetClass,
+ type_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(styp6,XmNvalueChangedCallback,station_type_toggle,"5");
+
+
+ // Igate Options
+ frame5 = XtVaCreateManagedWidget("Configure_defaults frame5",
+ xmFrameWidgetClass,
+ my_form,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, frame4,
+ XmNtopOffset,10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ igate_option = XtVaCreateManagedWidget(langcode("IGPUPCF000"),
+ xmLabelWidgetClass,
+ frame5,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ igate_box = XmCreateRadioBox(frame5,
+ "Configure_defaults Igate Options box",
+ al,
+ ac);
+
+ XtVaSetValues(igate_box,
+ XmNnumColumns,2,
+ NULL);
+
+ igtyp0 = XtVaCreateManagedWidget(langcode("IGPUPCF001"),
+ xmToggleButtonGadgetClass,
+ igate_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(igtyp0,XmNvalueChangedCallback,igate_type_toggle,"0");
+
+ igtyp1 = XtVaCreateManagedWidget(langcode("IGPUPCF002"),
+ xmToggleButtonGadgetClass,
+ igate_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(igtyp1,XmNvalueChangedCallback,igate_type_toggle ,"1");
+
+ igtyp2 = XtVaCreateManagedWidget(langcode("IGPUPCF003"),
+ xmToggleButtonGadgetClass,
+ igate_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(igtyp2,XmNvalueChangedCallback,igate_type_toggle,"2");
+
+
+ // Miscellaneous Options
+ compressed_objects_items_tx = XtVaCreateManagedWidget(langcode("WPUPCFD024"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame5,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ new_bulletin_popup_enable = XtVaCreateManagedWidget(langcode("WPUPCFD027"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, compressed_objects_items_tx,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ zero_bulletin_popup_enable = XtVaCreateManagedWidget(langcode("WPUPCFD029"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, new_bulletin_popup_enable,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ warn_about_mouse_modifiers_enable = XtVaCreateManagedWidget(langcode("WPUPCFD028"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, new_bulletin_popup_enable,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, zero_bulletin_popup_enable,
+ XmNleftOffset,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Show all My trails in one color
+ my_trail_diff_color_enable = XtVaCreateManagedWidget(langcode("WPUPCFD032"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, new_bulletin_popup_enable,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, warn_about_mouse_modifiers_enable,
+ XmNleftOffset,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ // Check box to load predefined (SAR/Event) objects menu from a file or not.
+ xastir_snprintf(loadfrom,
+ sizeof(loadfrom),
+ "%s %s",
+ langcode("WPUPCFD031"),
+#ifdef OBJECT_DEF_FILE_USER_BASE
+ get_user_base_dir("config", temp_base_dir, sizeof(temp_base_dir)));
+#else // OBJECT_DEF_FILE_USER_BASE
+ get_data_base_dir("config"));
+#endif // OBJECT_DEF_FILE_USER_BASE
+
+ load_predefined_objects_menu_from_file_enable = XtVaCreateManagedWidget(loadfrom,
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, zero_bulletin_popup_enable,
+ XmNtopOffset,5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // lesstif as of 0.95 in 2008 doesn't fully support combo boxes
+ //
+ // Need to replace combo boxes with a pull down menu when lesstif is used.
+ // See xpdf's XPDFViewer.cc/XPDFViewer.h for an example.
+
+ cb_items[0] = XmStringCreateLocalized("predefined_SAR.sys");
+ cb_items[1] = XmStringCreateLocalized("predefined_EVENT.sys");
+ cb_items[2] = XmStringCreateLocalized("predefined_USER.sys");
+#ifdef USE_COMBO_BOX
+ // Combo box to pick file from which to load predefined objects menu
+ load_predefined_objects_menu_from_file = XtVaCreateManagedWidget("Load objects menu filename ComboBox",
+ xmComboBoxWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, zero_bulletin_popup_enable,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, load_predefined_objects_menu_from_file_enable,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNcomboBoxType, XmDROP_DOWN_LIST,
+ XmNpositionMode, XmONE_BASED,
+ XmNvisibleItemCount, 3,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmComboBoxAddItem(load_predefined_objects_menu_from_file,cb_items[0],1,1);
+ XmComboBoxAddItem(load_predefined_objects_menu_from_file,cb_items[1],2,1);
+ XmComboBoxAddItem(load_predefined_objects_menu_from_file,cb_items[2],3,1);
+
+ lpomff_widget = load_predefined_objects_menu_from_file;
+#else
+ // Menu replacement for combo box when using lesstif.
+ // Not a full replacement, as combo box in motif can have editable values,
+ // not just selection from predefined list as is the case here.
+ ac = 0;
+ XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
+ XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ lpomff_menuPane = XmCreatePulldownMenu(my_form,"lpomff_menuPane", al, ac);
+ //lpomff_menu is zero based, constants for filenames are one based
+ //lpomff_value is set to match constants in callback.
+ for (i=0;i<3;i++) {
+ ac = 0;
+ XtSetArg(al[ac], XmNlabelString, cb_items[i]); ac++;
+ XtSetArg(al[ac], XmNuserData, (XtPointer)i); ac++;
+ sprintf(buf,"button%d",i);
+ lpomff_button = XmCreatePushButton(lpomff_menuPane, buf, al, ac);
+ XtManageChild(lpomff_button);
+ XtAddCallback(lpomff_button, XmNactivateCallback, lpomff_menuCallback, Configure_defaults);
+ lpomff_buttons[i] = lpomff_button;
+ }
+ ac = 0;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ++ac;
+ XtSetArg(al[ac], XmNleftWidget, load_predefined_objects_menu_from_file_enable); ++ac;
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ++ac;
+ XtSetArg(al[ac], XmNtopWidget, zero_bulletin_popup_enable); ++ac;
+ XtSetArg(al[ac], XmNmarginWidth, 0); ++ac;
+ XtSetArg(al[ac], XmNmarginHeight, 0); ++ac;
+ XtSetArg(al[ac], XmNtopOffset, 5); ++ac;
+ XtSetArg(al[ac], XmNleftOffset, 10); ++ac;
+ XtSetArg(al[ac], XmNsubMenuId, lpomff_menuPane); ++ac;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ lpomff_menu = XmCreateOptionMenu(my_form, "sddd_Menu", al, ac);
+ XtManageChild(lpomff_menu);
+ lpomff_value = 2; // set a default value (line on off dash)
+ lpomff_widget = lpomff_menu;
+#endif // USE_COMBO_BOX
+ // free up space from combo box strings
+ for (i=0;i<3;i++) {
+ XmStringFree(cb_items[i]);
+ }
+
+
+#ifdef TRANSMIT_RAW_WX
+ raw_wx_tx = XtVaCreateManagedWidget(langcode("WPUPCFD023"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, lpomff_widget,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+#endif // TRANSMIT_RAW_WX
+
+ altnet_active = XtVaCreateManagedWidget(langcode("WPUPCFD025"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame5,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, compressed_objects_items_tx,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "ALTNET:"
+ altnet_label = XtVaCreateManagedWidget(langcode("WPUPCFD033"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, altnet_active,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, compressed_objects_items_tx,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ altnet_text = XtVaCreateManagedWidget("Configure_defaults Altnet_text",
+ xmTextWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 9,
+ XmNwidth, ((10*7)+2),
+ XmNmaxLength, 9,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, altnet_active,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, altnet_label,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ disable_dupe_check = XtVaCreateManagedWidget(langcode("WPUPCFD030"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame5,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, altnet_active,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+#ifdef TRANSMIT_RAW_WX
+ XmNtopWidget, raw_wx_tx,
+#else // TRANSMIT_RAW_WX
+ XmNtopWidget, lpomff_widget,
+#endif // TRANSMIT_RAW_WX
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+#ifdef TRANSMIT_RAW_WX
+ XmNtopWidget, raw_wx_tx,
+#else // TRANSMIT_RAW_WX
+ XmNtopWidget, lpomff_widget,
+#endif // TRANSMIT_RAW_WX
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Configure_defaults_change_data, configure_defaults_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Configure_defaults_destroy_shell, configure_defaults_dialog);
+
+ switch(output_station_type) {
+ case(0):
+ XmToggleButtonSetState(styp1,TRUE,FALSE);
+ Station_transmit_type=0;
+ break;
+
+ case(1):
+ XmToggleButtonSetState(styp2,TRUE,FALSE);
+ Station_transmit_type=1;
+ break;
+
+ case(2):
+ XmToggleButtonSetState(styp3,TRUE,FALSE);
+ Station_transmit_type=2;
+ break;
+
+ case(3):
+ XmToggleButtonSetState(styp4,TRUE,FALSE);
+ Station_transmit_type=3;
+ break;
+
+ case(4):
+ XmToggleButtonSetState(styp5,TRUE,FALSE);
+ Station_transmit_type=4;
+ break;
+
+ case(5):
+ XmToggleButtonSetState(styp6,TRUE,FALSE);
+ Station_transmit_type=5;
+ break;
+
+ default:
+ XmToggleButtonSetState(styp1,TRUE,FALSE);
+ Station_transmit_type=0;
+ break;
+ }
+
+#ifdef TRANSMIT_RAW_WX
+ if (transmit_raw_wx)
+ XmToggleButtonSetState(raw_wx_tx,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(raw_wx_tx,FALSE,FALSE);
+#endif // TRANSMIT_RAW_WX
+
+ if(transmit_compressed_objects_items)
+ XmToggleButtonSetState(compressed_objects_items_tx,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(compressed_objects_items_tx,FALSE,FALSE);
+
+ if(pop_up_new_bulletins)
+ XmToggleButtonSetState(new_bulletin_popup_enable,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(new_bulletin_popup_enable,FALSE,FALSE);
+
+ if(view_zero_distance_bulletins)
+ XmToggleButtonSetState(zero_bulletin_popup_enable,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(zero_bulletin_popup_enable,FALSE,FALSE);
+
+ if(warn_about_mouse_modifiers)
+ XmToggleButtonSetState(warn_about_mouse_modifiers_enable,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(warn_about_mouse_modifiers_enable,FALSE,FALSE);
+
+ // user interface refers to all my trails in one color
+ // my trail diff color as 0 means my trails in one color, so select
+ // button when my trail diff color is 0 rather than 1.
+ if(my_trail_diff_color)
+ XmToggleButtonSetState(my_trail_diff_color_enable,FALSE,FALSE);
+ else
+ XmToggleButtonSetState(my_trail_diff_color_enable,TRUE,FALSE);
+
+ if(predefined_menu_from_file) {
+ // Option to load the predefined SAR objects menu items from a file.
+ // Display the filename if one is currently selected and option is enabled.
+ if (predefined_object_definition_filename != NULL ) {
+
+#ifdef USE_COMBO_BOX
+ XmString tempSelection = XmStringCreateLocalized(predefined_object_definition_filename);
+ XmComboBoxSelectItem(load_predefined_objects_menu_from_file, tempSelection);
+ XmStringFree(tempSelection);
+#else
+ x = -1;
+ if (strncmp(predefined_object_definition_filename,"predefined_SAR.sys",strlen(predefined_object_definition_filename)) == 0)
+ x = 0;
+ if (strncmp(predefined_object_definition_filename,"predefined_EVENT.sys",strlen(predefined_object_definition_filename)) == 0)
+ x = 1;
+ if (strncmp(predefined_object_definition_filename,"predefined_USER.sys",strlen(predefined_object_definition_filename)) == 0)
+ x = 2;
+ i = 3;
+ // allow display of another filename from the config file.
+ // user won't be able to edit it, but they will see it.
+ if (x==-1) {
+ ac = 0;
+ cb_items[i] = XmStringCreateLocalized(predefined_object_definition_filename);
+ XtSetArg(al[ac], XmNlabelString, cb_items[i]); ac++;
+ XtSetArg(al[ac], XmNuserData, (XtPointer)i); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+ sprintf(buf,"button%d",i);
+ lpomff_button = XmCreatePushButton(lpomff_menuPane, buf, al, ac);
+ XtManageChild(lpomff_button);
+ XtAddCallback(lpomff_button, XmNactivateCallback, lpomff_menuCallback, Configure_defaults);
+ lpomff_buttons[i] = lpomff_button;
+ XmStringFree(cb_items[i]);
+ x = i;
+ }
+ XtVaSetValues(lpomff_menu, XmNmenuHistory, lpomff_buttons[x], NULL);
+ lpomff_value = x+1;
+#endif // USE_COMBO_BOX
+
+ }
+ XmToggleButtonSetState(load_predefined_objects_menu_from_file_enable,TRUE,FALSE);
+ } else {
+ // by default combo box is created with no selection
+ // make sure that toggle button is unchecked
+ XmToggleButtonSetState(load_predefined_objects_menu_from_file_enable,FALSE,FALSE);
+ }
+
+ XmToggleButtonSetState(altnet_active, altnet, FALSE);
+
+ XmToggleButtonSetState(disable_dupe_check, skip_dupe_checking, FALSE);
+
+ // Known to have memory leaks in some Motif versions:
+ //XmTextSetString(altnet_text, altnet_call);
+ XmTextReplace(altnet_text, (XmTextPosition) 0,
+ XmTextGetLastPosition(altnet_text), altnet_call);
+
+ switch(operate_as_an_igate) {
+ case(0):
+ XmToggleButtonSetState(igtyp0,TRUE,FALSE);
+ Igate_type=0;
+ break;
+
+ case(1):
+ XmToggleButtonSetState(igtyp1,TRUE,FALSE);
+ Igate_type=1;
+ break;
+
+ case(2):
+ XmToggleButtonSetState(igtyp2,TRUE,FALSE);
+ Igate_type=2;
+ break;
+
+ default:
+ XmToggleButtonSetState(igtyp0,TRUE,FALSE);
+ Igate_type=0;
+ break;
+ }
+ pos_dialog(configure_defaults_dialog);
+
+ delw = XmInternAtom(XtDisplay(configure_defaults_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(configure_defaults_dialog, delw, Configure_defaults_destroy_shell, (XtPointer)configure_defaults_dialog);
+
+ XtManageChild(my_form);
+ XtManageChild(type_box);
+ XtManageChild(igate_box);
+ XtManageChild(pane);
+
+ XtPopup(configure_defaults_dialog,XtGrabNone);
+ fix_dialog_size(configure_defaults_dialog);
+
+ // Move focus to the Close button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(configure_defaults_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(configure_defaults_dialog), XtWindow(configure_defaults_dialog));
+}
+
+
+
+
+
+/////////////////////////////////// Configure Timing Dialog //////////////////////////////////
+
+
+void Configure_timing_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ configure_timing_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Configure_timing_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ int value;
+
+
+ XmScaleGetValue(ghosting_time, &value); // Minutes
+ sec_old = (time_t)(value * 60); // Convert to seconds
+
+ XmScaleGetValue(clearing_time, &value); // Hours
+ sec_clear = (time_t)(value * 60 * 60); // Convert to seconds
+
+ XmScaleGetValue(posit_interval, &value); // Minutes * 10
+ POSIT_rate = (long)(value * 60 / 10); // Convert to seconds
+
+ XmScaleGetValue(gps_interval, &value); // Seconds
+ gps_time = (long)value;
+
+ XmScaleGetValue(dead_reckoning_time, &value);// Minutes
+ dead_reckoning_timeout = value * 60; // Convert to seconds
+
+ XmScaleGetValue(object_item_interval, &value);// Minutes
+ OBJECT_rate = value * 60; // Convert to seconds
+
+ XmScaleGetValue(removal_time, &value); // Days
+ sec_remove = (time_t)(value * 60 * 60 * 24);// Convert to seconds
+
+ // Set the new posit rate into effect immediately
+ posit_next_time = posit_last_time + POSIT_rate;
+
+ // Set the new GPS rate into effect immediately
+ sec_next_gps = sec_now() + gps_time;
+
+ // Set the serial port inter-character delay
+ XmScaleGetValue(serial_pacing_time, &serial_char_pacing); // Milliseconds
+
+ XmScaleGetValue(trail_segment_timeout, &value); // Minutes
+ trail_segment_time = (int)value;
+
+ XmScaleGetValue(trail_segment_distance_max, &value); // Degrees
+ trail_segment_distance = (int)value;
+
+#ifdef HAVE_GPSMAN
+ XmScaleGetValue(RINO_download_timeout, &value); // Degrees
+ RINO_download_interval = (int)value;
+#endif // HAVE_GPSMAN
+
+ XmScaleGetValue(net_map_slider, &net_map_timeout);
+
+ XmScaleGetValue(snapshot_interval_slider, &snapshot_interval);
+
+ redraw_on_new_data=2;
+ Configure_timing_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void Configure_timing( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, my_form, button_ok, button_cancel;
+ Atom delw;
+ XmString x_str;
+
+
+ if (!configure_timing_dialog) {
+ configure_timing_dialog = XtVaCreatePopupShell(langcode("WPUPCFTM01"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Configure_timing pane",
+ xmPanedWindowWidgetClass,
+ configure_timing_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Configure_timing my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 2,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Posit Time
+ x_str = XmStringCreateLocalized(langcode("WPUPCFTM02"));
+ posit_interval = XtVaCreateManagedWidget("Posit Interval",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNrightOffset, 5,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 0, // Zero minutes (disables the function)
+ XmNmaximum, 60*10, // 60 minutes
+ XmNdecimalPoints, 1, // Move decimal point over one
+ XmNscaleMultiple, 5, // Move 30 seconds per left mouse
+ XmNshowValue, TRUE,
+ XmNvalue, (int)((POSIT_rate * 10) / 60), // Minutes * 10
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+
+ // Interval for stations being considered old (symbol ghosting)
+ x_str = XmStringCreateLocalized(langcode("WPUPCFTM03"));
+ ghosting_time = XtVaCreateManagedWidget("Station Ghosting Time",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNrightOffset, 10,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 1, // One minute
+ XmNmaximum, 3*60, // Three hours
+ XmNshowValue, TRUE,
+ XmNvalue, (int)(sec_old/60),
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+ // Object Item Transmit Interval
+ x_str = XmStringCreateLocalized(langcode("WPUPCFTM04"));
+ object_item_interval = XtVaCreateManagedWidget("Object/Item Transmit Interval (min)",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, posit_interval,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNrightOffset, 5,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 5, // Five minutes
+ XmNmaximum, 120, // 120 minutes
+ XmNscaleMultiple, 5, // Move 5 minutes per left mouse
+ XmNshowValue, TRUE,
+ XmNvalue, (int)(OBJECT_rate / 60),
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+ // Interval for station not being displayed
+ x_str = XmStringCreateLocalized(langcode("WPUPCFTM05"));
+ clearing_time = XtVaCreateManagedWidget("Station Clear Time",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, posit_interval,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNrightOffset, 10,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 1, // One hour
+ XmNmaximum, 24*7, // One week
+ XmNshowValue, TRUE,
+ XmNvalue, (int)(sec_clear/(60*60)),
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+ // GPS Time
+ x_str = XmStringCreateLocalized(langcode("WPUPCFTM06"));
+ gps_interval = XtVaCreateManagedWidget("GPS Interval",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, object_item_interval,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNrightOffset, 5,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 1, // One second
+ XmNmaximum, 60, // Sixty seconds
+ XmNshowValue, TRUE,
+ XmNvalue, (int)gps_time,
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+ // Interval for station being removed from database
+ x_str = XmStringCreateLocalized(langcode("WPUPCFTM07"));
+ removal_time = XtVaCreateManagedWidget("Station Delete Time",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, object_item_interval,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNrightOffset, 10,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 1, // One Day
+ XmNmaximum, 14, // Two weeks
+ XmNshowValue, TRUE,
+ XmNvalue, (int)(sec_remove/(60*60*24)),
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+ // Dead Reckoning Timeout
+ x_str = XmStringCreateLocalized(langcode("WPUPCFTM08"));
+ dead_reckoning_time = XtVaCreateManagedWidget("DR Time (min)",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, gps_interval,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNrightOffset, 5,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 1, // One minute
+ XmNmaximum, 60, // Sixty minutes
+ XmNshowValue, TRUE,
+ XmNvalue, (int)(dead_reckoning_timeout / 60),
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+ // Serial Pacing Time (delay between each serial character)
+ x_str = XmStringCreateLocalized(langcode("WPUPCFTM09"));
+ serial_pacing_time = XtVaCreateManagedWidget("Serial Pacing Time (ms)",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, removal_time,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNrightOffset, 5,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 0, // Zero
+ XmNmaximum, 50, // Fifty milliseconds
+ XmNshowValue, TRUE,
+ XmNvalue, (int)(serial_char_pacing),
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+ // Time below which track segment will get drawn, in minutes
+ x_str = XmStringCreateLocalized(langcode("WPUPCFTM10"));
+ trail_segment_timeout = XtVaCreateManagedWidget("Trail segment timeout",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, dead_reckoning_time,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNrightOffset, 5,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 0, // Zero minutes
+ XmNmaximum, 12*60, // 12 hours
+ XmNshowValue, TRUE,
+ XmNvalue, trail_segment_time,
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+ // Interval at track segment will not get drawn, in degrees
+ x_str = XmStringCreateLocalized(langcode("WPUPCFTM11"));
+ trail_segment_distance_max = XtVaCreateManagedWidget("Trail segment interval degrees",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, dead_reckoning_time,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNrightOffset, 5,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 0, // Zero degrees
+ XmNmaximum, 45, // 90 degrees
+ XmNshowValue, TRUE,
+ XmNvalue, trail_segment_distance,
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+ // Time below which track segment will get drawn, in minutes
+ x_str = XmStringCreateLocalized(langcode("WPUPCFTM12"));
+ RINO_download_timeout = XtVaCreateManagedWidget("RINO download interval",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, trail_segment_timeout,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNrightOffset, 5,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 0, // Zero minutes (disables the function)
+ XmNmaximum, 30, // 30 minutes
+ XmNshowValue, TRUE,
+ XmNvalue, RINO_download_interval,
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+#ifndef HAVE_GPSMAN
+XtSetSensitive(RINO_download_timeout, FALSE);
+#endif // HAVE_GPSMAN
+
+ x_str = XmStringCreateLocalized(langcode("MPUPTGR017"));
+ net_map_slider = XtVaCreateManagedWidget("Net Map Timeout",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, trail_segment_timeout,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNrightOffset, 5,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 10,
+ XmNmaximum, 300,
+ XmNshowValue, TRUE,
+ XmNvalue, net_map_timeout,
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+ // Interval at which snapshots will be taken, in minutes
+ x_str = XmStringCreateLocalized(langcode("WPUPCFTM13"));
+ snapshot_interval_slider = XtVaCreateManagedWidget("Snapshot interval",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, RINO_download_timeout,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNrightOffset, 5,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 1, // 0.5 minutes
+ XmNmaximum, 30, // 30 minutes
+ XmNshowValue, TRUE,
+ XmNvalue, snapshot_interval,
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, snapshot_interval_slider,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, snapshot_interval_slider,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Configure_timing_change_data, configure_timing_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Configure_timing_destroy_shell, configure_timing_dialog);
+
+ pos_dialog(configure_timing_dialog);
+
+ delw = XmInternAtom(XtDisplay(configure_timing_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(configure_timing_dialog, delw, Configure_timing_destroy_shell, (XtPointer)configure_timing_dialog);
+
+ XtManageChild(my_form);
+ XtManageChild(pane);
+
+ XtPopup(configure_timing_dialog,XtGrabNone);
+ fix_dialog_size(configure_timing_dialog);
+
+ // Move focus to the Close button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(configure_timing_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(configure_timing_dialog), XtWindow(configure_timing_dialog));
+}
+
+
+
+
+
+/////////////////////////////////// Configure Coordinates Dialog //////////////////////////////////
+
+void coordinates_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if (state->set)
+ coordinate_system = atoi(which);
+ else
+ coordinate_system = USE_DDMMMM;
+
+ // Update any active view lists so their coordinates get updated
+ Station_List_fill(1,0); // Update View->Mobile Station list (has lat/lon or UTM info on it)
+ // Force redraw
+ redraw_on_new_data = 2;
+}
+
+
+
+
+
+void Configure_coordinates_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ configure_coordinates_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Configure_coordinates( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, my_form, button_ok, button_cancel, frame,
+ label, coord_box, coord_0, coord_1, coord_2,
+ coord_3, coord_4, coord_5;
+ Atom delw;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+
+ if (!configure_coordinates_dialog) {
+ configure_coordinates_dialog = XtVaCreatePopupShell(langcode("WPUPCFC001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Configure_coordinates pane",
+ xmPanedWindowWidgetClass,
+ configure_coordinates_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Configure_coordinates my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ // Interval for station being considered old
+ frame = XtVaCreateManagedWidget("Configure_coordinates frame",
+ xmFrameWidgetClass,
+ my_form,
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset,10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ label = XtVaCreateManagedWidget(langcode("WPUPCFC002"),
+ xmLabelWidgetClass,
+ frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ /*set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ coord_box = XmCreateRadioBox(frame,"Configure_coordinates coord_box",
+ al,
+ ac);
+
+ XtVaSetValues(coord_box,
+ XmNpacking, XmPACK_TIGHT,
+ XmNorientation, XmHORIZONTAL,
+ XmNnumColumns,5,
+ NULL);
+
+
+ coord_0 = XtVaCreateManagedWidget(langcode("WPUPCFC003"),
+ xmToggleButtonGadgetClass,
+ coord_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coord_0,XmNvalueChangedCallback,coordinates_toggle,"0");
+
+
+ coord_1 = XtVaCreateManagedWidget(langcode("WPUPCFC004"),
+ xmToggleButtonGadgetClass,
+ coord_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coord_1,XmNvalueChangedCallback,coordinates_toggle,"1");
+
+
+ coord_2 = XtVaCreateManagedWidget(langcode("WPUPCFC005"),
+ xmToggleButtonGadgetClass,
+ coord_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coord_2,XmNvalueChangedCallback,coordinates_toggle,"2");
+
+
+ coord_3 = XtVaCreateManagedWidget(langcode("WPUPCFC006"),
+ xmToggleButtonGadgetClass,
+ coord_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coord_3,XmNvalueChangedCallback,coordinates_toggle,"3");
+
+
+ coord_4 = XtVaCreateManagedWidget(langcode("WPUPCFC008"),
+ xmToggleButtonGadgetClass,
+ coord_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coord_4,XmNvalueChangedCallback,coordinates_toggle,"4");
+
+
+ coord_5 = XtVaCreateManagedWidget(langcode("WPUPCFC007"),
+ xmToggleButtonGadgetClass,
+ coord_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coord_5,XmNvalueChangedCallback,coordinates_toggle,"5");
+
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Configure_coordinates_destroy_shell, configure_coordinates_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Configure_coordinates_destroy_shell, configure_coordinates_dialog);
+
+ // Set the toggle buttons based on current data
+ switch (coordinate_system) {
+ case(USE_DDDDDD):
+ XmToggleButtonSetState(coord_0,TRUE,FALSE);
+ break;
+
+ case(USE_DDMMSS):
+ XmToggleButtonSetState(coord_2,TRUE,FALSE);
+ break;
+
+ case(USE_UTM):
+ XmToggleButtonSetState(coord_3,TRUE,FALSE);
+ break;
+
+ case(USE_UTM_SPECIAL):
+ XmToggleButtonSetState(coord_4,TRUE,FALSE);
+ break;
+
+ case(USE_MGRS):
+ XmToggleButtonSetState(coord_5,TRUE,FALSE);
+ break;
+
+ case(USE_DDMMMM):
+ default:
+ XmToggleButtonSetState(coord_1,TRUE,FALSE);
+ break;
+ }
+
+ pos_dialog(configure_coordinates_dialog);
+
+ delw = XmInternAtom(XtDisplay(configure_coordinates_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(configure_coordinates_dialog, delw, Configure_coordinates_destroy_shell, (XtPointer)configure_coordinates_dialog);
+
+ XtManageChild(my_form);
+ XtManageChild(coord_box);
+ XtManageChild(pane);
+
+ XtPopup(configure_coordinates_dialog,XtGrabNone);
+ fix_dialog_size(configure_coordinates_dialog);
+
+ // Move focus to the Close button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(configure_coordinates_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(configure_coordinates_dialog), XtWindow(configure_coordinates_dialog));
+}
+
+
+
+
+
+
+///////////////////////////////// Configure Audio Alarms Dialog ////////////////////////////////
+
+void Configure_audio_alarm_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ configure_audio_alarm_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Configure_audio_alarm_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ char *temp_ptr;
+
+
+ temp_ptr = XmTextFieldGetString(audio_alarm_config_play_data);
+ xastir_snprintf(sound_command,
+ sizeof(sound_command),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(sound_command);
+
+ temp_ptr = XmTextFieldGetString(audio_alarm_config_play_ons_data);
+ xastir_snprintf(sound_new_station,
+ sizeof(sound_new_station),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(sound_new_station);
+
+ temp_ptr = XmTextFieldGetString(audio_alarm_config_play_onm_data);
+ xastir_snprintf(sound_new_message,
+ sizeof(sound_new_message),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(sound_new_message);
+
+ temp_ptr = XmTextFieldGetString(audio_alarm_config_play_onpx_data);
+ xastir_snprintf(sound_prox_message,
+ sizeof(sound_prox_message),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(sound_prox_message);
+
+ temp_ptr = XmTextFieldGetString(prox_min_data);
+ xastir_snprintf(prox_min,
+ sizeof(prox_min),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(prox_min);
+
+ temp_ptr = XmTextFieldGetString(prox_max_data);
+ xastir_snprintf(prox_max,
+ sizeof(prox_max),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(prox_max);
+
+ temp_ptr = XmTextFieldGetString(audio_alarm_config_play_onbo_data);
+ xastir_snprintf(sound_band_open_message,
+ sizeof(sound_band_open_message),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(sound_band_open_message);
+
+ temp_ptr = XmTextFieldGetString(bando_min_data);
+ xastir_snprintf(bando_min,
+ sizeof(bando_min),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(bando_min);
+
+ temp_ptr = XmTextFieldGetString(bando_max_data);
+ xastir_snprintf(bando_max,
+ sizeof(bando_max),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(bando_max);
+
+ temp_ptr = XmTextFieldGetString(audio_alarm_config_wx_alert_data);
+ xastir_snprintf(sound_wx_alert_message,
+ sizeof(sound_wx_alert_message),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(sound_wx_alert_message);
+
+ if(XmToggleButtonGetState(audio_alarm_config_play_on_new_station))
+ sound_play_new_station=1;
+ else
+ sound_play_new_station=0;
+
+ if(XmToggleButtonGetState(audio_alarm_config_play_on_new_message))
+ sound_play_new_message=1;
+ else
+ sound_play_new_message=0;
+
+ if(XmToggleButtonGetState(audio_alarm_config_play_on_prox))
+ sound_play_prox_message=1;
+ else
+ sound_play_prox_message=0;
+
+ if(XmToggleButtonGetState(audio_alarm_config_play_on_bando))
+ sound_play_band_open_message=1;
+ else
+ sound_play_band_open_message=0;
+
+ if(XmToggleButtonGetState(audio_alarm_config_play_on_wx_alert))
+ sound_play_wx_alert_message=1;
+ else
+ sound_play_wx_alert_message=0;
+
+ Configure_audio_alarm_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+void Configure_audio_alarms( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, my_form, button_ok, button_cancel,
+ audio_play, file1, file2,
+ min1, min2, max1, max2,
+ minb1, minb2, maxb1, maxb2,
+ sep;
+ Atom delw;
+
+ if (!configure_audio_alarm_dialog) {
+ configure_audio_alarm_dialog = XtVaCreatePopupShell(langcode("WPUPCFA001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Configure_audio_alarms pane",
+ xmPanedWindowWidgetClass,
+ configure_audio_alarm_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Configure_audio_alarms my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 3,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ audio_play = XtVaCreateManagedWidget(langcode("WPUPCFA002"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ audio_alarm_config_play_data = XtVaCreateManagedWidget("Configure_audio_alarms Play Command",
+ xmTextFieldWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 40,
+ XmNwidth, ((40*7)+2),
+ XmNmaxLength, 80,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ file1 = XtVaCreateManagedWidget(langcode("WPUPCFA003"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, audio_play,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ file2 = XtVaCreateManagedWidget(langcode("WPUPCFA004"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, audio_play,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ audio_alarm_config_play_on_new_station = XtVaCreateManagedWidget(langcode("WPUPCFA005"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, file1,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ audio_alarm_config_play_ons_data = XtVaCreateManagedWidget("Configure_audio_alarms Play Command NS",
+ xmTextFieldWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 80,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, file2,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNleftWidget, audio_alarm_config_play_on_new_station,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNfontList, fontlist1,
+ NULL);
+
+ audio_alarm_config_play_on_new_message = XtVaCreateManagedWidget(langcode("WPUPCFA006"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, audio_alarm_config_play_on_new_station,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ audio_alarm_config_play_onm_data = XtVaCreateManagedWidget("Configure_audio_alarms Play Command NM",
+ xmTextFieldWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 80,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, audio_alarm_config_play_on_new_station,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNfontList, fontlist1,
+ NULL);
+
+ audio_alarm_config_play_on_prox = XtVaCreateManagedWidget(langcode("WPUPCFA007"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, audio_alarm_config_play_on_new_message,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ audio_alarm_config_play_onpx_data = XtVaCreateManagedWidget("Configure_audio_alarms Play Command PROX",
+ xmTextFieldWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 80,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, audio_alarm_config_play_on_new_message,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNfontList, fontlist1,
+ NULL);
+
+ min1 = XtVaCreateManagedWidget(langcode("WPUPCFA009"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, audio_alarm_config_play_on_prox,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ prox_min_data = XtVaCreateManagedWidget("Configure_audio_alarms prox min",
+ xmTextFieldWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 10,
+ XmNwidth, ((10*7)+2),
+ XmNmaxLength, 20,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, audio_alarm_config_play_onpx_data,
+ XmNtopOffset, 2,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNfontList, fontlist1,
+ NULL);
+
+ min2 = XtVaCreateManagedWidget(english_units?langcode("UNIOP00004"):langcode("UNIOP00005"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, audio_alarm_config_play_on_prox,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ max1 = XtVaCreateManagedWidget(langcode("WPUPCFA010"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, min1,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ prox_max_data = XtVaCreateManagedWidget("Configure_audio_alarms prox max",
+ xmTextFieldWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 10,
+ XmNwidth, ((10*7)+2),
+ XmNmaxLength, 20,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, prox_min_data,
+ XmNtopOffset, 2,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNfontList, fontlist1,
+ NULL);
+
+ max2 = XtVaCreateManagedWidget(english_units?langcode("UNIOP00004"):langcode("UNIOP00005"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, min1,
+ XmNtopOffset, 14,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ audio_alarm_config_play_on_bando = XtVaCreateManagedWidget(langcode("WPUPCFA008"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, max1,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ audio_alarm_config_play_onbo_data = XtVaCreateManagedWidget("Configure_audio_alarms Play Command BAND",
+ xmTextFieldWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 80,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, prox_max_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNfontList, fontlist1,
+ NULL);
+
+ minb1 = XtVaCreateManagedWidget(langcode("WPUPCFA009"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, audio_alarm_config_play_on_bando,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ bando_min_data = XtVaCreateManagedWidget("Configure_audio_alarms bando min",
+ xmTextFieldWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 12,
+ XmNwidth, ((10*7)+2),
+ XmNmaxLength, 20,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, audio_alarm_config_play_onbo_data,
+ XmNtopOffset, 2,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNfontList, fontlist1,
+ NULL);
+
+ minb2 = XtVaCreateManagedWidget(english_units?langcode("UNIOP00004"):langcode("UNIOP00005"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, audio_alarm_config_play_on_bando,
+ XmNtopOffset, 14,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ maxb1 = XtVaCreateManagedWidget(langcode("WPUPCFA010"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, minb1,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ bando_max_data = XtVaCreateManagedWidget("Configure_audio_alarms bando max",
+ xmTextFieldWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 10,
+ XmNwidth, ((10*7)+2),
+ XmNmaxLength, 20,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, bando_min_data,
+ XmNtopOffset, 2,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment,XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNfontList, fontlist1,
+ NULL);
+
+ maxb2 = XtVaCreateManagedWidget(english_units?langcode("UNIOP00004"):langcode("UNIOP00005"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, minb1,
+ XmNtopOffset, 14,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ audio_alarm_config_play_on_wx_alert = XtVaCreateManagedWidget(langcode("WPUPCFA011"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, maxb2,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ audio_alarm_config_wx_alert_data = XtVaCreateManagedWidget("Configure_audio_alarms Play Command WxAlert",
+ xmTextFieldWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 25,
+ XmNwidth, ((25*7)+2),
+ XmNmaxLength, 80,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, bando_max_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sep = XtVaCreateManagedWidget("Configure_audio_alarms sep",
+ xmSeparatorGadgetClass,
+ my_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, audio_alarm_config_play_on_wx_alert,
+ XmNtopOffset, 20,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Configure_audio_alarm_change_data, configure_audio_alarm_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Configure_audio_alarm_destroy_shell, configure_audio_alarm_dialog);
+
+ pos_dialog(configure_audio_alarm_dialog);
+
+ delw = XmInternAtom(XtDisplay(configure_audio_alarm_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(configure_audio_alarm_dialog, delw, Configure_audio_alarm_destroy_shell,
+ (XtPointer)configure_audio_alarm_dialog);
+
+ XmTextFieldSetString(audio_alarm_config_play_data,sound_command);
+ XmTextFieldSetString(audio_alarm_config_play_ons_data,sound_new_station);
+ XmTextFieldSetString(audio_alarm_config_play_onm_data,sound_new_message);
+ XmTextFieldSetString(audio_alarm_config_play_onpx_data,sound_prox_message);
+ XmTextFieldSetString(prox_min_data,prox_min);
+ XmTextFieldSetString(prox_max_data,prox_max);
+ XmTextFieldSetString(audio_alarm_config_play_onbo_data,sound_band_open_message);
+ XmTextFieldSetString(bando_min_data,bando_min);
+ XmTextFieldSetString(bando_max_data,bando_max);
+ XmTextFieldSetString(audio_alarm_config_wx_alert_data, sound_wx_alert_message);
+
+ if(sound_play_new_station)
+ XmToggleButtonSetState(audio_alarm_config_play_on_new_station,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(audio_alarm_config_play_on_new_station,FALSE,FALSE);
+
+ if(sound_play_new_message)
+ XmToggleButtonSetState(audio_alarm_config_play_on_new_message,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(audio_alarm_config_play_on_new_message,FALSE,FALSE);
+
+ if(sound_play_prox_message)
+ XmToggleButtonSetState(audio_alarm_config_play_on_prox,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(audio_alarm_config_play_on_prox,FALSE,FALSE);
+
+ if(sound_play_band_open_message)
+ XmToggleButtonSetState(audio_alarm_config_play_on_bando,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(audio_alarm_config_play_on_bando,FALSE,FALSE);
+
+ if (sound_play_wx_alert_message)
+ XmToggleButtonSetState(audio_alarm_config_play_on_wx_alert, TRUE, FALSE);
+ else
+ XmToggleButtonSetState(audio_alarm_config_play_on_wx_alert, FALSE, FALSE);
+
+ XtManageChild(my_form);
+ XtManageChild(pane);
+
+ XtPopup(configure_audio_alarm_dialog,XtGrabNone);
+ fix_dialog_size(configure_audio_alarm_dialog);
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(configure_audio_alarm_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(configure_audio_alarm_dialog), XtWindow(configure_audio_alarm_dialog));
+
+}
+
+
+
+
+
+///////////////////////////////////// Configure Speech Dialog //////////////////////////////////
+
+
+void Configure_speech_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+ configure_speech_dialog = (Widget)NULL;
+}
+
+
+
+
+
+void Test_speech(Widget widget, XtPointer clientData, XtPointer callData) {
+ SayText(SPEECH_TEST_STRING);
+}
+
+
+
+
+
+void Configure_speech_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+
+ if(XmToggleButtonGetState(speech_config_play_on_new_station))
+ festival_speak_new_station=1;
+ else
+ festival_speak_new_station=0;
+
+ if(XmToggleButtonGetState(speech_config_play_on_new_message_alert))
+ festival_speak_new_message_alert=1;
+ else
+ festival_speak_new_message_alert=0;
+
+ if(XmToggleButtonGetState(speech_config_play_on_new_message_body))
+ festival_speak_new_message_body=1;
+ else
+ festival_speak_new_message_body=0;
+
+ if(XmToggleButtonGetState(speech_config_play_on_prox))
+ festival_speak_proximity_alert=1;
+ else
+ festival_speak_proximity_alert=0;
+
+ if(XmToggleButtonGetState(speech_config_play_on_trak))
+ festival_speak_tracked_proximity_alert=1;
+ else
+ festival_speak_tracked_proximity_alert=0;
+
+ if(XmToggleButtonGetState(speech_config_play_on_bando))
+ festival_speak_band_opening=1;
+ else
+ festival_speak_band_opening=0;
+
+ if(XmToggleButtonGetState(speech_config_play_on_new_wx_alert))
+ festival_speak_new_weather_alert=1;
+ else
+ festival_speak_new_weather_alert=0;
+
+ Configure_speech_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+//Make it helpful - Gray the config selections, but add a choice
+//that basicly pops up a box that says where to get Festival, have
+//it be ungrayed if Festival isn't installed.
+
+void Configure_speech( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, my_form, button_ok, button_cancel, file1,
+ sep, button_test;
+ Atom delw;
+
+ if (!configure_speech_dialog) {
+ configure_speech_dialog = XtVaCreatePopupShell(langcode("WPUPCFSP01"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Configure_speech pane",
+ xmPanedWindowWidgetClass,
+ configure_speech_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Configure_speech my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ file1 = XtVaCreateManagedWidget(langcode("WPUPCFSP02"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ speech_config_play_on_new_station = XtVaCreateManagedWidget(langcode("WPUPCFSP03"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, file1,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+#ifndef HAVE_FESTIVAL
+ XmNsensitive, FALSE,
+#endif /* HAVE_FESTIVAL */
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ speech_config_play_on_new_message_alert = XtVaCreateManagedWidget(langcode("WPUPCFSP04"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, speech_config_play_on_new_station,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+#ifndef HAVE_FESTIVAL
+ XmNsensitive, FALSE,
+#endif /* HAVE_FESTIVAL */
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ speech_config_play_on_new_message_body = XtVaCreateManagedWidget(langcode("WPUPCFSP05"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, speech_config_play_on_new_message_alert,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+#ifndef HAVE_FESTIVAL
+ XmNsensitive, FALSE,
+#endif /* HAVE_FESTIVAL */
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ speech_config_play_on_prox = XtVaCreateManagedWidget(langcode("WPUPCFSP06"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, speech_config_play_on_new_message_body,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+#ifndef HAVE_FESTIVAL
+ XmNsensitive, FALSE,
+#endif /* HAVE_FESTIVAL */
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ speech_config_play_on_trak = XtVaCreateManagedWidget(langcode("WPUPCFSP09"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, speech_config_play_on_prox,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+#ifndef HAVE_FESTIVAL
+ XmNsensitive, FALSE,
+#endif /* HAVE_FESTIVAL */
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ speech_config_play_on_bando = XtVaCreateManagedWidget(langcode("WPUPCFSP07"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, speech_config_play_on_trak,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+#ifndef HAVE_FESTIVAL
+ XmNsensitive, FALSE,
+#endif /* HAVE_FESTIVAL */
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ speech_config_play_on_new_wx_alert = XtVaCreateManagedWidget(langcode("WPUPCFSP08"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, speech_config_play_on_bando,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+#ifndef HAVE_FESTIVAL
+ XmNsensitive, FALSE,
+#endif /* HAVE_FESTIVAL */
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ sep = XtVaCreateManagedWidget("Configure_speech sep",
+ xmSeparatorGadgetClass,
+ my_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, speech_config_play_on_new_wx_alert,
+ XmNtopOffset, 20,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_test = XtVaCreateManagedWidget(langcode("PULDNFI003"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 4,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 5,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_test, XmNactivateCallback, Test_speech, configure_speech_dialog);
+ XtAddCallback(button_ok, XmNactivateCallback, Configure_speech_change_data, configure_speech_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Configure_speech_destroy_shell, configure_speech_dialog);
+
+ pos_dialog(configure_speech_dialog);
+
+ delw = XmInternAtom(XtDisplay(configure_speech_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(configure_speech_dialog, delw, Configure_speech_destroy_shell,
+ (XtPointer)configure_speech_dialog);
+
+
+ if(festival_speak_new_station)
+ XmToggleButtonSetState(speech_config_play_on_new_station,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(speech_config_play_on_new_station,FALSE,FALSE);
+
+ if(festival_speak_new_message_alert)
+ XmToggleButtonSetState(speech_config_play_on_new_message_alert,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(speech_config_play_on_new_message_alert,FALSE,FALSE);
+
+ if(festival_speak_new_message_body)
+ XmToggleButtonSetState(speech_config_play_on_new_message_body,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(speech_config_play_on_new_message_body,FALSE,FALSE);
+
+ if(festival_speak_proximity_alert)
+ XmToggleButtonSetState(speech_config_play_on_prox,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(speech_config_play_on_prox,FALSE,FALSE);
+
+ if(festival_speak_tracked_proximity_alert)
+ XmToggleButtonSetState(speech_config_play_on_trak,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(speech_config_play_on_trak,FALSE,FALSE);
+
+ if(festival_speak_band_opening)
+ XmToggleButtonSetState(speech_config_play_on_bando,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(speech_config_play_on_bando,FALSE,FALSE);
+
+ if(festival_speak_new_weather_alert)
+ XmToggleButtonSetState(speech_config_play_on_new_wx_alert,TRUE,FALSE);
+ else
+ XmToggleButtonSetState(speech_config_play_on_new_wx_alert,FALSE,FALSE);
+
+ XtManageChild(my_form);
+ XtManageChild(pane);
+
+ XtPopup(configure_speech_dialog,XtGrabNone);
+ fix_dialog_size(configure_speech_dialog);
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(configure_speech_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(configure_speech_dialog), XtWindow(configure_speech_dialog));
+
+}
+
+
+
+
+
+/*
+ * Track_Me
+ *
+ */
+void Track_Me( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ xastir_snprintf(tracking_station_call,
+ sizeof(tracking_station_call),
+ "%s",
+ my_callsign);
+ track_me = atoi(which);
+ track_station_on = atoi(which);
+ display_zoom_status();
+ }
+ else {
+ track_me = 0;
+ track_station_on = 0;
+ display_zoom_status();
+ }
+}
+
+
+
+
+
+// Pointer to the Move/Measure cursor object
+static Cursor cs_move_measure = (Cursor)NULL;
+
+/*
+ * Move_Object
+ *
+ */
+void Move_Object( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ moving_object = atoi(which);
+ XmToggleButtonSetState(measure_button, FALSE, FALSE);
+ measuring_distance = 0;
+
+ // Change the cursor
+ if(!cs_move_measure) {
+ cs_move_measure=XCreateFontCursor(XtDisplay(da),XC_crosshair);
+ }
+
+ (void)XDefineCursor(XtDisplay(da),XtWindow(da),cs_move_measure);
+ (void)XFlush(XtDisplay(da));
+ }
+ else {
+ moving_object = 0;
+
+ // Remove the special "crosshair" cursor
+ (void)XUndefineCursor(XtDisplay(da),XtWindow(da));
+ (void)XFlush(XtDisplay(da));
+ }
+}
+
+
+
+
+
+/*
+ * Measure_Distance
+ *
+ */
+void Measure_Distance( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ measuring_distance = atoi(which);
+ XmToggleButtonSetState(move_button, FALSE, FALSE);
+ moving_object = 0;
+
+ // Change the cursor
+ if(!cs_move_measure) {
+ cs_move_measure=XCreateFontCursor(XtDisplay(da),XC_crosshair);
+ }
+
+ (void)XDefineCursor(XtDisplay(da),XtWindow(da),cs_move_measure);
+ (void)XFlush(XtDisplay(da));
+ }
+ else {
+ measuring_distance = 0;
+
+ // Remove the special "crosshair" cursor
+ (void)XUndefineCursor(XtDisplay(da),XtWindow(da));
+ (void)XFlush(XtDisplay(da));
+ }
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////
+
+
+
+/*
+ * Destroy Configure Station Dialog Popup Window
+ */
+void Configure_station_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ (void)XFreePixmap(XtDisplay(appshell),CS_icon0); // ???? DK7IN: avoid possible memory leak ?
+ (void)XFreePixmap(XtDisplay(appshell),CS_icon);
+ XtDestroyWidget(shell);
+ configure_station_dialog = (Widget)NULL;
+
+ // Take down the symbol selection dialog as well (if it's up)
+ if (select_symbol_dialog) {
+ Select_symbol_destroy_shell( widget, select_symbol_dialog, callData);
+ }
+
+ // NULL out the dialog field in the global struct used for
+ // Coordinate Calculator. Prevents segfaults if the calculator is
+ // still up and trying to write to us.
+ coordinate_calc_array.calling_dialog = NULL;
+}
+
+
+
+
+
+void Configure_station_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ Configure_station_pos_amb = atoi(which);
+ else
+ Configure_station_pos_amb = 0;
+}
+
+
+
+
+
+/*
+ * Process changes to station data
+ */
+void Configure_station_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+ char temp[40];
+ char old_callsign[MAX_CALLSIGN+1];
+ int ok = 1;
+ int temp2;
+ int temp3;
+ char *temp_ptr;
+ char *temp_ptr2;
+
+
+ transmit_compressed_posit = (int)XmToggleButtonGetState(compressed_posit_tx);
+
+ xastir_snprintf(old_callsign,
+ sizeof(old_callsign),
+ "%s",
+ my_callsign);
+
+ /*fprintf(stderr,"Changing Configure station data\n");*/
+
+ temp_ptr = XmTextFieldGetString(station_config_call_data);
+ xastir_snprintf(my_callsign,
+ sizeof(my_callsign),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(my_callsign);
+ (void)to_upper(my_callsign);
+ (void)remove_trailing_dash_zero(my_callsign);
+
+ // Enter NOCALL if there's nothing left.
+ if (my_callsign[0] == '\0')
+ xastir_snprintf(my_callsign,
+ sizeof(my_callsign),
+ "NOCALL");
+
+ temp_ptr = XmTextFieldGetString(station_config_slat_data_ns);
+ if((char)toupper((int)temp_ptr[0])=='S')
+ temp[0]='S';
+ else
+ temp[0]='N';
+ XtFree(temp_ptr);
+
+ // Check latitude for out-of-bounds
+ temp_ptr = XmTextFieldGetString(station_config_slat_data_deg);
+ temp2 = atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ if ( (temp2 > 90) || (temp2 < 0) )
+ ok = 0;
+
+ temp_ptr = XmTextFieldGetString(station_config_slat_data_min);
+ temp3 = atof(temp_ptr);
+ XtFree(temp_ptr);
+
+ if ( (temp3 >= 60.0) || (temp3 < 0.0) )
+ ok = 0;
+
+ if ( (temp2 == 90) && (temp3 != 0.0) )
+ ok = 0;
+
+ temp_ptr = XmTextFieldGetString(station_config_slat_data_deg);
+ temp_ptr2 = XmTextFieldGetString(station_config_slat_data_min);
+ xastir_snprintf(my_lat, sizeof(my_lat), "%02d%06.3f%c",
+ atoi(temp_ptr),
+ atof(temp_ptr2),temp[0]);
+ XtFree(temp_ptr);
+ XtFree(temp_ptr2);
+
+ temp_ptr = XmTextFieldGetString(station_config_slong_data_ew);
+ if((char)toupper((int)temp_ptr[0])=='E')
+ temp[0]='E';
+ else
+ temp[0]='W';
+ XtFree(temp_ptr);
+
+ // Check longitude for out-of-bounds
+ temp_ptr = XmTextFieldGetString(station_config_slong_data_deg);
+ temp2 = atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ if ( (temp2 > 180) || (temp2 < 0) )
+ ok = 0;
+
+ temp_ptr = XmTextFieldGetString(station_config_slong_data_min);
+ temp3 = atof(temp_ptr);
+ XtFree(temp_ptr);
+
+ if ( (temp3 >= 60.0) || (temp3 < 0.0) )
+ ok = 0;
+
+ if ( (temp2 == 180) && (temp3 != 0.0) )
+ ok = 0;
+
+ temp_ptr = XmTextFieldGetString(station_config_slong_data_deg);
+ temp_ptr2 = XmTextFieldGetString(station_config_slong_data_min);
+ xastir_snprintf(my_long, sizeof(my_long), "%03d%06.3f%c",
+ atoi(temp_ptr),
+ atof(temp_ptr2),temp[0]);
+ XtFree(temp_ptr);
+ XtFree(temp_ptr2);
+
+ temp_ptr = XmTextFieldGetString(station_config_group_data);
+ my_group=temp_ptr[0];
+ if(isalpha((int)my_group))
+ my_group = toupper((int)temp_ptr[0]);
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(station_config_symbol_data);
+ my_symbol = temp_ptr[0];
+ XtFree(temp_ptr);
+
+ if(isdigit((int)my_phg[3]) && isdigit((int)my_phg[4]) && isdigit((int)my_phg[5]) && isdigit((int)my_phg[6])) {
+ my_phg[0] = 'P';
+ my_phg[1] = 'H';
+ my_phg[2] = 'G';
+ my_phg[7] = '\0';
+ } else
+ my_phg[0]='\0';
+
+ /* set station ambiguity*/
+ position_amb_chars = Configure_station_pos_amb;
+
+ if (transmit_compressed_posit) {
+ position_amb_chars = 0;
+ }
+
+ temp_ptr = XmTextFieldGetString(station_config_comment_data);
+ xastir_snprintf(my_comment,
+ sizeof(my_comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(my_comment);
+
+ /* TO DO: KILL only my station data? */
+ if (ok) { // If entered data was valid
+
+ // Check whether we changed our callsign
+ if (strcasecmp(old_callsign,my_callsign) != 0) {
+ station_del(old_callsign); // move to new sort location...
+
+ // If TrackMe is enabled, copy the new callsign into the
+ // track_station_call variable. If we don't do this, we
+ // will still be tracking our old callsign.
+ if (track_me) {
+ xastir_snprintf(tracking_station_call,
+ sizeof(tracking_station_call),
+ "%s",
+ my_callsign);
+ }
+ }
+
+ // Update our parameters
+ my_station_add(my_callsign,my_group,my_symbol,my_long,my_lat,my_phg,my_comment,(char)position_amb_chars);
+
+ redraw_on_new_data=2;
+ Configure_station_destroy_shell(widget,clientData,callData);
+ }
+
+ // Check for proper weather symbols if a weather station
+ (void)check_weather_symbol();
+
+ // Check for use of NWS symbols
+ (void)check_nws_weather_symbol();
+}
+
+
+
+
+
+/*
+ * Update symbol picture for changed symbol or table
+ */
+void updateSymbolPictureCallback( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char table, overlay;
+ char symb, group;
+ char *temp_ptr;
+
+
+ XtVaSetValues(station_config_icon, XmNlabelPixmap, CS_icon0, NULL); // clear old icon
+ XtManageChild(station_config_icon);
+
+ temp_ptr = XmTextFieldGetString(station_config_group_data);
+ group = temp_ptr[0];
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(station_config_symbol_data);
+ symb = temp_ptr[0];
+ XtFree(temp_ptr);
+
+ if (group == '/' || group == '\\') {
+ table = group;
+ overlay = ' ';
+ } else {
+ table = '\\';
+ overlay = group;
+ }
+ symbol(station_config_icon,0,table,symb,overlay,CS_icon,0,0,0,' '); // create icon
+
+ XtVaSetValues(station_config_icon,XmNlabelPixmap,CS_icon,NULL); // draw new icon
+ XtManageChild(station_config_icon);
+}
+
+
+
+
+
+/* Power radio buttons */
+void Power_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+
+ my_phg[3] = which[0]; // Set to power desired
+
+ if (which[0] == 'x') { // Disable PHG field if 'x' found
+ my_phg[0] = '\0';
+ }
+ } else {
+ my_phg[3] = '3'; // 10 Watts (default in spec if none specified)
+ }
+ my_phg[8] = '\0';
+
+ //fprintf(stderr,"PHG: %s\n",my_phg);
+}
+
+
+
+
+
+/* Height radio buttons */
+void Height_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ my_phg[4] = which[0]; // Set to height desired
+ } else {
+ my_phg[4] = '1'; // 20 Feet above average terrain (default in spec if none specified)
+ }
+ my_phg[8] = '\0';
+
+ //fprintf(stderr,"PHG: %s\n",my_phg);
+}
+
+
+
+
+
+
+/* Gain radio buttons */
+void Gain_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ my_phg[5] = which[0]; // Set to gain desired
+ } else {
+ my_phg[5] = '3'; // 3dB gain antenna (default in spec if none specified)
+ }
+ my_phg[8] = '\0';
+
+ //fprintf(stderr,"PHG: %s\n",my_phg);
+}
+
+
+
+
+
+
+/* Directivity radio buttons */
+void Directivity_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ my_phg[6] = which[0]; // Set to directivity desired
+ } else {
+ my_phg[6] = '0'; // Omni-directional antenna (default in spec if none specified)
+ }
+ my_phg[8] = '\0';
+
+ //fprintf(stderr,"PHG: %s\n",my_phg);
+}
+
+
+
+
+
+void Posit_compressed_toggle( /*@unused@*/ Widget w, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ transmit_compressed_posit = atoi(which);
+ else
+ transmit_compressed_posit = 0;
+
+ if(transmit_compressed_posit) {
+ // Compressed posits don't allow position ambiguity
+ position_amb_chars = 0;
+ XtSetSensitive(posamb0,FALSE);
+ XtSetSensitive(posamb1,FALSE);
+ XtSetSensitive(posamb2,FALSE);
+ XtSetSensitive(posamb3,FALSE);
+ XtSetSensitive(posamb4,FALSE);
+ }
+ else { // Position ambiguity ok for this mode
+ XtSetSensitive(posamb0,TRUE);
+ XtSetSensitive(posamb1,TRUE);
+ XtSetSensitive(posamb2,TRUE);
+ XtSetSensitive(posamb3,TRUE);
+ XtSetSensitive(posamb4,TRUE);
+ }
+}
+
+
+
+
+
+/*
+ * Select a symbol graphically
+ */
+void Configure_change_symbol(/*@unused@*/ Widget widget, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+
+ //fprintf(stderr,"Trying to change a symbol\n");
+ symbol_change_requested_from = 1; // Tell Select_symbol who to return the data to
+ Select_symbol(widget, clientData, callData);
+}
+
+
+
+
+
+
+/*
+ * Setup Configure Station dialog
+ */
+void Configure_station( /*@unused@*/ Widget ww, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, cs_form, cs_form1, button_ok, button_cancel, call, frame, frame2,
+ framephg, pg2, formphg,
+ power_box,poption0,poption1,poption2,poption3,poption4,poption5,poption6,poption7,poption8,poption9,poption10,
+ height_box,hoption1,hoption2,hoption3,hoption4,hoption5,hoption6,hoption7,hoption8,hoption9,hoption10,
+ gain_box,goption1,goption2,goption3,goption4,goption5,goption6,goption7,goption8,goption9,goption10,
+ directivity_box,doption1,doption2,doption3,doption4,doption5,doption6,doption7,doption8,doption9,
+ slat,
+ slat_deg, slat_min, slat_ns,
+ slong,
+ slong_deg, slong_min, slong_ew,
+ sts, group, st_symbol, comment,
+ posamb,option_box,
+ sep, configure_button_symbol, compute_button;
+ char temp_data[40];
+ Atom delw;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+
+
+ if(!configure_station_dialog) {
+ configure_station_dialog = XtVaCreatePopupShell(langcode("WPUPCFS001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Configure_station pane",
+ xmPanedWindowWidgetClass,
+ configure_station_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ cs_form = XtVaCreateWidget("Configure_station cs_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ call = XtVaCreateManagedWidget(langcode("WPUPCFS002"),
+ xmLabelWidgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ station_config_call_data = XtVaCreateManagedWidget("Configure_station call_data",
+ xmTextFieldWidgetClass,
+ cs_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 10,
+ XmNwidth, ((10*7)+2),
+ XmNmaxLength, 9,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ compressed_posit_tx = XtVaCreateManagedWidget(langcode("WPUPCFS029"),
+ xmToggleButtonWidgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(compressed_posit_tx,XmNvalueChangedCallback,Posit_compressed_toggle,"1");
+
+ slat = XtVaCreateManagedWidget(langcode("WPUPCFS003"),
+ xmLabelWidgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, call,
+ XmNtopOffset, 25,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ station_config_slat_data_deg = XtVaCreateManagedWidget("Configure_station lat_deg",
+ xmTextFieldWidgetClass,
+ cs_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 3,
+ XmNmaxLength, 2,
+ XmNtopOffset, 20,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, call,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ slat_deg = XtVaCreateManagedWidget(langcode("WPUPCFS004"),
+ xmLabelWidgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, call,
+ XmNtopOffset, 25,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, station_config_slat_data_deg,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ station_config_slat_data_min = XtVaCreateManagedWidget("Configure_station lat_min",
+ xmTextFieldWidgetClass,
+ cs_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNmaxLength, 6,
+ XmNtopOffset, 20,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, slat_deg,
+ XmNleftOffset, 10,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, call,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ slat_min = XtVaCreateManagedWidget(langcode("WPUPCFS005"),
+ xmLabelWidgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, call,
+ XmNtopOffset, 25,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, station_config_slat_data_min,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ station_config_slat_data_ns = XtVaCreateManagedWidget("Configure_station lat_ns",
+ xmTextFieldWidgetClass,
+ cs_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 1,
+ XmNmaxLength, 1,
+ XmNtopOffset, 20,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, slat_min,
+ XmNleftOffset, 10,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, call,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ slat_ns = XtVaCreateManagedWidget(langcode("WPUPCFS006"),
+ xmLabelWidgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, call,
+ XmNtopOffset, 25,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, station_config_slat_data_ns,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ slong = XtVaCreateManagedWidget(langcode("WPUPCFS007"),
+ xmLabelWidgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, slat,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ station_config_slong_data_deg = XtVaCreateManagedWidget("Configure_station long_deg",
+ xmTextFieldWidgetClass,
+ cs_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 3,
+ XmNmaxLength, 3,
+ XmNtopOffset, 14,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, slat,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ slong_deg = XtVaCreateManagedWidget(langcode("WPUPCFS004"),
+ xmLabelWidgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, slat,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, station_config_slong_data_deg,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ station_config_slong_data_min = XtVaCreateManagedWidget("Configure_station long_min",
+ xmTextFieldWidgetClass,
+ cs_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNmaxLength, 6,
+ XmNtopOffset, 14,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, slong_deg,
+ XmNleftOffset, 10,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, slat,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ slong_min = XtVaCreateManagedWidget(langcode("WPUPCFS005"),
+ xmLabelWidgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, slat,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, station_config_slong_data_min,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ station_config_slong_data_ew = XtVaCreateManagedWidget("Configure_station long_ew",
+ xmTextFieldWidgetClass,
+ cs_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 1,
+ XmNmaxLength, 1,
+ XmNtopOffset, 14,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, slong_min,
+ XmNleftOffset, 10,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, slat,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ slong_ew = XtVaCreateManagedWidget(langcode("WPUPCFS008"),
+ xmLabelWidgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, slat,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, station_config_slong_data_ew,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ compute_button = XtVaCreateManagedWidget(langcode("COORD002"),
+ xmPushButtonGadgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, slat,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, slong_ew,
+ XmNleftOffset, 15,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Fill in the pointers to our input textfields so that the
+ // coordinate calculator can fiddle with them.
+ coordinate_calc_array.calling_dialog = configure_station_dialog;
+ coordinate_calc_array.input_lat_deg = station_config_slat_data_deg;
+ coordinate_calc_array.input_lat_min = station_config_slat_data_min;
+ coordinate_calc_array.input_lat_dir = station_config_slat_data_ns;
+ coordinate_calc_array.input_lon_deg = station_config_slong_data_deg;
+ coordinate_calc_array.input_lon_min = station_config_slong_data_min;
+ coordinate_calc_array.input_lon_dir = station_config_slong_data_ew;
+// XtAddCallback(compute_button, XmNactivateCallback, Coordinate_calc, configure_station_dialog);
+// XtAddCallback(compute_button, XmNactivateCallback, Coordinate_calc, "Configure_station");
+ XtAddCallback(compute_button, XmNactivateCallback, Coordinate_calc, langcode("WPUPCFS001"));
+
+
+
+
+//----- Frame for table / symbol
+ frame = XtVaCreateManagedWidget("Configure_station frame",
+ xmFrameWidgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, slong_ew,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ // "Station Symbol"
+ sts = XtVaCreateManagedWidget(langcode("WPUPCFS009"),
+ xmLabelWidgetClass,
+ frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ cs_form1 = XtVaCreateWidget("Configure_station cs_form1",
+ xmFormWidgetClass,
+ frame,
+ XmNfractionBase, 5,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Group/overlay"
+ group = XtVaCreateManagedWidget(langcode("WPUPCFS010"),
+ xmLabelWidgetClass,
+ cs_form1,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 10,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 100,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // table
+ station_config_group_data = XtVaCreateManagedWidget("Configure_station group",
+ xmTextFieldWidgetClass,
+ cs_form1,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 1,
+ XmNmaxLength, 1,
+ XmNtopOffset, 6,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, group,
+ XmNleftOffset, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Symbol"
+ st_symbol = XtVaCreateManagedWidget(langcode("WPUPCFS011"),
+ xmLabelWidgetClass,
+ cs_form1,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, station_config_group_data,
+ XmNleftOffset, 20,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // symbol
+ station_config_symbol_data = XtVaCreateManagedWidget("Configure_station symbol",
+ xmTextFieldWidgetClass,
+ cs_form1,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 1,
+ XmNmaxLength, 1,
+ XmNtopOffset, 6,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, st_symbol,
+ XmNleftOffset, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // icon
+ CS_icon0 = XCreatePixmap(XtDisplay(appshell),
+ RootWindowOfScreen(XtScreen(appshell)),
+ 20,
+ 20,
+ DefaultDepthOfScreen(XtScreen(appshell)));
+ CS_icon = XCreatePixmap(XtDisplay(appshell),
+ RootWindowOfScreen(XtScreen(appshell)),
+ 20,
+ 20,
+ DefaultDepthOfScreen(XtScreen(appshell)));
+ station_config_icon = XtVaCreateManagedWidget("Configure_station icon",
+ xmLabelWidgetClass,
+ cs_form1,
+ XmNlabelType, XmPIXMAP,
+ XmNlabelPixmap, CS_icon,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, station_config_symbol_data,
+ XmNleftOffset, 15,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ configure_button_symbol = XtVaCreateManagedWidget(langcode("WPUPCFS028"),
+ xmPushButtonGadgetClass,
+ cs_form1,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 6,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, station_config_icon,
+ XmNleftOffset, 15,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(configure_button_symbol, XmNactivateCallback, Configure_change_symbol, configure_station_dialog);
+
+
+//----- Frame for Power-Gain
+ framephg = XtVaCreateManagedWidget("Configure_station framephg",
+ xmFrameWidgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ pg2 = XtVaCreateManagedWidget(langcode("WPUPCFS012"),
+ xmLabelWidgetClass,
+ framephg,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ formphg = XtVaCreateWidget("Configure_station power_form",
+ xmFormWidgetClass,
+ framephg,
+ XmNfractionBase, 5,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // Power
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ power_box = XmCreateRadioBox(formphg,
+ "Configure_station Power Radio Box",
+ al,
+ ac);
+
+ XtVaSetValues(power_box,
+ XmNpacking, XmPACK_TIGHT,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnumColumns,11,
+ NULL);
+
+ poption0 = XtVaCreateManagedWidget(langcode("WPUPCFS013"),
+ xmToggleButtonGadgetClass,
+ power_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(poption0,XmNvalueChangedCallback,Power_toggle,"x");
+
+ // 0 Watts
+ poption1 = XtVaCreateManagedWidget("0W",
+ xmToggleButtonGadgetClass,
+ power_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(poption1,XmNvalueChangedCallback,Power_toggle,"0");
+
+ // 1 Watt
+ poption2 = XtVaCreateManagedWidget("1W",
+ xmToggleButtonGadgetClass,
+ power_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(poption2,XmNvalueChangedCallback,Power_toggle,"1");
+
+ // 4 Watts
+ poption3 = XtVaCreateManagedWidget("4W",
+ xmToggleButtonGadgetClass,
+ power_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(poption3,XmNvalueChangedCallback,Power_toggle,"2");
+
+ // 9 Watts
+ poption4 = XtVaCreateManagedWidget("9W",
+ xmToggleButtonGadgetClass,
+ power_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(poption4,XmNvalueChangedCallback,Power_toggle,"3");
+
+ // 16 Watts
+ poption5 = XtVaCreateManagedWidget("16W",
+ xmToggleButtonGadgetClass,
+ power_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(poption5,XmNvalueChangedCallback,Power_toggle,"4");
+
+ // 25 Watts
+ poption6 = XtVaCreateManagedWidget("25W",
+ xmToggleButtonGadgetClass,
+ power_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(poption6,XmNvalueChangedCallback,Power_toggle,"5");
+
+ // 36 Watts
+ poption7 = XtVaCreateManagedWidget("36W",
+ xmToggleButtonGadgetClass,
+ power_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(poption7,XmNvalueChangedCallback,Power_toggle,"6");
+
+ // 49 Watts
+ poption8 = XtVaCreateManagedWidget("49W",
+ xmToggleButtonGadgetClass,
+ power_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(poption8,XmNvalueChangedCallback,Power_toggle,"7");
+
+ // 64 Watts
+ poption9 = XtVaCreateManagedWidget("64W",
+ xmToggleButtonGadgetClass,
+ power_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(poption9,XmNvalueChangedCallback,Power_toggle,"8");
+
+ // 81 Watts
+ poption10 = XtVaCreateManagedWidget("81W",
+ xmToggleButtonGadgetClass,
+ power_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(poption10,XmNvalueChangedCallback,Power_toggle,"9");
+
+
+ // Height
+ height_box = XmCreateRadioBox(formphg,
+ "Configure_station Height Radio Box",
+ al,
+ ac);
+
+ XtVaSetValues(height_box,
+ XmNpacking, XmPACK_TIGHT,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget,power_box,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnumColumns,10,
+ NULL);
+
+
+ // 10 Feet
+ hoption1 = XtVaCreateManagedWidget(
+ (english_units) ? "10ft" : "3m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption1,XmNvalueChangedCallback,Height_toggle,"0");
+
+ // 20 Feet
+ hoption2 = XtVaCreateManagedWidget(
+ (english_units) ? "20ft" : "6m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption2,XmNvalueChangedCallback,Height_toggle,"1");
+
+ // 40 Feet
+ hoption3 = XtVaCreateManagedWidget(
+ (english_units) ? "40ft" : "12m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption3,XmNvalueChangedCallback,Height_toggle,"2");
+
+ // 80 Feet
+ hoption4 = XtVaCreateManagedWidget(
+ (english_units) ? "80ft" : "24m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption4,XmNvalueChangedCallback,Height_toggle,"3");
+
+ // 160 Feet
+ hoption5 = XtVaCreateManagedWidget(
+ (english_units) ? "160ft" : "49m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption5,XmNvalueChangedCallback,Height_toggle,"4");
+
+ // 320 Feet
+ hoption6 = XtVaCreateManagedWidget(
+ (english_units) ? "320ft" : "98m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption6,XmNvalueChangedCallback,Height_toggle,"5");
+
+ // 640 Feet
+ hoption7 = XtVaCreateManagedWidget(
+ (english_units) ? "640ft" : "195m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption7,XmNvalueChangedCallback,Height_toggle,"6");
+
+ // 1280 Feet
+ hoption8 = XtVaCreateManagedWidget(
+ (english_units) ? "1280ft" : "390m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption8,XmNvalueChangedCallback,Height_toggle,"7");
+
+ // 2560 Feet
+ hoption9 = XtVaCreateManagedWidget(
+ (english_units) ? "2560ft" : "780m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption9,XmNvalueChangedCallback,Height_toggle,"8");
+
+ // 5120 Feet
+ hoption10 = XtVaCreateManagedWidget(
+ (english_units) ? "5120ft" : "1561m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption10,XmNvalueChangedCallback,Height_toggle,"9");
+
+
+ // Gain
+ gain_box = XmCreateRadioBox(formphg,
+ "Configure_station Gain Radio Box",
+ al,
+ ac);
+
+ XtVaSetValues(gain_box,
+ XmNpacking, XmPACK_TIGHT,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget,height_box,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnumColumns,10,
+ NULL);
+
+
+ // 0 dB
+ goption1 = XtVaCreateManagedWidget("0dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption1,XmNvalueChangedCallback,Gain_toggle,"0");
+
+ // 1 dB
+ goption2 = XtVaCreateManagedWidget("1dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption2,XmNvalueChangedCallback,Gain_toggle,"1");
+
+ // 2 dB
+ goption3 = XtVaCreateManagedWidget("2dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption3,XmNvalueChangedCallback,Gain_toggle,"2");
+
+ // 3 dB
+ goption4 = XtVaCreateManagedWidget("3dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption4,XmNvalueChangedCallback,Gain_toggle,"3");
+
+ // 4 dB
+ goption5 = XtVaCreateManagedWidget("4dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption5,XmNvalueChangedCallback,Gain_toggle,"4");
+
+ // 5 dB
+ goption6 = XtVaCreateManagedWidget("5dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption6,XmNvalueChangedCallback,Gain_toggle,"5");
+
+ // 6 dB
+ goption7 = XtVaCreateManagedWidget("6dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption7,XmNvalueChangedCallback,Gain_toggle,"6");
+
+ // 7 dB
+ goption8 = XtVaCreateManagedWidget("7dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption8,XmNvalueChangedCallback,Gain_toggle,"7");
+
+ // 8 dB
+ goption9 = XtVaCreateManagedWidget("8dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption9,XmNvalueChangedCallback,Gain_toggle,"8");
+
+ // 9 dB
+ goption10 = XtVaCreateManagedWidget("9dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption10,XmNvalueChangedCallback,Gain_toggle,"9");
+
+
+ // Gain
+ directivity_box = XmCreateRadioBox(formphg,
+ "Configure_station Directivity Radio Box",
+ al,
+ ac);
+
+ XtVaSetValues(directivity_box,
+ XmNpacking, XmPACK_TIGHT,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget,gain_box,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnumColumns,10,
+ NULL);
+
+
+ // Omni-directional
+ doption1 = XtVaCreateManagedWidget(langcode("WPUPCFS016"), // Omni
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption1,XmNvalueChangedCallback,Directivity_toggle,"0");
+
+ // 45 NE
+ doption2 = XtVaCreateManagedWidget("45�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption2,XmNvalueChangedCallback,Directivity_toggle,"1");
+
+ // 90 E
+ doption3 = XtVaCreateManagedWidget("90�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption3,XmNvalueChangedCallback,Directivity_toggle,"2");
+
+ // 135 SE
+ doption4 = XtVaCreateManagedWidget("135�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption4,XmNvalueChangedCallback,Directivity_toggle,"3");
+
+ // 180 S
+ doption5 = XtVaCreateManagedWidget("180�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption5,XmNvalueChangedCallback,Directivity_toggle,"4");
+
+ // 225 SW
+ doption6 = XtVaCreateManagedWidget("225�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption6,XmNvalueChangedCallback,Directivity_toggle,"5");
+
+ // 270 W
+ doption7 = XtVaCreateManagedWidget("270�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption7,XmNvalueChangedCallback,Directivity_toggle,"6");
+
+ // 315 NW
+ doption8 = XtVaCreateManagedWidget("315�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption8,XmNvalueChangedCallback,Directivity_toggle,"7");
+
+ // 360 N
+ doption9 = XtVaCreateManagedWidget("360�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption9,XmNvalueChangedCallback,Directivity_toggle,"8");
+
+
+//-----------------------
+ comment = XtVaCreateManagedWidget(langcode("WPUPCFS017"),
+ xmLabelWidgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, framephg,
+ XmNtopOffset, 15,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ station_config_comment_data = XtVaCreateManagedWidget("Configure_station comment",
+ xmTextFieldWidgetClass,
+ cs_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 60,
+ XmNwidth, ((60*7)+2),
+ XmNmaxLength, MAX_COMMENT,
+ XmNtopOffset, 11,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, comment,
+ XmNleftOffset, 5,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, framephg,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+//Position Ambiguity Frame
+ frame2 = XtVaCreateManagedWidget("Configure_station frame2",
+ xmFrameWidgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, comment,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ posamb = XtVaCreateManagedWidget(langcode("WPUPCFS018"),
+ xmLabelWidgetClass,
+ frame2,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ /*set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ option_box = XmCreateRadioBox(frame2,
+ "Configure_station Option box",
+ al,
+ ac);
+
+ XtVaSetValues(option_box,
+ XmNnumColumns,5,
+ NULL);
+
+ posamb0 = XtVaCreateManagedWidget(langcode("WPUPCFS019"),
+ xmToggleButtonGadgetClass,
+ option_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(posamb0,XmNvalueChangedCallback,Configure_station_toggle,"0");
+
+ posamb1 = XtVaCreateManagedWidget(english_units?langcode("WPUPCFS020"):langcode("WPUPCFS024"),
+ xmToggleButtonGadgetClass,
+ option_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(posamb1,XmNvalueChangedCallback,Configure_station_toggle,"1");
+
+
+ posamb2 = XtVaCreateManagedWidget(english_units?langcode("WPUPCFS021"):langcode("WPUPCFS025"),
+ xmToggleButtonGadgetClass,
+ option_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(posamb2,XmNvalueChangedCallback,Configure_station_toggle,"2");
+
+ posamb3 = XtVaCreateManagedWidget(english_units?langcode("WPUPCFS022"):langcode("WPUPCFS026"),
+ xmToggleButtonGadgetClass,
+ option_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(posamb3,XmNvalueChangedCallback,Configure_station_toggle,"3");
+
+ posamb4 = XtVaCreateManagedWidget(english_units?langcode("WPUPCFS023"):langcode("WPUPCFS027"),
+ xmToggleButtonGadgetClass,
+ option_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(posamb4,XmNvalueChangedCallback,Configure_station_toggle,"4");
+
+ sep = XtVaCreateManagedWidget("Configure_station sep",
+ xmSeparatorGadgetClass,
+ cs_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame2,
+ XmNtopOffset, 14,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),
+ xmPushButtonGadgetClass,
+ cs_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Configure_station_change_data, configure_station_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Configure_station_destroy_shell, configure_station_dialog);
+
+ // fill in current data
+ XmTextFieldSetString(station_config_call_data,my_callsign);
+
+ substr(temp_data,my_lat,2);
+ XmTextFieldSetString(station_config_slat_data_deg,temp_data);
+ substr(temp_data,my_lat+2,6);
+ XmTextFieldSetString(station_config_slat_data_min,temp_data);
+ substr(temp_data,my_lat+8,1);
+ XmTextFieldSetString(station_config_slat_data_ns,temp_data);
+
+ substr(temp_data,my_long,3);
+ XmTextFieldSetString(station_config_slong_data_deg,temp_data);
+ substr(temp_data,my_long+3,6);
+ XmTextFieldSetString(station_config_slong_data_min,temp_data);
+ substr(temp_data,my_long+9,1);
+ XmTextFieldSetString(station_config_slong_data_ew,temp_data);
+
+ temp_data[0] = my_group;
+ temp_data[1] = '\0';
+ XmTextFieldSetString(station_config_group_data,temp_data);
+ XtAddCallback(station_config_group_data, XmNvalueChangedCallback, updateSymbolPictureCallback, configure_station_dialog);
+
+ temp_data[0] = my_symbol;
+ temp_data[1] = '\0';
+ XmTextFieldSetString(station_config_symbol_data,temp_data);
+ XtAddCallback(station_config_symbol_data, XmNvalueChangedCallback, updateSymbolPictureCallback, configure_station_dialog);
+
+ // update symbol picture
+ (void)updateSymbolPictureCallback((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
+
+
+ if (my_phg[0]=='P') {
+ switch (my_phg[3]) {
+ case '0':
+ XmToggleButtonGadgetSetState(poption1, TRUE, TRUE);
+ break;
+ case '1':
+ XmToggleButtonGadgetSetState(poption2, TRUE, TRUE);
+ break;
+ case '2':
+ XmToggleButtonGadgetSetState(poption3, TRUE, TRUE);
+ break;
+ case '3':
+ XmToggleButtonGadgetSetState(poption4, TRUE, TRUE);
+ break;
+ case '4':
+ XmToggleButtonGadgetSetState(poption5, TRUE, TRUE);
+ break;
+ case '5':
+ XmToggleButtonGadgetSetState(poption6, TRUE, TRUE);
+ break;
+ case '6':
+ XmToggleButtonGadgetSetState(poption7, TRUE, TRUE);
+ break;
+ case '7':
+ XmToggleButtonGadgetSetState(poption8, TRUE, TRUE);
+ break;
+ case '8':
+ XmToggleButtonGadgetSetState(poption9, TRUE, TRUE);
+ break;
+ case '9':
+ XmToggleButtonGadgetSetState(poption10, TRUE, TRUE);
+ break;
+ case 'x':
+ default:
+ XmToggleButtonGadgetSetState(poption0, TRUE, TRUE);
+ break;
+ }
+ switch (my_phg[4]) {
+ case '0':
+ XmToggleButtonGadgetSetState(hoption1, TRUE, TRUE);
+ break;
+ case '1':
+ XmToggleButtonGadgetSetState(hoption2, TRUE, TRUE);
+ break;
+ case '2':
+ XmToggleButtonGadgetSetState(hoption3, TRUE, TRUE);
+ break;
+ case '3':
+ XmToggleButtonGadgetSetState(hoption4, TRUE, TRUE);
+ break;
+ case '4':
+ XmToggleButtonGadgetSetState(hoption5, TRUE, TRUE);
+ break;
+ case '5':
+ XmToggleButtonGadgetSetState(hoption6, TRUE, TRUE);
+ break;
+ case '6':
+ XmToggleButtonGadgetSetState(hoption7, TRUE, TRUE);
+ break;
+ case '7':
+ XmToggleButtonGadgetSetState(hoption8, TRUE, TRUE);
+ break;
+ case '8':
+ XmToggleButtonGadgetSetState(hoption9, TRUE, TRUE);
+ break;
+ case '9':
+ XmToggleButtonGadgetSetState(hoption10, TRUE, TRUE);
+ break;
+ default:
+ break;
+ }
+ switch (my_phg[5]) {
+ case '0':
+ XmToggleButtonGadgetSetState(goption1, TRUE, TRUE);
+ break;
+ case '1':
+ XmToggleButtonGadgetSetState(goption2, TRUE, TRUE);
+ break;
+ case '2':
+ XmToggleButtonGadgetSetState(goption3, TRUE, TRUE);
+ break;
+ case '3':
+ XmToggleButtonGadgetSetState(goption4, TRUE, TRUE);
+ break;
+ case '4':
+ XmToggleButtonGadgetSetState(goption5, TRUE, TRUE);
+ break;
+ case '5':
+ XmToggleButtonGadgetSetState(goption6, TRUE, TRUE);
+ break;
+ case '6':
+ XmToggleButtonGadgetSetState(goption7, TRUE, TRUE);
+ break;
+ case '7':
+ XmToggleButtonGadgetSetState(goption8, TRUE, TRUE);
+ break;
+ case '8':
+ XmToggleButtonGadgetSetState(goption9, TRUE, TRUE);
+ break;
+ case '9':
+ XmToggleButtonGadgetSetState(goption10, TRUE, TRUE);
+ break;
+ default:
+ break;
+ }
+ switch (my_phg[6]) {
+ case '0':
+ XmToggleButtonGadgetSetState(doption1, TRUE, TRUE);
+ break;
+ case '1':
+ XmToggleButtonGadgetSetState(doption2, TRUE, TRUE);
+ break;
+ case '2':
+ XmToggleButtonGadgetSetState(doption3, TRUE, TRUE);
+ break;
+ case '3':
+ XmToggleButtonGadgetSetState(doption4, TRUE, TRUE);
+ break;
+ case '4':
+ XmToggleButtonGadgetSetState(doption5, TRUE, TRUE);
+ break;
+ case '5':
+ XmToggleButtonGadgetSetState(doption6, TRUE, TRUE);
+ break;
+ case '6':
+ XmToggleButtonGadgetSetState(doption7, TRUE, TRUE);
+ break;
+ case '7':
+ XmToggleButtonGadgetSetState(doption8, TRUE, TRUE);
+ break;
+ case '8':
+ XmToggleButtonGadgetSetState(doption9, TRUE, TRUE);
+ break;
+ default:
+ break;
+ }
+ } else { // PHG field disabled
+ XmToggleButtonGadgetSetState(poption0, TRUE, TRUE);
+ }
+
+
+ XmTextFieldSetString(station_config_comment_data,my_comment);
+
+
+ if(transmit_compressed_posit) {
+ // Compressed posits don't allow position ambiguity
+ XmToggleButtonSetState(compressed_posit_tx,TRUE,FALSE);
+ position_amb_chars = 0;
+ XtSetSensitive(posamb0,FALSE);
+ XtSetSensitive(posamb1,FALSE);
+ XtSetSensitive(posamb2,FALSE);
+ XtSetSensitive(posamb3,FALSE);
+ XtSetSensitive(posamb4,FALSE);
+ }
+ else { // Position ambiguity ok for this mode
+ XmToggleButtonSetState(compressed_posit_tx,FALSE,FALSE);
+
+ XtSetSensitive(posamb0,TRUE);
+ XtSetSensitive(posamb1,TRUE);
+ XtSetSensitive(posamb2,TRUE);
+ XtSetSensitive(posamb3,TRUE);
+ XtSetSensitive(posamb4,TRUE);
+ }
+
+ Configure_station_pos_amb = position_amb_chars;
+ switch (Configure_station_pos_amb) {
+ case(0):
+ XmToggleButtonSetState(posamb0,TRUE,FALSE);
+ break;
+
+ case(1):
+ XmToggleButtonSetState(posamb1,TRUE,FALSE);
+ break;
+
+ case(2):
+ XmToggleButtonSetState(posamb2,TRUE,FALSE);
+ break;
+
+ case(3):
+ XmToggleButtonSetState(posamb3,TRUE,FALSE);
+ break;
+
+ case(4):
+ XmToggleButtonSetState(posamb4,TRUE,FALSE);
+ break;
+
+ default:
+ XmToggleButtonSetState(posamb0,TRUE,FALSE);
+ break;
+ }
+
+ pos_dialog(configure_station_dialog);
+
+ delw = XmInternAtom(XtDisplay(configure_station_dialog),"WM_DELETE_WINDOW", FALSE);
+
+ XmAddWMProtocolCallback(configure_station_dialog, delw, Configure_station_destroy_shell, (XtPointer)configure_station_dialog);
+
+ XtManageChild(cs_form);
+ XtManageChild(cs_form1);
+ XtManageChild(option_box);
+ XtManageChild(power_box);
+ XtManageChild(height_box);
+ XtManageChild(gain_box);
+ XtManageChild(directivity_box);
+ XtManageChild(formphg);
+ XtManageChild(pane);
+
+ XtPopup(configure_station_dialog,XtGrabNone);
+
+ fix_dialog_size(configure_station_dialog);
+
+ // Move focus to the Close button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(configure_station_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(configure_station_dialog), XtWindow(configure_station_dialog));
+}
+
+
+
+
+
+// Borrowed from the libiberty library, a GPL'ed program.
+//
+void freeargv (char **vector) {
+ register char **scan;
+
+ if (vector != NULL) {
+ for (scan = vector; *scan != NULL; scan++) {
+ free (*scan);
+ }
+ free (vector);
+ }
+}
+
+
+
+
+
+// Borrowed from the libiberty library, a GPL'ed program.
+//
+char **dupargv (char **argv) {
+ int argc;
+ char **copy;
+
+ if (argv == NULL)
+ return NULL;
+
+ /* the vector */
+ for (argc = 0; argv[argc] != NULL; argc++);
+
+ copy = (char **) calloc ((argc + 1), sizeof (char *));
+
+ if (copy == NULL)
+ return NULL;
+
+ /* the strings */
+ for (argc = 0; argv[argc] != NULL; argc++) {
+ int len = strlen (argv[argc]);
+
+ copy[argc] = malloc (sizeof (char *) * (len + 1));
+ if (copy[argc] == NULL) {
+ freeargv (copy);
+ return NULL;
+ }
+ strcpy (copy[argc], argv[argc]);
+ }
+ copy[argc] = NULL;
+ return copy;
+}
+
+
+
+
+
+///////////////////////////////////////////// main /////////////////////////////////////////////
+
+
+// Third argument is now deprecated
+//int main(int argc, char *argv[], char *envp[]) {
+
+int main(int argc, char *argv[], char *envp[]) {
+ int ag, ag_error, trap_segfault, deselect_maps_on_startup;
+ uid_t user_id;
+ struct passwd *user_info;
+ static char lang_to_use_or[30];
+ char temp[100];
+ static char *Geometry = NULL;
+ static int xt = 0;
+ char temp_base_dir[MAX_VALUE];
+
+ // Define some overriding resources for the widgets.
+ // Look at files in /usr/X11/lib/X11/app-defaults for ideas.
+ String fallback_resources[] = {
+
+// "Mwm*iconImageForeground: #000000000000\n",
+
+ "*initialResourcesPersistent: False\n",
+
+// Default font if nothing else overrides it:
+ "*.fontList: fixed\n",
+
+ "*List.Translations: #override \n\
+ <Key>Return: Select(children)\n\
+ <Key>space: Select(children)\n",
+
+ "*List.baseTranslations: #override \n\
+ <Key>Return: Select(children)\n\
+ <Key>space: Select(children)\n",
+
+ "*XmTextField.translations: #override \
+ <Key>Return: activate()\n\
+ <Key>Enter: activate()\n",
+
+ "*.Text.Translations: #override\n\
+ Ctrl<Key>S: no-op(RingBell)\n\
+ Ctrl<Key>R: no-op(RingBell)\n\
+ <Key>space: next-page()\n\
+ <Key>F: next-page()\n\
+ Ctrl<Key>B: previous-page()\n\
+ <Key>B: previous-page()\n\
+ <Key>K: scroll-one-line-down()\n\
+ <Key>Y: scroll-one-line-down()\n\
+ <Key>J: scroll-one-line-up()\n\
+ <Key>E: scroll-one-line-up()\n\
+ <Key>Return: scroll-one-line-up()\n\
+ <Key>q: quit()\n",
+
+ "*.Text.baseTranslations: #override\n\
+ <Key>space: next-page()\n\
+ <Key>F: next-page()\n\
+ Ctrl<Key>B: previous-page()\n\
+ <Key>K: scroll-one-line-down()\n\
+ <Key>Y: scroll-one-line-down()\n\
+ <Key>J: scroll-one-line-up()\n\
+ <Key>E: scroll-one-line-up()\n\
+ <Key>Return: scroll-one-line-up()\n\
+ <Key>q: quit()\n",
+
+ "*.vertical.Translations: #override\n\
+ <Key>space: StartScroll(Forward) NotifyScroll(FullLength) EndScroll() \n\
+ <Key>Delete: StartScroll(Backward) NotifyScroll(FullLength) EndScroll() \n\
+ Ctrl<Key>Up: KbdScroll(up,50) EndScroll()\n\
+ Ctrl<Key>Down: KbdScroll(down,50) EndScroll()\n\
+ <Key>Up: KbdScroll(up,10) EndScroll()\n\
+ <Key>Down: KbdScroll(down,10) EndScroll()\n\
+ <Key>Page_Up: KbdScroll(up,90) EndScroll()\n\
+ <Key>Page_Down: KbdScroll(down,90) EndScroll()\n",
+
+ "*.horizontal.translations: #override \n\
+ Ctrl<Key>Left: KbdScroll(left,50) EndScroll()\n\
+ Ctrl<Key>Right: KbdScroll(right,50) EndScroll()\n\
+ <Key>Left: KbdScroll(left,10) EndScroll()\n\
+ <Key>Right: KbdScroll(right,10) EndScroll()\n",
+
+ "*.horizontal.accelerators: #override \n\
+ Ctrl<Key>Left: KbdScroll(left,50) EndScroll()\n\
+ Ctrl<Key>Right: KbdScroll(right,50) EndScroll()\n\
+ <Key>Left: KbdScroll(left,10) EndScroll()\n\
+ <Key>Right: KbdScroll(right,10) EndScroll()\n",
+
+ "*.vertical.accelerators: #override \n\
+ Ctrl<Key>Up: KbdScroll(up,50) EndScroll()\n\
+ Ctrl<Key>Down: KbdScroll(down,50) EndScroll()\n\
+ <Key>Up: KbdScroll(up,10) EndScroll()\n\
+ <Key>Down: KbdScroll(down,10) EndScroll()\n\
+ <Key>Page_Up: KbdScroll(up,90) EndScroll()\n\
+ <Key>Page_Down: KbdScroll(down,90) EndScroll()\n",
+
+ "*.nodeText.Translations: #override \n\
+ None<Key>b: beginning-of-file() \n\
+ <Key>Home: beginning-of-file() \n\
+ <Key>Delete: previous-page() \n\
+ <Key>Prior: previous-page() \n\
+ <Key>Next: next-page() \n\
+ <Key>space: next-page() \n\
+ None<Btn1Down>: select-end() info_click() \n",
+
+ "*.arg.translations: #override \n\
+ <Key>Return: confirm() \n\
+ Ctrl<Key>G: abort() \n",
+
+ "*.pane.text.translations: #override \n\
+ None<Key>q: MenuPopdown(help) \n\
+ None<Key>b: beginning-of-file() \n\
+ <Key>Home: beginning-of-file() \n\
+ <Key>Delete: previous-page() \n\
+ <Key>Prior: previous-page() \n\
+ <Key>Next: next-page() \n\
+ <Key>space: next-page() \n",
+
+ "*.dialog.value.translations: #override \n\
+ <Key>Return: confirm() \n\
+ Ctrl<Key>G: abort() \n\
+ <Key>Tab: Complete()\n",
+
+ "*.dialog.value.baseTranslations: #override \n\
+ <Key>Return: confirm() \n\
+ Ctrl<Key>G: abort() \n",
+
+ "*.baseTranslations: #override \n\
+ Ctrl<Key>q: Quit()\n\
+ Ctrl<Key>c: Quit()\n\
+ <Key>Return: Accept()\n",
+
+ "*Translations: #override \n\
+ <Key>q: Quit()\n\
+ <Key>c: Quit()\n\
+ Ctrl <Key>n: Next()\n\
+ Ctrl <Key>p: Prev()\n",
+
+ "*minWidth: 200\n",
+
+ "*minHeight: 100\n",
+
+ NULL
+ };
+
+
+#ifndef optarg
+ extern char *optarg;
+#endif // optarg
+
+#ifdef USING_LIBGC
+ GC_find_leak = 1;
+ GC_INIT();
+#endif // USING_LIBGC
+
+
+ // Make copies of argc/argv/envp so that we can start other
+ // processes and know the environment we were started with.
+ //
+ my_argc = argc;
+// my_argv = argv;
+ my_argv = dupargv(argv);
+ my_envp = (void *)&envp[0];
+
+
+
+ euid = geteuid();
+ egid = getegid();
+
+ DISABLE_SETUID_PRIVILEGE;
+
+ program_start_time = sec_now(); // For use by "Display Uptime"
+
+ (void)setlocale(LC_NUMERIC, "C");
+ (void)setlocale(LC_CTYPE, "C");
+
+#ifdef HAVE_LIBCURL
+ curl_global_init(CURL_GLOBAL_ALL);
+#endif
+
+
+#ifdef HAVE_GRAPHICSMAGICK
+ InitializeMagick(*argv);
+#else // HAVE_GRAPHICSMAGICK
+ #ifdef HAVE_IMAGEMAGICK
+ #if (MagickLibVersion < 0x0538)
+ MagickIncarnate(*argv);
+ #else // MagickLibVersion < 0x0538
+ InitializeMagick(*argv);
+ #endif // MagickLibVersion < 0x0538
+ #endif // HAVE_IMAGEMAGICK
+#endif //HAVE_GRAPHICSMAGICK
+
+
+ /* check fhs directories ?*/
+
+ /* setup values */
+ redo_list = FALSE; // init lists
+
+ xa_config_dir[0]='\0';
+
+ delay_time = 0;
+ last_weather_cycle = sec_now();
+ redraw_on_new_packet_data = 0;
+ next_file_read = sec_now(); // init file replay timing
+ redraw_on_new_data = 0;
+ display_up = 0;
+ display_up_first = 0;
+ max_transmit_time = (time_t)900l;
+ sec_next_gps = 0l;
+ gprmc_save_string[0] = '\0';
+ gpgga_save_string[0] = '\0';
+ sec_next_raw_wx = 0l;
+ auto_reply = 0;
+ satellite_ack_mode = 0;
+ last_time = 0l;
+ next_time = (time_t)120l;
+ net_last_time = 0l;
+ net_next_time = (time_t)120l;
+ posit_last_time = 0l;
+ posit_next_time = 0l;
+ wait_to_redraw=1;
+
+ last_popup_x = 0;
+ last_popup_y = 0;
+ trap_segfault = 0; // Default is to dump core
+ deselect_maps_on_startup = 0;
+ debug_level = 0;
+ install_colormap = 0;
+ last_sound_pid = 0;
+
+ my_last_course = 0;
+ my_last_speed = 0;
+ my_last_altitude = 0l;
+ my_last_altitude_time = 0l;
+
+ wx_station_type[0] = '\0';
+ last_alert_redraw = 0;
+ igate_msgs_tx = 0;
+ last_statusline = 0; // inactive statusline
+
+ last_object[0] = '\0'; // initialize object dialog
+ last_obj_grp = '\\';
+ last_obj_sym = '!';
+
+ clear_rain_data(); // init weather data
+ clear_local_wx_data();
+
+ next_redraw = sec_now()+60; // init redraw timing
+ last_redraw = sec_now();
+
+ lang_to_use_or[0] = '\0';
+ ag_error=0;
+
+ // Reset the gps variables.
+ xastir_snprintf(gps_sats,
+ sizeof(gps_sats),
+ "00");
+ gps_valid = 0;
+
+ memset(&appshell, 0, sizeof(appshell));
+
+ // Here we had to add "g:" in order to allow -geometry to be
+ // used and x: to allow xt arguments, which is actually parsed out
+ // by the XtIntrinsics code, not directly in Xastir code.
+ //
+ while ((ag = getopt(argc, argv, "c:f:v:l:g:x:012346789timp")) != EOF) {
+
+ switch (ag) {
+
+ case 'c':
+ if (optarg) {
+ xastir_snprintf(xa_config_dir,sizeof(xa_config_dir),"%s", optarg);
+ fprintf(stderr,"Using config dir %s\n",xa_config_dir);
+ }
+ break;
+
+ case 'f': // Track callsign
+ if (optarg) {
+ xastir_snprintf(temp_tracking_station_call,
+ sizeof(temp_tracking_station_call),
+ "%s",
+ optarg);
+ fprintf(stderr,
+ "Tracking callsign %s\n",
+ temp_tracking_station_call);
+ (void)remove_leading_spaces(temp_tracking_station_call);
+ (void)remove_trailing_spaces(temp_tracking_station_call);
+ (void)remove_trailing_dash_zero(temp_tracking_station_call);
+ (void)to_upper(temp_tracking_station_call);
+ }
+ break;
+
+ case 't':
+ fprintf(stderr,"Internal SIGSEGV handler enabled\n");
+ trap_segfault = 1;
+ break;
+
+ case 'v':
+ fprintf(stderr,"debug");
+ if (optarg) {
+ debug_level = atoi(optarg);
+ fprintf(stderr," level %d", debug_level);
+ }
+ fprintf(stderr,"\n");
+ break;
+
+ case 'l':
+ fprintf(stderr,"Language is");
+ if (optarg) {
+ lang_to_use_or[0] = '\0';
+ if (strncasecmp(optarg,"ENGLISH", 7) == 0) {
+ xastir_snprintf(lang_to_use_or, sizeof(lang_to_use_or), "English");
+ } else if (strncasecmp(optarg,"DUTCH", 5) == 0) {
+ xastir_snprintf(lang_to_use_or, sizeof(lang_to_use_or), "Dutch");
+ } else if (strncasecmp(optarg,"FRENCH", 6) == 0) {
+ xastir_snprintf(lang_to_use_or, sizeof(lang_to_use_or), "French");
+ } else if (strncasecmp(optarg,"GERMAN", 6) == 0) {
+ xastir_snprintf(lang_to_use_or, sizeof(lang_to_use_or), "German");
+ } else if (strncasecmp(optarg,"SPANISH", 7) == 0) {
+ xastir_snprintf(lang_to_use_or, sizeof(lang_to_use_or), "Spanish");
+ } else if (strncasecmp(optarg,"ITALIAN", 7) == 0) {
+ xastir_snprintf(lang_to_use_or, sizeof(lang_to_use_or), "Italian");
+ } else if (strncasecmp(optarg,"PORTUGUESE",10) == 0) {
+ xastir_snprintf(lang_to_use_or, sizeof(lang_to_use_or), "Portuguese");
+ } else if (strncasecmp(optarg,"ELMERFUDD",10) == 0) {
+ xastir_snprintf(lang_to_use_or, sizeof(lang_to_use_or), "ElmerFudd");
+ } else if (strncasecmp(optarg,"MUPPETSCHEF",10) == 0) {
+ xastir_snprintf(lang_to_use_or, sizeof(lang_to_use_or), "MuppetsChef");
+ } else if (strncasecmp(optarg,"OLDEENGLISH",10) == 0) {
+ xastir_snprintf(lang_to_use_or, sizeof(lang_to_use_or), "OldeEnglish");
+ } else if (strncasecmp(optarg,"PIGLATIN",10) == 0) {
+ xastir_snprintf(lang_to_use_or, sizeof(lang_to_use_or), "PigLatin");
+ } else if (strncasecmp(optarg,"PIRATEENGLISH",10) == 0) {
+ xastir_snprintf(lang_to_use_or, sizeof(lang_to_use_or), "PirateEnglish");
+ } else {
+ ag_error++;
+ fprintf(stderr," INVALID");
+ }
+ if (!ag_error)
+ fprintf(stderr," %s", lang_to_use_or);
+ }
+ fprintf(stderr,"\n");
+ break;
+
+ case 'i':
+ fprintf(stderr,"Install Colormap\n");
+ install_colormap = (int)TRUE;
+ break;
+
+ case 'm':
+ fprintf(stderr,"De-select Maps\n");
+ deselect_maps_on_startup = (int)TRUE;
+ break;
+
+ case 'g': // -geometry
+ Geometry = argv[optind++];
+ break;
+
+ case 'x': // -xtsessionID
+ optind++; // swallow argument, let XtIntrinsics deal with it.
+ xt = 1;
+ break;
+
+ case 'p': // Disable popups
+ disable_all_popups = 1;
+ pop_up_new_bulletins = 0;
+ warn_about_mouse_modifiers = 0;
+ break;
+
+ default:
+ ag_error++;
+ break;
+ }
+ }
+
+
+ if (ag_error){
+ fprintf(stderr,"\nXastir Command line Options\n\n");
+ fprintf(stderr,"-c /path/dir Xastir config dir\n");
+ fprintf(stderr,"-f callsign Track callsign\n");
+ fprintf(stderr,"-i Install private Colormap\n");
+ fprintf(stderr,"-geometry WxH+X+Y Set Window Geometry\n");
+ fprintf(stderr,"-l Dutch Set the language to Dutch\n");
+ fprintf(stderr,"-l English Set the language to English\n");
+ fprintf(stderr,"-l French Set the language to French\n");
+ fprintf(stderr,"-l German Set the language to German\n");
+ fprintf(stderr,"-l Italian Set the language to Italian\n");
+ fprintf(stderr,"-l Portuguese Set the language to Portuguese\n");
+ fprintf(stderr,"-l Spanish Set the language to Spanish\n");
+ fprintf(stderr,"-l ElmerFudd Set the language to ElmerFudd\n");
+ fprintf(stderr,"-l MuppetsChef Set the language to MuppetsChef\n");
+ fprintf(stderr,"-l OldeEnglish Set the language to OldeEnglish\n");
+ fprintf(stderr,"-l PigLatin Set the language to PigLatin\n");
+ fprintf(stderr,"-l PirateEnglish Set the language to PirateEnglish\n");
+ fprintf(stderr,"-m Deselect Maps\n");
+ fprintf(stderr,"-p Disable popups\n");
+ fprintf(stderr,"-t Internal SIGSEGV handler enabled\n");
+ fprintf(stderr,"-v level Set the debug level\n\n");
+ fprintf(stderr,"\n");
+ exit(0); // Exiting after dumping out command-line options
+ }
+
+
+ // If we don't make this call, we can't access Xt or
+ // Xlib calls from multiple threads at the same time.
+ // Note that Motif from the OSF (including OpenMotif)
+ // still can't handle multiple threads talking to it at
+ // the same time. See:
+ // http://www.faqs.org/faqs/x-faq/part7/section-46.html
+ // We'll probably have to add in a global mutex lock in
+ // order to keep from accessing the widget set from more
+ // than one thread.
+ //
+ XInitThreads();
+
+
+ // Set language attribs. Must be called prior to
+ // XtVaOpenApplication().
+ (void)XtSetLanguageProc((XtAppContext) NULL,
+ XtSetLanguageProc(NULL, NULL, NULL),
+ (XtPointer) NULL );
+
+
+ if (Geometry) {
+ //
+ // Really we should be merging with the RDB database as well
+ // and then parsing the final geometry (Xlib Programming
+ // Manual section 14.4.3 and 14.4.4).
+ //
+ geometry_flags = XParseGeometry(Geometry,
+ &geometry_x,
+ &geometry_y,
+ &geometry_width,
+ &geometry_height);
+
+/*
+ if ((WidthValue|HeightValue) & geometry_flags) {
+ fprintf(stderr,"Found width/height\n");
+ }
+ if (XValue & geometry_flags) {
+ fprintf(stderr,"Found X-offset\n");
+ }
+ if (YValue & geometry_flags) {
+ fprintf(stderr,"Found Y-offset\n");
+ }
+ fprintf(stderr,
+ "appshell: Width:%4d Height:%4d X-offset:%4d Y-offset:%4d\n",
+ (int)geometry_width,
+ (int)geometry_height,
+ (int)geometry_x,
+ (int)geometry_y);
+*/
+ }
+
+
+ /* get User info */
+ user_id = getuid();
+ user_info = getpwuid(user_id);
+ xastir_snprintf(user_dir,
+ sizeof(user_dir),
+ "%s",
+ user_info->pw_dir);
+
+ /*
+ fprintf(stderr,"User %s, Dir %s\n",user_info->pw_name,user_dir);
+ fprintf(stderr,"User dir %s\n",get_user_base_dir(""));
+ fprintf(stderr,"Data dir %s\n",get_data_base_dir(""));
+ */
+
+ /* check user directories */
+ if (filethere(get_user_base_dir("", temp_base_dir, sizeof(temp_base_dir))) != 1) {
+ fprintf(stderr,"Making user dir\n");
+ if (mkdir(get_user_base_dir("", temp_base_dir, sizeof(temp_base_dir)),S_IRWXU) !=0){
+ fprintf(stderr,"Fatal error making user dir '%s':\n\t%s \n",
+ get_user_base_dir("", temp_base_dir, sizeof(temp_base_dir)), strerror(errno) );
+
+ // Creature to feep later?
+ // needs <libgen.h>
+ // fprintf(stderr,"Check to see if '%s' exists \n",
+ // dirname(get_user_base_dir("")) );
+
+ exit(errno);
+ }
+
+ }
+
+ if (filethere(get_user_base_dir("config", temp_base_dir, sizeof(temp_base_dir))) != 1) {
+ fprintf(stderr,"Making user config dir\n");
+ if (mkdir(get_user_base_dir("config", temp_base_dir, sizeof(temp_base_dir)),S_IRWXU) !=0){
+ fprintf(stderr,"Fatal error making user dir '%s':\n\t%s \n",
+ get_user_base_dir("config", temp_base_dir, sizeof(temp_base_dir)), strerror(errno) );
+ exit(errno);
+ }
+ }
+
+ if (filethere(get_user_base_dir("data", temp_base_dir, sizeof(temp_base_dir))) != 1) {
+ fprintf(stderr,"Making user data dir\n");
+ if (mkdir(get_user_base_dir("data", temp_base_dir, sizeof(temp_base_dir)),S_IRWXU) !=0){
+ fprintf(stderr,"Fatal error making user dir '%s':\n\t%s \n",
+ get_user_base_dir("data", temp_base_dir, sizeof(temp_base_dir)), strerror(errno) );
+ exit(errno);
+ }
+ }
+
+ if (filethere(get_user_base_dir("logs", temp_base_dir, sizeof(temp_base_dir))) != 1) {
+ fprintf(stderr,"Making user log dir\n");
+ if (mkdir(get_user_base_dir("logs", temp_base_dir, sizeof(temp_base_dir)),S_IRWXU) !=0 ){
+ fprintf(stderr,"Fatal error making user dir '%s':\n\t%s \n",
+ get_user_base_dir("logs", temp_base_dir, sizeof(temp_base_dir)), strerror(errno) );
+ exit(errno);
+ }
+ }
+
+ if (filethere(get_user_base_dir("tracklogs", temp_base_dir, sizeof(temp_base_dir))) != 1) {
+ fprintf(stderr,"Making user tracklogs dir\n");
+ if (mkdir(get_user_base_dir("tracklogs", temp_base_dir, sizeof(temp_base_dir)),S_IRWXU) !=0 ){
+ fprintf(stderr,"Fatal error making user dir '%s':\n\t%s \n",
+ get_user_base_dir("tracklogs", temp_base_dir, sizeof(temp_base_dir)), strerror(errno) );
+ exit(errno);
+ }
+ }
+
+ if (filethere(get_user_base_dir("tmp", temp_base_dir, sizeof(temp_base_dir))) != 1) {
+ fprintf(stderr,"Making user tmp dir\n");
+ if (mkdir(get_user_base_dir("tmp", temp_base_dir, sizeof(temp_base_dir)),S_IRWXU) !=0 ){
+ fprintf(stderr,"Fatal error making user dir '%s':\n\t%s \n",
+ get_user_base_dir("tmp", temp_base_dir, sizeof(temp_base_dir)), strerror(errno) );
+ exit(errno);
+ }
+ }
+
+ if (filethere(get_user_base_dir("gps", temp_base_dir, sizeof(temp_base_dir))) != 1) {
+ fprintf(stderr,"Making user gps dir\n");
+ if ( mkdir(get_user_base_dir("gps", temp_base_dir, sizeof(temp_base_dir)),S_IRWXU) !=0 ){
+ fprintf(stderr,"Fatal error making user dir '%s':\n\t%s \n",
+ get_user_base_dir("gps", temp_base_dir, sizeof(temp_base_dir)), strerror(errno) );
+ exit(errno);
+ }
+ }
+
+ if (filethere(get_user_base_dir("map_cache", temp_base_dir, sizeof(temp_base_dir))) != 1) {
+ fprintf(stderr,"Making map_cache dir\n");
+ if (mkdir(get_user_base_dir("map_cache", temp_base_dir, sizeof(temp_base_dir)),S_IRWXU) !=0 ){
+ fprintf(stderr,"Fatal error making user dir '%s':\n\t%s \n",
+ get_user_base_dir("map_cache", temp_base_dir, sizeof(temp_base_dir)), strerror(errno) );
+ exit(errno);
+ }
+ }
+
+
+ /* done checking user dirs */
+
+
+
+
+
+#ifdef USE_PID_FILE_CHECK
+
+ if (pid_file_check(xt) !=0 ){
+ fprintf(stderr,"pid_file_check failed:\t%s \n", strerror(errno) );
+ exit(errno);
+ }
+
+#endif
+
+
+
+ // initialize interfaces
+ init_critical_section(&port_data_lock); // Protects the port_data[] array of structs
+ init_critical_section(&output_data_lock); // Protects interface.c:channel_data() function only
+ init_critical_section(&data_lock); // Protects global incoming_data_queue
+ init_critical_section(&connect_lock); // Protects port_data[].thread_status and port_data[].connect_status
+// We should probably protect redraw_on_new_data, alert_redraw_on_update, and
+// redraw_on_new_packet_data variables as well?
+// Also need to protect dialogs.
+
+#ifdef HAVE_DB
+ connections_initialized = 0;
+#endif // HAVE_DB
+
+#ifdef USE_MAP_CACHE
+ map_cache_init();
+#endif // USE_MAP_CACHE
+
+ (void)bulletin_gui_init();
+ (void)db_init();
+ (void)draw_symbols_init();
+ (void)interface_gui_init();
+ (void)list_gui_init();
+ (void)locate_gui_init();
+ (void)geocoder_gui_init();
+ (void)location_gui_init();
+ (void)maps_init();
+ (void)map_gdal_init();
+ (void)messages_gui_init();
+ (void)popup_gui_init();
+ (void)track_gui_init();
+ (void)view_message_gui_init();
+ (void)wx_gui_init();
+ (void)igate_init();
+
+ clear_all_port_data(); // clear interface port data
+
+ (void) signal(SIGINT,quit); // set signal on stop
+ (void) signal(SIGQUIT,quit);
+ (void) signal(SIGTERM,quit);
+
+
+ // Make sure that we reset to SIG_DFL handler any time we spawn
+ // a child process. This is so the child process doesn't call
+ // restart() as well. Only the main process needs to call
+ // restart() on receiving a SIGHUP. We can do this via the
+ // following call:
+ //
+ // (void)signal(SIGHUP,SIG_DFL);
+ //
+ (void) signal(SIGHUP,restart); // Shut down/restart if SIGHUP received
+
+
+#ifndef OLD_PTHREADS
+ (void) signal(SIGUSR1,usr1sig); // take a snapshot on demand
+ (void) signal(SIGUSR2,usr2sig); // transmit now on demand
+#else // OLD_PTHREADS
+# warning ***** Old kernel detected: Disabling SIGUSR1 handler (snapshot on demand) *****
+#endif // OLD_PTHREADS
+
+#ifdef HAVE_SIGIGNORE
+ (void) sigignore(SIGPIPE);
+#else // HAVE_SIGIGNORE
+ (void) signal(SIGPIPE,SIG_IGN); // set sigpipe signal to ignore
+#endif // HAVE_SIGIGNORE
+
+ if (trap_segfault)
+ (void) signal(SIGSEGV,segfault);// set segfault signal to check
+
+
+ // Load program parameters or set to default values
+ load_data_or_default();
+
+
+ // Start the listening socket. If we fork it early we end up
+ // with much smaller process memory allocated for it and all its
+ // children. The server will authenticate each client that
+ // connects. We'll share all of our data with the server, which
+ // will send it to all connected/authenticated clients.
+ // Anything transmitted by the clients will come back to us and
+ // standard igating rules should apply from there.
+ if (enable_server_port) {
+ tcp_server_pid = Fork_TCP_server(my_argc, my_argv, my_envp);
+ udp_server_pid = Fork_UDP_server(my_argc, my_argv, my_envp);
+ }
+
+
+ if (deselect_maps_on_startup) {
+ unlink( get_user_base_dir(SELECTED_MAP_DATA, temp_base_dir, sizeof(temp_base_dir)) ); // Remove the selected_maps.sys file
+ }
+
+ update_units(); // set up conversion factors and strings
+
+ /* do language links */
+ if (strlen(lang_to_use_or) > 0)
+ xastir_snprintf(lang_to_use,
+ sizeof(lang_to_use),
+ "%s",
+ lang_to_use_or);
+
+ xastir_snprintf(temp, sizeof(temp), "help/help-%s.dat", lang_to_use);
+ (void)unlink(get_user_base_dir("config/help.dat", temp_base_dir, sizeof(temp_base_dir)));
+
+ // Note that this symlink will probably not fail. It's easy to
+ // create a symlink that points to nowhere.
+ if (symlink(get_data_base_dir(temp),get_user_base_dir("config/help.dat", temp_base_dir, sizeof(temp_base_dir))) == -1) {
+ fprintf(stderr,"Error creating database link for help.dat\n");
+ fprintf(stderr,
+ "Couldn't create symlink: %s -> %s\n",
+ get_user_base_dir("config/help.dat", temp_base_dir, sizeof(temp_base_dir)),
+ get_data_base_dir(temp));
+ exit(0); // Exiting 'cuz online help won't work.
+ }
+
+ xastir_snprintf(temp, sizeof(temp), "config/language-%s.sys", lang_to_use);
+ (void)unlink(get_user_base_dir("config/language.sys", temp_base_dir, sizeof(temp_base_dir)));
+
+ // Note that this symlink will probably not fail. It's easy to
+ // create a symlink that points to nowhere.
+ if (symlink(get_data_base_dir(temp),get_user_base_dir("config/language.sys", temp_base_dir, sizeof(temp_base_dir))) == -1) {
+ fprintf(stderr,"Error creating database link for language.sys\n");
+ fprintf(stderr,
+ "Couldn't create symlink: %s -> %s\n",
+ get_user_base_dir("config/language.sys", temp_base_dir, sizeof(temp_base_dir)),
+ get_data_base_dir(temp));
+ exit(0); // We can't set our language, so exit.
+ }
+
+ /* (NEW) set help file area */
+ xastir_snprintf(HELP_FILE,
+ sizeof(HELP_FILE),
+ "%s",
+ "config/help.dat");
+
+#ifdef HAVE_FESTIVAL
+ /* Initialize the festival speech synthesis port */
+ if (SayTextInit())
+ {
+ fprintf(stderr,"Error connecting to Festival speech server.\n");
+ //exit(0); // Not worth exiting just because we can't talk!
+ }
+#endif // HAVE_FESTIVAL
+
+
+ /* populate the predefined object (SAR/Public service) struct */
+ Populate_predefined_objects(predefinedObjects);
+
+ if (load_color_file()) {
+ if (load_language_file(get_user_base_dir("config/language.sys", temp_base_dir, sizeof(temp_base_dir)))) {
+ init_device_names(); // set interface names
+ clear_message_windows();
+ clear_popup_message_windows();
+ init_station_data(); // init station storage
+ init_message_data(); // init messages
+ reset_outgoing_messages();
+
+
+ // This convenience function calls (in turn):
+ // XtToolkitInitialize()
+ // XtCreateApplicationContext()
+ // XtOpenDisplay()
+ // XtAppCreateShell().
+ //
+ appshell = XtVaOpenApplication(
+ &app_context,
+ "Xastir",
+ NULL,
+ 0,
+ &argc,
+ argv,
+ fallback_resources,
+ sessionShellWidgetClass,
+ XmNmappedWhenManaged, FALSE,
+ NULL);
+
+ display = XtDisplay(appshell);
+
+ if (!display) {
+ fprintf(stderr,"%s: can't open display, exiting...\n", argv[0]);
+ exit(-1); // Must exit here as we can't get our display.
+ }
+
+ XtSetValues(XmGetXmDisplay(display), NULL, 0);
+
+ // DK7IN: now scanf and printf use "," instead of "."
+ // that leads to several problems in the initialization.
+ //
+ // DK7IN: inserted next line here for avoiding scanf
+ // errors during init!
+ //
+// (void)setlocale(LC_NUMERIC, "C"); // DK7IN: It's now ok
+ (void)setlocale(LC_CTYPE, "C"); // K4INT: Make sure strings work OK.
+
+
+ setup_visual_info(display, DefaultScreen(display));
+
+
+ // Get colormap (N7TAP: do we need this if the screen
+ // visual is TRUE or DIRECT?
+ //
+ cmap = DefaultColormapOfScreen(XtScreen(appshell));
+ if (visual_type == NOT_TRUE_NOR_DIRECT) {
+ if (install_colormap) {
+ cmap = XCopyColormapAndFree(display, cmap);
+ XtVaSetValues(appshell, XmNcolormap, cmap, NULL);
+ }
+ }
+
+
+//fprintf(stderr,"***index_restore_from_file\n");
+
+ // Read the current map index file into the index linked list
+ index_restore_from_file();
+
+
+ // Reload tactical calls. This implements persistence
+ // for this type.
+ reload_tactical_calls();
+
+
+//fprintf(stderr,"***create_appshell\n");
+
+
+ // This call fills in the top-level window and then
+ // calls XtRealize.
+ //
+ create_appshell(display, argv[0], argc, argv);
+
+
+ // reset language attribs for numeric, program needs
+ // decimal in US for all data!
+ (void)setlocale(LC_NUMERIC, "C");
+ (void)setlocale(LC_CTYPE, "C");
+ // DK7IN: now scanf and printf work as wanted...
+
+
+//fprintf(stderr,"***check_fcc_data\n");
+
+ /* check for ham databases */
+ (void)check_rac_data();
+ (void)check_fcc_data();
+
+
+ // Find the extents of every map we have. Use the smart
+ // timestamp-checking reindexing (quicker).
+ if ( index_maps_on_startup ) {
+ map_indexer(0);
+ }
+
+
+ // Check whether we're running Xastir for the first time.
+ // If so, my_callsign will be "NOCALL". In this case
+ // write "worldhi.map" into ~/.xastir/config/selected_maps.sys
+ // so that we get the default map on startup. Also
+ // request to bring up the Configure->Station dialog in
+ // this case.
+ //
+ if (strncasecmp(my_callsign,"NOCALL",6) == 0) {
+ FILE *ff;
+
+// fprintf(stderr,"***** First time run *****\n");
+
+ // Set the flag
+ first_time_run = 1;
+
+ // Write the default map into the selected map file
+ ff = fopen( get_user_base_dir(SELECTED_MAP_DATA, temp_base_dir, sizeof(temp_base_dir)), "a");
+ if (ff != NULL) {
+ fprintf(ff,"worldhi.map\n");
+ (void)fclose(ff);
+ }
+ }
+
+
+ // Mark the "selected" field in the in-memory map index
+ // to correspond to the selected_maps.sys file.
+ map_chooser_init();
+
+
+ // Warn the user if altnet is enabled on startup. This
+ // is so that the people who are button pushers/knob turners
+ // will know what's wrong when they don't see stations on their
+ // screen anymore.
+ //
+ if (altnet) {
+ // "Warning"
+ // "Altnet is enabled (File->Configure->Defaults dialog)");
+ popup_message_always( langcode("POPEM00035"),
+ langcode("POPEM00051") );
+ }
+
+
+ // Start UpdateTime. It schedules itself to be run
+ // again each time. This is also the process that
+ // starts up the interfaces.
+ UpdateTime( (XtPointer) da , (XtIntervalId) NULL );
+
+
+ // Update the logging indicator
+ Set_Log_Indicator();
+
+
+ XtAppMainLoop(app_context);
+
+
+ } else
+ fprintf(stderr,"Error in language file! Exiting...\n");
+
+ } else
+ fprintf(stderr,"Error in Color file! Exiting...\n");
+
+ quit(0);
+ return 0;
+}
+
+
diff --git a/src/main.h b/src/main.h
new file mode 100644
index 0000000..f9e085a
--- /dev/null
+++ b/src/main.h
@@ -0,0 +1,463 @@
+/*
+ * $Id: main.h,v 1.110 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifndef XASTIR_MAIN_H
+#define XASTIR_MAIN_H
+
+#include <X11/Intrinsic.h>
+
+// For mutex debugging with Linux threads only
+#ifdef __linux__
+ #define MUTEX_DEBUG 1
+#endif // __linux__
+
+
+// This gets defined if pthreads implementation uses SIGUSR1/SIGUSR2
+// signals. This disables our SIGUSR1 handler which disallows
+// creating snapshots on receipt of that signal. Old kernels (2.0
+// and early 2.1) had only 32 signals available so only USR1/USR2
+// were available for LinuxThreads use. Newer kernels have more
+// signals available, making USR1/USR2 available to programs again.
+// _NSIG is defined in /usr/include/bits/signum.h
+//
+#ifdef __linux__
+# ifdef _NSIG
+# if (_NSIG <= 32)
+# define OLD_PTHREADS
+//# warning ***** OLD_PTHREADS DETECTED *****
+# else
+//# warning ***** NEW_PTHREADS DETECTED *****
+# endif // if (_NSIG...)
+# endif // _NSIG
+#endif // __linux__
+
+
+// To enable the "Transmit Raw WX data" button in
+// Configure->Defaults dialog. Warning: If you enable this, enable
+// the button in Configure->Defaults, and are running a weather
+// station that puts out raw data that is NOT allowed by the APRS
+// spec, you'll be putting out garbage and trashing the channel.
+//
+//#define TRANSMIT_RAW_WX
+
+// To use predefined object configuration files from within the
+// user's base directory e.g. ~/.xastir/config/predefined_SAR.sys
+// rather than from the main base directory, enable this definition.
+//#define OBJECT_DEF_FILE_USER_BASE
+
+extern int enable_server_port;
+
+
+extern char altnet_call[MAX_CALLSIGN+1];
+extern int altnet;
+extern Widget iface_da;
+extern FILE *read_file_ptr;
+extern int interrupt_drawing_now;
+
+
+#define VERSIONFRM (!altnet?XASTIR_TOCALL:altnet_call) /* Packet version info */
+
+
+#ifdef __LCLINT__
+#define PACKAGE "xastir"
+#define VERSION "lclint"
+#define VERSIONTXT "xastir lclint debug version"
+#else // __LCLINT__
+#define VERSIONTXT PACKAGE " " VERSION
+#endif // __LCLINT__
+
+
+#define VERSIONLABEL VERSIONTXT
+
+// NOTE: This is out of date and not used anymore anyway.
+#define VERSIONMESSAGE "XASTIR Version: " VERSION "\n\nAmateur Station Tracking and Information Reporting\nby Frank Giannandrea, KC2GJS was KC0DGE\n Code added by:\n Richard Hagemeyer - VE3UNW, Curt Mills - WE7U,\n Mike Sims - KA9KIM, Gerald Stueve - K4INT was KE4NFJ,\n Mark Grennan - KD5AMB, Henk de Groot - PE1DNN,\n Jim Sevilla - KD6VPE, Jose R. Marte A. - HI8GN,\n Michael G. Petry - N3NYN, Lloyd Miller - VE6LFM,\n Alessandro Frigeri - IK0YUP,\n Chuck Byam - KG4I [...]
+
+// NOTE: This is out of date and not used anymore anyway.
+#define ABOUTGNUL "XASTIR, Copyright (C) 1999, 2000 Frank Giannandrea\nXASTIR comes with ABSOLUTELY NO WARRANTY;\nThis is free software, and you are welcome\nto redistribute it under certain conditions;\nsee the GNU LICENSE for details.\n"
+
+#define MAX_PHG 8
+#define MAX_COMMENT 80
+
+
+
+//////////////////////////////////////////////////////////////////////
+// These globals and prototypes are from:
+// http://lightconsulting.com/~thalakan/process-title-notes.html
+// They seems to work fine on Linux, but they only change the "ps"
+// listings, not the top listings. I don't know why yet.
+
+/* Globals */
+//extern char **Argv = ((void *)0);
+//extern char *__progname, *__progname_full;
+//extern char *LastArgv = ((void *)0);
+
+/* Prototypes */
+extern void set_proc_title(char *fmt,...);
+extern void init_set_proc_title(int argc, char *argv[], char *envp[]);
+
+// New stuff defined by Xastir project:
+extern int my_argc;
+extern char **my_argv;
+extern char **my_envp;
+//////////////////////////////////////////////////////////////////////
+
+extern int input_x;
+extern int input_y;
+
+#define MAX_RELAY_DIGIPEATER_CALLS 50
+extern char relay_digipeater_calls[10*MAX_RELAY_DIGIPEATER_CALLS];
+extern int skip_dupe_checking;
+extern int serial_char_pacing; // Inter-character delay in ms.
+extern int disable_all_maps;
+extern int re_sort_maps;
+extern Widget trackme_button;
+extern Widget CAD_close_polygon_menu_item;
+extern int debug_level;
+extern int my_position_valid;
+extern int using_gps_position;
+extern int transmit_now;
+extern char DATABASE_FILE[];
+extern char DATABASE_POINTER_FILE[];
+extern char DATABASE_POINTER_TEMP[];
+extern char ALERT_MAP_DIR[400];
+extern char SELECTED_MAP_DIR[400];
+extern char SELECTED_MAP_DATA[400];
+extern char MAP_INDEX_DATA[400];
+extern char AUTO_MAP_DIR[400];
+extern char SYMBOLS_DIR[400];
+extern char LOGFILE_IGATE[400];
+extern char LOGFILE_TNC[400];
+extern char LOGFILE_NET[400];
+extern char LOGFILE_MESSAGE[400];
+extern char LOGFILE_WX[400];
+extern char LOGFILE_WX_ALERT[400];
+extern char HELP_FILE[];
+extern char SOUND_DIR[400];
+extern time_t WX_ALERTS_REFRESH_TIME;
+extern time_t remove_ID_message_time;
+extern int pending_ID_message;
+extern time_t gps_time;
+extern time_t POSIT_rate;
+extern time_t OBJECT_rate;
+extern time_t update_DR_rate;
+
+extern time_t posit_last_time;
+extern time_t posit_next_time;
+
+extern int smart_beaconing;
+extern int sb_POSIT_rate;
+extern int sb_last_heading;
+extern int sb_current_heading;
+extern time_t sb_last_posit_time;
+extern int sb_turn_min;
+extern int sb_turn_slope;
+extern int sb_turn_time;
+extern int sb_posit_fast;
+extern int sb_posit_slow;
+extern int sb_low_speed_limit;
+extern int sb_high_speed_limit;
+
+extern int pop_up_new_bulletins;
+extern int view_zero_distance_bulletins;
+extern int warn_about_mouse_modifiers;
+extern int predefined_menu_from_file;
+
+extern int draw_labeled_grid_border; // used to turn on or off border on map
+
+extern int my_trail_diff_color; // trails for mycall with different ssids have the same or a different color
+
+extern int output_station_type;
+
+extern int emergency_beacon;
+
+typedef struct _selections {
+ int none;
+ int mine;
+ int tnc;
+ int direct;
+ int via_digi;
+ int net;
+ int tactical;
+ int old_data;
+
+ int stations;
+ int fixed_stations;
+ int moving_stations;
+ int weather_stations;
+ int CWOP_wx_stations;
+ int objects;
+ int weather_objects;
+ int gauge_objects;
+ int other_objects;
+} Selections;
+extern Selections Select_;
+
+typedef struct _what_to_display {
+ int callsign;
+ int label_all_trackpoints;
+ int symbol;
+ int symbol_rotate;
+ int trail;
+
+ int course;
+ int speed;
+ int speed_short;
+ int altitude;
+
+ int weather;
+ int weather_text;
+ int temperature_only;
+ int wind_barb;
+
+ int aloha_circle;
+ int ambiguity;
+ int phg;
+ int default_phg;
+ int phg_of_moving;
+
+ int df_data;
+ int df_beamwidth_data;
+ int df_bearing_data;
+ int dr_data;
+ int dr_arc;
+ int dr_course;
+ int dr_symbol;
+
+ int dist_bearing;
+ int last_heard;
+} What_to_display;
+extern What_to_display Display_;
+
+extern int currently_selected_stations;
+extern int currently_selected_stations_save;
+extern Pixel colors[256];
+#define MAX_TRAIL_COLORS 32
+extern Pixel trail_colors[MAX_TRAIL_COLORS];
+extern int current_trail_color;
+extern int english_units;
+extern int do_dbstatus;
+extern int redraw_on_new_data;
+extern int redo_list;
+extern int operate_as_an_igate;
+
+#ifdef TRANSMIT_RAW_WX
+extern int transmit_raw_wx;
+#endif // TRANSMIT_RAW_WX
+
+extern int transmit_compressed_posit;
+extern int transmit_compressed_objects_items;
+extern int log_igate;
+extern int log_tnc_data;
+extern int log_net_data;
+extern int log_message_data;
+extern int log_wx_alert_data;
+extern int log_wx;
+extern int snapshots_enabled;
+extern int kmlsnapshots_enabled;
+extern char user_dir[];
+extern char lang_to_use[30];
+extern char my_group;
+extern char my_symbol;
+extern char my_phg[MAX_PHG+1];
+extern char my_comment[MAX_COMMENT+1];
+extern int map_background_color;
+extern int map_color_fill;
+extern int letter_style;
+extern int icon_outline_style;
+extern int wx_alert_style;
+extern time_t map_refresh_interval;
+extern time_t map_refresh_time;
+extern char sound_command[90];
+extern pid_t last_sound_pid;
+extern int sound_play_new_station;
+extern int sound_play_new_message;
+extern int sound_play_prox_message;
+extern int sound_play_band_open_message;
+extern int sound_play_wx_alert_message;
+extern char sound_new_station[90];
+extern char sound_new_message[90];
+extern char sound_prox_message[90];
+extern char sound_band_open_message[90];
+extern char sound_wx_alert_message[90];
+extern int ATV_screen_ID;
+extern int festival_speak_ID;
+extern int festival_speak_new_station;
+extern int festival_speak_proximity_alert;
+extern int festival_speak_tracked_proximity_alert;
+extern int festival_speak_band_opening;
+extern int festival_speak_new_message_alert;
+extern int festival_speak_new_message_body;
+extern int festival_speak_new_weather_alert;
+extern char prox_min[30];
+extern char prox_max[30];
+extern time_t sec_old;
+extern time_t sec_clear;
+extern int trail_segment_time;
+extern int trail_segment_distance;
+extern int RINO_download_interval;
+extern int dead_reckoning_timeout;
+extern char bando_min[30];
+extern char bando_max[30];
+extern int Display_packet_data_type;
+extern int show_only_station_capabilities;
+extern int Display_packet_data_mine_only;
+extern int menu_x;
+extern int menu_y;
+extern long my_last_altitude;
+extern time_t my_last_altitude_time;
+extern int my_last_course;
+extern int my_last_speed; // in knots
+extern unsigned igate_msgs_tx;
+extern int symbols_loaded;
+extern GC gc2;
+extern GC gc_tint;
+extern GC gc_stipple;
+extern GC gc_bigfont;
+extern int read_file;
+extern float x_screen_distance;
+extern time_t max_transmit_time;
+extern int transmit_disable;
+extern int posit_tx_disable;
+extern int object_tx_disable;
+extern int map_chooser_expand_dirs;
+extern int request_new_image;
+extern int disable_all_popups;
+extern char temp_tracking_station_call[30];
+
+extern int coordinate_system;
+#define USE_DDDDDD 0
+#define USE_DDMMMM 1
+#define USE_DDMMSS 2
+#define USE_UTM 3
+#define USE_UTM_SPECIAL 4
+#define USE_MGRS 5
+
+typedef struct {
+ Widget calling_dialog; // NULL if the calling dialog has been closed.
+ Widget input_lat_deg; // Pointers to calling dialog's widgets
+ Widget input_lat_min; // (Where to get/put the data)
+ Widget input_lat_dir;
+ Widget input_lon_deg;
+ Widget input_lon_min;
+ Widget input_lon_dir;
+} coordinate_calc_array_type;
+extern coordinate_calc_array_type coordinate_calc_array;
+extern void Coordinate_calc(Widget w, XtPointer clientData, XtPointer callData);
+
+
+extern void HandlePendingEvents(XtAppContext app);
+extern void create_gc(Widget w);
+extern void Station_info(Widget w, XtPointer clientData, XtPointer calldata);
+extern void Station_List(Widget w, XtPointer clientData, XtPointer calldata);
+extern void Tracks_All_Clear(Widget w, XtPointer clientData, XtPointer callData);
+extern void Locate_station(Widget w, XtPointer clientData, XtPointer callData);
+extern void Locate_place(Widget w, XtPointer clientData, XtPointer callData);
+extern void Geocoder_place(Widget w, XtPointer clientData, XtPointer callData);
+extern void Display_Wx_Alert(Widget w, XtPointer clientData, XtPointer callData);
+extern void Auto_msg_option(Widget w, XtPointer clientData, XtPointer calldata);
+extern void Auto_msg_set(Widget w, XtPointer clientData, XtPointer calldata);
+extern void Bulletins(Widget w, XtPointer clientData, XtPointer callData);
+extern void on_off_switch(int switchpos, Widget first, Widget second);
+extern void busy_cursor(Widget w);
+extern void pos_dialog(Widget w);
+extern int create_image(Widget w);
+extern void draw_tiger_map (Widget w, char *filenm, int destination_pixmap, int nocache);
+
+typedef struct _transparent_color_record{
+ unsigned long trans_color;
+ struct _transparent_color_record *next;
+} transparent_color_record;
+
+extern int check_trans (XColor c, transparent_color_record *c_trans_color_head);
+
+extern void draw_WMS_map (Widget w, char *filenm, int destination_pixmap, char *URL, transparent_color_record *c_trans_color_head, int nocache);
+
+extern void locate_gui_init(void);
+extern void geocoder_gui_init(void);
+extern void location_gui_init(void);
+extern void view_message_gui_init(void);
+extern void wx_gui_init(void);
+extern long get_x_scale(long x, long y, long ysc);
+
+extern Widget Display_data_dialog;
+extern Widget Display_data_text;
+extern Widget text3;
+extern Widget text4;
+extern Widget log_indicator;
+extern void display_zoom_status(void);
+extern void Center_Zoom(Widget w, XtPointer clientData, XtPointer calldata);
+extern int center_zoom_override;
+extern void statusline(char *status_text,int update);
+extern void stderr_and_statusline(char *message);
+extern int SayTextInit(void);
+extern int SayText(char *text);
+extern Widget auto_msg_toggle;
+
+// Symbol update stuff
+extern Widget configure_station_dialog;
+extern Widget station_config_group_data;
+extern Widget station_config_symbol_data;
+extern void updateSymbolPictureCallback(Widget w,XtPointer clientData,XtPointer callData);
+
+extern Widget object_dialog;
+extern Widget object_group_data;
+extern Widget object_symbol_data;
+extern void updateObjectPictureCallback(Widget w,XtPointer clientData,XtPointer callData);
+
+extern void Draw_All_CAD_Objects(Widget w);
+
+// unit conversion
+extern char un_alt[2+1];
+extern char un_dst[2+1];
+extern char un_spd[4+1];
+extern double cvt_m2len;
+extern double cvt_dm2len;
+extern double cvt_hm2len;
+extern double cvt_kn2len;
+extern double cvt_mi2len;
+
+// euid and egid
+extern uid_t euid;
+extern gid_t egid;
+
+/* JMT - works in FreeBSD */
+#define DISABLE_SETUID_PRIVILEGE do { \
+seteuid(getuid()); \
+setegid(getgid()); \
+if (debug_level & 4) { fprintf(stderr, "Changing euid to %d and egid to %d\n", (int)getuid(), (int)getgid()); } \
+} while(0)
+#define ENABLE_SETUID_PRIVILEGE do { \
+seteuid(euid); \
+setegid(egid); \
+if (debug_level & 4) { fprintf(stderr, "Changing euid to %d and egid to %d\n", (int)euid, (int)egid); } \
+} while(0)
+
+#ifdef HAVE_LIBSHP
+extern void create_map_from_trail(char *call_sign);
+#endif // HAVE_LIBSHP
+
+
+#endif /* XASTIR_MAIN_H */
+
+
diff --git a/src/map_OSM.c b/src/map_OSM.c
new file mode 100644
index 0000000..a417a4f
--- /dev/null
+++ b/src/map_OSM.c
@@ -0,0 +1,1655 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ *
+ * $Id: map_OSM.c,v 1.16 2012/11/01 18:57:19 we7u Exp $
+ *
+ * Copyright (C) 2010-2012 The Xastir Group
+ *
+ * This file was contributed by Jerry Dunmire, KA6HLD.
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ *
+ * This file derived from map_tiger.c which has the following copyrights:
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <dirent.h>
+#include <netinet/in.h>
+#include <Xm/XmAll.h>
+
+#ifdef HAVE_X11_XPM_H
+#include <X11/xpm.h>
+#ifdef HAVE_LIBXPM // if we have both, prefer the extra library
+#undef HAVE_XM_XPMI_H
+#endif // HAVE_LIBXPM
+#endif // HAVE_X11_XPM_H
+
+#ifdef HAVE_XM_XPMI_H
+#include <Xm/XpmI.h>
+#endif // HAVE_XM_XPMI_H
+
+#include <X11/Xlib.h>
+
+#include <math.h>
+
+#include "xastir.h"
+#include "maps.h"
+#include "fetch_remote.h"
+#include "util.h"
+#include "main.h"
+#include "color.h"
+#include "xa_config.h"
+
+#include "map_cache.h"
+
+#include "tile_mgmnt.h"
+#include "map_OSM.h"
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+#ifdef HAVE_MAGICK
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+#undef RETSIGTYPE
+// TVR: "stupid ImageMagick"
+// The problem is that magick/api.h includes Magick's config.h file, and that
+// pulls in all the same autoconf-generated defines that we use.
+// plays those games below, but I don't think in the end that they actually
+// make usable macros with our own data in them.
+// Fortunately, we don't need them, so I'll just undef the ones that are
+// causing problems today. See main.c for fixes that preserve our values.
+#undef PACKAGE
+#undef VERSION
+/* JMT - stupid ImageMagick */
+#define XASTIR_PACKAGE_BUGREPORT PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#define XASTIR_PACKAGE_NAME PACKAGE_NAME
+#undef PACKAGE_NAME
+#define XASTIR_PACKAGE_STRING PACKAGE_STRING
+#undef PACKAGE_STRING
+#define XASTIR_PACKAGE_TARNAME PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#define XASTIR_PACKAGE_VERSION PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#ifdef HAVE_GRAPHICSMAGICK
+/*#include <GraphicsMagick/magick/api.h>*/
+#include <magick/api.h>
+#else // HAVE_GRAPHICSMAGICK
+#include <magick/api.h>
+#endif // HAVE_GRAPHICSMAGICK
+#undef PACKAGE_BUGREPORT
+#define PACKAGE_BUGREPORT XASTIR_PACKAGE_BUGREPORT
+#undef XASTIR_PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#define PACKAGE_NAME XASTIR_PACKAGE_NAME
+#undef XASTIR_PACKAGE_NAME
+#undef PACKAGE_STRING
+#define PACKAGE_STRING XASTIR_PACKAGE_STRING
+#undef XASTIR_PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#define PACKAGE_TARNAME XASTIR_PACKAGE_TARNAME
+#undef XASTIR_PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#define PACKAGE_VERSION XASTIR_PACKAGE_VERSION
+#undef XASTIR_PACKAGE_VERSION
+
+// This matte color was chosen emphirically to work well with the
+// contours from topOSM.
+#if (QuantumDepth == 8)
+#define MATTE_RED (0xa7)
+#define MATTE_GREEN (0xa7)
+#define MATTE_BLUE (0xa7)
+#define MATTE_OPACITY (0x00)
+#define MATTE_COLOR_STRING "xc:#a7a7a7"
+//#define MATTE_COLOR_STRING "xc:#a7a7a700"
+//#define MATTE_OPACITY (0xff)
+//#define MATTE_COLOR_STRING "xc:#a7a7a7ff"
+#elif (QuantumDepth == 16)
+#define MATTE_RED (0xa700)
+#define MATTE_GREEN (0xa700)
+#define MATTE_BLUE (0xa700)
+#define MATTE_OPACITY (0x0000)
+#define MATTE_COLOR_STRING "xc:#a700a700a700"
+//#define MATTE_COLOR_STRING "xc:#a700a700a700ffff"
+#else
+#error "QuantumDepth != 16 or 8"
+#endif // QuantumDepth
+
+#endif // HAVE_MAGICK
+
+// Must be last include file
+#include "leak_detection.h"
+
+#define xastirColorsMatch(p,q) (((p).red == (q).red) && ((p).blue == (q).blue) \
+ && ((p).green == (q).green))
+
+// osm_scale_x - map Xastir scale_x value to an OSM binned value
+//
+// Note that the terms 'higher' and 'lower' are confusing because a
+// smaller Xastir scale number is a larger OSM zoom level. OSM zoom level
+// 0 would show the whole world in a 256x256 pixel tile, OSM zoom level
+// 18 (the max) would require 2^18 tiles to simple wrap the equator.
+//
+// On the equator, OSM zoom level 0 equates to ~97 miles/pixel
+// and OSM zoom level 18 equates to ~2 ft/pixel
+//
+// direction = -1, zoom in
+// direction = 1, zoom out
+// direction = 0, nearst level out from the xastir scale
+//
+#define MAX_OSM_ZOOM_LEVEL 18
+#define OSM_ZOOM_LEVELS (MAX_OSM_ZOOM_LEVEL + 1)
+
+static long osm_scale_x(long xastir_scale_x) {
+
+ long osm_level[OSM_ZOOM_LEVELS] = {1, 2, 4, 8, 15, 31, 62, 124, \
+ 247, 494, 989, 1978, 3955, 7910, 15820, 31641,\
+ 63281, 126563, 253125};
+ long osm_scale_x = osm_level[0];
+ int i = 0;
+
+ for (i=1; i <= MAX_OSM_ZOOM_LEVEL; i++) {
+ if (xastir_scale_x > osm_level[i]) {
+ continue;
+ } else {
+ if (abs(osm_level[i - 1] - xastir_scale_x) < abs(osm_level[i] - xastir_scale_x)) {
+ osm_scale_x = osm_level[i - 1];
+ } else {
+ osm_scale_x = osm_level[i];
+ }
+ break;
+ }
+ }
+
+ if (i > MAX_OSM_ZOOM_LEVEL) {
+ i = MAX_OSM_ZOOM_LEVEL;
+ osm_scale_x = osm_level[i];
+ }
+
+ return(osm_scale_x);
+
+} // osm_scale_x()
+
+
+/*
+ * adj_to_OSM_level - adjust scale_x and scale_y to approximate an OSM zoom level
+ *
+ * The OSM zoom level closest to the scale_x value will be chosen and scale_x is modified.
+ * The scale_y value (pointed to by the second argument) is scaled proportionaly. Both
+ * values pointed to by the arguments are modified.
+ */
+void adj_to_OSM_level( long *new_scale_x, long *new_scale_y) {
+
+ long scale;
+
+ scale = osm_scale_x(*new_scale_x);
+
+ // the y scale must also be adjusted.
+ *new_scale_y = (int)(((double)(*new_scale_y) * ((double)scale / (double)(*new_scale_x)) + 0.5));
+ *new_scale_x = scale;
+
+ return;
+
+} // adj_to_OSM_level()
+
+
+/*
+ * osm_zoom_level - translate the longitude scale to the nearest OSM zoom level
+ *
+ * OSM tile scaling is based on the number of tiles needed to wrap the earth at the equator.
+ * A tile is 256x256 pixels.
+ */
+unsigned int osm_zoom_level(long scale_x) {
+ double circumference = 360.0*3600.0*100.0; // Xastir Units = 1/100 second.
+ double zf;
+ int z;
+ zf = (log(circumference / (double)scale_x) / log(2.0)) - 8.0;
+ z = (int)(zf + 0.5);
+
+ // OSM levels run from 0 to 18. Not all levels are available for all views.
+ if (z < 0) {
+ z = 0;
+ }
+ if (z > 18) {
+ z = 18;
+ }
+
+ return((unsigned int)z);
+
+} // osm_zoom_level()
+
+
+static KeySym OptimizeKey = 0;
+static KeySym ReportScaleKey = 0;
+
+void init_OSM_values(void) {
+ OptimizeKey = 0;
+ ReportScaleKey = 0;
+ return;
+}
+
+int OSM_optimize_key(KeySym key) {
+ return (key == OptimizeKey ? TRUE : FALSE);
+}
+
+void set_OSM_optimize_key(KeySym key) {
+ OptimizeKey = key;
+ return;
+}
+
+int OSM_report_scale_key(KeySym key) {
+ return (key == ReportScaleKey ? TRUE : FALSE);
+}
+
+void set_OSM_report_scale_key(KeySym key) {
+ ReportScaleKey = key;
+ return;
+}
+
+static void get_OSM_local_file(char * local_filename, char * fileimg){
+#ifdef HAVE_MAGICK
+ time_t query_start_time, query_end_time;
+
+#ifdef USE_MAP_CACHE
+ int map_cache_return = 1; // Default = cache miss
+ char *cache_file_id;
+#endif // USE_MAP_CACHE
+
+ char temp_file_path[MAX_VALUE];
+
+ if (debug_level & 512) {
+ query_start_time=time(&query_start_time);
+ }
+
+
+#ifdef USE_MAP_CACHE
+
+ if (!map_cache_fetch_disable) {
+
+ // Delete old copy from the cache
+ if (map_cache_fetch_disable && fileimg[0] != '\0') {
+ if (map_cache_del(fileimg)) {
+ if (debug_level & 512) {
+ fprintf(stderr,"Couldn't delete old map from cache\n");
+ }
+ }
+ }
+
+set_dangerous("map_OSM: map_cache_get");
+ map_cache_return = map_cache_get(fileimg,local_filename);
+clear_dangerous();
+ }
+
+ if (debug_level & 512) {
+ fprintf(stderr,"map_cache_return: <%d> bytes returned: %d\n",
+ map_cache_return,
+ (int) strlen(local_filename));
+ }
+
+ if (map_cache_return != 0 ) {
+
+set_dangerous("map_OSM: map_cache_fileid");
+ cache_file_id = map_cache_fileid();
+ xastir_snprintf(local_filename,
+ MAX_FILENAME, // hardcoded to avoid sizeof()
+ "%s/map_%s.%s",
+ get_user_base_dir("map_cache", temp_file_path, sizeof(temp_file_path)),
+ cache_file_id,
+ "png");
+ free(cache_file_id);
+clear_dangerous();
+
+#else // USE_MAP_CACHE
+
+ xastir_snprintf(local_filename,
+ MAX_FILENAME, // hardcoded to avoid sizeof()
+ "%s/map.%s",
+ get_user_base_dir("tmp", temp_file_path, sizeof(temp_file_path)),
+ "png");
+
+#endif // USE_MAP_CACHE
+
+
+ // Erase any previously existing local file by the same name.
+ // This avoids the problem of having an old map image here and
+ // the code trying to display it when the download fails.
+
+ unlink( local_filename );
+
+ if (fetch_remote_file(fileimg, local_filename)) {
+ // Had trouble getting the file. Abort.
+ return;
+ }
+
+ // For debugging the MagickError/MagickWarning segfaults.
+ //system("cat /dev/null >/var/tmp/xastir_hacker_map.png");
+
+
+#ifdef USE_MAP_CACHE
+
+set_dangerous("map_OSM: map_cache_put");
+ map_cache_put(fileimg,local_filename);
+clear_dangerous();
+
+ } // end if is cached DHBROWN
+
+#endif // MAP_CACHE
+
+
+ if (debug_level & 512) {
+ fprintf (stderr, "Fetch or query took %d seconds\n",
+ (int) (time(&query_end_time) - query_start_time));
+ }
+
+ // Set permissions on the file so that any user can overwrite it.
+ chmod(local_filename, 0666);
+
+#endif //HAVE_MAGICK
+
+} // end get_OSM_local_file
+
+
+static long xastirLat2pixelLat(
+ long xlat, int osm_zoom ) {
+ double lat; // in radians
+ double projection, y;
+ long pixelLat;
+
+ lat = convert_lat_l2r(xlat);
+
+ // xastir latitude values can exceed +/- 90.0 degrees because
+ // the latitude is the extent of the display window. Limit the
+ // OSM latitute to less than +/- 90.0 degrees so that the projection
+ // calculation does not blow up or return unreasonable values.
+ if (lat > ((89.0/180.0) * M_PI)) {
+ lat = ((89.0/180.0) * M_PI);
+ } else if (lat < ((-89.0/180.0) * M_PI)) {
+ lat = ((-89.0/180.0) * M_PI);
+ }
+
+
+ projection = log(tan(lat) + (1.0 / cos(lat)));
+ y = projection / M_PI;
+ y = 1.0 - y;
+ pixelLat = (long)((y * (double)(1<<(osm_zoom + 8))) / 2.0);
+ return(pixelLat);
+} // xastirLat2pixelLat()
+
+
+static double pixelLat2Lat(long osm_lat, int osm_zoom){
+ double lat, projection, y;
+ y = (double)osm_lat * 2.0 / (double)(1<<(osm_zoom + 8));
+ y = 1.0 - y;
+ projection = y * M_PI;
+ lat = 2.0 * atan(exp(projection)) - (M_PI / 2.0);
+ lat = (lat * 180.0 ) / M_PI;
+ return(lat);
+} // pixelLat2Lat()
+
+
+static long pixelLat2xastirLat(long osm_lat, int osm_zoom) {
+ double lat;
+ long xastirLat;
+ lat = pixelLat2Lat(osm_lat, osm_zoom);
+ xastirLat = (long)((90.0 - lat) * 3600.0 * 100.0);
+ return (xastirLat);
+} // pixelLat2xastirLat()
+
+
+static long xastirLon2pixelLon(
+ long xlon, int osm_zoom) {
+ double lon;
+ long pixelLon;
+ lon = xlon / (3600.0 * 100.0);
+ lon = lon * (1<<(osm_zoom +8));
+ lon = lon / 360.0;
+ pixelLon = lon;
+ return(pixelLon);
+} // xastirLon2pixelLon()
+
+
+static double pixelLon2Lon(long osm_lon, int osm_zoom) {
+ double lon;
+ lon = osm_lon * 360.0 ;
+ lon = lon / (1<<(osm_zoom + 8));
+ return(lon);
+} // pixelLon2Lon()
+
+
+static long pixelLon2xastirLon(long osm_lon, int osm_zoom) {
+ long xastirLon;
+ xastirLon = (long)(pixelLon2Lon(osm_lon, osm_zoom) * 3600.0 * 100.0);
+ return(xastirLon);
+} // pixelLon2xastirLon()
+
+
+#ifdef HAVE_MAGICK
+/**********************************************************
+ * draw_image() - copy a image onto the display
+ **********************************************************/
+static void draw_image(
+ Widget w,
+ Image *image,
+ ExceptionInfo *except_ptr,
+ unsigned offsetx,
+ unsigned offsety) {
+ int l;
+ XColor my_colors[256];
+ PixelPacket *pixel_pack;
+ PixelPacket temp_pack;
+ IndexPacket *index_pack;
+ unsigned image_row;
+ unsigned image_col;
+ unsigned scr_x, scr_y; // screen pixel plot positions
+
+ //if (debug_level & 512)
+ // fprintf(stderr,"Color depth is %i \n", (int)image->depth);
+
+ if (image->colorspace != RGBColorspace) {
+ fprintf(stderr,"TBD: I don't think we can deal with colorspace != RGB");
+ return;
+ }
+
+ // If were are drawing to a low bpp display (typically < 8bpp)
+ // try to reduce the number of colors in an image.
+ // This may take some time, so it would be best to do ahead of
+ // time if it is a static image.
+#if (MagickLibVersion < 0x0540)
+ if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL) > 128) {
+#else // MagickLib >= 540
+ if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL, except_ptr) > 128) {
+#endif // MagickLib Version
+
+ if (image->storage_class == PseudoClass) {
+#if (MagickLibVersion < 0x0549)
+ CompressColormap(image); // Remove duplicate colors
+#else // MagickLib >= 0x0549
+ CompressImageColormap(image); // Remove duplicate colors
+#endif // MagickLibVersion < 0x0549
+ }
+
+ // Quantize down to 128 will go here...
+ }
+
+
+ pixel_pack = GetImagePixels(image, 0, 0, image->columns, image->rows);
+ if (!pixel_pack) {
+ fprintf(stderr,"pixel_pack == NULL!!!");
+ return;
+ }
+
+ index_pack = GetIndexes(image);
+ if (image->storage_class == PseudoClass && !index_pack) {
+ fprintf(stderr,"PseudoClass && index_pack == NULL!!!");
+ return;
+ }
+
+
+ if (image->storage_class == PseudoClass && image->colors <= 256) {
+ for (l = 0; l < (int)image->colors; l++) {
+ // Need to check how to do this for ANY image, as
+ // ImageMagick can read in all sorts of image files
+ temp_pack = image->colormap[l];
+ //if (debug_level & 512)
+ // fprintf(stderr,"Colormap color is %i %i %i \n",
+ // temp_pack.red, temp_pack.green, temp_pack.blue);
+
+ // Here's a tricky bit: PixelPacket entries are defined as
+ // Quantum's. Quantum is defined in
+ // /usr/include/magick/image.h as either an unsigned short
+ // or an unsigned char, depending on what "configure"
+ // decided when ImageMagick was installed. We can determine
+ // which by looking at MaxRGB or QuantumDepth.
+ //
+ if (QuantumDepth == 16) { // Defined in /usr/include/magick/image.h
+ if (debug_level & 512)
+ fprintf(stderr,"Color quantum is [0..65535]\n");
+ my_colors[l].red = temp_pack.red * raster_map_intensity;
+ my_colors[l].green = temp_pack.green * raster_map_intensity;
+ my_colors[l].blue = temp_pack.blue * raster_map_intensity;
+ }
+ else { // QuantumDepth = 8
+ if (debug_level & 512)
+ fprintf(stderr,"Color quantum is [0..255]\n");
+ my_colors[l].red = (temp_pack.red << 8) * raster_map_intensity;
+ my_colors[l].green = (temp_pack.green << 8) * raster_map_intensity;
+ my_colors[l].blue = (temp_pack.blue << 8) * raster_map_intensity;
+ }
+
+ // Get the color allocated on < 8bpp displays. pixel color is written to my_colors.pixel
+ if (visual_type == NOT_TRUE_NOR_DIRECT) {
+// XFreeColors(XtDisplay(w), cmap, &(my_colors[l].pixel),1,0);
+ XAllocColor(XtDisplay(w), cmap, &my_colors[l]);
+ }
+ else {
+ pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue,
+ &my_colors[l].pixel);
+ }
+
+ //if (debug_level & 512)
+ // fprintf(stderr,"Color allocated is %li %i %i %i \n", my_colors[l].pixel,
+ // my_colors[l].red, my_colors[l].blue, my_colors[l].green);
+ }
+ }
+
+ // loop over image pixel rows
+ for (image_row = 0; image_row < image->rows; image_row++) {
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ scr_y = image_row + offsety;
+
+ // loop over image pixel colums
+ for (image_col = 0; image_col < image->columns; image_col++) {
+ scr_x = image_col + offsetx;
+ // now copy a pixel from the image to the screen
+ l = image_col + (image_row * image->columns);
+ if (image->storage_class == PseudoClass) {
+ // Make matte transparent
+ if (xastirColorsMatch(pixel_pack[l],image->matte_color)) {
+ continue;
+ }
+ XSetForeground(XtDisplay(w), gc, my_colors[index_pack[l]].pixel);
+ }
+ else {
+ // Skip transparent pixels
+ if (pixel_pack[l].opacity == TransparentOpacity) {
+ continue;
+ }
+
+ // It is not safe to assume that the red/green/blue
+ // elements of pixel_pack of type Quantum are the
+ // same as the red/green/blue of an XColor!
+ if (QuantumDepth==16) {
+ my_colors[0].red=pixel_pack[l].red;
+ my_colors[0].green=pixel_pack[l].green;
+ my_colors[0].blue=pixel_pack[l].blue;
+ }
+ else { // QuantumDepth=8
+ // shift the bits of the 8-bit quantity so that
+ // they become the high bigs of my_colors.*
+ my_colors[0].red=pixel_pack[l].red<<8;
+ my_colors[0].green=pixel_pack[l].green<<8;
+ my_colors[0].blue=pixel_pack[l].blue<<8;
+ }
+ // NOW my_colors has the right r,g,b range for
+ // pack_pixel_bits
+ pack_pixel_bits(my_colors[0].red * raster_map_intensity,
+ my_colors[0].green * raster_map_intensity,
+ my_colors[0].blue * raster_map_intensity,
+ &my_colors[0].pixel);
+ XSetForeground(XtDisplay(w), gc, my_colors[0].pixel);
+ }
+ // write the pixel from the map image to the
+ // screen.
+ (void)XFillRectangle (XtDisplay (w),pixmap,gc,scr_x,scr_y,1,1);
+ } // loop over map pixel columns
+ } // loop over map pixel rows
+
+ return;
+} // end draw_image()
+
+
+/**********************************************************
+ * draw_OSM_image() - copy map image to display
+ **********************************************************/
+static void draw_OSM_image(
+ Widget w,
+ Image *image,
+ ExceptionInfo *except_ptr,
+ tiepoint *tpNW,
+ tiepoint *tpSE,
+ int osm_zl)
+{
+ int l;
+ XColor my_colors[256];
+ PixelPacket *pixel_pack;
+ PixelPacket temp_pack;
+ IndexPacket *index_pack;
+ long map_image_row;
+ long map_image_col;
+ long map_x_min, map_x_max; // map boundaries for in screen part of map
+ long map_y_min, map_y_max;
+ int map_seen = 0;
+ int map_act;
+ int map_done;
+
+ long scr_x, scr_y; // screen pixel plot positions
+ long scr_xp, scr_yp; // previous screen plot positions
+ int scr_dx, scr_dy; // increments in screen plot positions
+
+ //if (debug_level & 512)
+ // fprintf(stderr,"Color depth is %i \n", (int)image->depth);
+
+ if (image->colorspace != RGBColorspace) {
+ fprintf(stderr,"TBD: I don't think we can deal with colorspace != RGB");
+ return;
+ }
+
+ // If were are drawing to a low bpp display (typically < 8bpp)
+ // try to reduce the number of colors in an image.
+ // This may take some time, so it would be best to do ahead of
+ // time if it is a static image.
+#if (MagickLibVersion < 0x0540)
+ if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL) > 128) {
+#else // MagickLib >= 540
+ if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL, except_ptr) > 128) {
+#endif // MagickLib Version
+
+ if (image->storage_class == PseudoClass) {
+#if (MagickLibVersion < 0x0549)
+ CompressColormap(image); // Remove duplicate colors
+#else // MagickLib >= 0x0549
+ CompressImageColormap(image); // Remove duplicate colors
+#endif // MagickLibVersion < 0x0549
+ }
+
+ // Quantize down to 128 will go here...
+ }
+
+
+ pixel_pack = GetImagePixels(image, 0, 0, image->columns, image->rows);
+ if (!pixel_pack) {
+ fprintf(stderr,"pixel_pack == NULL!!!");
+ return;
+ }
+
+ index_pack = GetIndexes(image);
+ if (image->storage_class == PseudoClass && !index_pack) {
+ fprintf(stderr,"PseudoClass && index_pack == NULL!!!");
+ return;
+ }
+
+
+ if (image->storage_class == PseudoClass && image->colors <= 256) {
+ for (l = 0; l < (int)image->colors; l++) {
+ // Need to check how to do this for ANY image, as
+ // ImageMagick can read in all sorts of image files
+ temp_pack = image->colormap[l];
+ //if (debug_level & 512)
+ // fprintf(stderr,"Colormap color is %i %i %i \n",
+ // temp_pack.red, temp_pack.green, temp_pack.blue);
+
+ // Here's a tricky bit: PixelPacket entries are defined as
+ // Quantum's. Quantum is defined in
+ // /usr/include/magick/image.h as either an unsigned short
+ // or an unsigned char, depending on what "configure"
+ // decided when ImageMagick was installed. We can determine
+ // which by looking at MaxRGB or QuantumDepth.
+ //
+ if (QuantumDepth == 16) { // Defined in /usr/include/magick/image.h
+ //if (debug_level & 512)
+ // fprintf(stderr,"Color quantum is [0..65535]\n");
+ my_colors[l].red = temp_pack.red * raster_map_intensity;
+ my_colors[l].green = temp_pack.green * raster_map_intensity;
+ my_colors[l].blue = temp_pack.blue * raster_map_intensity;
+ }
+ else { // QuantumDepth = 8
+ //if (debug_level & 512)
+ // fprintf(stderr,"Color quantum is [0..255]\n");
+ my_colors[l].red = (temp_pack.red << 8) * raster_map_intensity;
+ my_colors[l].green = (temp_pack.green << 8) * raster_map_intensity;
+ my_colors[l].blue = (temp_pack.blue << 8) * raster_map_intensity;
+ }
+
+ // Get the color allocated on < 8bpp displays. pixel color is written to my_colors.pixel
+ if (visual_type == NOT_TRUE_NOR_DIRECT) {
+// XFreeColors(XtDisplay(w), cmap, &(my_colors[l].pixel),1,0);
+ XAllocColor(XtDisplay(w), cmap, &my_colors[l]);
+ }
+ else {
+ pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue,
+ &my_colors[l].pixel);
+ }
+
+ //if (debug_level & 512)
+ // fprintf(stderr,"Color allocated is %li %i %i %i \n", my_colors[l].pixel,
+ // my_colors[l].red, my_colors[l].blue, my_colors[l].green);
+ }
+ }
+
+ /*
+ * Here are the corners of our viewport, using the Xastir
+ * coordinate system. Notice that Y is upside down:
+ *
+ * left edge of view = NW_corner_longitude
+ * right edge of view = SE_corner_longitude
+ * top edge of view = NW_corner_latitude
+ * bottom edge of view = SE_corner_latitude
+ *
+ * The corners of our image were calculated and stored
+ * above as tiepoints using OSM units (pixels/circle). They are:
+ *
+ * left edge of map = tp[0].x_long
+ * right edge of map = tp[1].x_long
+ * top edge of map = tp[0].y_lat
+ * bottom edge of map = tp[1].y_lat
+ *
+ */
+
+ scr_dx = 1;
+ scr_dy = 1;
+
+ // calculate map pixel range in y direction that falls into screen area
+ map_y_min = map_y_max = 0l;
+ for (map_image_row = 0; map_image_row < (long)image->rows; map_image_row++){
+ scr_y = (pixelLat2xastirLat(map_image_row + tpNW->y_lat, osm_zl) - NW_corner_latitude) / scale_y;
+ if (scr_y > 0) {
+ if (scr_y < screen_height) {
+ map_y_max = map_image_row; // update last map pixel in y
+ } else
+ break; // done, reached bottom screen border
+ } else { // pixel is above screen
+ map_y_min = map_image_row; // update first map pixel in y
+ }
+ }
+
+ // Calculate the position of the map image relative to the screen
+ map_x_min = map_x_max = 0l;
+ for (map_image_col = 0; map_image_col < (long)image->columns; map_image_col++) {
+ scr_x = (pixelLon2xastirLon(map_image_col + tpNW->x_long, osm_zl) - NW_corner_longitude) / scale_x;
+ if (scr_x > 0) {
+ if (scr_x < screen_width)
+ map_x_max = map_image_col; // update last map pixel in x
+ else
+ break; // done, reached right screen border
+ } else { // pixel is left from screen
+ map_x_min = map_image_col; // update first map pixel in x
+ }
+ }
+
+ scr_yp = -1;
+ map_done = 0;
+ map_act = 0;
+ map_seen = 0;
+
+ // loop over map pixel rows
+ for (map_image_row = map_y_min; (map_image_row <= map_y_max); map_image_row++) {
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ scr_y = (pixelLat2xastirLat(map_image_row + tpNW->y_lat, osm_zl)
+ - NW_corner_latitude) / scale_y;
+
+ // image rows do not match 1:1 with screen rows due to Mercator
+ // scaling, so scr_dy will be passed to XFillRectangle to
+ // handle that issue.
+ // scr_dy is in rows and must be a minimum of 1 row.
+ scr_dy = (( pixelLat2xastirLat(map_image_row + 1 + tpNW->y_lat, osm_zl)
+ - NW_corner_latitude) / scale_y) - scr_y;
+ if (scr_dy < 1)
+ scr_dy = 1;
+
+ if (scr_y != scr_yp) { // don't do a row twice
+ scr_yp = scr_y; // remember as previous y
+ scr_xp = -1;
+ // loop over map pixel columns
+ map_act = 0;
+ for (map_image_col = map_x_min; map_image_col <= map_x_max; map_image_col++) {
+ scr_x = ( pixelLon2xastirLon(map_image_col + tpNW->x_long, osm_zl)
+ - NW_corner_longitude) / scale_x;
+ // handle the case when here the horizontal resolution
+ // of the image is less than the horizontal resolution
+ // displayed. scr_dx is passed to XFillRectangle() below
+ // and must be at least 1 column.
+ scr_dx = ( (pixelLon2xastirLon(map_image_col + 1 + tpNW->x_long, osm_zl)
+ - NW_corner_longitude) / scale_x) - scr_x;
+ if (scr_dx < 1)
+ scr_dx = 1;
+ if (scr_x != scr_xp) { // don't do a pixel twice
+ scr_xp = scr_x; // remember as previous x
+
+ // check map boundaries in y direction
+ if (map_image_row >= 0 && map_image_row <= tpSE->img_y) {
+ map_seen = 1;
+ map_act = 1; // detects blank screen rows (end of map)
+
+ // now copy a pixel from the map image to the screen
+ l = map_image_col + map_image_row * image->columns;
+ if (image->storage_class == PseudoClass) {
+ // Make matte transparent by skipping pixels
+ if (xastirColorsMatch(pixel_pack[l],image->matte_color)) {
+ continue;
+ }
+ XSetForeground(XtDisplay(w), gc, my_colors[index_pack[l]].pixel);
+ }
+ else {
+ // Skip transparent pixels and make matte
+ // colored pixels transparent (by skipping)
+ if ((pixel_pack[l].opacity == TransparentOpacity)
+ || (xastirColorsMatch(pixel_pack[l], image->matte_color))){
+ continue;
+ }
+
+ // It is not safe to assume that the red/green/blue
+ // elements of pixel_pack of type Quantum are the
+ // same as the red/green/blue of an XColor!
+ if (QuantumDepth==16) {
+ my_colors[0].red=pixel_pack[l].red;
+ my_colors[0].green=pixel_pack[l].green;
+ my_colors[0].blue=pixel_pack[l].blue;
+ }
+ else { // QuantumDepth=8
+ // shift the bits of the 8-bit quantity so that
+ // they become the high bigs of my_colors.*
+ my_colors[0].red=pixel_pack[l].red<<8;
+ my_colors[0].green=pixel_pack[l].green<<8;
+ my_colors[0].blue=pixel_pack[l].blue<<8;
+ }
+ // NOW my_colors has the right r,g,b range for
+ // pack_pixel_bits
+ pack_pixel_bits(my_colors[0].red * raster_map_intensity,
+ my_colors[0].green * raster_map_intensity,
+ my_colors[0].blue * raster_map_intensity,
+ &my_colors[0].pixel);
+ XSetForeground(XtDisplay(w), gc, my_colors[0].pixel);
+ }
+ // write the pixel from the map image to the
+ // screen. Strech to a rectangle as needed
+ // specified by scr_dx and scr_dy.
+ (void)XFillRectangle (XtDisplay (w),pixmap,gc,scr_x,scr_y,scr_dx,scr_dy);
+ } // check map boundaries in y direction
+ } // don't do a screen pixel twice (in the same row)
+ } // loop over map pixel columns
+
+ if (map_seen && !map_act)
+ map_done = 1;
+ } // don't do a screen row twice.
+ } // loop over map pixel rows
+} // end draw_OSM_image()
+
+
+/**********************************************************
+ * draw_OSM_tiles() - retrieve enough map tiles to fill the display
+ **********************************************************/
+// MaxTextExtent is an ImageMagick/GraphicMagick constant
+#define MAX_TMPSTRING MaxTextExtent
+
+void draw_OSM_tiles (Widget w,
+ char *filenm, // this is the name of the xastir map file
+ int destination_pixmap,
+ char *server_url, // if specified in xastir map file
+ char *tileCacheDir, // if specified in xastir map file
+ char *mapName, // if specified in xastir map file
+ char *tileExt) { // if specified in xastir map file
+
+ char serverURL[MAX_FILENAME];
+ char tileRootDir[MAX_FILENAME];
+ char map_it[MAX_FILENAME];
+ char short_filenm[MAX_FILENAME];
+ int osm_zl;
+ tileArea_t tiles;
+ coord_t corner;
+ tiepoint NWcorner;
+ tiepoint SEcorner;
+ unsigned long tilex, tiley;
+ unsigned long tileCnt = 0;
+ unsigned long numTiles;
+ int interrupted = 0;
+
+ ExceptionInfo exception;
+ Image *canvas = NULL;
+ Image *tile = NULL;
+ ImageInfo *canvas_info = NULL;
+ ImageInfo *tile_info = NULL;
+ unsigned int row, col;
+ unsigned int offset_x, offset_y;
+ char tmpString[MAX_TMPSTRING];
+
+#ifdef HAVE_LIBCURL
+ CURL *mySession;
+ char errBuf[CURL_ERROR_SIZE];
+ int curl_result;
+#endif // HAVE_LIBCURL
+ char temp_file_path[MAX_VALUE];
+
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ // We're indexing only. Save the extents in the index.
+ // Force the extents to the edges of the earth for the
+ // index file.
+ index_update_xastir(filenm, // Filename only
+ 64800000l, // Bottom
+ 0l, // Top
+ 0l, // Left
+ 129600000l, // Right
+ 0); // Default Map Level
+
+ // Update statusline
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ langcode ("BBARSTA039"), // Indexing %s
+ short_filenm);
+ statusline(map_it,0); // Indexing
+
+ return; // Done indexing this file
+ }
+
+ if (tileCacheDir[0] != '\0') {
+ if (tileCacheDir[0] == '/') {
+ xastir_snprintf(tileRootDir, sizeof(tileRootDir),
+ "%s", tileCacheDir);
+ } else {
+ xastir_snprintf(tileRootDir, sizeof(tileRootDir),
+ "%s", get_user_base_dir(tileCacheDir, temp_file_path, sizeof(temp_file_path)));
+ }
+ } else {
+ xastir_snprintf(tileRootDir, sizeof(tileRootDir),
+ "%s", get_user_base_dir("OSMtiles", temp_file_path, sizeof(temp_file_path)));
+ }
+
+ if (mapName[0] != '\0') {
+ xastir_snprintf(tmpString, sizeof(tmpString), "/%s", mapName);
+ strncat(tileRootDir, tmpString, sizeof(tileRootDir) - 1 - strlen(tileRootDir));
+ }
+
+ if (server_url[0] != '\0') {
+ xastir_snprintf(serverURL, sizeof(serverURL),
+ "%s", server_url);
+ } else {
+ xastir_snprintf(serverURL, sizeof(serverURL),
+ "%s", "http://tile.openstreetmap.org");
+ }
+
+ if (server_url[strlen(serverURL) - 1] == '/') {
+ serverURL[strlen(serverURL) - 1] = '\0';
+ }
+
+ // Create a shorter filename for display (one that fits the
+ // status line more closely). Allow space for the
+ // "Indexing " or "Loading " strings.
+ if (strlen(filenm) > (41 - 9)) {
+ int avail = 41 - 11;
+ int new_len = strlen(filenm) - avail;
+
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "..%s",
+ &filenm[new_len]);
+ }
+ else {
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "%s",
+ filenm);
+ }
+
+ GetExceptionInfo(&exception);
+
+ if (debug_level & 512) {
+ unsigned long lat, lon;
+ (void)convert_to_xastir_coordinates(&lon, &lat,
+ f_NW_corner_longitude, f_NW_corner_latitude);
+ fprintf(stderr, "NW_corner_longitude = %f, %ld, %ld\n",
+ f_NW_corner_longitude, NW_corner_longitude, lon);
+ fprintf(stderr, "NW_corner_latitude = %f, %ld, %ld\n",
+ f_NW_corner_latitude, NW_corner_latitude, lat);
+
+ (void)convert_to_xastir_coordinates(&lon, &lat,
+ f_SE_corner_longitude, f_SE_corner_latitude);
+ fprintf(stderr, "SE_corner_longitude = %f, %ld, %ld\n",
+ f_SE_corner_longitude, SE_corner_longitude, lon);
+ fprintf(stderr, "SE_corner_latitude = %f, %ld, %ld\n",
+ f_SE_corner_latitude, SE_corner_latitude, lat);
+ }
+
+ osm_zl = osm_zoom_level(scale_x);
+ calcTileArea(f_NW_corner_longitude, f_NW_corner_latitude,
+ f_SE_corner_longitude, f_SE_corner_latitude,
+ osm_zl, &tiles);
+
+ xastir_snprintf(map_it, sizeof(map_it), "%s",
+ langcode ("BBARSTA050")); // Downloading tiles...
+ statusline(map_it,0);
+ XmUpdateDisplay(text);
+
+ // make sure all the map directories exist
+ mkOSMmapDirs(tileRootDir, tiles.startx, tiles.endx, osm_zl);
+
+ // Check to see how many tiles need to be downloaded
+ // A simple calculation doesn't work well here because some
+ // (possibly all) of the tiles may exist in the cache.
+ numTiles = tilesMissing(tiles.startx, tiles.endx, tiles.starty,
+ tiles.endy, osm_zl, tileRootDir,
+ tileExt[0] != '\0' ? tileExt : "png");
+
+#ifdef HAVE_LIBCURL
+ mySession = xastir_curl_init(errBuf);
+#endif // HAVE_LIBCURL
+
+ // get the tiles
+ tileCnt = 1;
+ for (tilex = tiles.startx; tilex <= tiles.endx; tilex++) {
+ for (tiley = tiles.starty; tiley <= tiles.endy; tiley++) {
+ if ((numTiles > 0) & (tileCnt <= numTiles)) {
+ xastir_snprintf(map_it, sizeof(map_it), langcode("BBARSTA051"),
+ tileCnt, numTiles); // Downloading tile %ls of %ls
+ statusline(map_it,0);
+ XmUpdateDisplay(text);
+ }
+
+#ifdef HAVE_LIBCURL
+ curl_result = getOneTile(mySession, serverURL, tilex, tiley,
+ osm_zl, tileRootDir, tileExt[0] != '\0' ? tileExt : "png");
+ if (curl_result < 0) {
+ fprintf(stderr, "Download error for tile: %s/%i/%li/%li.%s\n",
+ serverURL, osm_zl, tilex, tiley,
+ tileExt[0] != '\0' ? tileExt : "png");
+ fprintf(stderr, "curl told us %d\n", -1 * curl_result);
+ fprintf(stderr, "curlerr: %s\n", errBuf);
+ } else {
+ tileCnt += curl_result;
+ }
+#else
+ tileCnt += getOneTile(serverURL, tilex, tiley,
+ osm_zl, tileRootDir, tileExt[0] != '\0' ? tileExt : "png");
+#endif // HAVE_LIBCURL
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ interrupted = 1;
+ break;
+ }
+ }
+ if (interrupted == 1) {
+ break;
+ }
+ }
+
+#ifdef HAVE_LIBCURL
+ curl_easy_cleanup(mySession);
+#endif // HAVE_LIBCURL
+
+ if (interrupted != 1) {
+ // calculate tie points
+ NWcorner.img_x = 0;
+ NWcorner.img_y = 0;
+ NWcorner.x_long = tiles.startx * 256;
+ NWcorner.y_lat = tiles.starty * 256;
+
+ if (debug_level & 512) {
+ fprintf(stderr, "scale = %ld, zoom = %d\n", scale_x, osm_zl);
+ fprintf(stderr, "NW corner:\n");
+ fprintf(stderr, " img_x = %d, img_y = %d\n", NWcorner.img_x, NWcorner.img_y);
+ fprintf(stderr, " x_long = %ld, y_lat = %ld\n", NWcorner.x_long, NWcorner.y_lat);
+ fprintf(stderr, "req. lon = %f, lat = %f\n", f_NW_corner_longitude,
+ f_NW_corner_latitude);
+ tile2coord(tiles.startx, tiles.starty, osm_zl, &corner);
+ fprintf(stderr, "ret. lon = %f, lat = %f\n", corner.lon, corner.lat);
+ fprintf(stderr, "tile x = %li, y = %li\n", tiles.startx, tiles.starty);
+ }
+
+ // The NW corner of the next tile is the SE corner of the last tile
+ // we fetched. So add one to the end tile numbers before calculating
+ // the coordinates.
+ SEcorner.img_x = (256 * ((tiles.endx + 1) - tiles.startx)) - 1;
+ SEcorner.img_y = (256 * ((tiles.endy + 1) - tiles.starty)) - 1;
+ SEcorner.x_long = (tiles.endx + 1) * 256;
+ SEcorner.y_lat = (tiles.endy + 1) * 256;
+
+ if (debug_level & 512) {
+ fprintf(stderr, "SE corner:\n");
+ fprintf(stderr, " img_x = %d, img_y = %d\n", SEcorner.img_x, SEcorner.img_y);
+ fprintf(stderr, " x_long = %ld, y_lat = %ld\n", SEcorner.x_long, SEcorner.y_lat);
+ fprintf(stderr, "req. lon = %f, lat = %f\n", f_SE_corner_longitude,
+ f_SE_corner_latitude);
+ tile2coord(tiles.endx + 1, tiles.endy + 1, osm_zl, &corner);
+ fprintf(stderr, "ret. lon = %f, lat = %f\n", corner.lon, corner.lat);
+ fprintf(stderr, "tile x = %li, y = %li\n", tiles.endx, tiles.endy);
+ }
+
+ /*
+ * Create a canvas upon which the tiles will be composited.
+ */
+ canvas_info=CloneImageInfo((ImageInfo *)NULL);
+
+ // Set canvas dimensions in pixels
+ xastir_snprintf(tmpString, sizeof(tmpString), "%lix%li",
+ ((tiles.endx + 1) - tiles.startx) * 256,
+ ((tiles.endy + 1) - tiles.starty) * 256);
+ (void)CloneString(&canvas_info->size, tmpString);
+
+ /*
+ * A file name based on a color creates an image filled
+ * with that color. The matte color will be treated as
+ * transparent when the completed OSM map gets copied to the X
+ * display.
+ */
+ FormatString(canvas_info->filename, "%s", MATTE_COLOR_STRING);
+ canvas = ReadImage(canvas_info, &exception);
+ if (exception.severity != UndefinedException) {
+ CatchException(&exception);
+ fprintf(stderr, "Could not allocate canvas to hold tiles.\n");
+ if (canvas_info != NULL) {
+ DestroyImageInfo(canvas_info);
+ }
+ return;
+ }
+ // Make sure that the canvas is an image type that uses the
+ // opacity channel for compositing.
+ SetImageType(canvas, PaletteMatteType);
+
+ // Fill the image with an opaque color. Ultimately pixels that
+ // are this color will be skipped when the image is written to
+ // the screen.
+ canvas->background_color.red = MATTE_RED;
+ canvas->background_color.green = MATTE_GREEN;
+ canvas->background_color.blue = MATTE_BLUE;
+ canvas->background_color.opacity = MATTE_OPACITY;
+ SetImage(canvas, MATTE_OPACITY);
+
+ xastir_snprintf(map_it, sizeof(map_it), "%s",
+ langcode ("BBARSTA049")); // Reading tiles...
+ statusline(map_it,0);
+ XmUpdateDisplay(text);
+
+ tile_info = CloneImageInfo((ImageInfo *)NULL);
+
+ // Read the tile and composite them onto the canvas
+ for (col = tiles.starty, offset_y = 0;
+ col <= tiles.endy;
+ col++, offset_y += 256) {
+ for (row = tiles.startx, offset_x = 0;
+ row <= tiles.endx;
+ row++, offset_x += 256) {
+ xastir_snprintf(tmpString, sizeof(tmpString),
+ "%s/%d/%d/%d.%s", tileRootDir, osm_zl, row, col,
+ tileExt[0] != '\0' ? tileExt : "png");
+ strncpy(tile_info->filename, tmpString, MaxTextExtent);
+
+ tile = ReadImage(tile_info,&exception);
+ if (exception.severity != UndefinedException) {
+ CatchException(&exception);
+ xastir_snprintf(tmpString, sizeof(tmpString), "%s/%d/%d/%d.%s",
+ tileRootDir, osm_zl, row, col,
+ tileExt[0] != '\0' ? tileExt : "png");
+ if (debug_level & 512) {
+ fprintf(stderr, "%s NOT removed.\n", tmpString);
+ } else {
+ fprintf(stderr, "Removing %s\n", tmpString);
+ unlink(tmpString);
+ }
+ // clear exception so next iteration doesn't fail
+ GetExceptionInfo(&exception);
+
+ // replace the missing tile with a place holder
+ //(void)strcpy(tile_info->filename, "xc:red");
+ //tile = ReadImage(tile_info, &exception);
+ }
+ if (tile) {
+ (void)CompositeImage(canvas, OverCompositeOp,
+ tile, offset_x, offset_y);
+ DestroyImage(tile);
+ }
+ }
+ }
+
+ // Set the matte color for use in transparentency testing
+ canvas->matte_color.red = MATTE_RED;
+ canvas->matte_color.green = MATTE_GREEN;
+ canvas->matte_color.blue = MATTE_BLUE;
+
+ if (debug_level & 512) {
+ DescribeImage(canvas, stderr, 0);
+ WriteImages(canvas_info, canvas, "/tmp/xastirOSMTiledMap.png", &exception);
+ }
+
+ draw_OSM_image(w, canvas, &exception, &NWcorner, &SEcorner, osm_zl);
+
+ // Display the OpenStreetMap attribution
+ // Just resuse the tile structure rather than creating another.
+ xastir_snprintf(tmpString, sizeof(tmpString),
+ "%s/CC_OpenStreetMap.png", get_data_base_dir("maps"));
+ strncpy(tile_info->filename, tmpString, MaxTextExtent);
+
+ tile = ReadImage(tile_info,&exception);
+ if (exception.severity != UndefinedException) {
+ CatchException(&exception);
+ } else {
+ draw_image(w, tile, &exception, 4, 4);
+ DestroyImage(tile);
+ }
+ } else {
+ // map draw was interrupted
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ }
+
+ /*
+ * Release resources
+ */
+ if (tile_info != NULL)
+ DestroyImageInfo(tile_info);
+ if (canvas_info != NULL)
+ DestroyImageInfo(canvas_info);
+ if (canvas != NULL)
+ DestroyImage(canvas);
+ DestroyExceptionInfo(&exception);
+ return;
+
+} // draw_OSM_tiles()
+
+
+/**********************************************************
+ * draw_OSM_map() - retreive an image that is the size of the display
+ **********************************************************/
+void draw_OSM_map (Widget w,
+ char *filenm,
+ int destination_pixmap,
+ char *url,
+ char *style,
+ int nocache) { // For future implementation of a "refresh cached map" option
+ char file[MAX_FILENAME]; // Complete path/name of image file
+ char short_filenm[MAX_FILENAME];
+ FILE *f; // Filehandle of image file
+ char fileimg[MAX_FILENAME]; // Ascii name of image file, read from GEO file
+ char OSMtmp[MAX_FILENAME*2]; // Used for putting together the OSMmap query
+ tiepoint tp[2]; // Calibration points for map
+
+ char local_filename[MAX_FILENAME];
+
+ ExceptionInfo exception;
+ Image *image;
+ ImageInfo *image_info;
+ double left, right, top, bottom;
+ double lat_center = 0;
+ double long_center = 0;
+
+ char map_it[MAX_FILENAME];
+ char tmpstr[1001];
+ int osm_zl = 18; // OSM zoom level, at 18, the whole
+ // world fits in one 256x256 tile.
+ unsigned map_image_width; // Image width
+ unsigned map_image_height; // Image height
+ // TODO: put the max_image_* limits in the .geo/.osm file because it could change on a by-server
+ // basis and the server URL can be specified in the .geo/.osm file.
+ unsigned max_image_width = 2000; // This value is for the default server
+ unsigned max_image_height = 2000; // This value is for the default server
+
+ // initialize this
+ local_filename[0]='\0';
+
+ // Create a shorter filename for display (one that fits the
+ // status line more closely). Subtract the length of the
+ // "Indexing " and/or "Loading " strings as well.
+ if (strlen(filenm) > (41 - 9)) {
+ int avail = 41 - 11;
+ int new_len = strlen(filenm) - avail;
+
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "..%s",
+ &filenm[new_len]);
+ }
+ else {
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "%s",
+ filenm);
+ }
+
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ langcode ("BBARSTA028"),
+ short_filenm);
+ statusline(map_it,0); // Loading ...
+ XmUpdateDisplay(text);
+
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ // We're indexing only. Save the extents in the index.
+ // Force the extents to the edges of the earth for the
+ // index file.
+ index_update_xastir(filenm, // Filename only
+ 64800000l, // Bottom
+ 0l, // Top
+ 0l, // Left
+ 129600000l, // Right
+ 0); // Default Map Level
+
+ // Update statusline
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ langcode ("BBARSTA039"),
+ short_filenm);
+ statusline(map_it,0); // Loading/Indexing ...
+
+ return; // Done indexing this file
+ }
+
+ // calculate the OSM zoom level (osm_zl) that is nearest the xastir scale
+ osm_zl = osm_zoom_level(scale_x);
+
+ // Calculate the image size to request. The size will be saved as tiepoints
+ // for the top-left and bottom-right of the image.
+ tp[0].x_long = xastirLon2pixelLon(NW_corner_longitude, osm_zl); // OSM pixels
+ tp[1].x_long = xastirLon2pixelLon(SE_corner_longitude, osm_zl); // OSM pixels
+ tp[0].y_lat = xastirLat2pixelLat(NW_corner_latitude, osm_zl); // OSM pixels
+ tp[1].y_lat = xastirLat2pixelLat(SE_corner_latitude, osm_zl); // OSM pixels
+
+ map_image_height = tp[1].y_lat - tp[0].y_lat;
+ map_image_width = tp[1].x_long - tp[0].x_long;
+
+ // Limit dimensions to the max the server will allow.
+ if (map_image_width > max_image_width) {
+ int tmp = ((map_image_width - map_image_height) / 2) + 1;
+ tp[0].x_long += tmp;
+ tp[1].x_long -= tmp;
+ map_image_width = tp[1].x_long - tp[0].x_long;
+ }
+
+ if (map_image_height > max_image_height) {
+ int tmp = ((map_image_height - max_image_height) / 2) + 1;
+ tp[0].y_lat += tmp;
+ tp[1].y_lat -= tmp;
+ map_image_height = tp[1].y_lat - tp[0].y_lat;
+ }
+
+ // Size and coordinates for the tiepoints in pixels
+ tp[0].img_x = 0;
+ tp[0].img_y = 0;
+ tp[1].img_x = map_image_width - 1;
+ tp[1].img_y = map_image_height - 1;
+
+ // calculate the center coordinates for the image request
+ left = (double)((NW_corner_longitude - 64800000l )/360000.0); // Lat/long Coordinates, degrees
+ top = (double)(-((NW_corner_latitude - 32400000l )/360000.0)); // Lat/long Coordinates, degrees
+ right = (double)((SE_corner_longitude - 64800000l)/360000.0); //Lat/long Coordinates, degrees
+ bottom = (double)(-((SE_corner_latitude - 32400000l)/360000.0));//Lat/long Coordinates, degrees
+
+ long_center = (left + right)/2.0l; // degrees
+
+ // The vertical center of the image must be calculated from the OSM image size to
+ // compensate for latitude scaling (Mercator). This is particularly important for small image/screen
+ // sizes and may not be apparent on large displays.
+ lat_center = pixelLat2Lat((map_image_height / 2) + tp[0].y_lat, osm_zl);
+
+ /*
+ * Query format to the StaticMap
+ * See: http://ojw.dev.openstreetmap.org/StaticMap/?mode=API&
+ *
+ * http://ojw.dev.openstreetmap.org/StaticMap/?lat=LL.LLLLLL&lon=-LLL.LLLLL&z=15& \
+ * w=WWW&h=HHH&layer=osmarender&mode=Export&att=none&show=1
+ */
+
+ if (url[0] != '\0') {
+ xastir_snprintf(OSMtmp, sizeof(OSMtmp), "%s", url);
+ } else {
+ xastir_snprintf(OSMtmp, sizeof(OSMtmp), "http://ojw.dev.openstreetmap.org/StaticMap/");
+ }
+ //xastir_snprintf(tmpstr, sizeof(tmpstr), "?mode=Export&att=text&show=1&");
+ xastir_snprintf(tmpstr, sizeof(tmpstr), "?mode=Export&show=1&");
+ strncat (OSMtmp, tmpstr, sizeof(OSMtmp) - 1 - strlen(OSMtmp));
+
+ if (style[0] != '\0') {
+ xastir_snprintf(tmpstr, sizeof(tmpstr), "%s", style);
+ strncat (OSMtmp, tmpstr, sizeof(OSMtmp) - 1 - strlen(OSMtmp));
+ } else {
+ xastir_snprintf(tmpstr, sizeof(tmpstr), "layer=osmarender&");
+ strncat (OSMtmp, tmpstr, sizeof(OSMtmp) - 1 - strlen(OSMtmp));
+ }
+
+ xastir_snprintf(tmpstr, sizeof(tmpstr), "&lat=%f\046lon=%f\046", lat_center, long_center);
+ strncat (OSMtmp, tmpstr, sizeof(OSMtmp) - 1 - strlen(OSMtmp));
+
+ xastir_snprintf(tmpstr, sizeof(tmpstr), "w=%i\046h=%i\046", map_image_width, map_image_height);
+ strncat (OSMtmp, tmpstr, sizeof(OSMtmp) - 1 - strlen(OSMtmp));
+
+ xastir_snprintf(tmpstr, sizeof(tmpstr), "z=%d", osm_zl);
+ strncat (OSMtmp, tmpstr, sizeof(OSMtmp) - 1 - strlen(OSMtmp));
+
+ xastir_snprintf(fileimg, sizeof(fileimg), "%s", OSMtmp);
+
+ if (debug_level & 512) {
+ fprintf(stderr,"left side is %f\n", left);
+ fprintf(stderr,"right side is %f\n", right);
+ fprintf(stderr,"top is %f\n", top);
+ fprintf(stderr,"bottom is %f\n", bottom);
+ fprintf(stderr,"lat center is %f\n", lat_center);
+ fprintf(stderr,"long center is %f\n", long_center);
+ fprintf(stderr,"screen width is %li\n", screen_width);
+ fprintf(stderr,"screen height is %li\n", screen_height);
+ fprintf(stderr,"OSM image width is %i\n", map_image_width);
+ fprintf(stderr,"OSM image height is %i\n", map_image_height);
+ fprintf(stderr,"scale_y = %li\n", scale_y);
+ fprintf(stderr,"scale_x = %li\n", scale_x);
+ fprintf(stderr,"OSM zoom level = %i\n", osm_zl);
+ fprintf(stderr,"fileimg is %s\n", fileimg);
+ fprintf(stderr,"ftp or http file: %s\n", fileimg);
+ }
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ get_OSM_local_file(local_filename,fileimg);
+
+ // Tell ImageMagick where to find it
+ xastir_snprintf(file,
+ sizeof(file),
+ "%s",
+ local_filename);
+
+ GetExceptionInfo(&exception);
+
+ image_info=CloneImageInfo((ImageInfo *) NULL);
+
+ xastir_snprintf(image_info->filename,
+ sizeof(image_info->filename),
+ "%s",
+ file);
+
+ if (debug_level & 512) {
+ fprintf(stderr,"Copied %s into image info.\n", file);
+ fprintf(stderr,"image_info got: %s\n", image_info->filename);
+ fprintf(stderr,"Entered ImageMagick code.\n");
+ fprintf(stderr,"Attempting to open: %s\n", image_info->filename);
+ }
+
+ // We do a test read first to see if the file exists, so we
+ // don't kill Xastir in the ReadImage routine.
+ f = fopen (image_info->filename, "r");
+ if (f == NULL) {
+ if (debug_level & 512)
+ fprintf(stderr,"File could not be read\n");
+
+#ifdef USE_MAP_CACHE
+
+ // clear from cache if bad
+ if (map_cache_del(fileimg)) {
+ if (debug_level & 512) {
+ fprintf(stderr,"Couldn't delete unreadable map from cache\n");
+ }
+ }
+#endif
+
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+ (void)fclose (f);
+
+
+ image = ReadImage(image_info, &exception);
+
+ if (image == (Image *) NULL) {
+ MagickWarning(exception.severity, exception.reason, exception.description);
+ //fprintf(stderr,"MagickWarning\n");
+
+#ifdef USE_MAP_CACHE
+ // clear from cache if bad
+ if (map_cache_del(fileimg)) {
+ if (debug_level & 512) {
+ fprintf(stderr,"Couldn't delete map from cache\n");
+ }
+ }
+#endif
+
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+
+ } else if ( (image->columns != map_image_width)
+ || (image->rows != map_image_height)) {
+ fprintf(stderr, "Server returned an image size different than requested!\n");
+
+#ifdef USE_MAP_CACHE
+ // clear from cache if bad
+ if (map_cache_del(fileimg)) {
+ if (debug_level & 512) {
+ fprintf(stderr,"Couldn't delete map from cache\n");
+ }
+ }
+#endif
+ if (image) {
+ DestroyImage(image);
+ }
+ if (image_info) {
+ DestroyImageInfo(image_info);
+ }
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+ if (debug_level & 512) {
+ fprintf(stderr,"Image: %s\n", file);
+ fprintf(stderr,"Image size %d %d\n", map_image_width, map_image_height);
+#if (MagickLibVersion < 0x0540)
+ fprintf(stderr,"Unique colors = %d\n", GetNumberColors(image, NULL));
+#else // MagickLib < 540
+ fprintf(stderr,"Unique colors = %ld\n", GetNumberColors(image, NULL, &exception));
+#endif // MagickLib < 540
+ fprintf(stderr,"image matte is %i\n", image->matte);
+ } // debug_level & 512
+
+ draw_OSM_image(w, image, &exception, &(tp[0]), &(tp[1]), osm_zl);
+ DestroyImage(image);
+
+ // Display the OpenStreetMap attribution
+ xastir_snprintf(OSMtmp, sizeof(OSMtmp),
+ "%s/CC_OpenStreetMap.png", get_data_base_dir("maps"));
+ strncpy(image_info->filename, OSMtmp, MaxTextExtent);
+
+ image = ReadImage(image_info,&exception);
+ if (exception.severity != UndefinedException) {
+ CatchException(&exception);
+ } else {
+ draw_image(w, image, &exception, 4, 4);
+ }
+
+
+ // Clean up
+ if (image) {
+ DestroyImage(image);
+ }
+ if (image_info) {
+ DestroyImageInfo(image_info);
+ }
+ DestroyExceptionInfo(&exception);
+
+} // end draw_OSM_map()
+
+
+#endif //HAVE_MAGICK
+///////////////////////////////////////////// End of OpenStreetMap code ///////////////////////////////////////
+
+
+
diff --git a/src/map_OSM.h b/src/map_OSM.h
new file mode 100644
index 0000000..8324ff2
--- /dev/null
+++ b/src/map_OSM.h
@@ -0,0 +1,60 @@
+/*
+ * $Id: map_OSM.h,v 1.6 2012/11/01 18:57:19 we7u Exp $
+ *
+ * Copyright (C) 2012 The Xastir Group
+ *
+ * This file was contributed by Jerry Dunmire, KA6HLD.
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ *
+ */
+#ifndef OSM_H
+#define OSM_H
+
+#include <X11/X.h> // for KeySym
+
+#define MAX_OSMSTYLE 1000 // max characters in the a OSM style argument
+#define MAX_OSM_URL 1000 // max characters for a OSM URL
+#define MAX_OSMEXT 10 // max characters for a tilename extension
+
+void adj_to_OSM_level(
+ long *new_scale_x,
+ long *new_scale_y);
+
+void draw_OSM_map(Widget w,
+ char *filenm,
+ int destination_pixmap,
+ char *url,
+ char *style,
+ int nocache);
+
+void draw_OSM_tiles(Widget w,
+ char *filenm,
+ int destination_pixmap,
+ char *server_url,
+ char *tileCacheDir,
+ char *mapName,
+ char *tileExt);
+
+unsigned int osm_zoom_level(long scale_x);
+void init_OSM_values(void);
+int OSM_optimize_key(KeySym key);
+void set_OSM_optimize_key(KeySym key);
+int OSM_report_scale_key(KeySym key);
+void set_OSM_report_scale_key(KeySym key);
+
+#endif //OSM_H
diff --git a/src/map_WMS.c b/src/map_WMS.c
new file mode 100644
index 0000000..db1359b
--- /dev/null
+++ b/src/map_WMS.c
@@ -0,0 +1,1042 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: map_WMS.c,v 1.42 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <dirent.h>
+#include <netinet/in.h>
+#include <Xm/XmAll.h>
+
+#ifdef HAVE_X11_XPM_H
+#include <X11/xpm.h>
+#ifdef HAVE_LIBXPM // if we have both, prefer the extra library
+#undef HAVE_XM_XPMI_H
+#endif // HAVE_LIBXPM
+#endif // HAVE_X11_XPM_H
+
+#ifdef HAVE_XM_XPMI_H
+#include <Xm/XpmI.h>
+#endif // HAVE_XM_XPMI_H
+
+#include <X11/Xlib.h>
+
+#include <math.h>
+
+#include "xastir.h"
+#include "maps.h"
+#include "alert.h"
+#include "fetch_remote.h"
+#include "util.h"
+#include "main.h"
+#include "datum.h"
+#include "draw_symbols.h"
+#include "rotated.h"
+#include "color.h"
+#include "xa_config.h"
+
+#include "map_cache.h"
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+#ifdef HAVE_MAGICK
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+#undef RETSIGTYPE
+// TVR: "stupid ImageMagick"
+// The problem is that magick/api.h includes Magick's config.h file, and that
+// pulls in all the same autoconf-generated defines that we use.
+// plays those games below, but I don't think in the end that they actually
+// make usable macros with our own data in them.
+// Fortunately, we don't need them, so I'll just undef the ones that are
+// causing problems today. See main.c for fixes that preserve our values.
+#undef PACKAGE
+#undef VERSION
+/* JMT - stupid ImageMagick */
+#define XASTIR_PACKAGE_BUGREPORT PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#define XASTIR_PACKAGE_NAME PACKAGE_NAME
+#undef PACKAGE_NAME
+#define XASTIR_PACKAGE_STRING PACKAGE_STRING
+#undef PACKAGE_STRING
+#define XASTIR_PACKAGE_TARNAME PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#define XASTIR_PACKAGE_VERSION PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#ifdef HAVE_GRAPHICSMAGICK
+/*#include <GraphicsMagick/magick/api.h>*/
+#include <magick/api.h>
+#else // HAVE_GRAPHICSMAGICK
+#include <magick/api.h>
+#endif // HAVE_GRAPHICSMAGICK
+#undef PACKAGE_BUGREPORT
+#define PACKAGE_BUGREPORT XASTIR_PACKAGE_BUGREPORT
+#undef XASTIR_PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#define PACKAGE_NAME XASTIR_PACKAGE_NAME
+#undef XASTIR_PACKAGE_NAME
+#undef PACKAGE_STRING
+#define PACKAGE_STRING XASTIR_PACKAGE_STRING
+#undef XASTIR_PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#define PACKAGE_TARNAME XASTIR_PACKAGE_TARNAME
+#undef XASTIR_PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#define PACKAGE_VERSION XASTIR_PACKAGE_VERSION
+#undef XASTIR_PACKAGE_VERSION
+#endif // HAVE_MAGICK
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+/**********************************************************
+ * draw_WMS_map()
+ **********************************************************/
+#ifdef HAVE_MAGICK
+void draw_WMS_map (Widget w,
+ char *filenm,
+ int destination_pixmap,
+ char *URL,
+ transparent_color_record *c_trans_color_head,
+ int nocache) { // If non-zero, don't use cached version
+
+
+ char file[MAX_FILENAME]; // Complete path/name of image file
+ char short_filenm[MAX_FILENAME];
+ FILE *f; // Filehandle of image file
+ char fileimg[MAX_FILENAME]; // Ascii name of image file, read from GEO file
+ char WMStmp[MAX_FILENAME*2]; // Used for putting together the WMS map query
+ int width, height;
+ tiepoint tp[2]; // Calibration points for map, read in from .geo file
+ register long map_c_T, map_c_L; // map delta NW edge coordinates, DNN: these should be signed
+ register long tp_c_dx, tp_c_dy; // tiepoint coordinate differences
+ unsigned long c_x_min, c_y_min;// top left coordinates of map inside screen
+ unsigned long c_y_max; // bottom right coordinates of map inside screen
+ double c_x; // Xastir coordinates 1/100 sec, 0 = 180�W
+ double c_y; // Xastir coordinates 1/100 sec, 0 = 90�N
+
+ long map_y_0; // map pixel pointer prior to TM adjustment
+ register long map_x, map_y; // map pixel pointers, DNN: this was a float, chg to long
+ long map_x_min, map_x_max; // map boundaries for in screen part of map
+ long map_y_min, map_y_max; //
+ long map_x_ctr; // half map width in pixel
+ long map_y_ctr; // half map height in pixel
+ int map_seen = 0;
+ int map_act;
+ int map_done;
+
+ long map_c_yc; // map center, vert coordinate
+ long map_c_xc; // map center, hor coordinate
+ double map_c_dx, map_c_dy; // map coordinates increment (pixel width)
+ double c_dx; // adjusted map pixel width
+
+ long scr_x, scr_y; // screen pixel plot positions
+ long scr_xp, scr_yp; // previous screen plot positions
+ int scr_dx, scr_dy; // increments in screen plot positions
+ long scr_x_mc; // map center in screen units
+
+ long scr_c_xr;
+
+ long scale_xa; // adjusted for topo maps
+ double scale_x_nm; // nm per Xastir coordinate unit
+ long scale_x0; // at widest map area
+
+ char local_filename[MAX_FILENAME];
+ ExceptionInfo exception;
+ Image *image;
+ ImageInfo *image_info;
+ PixelPacket *pixel_pack;
+ PixelPacket temp_pack;
+ IndexPacket *index_pack;
+ int l;
+ XColor my_colors[256];
+ int trans_skip = 0; // skip transparent pixel
+ double left, right, top, bottom, map_width, map_height;
+ double lat_center = 0;
+ double long_center = 0;
+
+ char map_it[MAX_FILENAME];
+ char tmpstr[100];
+ int geo_image_width; // Image width from GEO file
+ int geo_image_height; // Image height from GEO file
+
+ time_t query_start_time, query_end_time;
+
+#ifdef USE_MAP_CACHE
+ int map_cache_return;
+ char * cache_file_id;
+#endif // USE_MAP_CACHE
+
+ char temp_file_path[MAX_VALUE];
+
+ if (debug_level & 512) {
+ if (nocache)
+ fprintf(stderr,"draw_WMS_map: NOCACHE selected\n");
+ else
+ fprintf(stderr,"draw_WMS_map: CACHING if enabled\n");
+ }
+
+ // Create a shorter filename for display (one that fits the
+ // status line more closely). Subtract the length of the
+ // "Indexing " and/or "Loading " strings as well.
+ if (strlen(filenm) > (41 - 9)) {
+ int avail = 41 - 11;
+ int new_len = strlen(filenm) - avail;
+
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "..%s",
+ &filenm[new_len]);
+ }
+ else {
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "%s",
+ filenm);
+ }
+
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ langcode ("BBARSTA028"),
+ short_filenm);
+ statusline(map_it,0); // Loading ...
+
+
+
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ // We're indexing only. Save the extents in the index.
+ // Force the extents to the edges of the earth for the
+ // index file.
+ index_update_xastir(filenm, // Filename only
+ 64800000l, // Bottom
+ 0l, // Top
+ 0l, // Left
+ 129600000l, // Right
+ 0); // Default Map Level
+
+ // Update statusline
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ langcode ("BBARSTA039"),
+ short_filenm);
+ statusline(map_it,0); // Loading/Indexing ...
+
+ return; // Done indexing this file
+ }
+
+
+ // Tiepoint for upper left screen corner
+ //
+ tp[0].img_x = 0; // Pixel Coordinates
+ tp[0].img_y = 0; // Pixel Coordinates
+ tp[0].x_long = NW_corner_longitude; // Xastir Coordinates
+ tp[0].y_lat = NW_corner_latitude; // Xastir Coordinates
+
+
+ // Tiepoint for lower right screen corner
+ //
+ // Here we must use scale_x for both directions because we have
+ // square pixels returned by the WMS server.
+
+
+// Really what we want to do here is to change our bounding box for
+// our request to fit square pixels, using scale_x for both
+// dimensions, and to change our tiepoints to match. WMS servers
+// currently feed us back square pixels but the spec says that the
+// servers should be capable of sending back rectangular pixels, so
+// the images we get back may change if we don't request square
+// pixels each time.
+//
+// TODO: Change our imagesize, bounding rectangle requested, and
+// tiepoints to fit square pixels and to use scale_x for both
+// dimensions.
+//
+// Actually, looking at the changes that were made, it looks like we
+// _are_ using square pixels and requesting a bounding box based on
+// scale_x for both dimensions, so we might be good to go as-is.
+
+
+ //
+ tp[1].img_x = screen_width - 1; // Pixel Coordinates
+ tp[1].img_y = screen_height - 1; // Pixel Coordinates
+ tp[1].x_long = SE_corner_longitude; // Xastir Coordinates
+
+// Modified to use same scale (scale_x) for both dimensions, square
+// pixels. Don't use SE_corner_latitude here as it uses scale_y!
+// tp[1].y_lat = NW_corner_latitude + ((screen_height) * scale_y); // Xastir Coordinates
+ tp[1].y_lat = NW_corner_latitude + ((screen_height) * scale_x); // Xastir Coordinates
+
+
+ // Again, use scale_x for both directions due to the square
+ // pixels returned from the WMS server.
+ //
+ left = (double)((NW_corner_longitude - 64800000l )/360000.0); // Lat/long Coordinates
+ top = (double)(-((NW_corner_latitude - 32400000l )/360000.0)); // Lat/long Coordinates
+ right = (double)((SE_corner_longitude - 64800000l)/360000.0);//Lat/long Coordinates
+
+// Modified to use same scale (scale_x) for both dimensions, square
+// pixels. Don't use SE_corner_latitude here as it uses scale_y!
+// bottom = (double)(-(((NW_corner_latitude + ((screen_height) * scale_y) ) - 32400000l)/360000.0));//Lat/long Coordinates
+ bottom = (double)(-(((NW_corner_latitude + ((screen_height) * scale_x) ) - 32400000l)/360000.0));//Lat/long Coordinates
+
+
+ map_width = right - left; // Lat/long Coordinates
+ map_height = top - bottom; // Lat/long Coordinates
+
+ geo_image_width = screen_width;
+ geo_image_height = screen_height;
+
+ long_center = (left + right)/2.0l;
+ lat_center = (top + bottom)/2.0l;
+
+
+// Example query for a WMS map server....
+// xastir_snprintf(fileimg, sizeof(fileimg),
+// "\'http://mesonet.tamu.edu/cgi-bin/p-warn?SERVICE=WMS&VERSION=1.1.1&REQUEST=getmap&layers=radar&BBOX=-129.000,52.500,-111.000,42.500&HEIGHT=1000&WIDTH=1800&FORMAT=image/png\'");
+
+
+// xastir_snprintf(WMStmp, sizeof(WMStmp),
+// "http://mesonet.tamu.edu/cgi-bin/p-warn?SERVICE=WMS&VERSION=1.1.1&REQUEST=getmap");
+
+
+ xastir_snprintf(WMStmp, sizeof(WMStmp), "%s", URL);
+ strncat(WMStmp, "&REQUEST=getmap", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ strncat(WMStmp, "&EXCEPTIONS=INIMAGE", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+// This specifies a bounding box based on square pixels.
+ xastir_snprintf(tmpstr, sizeof(tmpstr),
+ "&BBOX=%8.5f,%7.5f,%8.5f,%7.5f",
+ left, // Lower left
+ bottom, // Lower left
+ right, // Upper right
+ top); // Upper right
+ strncat (WMStmp, tmpstr, sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ xastir_snprintf(tmpstr, sizeof(tmpstr), "&HEIGHT=%d", geo_image_height);
+ strncat (WMStmp, tmpstr, sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ xastir_snprintf(tmpstr, sizeof(tmpstr), "&WIDTH=%d", geo_image_width);
+ strncat (WMStmp, tmpstr, sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+
+// These should be specified in the .geo file instead of hard-coded:
+//
+// strncat(WMStmp, "&VERSION=1.0.0", sizeof(WMStmp) - 1 - strlen(WMStmp));
+// strncat(WMStmp, "&FORMAT=image/png", sizeof(WMStmp) - 1 - strlen(WMStmp));
+// strncat(WMStmp, "&TRANSPARENT=TRUE", sizeof(WMStmp) - 1 - strlen(WMStmp));
+// strncat(WMStmp, "&BGCOLOR=0xffffff", sizeof(WMStmp) - 1 - strlen(WMStmp));
+// strncat(WMStmp, "&BGCOLOR=0x000000", sizeof(WMStmp) - 1 - strlen(WMStmp));
+// strncat(WMStmp, "&CRS=CRS:84", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+
+
+
+
+/*
+ xastir_snprintf(WMStmp, sizeof(WMStmp), "http://tiger.census.gov/cgi-bin/mapper/map.png?");
+
+ if (tiger_show_grid)
+ strncat(WMStmp, "&on=GRID", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ else
+ strncat(WMStmp, "&off=GRID", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ if (tiger_show_counties)
+ strncat(WMStmp, "&on=counties", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ else
+ strncat(WMStmp, "&off=counties", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ if (tiger_show_cities)
+ strncat(WMStmp, "&on=CITIES", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ else
+ strncat(WMStmp, "&off=CITIES", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ if (tiger_show_places)
+ strncat(WMStmp, "&on=places", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ else
+ strncat(WMStmp, "&off=places", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ if (tiger_show_majroads)
+ strncat(WMStmp, "&on=majroads", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ else
+ strncat(WMStmp, "&off=majroads", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ if (tiger_show_streets)
+ strncat(WMStmp, "&on=streets", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ // Don't turn streets off since this will automagically show up as you zoom in.
+
+ if (tiger_show_railroad)
+ strncat(WMStmp, "&on=railroad", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ else
+ strncat(WMStmp, "&off=railroad", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ if (tiger_show_states)
+ strncat(WMStmp, "&on=states", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ else
+ strncat(WMStmp, "&off=states", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ if (tiger_show_interstate)
+ strncat(WMStmp, "&on=interstate", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ else
+ strncat(WMStmp, "&off=interstate", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ if (tiger_show_ushwy)
+ strncat(WMStmp, "&on=ushwy", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ else
+ strncat(WMStmp, "&off=ushwy", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ if (tiger_show_statehwy)
+ strncat(WMStmp, "&on=statehwy", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ else
+ strncat(WMStmp, "&off=statehwy", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ if (tiger_show_water)
+ strncat(WMStmp, "&on=water", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ else
+ strncat(WMStmp, "&off=water", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ if (tiger_show_lakes)
+ strncat(WMStmp, "&on=shorelin", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ else
+ strncat(WMStmp, "&off=shorelin", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ if (tiger_show_misc)
+ strncat(WMStmp, "&on=miscell", sizeof(WMStmp) - 1 - strlen(WMStmp));
+ else
+ strncat(WMStmp, "&off=miscell", sizeof(WMStmp) - 1 - strlen(WMStmp));
+
+ xastir_snprintf(tmpstr, sizeof(tmpstr), "&lat=%f\046lon=%f\046", lat_center, long_center);
+ strncat (WMStmp, tmpstr, sizeof(WMStmp) - 1 - strlen(WMStmp));
+ xastir_snprintf(tmpstr, sizeof(tmpstr), "wid=%f\046ht=%f\046", map_width, map_height);
+ strncat (WMStmp, tmpstr, sizeof(WMStmp) - 1 - strlen(WMStmp));
+ xastir_snprintf(tmpstr, sizeof(tmpstr), "iwd=%i\046iht=%i", tp[1].img_x + 1, tp[1].img_y + 1);
+ strncat (WMStmp, tmpstr, sizeof(WMStmp) - 1 - strlen(WMStmp)); */
+
+
+ xastir_snprintf(fileimg, sizeof(fileimg), "%s", WMStmp);
+
+ if (debug_level & 512) {
+ fprintf(stderr,"left side is %f\n", left);
+ fprintf(stderr,"right side is %f\n", right);
+ fprintf(stderr,"top is %f\n", top);
+ fprintf(stderr,"bottom is %f\n", bottom);
+ fprintf(stderr,"lat center is %f\n", lat_center);
+ fprintf(stderr,"long center is %f\n", long_center);
+ fprintf(stderr,"screen width is %li\n", screen_width);
+ fprintf(stderr,"screen height is %li\n", screen_height);
+ fprintf(stderr,"map width is %f\n", map_width);
+ fprintf(stderr,"map height is %f\n", map_height);
+ fprintf(stderr,"fileimg is %s\n", fileimg);
+ fprintf(stderr,"ftp or http file: %s\n", fileimg);
+ }
+
+ if (debug_level & 512) {
+ query_start_time=time(&query_start_time);
+ }
+
+
+#ifdef USE_MAP_CACHE
+
+ if (nocache || map_cache_fetch_disable) {
+
+ // Delete old copy from the cache
+ if (map_cache_fetch_disable && fileimg[0] != '\0') {
+ if (map_cache_del(fileimg)) {
+ if (debug_level & 512) {
+ fprintf(stderr,"Couldn't delete old map from cache\n");
+ }
+ }
+ }
+
+ // Simulate a cache miss
+ map_cache_return = 1;
+ }
+ else {
+ // Else look for the file in the cache
+ map_cache_return = map_cache_get(fileimg,local_filename);
+ }
+
+ if (debug_level & 512) {
+ fprintf(stderr,"map_cache_return: %d\n", map_cache_return);
+ }
+
+
+ // Don't use cached version if "nocache" is non-zero
+ //
+ if (nocache || map_cache_return != 0 ) {
+ // Caching has not been requested or cached file not found.
+ // We must snag the remote file via libcurl or wget.
+
+ if (nocache) {
+ xastir_snprintf(local_filename,
+ sizeof(local_filename),
+ "%s/map.%s",
+ get_user_base_dir("tmp", temp_file_path, sizeof(temp_file_path)),
+ "png");
+ }
+ else {
+ cache_file_id = map_cache_fileid();
+ xastir_snprintf(local_filename,
+ sizeof(local_filename),
+ "%s/map_%s.%s",
+ get_user_base_dir("map_cache", temp_file_path, sizeof(temp_file_path)),
+ cache_file_id,
+ "png");
+ free(cache_file_id);
+ }
+
+#else // USE_MAP_CACHE
+
+ xastir_snprintf(local_filename,
+ sizeof(local_filename),
+ "%s/map.%s",
+ get_user_base_dir("tmp", temp_file_path, sizeof(temp_file_path)),
+ "png");
+
+#endif // USE_MAP_CACHE
+
+
+ // Erase any previously existing local file by the same name.
+ // This avoids the problem of having an old map image here and
+ // the code trying to display it when the download fails.
+
+ unlink( local_filename );
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ if (fetch_remote_file(fileimg, local_filename)) {
+ // Had trouble getting the file. Abort.
+ return;
+ }
+
+ // For debugging the MagickError/MagickWarning segfaults.
+ //system("cat /dev/null >/var/tmp/xastir_hacker_map.png");
+
+
+#ifdef USE_MAP_CACHE
+
+ // Cache this map only if nocache is zero
+ if (!nocache) {
+ map_cache_put(fileimg,local_filename);
+ }
+
+ } // end if is cached DHBROWN
+#endif // USE_MAP_CACHE
+
+
+ if (debug_level & 512) {
+ fprintf (stderr, "Fetch or query took %d seconds\n",
+ (int) (time(&query_end_time) - query_start_time));
+ }
+
+ // Set permissions on the file so that any user can overwrite it.
+ chmod(local_filename, 0666);
+
+ // Tell ImageMagick where to find it
+ xastir_snprintf(file,
+ sizeof(file),
+ "%s",
+ local_filename);
+
+ GetExceptionInfo(&exception);
+
+ image_info=CloneImageInfo((ImageInfo *) NULL);
+
+ xastir_snprintf(image_info->filename,
+ sizeof(image_info->filename),
+ "%s",
+ file);
+
+ if (debug_level & 512) {
+ fprintf(stderr,"Copied %s into image info.\n", file);
+ fprintf(stderr,"image_info got: %s\n", image_info->filename);
+ fprintf(stderr,"Entered ImageMagick code.\n");
+ fprintf(stderr,"Attempting to open: %s\n", image_info->filename);
+ }
+
+ // We do a test read first to see if the file exists, so we
+ // don't kill Xastir in the ReadImage routine.
+ f = fopen (image_info->filename, "r");
+ if (f == NULL) {
+ if (debug_level & 512)
+ fprintf(stderr,"File could not be read\n");
+
+#ifdef USE_MAP_CACHE
+ // clear from cache if bad
+ if (map_cache_del(fileimg)) {
+ if (debug_level & 512) {
+ fprintf(stderr,"Couldn't delete map from cache\n");
+ }
+ }
+#endif
+
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+ (void)fclose (f);
+
+
+ image = ReadImage(image_info, &exception);
+
+ if (image == (Image *) NULL) {
+ MagickWarning(exception.severity, exception.reason, exception.description);
+ //fprintf(stderr,"MagickWarning\n");
+
+#ifdef USE_MAP_CACHE
+ // clear from cache if bad
+ if (map_cache_del(fileimg)) {
+ if (debug_level & 512) {
+ fprintf(stderr,"Couldn't delete map from cache\n");
+ }
+ }
+#endif
+
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+
+ if (debug_level & 512)
+ fprintf(stderr,"Color depth is %i \n", (int)image->depth);
+
+ if (image->colorspace != RGBColorspace) {
+ fprintf(stderr,"TBD: I don't think we can deal with colorspace != RGB");
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+ width = image->columns;
+ height = image->rows;
+
+ // Code to mute the image so it's not as bright.
+/* if (raster_map_intensity < 1.0) {
+ char tempstr[30];
+
+ if (debug_level & 512)
+ fprintf(stderr,"level=%s\n", tempstr);
+
+ xastir_snprintf(tempstr,
+ sizeof(tempstr),
+ "%d, 100, 100",
+ (int)(raster_map_intensity * 100.0));
+
+ ModulateImage(image, tempstr);
+ }
+*/
+
+
+ // If were are drawing to a low bpp display (typically < 8bpp)
+ // try to reduce the number of colors in an image.
+ // This may take some time, so it would be best to do ahead of
+ // time if it is a static image.
+#if (MagickLibVersion < 0x0540)
+ if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL) > 128) {
+#else // MagickLib >= 540
+ if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL, &exception) > 128) {
+#endif // MagickLib Version
+
+ if (image->storage_class == PseudoClass) {
+#if (MagickLibVersion < 0x0549)
+ CompressColormap(image); // Remove duplicate colors
+#else // MagickLib >= 0x0549
+ CompressImageColormap(image); // Remove duplicate colors
+#endif // MagickLibVersion < 0x0549
+ }
+
+ // Quantize down to 128 will go here...
+ }
+
+
+ pixel_pack = GetImagePixels(image, 0, 0, image->columns, image->rows);
+ if (!pixel_pack) {
+ fprintf(stderr,"pixel_pack == NULL!!!");
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+
+ index_pack = GetIndexes(image);
+ if (image->storage_class == PseudoClass && !index_pack) {
+ fprintf(stderr,"PseudoClass && index_pack == NULL!!!");
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+
+ if (image->storage_class == PseudoClass && image->colors <= 256) {
+ for (l = 0; l < (int)image->colors; l++) {
+ // Need to check how to do this for ANY image, as ImageMagick can read in all sorts
+ // of image files
+ temp_pack = image->colormap[l];
+ if (debug_level & 512)
+ fprintf(stderr,"Colormap color is %i %i %i \n",
+ temp_pack.red, temp_pack.green, temp_pack.blue);
+
+ // Here's a tricky bit: PixelPacket entries are defined as Quantum's. Quantum
+ // is defined in /usr/include/magick/image.h as either an unsigned short or an
+ // unsigned char, depending on what "configure" decided when ImageMagick was installed.
+ // We can determine which by looking at MaxRGB or QuantumDepth.
+ //
+ if (QuantumDepth == 16) { // Defined in /usr/include/magick/image.h
+ if (debug_level & 512)
+ fprintf(stderr,"Color quantum is [0..65535]\n");
+ my_colors[l].red = temp_pack.red * raster_map_intensity;
+ my_colors[l].green = temp_pack.green * raster_map_intensity;
+ my_colors[l].blue = temp_pack.blue * raster_map_intensity;
+ }
+ else { // QuantumDepth = 8
+ if (debug_level & 512)
+ fprintf(stderr,"Color quantum is [0..255]\n");
+ my_colors[l].red = (temp_pack.red << 8) * raster_map_intensity;
+ my_colors[l].green = (temp_pack.green << 8) * raster_map_intensity;
+ my_colors[l].blue = (temp_pack.blue << 8) * raster_map_intensity;
+ }
+
+ // Get the color allocated on < 8bpp displays. pixel color is written to my_colors.pixel
+ if (visual_type == NOT_TRUE_NOR_DIRECT) {
+// XFreeColors(XtDisplay(w), cmap, &(my_colors[l].pixel),1,0);
+ XAllocColor(XtDisplay(w), cmap, &my_colors[l]);
+ }
+ else {
+ pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue,
+ &my_colors[l].pixel);
+ }
+
+ if (debug_level & 512)
+ fprintf(stderr,"Color allocated is %li %i %i %i \n", my_colors[l].pixel,
+ my_colors[l].red, my_colors[l].blue, my_colors[l].green);
+ }
+ }
+
+
+
+ /*
+ * Here are the corners of our viewport, using the Xastir
+ * coordinate system. Notice that Y is upside down:
+ *
+ * left edge of view = NW_corner_longitude
+ * right edge of view = SE_corner_longitude
+ * top edge of view = NW_corner_latitude
+ * bottom edge of view = SE_corner_latitude
+ *
+ * The corners of our map will soon be (after translating the
+ * tiepoints to the corners if they're not already there):
+ *
+ * left edge of map = tp[0].x_long in Xastir format
+ * right edge of map = tp[1].x_long
+ * top edge of map = tp[0].y_lat
+ * bottom edge of map = tp[1].y_lat
+ *
+ */
+ map_c_L = tp[0].x_long - NW_corner_longitude; // map left coordinate
+ map_c_T = tp[0].y_lat - NW_corner_latitude; // map top coordinate
+
+ tp_c_dx = (long)(tp[1].x_long - tp[0].x_long);// Width between tiepoints
+ tp_c_dy = (long)(tp[1].y_lat - tp[0].y_lat); // Height between tiepoints
+
+
+ // Check for tiepoints being in wrong relation to one another
+ if (tp_c_dx < 0)
+ tp_c_dx = -tp_c_dx; // New width between tiepoints
+ if (tp_c_dy < 0)
+ tp_c_dy = -tp_c_dy; // New height between tiepoints
+
+ // Calculate step size per pixel
+ map_c_dx = ((double) tp_c_dx / abs(tp[1].img_x - tp[0].img_x));
+ map_c_dy = ((double) tp_c_dy / abs(tp[1].img_y - tp[0].img_y));
+
+ // Scaled screen step size for use with XFillRectangle below
+ scr_dx = (int) (map_c_dx / scale_x) + 1;
+ scr_dy = (int) (map_c_dy / scale_y) + 1;
+
+ // calculate top left map corner from tiepoints
+ if (tp[0].img_x != 0) {
+ tp[0].x_long -= (tp[0].img_x * map_c_dx); // map left edge longitude
+ map_c_L = tp[0].x_long - NW_corner_longitude; // delta ??
+ tp[0].img_x = 0;
+ if (debug_level & 512)
+ fprintf(stderr,"Translated tiepoint_0 x: %d\t%lu\n", tp[0].img_x, tp[0].x_long);
+ }
+ if (tp[0].img_y != 0) {
+ tp[0].y_lat -= (tp[0].img_y * map_c_dy); // map top edge latitude
+ map_c_T = tp[0].y_lat - NW_corner_latitude;
+ tp[0].img_y = 0;
+ if (debug_level & 512)
+ fprintf(stderr,"Translated tiepoint_0 y: %d\t%lu\n", tp[0].img_y, tp[0].y_lat);
+ }
+
+ // calculate bottom right map corner from tiepoints
+ // map size is geo_image_width / geo_image_height
+ if (tp[1].img_x != (geo_image_width - 1) ) {
+ tp[1].img_x = geo_image_width - 1;
+ tp[1].x_long = tp[0].x_long + (tp[1].img_x * map_c_dx); // right
+ if (debug_level & 512)
+ fprintf(stderr,"Translated tiepoint_1 x: %d\t%lu\n", tp[1].img_x, tp[1].x_long);
+ }
+ if (tp[1].img_y != (geo_image_height - 1) ) {
+ tp[1].img_y = geo_image_height - 1;
+ tp[1].y_lat = tp[0].y_lat + (tp[1].img_y * map_c_dy); // bottom
+ if (debug_level & 512)
+ fprintf(stderr,"Translated tiepoint_1 y: %d\t%lu\n", tp[1].img_y, tp[1].y_lat);
+ }
+
+ if (debug_level & 512) {
+ fprintf(stderr,"X tiepoint width: %ld\n", tp_c_dx);
+ fprintf(stderr,"Y tiepoint width: %ld\n", tp_c_dy);
+ fprintf(stderr,"Loading imagemap: %s\n", file);
+ fprintf(stderr,"\nImage: %s\n", file);
+ fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height);
+ fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n",
+ map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y));
+ fprintf(stderr,"Image size %d %d\n", width, height);
+#if (MagickLibVersion < 0x0540)
+ fprintf(stderr,"Unique colors = %d\n", GetNumberColors(image, NULL));
+#else // MagickLib < 540
+ fprintf(stderr,"Unique colors = %ld\n", GetNumberColors(image, NULL, &exception));
+#endif // MagickLib < 540
+ fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T,
+ map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y));
+ fprintf(stderr,"image matte is %i\n", image->matte);
+ } // debug_level & 512
+
+ // draw the image from the file out to the map screen
+
+ // Get the border values for the X and Y for loops used
+ // for the XFillRectangle call later.
+
+ map_c_yc = (tp[0].y_lat + tp[1].y_lat) / 2; // vert center of map as reference
+ map_y_ctr = (long)(height / 2 +0.499);
+ scale_x0 = get_x_scale(0,map_c_yc,scale_y); // reference scaling at vert map center
+
+ map_c_xc = (tp[0].x_long + tp[1].x_long) / 2; // hor center of map as reference
+ map_x_ctr = (long)(width / 2 +0.499);
+ scr_x_mc = (map_c_xc - NW_corner_longitude) / scale_x; // screen coordinates of map center
+
+ // calculate map pixel range in y direction that falls into screen area
+ c_y_max = 0ul;
+ map_y_min = map_y_max = 0l;
+ for (map_y_0 = 0, c_y = tp[0].y_lat; map_y_0 < (long)height; map_y_0++, c_y += map_c_dy) {
+ scr_y = (c_y - NW_corner_latitude) / scale_y; // current screen position
+ if (scr_y > 0) {
+ if (scr_y < screen_height) {
+ map_y_max = map_y_0; // update last map pixel in y
+ c_y_max = (unsigned long)c_y;// bottom map inside screen coordinate
+ } else
+ break; // done, reached bottom screen border
+ } else { // pixel is above screen
+ map_y_min = map_y_0; // update first map pixel in y
+ }
+ }
+ c_y_min = (unsigned long)(tp[0].y_lat + map_y_min * map_c_dy); // top map inside screen coordinate
+
+ map_x_min = map_x_max = 0l;
+ for (map_x = 0, c_x = tp[0].x_long; map_x < (long)width; map_x++, c_x += map_c_dx) {
+ scr_x = (c_x - NW_corner_longitude)/ scale_x; // current screen position
+ if (scr_x > 0) {
+ if (scr_x < screen_width)
+ map_x_max = map_x; // update last map pixel in x
+ else
+ break; // done, reached right screen border
+ } else { // pixel is left from screen
+ map_x_min = map_x; // update first map pixel in x
+ }
+ }
+ c_x_min = (unsigned long)(tp[0].x_long + map_x_min * map_c_dx); // left map inside screen coordinate
+
+ scr_yp = -1;
+ scr_c_xr = SE_corner_longitude;
+ c_dx = map_c_dx; // map pixel width
+ scale_xa = scale_x0; // the compiler likes it ;-)
+
+ map_done = 0;
+ map_act = 0;
+ map_seen = 0;
+ scr_y = screen_height - 1;
+
+
+ // loop over map pixel rows
+ for (map_y_0 = map_y_min, c_y = (double)c_y_min; (map_y_0 <= map_y_max); map_y_0++, c_y += map_c_dy) {
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ scr_y = (c_y - NW_corner_latitude) / scale_y;
+ if (scr_y != scr_yp) { // don't do a row twice
+ scr_yp = scr_y; // remember as previous y
+ scr_xp = -1;
+ // loop over map pixel columns
+ map_act = 0;
+ scale_x_nm = calc_dscale_x(0,(long)c_y) / 1852.0; // nm per Xastir coordinate
+ for (map_x = map_x_min, c_x = (double)c_x_min; map_x <= map_x_max; map_x++, c_x += c_dx) {
+ scr_x = (c_x - NW_corner_longitude) / scale_x;
+ if (scr_x != scr_xp) { // don't do a pixel twice
+ scr_xp = scr_x; // remember as previous x
+ map_y = map_y_0;
+
+ if (map_y >= 0 && map_y <= tp[1].img_y) { // check map boundaries in y direction
+ map_seen = 1;
+ map_act = 1; // detects blank screen rows (end of map)
+
+ // now copy a pixel from the map image to the screen
+ l = map_x + map_y * image->columns;
+ trans_skip = 1; // possibily transparent
+ if (image->storage_class == PseudoClass) {
+ if ( c_trans_color_head &&
+ check_trans(my_colors[index_pack[l]],c_trans_color_head)) {
+ trans_skip = 1; // skip it
+ }
+ else {
+ XSetForeground(XtDisplay(w), gc, my_colors[index_pack[l]].pixel);
+ trans_skip = 0; // draw it
+ }
+ }
+ else {
+ // It is not safe to assume that the red/green/blue
+ // elements of pixel_pack of type Quantum are the
+ // same as the red/green/blue of an XColor!
+ if (QuantumDepth==16) {
+ my_colors[0].red=pixel_pack[l].red;
+ my_colors[0].green=pixel_pack[l].green;
+ my_colors[0].blue=pixel_pack[l].blue;
+ }
+ else { // QuantumDepth=8
+ // shift the bits of the 8-bit quantity so that
+ // they become the high bigs of my_colors.*
+ my_colors[0].red=pixel_pack[l].red<<8;
+ my_colors[0].green=pixel_pack[l].green<<8;
+ my_colors[0].blue=pixel_pack[l].blue<<8;
+ }
+ // NOW my_colors has the right r,g,b range for
+ // pack_pixel_bits
+ pack_pixel_bits(my_colors[0].red * raster_map_intensity,
+ my_colors[0].green * raster_map_intensity,
+ my_colors[0].blue * raster_map_intensity,
+ &my_colors[0].pixel);
+ if ( c_trans_color_head &&
+ check_trans(my_colors[0],c_trans_color_head)) {
+ trans_skip = 1; // skip it
+ }
+ else {
+ XSetForeground(XtDisplay(w), gc, my_colors[0].pixel);
+ trans_skip = 0; // draw it
+ }
+ }
+
+ // Skip drawing if a transparent pixel
+ if (!trans_skip) {
+ (void)XFillRectangle (XtDisplay (w),pixmap,gc,scr_x,scr_y,scr_dx,scr_dy);
+ }
+
+ } // check map boundaries in y direction
+ }
+ } // loop over map pixel columns
+ if (map_seen && !map_act)
+ map_done = 1;
+ }
+ } // loop over map pixel rows
+
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+}
+#endif //HAVE_MAGICK
diff --git a/src/map_cache.c b/src/map_cache.c
new file mode 100644
index 0000000..2a074ea
--- /dev/null
+++ b/src/map_cache.c
@@ -0,0 +1,1059 @@
+/*
+ * $Id: map_cache.c,v 1.35 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+/*
+ * The code in this file is used to cache maps downloaded
+ * from tiger.census.gov, and to manage that cache. It was written
+ * to use Berkeley DB version 4 or better.
+ *
+ * Dan Brown N8YSZ.
+ *
+ */
+
+
+// Need this one before the #ifdef in order to get the definition of
+// USE_MAP_CACHE, if defined.
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+
+#ifdef USE_MAP_CACHE
+//#warning USE_MAP_CACHE Defined
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "snprintf.h"
+#include "xastir.h"
+#include "xa_config.h"
+#include "main.h"
+#include "maps.h"
+#include "map_cache.h"
+#include <db.h>
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+
+
+// This is used to temporarily disable fetching from the map cache.
+// Used for refreshing corrupted maps in the cache.
+int map_cache_fetch_disable = 0;
+
+
+// Used to disable map caching entirely if the header and dblib
+// versions don't match, in order to avoid segfaults when the map
+// caching is used.
+int map_cache_disabled = 0;
+
+
+
+
+
+// Here we do a run-time check to verify that the header file we
+// used to compile with is the same version as the shared library
+// we're currently linked with. To do otherwise often results in
+// segfaults.
+//
+void map_cache_init(void) {
+ int warn_now = 0;
+
+ if (strcmp( DB_VERSION_STRING, db_version(NULL,NULL,NULL) ) != 0) {
+ fprintf(stderr,
+ "\n\n***** WARNING *****\n");
+ fprintf(stderr,
+ "Berkeley DB header files/shared library file do NOT match!\n");
+ fprintf(stderr,
+ "Disabling use of the map cache.\n");
+
+
+// Can't bring up a popup here 'cuz we don't have any GUI running
+// yet by this point.
+// popup_message_always(langcode("POPEM00034"),langcode("POPEM00046"));
+
+
+ warn_now++;
+ map_cache_disabled++;
+ }
+
+ if (debug_level & 5 || warn_now) {
+
+ //fprintf(stderr,
+ // "Berkeley DB Library Header File Version %d.%d.%d\n",
+ // DB_VERSION_MAJOR,
+ // DB_VERSION_MINOR,
+ // DB_VERSION_PATCH);
+
+ fprintf(stderr,
+ " Header file: %s\n",
+ DB_VERSION_STRING);
+
+ fprintf(stderr,
+ "Library file: %s\n",
+ db_version(NULL,NULL,NULL) );
+ }
+
+ if (warn_now) {
+ fprintf(stderr,
+ "***** WARNING *****\n");
+ }
+}
+
+
+
+
+
+// map_cache_put()
+//
+// Inputs:
+//
+// Outputs:
+//
+int map_cache_put( char * map_cache_url, char * map_cache_file ){
+
+// Puts an entry into the url->filename database
+// Tracks space used in "CACHE_SPACE_USED"
+
+ char mc_database_filename[MAX_FILENAME];
+ int mc_ret, mc_t_ret, mc_file_stat, mc_space_used ;
+ DBT mc_key, mc_data ;
+ DB *dbp;
+ struct stat file_status;
+ char mc_buf[128];
+ char temp_file_path[MAX_VALUE];
+
+ if (map_cache_disabled) {
+ return(1);
+ }
+
+ mc_space_used=0;
+
+ xastir_snprintf(mc_database_filename,
+ sizeof(mc_database_filename),
+ "%s/map_cache.db",
+ get_user_base_dir("map_cache", temp_file_path, sizeof(temp_file_path)));
+
+ // check for reasonable filename
+ // expects file name like /home/brown/.xastir/map_cache/map_1100052372.gif
+ // 1234567890123456789012345678901234567
+
+ mc_ret=strlen(map_cache_file);
+
+ if ( mc_ret < 37 ) {
+ if (debug_level & 512 ) {
+ fprintf(stderr,
+ "map_cache_put: Unusable filename: %s. Skipping encaching\n",
+ (map_cache_file == NULL) ? "(null)" : map_cache_file);
+ }
+ return (-1 * mc_ret);
+ }
+
+// stat the file to see if we even need to bother
+
+ if ((mc_file_stat=stat(map_cache_file, &file_status)) !=0) {
+ if (debug_level & 512 ) {
+ fprintf(stderr,
+ "map_cache_put: File Error: %s. Skipping encaching\n",
+ (map_cache_file == NULL) ? "(null)" : map_cache_file);
+ }
+
+ return (mc_file_stat);
+ }
+
+ if ( debug_level & 512) {
+ fprintf (stderr, "map_cache_put: file_status.st_size %d\n",
+ (int) file_status.st_size);
+ }
+
+// Create handle to db
+
+ if ((mc_ret = db_create(&dbp, NULL, 0)) != 0) {
+ fprintf(stderr, "map_cache_put db_create:%s\n", db_strerror(mc_ret));
+ return(1);
+ }
+
+// open the db
+
+#if (DB_VERSION_MAJOR<4) /** DB_VERSION Check **/
+#error DB_VERSION_MAJOR < 4
+
+#elif (DB_VERSION_MAJOR==4 && DB_VERSION_MINOR<=0 )
+
+ if ((mc_ret = dbp->open(dbp,
+ mc_database_filename , NULL, DB_CREATE, DB_BTREE, 0664)) != 0) {
+
+ dbp->err(dbp, mc_ret, "%s", mc_database_filename);
+ db_strerror(mc_ret);
+ }
+#elif (DB_VERSION_MAJOR==4 && DB_VERSION_MINOR>=1 )
+
+ if ((mc_ret = dbp->open(dbp,
+ NULL,mc_database_filename, NULL, DB_CREATE, DB_BTREE, 0664)) != 0) {
+
+ dbp->err(dbp, mc_ret, "%s", mc_database_filename);
+ db_strerror(mc_ret);
+ }
+
+#endif /** DB_VERSION Check **/
+
+// Before we put something in we need to see if we got space
+
+// if mc_cache_size_limit
+
+// Setup for get
+
+ memset(&mc_key, 0, sizeof(mc_key));
+ memset(&mc_data, 0, sizeof(mc_data));
+
+ mc_key.data = "CACHE_SPACE_USED";
+ mc_key.size = sizeof("CACHE_SPACE_USED");
+
+// check "CACHE_SPACE_USED" record in db
+
+// mc_ret is assigned here but not used. Commented it out for now.
+ if (((/* mc_ret = */ dbp->get(dbp, NULL, &mc_key, &mc_data, 0)) == 0) && ( mc_data.data != NULL ) ) {
+
+ if ( debug_level & 512 ) {
+ fprintf(stderr, "map_cache_put: %s: key retrieved: data was %s.\n",
+ (mc_key.data == NULL) ? "(null)" : (char *)mc_key.data,
+ (mc_data.data == NULL) ? "(null)" : (char *)mc_data.data);
+ }
+
+ if (mc_data.data == NULL)
+ mc_space_used = 0;
+ else
+ mc_space_used = atoi( (char *)mc_data.data);
+
+ if ( debug_level & 512 ) {
+ fprintf (stderr, "map_cache_put: CACHE_SPACE_USED = %.2f mb\n",
+ (mc_space_used/1024/1024.0));
+ }
+
+ }
+ else {
+
+ if (mc_data.data == NULL) {
+ if ( debug_level & 512 ) {
+ fprintf (stderr, "map_cache_put: CACHE_SPACE_USED get returned null \n");
+ }
+ }
+ else {
+ if ( debug_level & 512 ) {
+ fprintf (stderr, "map_cache_put: Unable to check CACHE_SPACE_USED: %s\n",
+ db_strerror(mc_ret));
+ }
+ }
+
+ // for now let us assume this is the first map entry and we
+ // just flag an error. Better procedure for later might be to
+ // return(mc_ret) indicating a database error of some sort
+
+ }
+
+// xastir_snprintf(map_cache_file, MAX_FILENAME, "%s",(char *)mc_data.data);
+
+ if ( debug_level & 512 ) {
+ fprintf (stderr, "map_cache_put: mc_space_used before = %d bytes file_status.st_size %d\n",
+ mc_space_used,
+ (int) file_status.st_size);
+ }
+
+ mc_space_used += (int) file_status.st_size;
+
+ if ( debug_level & 512 ) {
+ fprintf (stderr, "map_cache_put: mc_space_used after = %d bytes \n",
+ mc_space_used);
+ }
+
+ if ( mc_space_used > MAP_CACHE_SPACE_LIMIT) {
+ if ( debug_level & 512 ) {
+ fprintf (stderr, "map_cache_put: Warning cache space used: %.2f mb NOW OVER LIMIT: %.2f mb\n",
+ (mc_space_used/1024/1024.0),
+ (MAP_CACHE_SPACE_LIMIT/1024/1024.0));
+ }
+
+// Cache Cleanup
+// The warning is nice, but we should do something here
+// Needs LRU and or FIFO db structures
+
+ }
+ else {
+
+// else put cache_space_used
+
+// setup
+
+ memset(&mc_key, 0, sizeof(mc_key));
+ memset(&mc_data, 0, sizeof(mc_data));
+
+// data
+
+ mc_key.data = "CACHE_SPACE_USED";
+ mc_key.size = sizeof("CACHE_SPACE_USED");
+
+ xastir_snprintf(mc_buf, sizeof(mc_buf), "%d", mc_space_used);
+
+ if ( debug_level & 512 ) {
+ fprintf (stderr, "map_cache_put: mc_buf: %s len %d\n",
+ mc_buf,(int) sizeof(mc_buf));
+ }
+
+ mc_data.data = mc_buf ;
+ mc_data.size = sizeof(mc_buf);
+
+// put
+
+ if ((mc_ret = dbp->put(dbp, NULL, &mc_key, &mc_data, 0)) == 0) {
+
+ if ( debug_level & 512 ) {
+ fprintf(stderr, "map_cache_put: %s: key stored.\n",
+ (mc_key.data == NULL) ? "(null)" : (char *)mc_key.data);
+ }
+
+ }
+ else {
+
+ if ( debug_level & 512 ) {
+ dbp->err(dbp, mc_ret, "DB->put");
+ }
+// db_strerror(mc_ret);
+
+ return(mc_ret);
+
+ }
+
+ }
+
+// Setup for put of data
+
+ memset(&mc_key, 0, sizeof(mc_key));
+ memset(&mc_data, 0, sizeof(mc_data));
+
+// Real data at last
+
+ mc_key.data = map_cache_url;
+ mc_key.size = strlen(map_cache_url);
+ mc_data.data = map_cache_file;
+ mc_data.size = strlen(map_cache_file)+1; /* +1 includes \0 */
+
+// do the actual put
+
+ if ((mc_ret = dbp->put(dbp, NULL, &mc_key, &mc_data, 0)) == 0) {
+ if ( debug_level & 512 ) {
+ fprintf(stderr, "map_cache_put: %s: key stored.\n",
+ (mc_key.data == NULL) ? "(null)" : (char *)mc_key.data);
+ }
+ }
+ else {
+ if ( debug_level & 512 ) {
+ dbp->err(dbp, mc_ret, "DB->put") ;
+ }
+ // db_strerror(mc_ret);
+ return(mc_ret);
+ }
+
+ // Map now cached
+ statusline(langcode("CACHE001"), 1);
+
+// close the db
+
+ // Only try the close if we have a valid handle
+ if (dbp != NULL) {
+ if ((mc_t_ret = dbp->close(dbp, 0)) != 0 && mc_ret == 0) {
+ mc_ret = mc_t_ret;
+ db_strerror(mc_ret);
+ }
+ }
+
+/* end map_cache_put */
+
+ return (0) ;
+}
+
+
+
+
+
+// map_cache_get()
+//
+// Queries URL->Filename db
+// Calls map_cache_del to cleanup expired maps
+//
+// Inputs:
+//
+// Outputs: 0 if cached file is retrieved successfully
+// 1 if db can't be created
+// negative number if unusable filename or bad filestat
+// positive number if map has expired
+// return value from dbp->get if record not found
+//
+int map_cache_get( char * map_cache_url, char * map_cache_file ){
+ DBT mc_key, mc_data ;
+ DB *dbp;
+ int mc_ret, mc_t_ret, mc_file_stat ;
+ char mc_database_filename[MAX_FILENAME];
+ struct stat file_status;
+ char temp_file_path[MAX_VALUE];
+
+ if (map_cache_disabled) {
+ return(1);
+ }
+
+set_dangerous("map_cache_get: xastir_snprintf 1");
+ xastir_snprintf(mc_database_filename,
+ sizeof(mc_database_filename), // change to max_filename?
+ "%s/map_cache.db",
+ get_user_base_dir("map_cache", temp_file_path, sizeof(temp_file_path)));
+clear_dangerous();
+
+set_dangerous("map_cache_get: db_create");
+ if ((mc_ret = db_create(&dbp, NULL, 0)) != 0) {
+ fprintf(stderr, "map_cache_get db_create:%s\n", db_strerror(mc_ret));
+ return(1);
+ }
+clear_dangerous();
+
+#if (DB_VERSION_MAJOR<4) /** DB_VERSION Check **/
+#error DB_VERSION_MAJOR < 4
+
+#elif (DB_VERSION_MAJOR==4 && DB_VERSION_MINOR<=0 )
+
+set_dangerous("map_cache_get:dbp->open 1");
+ if ((mc_ret = dbp->open(dbp,
+ mc_database_filename, NULL, DB_CREATE, DB_BTREE, 0664)) != 0) {
+ ( debug_level & 512 ) ? dbp->err(dbp, mc_ret, "%s", mc_database_filename):0;
+ // db_strerror(mc_ret);
+ }
+clear_dangerous();
+
+#elif (DB_VERSION_MAJOR==4 && DB_VERSION_MINOR>=1 )
+
+set_dangerous("map_cache_get:dbp->open 2");
+ if ((mc_ret = dbp->open(dbp,
+ NULL,mc_database_filename, NULL, DB_CREATE, DB_BTREE, 0664)) != 0) {
+ if (debug_level & 512) {
+ dbp->err(dbp, mc_ret, "%s", mc_database_filename);
+ // db_strerror(mc_ret);
+ }
+ }
+clear_dangerous();
+
+#endif /** DB_VERSION Check **/
+
+ memset(&mc_key, 0, sizeof(mc_key));
+ memset(&mc_data, 0, sizeof(mc_data));
+
+ mc_key.data=map_cache_url ;
+ mc_key.size=strlen(map_cache_url);
+
+ statusline("Checking Map Cache",1);
+ if (debug_level & 512 ) {
+ fprintf(stderr, "map_cache_get: Checking Map Cache\n");
+ }
+
+
+set_dangerous("map_cache_get:dbp->get");
+ if ((mc_ret = dbp->get(dbp, NULL, &mc_key, &mc_data, 0)) == 0) {
+ if ( debug_level & 512 ) {
+ fprintf(stderr, "map_cache_get: %s: key retrieved: data was %s.\n",
+ (mc_key.data == NULL) ? "(null)" : (char *)mc_key.data,
+ (mc_data.data == NULL) ? "(null)" : (char *)mc_data.data);
+ }
+set_dangerous("map_cache_get: xastir_snprintf 2");
+ xastir_snprintf(map_cache_file, MAX_FILENAME, "%s",(char *)mc_data.data);
+clear_dangerous();
+
+ // check for reasonable filename
+ // expects file name like /home/brown/.xastir/map_cache/map_1100052372.gif
+ // 1234567890123456789012345678901234567
+
+ mc_ret=strlen(map_cache_file);
+
+ if ( mc_ret < 37 ) {
+
+ if (debug_level & 512 ) {
+ fprintf(stderr,
+ "map_cache_get: Unusable filename: %s. Deleting key %s from cache\n",
+ (map_cache_file == NULL) ? "(null)" : map_cache_file,
+ (map_cache_url == NULL) ? "(null)" : map_cache_url);
+ }
+set_dangerous("map_cache_get: map_cache_del 1");
+ map_cache_del(map_cache_url);
+ if (dbp != NULL) {
+ if ((mc_t_ret = dbp->close(dbp, 0)) != 0 && mc_ret == 0){
+ mc_ret = mc_t_ret;
+ // db_strerror(mc_ret);
+ }
+ }
+clear_dangerous();
+
+ return (-1 * mc_ret);
+ }
+
+
+ // check age of file - based on name - delete if too old
+
+ if (debug_level & 512 ) {
+ fprintf(stderr, "map_cache_get: Checking age\n");
+ }
+
+set_dangerous("map_cache_get: map_cache_expired");
+ if ( (mc_ret=map_cache_expired(map_cache_file, (MC_MAX_FILE_AGE)))){
+ if ( debug_level & 512 ) {
+ fprintf(stderr, "map_cache_get: deleting expired key: %s.\n",
+ (mc_key.data == NULL) ? "(null)" : (char *)mc_key.data);
+ }
+set_dangerous("map_cache_get: map_cache_del 2");
+ map_cache_del(map_cache_url);
+ if (dbp != NULL) {
+ if ((mc_t_ret = dbp->close(dbp, 0)) != 0 && mc_ret == 0){
+ mc_ret = mc_t_ret;
+ // db_strerror(mc_ret);
+ }
+ }
+clear_dangerous();
+ return (mc_ret);
+ }
+clear_dangerous();
+
+ // check if the file exists
+ if ( debug_level & 512 ) {
+ fprintf(stderr,"map_cache_get: checking for existence of map_cache_file: %s.\n",
+ (map_cache_file == NULL) ? "(null)" : map_cache_file);
+ }
+
+ mc_file_stat=stat(map_cache_file, &file_status);
+
+ if ( debug_level & 512 ) {
+ fprintf(stderr,"map_cache_get: map_cache_file %s stat returned:%d.\n",
+ (map_cache_file == NULL) ? "(null)" : map_cache_file,
+ mc_file_stat);
+ }
+
+ if ( mc_file_stat == -1 ) {
+ //
+ if ( debug_level & 512 ) {
+ fprintf(stderr,"map_cache_get: attempting to delete map_cache_file %s \n",
+ (map_cache_file == NULL) ? "(null)" : map_cache_file);
+ }
+
+set_dangerous("map_cache_get: dbp->del");
+ if ((mc_ret = dbp->del(dbp, NULL, &mc_key, 0)) == 0) {
+ if ( debug_level & 512 ) {
+ fprintf(stderr, "map_cache_get: File stat failed %s: key was deleted.\n",
+ (mc_key.data == NULL) ? "(null)" : (char *)mc_key.data);
+ }
+ }
+ else {
+ if ( debug_level & 512 ) {
+ dbp->err(dbp, mc_ret, "DB->del");
+ }
+ // db_strerror(mc_ret);
+ }
+clear_dangerous();
+
+set_dangerous("map_cache_get: dbp->close 1");
+ // Only try the close if we have a valid handle
+ if (dbp != NULL) {
+ if ((mc_t_ret = dbp->close(dbp, 0)) != 0 && mc_ret == 0){
+ mc_ret = mc_t_ret;
+ // db_strerror(mc_ret);
+ }
+ }
+clear_dangerous();
+
+ // db_strerror(mc_ret);
+ // Return the file stat if there was a file problem
+ return (mc_file_stat);
+ }
+ else {
+
+set_dangerous("map_cache_get: dbp->close 2");
+ // Only try the close if we have a valid handle
+ if (dbp != NULL) {
+ if ((mc_t_ret = dbp->close(dbp, 0)) != 0 && mc_ret == 0){
+ mc_ret = mc_t_ret;
+ // db_strerror(mc_ret);
+ }
+ }
+clear_dangerous();
+ // If we made it here all is good
+
+ // Loading Cached Map
+ statusline(langcode("CACHE002"), 1);
+ return (0);
+ }
+
+ }
+ else {
+ if ( debug_level & 512 ) {
+ fprintf(stderr, "map_cache_get: Get failed. Key was: %s.\n",
+ (mc_key.data == NULL) ? "(null)" : (char *)mc_key.data);
+ }
+
+ if (debug_level & 512) {
+ dbp->err(dbp, mc_ret, "DB->get");
+ // db_strerror(mc_ret);
+ }
+
+ // there was some problem getting things from the db
+ // return the return from the get
+
+ // Map not found in cache...
+ statusline(langcode("CACHE003"), 1);
+ set_dangerous("map_cache_get: dbp->close 3");
+ // Only try the close if we have a valid handle
+ if (dbp != NULL) {
+ if ((mc_t_ret = dbp->close(dbp, 0)) != 0 && mc_ret == 0){
+ mc_ret = mc_t_ret;
+ // db_strerror(mc_ret);
+ }
+ }
+ clear_dangerous();
+ return (mc_ret);
+ }
+
+clear_dangerous();
+
+/** end map_cache_get **/
+}
+
+
+
+
+
+// map_cache_del()
+//
+// Delete entry from the cache and unlink associated file from disk
+//
+// Inputs: Map URL
+//
+// Outputs: 0 if successful deleting the item from the cache
+// 1 if error in creating/opening DB file
+// mc_ret if unlink failed or if error in DB->del
+//
+int map_cache_del( char * map_cache_url ){
+ DBT mc_key, mc_data, mc_size_key, mc_size_data ;
+ DB *dbp;
+ int mc_ret, mc_t_ret, mc_file_stat, mc_space_used;
+ char mc_database_filename[MAX_FILENAME];
+ char mc_delete_file[MAX_FILENAME];
+ struct stat file_status;
+ char mc_buf[128];
+ char temp_file_path[MAX_VALUE];
+
+ if (map_cache_disabled) {
+ return(1);
+ }
+
+ mc_space_used = 0 ;
+
+ xastir_snprintf(mc_database_filename,
+ MAX_FILENAME,
+ "%s/map_cache.db",
+ get_user_base_dir("map_cache", temp_file_path, sizeof(temp_file_path)));
+
+ if ((mc_ret = db_create(&dbp, NULL, 0)) != 0) {
+ fprintf(stderr, "map_cache_del db_create:%s\n", db_strerror(mc_ret));
+ return(1);
+ }
+
+#if (DB_VERSION_MAJOR<4) /** DB_VERSION Check **/
+#error DB_VERSION_MAJOR < 4
+
+#elif (DB_VERSION_MAJOR==4 && DB_VERSION_MINOR<=0 )
+
+ if ((mc_ret = dbp->open(dbp, mc_database_filename, NULL, DB_CREATE, DB_BTREE, 0664)) != 0) {
+ ( debug_level & 512 ) ? dbp->err(dbp, mc_ret, "%s", mc_database_filename):0;
+ // db_strerror(mc_ret);
+ return(1);
+ }
+#elif (DB_VERSION_MAJOR==4 && DB_VERSION_MINOR>=1 )
+
+ if ((mc_ret = dbp->open(dbp,
+ NULL,mc_database_filename, NULL, DB_CREATE, DB_BTREE, 0664)) != 0) {
+ if (debug_level & 512) {
+ dbp->err(dbp, mc_ret, "%s", mc_database_filename);
+ // db_strerror(mc_ret);
+ }
+ return(1);
+ }
+
+#endif /** DB_VERSION Check **/
+
+ memset(&mc_key, 0, sizeof(mc_key));
+ memset(&mc_data, 0, sizeof(mc_data));
+
+ mc_key.data=map_cache_url ;
+ mc_key.size=strlen(map_cache_url);
+
+ // Try to get the key from the cache
+ if ((mc_ret = dbp->get(dbp, NULL, &mc_key, &mc_data, 0)) != 0) {
+ // Couldn't get the key from the cache
+
+ if ( debug_level & 512 ) {
+ dbp->err(dbp, mc_ret, "DB->del");
+ }
+ // db_strerror(mc_ret);
+
+ // Only try the close if we have a valid handle
+ if (dbp != NULL) {
+set_dangerous("map_cache_del: dbp->close 1");
+ dbp->close(dbp, 0);
+clear_dangerous();
+ }
+ return (mc_ret);
+ }
+
+ if ( debug_level & 512 ) {
+ fprintf(stderr, "map_cache_del: %s: key retrieved: data was %s.\n",
+ (mc_key.data == NULL) ? "(null)" : (char *)mc_key.data,
+ (mc_data.data == NULL) ? "(null)" : (char *)mc_data.data);
+ }
+
+ // stat the file
+
+ xastir_snprintf(mc_delete_file,
+ MAX_FILENAME,
+ "%s",
+ (char *) mc_data.data);
+
+set_dangerous("map_cache_del: stat");
+ mc_file_stat = stat(mc_delete_file, &file_status);
+clear_dangerous();
+
+ if ( debug_level & 512 ) {
+ fprintf(stderr,"map_cache_del: file %s stat returned:%d.\n",
+ (mc_data.data == NULL) ? "(null)" : (char *) mc_data.data,
+ mc_file_stat);
+ }
+
+ if (mc_file_stat != 0 ) {
+
+// file stat was not good - do something here
+// RETURN() HERE?
+
+ }
+
+
+// Setup for get CACHE_SPACE_USED
+
+ memset(&mc_size_key, 0, sizeof(mc_size_key));
+ memset(&mc_size_data, 0, sizeof(mc_size_data));
+
+ mc_size_key.data = "CACHE_SPACE_USED";
+ mc_size_key.size = sizeof("CACHE_SPACE_USED");
+
+// check "CACHE_SPACE_USED" record in db
+
+ if (((mc_ret = dbp->get(dbp, NULL, &mc_size_key, &mc_size_data, 0)) == 0)
+ && ( mc_size_data.data != NULL )
+ && ( strlen(mc_size_data.data) != 0 ) ) {
+
+ if ( debug_level & 512 ) {
+ fprintf(stderr, "map_cache_del: %s: key retrieved: data was %s.\n",
+ (mc_size_key.data == NULL) ? "(null)" : (char *)mc_size_key.data,
+ (mc_size_data.data == NULL) ? "(null)" : (char *)mc_size_data.data);
+ }
+
+set_dangerous("map_cache_del: atoi");
+ if (mc_size_data.data == NULL)
+ mc_space_used = 0;
+ else
+ mc_space_used = atoi( (char *)mc_size_data.data);
+clear_dangerous();
+
+ if ( debug_level & 512 ) {
+ fprintf (stderr, "map_cache_del: CACHE_SPACE_USED = %.2f mb\n",
+ (mc_space_used/1024/1024.0));
+ }
+ }
+ else {
+ // Failed the "dpb->get" operation
+
+ if (mc_size_data.data == NULL) {
+
+ if ( debug_level & 512 ) {
+ fprintf (stderr, "map_cache_del: CACHE_SPACE_USED get returned null \n");
+ }
+ }
+ else {
+
+ if ( debug_level & 512 ) {
+ fprintf (stderr, "map_cache_del: Unable to check CACHE_SPACE_USED: %s\n",
+ db_strerror(mc_ret));
+ }
+ }
+
+// RETURN() HERE?
+
+ }
+
+
+ if ( debug_level & 512 ) {
+ fprintf (stderr, "map_cache_del: mc_space_used before = %d bytes file_status.st_size %d\n",
+ mc_space_used,
+ (int) file_status.st_size);
+ }
+
+ mc_ret = unlink( mc_delete_file );
+
+ if ( debug_level & 512 ) {
+ fprintf(stderr,"map_cache_del: file %s unlink returned:%d.\n",
+ (mc_delete_file == NULL) ? "(null)" : mc_delete_file,
+ mc_ret);
+ }
+
+ if (mc_ret != 0 ) {
+
+ if ( debug_level & 512 ) {
+ fprintf (stderr, "map_cache_del: unlink failed mc_space_used = %d bytes \n",
+ mc_space_used);
+ }
+ return(mc_ret);
+ }
+
+
+// Update cache_space_used
+
+// setup
+
+ mc_space_used -= (int) file_status.st_size;
+
+ if (mc_space_used < 0) {
+ mc_space_used = 0;
+ }
+
+ if ( debug_level & 512 ) {
+ fprintf (stderr, "map_cache_del: unlink succeeded mc_space_used = %d bytes \n",
+ mc_space_used);
+ }
+
+ memset(&mc_size_key, 0, sizeof(mc_size_key));
+ memset(&mc_size_data, 0, sizeof(mc_size_data));
+
+// data
+
+ mc_size_key.data = "CACHE_SPACE_USED";
+ mc_size_key.size = sizeof("CACHE_SPACE_USED");
+
+ xastir_snprintf(mc_buf, sizeof(mc_buf), "%d", mc_space_used);
+
+ if ( debug_level & 512 ) {
+ fprintf (stderr, "map_cache_del: mc_buf: %s len %d\n",
+ mc_buf, (int)sizeof(mc_buf));
+ }
+
+ mc_size_data.data = mc_buf ;
+ mc_size_data.size = sizeof(mc_buf);
+
+// put
+
+ if ((mc_ret = dbp->put(dbp, NULL, &mc_size_key, &mc_size_data, 0)) != 0) {
+ // Failed the "dbp->put" operation
+
+ if ( debug_level & 512 ) {
+ dbp->err(dbp, mc_ret, "DB->put");
+ }
+
+ // db_strerror(mc_ret);
+
+// RETURN() HERE?
+
+ }
+
+ if ( debug_level & 512 ) {
+ fprintf(stderr,"map_cache_del: %s: key stored.\n",
+ (mc_size_key.data == NULL) ? "(null)" : (char *)mc_size_key.data);
+ }
+
+
+ // remove entry from cache url->filename database
+
+ if ((mc_ret = dbp->del(dbp, NULL, &mc_key, 0)) != 0){
+ // Failed the "dbp->del" operation
+
+ if ( debug_level & 512 ) {
+ dbp->err(dbp, mc_ret, "DB->del");
+ }
+ // db_strerror(mc_ret);
+
+// RETURN() HERE?
+
+ }
+
+ if ( debug_level & 512 ) {
+ fprintf(stderr, "map_cache_del: %s: key was deleted.\n",
+ (mc_key.data == NULL) ? "(null)" : (char *)mc_key.data);
+ }
+
+ // close the db.
+
+ // Only try the close if we have a valid handle
+ if (dbp != NULL) {
+
+set_dangerous("map_cache_del: dbp->close 2");
+ if ((mc_t_ret = dbp->close(dbp, 0)) != 0 && mc_ret == 0){
+clear_dangerous();
+
+ mc_ret = mc_t_ret;
+ // db_strerror(mc_ret);
+
+// RETURN() HERE?
+
+ }
+ }
+
+ return (0); // All is well
+
+/** end map_cache_del **/
+}
+
+
+
+
+
+char * map_cache_fileid(void) {
+
+ // returns a unique identifier
+ // used for generating filenames for cached files
+
+ time_t t;
+ char * mc_time_buf;
+
+
+ mc_time_buf = malloc (16);
+ sprintf( mc_time_buf, "%d",(int) time(&t));
+ return (mc_time_buf);
+}
+
+
+
+
+
+// check for files old enough to expire
+// this is lame but it should work for now.
+// expects file name like /home/brown/.xastir/map_cache/map_1100052372.gif
+//
+// writing this proved a good example of why pointer arithmetic is tricky
+// and a good example of why I should avoid it - n8ysz 20041110
+//
+int map_cache_expired( char * mc_filename, time_t mc_max_age ){
+ time_t mc_t,mc_file_age;
+ char *mc_filename_tmp, *mc_time_buf_tmp, *mc_time_buf;
+
+
+ if (map_cache_disabled) {
+ return(0);
+ }
+
+ mc_time_buf=malloc(MAX_FILENAME);
+ mc_time_buf_tmp=mc_time_buf;
+
+ // grab filename
+ mc_filename_tmp=strrchr(mc_filename,'/');
+
+ // clean up map_
+ mc_filename_tmp=strchr(mc_filename_tmp,'_');
+ ++mc_filename_tmp;
+
+ // save up to .gif
+ while ((*mc_time_buf_tmp++ = *mc_filename_tmp++) != '.' )
+ ;
+
+ *(--mc_time_buf_tmp) ='\0';
+
+// if ( debug_level & 512 ) {
+// fprintf(stderr, "map_cache_expired: mc_filename is: %s mc_time_buf is: %s.\n", mc_filename, mc_time_buf);
+// }
+
+ mc_file_age=(time(&mc_t) - ((time_t) atoi(mc_time_buf)) );
+
+ if ( mc_file_age < mc_max_age ) {
+ if ( debug_level & 512 ) {
+ fprintf(stderr, "map_cache_expired: mc_filename %s is NOT expired. mc_time_buf is: %s.\n",
+ (mc_filename == NULL) ? "(null)" : mc_filename,
+ (mc_time_buf == NULL) ? "(null)" : mc_time_buf);
+ }
+ free(mc_time_buf);
+ return (0);
+ }
+ else {
+ if ( debug_level & 512 ) {
+ fprintf(stderr, "map_cache_expired: mc_filename %s IS expired. mc_time_buf is: %s.\n",
+ (mc_filename == NULL) ? "(null)" : mc_filename,
+ (mc_time_buf == NULL) ? "(null)" : mc_time_buf);
+ }
+ free(mc_time_buf);
+ return ((int)mc_file_age);
+ }
+
+
+ // sprintf( mc_time_buf, "%d",(int)
+
+ return (0);
+}
+
+
+
+
+
+// Functions that need writing
+
+int mc_check_space_used (void) {
+
+ if (map_cache_disabled) {
+ return(0);
+ }
+
+ return(0);
+}
+
+
+
+
+
+int mc_update_space_used (void) {
+
+ if (map_cache_disabled) {
+ return(0);
+ }
+
+ return(0);
+}
+
+
+#endif // USE_MAP_CACHE
+
+
diff --git a/src/map_cache.h b/src/map_cache.h
new file mode 100644
index 0000000..1b052ca
--- /dev/null
+++ b/src/map_cache.h
@@ -0,0 +1,79 @@
+/*
+ * $Id: map_cache.h,v 1.14 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifndef XASTIR_MAP_CACHE_H
+#define XASTIR_MAP_CACHE_H
+
+// Global variable declarations
+extern int map_cache_fetch_disable;
+
+
+// External function declarations
+
+extern void map_cache_init(void);
+
+// Saves file and puts entries into cache db
+extern int map_cache_put( char * map_cache_url, char * map_cache_file );
+
+// Retrieves entry from cache db - checks existance of file
+extern int map_cache_get( char * map_cache_url, char * map_cache_file );
+
+// Deletes cached map file and the entry from cache
+extern int map_cache_del( char * map_cache_url );
+
+// Checks to see if map is expired based on date embedded in filename
+extern int map_cache_expired( char * mc_filename, time_t mc_max_age );
+
+// Generates filename based on current time
+extern char * map_cache_fileid(void);
+
+
+// Static variable definitions
+// These should probably be runtime options
+
+// Cache expiration times
+// about 6mo
+#define MC_MAX_FILE_AGE 6*30*24*60*60
+
+// 1 hr
+//#define MC_MAX_FILE_AGE 60*60
+
+// 5 seconds -- don't do this except for testing
+//#define MC_MAX_FILE_AGE 5
+
+// Cache Space Limit in bytes
+
+// 1 megabytes == about ten 1024x768 map gifs n8ysz
+// MAP_CACHE_SPACE_LIMIT=1024*1024
+
+// 16 megabytes
+// MAP_CACHE_SPACE_LIMIT=16*1024*1024
+
+// 128 megabytes
+#define MAP_CACHE_SPACE_LIMIT 128*1024*1024
+
+
+#endif /* XASTIR_MAP_CACHE_H */
diff --git a/src/map_dos.c b/src/map_dos.c
new file mode 100644
index 0000000..f1668e5
--- /dev/null
+++ b/src/map_dos.c
@@ -0,0 +1,1364 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: map_dos.c,v 1.30 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <dirent.h>
+#include <netinet/in.h>
+#include <Xm/XmAll.h>
+
+#ifdef HAVE_X11_XPM_H
+#include <X11/xpm.h>
+#ifdef HAVE_LIBXPM // if we have both, prefer the extra library
+#undef HAVE_XM_XPMI_H
+#endif // HAVE_LIBXPM
+#endif // HAVE_X11_XPM_H
+
+#ifdef HAVE_XM_XPMI_H
+#include <Xm/XpmI.h>
+#endif // HAVE_XM_XPMI_H
+
+#include <X11/Xlib.h>
+
+#include <math.h>
+
+#include "xastir.h"
+#include "maps.h"
+#include "alert.h"
+#include "util.h"
+#include "main.h"
+#include "datum.h"
+#include "draw_symbols.h"
+#include "rotated.h"
+#include "color.h"
+#include "xa_config.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+#define DOS_HDR_LINES 8
+#define GRID_MORE 5000
+
+extern int npoints; /* tsk tsk tsk -- globals */
+extern int mag;
+
+/* MAP pointers */
+
+static map_vectors *map_vectors_ptr;
+static text_label *map_text_label_ptr;
+static symbol_label *map_symbol_label_ptr;
+
+/* MAP counters */
+
+//static long vectors_num;
+//static long text_label_num;
+//static long object_label_num;
+
+
+
+
+/**********************************************************
+ * map_plot()
+ *
+ * Plots vectors on the map. If "color" is non-zero,
+ * then it draws filled polygons in the color of
+ * "object_behavior"? Weird.
+ **********************************************************/
+void map_plot (Widget w, long max_x, long max_y, long x_long_cord,
+ long y_lat_cord, unsigned char color, long object_behavior,
+ int destination_pixmap, int draw_filled) {
+
+ static int redraw_check;
+ static XPoint points[MAX_MAP_POINTS];
+ static unsigned char last_color = (unsigned char)0;
+ static unsigned char last_behavior = (unsigned char)0, first_behavior = (unsigned char)0;
+ long x, y;
+ int draw_ok;
+ unsigned char line_behavior, fill_color;
+ char warning[200];
+
+ /* don't ever go over MAX_MAP_POINTS have a bad map not a crashed program */
+ if (npoints > MAX_MAP_POINTS) {
+ xastir_snprintf(warning, sizeof(warning), "Warning line point count overflow: map_plot\b\n");
+ XtAppWarning (app_context, warning);
+ npoints = MAX_MAP_POINTS;
+ }
+
+ /* if map_color_levels are on see if we should draw the line? */
+ draw_ok = 0;
+ if (map_color_levels) // Decide which colors to display at this zoom level
+
+ switch (color) {
+
+ case (0x01):
+ case (0x14):
+ case (0x18):
+ if (mag < 100)
+ draw_ok = 1;
+ break;
+
+ case (0x15):
+ case (0x19):
+ if (mag < 600)
+ draw_ok = 1;
+ break;
+
+ case (0x16):
+ if (mag < 800)
+ draw_ok = 1;
+ break;
+
+ default:
+ draw_ok = 1;
+ break;
+
+ } // end of switch
+ else { // Display all colors
+ draw_ok = 1;
+ }
+
+ if (draw_ok) {
+ x = ((x_long_cord - NW_corner_longitude) / scale_x);
+ y = ((y_lat_cord - NW_corner_latitude) / scale_y);
+ if (x < -MAX_OUTBOUND)
+ x = -MAX_OUTBOUND;
+
+ if (y < -MAX_OUTBOUND)
+ y = -MAX_OUTBOUND;
+
+ if (x > max_x)
+ x = max_x;
+
+ if (y > max_y)
+ y = max_y;
+
+ if (debug_level & 16)
+ fprintf(stderr," MAP Plot - max_x: %ld, max_y: %ld, x: %ld, y: %ld, color: %d, behavior: %lx, points: %d\n",
+ max_x, max_y, x, y, (int)color, (unsigned long)object_behavior, npoints);
+
+ if ( (last_color != color) || (color == (unsigned char)0xff) ) {
+ if (npoints && (last_color != (unsigned char)0xff) ) {
+ line_behavior = last_behavior;
+ if (last_behavior & 0x80) {
+ if (color) {
+ fill_color = (last_behavior & ~0x80) + (unsigned char)0x60;
+ if (fill_color > (unsigned char)0x69)
+ fill_color = (unsigned char)0x60;
+ }
+ else {
+ fill_color = (unsigned char)object_behavior;
+ }
+
+
+ // Here's where we draw filled areas using fill_color.
+
+ (void)XSetForeground (XtDisplay (w), gc, colors[(int)fill_color]);
+
+ switch (destination_pixmap) {
+
+ case DRAW_TO_PIXMAP:
+ // We must be drawing maps 'cuz this is the pixmap we use for it.
+ if (map_color_fill && draw_filled) {
+
+ if (npoints >= 3) {
+ (void)XFillPolygon(XtDisplay(w),
+ pixmap,
+ gc,
+ points,
+ npoints,
+ Nonconvex,
+ CoordModeOrigin);
+ }
+ else {
+// fprintf(stderr,
+// "map_plot:Too few points:%d, Skipping XFillPolygon()",
+// npoints);
+ }
+ }
+ break;
+
+ case DRAW_TO_PIXMAP_ALERTS:
+ fprintf(stderr,"You're calling the wrong routine to draw weather alerts!\n");
+ break;
+
+ case DRAW_TO_PIXMAP_FINAL:
+ // We must be drawing symbols/tracks 'cuz this is the pixmap we use for it.
+
+ if (npoints >= 3) {
+ (void)XFillPolygon(XtDisplay(w),
+ pixmap_final,
+ gc,
+ points,
+ npoints,
+ Nonconvex,
+ CoordModeOrigin);
+ }
+ else {
+// fprintf(stderr,
+// "map_plot:Too few points:%d, Skipping XFillPolygon()",
+// npoints);
+ }
+ break;
+
+ } // end of switch
+
+ line_behavior = first_behavior;
+ }
+ if (line_behavior & 0x01)
+ (void)XSetLineAttributes (XtDisplay (w), gc, 2, LineSolid, CapButt,JoinMiter);
+ else
+ (void)XSetLineAttributes (XtDisplay (w), gc, 1, LineSolid, CapButt,JoinMiter);
+
+ if (color == (unsigned char)0x56)
+ (void)XSetLineAttributes (XtDisplay (w), gc, 10, LineSolid, CapButt,JoinMiter);
+
+ // Set the color for drawing lines/borders
+ (void)XSetForeground (XtDisplay (w), gc, colors[(int)last_color]);
+
+ switch (destination_pixmap) {
+
+ case DRAW_TO_PIXMAP_FINAL:
+ (void)XDrawLines (XtDisplay (w),
+ pixmap_final,
+ gc,
+ points,
+ l16(npoints),
+ CoordModeOrigin);
+ break;
+
+ case DRAW_TO_PIXMAP:
+ (void)XDrawLines (XtDisplay (w),
+ pixmap,
+ gc,
+ points,
+ l16(npoints),
+ CoordModeOrigin);
+ break;
+
+ case DRAW_TO_PIXMAP_ALERTS:
+ fprintf(stderr,"You're calling the wrong routine to draw weather alerts!\n");
+ break;
+ } // end of switch
+
+ npoints = 0;
+
+ /* check to see if we have been away from the screen too long */
+ if (redraw_check > 1000) {
+ redraw_check = 0;
+ XmUpdateDisplay (XtParent (da));
+ }
+ redraw_check++;
+ }
+ last_color = color;
+ if (color == (unsigned char)0xff) {
+ npoints = 0;
+ first_behavior = (unsigned char)object_behavior;
+ }
+ points[npoints].x = l16(x);
+ points[npoints].y = l16(y);
+ if ( (points[npoints].x > (-MAX_OUTBOUND))
+ && (points[npoints].x < (short)max_x)
+ && (points[npoints].y > (-MAX_OUTBOUND))
+ && (points[npoints].y < (short)max_y)
+ && (color != (unsigned char)0) )
+
+ npoints++;
+
+ last_behavior = (unsigned char)object_behavior;
+ return;
+ }
+ points[npoints].x = l16(x);
+ points[npoints].y = l16(y);
+ last_behavior = (unsigned char)object_behavior;
+
+ if (points[npoints].x != points[npoints - 1].x || points[npoints].y != points[npoints - 1].y) {
+ if (last_behavior & 0x80) {
+ npoints++;
+ }
+ else if (points[npoints].x > (-MAX_OUTBOUND)
+ && points[npoints].x < (short)max_x
+ && points[npoints].y > (-MAX_OUTBOUND)
+ && points[npoints].y < (short)max_y) {
+ npoints++;
+ }
+ }
+ }
+ else {
+ npoints = 0;
+ }
+} /* map_plot */
+
+
+
+
+
+void draw_dos_map(Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *mdf) {
+
+ FILE *f;
+ char file[MAX_FILENAME];
+ char short_filenm[MAX_FILENAME];
+ char map_it[MAX_FILENAME];
+
+ /* map header info */
+ char map_type[5];
+ char map_version[5];
+ char file_name[33];
+// char *ext;
+ char map_title[33];
+ char map_creator[9];
+ unsigned long creation_date;
+ unsigned long left_boundary;
+ unsigned long right_boundary;
+ unsigned long top_boundary;
+ unsigned long bottom_boundary;
+ char map_reserved1[9];
+ long total_vector_points;
+ long total_labels;
+ char map_reserved2[141];
+ char Buffer[2049];
+ char *ptr;
+ int dos_labels;
+ int dos_flag;
+ long temp;
+ int points_per_degree;
+ int map_range;
+
+ /* vector info */
+ unsigned char vector_start;
+ unsigned char object_behavior;
+ unsigned long x_long_cord;
+ unsigned long y_lat_cord;
+
+ /* label data */
+ char label_type[3];
+ unsigned long label_x_cord;
+ unsigned long label_y_cord;
+ int temp_mag;
+ int label_mag;
+ char label_symbol_del;
+ char label_symbol_char;
+ char label_text_color;
+ char label_text[50];
+
+ unsigned long year;
+ unsigned long days;
+ long count;
+ int label_length;
+ int i;
+ int map_maxed_vectors;
+ int map_maxed_text_labels;
+ int map_maxed_symbol_labels;
+ map_vectors *vectors_ptr;
+ text_label *text_ptr;
+ symbol_label *symbol_ptr;
+ int line_width;
+ int x, y;
+ int color;
+ long max_x, max_y;
+ int in_window = 0;
+ char symbol_table;
+ char symbol_id;
+ char symbol_color;
+ int embedded_object;
+
+ int draw_filled;
+ unsigned char last_behavior, special_fill = (unsigned char)FALSE;
+
+
+ draw_filled=mdf->draw_filled;
+
+ x = 0;
+ y = 0;
+ color = -1;
+ line_width = 1;
+ mag = (1 * scale_y) / 2; // determines if details are drawn
+
+ /* MAP counters */
+ vectors_ptr = map_vectors_ptr;
+ text_ptr = map_text_label_ptr;
+ symbol_ptr = map_symbol_label_ptr;
+
+ map_maxed_vectors = 0;
+ map_maxed_text_labels = 0;
+ map_maxed_symbol_labels = 0;
+ npoints = 0;
+
+ xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm);
+
+ // Create a shorter filename for display (one that fits the
+ // status line more closely). Subtract the length of the
+ // "Indexing " and/or "Loading " strings as well.
+ if (strlen(filenm) > (41 - 9)) {
+ int avail = 41 - 11;
+ int new_len = strlen(filenm) - avail;
+
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "..%s",
+ &filenm[new_len]);
+ }
+ else {
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "%s",
+ filenm);
+ }
+
+ f = fopen (file, "r");
+ if (f == NULL) {
+ fprintf(stderr,"Couldn't open file: %s\n", file);
+ return;
+ }
+
+ (void)fread (map_type, 4, 1, f);
+ map_type[4] = '\0';
+ dos_labels = FALSE;
+ points_per_degree = 300;
+
+
+// DOS-type map header portion of the code.
+
+ if (strtod (map_type, &ptr) > 0.01 && (*ptr == '\0' || *ptr == ' ' || *ptr == ',')) {
+ int j;
+
+ if (debug_level & 512)
+ fprintf(stderr,"\nDOS Map\n");
+
+ top_boundary = left_boundary = bottom_boundary = right_boundary = 0;
+ rewind (f);
+ map_title[0] = map_creator[0] = Buffer[0] = '\0';
+ // set map_type for DOS ASCII maps
+ xastir_snprintf(map_type,sizeof(map_type),"DOS ");
+ map_type[4] = '\0';
+ xastir_snprintf(file_name,sizeof(file_name),"%s",filenm);
+ total_vector_points = 200000;
+ total_labels = 2000;
+
+ for (j = 0; j < DOS_HDR_LINES; strlen(Buffer) ? 1 : j++) {
+
+ (void)fgets (&Buffer[strlen (Buffer)],(int)sizeof (Buffer) - (strlen (Buffer)), f);
+
+// if (!strlen(Buffer))
+// j++;
+
+ while ((ptr = strpbrk (Buffer, "\r\n")) != NULL && j < DOS_HDR_LINES) {
+
+ *ptr = '\0';
+
+ for (ptr++; *ptr == '\r' || *ptr == '\n'; ptr++) ;
+
+ switch (j) {
+
+ case 0:
+//fprintf(stderr,"top_boundary: %s\n", Buffer);
+ top_boundary = (unsigned long) (-atof (Buffer) * 360000 + 32400000);
+ break;
+
+ case 1:
+//fprintf(stderr,"left_boundary: %s\n", Buffer);
+ left_boundary = (unsigned long) (-atof (Buffer) * 360000 + 64800000);
+ break;
+
+ case 2:
+//fprintf(stderr,"points_per_degree: %s\n", Buffer);
+ points_per_degree = (int) atof (Buffer);
+ break;
+
+ case 3:
+//fprintf(stderr,"bottom_boundary: %s\n", Buffer);
+ bottom_boundary = (unsigned long) (-atof (Buffer) * 360000 + 32400000);
+ bottom_boundary = bottom_boundary + bottom_boundary - top_boundary;
+ break;
+
+ case 4:
+//fprintf(stderr,"right_boundary: %s\n", Buffer);
+ right_boundary = (unsigned long) (-atof (Buffer) * 360000 + 64800000);
+ right_boundary = right_boundary + right_boundary - left_boundary;
+ break;
+
+ case 5:
+//fprintf(stderr,"map_range: %s\n", Buffer);
+ map_range = (int) atof (Buffer);
+ break;
+
+ case 7:
+//fprintf(stderr,"Map Version: %s\n", Buffer);
+ xastir_snprintf(map_version,sizeof(map_version),"%s",Buffer);
+//fprintf(stderr,"MAP VERSION: %s\n", map_version);
+ break;
+ } // end of switch
+
+ xastir_snprintf(Buffer,sizeof(Buffer),"%s",ptr);
+
+// if (strlen (Buffer))
+// j++;
+
+ }
+ } // End of DOS-type map header portion
+ }
+ else {
+
+// Windows-type map header portion
+
+ if (debug_level & 512)
+ fprintf(stderr,"\nWindows map\n");
+
+ (void)fread (map_version, 4, 1, f);
+ map_version[4] = '\0';
+
+ (void)fread (file_name, 32, 1, f);
+ file_name[32] = '\0';
+
+ (void)fread (map_title, 32, 1, f);
+ map_title[32] = '\0';
+ if (debug_level & 16)
+ fprintf(stderr,"Map Title %s\n", map_title);
+
+ (void)fread (map_creator, 8, 1, f);
+ map_creator[8] = '\0';
+ if (debug_level & 16)
+ fprintf(stderr,"Map Creator %s\n", map_creator);
+
+ (void)fread (&temp, 4, 1, f);
+ creation_date = ntohl (temp);
+ if (debug_level & 16)
+ fprintf(stderr,"Creation Date %lX\n", creation_date);
+
+ year = creation_date / 31536000l;
+ days = (creation_date - (year * 31536000l)) / 86400l;
+ if (debug_level & 16)
+ fprintf(stderr,"year is %ld + days %ld\n", 1904l + year, (long)days);
+
+ (void)fread (&temp, 4, 1, f);
+ left_boundary = ntohl (temp);
+
+ (void)fread (&temp, 4, 1, f);
+ right_boundary = ntohl (temp);
+
+ (void)fread (&temp, 4, 1, f);
+ top_boundary = ntohl (temp);
+
+ (void)fread (&temp, 4, 1, f);
+ bottom_boundary = ntohl (temp);
+
+ if (strcmp (map_version, "2.00") != 0) {
+ left_boundary *= 10;
+ right_boundary *= 10;
+ top_boundary *= 10;
+ bottom_boundary *= 10;
+ }
+
+ (void)fread (map_reserved1, 8, 1, f);
+ (void)fread (&temp, 4, 1, f);
+ total_vector_points = (long)ntohl (temp);
+ (void)fread (&temp, 4, 1, f);
+ total_labels = (long)ntohl (temp);
+ (void)fread (map_reserved2, 140, 1, f);
+
+ } // End of Windows-type map header portion
+
+
+ // Done processing map header info. The rest of this
+ // function performs the actual drawing of both DOS-type
+ // and Windows-type maps to the screen.
+
+
+ if (debug_level & 16) {
+ fprintf(stderr,"Map Type: %s, Version: %s, Filename: %s\n", map_type, map_version, file_name);
+ fprintf(stderr,"Left Boundary: %ld, Right Boundary: %ld\n", (long)left_boundary,(long)right_boundary);
+ fprintf(stderr,"Top Boundary: %ld, Bottom Boundary: %ld\n", (long)top_boundary,(long)bottom_boundary);
+ fprintf(stderr,"Total vector points: %ld, total labels: %ld\n",total_vector_points, total_labels);
+ }
+
+
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ // We're indexing only. Save the extents in the index.
+ index_update_xastir(filenm, // Filename only
+ bottom_boundary, // Bottom
+ top_boundary, // Top
+ left_boundary, // Left
+ right_boundary, // Right
+ 1000); // Default Map Level
+
+ (void)fclose (f);
+
+ // Update the statusline
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ langcode ("BBARSTA039"),
+ short_filenm);
+ statusline(map_it,0); // Loading/Indexing ...
+
+ return; // Done indexing this file
+ }
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ (void)fclose(f);
+
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ // Check to see if we should draw the map
+ in_window = map_onscreen(left_boundary, right_boundary, top_boundary, bottom_boundary, 1);
+
+ if (!in_window) {
+ (void)fclose (f);
+ return;
+ }
+
+ // Update the statusline
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ langcode ("BBARSTA028"),
+ short_filenm);
+ statusline(map_it,0); // Loading/Indexing ...
+
+ object_behavior = '\0';
+
+ if (debug_level & 16)
+ fprintf(stderr,"in Boundary %s\n", map_it);
+
+ (void)XSetLineAttributes (XtDisplay (w), gc, line_width, LineSolid, CapButt,JoinMiter);
+
+ /* read vectors */
+ max_x = screen_width + MAX_OUTBOUND;
+ max_y = screen_height + MAX_OUTBOUND;
+
+ x_long_cord = 0;
+ y_lat_cord = 0;
+ color = 0;
+ dos_flag = 0;
+
+ for (count = 0l;count < total_vector_points && !feof (f) && !dos_labels; count++) {
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ (void)fclose(f);
+
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+// DOS type map
+
+ if (strncmp ("DOS ", map_type, 4) == 0) {
+
+ (void)fgets (&Buffer[strlen (Buffer)],(int)sizeof (Buffer) - (strlen (Buffer)), f);
+
+ while ((ptr = strpbrk (Buffer, "\r\n")) != NULL && !dos_labels) {
+ long LatHld = 0, LongHld;
+ char *trailer;
+
+ *ptr = '\0';
+
+ for (ptr++; *ptr == '\r' || *ptr == '\n'; ptr++) ;
+
+process: if (strncasecmp ("Line", map_version, 4) == 0) {
+ int k;
+
+ color = (int)strtol (Buffer, &trailer, 0);
+
+ if (trailer && (*trailer == ',' || *trailer == ' ')) {
+ trailer++;
+
+ if (color == -1) {
+ dos_labels = (int)TRUE;
+ xastir_snprintf(Buffer,sizeof(Buffer),"%s",ptr);
+ break;
+ }
+
+ for (k = strlen (trailer) - 1; k >= 0; k--) {
+ trailer[k] = (char)( (int)trailer[k] - 27 );
+ }
+
+ while (*trailer) {
+ LongHld = (long)( (int)(*(unsigned char *)trailer) * 16);
+ trailer++;
+ LatHld = (long)( (int)(*(unsigned char *)trailer) * 8);
+ trailer++;
+ LongHld += (long)((*trailer >> 3) & 0xf);
+ LatHld += (long)( (*trailer) & 0x7);
+ trailer++;
+ LatHld = ((double)LatHld * 360000.0) / points_per_degree;
+ LongHld = ((double)LongHld * 360000.0) / points_per_degree;
+ x_long_cord = LongHld + left_boundary;
+ y_lat_cord = LatHld + top_boundary;
+ map_plot (w,
+ max_x,
+ max_y,
+ (long)x_long_cord,
+ (long)y_lat_cord,
+ (unsigned char)color,
+ 0,
+ destination_pixmap,
+ draw_filled);
+ }
+ map_plot (w,
+ max_x,
+ max_y,
+ (long)x_long_cord,
+ (long)y_lat_cord,
+ '\0',
+ 0,
+ destination_pixmap,
+ draw_filled);
+ }
+ }
+
+ else if (strncasecmp ("ASCII", map_version, 4) == 0) {
+
+ if (color == 0) {
+ color = (int)strtol (Buffer, &trailer, 0);
+ if (trailer && strpbrk (trailer, ", ")) {
+
+ for (; *trailer == ',' || *trailer == ' '; trailer++) ;
+
+ dos_flag = (int)strtol (trailer, &trailer, 0);
+ if (dos_flag == -1)
+ dos_labels = (int)TRUE;
+ }
+ }
+ else {
+ LongHld = strtol (Buffer, &trailer, 0);
+
+ if (trailer && strpbrk (trailer, ", ")) {
+
+ for (; *trailer == ',' || *trailer == ' '; trailer++) ;
+
+ LatHld = strtol (trailer, &trailer, 0);
+ }
+ else if (LongHld == 0 && *trailer != '\0') {
+ xastir_snprintf(map_version,sizeof(map_version),"Comp");
+ map_version[4] = '\0';
+ goto process;
+ }
+ if (LongHld == 0 && LatHld == 0) {
+ color = 0;
+ map_plot (w,
+ max_x,
+ max_y,
+ (long)x_long_cord,
+ (long)y_lat_cord,
+ (unsigned char)color,
+ 0,
+ destination_pixmap,
+ draw_filled);
+ }
+ else if (LongHld == 0 && LatHld == -1) {
+ dos_labels = (int)TRUE;
+ map_plot (w,
+ max_x,
+ max_y,
+ (long)x_long_cord,
+ (long)y_lat_cord,
+ '\0',
+ 0,
+ destination_pixmap,
+ draw_filled);
+ }
+ else {
+ LatHld = ((double)LatHld * 360000.0) / points_per_degree;
+ LongHld = ((double)LongHld * 360000.0) / points_per_degree;
+ x_long_cord = LongHld + left_boundary;
+ y_lat_cord = LatHld + top_boundary;
+ map_plot (w,
+ max_x,
+ max_y,
+ (long)x_long_cord,
+ (long)y_lat_cord,
+ (unsigned char)color,
+ 0,
+ destination_pixmap,
+ draw_filled);
+ }
+ }
+ }
+ else if (strncasecmp ("Comp", map_version, 4) == 0) {
+ char Tag[81];
+ int k;
+
+ Tag[80] = '\0';
+ if (color == 0) {
+ color = (int)strtol (Buffer, &trailer, 0);
+ if (trailer && strpbrk (trailer, ", ")) {
+
+ for (; *trailer == ',' || *trailer == ' '; trailer++) ;
+
+ dos_flag = (int)strtol (trailer, &trailer, 0);
+ xastir_snprintf(Tag,sizeof(Tag),"%s",trailer);
+ Tag[79] = '\0';
+ if (dos_flag == -1)
+ dos_labels = (int)TRUE;
+ }
+ }
+ else {
+ LongHld = strtol (Buffer, &trailer, 0);
+
+ for (; *trailer == ',' || *trailer == ' '; trailer++) ;
+
+ LatHld = strtol (trailer, &trailer, 0);
+ if (LatHld == 0 && *trailer != '\0') {
+ LatHld = 1;
+ }
+
+ if (LongHld == 0 && LatHld == 0) {
+ color = 0;
+ map_plot (w,
+ max_x,
+ max_y,
+ (long)x_long_cord,
+ (long)y_lat_cord,
+ (unsigned char)color,
+ 0,
+ destination_pixmap,
+ draw_filled);
+ }
+ else if (LongHld == 0 && LatHld == -1) {
+ dos_labels = (int)TRUE;
+ map_plot (w,
+ max_x,
+ max_y,
+ (long)x_long_cord,
+ (long)y_lat_cord,
+ (unsigned char)color,
+ 0,
+ destination_pixmap,
+ draw_filled);
+ }
+
+ if (color && !dos_labels) {
+ trailer = Buffer;
+
+ for (k = strlen (trailer) - 1; k >= 0; k--) {
+ trailer[k] = (char)((int)trailer[k] - 27);
+ }
+
+ while (*trailer) {
+
+ LongHld = (long)( (int)(*(unsigned char *)trailer) * 16);
+ trailer++;
+ LatHld = (long)( (int)(*(unsigned char *)trailer) * 8);
+ trailer++;
+ LongHld += (long)((*(unsigned char *)trailer >> 3) & 0xf);
+ LatHld += (*trailer) & 7l;
+ trailer++;
+ LatHld = ((double)LatHld * 360000.0) / points_per_degree;
+ LongHld = ((double)LongHld * 360000.0) / points_per_degree;
+ x_long_cord = LongHld + left_boundary;
+ y_lat_cord = LatHld + top_boundary;
+ map_plot (w,
+ max_x,
+ max_y,
+ (long)x_long_cord,
+ (long)y_lat_cord,
+ (unsigned char)color,
+ 0,
+ destination_pixmap,
+ draw_filled);
+ }
+ }
+ }
+ }
+ else {
+ LongHld = strtol (Buffer, &trailer, 0);
+ if (trailer) {
+ if (*trailer == ',' || *trailer == ' ') {
+ if (LongHld == 0) {
+ xastir_snprintf(map_version,sizeof(map_version),"ASCII");
+ }
+
+ map_version[4] = '\0';
+
+ trailer++;
+
+ dos_flag = (int)strtol (trailer, &trailer, 0);
+ if (dos_flag == -1) {
+ dos_labels = (int)TRUE;
+ }
+
+ if (dos_flag == 0 && *trailer != '\0') {
+ xastir_snprintf(map_version,sizeof(map_version),"Line");
+ map_version[4] = '\0';
+ goto process;
+ }
+ color = (int)LongHld;
+ }
+ }
+ else {
+ xastir_snprintf(map_version,sizeof(map_version),"Comp");
+ }
+ map_version[4] = '\0';
+ }
+ xastir_snprintf(Buffer,sizeof(Buffer),"%s",ptr);
+ }
+ }
+ else {
+
+// Windows type map...
+
+ last_behavior = object_behavior;
+ (void)fread (&vector_start, 1, 1, f);
+ (void)fread (&object_behavior, 1, 1, f); // Fill Color?
+
+ if (strcmp (map_type, "COMP") == 0) {
+ short temp_short;
+ long LatOffset, LongOffset;
+
+ LatOffset = (long)(top_boundary - top_boundary % 6000);
+ LongOffset = (long)(left_boundary - left_boundary % 6000);
+ (void)fread (&temp_short, 2, 1, f);
+ x_long_cord = (ntohs (temp_short) * 10 + LongOffset);
+ (void)fread (&temp_short, 2, 1, f);
+ y_lat_cord = (ntohs (temp_short) * 10 + LatOffset);
+ }
+ else {
+ (void)fread (&temp, 4, 1, f);
+ x_long_cord = ntohl (temp);
+ if (strcmp (map_version, "2.00") != 0)
+ x_long_cord *= 10;
+
+ (void)fread (&temp, 4, 1, f);
+ y_lat_cord = ntohl (temp);
+ if (strcmp (map_version, "2.00") != 0)
+ y_lat_cord *= 10;
+ }
+
+ if (alert_color && last_behavior & 0x80 && (int)vector_start == 0xff) {
+ map_plot (w,
+ max_x,
+ max_y,
+ (long)x_long_cord,
+ (long)y_lat_cord,
+ '\0',
+ (long)alert_color,
+ destination_pixmap,
+ draw_filled);
+ //special_fill = TRUE;
+ }
+ map_plot (w,
+ max_x,
+ max_y,
+ (long)x_long_cord,
+ (long)y_lat_cord,
+ vector_start,
+ (long)object_behavior,
+ destination_pixmap,
+ draw_filled);
+ }
+ }
+ if (alert_color) {
+ map_plot (w,
+ max_x,
+ max_y,
+ 0,
+ 0,
+ '\0',
+ special_fill ? (long)0xfd : (long)alert_color,
+ destination_pixmap,
+ draw_filled);
+ }
+ else {
+ map_plot (w,
+ max_x,
+ max_y,
+ 0,
+ 0,
+ (unsigned char)0xff,
+ 0,
+ destination_pixmap,
+ draw_filled);
+ }
+
+ (void)XSetForeground (XtDisplay (w), gc, colors[20]);
+ line_width = 2;
+ (void)XSetLineAttributes (XtDisplay (w), gc, line_width, LineSolid, CapButt,JoinMiter);
+
+
+ // Here is the map label section of the code for both DOS & Windows-type maps
+ if (map_labels) {
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ (void)fclose(f);
+
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ /* read labels */
+ for (count = 0l; count < total_labels && !feof (f); count++) {
+
+//DOS-Type Map Labels
+
+ embedded_object = 0;
+
+ if (strcmp (map_type, "DOS ") == 0) { // Handle DOS-type map labels/embedded objects
+ char *trailer;
+
+ (void)fgets (&Buffer[strlen (Buffer)],(int)sizeof (Buffer) - (strlen (Buffer)), f);
+
+ for (; (ptr = strpbrk (Buffer, "\r\n")) != NULL;xastir_snprintf(Buffer,sizeof(Buffer),"%s",ptr)) {
+
+ *ptr = '\0';
+ label_type[0] = (char)0x08;
+
+ for (ptr++; *ptr == '\r' || *ptr == '\n'; ptr++) ;
+
+ trailer = strchr (Buffer, ',');
+ if (trailer && strncmp (Buffer, "0", 1) != 0) {
+ *trailer = '\0';
+ trailer++;
+ xastir_snprintf(label_text,sizeof(label_text),"%s",Buffer);
+
+ // Check for '#' or '$' as the first character of the label.
+ // If found, we have an embedded symbol and colored text to display.
+ symbol_table = ' ';
+ symbol_id = ' ';
+ symbol_color = '0';
+
+ if ( (label_text[0] == '$') || (label_text[0] == '#') ) {
+ // We found an embedded map object
+ embedded_object = 1; // Set the flag
+ if (label_text[0] == '$') { // Old format: $xC
+ symbol_table = '/';
+ symbol_id = label_text[1];
+ symbol_color = label_text[2];
+ // Take the object out of the label text
+ xastir_snprintf(label_text,sizeof(label_text),"%s",Buffer+3);
+ }
+ else { // Could be in new or old format with a leading '#' character
+ symbol_table = label_text[1];
+ if (symbol_table == '/' || symbol_table == '\\') { // New format: #/xC
+ symbol_id = label_text[2];
+ symbol_color = label_text[3];
+ // Take the object out of the label text
+ xastir_snprintf(label_text,sizeof(label_text),"%s",Buffer+4);
+ }
+ else { // Old format: #xC
+ symbol_table = '\\';
+ symbol_id = label_text[1];
+ symbol_color = label_text[2];
+ // Take the object out of the label text
+ xastir_snprintf(label_text,sizeof(label_text),"%s",Buffer+3);
+ }
+ }
+ if (debug_level & 512)
+ fprintf(stderr,"Found embedded object: %c %c %c %s\n",symbol_table,symbol_id,symbol_color,label_text);
+ }
+
+
+ label_length = (int)strlen (label_text);
+ label_y_cord = (unsigned long) (-strtod (trailer, &trailer) * 360000) + 32400000;
+ trailer++;
+ label_x_cord = (unsigned long) (-strtod (trailer, &trailer) * 360000) + 64800000;
+ trailer++;
+ label_mag = (int)strtol (trailer, &trailer, 0) * 20;
+
+ if ((label_type[0] & 0x80) == '\0') /* left of coords */
+ x = ((label_x_cord - NW_corner_longitude) / scale_x) - (label_length * 6);
+ else /* right of coords */
+ x = ((label_x_cord - NW_corner_longitude) / scale_x);
+
+ y = ((label_y_cord - NW_corner_latitude) / scale_y);
+ if (x > (0) && (x < (int)screen_width)) {
+ if (y > (0) && (y < (int)screen_height)) {
+ /*fprintf(stderr,"Label mag %d mag %d\n",label_mag,(scale_x*2)-1); */
+ //if (label_mag > (int)((scale_x * 2) - 1) || label_mag == 0)
+ if (label_mag > (int)((scale_x) - 1) || label_mag == 0) {
+ if (embedded_object) {
+ // NOTE: 0x21 is the first color for the area object or "DOS" colors
+ draw_label_text (w, x+10, y+5, label_length,colors[0x21 + symbol_color],label_text);
+ symbol(w,0,symbol_table,symbol_id,' ',pixmap,1,x-10,y-10,' ');
+ }
+ else {
+ draw_label_text (w, x, y, label_length,colors[(int)(label_type[0] & 0x7f)],label_text);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else { // Handle Windows-type map labels/embedded objects
+ int rotation = 0;
+ char rotation_factor[5];
+
+// Windows-Type Map Labels
+
+ char label_type_1[2], label_type_2[2];
+
+ // Snag first two bytes of label
+ (void)fread (label_type_1, 1, 1, f);
+ (void)fread (label_type_2, 1, 1, f);
+
+ if (label_type_2[0] == '\0') { // Found a label
+
+ // Found text label
+ (void)fread (&temp, 4, 1, f); /* x */
+ label_x_cord = ntohl (temp);
+ if (strcmp (map_version, "2.00") != 0)
+ label_x_cord *= 10;
+
+ (void)fread (&temp, 4, 1, f); /* y */
+ label_y_cord = ntohl (temp);
+ if (strcmp (map_version, "2.00") != 0)
+ label_y_cord *= 10;
+
+ (void)fread (&temp_mag, 2, 1, f); /* mag */
+ label_mag = (int)ntohs (temp_mag);
+ if (strcmp (map_version, "2.00") != 0)
+ label_mag *= 10;
+
+ if (strcmp (map_type, "COMP") == 0) {
+
+ for (i = 0; i < 32; i++) {
+ (void)fread (&label_text[i], 1, 1, f);
+ if (label_text[i] == '\0') {
+ break;
+ }
+ }
+ label_text[32] = '\0'; // Make sure we have a terminator
+ }
+ else {
+ (void)fread (label_text, 32, 1, f); /* text */
+ label_text[32] = '\0'; // Make sure we have a terminator
+ }
+
+
+ // Special strings like: "#123" are rotation factors for labels
+ // in degrees. This is not documented in the windows-type map
+ // format documents that I could find.
+ if (label_text[0] == '#') {
+ int i,j;
+
+ if (debug_level & 512)
+ fprintf(stderr,"%s\n",label_text);
+
+ // Save the rotation factor in "rotation"
+ for ( i=1; i<4; i++ ) {
+ rotation_factor[i-1] = label_text[i];
+ }
+
+ rotation_factor[3] = '\0';
+ rotation = atoi(rotation_factor);
+
+ // Take rotation factor out of label string
+ for ( i=4, j=0; i < (int)(strlen(label_text)+1); i++,j++) {
+ label_text[j] = label_text[i];
+ }
+
+ //fprintf(stderr,"Windows label: %s, rotation factor: %d\n",label_text, rotation);
+ }
+
+ label_length = (int)strlen (label_text);
+
+ for (i = (label_length - 1); i > 0; i--) {
+ if (label_text[i] == ' ') {
+ label_text[i] = '\0';
+ }
+ else {
+ break;
+ }
+ }
+
+ label_length = (int)strlen (label_text);
+ /*fprintf(stderr,"labelin:%s\n",label_text); */
+
+ if ((label_type_1[0] & 0x80) == '\0') {
+ /* left of coords */
+ x = ((label_x_cord - NW_corner_longitude) / scale_x) - (label_length * 6);
+ x = 0; // ??????
+ }
+ else {
+ /* right of coords */
+ x = ((label_x_cord - NW_corner_longitude) / scale_x);
+ }
+
+ y = ((label_y_cord - NW_corner_latitude) / scale_y);
+
+ if (x > (0) && (x < (int)screen_width)) {
+
+ if (y > (0) && (y < (int)screen_height)) {
+
+ /*fprintf(stderr,"Label mag %d mag %d\n",label_mag,(scale_x*2)-1); */
+ //if (label_mag > (int)((scale_x * 2) - 1) || label_mag == 0)
+ if (label_mag > (int)((scale_x) - 1) || label_mag == 0) {
+ // Note: We're not drawing the labels in the right colors
+ if (rotation == 0) { // Non-rotated label
+// draw_label_text (w,
+// x,
+// y,
+// label_length,
+// colors[(int)(label_type_1[0] & 0x7f)],
+// label_text);
+ draw_rotated_label_text (w,
+ -90.0,
+ x,
+ y,
+ label_length,
+ colors[(int)(label_type_1[0] & 0x7f)],
+ label_text,
+ FONT_DEFAULT);
+ }
+ else { // Rotated label
+ draw_rotated_label_text (w,
+ rotation,
+ x,
+ y,
+ label_length,
+ colors[(int)(label_type_1[0] & 0x7f)],
+ label_text,
+ FONT_DEFAULT);
+ }
+ }
+ }
+ }
+ }
+ else if (label_type_2[0] == '\1' && label_type_1[0] == '\0') { // Found an embedded object
+
+ //fprintf(stderr,"Found windows embedded symbol\n");
+
+ /* label is an embedded symbol */
+ (void)fread (&temp, 4, 1, f);
+ label_x_cord = ntohl (temp);
+ if (strcmp (map_version, "2.00") != 0)
+ label_x_cord *= 10;
+
+ (void)fread (&temp, 4, 1, f);
+ label_y_cord = ntohl (temp);
+ if (strcmp (map_version, "2.00") != 0)
+ label_y_cord *= 10;
+
+ (void)fread (&temp_mag, 2, 1, f);
+ label_mag = (int)ntohs (temp_mag);
+ if (strcmp (map_version, "2.00") != 0)
+ label_mag *= 10;
+
+ (void)fread (&label_symbol_del, 1, 1, f); // Snag symbol table char
+ (void)fread (&label_symbol_char, 1, 1, f); // Snag symbol char
+ (void)fread (&label_text_color, 1, 1, f); // Snag text color (should be 1-9, others should default to black)
+ if (label_text_color < '1' && label_text_color > '9')
+ label_text_color = '0'; // Default to black
+
+ x = ((label_x_cord - NW_corner_longitude) / scale_x);
+ y = ((label_y_cord - NW_corner_latitude) / scale_y);
+
+ // Read the label text portion
+ if (strcmp (map_type, "COMP") == 0) {
+
+ for (i = 0; i < 32; i++) {
+ (void)fread (&label_text[i], 1, 1, f);
+ if (label_text[i] == '\0')
+ break;
+ }
+ }
+ else {
+ (void)fread (label_text, 29, 1, f);
+ }
+
+ // NOTE: 0x21 is the first color for the area object or "DOS" colors
+ draw_label_text (w, x+10, y+5, strlen(label_text),colors[0x21 + label_text_color],label_text);
+ symbol(w,0,label_symbol_del,label_symbol_char,' ',pixmap,1,x-10,y-10,' ');
+
+ if (debug_level & 512)
+ fprintf(stderr,"Windows map, embedded object: %c %c %c %s\n",
+
+ label_symbol_del,label_symbol_char,label_text_color,label_text);
+ }
+ else {
+ if (debug_level & 512)
+ fprintf(stderr,"Weird label in Windows map, neither a plain label nor an object: %d %d\n",
+ label_type_1[0],label_type_2[0]);
+ }
+ }
+ }
+ } // if (map_labels)
+
+ (void)fclose (f);
+}
+
+
diff --git a/src/map_gdal.c b/src/map_gdal.c
new file mode 100644
index 0000000..e712bd3
--- /dev/null
+++ b/src/map_gdal.c
@@ -0,0 +1,5087 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: map_gdal.c,v 1.159 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 2004-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ *
+ *
+ */
+
+
+#define TIGER_POLYGONS
+
+
+//
+// NOTE: GDAL sample data can be found here:
+//
+// ftp://ftp.remotesensing.org/gdal/data
+// or here: http://gdal.maptools.org/dl/data/
+//
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+//#include <stdio.h>
+#include <stdlib.h>
+//#include <unistd.h>
+//#include <sys/stat.h>
+//#include <ctype.h>
+//#include <sys/types.h>
+//#include <pwd.h>
+//#include <errno.h>
+
+// Needed for Solaris
+//#ifdef HAVE_STRINGS_H
+//#include <strings.h>
+//#endif // HAVE_STRINGS_H
+
+//#include <dirent.h>
+//#include <netinet/in.h>
+//#include <Xm/XmAll.h>
+
+//#ifdef HAVE_X11_XPM_H
+//#include <X11/xpm.h>
+//#ifdef HAVE_LIBXPM // if we have both, prefer the extra library
+//#undef HAVE_XM_XPMI_H
+//#endif // HAVE_LIBXPM
+//#endif // HAVE_X11_XPM_H
+
+//#ifdef HAVE_XM_XPMI_H
+//#include <Xm/XpmI.h>
+//#endif // HAVE_XM_XPMI_H
+
+//#include <X11/Xlib.h>
+
+//#include <math.h>
+
+#include "maps.h"
+#include "alert.h"
+//#include "util.h"
+#include "main.h"
+//#include "datum.h"
+#include "draw_symbols.h"
+//#include "rotated.h"
+//#include "color.h"
+//#include "xa_config.h"
+
+#ifdef TIGER_POLYGONS
+#include "hashtable.h"
+#include "hashtable_itr.h"
+#endif // TIGER_POLYGONS
+
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+
+
+#ifdef HAVE_LIBGDAL
+
+//#warning
+//#warning
+//#warning GDAL/OGR library support is not fully implemented yet!
+//#warning Preliminary TIGER/Line, Shapefile, mid/mif/tab (MapInfo),
+//#warning and SDTS support is functional, including on-the-fly
+//#warning coordinate conversion for both indexing and drawing.
+//#warning
+//#warning
+
+// Getting rid of stupid compiler warnings in GDAL
+#define XASTIR_PACKAGE_BUGREPORT PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#define XASTIR_PACKAGE_NAME PACKAGE_NAME
+#undef PACKAGE_NAME
+#define XASTIR_PACKAGE_STRING PACKAGE_STRING
+#undef PACKAGE_STRING
+#define XASTIR_PACKAGE_TARNAME PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#define XASTIR_PACKAGE_VERSION PACKAGE_VERSION
+#undef PACKAGE_VERSION
+
+#include "gdal.h"
+#include "ogr_api.h"
+#include "ogr_srs_api.h"
+//#include "cpl_string.h"
+
+#undef PACKAGE_BUGREPORT
+#define PACKAGE_BUGREPORT XASTIR_PACKAGE_BUGREPORT
+#undef XASTIR_PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#define PACKAGE_NAME XASTIR_PACKAGE_NAME
+#undef XASTIR_PACKAGE_NAME
+#undef PACKAGE_STRING
+#define PACKAGE_STRING XASTIR_PACKAGE_STRING
+#undef XASTIR_PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#define PACKAGE_TARNAME XASTIR_PACKAGE_TARNAME
+#undef XASTIR_PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#define PACKAGE_VERSION XASTIR_PACKAGE_VERSION
+#undef XASTIR_PACKAGE_VERSION
+#endif // HAVE_LIBGDAL
+
+
+// Needs to be down here so that the LIB_GC stuff will compile in
+// ok.
+#include "xastir.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+
+
+void map_gdal_init(void) {
+
+#ifdef HAVE_LIBGDAL
+
+ GDALDriverH gDriver; // GDAL driver
+ OGRSFDriverH oDriver; // OGR driver
+ int ii;
+ int jj;
+
+
+ // Register all known GDAL drivers
+ GDALAllRegister();
+
+ // Register all known OGR drivers
+ OGRRegisterAll();
+
+ // Print out each supported GDAL driver.
+ //
+ ii = GDALGetDriverCount();
+
+// fprintf(stderr," GDAL Registered Drivers:\n");
+ for (jj = 0; jj < ii; jj++) {
+ gDriver = GDALGetDriver(jj);
+// fprintf(stderr,"%10s %s\n",
+// GDALGetDriverShortName(gDriver),
+// GDALGetDriverLongName(gDriver) );
+ }
+// fprintf(stderr," (none)\n");
+
+
+ // Print out each supported OGR driver
+ //
+ ii = OGRGetDriverCount();
+
+// fprintf(stderr," OGR Registered Drivers:\n");
+
+ for (jj = 0; jj < ii; jj++) {
+ char *drv_name;
+
+
+ oDriver = OGRGetDriver(jj);
+ drv_name = (char *)OGR_Dr_GetName(oDriver);
+
+ if (strstr(drv_name,"Shapefile")) {
+#ifdef GDAL_SHAPEFILES
+ fprintf(stderr," shp ESRI Shapefile (via GDAL)\n");
+#endif // GDAL_SHAPEFILES
+ }
+ else if (strstr(drv_name,"NTF")) {
+ // Not enabled in Xastir yet
+ }
+ else if (strstr(drv_name,"SDTS")) {
+ fprintf(stderr," ddf Spatial Data Transfer Standard (SDTS)\n");
+ }
+ else if (strstr(drv_name,"TIGER")) {
+ fprintf(stderr," rt1 US Census Bureau TIGER/Line\n");
+ }
+ else if (strstr(drv_name,"S57")) {
+ fprintf(stderr," s57 International Hydrographic Organization (IHO) S-57\n");
+ }
+ else if (strstr(drv_name,"MapInfo")) {
+ fprintf(stderr," tab MapInfo TAB\n");
+ fprintf(stderr," mid MapInfo MID\n");
+ fprintf(stderr," mif MapInfo MIF\n");
+ }
+ else if (strstr(drv_name,"DGN")) {
+ fprintf(stderr," dgn MicroStation DGN\n");
+ }
+ else if (strstr(drv_name,"VRT")) {
+ // Not enabled in Xastir yet
+ }
+ else if (strstr(drv_name,"AVCBin")) {
+ // Not enabled in Xastir yet
+ }
+ else if (strstr(drv_name,"REC")) {
+ // Not enabled in Xastir yet
+ }
+ else if (strstr(drv_name,"Memory")) {
+ // Not enabled in Xastir yet
+ }
+ else if (strstr(drv_name,"GML")) {
+ // Not enabled in Xastir yet
+ }
+ else if (strstr(drv_name,"PostgreSQL")) {
+ // Not enabled in Xastir yet
+ }
+ }
+ fprintf(stderr,"\n");
+
+ atexit(GDALDestroyDriverManager);
+#endif // HAVE_LIBGDAL
+
+}
+
+
+
+
+
+/* TODO:
+ * projections
+ * multiple bands
+ * colormaps
+ * .geo files vs. .wld
+ * map index
+ */
+
+
+#ifdef HAVE_LIBGDAL
+
+void draw_gdal_map(Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *mdf) {
+
+ GDALDatasetH hDataset;
+ char file[MAX_FILENAME]; // Complete path/name of image
+ GDALDriverH hDriver;
+ double adfGeoTransform[6];
+// double map_x_mind, map_x_maxd, map_dxd; // decimal degrees
+// double map_y_mind, map_y_maxd, map_dyd; // decimal degrees
+ unsigned long map_x_min, map_x_max; // xastir units
+ unsigned long map_y_min, map_y_max; // xastir units
+ long map_dx, map_dy; // xastir units
+ double scr_m_dx, scr_m_dy; // screen pixels per map pixel
+ unsigned long map_s_x_min, map_s_x_max, map_s_x; // map pixels
+// unsigned long map_s_y_min, map_s_y_max, map_s_y; // map pixels
+ unsigned long scr_s_x_min, scr_s_x_max, scr_s_x; // screen pixels
+// unsigned long scr_s_y_min, scr_s_y_max, scr_s_y; // screen pixels
+
+ //
+ GDALRasterBandH hBand = NULL;
+ int numBand, hBandc;
+ int nBlockXSize, nBlockYSize;
+ // int bGotMin, bGotMax;
+ // double adfMinMax[2];
+ //
+ const char *pszProjection;
+ float *pafScanline;
+ int nXSize;
+ unsigned int width,height;
+ GDALColorTableH hColorTable;
+ GDALColorInterp hColorInterp;
+ GDALPaletteInterp hPalInterp;
+ GDALColorEntry colEntry;
+ GDALDataType hType;
+ double dfNoData;
+ int bGotNodata;
+ int i;
+
+ xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm);
+
+ if ( debug_level & 16 )
+ fprintf(stderr,"Calling GDALOpen on file: %s\n", file);
+
+ hDataset = GDALOpenShared( file, GA_ReadOnly );
+
+ if( hDataset == NULL ) {
+ fprintf(stderr,"GDAL couldn't open file: %s\n", file);
+ }
+
+
+ if ( debug_level & 16 ) {
+ hDriver = GDALGetDatasetDriver( hDataset );
+ fprintf( stderr, "Driver: %s/%s\n",
+ GDALGetDriverShortName( hDriver ),
+ GDALGetDriverLongName( hDriver ) );
+
+ fprintf( stderr,"Size is %dx%dx%d\n",
+ GDALGetRasterXSize( hDataset ),
+ GDALGetRasterYSize( hDataset ),
+ GDALGetRasterCount( hDataset ) );
+
+ if( GDALGetProjectionRef( hDataset ) != NULL )
+ fprintf( stderr,"Projection is `%s'\n", GDALGetProjectionRef( hDataset ) );
+
+ if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None ) {
+ fprintf( stderr,"Origin = (%.6f,%.6f)\n",
+ adfGeoTransform[0], adfGeoTransform[3] );
+
+ fprintf( stderr,"Pixel Size = (%.6f,%.6f)\n",
+ adfGeoTransform[1], adfGeoTransform[5] );
+ }
+ }
+ pszProjection = GDALGetProjectionRef( hDataset );
+ GDALGetGeoTransform( hDataset, adfGeoTransform );
+ numBand = GDALGetRasterCount( hDataset );
+ width = GDALGetRasterXSize( hDataset );
+ height = GDALGetRasterYSize( hDataset );
+ // will have to delay these calcs until after a proj call
+ map_x_min = 64800000l + (360000.0 * adfGeoTransform[0]);
+ map_x_max = 64800000l + (360000.0 * (adfGeoTransform[0] + adfGeoTransform[1] * width));
+ map_y_min = 32400000l + (360000.0 * (-adfGeoTransform[3] ));
+ map_y_max = 32400000l + (360000.0 * (-adfGeoTransform[3] + adfGeoTransform[5] * height));
+ map_dx = adfGeoTransform[1] * 360000.0;
+ map_dy = adfGeoTransform[5] * 360000.0;
+ scr_m_dx = scale_x / map_dx;
+ scr_m_dy = scale_y / map_dy;
+
+ /*
+ * Here are the corners of our viewport, using the Xastir
+ * coordinate system. Notice that Y is upside down:
+ *
+ * left edge of view = NW_corner_longitude
+ * right edge of view = SE_corner_longitude
+ * top edge of view = NW_corner_latitude
+ * bottom edge of view = SE_corner_latitude
+ *
+ * The corners of our map:
+ *
+ * left edge of map = map_x_min in Xastir format
+ * right edge of map = map_x_max
+ * top edge of map = map_y_min
+ * bottom edge of map = map_y_max
+ *
+ * Map scale in xastir units per pixel: map_dx and map_dy
+ * Map scale in screen pixels per map pixel: scr_m_dx and scr_m_dy
+ *
+ * map pixel offsets that are on screen:
+ * left edge of map = map_s_x_min
+ * right edge of map = map_s_x_max
+ * top edge of map = map_s_y_min
+ * bottom edge of map = map_s_y_max
+ *
+ * screen pixel offsets for map edges:
+ * left edge of map = scr_s_x_min
+ * right edge of map = scr_s_x_max
+ * top edge of map = scr_s_y_min
+ * bottom edge of map = scr_s_y_max
+ *
+ */
+
+
+// Setting some variables that haven't been set yet.
+map_s_x_min = 0;
+scr_s_x_min = 0;
+
+
+ // calculate map range on screen
+ scr_s_x_max = map_s_x_max = 0ul;
+ for ( map_s_x = 0, scr_s_x = 0; map_s_x_min < width; map_s_x_min++, scr_s_x_min += scr_m_dx) {
+ if ((NW_corner_longitude + (scr_s_x_min * scale_x)) > (map_x_min + (map_s_x_min * map_dx)))
+ map_s_x_min = map_s_x;
+
+
+ }
+
+ for (hBandc = 0; hBandc < numBand; hBandc++) {
+ hBand = GDALGetRasterBand( hDataset, hBandc + 1 );
+ dfNoData = GDALGetRasterNoDataValue( hBand, &bGotNodata );
+ GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
+ hType = GDALGetRasterDataType(hBand);
+
+ if ( debug_level & 16 ) {
+ fprintf(stderr, "Band %d (/%d):\n", hBandc, numBand);
+ fprintf( stderr, " Block=%dx%d Type=%s.\n",
+ nBlockXSize, nBlockYSize,
+ GDALGetDataTypeName(hType) );
+ if( GDALGetDescription( hBand ) != NULL
+ && strlen(GDALGetDescription( hBand )) > 0 )
+ fprintf(stderr, " Description = %s\n", GDALGetDescription(hBand) );
+ if( strlen(GDALGetRasterUnitType(hBand)) > 0 )
+ fprintf(stderr, " Unit Type: %s\n", GDALGetRasterUnitType(hBand) );
+ if( bGotNodata )
+ fprintf(stderr, " NoData Value=%g\n", dfNoData );
+ }
+ // handle colormap stuff
+
+ hColorInterp = GDALGetRasterColorInterpretation ( hBand );
+ if ( debug_level & 16 )
+ fprintf ( stderr, " Band's Color is interpreted as %s.\n",
+ GDALGetColorInterpretationName (hColorInterp));
+
+ if( GDALGetRasterColorInterpretation(hBand) == GCI_PaletteIndex ) {
+
+ hColorTable = GDALGetRasterColorTable( hBand );
+ hPalInterp = GDALGetPaletteInterpretation ( hColorTable );
+
+ if ( debug_level & 16 )
+ fprintf( stderr, " Band has a color table (%s) with %d entries.\n",
+ GDALGetPaletteInterpretationName( hPalInterp),
+ GDALGetColorEntryCount( hColorTable ) );
+
+ for( i = 0; i < GDALGetColorEntryCount( hColorTable ); i++ ) {
+ GDALGetColorEntryAsRGB( hColorTable, i, &colEntry );
+ fprintf( stderr, " %3d: %d,%d,%d,%d\n",
+ i,
+ colEntry.c1,
+ colEntry.c2,
+ colEntry.c3,
+ colEntry.c4 );
+ }
+ } // PaletteIndex
+
+
+ }
+ //
+
+ if ( numBand == 1) { // single band
+
+ }
+ if ( numBand == 3) { // seperate RGB bands
+
+ }
+
+
+
+
+
+ nXSize = GDALGetRasterBandXSize( hBand );
+
+ pafScanline = (float *) malloc(sizeof(float)*nXSize);
+ CHECKMALLOC(pafScanline);
+
+ GDALRasterIO( hBand, GF_Read, 0, 0, nXSize, 1,
+ pafScanline, nXSize, 1, GDT_Float32,
+ 0, 0 );
+
+ /* The raster is */
+
+
+
+
+ // Check for map draw interrupts. Clean up and exit if found.
+ // Put this also inside the raster-line processing loop so that
+ // it gets check once per raster line. That makes for fast
+ // zooming/panning even with a lot of maps selected.
+ //
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ return; // Exit early
+ }
+
+
+
+
+ GDALClose(hDataset);
+}
+
+
+
+/////////////////////////////////////////////////////////////////////
+// Above this point is GDAL code (raster), below is OGR code
+// (vector).
+/////////////////////////////////////////////////////////////////////
+
+
+
+//WE7U
+//
+// Possible Optimizations:
+// -----------------------
+//
+// For Tiger and/or SDTS: If we can figure out what type of map we
+// have, only load those layers that make sense. Skip the rest.
+//
+// Only change the drawing style/color if it is different than the
+// last specified one. Have the drawing routines actually make the
+// X11 calls instead of the "guess" function, in order to eliminate
+// extra calls.
+//
+// Compute the spatial transforms for a layer only if it has a
+// different spatial reference from the last layer.
+//
+// Break the "guess" function into one for files, one for layers,
+// and perhaps one for features. Call the "features" one sparingly
+// if it exists, so that we can skip that code most of the time.
+//
+// Re-write the "guess" function so that it turns into a general map
+// preferences feature. Make sure to use hash tables to keep it
+// fast.
+//
+// Tie the Tigermap config buttons into the TIGER/Line layers as
+// well, skip those layers that we don't have selected. Perhaps tie
+// Tiger/Shapefiles into the same scheme as those have specific
+// filenames we can key off of.
+
+
+
+int label_color_guess;
+int sdts_elevation_in_meters = 1; // Default meters
+int hypsography_layer = 0; // Topo contours
+int hydrography_layer = 0; // Underwater contours
+int water_layer = 0;
+int roads_trails_layer = 0;
+int railroad_layer = 0;
+int misc_transportation_layer = 0;
+
+
+
+// guess_vector_attributes()
+//
+// Feel free to change the name. At the moment it's somewhat
+// appropriate, but I would hope that in the future it won't be.
+// This should tie in nicely to the dbfawk stuff, and perhaps other
+// schemes for the user to determine drawing attributes. Basically,
+// if dbfawk is compiled in, go do that instead of doing what this
+// routine does.
+//
+// What we need to do: Come up with a signature match for the
+// driver type, filename, layer, and sometimes object_type and
+// file_attributes. Use that to determine drawing width, label
+// size/placement, color, etc. If the signature could also specify
+// how often the signature needs to be re-examined, that would be a
+// plus. If it only needs to be set once per file, we could save a
+// lot of time.
+//
+// Note that draw_polygon_with_mask() uses gc_temp instead of gc.
+// This means we have to pass colors down to it so that it can set
+// the color itself. We currently just use the label_color variable
+// to do this, but we really should use a different variable, as
+// label color and object color can be different.
+//
+// Depending on what needs to be done for different file
+// types/layers/geometries, we might want to break this function up
+// into several, so that we can optimize for speed. If something
+// only needs to be set once per file, or once per layer, do so.
+// Don't set it over and over again (Don't set it once per object
+// drawn).
+//
+// Consider trying GXxor function with gc_tint someday to see what
+// the contour lines look like with that method: Should make them
+// quite readable no matter what the underlying map colors.
+//
+// Set attributes based on what sort of file/layer/shape we're
+// dealing with. driver_type may be any of:
+//
+// "AVCbin"
+// "DGN"
+// "FMEObjects Gateway"
+// "GML"
+// "Memory"
+// "MapInfo File"
+// "UK .NTF"
+// "OCI"
+// "ODBC"
+// "OGDI"
+// "PostgreSQL"
+// "REC"
+// "S57"
+// "SDTS"
+// "ESRI Shapefile"
+// "TIGER"
+// "VRT"
+//
+// Shapefiles: If Mapshots or ESRI tiger->Shapefiles, guess the
+// coloring and line widths based on the filename and the associated
+// field contents.
+//
+// SDTS: Guess the coloring/line widths based on the ENTITY_LABEL.
+//
+// TIGER: Guess coloring/line widths based on the CFCC field.
+//
+// MapInfo: Guess based on layer?
+//
+// DGN: ??
+//
+//
+void guess_vector_attributes( Widget w,
+ const char *driver_type,
+ char *full_filename,
+ OGRLayerH layerH,
+ OGRFeatureH featureH,
+ int geometry_type ) {
+ int ii;
+ const char *pii = NULL;
+
+ label_color_guess = -1; // Default = don't draw the feature
+
+
+//fprintf(stderr,"guess: %s\n", full_filename);
+
+
+ // Default line type
+ (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineSolid, CapButt,JoinMiter);
+
+
+/*
+ switch (driver_type) {
+ default:
+ break;
+ }
+
+
+ switch (layerH) {
+ case 0:
+ case 1:
+ default:
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black
+ break;
+ }
+*/
+
+
+
+ // SDTS FILES
+ // ----------
+ // Check the ENTITY_LABEL. That gives us very detailed info
+ // about the type of feature we're dealing with so that we can
+ // decide how to draw it.
+ //
+ if (strstr(driver_type,"SDTS")) {
+
+ ii = OGR_F_GetFieldIndex( featureH, "ENTITY_LABEL");
+ if (ii != -1) {
+ const char *entity_num;
+
+ entity_num = OGR_F_GetFieldAsString( featureH, ii);
+
+//fprintf(stderr,"ENTITY_LABEL: %s\n", entity_num);
+
+ if (strncmp(entity_num,"020",3) == 0) {
+ // Contour lines
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x0e]); // yellow
+ label_color_guess = 0x0e; // yellow
+ }
+ else if (strncmp(entity_num,"050",3) == 0) {
+ // hydrography
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x0e]); // yellow
+ label_color_guess = 0x0e; // yellow
+ }
+ else if (strncmp(entity_num,"070",3) == 0) {
+ // vegetative surface cover
+ label_color_guess = -1;
+ return; // Don't display it
+ }
+ else if (strncmp(entity_num,"080",3) == 0) {
+ // non-vegetative features
+ label_color_guess = -1;
+ return; // Don't display it
+ }
+ else if (strncmp(entity_num,"090",3) == 0) {
+ // boundaries
+ label_color_guess = -1;
+ return; // Don't display it
+ }
+ else if (strncmp(entity_num,"150",3) == 0) {
+ // survey control and markers
+ label_color_guess = -1;
+ return; // Don't display it
+ }
+ else if (strncmp(entity_num,"170",3) == 0) {
+ // roads and trails
+ (void)XSetForeground(XtDisplay(da), gc, colors[(int)0x08]); // black
+ label_color_guess = 0x08;
+ }
+ else if (strncmp(entity_num,"180",3) == 0) {
+ // railroads
+ (void)XSetLineAttributes (XtDisplay (w), gc, 1, LineOnOffDash, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da), gc, colors[(int)0x01]); // purple
+ label_color_guess = 0x01;
+ }
+ else if (strncmp(entity_num,"190",3) == 0) {
+ // pipelines, transmissions lines, misc transportation
+ (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineOnOffDash, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da), gc, colors[(int)0x4d]); // white
+ label_color_guess = 0x4d;
+ }
+ else if (strncmp(entity_num,"200",3) == 0) {
+ // man-made features
+ label_color_guess = -1;
+ return; // Don't display it
+ }
+ else if (strncmp(entity_num,"300",3) == 0) {
+ // public land survey system
+ label_color_guess = -1;
+ return; // Don't display it
+ }
+ }
+ return;
+ } // End of SDTS
+
+
+
+ // RAW TIGER FILES
+ // ---------------
+ // Attempt to snag the CFCC field. This tells us what the
+ // feature is and we can get clues from it as to how to draw the
+ // feature.
+ //
+ if (strstr(driver_type,"TIGER")) {
+
+ ii = OGR_F_GetFieldIndex(featureH, "CFCC");
+
+ if (ii != -1) { // Found one of the fields
+
+ pii = OGR_F_GetFieldAsString(featureH, ii);
+
+//fprintf(stderr,"CFCC: %s\n", pii);
+
+ if (!pii)
+ return;
+
+ switch (pii[0]) {
+
+ case 'A': // Road
+ case 'P': // Provisional Road
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black
+ label_color_guess = 0x08; // black
+ break;
+
+ case 'B': // Railroad
+ (void)XSetLineAttributes (XtDisplay (w), gc, 1, LineOnOffDash, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x01]); // purple
+ label_color_guess = 0x01; // purple
+ break;
+
+ case 'C': // Misc Ground Transportation
+ (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineOnOffDash, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x4d]); // white
+ label_color_guess = 0x4d; // white
+ break;
+
+ case 'D': // Landmark
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black
+ label_color_guess = 0x08; // black
+ break;
+
+ case 'E': // Physical Feature
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black
+ label_color_guess = 0x08; // black
+ break;
+
+ case 'F': // Non-visible Feature
+ label_color_guess = -1;
+ return; // Don't display it!
+ break;
+
+ case 'H': // Hydrography (water)
+ water_layer++;
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x1a]); // Steel Blue
+ label_color_guess = 0x1a; // Steel Blue
+ break;
+
+ case 'X': // Feature not yet classified
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black
+ label_color_guess = 0x08; // black
+ break;
+
+ default:
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black
+ label_color_guess = 0x08; // black
+ break;
+
+ } // End of switch
+ } // End of if
+
+ return;
+
+ } // End of TIGER
+
+
+
+ // SHAPEFILES
+ // ----------
+ //
+ ii = OGR_F_GetFieldIndex(featureH, "LANDNAME");
+ if (ii != -1) {
+ (void)XSetForeground(XtDisplay(da), gc, colors[(int)0x1a]); // Steel Blue
+ label_color_guess = 0x1a;
+ }
+
+
+
+ switch (geometry_type) {
+
+
+ case 1: // Point
+ case 4: // MultiPoint
+ case 0x80000001: // Point25D
+ case 0x80000004: // MultiPoint25D
+
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black
+ label_color_guess = 0x08; // black
+
+ break;
+
+
+ case 2: // LineString (polyline)
+ case 5: // MultiLineString
+ case 0x80000002: // LineString25D
+ case 0x80000005: // MultiLineString25D
+
+ if (hypsography_layer || hydrography_layer) {
+
+ // Set color for SDTS hypsography layer (contours)
+// (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x43]); // gray80
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x0e]); // yellow
+// label_color_guess = 0x4d; // white
+ label_color_guess = 0x0e; // yellow
+ }
+ else if (roads_trails_layer) {
+ (void)XSetForeground(XtDisplay(da), gc, colors[(int)0x08]); // black
+ label_color_guess = 0x08;
+ }
+ else if (railroad_layer) {
+ (void)XSetLineAttributes (XtDisplay (w), gc, 1, LineOnOffDash, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da), gc, colors[(int)0x01]); // purple
+ label_color_guess = 0x01;
+ }
+ else if (misc_transportation_layer) {
+ (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineOnOffDash, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da), gc, colors[(int)0x4d]); // white
+ label_color_guess = 0x4d;
+ }
+ else if (strstr(full_filename,"lkH")) {
+ (void)XSetForeground(XtDisplay(da), gc, colors[(int)0x1a]); // Steel Blue
+ label_color_guess = 0x1a;
+ }
+ else if (strstr(full_filename,"lkB")) {
+ // Railroad
+ (void)XSetForeground(XtDisplay(da), gc, colors[(int)0x01]); // purple
+ label_color_guess = 0x01;
+ }
+ else {
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black
+ label_color_guess = 0x08; // black
+ }
+ break;
+
+
+ case 3: // Polygon
+ case 6: // MultiPolygon
+ case 0x80000003: // Polygon25D
+ case 0x80000006: // MultiPolygon25D
+
+ if (hypsography_layer || hydrography_layer) {
+
+ // Set color for SDTS hypsography layer (contours)
+// (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x43]); // gray80
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x0e]); // yellow
+// label_color_guess = 0x4d; // white
+ label_color_guess = 0x0e; // yellow
+ }
+ else if (roads_trails_layer) {
+ (void)XSetForeground(XtDisplay(da), gc, colors[(int)0x08]); // black
+ label_color_guess = 0x08;
+ }
+ else if (railroad_layer) {
+ (void)XSetLineAttributes (XtDisplay (w), gc, 1, LineOnOffDash, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da), gc, colors[(int)0x01]); // purple
+ label_color_guess = 0x01;
+ }
+ else if (misc_transportation_layer) {
+ (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineOnOffDash, CapButt,JoinMiter);
+ (void)XSetForeground(XtDisplay(da), gc, colors[(int)0x4d]); // white
+ label_color_guess = 0x4d;
+ }
+ else if (strstr(full_filename,"wat")) {
+ (void)XSetForeground(XtDisplay(da), gc, colors[(int)0x1a]); // Steel Blue
+ label_color_guess = 0x1a;
+ }
+ else {
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black
+ label_color_guess = 0x08; // black
+ }
+ break;
+
+
+ case 7: // GeometryCollection
+ case 0x80000007: // GeometryCollection25D
+ default: // Unknown/Unimplemented
+
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x0e]); // yellow
+ label_color_guess = 0x08; // black
+ break;
+ }
+
+
+//fprintf(stderr,"label_color_guess:%02x\n",label_color_guess);
+
+}
+
+
+
+
+
+void Draw_OGR_Labels( Widget w,
+ Pixmap pixmap,
+ OGRFeatureH featureH,
+ OGRGeometryH geometryH,
+ XPoint *xpoints,
+ int num_points,
+ int color) {
+
+ int ii;
+ const char *pii = NULL;
+ char label[200] = "";
+ float angle = 0.0; // Angle for the beginning of this polyline
+ int scale_factor = 10;
+
+
+//fprintf(stderr,"Draw_OGR_Labels start\n");
+
+ if (featureH == NULL)
+ return; // Exit early
+
+
+ // Recursively call this routine if we have a lot of points, so
+ // that we draw labels at multiple points along the line. The
+ // number of points skipped should probably be tied to the zoom
+ // level so that we get an appropriate number of labels at each
+ // scale. The goal should probably be two or three labels max
+ // per object.
+ //
+ if (num_points > ((scale_factor * scale_y)+1)) {
+ int skip = scale_factor * scale_y;
+
+ Draw_OGR_Labels(w,
+ pixmap,
+ featureH,
+ geometryH,
+ &xpoints[skip],
+ num_points - skip,
+ color);
+ }
+
+
+ if (num_points > 1) {
+ // Compute the label rotation angle
+ float diff_X = (int)xpoints[1].x - xpoints[0].x;
+ float diff_Y = (int)xpoints[1].y - xpoints[0].y;
+
+ if (diff_X == 0.0) { // Avoid divide by zero errors
+ diff_X = 0.0000001;
+ }
+ if (diff_Y == 0.0) { // Avoid divide by zero errors
+ diff_Y = 0.0000001;
+ }
+
+ angle = atan( diff_X / diff_Y ); // Compute in radians
+
+ // Convert to degrees
+ angle = angle / (2.0 * M_PI );
+ angle = angle * 360.0;
+
+ // Change to fit our rotate label function's idea of angle
+ angle = 360.0 - angle;
+
+ if (angle >= 360.0 || angle <= 0.0)
+ angle = 0.0;
+ }
+
+
+ //fprintf(stderr,"Y: %f\tX:
+ //%f\tAngle: %f ==>
+ //",diff_Y,diff_X,angle);
+
+ if ( angle > 90.0 ) {angle += 180.0;}
+ if ( angle >= 360.0 ) {angle -= 360.0;}
+
+ //fprintf(stderr,"%f\t%s\n",angle,temp);
+
+
+ // Debug code
+ //OGR_F_DumpReadable( featureH, stderr );
+ //OGR_G_DumpReadable(geometryH, stderr, "Shape: ");
+
+ // Snag a few special features, use for labels
+ //
+ ii = OGR_F_GetFieldIndex(featureH, "NAME");
+ if (ii == -1) {
+ ii = OGR_F_GetFieldIndex(featureH, "FENAME");
+ }
+ if (ii == -1) {
+
+ ii = OGR_F_GetFieldIndex(featureH, "ELEVATION");
+
+ if (ii != -1) { // Found an elevation field
+
+ // Convert to the user's desired units based on the
+ // setting of the "english_units" global variable, which
+ // is set by the Enable English Units toggle.
+ //
+ if (english_units) { // We desire English Units (feet)
+ if (sdts_elevation_in_meters) {
+ // Map file is in meters, convert to feet for
+ // display
+ xastir_snprintf(label,
+ sizeof(label),
+ "%ift",
+ (int)((OGR_F_GetFieldAsInteger(featureH, ii) * 3.28084) + 0.5));
+ }
+ else {
+ // Map file is already in feet
+ xastir_snprintf(label,
+ sizeof(label),
+ "%sft",
+ OGR_F_GetFieldAsString(featureH, ii));
+ }
+ }
+ else { // We desire metric Units (meters)
+ if (!sdts_elevation_in_meters) {
+ // Map file is in feet, convert to meters for
+ // display
+ xastir_snprintf(label,
+ sizeof(label),
+ "%im",
+ (int)((OGR_F_GetFieldAsInteger(featureH, ii) * 0.3048) + 0.5));
+ }
+ else {
+ // Map file is already in meters
+ xastir_snprintf(label,
+ sizeof(label),
+ "%sm",
+ OGR_F_GetFieldAsString(featureH, ii));
+ }
+ }
+
+ // Test for empty value
+ if (label[0] == 'f' || label[0] == 'm')
+ return;
+
+//fprintf(stderr,"Elevation label: %s, angle: %2.1f\n", label, angle);
+ }
+ }
+
+
+ // Check whether we found a field and if we haven't already
+ // created a label. If so, snag the field.
+ if (ii != -1 && label[0] == '\0') {
+ pii = OGR_F_GetFieldAsString(featureH, ii);
+
+ if (pii && pii[0] != '\0') {
+ xastir_snprintf(label,
+ sizeof(label),
+ "%s",
+ pii);
+ }
+ }
+
+
+ // Draw at least one label. In the future we can pick and
+ // choose among the points passed to us and draw the quantity of
+ // labels that are appropriate for the zoom level. Whether to
+ // draw labels for more minor objects as we zoom out is another
+ // problem that must be solved.
+ //
+ // Here "label" will always evaluate as true: It's an address!
+ //if (label && map_labels /* && !skip_label */ ) {
+ if (map_labels /* && !skip_label */ ) {
+
+ // Check that we're not trying to draw the label out of
+ // bounds for the X11 calls.
+ //
+ if ( xpoints[0].x+10 < screen_width
+ && xpoints[0].x+10 > 0
+ && xpoints[0].y+5 < screen_height
+ && xpoints[0].y+5 > 0) {
+
+/*
+ if (angle == 0.0) { // Non-rotated label
+
+ draw_rotated_label_text (w,
+ -90.0,
+ xpoints[0].x+10,
+ xpoints[0].y+5,
+ strlen(label),
+ colors[color],
+ label,
+ FONT_DEFAULT);
+ }
+
+ else { // Rotated label
+*/
+ draw_rotated_label_text (w,
+ angle,
+ xpoints[0].x+10,
+ xpoints[0].y+5,
+ strlen(label),
+ colors[color],
+ label,
+ FONT_DEFAULT);
+// }
+ }
+ }
+
+//fprintf(stderr,"Draw_OGR_Labels end\n");
+
+}
+
+
+
+
+
+// Draw_OGR_Points().
+//
+// A function which can be recursively called. Tracks the recursion
+// depth so that we can recover if we exceed the maximum. If we
+// keep finding geometries below us, keep calling the same function.
+// Simple and efficient.
+//
+// Really the important thing here is not to draw a tiny dot on the
+// screen, but to draw a symbol and/or a label at that point on the
+// screen. We'll need more code to handle that stuff though, to
+// determine which field in the file to use as a label and the
+// font/color/placement/size/etc.
+//
+void Draw_OGR_Points( Widget w,
+ OGRFeatureH featureH,
+ OGRGeometryH geometryH,
+ int level,
+ OGRCoordinateTransformationH transformH) {
+
+ int kk;
+ int object_num = 0;
+ int num_points;
+ int ii;
+ int skip_duplicates = 0;
+
+
+//fprintf(stderr, "Draw_OGR_Points\n");
+
+ if (geometryH == NULL)
+ return; // Exit early
+
+ // Check for more objects below this one, recursing into any
+ // objects found. "level" keeps us from recursing too far (we
+ // don't want infinite recursion here).
+ //
+ object_num = OGR_G_GetGeometryCount(geometryH);
+ // Iterate through the objects found. If another geometry is
+ // detected, call this function again recursively. That will
+ // cause all of the lower objects to get drawn.
+ //
+ if (object_num) {
+
+ //fprintf(stderr, "DrawPoints: Found %d geometries\n", object_num);
+
+ for ( kk = 0; kk < object_num; kk++ ) {
+ OGRGeometryH child_geometryH;
+ int sub_object_num;
+
+
+ // See if we have geometries below this one.
+ child_geometryH = OGR_G_GetGeometryRef(geometryH, kk);
+
+ sub_object_num = OGR_G_GetGeometryCount(child_geometryH);
+
+ if (sub_object_num) {
+ // We found geometries below this. Recurse.
+ if (level < 5) {
+ //fprintf(stderr, "DrawPoints: Recursing level %d\n", level);
+ Draw_OGR_Points(w,
+ featureH,
+ child_geometryH,
+ level+1,
+ transformH);
+ }
+ }
+ }
+ return;
+ }
+
+
+ // Draw
+
+ // Get number of elements (points)
+ num_points = OGR_G_GetPointCount(geometryH);
+ //fprintf(stderr," Number of elements: %d\n",num_points);
+
+ // Draw the points
+ for ( ii = 0; ii < num_points; ii++ ) {
+ double X1, Y1, Z1;
+ XPoint xpoint;
+
+
+ // Get the point!
+ OGR_G_GetPoint(geometryH,
+ ii,
+ &X1,
+ &Y1,
+ &Z1);
+
+ if (transformH) {
+ // Convert to WGS84 coordinates.
+ if (!OCTTransform(transformH, 1, &X1, &Y1, &Z1)) {
+ fprintf(stderr,
+ "Couldn't convert point to WGS84\n");
+ // Draw it anyway. It _might_ be in WGS84 or
+ // NAD83!
+ }
+ }
+
+
+ // Skip the map_visible_lat_lon() check:
+ // draw_point_ll() does the check for us.
+ //
+ draw_point_ll(da,
+ (float)Y1,
+ (float)X1,
+ gc,
+ pixmap,
+ skip_duplicates);
+
+ skip_duplicates = 1;
+
+// We could use a flag back from draw_point_ll() that tells us
+// whether the point was within the view. That way we know whether
+// or not to draw the label.
+
+ xpoint.x = (short)X1;
+ xpoint.y = (short)Y1;
+
+/*
+ // Draw the corresponding label
+ Draw_OGR_Labels(w,
+ pixmap,
+ featureH,
+ geometryH,
+ &xpoint,
+ 1, // Number of points
+ label_color_guess);
+*/
+ }
+}
+
+
+
+
+
+// Draw_OGR_Lines().
+//
+// A function which can be recursively called. Tracks the recursion
+// depth so that we can recover if we exceed the maximum. If we
+// keep finding geometries below us, keep calling the same function.
+// Simple and efficient.
+//
+// In the case of !fast_extents, it might be faster to convert the
+// entire object to Xastir coordinates, then check whether it is
+// visible. That would elimate two conversions in the case that the
+// object gets drawn. For the fast_extents case, we're just
+// snagging the extents instead of the entire object, so we might
+// just leave it as-is.
+//
+void Draw_OGR_Lines( Widget w,
+ OGRFeatureH featureH,
+ OGRGeometryH geometryH,
+ int level,
+ OGRCoordinateTransformationH transformH,
+ int fast_extents) {
+
+ int kk;
+ int object_num = 0;
+ int num_points;
+ OGREnvelope envelopeH;
+
+
+//fprintf(stderr, "Draw_OGR_Lines\n");
+
+ if (geometryH == NULL)
+ return; // Exit early
+
+ // Check for more objects below this one, recursing into any
+ // objects found. "level" keeps us from recursing too far (we
+ // don't want infinite recursion here).
+ //
+ object_num = OGR_G_GetGeometryCount(geometryH);
+
+ // Iterate through the objects found. If another geometry is
+ // detected, call this function again recursively. That will
+ // cause all of the lower objects to get drawn.
+ //
+ if (object_num) {
+
+ //fprintf(stderr, "DrawLines: Found %d geometries\n", object_num);
+
+ for ( kk = 0; kk < object_num; kk++ ) {
+ OGRGeometryH child_geometryH;
+ int sub_object_num;
+
+
+ // Check for more geometries below this one.
+ child_geometryH = OGR_G_GetGeometryRef(geometryH, kk);
+
+ sub_object_num = OGR_G_GetGeometryCount(child_geometryH);
+
+ if (sub_object_num) {
+ // We found geometries below this. Recurse.
+ if (level < 5) {
+ //fprintf(stderr, "DrawLines: Recursing level %d\n", level);
+ Draw_OGR_Lines(w,
+ featureH,
+ child_geometryH,
+ level+1,
+ transformH,
+ fast_extents);
+ }
+ }
+ }
+ return;
+ }
+
+
+ // Draw it. Standard linestring files return 0 for object_num.
+ // Multilinestring must return more, so we recurse?
+ // Yet to be tested!
+
+
+ // If we have fast_extents available, take advantage of it to
+ // escape this routine as quickly as possible, should the object
+ // not be within our view.
+ //
+ if (fast_extents) {
+
+ // Get the extents for this Polyline
+ OGR_G_GetEnvelope(geometryH, &envelopeH);
+
+ // Convert the extents to WGS84/Geographic coordinate system
+ if (transformH) {
+//fprintf(stderr,"Converting to WGS84\n");
+ // Convert to WGS84 coordinates.
+ if (!OCTTransform(transformH, 2, &envelopeH.MinX, &envelopeH.MinY, NULL)) {
+ fprintf(stderr,
+ "Couldn't convert point to WGS84\n");
+ }
+ }
+
+/*
+fprintf(stderr,"MinY:%f, MaxY:%f, MinX:%f, MaxX:%f\n",
+ envelopeH.MinY,
+ envelopeH.MaxY,
+ envelopeH.MinX,
+ envelopeH.MaxX);
+*/
+
+ if (map_visible_lat_lon( envelopeH.MinY, // bottom
+ envelopeH.MaxY, // top
+ envelopeH.MinX, // left
+ envelopeH.MaxX) ) { // right
+//fprintf(stderr, "Fast Extents: Line is visible\n");
+ }
+ else {
+//fprintf(stderr, "Fast Extents: Line is NOT visible\n");
+ return; // Exit early
+ }
+
+ // If we made it this far with an object with
+ // fast_extents , the feature is within our view.
+ }
+
+ else { // Fast extents are not available. Compute the
+ // extents ourselves once we have all the points,
+ // then check whether this object is within our
+ // view.
+ }
+
+
+ num_points = OGR_G_GetPointCount(geometryH);
+//fprintf(stderr," Number of elements: %d\n",num_points);
+
+
+ // Draw the polyline
+ //
+ if (num_points > 0) {
+ int ii;
+ double *vectorX;
+ double *vectorY;
+ double *vectorZ;
+ unsigned long *XL = NULL;
+ unsigned long *YL = NULL;
+ long *XI = NULL;
+ long *YI = NULL;
+ XPoint *xpoints = NULL;
+
+
+ // Get some memory to hold the vectors
+ vectorX = (double *)malloc(sizeof(double) * num_points);
+ vectorY = (double *)malloc(sizeof(double) * num_points);
+ vectorZ = (double *)malloc(sizeof(double) * num_points);
+ CHECKMALLOC(vectorX);
+ CHECKMALLOC(vectorY);
+ CHECKMALLOC(vectorZ);
+
+ // Get the points, fill in the vectors
+ for ( ii = 0; ii < num_points; ii++ ) {
+
+ OGR_G_GetPoint(geometryH,
+ ii,
+ &vectorX[ii],
+ &vectorY[ii],
+ &vectorZ[ii]);
+ }
+
+ if (transformH) {
+//fprintf(stderr,"Converting to WGS84\n");
+ // Convert all vectors to WGS84 coordinates.
+ if (!OCTTransform(transformH, num_points, vectorX, vectorY, vectorZ)) {
+ fprintf(stderr,
+ "Couldn't convert vectors to WGS84\n");
+ }
+ }
+ else {
+//fprintf(stderr,"No transform available\n");
+ }
+
+ // For the non-fast_extents case, we need to compute the
+ // extents and check whether this object is within our
+ // view.
+ //
+
+// WE7U
+// Replace with draw_vector_ll() and we won't have to compute
+// extents here.
+
+ if (!fast_extents) {
+ double MinX, MaxX, MinY, MaxY;
+
+ MinX = vectorX[0];
+ MaxX = vectorX[0];
+ MinY = vectorY[0];
+ MaxY = vectorY[0];
+
+ for ( ii = 1; ii < num_points; ii++ ) {
+ if (vectorX[ii] < MinX) MinX = vectorX[ii];
+ if (vectorX[ii] > MaxX) MaxX = vectorX[ii];
+ if (vectorY[ii] < MinY) MinY = vectorY[ii];
+ if (vectorY[ii] > MaxY) MaxY = vectorY[ii];
+ }
+
+/*
+fprintf(stderr,"MinY:%f, MaxY:%f, MinX:%f, MaxX:%f\n",
+ MinY,
+ MaxY,
+ MinX,
+ MaxX);
+*/
+
+ // We have the extents now in geographic/WGS84
+ // datum. Check for visibility.
+ //
+ if (map_visible_lat_lon( MinY, // bottom
+ MaxY, // top
+ MinX, // left
+ MaxX) ) { // right
+//fprintf(stderr, "Line is visible\n");
+ }
+ else {
+
+//fprintf(stderr, "Line is NOT visible\n");
+
+ // Free the allocated vector memory
+ if (vectorX)
+ free(vectorX);
+ if (vectorY)
+ free(vectorY);
+ if (vectorZ)
+ free(vectorZ);
+
+ return; // Exit early
+ }
+ }
+
+ // If we've gotten to this point, part or all of the
+ // object is within our view so at least some drawing
+ // should occur.
+
+
+// WE7U
+// This next section should be replaced with calls to draw_vector_ll()
+// instead of converting to Xastir coordinates, then screen
+// coordinates and truncating the lines. draw_vector_ll() uses
+// proper line-clipping so that the slope of the lines don't
+// change.
+//
+// Draw_OGR_Labels() would need to be changed also so that it
+// doesn't use screen coordinates or perhaps leave the screen
+// coordinate calc's in if it's too difficult or would slow things
+// down too much.
+//
+// Another option is to use maps.c:clip2d_screen() to eliminate
+// and/or clip lines based on screen coordinates.
+//
+// If we clip lines in the arrays then the Draw_OGR_Labels()
+// function will have less work to do as it'll only be working
+// against visible points. An excellent speedup.
+//
+// Make sure we don't end up drawing a polyline/polygon along the
+// screen edges due to clipping a larger polygon. Each vector needs
+// to be treated separately: If one endpoint is the same for two
+// vectors in the array and we do clipping, we'll have problems.
+
+
+ XL = (unsigned long *)malloc(sizeof(unsigned long) * num_points);
+ YL = (unsigned long *)malloc(sizeof(unsigned long) * num_points);
+ CHECKMALLOC(XL);
+ CHECKMALLOC(YL);
+
+ // Convert arrays to the Xastir coordinate system
+ for (ii = 0; ii < num_points; ii++) {
+ convert_to_xastir_coordinates(&XL[ii],
+ &YL[ii],
+ vectorX[ii],
+ vectorY[ii]);
+ }
+
+ // Free the allocated vector memory
+ if (vectorX)
+ free(vectorX);
+ if (vectorY)
+ free(vectorY);
+ if (vectorZ)
+ free(vectorZ);
+
+ XI = (long *)malloc(sizeof(long) * num_points);
+ YI = (long *)malloc(sizeof(long) * num_points);
+ CHECKMALLOC(XI);
+ CHECKMALLOC(YI);
+
+ // Convert arrays to screen coordinates. Careful here!
+ // The format conversions you'll need if you try to
+ // compress this into two lines will get you into
+ // trouble.
+ //
+ // We also clip to screen size and compute min/max
+ // values here.
+ for (ii = 0; ii < num_points; ii++) {
+ XI[ii] = XL[ii] - NW_corner_longitude;
+ XI[ii] = XI[ii] / scale_x;
+
+ YI[ii] = YL[ii] - NW_corner_latitude;
+ YI[ii] = YI[ii] / scale_y;
+
+// Here we truncate: We should polygon clip instead, so that the
+// slopes of the line segments don't change. Points beyond +/-
+// 32767 can cause problems in X11 when we draw.
+ XI[ii] = l16(XI[ii]);
+ YI[ii] = l16(YI[ii]);
+ }
+
+ // We don't need the Xastir coordinate system arrays
+ // anymore. We've already converted to screen
+ // coordinates.
+ if (XL)
+ free(XL);
+ if (YL)
+ free(YL);
+
+ // Set up the XPoint array.
+ xpoints = (XPoint *)malloc(sizeof(XPoint) * num_points);
+ CHECKMALLOC(xpoints);
+
+ // Load up our xpoints array
+ for (ii = 0; ii < num_points; ii++) {
+ xpoints[ii].x = l16(XI[ii]);
+ xpoints[ii].y = l16(YI[ii]);
+ }
+
+ // Free the screen coordinate arrays.
+ if (XI)
+ free(XI);
+ if (YI)
+ free(YI);
+
+
+ // Actually draw the lines
+ (void)XDrawLines(XtDisplay(da),
+ pixmap,
+ gc,
+ xpoints,
+ l16(num_points),
+ CoordModeOrigin);
+
+ // Draw the corresponding labels
+ Draw_OGR_Labels(w,
+ pixmap,
+ featureH,
+ geometryH,
+ xpoints,
+ num_points,
+ label_color_guess);
+
+ if (xpoints)
+ free(xpoints);
+
+ }
+}
+
+
+
+
+
+// create_clip_mask()
+//
+// Create a rectangular X11 Region. It should be the size of the
+// extents for the outer polygon.
+//
+Region create_clip_mask( int num,
+ int minX,
+ int minY,
+ int maxX,
+ int maxY) {
+
+ XRectangle rectangle;
+ Region region;
+
+
+//fprintf(stderr,"create_clip_mask: num=%i ", num);
+
+ rectangle.x = (short) minX;
+ rectangle.y = (short) minY;
+ rectangle.width = (unsigned short)(maxX - minX + 1);
+ rectangle.height = (unsigned short)(maxY - minY + 1);
+
+ // Create an empty region
+ region = XCreateRegion();
+
+/*
+ fprintf(stderr,"Create: x:%d y:%d x:%d y:%d\n",
+ minX,
+ minY,
+ maxX,
+ maxY);
+
+ fprintf(stderr,"Create: x:%d y:%d w:%d h:%d\n",
+ rectangle.x,
+ rectangle.y,
+ rectangle.width,
+ rectangle.height);
+*/
+
+ // Create a region containing a filled rectangle
+ XUnionRectWithRegion(&rectangle,
+ region,
+ region);
+
+//fprintf(stderr,"Done\n");
+
+ return(region);
+}
+
+
+
+
+
+// create_hole_in_mask()
+//
+// Create a hole in an X11 Region, using a polygon as input. X11
+// Region must have been created with "create_clip_mask()" before
+// this function is called.
+//
+Region create_hole_in_mask( Region mask,
+ int num,
+ long *X,
+ long *Y) {
+
+ Region region2 = NULL;
+ Region region3 = NULL;
+ XPoint *xpoints = NULL;
+ int ii;
+
+
+//fprintf(stderr,"create_hole_in_mask: num=%i ", num);
+
+ if (num < 3) { // Not enough for a polygon
+ fprintf(stderr,
+ "create_hole_in_mask:XPolygonRegion w/too few vertices: %d\n",
+ num);
+ return(mask); // Net result = no change to Region
+ }
+
+ // Get memory to hold the points
+ xpoints = (XPoint *)malloc(sizeof(XPoint) * num);
+ CHECKMALLOC(xpoints);
+
+ // Load up our xpoints array
+ for (ii = 0; ii < num; ii++) {
+ xpoints[ii].x = (short)X[ii];
+ xpoints[ii].y = (short)Y[ii];
+ }
+
+ // Create empty regions
+ region2 = XCreateRegion();
+ region3 = XCreateRegion();
+
+ // Draw the "hole" polygon
+ region2 = XPolygonRegion(xpoints,
+ num,
+ WindingRule);
+
+ // Free the allocated memory
+ if (xpoints)
+ free(xpoints);
+
+ XSubtractRegion(mask, region2, region3);
+
+ // Get rid of the two regions we no longer need.
+ XDestroyRegion(mask);
+ XDestroyRegion(region2);
+
+//fprintf(stderr,"Done\n");
+
+ // Return our new region that has another hole in it.
+ return(region3);
+}
+
+
+
+
+
+// draw_polygon_with_mask()
+//
+// Draws a polygon onto a pixmap using an X11 Region to mask areas
+// that shouldn't be drawn over (holes). X11 Region is created with
+// the "create_clip_mask()" function, holes in it are created with
+// the "create_hole_in_mask()" function. The polygon used to create
+// the initial X11 Region was saved away during the creation. Now
+// we just draw it to the pixmap using the X11 Region as a mask.
+//
+void draw_polygon_with_mask( Region mask,
+ XPoint *xpoints,
+ int num_points) {
+
+ GC gc_temp = NULL;
+ XGCValues gc_temp_values;
+
+
+// fprintf(stderr,"draw_polygon_with_mask: ");
+
+ // There were "hole" polygons, so by now we've created a "holey"
+ // region. Draw a filled polygon with gc_temp here and then get
+ // rid of gc_temp and the regions.
+
+ gc_temp = XCreateGC(XtDisplay(da),
+ XtWindow(da),
+ 0,
+ &gc_temp_values);
+
+
+ // Set the clip-mask into the GC. This GC is now ruined for
+ // other purposes, so destroy it when we're done drawing this
+ // one shape.
+ if (mask != NULL)
+ XSetRegion(XtDisplay(da), gc_temp, mask);
+
+ (void)XSetForeground(XtDisplay(da),
+ gc_temp,
+ colors[(int)label_color_guess]);
+
+ // Actually draw the filled polygon
+ (void)XFillPolygon(XtDisplay(da),
+ pixmap,
+ gc_temp,
+ xpoints,
+ num_points,
+ Nonconvex,
+ CoordModeOrigin);
+
+ if (mask != NULL)
+ XDestroyRegion(mask);
+
+ if (gc_temp != NULL)
+ XFreeGC(XtDisplay(da), gc_temp);
+
+// fprintf(stderr,"Done!\n");
+}
+
+
+
+
+
+// Draw_OGR_Polygons().
+//
+// A function which can be recursively called. Tracks the recursion
+// depth so that we can recover if we exceed the maximum. If we
+// keep finding geometries below us, keep calling the same function.
+// Simple and efficient.
+//
+// This can get complicated for Shapefiles: Polygons are composed
+// of multiple rings. If a ring goes in one direction, it's a fill
+// polygon, if the other direction, it's a hole polygon.
+//
+// Can test the operation using Shapefiles for Island County, WA,
+// Camano Island, where there's an Island in Puget Sound that has a
+// lake with an island in it (48.15569N/122.48953W)!
+//
+// At 48.43867N/122.61687W there's another lake with an island in
+// it, but this lake isn't on an island like the first example.
+//
+// A note from Frank Warmerdam (GDAL guy):
+//
+// "An OGRPolygon objects consists of one outer ring and zero or
+// more inner rings. The inner rings are holes. The C API kind of
+// hides this fact, but you should be able to assume that the first
+// ring is an outer ring, and any other rings are inner rings
+// (holes). Note that in the simple features geometry model you
+// can't make any assumptions about the winding direction of holes
+// or outer rings.
+//
+// Some polygons when read from Shapefiles will be returned as
+// OGRMultiPolygon. These are basically areas that have multiple
+// outer rings. For instance, if you had one feature that was a
+// chain of islands. In the past (and likely even now with some
+// format drivers) these were just returned as polygons with the
+// outer and inner rings all mixed up. But the development code
+// includes fixes (for shapefiles at least) to fix this up and
+// convert into a multi polygon so you can properly establish what
+// are outer rings, and what are inner rings (holes)."
+//
+// In the case of !fast_extents, it might be faster to convert the
+// entire object to Xastir coordinates, then check whether it is
+// visible. That would elimate two conversions in the case that the
+// object gets drawn. For the fast_extents case, we're just
+// snagging the extents instead of the entire object, so we might
+// just leave it as-is.
+//
+void Draw_OGR_Polygons( Widget w,
+ OGRFeatureH featureH,
+ OGRGeometryH geometryH,
+ int level,
+ OGRCoordinateTransformationH transformH,
+ int draw_filled,
+ int fast_extents) {
+
+ int kk;
+ int object_num = 0;
+ Region mask = NULL;
+ XPoint *xpoints = NULL;
+ int num_outer_points = 0;
+
+
+//fprintf(stderr,"Draw_OGR_Polygons\n");
+
+ if (geometryH == NULL)
+ return; // Exit early
+
+ // Check for more objects below this one, recursing into any
+ // objects found. "level" keeps us from recursing too far (we
+ // don't want infinite recursion here). These objects may be
+ // rings or they may be other polygons in a collection.
+ //
+ object_num = OGR_G_GetGeometryCount(geometryH);
+
+ // Iterate through the objects found. If another geometry is
+ // detected, call this function again recursively. That will
+ // cause all of the lower objects to get drawn.
+ //
+ for ( kk = 0; kk < object_num; kk++ ) {
+ OGRGeometryH child_geometryH;
+ int sub_object_num;
+
+
+ // This may be a ring, or another object with rings.
+ child_geometryH = OGR_G_GetGeometryRef(geometryH, kk);
+
+ sub_object_num = OGR_G_GetGeometryCount(child_geometryH);
+
+ if (sub_object_num) {
+ // We found geometries below this. Recurse.
+ if (level < 5) {
+
+ // If we got here, we're dealing with a multipolygon
+ // file. There are multiple sets of polygon
+ // objects, each may have inner (hole) and outer
+ // (fill) rings. If (level > 0), it's a
+ // multipolygon layer.
+
+//fprintf(stderr, "DrawPolygons: Recursing level %d\n", level);
+
+ Draw_OGR_Polygons(w,
+ featureH,
+ child_geometryH,
+ level+1,
+ transformH,
+ draw_filled,
+ fast_extents);
+ }
+ }
+
+ else { // Draw
+ int polygon_points;
+ OGREnvelope envelopeH;
+ int polygon_hole = 0;
+ int single_polygon = 0;
+
+
+ // if (kk==0) we're dealing with an outer (fill) ring.
+ // If (kk>0) we're dealing with an inner (hole) ring.
+ if (kk == 0 || object_num == 1) {
+ if (object_num == 1) {
+//fprintf(stderr,"Polygon->Fill\n");
+ single_polygon++;
+ }
+ else {
+//fprintf(stderr,"Polygon->Fill w/holes\n");
+ }
+
+ }
+ else if (object_num > 1) {
+//fprintf(stderr,"Polygon->Hole\n");
+ polygon_hole++;
+ }
+
+ if (fast_extents) {
+
+ // Get the extents for this Polygon
+ OGR_G_GetEnvelope(geometryH, &envelopeH);
+
+ // Convert them to WGS84/Geographic coordinate system
+ if (transformH) {
+ // Convert to WGS84 coordinates.
+ if (!OCTTransform(transformH, 2, &envelopeH.MinX, &envelopeH.MinY, NULL)) {
+ fprintf(stderr,
+ "Couldn't convert to WGS84\n");
+ }
+ }
+
+ if (map_visible_lat_lon( envelopeH.MinY, // bottom
+ envelopeH.MaxY, // top
+ envelopeH.MinX, // left
+ envelopeH.MaxX) ) { // right
+ //fprintf(stderr, "Fast Extents: Polygon is visible\n");
+ }
+ else {
+ //fprintf(stderr, "Fast Extents: Polygon is NOT visible\n");
+ return; // Exit early
+ }
+
+ // If we made it this far, the feature is within our
+ // view (if it has fast_extents).
+ }
+ else {
+ // Fast extents not available. We'll need to
+ // compute our own extents below.
+ }
+
+ polygon_points = OGR_G_GetPointCount(child_geometryH);
+//fprintf(stderr, "Vertices: %d\n", polygon_points);
+
+ if (polygon_points > 3) { // Not a polygon if < 3 points
+ int mm;
+ double *vectorX;
+ double *vectorY;
+ double *vectorZ;
+
+
+ // Get some memory to hold the polygon vectors
+ vectorX = (double *)malloc(sizeof(double) * polygon_points);
+ vectorY = (double *)malloc(sizeof(double) * polygon_points);
+ vectorZ = (double *)malloc(sizeof(double) * polygon_points);
+ CHECKMALLOC(vectorX);
+ CHECKMALLOC(vectorY);
+ CHECKMALLOC(vectorZ);
+
+ // Get the points, fill in the vectors
+ for ( mm = 0; mm < polygon_points; mm++ ) {
+
+ OGR_G_GetPoint(child_geometryH,
+ mm,
+ &vectorX[mm],
+ &vectorY[mm],
+ &vectorZ[mm]);
+ }
+
+
+ if (transformH) {
+ // Convert entire polygon to WGS84 coordinates.
+ if (!OCTTransform(transformH, polygon_points, vectorX, vectorY, vectorZ)) {
+// fprintf(stderr,
+// "Couldn't convert polygon to WGS84\n");
+//return;
+ }
+ }
+
+
+ // For the non-fast_extents case, we need to compute
+ // the extents and check whether this object is
+ // within our view.
+ //
+ if (!fast_extents) {
+ double MinX, MaxX, MinY, MaxY;
+
+ MinX = vectorX[0];
+ MaxX = vectorX[0];
+ MinY = vectorY[0];
+ MaxY = vectorY[0];
+
+ for ( mm = 1; mm < polygon_points; mm++ ) {
+ if (vectorX[mm] < MinX) MinX = vectorX[mm];
+ if (vectorX[mm] > MaxX) MaxX = vectorX[mm];
+ if (vectorY[mm] < MinY) MinY = vectorY[mm];
+ if (vectorY[mm] > MaxY) MaxY = vectorY[mm];
+ }
+
+ // We have the extents now in geographic/WGS84
+ // datum. Check for visibility.
+ //
+ if (map_visible_lat_lon( MinY, // bottom
+ MaxY, // top
+ MinX, // left
+ MaxX) ) { // right
+//fprintf(stderr, "Polygon is visible\n");
+ }
+ else {
+
+//fprintf(stderr, "Polygon is NOT visible\n");
+
+ // Free the allocated vector memory
+ if (vectorX)
+ free(vectorX);
+ if (vectorY)
+ free(vectorY);
+ if (vectorZ)
+ free(vectorZ);
+
+ //return; // Exit early
+ continue; // Next ieration of the loop
+ }
+ }
+
+
+ // If draw_filled != 0, draw the polygon using X11
+ // polygon calls instead of just drawing the border.
+ //
+ if (draw_filled) { // Draw a filled polygon
+ unsigned long *XL = NULL;
+ unsigned long *YL = NULL;
+ long *XI = NULL;
+ long *YI = NULL;
+ int nn;
+ int minX, maxX, minY, maxY;
+
+
+ XL = (unsigned long *)malloc(sizeof(unsigned long) * polygon_points);
+ YL = (unsigned long *)malloc(sizeof(unsigned long) * polygon_points);
+ CHECKMALLOC(XL);
+ CHECKMALLOC(YL);
+
+ // Convert arrays to the Xastir coordinate
+ // system
+ for (nn = 0; nn < polygon_points; nn++) {
+ convert_to_xastir_coordinates(&XL[nn],
+ &YL[nn],
+ vectorX[nn],
+ vectorY[nn]);
+ }
+
+
+ XI = (long *)malloc(sizeof(long) * polygon_points);
+ YI = (long *)malloc(sizeof(long) * polygon_points);
+ CHECKMALLOC(XI);
+ CHECKMALLOC(YI);
+
+// Note: We're limiting screen size to 32767 in this routine.
+ minX = -32768;
+ maxX = 32767;
+ minY = -32768;
+ maxY = 32767;
+
+
+ // Convert arrays to screen coordinates.
+ // Careful here! The format conversions you'll
+ // need if you try to compress this into two
+ // lines will get you into trouble.
+ //
+ // We also clip to screen size and compute
+ // min/max values here.
+ for (nn = 0; nn < polygon_points; nn++) {
+ XI[nn] = XL[nn] - NW_corner_longitude;
+ XI[nn] = XI[nn] / scale_x;
+
+ YI[nn] = YL[nn] - NW_corner_latitude;
+ YI[nn] = YI[nn] / scale_y;
+
+// Here we truncate: We should polygon clip instead, so that the
+// slopes of the line segments don't change. Points beyond +/-
+// 32767 can cause problems in X11 when we draw. Here we are more
+// interested in keeping the rectangles small and fast. Screen-size
+// or smaller basically.
+ XI[nn] = l16(XI[nn]);
+ YI[nn] = l16(YI[nn]);
+
+ if (!polygon_hole) {
+
+ // Find the min/max extents for the
+ // arrays. We use that to set the size
+ // of our mask region.
+ if (XI[nn] < minX) minX = XI[nn];
+ if (XI[nn] > maxX) maxX = XI[nn];
+ if (YI[nn] < minY) minY = YI[nn];
+ if (YI[nn] > maxY) maxY = YI[nn];
+ }
+ }
+
+
+ // We don't need the Xastir coordinate system
+ // arrays anymore. We've already converted to
+ // screen coordinates.
+ if (XL)
+ free(XL);
+ if (YL)
+ free(YL);
+
+ if (!polygon_hole) { // Outer ring (fill)
+ int pp;
+
+ // Set up the XPoint array that we'll need
+ // for our final draw (after the "holey"
+ // region is set up if we have multiple
+ // rings).
+ xpoints = (XPoint *)malloc(sizeof(XPoint) * polygon_points);
+ CHECKMALLOC(xpoints);
+
+ // Load up our xpoints array
+ for (pp = 0; pp < polygon_points; pp++) {
+ xpoints[pp].x = (short)XI[pp];
+ xpoints[pp].y = (short)YI[pp];
+ }
+ num_outer_points = polygon_points;
+ }
+
+
+ // If we have no inner polygons, skip the whole
+ // X11 Region thing and just draw a filled
+ // polygon to the pixmap for speed. We do that
+ // here via the "single_polygon" variable.
+ //
+ if (!polygon_hole) { // Outer ring (fill)
+
+ if (single_polygon) {
+ mask = NULL;
+ }
+ else {
+ // Pass the extents of the polygon to
+ // create a mask rectangle out of them.
+ mask = create_clip_mask(polygon_points,
+ minX,
+ minY,
+ maxX,
+ maxY);
+ }
+ }
+ else { // Inner ring (hole)
+
+ // Pass the entire "hole" polygon set of
+ // vertices into the hole region creation
+ // function. This knocks a hole in our mask
+ // so that underlying map layers can show
+ // through.
+
+ // This segfaults for TIGER polygons without
+ // the if(mask) part.
+ //
+ if (mask) { // create_clip_mask has been
+ // called already
+ mask = create_hole_in_mask(mask,
+ polygon_points,
+ XI,
+ YI);
+ }
+ else {
+ fprintf(stderr,
+ "Draw_OGR_Polygons: Attempt to make hole in empty polygon mask!\n");
+ }
+ }
+
+
+ // Free the screen coordinate arrays.
+ if (XI)
+ free(XI);
+ if (YI)
+ free(YI);
+
+ // Draw the original polygon to the pixmap
+ // using the X11 Region as a mask. Mask may be
+ // null if we're doing a single outer polygon
+ // with no "hole" polygons.
+ if (kk == (object_num - 1)) {
+ draw_polygon_with_mask(mask,
+ xpoints,
+ num_outer_points);
+
+
+ // Draw the corresponding labels
+ Draw_OGR_Labels(w,
+ pixmap,
+ featureH,
+ geometryH,
+ xpoints,
+ num_outer_points,
+ label_color_guess);
+
+ free(xpoints);
+ }
+ } // end of draw_filled
+
+
+ else { // We're drawing non-filled polygons.
+ // Draw just the border.
+ int skip_duplicates = 0;
+
+ if (polygon_hole) {
+ // Inner ring, draw a dashed line
+ (void)XSetLineAttributes (XtDisplay(da), gc, 0, LineOnOffDash, CapButt,JoinMiter);
+ }
+ else {
+ // Outer ring, draw a solid line
+ (void)XSetLineAttributes (XtDisplay(da), gc, 0, LineSolid, CapButt,JoinMiter);
+ }
+
+ for ( mm = 1; mm < polygon_points; mm++ ) {
+
+/*
+fprintf(stderr,"Vector %d: %7.5f %8.5f %7.5f %8.5f\n",
+ mm,
+ vectorY[mm-1],
+ vectorX[mm-1],
+ vectorY[mm],
+ vectorX[mm]);
+*/
+
+
+ draw_vector_ll(da,
+ (float)vectorY[mm-1],
+ (float)vectorX[mm-1],
+ (float)vectorY[mm],
+ (float)vectorX[mm],
+ gc,
+ pixmap,
+ skip_duplicates);
+
+ skip_duplicates = 1;
+ }
+
+/*
+ // Draw the corresponding labels
+ Draw_OGR_Labels(w,
+ pixmap,
+ featureH,
+ geometryH,
+ xpoints,
+ num_points,
+ label_color_guess);
+*/
+
+ }
+
+
+// For weather polygons, we might want to draw the border color in a
+// different color so that we can see these borders easily, or skip
+// drawing the border itself for a few pixels, like UI-View does.
+
+ // Free the allocated vector memory
+ if (vectorX)
+ free(vectorX);
+ if (vectorY)
+ free(vectorY);
+ if (vectorZ)
+ free(vectorZ);
+
+ }
+ else {
+ // Not enough points to draw a polygon
+ }
+ }
+ }
+}
+
+
+
+
+
+// Set up coordinate translation: We need it for indexing and
+// drawing so we do it first and keep pointers to our transforms.
+//
+// Inputs: datasourceH
+// layerH
+//
+// Outputs: map_spatialH
+// transformH
+// reverse_transformH
+// wgs84_spatialH
+// no_spatial
+// geographic
+// projected
+// local
+// datum
+// geogcs
+//
+void setup_coord_translation(OGRDataSourceH datasourceH,
+ OGRLayerH layerH,
+ OGRSpatialReferenceH *map_spatialH,
+ OGRCoordinateTransformationH *transformH,
+ OGRCoordinateTransformationH *reverse_transformH,
+ OGRSpatialReferenceH *wgs84_spatialH,
+ int *no_spatial,
+ int *geographic,
+ int *projected,
+ int *local,
+ const char *datum,
+ const char *geogcs) {
+
+
+ *map_spatialH = NULL;
+ *transformH = NULL;
+ *reverse_transformH = NULL;
+ *wgs84_spatialH = NULL;
+ datum = NULL;
+ geogcs = NULL;
+
+
+set_dangerous("map_gdal: OGR_DS_GetLayerCount");
+ if (OGR_DS_GetLayerCount(datasourceH) <= 0) {
+clear_dangerous();
+ fprintf(stderr,"No layers detected\n");
+ return; // No layers detected!
+ }
+clear_dangerous();
+
+
+ // Query the coordinate system for the dataset.
+set_dangerous("map_gdal: OGR_L_GetSpatialRef");
+ *map_spatialH = OGR_L_GetSpatialRef(layerH);
+clear_dangerous();
+
+
+ if (*map_spatialH) {
+ const char *temp;
+
+
+ // We found spatial data
+ no_spatial = 0;
+
+
+set_dangerous("map_gdal: OGRIsGeographic");
+ if (OSRIsGeographic(*map_spatialH)) {
+ geographic++;
+ }
+ else if (OSRIsProjected(*map_spatialH)) {
+ projected++;
+ }
+ else {
+ local++;
+ }
+clear_dangerous();
+
+
+ // PROJCS, GEOGCS, DATUM, SPHEROID, PROJECTION
+ //
+set_dangerous("map_gdal:OSRGetAttrValue");
+ if (projected) {
+ temp = OSRGetAttrValue(*map_spatialH, "PROJCS", 0);
+ temp = OSRGetAttrValue(*map_spatialH, "PROJECTION", 0);
+ }
+ temp = OSRGetAttrValue(*map_spatialH, "SPHEROID", 0);
+ datum = OSRGetAttrValue(*map_spatialH, "DATUM", 0);
+ geogcs = OSRGetAttrValue(*map_spatialH, "GEOGCS", 0);
+clear_dangerous();
+
+ }
+
+
+ else {
+
+ if (debug_level & 16)
+ fprintf(stderr," Couldn't get spatial reference\n");
+
+ // For this case, assume that it is WGS84/geographic, and
+ // attempt to index as-is. If the numbers don't make sense,
+ // we can skip indexing this dataset.
+
+ // Perhaps some layers may have a spatial reference, and
+ // others might not? Solved this problem by defined
+ // "no_spatial", which will be '1' if no spatial data was
+ // found in any of the layers. In that case we just store
+ // the extents we find.
+ }
+
+
+//fprintf(stderr,"Datum: %s\n", datum);
+//fprintf(stderr,"GOGCS: %s\n", geogcs);
+
+
+ if (no_spatial) { // No spatial info found
+
+ *transformH = NULL; // No transforms needed
+ *reverse_transformH = NULL;
+
+ if (debug_level & 16) {
+ fprintf(stderr,
+ " No spatial info found, NO CONVERSION DONE!, %s\n",
+ geogcs);
+ }
+ }
+ else if ( geographic // Geographic and correct datum
+ && ( strcasecmp(geogcs,"WGS84") == 0
+ || strcasecmp(geogcs,"NAD83") == 0
+ || strcasecmp(datum,"North_American_Datum_1983") == 0
+ || strcasecmp(datum,"World_Geodetic_System_1984") == 0
+ || strcasecmp(datum,"D_North_American_1983") == 0 ) ) {
+
+// We also need to check "DATUM", as some datasets have nothing in
+// the "GEOGCS" variable. Check for "North_American_Datum_1983" or
+// "???".
+
+ *transformH = NULL; // No transforms needed
+ *reverse_transformH = NULL;
+
+ if (debug_level & 16) {
+ fprintf(stderr,
+ " Geographic coordinate system, NO CONVERSION NEEDED!, %s\n",
+ geogcs);
+ }
+ }
+
+ else { // We have coordinates but they're in the wrong datum or
+ // in a projected/local coordinate system. Set up a
+ // transform to WGS84.
+
+ if (geographic) {
+ if (debug_level & 16) {
+ fprintf(stderr,
+ " Found geographic/wrong datum: %s. Converting to wgs84 datum\n",
+ geogcs);
+ fprintf(stderr, " DATUM: %s\n", datum);
+ }
+ }
+
+ else if (projected) {
+ if (debug_level & 16) {
+ fprintf(stderr,
+ " Found projected coordinates: %s. Converting to geographic/wgs84 datum\n",
+ geogcs);
+ }
+ }
+
+ else if (local) {
+ // Convert to geographic/WGS84? How?
+
+ if (debug_level & 16) {
+ fprintf(stderr,
+ " Found local coordinate system. Returning\n");
+ }
+
+ // Close data source
+ if (datasourceH != NULL) {
+ OGR_DS_Destroy( datasourceH );
+ }
+
+ return; // Exit early
+ }
+
+ else {
+ // Abandon all hope, ye who enter here! We don't
+ // have a geographic, projected, or local coordinate
+ // system.
+
+ // Close data source
+ if (datasourceH != NULL) {
+ OGR_DS_Destroy( datasourceH );
+ }
+
+ return; // Exit early
+ }
+
+
+ *wgs84_spatialH = OSRNewSpatialReference(NULL);
+
+
+ if (*wgs84_spatialH == NULL) {
+ if (debug_level & 16) {
+ fprintf(stderr,
+ "Couldn't create empty wgs84_spatialH object\n");
+ }
+
+ // Close data source
+ if (datasourceH != NULL) {
+ OGR_DS_Destroy( datasourceH );
+ }
+
+ return; // Exit early
+ }
+
+
+ if (OSRSetWellKnownGeogCS(*wgs84_spatialH,"WGS84") == OGRERR_FAILURE) {
+
+ // Couldn't fill in WGS84 parameters.
+ if (debug_level & 16) {
+ fprintf(stderr,
+ "Couldn't fill in wgs84 spatial reference parameters\n");
+ }
+
+ // NOTE: DO NOT destroy map_spatialH! It is part of
+ // the datasource. You'll get a segfault if you
+ // try, at the point where you destroy the
+ // datasource.
+
+ if (*wgs84_spatialH != NULL) {
+ OSRDestroySpatialReference(*wgs84_spatialH);
+ }
+
+ // Close data source
+ if (datasourceH != NULL) {
+ OGR_DS_Destroy( datasourceH );
+ }
+
+ return; // Exit early
+ }
+
+
+ if (*map_spatialH == NULL || *wgs84_spatialH == NULL) {
+ if (debug_level & 16) {
+ fprintf(stderr,
+ "Couldn't transform because map_spatialH or wgs84_spatialH are NULL\n");
+ }
+
+ if (*wgs84_spatialH != NULL) {
+ OSRDestroySpatialReference(wgs84_spatialH);
+ }
+
+ // Close data source
+ if (datasourceH != NULL) {
+ OGR_DS_Destroy( datasourceH );
+ }
+
+ return; // Exit early
+ }
+
+
+ else {
+ // Set up transformation from original datum to wgs84
+ // datum.
+//fprintf(stderr,"Creating transform and reverse_transform\n");
+ *transformH = OCTNewCoordinateTransformation(
+ *map_spatialH, *wgs84_spatialH);
+
+ // Set up transformation from wgs84 datum to original
+ // datum.
+ *reverse_transformH = OCTNewCoordinateTransformation(
+ *wgs84_spatialH, *map_spatialH);
+
+
+ if (*transformH == NULL || *reverse_transformH == NULL) {
+ // Couldn't create transformation objects
+// if (debug_level & 16) {
+ fprintf(stderr,
+ "Couldn't create transformation objects\n");
+// }
+
+/*
+ if (*wgs84_spatialH != NULL) {
+ OSRDestroySpatialReference(wgs84_spatialH);
+ }
+
+ // Close data source
+ if (datasourceH != NULL) {
+ OGR_DS_Destroy( datasourceH );
+ }
+*/
+
+ return; // Exit early
+ }
+ }
+ }
+
+clear_dangerous();
+
+} // End of setup_coord_translation()
+
+
+
+
+
+// Need this declaration for weather alerts currently
+#ifdef HAVE_LIBSHP
+extern void draw_shapefile_map (Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *mdf);
+#endif /* HAVE_LIBSHP */
+
+
+// For AreaLandmarks and Landmarks data. Allows us to look
+// up the POLYID integer given the LAND integer.
+typedef struct _landmarkinfo {
+ int LAND; // From AreaLandmarks
+ int POLYID; // From AreaLandmarks
+ char CENID[6]; // From AreaLandmarks
+}landmarkinfo;
+
+typedef struct _tlid_struct {
+ int TLID; // Max value is 2^31 or 2,147,483,647
+ struct _tlid_struct *next;
+}tlid_struct;
+
+typedef struct _polyinfo {
+ int POLYID; // From Polygon, polygon ID
+ char CENID[6]; // From Polygon, many others
+ double POLYLONG; // From PIP
+ double POLYLAT; // From PIP
+ int WATER; // From PIP, 1 or 2 = water
+ int LAND; // From AreaLandmarks, Landmark ID
+ char CFCC[4]; // From Landmarks
+ char LANAME[31]; // From Landmarks, Landmark name
+ struct _tlid_struct *tlid_list; // From PolyChainLink
+}polyinfo;
+
+typedef struct _tlidinfo {
+ int TLID; // Tiger/Line ID
+ char FEDIRP[3]; // Size from Tiger 2003 definitions
+ char FENAME[31];// Size from Tiger 2003 definitions
+ char FETYPE[5]; // Size from Tiger 2003 definitions
+ char FEDIRS[3]; // Size from Tiger 2003 definitions
+ OGRGeometryH geometryH;
+}tlidinfo;
+
+#define LAND_HASH_SIZE 5000
+#define POLYID_HASH_SIZE 64000
+#define TLID_HASH_SIZE 240000
+
+
+
+
+
+// Create hash from key. LAND is unique within each county.
+// We perform the modulus function on it with the size of
+// our hash to derive the hash key.
+//
+unsigned int landmark_hash_from_key(void *key) {
+ landmarkinfo *temp = key;
+
+ return(temp->LAND % LAND_HASH_SIZE);
+}
+
+
+
+
+
+// Test equality of hash keys. In this case LAND is the key
+// we care about.
+//
+int landmark_keys_equal(void *key1, void *key2) {
+ landmarkinfo *temp1 = key1;
+ landmarkinfo *temp2 = key2;
+
+ if (temp1->LAND == temp2->LAND)
+ return(1); // LAND fields match
+ else
+ return(0); // No match
+}
+
+
+
+
+
+// FUNCTION:
+// Create hash from key. POLYID is unique within each
+// CENID. We perform the modulus function on it with the
+// size of our hash to derive the hash key.
+//
+unsigned int polyid_hash_from_key(void *key) {
+ polyinfo *temp = key;
+
+ return(temp->POLYID % POLYID_HASH_SIZE);
+}
+
+
+
+
+
+// FUNCTION:
+// Test equality of hash keys. In this case POLYID (and
+// CENID?) are the keys we care about.
+//
+int polyid_keys_equal(void *key1, void *key2) {
+ polyinfo *temp1 = key1;
+ polyinfo *temp2 = key2;
+
+ if (temp1->POLYID == temp2->POLYID)
+ return(1); // POLYID fields match
+ else
+ return(0); // No match
+}
+
+
+
+
+
+// FUNCTION:
+// Create hash from key. TLID is unique across the U.S. We
+// perform the modulus function on it with the size of our
+// hash to derive the hash key.
+//
+unsigned int tlid_hash_from_key(void *key) {
+ tlidinfo *temp = key;
+
+ return(temp->TLID % TLID_HASH_SIZE);
+}
+
+
+
+
+
+// FUNCTION:
+// Test equality of hash keys. In this case TLID is the
+// absolute key that we care about.
+//
+int tlid_keys_equal(void *key1, void *key2) {
+ tlidinfo *temp1 = key1;
+ tlidinfo *temp2 = key2;
+
+ if (temp1->TLID == temp2->TLID)
+ return(1); // TLID fields match
+ else
+ return(0); // No match
+}
+
+
+
+
+
+// For TIGER, we must create polygons from the vector lines. Use
+// this function in the C API to do that:
+//
+// OGRGeometryH CPL_DLL OGRBuildPolygonFromEdges(
+// OGRGeometryH hLinesAsCollection,
+// int bBestEffort,
+// int bAutoClose,
+// double dfTolerance,
+// OGRErr * peErr );
+//
+// We may need to create some as "hole" polygons and some as "fill"
+// polygons, then order the vectors properly to pass off to the
+// Draw_OGR_Polygon() function.
+//
+//
+// The GDAL docs say to use these flags to compile:
+// `gdal-config --libs` `gdal-config * --cflags`
+// but so far they return: "-L/usr/local/lib -lgdal" and
+// "-I/usr/local/include", which aren't much. Leaving it hard-coded
+// in configure.ac for now instead of using "gdal-config".
+//
+// GRASS module that does OGR (for reference): v.in.ogr
+//
+// This function started out as very nearly verbatim the example
+// C-API code off the OGR web pages.
+//
+// If destination_pixmap equals INDEX_CHECK_TIMESTAMPS or
+// INDEX_NO_TIMESTAMPS, then we are indexing the file (finding the
+// extents) instead of drawing it.
+//
+// Indexing/drawing works properly for either geographic or
+// projected coordinates, and does conversions to geographic/WGS84
+// datum before storing the extents in the map index. It does not
+// work for local coordinate systems.
+//
+//
+// TODO:
+// *) map_visible_ll() needs to be re-checked. Lines are not
+// showing up sometimes when the end points are way outside the
+// view. Perhaps need line_visible() and line_visible_ll()
+// functions? If I don't want to compute the slope of a line and
+// such, might just check for line ends being within boundaries
+// or left/above, and within boundaries or right/below, to catch
+// those lines that slant across the view.
+// *) Dbfawk support or similar? Map preferences: Colors, line
+// widths, layering, filled, choose label field, label
+// fonts/placement/color.
+// *) Allow user to select layers to draw/ignore. Very important
+// for those sorts of files that provide all layers (i.e. Tiger &
+// SDTS).
+// *) Weather alert tinted polygons, draw to the correct pixmap,
+// draw only those shapes called for, not the entire map.
+// *) Fast Extents: We now pass a variable to the draw functions
+// that tells whether we can do fast extents, but we still need
+// to compute our own extents after we have the points for a
+// shape in an array. We could either check extents or just call
+// the draw functions, which skip drawing if outside our view
+// anyway (we currently do the latter).
+
+
+// We've changed over to the spatial filter scheme: Set a spatial
+// filter based on our current view, draw only those objects that
+// OGR_L_GetNextFeature() passes back to us. That saves a lot of
+// coordinate conversion code and speeds things up dramatically.
+
+
+// *) Figure out why SDTS hypsography (contour lines) on top of
+// terraserver gives strange results when zooming/panning
+// sometimes. Restarting Xastir cleans up the image. Perhaps
+// colors or GC's are getting messed up? Perhaps lines segments
+// are too long when drawing?
+// *) Some sort of warning to the operator if large regions are
+// being filled, and there's a base raster map? Dbfawk likes to
+// fill counties in with purple, wiping out rasters underneath.
+// *) Draw portions of a line/polygon correctly, instead of just
+// dropping or concatenating lines. This can cause missing line
+// segments that cross the edge of our view, or incorrect slopes
+// for lines that cross the edge.
+// NOTE: Have switched to chopping at +/- 32767 pixels, which
+// seems to fix this nicely. Chopping at much less causes
+// problems, while X11 has problems at +/- 32767 or higher.
+// *) Speed things up in any way possible.
+//
+//
+// Regarding coordinate systems, a note from Frank Warmerdam: "In
+// theory different layers in a datasource can have different
+// coordinate systems, though this is uncommon. It does happen
+// though."
+//
+// Question regarding how to specify drawing preferences, answered
+// by Frank: "There are many standards. Within the OGR API the
+// preferred approach to this is the OGR Feature Style
+// Specification:
+//
+// http://gdal.velocet.ca/~warmerda/projects/opengis/ogr_feature_style_008.html
+//
+// Basically this is intended to provide a mechanism for different
+// underlying formats to indicate their rendering information. It
+// is at least partially implemented for the DGN and Mapinfo
+// drivers. The only applications that I am aware of taking
+// advantage of it are OpenEV and MapServer."
+
+void draw_ogr_map( Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *mdf) {
+
+ OGRDataSourceH datasourceH = NULL;
+ OGRSFDriverH driver = NULL;
+ OGRSpatialReferenceH map_spatialH = NULL;
+ OGRSpatialReferenceH wgs84_spatialH = NULL;
+ OGRCoordinateTransformationH transformH = NULL;
+ OGRCoordinateTransformationH reverse_transformH = NULL;
+ OGRGeometryH spatial_filter_geometryH = NULL;
+ int ii, numLayers;
+ char full_filename[300];
+ const char *ptr;
+ const char *driver_type;
+ int no_spatial = 1;
+ int geographic = 0;
+ int projected = 0;
+ int local = 0;
+ const char *datum = NULL;
+ const char *geogcs = NULL;
+ double ViewX[2], ViewY[2], ViewZ[2];
+ double ViewX2[2], ViewY2[2], ViewZ2[2];
+ long ViewLX[2], ViewLY[2];
+ float f_latitude0, f_latitude1, f_longitude0, f_longitude1;
+ char status_text[MAX_FILENAME];
+ char short_filenm[MAX_FILENAME];
+ int draw_filled;
+
+ draw_filled=mdf->draw_filled;
+
+ if (debug_level & 16)
+ fprintf(stderr,"Entered draw_ogr_map function\n");
+
+
+/******************************************************************/
+// We don't want to process weather alerts right now in this code.
+// We're not set up for it yet. Call the original shapefile map
+// function instead. We added an extern declaration above in order
+// that this function knows about the draw_shapefile_map() function
+// parameters. Remove that declaration once we support weather
+// alerts in this code natively.
+//
+if (alert) {
+
+#ifdef HAVE_LIBSHP
+
+ // We have a weather alert, call the original function instead.
+ draw_shapefile_map(w,
+ dir,
+ filenm,
+ alert,
+ alert_color,
+ destination_pixmap,
+ mdf);
+
+#endif // HAVE_LIBSHP
+
+ return;
+}
+/******************************************************************/
+
+
+ xastir_snprintf(full_filename,
+ sizeof(full_filename),
+ "%s/%s",
+ dir,
+ filenm);
+
+
+ // Create a shorter filename for display (one that fits the
+ // status line more closely). Subtract the length of the
+ // "Indexing " and/or "Loading " strings as well.
+ if (strlen(filenm) > (41 - 9)) {
+ int avail = 41 - 11;
+ int new_len = strlen(filenm) - avail;
+
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "..%s",
+ &filenm[new_len]);
+ }
+ else {
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "%s",
+ filenm);
+ }
+
+
+// if (debug_level & 16)
+ fprintf(stderr,"Opening datasource %s\n", full_filename);
+
+ //
+ // One computer segfaulted at OGROpen() if a .prj file was
+ // present with a shapefile. Another system with newer Linux/
+ // libtiff/ libgeotiff works fine. Getting rid of older header
+ // files/ libraries, then recompiling/installing libproj/
+ // libgeotiff/ libshape/ libgdal/ Xastir seemed to fix it.
+ //
+ // Open data source
+set_dangerous("map_gdal: OGROpen");
+ datasourceH = OGROpen(full_filename,
+ 0 /* bUpdate */,
+ &driver);
+clear_dangerous();
+
+ if (datasourceH == NULL) {
+/*
+ fprintf(stderr,
+ "Unable to open %s\n",
+ full_filename);
+*/
+ return;
+ }
+
+ if (debug_level & 16)
+ fprintf(stderr,"Opened datasource %s\n", full_filename);
+
+ driver_type = OGR_Dr_GetName(driver);
+
+ if (debug_level & 16)
+ fprintf(stderr,"%s: ", driver_type);
+
+ // Get name/path. Less than useful since we should already know
+ // this.
+ ptr = OGR_DS_GetName(datasourceH);
+
+ if (debug_level & 16)
+ fprintf(stderr,"%s\n", ptr);
+
+
+ // Implement the indexing functions, so that we can use these
+ // map formats from within Xastir. Without an index, it'll
+ // never appear in the map chooser. Use the OGR "envelope"
+ // functions to get the extents for the each layer in turn.
+ // We'll find the min/max of the overall set of layers and use
+ // that for the extents for the entire dataset.
+ //
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+// We're indexing only. Save the extents in the index.
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+
+
+ double file_MinX = 0;
+ double file_MaxX = 0;
+ double file_MinY = 0;
+ double file_MaxY = 0;
+ int first_extents = 1;
+
+
+ xastir_snprintf(status_text,
+ sizeof(status_text),
+ langcode ("BBARSTA039"),
+ short_filenm);
+ statusline(status_text,0); // Indexing ...
+
+//fprintf(stderr,"Indexing %s\n", filenm);
+
+ // Use the OGR "envelope" function to get the extents for
+ // the entire file or dataset. Remember that it could be in
+ // state-plane coordinate system or something else equally
+ // strange. Convert it to WGS84 or NAD83 geographic
+ // coordinates before saving the index.
+
+ // Loop through all layers in the data source. We can't get
+ // the extents for the entire data source without looping
+ // through the layers.
+ //
+ numLayers = OGR_DS_GetLayerCount(datasourceH);
+ for ( ii=0; ii<numLayers; ii++ ) {
+ OGRLayerH layerH;
+ OGREnvelope psExtent;
+
+
+ layerH = OGR_DS_GetLayer( datasourceH, ii );
+
+ if (layerH == NULL) {
+
+ if (debug_level & 16) {
+ fprintf(stderr,
+ "Unable to open layer %d of %s\n",
+ ii,
+ full_filename);
+ }
+
+ if (wgs84_spatialH != NULL) {
+ OSRDestroySpatialReference(wgs84_spatialH);
+ }
+
+// if (transformH != NULL) {
+// OCTDestroyCoordinateTransformation(transformH);
+// }
+
+// if (reverse_transformH != NULL) {
+// OCTDestroyCoordinateTransformation(reverse_transformH);
+// }
+
+ // Close data source
+ if (datasourceH != NULL) {
+ OGR_DS_Destroy( datasourceH );
+ }
+
+ return; // Exit early
+ }
+
+
+ // Set up the coordinate translations we may need for
+ // both indexing and drawing operations. It sets up the
+ // transform and the reverse transforms we need to
+ // convert between the spatial coordinate systems.
+ //
+ setup_coord_translation(datasourceH, // Input
+ layerH, // Input
+ &map_spatialH, // Output
+ &transformH, // Output
+ &reverse_transformH, // Output
+ &wgs84_spatialH, // Output
+ &no_spatial, // Output
+ &geographic, // Output
+ &projected, // Output
+ &local, // Output
+ datum, // Output
+ geogcs); // Output
+
+
+ // Get the extents for this layer. OGRERR_FAILURE means
+ // that the layer has no spatial info or that it would be
+ // an expensive operation to establish the extent.
+ // Here we set the force option to TRUE in order to read
+ // all of the extents even for files where that would be
+ // an expensive operation. We're trying to index the
+ // file after all! Whether or not the operation is
+ // expensive makes no difference at this point.
+ //
+ if (OGR_L_GetExtent(layerH, &psExtent, TRUE) != OGRERR_FAILURE) {
+
+// fprintf(stderr,
+// " MinX: %f, MaxX: %f, MinY: %f, MaxY: %f\n",
+// psExtent.MinX,
+// psExtent.MaxX,
+// psExtent.MinY,
+// psExtent.MaxY);
+
+ // If first value, store it.
+ if (first_extents) {
+ file_MinX = psExtent.MinX;
+ file_MaxX = psExtent.MaxX;
+ file_MinY = psExtent.MinY;
+ file_MaxY = psExtent.MaxY;
+
+ first_extents = 0;
+ }
+ else {
+ // Store the min/max values
+ if (psExtent.MinX < file_MinX)
+ file_MinX = psExtent.MinX;
+ if (psExtent.MaxX > file_MaxX)
+ file_MaxX = psExtent.MaxX;
+ if (psExtent.MinY < file_MinY)
+ file_MinY = psExtent.MinY;
+ if (psExtent.MaxY > file_MaxY)
+ file_MaxY = psExtent.MaxY;
+ }
+ }
+ // No need to free layerH handle, it belongs to the
+ // datasource.
+ }
+ // All done looping through the layers.
+
+
+ // We only know how to handle geographic or projected
+ // coordinate systems. Test for these.
+ if ( !first_extents && (geographic || projected || no_spatial) ) {
+ // Need to also check datum! Must be NAD83 or WGS84 and
+ // geographic for our purposes.
+/*
+ if ( no_spatial
+ || (geographic
+ && ( strcasecmp(geogcs,"WGS84") == 0
+ || strcasecmp(geogcs,"NAD83") == 0) ) ) {
+// Also check "datum" here
+
+ fprintf(stderr,
+ "Geographic coordinate system, %s, adding to index\n",
+ geogcs);
+
+ if ( file_MinY >= -90.0 && file_MinY <= 90.0
+ && file_MaxY >= -90.0 && file_MaxY <= 90.0
+ && file_MinX >= -180.0 && file_MinX <= 180.0
+ && file_MaxX >= -180.0 && file_MaxX <= 180.0) {
+
+ // Check for all-zero entries
+ if ( file_MinY == 0.0
+ && file_MaxY == 0.0
+ && file_MinX == 0.0
+ && file_MaxX == 0.0 ) {
+// if (debug_level & 16) {
+ fprintf(stderr,
+ "Geographic coordinates are all zero, skipping indexing\n");
+ fprintf(stderr,"MinX:%f MinY:%f MaxX:%f MaxY:%f\n",
+ file_MinX,
+ file_MinY,
+ file_MaxX,
+ file_MaxY);
+// }
+ }
+ else {
+
+// Debug: Don't add them to the index so that we can experiment
+// with datum translation and such.
+//#define WE7U
+#ifndef WE7U
+ index_update_ll(filenm, // Filename only
+ file_MinY, // Bottom
+ file_MaxY, // Top
+ file_MinX, // Left
+ file_MaxX, // Right
+ 1000); // Default Map Layer
+#endif // WE7U
+ }
+ }
+ else {
+// if (debug_level & 16) {
+ fprintf(stderr,
+ "Geographic coordinates out of bounds, skipping indexing\n");
+ fprintf(stderr,"MinX:%f MinY:%f MaxX:%f MaxY:%f\n",
+ file_MinX,
+ file_MinY,
+ file_MaxX,
+ file_MaxY);
+// }
+ }
+ }
+ else { // We have coordinates but they're in the wrong
+ // datum or in a projected coordinate system.
+ // Convert to WGS84 coordinates.
+*/
+ double x[2];
+ double y[2];
+
+
+ x[0] = file_MinX;
+ x[1] = file_MaxX;
+ y[0] = file_MinY;
+ y[1] = file_MaxY;
+
+// fprintf(stderr,"Before: %f,%f\t%f,%f\n",
+// x[0],y[0],
+// x[1],y[1]);
+
+ // We can get files that have a weird coordinate
+ // system in them that doesn't have a transform
+ // defined. One such was "unamed". Check whether
+ // we have a valid transform. If not, just assume
+ // we're ok and index it as-is.
+ if (transformH == NULL) {
+ if (debug_level & 16)
+ fprintf(stderr, "No transform available!\n");
+ }
+ else {
+
+// fprintf(stderr,"Before: %f,%f\t%f,%f\n",
+// x[0],y[0],
+// x[1],y[1]);
+
+
+ if (OCTTransform(transformH, 2, x, y, NULL)) {
+
+// fprintf(stderr," After: %f,%f\t%f,%f\n",
+// x[0],y[0],
+// x[1],y[1]);
+ }
+ }
+
+ if ( y[0] >= -90.0 && y[0] <= 90.0
+ && y[1] >= -90.0 && y[1] <= 90.0
+ && x[0] >= -180.0 && x[0] <= 180.0
+ && x[1] >= -180.0 && x[1] <= 180.0) {
+
+ // Check for all-zero entries
+ if ( file_MinY == 0.0
+ && file_MaxY == 0.0
+ && file_MinX == 0.0
+ && file_MaxX == 0.0 ) {
+// if (debug_level & 16) {
+ fprintf(stderr,
+ "Coordinates are all zero, skipping indexing\n");
+ fprintf(stderr,"MinX:%f MinY:%f MaxX:%f MaxY:%f\n",
+ file_MinX,
+ file_MinY,
+ file_MaxX,
+ file_MaxY);
+// }
+ }
+ else {
+
+// Debug: Don't add them to the index so that we can experiment
+// with datum translation and such.
+#ifndef WE7U
+ index_update_ll(filenm, // Filename only
+ y[0], // Bottom
+ y[1], // Top
+ x[0], // Left
+ x[1], // Right
+ 1000); // Default Map Layer
+#endif // WE7U
+ }
+ }
+ else {
+// if (debug_level & 16) {
+ fprintf(stderr,
+ "Coordinates out of bounds, skipping indexing\n");
+ fprintf(stderr,"MinX:%f MinY:%f MaxX:%f MaxY:%f\n",
+ file_MinX,
+ file_MinY,
+ file_MaxX,
+ file_MaxY);
+// }
+ }
+// }
+ }
+
+ // Debug code:
+ // For now, set the index to be the entire world to get
+ // things up and running.
+// index_update_ll(filenm, // Filename only
+// -90.0, // Bottom
+// 90.0, // Top
+// -180.0, // Left
+// 180.0, // Right
+// 1000); // Default Map Layer
+
+ if (wgs84_spatialH != NULL) {
+ OSRDestroySpatialReference(wgs84_spatialH);
+ }
+
+ if (transformH != NULL) {
+ OCTDestroyCoordinateTransformation(transformH);
+ }
+
+ if (reverse_transformH != NULL) {
+ OCTDestroyCoordinateTransformation(reverse_transformH);
+ }
+
+ // Close data source
+ if (datasourceH != NULL) {
+ OGR_DS_Destroy( datasourceH );
+ }
+
+ return; // Done indexing the file
+ }
+
+
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+// The code below this point is for drawing, not indexing.
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+
+
+ xastir_snprintf(status_text,
+ sizeof(status_text),
+ langcode ("BBARSTA028"),
+ short_filenm);
+ statusline(status_text,0); // Loading ...
+
+// fprintf(stderr,"Loading %s\n", filenm);
+
+
+
+ // Find out what type of file we're dealing with. This reports
+ // one of:
+ //
+ // "AVCbin"
+ // "DGN"
+ // "FMEObjects Gateway"
+ // "GML"
+ // "Memory"
+ // "MapInfo File"
+ // "UK .NTF"
+ // "OCI"
+ // "ODBC"
+ // "OGDI"
+ // "PostgreSQL"
+ // "REC"
+ // "S57"
+ // "SDTS"
+ // "ESRI Shapefile"
+ // "TIGER"
+ // "VRT"
+ //
+
+
+ // If we're going to write, we need to test the capability using
+ // these functions:
+ // OGR_Dr_TestCapability(); // Does Driver have write capability?
+ // OGR_DS_TestCapability(); // Can we create new layers?
+
+
+// Optimization: Get the envelope for each layer if it's not an
+// expensive operation. Skip the layer if it's completely outside
+// our viewport.
+// Faster yet: Set up a SpatialFilter, then GetNextFeature() should
+// only return features that are within our maximum bounding
+// rectangle (MBR). setup_coord_translation() may have already set
+// up "wgs84_spatialH" for us as a SpatialReference.
+
+
+
+//(void)XSetFunction();
+(void)XSetFillStyle(XtDisplay(w), gc, FillSolid);
+
+
+
+ // Set up the geometry for the spatial filtering we'll do later
+ // in the layer loop. The geometry should specify our current
+ // view, but in the spatial reference system of the map layer.
+ //
+ // Fill in the corner coordinates of our viewport, in lat/long
+ // coordinates.
+ //
+/*
+ ViewX[0] = -110.0;
+ ViewY[0] = 40.0;
+ ViewZ[0] = 0.0;
+ ViewX[1] = -090.0;
+ ViewY[1] = 35.0;
+ ViewZ[1] = 0.0;
+*/
+ //long center_longitude; // Longitude at center of map
+ //long center_latitude; // Latitude at center of map
+
+ // Longitude, NW corner of map screen
+ ViewLX[0] = NW_corner_longitude;
+ // Latitude, NW corner of map screen
+ ViewLY[0] = NW_corner_latitude;
+ // Longitude, SE corner of map screen
+ ViewLX[1] = center_longitude + (center_longitude - NW_corner_longitude);
+ // Latitude, SE corner of map screen
+ ViewLY[1] = center_latitude + (center_latitude - NW_corner_latitude);
+
+ // Check for out-of bounds values
+ if (ViewLX[0] < 0) ViewLX[0] = 0;
+ if (ViewLY[0] < 0) ViewLY[0] = 0;
+ if (ViewLX[1] < 0) ViewLX[1] = 0;
+ if (ViewLY[1] < 0) ViewLY[1] = 0;
+
+ if (ViewLX[0] > 129600000) ViewLX[0] = 129600000;
+ if (ViewLY[0] > 64800000) ViewLY[0] = 64800000;
+ if (ViewLX[1] > 129600000) ViewLX[1] = 129600000;
+ if (ViewLY[1] > 64800000) ViewLY[1] = 64800000;
+
+ // Now convert the coordinates from Xastir coordinate system to
+ // Lat/long degrees in the form of floats.
+
+ convert_from_xastir_coordinates(&f_longitude0,
+ &f_latitude0,
+ ViewLX[0],
+ ViewLY[0]);
+ convert_from_xastir_coordinates(&f_longitude1,
+ &f_latitude1,
+ ViewLX[1],
+ ViewLY[1]);
+
+ // Convert to doubles
+ ViewX[0] = (double)f_longitude0;
+ ViewY[0] = (double)f_latitude0;
+ ViewX[1] = (double)f_longitude1;
+ ViewY[1] = (double)f_latitude1;
+ ViewZ[0] = 0.0;
+ ViewZ[1] = 0.0;
+
+
+ sdts_elevation_in_meters = 0;
+
+ // If it is an SDTS file, determine whether we may have
+ // elevation in feet or meters. AHPT layer present = feet, AHPR
+ // layer present = meters.
+ if (strcasecmp(driver_type,"SDTS") == 0) {
+
+ if (OGR_DS_GetLayerByName(datasourceH, "AHPR")) {
+ fprintf(stderr,"Elevation is in meters\n");
+ sdts_elevation_in_meters = 1;
+ }
+
+ if (OGR_DS_GetLayerByName(datasourceH, "AHPT")) {
+ fprintf(stderr,"Elevation is in feet\n");
+ }
+ }
+
+
+ // If we put these flags down in the layer loop, we end up with
+ // all black lines being drawn. Perhaps the layer that defines
+ // the types isn't the same layer that contains the vectors that
+ // get drawn?
+ //
+ hypsography_layer = 0;
+ hydrography_layer = 0;
+ water_layer = 0;
+ roads_trails_layer = 0;
+ railroad_layer = 0;
+ misc_transportation_layer = 0;
+
+
+
+ numLayers = OGR_DS_GetLayerCount(datasourceH);
+
+
+
+
+
+
+
+
+
+
+#ifdef TIGER_POLYGONS
+ // Special handling for TIGER files so that we can extract/draw
+ // polygons.
+ //
+ // Tiger Polygons:
+ // *) Read "Polygon". Snag "POLYID" and "CENID" fields.
+//DONE!
+ // *) Read "PIP". Match "POLYID" (and "CENID"?) field. Snag
+ // "POLYLONG", "POLYLAT", and "WATER" fields. We'll use the
+ // lat/long as the point to draw labels. "WATER"=1:
+ // Perennial. "WATER"=2: Intermittent.
+//DONE!
+ // *) Read "AreaLandmarks". Match on "POLYID" (and "CENID"?) if
+ // possible. Snag "LAND" field.
+//DONE!
+ // *) Read "Landmarks". Match on "LAND" field. Snag "CFCC" and
+ // "LANAME" fields.
+//DONE!
+ // *) Read "PolyChainLink". Match "POLYID" to either "POLYIDL" or
+ // "POLYIDR" (and "CENID" to either "CENIDL" or "CENIDR"?).
+ // Snag "TLID" fields.
+//DONE!
+ // *) Read the "CompleteChain" layer, caching the geometry of any
+ // lines that match "TLID" fields found above. We might just
+ // cache these with the polygon info while drawing the
+ // vectors/points, then if a "polygon_flag" is set, proceed
+ // to the last phases of drawing polygons. This will allow
+ // us to read in the vector information once instead of
+ // twice. Actually, reversing this would be better so that
+ // we draw vectors on top of the polygons, so that roads and
+ // railroads and such will get drawn on top of water, streams
+ // will get drawn on top of city color-fill, etc.
+//DONE!
+ // *) Once we've processed the CompleteChain layer, turn those
+ // geometries into real polygons:
+ // Create a wkbGeometryCollection object.
+//DONE!
+ // BuildPolygonFromEdges()
+//DONE!
+ // Draw the polygons. Decide whether to draw based on the
+ // WATER field and/or the CFCC field if present.
+//DONE!
+ // *) Draw non-polygon vectors.
+//DONE!
+ //
+ if (draw_filled && strcasecmp(driver_type,"TIGER") == 0) {
+ struct hashtable *polyid_hash;
+ struct hashtable *landmark_hash;
+ struct hashtable *tlid_hash;
+
+ OGRLayerH layerH;
+ OGRFeatureH featureH;
+ struct hashtable_itr *iterator = NULL;
+
+ // Create the empty hash table for polyid
+ polyid_hash = create_hashtable(POLYID_HASH_SIZE,
+ polyid_hash_from_key,
+ polyid_keys_equal);
+
+ // Create the empty hash table for "landmark"
+ landmark_hash = create_hashtable(LAND_HASH_SIZE,
+ landmark_hash_from_key,
+ landmark_keys_equal);
+
+ // Create the empty hash table for tlid
+ tlid_hash = create_hashtable(TLID_HASH_SIZE,
+ tlid_hash_from_key,
+ tlid_keys_equal);
+
+
+fprintf(stderr,"Starting polygon reassembly\n");
+fprintf(stderr," Polygon Layer ");
+start_timer();
+
+
+ layerH = OGR_DS_GetLayerByName(datasourceH, "Polygon");
+ if (layerH) {
+ // Loop through all of the "Polygon" layer records,
+ // saving the POLYID/CENID fields.
+ polyinfo *temp;
+
+ while ( (featureH = OGR_L_GetNextFeature( layerH )) != NULL ) {
+ int kk;
+
+ kk = OGR_F_GetFieldIndex( featureH, "POLYID");
+ if (kk != -1) {
+ int polyid;
+ int mm;
+
+ polyid = OGR_F_GetFieldAsInteger( featureH, kk);
+
+ // Allocate struct
+ temp = (polyinfo *)malloc(sizeof(polyinfo));
+ temp->POLYID = polyid;
+
+//fprintf(stderr,"POLYID:%i\n", polyid);
+
+ // Fill in some defaults
+ temp->WATER = 0;
+ temp->LAND = -1;
+ temp->CFCC[0] = '\0';
+ temp->LANAME[0] = '\0';
+ temp->tlid_list = NULL;
+
+ mm = OGR_F_GetFieldIndex( featureH, "CENID");
+ if (mm != -1) {
+ const char *cenid;
+
+ cenid = OGR_F_GetFieldAsString( featureH, mm);
+ xastir_snprintf(temp->CENID,
+ sizeof(temp->CENID),
+ "%s",
+ cenid);
+//fprintf(stderr,"CENID:%s\n", cenid);
+ }
+ else {
+ temp->CENID[0] = '\0';
+ }
+
+ // Insert a new value into the hash
+// Remember to free() the hash storage later
+
+ if (!hashtable_insert(polyid_hash,&temp->POLYID, temp)) {
+ fprintf(stderr,"Couldn't insert into polyid_hash\n");
+ free(temp);
+ }
+//fprintf(stderr,"%i ",temp->POLYID);
+ }
+
+ if (featureH != NULL)
+ OGR_F_Destroy( featureH );
+
+ } // End of while
+ } // End of if (layerH)
+
+
+stop_timer(); print_timer_results(); start_timer();
+fprintf(stderr," PIP Layer ");
+
+
+ layerH = OGR_DS_GetLayerByName(datasourceH, "PIP");
+ if (layerH) {
+ // Loop through all of the "PIP" layer records,
+ // saving the POLYLONG/POLYLAT/WATER fields.
+
+ while ( (featureH = OGR_L_GetNextFeature( layerH )) != NULL ) {
+ int kk;
+
+ kk = OGR_F_GetFieldIndex( featureH, "POLYID");
+ if (kk != -1) {
+ int polyid;
+ polyinfo *found;
+
+
+ polyid = OGR_F_GetFieldAsInteger( featureH, kk);
+
+ // Find an entry in the hash
+ found = hashtable_search(polyid_hash, &polyid);
+ if (found) { // Found a match!
+ int mm;
+
+//fprintf(stderr,"Found a match for POLYID in PIP layer!\n");
+
+ mm = OGR_F_GetFieldIndex( featureH, "POLYLONG");
+ if (mm != -1) {
+ double polylong;
+
+//fprintf(stderr,"POLYLONG\t");
+ polylong = OGR_F_GetFieldAsDouble( featureH, mm);
+ found->POLYLONG = polylong;
+ }
+
+ mm = OGR_F_GetFieldIndex( featureH, "POLYLAT");
+ if (mm != -1) {
+ double polylat;
+
+//fprintf(stderr,"POLYLAT\t");
+ polylat = OGR_F_GetFieldAsDouble( featureH, mm);
+ found->POLYLAT = polylat;
+ }
+
+ mm = OGR_F_GetFieldIndex( featureH, "WATER");
+ if (mm != -1) {
+ int water;
+
+//fprintf(stderr,"WATER\n");
+ water = OGR_F_GetFieldAsInteger( featureH, mm);
+ found->WATER = water;
+ }
+ }
+ }
+
+ if (featureH != NULL)
+ OGR_F_Destroy( featureH );
+
+ } // End of while
+ } // End of if (layerH)
+
+
+stop_timer(); print_timer_results(); start_timer();
+fprintf(stderr," AreaLandmarks Layer ");
+
+
+ layerH = OGR_DS_GetLayerByName(datasourceH, "AreaLandmarks");
+ if (layerH) {
+ // Loop through all of the "AreaLandmarks" layer records,
+ // saving the LAND fields in landmark_hash.
+
+ while ( (featureH = OGR_L_GetNextFeature( layerH )) != NULL ) {
+ int kk;
+
+ kk = OGR_F_GetFieldIndex( featureH, "LAND");
+ if (kk != -1) {
+ int land;
+
+ land = OGR_F_GetFieldAsInteger( featureH, kk);
+
+ kk = OGR_F_GetFieldIndex( featureH, "POLYID");
+ if (kk != -1) {
+ int polyid;
+ landmarkinfo *temp;
+
+ polyid = OGR_F_GetFieldAsInteger( featureH, kk);
+
+ // Allocate struct
+ temp = (landmarkinfo *)malloc(sizeof(landmarkinfo));
+ temp->LAND = land;
+ temp->POLYID = polyid;
+
+ kk = OGR_F_GetFieldIndex( featureH, "CENID");
+ if (kk != -1) {
+ const char *cenid;
+
+ cenid = OGR_F_GetFieldAsString( featureH, kk);
+ xastir_snprintf(temp->CENID,
+ sizeof(temp->CENID),
+ "%s",
+ cenid);
+ }
+ else {
+ temp->CENID[0] = '\0';
+ }
+
+ // Insert a new value into the hash
+// Remember to free() the hash storage later
+ if (!hashtable_insert(landmark_hash,&temp->LAND, temp)) {
+ fprintf(stderr,"Couldn't insert into landmark_hash\n");
+ free(temp);
+ }
+ }
+ }
+
+ if (featureH != NULL)
+ OGR_F_Destroy( featureH );
+
+ } // End of while
+ } // End of if (layerH)
+
+
+stop_timer(); print_timer_results(); start_timer();
+fprintf(stderr," Landmarks Layer ");
+
+
+ layerH = OGR_DS_GetLayerByName(datasourceH, "Landmarks");
+ if (layerH) {
+ // Loop through all of the "Landmarks" layer records,
+ // use the LAND value to search for the POLYID value in
+ // the landmark hash, then use the POLYID value to find
+ // the actual record in the polyid_hash and fill in the
+ // LANAME/CFCC fields there.
+ //
+ while ( (featureH = OGR_L_GetNextFeature( layerH )) != NULL ) {
+ int kk;
+
+ kk = OGR_F_GetFieldIndex( featureH, "LAND");
+ if (kk != -1) {
+ int land;
+ landmarkinfo *found;
+
+ land = OGR_F_GetFieldAsInteger( featureH, kk);
+
+ // Find an entry in landmark_hash
+ found = hashtable_search(landmark_hash, &land);
+ if (found) { // Found a match!
+ polyinfo *found2;
+
+//fprintf(stderr,"Found a match for LAND (%i) in Landmarks layer!\n", land);
+
+ // Find the corresponding entry in the polyid_hash
+ found2 = hashtable_search(polyid_hash, &found->POLYID);
+ if (found2) { // We have our destination record
+ int mm;
+
+//fprintf(stderr,"Found a match for POLYID (%i) in Landmarks layer!\n", found2->POLYID);
+
+ mm = OGR_F_GetFieldIndex( featureH, "CFCC");
+ if (mm != -1) {
+ const char *cfcc;
+
+ cfcc = OGR_F_GetFieldAsString( featureH, mm);
+//fprintf(stderr,"CFCC:%s\n", cfcc);
+ xastir_snprintf(found2->CFCC,
+ sizeof(found2->CFCC),
+ "%s",
+ cfcc);
+ }
+
+ mm = OGR_F_GetFieldIndex( featureH, "LANAME");
+ if (mm != -1) {
+ const char *laname;
+
+ laname = OGR_F_GetFieldAsString( featureH, mm);
+//fprintf(stderr,"LANAME:%s\n",laname);
+
+ xastir_snprintf(found2->LANAME,
+ sizeof(found2->LANAME),
+ "%s",
+ laname);
+ }
+ }
+ }
+ }
+
+ if (featureH != NULL)
+ OGR_F_Destroy( featureH );
+
+ } // End of while
+
+ // Restart reads of this layer at the first feature.
+ OGR_L_ResetReading(layerH);
+ }
+
+
+
+// The below section is probably not correct yet. I'll assume that
+// we need to watch how we do the right/left thing and construct our
+// chain appropriately, else we'll end up with weird polygons that
+// have all of the correct vertices but the wrong line segments
+// between them.
+// We also need to collect the geometry information for all of the
+// matches and link them together, so we can then use
+// OGRBuildPolygonFromEdges() to construct a real polygon that we
+// can draw.
+//
+
+
+stop_timer(); print_timer_results(); start_timer();
+fprintf(stderr," PolyChainLink Layer ");
+
+
+ layerH = OGR_DS_GetLayerByName(datasourceH, "PolyChainLink");
+ if (layerH) {
+ // Match "POLYID" from above to either "POLYIDL" or
+ // "POLYIDR" fields. Save the "TLID" fields on matches.
+ while ( (featureH = OGR_L_GetNextFeature( layerH )) != NULL ) {
+ int kk, mm, nn;
+ int polyidl = -1;
+ int polyidr = -1;
+ int tlid = -1;
+ polyinfo *found1;
+ polyinfo *found2;
+
+
+ kk = OGR_F_GetFieldIndex( featureH, "POLYIDL" );
+ mm = OGR_F_GetFieldIndex( featureH, "POLYIDR" );
+ nn = OGR_F_GetFieldIndex( featureH, "TLID" );
+
+ if (kk != -1)
+ polyidl = OGR_F_GetFieldAsInteger( featureH, kk);
+ if (mm != -1)
+ polyidr = OGR_F_GetFieldAsInteger( featureH, mm);
+ if (nn != -1)
+ tlid = OGR_F_GetFieldAsInteger( featureH, nn);
+
+
+ // Find an entry in the hash. Check both polyidl
+ // and polyidr for matches this time. If either
+ // match, add to the record.
+ //
+ found1 = hashtable_search(polyid_hash, &polyidl);
+ found2 = hashtable_search(polyid_hash, &polyidr);
+
+ if (found1 || found2) { // Found at least one match!
+ tlid_struct *tlid_temp;
+
+//fprintf(stderr,"Found a match for POLYIDL or POLYIDR in PolyChainLink layer!\n");
+
+ // Link it in at the END of the list to keep the
+ // line order correct. These are short lists on
+ // average so we're not losing too much time by
+ // traversing down the list each time. We could
+ // later make it a doubly-linked list in order
+ // to speed things up.
+ //
+ if (found1) {
+ // Allocate a new record and link it in at the
+ // end of the list. Fill it in with the value
+ // of TLID.
+ tlid_temp = (tlid_struct *)malloc(sizeof(tlid_struct));
+ tlid_temp->TLID = tlid;
+ tlid_temp->next = NULL;
+
+/*
+ if (found1->tlid_list == NULL) {
+ // List is NULL: Add the new record
+ found1->tlid_list = tlid_temp;
+ }
+ else { // List has at least one record.
+ // Traverse to the end of the list.
+ tlid_struct *p;
+
+ p = found1->tlid_list; // Head of list
+ while (p->next != NULL) {
+ p = p->next;
+ }
+ // We should be sitting at the last record.
+ // Add our new record to the end.
+ p->next = tlid_temp;
+ }
+*/
+
+// Try linking it at the beginning of the list instead, which will
+// change the drawing order of the vertices but should be much
+// faster.
+tlid_temp->next = found1->tlid_list;
+found1->tlid_list = tlid_temp;
+
+ }
+ if (found2) {
+ // Allocate a new record and link it in at the
+ // end of the list. Fill it in with the value
+ // of TLID.
+ tlid_temp = (tlid_struct *)malloc(sizeof(tlid_struct));
+ tlid_temp->TLID = tlid;
+ tlid_temp->next = NULL;
+
+/*
+ if (found2->tlid_list == NULL) {
+ // List is NULL: Add the new record
+ found2->tlid_list = tlid_temp;
+ }
+ else { // List has at least one record.
+ // Traverse to the end of the list.
+ tlid_struct *p;
+
+ p = found2->tlid_list; // Head of list
+ while (p->next != NULL) {
+ p = p->next;
+ }
+ // We should be sitting at the last record.
+ // Add our new record to the end.
+ p->next = tlid_temp;
+ }
+*/
+
+// Try linking it at the beginning of the list instead, which will
+// change the drawing order of the vertices but should be much
+// faster.
+tlid_temp->next = found2->tlid_list;
+found2->tlid_list = tlid_temp;
+
+ }
+ }
+
+ if (featureH != NULL)
+ OGR_F_Destroy( featureH );
+
+ } // End of while
+ }
+
+
+stop_timer(); print_timer_results(); start_timer();
+fprintf(stderr," CompleteChain Layer ");
+
+
+ // Run through the CompleteChain layer. Snag TLID, FEDIRP,
+ // FENAME, FETYPE, FEDIRS, and geometry, store it in a new
+ // hash by TLID.
+ //
+ layerH = OGR_DS_GetLayerByName(datasourceH, "CompleteChain");
+ if (layerH) {
+ tlidinfo *temp;
+
+ // Create a new hash table with TLID as the hash key.
+ while ( (featureH = OGR_L_GetNextFeature( layerH )) != NULL ) {
+ int kk;
+
+ kk = OGR_F_GetFieldIndex( featureH, "TLID");
+ if (kk != -1) {
+ int ll,mm,nn,oo;
+ int tlid;
+ const char *fedirp;
+ const char *fename;
+ const char *fetype;
+ const char *fedirs;
+ OGRGeometryH geometryH;
+
+
+ tlid = OGR_F_GetFieldAsInteger(featureH, kk);
+
+ // Allocate struct
+ temp = (tlidinfo *)malloc(sizeof(tlidinfo));
+ temp->TLID = tlid;
+ temp->FEDIRP[0] = '\0';
+ temp->FENAME[0] = '\0';
+ temp->FETYPE[0] = '\0';
+ temp->FEDIRS[0] = '\0';
+ temp->geometryH = NULL;
+
+//fprintf(stderr,"TLID:%i\n", tlid);
+
+ ll = OGR_F_GetFieldIndex( featureH, "FEDIRP");
+ mm = OGR_F_GetFieldIndex( featureH, "FENAME");
+ nn = OGR_F_GetFieldIndex( featureH, "FETYPE");
+ oo = OGR_F_GetFieldIndex( featureH, "FEDIRS");
+
+ if (ll != -1) {
+ fedirp = OGR_F_GetFieldAsString( featureH, ll);
+ if (fedirp != NULL) {
+ xastir_snprintf(temp->FEDIRP,
+ sizeof(temp->FEDIRP),
+ "%s",
+ fedirp);
+ }
+ }
+ if (mm != -1) {
+ fename = OGR_F_GetFieldAsString( featureH, mm);
+ if (fename != NULL) {
+ xastir_snprintf(temp->FENAME,
+ sizeof(temp->FENAME),
+ "%s",
+ fename);
+ }
+ }
+ if (nn != -1) {
+ fetype = OGR_F_GetFieldAsString( featureH, nn);
+ if (fetype != NULL) {
+ xastir_snprintf(temp->FETYPE,
+ sizeof(temp->FETYPE),
+ "%s",
+ fetype);
+ }
+ }
+ if (oo != -1) {
+ fedirs = OGR_F_GetFieldAsString( featureH, oo);
+ if (fedirs != NULL) {
+ xastir_snprintf(temp->FEDIRS,
+ sizeof(temp->FEDIRS),
+ "%s",
+ fedirs);
+ }
+ }
+
+
+ // Get a handle to the geometry itself, make a
+ // clone of it and tie it to the struct.
+ geometryH = OGR_F_GetGeometryRef(featureH);
+ if (geometryH) {
+ temp->geometryH = OGR_G_Clone(geometryH);
+ }
+
+
+ // Insert a new value into the hash
+// Remember to free() the hash storage later
+ if (!hashtable_insert(tlid_hash,&temp->TLID, temp)) {
+ fprintf(stderr,"Couldn't insert into tlid_hash\n");
+ free(temp);
+ }
+ }
+
+ if (featureH != NULL)
+ OGR_F_Destroy( featureH );
+
+ } // End of while
+
+ // Restart reads of this layer at the first feature.
+ OGR_L_ResetReading(layerH);
+
+ } // End of CompleteChain layer section
+
+
+stop_timer(); print_timer_results(); start_timer();
+fprintf(stderr,"Combine Hashes, Create/Draw Polygon ");
+
+
+ // We have two hashes with part of the info in each of them.
+ // We should be able to iterate through the polyid_hash,
+ // snag the TLID parameters out of each polygon, and then
+ // snag the geometry for each TLID out of the tlid_hash.
+ // Through this method we can draw each polygon one at a
+ // time by creating a polygon geometry out of each one.
+
+ // Iterate over the polyid_hash, drawing polygons as we go.
+ //
+ if (hashtable_count(polyid_hash) > 0) {
+//fprintf(stderr,"polyid_hash\n");
+ iterator = hashtable_iterator(polyid_hash);
+//fprintf(stderr,"got iterator\n");
+ do {
+ polyinfo *record;
+ tlid_struct *head;
+ OGRGeometryH collectionH;
+ OGRGeometryH newpolygonH;
+ OGRErr error;
+
+
+ record = hashtable_iterator_value(iterator);
+
+//fprintf(stderr,"got record\n");
+
+
+// Create an empty geometry collection that we can add other
+// geometries to.
+ collectionH = OGR_G_CreateGeometry(wkbGeometryCollection);
+
+ if (collectionH == NULL)
+ fprintf(stderr,"collectionH is empty\n");
+
+
+ // Iterate through the tlid_list linked list. Look
+ // up each TLID in the tlid_hash.
+ head = record->tlid_list;
+ while (head) {
+ tlidinfo *found;
+ OGRErr error;
+
+ // Find this TLID in the tlid_hash
+ found = hashtable_search(tlid_hash, &head->TLID);
+ if (found) { // Found a match!
+//fprintf(stderr,"T");
+ // Snag the geometry associated with this
+ // TLID. Add it to the geometry collection
+ // for this POLYID.
+ error = OGR_G_AddGeometry(collectionH,
+ found->geometryH);
+ if (error != OGRERR_NONE)
+ fprintf(stderr,
+ "OGR_G_AddGeometry: Unsupported geometry type?\n");
+ }
+ else {
+//fprintf(stderr,"?");
+ }
+
+ // Skip to the next tlid entry
+ head = head->next;
+ }
+
+
+// Create a polygon geometry out of the geometry collection.
+ newpolygonH = OGRBuildPolygonFromEdges(collectionH,
+ 1, // bBestEffort
+ 1, // bAutoClose
+ 0.0, // dfTolerance
+ &error); // OGRerr
+ if (error == OGRERR_NONE) {
+//fprintf(stderr,"\t\t\tCreated polygon!\n");
+ }
+ else {
+ fprintf(stderr,"Failed to create polygon!\n");
+ }
+
+
+ // Draw the polygons. All of the information to do
+ // so is available now.
+/*
+ guess_vector_attributes(w,
+ driver_type,
+ full_filename,
+ layerH,
+ featureH,
+ geometry_type);
+*/
+
+// For testing purposes only draw the water polygons.
+
+//if (record->WATER > 0 && record->CFCC[0] != 'H')
+// fprintf(stderr,"WATER polygon but no \'H\' CFCC! CFCC=%s\n", record->CFCC);
+
+ if (record->WATER > 0 || record->CFCC[0] == 'H') {
+
+ if (strncasecmp(record->CFCC,"H81",3) == 0) { // glacier
+ label_color_guess = 0x4d; // white
+//fprintf(stderr,"CFCC:%s\t", record->CFCC);
+//fprintf(stderr,"%s\n", record->LANAME);
+ }
+ else {
+ label_color_guess = 0x1a; // Steel Blue
+ }
+
+ if (label_color_guess != -1) {
+ Draw_OGR_Polygons(w,
+ //featureH,
+ NULL,
+ newpolygonH,
+ 1,
+ transformH,
+ draw_filled,
+ //fast_extents);
+ 1);
+ }
+ }
+
+
+ // Free the polygon structure
+ OGR_G_DestroyGeometry(newpolygonH);
+
+ // Free the geometry collection structure
+ OGR_G_DestroyGeometry(collectionH);
+
+ // Free the current hash element, advance to the next
+ } while (hashtable_iterator_advance(iterator));
+#ifndef USING_LIBGC
+ if (iterator) free(iterator);
+#endif // USING_LIBGC
+ }
+
+
+stop_timer(); print_timer_results(); start_timer();
+fprintf(stderr," Free'ing hash memory ");
+
+
+ // Free the memory we've allocated for the hashes.
+
+
+ // Iterate over the polyid_hash, free'ing the tlid_struct's
+ // that we allocated. Don't remove the hash entry or free
+ // the polyinfo struct inside the loop as that will break
+ // the iterator.
+ //
+//fprintf(stderr,"Hash elements: polyid:%6i ", hashtable_count(polyid_hash));
+ if (hashtable_count(polyid_hash) > 0) {
+ iterator = hashtable_iterator(polyid_hash);
+ do {
+ polyinfo *record;
+ tlid_struct *head;
+ tlid_struct *p;
+
+ record = hashtable_iterator_value(iterator);
+
+ // Free the tlid_struct linked list
+ head = record->tlid_list;
+ while (head) {
+//fprintf(stderr,"TLID ");
+ p = head;
+ head = head->next;
+ free(p);
+ }
+
+ // Free the current hash element, advance to the next
+ } while (hashtable_iterator_remove(iterator));
+#ifndef USING_LIBGC
+ if (iterator) free(iterator);
+#endif // USING_LIBGC
+ }
+ // polyid_hash should be empty at this point.
+
+
+ // Iterate over the tlid_hash, free'ing the geometry memory
+ // that we allocated. Don't remove the hash entry or free
+ // the tlidinfo struct inside the loop as that will break
+ // the iterator.
+ //
+//fprintf(stderr,"tlid:%6i ", hashtable_count(tlid_hash));
+ if (hashtable_count(tlid_hash) > 0) {
+ iterator = hashtable_iterator(tlid_hash);
+ do {
+ tlidinfo *record;
+
+ record = hashtable_iterator_value(iterator);
+
+ // Free the geometry structure
+ OGR_G_DestroyGeometry(record->geometryH);
+
+ // Free the current hash element, advance to the next
+ } while (hashtable_iterator_remove(iterator));
+
+#ifndef USING_LIBGC
+ if (iterator) free(iterator);
+#endif // USING_LIBGC
+ }
+ // tlid_hash should be empty at this point.
+
+
+ // Iterate over the landmark_hash, free'ing the memory
+ // that we allocated. Don't remove the hash entry of free
+ // the landmarkinfo struct inside the loop as that will
+ // break the iterator.
+ //
+//fprintf(stderr,"landmark:%6i\n", hashtable_count(landmark_hash));
+ if (hashtable_count(landmark_hash) > 0) {
+ iterator = hashtable_iterator(landmark_hash);
+ do {
+ // Free the current hash element, advance to the next
+ } while (hashtable_iterator_remove(iterator));
+#ifndef USING_LIBGC
+ if (iterator) free(iterator);
+#endif // USING_LIBGC
+ }
+ // landmark_hash should be empty at this point.
+
+
+ // Destroy the hash tables. If the second argument is a
+ // one, it indicates that the values should be free'd as
+ // well.
+ //
+ hashtable_destroy(polyid_hash, 1);
+ hashtable_destroy(tlid_hash, 1);
+ hashtable_destroy(landmark_hash, 1);
+
+
+stop_timer(); print_timer_results();
+//fprintf(stderr,"Done\n");
+
+
+ } // End of special TIGER section
+
+#endif // TIGER_POLYGONS
+
+
+
+
+
+
+
+
+
+
+ // Loop through all layers in the data source.
+ //
+ // Optimizations:
+ // SDTS, load only those layers that make sense.
+ // TIGER, same thing, based on the type of file. We probably need
+ // to do some serious changes to how we do TIGER layers anyway,
+ // as we have to pull multiple things together in order to draw
+ // polygons.
+ //
+ for ( ii=0; ii<numLayers; ii++ ) {
+ OGRLayerH layerH;
+ OGRFeatureH featureH;
+// OGRFeatureDefnH layerDefn;
+ OGREnvelope psExtent;
+ int extents_found = 0;
+ char geometry_type_name[50] = "";
+ int geometry_type = -1;
+ int fast_extents = 0;
+ int features_processed = 0;
+ const char *layer_name;
+
+
+//fprintf(stderr,"Layer %d:\n", ii);
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+
+ if (wgs84_spatialH != NULL) {
+ OSRDestroySpatialReference(wgs84_spatialH);
+ }
+
+// if (transformH != NULL) {
+// OCTDestroyCoordinateTransformation(transformH);
+// }
+
+// if (reverse_transformH != NULL) {
+// OCTDestroyCoordinateTransformation(reverse_transformH);
+// }
+
+ // Close data source
+ if (datasourceH != NULL) {
+ OGR_DS_Destroy( datasourceH );
+ }
+
+ return; // Exit early
+ }
+
+ layerH = OGR_DS_GetLayer( datasourceH, ii );
+
+ if (layerH == NULL) {
+ if (debug_level & 16) {
+ fprintf(stderr,
+ "Unable to open layer %d of %s\n",
+ ii,
+ full_filename);
+ }
+
+ if (wgs84_spatialH != NULL) {
+ OSRDestroySpatialReference(wgs84_spatialH);
+ }
+
+// if (transformH != NULL) {
+// OCTDestroyCoordinateTransformation(transformH);
+// }
+
+// if (reverse_transformH != NULL) {
+// OCTDestroyCoordinateTransformation(reverse_transformH);
+// }
+
+ // Close data source
+ if (datasourceH != NULL) {
+ OGR_DS_Destroy( datasourceH );
+ }
+
+ return; // Exit early
+ }
+
+
+ // Determine what kind of layer we're dealing with and set
+ // some flags.
+ //
+ layer_name = OGR_FD_GetName( OGR_L_GetLayerDefn( layerH ) );
+
+ if (layer_name != NULL) {
+
+//fprintf(stderr,"Layer %i: %s\n", ii, layer_name);
+
+ if (strcasecmp(driver_type,"SDTS") == 0) {
+ //
+ // Layer 0: ARDF Roads/Trails Layer
+ // Layer 1: ARRF Railroad Layer
+ // Layer 2: AMTF Misc Transportation Layer
+ // Layer 3: ARDM
+ // Layer 4: ACOI
+ // Layer 5: AHDR
+ // Layer 6: NP01
+ // Layer 7: NP02
+ // Layer 8: NP03
+ // Layer 9: NP04
+ // Layer 10: NP05
+ // Layer 11: NP06
+ // Layer 12: NP07
+ // Layer 13: NP08
+ // Layer 14: NP09
+ // Layer 15: NP10
+ // Layer 16: NP11
+ // Layer 17: NP12
+ // Layer 18: NA01
+ // Layer 19: NA02
+ // Layer 20: NA03
+ // Layer 21: NA04
+ // Layer 22: NA05
+ // Layer 23: NA06
+ // Layer 24: NA07
+ // Layer 25: NA08
+ // Layer 26: NA09
+ // Layer 27: NA10
+ // Layer 28: NA11
+ // Layer 29: NA12
+ // Layer 30: NO01
+ // Layer 31: NO02
+ // Layer 32: NO03
+ // Layer 33: NO04
+ // Layer 34: NO05
+ // Layer 35: NO06
+ // Layer 36: NO07
+ // Layer 37: NO08
+ // Layer 38: NO09
+ // Layer 39: NO10
+ // Layer 40: NO11
+ // Layer 41: NO12
+ // Layer 42: LE01
+ // Layer 43: LE02
+ // Layer 44: LE03
+ // Layer 45: LE04
+ // Layer 46: LE05
+ // Layer 47: LE06
+ // Layer 48: LE07
+ // Layer 49: LE08
+ // Layer 50: LE09
+ // Layer 51: LE10
+ // Layer 52: LE11
+ // Layer 53: LE12
+ // Layer 54: PC01
+ // Layer 55: PC02
+ // Layer 56: PC03
+ // Layer 57: PC04
+ // Layer 58: PC05
+ // Layer 59: PC06
+ // Layer 60: PC07
+ // Layer 61: PC08
+ // Layer 62: PC09
+ // Layer 63: PC10
+ // Layer 64: PC11
+ // Layer 65: PC12
+ //
+ if (strncasecmp(layer_name,"AHPF",4) == 0) {
+ hypsography_layer++; // Topo contours
+ fprintf(stderr,"Hypsography Layer (topo contours)\n");
+ }
+ else if (strncasecmp(layer_name,"AHYF",4) == 0) {
+ hydrography_layer++; // Underwater contours
+ fprintf(stderr,"Hydrography Layer (underwater topo contours)\n");
+ }
+ else if (strncasecmp(layer_name,"ARDF",4) == 0) {
+ roads_trails_layer++;
+ fprintf(stderr,"Roads/Trails Layer\n");
+ }
+ else if (strncasecmp(layer_name,"ARRF",4) == 0) {
+ railroad_layer++;
+ fprintf(stderr,"Railroad Layer\n");
+ }
+ else if (strncasecmp(layer_name,"AMTF",4) == 0) {
+ misc_transportation_layer++;
+ fprintf(stderr,"Misc Transportation Layer\n");
+ }
+ }
+ else if (strcasecmp(driver_type,"TIGER") == 0) {
+ //
+ // Layer 0: CompleteChain
+ // Layer 1: AltName
+ // Layer 2: FeatureIds
+ // Layer 3: ZipCodes
+ // Layer 4: Landmarks
+ // Layer 5: AreaLandmarks
+ // Layer 6: Polygon
+ // Layer 7: PolygonCorrections
+ // Layer 8: EntityNames
+ // Layer 9: PolygonEconomic
+ // Layer 10: IDHistory
+ // Layer 11: PolyChainLink
+ // Layer 12: PIP
+ // Layer 13: TLIDRange
+ // Layer 14: ZeroCellID
+ // Layer 15: OverUnder
+ // Layer 16: ZipPlus4
+ //
+ if (strncasecmp(layer_name,"AltName",7) == 0) {
+ continue; // Skip this layer
+ }
+ else if (strncasecmp(layer_name,"ZipCodes",8) == 0) {
+ continue; // Skip this layer
+ }
+ else if (strncasecmp(layer_name,"Landmarks",9) == 0) {
+ continue; // Skip this layer
+ }
+ else if (strncasecmp(layer_name,"PolygonCorrections",18) == 0) {
+ continue; // Skip this layer
+ }
+ else if (strncasecmp(layer_name,"AreaLandmarks",13) == 0) {
+ continue; // Skip this layer
+ }
+ else if (strncasecmp(layer_name,"PolygonEconomic",15) == 0) {
+ continue; // Skip this layer
+ }
+ else if (strncasecmp(layer_name,"IDHistory",9) == 0) {
+ continue; // Skip this layer
+ }
+ else if (strncasecmp(layer_name,"ZeroCellID",10) == 0) {
+ continue; // Skip this layer
+ }
+ else if (strncasecmp(layer_name,"OverUnder",9) == 0) {
+ continue; // Skip this layer
+ }
+ else if (strncasecmp(layer_name,"ZipPlus4",8) == 0) {
+ continue; // Skip this layer
+ }
+ }
+ }
+
+
+//fprintf(stderr," Processing Layer %i\n", ii);
+
+
+
+ // Set up the coordinate translations we may need for both
+ // indexing and drawing operations. It sets up the
+ // transform and the reverse transforms we need to convert
+ // between the spatial coordinate systems.
+ //
+ setup_coord_translation(datasourceH, // Input
+ layerH, // Input
+ &map_spatialH, // Output
+ &transformH, // Output
+ &reverse_transformH, // Output
+ &wgs84_spatialH, // Output
+ &no_spatial, // Output
+ &geographic, // Output
+ &projected, // Output
+ &local, // Output
+ datum, // Output
+ geogcs); // Output
+
+
+ // Snag the original values (again if 2nd or later loop
+ // iteration).
+ ViewX2[0] = ViewX[0];
+ ViewX2[1] = ViewX[1];
+ ViewY2[0] = ViewY[0];
+ ViewY2[1] = ViewY[1];
+ if (reverse_transformH) {
+ // Convert our view coordinates from WGS84 to this map
+ // layer's coordinates.
+ if (!OCTTransform(reverse_transformH, 2, ViewX2, ViewY2, ViewZ2)) {
+ fprintf(stderr,
+ "Couldn't convert points from WGS84 to map's spatial reference\n");
+ // Use the coordinates anyway (don't exit). We may be
+ // lucky enough to have things work anyway.
+ }
+ // Get rid of our reverse transform. We shan't need it
+ // again.
+ OCTDestroyCoordinateTransformation(reverse_transformH);
+ reverse_transformH = NULL;
+ }
+
+//fprintf(stderr,"%2.5f %2.5f %2.5f %2.5f\n",
+// ViewY2[0], ViewX2[0], ViewY2[1], ViewX2[1]);
+
+
+ // Add these converted points to the spatial_filter_geometry so
+ // that we can set our spatial filter in the layer loop below.
+ // Snag the spatial reference from the map dataset 'cuz they
+ // should match now.
+ //
+ spatial_filter_geometryH = OGR_G_CreateGeometry(2); // LineString Type
+
+ // Use the map spatial geometry so that we match the map
+ OGR_G_AssignSpatialReference(spatial_filter_geometryH, map_spatialH);
+
+ // Add the corners of the viewport
+ OGR_G_AddPoint(spatial_filter_geometryH, ViewX2[0], ViewY2[0], ViewZ2[0]);
+ OGR_G_AddPoint(spatial_filter_geometryH, ViewX2[0], ViewY2[1], ViewZ2[1]);
+ OGR_G_AddPoint(spatial_filter_geometryH, ViewX2[1], ViewY2[1], ViewZ2[0]);
+ OGR_G_AddPoint(spatial_filter_geometryH, ViewX2[1], ViewY2[0], ViewZ2[1]);
+
+ // Set spatial filter so that the GetNextFeature() call will
+ // only return features that are within our view. Note that
+ // the geometry used here should be in the same spacial
+ // reference system as the layer itself, so we need to
+ // convert our coordinates into the map coordinates before
+ // setting the filter. We do this coordinate conversion and
+ // create the geometry outside the layer loop to save some
+ // time, then just set the spatial filter with the same
+ // geometry for each iteration.
+ //
+ // Note that this spatial filter doesn't strictly filter at
+ // the borders specified, but it does filter out a lot of
+ // the features that are outside our borders. This speeds
+ // up map drawing tremendously!
+ //
+ OGR_L_SetSpatialFilter( layerH, spatial_filter_geometryH);
+
+
+
+ // Test the capabilities of the layer to know the best way
+ // to access it:
+ //
+ // OLCRandomRead: TRUE if the OGR_L_GetFeature() function works
+ // for this layer.
+ // NOTE: Tiger and Shapefile report this as TRUE.
+ //
+ // OLCFastSpatialFilter: TRUE if this layer implements spatial
+ // filtering efficiently.
+ //
+ // OLCFastFeatureCount: TRUE if this layer can return a feature
+ // count (via OGR_L_GetFeatureCount()) efficiently. In some cases
+ // this will return TRUE until a spatial filter is installed after
+ // which it will return FALSE.
+ // NOTE: Tiger and Shapefile report this as TRUE.
+ //
+ // OLCFastGetExtent: TRUE if this layer can return its data extent
+ // (via OGR_L_GetExtent()) efficiently ... ie. without scanning
+ // all the features. In some cases this will return TRUE until a
+ // spatial filter is installed after which it will return FALSE.
+ // NOTE: Shapefile reports this as TRUE.
+ //
+ if (ii == 0) { // First layer
+ if (debug_level & 16)
+ fprintf(stderr, " ");
+ if (OGR_L_TestCapability(layerH, OLCRandomRead)) {
+ if (debug_level & 16)
+ fprintf(stderr, "Random Read, ");
+ }
+ if (OGR_L_TestCapability(layerH, OLCFastSpatialFilter)) {
+ if (debug_level & 16)
+ fprintf(stderr,
+ "Fast Spatial Filter, ");
+ }
+ if (OGR_L_TestCapability(layerH, OLCFastFeatureCount)) {
+ if (debug_level & 16)
+ fprintf(stderr,
+ "Fast Feature Count, ");
+ }
+ if (OGR_L_TestCapability(layerH, OLCFastGetExtent)) {
+ if (debug_level & 16)
+ fprintf(stderr,
+ "Fast Get Extent, ");
+ // Save this away and decide whether to
+ // request/compute extents based on this.
+ fast_extents = 1;
+ }
+ }
+
+
+/*
+ if (map_spatialH) {
+ const char *temp;
+ int geographic = 0;
+ int projected = 0;
+
+
+ if (OSRIsGeographic(map_spatialH)) {
+ if (ii == 0) {
+ if (debug_level & 16)
+ fprintf(stderr," Geographic Coord, ");
+ }
+ geographic++;
+ }
+ else if (OSRIsProjected(map_spatialH)) {
+ if (ii == 0) {
+ if (debug_level & 16)
+ fprintf(stderr," Projected Coord, ");
+ }
+ projected++;
+ }
+ else {
+ if (ii == 0) {
+ if (debug_level & 16)
+ fprintf(stderr," Local Coord, ");
+ }
+ }
+
+ // PROJCS, GEOGCS, DATUM, SPHEROID, PROJECTION
+ //
+ temp = OSRGetAttrValue(map_spatialH, "DATUM", 0);
+ if (ii == 0) {
+ if (debug_level & 16)
+ fprintf(stderr,"DATUM: %s, ", temp);
+ }
+
+ if (projected) {
+ temp = OSRGetAttrValue(map_spatialH, "PROJCS", 0);
+ if (ii == 0) {
+ if (debug_level & 16)
+ fprintf(stderr,"PROJCS: %s, ", temp);
+ }
+
+ temp = OSRGetAttrValue(map_spatialH, "PROJECTION", 0);
+ if (ii == 0) {
+ if (debug_level & 16)
+ fprintf(stderr,"PROJECTION: %s, ", temp);
+ }
+ }
+
+ temp = OSRGetAttrValue(map_spatialH, "GEOGCS", 0);
+ if (ii == 0) {
+ if (debug_level & 16)
+ fprintf(stderr,"GEOGCS: %s, ", temp);
+ }
+
+ temp = OSRGetAttrValue(map_spatialH, "SPHEROID", 0);
+ if (ii == 0) {
+ if (debug_level & 16)
+ fprintf(stderr,"SPHEROID: %s, ", temp);
+ }
+
+ }
+ else {
+ if (ii == 0) {
+ if (debug_level & 16)
+ fprintf(stderr," No Spatial Info, ");
+ // Assume geographic/WGS84 unless the coordinates go
+ // outside the range of lat/long, in which case,
+ // exit.
+ }
+ }
+*/
+
+
+
+ // Get the extents for this layer. OGRERR_FAILURE means
+ // that the layer has no spatial info or that it would be
+ // an expensive operation to establish the extent.
+ //OGRErr OGR_L_GetExtent(OGRLayerH hLayer, OGREnvelope *psExtent, int bForce);
+ if (OGR_L_GetExtent(layerH, &psExtent, FALSE) != OGRERR_FAILURE) {
+ // We have extents. Check whether any part of the layer
+ // is within our viewport.
+ if (ii == 0) {
+ if (debug_level & 16)
+ fprintf(stderr, "Extents obtained.");
+ }
+ extents_found++;
+ }
+ if (ii == 0) {
+ if (debug_level & 16)
+ fprintf(stderr, "\n");
+ }
+
+
+/*
+ if (extents_found) {
+ fprintf(stderr,
+ " MinX: %f, MaxX: %f, MinY: %f, MaxY: %f\n",
+ psExtent.MinX,
+ psExtent.MaxX,
+ psExtent.MinY,
+ psExtent.MaxY);
+ }
+*/
+
+
+// Dump info about this layer
+/*
+ layerDefn = OGR_L_GetLayerDefn( layerH );
+ if (layerDefn != NULL) {
+ int jj;
+ int numFields;
+
+ numFields = OGR_FD_GetFieldCount( layerDefn );
+
+ fprintf(stderr," Layer %d: '%s'\n", ii, OGR_FD_GetName(layerDefn));
+
+ for ( jj=0; jj<numFields; jj++ ) {
+ OGRFieldDefnH fieldDefn;
+
+ fieldDefn = OGR_FD_GetFieldDefn( layerDefn, jj );
+ fprintf(stderr," Field %d: %s (%s)\n",
+ jj, OGR_Fld_GetNameRef(fieldDefn),
+ OGR_GetFieldTypeName(OGR_Fld_GetType(fieldDefn)));
+ }
+ fprintf(stderr,"\n");
+ }
+
+
+ // Restart reads of this layer at the first feature.
+ //OGR_L_ResetReading(layerH);
+*/
+
+
+
+// Optimization: Get the envelope for each feature, skip the
+// feature if it's completely outside our viewport.
+
+ // Loop through all of the features in the layer.
+ //
+// if ( (featureH = OGR_L_GetNextFeature( layerH ) ) != NULL ) {
+//if (0) {
+ while ( (featureH = OGR_L_GetNextFeature( layerH )) != NULL ) {
+ OGRGeometryH geometryH;
+ int num = 0;
+// char *buffer;
+
+
+features_processed++;
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ if (featureH != NULL)
+ OGR_F_Destroy( featureH );
+
+ if (wgs84_spatialH != NULL) {
+ OSRDestroySpatialReference(wgs84_spatialH);
+ }
+
+ if (transformH != NULL) {
+ OCTDestroyCoordinateTransformation(transformH);
+ }
+
+// if (reverse_transformH != NULL) {
+// OCTDestroyCoordinateTransformation(reverse_transformH);
+// }
+
+ // Close data source
+ if (datasourceH != NULL) {
+ OGR_DS_Destroy( datasourceH );
+ }
+
+ return; // Exit early
+ }
+
+ if (featureH == NULL) {
+ continue;
+ }
+
+
+// Debug code
+//OGR_F_DumpReadable( featureH, stderr );
+
+
+ // Get a handle to the geometry itself
+ geometryH = OGR_F_GetGeometryRef(featureH);
+ if (geometryH == NULL) {
+ OGR_F_Destroy( featureH );
+// if (strlen(geometry_type_name) == 0) {
+ if (debug_level & 16)
+ fprintf(stderr," Layer %02d: - No geometry info -\n", ii);
+// geometry_type_name[0] = ' ';
+// geometry_type_name[1] = '\0';
+// }
+// Break out of this loop. We don't know how to draw anything but
+// geometry features yet. Change this when we start drawing labels.
+ break;
+// continue;
+ }
+
+
+
+ // More debug code. Print the Well Known Text
+ // representation of the geometry.
+ //if (OGR_G_ExportToWkt(geometryH, &buffer) == 0) {
+ // fprintf(stderr, "%s\n", buffer);
+ //}
+
+
+ // These are from the OGRwkbGeometryType enumerated set
+ // in ogr_core.h:
+ //
+ // 0 "Unknown"
+ // 1 "POINT" (ogrpoint.cpp)
+ // 2 "LINESTRING" (ogrlinestring.cpp)
+ // 3 "POLYGON" (ogrpolygon.cpp)
+ // 4 "MULTIPOINT" (ogrmultipoint.cpp)
+ // 5 "MULTILINESTRING" (ogrmultilinestring.cpp)
+ // 6 "MULTIPOLYGON" (ogrmultipolygon.cpp)
+ // 7 "GEOMETRYCOLLECTION" (ogrgeometrycollection.cpp)
+ // 100 "None"
+ // 101 "LINEARRING" (ogrlinearring.cpp)
+ // 0x80000001 "Point25D"
+ // 0x80000002 "LineString25D"
+ // 0x80000003 "Polygon25D"
+ // 0x80000004 "MultiPoint25D"
+ // 0x80000005 "MultiLineString25D"
+ // 0x80000006 "MultiPolygon25D"
+ // 0x80000007 "GeometryCollection25D"
+ //
+ // The geometry type will be the same for any particular
+ // layer. We take advantage of that here by querying
+ // once per layer and saving the results in variables.
+ //
+ if (strlen(geometry_type_name) == 0) {
+ xastir_snprintf(geometry_type_name,
+ sizeof(geometry_type_name),
+ "%s",
+ OGR_G_GetGeometryName(geometryH));
+ geometry_type = OGR_G_GetGeometryType(geometryH);
+// fprintf(stderr," Layer %02d: ", ii);
+// fprintf(stderr," Type: %d, %s\n",
+// geometry_type,
+// geometry_type_name);
+ }
+
+// Debug code
+//OGR_G_DumpReadable(geometryH, stderr, "Shape: ");
+
+
+
+// We could call OGR_G_GetEnvelope() here and calculate for
+// ourselves it if is in our viewport, or we could set a filter and
+// let the library pass us only those that fit.
+//
+// If point or line feature, draw in normal manner. If polygon
+// feature, do the "rotation one way = fill, rotation the other way
+// = hole" thing?
+//
+// We need all of the coordinates in WGS84 lat/long. Use the
+// conversion code that's in the indexing portion of this routine to
+// accomplish this.
+
+
+ switch (geometry_type) {
+
+ case 1: // Point
+ case 4: // MultiPoint
+ case 0x80000001: // Point25D
+ case 0x80000004: // MultiPoint25D
+
+ // Do this one time for the file itself to get
+ // some usable defaults.
+ guess_vector_attributes(w,
+ driver_type,
+ full_filename,
+ layerH,
+ featureH,
+ geometry_type);
+
+ if (label_color_guess != -1) {
+ Draw_OGR_Points(w,
+ featureH,
+ geometryH,
+ 1,
+ transformH);
+ }
+ break;
+
+ case 2: // LineString (polyline)
+ case 5: // MultiLineString
+ case 0x80000002: // LineString25D
+ case 0x80000005: // MultiLineString25D
+
+ // Do this one time for the file itself to get
+ // some usable defaults.
+ guess_vector_attributes(w,
+ driver_type,
+ full_filename,
+ layerH,
+ featureH,
+ geometry_type);
+
+ // Special handling for TIGER water polygons,
+ // which are represented as polylines instead of
+ // polygons.
+ //
+// How do we get the TIGER water drawn as filled polygons???
+ //
+ if (label_color_guess != -1) {
+ if (water_layer && strstr(driver_type,"TIGER")) {
+//fprintf(stderr,"TIGER water layer\n");
+
+ Draw_OGR_Lines(w,
+ featureH,
+ geometryH,
+ 1,
+ transformH,
+ fast_extents);
+ }
+ else { // Normal processing
+ Draw_OGR_Lines(w,
+ featureH,
+ geometryH,
+ 1,
+ transformH,
+ fast_extents);
+ }
+ }
+ break;
+
+ case 3: // Polygon
+ case 6: // MultiPolygon
+ case 0x80000003: // Polygon25D
+ case 0x80000006: // MultiPolygon25D
+
+ // Do this one time for the file itself to get
+ // some usable defaults.
+ guess_vector_attributes(w,
+ driver_type,
+ full_filename,
+ layerH,
+ featureH,
+ geometry_type);
+
+ if (label_color_guess != -1) {
+ Draw_OGR_Polygons(w,
+ featureH,
+ geometryH,
+ 1,
+ transformH,
+ draw_filled,
+ fast_extents);
+ }
+ break;
+
+ case 7: // GeometryCollection
+ case 0x80000007: // GeometryCollection25D
+ default: // Unknown/Unimplemented
+
+ num = 0;
+ if (debug_level & 16)
+ fprintf(stderr," Unknown or unimplemented geometry\n");
+ break;
+ }
+ if (featureH)
+ OGR_F_Destroy( featureH );
+ } // End of feature loop
+ // No need to free layerH handle, it belongs to the datasource
+
+//fprintf(stderr,"Features Processed: %d\n\n", features_processed);
+ } // End of layer loop
+
+ if (transformH != NULL) {
+ OCTDestroyCoordinateTransformation(transformH);
+ }
+
+// if (reverse_transformH != NULL) {
+// OCTDestroyCoordinateTransformation(reverse_transformH);
+// }
+
+ if (wgs84_spatialH != NULL) {
+ OSRDestroySpatialReference(wgs84_spatialH);
+ }
+
+ // Close data source
+ if (datasourceH != NULL) {
+ OGR_DS_Destroy( datasourceH );
+ }
+}
+
+
+
+#endif // HAVE_LIBGDAL
+
+
diff --git a/src/map_geo.c b/src/map_geo.c
new file mode 100644
index 0000000..c1dea05
--- /dev/null
+++ b/src/map_geo.c
@@ -0,0 +1,2550 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: map_geo.c,v 1.109 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+//#define FUZZYRASTER
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <dirent.h>
+#include <netinet/in.h>
+#include <Xm/XmAll.h>
+
+#ifdef HAVE_X11_XPM_H
+#include <X11/xpm.h>
+#ifdef HAVE_LIBXPM // if we have both, prefer the extra library
+#undef HAVE_XM_XPMI_H
+#endif // HAVE_LIBXPM
+#endif // HAVE_X11_XPM_H
+
+#ifdef HAVE_XM_XPMI_H
+#include <Xm/XpmI.h>
+#endif // HAVE_XM_XPMI_H
+
+#include <X11/Xlib.h>
+
+#include <math.h>
+
+#include "xastir.h"
+#include "maps.h"
+#include "map_cache.h"
+#include "alert.h"
+#include "fetch_remote.h"
+#include "util.h"
+#include "main.h"
+#include "datum.h"
+#include "draw_symbols.h"
+#include "rotated.h"
+#include "color.h"
+#include "xa_config.h"
+
+#include "map_OSM.h"
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+
+// Check for XPM and/or ImageMagick. We use "NO_GRAPHICS"
+// to disable some routines below if the support for them
+// is not compiled in.
+#if !(defined(HAVE_LIBXPM) || defined(HAVE_LIBXPM_IN_XM) || defined(HAVE_MAGICK))
+ #define NO_GRAPHICS 1
+#endif // !(HAVE_LIBXPM || HAVE_LIBXPM_IN_XM || HAVE_MAGICK)
+
+#if !(defined(HAVE_LIBXPM) || defined(HAVE_LIBXPM_IN_XM))
+ #define NO_XPM 1
+#endif // !(HAVE_LIBXPM || HAVE_LIBXPM_IN_XM)
+
+
+#ifdef HAVE_MAGICK
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+#undef RETSIGTYPE
+// TVR: "stupid ImageMagick"
+// The problem is that magick/api.h includes Magick's config.h file, and that
+// pulls in all the same autoconf-generated defines that we use.
+// plays those games below, but I don't think in the end that they actually
+// make usable macros with our own data in them.
+// Fortunately, we don't need them, so I'll just undef the ones that are
+// causing problems today. See main.c for fixes that preserve our values.
+#undef PACKAGE
+#undef VERSION
+/* JMT - stupid ImageMagick */
+#define XASTIR_PACKAGE_BUGREPORT PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#define XASTIR_PACKAGE_NAME PACKAGE_NAME
+#undef PACKAGE_NAME
+#define XASTIR_PACKAGE_STRING PACKAGE_STRING
+#undef PACKAGE_STRING
+#define XASTIR_PACKAGE_TARNAME PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#define XASTIR_PACKAGE_VERSION PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#ifdef HAVE_GRAPHICSMAGICK
+/*#include <GraphicsMagick/magick/api.h>*/
+/* Define MAGICK_IMPLEMENTATION to access private interfaces
+ * such as DestroyImagePixels(). This may not be a good thing,
+ * but DestroyImagePixels() has been in this code for a long
+ * time. Defining MAGIC_IMPLEMENTATION eliminates the warning that is
+ * now (9/28/2010) being seen on some distros (Ubuntu 10.04 and
+ * OpenSuSE-11.3)
+ */
+#define MAGICK_IMPLEMENTATION
+#include <magick/api.h>
+#else // HAVE_GRAPHICSMAGICK
+#include <magick/api.h>
+#endif // HAVE_GRAPHICSMAGICK
+#undef PACKAGE_BUGREPORT
+#define PACKAGE_BUGREPORT XASTIR_PACKAGE_BUGREPORT
+#undef XASTIR_PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#define PACKAGE_NAME XASTIR_PACKAGE_NAME
+#undef XASTIR_PACKAGE_NAME
+#undef PACKAGE_STRING
+#define PACKAGE_STRING XASTIR_PACKAGE_STRING
+#undef XASTIR_PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#define PACKAGE_TARNAME XASTIR_PACKAGE_TARNAME
+#undef XASTIR_PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#define PACKAGE_VERSION XASTIR_PACKAGE_VERSION
+#undef XASTIR_PACKAGE_VERSION
+#endif // HAVE_MAGICK
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+int check_interrupt(
+#ifdef HAVE_MAGICK
+ Image *image, ImageInfo *image_info, ExceptionInfo *exception,
+#else // HAVE_MAGICK
+ XImage *xi,
+#endif // HAVE_MAGICK
+ Widget *da, Pixmap *pixmap,
+ GC *gc, unsigned long screen_width, unsigned long screen_height)
+{
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+#ifdef HAVE_MAGICK
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ #else // HAVE_MAGICK
+ if (xi)
+ XDestroyImage (xi);
+#endif // HAVE_MAGICK
+ // Update to screen
+ (void)XCopyArea(XtDisplay(*da),
+ *pixmap,
+ XtWindow(*da),
+ *gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+#ifdef HAVE_MAGICK
+ DestroyExceptionInfo(exception);
+#endif // HAVE_MAGICK
+ return(~0);
+ } else
+ return(0);
+}
+
+void draw_geo_image_map (Widget w, char *dir, char *filenm,
+ alert_entry *alert, u_char alert_color, int destination_pixmap,
+ map_draw_flags *mdf);
+
+
+
+
+
+/* typedef struct _transparent_color_record{
+ unsigned long trans_color;
+ struct _transparent_color_record *next;
+ } transparent_color_record;
+*/
+ // Pointer to head of transparent color linked list.
+ transparent_color_record *trans_color_head = NULL;
+
+
+
+
+
+ // Empty out the linked list containing transparent colors
+ void empty_trans_color_list(void) {
+ transparent_color_record *p;
+
+ while (trans_color_head != NULL) {
+ p = trans_color_head;
+ trans_color_head = p->next;
+ free(p);
+ }
+ }
+
+
+
+
+
+ // Add a new transparent color to the linked list
+ void new_trans_color(unsigned long trans_color) {
+ transparent_color_record *p;
+
+//fprintf(stderr,"New transparent color: %lx\n", trans_color);
+
+ p = (transparent_color_record *)malloc( sizeof(transparent_color_record) );
+
+ // Fill in value
+ p->trans_color = trans_color;
+
+ // Link it to transparent color list
+ p->next = trans_color_head;
+ trans_color_head = p;
+ }
+
+
+
+
+
+/********************(**********************************************
+* check_trans()
+*
+* See if this pixel's color should be transparent
+*
+* We only call this from blocks where ImageMagick is used, so we're
+* ok to use IM calls.
+******************************************(************************/
+
+int check_trans (XColor c, transparent_color_record *c_trans_color_head) {
+ transparent_color_record *p = c_trans_color_head;
+
+ // fprintf (stderr, "pix = %li,%lx, chk = %li,%lx.\n",c.pixel,c.pixel,c_trans_color,c_trans_color);
+ // A linked list from the geo file of colors to zap.
+
+ // if ( c.pixel == (unsigned long) 0x000000 ) {
+ // return 1; // black background
+ //}
+ while (p) {
+ if ( c.pixel == p->trans_color ) {
+ return 1;
+ }
+ p = p->next;
+ }
+
+ return 0; // everything else is OK to draw
+}
+
+
+
+
+
+// Regarding MAP CACHING for toporama maps: Here we are only
+// snagging a .geo file for toporama from findu.com: We send the
+// parameters off to findu.com, it computes the .geo file, we
+// download it, then we call draw_geo_image_map() with it. We would
+// have to cache the .geo files from findu, we'd have to modify them
+// to point to our local cached map file (maybe), and we'd of course
+// have to cache that map image as well. The image filename on
+// findu changes each time we call with the same parameters, so we'd
+// have to give the image file our own name based on the parameters
+// and write that same name into the cached .geo file. A bit of
+// work, but it _could_ be done. Actually, we should be able to map
+// between the original URL we use to request the .GEO file and the
+// final image we received. That way the name would stay the same
+// each time we made the request. There may be other things we need
+// from the generated .GEO file though.
+//
+// For this particular case we need to snag a remote .geo file and
+// then start the process all over again. The URL we'll need to use
+// looks something like this:
+//
+// http://mm.aprs.net/toporama.cgi?set=50|lat=44.59333|lon=-75.72933|width=800|height=600|zoom=1
+//
+// Where the lat/lon are the center of our view, and the
+// width/height depend on our window size. The "set" parameter
+// decides whether we're fetching 50k or 250k maps.
+//
+void draw_toporama_map (Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *mdf,
+ int toporama_flag) { // 50 or 250
+
+#ifdef HAVE_MAGICK
+
+ char fileimg[MAX_FILENAME+1]; // Ascii name of image file, read from GEO file
+ char map_it[MAX_FILENAME];
+ char local_filename[MAX_FILENAME];
+ char file[MAX_FILENAME+1]; // Complete path/name of image file
+ char short_filenm[MAX_FILENAME+1];
+ FILE *f; // Filehandle of image file
+ double lat_center = 0;
+ double long_center = 0;
+ double left, right, top, bottom;
+ int my_screen_width, my_screen_height;
+ float my_zoom = 1.0;
+ char temp_file_path[MAX_VALUE];
+
+ // Create a shorter filename for display (one that fits the
+ // status line more closely). Subtract the length of the
+ // "Indexing " and/or "Loading " strings as well.
+ if (strlen(filenm) > (41 - 9)) {
+ int avail = 41 - 11;
+ int new_len = strlen(filenm) - avail;
+
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "..%s",
+ &filenm[new_len]);
+ }
+ else {
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "%s",
+ filenm);
+ }
+
+
+ //fprintf(stderr, "Found TOPORAMA in a .geo file, %dk scale\n", toporama_flag);
+
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ // We're indexing only. Save the extents in the index.
+ // Force the extents to the edges of the earth for the index
+ // file.
+ index_update_xastir(filenm, // Filename only
+ 64800000l, // Bottom
+ 0l, // Top
+ 0l, // Left
+ 129600000l, // Right
+ 0); // Default Map Level
+
+ // Update statusline
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ langcode ("BBARSTA039"),
+ short_filenm);
+ statusline(map_it,0); // Loading/Indexing ...
+
+ return; // Done indexing this file
+ }
+
+
+ // Compute the parameters we'll need for the URL, fetch the .geo
+ // file at that address, then pass that .geo file off to
+ // draw_geo_image_map(). This will cause us to fetch the image
+ // file corresponding to the .geo file and display it. We may
+ // also need to tweak the zoom parameter for our current zoom
+ // level so that things match up properly.
+
+
+ // Compute the center of our view in decimal lat/long.
+ left = (double)((NW_corner_longitude - 64800000l )/360000.0); // Lat/long Coordinates
+ top = (double)(-((NW_corner_latitude - 32400000l )/360000.0)); // Lat/long Coordinates
+ right = (double)((SE_corner_longitude - 64800000l)/360000.0);//Lat/long Coordinates
+ bottom = (double)(-((SE_corner_latitude - 32400000l)/360000.0));//Lat/long Coordinates
+
+ long_center = (left + right)/2.0l;
+ lat_center = (top + bottom)/2.0l;
+
+ // We now have the center in decimal lat/long. We also have the
+ // screen width and height in pixels, which we can use in the
+ // URL as well (depending on the zoom parameter and how to make
+ // the finished display look nice).
+
+
+ // Compute the size of the image we want to snag. It should be
+ // easy to get darn near anything to work, although the size and
+ // scale of the image will drastically affect how nicely the
+ // finished map display will look.
+
+
+ // Compute the zoom parameter for the URL.
+
+
+ // A test URL that works, just to get things going. This URL
+ // requests 1:50k scale maps ("set=50").
+ //xastir_snprintf(fileimg, sizeof(fileimg),
+ // "\"http://mm.aprs.net/toporama.cgi?set=50|lat=44.59333|lon=-75.72933|width=800|height=600|zoom=1\"");
+
+ // Compute our custom URL based on our map view and the
+ // requested map scale.
+ //
+ my_screen_width = (int)screen_width;
+ my_screen_height = (int)screen_height;
+
+ if (toporama_flag == 50) { // 1:50k
+
+ my_zoom = 32.0 / scale_y;
+
+ if (scale_y <= 16)
+ my_zoom = 2.0;
+ }
+ else { // toporama_flag == 250 (1:250k)
+
+ my_zoom = 128.0 / scale_y;
+
+ if (scale_y <= 64)
+ my_zoom = 2.0;
+ }
+
+ // Set a max zoom limit so we don't tax the server too much.
+ if (my_zoom < 0.02)
+ my_zoom = 0.02;
+
+ xastir_snprintf(fileimg, sizeof(fileimg),
+ "http://mm.aprs.net/toporama.cgi?set=%d|lat=%f|lon=%f|width=%d|height=%d|zoom=%0.3f",
+// "http://www2.findu.com/toporama.cgi?set=%d|lat=%f|lon=%f|width=%d|height=%d|zoom=%0.3f",
+ toporama_flag, // Scale, 50 or 250
+ lat_center,
+ long_center,
+ my_screen_width,
+ my_screen_height,
+ my_zoom);
+
+//fprintf(stderr,"%s\n", fileimg);
+
+ // Create a local filename that we'll save to.
+ xastir_snprintf(local_filename,
+ sizeof(local_filename),
+ "%s/map.geo",
+ get_user_base_dir("tmp", temp_file_path, sizeof(temp_file_path)));
+
+ // Erase any previously existing local file by the same
+ // name. This avoids the problem of having an old map image
+ // here and the code trying to display it when the download
+ // fails.
+ unlink( local_filename );
+
+
+ // Call wget or libcurl to fetch the .geo file. Best would be
+ // to create a generic "fetch" routine which would fetch a
+ // remote file, then go back and rework all of the various map
+ // routines to use it.
+
+ if (fetch_remote_file(fileimg, local_filename)) {
+ // Had trouble getting the file. Abort.
+ return;
+ }
+
+ // Set permissions on the file so that any user can overwrite it.
+ chmod(local_filename, 0666);
+
+ // We now re-use the "file" variable. It'll hold the
+ //name of the map file now instead of the .geo file.
+
+ // Tell ImageMagick where to find it
+ xastir_snprintf(file,sizeof(file),"%s",local_filename);
+
+
+
+// Check whether we got a reasonable ~/.xastir/tmp/map.geo file from
+// the fetch. If so, pass it off to the routine which can draw it.
+
+ // We also need to write a valid IMAGESIZE line into the .geo
+ // file. We know these parameters because they should match
+ // screen_width/screen_height.
+ //
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ "IMAGESIZE\t%d\t%d\n",
+ my_screen_width,
+ my_screen_height);
+
+// Another thing we might need is a TRANSPARENT line, for the grey
+// color we see crossing over the U.S. border and obscuring maps on
+// this side of the border.
+
+ f = fopen (local_filename, "a");
+ if (f != NULL) {
+ fprintf(f, "%s", map_it);
+ (void)fclose (f);
+ }
+ else {
+ fprintf(stderr,"Couldn't open file: %s to add IMAGESIZE tag\n", local_filename);
+ return;
+ }
+
+
+ // Call draw_geo_image_map() with our newly-fetched .geo file,
+ // passing it most of the parameters that we were originally
+ // passed in order to effect the map draw.
+ draw_geo_image_map (w,
+ get_user_base_dir("tmp", temp_file_path, sizeof(temp_file_path)),
+ "map.geo",
+ alert,
+ alert_color,
+ destination_pixmap,
+ mdf);
+
+#endif // HAVE_MAGICK
+}
+
+
+
+
+
+/**********************************************************
+ * draw_geo_image_map()
+ *
+ * If we have found a ".geo" file, we read it here and plot
+ * the graphic image into the current viewport.
+ * We check first to see whether the map should be plotted
+ * and skip it if it's not in our viewport. These images
+ * are expected to be aligned in the lat/lon directions
+ * (not rotated) and rectangular.
+ **********************************************************/
+
+void draw_geo_image_map (Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *mdf) {
+#ifdef NO_GRAPHICS
+ fprintf(stderr,"XPM and/or ImageMagick support have not been compiled in.\n");
+#else // NO_GRAPHICS
+ char file[MAX_FILENAME+1]; // Complete path/name of image file
+ char short_filenm[MAX_FILENAME+1];
+ FILE *f; // Filehandle of image file
+ char line[MAX_FILENAME]; // One line from GEO file
+ char fileimg[MAX_FILENAME+1]; // Ascii name of image file, read from GEO file
+ char tileCache[MAX_FILENAME+1]; // directory for the OSM tile cache, read from GEO file.
+ char OSMstyle[MAX_OSMSTYLE];
+ char OSMtileExt[MAX_OSMEXT];
+
+ // Start with an empty fileimg[] string so that we can
+ // tell if a URL has been specified in the file. Same for OSMstyle.
+ fileimg[0] = '\0';
+ OSMstyle[0] = '\0';
+ tileCache[0] = '\0';
+ OSMtileExt[0] = '\0';
+
+ int width,height;
+#ifndef NO_XPM
+ XpmAttributes atb; // Map attributes after map's read into an XImage
+#endif // HAVE_MAGICK
+
+ tiepoint tp[2]; // Calibration points for map, read in from .geo file
+ int n_tp; // Temp counter for number of tiepoints read
+ float temp_long, temp_lat;
+ register long map_c_T, map_c_L; // map delta NW edge coordinates, DNN: these should be signed
+ register long tp_c_dx, tp_c_dy; // tiepoint coordinate differences
+// DK7IN--
+ int test; // temporary debugging
+
+ unsigned long c_x_min, c_y_min;// top left coordinates of map inside screen
+ unsigned long c_y_max; // bottom right coordinates of map inside screen
+ double c_x; // Xastir coordinates 1/100 sec, 0 = 180�W
+ double c_y; // Xastir coordinates 1/100 sec, 0 = 90�N
+ double c_y_a; // coordinates correction for Transverse Mercator
+
+ long map_y_0; // map pixel pointer prior to TM adjustment
+ register long map_x, map_y; // map pixel pointers, DNN: this was a float, chg to long
+ long map_x_min, map_x_max; // map boundaries for in screen part of map
+ long map_y_min, map_y_max; //
+ long map_x_ctr; // half map width in pixel
+ long map_y_ctr; // half map height in pixel
+// long x;
+ int map_seen, map_act, map_done;
+ double corrfact;
+
+ long map_c_yc; // map center, vert coordinate
+ long map_c_xc; // map center, hor coordinate
+ double map_c_dx, map_c_dy; // map coordinates increment (pixel width)
+ double c_dx; // adjusted map pixel width
+
+ long scr_x, scr_y; // screen pixel plot positions
+ long scr_xp, scr_yp; // previous screen plot positions
+ int scr_dx, scr_dy; // increments in screen plot positions
+ long scr_x_mc; // map center in screen units
+
+ long scr_c_xr;
+
+ double dist; // distance from equator in nm
+ double ew_ofs; // distance from map center in nm
+
+ long scale_xa; // adjusted for topo maps
+ double scale_x_nm; // nm per Xastir coordinate unit
+ long scale_x0; // at widest map area
+
+#ifdef HAVE_MAGICK
+ char local_filename[MAX_FILENAME];
+ ExceptionInfo exception;
+ Image *image;
+ ImageInfo *image_info;
+ PixelPacket *pixel_pack;
+ PixelPacket temp_pack;
+ IndexPacket *index_pack;
+ int l;
+ XColor my_colors[256];
+ time_t query_start_time, query_end_time;
+ char gamma[16];
+ struct {
+ float r_gamma;
+ float g_gamma;
+ float b_gamma;
+ int gamma_flag;
+ int contrast;
+ int negate;
+ int equalize;
+ int normalize;
+ char level[32];
+ char modulate[32];
+ } imagemagick_options = { 1.0, 1.0, 1.0, 0, 0, -1, 0, 0, "", "" };
+ double left, right, top, bottom, map_width, map_height;
+ //N0VH
+// double lat_center = 0;
+// double long_center = 0;
+ // Terraserver variables
+ double top_n=0, left_e=0, bottom_n=0, right_e=0, map_top_n=0, map_left_e=0;
+ int z, url_n=0, url_e=0, t_zoom=16, t_scale=12800;
+ char zstr0[8];
+ char zstr1[8];
+#else // HAVE_MAGICK
+ XImage *xi; // Temp XImage used for reading in current image
+#endif // HAVE_MAGICK
+
+ int terraserver_flag = 0; // U.S. satellite images/topo/reflectivity/urban
+ // areas via terraserver
+ int tigerserver_flag = 0; // U.S. Street maps via census.gov
+ int OSMserver_flag = 0; // OpenStreetMaps server, 1 = static maps, 2 = tiled
+ unsigned tmp_zl = 0;
+
+ int toporama_flag = 0; // Canadian topo's from mm.aprs.net (originally from Toporama)
+ int WMSserver_flag = 0; // WMS server
+ char map_it[MAX_FILENAME];
+ int geo_image_width = 0; // Image width from GEO file
+ int geo_image_height = 0; // Image height from GEO file
+ char geo_datum[8+1]; // WGS-84 etc.
+ char geo_projection[256+1]; // TM, UTM, GK, LATLON etc.
+ int map_proj=0;
+ int map_refresh_interval_temp = 0;
+ int nocache = 0; // Don't cache the file if non-zero
+#ifdef FUZZYRASTER
+ int rasterfuzz = 3; // ratio to skip
+#endif //FUZZYRASTER
+ unsigned long temp_trans_color; // what color to zap
+ int trans_skip = 0; // skip transparent pixel
+ int crop_x1=0, crop_x2=0, crop_y1=0, crop_y2=0; // pixel crop box
+ int do_crop = 0; // do we crop pixels
+//#define TIMING_DEBUG
+#ifdef TIMING_DEBUG
+ time_mark(1);
+#endif // TIMING_DEBUG
+
+#ifdef HAVE_MAGICK
+ #ifdef USE_MAP_CACHE
+ int map_cache_return;
+ char *cache_file_id;
+ #endif // USE_MAP_CACHE
+#endif // HAVE_MAGICK
+
+ char temp_file_path[MAX_VALUE];
+ KeySym OSM_key = 0;
+
+ xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm);
+
+ // Create a shorter filename for display (one that fits the
+ // status line more closely). Subtract the length of the
+ // "Indexing " and/or "Loading " strings as well.
+ if (strlen(filenm) > (41 - 9)) {
+ int avail = 41 - 11;
+ int new_len = strlen(filenm) - avail;
+
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "..%s",
+ &filenm[new_len]);
+ }
+ else {
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "%s",
+ filenm);
+ }
+
+
+ // Read the .geo file to find out map filename and tiepoint info
+
+ // Empty the transparent color list before we start reading in a
+ // new .geo file.
+ empty_trans_color_list();
+
+ n_tp = 0;
+ geo_datum[0] = '\0';
+ geo_projection[0] = '\0';
+ f = fopen (file, "r");
+ if (f != NULL) {
+ while (!feof (f)) {
+ (void)get_line (f, line, MAX_FILENAME);
+ if (strncasecmp (line, "FILENAME", 8) == 0) {
+ if (1 != sscanf (line + 9, "%s", fileimg)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error\n");
+ }
+ if (fileimg[0] != '/' ) { // not absolute path
+ // make it relative to the .geo file
+ char temp[MAX_FILENAME];
+
+ // grab .geo file name
+ xastir_snprintf(temp,sizeof(temp),"%s",file);
+
+ (void)get_map_dir(temp); // leaves just the path and trailing /
+ if (strlen(temp) < (MAX_FILENAME - 1 - strlen(fileimg)))
+ strncat(temp,
+ fileimg,
+ sizeof(temp) - 1 - strlen(temp));
+ xastir_snprintf(fileimg,sizeof(fileimg),"%s",temp);
+ }
+ }
+ if (strncasecmp (line, "URL", 3) == 0)
+ if (1 != sscanf (line + 4, "%s", fileimg)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error\n");
+ }
+
+ if (n_tp < 2) { // Only take the first two tiepoints
+ if (strncasecmp (line, "TIEPOINT", 8) == 0) {
+ if (4 != sscanf (line + 9, "%d %d %f %f",
+ &tp[n_tp].img_x,
+ &tp[n_tp].img_y,
+ &temp_long,
+ &temp_lat)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error\n");
+ }
+ // Convert tiepoints from lat/lon to Xastir coordinates
+ tp[n_tp].x_long = 64800000l + (360000.0 * temp_long);
+ tp[n_tp].y_lat = 32400000l + (360000.0 * (-temp_lat));
+ n_tp++;
+ }
+ }
+
+ if (strncasecmp (line, "IMAGESIZE", 9) == 0)
+ if (2 != sscanf (line + 10, "%d %d",&geo_image_width,&geo_image_height)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error\n");
+ }
+
+ if (strncasecmp (line, "DATUM", 5) == 0)
+ if (1 != sscanf (line + 6, "%8s",geo_datum)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error\n");
+ }
+
+ if (strncasecmp (line, "PROJECTION", 10) == 0)
+ // Ignores leading and trailing space (nice!)
+ if (1 != sscanf (line + 11, "%256s",geo_projection)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error\n");
+ }
+
+ if (strncasecmp (line, "TERRASERVER-URBAN", 17) == 0)
+ terraserver_flag = 4;
+
+ if (strncasecmp (line, "TERRASERVER-REFLECTIVITY", 24) == 0)
+ terraserver_flag = 3;
+
+ if (strncasecmp (line, "TERRASERVER-TOPO", 16) == 0) {
+ // Set to max brightness as it looks weird when the
+ // intensity variable comes into play.
+#ifdef HAVE_MAGICK
+// This one causes problems now. Not sure why.
+// xastir_snprintf(imagemagick_options.modulate,32,"100 100 100");
+#endif // HAVE_MAGICK
+ terraserver_flag = 2;
+ }
+
+ if (strncasecmp (line, "TERRASERVER-SATELLITE", 21) == 0)
+ terraserver_flag = 1;
+
+ if (strncasecmp (line, "TIGERMAP", 8) == 0)
+ tigerserver_flag = 1;
+
+ if (strncasecmp (line, "OSMSTATICMAP", 12) == 0)
+ {
+ OSMserver_flag = 1;
+ if (strlen(line) > 13) {
+ if (1 != sscanf (line + 13, "%s", OSMstyle)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error for OSM style.\n");
+ }
+ }
+ }
+
+ if (strncasecmp (line, "OSM_TILED_MAP", 13) == 0)
+ {
+ OSMserver_flag = 2;
+ if (strlen(line) > 14) {
+ if (1 != sscanf (line + 14, "%s", OSMstyle)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error for OSM style.\n");
+ }
+ }
+ }
+
+ if (OSMserver_flag > 0) { // the following keywords are only valid for OSM maps
+ if (strncasecmp (line, "OSM_OPTIMIZE_KEY", 16) == 0){
+ if ((destination_pixmap != INDEX_CHECK_TIMESTAMPS)
+ && (destination_pixmap != INDEX_NO_TIMESTAMPS)) {
+ if (strlen(line) > 17) {
+ if (1 != sscanf (line + 17, "%lu", &OSM_key)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error for OSM_OPTIMIZE_KEY.\n");
+ } else {
+ set_OSM_optimize_key(OSM_key);
+ }
+ }
+ }
+ }
+
+ if (strncasecmp (line, "OSM_REPORT_SCALE_KEY", 20) == 0){
+ if ((destination_pixmap != INDEX_CHECK_TIMESTAMPS)
+ && (destination_pixmap != INDEX_NO_TIMESTAMPS)) {
+ if (strlen(line) > 21) {
+ if (1 != sscanf (line + 21, "%lu", &OSM_key)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error for OSM_OPTIMIZE_KEY.\n");
+ } else {
+ set_OSM_report_scale_key(OSM_key);
+ }
+ }
+ }
+ }
+
+ if (strncasecmp (line, "TILE_DIR", 8) == 0) {
+ if (strlen(line) > 9) {
+ if (1 != sscanf (line + 9, "%s", tileCache)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error for TILE_DIR\n");
+ }
+ }
+ }
+
+ if (strncasecmp (line, "TILE_EXT", 8) == 0) {
+ if (strlen(line) > 9) {
+ if (1 != sscanf (line + 9, "%s", OSMtileExt)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error for TILE_EXT\n");
+ }
+ }
+ }
+
+ if (strncasecmp(line, "ZOOM_LEVEL_MIN", 14) == 0) {
+ if (strlen(line) > 15) {
+ if (1 != sscanf(line + 15, "%u", &tmp_zl)) {
+ fprintf(stderr, "draw_geo_image_map:sscanf parsing error for ZOOM_LEVEL_MIN\n");
+ } else {
+ if (!(osm_zoom_level(scale_x) >= tmp_zl)) {
+ // skip this map because the zoom level
+ // is not supported.
+ if (debug_level & 512) {
+ fprintf(stderr, "Skipping OSM map. zl = %u < %u\n", osm_zoom_level(scale_x), tmp_zl);
+ }
+ return;
+ }
+ }
+ }
+ }
+ if (strncasecmp(line, "ZOOM_LEVEL_MAX", 14) == 0) {
+ if (strlen(line) > 15) {
+ if (1 != sscanf(line + 15, "%u", &tmp_zl)) {
+ fprintf(stderr, "draw_geo_image_map:sscanf parsing error for ZOOM_LEVEL_MAX\n");
+ } else {
+ if (!(tmp_zl >= osm_zoom_level(scale_x))) {
+ // skip this map because the zoom level
+ // is not supported.
+ if (debug_level & 512) {
+ fprintf(stderr, "Skipping OSM map. zl = %u > %u\n", osm_zoom_level(scale_x), tmp_zl);
+ }
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ if (strncasecmp (line, "WMSSERVER", 9) == 0)
+ WMSserver_flag = 1;
+
+ // Check for Canadian topo map request
+ if (strncasecmp (line, "TOPORAMA-50k", 12) == 0) {
+ toporama_flag = 50;
+ }
+ if (strncasecmp (line, "TOPORAMA-250k", 13) == 0) {
+ toporama_flag = 250;
+ }
+
+
+ // Check whether we're indexing or drawing the map.
+ // Exclude setting the map refresh interval from
+ // indexing.
+ if ( (destination_pixmap != INDEX_CHECK_TIMESTAMPS)
+ && (destination_pixmap != INDEX_NO_TIMESTAMPS) ) {
+
+ if (strncasecmp (line, "REFRESH", 7) == 0) {
+ if (1 != sscanf (line + 8, "%d", &map_refresh_interval_temp)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error\n");
+ }
+ if ( map_refresh_interval_temp > 0 &&
+ ( map_refresh_interval == 0 ||
+ map_refresh_interval_temp < map_refresh_interval) ) {
+ map_refresh_interval = (time_t) map_refresh_interval_temp;
+ map_refresh_time = sec_now() + map_refresh_interval;
+
+ if (debug_level & 512)
+ fprintf(stderr, "Map Refresh set to %d.\n", (int) map_refresh_interval);
+ }
+ nocache = map_refresh_interval_temp;
+ }
+ }
+
+ if (strncasecmp(line, "TRANSPARENT", 11) == 0) {
+ // need to make this read a list of colors to zap
+ // out. Use 32-bit unsigned values, so we can
+ // handle 32-bit color displays.
+ if (1 != sscanf (line + 12, "%lx", &temp_trans_color)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error\n");
+ }
+
+ {
+ unsigned short r,g,b;
+ // We'll assume the temp_trans_color has been
+ // specified as a 24-bit quantity
+ r = (temp_trans_color&0xff0000) >> 16;
+ g = (temp_trans_color&0x00ff00)>>8;
+ b = temp_trans_color&0x0000ff;
+ // Now this is an incredible kludge, but seems to be right
+ // Apparently, if QuantumDepth is 16 bits, r, g, and b
+ // values are duplicated in the high and low byte, which
+ // is just bizarre
+#ifdef HAVE_MAGICK
+ if (QuantumDepth == 16) {
+ r=r|(r<<8);
+ g=g|(g<<8);
+ b=b|(b<<8);
+ }
+#endif // HAVE_MAGICK
+ //fprintf(stderr,"Original Transparent %lx\n",temp_trans_color);
+ //fprintf(stderr,"Transparent r,g,b=%x,%x,%x\n",r,g,b);
+ if (visual_type == NOT_TRUE_NOR_DIRECT) {
+ XColor junk;
+
+#ifdef HAVE_MAGICK
+ if (QuantumDepth == 16) {
+ junk.red=r;
+ junk.green=g;
+ junk.blue=b;
+ }
+ else
+#endif // HAVE_MAGICK
+ {
+ junk.red= r<<8;
+ junk.green = g<<8;
+ junk.blue = b<<8;
+ }
+ XAllocColor(XtDisplay(w),cmap,&junk);
+ temp_trans_color = junk.pixel;
+ } else {
+ pack_pixel_bits(r,g,b,&temp_trans_color);
+ }
+ //fprintf(stderr,"Packed Transparent %lx\n",temp_trans_color);
+ }
+
+//fprintf(stderr,"New Transparent: %lx\n",temp_trans_color);
+
+ // Link color to transparent color list
+ new_trans_color(temp_trans_color);
+ }
+ if (strncasecmp(line, "CROP", 4) == 0) {
+ if (4 != sscanf (line + 5, "%d %d %d %d",
+ &crop_x1,
+ &crop_y1,
+ &crop_x2,
+ &crop_y2 )) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error\n");
+ }
+ if (crop_x1 < 0 ) crop_x1 = 0;
+ if (crop_y1 < 0 ) crop_y1 = 0;
+ if (crop_x2 < 0 ) crop_x2 = 0;
+ if (crop_y2 < 0 ) crop_y2 = 0;
+ if (crop_x2 < crop_x1 ) // swap
+ {do_crop = crop_x1; crop_x1=crop_x2; crop_x2=do_crop;}
+ if (crop_y2 < crop_y1 ) // swap
+ {do_crop = crop_y1; crop_y1=crop_y2; crop_y2=do_crop;}
+ do_crop = 1;
+ }
+#ifdef HAVE_MAGICK
+ if (strncasecmp(line, "GAMMA", 5) == 0)
+ imagemagick_options.gamma_flag = sscanf(line + 6, "%f,%f,%f",
+ &imagemagick_options.r_gamma,
+ &imagemagick_options.g_gamma,
+ &imagemagick_options.b_gamma);
+ if (strncasecmp(line, "CONTRAST", 8) == 0) {
+ if (1 != sscanf(line + 9, "%d", &imagemagick_options.contrast)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error\n");
+ }
+ }
+ if (strncasecmp(line, "NEGATE", 6) == 0) {
+ if (1 != sscanf(line + 7, "%d", &imagemagick_options.negate)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error\n");
+ }
+ }
+ if (strncasecmp(line, "EQUALIZE", 8) == 0)
+ imagemagick_options.equalize = 1;
+ if (strncasecmp(line, "NORMALIZE", 9) == 0)
+ imagemagick_options.normalize = 1;
+#if (MagickLibVersion >= 0x0539)
+ if (strncasecmp(line, "LEVEL", 5) == 0) {
+ xastir_snprintf(imagemagick_options.level,
+ sizeof(imagemagick_options.level),
+ "%s",
+ line+6);
+ }
+#endif // MagickLibVersion >= 0x0539
+ if (strncasecmp(line, "MODULATE", 8) == 0) {
+ xastir_snprintf(imagemagick_options.modulate,
+ sizeof(imagemagick_options.modulate),
+ "%s",
+ line+9);
+ }
+#endif // HAVE_MAGICK
+ }
+ (void)fclose (f);
+ }
+ else {
+ fprintf(stderr,"Couldn't open file: %s\n", file);
+ return;
+ }
+
+
+ // Check whether Tigermap has been selected. If so, run off to
+ // another routine to service this request.
+ //
+ if (tigerserver_flag) {
+
+#ifdef HAVE_MAGICK
+
+ // We need to send the "nocache" parameter to this function
+ // for those instances when the tigermap received is bad.
+ // Later the GUI can implement a method for refreshing the
+ // latest map and replacing the bad map in the cache.
+ //
+ draw_tiger_map(w, filenm, destination_pixmap, nocache);
+
+#endif // HAVE_MAGICK
+
+ return;
+ }
+ //
+ // Check whether OpenStreetMap has been selected. If so, run off to
+ // another routine to service this request.
+ //
+ if (OSMserver_flag == 1) {
+
+#ifdef HAVE_MAGICK
+
+ // We need to send the "nocache" parameter to this function
+ // for those instances when the received map is bad.
+ // Later the GUI can implement a method for refreshing the
+ // latest map and replacing the bad map in the cache.
+ //
+ // fileimg is the server URL, if specified.
+ draw_OSM_map(w, filenm, destination_pixmap, fileimg, OSMstyle, nocache);
+
+#endif // HAVE_MAGICK
+
+ return;
+ } else if (OSMserver_flag == 2) {
+#ifdef HAVE_MAGICK
+
+ // fileimg is the server URL, if specified.
+ draw_OSM_tiles(w, filenm, destination_pixmap, fileimg, tileCache, OSMstyle, OSMtileExt);
+
+#endif // HAVE_MAGICK
+
+ return;
+ }
+
+
+
+ // Check whether a WMS server has been selected. If so, run off
+ // to another routine to service this request.
+ //
+ if (WMSserver_flag) {
+
+#ifdef HAVE_MAGICK
+ // Pass the URL in "fileimg"
+ draw_WMS_map(w,
+ filenm,
+ destination_pixmap,
+ fileimg,
+ trans_color_head,
+ nocache); // Don't use cached version if non-zero
+
+#endif // HAVE_MAGICK
+
+ return;
+ }
+
+
+ if (toporama_flag) {
+
+#ifdef HAVE_MAGICK
+ // Pass all of the parameters to it. We'll need to use them
+ // to call draw_geo_image_map() again shortly, after we
+ // fetch the remote .geo file.
+ //
+ draw_toporama_map(w,
+ dir,
+ filenm,
+ alert,
+ alert_color,
+ destination_pixmap,
+ mdf,
+ toporama_flag);
+#endif // HAVE_MAGICK
+
+ return;
+ }
+
+
+
+// DK7IN: I'm experimenting with the adjustment of topo maps with
+// Transverse Mercator projection. Those maps have equal scaling
+// in distance while we use equal scaling in degrees.
+
+// For now I use the map center as central meridian (I think that
+// is ok for mapblast), that will change with UTM and Gauss-Krueger
+
+// I have introduced new entries in the geo file for that...
+// I first adjust the x scaling depending on the latitude
+// Then I move points in y direction depending on the offset from
+// the central meridian. I hope I get that right with those
+// approximations. I have the correct formulas, but that will
+// be very computing intensive and result in slow map loading...
+
+// if (geo_datum[0] != '\0')
+// fprintf(stderr,"Map Datum: %s\n",geo_datum); // not used now...
+
+ if (geo_projection[0] == '\0')
+ // default
+ xastir_snprintf(geo_projection,
+ sizeof(geo_projection),
+ "LatLon");
+ //fprintf(stderr,"Map Projection: %s\n",geo_projection);
+ // (void)to_upper(geo_projection);
+ if (strcasecmp(geo_projection,"TM") == 0)
+ map_proj = 1; // Transverse Mercator
+ else
+ map_proj = 0; // Lat/Lon, default
+
+#ifdef HAVE_MAGICK
+ if (terraserver_flag) {
+//http://terraservice.net/download.ashx?t=1&s=10&x=2742&y=26372&z=10&w=820&h=480
+ if (scale_y <= 4) {
+ t_zoom = 10; // 1m/pixel
+ t_scale = 200;
+ }
+ else if (scale_y <= 8) {
+ t_zoom = 11; // 2m/pixel
+ t_scale = 400;
+ }
+ else if (scale_y <= 16) {
+ t_zoom = 12; // 4m/pixel
+ t_scale = 800;
+ }
+ else if (scale_y <= 32) {
+ t_zoom = 13; // 8m/pixel
+ t_scale = 1600;
+ }
+ else if (scale_y <= 64) {
+ t_zoom = 14; // 16m/pixel
+ t_scale = 3200;
+ }
+ else if (scale_y <= 128) {
+ t_zoom = 15; // 32m/pixel
+ t_scale = 6400;
+ }
+ else {
+ t_zoom = 16; // 64m/pixel
+ t_scale = 12800;
+ }
+
+ top = -((NW_corner_latitude - 32400000l) / 360000.0);
+ left = (NW_corner_longitude - 64800000l) / 360000.0;
+ ll_to_utm_ups(gDatum[D_NAD_83_CONUS].ellipsoid,
+ top,
+ left,
+ &top_n,
+ &left_e,
+ zstr0,
+ sizeof(zstr0) );
+ if (1 != sscanf(zstr0, "%d", &z)) {
+ fprintf(stderr,"draw_geo_image_map:sscanf parsing error\n");
+ }
+
+ bottom = -((SE_corner_latitude - 32400000l) / 360000.0);
+ right = (SE_corner_longitude - 64800000l) / 360000.0;
+
+ ll_to_utm_ups(gDatum[D_NAD_83_CONUS].ellipsoid,
+ bottom,
+ right,
+ &bottom_n,
+ &right_e,
+ zstr1,
+ sizeof(zstr1) );
+
+
+//
+// NOTE:
+// POSSIBLE FUTURE ENHANCEMENT:
+// If zstr0 != zstr1, we have a viewscreen that crosses a UTM zone
+// boundary. Terraserver/Toposerver will only feed us a map for one
+// side of it or the other. It'd be VERY nice if some day we could
+// check for this condition and do two map loads instead of the one.
+// We'd need to stop drawing right at the boundary for each map
+// also, so that they'd tile together nicely.
+//
+
+
+ map_top_n = (int)((top_n / t_scale) + 1) * t_scale;
+ map_left_e = (int)((left_e / t_scale) + 0) * t_scale;
+ utm_ups_to_ll(gDatum[D_NAD_83_CONUS].ellipsoid,
+ map_top_n,
+ map_left_e,
+ zstr0,
+ &top,
+ &left);
+
+
+// Below here things can get messed up. We can end up with very
+// large and/or negative values for geo_image_width and/or
+// geo_image_height. Usually happens around UTM zone boundaries.
+//
+// Terraserver uses UTM coordinates for specifying the maps instead
+// of lat/long. Note that we're also not supposed to cross UTM
+// zones in our requests.
+//
+// t = 1 - 4, theme. 1=DOQ (aerial photo)
+// 2=DRG (topo)
+// 3=shaded relief
+// 4=Color photos/Urban areas
+// s = 10 - 16, scale. 10=1 meter/pixel. 11=2 meters/pixel.
+// x = UTM easting, center of image
+// y = UTM northing, center of image
+// z = 1 - 60, UTM zone, center of image
+// w = 50 - 2000, width in pixels
+// h = 50 - 2000, height in pixels
+// logo = 0/1, USGS logo in image if 1
+//
+
+ // This number gets messed up if we cross zones. UTM lines
+ // are slanted, so we _can_ cross zones vertically!
+ geo_image_height = abs(map_top_n - bottom_n) * 200 / t_scale;
+
+ // This number gets messed up if we cross zones
+ geo_image_width = abs(right_e - map_left_e) * 200 / t_scale;
+
+
+//fprintf(stderr,"\ngeo_image_height:%d\tmap_top_n:%0.1f\tbottom_n:%0.1f\tt_scale:%d\n",
+//geo_image_height,
+//map_top_n,
+//bottom_n,
+//t_scale);
+// map_top_n is the one that goes whacko, throwing off the height.
+// Check whether this is because we're crossing a UTM zone. We
+// _can_ cross zones vertically because the UTM lines are slanted.
+
+//fprintf(stderr,"geo_image_width:%d\tright_e:%0.1f\tmap_left_e:%0.1f\tt_scale:%d\n",
+//geo_image_width,
+//right_e,
+//map_left_e,
+//t_scale);
+// right_e is the one that goes whacko, throwing off the width.
+// Check whether this is because we're crossing a UTM zone.
+
+
+ if (geo_image_height < 50)
+ geo_image_height = 50;
+
+ if (geo_image_width < 50)
+ geo_image_width = 50;
+
+ if (geo_image_height > 2000)
+ geo_image_height = geo_image_width;
+
+ if (geo_image_width > 2000)
+ geo_image_width = geo_image_height;
+
+ if (geo_image_height > 2000)
+ geo_image_height = geo_image_width;
+ if (geo_image_width > 2000)
+ geo_image_width = geo_image_height;
+
+
+ map_width = right - left;
+ map_height = top - bottom;
+
+ tp[0].img_x = 0;
+ tp[0].img_y = 0;
+ tp[0].x_long = 64800000l + (360000.0 * left);
+ tp[0].y_lat = 32400000l + (360000.0 * (-top));
+
+ tp[1].img_x = geo_image_width - 1;
+ tp[1].img_y = geo_image_height - 1;
+ tp[1].x_long = 64800000l + (360000.0 * right);
+ tp[1].y_lat = 32400000l + (360000.0 * (-bottom));
+
+ url_n = (int)(top_n / t_scale); // The request URL does not use the
+ url_e = (int)(left_e / t_scale); // N/E of the map corner
+
+
+ xastir_snprintf(fileimg, sizeof(fileimg),
+ "http://terraservice.net/download.ashx?t=%d\046s=%d\046x=%d\046y=%d\046z=%d\046w=%d\046h=%d",
+// "http://terraserver-usa.net/download.ashx?t=%d\046s=%d\046x=%d\046y=%d\046z=%d\046w=%d\046h=%d",
+ terraserver_flag, // 1, 2, 3, or 4
+ t_zoom,
+ url_e, // easting, center of map
+ url_n, // northing, center of map
+ z,
+ geo_image_width,
+ geo_image_height);
+//http://terraservice.net/download.ashx?t=1&s=11&x=1384&y=13274&z=10&w=1215&h=560
+//fprintf(stderr,"%s\n",fileimg);
+
+ if (debug_level & 16) {
+ fprintf(stderr,"URL: %s\n", fileimg);
+ }
+ }
+#endif // HAVE_MAGICK
+
+ //
+ // DK7IN: we should check what we got from the geo file
+ // we use geo_image_width, but it might not be initialised...
+ // and it's wrong if the '\n' is missing at the end...
+
+ /*
+ * Here are the corners of our viewport, using the Xastir
+ * coordinate system. Notice that Y is upside down:
+ *
+ * left edge of view = NW_corner_longitude
+ * right edge of view = SE_corner_longitude
+ * top edge of view = NW_corner_latitude
+ * bottom edge of view = SE_corner_latitude
+ *
+ * The corners of our map will soon be (after translating the
+ * tiepoints to the corners if they're not already there):
+ *
+ * left edge of map = tp[0].x_long in Xastir format
+ * right edge of map = tp[1].x_long
+ * top edge of map = tp[0].y_lat
+ * bottom edge of map = tp[1].y_lat
+ *
+ */
+ map_c_L = tp[0].x_long - NW_corner_longitude; // map left coordinate
+ map_c_T = tp[0].y_lat - NW_corner_latitude; // map top coordinate
+
+ tp_c_dx = (long)(tp[1].x_long - tp[0].x_long);// Width between tiepoints
+ tp_c_dy = (long)(tp[1].y_lat - tp[0].y_lat); // Height between tiepoints
+
+
+ // Check for tiepoints being in wrong relation to one another
+ if (tp_c_dx < 0) tp_c_dx = -tp_c_dx; // New width between tiepoints
+ if (tp_c_dy < 0) tp_c_dy = -tp_c_dy; // New height between tiepoints
+
+
+ if (debug_level & 512) {
+ fprintf(stderr,"X tiepoint width: %ld\n", tp_c_dx);
+ fprintf(stderr,"Y tiepoint width: %ld\n", tp_c_dy);
+ }
+
+ // Calculate step size per pixel
+ map_c_dx = ((double) tp_c_dx / abs(tp[1].img_x - tp[0].img_x));
+ map_c_dy = ((double) tp_c_dy / abs(tp[1].img_y - tp[0].img_y));
+
+ // Scaled screen step size for use with XFillRectangle below
+ scr_dx = (int) (map_c_dx / scale_x) + 1;
+ scr_dy = (int) (map_c_dy / scale_y) + 1;
+
+ if (debug_level & 512) {
+ fprintf(stderr,"\nImage: %s\n", file);
+ fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height);
+ fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y));
+ }
+
+ // calculate top left map corner from tiepoints
+ if (tp[0].img_x != 0) {
+ tp[0].x_long -= (tp[0].img_x * map_c_dx); // map left edge longitude
+ map_c_L = tp[0].x_long - NW_corner_longitude; // delta ??
+ tp[0].img_x = 0;
+ if (debug_level & 512)
+ fprintf(stderr,"Translated tiepoint_0 x: %d\t%lu\n", tp[0].img_x, tp[0].x_long);
+ }
+ if (tp[0].img_y != 0) {
+ tp[0].y_lat -= (tp[0].img_y * map_c_dy); // map top edge latitude
+ map_c_T = tp[0].y_lat - NW_corner_latitude;
+ tp[0].img_y = 0;
+ if (debug_level & 512)
+ fprintf(stderr,"Translated tiepoint_0 y: %d\t%lu\n", tp[0].img_y, tp[0].y_lat);
+ }
+
+ // By this point, geo_image_width & geo_image_height have to
+ // have been initialized to something.
+
+ if ( (geo_image_width == 0) || (geo_image_height == 0) ) {
+
+ if ( (strncasecmp ("http", fileimg, 4) == 0)
+ || (strncasecmp ("ftp", fileimg, 3) == 0)) {
+ // what to do for remote files... hmm... -cbell
+ } else {
+
+#ifdef HAVE_MAGICK
+ GetExceptionInfo(&exception);
+ image_info=CloneImageInfo((ImageInfo *) NULL);
+ xastir_snprintf(image_info->filename,
+ sizeof(image_info->filename),
+ "%s",
+ fileimg);
+ if (debug_level & 16) {
+ fprintf(stderr,"Copied %s into image info.\n", file);
+ fprintf(stderr,"image_info got: %s\n", image_info->filename);
+ fprintf(stderr,"Entered ImageMagick code.\n");
+ fprintf(stderr,"Attempting to open: %s\n", image_info->filename);
+ }
+
+ // We do a test read first to see if the file exists, so we
+ // don't kill Xastir in the ReadImage routine.
+ f = fopen (image_info->filename, "r");
+ if (f == NULL) {
+fprintf(stderr,"1 ");
+ fprintf(stderr,"File %s could not be read\n",image_info->filename);
+
+#ifdef USE_MAP_CACHE
+ // clear from cache if bad
+ if (map_cache_del(fileimg)) {
+ if (debug_level & 512) {
+ fprintf(stderr,"Couldn't delete map from cache\n");
+ }
+ }
+#endif
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+ (void)fclose (f);
+
+ image = PingImage(image_info, &exception);
+
+ if (image == (Image *) NULL) {
+ MagickWarning(exception.severity, exception.reason, exception.description);
+ //fprintf(stderr,"MagickWarning\n");
+
+#ifdef USE_MAP_CACHE
+ // clear from cache if bad
+ if (map_cache_del(fileimg)) {
+ if (debug_level & 512) {
+ fprintf(stderr,"Couldn't delete map from cache\n");
+ }
+ }
+#endif
+
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+ if (debug_level & 16)
+ fprintf(stderr,"Color depth is %i \n", (int)image->depth);
+
+ geo_image_width = image->magick_columns;
+ geo_image_height = image->magick_rows;
+
+ // close and clean up imagemagick
+
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+#endif // HAVE_MAGICK
+ }
+ }
+
+ // fprintf(stderr, "Geo: %s: size %ux%u.\n",file, geo_image_width, geo_image_height);
+ // if that did not generate a valid size, bail out...
+ if ( (geo_image_width == 0) || (geo_image_height == 0) ) {
+ fprintf(stderr,"*** Skipping '%s', IMAGESIZE tag missing or incorrect. ***\n",file);
+ fprintf(stderr,"Perhaps no XPM/ImageMagick/GraphicsMagick library support is installed?\n");
+ return;
+ }
+ // calculate bottom right map corner from tiepoints
+ // map size is geo_image_width / geo_image_height
+ if (tp[1].img_x != (geo_image_width - 1) ) {
+ tp[1].img_x = geo_image_width - 1;
+ tp[1].x_long = tp[0].x_long + (tp[1].img_x * map_c_dx); // right
+ if (debug_level & 512)
+ fprintf(stderr,"Translated tiepoint_1 x: %d\t%lu\n", tp[1].img_x, tp[1].x_long);
+ }
+ if (tp[1].img_y != (geo_image_height - 1) ) {
+ tp[1].img_y = geo_image_height - 1;
+ tp[1].y_lat = tp[0].y_lat + (tp[1].img_y * map_c_dy); // bottom
+ if (debug_level & 512)
+ fprintf(stderr,"Translated tiepoint_1 y: %d\t%lu\n", tp[1].img_y, tp[1].y_lat);
+ }
+
+
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ // We're indexing only. Save the extents in the index.
+ if (terraserver_flag) {
+ // Force the extents to the edges of the earth for the
+ // index file.
+ index_update_xastir(filenm, // Filename only
+ 64800000l, // Bottom
+ 0l, // Top
+ 0l, // Left
+ 129600000l, // Right
+ 0); // Default Map Level
+ }
+ else {
+ index_update_xastir(filenm, // Filename only
+ tp[1].y_lat, // Bottom
+ tp[0].y_lat, // Top
+ tp[0].x_long, // Left
+ tp[1].x_long, // Right
+ 0); // Default Map Level
+ }
+
+ // Update statusline
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ langcode ("BBARSTA039"),
+ short_filenm);
+ statusline(map_it,0); // Loading/Indexing ...
+
+ return; // Done indexing this file
+ }
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ // Check whether map is inside our current view
+ // bottom top left right
+ if (!map_visible (tp[1].y_lat, tp[0].y_lat, tp[0].x_long, tp[1].x_long)) {
+ if (debug_level & 16) {
+ fprintf(stderr,"Map not in current view, skipping: %s\n", file);
+ fprintf(stderr,"\nImage: %s\n", file);
+ fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height);
+ fprintf(stderr," Map: lat0:%ld\t lon0:%ld\t lat1:%ld\t lon1:%ld\n",
+ tp[0].y_lat,
+ tp[0].x_long,
+ tp[1].y_lat,
+ tp[1].x_long);
+ fprintf(stderr,"Screen: NWlat:%ld\tNWlon:%ld\tSElat:%ld\tSElon:%ld\n",
+ NW_corner_latitude,
+ NW_corner_longitude,
+ SE_corner_latitude,
+ SE_corner_longitude);
+ fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y));
+ }
+ return; // Skip this map
+#ifdef FUZZYRASTER
+ } else if (((float)(map_c_dx/scale_x) > rasterfuzz) ||
+ ((float)(scale_x/map_c_dx) > rasterfuzz) ||
+ ((float)(map_c_dy/scale_y) > rasterfuzz) ||
+ ((float)(scale_y/map_c_dy) > rasterfuzz)) {
+ fprintf(stderr,"Skipping fuzzy map %s with sx=%f,sy=%f.\n", file,
+ (float)(map_c_dx/scale_x),(float)(map_c_dy/scale_y));
+ return;
+#endif //FUZZYRASTER
+ } else if (debug_level & 16) {
+ fprintf(stderr,"Loading imagemap: %s\n", file);
+ fprintf(stderr,"\nImage: %s\n", file);
+ fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height);
+ fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y));
+ }
+
+ // Update statusline
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ langcode ("BBARSTA028"),
+ short_filenm);
+ statusline(map_it,0); // Loading/Indexing ...
+
+#ifndef NO_XPM
+ atb.valuemask = 0;
+#endif // NO_XPM
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+// Best here would be to add the process ID or user ID to the filename
+// (to keep the filename distinct for different users), and to check
+// the timestamp on the map file. If it's older than xx minutes, go
+// get another one. Make sure to delete the temp files when closing
+// Xastir. It'd probably be good to check for old files and delete
+// them when starting Xastir as well.
+
+ // Check to see if we have to use "wget" to go get an internet map
+ if ( (strncasecmp ("http", fileimg, 4) == 0)
+ || (strncasecmp ("ftp", fileimg, 3) == 0)
+ || (terraserver_flag) ) {
+#ifdef HAVE_MAGICK
+ char *ext;
+
+ if (debug_level & 16)
+ fprintf(stderr,"ftp or http file: %s\n", fileimg);
+
+ if (terraserver_flag)
+ ext = "jpg";
+ else
+ ext = get_map_ext(fileimg); // Use extension to determine image type
+
+ if (debug_level & 512) {
+ query_start_time=time(&query_start_time);
+ }
+
+#ifdef USE_MAP_CACHE
+
+ if (nocache || map_cache_fetch_disable) {
+
+ // Delete old copy from the cache
+ if (map_cache_fetch_disable && fileimg[0] != '\0') {
+ if (map_cache_del(fileimg)) {
+ if (debug_level & 512) {
+ fprintf(stderr,"Couldn't delete old map from cache\n");
+ }
+ }
+ }
+
+ // Simulate a cache miss
+ map_cache_return = 1;
+ }
+ else {
+ // Look for the file in the cache
+ map_cache_return = map_cache_get(fileimg,local_filename);
+ }
+
+ if (debug_level & 512) {
+ fprintf(stderr,"map_cache_return: %d\n", map_cache_return);
+ }
+
+ // If nocache is non-zero, we're supposed to refresh the map
+ // at intervals. Don't use a cached version of the map in
+ // that case.
+ //
+ if (nocache || map_cache_return != 0 ) {
+
+ // Caching not requested or cached file not found. We
+ // must snag the remote file via libcurl or wget.
+
+ if (nocache) {
+ xastir_snprintf(local_filename,
+ sizeof(local_filename),
+ "%s/map.%s",
+ get_user_base_dir("tmp", temp_file_path, sizeof(temp_file_path)),ext);
+ }
+ else {
+ cache_file_id = map_cache_fileid();
+ xastir_snprintf(local_filename,
+ sizeof(local_filename),
+ "%s/map_%s.%s",
+ get_user_base_dir("map_cache", temp_file_path, sizeof(temp_file_path)),
+ cache_file_id,
+ ext);
+ free(cache_file_id);
+ }
+
+#else // USE_MAP_CACHE
+
+ xastir_snprintf(local_filename,
+ sizeof(local_filename),
+ "%s/map.%s",
+ get_user_base_dir("tmp", temp_file_path, sizeof(temp_file_path)),ext);
+
+#endif // USE_MAP_CACHE
+
+
+ // Erase any previously existing local file by the same
+ // name. This avoids the problem of having an old map image
+ // here and the code trying to display it when the download
+ // fails.
+ unlink( local_filename );
+
+ if (fetch_remote_file(fileimg, local_filename)) {
+ // Had trouble getting the file. Abort.
+ return;
+ }
+
+#ifdef USE_MAP_CACHE
+
+ // Cache the map only if map_refresh_interval_temp is zero
+ if (!map_refresh_interval_temp) {
+ map_cache_put(fileimg,local_filename);
+ }
+
+ } // end if is cached
+#endif // MAP_CACHE
+
+ if (debug_level & 512) {
+ fprintf (stderr, "Fetch or query took %d seconds\n",
+ (int) (time(&query_end_time) - query_start_time));
+ }
+
+ // Set permissions on the file so that any user can overwrite it.
+ chmod(local_filename, 0666);
+
+ // We now re-use the "file" variable. It'll hold the
+ //name of the map file now instead of the .geo file.
+ // Tell ImageMagick where to find it
+ xastir_snprintf(file, sizeof(file), "%s", local_filename);
+#endif // HAVE_MAGICK
+
+ } else {
+ //fprintf(stderr,"Not ftp or http file\n");
+
+ // We now re-use the "file" variable. It'll hold the
+ //name of the map file now instead of the .geo file.
+ xastir_snprintf(file, sizeof(file), "%s", fileimg);
+ }
+
+ //fprintf(stderr,"File = %s\n",file);
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+// The status line is not updated yet, probably 'cuz we're too busy
+// getting the map in this thread and aren't redrawing?
+
+#ifdef HAVE_MAGICK
+ GetExceptionInfo(&exception);
+ image_info=CloneImageInfo((ImageInfo *) NULL);
+ xastir_snprintf(image_info->filename,
+ sizeof(image_info->filename),
+ "%s",
+ file);
+ if (debug_level & 16) {
+ fprintf(stderr,"Copied %s into image info.\n", file);
+ fprintf(stderr,"image_info got: %s\n", image_info->filename);
+ fprintf(stderr,"Entered ImageMagick code.\n");
+ fprintf(stderr,"Attempting to open: %s\n", image_info->filename);
+ }
+
+ // We do a test read first to see if the file exists, so we
+ // don't kill Xastir in the ReadImage routine.
+ f = fopen (image_info->filename, "r");
+ if (f == NULL) {
+fprintf(stderr,"2 ");
+ fprintf(stderr,"File %s could not be read\n",image_info->filename);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+ (void)fclose (f);
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+ image = ReadImage(image_info, &exception);
+
+ if (image == (Image *) NULL) {
+ MagickWarning(exception.severity, exception.reason, exception.description);
+ //fprintf(stderr,"MagickWarning\n");
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+ if (debug_level & 16)
+ fprintf(stderr,"Color depth is %i \n", (int)image->depth);
+
+ if (image->colorspace != RGBColorspace) {
+ fprintf(stderr,"TBD: I don't think we can deal with colorspace != RGB");
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+ width = image->columns;
+ height = image->rows;
+
+ if (check_interrupt(image, image_info,
+ &exception, &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+ // gamma setup
+ if (imagemagick_options.gamma_flag == 0 ||
+ imagemagick_options.gamma_flag == 1) {
+ if (imagemagick_options.gamma_flag == 0) // if not set in file, set to 1.0
+ imagemagick_options.r_gamma = 1.0;
+
+ imagemagick_options.gamma_flag = 1; // set flag to do gamma
+
+ imagemagick_options.r_gamma += imagemagick_gamma_adjust;
+
+ if (imagemagick_options.r_gamma > 0.95 && imagemagick_options.r_gamma < 1.05)
+ imagemagick_options.gamma_flag = 0; // don't bother if near 1.0
+ else if (imagemagick_options.r_gamma < 0.1)
+ imagemagick_options.r_gamma = 0.1; // 0.0 is black and negative is really wacky
+
+ xastir_snprintf(gamma, sizeof(gamma), "%.1f", imagemagick_options.r_gamma);
+ }
+ else if (imagemagick_options.gamma_flag == 3) {
+ // No checking if you specify 3 channel gamma correction, so you can try negative
+ // numbers, etc. if you wish.
+ imagemagick_options.gamma_flag = 1; // set flag to do gamma
+ imagemagick_options.r_gamma += imagemagick_gamma_adjust;
+ imagemagick_options.g_gamma += imagemagick_gamma_adjust;
+ imagemagick_options.b_gamma += imagemagick_gamma_adjust;
+ xastir_snprintf(gamma, sizeof(gamma), "%.1f,%.1f,%.1f",
+ imagemagick_options.r_gamma,
+ imagemagick_options.g_gamma,
+ imagemagick_options.b_gamma);
+ }
+ else
+ imagemagick_options.gamma_flag = 0;
+
+ if (check_interrupt(image, image_info,
+ &exception, &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+ if (imagemagick_options.gamma_flag) {
+ if (debug_level & 16)
+ fprintf(stderr,"gamma=%s\n", gamma);
+ GammaImage(image, gamma);
+ }
+
+ if (check_interrupt(image, image_info,
+ &exception, &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+ if (imagemagick_options.contrast != 0) {
+ if (debug_level & 16)
+ fprintf(stderr,"contrast=%d\n", imagemagick_options.contrast);
+ ContrastImage(image, imagemagick_options.contrast);
+ }
+
+ if (check_interrupt(image, image_info,
+ &exception, &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+ if (imagemagick_options.negate != -1) {
+ if (debug_level & 16)
+ fprintf(stderr,"negate=%d\n", imagemagick_options.negate);
+ NegateImage(image, imagemagick_options.negate);
+ }
+
+ if (check_interrupt(image, image_info,
+ &exception, &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+ if (imagemagick_options.equalize) {
+ if (debug_level & 16)
+ fprintf(stderr,"equalize");
+ EqualizeImage(image);
+ }
+
+ if (check_interrupt(image, image_info,
+ &exception, &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+ if (imagemagick_options.normalize) {
+ if (debug_level & 16)
+ fprintf(stderr,"normalize");
+ NormalizeImage(image);
+ }
+
+ if (check_interrupt(image, image_info,
+ &exception, &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+#if (MagickLibVersion >= 0x0539)
+ if (imagemagick_options.level[0] != '\0') {
+ if (debug_level & 16)
+ fprintf(stderr,"level=%s\n", imagemagick_options.level);
+ LevelImage(image, imagemagick_options.level);
+ }
+#endif // MagickLibVersion >= 0x0539
+
+ if (check_interrupt(image, image_info,
+ &exception, &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+ if (imagemagick_options.modulate[0] != '\0') {
+ if (debug_level & 16)
+ fprintf(stderr,"modulate=%s\n", imagemagick_options.modulate);
+ ModulateImage(image, imagemagick_options.modulate);
+ }
+/*
+ // Else check the menu option for raster intensity
+ else if (raster_map_intensity < 1.0) {
+ char tempstr[30];
+ int temp_i;
+
+ temp_i = (int)(raster_map_intensity * 100.0);
+
+ xastir_snprintf(tempstr,
+ sizeof(tempstr),
+ "%d, 100, 100",
+ temp_i);
+
+//fprintf(stderr,"Modulate: %s\n", tempstr);
+
+ ModulateImage(image, tempstr);
+ }
+*/
+
+ if (check_interrupt(image, image_info,
+ &exception, &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+ // crop image: if we just use CropImage(), then the tiepoints will be off
+ // make border pixels transparent.
+ // cbell - this is a first attempt, it will be integrated into the
+ // lower loops to speed them up...
+ if ( do_crop) {
+ int x, y;
+ // PixelPacket target;
+ register PixelPacket *q;
+
+ // target=GetOnePixel(image,0,0);
+ for (y=0; y < (long) image->rows; y++) {
+ q=GetImagePixels(image,0,y,image->columns,1);
+ if (q == (PixelPacket *) NULL)
+ fprintf(stderr, "GetImagePixels Failed....\n");
+ for (x=0; x < (int) image->columns; x++) {
+ if ( (x < crop_x1) || (x > crop_x2) ||
+ (y < crop_y1) || (y > crop_y2)) {
+ q->opacity=(Quantum) 1;
+ }
+ q++;
+ }
+ if (!SyncImagePixels(image))
+ fprintf(stderr, "SyncImagePixels Failed....\n");
+ }
+ DestroyImagePixels(image);
+ }
+
+ // If were are drawing to a low bpp display (typically < 8bpp)
+ // try to reduce the number of colors in an image.
+ // This may take some time, so it would be best to do ahead of
+ // time if it is a static image.
+#if (MagickLibVersion < 0x0540)
+ if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL) > 128) {
+#else // MagickLib >= 540
+ if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL, &exception) > 128) {
+#endif // MagickLib Version
+
+ if (image->storage_class == PseudoClass) {
+#if (MagickLibVersion < 0x0549)
+ CompressColormap(image); // Remove duplicate colors
+#else // MagickLib >= 0x0549
+ CompressImageColormap(image); // Remove duplicate colors
+#endif // MagickLibVersion < 0x0549
+ }
+
+ // Quantize down to 128 will go here...
+ }
+
+ if (check_interrupt(image, image_info,
+ &exception, &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+ pixel_pack = GetImagePixels(image, 0, 0, image->columns, image->rows);
+ if (!pixel_pack) {
+ fprintf(stderr,"pixel_pack == NULL!!!");
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+ if (check_interrupt(image, image_info,
+ &exception, &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+ index_pack = GetIndexes(image);
+ if (image->storage_class == PseudoClass && !index_pack) {
+ fprintf(stderr,"PseudoClass && index_pack == NULL!!!");
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+ if (check_interrupt(image, image_info,
+ &exception, &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+ if (debug_level & 16)
+#ifdef HAVE_GRAPHICSMAGICK
+ fprintf(stderr,"Colors = %d\n", (int)image->colors);
+#else // HAVE_GRAPHICSMAGICK
+ fprintf(stderr,"Colors = %ld\n", image->colors);
+#endif // HAVE_GRAPHICSMAGICK
+
+ // Set up our own version of the color map.
+ if (image->storage_class == PseudoClass && image->colors <= 256) {
+ for (l = 0; l < (int)image->colors; l++) {
+ int leave_unchanged = 0;
+
+ // Need to check how to do this for ANY image, as ImageMagick can read in all sorts
+ // of image files
+ temp_pack = image->colormap[l];
+ if (debug_level & 16)
+ fprintf(stderr,"Colormap color is %i %i %i \n",
+ temp_pack.red, temp_pack.green, temp_pack.blue);
+
+ // Here's a tricky bit: PixelPacket entries are defined as Quantum's. Quantum
+ // is defined in /usr/include/magick/image.h as either an unsigned short or an
+ // unsigned char, depending on what "configure" decided when ImageMagick was installed.
+ // We can determine which by looking at MaxRGB or QuantumDepth.
+ //
+
+ if (QuantumDepth == 16) { // Defined in /usr/include/magick/magick_config.h
+ if (debug_level & 16)
+ fprintf(stderr,"Color quantum is [0..65535]\n");
+
+ my_colors[l].red = temp_pack.red;
+ my_colors[l].green = temp_pack.green;
+ my_colors[l].blue = temp_pack.blue;
+ }
+ else { // QuantumDepth = 8
+ if (debug_level & 16)
+ fprintf(stderr,"Color quantum is [0..255]\n");
+
+ my_colors[l].red = temp_pack.red << 8;
+ my_colors[l].green = temp_pack.green << 8;
+ my_colors[l].blue = temp_pack.blue << 8;
+ }
+
+ // Take care not to screw up the transparency value by
+ // the raster_map_intensity multiplication factor.
+ if ( trans_color_head ) {
+//fprintf(stderr,"Checking for transparency\n");
+
+ // Get the color allocated on < 8bpp displays. pixel color is written to my_colors.pixel
+ if (visual_type == NOT_TRUE_NOR_DIRECT) {
+// XFreeColors(XtDisplay(w), cmap, &(my_colors[l].pixel),1,0);
+ XAllocColor(XtDisplay(w), cmap, &my_colors[l]);
+ }
+ else {
+ pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue,
+ &my_colors[l].pixel);
+ }
+
+ if (check_trans(my_colors[l],trans_color_head) ) {
+
+ // Found a transparent color. Leave it alone.
+ leave_unchanged++;
+//fprintf(stderr,"Found transparency\n");
+// We never get here!
+ }
+ }
+
+ // Use the map_intensity value if it's not a transparent
+ // color we're dealing with.
+ if (!leave_unchanged) {
+ my_colors[l].red = my_colors[l].red * raster_map_intensity;
+ my_colors[l].green = my_colors[l].green * raster_map_intensity;
+ my_colors[l].blue = my_colors[l].blue * raster_map_intensity;
+ }
+
+
+ // Get the color allocated on < 8bpp displays. pixel color is written to my_colors.pixel
+ if (visual_type == NOT_TRUE_NOR_DIRECT) {
+// XFreeColors(XtDisplay(w), cmap, &(my_colors[l].pixel),1,0);
+ XAllocColor(XtDisplay(w), cmap, &my_colors[l]);
+ }
+ else {
+ pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue,
+ &my_colors[l].pixel);
+ }
+
+ if (debug_level & 16)
+ fprintf(stderr,"Color allocated is %li %i %i %i \n", my_colors[l].pixel,
+ my_colors[l].red, my_colors[l].blue, my_colors[l].green);
+ }
+ }
+
+ if (check_interrupt(image, image_info,
+ &exception, &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+#ifdef TIMING_DEBUG
+ time_mark(0);
+#endif // TIMING_DEBUG
+
+ if (debug_level & 16) {
+ fprintf(stderr,"Image size %d %d\n", width, height);
+#if (MagickLibVersion < 0x0540)
+ fprintf(stderr,"Unique colors = %d\n", GetNumberColors(image, NULL));
+#else // MagickLibVersion < 0x0540
+ fprintf(stderr,"Unique colors = %ld\n", GetNumberColors(image, NULL, &exception));
+#endif // MagickLibVersion < 0x0540
+ fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T,
+ map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y));
+
+ #if (MagickLibVersion < 0x0540)
+ fprintf(stderr,"is Gray Image = %i\n", IsGrayImage(image));
+ fprintf(stderr,"is Monochrome Image = %i\n", IsMonochromeImage(image));
+ //fprintf(stderr,"is Opaque Image = %i\n", IsOpaqueImage(image));
+ //fprintf(stderr,"is PseudoClass = %i\n", image->storage_class == PseudoClass);
+ #else // MagickLibVersion < 0x0540
+ fprintf(stderr,"is Gray Image = %i\n", IsGrayImage( image, &exception ));
+ fprintf(stderr,"is Monochrome Image = %i\n", IsMonochromeImage( image, &exception ));
+ //fprintf(stderr,"is Opaque Image = %i\n", IsOpaqueImage( image, &exception ));
+ //fprintf(stderr,"is PseudoClass = %i\n", image->storage_class == PseudoClass);
+ #endif // MagickLibVersion < 0x0540
+
+ fprintf(stderr,"image matte is %i\n", image->matte);
+ fprintf(stderr,"Colorspace = %i\n", image->colorspace);
+ if (image->colorspace == UndefinedColorspace)
+ fprintf(stderr,"Class Type = Undefined\n");
+ else if (image->colorspace == RGBColorspace)
+ fprintf(stderr,"Class Type = RGBColorspace\n");
+ else if (image->colorspace == GRAYColorspace)
+ fprintf(stderr,"Class Type = GRAYColorspace\n");
+ else if (image->colorspace == sRGBColorspace)
+ fprintf(stderr,"Class Type = sRGBColorspace\n");
+ }
+
+#else // HAVE_MAGICK
+
+ // We don't have ImageMagick libs compiled in, so use the
+ // XPM library instead.
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ // Check whether file has .xpm or .xpm.Z or .xpm.gz at the end.
+ // If not, don't use the XpmReadFileToImage call below.
+
+ if ( !strstr(filenm,"xpm")
+ && !strstr(filenm,"XPM")
+ && !strstr(filenm,"Xpm") ) {
+ fprintf(stderr,
+ "Error: File format not supported by XPM library: %s\n",
+ filenm);
+ return;
+ }
+
+ /* XpmReadFileToImage is the call we wish to avoid if at all
+ * possible. On large images this can take quite a while. We
+ * check above to see whether the image is inside our viewport,
+ * and if not we skip loading the image.
+ */
+ if (! XpmReadFileToImage (XtDisplay (w), file, &xi, NULL, &atb) == XpmSuccess) {
+ fprintf(stderr,"ERROR loading %s\n", file);
+ if (xi)
+ XDestroyImage (xi);
+ return;
+ }
+
+ if (debug_level & 16) {
+ fprintf(stderr,"Image size %d %d\n", (int)atb.width, (int)atb.height);
+ fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n",
+ map_c_L,
+ map_c_T,
+ map_c_dx,
+ (int) (map_c_dx / scale_x),
+ map_c_dy,
+ (int) (map_c_dy / scale_y));
+ }
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ if (xi)
+ XDestroyImage (xi);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ width = atb.width;
+ height = atb.height;
+
+#endif // HAVE_MAGICK
+
+ // draw the image from the file out to the map screen
+
+ // Get the border values for the X and Y for loops used
+ // for the XFillRectangle call later.
+
+ map_c_yc = (tp[0].y_lat + tp[1].y_lat) / 2; // vert center of map as reference
+ map_y_ctr = (long)(height / 2 +0.499);
+ scale_x0 = get_x_scale(0,map_c_yc,scale_y); // reference scaling at vert map center
+
+ map_c_xc = (tp[0].x_long + tp[1].x_long) / 2; // hor center of map as reference
+ map_x_ctr = (long)(width / 2 +0.499);
+ scr_x_mc = (map_c_xc - NW_corner_longitude) / scale_x; // screen coordinates of map center
+
+ // calculate map pixel range in y direction that falls into screen area
+ c_y_max = 0ul;
+ map_y_min = map_y_max = 0l;
+ for (map_y_0 = 0, c_y = tp[0].y_lat; map_y_0 < (long)height; map_y_0++, c_y += map_c_dy) {
+ scr_y = (c_y - NW_corner_latitude) / scale_y; // current screen position
+ if (scr_y > 0) {
+ if (scr_y < screen_height) {
+ map_y_max = map_y_0; // update last map pixel in y
+ c_y_max = (unsigned long)c_y;// bottom map inside screen coordinate
+ } else
+ break; // done, reached bottom screen border
+ } else { // pixel is above screen
+ map_y_min = map_y_0; // update first map pixel in y
+ }
+ }
+// fprintf(stderr,"map top: %ld bottom: %ld\n",tp[0].y_lat,tp[1].y_lat);
+ c_y_min = (unsigned long)(tp[0].y_lat + map_y_min * map_c_dy); // top map inside screen coordinate
+
+// // find the y coordinate nearest to the equator
+// c_y = 90*60*60*100; // Equator
+// if ((c_y_min>c_y && c_y_max>c_y) || (c_y_min<c_y && c_y_max<c_y)) {
+// if (abs(c_y_min-c_y) > abs(c_y_max-c_y))
+// c_y = c_y_max; // north
+// else
+// c_y = c_y_min; // south
+// }
+// scale_x0 = get_x_scale(0,(long)c_y,scale_y); // calc widest map area in x
+
+// if (map_proj != 1) {
+ // calculate map pixel range in x direction that falls into screen area
+ map_x_min = map_x_max = 0l;
+ for (map_x = 0, c_x = tp[0].x_long; map_x < (long)width; map_x++, c_x += map_c_dx) {
+ scr_x = (c_x - NW_corner_longitude)/ scale_x; // current screen position
+ if (scr_x > 0) {
+ if (scr_x < screen_width)
+ map_x_max = map_x; // update last map pixel in x
+ else
+ break; // done, reached right screen border
+ } else { // pixel is left from screen
+ map_x_min = map_x; // update first map pixel in x
+ }
+ }
+ c_x_min = (unsigned long)(tp[0].x_long + map_x_min * map_c_dx); // left map inside screen coordinate
+// }
+// for (scr_y = scr_y_min; scr_y <= scr_y_max;scr_y++) { // screen lines
+// }
+
+ test = 1; // DK7IN: debuging
+ scr_yp = -1;
+ scr_c_xr = SE_corner_longitude;
+ c_dx = map_c_dx; // map pixel width
+ scale_xa = scale_x0; // the compiler likes it ;-)
+
+// for (map_y_0 = 0, c_y = tp[0].y_lat; map_y_0 < (long)height; map_y_0++, c_y += map_c_dy) {
+// scr_y = (c_y - NW_corner_latitude) / scale_y; // current screen position
+
+ map_done = 0;
+ map_act = 0;
+ map_seen = 0;
+ scr_y = screen_height - 1;
+
+#ifdef TIMING_DEBUG
+ time_mark(0);
+#endif // TIMING_DEBUG
+
+
+ if (check_interrupt(
+#ifdef HAVE_MAGICK
+ image, image_info, &exception,
+#else // HAVE_MAGICK
+ xi,
+#endif // HAVE_MAGICK
+ &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+
+ // loop over map pixel rows
+ for (map_y_0 = map_y_min, c_y = (double)c_y_min;
+ (map_y_0 <= map_y_max) || (map_proj == 1 && !map_done && scr_y < screen_height);
+ map_y_0++, c_y += map_c_dy) {
+
+ if (check_interrupt(
+#ifdef HAVE_MAGICK
+ image, image_info, &exception,
+#else // HAVE_MAGICK
+ xi,
+#endif // HAVE_MAGICK
+ &da, &pixmap, &gc, screen_width, screen_height))
+ return;
+
+ scr_y = (c_y - NW_corner_latitude) / scale_y;
+ if (scr_y != scr_yp) { // don't do a row twice
+ scr_yp = scr_y; // remember as previous y
+ if (map_proj == 1) { // Transverse Mercator correction in x
+ scale_xa = get_x_scale(0,(long)c_y,scale_y); // recalc scale_x for current y
+ c_dx = map_c_dx * scale_xa / scale_x0; // adjusted map pixel width
+
+ map_x_min = map_x_ctr - (map_c_xc - NW_corner_longitude) / c_dx;
+ if (map_x_min < 0)
+ map_x_min = 0;
+ c_x_min = map_c_xc - (map_x_ctr - map_x_min) * c_dx;
+ map_x_max = map_x_ctr - (map_c_xc - scr_c_xr) / c_dx;
+ if (map_x_max > (long)width)
+ map_x_max = width;
+ scr_dx = (int) (c_dx / scale_x) + 1; // at least 1 pixel wide
+ }
+
+// if (c_y == (double)c_y_min) { // first call
+// fprintf(stderr,"map: min %ld ctr %ld max %ld, c_dx %ld, c_x_min %ld, c_y_min %ld\n",map_x_min,map_x_ctr,map_x_max,(long)c_dx,c_x_min,c_y_min);
+// }
+ scr_xp = -1;
+ // loop over map pixel columns
+ map_act = 0;
+ scale_x_nm = calc_dscale_x(0,(long)c_y) / 1852.0; // nm per Xastir coordinate
+ for (map_x = map_x_min, c_x = (double)c_x_min; map_x <= map_x_max; map_x++, c_x += c_dx) {
+ scr_x = (c_x - NW_corner_longitude) / scale_x;
+ if (scr_x != scr_xp) { // don't do a pixel twice
+ scr_xp = scr_x; // remember as previous x
+ if (map_proj == 1) { // Transverse Mercator correction in y
+// DK7IN--
+ dist = (90*60 - (c_y / 6000.0)); // equator distance in nm
+ // ?? 180W discontinuity! not done yet
+ ew_ofs = (c_x - (double)map_c_xc) * scale_x_nm; // EW offset from center in nm
+ //corrfact = (map_y_0 - map_y_ctr)/(2*map_y_ctr); // 0..50%
+ //corrfact = fabs(ew_ofs/dist)*3.0;
+ //corrfact = 1.0-1.0*(0.5*map_y_0 / map_y_ctr);
+ corrfact = 1.0;
+ c_y_a = (fabs(dist) - sqrt((double)(dist*dist - ew_ofs*ew_ofs)))*6000.0; // in Xastir units
+ if (dist < 0) // S
+ map_y = map_y_0 + (long)(corrfact*c_y_a / map_c_dy); // coord per pixel
+ else // N
+ map_y = map_y_0 - (long)(corrfact*c_y_a / map_c_dy);
+// if (test < 10) {
+// fprintf(stderr,"dist: %ldkm, ew_ofs: %ldkm, dy: %ldkm\n",(long)(1.852*dist),(long)(1.852*ew_ofs),(long)(1.852*c_y_a/6000.0));
+// fprintf(stderr," corrfact: %f, mapy0: %ld, mapy: %ld\n",corrfact,map_y_0,map_y);
+// test++;
+// }
+ } else {
+ map_y = map_y_0;
+ }
+
+ if (map_y >= 0 && map_y <= tp[1].img_y) { // check map boundaries in y direction
+ map_seen = 1;
+ map_act = 1; // detects blank screen rows (end of map)
+
+// DK7IN--
+
+//----- copy pixel from map to screen ---------------------
+// if (c_y == (double)c_y_min && (scr_x < 5 || (c_x == (double)c_x_min))) { // first call
+// fprintf(stderr,"map: x %ld y %ld scr: x %ld y %ld dx %d, dy %d\n",map_x,map_y,scr_x,scr_y,scr_dx,scr_dy);
+// fprintf(stderr,"color: %ld\n",XGetPixel (xi, map_x, map_y));
+// // 65529
+// }
+
+ // now copy a pixel from the map image to the screen
+#ifdef HAVE_MAGICK
+ l = map_x + map_y * image->columns;
+ trans_skip = 1; // possibly transparent
+ if (image->storage_class == PseudoClass) {
+ if ( trans_color_head &&
+ check_trans(my_colors[index_pack[l]],trans_color_head) ) {
+ trans_skip = 1; // skip it
+ }
+ else {
+ XSetForeground(XtDisplay(w), gc, my_colors[index_pack[l]].pixel);
+ trans_skip = 0; // draw it
+ }
+ } else {
+ // It is not safe to assume that the red/green/blue
+ // elements of pixel_pack of type Quantum are the
+ // same as the red/green/blue of an XColor!
+ if (QuantumDepth==16) {
+ my_colors[0].red=pixel_pack[l].red;
+ my_colors[0].green=pixel_pack[l].green;
+ my_colors[0].blue=pixel_pack[l].blue;
+ }
+ else { // QuantumDepth=8
+ // shift the bits of the 8-bit quantity so that
+ // they become the high bigs of my_colors.*
+ my_colors[0].red=pixel_pack[l].red<<8;
+ my_colors[0].green=pixel_pack[l].green<<8;
+ my_colors[0].blue=pixel_pack[l].blue<<8;
+ }
+ // NOW my_colors has the right r,g,b range for
+ // pack_pixel_bits
+ pack_pixel_bits(my_colors[0].red * raster_map_intensity,
+ my_colors[0].green * raster_map_intensity,
+ my_colors[0].blue * raster_map_intensity,
+ &my_colors[0].pixel);
+ if ( trans_color_head &&
+ check_trans(my_colors[0],trans_color_head) ) {
+ trans_skip = 1; // skip it
+ }
+ else {
+ XSetForeground(XtDisplay(w), gc, my_colors[0].pixel);
+ trans_skip = 0; // draw it
+ }
+ }
+#else // HAVE_MAGICK
+ (void)XSetForeground (XtDisplay (w), gc, XGetPixel (xi, map_x, map_y));
+#endif // HAVE_MAGICK
+
+
+ // Skip drawing if a transparent pixel
+#ifdef HAVE_MAGICK
+ if ( pixel_pack[l].opacity == 0 && !trans_skip ) // skip transparent
+#else // HAVE_MAGICK
+ if (!trans_skip) // skip transparent
+#endif // HAVE_MAGICK
+
+ (void)XFillRectangle (XtDisplay (w),pixmap,gc,scr_x,scr_y,scr_dx,scr_dy);
+ } // check map boundaries in y direction
+ }
+ } // loop over map pixel columns
+ if (map_seen && !map_act)
+ map_done = 1;
+ }
+ } // loop over map pixel rows
+
+#ifdef HAVE_MAGICK
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ #else // HAVE_MAGICK
+ if (xi)
+ XDestroyImage (xi);
+#endif // HAVE_MAGICK
+
+#ifdef TIMING_DEBUG
+ time_mark(0);
+#endif // TIMING_DEBUG
+#endif // NO_GRAPHICS
+}
diff --git a/src/map_gnis.c b/src/map_gnis.c
new file mode 100644
index 0000000..89097fb
--- /dev/null
+++ b/src/map_gnis.c
@@ -0,0 +1,1405 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: map_gnis.c,v 1.41 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <dirent.h>
+#include <netinet/in.h>
+#include <Xm/XmAll.h>
+
+#ifdef HAVE_X11_XPM_H
+#include <X11/xpm.h>
+#ifdef HAVE_LIBXPM // if we have both, prefer the extra library
+#undef HAVE_XM_XPMI_H
+#endif // HAVE_LIBXPM
+#endif // HAVE_X11_XPM_H
+
+#ifdef HAVE_XM_XPMI_H
+#include <Xm/XpmI.h>
+#endif // HAVE_XM_XPMI_H
+
+#include <X11/Xlib.h>
+
+#include <math.h>
+
+#include "xastir.h"
+#include "maps.h"
+#include "alert.h"
+#include "util.h"
+#include "main.h"
+#include "datum.h"
+#include "draw_symbols.h"
+#include "rotated.h"
+#include "color.h"
+#include "xa_config.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+//NOTE: This function has a problem if a non-gnis file is labeled
+//with a ".gnis" extension. It causes a segfault in Xastir. More
+//error checking needs to be done in order to prevent this.
+
+// draw_gnis_map()
+//
+// Allows drawing a background map of labels for the viewport.
+// Example format (old):
+// "WA","Abbey View Memorial Park","cemetery","Snohomish","53","061","474647N","1221650W","47.77972","-122.28056","","","","","420","","Edmonds East"
+//
+// Example format (new):
+// 376016|ID|12th Ave Drain|stream|Canyon|16|027|433107N|1163348W|43.51861|-116.56333||||||||Nampa
+//
+// These types of files are available from http://geonames.usgs.gov/
+// under "Download State Gazetteer Data - Available Via Anonymous FTP".
+// A typical filename would be: "WA_Features_20090401.zip". Do not get the other
+// types of files which are columnar. The files that we parse are
+// pipe-delimited.
+//
+void draw_gnis_map (Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *mdf)
+{
+ char file[MAX_FILENAME]; // Complete path/name of GNIS file
+ char short_filenm[MAX_FILENAME];
+ FILE *f; // Filehandle of GNIS file
+ char line[MAX_FILENAME]; // One line of text from file
+ char *i, *j;
+ char state[50];
+ char name[200];
+ char type[100];
+ char county[100];
+ char latitude[15];
+ char longitude[15];
+ char population[15];
+ char lat_dd[3];
+ char lat_mm[3];
+ char lat_ss[3];
+ char lat_dir[2];
+ char long_dd[4];
+ char long_mm[3];
+ char long_ss[3];
+ char long_dir[2];
+ char lat_str[15];
+ char long_str[15];
+ int temp1;
+ long coord_lon, coord_lat;
+ long min_lat, min_lon, max_lat, max_lon;
+ int ok;
+ long x,y;
+ char symbol_table, symbol_id, symbol_over;
+ unsigned long bottom_extent = 0l;
+ unsigned long top_extent = 0l;
+ unsigned long left_extent = 0l;
+ unsigned long right_extent = 0l;
+ char status_text[MAX_FILENAME];
+ int count = 0;
+
+
+ //fprintf(stderr,"draw_gnis_map starting: %s/%s\n",dir,filenm);
+
+ xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm);
+
+ // Create a shorter filename for display (one that fits the
+ // status line more closely). Subtract the length of the
+ // "Indexing " and/or "Loading " strings as well.
+ if (strlen(filenm) > (41 - 9)) {
+ int avail = 41 - 11;
+ int new_len = strlen(filenm) - avail;
+
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "..%s",
+ &filenm[new_len]);
+ }
+ else {
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "%s",
+ filenm);
+ }
+
+ // Screen view
+ min_lat = SE_corner_latitude;
+ max_lat = NW_corner_latitude;
+ min_lon = NW_corner_longitude;
+ max_lon = SE_corner_longitude;
+
+
+ // The map extents in the map index are checked in draw_map to
+ // see whether we should draw the map at all.
+
+
+ // Update the statusline for this map name
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+ xastir_snprintf(status_text,
+ sizeof(status_text),
+ langcode ("BBARSTA039"),
+ short_filenm);
+ }
+ else {
+ xastir_snprintf(status_text,
+ sizeof(status_text),
+ langcode ("BBARSTA028"),
+ short_filenm);
+ }
+ statusline(status_text,0); // Loading/Indexing ...
+
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+
+/*
+Latest pipe-delimited format from USGS (as of 08/12/2004):
+----------------------------------------------------------
+Feature ID Number (FID)
+State Alpha Code
+Feature Name
+Feature Type
+County Name
+State Number Code (FIPS Code)
+County Number Code (FIPS Code)
+Primary Latitude (DMS)
+Primary Longitude (DMS)
+Primary Latitude (decimal degrees)
+Primary Longitude (decimal degrees)
+Source Latitude (DMS)
+Source Longitude (DMS)
+Source Latitude (decimal degrees)
+Source Longitude (decimal degrees)
+Elevation
+Estimated Population
+Federal Status
+Cell Name
+*/
+
+
+ // Attempt to open the file
+ f = fopen (file, "r");
+ if (f != NULL) {
+ while (!feof (f)) { // Loop through entire file
+ int lat_in_view = 0;
+
+ count++;
+ if ((count % 16) == 0) {
+
+ // Check whether map drawing should be interrupted.
+ // Check every 16 lines.
+ //
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ (void)fclose (f);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+ }
+
+ if ( get_line (f, line, MAX_FILENAME) ) { // Snag one line of data
+
+ // It is common for these lines to have incredible
+ // numbers of spaces at the end, so trim them here.
+ (void)remove_trailing_spaces(line);
+
+ if (strlen(line) > 0) {
+
+ // Default population, in case the field isn't
+ // present in the file.
+ xastir_snprintf(population,sizeof(population),"0");
+
+// Examples of old/new format:
+// 1462331|VA|Abingdon Elementary School|school|Arlington|51|013|385023N|0770546W|38.83972|-77.09611||||||||Alexandria
+// 1462331|VA|Abingdon Elementary School|School|Arlington|51|013|385023N|0770545W|38.8398349|-77.0958117|56|Alexandria
+// 2008 Format follows
+//FEATURE_ID|FEATURE_NAME|FEATURE_CLASS|STATE_ALPHA|STATE_NUMERIC|COUNTY_NAME|COUNTY_NUMERIC|PRIMARY_LAT_DMS|PRIM_LONG_DMS|PRIM_LAT_DEC|PRIM_LONG_DEC|SOURCE_LAT_DMS|SOURCE_LONG_DMS|SOURCE_LAT_DEC|SOURCE_LONG_DEC|ELEVATION|MAP_NAME|DATE_CREATED|DATE_EDITED
+//205110|Appalachian National Scenic Trail|Trail|PA|42|Perry|099|401920N|0770439W|40.3221113|-77.0775473|||||201|Wertzville|09/12/1979|05/19/2008
+
+ //NOTE: We handle running off the end of "line"
+ //via the "continue" statement. Skip the line
+ //if we don't find enough parameters while
+ //parsing.
+
+ // Find end of Feature ID Number field
+ j = index(line,'|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+//NOTE: It'd be nice to take the part after the comma and put it before the rest
+// of the text someday, i.e. "Cassidy, Lake".
+
+ // Find end of Feature Name field
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ i[0] = '\0';
+ xastir_snprintf(name,sizeof(name),"%s",j);
+
+ // Find end of Feature Type field
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ j[0] = '\0';
+ xastir_snprintf(type,sizeof(type),"%s",i);
+
+ // Find end of State field
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ i[0] = '\0';
+ xastir_snprintf(state,sizeof(state),"%s",j);
+
+ // Find end of State Number Code field
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ j[0] = '\0';
+
+ // Find end of County Name field
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ i[0] = '\0';
+ xastir_snprintf(county,sizeof(county),"%s",j);
+
+ // Find end of County Number Code field
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ j[0] = '\0';
+
+// Examples of old/new format:
+// 1462331|VA|Abingdon Elementary School|school|Arlington|51|013|385023N|0770546W|38.83972|-77.09611||||||||Alexandria
+// 1462331|VA|Abingdon Elementary School|School|Arlington|51|013|385023N|0770545W|38.8398349|-77.0958117|56|Alexandria
+
+ // Find end of Primary Latitude field (DDMMSSN)
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ i[0] = '\0';
+ xastir_snprintf(latitude,sizeof(latitude),"%s",j);
+ if (!isdigit((int)latitude[0])) { // skip record if not
+ continue; // numeric! (e.g. "UNKNOWN")
+ }
+
+//WE7U
+ clean_string(latitude);
+
+ // Find end of Primary Longitude field (DDDMMSSW)
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ j[0] = '\0';
+ xastir_snprintf(longitude,sizeof(longitude),"%s",i);
+ if (!isdigit((int)longitude[0])) { // skip record if not
+ continue; // numeric (e.g. UNKNOWN)
+ }
+
+//WE7U
+ clean_string(longitude);
+
+ // Find end of Primary Latitude field (decimal
+ // degrees)
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ i[0] = '\0';
+
+ // Find end of Primary Longitude field (decimal
+ // degrees)
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ j[0] = '\0';
+
+// Examples of old/new format:
+// 1462331|VA|Abingdon Elementary School|school|Arlington|51|013|385023N|0770546W|38.83972|-77.09611||||||||Alexandria
+// 1462331|VA|Abingdon Elementary School|School|Arlington|51|013|385023N|0770545W|38.8398349|-77.0958117|56|Alexandria
+
+ // Find end of Source Latitude field (DMS) (old
+ // format) or elevation (new format)
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ i[0] = '\0';
+
+ // Find end of Source Longitude field (DMS) (old
+ // format) or
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ j[0] = '\0';
+
+ // Find end of Source Latitude field (decimal
+ // degrees)
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ i[0] = '\0';
+
+ // Find end of Source Longitude field (decimal
+ // degrees)
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ j[0] = '\0';
+
+ // Find end of Elevation field
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ i[0] = '\0';
+
+ // Find end of Estimated Population field
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ if ( j != NULL ) {
+ j[0] = '\0';
+ xastir_snprintf(population,sizeof(population),"%s",i);
+ }
+
+FINISH:
+ // There are two more fields (old format),
+ // "Federal Status" and "Cell Name". We ignore
+ // those for now.
+
+ if (strlen(latitude) < 7)
+ continue; // We really don't have any latitude here.
+ lat_dd[0] = latitude[0];
+ lat_dd[1] = latitude[1];
+ lat_dd[2] = '\0';
+
+ lat_mm[0] = latitude[2];
+ lat_mm[1] = latitude[3];
+ lat_mm[2] = '\0';
+
+ lat_ss[0] = latitude[4];
+ lat_ss[1] = latitude[5];
+ lat_ss[2] = '\0';
+
+ lat_dir[0] = latitude[6];
+ lat_dir[1] = '\0';
+
+ // Now must convert from DD MM SS format to DD MM.MM format so that we
+ // can run it through our conversion routine to Xastir coordinates.
+ if (1 != sscanf(lat_ss, "%d", &temp1)) {
+ fprintf(stderr,"draw_gnis_map:sscanf parsing error\n");
+ }
+
+ temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding
+ xastir_snprintf(lat_str, sizeof(lat_str), "%s%s.%02d%s", lat_dd,
+ lat_mm, temp1, lat_dir);
+ coord_lat = convert_lat_s2l(lat_str);
+
+ // Quick test of latitude to see if it's within
+ // our view. If not and we're not doing
+ // indexing, skip this line and go on to the
+ // next.
+ if (coord_lat <= min_lat && coord_lat >= max_lat) {
+ // Latitude is ok
+ lat_in_view++;
+ }
+ else { // Latitude not in current view
+
+ // Check whether we're indexing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+ // Process the line 'cuz we're indexing
+ }
+ else { // Not indexing so skip to the next
+ // line in the file
+ continue;
+ }
+ }
+
+ if (strlen(longitude) < 8)
+ continue; // We really don't have any longitude here.
+ long_dd[0] = longitude[0];
+ long_dd[1] = longitude[1];
+ long_dd[2] = longitude[2];
+ long_dd[3] = '\0';
+
+ long_mm[0] = longitude[3];
+ long_mm[1] = longitude[4];
+ long_mm[2] = '\0';
+
+ long_ss[0] = longitude[5];
+ long_ss[1] = longitude[6];
+ long_ss[2] = '\0';
+
+ long_dir[0] = longitude[7];
+ long_dir[1] = '\0';
+
+ if (1 != sscanf(long_ss, "%d", &temp1)) {
+ fprintf(stderr,"draw_gnis_map:sscanf parsing error\n");
+ }
+
+ temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding
+ xastir_snprintf(long_str, sizeof(long_str), "%s%s.%02d%s", long_dd,
+ long_mm, temp1, long_dir);
+ coord_lon = convert_lon_s2l(long_str);
+
+
+ // Check whether we're indexing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ // Save the min/max extents of the file. We
+ // should really initially set the extents
+ // to the min/max for the Xastir coordinate
+ // system, but in practice zeroes should
+ // work just as well.
+ //
+ if ((coord_lat > (long)bottom_extent) || (bottom_extent == 0l))
+ bottom_extent = coord_lat;
+ if ((coord_lat < (long)top_extent) || (top_extent == 0l))
+ top_extent = coord_lat;
+ if ((coord_lon < (long)left_extent) || (left_extent == 0l))
+ left_extent = coord_lon;
+ if ((coord_lon > (long)right_extent) || (right_extent == 0l))
+ right_extent = coord_lon;
+ }
+ // Now check whether this lat/lon is within our viewport. If it
+ // is, draw a text label at that location.
+ else if (coord_lon >= min_lon && coord_lon <= max_lon
+ && lat_in_view) {
+
+ clean_string(state);
+ clean_string(name);
+ clean_string(type);
+ clean_string(county);
+ clean_string(population);
+
+ if (debug_level & 16) {
+ fprintf(stderr,"%s\t%s\t%s\t%s\t%s\t%s\t\t",
+ state, name, type, county, latitude, longitude);
+ fprintf(stderr,"%s %s %s %s\t%s %s %s %s\t\t",
+ lat_dd, lat_mm, lat_ss, lat_dir, long_dd, long_mm, long_ss, long_dir);
+ fprintf(stderr,"%s\t%s\n", lat_str, long_str);
+ }
+
+ // Convert to screen coordinates. Careful
+ // here! The format conversions you'll need
+ // if you try to compress this into two
+ // lines will get you into trouble.
+ x = coord_lon - NW_corner_longitude;
+ y = coord_lat - NW_corner_latitude;
+ x /= scale_x;
+ y /= scale_y;
+
+ ok = 1;
+
+ /* set default symbol */
+ symbol_table = '/';
+ symbol_id = '.'; /* small x */
+ symbol_over = ' ';
+
+ if (strcasecmp(type,"airport") == 0) {
+ symbol_id = '^';
+ if (scale_y > 100)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"arch") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"area") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"arroyo") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"bar") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"basin") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"bay") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"beach") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"bench") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"bend") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"bridge") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"building") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"canal") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"cape") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"cave") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"cemetery") == 0) {
+ symbol_table = '\\';
+ symbol_id = '+';
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"census") == 0) {
+ /* if (scale_y > 50)*/ /* Census divisions */
+ ok = 0;
+ }
+ else if (strcasecmp(type,"channel") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"church") == 0) {
+ symbol_table = '\\';
+ symbol_id = '+';
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"civil") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"cliff") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"crater") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"crossing") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"dam") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"falls") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"flat") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"forest") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"gap") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"geyser") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"glacier") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"gut") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"harbor") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"hospital") == 0) {
+ symbol_id = 'h';
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"island") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"isthmus") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"lake") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"lava") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"levee") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"locale") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"military") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"mine") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"oilfield") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"other") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"park") == 0) {
+ symbol_table = '\\';
+ symbol_id = ';';
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"pillar") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"plain") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"po") == 0) {
+ symbol_id = ']';
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"ppl") == 0) {
+ symbol_id = '/';
+ if (scale_y > 20000) // Don't draw cities at zoom higher than 20,000
+ ok = 0;
+ else if (scale_y > 4000) { // Don't draw cities of less than 20,000
+ if (atoi(population) < 50000) {
+ ok = 0;
+ }
+ }
+ else if (scale_y > 1500) { // Don't draw cities of less than 10,000
+ if (atoi(population) < 20000) {
+ ok = 0;
+ }
+ }
+ else if (scale_y > 750) { // Don't draw cities of less than 5,000
+ if (atoi(population) < 10000) {
+ ok = 0;
+ }
+ }
+ else if (scale_y > 200) { // Don't draw cities
+ // of less than 1,000
+ if (atoi(population) < 1000) {
+ ok = 0;
+ //fprintf(stderr,
+ // "Name: %s\tPopulation: %s\n",name,
+ // population);
+ }
+ }
+ }
+ else if (strcasecmp(type,"range") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"rapids") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"reserve") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"reservoir") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"ridge") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"school") == 0) {
+ symbol_id = 'K';
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"sea") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"slope") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"spring") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"stream") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"summit") == 0) {
+ if (scale_y > 100)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"swamp") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"trail") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"tower") == 0) {
+ symbol_id = 'r';
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"tunnel") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"valley") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"well") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"woods") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"ruin") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else {
+ fprintf(stderr,"Something unusual found, Type:%s\tState:%s\tCounty:%s\tName:%s\n",
+ type,state,county,name);
+ }
+
+ if (ok == 1) { // If ok to draw it
+ symbol(w, 0, symbol_table, symbol_id, symbol_over, pixmap, 1, x-10, y-10, ' ');
+ draw_nice_string(w, pixmap, 0, x+10, y+5, (char*)name, 0xf, 0x10, strlen(name));
+ }
+
+ }
+ else {
+ //fprintf(stderr,"Not in viewport. Coordinates: %ld %ld\n",coord_lat,coord_lon);
+ //fprintf(stderr,"Min/Max Lat: %ld %ld\n",min_lat,max_lat);
+ //fprintf(stderr,"Min/Max Lon: %ld %ld\n",min_lon,max_lon);
+ }
+ }
+ }
+ } // End of while
+ (void)fclose (f);
+
+
+ // Check whether we're indexing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ // We're indexing only. Save the extents in the index.
+ index_update_xastir(filenm, // Filename only
+ bottom_extent, // Bottom
+ top_extent, // Top
+ left_extent, // Left
+ right_extent, // Right
+ 99999); // Default Map Level
+ }
+ }
+ else {
+ fprintf(stderr,"Couldn't open file: %s\n", file);
+ return;
+ }
+ if (debug_level & 16)
+ fprintf(stderr,"Exiting draw_gnis_map\n");
+}
+
+
+
+
+
+// Search for a placename among GNIS files
+//
+// We need to search a file in the map directory that has the filename
+// STATE.gis, where STATE is from the "state" variable passed to us.
+// Search for the placename/county/state/type that the user requested.
+// Once found, center the map on that location or bring up a response
+// dialog that asks whether one wants to go there, and that dialog
+// provides info about the place found, with a possible selection
+// out of a list of matches.
+// Might also need to place a label at that position on the map in
+// case that GNIS file isn't currently selected.
+//
+int gnis_locate_place( Widget w,
+ char *name_in,
+ char *state_in,
+ char *county_in,
+ char *quad_in,
+ char *type_in,
+ char *filename_in,
+ int follow_case,
+ int get_match,
+ char match_array_name[50][200],
+ long match_array_lat[50],
+ long match_array_long[50] ) {
+
+ char file[MAX_FILENAME]; // Complete path/name of GNIS file
+ FILE *f; // Filehandle of GNIS file
+ char line[MAX_FILENAME]; // One line of text from file
+ char *i, *j;
+ char state[50];
+ char state_in2[50];
+ char name[200];
+ char name_in2[50];
+ char type[100];
+ char type_in2[50];
+ char county[100];
+ char county_in2[50];
+ char quad[100];
+ char quad_in2[100];
+ char latitude[15];
+ char longitude[15];
+ char population[15];
+ char lat_dd[3];
+ char lat_mm[3];
+ char lat_ss[3];
+ char lat_dir[2];
+ char long_dd[4];
+ char long_mm[3];
+ char long_ss[3];
+ char long_dir[2];
+ char lat_str[15];
+ char long_str[15];
+ int temp1;
+ long coord_lon, coord_lat;
+ int ok;
+ struct stat file_status;
+ int my_count = 0;
+
+
+ xastir_snprintf(file,sizeof(file),"%s",filename_in);
+
+ if (debug_level & 16)
+ fprintf(stderr,"File: %s\n",file);
+
+
+ xastir_snprintf(name_in2,sizeof(name_in2),"%s",name_in);
+ xastir_snprintf(state_in2,sizeof(state_in2),"%s",state_in);
+ xastir_snprintf(county_in2,sizeof(county_in2),"%s",county_in);
+ xastir_snprintf(quad_in2,sizeof(quad_in2),"%s",quad_in);
+ xastir_snprintf(type_in2,sizeof(type_in2),"%s",type_in);
+
+
+ // Convert State/Province to upper-case always (they're
+ // always upper-case in the GNIS files from USGS.
+ to_upper(state_in2);
+
+
+ if (debug_level & 16)
+ fprintf(stderr,"Name:%s\tState:%s\tCounty:%s\tQuad:%s\tType:%s\n",
+ name_in,state_in2,county_in,quad_in,type_in);
+
+
+ // If "Match Case" togglebutton is not set, convert the
+ // rest of the keys to upper-case.
+ if (!follow_case) {
+ to_upper(name_in2);
+ to_upper(county_in2);
+ to_upper(quad_in2);
+ to_upper(type_in2);
+ }
+
+
+ // Check status of the file
+ if (stat(file, &file_status) < 0) {
+ // "Can't open file"
+ popup_message( langcode("POPEM00028"), filename_in );
+ return(0);
+ }
+ // Check for regular file
+ if (!S_ISREG(file_status.st_mode)) {
+ // "Can't open file"
+ popup_message( langcode("POPEM00028"), filename_in );
+ return(0);
+ }
+ // Attempt to open the file
+ f = fopen (file, "r");
+ if (f == NULL) {
+ // "Can't open file"
+ popup_message_always( langcode("POPEM00028"), filename_in );
+ return(0);
+ }
+
+ while (!feof (f)) { // Loop through entire file
+ if ( get_line (f, line, MAX_FILENAME) ) { // Snag one line of data
+ if (strlen(line) > 0) {
+
+
+//NOTE: How do we handle running off the end of "line" while using "index"?
+// Short lines here can cause segfaults.
+
+ // Find end of Feature ID Number field
+ j = index(line,'|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+//NOTE: It'd be nice to take the part after the comma and put it before the rest
+// of the text someday, i.e. "Cassidy, Lake".
+
+ // Find end of Feature Name field
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+ xastir_snprintf(name,sizeof(name),"%s",j);
+ clean_string(name);
+
+ // Find end of Feature Type field
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+ xastir_snprintf(type,sizeof(type),"%s",i);
+ clean_string(type);
+
+ // Find end of State field
+ i = index(++j,'|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+ xastir_snprintf(state,sizeof(state),"%s",j);
+ clean_string(state);
+
+ // Find end of State Number Code field
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+
+ // Find end of County Name field
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+ xastir_snprintf(county,sizeof(county),"%s",j);
+ clean_string(county);
+
+ // Find end of County Number Code field
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+
+ // Find end of Primary Latitude field (DDMMSSN)
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+ xastir_snprintf(latitude,sizeof(latitude),"%s",j);
+ clean_string(latitude);
+
+ // Find end of Primary Longitude field (DDDMMSSW)
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+ xastir_snprintf(longitude,sizeof(longitude),"%s",i);
+ clean_string(longitude);
+
+ // Find end of Primary Latitude field (decimal
+ // degrees)
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+
+ // Find end of Primary Longitude field (decimal
+ // degrees)
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+
+ // Find end of Source Latitude field (DMS)
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+
+ // Find end of Source Longitude (DMS)
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+
+ // Find end of Source Latitude field (decimal
+ // degrees)
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+
+ // Find end of Source Longitude field (decimal
+ // degrees)
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+
+ // Find end of Estimated Population field
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+
+ xastir_snprintf(population,sizeof(population),"%s",j);
+ clean_string(population);
+
+ // Find end of Quad field
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+
+ xastir_snprintf(quad,sizeof(quad),"%s",i);
+ clean_string(quad);
+
+ // If "Match Case" togglebutton is not set, convert
+ // the data to upper-case before we do our compare.
+ if (!follow_case) {
+ to_upper(name);
+ to_upper(state);
+ to_upper(county);
+ to_upper(quad);
+ to_upper(type);
+ }
+
+// Still need to code for the "Match Exact" togglebutton.
+
+
+ // Now compare the input variables with those we've
+ // parsed. If a match, bring up a list of items which
+ // match.
+ //
+ ok = 1;
+ if (get_match) { // Looking for exact match
+ if (name_in2[0] != '\0')
+ if (strcmp(name,name_in2) != 0)
+ ok = 0;
+ if (state_in2[0] != '\0')
+ if (strcmp(state,state_in2) != 0)
+ ok = 0;
+ if (county_in2[0] != '\0')
+ if (strcmp(county,county_in2) != 0)
+ ok = 0;
+ if (quad_in2[0] != '\0')
+ if (strcmp(quad,quad_in2) != 0)
+ ok = 0;
+ if (type_in2[0] != '\0')
+ if (strcmp(type,type_in2) != 0)
+ ok = 0;
+ }
+ else { // Look for substring in file, not exact match
+ if (name_in2[0] != '\0')
+ if (strstr(name,name_in2) == NULL)
+ ok = 0;
+ if (state_in2[0] != '\0')
+ if (strstr(state,state_in2) == NULL)
+ ok = 0;
+ if (county_in2[0] != '\0')
+ if (strstr(county,county_in2) == NULL)
+ ok = 0;
+ if (quad_in2[0] != '\0')
+ if (strstr(quad,quad_in2) == NULL)
+ ok = 0;
+ if (type_in2[0] != '\0')
+ if (strstr(type,type_in2) == NULL)
+ ok = 0;
+ }
+
+
+ if (ok) {
+ if (debug_level & 16)
+ fprintf(stderr,"Match: %s,%s,%s,%s\n",name,state,county,type);
+
+// This one pops up the names of whatever we found.
+// "Found It!"
+//popup_message_always( langcode("POPEM00029"), name );
+
+ if (strlen(latitude) < 7)
+ continue; // We really don't have any latitude here.
+ lat_dd[0] = latitude[0];
+ lat_dd[1] = latitude[1];
+ lat_dd[2] = '\0';
+
+ lat_mm[0] = latitude[2];
+ lat_mm[1] = latitude[3];
+ lat_mm[2] = '\0';
+
+ lat_ss[0] = latitude[4];
+ lat_ss[1] = latitude[5];
+ lat_ss[2] = '\0';
+
+ lat_dir[0] = latitude[6];
+ lat_dir[1] = '\0';
+
+ if (strlen(longitude) < 8)
+ continue; // We really don't have any longitude here.
+ long_dd[0] = longitude[0];
+ long_dd[1] = longitude[1];
+ long_dd[2] = longitude[2];
+ long_dd[3] = '\0';
+
+ long_mm[0] = longitude[3];
+ long_mm[1] = longitude[4];
+ long_mm[2] = '\0';
+
+ long_ss[0] = longitude[5];
+ long_ss[1] = longitude[6];
+ long_ss[2] = '\0';
+
+ long_dir[0] = longitude[7];
+ long_dir[1] = '\0';
+
+ // Now must convert from DD MM SS format to DD MM.MM format so that we
+ // can run it through our conversion routine to Xastir coordinates.
+ if (1 != sscanf(lat_ss, "%d", &temp1)) {
+ fprintf(stderr,"locate_place:sscanf parsing error\n");
+ }
+
+ temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding
+ xastir_snprintf(lat_str, sizeof(lat_str), "%s%s.%02d%s", lat_dd,
+ lat_mm, temp1, lat_dir);
+ coord_lat = convert_lat_s2l(lat_str);
+
+ if (1 != sscanf(long_ss, "%d", &temp1)) {
+ fprintf(stderr,"locate_place:sscanf parsing error\n");
+ }
+
+ temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding
+ xastir_snprintf(long_str, sizeof(long_str), "%s%s.%02d%s", long_dd,
+ long_mm, temp1, long_dir);
+ coord_lon = convert_lon_s2l(long_str);
+
+
+//set_map_position(w, coord_lat, coord_lon);
+
+ // Fill in the array values with what we just
+ // found, increment the counter.
+ xastir_snprintf(match_array_name[my_count],200,"%s",name);
+ match_array_lat[my_count] = coord_lat;
+ match_array_long[my_count] = coord_lon;
+ my_count++;
+
+ // Check for a max array. Return if it is full.
+ if (my_count > 50) {
+ return(50);
+ }
+ }
+ }
+ }
+ }
+
+ return(my_count);
+}
+
+
diff --git a/src/map_pdb.c b/src/map_pdb.c
new file mode 100644
index 0000000..ee156d4
--- /dev/null
+++ b/src/map_pdb.c
@@ -0,0 +1,585 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: map_pdb.c,v 1.24 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <dirent.h>
+#include <netinet/in.h>
+#include <Xm/XmAll.h>
+
+#ifdef HAVE_X11_XPM_H
+#include <X11/xpm.h>
+#ifdef HAVE_LIBXPM // if we have both, prefer the extra library
+#undef HAVE_XM_XPMI_H
+#endif // HAVE_LIBXPM
+#endif // HAVE_X11_XPM_H
+
+#ifdef HAVE_XM_XPMI_H
+#include <Xm/XpmI.h>
+#endif // HAVE_XM_XPMI_H
+
+#include <X11/Xlib.h>
+
+#include <math.h>
+
+#include "xastir.h"
+#include "maps.h"
+#include "alert.h"
+#include "util.h"
+#include "main.h"
+#include "datum.h"
+#include "draw_symbols.h"
+#include "rotated.h"
+#include "color.h"
+#include "xa_config.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+#define DOS_HDR_LINES 8
+#define GRID_MORE 5000
+
+
+// Note: There are long's in the pdb_hdr that are not being used.
+// If they were, the ntohl() function would need to be used in order
+// to make sure they were represented correctly on big-endian and
+// little-endian machines. Same goes for short's, make sure ntohs()
+// is used in all cases.
+//
+// Also Note: It looks like all the values in the data structures are
+// unsigned, we may have to explicitly define the long's as well. -KD6ZWR
+//
+void draw_palm_image_map(Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *mdf) {
+
+// Do NOT change any of these structs. They have to match the
+// structs that the palm maps were made with.
+#pragma pack(1)
+ struct {
+ char name[32];
+ short file_attributes;
+ short version; // 2: No placeholder bytes in file, 3: w/bytes
+ long creation_date;
+ long modification_date;
+ long backup_date;
+ long modification_number;
+ long app_info;
+ long sort_info;
+ char database_type[4];
+ char creator_type[4];
+ long unique_id_seed;
+ long next_record_list;
+ short number_of_records;
+ } pdb_hdr;
+
+ struct {
+ long record_data_offset;
+ char category;
+ char id[3];
+ } prl;
+
+ // Two placeholder bytes where were added in version 3. We
+ // skip these below automatically using the fseek calls and the
+ // record offsets.
+ //struct {
+ // short placeholder;
+ //} pdb_ph;
+
+ struct {
+ long left_bounds;
+ long right_bounds;
+ long top_bounds;
+ long bottom_bounds;
+ char menu_name[12];
+ short granularity;
+ char sort_order;
+ char fill[33];
+ } pmf_hdr;
+
+ struct {
+ char type;
+ char sub_type;
+ short minimum_zoom;
+ } record_hdr;
+
+ struct {
+ unsigned short next_vector;
+ unsigned short left_bounds;
+ unsigned short right_bounds;
+ unsigned short top_bounds;
+ unsigned short bottom_bounds;
+ unsigned short line_start_x;
+ unsigned short line_start_y;
+ } vector_hdr;
+
+ struct {
+ unsigned char next_x;
+ unsigned char next_y;
+ } vector_point;
+
+ struct {
+ unsigned short next_label;
+ unsigned short start_x;
+ unsigned short start_y;
+ char symbol_set;
+ char symbol_char;
+ char color;
+ char treatment;
+ short fill;
+ char text[20];
+ } label_record;
+
+ FILE *fn;
+ char filename[MAX_FILENAME];
+ char short_filenm[MAX_FILENAME];
+ int records, record_count, count;
+ int scale;
+ long map_left, map_right, map_top, map_bottom, max_x, max_y;
+ long record_ptr;
+ long line_x, line_y;
+ int vector;
+ char status_text[MAX_FILENAME];
+ int draw_filled;
+
+ draw_filled = mdf->draw_filled;
+
+ xastir_snprintf(filename, sizeof(filename), "%s/%s", dir, filenm);
+
+ // Create a shorter filename for display (one that fits the
+ // status line more closely). Subtract the length of the
+ // "Indexing " and/or "Loading " strings as well.
+ if (strlen(filenm) > (41 - 9)) {
+ int avail = 41 - 11;
+ int new_len = strlen(filenm) - avail;
+
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "..%s",
+ &filenm[new_len]);
+ }
+ else {
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "%s",
+ filenm);
+ }
+
+ if ((fn = fopen(filename, "r")) == NULL) {
+ fprintf(stderr,"Couldn't open file: %s\n", filename);
+ return;
+ }
+
+ if (debug_level & 512)
+ fprintf(stderr,"opened file: %s\n", filename);
+
+ fread(&pdb_hdr, sizeof(pdb_hdr), 1, fn);
+
+ if (strncmp(pdb_hdr.database_type, "map1", 4) != 0
+ || strncmp(pdb_hdr.creator_type, "pAPR", 4) != 0) {
+ fprintf(stderr,"Not Palm OS Map: %s\n", filename);
+ fclose(fn);
+ return;
+ }
+
+ records = ntohs(pdb_hdr.number_of_records);
+
+ fread(&prl, sizeof(prl), 1, fn);
+
+ if (debug_level & 512) {
+ fprintf(stderr,"Palm Map: %s, %d records, offset: %8x\n",
+ pdb_hdr.name,
+ records,
+ (unsigned int)ntohl(prl.record_data_offset));
+ }
+
+ // Save the current pointer into the file
+ record_ptr = (long)ftell(fn);
+ // record_ptr should now be point to the next record list in
+ // the sequence (if there is another one).
+
+ // Point to the map file header corresponding to the record
+ // list we just read in & snag it.
+ fseek(fn, ntohl(prl.record_data_offset), SEEK_SET);
+ fread(&pmf_hdr, sizeof(pmf_hdr), 1, fn);
+
+ scale = ntohs(pmf_hdr.granularity);
+ map_left = ntohl(pmf_hdr.left_bounds);
+ map_right = ntohl(pmf_hdr.right_bounds);
+ map_top = ntohl(pmf_hdr.top_bounds);
+ map_bottom = ntohl(pmf_hdr.bottom_bounds);
+
+ if (debug_level & 512) {
+ fprintf(stderr,"\tLeft %ld, Right %ld, Top %ld, Bottom %ld, %s, Scale %d, %d\n",
+ map_left,
+ map_right,
+ map_top,
+ map_bottom,
+ pmf_hdr.menu_name,
+ scale,
+ pmf_hdr.sort_order);
+ }
+
+ // DNN: multipy by 10; pocketAPRS corners in tenths of seconds,
+ // internal map in hundredths of seconds (was "scale" which was wrong,
+ // scale is not used for the map corners)
+ // Multipy now so we don't have to do it for every use below...
+ map_left *= 10;
+ map_right *= 10;
+ map_top *= 10;
+ map_bottom *= 10;
+
+
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ // We're indexing only. Save the extents in the index.
+ index_update_xastir(filenm, // Filename only
+ map_bottom, // Bottom
+ map_top, // Top
+ map_left, // Left
+ map_right, // Right
+ 1000); // Default Map Level
+
+ fclose(fn);
+
+ // Update the statusline for this map name.
+ xastir_snprintf(status_text,
+ sizeof(status_text),
+ langcode ("BBARSTA039"),
+ short_filenm);
+ statusline(status_text,0); // Loading/Indexing ...
+
+ return; // Done indexing this file
+ }
+
+
+ if (!map_onscreen(map_left, map_right, map_top, map_bottom, 1)) {
+ fclose(fn);
+ return;
+ }
+
+
+ // Update the statusline for this map name
+ xastir_snprintf(status_text,
+ sizeof(status_text),
+ langcode ("BBARSTA028"),
+ short_filenm);
+ statusline(status_text,0); // Loading/Indexing ...
+
+
+ max_x = (long)(screen_width + MAX_OUTBOUND);
+ max_y = (long)(screen_height + MAX_OUTBOUND);
+
+
+ /* read vectors */
+ for (record_count = 2; record_count <= records; record_count++) {
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ fclose(fn);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ // Point to the next record list header & snag it
+ fseek(fn, record_ptr, SEEK_SET);
+ fread(&prl, sizeof(prl), 1, fn);
+
+ if (debug_level & 512) {
+ fprintf(stderr,"\tRecord %d, offset: %8x\n",
+ record_count,
+ (unsigned int)ntohl(prl.record_data_offset));
+ }
+
+ // Save a pointer to the next record list header
+ record_ptr = (long)ftell(fn);
+
+ // Point to the next map file header & snag it
+ fseek(fn, ntohl(prl.record_data_offset), SEEK_SET);
+ fread(&record_hdr, sizeof(record_hdr), 1, fn);
+
+ if (debug_level & 512) {
+ fprintf(stderr,"\tType %d, Sub %d, Zoom %d\n",
+ record_hdr.type,
+ record_hdr.sub_type,
+ (unsigned short) ntohs(record_hdr.minimum_zoom));
+ }
+
+ if (record_hdr.type > 0 && record_hdr.type < 16) {
+
+ vector = True;
+
+ while (vector && fread(&vector_hdr, sizeof(vector_hdr), 1, fn)) {
+
+ count = (unsigned short) ntohs(vector_hdr.next_vector);
+
+ if (count && !(count&1)) {
+ line_x = (long)ntohs(vector_hdr.line_start_x);
+ line_y = (long)ntohs(vector_hdr.line_start_y);
+
+ if (debug_level & 512) {
+ fprintf(stderr,"\tvector %d, left %d, right %d, top %d, bottom %d, start x %ld, start y %ld\n",
+ count,
+ (unsigned short) ntohs(vector_hdr.left_bounds),
+ (unsigned short) ntohs(vector_hdr.right_bounds),
+ (unsigned short) ntohs(vector_hdr.top_bounds),
+ (unsigned short) ntohs(vector_hdr.bottom_bounds),
+ line_x,
+ line_y);
+ }
+
+ // DNN: Only line_x and line_y are scaled,
+ // not map_left and map_top
+ map_plot (w,
+ max_x,
+ max_y,
+ map_left + (line_x * scale),
+ map_top + (line_y * scale),
+ record_hdr.type, // becomes the color choice
+ 0,
+ destination_pixmap,
+ draw_filled);
+
+ for (count -= sizeof(vector_hdr); count > 0; count -= sizeof(vector_point)) {
+
+ fread(&vector_point, sizeof(vector_point), 1, fn);
+
+ if ((debug_level & 513) == 513) {
+ fprintf(stderr,"\tnext x %d, next y %d\n",
+ vector_point.next_x,
+ vector_point.next_y);
+ }
+
+ line_x += vector_point.next_x - 127;
+ line_y += vector_point.next_y - 127;
+
+ // DNN: Only line_x and line_y are scaled,
+ // not map_left and map_top
+ map_plot (w,
+ max_x,
+ max_y,
+ map_left + (line_x * scale),
+ map_top + (line_y * scale),
+ record_hdr.type,
+ 0,
+ destination_pixmap,
+ draw_filled);
+ }
+
+ // DNN: Only line_x and line_y are scaled,
+ // not map_left and map_top
+ map_plot (w,
+ max_x,
+ max_y,
+ map_left + (line_x * scale),
+ map_top + (line_y * scale),
+ 0, // Color 0
+ 0,
+ destination_pixmap,
+ draw_filled);
+ }
+ else {
+ vector = False;
+ }
+ }
+ }
+ else if ( (record_hdr.type == 0) // We have a label
+ && map_labels) { // and we wish to draw it
+ long label_x_cord;
+ long label_y_cord;
+ int label_length;
+ int label;
+ long label_mag;
+ long x;
+ long y;
+ int i;
+ int color;
+
+
+ label_mag = (long) ntohs(record_hdr.minimum_zoom);
+
+ // DNN: Multiplication by 4 looks reasonable on the map I
+ // checked, be my guest to come up with a better value...
+ // For the map I used the behaviour mimics the
+ // behaviour on pocketAPRS when the labels show up
+ label_mag *= 4;
+
+ label = True;
+
+ while (label && fread(&label_record, sizeof(label_record), 1, fn)) {
+
+ count = ntohs(label_record.next_label);
+
+ if (count && !(count&1)) {
+ line_x = (long)ntohs(vector_hdr.line_start_x);
+ line_y = (long)ntohs(vector_hdr.line_start_y);
+
+ if (debug_level & 512) {
+ fprintf(stderr,"\t%d, %d, %d, %d, %d, %d, 0x%x, %s\n",
+ ntohs(label_record.next_label),
+ ntohs(label_record.start_x),
+ ntohs(label_record.start_y),
+ label_record.symbol_set,
+ label_record.symbol_char,
+ label_record.color,
+ label_record.treatment,
+ label_record.text);
+ }
+
+ label_x_cord = map_left +
+ (((long) ntohs(label_record.start_x)) * scale);
+ label_y_cord = map_top +
+ (((long) ntohs(label_record.start_y)) * scale);
+
+ // DNN: Skip empty labels
+ if(label_record.text[0] != '\0') {
+ label_record.text[19] = '\0'; // Make sure we have a terminator
+ label_length = (int)strlen (label_record.text);
+
+ for (i = (label_length - 1); i > 0; i--) {
+ if (label_record.text[i] == ' ')
+ label_record.text[i] = '\0';
+ else
+ break;
+ }
+
+ label_length = (int)strlen (label_record.text);
+
+ // DNN: todo: treatment:
+ // bit 7: inverse
+ // bit 6: draw beneath map line data
+ // bit 5,4: 00 = left, 01 = center, 10 = right
+ // bit 3,2,1,0: typeface 0 = normal, 1 = bold,
+ // 2 = large, 3 = extra large
+ //
+ // For now KISS, just put it on the map.
+
+ x = ((label_x_cord - NW_corner_longitude) / scale_x);
+
+ /* examine bits 4 and 5 of treatment */
+ if((label_record.treatment & 0x30) == 0x00) {
+ /* left of coords */
+ x = x - (label_length * 6);
+ }
+ else if((label_record.treatment & 0x30) == 0x10) {
+ /* center */
+ x = x - (label_length * 3);
+ }
+ else {
+ /* right of coords */
+ x = ((label_x_cord - NW_corner_longitude) / scale_x);
+ }
+
+ y = ((label_y_cord - NW_corner_latitude) / scale_y);
+
+ // Color selection
+ switch (label_record.color) {
+ case 0:
+ color = 0x08; // black
+ break;
+ case 1:
+ color = 0x07; // darkgray
+ break;
+ case 2:
+ color = 0x14; // lightgray
+ break;
+ case 3:
+ color = 0x0f; // white
+ break;
+ default:
+ color = 0x08; // black
+ break;
+ }
+
+ if (label_mag > (int)((scale_x) - 1) || label_mag == 0) {
+ if (x > (0) && (x < (int)screen_width)) {
+ if (y > (0) && (y < (int)screen_height)) {
+ draw_rotated_label_text (w,
+ -90.0,
+ x,
+ y,
+ label_length,
+ colors[color],
+ label_record.text,
+ FONT_DEFAULT);
+ }
+ }
+ }
+ }
+ /* Label has a symbol */
+ if(label_record.symbol_char != '\0') {
+ // DNN: Not implemented (yet)
+ }
+ }
+ else {
+ label = False;
+ }
+ } // End of while
+ } // End of else if
+ } // end of for loop
+
+ fclose(fn);
+
+ if (debug_level & 512)
+ fprintf(stderr,"Closed file\n");
+}
diff --git a/src/map_pop.c b/src/map_pop.c
new file mode 100644
index 0000000..9224f3d
--- /dev/null
+++ b/src/map_pop.c
@@ -0,0 +1,1405 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id$
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <dirent.h>
+#include <netinet/in.h>
+#include <Xm/XmAll.h>
+
+#ifdef HAVE_X11_XPM_H
+#include <X11/xpm.h>
+#ifdef HAVE_LIBXPM // if we have both, prefer the extra library
+#undef HAVE_XM_XPMI_H
+#endif // HAVE_LIBXPM
+#endif // HAVE_X11_XPM_H
+
+#ifdef HAVE_XM_XPMI_H
+#include <Xm/XpmI.h>
+#endif // HAVE_XM_XPMI_H
+
+#include <X11/Xlib.h>
+
+#include <math.h>
+
+#include "xastir.h"
+#include "maps.h"
+#include "alert.h"
+#include "util.h"
+#include "main.h"
+#include "datum.h"
+#include "draw_symbols.h"
+#include "rotated.h"
+#include "color.h"
+#include "xa_config.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+//NOTE: This function has a problem if a non-pop file is labeled
+//with a ".pop" extension. It causes a segfault in Xastir. More
+//error checking needs to be done in order to prevent this.
+
+// draw_pop_map()
+//
+// Allows drawing a background map of labels for the viewport.
+// Example format (old):
+// "WA","Abbey View Memorial Park","cemetery","Snohomish","53","061","474647N","1221650W","47.77972","-122.28056","","","","","420","","Edmonds East"
+//
+// Example format (new):
+// 376016|ID|12th Ave Drain|stream|Canyon|16|027|433107N|1163348W|43.51861|-116.56333||||||||Nampa
+//
+// These types of files are available from ftp://aprs.tamu.edu/
+// A typical filename would be: "WA_deci.gz". Do not get the other
+// types of files which are columnar. The files that we parse are
+// pipe-delimited.
+// These files were originally from geonames.usgs.gov but the format changed
+// on that site from population to elevation and the display of populated sites
+// was severly broken by the new format. The population information should be
+// gathered from census.gov or other locations concerned with population mapping.
+//
+void draw_pop_map (Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *mdf)
+{
+ char file[MAX_FILENAME]; // Complete path/name of pop file
+ char short_filenm[MAX_FILENAME];
+ FILE *f; // Filehandle of pop file
+ char line[MAX_FILENAME]; // One line of text from file
+ char *i, *j;
+ char state[50];
+ char name[200];
+ char type[100];
+ char county[100];
+ char latitude[15];
+ char longitude[15];
+ char population[15];
+ char lat_dd[3];
+ char lat_mm[3];
+ char lat_ss[3];
+ char lat_dir[2];
+ char long_dd[4];
+ char long_mm[3];
+ char long_ss[3];
+ char long_dir[2];
+ char lat_str[15];
+ char long_str[15];
+ int temp1;
+ long coord_lon, coord_lat;
+ long min_lat, min_lon, max_lat, max_lon;
+ int ok;
+ long x,y;
+ char symbol_table, symbol_id, symbol_over;
+ unsigned long bottom_extent = 0l;
+ unsigned long top_extent = 0l;
+ unsigned long left_extent = 0l;
+ unsigned long right_extent = 0l;
+ char status_text[MAX_FILENAME];
+ int count = 0;
+
+
+ //fprintf(stderr,"draw_pop_map starting: %s/%s\n",dir,filenm);
+
+ xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm);
+
+ // Create a shorter filename for display (one that fits the
+ // status line more closely). Subtract the length of the
+ // "Indexing " and/or "Loading " strings as well.
+ if (strlen(filenm) > (41 - 9)) {
+ int avail = 41 - 11;
+ int new_len = strlen(filenm) - avail;
+
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "..%s",
+ &filenm[new_len]);
+ }
+ else {
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "%s",
+ filenm);
+ }
+
+ // Screen view
+ min_lat = SE_corner_latitude;
+ max_lat = NW_corner_latitude;
+ min_lon = NW_corner_longitude;
+ max_lon = SE_corner_longitude;
+
+
+ // The map extents in the map index are checked in draw_map to
+ // see whether we should draw the map at all.
+
+
+ // Update the statusline for this map name
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+ xastir_snprintf(status_text,
+ sizeof(status_text),
+ langcode ("BBARSTA039"),
+ short_filenm);
+ }
+ else {
+ xastir_snprintf(status_text,
+ sizeof(status_text),
+ langcode ("BBARSTA028"),
+ short_filenm);
+ }
+ statusline(status_text,0); // Loading/Indexing ...
+
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+
+/*
+Latest pipe-delimited format from USGS (as of 08/12/2004):
+----------------------------------------------------------
+Feature ID Number (FID)
+State Alpha Code
+Feature Name
+Feature Type
+County Name
+State Number Code (FIPS Code)
+County Number Code (FIPS Code)
+Primary Latitude (DMS)
+Primary Longitude (DMS)
+Primary Latitude (decimal degrees)
+Primary Longitude (decimal degrees)
+Source Latitude (DMS)
+Source Longitude (DMS)
+Source Latitude (decimal degrees)
+Source Longitude (decimal degrees)
+Elevation
+Estimated Population
+Federal Status
+Cell Name
+*/
+
+
+ // Attempt to open the file
+ f = fopen (file, "r");
+ if (f != NULL) {
+ while (!feof (f)) { // Loop through entire file
+ int lat_in_view = 0;
+
+ count++;
+ if ((count % 16) == 0) {
+
+ // Check whether map drawing should be interrupted.
+ // Check every 16 lines.
+ //
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ (void)fclose (f);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+ }
+
+ if ( get_line (f, line, MAX_FILENAME) ) { // Snag one line of data
+
+ // It is common for these lines to have incredible
+ // numbers of spaces at the end, so trim them here.
+ (void)remove_trailing_spaces(line);
+
+ if (strlen(line) > 0) {
+
+ // Default population, in case the field isn't
+ // present in the file.
+ xastir_snprintf(population,sizeof(population),"0");
+
+// Examples of old/new format:
+// 1462331|VA|Abingdon Elementary School|school|Arlington|51|013|385023N|0770546W|38.83972|-77.09611||||||||Alexandria
+// 1462331|VA|Abingdon Elementary School|School|Arlington|51|013|385023N|0770545W|38.8398349|-77.0958117|56|Alexandria
+
+ //NOTE: We handle running off the end of "line"
+ //via the "continue" statement. Skip the line
+ //if we don't find enough parameters while
+ //parsing.
+
+ // Find end of Feature ID Number field
+ j = index(line,'|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ // Find end of State field
+ i = index(j+1, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ i[0] = '\0';
+ xastir_snprintf(state,sizeof(state),"%s",j+1);
+
+//NOTE: It'd be nice to take the part after the comma and put it before the rest
+// of the text someday, i.e. "Cassidy, Lake".
+
+ // Find end of Feature Name field
+ j = index(i+1, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ j[0] = '\0';
+ xastir_snprintf(name,sizeof(name),"%s",i+1);
+
+ // Find end of Feature Type field
+ i = index(j+1, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ i[0] = '\0';
+ xastir_snprintf(type,sizeof(type),"%s",j+1);
+
+ // Find end of County Name field
+ j = index(i+1, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ j[0] = '\0';
+ xastir_snprintf(county,sizeof(county),"%s",i+1);
+
+ // Find end of State Number Code field
+ i = index(j+1, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ i[0] = '\0';
+
+ // Find end of County Number Code field
+ j = index(i+1, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ j[0] = '\0';
+
+// Examples of old/new format:
+// 1462331|VA|Abingdon Elementary School|school|Arlington|51|013|385023N|0770546W|38.83972|-77.09611||||||||Alexandria
+// 1462331|VA|Abingdon Elementary School|School|Arlington|51|013|385023N|0770545W|38.8398349|-77.0958117|56|Alexandria
+
+ // Find end of Primary Latitude field (DDMMSSN)
+ i = index(j+1, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ i[0] = '\0';
+ xastir_snprintf(latitude,sizeof(latitude),"%s",j+1);
+ if (!isdigit((int)latitude[0])) { // skip record if not
+ continue; // numeric! (e.g. "UNKNOWN")
+ }
+
+//WE7U
+ clean_string(latitude);
+
+ // Find end of Primary Longitude field (DDDMMSSW)
+ j = index(i+1, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ j[0] = '\0';
+ xastir_snprintf(longitude,sizeof(longitude),"%s",i+1);
+ if (!isdigit((int)longitude[0])) { // skip record if not
+ continue; // numeric (e.g. UNKNOWN)
+ }
+
+//WE7U
+ clean_string(longitude);
+
+ // Find end of Primary Latitude field (decimal
+ // degrees)
+ i = index(j+1, '|');
+
+ if (i == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ i[0] = '\0';
+
+ // Find end of Primary Longitude field (decimal
+ // degrees)
+ j = index(i+1, '|');
+
+ if (j == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ j[0] = '\0';
+
+// Examples of old/new format:
+// 1462331|VA|Abingdon Elementary School|school|Arlington|51|013|385023N|0770546W|38.83972|-77.09611||||||||Alexandria
+// 1462331|VA|Abingdon Elementary School|School|Arlington|51|013|385023N|0770545W|38.8398349|-77.0958117|56|Alexandria
+
+ // Find end of Source Latitude field (DMS) (old
+ // format) or elevation (new format)
+ i = index(j+1, '|');
+
+ if (i == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ i[0] = '\0';
+
+ // Find end of Source Longitude field (DMS) (old
+ // format) or
+ j = index(i+1, '|');
+
+ if (j == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ j[0] = '\0';
+
+ // Find end of Source Latitude field (decimal
+ // degrees)
+ i = index(j+1, '|');
+
+ if (i == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ i[0] = '\0';
+
+ // Find end of Source Longitude field (decimal
+ // degrees)
+ j = index(i+1, '|');
+
+ if (j == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ j[0] = '\0';
+
+ // Find end of Elevation field
+ i = index(j+1, '|');
+
+ if (i == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ i[0] = '\0';
+
+ // Find end of Estimated Population field
+ j = index(i+1, '|');
+
+ if (j == NULL) { // Pipe not found
+ goto FINISH; // We have enough to process now
+ }
+
+ if ( j != NULL ) {
+ j[0] = '\0';
+ xastir_snprintf(population,sizeof(population),"%s",i+1);
+ }
+
+FINISH:
+ // There are two more fields (old format),
+ // "Federal Status" and "Cell Name". We ignore
+ // those for now.
+
+ if (strlen(latitude) < 7)
+ continue; // We really don't have any latitude here!
+ lat_dd[0] = latitude[0];
+ lat_dd[1] = latitude[1];
+ lat_dd[2] = '\0';
+
+ lat_mm[0] = latitude[2];
+ lat_mm[1] = latitude[3];
+ lat_mm[2] = '\0';
+
+ lat_ss[0] = latitude[4];
+ lat_ss[1] = latitude[5];
+ lat_ss[2] = '\0';
+
+ lat_dir[0] = latitude[6];
+ lat_dir[1] = '\0';
+
+ // Now must convert from DD MM SS format to DD MM.MM format so that we
+ // can run it through our conversion routine to Xastir coordinates.
+ if (1 != sscanf(lat_ss, "%d", &temp1)) {
+ fprintf(stderr,"draw_pop_map:sscanf parsing error\n");
+ }
+
+ temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding
+ xastir_snprintf(lat_str, sizeof(lat_str), "%s%s.%02d%s", lat_dd,
+ lat_mm, temp1, lat_dir);
+ coord_lat = convert_lat_s2l(lat_str);
+
+ // Quick test of latitude to see if it's within
+ // our view. If not and we're not doing
+ // indexing, skip this line and go on to the
+ // next.
+ if (coord_lat <= min_lat && coord_lat >= max_lat) {
+ // Latitude is ok
+ lat_in_view++;
+ }
+ else { // Latitude not in current view
+
+ // Check whether we're indexing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+ // Process the line 'cuz we're indexing
+ }
+ else { // Not indexing so skip to the next
+ // line in the file
+ continue;
+ }
+ }
+
+ if (strlen(longitude) < 8)
+ continue; // We really don't have any latitude here!
+ long_dd[0] = longitude[0];
+ long_dd[1] = longitude[1];
+ long_dd[2] = longitude[2];
+ long_dd[3] = '\0';
+
+ long_mm[0] = longitude[3];
+ long_mm[1] = longitude[4];
+ long_mm[2] = '\0';
+
+ long_ss[0] = longitude[5];
+ long_ss[1] = longitude[6];
+ long_ss[2] = '\0';
+
+ long_dir[0] = longitude[7];
+ long_dir[1] = '\0';
+
+ if (1 != sscanf(long_ss, "%d", &temp1)) {
+ fprintf(stderr,"draw_pop_map:sscanf parsing error\n");
+ }
+
+ temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding
+ xastir_snprintf(long_str, sizeof(long_str), "%s%s.%02d%s", long_dd,
+ long_mm, temp1, long_dir);
+ coord_lon = convert_lon_s2l(long_str);
+
+
+ // Check whether we're indexing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ // Save the min/max extents of the file. We
+ // should really initially set the extents
+ // to the min/max for the Xastir coordinate
+ // system, but in practice zeroes should
+ // work just as well.
+ //
+ if ((coord_lat > (long)bottom_extent) || (bottom_extent == 0l))
+ bottom_extent = coord_lat;
+ if ((coord_lat < (long)top_extent) || (top_extent == 0l))
+ top_extent = coord_lat;
+ if ((coord_lon < (long)left_extent) || (left_extent == 0l))
+ left_extent = coord_lon;
+ if ((coord_lon > (long)right_extent) || (right_extent == 0l))
+ right_extent = coord_lon;
+ }
+ // Now check whether this lat/lon is within our viewport. If it
+ // is, draw a text label at that location.
+ else if (coord_lon >= min_lon && coord_lon <= max_lon
+ && lat_in_view) {
+
+ clean_string(state);
+ clean_string(name);
+ clean_string(type);
+ clean_string(county);
+ clean_string(population);
+
+ if (debug_level & 16) {
+ fprintf(stderr,"%s\t%s\t%s\t%s\t%s\t%s\t\t",
+ state, name, type, county, latitude, longitude);
+ fprintf(stderr,"%s %s %s %s\t%s %s %s %s\t\t",
+ lat_dd, lat_mm, lat_ss, lat_dir, long_dd, long_mm, long_ss, long_dir);
+ fprintf(stderr,"%s\t%s\n", lat_str, long_str);
+ }
+
+ // Convert to screen coordinates. Careful
+ // here! The format conversions you'll need
+ // if you try to compress this into two
+ // lines will get you into trouble.
+ x = coord_lon - NW_corner_longitude;
+ y = coord_lat - NW_corner_latitude;
+ x /= scale_x;
+ y /= scale_y;
+
+ ok = 1;
+
+ /* set default symbol */
+ symbol_table = '/';
+ symbol_id = '.'; /* small x */
+ symbol_over = ' ';
+
+ if (strcasecmp(type,"airport") == 0) {
+ symbol_id = '^';
+ if (scale_y > 100)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"arch") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"area") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"arroyo") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"bar") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"basin") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"bay") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"beach") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"bench") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"bend") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"bridge") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"building") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"canal") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"cape") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"cave") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"cemetery") == 0) {
+ symbol_table = '\\';
+ symbol_id = '+';
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"census") == 0) {
+ /* if (scale_y > 50)*/ /* Census divisions */
+ ok = 0;
+ }
+ else if (strcasecmp(type,"channel") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"church") == 0) {
+ symbol_table = '\\';
+ symbol_id = '+';
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"civil") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"cliff") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"crater") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"crossing") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"dam") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"falls") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"flat") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"forest") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"gap") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"geyser") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"glacier") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"gut") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"harbor") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"hospital") == 0) {
+ symbol_id = 'h';
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"island") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"isthmus") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"lake") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"lava") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"levee") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"locale") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"military") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"mine") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"oilfield") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"other") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"park") == 0) {
+ symbol_table = '\\';
+ symbol_id = ';';
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"pillar") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"plain") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"po") == 0) {
+ symbol_id = ']';
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"ppl") == 0) {
+ symbol_id = '/';
+ if (scale_y > 20000) // Don't draw cities at zoom higher than 20,000
+ ok = 0;
+ else if (scale_y > 4000) { // Don't draw cities of less than 20,000
+ if (atoi(population) < 50000) {
+ ok = 0;
+ }
+ }
+ else if (scale_y > 1500) { // Don't draw cities of less than 10,000
+ if (atoi(population) < 20000) {
+ ok = 0;
+ }
+ }
+ else if (scale_y > 750) { // Don't draw cities of less than 5,000
+ if (atoi(population) < 10000) {
+ ok = 0;
+ }
+ }
+ else if (scale_y > 200) { // Don't draw cities
+ // of less than 1,000
+ if (atoi(population) < 1000) {
+ ok = 0;
+ //fprintf(stderr,
+ // "Name: %s\tPopulation: %s\n",name,
+ // population);
+ }
+ }
+ }
+ else if (strcasecmp(type,"range") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"rapids") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"reserve") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"reservoir") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"ridge") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"school") == 0) {
+ symbol_id = 'K';
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"sea") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"slope") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"spring") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"stream") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"summit") == 0) {
+ if (scale_y > 100)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"swamp") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"trail") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"tower") == 0) {
+ symbol_id = 'r';
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"tunnel") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"valley") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"well") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"woods") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else if (strcasecmp(type,"ruin") == 0) {
+ if (scale_y > 50)
+ ok = 0;
+ }
+ else {
+ fprintf(stderr,"Something unusual found, Type:%s\tState:%s\tCounty:%s\tName:%s\n",
+ type,state,county,name);
+ }
+
+ if (ok == 1) { // If ok to draw it
+ symbol(w, 0, symbol_table, symbol_id, symbol_over, pixmap, 1, x-10, y-10, ' ');
+ draw_nice_string(w, pixmap, 0, x+10, y+5, (char*)name, 0xf, 0x10, strlen(name));
+ }
+
+ }
+ else {
+ //fprintf(stderr,"Not in viewport. Coordinates: %ld %ld\n",coord_lat,coord_lon);
+ //fprintf(stderr,"Min/Max Lat: %ld %ld\n",min_lat,max_lat);
+ //fprintf(stderr,"Min/Max Lon: %ld %ld\n",min_lon,max_lon);
+ }
+ }
+ }
+ } // End of while
+ (void)fclose (f);
+
+
+ // Check whether we're indexing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ // We're indexing only. Save the extents in the index.
+ index_update_xastir(filenm, // Filename only
+ bottom_extent, // Bottom
+ top_extent, // Top
+ left_extent, // Left
+ right_extent, // Right
+ 99999); // Default Map Level
+ }
+ }
+ else {
+ fprintf(stderr,"Couldn't open file: %s\n", file);
+ return;
+ }
+ if (debug_level & 16)
+ fprintf(stderr,"Exiting draw_pop_map\n");
+}
+
+
+
+
+
+// Search for a placename among pop files
+//
+// We need to search a file in the map directory that has the filename
+// STATE.gis, where STATE is from the "state" variable passed to us.
+// Search for the placename/county/state/type that the user requested.
+// Once found, center the map on that location or bring up a response
+// dialog that asks whether one wants to go there, and that dialog
+// provides info about the place found, with a possible selection
+// out of a list of matches.
+// Might also need to place a label at that position on the map in
+// case that pop file isn't currently selected.
+//
+int pop_locate_place( Widget w,
+ char *name_in,
+ char *state_in,
+ char *county_in,
+ char *quad_in,
+ char *type_in,
+ char *filename_in,
+ int follow_case,
+ int get_match,
+ char match_array_name[50][200],
+ long match_array_lat[50],
+ long match_array_long[50] ) {
+
+ char file[MAX_FILENAME]; // Complete path/name of pop file
+ FILE *f; // Filehandle of pop file
+ char line[MAX_FILENAME]; // One line of text from file
+ char *i, *j;
+ char state[50];
+ char state_in2[50];
+ char name[200];
+ char name_in2[50];
+ char type[100];
+ char type_in2[50];
+ char county[100];
+ char county_in2[50];
+ char quad[100];
+ char quad_in2[100];
+ char latitude[15];
+ char longitude[15];
+ char population[15];
+ char lat_dd[3];
+ char lat_mm[3];
+ char lat_ss[3];
+ char lat_dir[2];
+ char long_dd[4];
+ char long_mm[3];
+ char long_ss[3];
+ char long_dir[2];
+ char lat_str[15];
+ char long_str[15];
+ int temp1;
+ long coord_lon, coord_lat;
+ int ok;
+ struct stat file_status;
+ int my_count = 0;
+
+
+ xastir_snprintf(file,sizeof(file),"%s",filename_in);
+
+ if (debug_level & 16)
+ fprintf(stderr,"File: %s\n",file);
+
+
+ xastir_snprintf(name_in2,sizeof(name_in2),"%s",name_in);
+ xastir_snprintf(state_in2,sizeof(state_in2),"%s",state_in);
+ xastir_snprintf(county_in2,sizeof(county_in2),"%s",county_in);
+ xastir_snprintf(quad_in2,sizeof(quad_in2),"%s",quad_in);
+ xastir_snprintf(type_in2,sizeof(type_in2),"%s",type_in);
+
+
+ // Convert State/Province to upper-case always (they're
+ // always upper-case in the pop files from USGS.
+ to_upper(state_in2);
+
+
+ if (debug_level & 16)
+ fprintf(stderr,"Name:%s\tState:%s\tCounty:%s\tQuad:%s\tType:%s\n",
+ name_in,state_in2,county_in,quad_in,type_in);
+
+
+ // If "Match Case" togglebutton is not set, convert the
+ // rest of the keys to upper-case.
+ if (!follow_case) {
+ to_upper(name_in2);
+ to_upper(county_in2);
+ to_upper(quad_in2);
+ to_upper(type_in2);
+ }
+
+
+ // Check status of the file
+ if (stat(file, &file_status) < 0) {
+ // "Can't open file"
+ popup_message( langcode("POPEM00028"), filename_in );
+ return(0);
+ }
+ // Check for regular file
+ if (!S_ISREG(file_status.st_mode)) {
+ // "Can't open file"
+ popup_message( langcode("POPEM00028"), filename_in );
+ return(0);
+ }
+ // Attempt to open the file
+ f = fopen (file, "r");
+ if (f == NULL) {
+ // "Can't open file"
+ popup_message_always( langcode("POPEM00028"), filename_in );
+ return(0);
+ }
+
+ while (!feof (f)) { // Loop through entire file
+ if ( get_line (f, line, MAX_FILENAME) ) { // Snag one line of data
+ if (strlen(line) > 0) {
+
+
+//NOTE: How do we handle running off the end of "line" while using "index"?
+// Short lines here can cause segfaults.
+
+ // Find end of Feature ID Number field
+ j = index(line,'|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip this line
+ }
+
+ // Find end of State field
+ i = index(++j,'|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+ xastir_snprintf(state,sizeof(state),"%s",j);
+ clean_string(state);
+
+//NOTE: It'd be nice to take the part after the comma and put it before the rest
+// of the text someday, i.e. "Cassidy, Lake".
+
+ // Find end of Feature Name field
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+ xastir_snprintf(name,sizeof(name),"%s",i);
+ clean_string(name);
+
+ // Find end of Feature Type field
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+ xastir_snprintf(type,sizeof(type),"%s",j);
+ clean_string(type);
+
+ // Find end of County Name field
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+ xastir_snprintf(county,sizeof(county),"%s",i);
+ clean_string(county);
+
+ // Find end of State Number Code field
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+
+ // Find end of County Number Code field
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+
+ // Find end of Primary Latitude field (DDMMSSN)
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+ xastir_snprintf(latitude,sizeof(latitude),"%s",j);
+ clean_string(latitude);
+
+ // Find end of Primary Longitude field (DDDMMSSW)
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+ xastir_snprintf(longitude,sizeof(longitude),"%s",i);
+ clean_string(longitude);
+
+ // Find end of Primary Latitude field (decimal
+ // degrees)
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+
+ // Find end of Primary Longitude field (decimal
+ // degrees)
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+
+ // Find end of Source Latitude field (DMS)
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+
+ // Find end of Source Longitude (DMS)
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+
+ // Find end of Source Latitude field (decimal
+ // degrees)
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+
+ // Find end of Source Longitude field (decimal
+ // degrees)
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+
+ // Find end of Elevation field
+ i = index(++j, '|');
+
+ if (i == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ i[0] = '\0';
+
+ // Find end of Estimated Population field
+ j = index(++i, '|');
+
+ if (j == NULL) { // Pipe not found
+ continue; // Skip line
+ }
+
+ j[0] = '\0';
+ xastir_snprintf(population,sizeof(population),"%s",i);
+ clean_string(population);
+
+ // Snag Cell Name field (Quad name, last field)
+ xastir_snprintf(quad,sizeof(quad),"%s",j+1);
+ clean_string(quad);
+
+ // If "Match Case" togglebutton is not set, convert
+ // the data to upper-case before we do our compare.
+ if (!follow_case) {
+ to_upper(name);
+ to_upper(state);
+ to_upper(county);
+ to_upper(quad);
+ to_upper(type);
+ }
+
+// Still need to code for the "Match Exact" togglebutton.
+
+
+ // Now compare the input variables with those we've
+ // parsed. If a match, bring up a list of items which
+ // match.
+ //
+ ok = 1;
+ if (get_match) { // Looking for exact match
+ if (name_in2[0] != '\0')
+ if (strcmp(name,name_in2) != 0)
+ ok = 0;
+ if (state_in2[0] != '\0')
+ if (strcmp(state,state_in2) != 0)
+ ok = 0;
+ if (county_in2[0] != '\0')
+ if (strcmp(county,county_in2) != 0)
+ ok = 0;
+ if (quad_in2[0] != '\0')
+ if (strcmp(quad,quad_in2) != 0)
+ ok = 0;
+ if (type_in2[0] != '\0')
+ if (strcmp(type,type_in2) != 0)
+ ok = 0;
+ }
+ else { // Look for substring in file, not exact match
+ if (name_in2[0] != '\0')
+ if (strstr(name,name_in2) == NULL)
+ ok = 0;
+ if (state_in2[0] != '\0')
+ if (strstr(state,state_in2) == NULL)
+ ok = 0;
+ if (county_in2[0] != '\0')
+ if (strstr(county,county_in2) == NULL)
+ ok = 0;
+ if (quad_in2[0] != '\0')
+ if (strstr(quad,quad_in2) == NULL)
+ ok = 0;
+ if (type_in2[0] != '\0')
+ if (strstr(type,type_in2) == NULL)
+ ok = 0;
+ }
+
+
+ if (ok) {
+ if (debug_level & 16)
+ fprintf(stderr,"Match: %s,%s,%s,%s\n",name,state,county,type);
+
+// This one pops up the names of whatever we found.
+// "Found It!"
+//popup_message_always( langcode("POPEM00029"), name );
+
+ if (strlen(latitude) < 7)
+ continue; // We really don't have any latitude here!
+ lat_dd[0] = latitude[0];
+ lat_dd[1] = latitude[1];
+ lat_dd[2] = '\0';
+
+ lat_mm[0] = latitude[2];
+ lat_mm[1] = latitude[3];
+ lat_mm[2] = '\0';
+
+ lat_ss[0] = latitude[4];
+ lat_ss[1] = latitude[5];
+ lat_ss[2] = '\0';
+
+ lat_dir[0] = latitude[6];
+ lat_dir[1] = '\0';
+
+ if (strlen(longitude) < 8)
+ continue; // We really don't have any longitude here!
+ long_dd[0] = longitude[0];
+ long_dd[1] = longitude[1];
+ long_dd[2] = longitude[2];
+ long_dd[3] = '\0';
+
+ long_mm[0] = longitude[3];
+ long_mm[1] = longitude[4];
+ long_mm[2] = '\0';
+
+ long_ss[0] = longitude[5];
+ long_ss[1] = longitude[6];
+ long_ss[2] = '\0';
+
+ long_dir[0] = longitude[7];
+ long_dir[1] = '\0';
+
+ // Now must convert from DD MM SS format to DD MM.MM format so that we
+ // can run it through our conversion routine to Xastir coordinates.
+ if (1 != sscanf(lat_ss, "%d", &temp1)) {
+ fprintf(stderr,"locate_place:sscanf parsing error\n");
+ }
+
+ temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding
+ xastir_snprintf(lat_str, sizeof(lat_str), "%s%s.%02d%s", lat_dd,
+ lat_mm, temp1, lat_dir);
+ coord_lat = convert_lat_s2l(lat_str);
+
+ if (1 != sscanf(long_ss, "%d", &temp1)) {
+ fprintf(stderr,"locate_place:sscanf parsing error\n");
+ }
+
+ temp1 = (int)((temp1 / 60.0) * 100 + 0.5); // Poor man's rounding
+ xastir_snprintf(long_str, sizeof(long_str), "%s%s.%02d%s", long_dd,
+ long_mm, temp1, long_dir);
+ coord_lon = convert_lon_s2l(long_str);
+
+
+//set_map_position(w, coord_lat, coord_lon);
+
+ // Fill in the array values with what we just
+ // found, increment the counter.
+ xastir_snprintf(match_array_name[my_count],200,"%s",name);
+ match_array_lat[my_count] = coord_lat;
+ match_array_long[my_count] = coord_lon;
+ my_count++;
+
+ // Check for a max array. Return if it is full.
+ if (my_count > 50) {
+ return(50);
+ }
+ }
+ }
+ }
+ }
+
+ return(my_count);
+}
+
+
diff --git a/src/map_shp.c b/src/map_shp.c
new file mode 100644
index 0000000..7a1e2c6
--- /dev/null
+++ b/src/map_shp.c
@@ -0,0 +1,4182 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: map_shp.c,v 1.144 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ *
+ *
+ * Please see separate copyright notice attached to the
+ * shape_ring_direction() function in this file.
+ *
+ * DBFAWK TODO:
+ * - reload .dbfawk's when they've changed (or maps are reindexed)
+ * - scale line widths based on zoom level (see city_flag, for example)
+ * - allow multiple font sizes (font_size=small|medium|large|huge)
+ * - allow multiple font faces?
+ * - allow setting of map layer for individual shapes
+ * - transparency
+ * - allow setting fill_style (solid, stippled, etc.)
+ * - do more config/ *.dbfawk files!
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <dirent.h>
+#include <netinet/in.h>
+#include <Xm/XmAll.h>
+
+#ifdef HAVE_X11_XPM_H
+#include <X11/xpm.h>
+#ifdef HAVE_LIBXPM // if we have both, prefer the extra library
+#undef HAVE_XM_XPMI_H
+#endif // HAVE_LIBXPM
+#endif // HAVE_X11_XPM_H
+
+#ifdef HAVE_XM_XPMI_H
+#include <Xm/XpmI.h>
+#endif // HAVE_XM_XPMI_H
+
+#include <X11/Xlib.h>
+
+#include <math.h>
+
+#include "xastir.h"
+#include "maps.h"
+#include "alert.h"
+#include "util.h"
+#include "main.h"
+#include "datum.h"
+#include "draw_symbols.h"
+#include "rotated.h"
+#include "color.h"
+#include "xa_config.h"
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+#define CHECKREALLOC(m) if (!m) { fprintf(stderr, "***** Realloc Failed *****\n"); exit(0); }
+
+#ifdef HAVE_LIBSHP
+#ifdef HAVE_LIBPCRE
+#include "awk.h"
+#include "dbfawk.h"
+#endif /* HAVE_LIBPCRE */
+#ifdef HAVE_SHAPEFIL_H
+#include <shapefil.h>
+#else // HAVE_SHAPEFIL_H
+#ifdef HAVE_LIBSHP_SHAPEFIL_H
+#include <libshp/shapefil.h>
+#else // HAVE_LIBSHP_SHAPEFIL_H
+#error HAVE_LIBSHP defined but no corresponding include defined
+#endif // HAVE_LIBSHP_SHAPEFIL_H
+#endif // HAVE_SHAPEFIL_H
+
+extern int npoints; /* tsk tsk tsk -- globals */
+
+#ifdef USE_RTREE
+#include <rtree/index.h>
+#include "shp_hash.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+static int *RTree_hitarray=NULL;
+int RTree_hitarray_size=0;
+int RTree_hitarray_index=0;
+
+
+//This trivial routine is used by the RTreeSearch as a callback when it finds
+// a match.
+int RTreeSearchCallback(int id, void* arg)
+{
+ if (!RTree_hitarray) {
+ RTree_hitarray = (int *)malloc(1000*sizeof(int));
+ RTree_hitarray_size=1000;
+ }
+ if (RTree_hitarray_size <= RTree_hitarray_index) {
+ int *ptr;
+ ptr = realloc(RTree_hitarray, (RTree_hitarray_size+1000)*sizeof(int));
+ CHECKREALLOC(ptr); // fatal error if we can't get 'em :-(
+ RTree_hitarray=ptr;
+ RTree_hitarray_size += 1000;
+ //fprintf(stderr,"Hitarray now at %d\n",RTree_hitarray_size);
+ }
+
+
+ RTree_hitarray[RTree_hitarray_index++]=id-1;
+ return 1; // signal to keep searching for more matches
+}
+#endif // USE_RTREE
+
+
+
+
+
+/*******************************************************************
+ * create_shapefile_map()
+ *
+ * Do we have a need for storing date/ time/ speed/ course/
+ * altitude/ heard-direct for each point? Altitude could be stored
+ * in the Z space. If we store a station's trail as an SHPT_POINT
+ * file, then we can associate a bunch of info with each point:
+ * date/time, altitude, course, speed, status/comments, path, port,
+ * heard-direct, weather data, etc. We could also dynamically
+ * change the number of fields based on what we have a need to
+ * store, using field-names to determine what's stored in each file.
+ *
+ * shapefile_name is the path/name of the map file we wish to create
+ * (without the extension).
+ *
+ * type = SHPT_POINT, SHPT_ARC, SHPT_POLYGON,
+ * SHPT_MULTIPOINT, etc.
+ *
+ * quantity equals the number of vertices we have.
+ *
+ * padfx/padfy/padfz are the vertices themselves, in double format.
+ *******************************************************************/
+void create_shapefile_map(char *dir, char *shapefile_name, int type,
+ int quantity, double *padfx, double *padfy, double *padfz,
+ int add_timestamp, char * shape_label) {
+
+ SHPHandle my_shp_handle;
+ SHPObject *my_object;
+ DBFHandle my_dbf_handle;
+ char timedatestring[101];
+ int index;
+ int max_objects = 1;
+ char credit_string[] = "Created by Xastir, http://www.xastir.org";
+ char temp_shapefile_name[MAX_FILENAME];
+ char temp_prj_name[MAX_FILENAME];
+
+ if (debug_level & 16) {
+ fprintf(stderr,"create_shapefile_map\n");
+ fprintf(stderr,"%s %s %d %d %d\n",
+ dir,
+ shapefile_name,
+ type,
+ quantity,
+ add_timestamp);
+ }
+
+ if (quantity == 0) {
+ // No reason to make a map if we don't have any points.
+ return;
+ }
+
+ // Get the time/datestamp
+ get_timestamp(timedatestring);
+
+ if (add_timestamp) { // Prepend a timestamp to the filename
+ int ii;
+
+ xastir_snprintf(temp_shapefile_name,
+ sizeof(temp_shapefile_name),
+ "%s%s_%s",
+ dir,
+ timedatestring,
+ shapefile_name);
+
+ // Change spaces and colons to underlines
+ for (ii = 0; ii < (int)strlen(temp_shapefile_name); ii++) {
+ if (temp_shapefile_name[ii] == ' ' ||
+ temp_shapefile_name[ii] == ':') {
+ temp_shapefile_name[ii] = '_';
+ }
+
+ }
+ }
+ else { // Use the filename directly, no timestamp
+ xastir_snprintf(temp_shapefile_name,
+ sizeof(temp_shapefile_name),
+ "%s%s",
+ dir,
+ shapefile_name);
+ }
+
+ if (debug_level & 16)
+ fprintf(stderr, "Creating file %s\n", temp_shapefile_name);
+
+ // Create empty .shp/.shx/.dbf files
+ //
+ my_shp_handle = SHPCreate(temp_shapefile_name, type);
+ my_dbf_handle = DBFCreate(temp_shapefile_name);
+
+ // Check whether we were able to open these handles
+ if ((my_shp_handle == NULL) || (my_dbf_handle == NULL)) {
+ // Probably write-protected directory
+ fprintf(stderr, "Could not create shapefile %s\n",
+ temp_shapefile_name);
+ return;
+ }
+
+ // Write out a WKT in a .prj file to go with this shapefile.
+ xastir_snprintf(temp_prj_name,
+ sizeof(temp_prj_name),
+ "%s.prj",
+ temp_shapefile_name);
+ xastirWriteWKT(temp_prj_name);
+
+ // Create the different fields we'll use to store the
+ // attributes:
+ //
+ // Add a credits field and set the length. Field 0.
+ DBFAddField(my_dbf_handle, "Credits", FTString, strlen(credit_string) + 1, 0);
+ //
+ // Add a date/time field and set the length. Field 1.
+ DBFAddField(my_dbf_handle, "DateTime", FTString, strlen(timedatestring) + 1, 0);
+
+ // Add a label field
+ DBFAddField(my_dbf_handle, "Label", FTString, strlen(shape_label) + 1, 0);
+
+ // Note that if were passed additional parameters that went
+ // along with the lat/long/altitude points, we could write those
+ // into the DBF file in the loop below. We would have to change
+ // from a polygon to a point filetype though.
+
+ // Populate the files with objects and attributes. Perform this
+ // loop once for each object.
+ //
+ for (index = 0; index < max_objects; index++) {
+
+ // Create a temporary object from the vertices
+ my_object = SHPCreateSimpleObject( type,
+ quantity,
+ padfx,
+ padfy,
+ padfz);
+
+ // Write out the vertices
+ SHPWriteObject( my_shp_handle,
+ -1,
+ my_object);
+
+ // Destroy the temporary object
+ SHPDestroyObject(my_object);
+
+// Note that with the current setup the below really only get
+// written into the file once. Check it with dbfinfo/dbfdump.
+
+ // Write the credits attributes
+ DBFWriteStringAttribute( my_dbf_handle,
+ index,
+ 0,
+ credit_string);
+
+ // Write the time/date string
+ DBFWriteStringAttribute( my_dbf_handle,
+ index,
+ 1,
+ timedatestring);
+
+ // Write the label string
+ DBFWriteStringAttribute( my_dbf_handle,
+ index,
+ 2,
+ shape_label);
+ }
+
+ // Close the .shp/.shx/.dbf files
+ SHPClose(my_shp_handle);
+ DBFClose(my_dbf_handle);
+}
+
+
+
+
+
+// Function which creates a Shapefile map from an APRS trail.
+//
+// Navigate through the linked list of TrackRow structs to pick out
+// the lat/long and write them into arrays of floats. We then pass
+// those arrays to create_shapefile_map().
+//
+void create_map_from_trail(char *call_sign) {
+ DataRow *p_station;
+
+
+ // Find the station in our database. Count the number of points
+ // for that station first, then allocate some arrays to hold
+ // that quantity of points. Stuff the lat/long into the arrays
+ // and then call create_shapefile_map().
+ //
+ if (search_station_name(&p_station, call_sign, 1)) {
+ int count;
+ int ii;
+ TrackRow *ptr;
+ char temp[MAX_FILENAME];
+ char temp2[MAX_FILENAME];
+ double *x;
+ double *y;
+ double *z;
+ char temp_base_dir[MAX_VALUE];
+
+ count = 0;
+ ptr = p_station->oldest_trackpoint;
+ while (ptr != NULL) {
+ count++;
+ ptr = ptr->next;
+ }
+
+//fprintf(stderr, "Quantity of points: %d\n", count);
+
+ if (count == 0) {
+ // No reason to make a map if we don't have any points
+ // in the track list.
+ return;
+ }
+
+ // We know how many points are in the linked list. Allocate
+ // arrays to hold the values.
+ x = (double *) malloc( count * sizeof(double) );
+ y = (double *) malloc( count * sizeof(double) );
+ z = (double *) malloc( count * sizeof(double) );
+ CHECKMALLOC(x);
+ CHECKMALLOC(y);
+ CHECKMALLOC(z);
+
+ // Fill in the values. We need to convert from Xastir
+ // coordinate system to lat/long doubles as we go.
+ ptr = p_station->oldest_trackpoint;
+ ii = 0;
+ while ((ptr != NULL) && (ii < count) ) {
+
+ // Convert from Xastir coordinates to lat/long
+
+ // Convert to string
+ convert_lon_l2s(ptr->trail_long_pos, temp, sizeof(temp), CONVERT_DEC_DEG);
+ // Convert to double and stuff into array of doubles
+ if (1 != sscanf(temp, "%lf", &x[ii])) {
+ fprintf(stderr,"create_map_from_trail:sscanf parsing error\n");
+ }
+ // If longitude string contains "W", make the final
+ // result negative.
+ if (index(temp, 'W'))
+ x[ii] = x[ii] * -1.0;
+
+ // Convert to string
+ convert_lat_l2s(ptr->trail_lat_pos, temp, sizeof(temp), CONVERT_DEC_DEG);
+ // Convert to double and stuff into array of doubles
+ if (1 != sscanf(temp, "%lf", &y[ii])) {
+ fprintf(stderr,"create_map_from_trail:sscanf parsing error\n");
+ }
+ // If latitude string contains "S", make the final
+ // result negative.
+ if (index(temp, 'S'))
+ y[ii] = y[ii] * -1.0;
+
+ z[ii] = ptr->altitude; // Altitude (meters), undefined=-99999
+
+ ptr = ptr->next;
+ ii++;
+ }
+
+ // Create a Shapefile from the APRS trail. Write it into
+ // "~/.xastir/tracklogs" and add a date/timestamp to the end.
+ //
+ xastir_snprintf(temp, sizeof(temp),
+ "%s/",
+ get_user_base_dir("tracklogs", temp_base_dir, sizeof(temp_base_dir)));
+
+ // Create filename
+ xastir_snprintf(temp2, sizeof(temp2),
+ "%s%s",
+ call_sign,
+ "_APRS_Trail_Red");
+
+ create_shapefile_map(
+ temp,
+ temp2,
+ SHPT_ARC,
+ count,
+ x,
+ y,
+ z,
+ 1, // Add a timestamp to the front of the filename
+ call_sign);
+
+ // Free the storage that we malloc'ed
+ free(x);
+ free(y);
+ free(z);
+ }
+ else { // Couldn't find the station of interest
+ }
+}
+
+
+
+
+
+// Code borrowed from Shapelib which determines whether a ring is CW
+// or CCW. Thanks to Frank Warmerdam for permitting us to use this
+// under the GPL license! Per e-mail of 04/29/2003 between Frank
+// and Curt, WE7U. Frank gave permission for us to use _any_
+// portion of Shapelib inside the GPL'ed Xastir program.
+//
+// Test Ring for Clockwise/Counter-Clockwise (fill or hole ring)
+//
+// Return 1 for Clockwise (fill ring)
+// Return -1 for Counter-Clockwise (hole ring)
+// Return 0 for error/indeterminate (shouldn't get this!)
+//
+int shape_ring_direction ( SHPObject *psObject, int Ring ) {
+ int nVertStart;
+ int nVertCount;
+ int iVert;
+ float dfSum;
+ int result;
+
+
+ nVertStart = psObject->panPartStart[Ring];
+
+ if( Ring == psObject->nParts-1 )
+ nVertCount = psObject->nVertices - psObject->panPartStart[Ring];
+ else
+ nVertCount = psObject->panPartStart[Ring+1]
+ - psObject->panPartStart[Ring];
+
+ dfSum = 0.0;
+ for( iVert = nVertStart; iVert < nVertStart+nVertCount-1; iVert++ )
+ {
+ dfSum += psObject->padfX[iVert] * psObject->padfY[iVert+1]
+ - psObject->padfY[iVert] * psObject->padfX[iVert+1];
+ }
+
+ dfSum += psObject->padfX[iVert] * psObject->padfY[nVertStart]
+ - psObject->padfY[iVert] * psObject->padfX[nVertStart];
+
+ if (dfSum < 0.0)
+ result = 1;
+ else if (dfSum > 0.0)
+ result = -1;
+ else
+ result = 0;
+
+ return(result);
+}
+
+
+
+
+
+/**********************************************************
+ * draw_shapefile_map()
+ *
+ * This function handles both weather-alert shapefiles (from the
+ * NOAA site) and shapefiles used as maps (from a number of
+ * sources).
+ *
+ * If destination_pixmap equals INDEX_CHECK_TIMESTAMPS or
+ * INDEX_NO_TIMESTAMPS, then we are indexing the file (finding the
+ * extents) instead of drawing it.
+ *
+ * The current implementation can draw Polygon, PolyLine, and Point
+ * Shapefiles, but only from a few sources (NOAA, Mapshots.com, and
+ * ESRI/GeographyNetwork.com). We don't handle some of the more
+ * esoteric formats. We now handle the "hole" drawing in polygon
+ * shapefiles, where one direction around the ring means a fill, and
+ * the other direction means a hole in the polygon.
+ *
+ * Note that we must currently hard-code the file-recognition
+ * portion and the file-drawing portion, because every new source of
+ * Shapefiles has a different format, and the fields and field
+ * definitions can all change between them.
+ *
+ * If alert is NULL, draw every shape that fits the screen. If
+ * non-NULL, draw only the shape that matches the zone number.
+ *
+ * Here's what I get for the County_Warning_Area Shapefile:
+ *
+ *
+ * Info for shapefiles/county_warning_areas/w_24ja01.shp
+ * 4 Columns, 121 Records in file
+ * WFO string (3,0)
+ * CWA string (3,0)
+ * LON float (18,5)
+ * LAT float (18,5)
+ * Info for shapefiles/county_warning_areas/w_24ja01.shp
+ * Polygon(5), 121 Records in file
+ * File Bounds: ( 0, 0)
+ * ( 179.7880249, 71.39809418)
+ *
+ * From the NOAA web pages:
+
+ Zone Alert Maps: (polygon) (such as z_16mr01.shp)
+ ----------------
+ field name type width,dec description
+ STATE character 2 [ss] State abbrev (US Postal Standard)
+ ZONE character 3 [zzz] Zone number, from WSOM C-11
+ CWA character 3 County Warning Area, from WSOM C-47
+ NAME character 254 Zone name, from WSOM C-11
+ STATE_ZONE character 5 [sszzz] state+("00"+zone.trim).right(3))
+ TIME_ZONE character 2 [tt] Time Zone, 2 chars if split
+ FE_AREA character 2 [aa] Cardinal area of state (occasional)
+ LON numeric 10,5 Longitude of centroid [decimal degrees]
+ LAT numeric 9,5 Latitude of centroid [decimal degrees]
+
+
+ NOTE: APRS weather alerts have these sorts of codes in them:
+ AL_C001
+ AUTAUGACOUNTY
+ MS_C075
+ LAUDERDALE&NEWTONCOUNTIES
+ KY_C009
+ EDMONSON
+ MS_CLARKE
+ MS_C113
+ MN_Z076
+ PIKECOUNTY
+ ATTALACOUNTY
+ ST.LUCIECOUNTY
+ CW_AGLD
+
+ The strings in the shapefiles are mixed-case, and it appears that the NAME field would
+ have the county name, in case state_zone-number format was not used. We can use the
+ STATE_ZONE filed for a match unless it is a non-standard form, in which case we'll need
+ to look through the NAME field, and perhaps chop off the "SS_" state portion first.
+
+
+ County Warning Areas: (polygon)
+ ---------------------
+ field name type width,dec description
+ WFO character 3 WFO Identifier (name of CWA)
+ CWA character 3 CWA Identifier (same as WFO)
+ LON numeric 10,5 Longitude of centroid [decimal degrees]
+ LAT numeric 9,5 Latitude of centroid [decimal degrees]
+
+ Coastal and Offshore Marine Areas: (polygon)
+ ----------------------------------
+ field name type width,dec description
+ ID character 6 Marine Zone Identifier
+ WFO character 3 Assigned WFO (Office Identifier)
+ NAME character 250 Name of Marine Zone
+ LON numeric 10,5 Longitude of Centroid [decimal degrees]
+ LAT numeric 9,5 Latitude of Centroid [decimal degrees]
+ WFO_AREA character 200 "Official Area of Responsibility", from WSOM D51/D52
+
+ Road Maps: (polyline)
+ ----------
+ field name type width,dec description
+ STFIPS numeric 2,0 State FIPS Code
+ CTFIPS numeric 3,0 County FIPS Code
+ MILES numeric 6,2 length [mi]
+ KILOMETERS numeric 6,2 length [km]
+ TOLL numeric 1,0
+ SURFACE numeric 1,0 Surface type
+ LANES numeric 2,0 Number of lanes
+ FEAT_CLASS numeric 2,0
+ CLASS character 30
+ SIGN1 character 6 Primary Sign Route
+ SIGN2 character 6 Secondary Sign Route
+ SIGN3 character 6 Alternate Sign Route
+ DESCRIPT character 35 Name of road (sparse)
+ SPEEDLIM numeric 16,0
+ SECONDS numeric 16,2
+
+Lakes (lk17de98.shp):
+---------------------
+field name type width,dec description
+NAME string (40,0)
+FEATURE string (40,0)
+LON float (10,5)
+LAT float (9,5)
+
+
+USGS Quads Overlay (24kgrid.shp) from
+http://data.geocomm.com/quadindex/
+----------------------------------
+field name type width,dec Example
+NAME string (30,0) Lummi Bay OE W
+STATE string (2,0) WA
+LAT string (6,0) 48.750
+LON string (8,0) -122.750
+MRC string (8,0) 48122-G7
+
+
+// Need to figure out which type of alert it is, select the corresponding shapefile,
+// then store the shapefile AND the alert_tag in the alert hash .filename list?
+// and draw the map. Add an item to alert hash to keep track?
+
+// The last parameter denotes loading into pixmap_alerts instead of pixmap or pixmap_final
+// Here's the old APRS-type map call:
+//map_search (w, alert_scan, alert, &alert_count,(int)(alert_status[i + 2] == DATA_VIA_TNC || alert_status[i + 2] == DATA_VIA_LOCAL), DRAW_TO_PIXMAP_ALERTS);
+
+// Check the zone name(s) to see which Shapefile(s) to use.
+
+ switch (zone[4]) {
+ case ('C'): // County File (c_16my01.shp)
+ break;
+*** case ('A'): // County Warning File (w_24ja01.shp)
+ break;
+ case ('Z'): // Zone File (z_16mr01.shp, z_16my01.shp, mz24ja01.shp, oz09de99.shp)
+ break;
+ case ('F'): // Fire weather (fz_ddmmyy.shp)
+ break;
+*** case ('A'): // Canadian Area (a_mmddyy.shp)
+ break;
+ case ('R'): // Canadian Region (r_mmddyy.shp)
+ break;
+ }
+
+
+ **********************************************************/
+
+#ifdef WITH_DBFAWK
+static dbfawk_sig_info *Dbf_sigs = NULL;
+static awk_symtab *Symtbl = NULL;
+/* default dbfawk rule when no better signature match is found */
+static awk_rule dbfawk_default_rules[] = {
+ { 0,
+ BEGIN,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ "dbfinfo=\"\"; key=\"\"; lanes=1; color=8; fill_color=13; fill_stipple=0; name=\"\"; filled=0; fill_style=0; pattern=0; display_level=65536; label_level=0",
+ 0,
+ 0 },
+};
+#define dbfawk_default_nrules (sizeof(dbfawk_default_rules)/sizeof(dbfawk_default_rules[0]))
+static dbfawk_sig_info *dbfawk_default_sig = NULL;
+#endif // WITH_DBFAWK
+
+void draw_shapefile_map (Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry * alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *mdf) {
+
+ DBFHandle hDBF;
+ SHPObject *object;
+ static XPoint points[MAX_MAP_POINTS];
+ char file[MAX_FILENAME]; /* Complete path/name of image file */
+ char short_filenm[MAX_FILENAME];
+ int i, fieldcount, recordcount, structure, ring;
+#ifndef WITH_DBFAWK
+ char ftype[15];
+ int nWidth, nDecimals;
+#endif /*!WITH_DBFAWK*/
+ SHPHandle hSHP;
+ int nShapeType, nEntities;
+ double adfBndsMin[4], adfBndsMax[4];
+ char *sType;
+ unsigned long my_lat, my_long;
+ long x,y;
+ int ok, index;
+ int polygon_hole_flag;
+ int *polygon_hole_storage;
+ GC gc_temp = NULL;
+ XGCValues gc_temp_values;
+ Region region[3];
+ int temp_region1;
+ int temp_region2;
+ int temp_region3;
+ int gps_flag = 0;
+ char gps_label[100];
+ int gps_color = 0x0c;
+#ifndef WITH_DBFAWK
+ int road_flag = 0;
+ int lake_flag = 0;
+ int river_flag = 0;
+ int railroad_flag = 0;
+ int school_flag = 0;
+ int path_flag = 0;
+ int city_flag = 0;
+#endif /*!WITH_DBFAWK*/
+ int quad_overlay_flag = 0;
+#ifndef WITH_DBFAWK
+ int mapshots_labels_flag = 0;
+#endif /*!WITH_DBFAWK*/
+ int weather_alert_flag = 0;
+ char *filename; // filename itself w/o directory
+ char search_param1[10];
+#ifndef WITH_DBFAWK
+ int search_field1 = 0;
+ int search_field2 = -1;
+#endif /* !WITH_DBFAWK */
+ char search_param2[10];
+ int found_shape = -1;
+#ifndef USE_RTREE
+ int start_record;
+ int end_record;
+#endif // !USE_RTREE
+ int ok_to_draw = 0;
+ int high_water_mark_i = 0;
+ int high_water_mark_index = 0;
+ char quad_label[100];
+ char status_text[MAX_FILENAME];
+#ifdef WITH_DBFAWK
+ /* these have to be static since I recycle Symtbl between calls */
+ static char dbfsig[1024],dbffields[1024],name[64],key[64],sym[4];
+ static int color,lanes,filled,pattern,display_level,label_level;
+ static int fill_style,fill_color;
+ static int fill_stipple;
+ //static int layer;
+ dbfawk_sig_info *sig_info = NULL;
+ dbfawk_field_info *fld_info = NULL;
+
+
+ int draw_filled_orig;
+#endif // WITH_DBFAWK
+ int draw_filled;
+ static int label_color = 8; /* set by dbfawk. Otherwise it's black. */
+ static int font_size = FONT_DEFAULT; // set by dbfawk, else this default
+
+ typedef struct _label_string {
+ char label[50];
+ int found;
+ struct _label_string *next;
+ } label_string;
+
+ // Define hash table for label pointers
+ label_string *label_hash[256];
+ // And the index into it
+ uint8_t hash_index = 0;
+
+ label_string *ptr2 = NULL;
+
+#ifdef USE_RTREE
+ struct Rect viewportRect;
+ double rXmin, rYmin, rXmax,rYmax;
+ shpinfo *si;
+ int nhits;
+#endif // USE_RTREE
+
+ // pull this out of the map_draw_flags
+ draw_filled = mdf->draw_filled;
+
+ // Initialize the hash table label pointers
+ for (i = 0; i < 256; i++) {
+ label_hash[i] = NULL;
+ }
+
+
+#ifdef WITH_DBFAWK
+ // We're going to change draw_filled a bunch if we've got Auto turned
+ // on, but we have to check --- save this!
+ draw_filled_orig=draw_filled;
+
+ // Re-initialize these static variables every time through here.
+ // Otherwise, if a dbfawk file forgets to set one, we'd use what the
+ // last map used. Sometimes that's ugly.
+ color=8;
+ lanes=1;
+ filled=0;
+ fill_style=0;
+ fill_color=13;
+ fill_stipple=0;
+ pattern=0;
+ display_level=8192;
+ label_level=0;
+ label_color=8;
+ font_size=FONT_DEFAULT;
+#endif // WITH_DBFAWK
+
+#ifdef WITH_DBFAWK
+ if (Dbf_sigs == NULL)
+ Dbf_sigs = dbfawk_load_sigs(get_data_base_dir("config"),".dbfawk");
+
+ if (debug_level & 16)
+ fprintf(stderr,"DBFAWK signatures %sfound in %s.\n",
+ (Dbf_sigs)?" ":"NOT ",get_data_base_dir("config"));
+
+ if (dbfawk_default_sig == NULL) {
+ /* set up default dbfawk when no sig matches */
+ // This one is ok to leave allocated, as it gets malloc'ed
+ // once during each runtime and then gets left alone. We
+ // don't need to free it.
+ dbfawk_default_sig = calloc(1,sizeof(dbfawk_sig_info));
+ CHECKMALLOC(dbfawk_default_sig);
+
+ // Calls awk_new_program which allocates memory. Again, we
+ // don't need to free this one, as it gets allocated only
+ // once per runtime.
+ dbfawk_default_sig->prog = awk_load_program_array(dbfawk_default_rules,dbfawk_default_nrules);
+ }
+#endif // WITH_DBFAWK
+
+ //fprintf(stderr,"*** Alert color: %d ***\n",alert_color);
+
+ // We don't draw the shapes if alert_color == -1
+ if (alert_color != 0xff)
+ ok_to_draw++;
+
+ search_param1[0] = '\0';
+ search_param2[0] = '\0';
+
+ xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm);
+
+ // Create a shorter filename for display (one that fits the
+ // status line more closely). Subtract the length of the
+ // "Indexing " and/or "Loading " strings as well.
+ if (strlen(filenm) > (41 - 9)) {
+ int avail = 41 - 11;
+ int new_len = strlen(filenm) - avail;
+
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "..%s",
+ &filenm[new_len]);
+ }
+ else {
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "%s",
+ filenm);
+ }
+
+ //fprintf(stderr,"draw_shapefile_map:start:%s\n",file);
+
+ filename = filenm;
+ i = strlen(filenm);
+ while ( (filenm[i] != '/') && (i >= 0) )
+ filename = &filenm[i--];
+ //fprintf(stderr,"draw_shapefile_map:filename:%s\ttitle:%s\n",filename,alert->title);
+
+ if (alert)
+ weather_alert_flag++;
+
+ // Check for ~/.xastir/tracklogs directory. We set up the
+ // labels and colors differently for these types of files.
+// if (strstr(filenm,".xastir/tracklogs")) { // We're in the ~/.xastir/tracklogs directory
+ if (strstr(filenm,"GPS")) { // We're in the maps/GPS directory
+ gps_flag++;
+ }
+
+ // Open the .dbf file for reading. This has the textual
+ // data (attributes) associated with each shape.
+ hDBF = DBFOpen( file, "rb" );
+ if ( hDBF == NULL ) {
+ if (debug_level & 16)
+ fprintf(stderr,"draw_shapefile_map: DBFOpen(%s,\"rb\") failed.\n", file );
+
+ return;
+ }
+ if (debug_level & 16)
+ fprintf(stderr,"\n---------------------------------------------\nInfo for %s\n",filenm);
+
+#ifdef WITH_DBFAWK
+ *dbfsig = '\0';
+ fieldcount = dbfawk_sig(hDBF,dbfsig,sizeof(dbfsig));
+#else // WITH_DBFAWK
+ fieldcount = DBFGetFieldCount(hDBF);
+#endif /* !WITH_DBFAWK */
+ if (fieldcount == 0) {
+ DBFClose( hDBF ); // Clean up open file descriptors
+ return; // Should have at least one field
+
+ }
+ recordcount = DBFGetRecordCount(hDBF);
+ if (recordcount == 0) {
+ DBFClose( hDBF ); // Clean up open file descriptors
+ return; // Should have at least one record
+ }
+ if (debug_level & 16) {
+ fprintf(stderr,"%d Columns, %d Records in file\n", fieldcount, recordcount);
+#ifdef WITH_DBFAWK
+ fprintf(stderr,"DBF signature: %s\n",dbfsig);
+#endif // WITH_DBFAWK
+ }
+#ifdef WITH_DBFAWK
+ if (Dbf_sigs) { /* see if we have a .dbfawk file that matches */
+ sig_info = dbfawk_find_sig(Dbf_sigs,dbfsig,file);
+ if (sig_info) gps_flag = 0; // trump gps_flag-- use dbfawk
+ if (!sig_info) {
+ fprintf(stderr,"No DBFAWK signature for %s! Using default.\n",filenm);
+ sig_info = dbfawk_default_sig;
+ }
+ if (sig_info) { /* we've got a .dbfawk, so set up symtbl */
+
+ if (!Symtbl) {
+ Symtbl = awk_new_symtab();
+ awk_declare_sym(Symtbl,"dbffields",STRING,dbffields,sizeof(dbffields));
+ awk_declare_sym(Symtbl,"color",INT,&color,sizeof(color));
+ awk_declare_sym(Symtbl,"lanes",INT,&lanes,sizeof(lanes));
+ //awk_declare_sym(Symtbl,"layer",INT,&layer,sizeof(layer));
+ awk_declare_sym(Symtbl,"name",STRING,name,sizeof(name));
+ awk_declare_sym(Symtbl,"key",STRING,key,sizeof(key));
+ awk_declare_sym(Symtbl,"symbol",STRING,sym,sizeof(sym));
+ awk_declare_sym(Symtbl,"filled",INT,&filled,sizeof(filled));
+ awk_declare_sym(Symtbl,"fill_style",INT,&fill_style,sizeof(fill_style));
+ awk_declare_sym(Symtbl,"fill_color",INT,&fill_color,sizeof(fill_color));
+ awk_declare_sym(Symtbl,"fill_stipple",INT,&fill_stipple,sizeof(fill_stipple));
+ awk_declare_sym(Symtbl,"pattern",INT,&pattern,sizeof(pattern));
+ awk_declare_sym(Symtbl,"display_level",INT,&display_level,sizeof(display_level));
+ awk_declare_sym(Symtbl,"label_level",INT,&label_level,sizeof(label_level));
+ awk_declare_sym(Symtbl,"label_color",INT,&label_color,sizeof(label_color));
+ awk_declare_sym(Symtbl,"font_size",INT,&font_size,sizeof(font_size));
+ }
+ if (awk_compile_program(Symtbl,sig_info->prog) < 0) {
+ fprintf(stderr,"Unable to compile .dbfawk program\n");
+
+ if (sig_info != NULL && sig_info != dbfawk_default_sig && (sig_info->sig == NULL)) {
+ dbfawk_free_sigs(sig_info);
+ }
+ return;
+ }
+ awk_exec_begin(sig_info->prog); /* execute a BEGIN rule if any */
+
+ /* find out which dbf fields we care to read */
+ fld_info = dbfawk_field_list(hDBF, dbffields);
+
+ } else { /* should never be reached anymore! */
+ fprintf(stderr,"No DBFAWK signature for %s and no default!\n",filenm);
+ //exit(1); // Debug
+ return;
+ }
+ }
+#endif /* WITH_DBFAWK */
+ /*
+ * DBFAWK: all this WX junk following to set up the search fields and
+ * parameters is now done by the dbfawk file which sets the "key"
+ * variable to the appropriate search key for each record which is
+ * compared to the alert->title[].
+ */
+#ifndef WITH_DBFAWK
+ // If we're doing weather alerts and index is not filled in yet
+ if (weather_alert_flag && (alert->index == -1) ) {
+
+ // For weather alerts:
+ // Need to figure out from the initial characters of the filename which
+ // type of file we're using, then compute the fields we're looking for.
+ // After we know that, need to look in the DBF file for a match. Once
+ // we find a match, we can open up the SHX/SHP files, go straight to
+ // the shape we want, and draw it.
+ switch (filenm[0]) {
+
+ case 'c': // County File
+ // County, c_ files: WI_C037
+ // STATE CWA COUNTYNAME
+ // AL BMX Morgan
+ // Need fields 0/1:
+ search_field1 = 0; // STATE
+ search_field2 = 3; // FIPS
+ xastir_snprintf(search_param1,sizeof(search_param1),"%c%c",
+ alert->title[0],
+ alert->title[1]);
+ xastir_snprintf(search_param2,sizeof(search_param2),"%c%c%c",
+ alert->title[4],
+ alert->title[5],
+ alert->title[6]);
+ break;
+
+ case 'w': // County Warning Area File
+ // County Warning Area, w_ files: CW_ATAE
+ // WFO CWA
+ // TAE TAE
+ // Need field 0
+ search_field1 = 0; // WFO
+ search_field2 = -1;
+ xastir_snprintf(search_param1,sizeof(search_param1),"%c%c%c",
+ alert->title[4],
+ alert->title[5],
+ alert->title[6]);
+ break;
+
+ case 'o': // Offshore Marine Area File
+ // Offshore Marine Zones, oz files: AN_Z081
+ // ID WFO NAME
+ // ANZ081 MPC Gulf of Maine
+ // Need field 0
+ search_field1 = 0; // ID
+ search_field2 = -1;
+ xastir_snprintf(search_param1,sizeof(search_param1),"%c%c%c%c%c%c",
+ alert->title[0],
+ alert->title[1],
+ alert->title[3],
+ alert->title[4],
+ alert->title[5],
+ alert->title[6]);
+ break;
+
+ case 'm': // Marine Area File
+ // Marine Zones, mz?????? files: PK_Z120
+ // ID WFO NAME
+ // PKZ120 AJK Area 1B. Southeast Alaska,
+ // Need field 0
+ search_field1 = 0; // ID
+ search_field2 = -1;
+ xastir_snprintf(search_param1,sizeof(search_param1),"%c%c%c%c%c%c",
+ alert->title[0],
+ alert->title[1],
+ alert->title[3],
+ alert->title[4],
+ alert->title[5],
+ alert->title[6]);
+ break;
+
+ case 'z': // Zone File
+ case 'f': // Fire zone file, KS_F033
+ default:
+ // Weather alert zones, z_ files: KS_Z033
+ // STATE_ZONE
+ // AK225
+ // Need field 4
+ search_field1 = 4; // STATE_ZONE
+ search_field2 = -1;
+ xastir_snprintf(search_param1,sizeof(search_param1),"%c%c%c%c%c",
+ alert->title[0],
+ alert->title[1],
+ alert->title[4],
+ alert->title[5],
+ alert->title[6]);
+ break;
+ }
+
+ //fprintf(stderr,"Search_param1: %s,\t",search_param1);
+ //fprintf(stderr,"Search_param2: %s\n",search_param2);
+ } /* weather_alert */
+
+ for (i=0; i < fieldcount; i++) {
+ char szTitle[12];
+
+ switch (DBFGetFieldInfo(hDBF, i, szTitle, &nWidth, &nDecimals)) {
+ case FTString:
+ xastir_snprintf(ftype,sizeof(ftype),"string");
+ break;
+
+ case FTInteger:
+ xastir_snprintf(ftype,sizeof(ftype),"integer");
+ break;
+
+ case FTDouble:
+ xastir_snprintf(ftype,sizeof(ftype),"float");
+ break;
+
+ case FTInvalid:
+ xastir_snprintf(ftype,sizeof(ftype),"invalid/unsupported");
+ break;
+
+ default:
+ xastir_snprintf(ftype,sizeof(ftype),"unknown");
+ break;
+ }
+
+ // Check for quad overlay type of map
+ if (strstr(filename,"24kgrid")) { // USGS Quad overlay file
+ quad_overlay_flag++;
+ }
+
+ // Check the filename for mapshots.com filetypes to see what
+ // type of file we may be dealing with.
+ if (strncasecmp(filename,"tgr",3) == 0) { // Found Mapshots or GeographyNetwork file
+
+ if (strstr(filename,"lpt")) { // Point file
+ mapshots_labels_flag++;
+ if (debug_level & 16) {
+ fprintf(stderr,"*** Found point file ***\n");
+ break;
+ }
+ else
+ break;
+ }
+ else if (strstr(filename,"plc")) { // Designated Places: Arlington
+ city_flag++;
+ mapshots_labels_flag++;
+ if (debug_level & 16) {
+ fprintf(stderr,"*** Found (Designated Places) ***\n");
+ break;
+ }
+ else
+ break;
+ }
+ else if (strstr(filename,"ctycu")) { // County Boundaries: WA, Snohomish
+ if (debug_level & 16) {
+ fprintf(stderr,"*** Found county (mapshots county) ***\n");
+ break;
+ }
+ else
+ break;
+ }
+ else if (strstr(filename,"lkA")) { // Roads
+ road_flag++;
+ mapshots_labels_flag++;
+ if (debug_level & 16) {
+ fprintf(stderr,"*** Found some roads (mapshots roads) ***\n");
+ break;
+ }
+ else
+ break;
+ }
+ else if (strstr(filename,"lkB")) { // Railroads
+ railroad_flag++;
+ mapshots_labels_flag++;
+ if (debug_level & 16) {
+ fprintf(stderr,"*** Found some railroads (mapshots railroads) ***\n");
+ break;
+ }
+ else
+ break;
+ }
+ else if (strstr(filename,"lkC")) { // Paths/etc. Pipelines? Transmission lines?
+ path_flag++;
+ if (debug_level & 16) {
+ fprintf(stderr,"*** Found some paths (mapshots paths/etc) ***\n");
+ break;
+ }
+ else
+ break;
+ }
+ else if (strstr(filename,"lkH")) { // Rivers/Streams/Lakes/Glaciers
+ river_flag++;
+ mapshots_labels_flag++;
+ if (debug_level & 16) {
+ fprintf(stderr,"*** Found water (mapshots rivers/streams/lakes/glaciers) ***\n");
+ break;
+ }
+ else
+ break;
+ }
+ else if ( strstr(filename,"elm") // Elementary school district
+ || strstr(filename,"mid") // Middle school district
+ || strstr(filename,"sec") // Secondary school district
+ || strstr(filename,"uni") ) { // Unified school district
+ school_flag++;
+ if (debug_level & 16) {
+ fprintf(stderr,"*** Found school district ***\n");
+ break;
+ }
+ else
+ break;
+ }
+ else if (strstr(filename,"urb")) { // Urban areas: Seattle, WA
+ if (debug_level & 16) {
+ fprintf(stderr,"*** Found (mapshots urban areas) ***\n");
+ break;
+ }
+ else
+ break;
+ }
+ else if (strstr(filename,"wat")) { // Bodies of water, creeks/lakes/glaciers
+ lake_flag++;
+ mapshots_labels_flag++;
+ if (debug_level & 16) {
+ fprintf(stderr,"*** Found some water (mapshots bodies of water, creeks/lakes/glaciers) ***\n");
+ break;
+ }
+ else
+ break;
+ }
+ }
+
+
+ // Attempt to guess which type of shapefile we're dealing
+ // with, and how we should draw it.
+ // If debug is on, we want to print out every field, otherwise
+ // break once we've made our guess on the type of shapefile.
+ if (debug_level & 16)
+ fprintf(stderr,"%15.15s\t%15s (%d,%d)\n", szTitle, ftype, nWidth, nDecimals);
+
+ if (strncasecmp(szTitle, "SPEEDLIM", 8) == 0) {
+ // sewroads shapefile?
+ road_flag++;
+ if (debug_level & 16)
+ fprintf(stderr,"*** Found some roads (SPEEDLIM*) ***\n");
+ else
+ break;
+ }
+ else if (strncasecmp(szTitle, "US_RIVS_ID", 10) == 0) {
+ // which shapefile?
+ river_flag++;
+ if (debug_level & 16)
+ fprintf(stderr,"*** Found some rivers (US_RIVS_ID*) ***\n");
+ else
+ break;
+ }
+ else if (strcasecmp(szTitle, "FEATURE") == 0) {
+ char *attr_str;
+ int j;
+ for (j=0; j < recordcount; j++) {
+ if (fieldcount >= (i+1)) {
+ attr_str = (char*)DBFReadStringAttribute(hDBF, j, i);
+ if (strncasecmp(attr_str, "LAKE", 4) == 0) {
+ // NOAA Lakes and Water Bodies (lk17de98) shapefile
+ lake_flag++;
+ if (debug_level & 16)
+ fprintf(stderr,"*** Found some lakes (FEATURE == LAKE*) ***\n");
+ break;
+ }
+ else if (strstr(attr_str, "Highway") != NULL ||
+ strstr(attr_str, "highway") != NULL ||
+ strstr(attr_str, "HIGHWAY") != NULL) {
+ // NOAA Interstate Highways of the US (in011502) shapefile
+ // NOAA Major Roads of the US (rd011802) shapefile
+ road_flag++;
+ if (debug_level & 16)
+ fprintf(stderr,"*** Found some roads (FEATURE == *HIGHWAY*) ***\n");
+ break;
+ }
+ }
+ }
+ if (!(debug_level & 16) && (lake_flag || road_flag))
+ break;
+ }
+ else if (strcasecmp(szTitle, "LENGTH") == 0 ||
+ strcasecmp(szTitle, "RR") == 0 ||
+ strcasecmp(szTitle, "HUC") == 0 ||
+ strcasecmp(szTitle, "TYPE") == 0 ||
+ strcasecmp(szTitle, "SEGL") == 0 ||
+ strcasecmp(szTitle, "PMILE") == 0 ||
+ strcasecmp(szTitle, "ARBSUM") == 0 ||
+ strcasecmp(szTitle, "PNAME") == 0 ||
+ strcasecmp(szTitle, "OWNAME") == 0 ||
+ strcasecmp(szTitle, "PNMCD") == 0 ||
+ strcasecmp(szTitle, "OWNMCD") == 0 ||
+ strcasecmp(szTitle, "DSRR") == 0 ||
+ strcasecmp(szTitle, "DSHUC") == 0 ||
+ strcasecmp(szTitle, "USDIR") == 0) {
+ // NOAA Rivers of the US (rv14fe02) shapefile
+ // NOAA Rivers of the US Subset (rt14fe02) shapefile
+ river_flag++;
+ if (river_flag >= 14) {
+ if (debug_level & 16)
+ fprintf(stderr,"*** Found some rivers (NOAA Rivers of the US or Subset) ***\n");
+ else
+ break;
+ }
+ }
+ } /* ... end for (i = 0; i < fieldcount; i++) */
+#endif /* !WITH_DBFAWK */
+
+ // Search for specific record if we're doing alerts
+ if (weather_alert_flag && (alert->index == -1) ) {
+ int done = 0;
+#ifndef WITH_DBFAWK
+ char *string1;
+ char *string2;
+#endif /* !DBFAWK */
+
+ // Step through all records
+ for( i = 0; i < recordcount && !done; i++ ) {
+#ifdef WITH_DBFAWK
+ int keylen;
+
+ if (sig_info) {
+ char modified_title[50];
+
+ dbfawk_parse_record(sig_info->prog,hDBF,fld_info,i);
+
+ keylen = strlen(key);
+ if (debug_level & 16) {
+ static char old_key[4]; // Used to limit number of output lines in debug mode
+
+ if (strncmp(old_key, key, 4)) {
+ fprintf(stderr,"dbfawk alert parse: record %d key=%s\n",
+ i,key);
+ memcpy(old_key, key, sizeof(old_key));
+ }
+ }
+
+ xastir_snprintf(modified_title, sizeof(modified_title), "%s", alert->title);
+
+ // Tweak for RED_FLAG alerts: If RED_FLAG alert
+ // we've changed the 'Z' to an 'F' in our
+ // alert->title already. Change the 'F' back to a
+ // 'Z' temporarily (modified_title) for our
+ // compares.
+ //
+ if (modified_title[3] == 'F' && strncmp(alert->filename, "fz", 2) == 0) {
+ modified_title[3] = 'Z';
+ }
+
+ // If match using keylen number of chars, try the
+ // same match but using titlelen number of chars
+ if (strncmp(modified_title,key,keylen) == 0) {
+ int titlelen;
+
+ titlelen = strlen(modified_title);
+
+ // Try the same match with titlelen number of
+ // chars
+ if (strncmp(modified_title,key,titlelen) == 0) {
+
+ found_shape = i;
+ done++;
+ if (debug_level & 16) {
+ fprintf(stderr,"dbfawk alert found it: %d \n",i);
+ fprintf(stderr,"Title %s, key %s\n",modified_title,key);
+
+ }
+ }
+ else {
+ // Found a match using keylen number of
+ // characters, but it's not a match using
+ // titlelen number of characters.
+ if (debug_level & 16) {
+ fprintf(stderr,
+ "dbfawk alert: match w/keylen, not w/titlelen: %s=%d %s=%d\n",
+ key,
+ keylen,
+ modified_title,
+ titlelen);
+ fprintf(stderr,"Title %s, key %s\n",modified_title,key);
+ }
+ }
+ }
+ }
+#else /* !WITH_DBFAWK */
+ char *ptr;
+ switch (filenm[0]) {
+ case 'c': // County File
+ // Remember that there's only one place for
+ // internal storage of the DBF string. This is
+ // why this code is organized with two "if"
+ // statements.
+ if (fieldcount >= (search_field1 + 1) ) {
+ string1 = (char *)DBFReadStringAttribute(hDBF,i,search_field1);
+ if (!strncasecmp(search_param1,string1,2)) {
+ //fprintf(stderr,"Found state\n");
+ if (fieldcount >= (search_field2 + 1) ) {
+ string2 = (char *)DBFReadStringAttribute(hDBF,i,search_field2);
+ ptr = string2;
+ ptr += 2; // Skip past first two characters of FIPS code
+ if (!strncasecmp(search_param2,ptr,3)) {
+//fprintf(stderr,"Found it! %s\tShape: %d\n",string1,i);
+ done++;
+ found_shape = i;
+ }
+ }
+ }
+ }
+ break;
+ case 'w': // County Warning Area File
+ if (fieldcount >= (search_field1 + 1) ) {
+ string1 = (char *)DBFReadStringAttribute(hDBF,i,search_field1);
+ if ( !strncasecmp(search_param1,string1,strlen(string1))
+ && (strlen(string1) != 0) ) {
+//fprintf(stderr,"Found it! %s\tShape: %d\n",string1,i);
+ done++;
+ found_shape = i;
+ }
+ }
+ break;
+ case 'o': // Offshore Marine Area File
+ if (fieldcount >= (search_field1 + 1) ) {
+ string1 = (char *)DBFReadStringAttribute(hDBF,i,search_field1);
+ if ( !strncasecmp(search_param1,string1,strlen(string1))
+ && (strlen(string1) != 0) ) {
+//fprintf(stderr,"Found it! %s\tShape: %d\n",string1,i);
+ done++;
+ found_shape = i;
+ }
+ }
+ break;
+ case 'm': // Marine Area File
+ if (fieldcount >= (search_field1 + 1) ) {
+ string1 = (char *)DBFReadStringAttribute(hDBF,i,search_field1);
+ if ( !strncasecmp(search_param1,string1,strlen(string1))
+ && (strlen(string1) != 0) ) {
+//fprintf(stderr,"Found it! %s\tShape: %d\n",string1,i);
+ done++;
+ found_shape = i;
+ }
+ }
+ break;
+ case 'z': // Zone File
+ case 'f': // Fire zone file
+ if (fieldcount >= (search_field1 + 1) ) {
+ string1 = (char *)DBFReadStringAttribute(hDBF,i,search_field1);
+ if ( !strncasecmp(search_param1,string1,strlen(string1))
+ && (strlen(string1) != 0) ) {
+//fprintf(stderr,"Found it! %s\tShape: %d\n",string1,i);
+ done++;
+ found_shape = i;
+ }
+ }
+ default:
+ break;
+ }
+#endif /* !WITH_DBFAWK */
+ }
+ alert->index = found_shape; // Fill it in 'cuz we just found it
+ } /* if (weather_alert_flag && alert_index == -1)... */
+ else if (weather_alert_flag) {
+ // We've been here before and we already know the index into the
+ // file to fetch this particular shape.
+ found_shape = alert->index;
+ if (debug_level & 16)
+ fprintf(stderr,"wx_alert: found_shape = %d\n",found_shape);
+ }
+
+ //fprintf(stderr,"Found shape: %d\n", found_shape);
+
+ if (debug_level & 16)
+ fprintf(stderr,"Calling SHPOpen()\n");
+
+ // Open the .shx/.shp files for reading.
+ // These are the index and the vertice files.
+ hSHP = SHPOpen( file, "rb" );
+ if( hSHP == NULL ) {
+ fprintf(stderr,"draw_shapefile_map: SHPOpen(%s,\"rb\") failed.\n", file );
+ DBFClose( hDBF ); // Clean up open file descriptors
+
+#ifdef WITH_DBFAWK
+ dbfawk_free_info(fld_info);
+ if (sig_info != NULL && sig_info != dbfawk_default_sig && (sig_info->sig == NULL)) {
+ dbfawk_free_sigs(sig_info);
+ }
+#endif // WITH_DBFAWK
+
+ return;
+ }
+
+
+ // Get the extents of the map file
+ SHPGetInfo( hSHP, &nEntities, &nShapeType, adfBndsMin, adfBndsMax );
+
+
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ xastir_snprintf(status_text,
+ sizeof(status_text),
+ langcode ("BBARSTA039"),
+ short_filenm);
+ statusline(status_text,0); // Indexing ...
+
+ // We're indexing only. Save the extents in the index.
+ index_update_ll(filenm, // Filename only
+ adfBndsMin[1], // Bottom
+ adfBndsMax[1], // Top
+ adfBndsMin[0], // Left
+ adfBndsMax[0], // Right
+ 1000); // Default Map Level
+
+ DBFClose( hDBF ); // Clean up open file descriptors
+ SHPClose( hSHP );
+
+#ifdef WITH_DBFAWK
+ dbfawk_free_info(fld_info);
+ if (sig_info != NULL && sig_info != dbfawk_default_sig && (sig_info->sig == NULL)) {
+ dbfawk_free_sigs(sig_info);
+ }
+#endif // WITH_DBFAWK
+
+ return; // Done indexing this file
+ }
+ else {
+ xastir_snprintf(status_text,
+ sizeof(status_text),
+ langcode ("BBARSTA028"),
+ short_filenm);
+ statusline(status_text,0); // Loading ...
+ }
+
+#ifdef USE_RTREE
+ // We put this section AFTER the code that determines whether we're merely
+ // indexing, so we don't bother to generate rtrees unless we're really
+ // drawing the file.
+ si=NULL;
+
+ // Don't bother even looking at the hash if this shapefile is completely
+ // contained in the current viewport. We'll have to read every shape
+ // in it anyway, and all we'd be doing is extra work searching the
+ // RTree
+ if (!map_inside_viewport_lat_lon(adfBndsMin[1],
+ adfBndsMax[1],
+ adfBndsMin[0],
+ adfBndsMax[0])) {
+ si = get_shp_from_hash(file);
+ if (!si) {
+ // we don't have what we need, so generate the index and make
+ // the hashtable entry
+ add_shp_to_hash(file,hSHP); // this will index all the shapes in
+ // an RTree and save the root in a
+ // shpinfo structure
+ si=get_shp_from_hash(file); // now get that structure
+ if (!si) {
+ fprintf(stderr,
+ "Panic! added %s, lost it already!\n",file);
+ exit(1);
+ }
+ }
+ }
+ // we need this for the rtree search
+ get_viewport_lat_lon(&rXmin, &rYmin, &rXmax, &rYmax);
+ viewportRect.boundary[0] = (RectReal) rXmin;
+ viewportRect.boundary[1] = (RectReal) rYmin;
+ viewportRect.boundary[2] = (RectReal) rXmax;
+ viewportRect.boundary[3] = (RectReal) rYmax;
+#endif // USE_RTREE
+
+ switch ( nShapeType ) {
+ case SHPT_POINT:
+ sType = "Point";
+ break;
+
+ case SHPT_POINTZ:
+ sType = "3D Point";
+ break;
+
+ case SHPT_ARC:
+ sType = "Polyline";
+ break;
+
+ case SHPT_ARCZ:
+ sType = "3D Polyline";
+ break;
+
+ case SHPT_POLYGON:
+ sType = "Polygon";
+ break;
+
+ case SHPT_POLYGONZ:
+ sType = "3D Polygon";
+ break;
+
+ case SHPT_MULTIPOINT:
+ fprintf(stderr,"Multi-Point Shapefile format not implemented: %s\n",file);
+ sType = "MultiPoint";
+ DBFClose( hDBF ); // Clean up open file descriptors
+ SHPClose( hSHP );
+
+#ifdef WITH_DBFAWK
+ dbfawk_free_info(fld_info);
+ if (sig_info != NULL && sig_info != dbfawk_default_sig && (sig_info->sig == NULL)) {
+ dbfawk_free_sigs(sig_info);
+ }
+#endif // WITH_DBFAWK
+
+ return; // Multipoint type. Not implemented yet.
+ break;
+
+ default:
+ DBFClose( hDBF ); // Clean up open file descriptors
+ SHPClose( hSHP );
+
+#ifdef WITH_DBFAWK
+ dbfawk_free_info(fld_info);
+ if (sig_info != NULL && sig_info != dbfawk_default_sig && (sig_info->sig == NULL)) {
+ dbfawk_free_sigs(sig_info);
+ }
+#endif // WITH_DBFAWK
+
+ return; // Unknown type. Don't know how to process it.
+ break;
+ }
+
+ if (debug_level & 16)
+ fprintf(stderr,"%s(%d), %d Records in file\n",sType,nShapeType,nEntities);
+
+ if (debug_level & 16)
+ fprintf(stderr,"File Bounds: (%15.10g,%15.10g)\n\t(%15.10g,%15.10g)\n",
+ adfBndsMin[0], adfBndsMin[1], adfBndsMax[0], adfBndsMax[1] );
+
+ // Check the bounding box for this shapefile. If none of the
+ // file is within our viewport, we can skip the entire file.
+
+ if (debug_level & 16)
+ fprintf(stderr,"Calling map_visible_lat_lon on the entire shapefile\n");
+
+ if (! map_visible_lat_lon( adfBndsMin[1], // Bottom
+ adfBndsMax[1], // Top
+ adfBndsMin[0], // Left
+ adfBndsMax[0]) ) { // Right
+ if (debug_level & 16)
+ fprintf(stderr,"No shapes within viewport. Skipping file...\n");
+
+ DBFClose( hDBF ); // Clean up open file descriptors
+ SHPClose( hSHP );
+
+#ifdef WITH_DBFAWK
+ dbfawk_free_info(fld_info);
+ if (sig_info != NULL && sig_info != dbfawk_default_sig && (sig_info->sig == NULL)) {
+ dbfawk_free_sigs(sig_info);
+ }
+#endif // WITH_DBFAWK
+
+ return; // The file contains no shapes in our viewport
+ }
+
+
+ // Set a default line width for all maps. This will most likely
+ // be modified for particular maps in later code.
+ (void)XSetLineAttributes(XtDisplay(w), gc, 0, LineSolid, CapButt,JoinMiter);
+
+
+ // NOTE: Setting the color here and in the "else" may not stick if we do more
+ // complex drawing further down like a SteelBlue lake with a black boundary,
+ // or if we have labels turned on which resets our color to black.
+ if (weather_alert_flag) { /* XXX */
+ char xbm_path[MAX_FILENAME];
+ unsigned int _w, _h;
+ int _xh, _yh;
+ int ret_val;
+ FILE *alert_fp = NULL;
+ char xbm_filename[MAX_FILENAME];
+
+
+ // This GC is used for weather alerts (writing to the
+ // pixmap: pixmap_alerts) and _was_ used for beam_heading
+ // rays, but no longer is.
+ (void)XSetForeground (XtDisplay (w), gc_tint, colors[(int)alert_color]);
+
+ // N7TAP: No more tinting as that would change the color of the alert, losing that information.
+ (void)XSetFunction(XtDisplay(w), gc_tint, GXcopy);
+ /*
+ Options are:
+ GXclear 0 (Don't use)
+ GXand src AND dst (Darker colors, black can result from overlap)
+ GXandReverse src AND (NOT dst) (Darker colors)
+ GXcopy src (Don't use)
+ GXandInverted (NOT src) AND dst (Pretty colors)
+ GXnoop dst (Don't use)
+ GXxor src XOR dst (Don't use, overlapping areas cancel each other out)
+ GXor src OR dst (More pastel colors, too bright?)
+ GXnor (NOT src) AND (NOT dst) (Darker colors, very readable)
+ GXequiv (NOT src) XOR dst (Bright, very readable)
+ GXinvert (NOT dst) (Don't use)
+ GXorReverse src OR (NOT dst) (Bright, not as readable as others)
+ GXcopyInverted (NOT src) (Don't use)
+ GXorInverted (NOT src) OR dst (Bright, not very readable)
+ GXnand (NOT src) OR (NOT dst) (Bright, not very readable)
+ GXset 1 (Don't use)
+ */
+
+
+ // Note that we can define more alert files for other countries. They just need to match
+ // the alert text that comes along in the NWS packet.
+ // Current alert files we have defined:
+ // winter_storm.xbm *
+ // snow.xbm
+ // winter_weather.xbm *
+ // flood.xbm
+ // torndo.xbm *
+ // red_flag.xbm
+ // wind.xbm
+ // alert.xbm (Used if no match to another filename)
+
+ // Alert texts we receive:
+ // FLOOD
+ // SNOW
+ // TORNDO
+ // WIND
+ // WINTER_STORM
+ // WINTER_WEATHER
+ // RED_FLAG
+ // SVRTSM (no file defined for this yet)
+ // Many others.
+
+ // Attempt to open the alert filename: <alert_tag>.xbm (lower-case alert text)
+ // to detect whether we have a matching filename for our alert text.
+ xastir_snprintf(xbm_filename, sizeof(xbm_filename), "%s", alert->alert_tag);
+
+ // Convert the filename to lower-case
+ to_lower(xbm_filename);
+
+ // Construct the complete path/filename
+ xastir_snprintf(xbm_path, sizeof(xbm_path), "%s/%s.xbm", SYMBOLS_DIR, xbm_filename);
+
+ // Try opening the file
+ alert_fp = fopen(xbm_path, "rb");
+ if (alert_fp == NULL) {
+ // Failed to find a matching file: Instead use the "alert.xbm" file
+ xastir_snprintf(xbm_path, sizeof(xbm_path), "%s/%s", SYMBOLS_DIR, "alert.xbm");
+ } else {
+ // Success: Close the file pointer
+ fclose(alert_fp);
+ }
+
+ /* XXX - need to add SVRTSM */
+
+
+ (void)XSetLineAttributes(XtDisplay(w), gc_tint, 0, LineSolid, CapButt,JoinMiter);
+ XFreePixmap(XtDisplay(w), pixmap_wx_stipple);
+ ret_val = XReadBitmapFile(XtDisplay(w),
+ DefaultRootWindow(XtDisplay(w)),
+ xbm_path,
+ &_w,
+ &_h,
+ &pixmap_wx_stipple,
+ &_xh,
+ &_yh);
+
+ if (ret_val != 0) {
+ fprintf(stderr,"XReadBitmapFile() failed: Bitmap not found? %s\n",xbm_path);
+
+ // We shouldn't exit on this one, as it's not so severe
+ // that we should kill Xastir. I've seen this happen
+ // after very long runtimes though, so perhaps there's a
+ // problem somewhere in the X11 server and/or it's
+ // caching?
+ //
+ //exit(1);
+ }
+ else {
+ // We successfully loaded the bitmap, so set the stipple
+ // properly to use it. Skip this part if we were
+ // unsuccessful at loading the bitmap.
+ (void)XSetStipple(XtDisplay(w), gc_tint, pixmap_wx_stipple);
+ }
+
+ } /* ...end if (weather_alert_flag) */
+ else { /* !weather_alert_flag */
+// Are these actually used anymore by the code? Colors get set later
+// when we know more about what we're dealing with.
+#ifndef WITH_DBFAWK
+ if (lake_flag || river_flag)
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x1a]); // Steel Blue
+ else if (path_flag)
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black
+ else if (railroad_flag)
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x01]); // purple
+ else if (city_flag || school_flag)
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x0e]); // yellow
+ else
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black
+#endif /* !WITH_DBFAWK */
+ }
+
+ // Now that we have the file open, we can read out the structures.
+ // We can handle Point, PolyLine and Polygon shapefiles at the moment.
+
+
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ DBFClose( hDBF ); // Clean up open file descriptors
+ SHPClose( hSHP );
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+
+#ifdef WITH_DBFAWK
+ dbfawk_free_info(fld_info);
+ if (sig_info != NULL && sig_info != dbfawk_default_sig && (sig_info->sig == NULL)) {
+ dbfawk_free_sigs(sig_info);
+ }
+#endif // WITH_DBFAWK
+
+ return;
+ }
+
+#ifdef USE_RTREE
+ // Now instead of looping over all the shapes, search for the ones that
+ // are in our viewport and only loop over those
+ //fprintf(stderr,"Deciding how to process this file...\n");
+ if (weather_alert_flag) { // We're drawing _one_ weather alert shape
+ //fprintf(stderr," weather alert flag set...\n");
+ if (found_shape != -1) { // Found the record
+ //fprintf(stderr," found_shape set...\n");
+ // just in case we haven't drawn any real maps yet...
+ if (!RTree_hitarray) {
+ //fprintf(stderr," mallocing hitarray...\n");
+ RTree_hitarray = (int *)malloc(sizeof(int)*1000);
+ RTree_hitarray_size=1000;
+ }
+ CHECKMALLOC(RTree_hitarray);
+ RTree_hitarray[0]=found_shape;
+ //fprintf(stderr," %s contains alert\n",file);
+ nhits=1;
+ }
+ else { // Didn't find the record
+ //fprintf(stderr," found_shape is -1...\n");
+ nhits=0;
+ }
+ }
+ else { // Draw an entire Shapefile map
+ //fprintf(stderr," weather_alert_flag not set...\n");
+ if (si) {
+ //fprintf(stderr," si is 0x%lx...\n",(unsigned long int) si);
+ RTree_hitarray_index=0;
+ // the callback will be executed every time the search finds a
+ // shape whose bounding box overlaps the viewport.
+ nhits = Xastir_RTreeSearch(si->root, &viewportRect,
+ (void *)RTreeSearchCallback, 0);
+ //fprintf(stderr,"Found %d hits in %s\n",nhits,file);
+ } else {
+ //fprintf(stderr," si not set ...\n");
+ // we read the entire shapefile
+ nhits=nEntities;
+ // fprintf(stderr," %s entirely in view, with %d shapes\n",file,nhits);
+ }
+ }
+ //fprintf(stderr," Done with decision, nhits is %d\n",nhits);
+#else // USE_RTREE
+ if (weather_alert_flag) { // We're drawing _one_ weather alert shape
+ if (found_shape != -1) { // Found the record
+ start_record = found_shape;
+ end_record = found_shape + 1;
+ }
+ else { // Didn't find the record
+ start_record = 0;
+ end_record = 0;
+ }
+ }
+ else { // Draw an entire Shapefile map
+ start_record = 0;
+ end_record = nEntities;
+ }
+#endif // USE_RTREE
+
+#ifdef USE_RTREE
+ // only iterate over the hits found by RTreeSearch, not all of them
+ for (RTree_hitarray_index=0; RTree_hitarray_index<nhits;
+ RTree_hitarray_index++) {
+#else // USE_RTREE
+
+ // Here's where we actually iterate through the entire file, drawing
+ // each structure as we find it.
+ for (structure = start_record; structure < end_record; structure++) {
+#endif // USE_RTREE
+ int skip_it = 0;
+ int skip_label = 0;
+
+
+ // Call HandlePendingEvents() every XX objects so that we
+ // can interrupt map drawing if necessary. Keep this at a
+ // power of two for speed. Bigger numbers speed up map
+ // drawing at the expense of being able to interrupt map
+ // drawing quickly. HandlePendingEvents() drops to about
+ // 0.5% CPU at 64 (according to gprof). That appears to be
+ // the break-even point where CPU is minimal.
+ //
+#ifdef USE_RTREE
+ if ( (RTree_hitarray_index % 64) == 0 ) {
+#else
+ if ( (structure % 64) == 0 ) {
+#endif
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ DBFClose( hDBF ); // Clean up open file descriptors
+ SHPClose( hSHP );
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+#ifdef WITH_DBFAWK
+ dbfawk_free_info(fld_info);
+ if (sig_info != NULL && sig_info != dbfawk_default_sig && (sig_info->sig == NULL)) {
+ dbfawk_free_sigs(sig_info);
+ }
+#endif // WITH_DBFAWK
+ return;
+ }
+ }
+
+
+#ifdef USE_RTREE
+ if (si) {
+ structure=RTree_hitarray[RTree_hitarray_index];
+ } else if ((weather_alert_flag && found_shape!=-1)) {
+ structure = RTree_hitarray[0];
+ } else {
+ structure = RTree_hitarray_index;
+ }
+#endif // USE_RTREE
+
+ // Have had segfaults before at the SHPReadObject() call
+ // when the Shapefile was corrupted.
+ //fprintf(stderr,"Before SHPReadObject:%d\n",structure);
+
+ object = SHPReadObject( hSHP, structure ); // Note that each structure can have multiple rings
+
+ //fprintf(stderr,"After SHPReadObject\n");
+
+ if (object == NULL)
+ continue; // Skip this iteration, go on to the next
+
+ // Fill in the boundary variables in the alert record. We use
+ // this info in load_alert_maps() to determine which alerts are
+ // within our view, without having to open up the shapefiles to
+ // get this info (faster).
+ if (weather_alert_flag) {
+ alert->top_boundary = object->dfYMax;
+ alert->left_boundary = object->dfXMin;
+ alert->bottom_boundary = object->dfYMin;
+ alert->right_boundary = object->dfXMax;
+ }
+
+ // Here we check the bounding box for this shape against our
+ // current viewport. If we can't see it, don't draw it.
+
+// if (debug_level & 16)
+// fprintf(stderr,"Calling map_visible_lat_lon on a shape\n");
+
+ if ( map_visible_lat_lon( object->dfYMin, // Bottom
+ object->dfYMax, // Top
+ object->dfXMin, // Left
+ object->dfXMax) ) { // Right
+
+ const char *temp;
+#ifndef WITH_DBFAWK
+ char temp2[100];
+#endif /*!WITH_DBFAWK*/
+ int jj;
+ int x0 = 0; // Used for computing label rotation
+ int x1 = 0;
+ int y0 = 0;
+ int y1 = 0;
+
+
+ if (debug_level & 16) {
+ fprintf(stderr,"Shape %d is visible, drawing it.", structure);
+ fprintf(stderr," Parts in shape: %d\n", object->nParts ); // Number of parts in this structure
+ }
+
+ if (debug_level & 16) {
+ // Print the field contents
+ for (jj = 0; jj < fieldcount; jj++) {
+ if (fieldcount >= (jj + 1) ) {
+ temp = DBFReadStringAttribute( hDBF, structure, jj );
+ if (temp != NULL) {
+ fprintf(stderr,"%s, ", temp);
+ }
+ }
+ }
+ fprintf(stderr,"\n");
+ fprintf(stderr,"Done with field contents\n");
+ }
+#ifdef WITH_DBFAWK
+ if (sig_info) {
+ dbfawk_parse_record(sig_info->prog,hDBF,fld_info,structure);
+ if (debug_level & 16) {
+ fprintf(stderr,"dbfawk parse of structure %d: ",structure);
+ fprintf(stderr,"color=%d ",color);
+ fprintf(stderr,"lanes=%d ",lanes);
+ fprintf(stderr,"name=%s ",name);
+ fprintf(stderr,"key=%s ",key);
+ fprintf(stderr,"symbol=%s ",sym);
+ fprintf(stderr,"filled=%d ",filled);
+ fprintf(stderr,"fill_style=%d ",fill_style);
+ fprintf(stderr,"fill_color=%d ",fill_color);
+ fprintf(stderr,"fill_stipple=%d ",fill_stipple);
+ fprintf(stderr,"pattern=%d ",pattern);
+ fprintf(stderr,"display_level=%d ",display_level);
+ fprintf(stderr,"label_level=%d ",label_level);
+ fprintf(stderr,"label_color=%d\n",label_color);
+ // fprintf(stderr,"layer=%d\n",layer);
+ }
+ /* set attributes */
+ (void)XSetForeground(XtDisplay(w), gc, colors[color]);
+
+
+ // Let the user decide whether to make the map
+ // filled or unfilled via the Map Properties dialog.
+ // This allows things like the NOAA counties map to
+ // be used as a base map (filled) or as a vector
+ // overlay map at the user's discretion. The
+ // choices available are:
+ // 0: Global No-Fill. Don't fill any polygons.
+ // 1: Global Fill. Fill all polygons.
+ // 2: Auto. dbfawk file, if present, takes over control.
+ //
+ if (debug_level & 16) {
+ fprintf(stderr," draw_filled is %d\n",draw_filled_orig);
+ }
+ switch (draw_filled_orig) {
+
+ case 0: // Global No-Fill (Vector)
+ // Do nothing, user has chosen Global
+ // No_Fill for this map. The draw_filled
+ // variable takes precedence.
+ break;
+
+ case 1: // Global Fill
+ // Do nothing, user has chosen Global
+ // Fill for this map. The draw_filled
+ // variable takes precedence.
+ break;
+
+ case 2: // Auto
+ default:
+ // User has chosen Auto Fill for this map,
+ // so the Dbfawk file controls the fill
+ // property. If no dbfawk file, "filled"
+ // will take on the default setting listed
+ // in dbfawk_default_rules[] above.
+ draw_filled = filled;
+ break;
+ }
+
+
+ if (weather_alert_flag) { /* XXX will this fix WX alerts? */
+ fill_style = FillStippled;
+ }
+
+ skip_it = (map_color_levels && (scale_y > display_level));
+ skip_label = (map_color_levels && (scale_y > label_level));
+
+ }
+#else /* WITH_DBFAWK */
+ if (draw_filled == 2) {
+ // "Auto" fill was chosen, but dbfawk support is not
+ // compiled in. Default to vector mode (no polygon
+ // fills)
+ draw_filled = 0;
+ }
+#endif /* WITH_DBFAWK */
+
+ /* This case statement is a mess. Lots of common code could be
+ used before the case but currently isn't */
+
+ switch ( nShapeType ) {
+
+
+ case SHPT_POINT:
+ case SHPT_POINTZ:
+ // We hit this case once for each point shape in
+ // the file, iff that shape is within our
+ // viewport.
+
+
+ if (debug_level & 16)
+ fprintf(stderr,"Found Point Shapefile\n");
+
+ // Read each point, place a label there, and an optional symbol
+ //object->padfX
+ //object->padfY
+ //object->padfZ
+
+// if ( mapshots_labels_flag
+// && map_labels
+// && (fieldcount >= 3) ) {
+
+ if (!skip_it) { // Need a bracket so we can define
+ // some local variables.
+ const char *temp = NULL;
+ int ok = 1;
+ int temp_ok;
+
+#ifdef WITH_DBFAWK
+ if (map_labels)
+ temp = name;
+#else /* !WITH_DBFAWK */
+ // If labels are enabled and we have enough
+ // fields in the .dbf file, read the label.
+ if (map_labels && fieldcount >= 1) {
+ // Snag the label from the .dbf file
+ temp = DBFReadStringAttribute( hDBF, structure, 0 );
+ }
+#endif /* !WITH_DBFAWK */
+ // Convert point to Xastir coordinates
+ temp_ok = convert_to_xastir_coordinates(&my_long,
+ &my_lat,
+ (float)object->padfX[0],
+ (float)object->padfY[0]);
+ //fprintf(stderr,"%ld %ld\n", my_long, my_lat);
+
+ if (!temp_ok) {
+ fprintf(stderr,"draw_shapefile_map1: Problem converting from lat/lon\n");
+ ok = 0;
+ x = 0;
+ y = 0;
+ }
+ else {
+ // Convert to screen coordinates. Careful
+ // here! The format conversions you'll need
+ // if you try to compress this into two
+ // lines will get you into trouble.
+ x = my_long - NW_corner_longitude;
+ y = my_lat - NW_corner_latitude;
+ x = x / scale_x;
+ y = y / scale_y;
+ }
+
+ if (ok == 1) {
+ char symbol_table = '/';
+ char symbol_id = '.'; /* small x */
+ char symbol_over = ' ';
+
+ // Fine-tuned the location here so that
+ // the middle of the 'X' would be at the
+ // proper pixel.
+#ifdef WITH_DBFAWK
+ if (*sym)
+ symbol(w,0,sym[0],sym[1],sym[2],pixmap,1,x-10,y-10,' ');
+ else
+ symbol(w, 0, symbol_table, symbol_id, symbol_over, pixmap, 1, x-10, y-10, ' ');
+#else // WITH_DBFAWK
+ symbol(w, 0, symbol_table, symbol_id, symbol_over, pixmap, 1, x-10, y-10, ' ');
+#endif //WITH_DBFAWK
+
+ // Fine-tuned this string so that it is
+ // to the right of the 'X' and aligned
+ // nicely.
+ if (map_labels && !skip_label) {
+// Labeling of points done here
+ draw_nice_string(w, pixmap, 0, x+10, y+5, (char*)temp, 0xf, 0x10, strlen(temp));
+ //(void)draw_label_text ( w, x, y, strlen(temp), colors[label_color], (char *)temp);
+ //(void)draw_rotated_label_text (w, 90, x+10, y, strlen(temp), colors[label_color], (char *)temp);
+ }
+ }
+ }
+ break;
+
+
+
+ case SHPT_ARC:
+ case SHPT_ARCZ:
+ // We hit this case once for each polyline shape
+ // in the file, iff at least part of that shape
+ // is within our viewport.
+
+
+ if (debug_level & 16)
+ fprintf(stderr,"Found Polylines\n");
+
+// Draw the PolyLines themselves:
+
+ // Default in case we forget to set the line
+ // width later:
+ (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineSolid, CapButt,JoinMiter);
+
+
+#ifdef WITH_DBFAWK
+ if (!skip_it) {
+ (void)XSetForeground(XtDisplay(w), gc, colors[color]);
+ (void)XSetLineAttributes(XtDisplay (w), gc,
+ (lanes)?lanes:1,
+ pattern,
+ CapButt,JoinMiter);
+ }
+#else /*!WITH_DBFAWK*/
+// Set up width and zoom level for roads
+ if (road_flag) {
+ int lanes = 0;
+ int dashed_line = 0;
+
+ if ( mapshots_labels_flag && (fieldcount >= 9) ) {
+ const char *temp;
+
+ temp = DBFReadStringAttribute( hDBF, structure, 8 ); // CFCC Field
+ switch (temp[1]) {
+ case '1': // A1? = Primary road or interstate highway
+ if (map_color_levels && scale_y > 16384)
+ skip_it++;
+ if (map_color_levels && scale_y > 16384)
+ skip_label++;
+ lanes = 4;
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x04]); // brown
+ break;
+ case '2': // A2? = Primary road w/o limited access, US highways
+ if (map_color_levels && scale_y > 8192)
+ skip_it++;
+ if (map_color_levels && scale_y > 8192)
+ skip_label++;
+ lanes = 3;
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black
+ break;
+ case '3': // A3? = Secondary road & connecting road, state highways
+ // Skip the road if we're above this zoom level
+ if (map_color_levels && scale_y > 256)
+ skip_it++;
+ if (map_color_levels && scale_y > 256)
+ skip_label++;
+ lanes = 2;
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black
+ switch (temp[2]) {
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ break;
+ case '7':
+ case '8':
+ default:
+ if (map_color_levels && scale_y > 128)
+ skip_label++;
+ break;
+ }
+ break;
+ case '4': // A4? = Local, neighborhood & rural roads, city streets
+ // Skip the road if we're above this zoom level
+ if (map_color_levels && scale_y > 96)
+ skip_it++;
+ // Skip labels above this zoom level to keep things uncluttered
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x28]); // gray35
+ break;
+ case '5': // A5? = Vehicular trail passable only by 4WD vehicle
+ // Skip the road if we're above this zoom level
+ if (map_color_levels && scale_y > 64)
+ skip_it++;
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+ dashed_line++;
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x28]); // gray35
+ break;
+ case '6': // A6? = Cul-de-sac, traffic circles, access ramp,
+ // service drive, ferry crossing
+ if (map_color_levels && scale_y > 64)
+ skip_it++;
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+
+ switch (temp[2]) {
+ case '5': // Ferry crossing
+ lanes = 2;
+ dashed_line++;
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x08]); // black
+ break;
+ default:
+ lanes = 1;
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x28]); // gray35
+ break;
+ }
+
+ break;
+ case '7': // A7? = Walkway or pedestrian trail, stairway,
+ // alley, driveway or service road
+ // Skip the road if we're above this zoom level
+ if (map_color_levels && scale_y > 64)
+ skip_it++;
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+ dashed_line++;
+
+ switch (temp[2]) {
+ case '1': // Walkway or trail for pedestrians
+ case '2': // Stairway or stepped road for pedestrians
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x0c]); // red
+ break;
+ default:
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x28]); // gray35
+ break;
+ }
+
+ break;
+ default:
+ lanes = 1;
+ if (map_color_levels && scale_y > 64)
+ skip_it++;
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x28]); // gray35
+ break;
+ }
+ }
+ else { // Must not be a mapshots or ESRI Tiger map
+ if (fieldcount >= 7) { // Need at least 7 fields if we're snagging #6, else segfault
+ lanes = DBFReadIntegerAttribute( hDBF, structure, 6 );
+
+ // In case we guess wrong on the
+ // type of file and the lanes are
+ // really out of bounds:
+ if (lanes < 1 || lanes > 10) {
+ //fprintf(stderr,"lanes = %d\n",lanes);
+ lanes = 1;
+ }
+ }
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x28]); // gray35
+ }
+ if (lanes != (int)NULL) {
+ if (dashed_line) {
+ (void)XSetLineAttributes (XtDisplay (w), gc, 1, LineOnOffDash, CapButt,JoinMiter);
+ }
+ else {
+ (void)XSetLineAttributes (XtDisplay (w), gc, lanes, LineSolid, CapButt,JoinMiter);
+ }
+ }
+ else {
+ (void)XSetLineAttributes (XtDisplay (w), gc, 1, LineSolid, CapButt,JoinMiter);
+ }
+ } // End of road flag portion
+
+// Set up width and zoom levels for water
+ else if (river_flag || lake_flag) {
+ int lanes = 0;
+ int dashed_line = 0;
+ int glacier_flag = 0;
+
+ if ( mapshots_labels_flag && (fieldcount >= 9) ) {
+ const char *temp;
+
+ temp = DBFReadStringAttribute( hDBF, structure, 8 ); // CFCC Field
+ switch (temp[1]) {
+ case '0': // H0? = Water feature/shoreline
+ // Skip the vector if we're above this zoom level
+ if (map_color_levels && scale_y > 4096)
+ skip_it++;
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 0;
+
+ switch (temp[2]) {
+ case '2': // Intermittent
+ dashed_line++;
+ // Skip the vector if we're above this zoom level
+ if (map_color_levels && scale_y > 64)
+ skip_it++;
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ break;
+ default:
+ break;
+ }
+
+ break;
+ case '1':
+ // Skip the vector if we're above this zoom level
+ if (map_color_levels && scale_y > 256)
+ skip_it++;
+ if (map_color_levels && scale_y > 128)
+ skip_label++;
+ switch (temp[2]) {
+ case '0':
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+ break;
+ case '1':
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+ break;
+ case '2':
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+ dashed_line++;
+ break;
+ case '3':
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+ break;
+ default:
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+ break;
+ }
+ break;
+ case '2':
+ // Skip the vector if we're above this zoom level
+ if (map_color_levels && scale_y > 256)
+ skip_it++;
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+
+ switch (temp[2]) {
+ case '2': // Intermittent
+ dashed_line++;
+ break;
+ default:
+ break;
+ }
+
+ break;
+ case '3':
+ // Skip the vector if we're above this zoom level
+ if (map_color_levels && scale_y > 256)
+ skip_it++;
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+
+ switch (temp[2]) {
+ case '2': // Intermittent
+ dashed_line++;
+ break;
+ default:
+ break;
+ }
+
+ break;
+ case '4':
+ // Skip the vector if we're above this zoom level
+ if (map_color_levels && scale_y > 256)
+ skip_it++;
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+
+ switch (temp[2]) {
+ case '2': // Intermittent
+ dashed_line++;
+ break;
+ default:
+ break;
+ }
+
+ break;
+ case '5':
+ // Skip the vector if we're above this zoom level
+ if (map_color_levels && scale_y > 256)
+ skip_it++;
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+ break;
+ case '6':
+ // Skip the vector if we're above this zoom level
+ if (map_color_levels && scale_y > 256)
+ skip_it++;
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+ break;
+ case '7': // Nonvisible stuff. Don't draw these
+ skip_it++;
+ skip_label++;
+ break;
+ case '8':
+ // Skip the vector if we're above this zoom level
+ if (map_color_levels && scale_y > 256)
+ skip_it++;
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+
+ switch (temp[2]) {
+ case '1': // Glacier
+ glacier_flag++;
+ break;
+ default:
+ break;
+ }
+
+ break;
+ default:
+ // Skip the vector if we're above this zoom level
+ if (map_color_levels && scale_y > 256)
+ skip_it++;
+ if (map_color_levels && scale_y > 16)
+ skip_label++;
+ lanes = 1;
+ break;
+ }
+ if (dashed_line) {
+ (void)XSetLineAttributes (XtDisplay (w), gc, lanes, LineOnOffDash, CapButt,JoinMiter);
+ }
+ else {
+ (void)XSetLineAttributes (XtDisplay (w), gc, lanes, LineSolid, CapButt,JoinMiter);
+ }
+ }
+ else { // We don't know how wide to make it, not a mapshots or ESRI Tiger maps
+ if (dashed_line) {
+ (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineOnOffDash, CapButt,JoinMiter);
+ }
+ else {
+ (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineSolid, CapButt,JoinMiter);
+ }
+ }
+ if (glacier_flag)
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x0f]); // white
+ else
+ (void)XSetForeground(XtDisplay(w), gc, colors[(int)0x1a]); // Steel Blue
+ } // End of river_flag/lake_flag code
+
+ else { // Set default line width, use whatever color is already defined by this point.
+ (void)XSetLineAttributes (XtDisplay (w), gc, 0, LineSolid, CapButt,JoinMiter);
+ }
+#endif /* !WITH_DBFAWK */
+
+//WE7U
+// I'd like to be able to change the color of each GPS track for
+// each team in the field. It'll help to differentiate the tracks
+// where they happen to cross.
+/* XXX - WITH_DBFAWK should handle this case too. Need to add a color
+ attribute to the generated dbf file */
+ if (gps_flag) {
+ int jj;
+ int done = 0;
+
+
+ // Fill in the label we'll use later
+ xastir_snprintf(gps_label,
+ sizeof(gps_label), "%s",
+ filename);
+
+ // Knock off the "_Color.shp" portion of the
+ // label. Find the last underline character
+ // and change it to an end-of-string.
+ jj = strlen(gps_label);
+ while ( !done && (jj > 0) ) {
+ if (gps_label[jj] == '_') {
+ gps_label[jj] = '\0'; // Terminate it here
+ done++;
+ }
+ jj--;
+ }
+
+
+ // Check for a color in the filename: i.e.
+ // "Team2_Track_Red.shp"
+ if (strstr(filenm,"_Red.shp")) {
+ gps_color = 0x0c; // Red
+ }
+ else if (strstr(filenm,"_Green.shp")) {
+// gps_color = 0x64; // ForestGreen
+ gps_color = 0x23; // Area Green Hi
+ }
+ else if (strstr(filenm,"_Black.shp")) {
+ gps_color = 0x08; // black
+ }
+ else if (strstr(filenm,"_White.shp")) {
+ gps_color = 0x0f; // white
+ }
+ else if (strstr(filenm,"_Orange.shp")) {
+// gps_color = 0x06; // orange
+// gps_color = 0x19; // orange2
+// gps_color = 0x41; // DarkOrange3 (good medium orange)
+ gps_color = 0x62; // orange3 (brighter)
+ }
+ else if (strstr(filenm,"_Blue.shp")) {
+ gps_color = 0x03; // cyan
+ }
+ else if (strstr(filenm,"_Yellow.shp")) {
+ gps_color = 0x0e; // yellow
+ }
+ else if (strstr(filenm,"_Purple.shp")) {
+ gps_color = 0x0b; // mediumorchid
+ }
+ else { // Default color
+ gps_color = 0x0c; // Red
+ }
+
+ // Set the color for the arc's
+ (void)XSetForeground(XtDisplay(w), gc, colors[gps_color]);
+
+ // Make the track nice and wide: Easy to
+ // see.
+// (void)XSetLineAttributes (XtDisplay (w), gc, 3, LineSolid, CapButt,JoinMiter);
+ (void)XSetLineAttributes (XtDisplay (w), gc, 3, LineOnOffDash, CapButt,JoinMiter);
+// (void)XSetLineAttributes (XtDisplay (w), gc, 3, LineDoubleDash, CapButt,JoinMiter);
+
+ } // End of gps flag portion
+
+
+ index = 0; // Index into our own points array.
+ // Tells how many points we've
+ // collected so far.
+
+
+ if (ok_to_draw && !skip_it) {
+
+ // Read the vertices for each vector now
+
+ for (ring = 0; ring < object->nVertices; ring++ ) {
+ int temp_ok;
+
+ ok = 1;
+
+ //fprintf(stderr,"\t%d:%g %g\t", ring, object->padfX[ring], object->padfY[ring] );
+ // Convert to Xastir coordinates
+ temp_ok = convert_to_xastir_coordinates(&my_long,
+ &my_lat,
+ (float)object->padfX[ring],
+ (float)object->padfY[ring]);
+ //fprintf(stderr,"%ld %ld\n", my_long, my_lat);
+
+ if (!temp_ok) {
+ fprintf(stderr,"draw_shapefile_map2: Problem converting from lat/lon\n");
+ ok = 0;
+ x = 0;
+ y = 0;
+ }
+ else {
+ // Convert to screen coordinates. Careful
+ // here! The format conversions you'll need
+ // if you try to compress this into two
+ // lines will get you into trouble.
+ x = my_long - NW_corner_longitude;
+ y = my_lat - NW_corner_latitude;
+ x = x / scale_x;
+ y = y / scale_y;
+
+
+ // Save the endpoints of the first line
+ // segment for later use in label rotation
+ if (ring == 0) {
+ // Save the first set of screen coordinates
+ x0 = (int)x;
+ y0 = (int)y;
+ }
+ else if (ring == 1) {
+ // Save the second set of screen coordinates
+ x1 = (int)x;
+ y1 = (int)y;
+ }
+ }
+
+ if (ok == 1) {
+ // XDrawLines uses 16-bit unsigned
+ // integers (shorts). Make sure we
+ // stay within the limits.
+ points[index].x = l16(x);
+ points[index].y = l16(y);
+ //fprintf(stderr,"%d %d\t", points[index].x, points[index].y);
+ index++;
+ }
+ if (index > high_water_mark_index)
+ high_water_mark_index = index;
+
+ if (index >= MAX_MAP_POINTS) {
+ index = MAX_MAP_POINTS - 1;
+ fprintf(stderr,"Trying to overrun the points array: SHPT_ARC, index=%d\n",index);
+ }
+ } // End of "for" loop for polyline points
+ }
+
+
+ if (ok_to_draw && !skip_it) {
+ (void)XDrawLines(XtDisplay(w),
+ pixmap,
+ gc,
+ points,
+ l16(index),
+ CoordModeOrigin);
+ }
+
+
+// Figure out and draw the labels for PolyLines. Note that we later
+// determine whether we want to draw the label at all. Move all
+// code possible below that decision point to keep everything fast.
+// Don't do unnecessary calculations if we're not going to draw the
+// label.
+
+#ifdef WITH_DBFAWK
+ temp = (gps_flag)?gps_label:name;
+#else /* !WITH_DBFAWK */
+ // We're done with drawing the arc's. Draw the
+ // labels in this next section.
+ //
+ temp = "";
+ if ( !skip_label
+ && !skip_it
+ && map_labels
+ && road_flag) {
+ char a[2],b[2],c[2];
+
+ if ( (mapshots_labels_flag) && (fieldcount >= 8) ) {
+ char temp3[3];
+ char temp4[31];
+ char temp5[5];
+ char temp6[3];
+
+ temp = DBFReadStringAttribute( hDBF, structure, 4 );
+ xastir_snprintf(temp3,sizeof(temp3),"%s",temp);
+ temp = DBFReadStringAttribute( hDBF, structure, 5 );
+ xastir_snprintf(temp4,sizeof(temp4),"%s",temp);
+ temp = DBFReadStringAttribute( hDBF, structure, 6 );
+ xastir_snprintf(temp5,sizeof(temp5),"%s",temp);
+ temp = DBFReadStringAttribute( hDBF, structure, 7 );
+ xastir_snprintf(temp6,sizeof(temp6),"%s",temp);
+
+ // Take care to not insert spaces if
+ // some of the strings are empty.
+ if (strlen(temp3) != 0)
+ xastir_snprintf(a,sizeof(a)," ");
+ else
+ a[0] = '\0';
+ if (strlen(temp4) != 0)
+ xastir_snprintf(b,sizeof(b)," ");
+ else
+ b[0] = '\0';
+ if (strlen(temp5) != 0)
+ xastir_snprintf(c,sizeof(c)," ");
+ else
+ c[0] = '\0';
+
+ xastir_snprintf(temp2,sizeof(temp2),"%s%s%s%s%s%s%s",
+ temp3,a,temp4,b,temp5,c,temp6);
+ temp = temp2;
+ }
+ else if (fieldcount >=10) { // Need at least 10 fields if we're snagging #9, else segfault
+ // For roads, we need to use SIGN1 if it exists, else use DESCRIP if it exists.
+ temp = DBFReadStringAttribute( hDBF, structure, 9 ); // SIGN1
+ }
+ if ( (temp == NULL) || (strlen(temp) == 0) ) {
+ if (fieldcount >=13) // Need at least 13 fields if we're snagging #12, else segfault
+ temp = DBFReadStringAttribute( hDBF, structure, 12 ); // DESCRIP
+ else
+ temp = NULL;
+ }
+ }
+ else if (!skip_label
+ && map_labels
+ && !skip_it
+ && (lake_flag || river_flag) ) {
+
+ if ( mapshots_labels_flag && river_flag && (fieldcount >= 8) ) {
+ char temp3[3];
+ char temp4[31];
+ char temp5[5];
+ char temp6[3];
+
+
+ temp = DBFReadStringAttribute( hDBF, structure, 4 );
+ xastir_snprintf(temp3,sizeof(temp3),"%s",temp);
+ temp = DBFReadStringAttribute( hDBF, structure, 5 );
+ xastir_snprintf(temp4,sizeof(temp4),"%s",temp);
+ temp = DBFReadStringAttribute( hDBF, structure, 6 );
+ xastir_snprintf(temp5,sizeof(temp5),"%s",temp);
+ temp = DBFReadStringAttribute( hDBF, structure, 7 );
+ xastir_snprintf(temp6,sizeof(temp6),"%s",temp);
+ xastir_snprintf(temp2,sizeof(temp2),"%s %s %s %s",
+ temp3,temp4,temp5,temp6);
+ temp = temp2;
+ }
+ else if (mapshots_labels_flag && lake_flag && (fieldcount >= 4) ) {
+ temp = DBFReadStringAttribute( hDBF, structure, 3 );
+ }
+ else if (fieldcount >=14) { // Need at least 14 fields if we're snagging #13, else segfault
+ temp = DBFReadStringAttribute( hDBF, structure, 13 ); // PNAME (rivers)
+ }
+ else
+ temp = NULL;
+ }
+
+
+ // First we need to convert over to using the
+ // temp2 variable, which is changeable. Make
+ // temp point to it. temp may already be
+ // pointing to the temp2 variable.
+
+ if (temp != temp2) {
+ // temp points to an unchangeable string
+
+ if (temp != NULL) { // NOAA interstates file has a NULL at this point
+ // Copy the string so we can change it
+ xastir_snprintf(temp2,sizeof(temp2),"%s",temp);
+ temp = temp2; // Point temp to it (for later use)
+ }
+ else {
+ temp2[0] = '\0';
+ }
+ }
+ else { // We're already set to work on temp2!
+ }
+
+
+ if ( map_labels && gps_flag ) {
+ // We're drawing GPS info. Use gps_label,
+ // overriding anything set before.
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ gps_label);
+ }
+
+
+ // Change "United States Highway 2" into "US 2"
+ // Look for substring at start of string
+ if ( strstr(temp2,"United States Highway") == temp2 ) {
+ int index;
+ // Convert to "US"
+ temp2[1] = 'S'; // Add an 'S'
+ index = 2;
+ while (temp2[index+19] != '\0') {
+ temp2[index] = temp2[index+19];
+ index++;
+ }
+ temp2[index] = '\0';
+ }
+ else { // Change "State Highway 204" into "State 204"
+ // Look for substring at start of string
+ if ( strstr(temp2,"State Highway") == temp2 ) {
+ int index;
+ // Convert to "State"
+ index = 5;
+ while (temp2[index+8] != '\0') {
+ temp2[index] = temp2[index+8];
+ index++;
+ }
+ temp2[index] = '\0';
+ }
+ else { // Change "State Route 2" into "State 2"
+ // Look for substring at start of string
+ if ( strstr(temp2,"State Route") == temp2 ) {
+ int index;
+ // Convert to "State"
+ index = 5;
+ while (temp2[index+6] != '\0') {
+ temp2[index] = temp2[index+6];
+ index++;
+ }
+ temp2[index] = '\0';
+ }
+ }
+ }
+#endif /* !WITH_DBFAWK */
+ if ( (temp != NULL)
+ && (strlen(temp) != 0)
+ && map_labels
+ && !skip_it
+ && !skip_label ) {
+ int temp_ok;
+
+ ok = 1;
+
+ // Convert to Xastir coordinates
+ temp_ok = convert_to_xastir_coordinates(&my_long,
+ &my_lat,
+ (float)object->padfX[0],
+ (float)object->padfY[0]);
+ //fprintf(stderr,"%ld %ld\n", my_long, my_lat);
+
+ if (!temp_ok) {
+ fprintf(stderr,"draw_shapefile_map3: Problem converting from lat/lon\n");
+ ok = 0;
+ x = 0;
+ y = 0;
+ }
+ else {
+ // Convert to screen coordinates. Careful
+ // here! The format conversions you'll need
+ // if you try to compress this into two
+ // lines will get you into trouble.
+ x = my_long - NW_corner_longitude;
+ y = my_lat - NW_corner_latitude;
+ x = l16(x / scale_x);
+ y = l16(y / scale_y);
+ }
+
+ if (ok == 1 && ok_to_draw) {
+
+ int new_label = 1;
+ int mod_number;
+
+ // Set up the mod_number, which is used
+ // below to determine how many of each
+ // identical label are skipped at each
+ // zoom level.
+
+// The goal here is to have one complete label visible on the screen
+// for each road. We end up skipping labels based on zoom level,
+// which, if the road doesn't have very many segments, may end up
+// drawing one label almost entirely off-screen. :-(
+
+// If we could check the first line segment to see if the label
+// would be drawn off-screen, perhaps we could start drawing at
+// segment #2? We'd have to check whether there is a segment #2.
+// Another possibility would be to shift the label on-screen. Would
+// this work for twisty/turny roads though? I suppose, 'cuz they'd
+// end up with more line segments and we could just draw at segment
+// #2 in that case instead of shifting.
+
+ if (scale_y == 1)
+ mod_number = 1;
+ else if (scale_y <= 2)
+ mod_number = 1;
+ else if (scale_y <= 4)
+ mod_number = 2;
+ else if (scale_y <= 8)
+ mod_number = 4;
+ else if (scale_y <= 16)
+ mod_number = 8;
+ else if (scale_y <= 32)
+ mod_number = 16;
+ else
+ mod_number = (int)(scale_y);
+
+ // Check whether we've written out this string
+ // already: Look for a match in our linked list
+
+// The problem with this method is that we might get strings
+// "written" at the extreme top or right edge of the display, which
+// means the strings wouldn't be visible, but Xastir thinks that it
+// wrote the string out visibly. To partially counteract this I've
+// set it up to write only some of the identical strings. This
+// still doesn't help in the cases where a street only comes in from
+// the top or right and doesn't have an intersection with another
+// street (and therefore another label) within the view.
+
+ // Hash index is just the first
+ // character. Tried using lower 6 bits
+ // of first two chars and lower 7 bits
+ // of first two chars but the result was
+ // slower than just using the first
+ // character.
+ hash_index = (uint8_t)(temp[0]);
+
+ ptr2 = label_hash[hash_index];
+ while (ptr2 != NULL) { // Step through the list
+ // Check 2nd character (fast!)
+ if ( (uint8_t)(ptr2->label[1]) == (uint8_t)(temp[1]) ) {
+ if (strcasecmp(ptr2->label,temp) == 0) { // Found a match
+ //fprintf(stderr,"Found a match!\t%s\n",temp);
+ new_label = 0;
+ ptr2->found = ptr2->found + 1; // Increment the "found" quantity
+
+// We change this "mod" number based on zoom level, so that long
+// strings don't overwrite each other, and so that we don't get too
+// many or too few labels drawn. This will cause us to skip
+// intersections (the tiger files appear to have a label at each
+// intersection). Between rural and urban areas, this method might
+// not work well. Urban areas have few intersections, so we'll get
+// fewer labels drawn.
+// A better method might be to check the screen location for each
+// one and only write the strings if they are far enough apart, and
+// only count a string as written if the start of it is onscreen and
+// the angle is correct for it to be written on the screen.
+
+ // Draw a number of labels
+ // appropriate for the zoom
+ // level.
+// Labeling: Skip label logic
+ if ( ((ptr2->found - 1) % mod_number) != 0) {
+ skip_label++;
+ }
+ ptr2 = NULL; // End the loop
+ }
+ else {
+ ptr2 = ptr2->next;
+ }
+ }
+ else {
+ ptr2 = ptr2->next;
+ }
+ }
+
+ if (!skip_label) { // Draw the string
+
+ // Compute the label rotation angle
+ float diff_X = (int)x1 - x0;
+ float diff_Y = (int)y1 - y0;
+ float angle = 0.0; // Angle for the beginning of this polyline
+
+ if (diff_X == 0.0) { // Avoid divide by zero errors
+ diff_X = 0.0000001;
+ }
+ angle = atan( diff_X / diff_Y ); // Compute in radians
+ // Convert to degrees
+ angle = angle / (2.0 * M_PI );
+ angle = angle * 360.0;
+
+ // Change to fit our rotate label function's idea of angle
+ angle = 360.0 - angle;
+
+ //fprintf(stderr,"Y: %f\tX: %f\tAngle: %f ==> ",diff_Y,diff_X,angle);
+
+ if ( angle > 90.0 ) {angle += 180.0;}
+ if ( angle >= 360.0 ) {angle -= 360.0;}
+
+ //fprintf(stderr,"%f\t%s\n",angle,temp);
+
+// Labeling of polylines done here
+
+// (void)draw_label_text ( w, x, y, strlen(temp), colors[label_color], (char *)temp);
+ if (gps_flag) {
+ (void)draw_rotated_label_text (w,
+ //(int)angle,
+ -90, // Horizontal, easiest to read
+ x,
+ y,
+ strlen(temp),
+ colors[gps_color],
+ (char *)temp,
+ font_size);
+ }
+ else {
+ (void)draw_rotated_label_text(w,
+ (int)angle,
+ x,
+ y,
+ strlen(temp),
+ colors[label_color],
+ (char *)temp,
+ font_size);
+ }
+ }
+
+ if (new_label) {
+
+ // Create a new record for this string
+ // and add it to the head of the list.
+ // Make sure to "free" this linked
+ // list.
+ //fprintf(stderr,"Creating a new record: %s\n",temp);
+ ptr2 = (label_string *)malloc(sizeof(label_string));
+ CHECKMALLOC(ptr2);
+
+ xastir_snprintf(ptr2->label,sizeof(ptr2->label),"%s",temp);
+ ptr2->found = 1;
+
+ // We use first character of string
+ // as our hash index.
+ hash_index = temp[0];
+
+ ptr2->next = label_hash[hash_index];
+ label_hash[hash_index] = ptr2;
+ //if (label_hash[hash_index]->next == NULL)
+ // fprintf(stderr,"only one record\n");
+ }
+ }
+ }
+ break;
+
+
+
+ case SHPT_POLYGON:
+ case SHPT_POLYGONZ:
+
+ if (debug_level & 16)
+ fprintf(stderr,"Found Polygons\n");
+
+#ifdef WITH_DBFAWK
+ // User requested filled polygons with stippling.
+ // Set the stipple now. need to do here, because if
+ // done earlier the labels get stippled, too.
+ (void)XSetFillStyle(XtDisplay(w), gc, fill_style);
+
+ if (draw_filled != 0 && fill_style == FillStippled) {
+
+
+ switch (fill_stipple) {
+ case 0:
+ (void)XSetStipple(XtDisplay(w), gc,
+ pixmap_13pct_stipple);
+ break;
+ case 1:
+ (void)XSetStipple(XtDisplay(w), gc,
+ pixmap_25pct_stipple);
+ break;
+ default:
+ (void)XSetStipple(XtDisplay(w), gc,
+ pixmap_25pct_stipple);
+ break;
+ }
+ }
+#endif // WITH_DBFAWK
+
+ // Each polygon can be made up of multiple
+ // rings, and each ring has multiple points that
+ // define it. We hit this case once for each
+ // polygon shape in the file, iff at least part
+ // of that shape is within our viewport.
+
+// We now handle the "hole" drawing in polygon shapefiles, where
+// clockwise direction around the ring means a fill, and CCW means a
+// hole in the polygon.
+//
+// Possible implementations:
+//
+// 1) Snag an algorithm for a polygon "fill" function from
+// somewhere, but add a piece that will check for being inside a
+// "hole" polygon and just not draw while traversing it (change the
+// pen color to transparent over the holes?).
+// SUMMARY: How to do this?
+//
+// 2) Draw to another layer, then copy only the filled pixels to
+// their final destination pixmap.
+// SUMMARY: Draw polygons once, then a copy operation.
+//
+// 3) Separate area: Draw polygon. Copy from other map layer into
+// holes, then copy the result back.
+// SUMMARY: How to determine outline?
+//
+// 4) Use clip-masks to prevent drawing over the hole areas: Draw
+// to another 1-bit pixmap or region. This area can be the size of
+// the max shape extents. Filled = 1. Holes = 0. Use that pixmap
+// as a clip-mask to draw the polygons again onto the final pixmap.
+// SUMMARY: We end up drawing the shape twice!
+//
+// MODIFICATION: Draw a filled rectangle onto the map pixmap using
+// the clip-mask to control where it actually gets drawn.
+// SUMMARY: Only end up drawing the shape once.
+//
+// 5) Inverted clip-mask: Draw just the holes to a separate pixmap:
+// Create a pixmap filled with 1's (XFillRectangle & GXset). Draw
+// the holes and use GXinvert to draw zero's to the mask where the
+// holes go. Use this as a clip-mask to draw the filled areas of
+// the polygon to the map pixmap.
+// SUMMARY: Faster than methods 1-4?
+//
+// 6) Use Regions to do the same method as #5 but with more ease.
+// Create a polygon Region, then create a Region for each hole and
+// subtract the hole from the polygon Region. Once we have a
+// complete polygon + holes, use that as the clip-mask for drawing
+// the real polygon. Use XSetRegion() on the GC to set this up. We
+// might have to do offsets as well so that the region maps properly
+// to our map pixmap when we draw the final polygon to it.
+// SUMMARY: Should be faster than methods 1-5.
+//
+// 7) Do method 6 but instead of drawing a polygon region, draw a
+// rectangle region first, then knock holes in it. Use that region
+// as the clip-mask for the XFillPolygon() later by calling
+// XSetRegion() on the GC. We don't really need a polygon region
+// for a clip-mask. A rectangle with holes in it will work just as
+// well and should be faster overall. We might have to do offsets
+// as well so that the region maps properly to our map pixmap when
+// we draw the final polygon to it.
+// SUMMARY: This might be the fastest method of the ones listed, if
+// drawing a rectangle region is faster than drawing a polygon
+// region. We draw the polygon once here instead of twice, and each
+// hole only once. The only added drawing time would be the
+// creation of the rectangle region, which should be fairly fast,
+// and the subtracting of the hole regions from it.
+//
+//
+// Shapefiles also allow identical points to be next to each other
+// in the vertice list. We should look for that and get rid of
+// duplicate vertices.
+
+
+//if (object->nParts > 1)
+//fprintf(stderr,"Number of parts: %d\n", object->nParts);
+
+
+// Unfortunately, for Polygon shapes we must make one pass through
+// the entire set of rings to see if we have any "hole" rings (as
+// opposed to "fill" rings). If we have any "hole" rings, we must
+// handle the drawing of the Shape quite differently.
+//
+// Read the vertices for each ring in the Shape. Test whether we
+// have a hole ring. If so, save the ring index away for the next
+// step when we actually draw the shape.
+
+ polygon_hole_flag = 0;
+
+ // Allocate storage for a flag for each ring in
+ // this Shape.
+ // !!Remember to free this storage later!!
+ polygon_hole_storage = (int *)malloc(object->nParts*sizeof(int));
+ CHECKMALLOC(polygon_hole_storage);
+
+// Run through the entire shape (all rings of it) once. Create an
+// array of flags that specify whether each ring is a fill or a
+// hole. If any holes found, set the global polygon_hole_flag as
+// well.
+
+ for (ring = 0; ring < object->nParts; ring++ ) {
+
+ // Testing for fill or hole ring. This will
+ // determine how we ultimately draw the
+ // entire shape.
+ //
+ switch ( shape_ring_direction( object, ring) ) {
+ case 0: // Error in trying to compute whether fill or hole
+ fprintf(stderr,"Error in computing fill/hole ring\n");
+ case 1: // It's a fill ring
+ // Do nothing for these two cases
+ // except clear the flag in our
+ // storage
+ polygon_hole_storage[ring] = 0;
+ break;
+ case -1: // It's a hole ring
+ // Add it to our list of hole rings
+ // here and set a flag. That way we
+ // won't have to run through
+ // SHPRingDir_2d again in the next
+ // loop.
+ polygon_hole_flag++;
+ polygon_hole_storage[ring] = 1;
+// fprintf(stderr, "Ring %d/%d is a polygon hole\n",
+// ring,
+// object->nParts);
+ break;
+ }
+ }
+// We're done with the initial run through the vertices of all
+// rings. We now know which rings are fills and which are holes and
+// have recorded the data.
+
+// Speedup: Only loop through the vertices once, by determining
+// hole/fill polygons as we go.
+
+
+//WE7U3
+ // Speedup: If not draw_filled, then don't go
+ // through the math and region code. Set the
+ // flag to zero so that we won't do all the math
+ // and the regions.
+ if (!map_color_fill || !draw_filled)
+ polygon_hole_flag = 0;
+
+ if (polygon_hole_flag) {
+ XRectangle rectangle;
+ long width, height;
+ double top_ll, left_ll, bottom_ll, right_ll;
+ int temp_ok;
+
+
+// fprintf(stderr, "%s:Found %d hole rings in shape %d\n",
+// file,
+// polygon_hole_flag,
+// structure);
+
+//WE7U3
+////////////////////////////////////////////////////////////////////////
+
+// Now that we know which are fill/hole rings, worry about drawing
+// each ring of the Shape:
+//
+// 1) Create a filled rectangle region, probably the size of the
+// Shape extents, and at the same screen coordinates as the entire
+// shape would normally be drawn.
+//
+// 2) Create a region for each hole ring and subtract these new
+// regions one at a time from the rectangle region created above.
+//
+// 3) When the "swiss-cheese" rectangle region is complete, draw
+// only the filled polygons onto the map pixmap using the
+// swiss-cheese rectangle region as the clip-mask. Use a temporary
+// GC for this operation, as I can't find a way to remove a
+// clip-mask from a GC. We may have to use offsets to make this
+// work properly.
+
+
+ // Create three regions and rotate between
+ // them, due to the XSubtractRegion()
+ // needing three parameters. If we later
+ // find that two of the parameters can be
+ // repeated, we can simplify our code.
+ // We'll rotate through them mod 3.
+
+ temp_region1 = 0;
+
+ // Create empty region
+ region[temp_region1] = XCreateRegion();
+
+ // Draw a rectangular clip-mask inside the
+ // Region. Use the same extents as the full
+ // Shape.
+
+ // Set up the real sizes from the Shape
+ // extents.
+ top_ll = object->dfYMax;
+ left_ll = object->dfXMin;
+ bottom_ll = object->dfYMin;
+ right_ll = object->dfXMax;
+
+ // Convert point to Xastir coordinates:
+ temp_ok = convert_to_xastir_coordinates(&my_long,
+ &my_lat,
+ left_ll,
+ top_ll);
+ //fprintf(stderr,"%ld %ld\n", my_long, my_lat);
+
+ if (!temp_ok) {
+ fprintf(stderr,"draw_shapefile_map4: Problem converting from lat/lon\n");
+ ok = 0;
+ x = 0;
+ y = 0;
+ }
+ else {
+ // Convert to screen coordinates. Careful
+ // here! The format conversions you'll need
+ // if you try to compress this into two
+ // lines will get you into trouble.
+ x = my_long - NW_corner_longitude;
+ y = my_lat - NW_corner_latitude;
+ x = x / scale_x;
+ y = y / scale_y;
+
+
+ // Here we check for really wacko points that will cause problems
+ // with the X drawing routines, and fix them.
+ if (x > 1700l) x = 1700l;
+ if (x < 0l) x = 0l;
+ if (y > 1700l) y = 1700l;
+ if (y < 0l) y = 0l;
+ }
+
+ // Convert points to Xastir coordinates
+ temp_ok = convert_to_xastir_coordinates(&my_long,
+ &my_lat,
+ right_ll,
+ bottom_ll);
+ //fprintf(stderr,"%ld %ld\n", my_long, my_lat);
+
+ if (!temp_ok) {
+ fprintf(stderr,"draw_shapefile_map5: Problem converting from lat/lon\n");
+ ok = 0;
+ width = 0;
+ height = 0;
+ }
+ else {
+ // Convert to screen coordinates. Careful
+ // here! The format conversions you'll need
+ // if you try to compress this into two
+ // lines will get you into trouble.
+ width = my_long - NW_corner_longitude;
+ height = my_lat - NW_corner_latitude;
+ width = width / scale_x;
+ height = height / scale_y;
+
+ // Here we check for really wacko points that will cause problems
+ // with the X drawing routines, and fix them.
+ if (width > 1700l) width = 1700l;
+ if (width < 1l) width = 1l;
+ if (height > 1700l) height = 1700l;
+ if (height < 1l) height = 1l;
+ }
+
+//TODO
+// We can run into trouble here because we only have 16-bit values
+// to work with. If we're zoomed in and the Shape is large in
+// comparison to the screen, we'll easily exceed these numbers.
+// Perhaps we'll need to work with something other than screen
+// coordinates? Perhaps truncating the values will be adequate.
+
+ rectangle.x = (short) x;
+ rectangle.y = (short) y;
+ rectangle.width = (unsigned short) width;
+ rectangle.height = (unsigned short) height;
+
+//fprintf(stderr,"*** Rectangle: %d,%d %dx%d\n", rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+
+ // Create the initial region containing a
+ // filled rectangle.
+ XUnionRectWithRegion(&rectangle,
+ region[temp_region1],
+ region[temp_region1]);
+
+ // Create a region for each set of hole
+ // vertices (CCW rotation of the vertices)
+ // and subtract each from the rectangle
+ // region.
+ for (ring = 0; ring < object->nParts; ring++ ) {
+ int endpoint;
+ int on_screen;
+
+
+ if (polygon_hole_storage[ring] == 1) {
+ // It's a hole polygon. Cut the
+ // hole out of our rectangle region.
+ int num_vertices = 0;
+ int nVertStart;
+
+
+ nVertStart = object->panPartStart[ring];
+
+ if( ring == object->nParts-1 )
+ num_vertices = object->nVertices
+ - object->panPartStart[ring];
+ else
+ num_vertices = object->panPartStart[ring+1]
+ - object->panPartStart[ring];
+
+//TODO
+// Snag the vertices and put them into the "points" array,
+// converting to screen coordinates as we go, then subtracting the
+// starting point, so that the regions remain small?
+//
+// We could either subtract the starting point of each shape from
+// each point, or take the hit on region size and just use the full
+// screen size (or whatever part of it the shape required plus the
+// area from the starting point to 0,0).
+
+
+ if ( (ring+1) < object->nParts)
+ endpoint = object->panPartStart[ring+1];
+ //else endpoint = object->nVertices;
+ else
+ endpoint = object->panPartStart[0] + object->nVertices;
+ //fprintf(stderr,"Endpoint %d\n", endpoint);
+ //fprintf(stderr,"Vertices: %d\n", endpoint - object->panPartStart[ring]);
+
+ i = 0; // i = Number of points to draw for one ring
+ on_screen = 0;
+
+ // index = ptr into the shapefile's array of points
+ for (index = object->panPartStart[ring]; index < endpoint; ) {
+ int temp_ok;
+
+
+ // Get vertice and convert to Xastir coordinates
+ temp_ok = convert_to_xastir_coordinates(&my_long,
+ &my_lat,
+ (float)object->padfX[index],
+ (float)object->padfY[index]);
+
+ //fprintf(stderr,"%lu %lu\t", my_long, my_lat);
+
+ if (!temp_ok) {
+ fprintf(stderr,"draw_shapefile_map6: Problem converting from lat/lon\n");
+ ok = 0;
+ x = 0;
+ y = 0;
+ }
+ else {
+ // Convert to screen coordinates. Careful
+ // here! The format conversions you'll need
+ // if you try to compress this into two
+ // lines will get you into trouble.
+ x = my_long - NW_corner_longitude;
+ y = my_lat - NW_corner_latitude;
+ x = x / scale_x;
+ y = y / scale_y;
+
+
+ //fprintf(stderr,"%ld %ld\t\t", x, y);
+
+ // Here we check for really
+ // wacko points that will
+ // cause problems with the X
+ // drawing routines, and fix
+ // them. Increment
+ // on_screen if any of the
+ // points might be on
+ // screen.
+ if (x > 1700l)
+ x = 1700l;
+ else if (x < 0l)
+ x = 0l;
+ else on_screen++;
+
+ if (y > 1700l)
+ y = 1700l;
+ else if (y < 0l)
+ y = 0l;
+ else on_screen++;
+
+ points[i].x = l16(x);
+ points[i].y = l16(y);
+
+if (on_screen) {
+// fprintf(stderr,"%d x:%d y:%d\n",
+// i,
+// points[i].x,
+// points[i].y);
+}
+ i++;
+ }
+ index++;
+
+ if (index > high_water_mark_index)
+ high_water_mark_index = index;
+
+ if (index > endpoint) {
+ index = endpoint;
+ fprintf(stderr,"Trying to run past the end of shapefile array: index=%d\n",index);
+ }
+ } // End of converting vertices for a ring
+
+
+ // Create and subtract the region
+ // only if it might be on screen.
+ if (on_screen) {
+ temp_region2 = (temp_region1 + 1) % 3;
+ temp_region3 = (temp_region1 + 2) % 3;
+
+ // Create empty regions.
+ region[temp_region2] = XCreateRegion();
+ region[temp_region3] = XCreateRegion();
+
+ // Draw the hole polygon
+ if (num_vertices >= 3) {
+ XDestroyRegion(region[temp_region2]); // Release the old
+ region[temp_region2] = XPolygonRegion(points,
+ num_vertices,
+ WindingRule);
+ }
+ else {
+ fprintf(stderr,
+ "draw_shapefile_map:XPolygonRegion with too few vertices:%d\n",
+ num_vertices);
+ }
+
+ // Subtract region2 from region1 and
+ // put the result into region3.
+//fprintf(stderr, "Subtracting region\n");
+ XSubtractRegion(region[temp_region1],
+ region[temp_region2],
+ region[temp_region3]);
+
+ // Get rid of the two regions we no
+ // longer need
+ XDestroyRegion(region[temp_region1]);
+ XDestroyRegion(region[temp_region2]);
+
+ // Indicate the final result region for
+ // the next iteration or the exit of the
+ // loop.
+ temp_region1 = temp_region3;
+ }
+ }
+ }
+
+ // region[temp_region1] now contains a
+ // clip-mask of the original polygon with
+ // holes cut out of it (swiss-cheese
+ // rectangle).
+
+ // Create temporary GC. It looks like we
+ // don't need this to create the regions,
+ // but we'll need it when we draw the filled
+ // polygons onto the map pixmap using the
+ // final region as a clip-mask.
+
+// Offsets?
+// XOffsetRegion
+
+// gc_temp_values.function = GXcopy;
+ gc_temp = XCreateGC(XtDisplay(w),
+ XtWindow(w),
+ 0,
+ &gc_temp_values);
+ // now copy the fill style and stipple from gc.
+ XCopyGC(XtDisplay(w),
+ gc,
+ (GCFillStyle|GCStipple),
+ gc_temp);
+
+ // Set the clip-mask into the GC. This GC
+ // is now ruined for other purposes, so
+ // destroy it when we're done drawing this
+ // one shape.
+ XSetRegion(XtDisplay(w), gc_temp, region[temp_region1]);
+ XDestroyRegion(region[temp_region1]);
+ }
+//WE7U3
+////////////////////////////////////////////////////////////////////////
+
+
+ // Read the vertices for each ring in this Shape
+ for (ring = 0; ring < object->nParts; ring++ ) {
+ int endpoint;
+#ifndef WITH_DBFAWK
+ int glacier_flag = 0;
+ const char *temp;
+
+ if (lake_flag || river_flag) {
+ if ( mapshots_labels_flag && (fieldcount >= 3) ) {
+ temp = DBFReadStringAttribute( hDBF, structure, 2 ); // CFCC Field
+ switch (temp[1]) {
+ case '8': // Special water feature
+ switch(temp[2]) {
+ case '1':
+ glacier_flag++; // Found a glacier
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+#endif /* !WITH_DBFAWK */
+ //fprintf(stderr,"Ring: %d\t\t", ring);
+
+ if ( (ring+1) < object->nParts)
+ endpoint = object->panPartStart[ring+1];
+ //else endpoint = object->nVertices;
+ else
+ endpoint = object->panPartStart[0] + object->nVertices;
+
+ //fprintf(stderr,"Endpoint %d\n", endpoint);
+ //fprintf(stderr,"Vertices: %d\n", endpoint - object->panPartStart[ring]);
+
+ i = 0; // i = Number of points to draw for one ring
+ // index = ptr into the shapefile's array of points
+ for (index = object->panPartStart[ring]; index < endpoint; ) {
+ int temp_ok;
+
+ ok = 1;
+
+ //fprintf(stderr,"\t%d:%g %g\t", index, object->padfX[index], object->padfY[index] );
+
+ // Get vertice and convert to Xastir coordinates
+ temp_ok = convert_to_xastir_coordinates(&my_long,
+ &my_lat,
+ (float)object->padfX[index],
+ (float)object->padfY[index]);
+
+ //fprintf(stderr,"%lu %lu\t", my_long, my_lat);
+
+ if (!temp_ok) {
+ fprintf(stderr,"draw_shapefile_map7: Problem converting from lat/lon\n");
+ ok = 0;
+ x = 0;
+ y = 0;
+ index++;
+ }
+ else {
+ // Convert to screen coordinates. Careful
+ // here! The format conversions you'll need
+ // if you try to compress this into two
+ // lines will get you into trouble.
+ x = my_long - NW_corner_longitude;
+ y = my_lat - NW_corner_latitude;
+ x = x / scale_x;
+ y = y / scale_y;
+
+
+ //fprintf(stderr,"%ld %ld\t\t", x, y);
+
+ // Here we check for really wacko points that will cause problems
+ // with the X drawing routines, and fix them.
+ points[i].x = l16(x);
+ points[i].y = l16(y);
+ i++; // Number of points to draw
+
+ if (i > high_water_mark_i)
+ high_water_mark_i = i;
+
+
+ if (i >= MAX_MAP_POINTS) {
+ i = MAX_MAP_POINTS - 1;
+ fprintf(stderr,"Trying to run past the end of our internal points array: i=%d\n",i);
+ }
+
+ //fprintf(stderr,"%d %d\t", points[i].x, points[i].y);
+
+ index++;
+
+ if (index > high_water_mark_index)
+ high_water_mark_index = index;
+
+ if (index > endpoint) {
+ index = endpoint;
+ fprintf(stderr,"Trying to run past the end of shapefile array: index=%d\n",index);
+ }
+ }
+ }
+
+ if ( (i >= 3)
+ && (ok_to_draw && !skip_it)
+ && ( !draw_filled || !map_color_fill || (draw_filled && polygon_hole_storage[ring] == 0) ) ) {
+ // We have a polygon to draw!
+//WE7U3
+ if ((!draw_filled || !map_color_fill) && polygon_hole_storage[ring] == 1) {
+ // We have a hole drawn as unfilled.
+ // Draw as a black dashed line.
+#ifdef WITH_DBFAWK
+ (void)XSetForeground(XtDisplay(w), gc, colors[color]);
+#else // WITH_DBFAWK
+ (void)XSetForeground(XtDisplay(w), gc, colors[0x08]); // black for border
+#endif // WITH_DBFAWK
+ (void)XSetLineAttributes (XtDisplay (w),
+ gc,
+ 0,
+ LineOnOffDash,
+ CapButt,
+ JoinMiter);
+ (void)XDrawLines(XtDisplay(w),
+ pixmap,
+ gc,
+ points,
+ l16(i),
+ CoordModeOrigin);
+ (void)XSetLineAttributes (XtDisplay (w),
+ gc,
+ 0,
+ LineSolid,
+ CapButt,
+ JoinMiter);
+ }
+ else if (quad_overlay_flag) {
+ (void)XDrawLines(XtDisplay(w),
+ pixmap,
+ gc,
+ points,
+ l16(i),
+ CoordModeOrigin);
+ }
+ /* old glacier, lake and river code was identical
+ with the exception of what color to use! */
+#ifdef WITH_DBFAWK
+ else if (!weather_alert_flag) {
+ /* color is already set by dbfawk(?) */
+ /* And so are lanes and pattern. Let's
+ use what was specified. */
+ (void)XSetLineAttributes(XtDisplay(w),
+ gc,
+ (lanes)?lanes:1,
+ pattern,
+ CapButt,
+ JoinMiter);
+#else /* !WITH_DBFAWK */
+ else if (glacier_flag||lake_flag||river_flag) {
+ int color = (glacier_flag)?0x0f:
+ (lake_flag||river_flag)?0x1a:8;
+#endif /* !WITH_DBFAWK */
+ (void)XSetForeground(XtDisplay(w), gc, colors[color]);
+ if (map_color_fill && draw_filled) {
+ if (polygon_hole_flag) {
+#ifdef WITH_DBFAWK
+ (void)XSetForeground(XtDisplay(w), gc_temp, colors[fill_color]);
+#else // WITH_DBFAWK
+ (void)XSetForeground(XtDisplay(w), gc_temp, colors[color]);
+#endif // WITH_DBFAWK
+ if (i >= 3) {
+ (void)XFillPolygon(XtDisplay(w),
+ pixmap,
+ gc_temp,
+ points,
+ i,
+ Nonconvex,
+ CoordModeOrigin);
+ }
+ else {
+ fprintf(stderr,
+ "draw_shapefile_map:Too few points:%d, Skipping XFillPolygon()",
+ npoints);
+ }
+ }
+ else { /* no holes in this polygon */
+ if (i >= 3) {
+ /* draw the filled polygon */
+#ifdef WITH_DBFAWK
+ (void)XSetForeground(XtDisplay(w), gc, colors[fill_color]);
+#endif // WITH_DBFAWK
+ (void)XFillPolygon(XtDisplay(w),
+ pixmap,
+ gc,
+ points,
+ i,
+ Nonconvex,
+ CoordModeOrigin);
+ }
+ else {
+ fprintf(stderr,
+ "draw_shapefile_map:Too few points:%d, Skipping XFillPolygon()",
+ npoints);
+ }
+ }
+ }
+ /* draw the polygon border */
+ (void)XSetForeground(XtDisplay(w), gc, colors[color]);
+ (void)XSetFillStyle(XtDisplay(w), gc, FillSolid);
+ (void)XDrawLines(XtDisplay(w),
+ pixmap,
+ gc,
+ points,
+ l16(i),
+ CoordModeOrigin);
+ }
+ else if (weather_alert_flag) {
+ (void)XSetFillStyle(XtDisplay(w), gc_tint, FillStippled);
+// We skip the hole/fill thing for these?
+
+ if (i >= 3) {
+ (void)XFillPolygon(XtDisplay(w),
+ pixmap_alerts,
+ gc_tint,
+ points,
+ i,
+ Nonconvex,
+ CoordModeOrigin);
+ }
+ else {
+ fprintf(stderr,
+ "draw_shapefile_map:Too few points:%d, Skipping XFillPolygon()",
+ npoints);
+ }
+
+ (void)XSetFillStyle(XtDisplay(w), gc_tint, FillSolid);
+ (void)XDrawLines(XtDisplay(w),
+ pixmap_alerts,
+ gc_tint,
+ points,
+ l16(i),
+ CoordModeOrigin);
+ }
+ else if (map_color_fill && draw_filled) { // Land masses?
+ if (polygon_hole_flag) {
+#ifndef WITH_DBFAWK
+ /* city_flag not needed WITH_DBFAWK */
+ if (city_flag)
+ (void)XSetForeground(XtDisplay(w), gc_temp, GetPixelByName(w,"RosyBrown")); // RosyBrown, duh
+ else
+ (void)XSetForeground(XtDisplay(w), gc_temp, colors[0xff]); // grey
+#else // WITH_DBFAWK
+ (void)XSetForeground(XtDisplay(w), gc_temp, colors[fill_color]);
+#endif /* WITH_DBFAWK */
+ if (i >= 3) {
+ (void)XFillPolygon(XtDisplay(w),
+ pixmap,
+ gc_temp,
+ points,
+ i,
+ Nonconvex,
+ CoordModeOrigin);
+ }
+ else {
+ fprintf(stderr,
+ "draw_shapefile_map:Too few points:%d, Skipping XFillPolygon()",
+ npoints);
+ }
+ }
+ else { /* no polygon hole */
+#ifndef WITH_DBFAWK
+ if (city_flag)
+ (void)XSetForeground(XtDisplay(w), gc, GetPixelByName(w,"RosyBrown")); // RosyBrown, duh
+ else
+ (void)XSetForeground(XtDisplay(w), gc, colors[0xff]); // grey
+#else // WITH_DBFAWK
+ (void)XSetForeground(XtDisplay(w), gc, colors[fill_color]);
+#endif /* !WITH_DFBAWK */
+ if (i >= 3) {
+ (void)XFillPolygon(XtDisplay (w),
+ pixmap,
+ gc,
+ points,
+ i,
+ Nonconvex,
+ CoordModeOrigin);
+ }
+ else {
+ fprintf(stderr,
+ "draw_shapefile_map:Too few points:%d, Skipping XFillPolygon()",
+ npoints);
+ }
+ }
+
+#ifdef WITH_DBFAWK
+ (void)XSetForeground(XtDisplay(w), gc, colors[color]); // border color
+#endif // WITH_DBFAWK
+
+ // Draw a thicker border for city boundaries
+#ifndef WITH_DBFAWK
+ if (city_flag) {
+ if (scale_y <= 64) {
+ (void)XSetLineAttributes(XtDisplay(w), gc, 2, LineSolid, CapButt,JoinMiter);
+ }
+ else if (scale_y <= 128) {
+ (void)XSetLineAttributes(XtDisplay(w), gc, 1, LineSolid, CapButt,JoinMiter);
+ }
+ else {
+ (void)XSetLineAttributes(XtDisplay(w), gc, 0, LineSolid, CapButt,JoinMiter);
+ }
+
+ (void)XSetForeground(XtDisplay(w), gc, colors[0x14]); // lightgray for border
+ }
+ else {
+ (void)XSetForeground(XtDisplay(w), gc, colors[0x08]); // black for border
+ }
+#else // WITH_DBFAWK
+ (void)XSetForeground(XtDisplay(w), gc, colors[color]); // border
+ (void)XSetFillStyle(XtDisplay(w), gc, FillSolid);
+#endif /* WITH_DBFAWK */
+
+ (void)XDrawLines(XtDisplay(w),
+ pixmap,
+ gc,
+ points,
+ l16(i),
+ CoordModeOrigin);
+ }
+ else { // Use whatever color is defined by this point.
+ (void)XSetLineAttributes(XtDisplay(w), gc, 0, LineSolid, CapButt,JoinMiter);
+ (void)XSetFillStyle(XtDisplay(w), gc, FillSolid);
+ (void)XDrawLines(XtDisplay(w),
+ pixmap,
+ gc,
+ points,
+ l16(i),
+ CoordModeOrigin);
+ }
+ }
+ }
+ // Free the storage that we allocated to hold
+ // the "hole" flags for the shape.
+ free(polygon_hole_storage);
+
+ if (polygon_hole_flag) {
+ //Free the temporary GC that we may have used to
+ //draw polygons using the clip-mask:
+ XFreeGC(XtDisplay(w), gc_temp);
+ }
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Done with drawing shapes, now draw labels
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef WITH_DBFAWK
+ temp = name;
+ // Set fill style back to defaults, or labels will get
+ // stippled along with polygons!
+ XSetFillStyle(XtDisplay(w), gc, FillSolid);
+
+#else /* !WITH_DBFAWK */
+ /* labels come from dbfawk, not here... */
+
+ temp = "";
+ if (lake_flag) {
+ if (map_color_levels && scale_y > 128)
+ skip_label++;
+ if (mapshots_labels_flag && (fieldcount >= 4) )
+ temp = DBFReadStringAttribute( hDBF, structure, 3 );
+ else if (fieldcount >= 1)
+ temp = DBFReadStringAttribute( hDBF, structure, 0 ); // NAME (lakes)
+ else
+ temp = NULL;
+ }
+ else if (city_flag) {
+ if (map_color_levels && scale_y > 512)
+ skip_label++;
+ if (mapshots_labels_flag && (fieldcount >= 4) )
+ temp = DBFReadStringAttribute( hDBF, structure, 3 ); // NAME (designated places)
+ else
+ temp = NULL;
+ }
+#endif /* !WITH_DBFAWK */
+ /* XXX - figure out how to set this from dbfawk: */
+ if (quad_overlay_flag) {
+ if (fieldcount >= 5) {
+ // Use just the last two characters of
+ // the quad index. "44072-A3" converts
+ // to "A3"
+ temp = DBFReadStringAttribute( hDBF, structure, 4 );
+ xastir_snprintf(quad_label,
+ sizeof(quad_label),
+ "%s ",
+ &temp[strlen(temp) - 2]);
+
+ // Append the name of the quad
+ temp = DBFReadStringAttribute( hDBF, structure, 0 );
+ strncat(quad_label,
+ temp,
+ sizeof(quad_label) - 1 - strlen(quad_label));
+ }
+ else {
+ quad_label[0] = '\0';
+ }
+ }
+
+ if ( (temp != NULL)
+ && (strlen(temp) != 0)
+ && map_labels
+ && !skip_label ) {
+ int temp_ok;
+
+ if (debug_level & 16) {
+ fprintf(stderr,"I think I should display labels\n");
+ }
+ ok = 1;
+
+ // Convert to Xastir coordinates:
+ // If quad overlay shapefile, need to
+ // snag the label coordinates from the DBF
+ // file instead. Note that the coordinates
+ // are for the bottom right corner of the
+ // quad, so we need to shift it left by 7.5'
+ // to make the label appear inside the quad
+ // (attached to the bottom left corner in
+ // this case).
+ /* XXX - figure out how to do WITH_DBFAWK: */
+ if (quad_overlay_flag) {
+ const char *dbf_temp;
+ float lat_f;
+ float lon_f;
+
+ if (fieldcount >= 4) {
+ dbf_temp = DBFReadStringAttribute( hDBF, structure, 2 );
+ if (1 != sscanf(dbf_temp, "%f", &lat_f)) {
+ fprintf(stderr,"draw_shapefile_map:sscanf parsing error\n");
+ }
+ dbf_temp = DBFReadStringAttribute( hDBF, structure, 3 );
+ if (1 != sscanf(dbf_temp, "%f", &lon_f)) {
+ fprintf(stderr,"draw_shapefile_map:sscanf parsing error\n");
+ }
+ lon_f = lon_f - 0.125;
+ }
+ else {
+ lat_f = 0.0;
+ lon_f = 0.0;
+ }
+
+ //fprintf(stderr,"Lat: %f, Lon: %f\t, Quad: %s\n", lat_f, lon_f, quad_label);
+
+ temp_ok = convert_to_xastir_coordinates(&my_long,
+ &my_lat,
+ (float)lon_f,
+ (float)lat_f);
+ }
+ else { // Not quad overlay, use vertices
+ // XXX - todo: center large polygon labels in the center (e.g. county boundary)
+ /* center label in polygon bounding box */
+ temp_ok = convert_to_xastir_coordinates(&my_long,
+ &my_lat,
+ ((float)(object->dfXMax + object->dfXMin))/2.0,
+ ((float)(object->dfYMax + object->dfYMin))/2.0);
+#ifdef notdef
+ temp_ok = convert_to_xastir_coordinates(&my_long,
+ &my_lat,
+ (float)object->padfX[0],
+ (float)object->padfY[0]);
+#endif // notdef
+ }
+ //fprintf(stderr,"%ld %ld\n", my_long, my_lat);
+
+ if (!temp_ok) {
+ fprintf(stderr,"draw_shapefile_map8: Problem converting from lat/lon\n");
+ ok = 0;
+ x = 0;
+ y = 0;
+ }
+ else {
+ // Convert to screen coordinates. Careful
+ // here! The format conversions you'll need
+ // if you try to compress this into two
+ // lines will get you into trouble.
+ x = my_long - NW_corner_longitude;
+ y = my_lat - NW_corner_latitude;
+ x = x / scale_x;
+ y = y / scale_y;
+
+// Labeling of polygons done here
+
+ if (ok == 1 && ok_to_draw) {
+ if (quad_overlay_flag) {
+ draw_nice_string(w,
+ pixmap,
+ 0,
+ x+2,
+ y-1,
+ (char*)quad_label,
+ 0xf,
+ 0x10,
+ strlen(quad_label));
+ }
+ else {
+#ifdef notdef
+ (void)draw_label_text ( w,
+ x,
+ y,
+ strlen(temp),
+ colors[label_color],
+ (char *)temp);
+#endif // notdef
+ if (debug_level & 16) {
+ fprintf(stderr,
+ " displaying label %s with color %x\n",
+ temp,label_color);
+ }
+ (void)draw_centered_label_text(w,
+ -90,
+ x,
+ y,
+ strlen(temp),
+ colors[label_color],
+ (char *)temp,
+ font_size);
+ }
+ }
+ }
+ }
+ break;
+
+ case SHPT_MULTIPOINT:
+ case SHPT_MULTIPOINTZ:
+ // Not implemented.
+ fprintf(stderr,"Shapefile Multi-Point format files aren't supported!\n");
+ break;
+
+ default:
+ // Not implemented.
+ fprintf(stderr,"Shapefile format not supported: Subformat unknown (default clause of switch)!\n");
+ break;
+
+ } // End of switch
+ }
+ SHPDestroyObject( object ); // Done with this structure
+ }
+
+
+ // Free our hash of label strings, if any. Each hash entry may
+ // have a linked list attached below it.
+ for (i = 0; i < 256; i++) {
+ ptr2 = label_hash[i];
+ while (ptr2 != NULL) {
+ label_hash[i] = ptr2->next;
+ //fprintf(stderr,"free: %s\n",ptr2->label);
+ free(ptr2);
+ ptr2 = label_hash[i];
+ }
+ }
+
+#ifdef WITH_DBFAWK
+ dbfawk_free_info(fld_info);
+ if (sig_info != NULL && sig_info != dbfawk_default_sig && (sig_info->sig == NULL)) {
+ dbfawk_free_sigs(sig_info);
+ }
+#endif // WITH_DBFAWK
+
+ DBFClose( hDBF );
+ SHPClose( hSHP );
+
+// XmUpdateDisplay (XtParent (da));
+
+ if (debug_level & 16) {
+ fprintf(stderr,"High-Mark Index:%d,\tHigh-Mark i:%d\n",
+ high_water_mark_index,
+ high_water_mark_i);
+ }
+
+ // Set fill style back to defaults
+ XSetFillStyle(XtDisplay(w), gc, FillSolid);
+}
+// End of draw_shapefile_map()
+
+
+
+
+
+#ifdef WITH_DBFAWK
+
+// This function will delete any pre-loaded dbfawk sigs and clear Dbf_sigs
+// This will trigger a reload the first time a shapfile is redisplayed
+void clear_dbfawk_sigs(void) {
+ // fprintf(stderr,"Clearing signatures.\n");
+ if (Dbf_sigs ) {
+ dbfawk_free_sigs(Dbf_sigs);
+ Dbf_sigs = NULL;
+ }
+}
+
+#endif // WITH_DBFAWK
+
+
+#endif // HAVE_LIBSHP
+
+
diff --git a/src/map_tif.c b/src/map_tif.c
new file mode 100644
index 0000000..4fb4486
--- /dev/null
+++ b/src/map_tif.c
@@ -0,0 +1,2824 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: map_tif.c,v 1.47 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <dirent.h>
+#include <netinet/in.h>
+#include <Xm/XmAll.h>
+
+#ifdef HAVE_X11_XPM_H
+#include <X11/xpm.h>
+#ifdef HAVE_LIBXPM // if we have both, prefer the extra library
+#undef HAVE_XM_XPMI_H
+#endif // HAVE_LIBXPM
+#endif // HAVE_X11_XPM_H
+
+#ifdef HAVE_XM_XPMI_H
+#include <Xm/XpmI.h>
+#endif // HAVE_XM_XPMI_H
+
+#include <X11/Xlib.h>
+
+#include <math.h>
+
+#include "xastir.h"
+#include "maps.h"
+#include "alert.h"
+#include "util.h"
+#include "main.h"
+#include "datum.h"
+#include "draw_symbols.h"
+#include "rotated.h"
+#include "color.h"
+#include "xa_config.h"
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+#define DOS_HDR_LINES 8
+#define GRID_MORE 5000
+
+extern int npoints; /* tsk tsk tsk -- globals */
+extern int mag;
+
+#ifdef HAVE_LIBGEOTIFF
+
+
+#include "xtiffio.h"
+//#include "geotiffio.h"
+
+#include "geo_normalize.h"
+
+
+// Needed for GTIFProj4FromLatLong() replacement below
+#ifdef HAVE_LIBGDAL
+# include "proj_api.h"
+#endif // HAVE_LIBGDAL
+
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+
+
+/**********************************************************
+ * get_alt_fgd_path()
+ *
+ * Used to search for .fgd in ../metadata subdir, as it is
+ * layed out on a USGS CDROM.
+ **********************************************************/
+void get_alt_fgd_path(char *fullpath, int fullpath_length) {
+ int len;
+ int i, j = 0;
+ char *dir = fullpath;
+ char fname[MAX_FILENAME];
+
+ // Split up into directory and filename
+ len = (int)strlen (fullpath);
+ for (i = len; i >= 0; i--) {
+ if (fullpath[i] == '/') {
+ dir = &fullpath[i];
+ break;
+ }
+ }
+ for (++i; i <= len; i++) {
+ fname[j++] = fullpath[i]; // Grab the filename
+ if (fullpath[i] == '\0')
+ break;
+ }
+
+ // We have the filename now. dir now points to
+ // the '/' at the end of the path.
+
+ // Now do it again to knock off the "data" subdirectory
+ // from the end.
+ dir[0] = '\0'; // Terminate the current string, wiping out the '/' character
+ len = (int)strlen (fullpath); // Length of the new shortened string
+ for (i = len; i >= 0; i--) {
+ if (fullpath[i] == '/') {
+ dir = &fullpath[i + 1]; // Dir now points to one past the '/' character
+ break;
+ }
+ }
+ for (++i; i <= len; i++) {
+ if (fullpath[i] == '\0')
+ break;
+ }
+
+ // Add "metadata/" into the path
+ xastir_snprintf(dir, fullpath_length, "metadata/%s", fname);
+ //fprintf(stderr,"FGD Directory: %s\n", fullpath);
+}
+
+
+
+
+
+/**********************************************************
+ * get_alt_fgd_path2()
+ *
+ * Used to search for .fgd in Metadata subdir. This function
+ * is no longer used.
+ **********************************************************/
+void get_alt_fgd_path2(char *fullpath, int fullpath_length) {
+ int len;
+ int i, j = 0;
+ char *dir = fullpath;
+ char fname[MAX_FILENAME];
+
+ // Split up into directory and filename
+ len = (int)strlen (fullpath);
+ for (i = len; i >= 0; i--) {
+ if (fullpath[i] == '/') {
+ dir = &fullpath[i + 1];
+ break;
+ }
+ }
+ for (++i; i <= len; i++) {
+ fname[j++] = fullpath[i];
+ if (fullpath[i] == '\0')
+ break;
+ }
+
+ // Add "Metadata/" into the path
+ xastir_snprintf(dir, fullpath_length, "Metadata/%s", fname);
+}
+
+
+
+
+
+/***********************************************************
+ * read_fgd_file()
+ *
+ * Read in the "*.fgd" file associated with the geoTIFF
+ * file. Get the corner points from it and return. If
+ * no fgd file exists for this map, return a 0.
+ ***********************************************************/
+int read_fgd_file ( char* tif_filename,
+ float* f_west_bounding,
+ float* f_east_bounding,
+ float* f_north_bounding,
+ float* f_south_bounding)
+{
+ char fgd_file[MAX_FILENAME];/* Complete path/name of .fgd file */
+ FILE *fgd; /* Filehandle of .fgd file */
+ char line[MAX_FILENAME]; /* One line from .fgd file */
+ int length;
+ char *ptr; /* Substring pointer */
+ int num_coordinates = 0;
+
+
+ /* Read the .fgd file to find corners of the map neat-line */
+ xastir_snprintf(fgd_file,
+ sizeof(fgd_file),
+ "%s",
+ tif_filename);
+ length = strlen(fgd_file);
+
+ /* Change the extension to ".fgd" */
+ fgd_file[length-3] = 'f';
+ fgd_file[length-2] = 'g';
+ fgd_file[length-1] = 'd';
+
+ if (debug_level & 512)
+ fprintf(stderr,"%s\n",fgd_file);
+
+ /*
+ * Search for the WEST/EAST/NORTH/SOUTH BOUNDING COORDINATES
+ * in the .fgd file.
+ */
+ fgd = fopen (fgd_file, "r");
+
+ // Try an alternate path (../metadata/ subdirectory) if the first path didn't work
+ // This allows working with USGS maps directly from CDROM
+ if (fgd == NULL) {
+ get_alt_fgd_path(fgd_file, sizeof(fgd_file) );
+
+ if (debug_level & 512)
+ fprintf(stderr,"%s\n",fgd_file);
+
+ fgd = fopen (fgd_file, "r");
+ }
+
+ if (fgd != NULL)
+ {
+ while ( ( !feof (fgd) ) && ( num_coordinates < 4 ) )
+ {
+ get_line (fgd, line, MAX_FILENAME);
+
+ if (*f_west_bounding == 0.0)
+ {
+ if ( ( (ptr = strstr(line, "WEST BOUNDING COORDINATE:") ) != NULL)
+ || ( (ptr = strstr(line, "West_Bounding_Coordinate:") ) != NULL) )
+ {
+ if (1 != sscanf (ptr + 25, " %f", f_west_bounding)) {
+ fprintf(stderr,"read_fgd_file:sscanf parsing error\n");
+ }
+ if (debug_level & 512)
+ fprintf(stderr,"West Bounding: %f\n",*f_west_bounding);
+ num_coordinates++;
+ }
+ }
+
+ else if (*f_east_bounding == 0.0)
+ {
+ if ( ( (ptr = strstr(line, "EAST BOUNDING COORDINATE:") ) != NULL)
+ || ( (ptr = strstr(line, "East_Bounding_Coordinate:") ) != NULL) )
+ {
+ if (1 != sscanf (ptr + 25, " %f", f_east_bounding)) {
+ fprintf(stderr,"read_fgd_file:sscanf parsing error\n");
+ }
+ if (debug_level & 512)
+ fprintf(stderr,"East Bounding: %f\n",*f_east_bounding);
+ num_coordinates++;
+ }
+ }
+
+ else if (*f_north_bounding == 0.0)
+ {
+ if ( ( (ptr = strstr(line, "NORTH BOUNDING COORDINATE:") ) != NULL)
+ || ( (ptr = strstr(line, "North_Bounding_Coordinate:") ) != NULL) )
+ {
+ if (1 != sscanf (ptr + 26, " %f", f_north_bounding)) {
+ fprintf(stderr,"read_fgd_file:sscanf parsing error\n");
+ }
+ if (debug_level & 512)
+ fprintf(stderr,"North Bounding: %f\n",*f_north_bounding);
+ num_coordinates++;
+ }
+ }
+
+ else if (*f_south_bounding == 0.0)
+ {
+ if ( ( (ptr = strstr(line, "SOUTH BOUNDING COORDINATE:") ) != NULL)
+ || ( (ptr = strstr(line, "South_Bounding_Coordinate:") ) != NULL) )
+ {
+ if (1 != sscanf (ptr + 26, " %f", f_south_bounding)) {
+ fprintf(stderr,"read_fgd_file:sscanf parsing error\n");
+ }
+ if (debug_level & 512)
+ fprintf(stderr,"South Bounding: %f\n",*f_south_bounding);
+ num_coordinates++;
+ }
+ }
+
+ }
+ fclose (fgd);
+ }
+ else
+ {
+ if (debug_level & 512)
+ fprintf(stderr,"Couldn't open '.fgd' file, assuming no map collar to chop %s\n",
+ tif_filename);
+ return(0);
+ }
+
+
+ /*
+ * We should now have exactly four bounding coordinates.
+ * These specify the map neat-line corners. We can use
+ * them to chop off the white collar from around the map.
+ */
+ if (num_coordinates != 4)
+ {
+ fprintf(stderr,"Couldn't find 4 bounding coordinates in '.fgd' file, map %s\n",
+ tif_filename);
+ return(0);
+ }
+
+
+ if (debug_level & 512) {
+ fprintf(stderr,"%f %f %f %f\n",
+ *f_south_bounding,
+ *f_north_bounding,
+ *f_west_bounding,
+ *f_east_bounding);
+ }
+
+ return(1); /* Successful */
+}
+
+
+
+
+
+#ifndef HAVE_LIBGDAL
+# define my_GTIFProj4FromLatLong GTIFProj4FromLatLong
+#else
+
+// If we have libgdal included then the GTIFProj4FromLatLong()
+// functions may not work. In this case we use the function below
+// instead.
+
+
+// This next function was borrowed from the libgeotiff project. We
+// have permission from Frank Warmerdam to use any code from
+// geotiff_proj4.c and relicense it under GPL, per private message
+// of 10/14/2005. Frank wrote that module.
+//
+// When we used the original function from libgeotiff we'd lose topo
+// map capability if we linked in libgdal. We avoid that problem by
+// having a local copy of the function here with a different name so
+// that libgdal can't try to override it.
+//
+//***********************************************************************
+// my_GTIFProj4FromLatLong()
+//
+// Convert lat/long values to projected coordinate for a
+// particular definition.
+//***********************************************************************
+
+int my_GTIFProj4FromLatLong( GTIFDefn * psDefn,
+ int nPoints,
+ double *padfX,
+ double *padfY ) {
+
+ char *pszProjection;
+ projPJ psPJ;
+ int i;
+
+// --------------------------------------------------------------------
+// Get a projection definition.
+// --------------------------------------------------------------------
+ pszProjection = GTIFGetProj4Defn( psDefn );
+
+ if( pszProjection == NULL )
+ return FALSE;
+
+//fprintf(stderr,"pszProjection:%s\n", pszProjection);
+// Returned this:
+// pszProjection:+proj=utm +zone=10 +ellps=clrk66 +units=m
+
+
+// --------------------------------------------------------------------
+// Initialize the projection
+// --------------------------------------------------------------------
+
+ psPJ = pj_init_plus(pszProjection);
+
+ if( psPJ == NULL ) {
+ return FALSE;
+ }
+
+// --------------------------------------------------------------------
+// Process each of the points.
+// --------------------------------------------------------------------
+
+ for( i = 0; i < nPoints; i++ ) {
+ projUV sUV;
+
+ sUV.u = padfX[i] * DEG_TO_RAD;
+ sUV.v = padfY[i] * DEG_TO_RAD;
+
+ sUV = pj_fwd( sUV, psPJ );
+
+ padfX[i] = sUV.u;
+ padfY[i] = sUV.v;
+ }
+
+ pj_free( psPJ );
+
+ return TRUE;
+}
+#endif // HAVE_LIBGDAL
+
+
+
+
+
+// Check the "GTIFProj4*" functions to see if we can use
+// datum.c instead for any of them. These calls are all in
+// draw_geotiff_image_map(). It looks like they deal with
+// converting from pixels to coordinates and vice-versa, so we
+// probably still need them. Perhaps we can borrow the code for
+// that and do it ourselves, to get rid of the extra library?
+
+/***********************************************************
+ * draw_geotiff_image_map()
+ *
+ * Here's where we handle geoTIFF files, such as USGS DRG
+ * topo maps. The .fgd file gives us the lat/lon of the map
+ * neat-line corners for USGS maps. We use this info to
+ * chop off the white map border. If no .fgd file is present,
+ * we assume there is no map collar to be cropped and display
+ * every pixel.
+ * We also translate from the map datum to WGS84. We use
+ * libgeotiff/libtiff/libproj for these operations.
+
+ * TODO:
+ * Provide support for datums other than NAD27/NAD83/WGS84.
+ * Libproj doesn't currently support many datums.
+ *
+ * Provide support for handling different map projections.
+ * Perhaps by reprojecting the map data and storing it on
+ * disk in another format.
+ *
+ * Select 'o', 'f', 'k', or 'c' maps based on zoom level.
+ * Might also put some hysteresis in this so that it keeps
+ * the current type of map through one extra zoom each way.
+ * 'c': Good from x256 to x064.
+ * 'f': Good from x128 to x032. Not very readable at x128.
+ * 'k': Good from x??? to x???.
+ * 'o': Good from x064 to x004. Not very readable at x64.
+ ***********************************************************/
+void draw_geotiff_image_map (Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *mdf) {
+ char file[MAX_FILENAME]; /* Complete path/name of image file */
+ char short_filenm[MAX_FILENAME];
+ TIFF *tif = (TIFF *) 0; /* Filehandle for tiff image file */
+ GTIF *gtif = (GTIF *) 0; /* GeoKey-level descriptor */
+ /* enum { VERSION = 0, MAJOR, MINOR }; */
+ int versions[3];
+ uint32 width; /* Width of the image */
+ uint32 height; /* Height of the image */
+ uint16 bitsPerSample; /* Should be 8 for USGS DRG's */
+ uint16 samplesPerPixel = 1; /* Should be 1 for USGS DRG's. Some maps
+ don't have this tag so we default to 1 */
+ uint32 rowsPerStrip; /* Should be 1 for USGS DRG's */
+ uint16 planarConfig; /* Should be 1 for USGS DRG's */
+ uint16 photometric; /* DRGs are RGB (2) */
+ int bytesPerRow; /* Bytes per scanline row of tiff file */
+ GTIFDefn defn; /* Stores geotiff details */
+ u_char *imageMemory; /* Fixed pointer to same memory area */
+ uint32 row; /* My row counter for the loop */
+ int num_colors; /* Number of colors in the geotiff colormap */
+ uint16 *red_orig, *green_orig, *blue_orig; /* Used for storing geotiff colors */
+ XColor my_colors[256]; /* Used for translating colormaps */
+ unsigned long west_bounding = 0;
+ unsigned long east_bounding = 0;
+ unsigned long north_bounding = 0;
+ unsigned long south_bounding = 0;
+ float f_west_bounding = 0.0;
+ float f_east_bounding = 0.0;
+ float f_north_bounding = 0.0;
+ float f_south_bounding = 0.0;
+
+ unsigned long west_bounding_wgs84 = 0;
+ unsigned long east_bounding_wgs84 = 0;
+ unsigned long north_bounding_wgs84 = 0;
+ unsigned long south_bounding_wgs84 = 0;
+
+ float f_NW_x_bounding;
+ float f_NW_y_bounding;
+ float f_NE_x_bounding;
+ float f_NE_y_bounding;
+ float f_SW_x_bounding;
+ float f_SW_y_bounding;
+ float f_SE_x_bounding;
+ float f_SE_y_bounding;
+
+ unsigned long NW_x_bounding_wgs84 = 0;
+ unsigned long NW_y_bounding_wgs84 = 0;
+ double f_NW_x_bounding_wgs84 = 0.0;
+ double f_NW_y_bounding_wgs84 = 0.0;
+
+ unsigned long NE_x_bounding_wgs84 = 0;
+ unsigned long NE_y_bounding_wgs84 = 0;
+ double f_NE_x_bounding_wgs84 = 0.0;
+ double f_NE_y_bounding_wgs84 = 0.0;
+
+ unsigned long SW_x_bounding_wgs84 = 0;
+ unsigned long SW_y_bounding_wgs84 = 0;
+ double f_SW_x_bounding_wgs84 = 0.0;
+ double f_SW_y_bounding_wgs84 = 0.0;
+
+ unsigned long SE_x_bounding_wgs84 = 0;
+ unsigned long SE_y_bounding_wgs84 = 0;
+ double f_SE_x_bounding_wgs84 = 0.0;
+ double f_SE_y_bounding_wgs84 = 0.0;
+
+ int NW_x = 0; /* Store pixel values for map neat-line */
+ int NW_y = 0; /* ditto */
+ int NE_x = 0; /* ditto */
+ int NE_y = 0; /* ditto */
+ int SW_x = 0; /* ditto */
+ int SW_y = 0; /* ditto */
+ int SE_x = 0; /* ditto */
+ int SE_y = 0; /* ditto */
+ int left_crop; /* Pixel cropping value */
+ int right_crop; /* Pixel cropping value */
+ int top_crop; /* Pixel cropping value */
+ int bottom_crop; /* Pixel cropping value */
+ double xxx, yyy; /* LFM: needs more accuracy here */
+ register long sxx, syy; /* X Y screen plot positions */
+ float steph;
+ register float stepw;
+ int stepwc, stephc;
+ char map_it[MAX_FILENAME]; /* Used to hold filename for status line */
+ int have_fgd; /* Tells where we have an associated *.fgd file */
+ //short datum;
+ char *datum_name; /* Points to text name of datum */
+ //double *GeoTie;
+ int crop_it = 0; /* Flag which tells whether the image should be cropped */
+
+ register uint32 column;
+
+ float xastir_left_x_increment;
+ float left_x_increment;
+ float xastir_left_y_increment;
+ float left_y_increment;
+ float xastir_right_x_increment;
+ float right_x_increment;
+ float xastir_right_y_increment;
+ float right_y_increment;
+ float xastir_top_y_increment;
+ float top_y_increment;
+ float xastir_bottom_y_increment;
+ float bottom_y_increment;
+ float xastir_avg_y_increment;
+ float avg_y_increment;
+ int row_offset;
+ register unsigned long current_xastir_left;
+ unsigned long current_xastir_right;
+ register uint32 current_left;
+ uint32 current_right;
+ uint32 current_line_width;
+ register unsigned long xastir_current_y;
+ register uint32 column_offset;
+ register unsigned long xastir_current_x;
+ double *PixelScale;
+ int have_PixelScale;
+ uint16 qty;
+ int SkipRows;
+ unsigned long view_min_x, view_max_x;
+ unsigned long view_min_y, view_max_y;
+
+ register unsigned long xastir_total_y;
+ int NW_line_offset;
+ int NE_line_offset;
+ int NW_xastir_x_offset;
+ int NE_xastir_x_offset;
+ int NW_xastir_y_offset;
+ int NW_x_offset;
+ int NE_x_offset;
+ float xastir_avg_left_right_y_increment;
+ register float total_avg_y_increment;
+ unsigned long view_left_minus_pixel_width;
+ unsigned long view_top_minus_pixel_height;
+ int proj_is_latlong;
+ short PCS;
+ int usgs_drg;
+ char *imagedesc;
+
+ usgs_drg = mdf->usgs_drg; // yes, no, or auto
+
+ if (debug_level & 16)
+ fprintf(stderr,"%s/%s\n", dir, filenm);
+
+
+ xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm);
+
+ // Create a shorter filename for display (one that fits the
+ // status line more closely). Subtract the length of the
+ // "Indexing " and/or "Loading " strings as well.
+ if (strlen(filenm) > (41 - 9)) {
+ int avail = 41 - 11;
+ int new_len = strlen(filenm) - avail;
+
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "..%s",
+ &filenm[new_len]);
+ }
+ else {
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "%s",
+ filenm);
+ }
+
+ /* Check whether we have an associated *.fgd file. This
+ * file contains the neat-line corner points for USGS DRG
+ * maps, which allows us to chop off the map collar.
+ */
+ have_fgd = read_fgd_file( file,
+ &f_west_bounding,
+ &f_east_bounding,
+ &f_north_bounding,
+ &f_south_bounding );
+
+ /*
+ * If we are able to read the fgd file then we have the lat/lon
+ * corner points in floating point variables. If there isn't
+ * an fgd file then we must get the info from the geotiff
+ * tags themselves and we assume that there's no map collar to
+ * chop off.
+ */
+
+
+ /*
+ * What we NEED to do (implemented a bit later in this function
+ * in order to support geotiff files created with other map
+ * datums, is to open up the geotiff file and get the map datum
+ * used for the data. Then convert the corner points to WGS84
+ * and check to see whether the image is inside our viewport.
+ * Some USGS geotiff maps have map data in NAD83 datum and the
+ * .fgd file incorrectly specifying NAD27 datum. There are also
+ * some USGS geotiff maps created with WGS84 datum.
+ */
+
+
+ /* convert_to_xastir_coordinates( x,y,longitude,latitude ); */
+ if (have_fgd) /* Could be a USGS file */
+ {
+ int temp_ok1, temp_ok2;
+
+ if (debug_level & 16) {
+ fprintf(stderr,"FGD: W:%f E:%f N:%f S:%f\n",
+ f_west_bounding,
+ f_east_bounding,
+ f_north_bounding,
+ f_south_bounding);
+ }
+
+ crop_it = 1; /* The map collar needs to be cropped */
+
+ temp_ok1 = convert_to_xastir_coordinates( &west_bounding,
+ &north_bounding,
+ f_west_bounding,
+ f_north_bounding );
+
+
+ temp_ok2 = convert_to_xastir_coordinates( &east_bounding,
+ &south_bounding,
+ f_east_bounding,
+ f_south_bounding );
+
+ if (!temp_ok1 || !temp_ok2) {
+ fprintf(stderr,"draw_geotiff_image_map: problem converting from lat/lon\n");
+ return;
+ }
+
+
+ /*
+ * Check whether map is inside our current view. It'd be
+ * good to do a datum conversion first, but we don't know
+ * what the datum is by this point in the code. I'm just
+ * doing this check here for speed, so that I can eliminate
+ * maps that aren't even close to our viewport area, without
+ * having to open those map files. All other maps that pass
+ * this test (at the next go-around later in the code) must
+ * have their corner points datum-shifted so that we can
+ * REALLY tell whether a map fits within the viewport.
+ *
+ * Perhaps add a bit to the corners (the max datum shift?)
+ * to do our quick check? I decided to add about 10 seconds
+ * to the map edges, which equates to 1000 in the Xastir
+ * coordinate system. That should be greater than any datum
+ * shift in North America for USGS topos. I'm artificially
+ * inflating the size of the map just for this quick
+ * elimination check.
+ *
+ * bottom top left right
+ */
+
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap != INDEX_CHECK_TIMESTAMPS)
+ && (destination_pixmap != INDEX_NO_TIMESTAMPS) ) {
+
+ // We're drawing.
+ if (!map_visible( south_bounding + 1000,
+ north_bounding - 1000,
+ west_bounding - 1000,
+ east_bounding + 1000 ) ) {
+ if (debug_level & 16) {
+ fprintf(stderr,"Map not within current view.\n");
+ fprintf(stderr,"Skipping map: %s\n", file);
+ }
+
+ // Map isn't inside our current view. We're done.
+ // Free any memory used and return.
+ //
+ return; // Skip this map
+ }
+ else {
+ if (debug_level & 16) {
+ fprintf(stderr,"Map is viewable\n");
+ }
+ }
+ }
+ } // End of if have_fgd
+
+
+ /*
+ * At this point the map MAY BE in our current view.
+ * We don't know for sure until we do a datum translation
+ * on the bounding coordinates and check again. Note that
+ * if there's not an accompanying .fgd file, we don't have
+ * the bounding coordinates yet by this point.
+ */
+
+ if (debug_level & 16)
+ fprintf(stderr,"XTIFFOpen\n");
+
+ /* Open TIFF descriptor to read GeoTIFF tags */
+ tif = XTIFFOpen (file, "r");
+ if (!tif)
+ return;
+
+ if (debug_level & 16)
+ fprintf(stderr,"GTIFNew\n");
+
+ /* Open GTIF Key parser. Keys will be read at this time */
+ gtif = GTIFNew (tif);
+ if (!gtif)
+ {
+ /* Close the TIFF file descriptor */
+ XTIFFClose (tif);
+ return;
+ }
+
+ if (debug_level & 16)
+ fprintf(stderr,"GTIFDirectoryInfo\n");
+
+ /*
+ * Get the GeoTIFF directory info. Need this for
+ * some of the operations further down in the code.
+ */
+ GTIFDirectoryInfo (gtif, versions, 0);
+
+ /*
+ if (versions[MAJOR] > 1)
+ {
+ fprintf(stderr,"This file is too new for me\n");
+ GTIFFree (gtif);
+ XTIFFClose (tif);
+ return;
+ }
+ */
+
+ if (debug_level & 16)
+ fprintf(stderr,"GTIFGetDefn\n");
+
+
+ /* I might want to attempt to avoid the GTIFGetDefn
+ * call, as it takes a bit of time per file. It
+ * normalizes the info. Try getting just the tags
+ * or keys that I need individually instead. I
+ * need "defn" for the GTIFProj4ToLatLong calls though.
+ */
+ if (GTIFGetDefn (gtif, &defn)) {
+ if (debug_level & 16)
+ GTIFPrintDefn (&defn, stdout);
+ }
+ else {
+ fprintf(stderr,"GTIFGetDefn failed\n");
+ }
+
+ proj_is_latlong=FALSE;
+
+ if( !GTIFKeyGet(gtif,ProjectedCSTypeGeoKey, &PCS,0,1)) {
+ // fprintf(stderr,"Warning: no PCS in geotiff file %s, assuming map is in lat/lon!\n", filenm);
+ proj_is_latlong=TRUE;
+ }
+
+ /* Fetch a few TIFF fields for this image */
+ if ( !TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &width) ) {
+ width = 5493;
+ fprintf(stderr,"No width tag found in file, setting it to 5493\n");
+ }
+
+ if ( !TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &height) ) {
+ height = 6840;
+ fprintf(stderr,"No height tag found in file, setting it to 6840\n");
+ }
+
+ // If we're autodetecting usgs_drg, check the image description tag
+ // Note, the TIFFGetField doesn't allocate a string, it returns a pointer
+ // to an existing one. Don't free it!
+ if (usgs_drg == 2) {
+ if ( TIFFGetField (tif, TIFFTAG_IMAGEDESCRIPTION, &imagedesc)) {
+ if (strncasecmp(imagedesc,"USGS GeoTIFF DRG",16) == 0) {
+ usgs_drg = 1; // Yes
+ }
+ else {
+ usgs_drg = 0; // No
+ }
+ }
+ else {
+ usgs_drg = 0; // No tag, assume not a usgs topo
+ }
+
+ }
+
+ /*
+ * If we don't have an associated .fgd file for this map,
+ * check for corner points in the ImageDescription
+ * tag (proposed new USGS DRG standard). Boundary
+ * coordinates will be the outside corners of the image
+ * unless I can find some other proof.
+ * Currently I assume that the map has no
+ * map collar to chop off and set the neat-line corners
+ * to be the outside corners of the image.
+ *
+ * NOTE: For the USGS files (with a map collar), the
+ * image must be cropped and rotated and is slightly
+ * narrower at one end (top for northern hemisphere, bottom
+ * for southern hemisphere). For other files with no map
+ * collar, the image is rectangular but the lat/lon
+ * coordinates may be rotated.
+ */
+ if (!have_fgd) // Not a USGS map or perhaps a newer spec
+ {
+ crop_it = 1; /* crop this map image */
+
+ /*
+ * Snag and parse ImageDescription tag here.
+ */
+
+ /* Code goes here for getting ImageDescription tag... */
+
+
+ /* Figure out the bounding coordinates for this map */
+ if (debug_level & 16)
+ fprintf(stderr,"\nCorner Coordinates:\n");
+
+ /* Find lat/lon for NW corner of image */
+ xxx = 0.0;
+ yyy = 0.0;
+ if ( GTIFImageToPCS( gtif, &xxx, &yyy ) ) // Do all 4 of these in one call?
+ {
+ if (debug_level & 16) {
+ fprintf(stderr,"%-13s ", "Upper Left" );
+ fprintf(stderr,"(%11.3f,%11.3f)\n", xxx, yyy );
+ }
+ }
+
+ if ( proj_is_latlong || GTIFProj4ToLatLong( &defn, 1, &xxx, &yyy ) ) // Do all 4 of these in one call?
+ {
+ if (debug_level & 16) {
+ fprintf(stderr," (%s,", GTIFDecToDMS( xxx, "Long", 2 ) );
+ fprintf(stderr,"%s)\n", GTIFDecToDMS( yyy, "Lat", 2 ) );
+ fprintf(stderr,"%f %f\n", xxx, yyy);
+ }
+ }
+ else {
+ if (!proj_is_latlong) {
+ fprintf(stderr,"Failed GTIFProj4ToLatLong() call\n");
+ }
+ }
+
+ f_NW_x_bounding = (float)xxx;
+ f_NW_y_bounding = (float)yyy;
+
+
+ /* Find lat/lon for NE corner of image */
+ xxx = width - 1;
+ yyy = 0.0;
+ if ( GTIFImageToPCS( gtif, &xxx, &yyy ) )
+ {
+ if (debug_level & 16) {
+ fprintf(stderr,"%-13s ", "Lower Right" );
+ fprintf(stderr,"(%11.3f,%11.3f)\n", xxx, yyy );
+ }
+ }
+
+ if ( proj_is_latlong || GTIFProj4ToLatLong( &defn, 1, &xxx, &yyy ) )
+ {
+ if (debug_level & 16) {
+ fprintf(stderr," (%s,", GTIFDecToDMS( xxx, "Long", 2 ) );
+ fprintf(stderr,"%s)\n", GTIFDecToDMS( yyy, "Lat", 2 ) );
+ fprintf(stderr,"%f %f\n", xxx, yyy);
+ }
+ }
+ else {
+ if (!proj_is_latlong) {
+ fprintf(stderr,"Failed GTIFProj4ToLatLong() call\n");
+ }
+ }
+
+ f_NE_x_bounding = (float)xxx;
+ f_NE_y_bounding = (float)yyy;
+
+ /* Find lat/lon for SW corner of image */
+ xxx = 0.0;
+ yyy = height - 1;
+ if ( GTIFImageToPCS( gtif, &xxx, &yyy ) )
+ {
+ if (debug_level & 16) {
+ fprintf(stderr,"%-13s ", "Lower Right" );
+ fprintf(stderr,"(%11.3f,%11.3f)\n", xxx, yyy );
+ }
+ }
+
+ if ( proj_is_latlong || GTIFProj4ToLatLong( &defn, 1, &xxx, &yyy ) )
+ {
+ if (debug_level & 16) {
+ fprintf(stderr," (%s,", GTIFDecToDMS( xxx, "Long", 2 ) );
+ fprintf(stderr,"%s)\n", GTIFDecToDMS( yyy, "Lat", 2 ) );
+ fprintf(stderr,"%f %f\n", xxx, yyy);
+ }
+ }
+ else {
+ if (!proj_is_latlong) {
+ fprintf(stderr,"Failed GTIFProj4ToLatLong() call\n");
+ }
+ }
+
+ f_SW_x_bounding = (float)xxx;
+ f_SW_y_bounding = (float)yyy;
+
+ /* Find lat/lon for SE corner of image */
+ xxx = width - 1;
+ yyy = height - 1;
+ if ( GTIFImageToPCS( gtif, &xxx, &yyy ) )
+ {
+ if (debug_level & 16) {
+ fprintf(stderr,"%-13s ", "Lower Right" );
+ fprintf(stderr,"(%11.3f,%11.3f)\n", xxx, yyy );
+ }
+ }
+
+ if ( proj_is_latlong || GTIFProj4ToLatLong( &defn, 1, &xxx, &yyy ) )
+ {
+ if (debug_level & 16) {
+ fprintf(stderr," (%s,", GTIFDecToDMS( xxx, "Long", 2 ) );
+ fprintf(stderr,"%s)\n", GTIFDecToDMS( yyy, "Lat", 2 ) );
+ fprintf(stderr,"%f %f\n", xxx, yyy);
+ }
+ }
+ else {
+ if (!proj_is_latlong) {
+ fprintf(stderr,"Failed GTIFProj4ToLatLong() call\n");
+ }
+ }
+
+ f_SE_x_bounding = (float)xxx;
+ f_SE_y_bounding = (float)yyy;
+
+ if (f_NW_y_bounding > 0) {
+ yyy=((f_NW_y_bounding > f_NE_y_bounding) ? f_NE_y_bounding
+ : f_NW_y_bounding);
+ xxx=((f_SW_y_bounding < f_SE_y_bounding) ? f_SE_y_bounding
+ : f_SW_y_bounding);
+ } else {
+ yyy=((f_NW_y_bounding < f_NE_y_bounding) ? f_NE_y_bounding
+ : f_NW_y_bounding);
+ xxx=((f_SW_y_bounding > f_SE_y_bounding) ? f_SE_y_bounding
+ : f_SW_y_bounding);
+ }
+ f_north_bounding = (float)yyy;
+ f_south_bounding = (float)xxx;
+ if (f_NE_x_bounding > 0) {
+ xxx=((f_NE_x_bounding < f_SE_x_bounding) ? f_SE_x_bounding
+ : f_NE_x_bounding);
+ yyy=((f_NW_x_bounding > f_SW_x_bounding) ? f_SW_x_bounding
+ : f_NW_x_bounding);
+ } else {
+ xxx=((f_NE_x_bounding > f_SE_x_bounding) ? f_SE_x_bounding
+ : f_NE_x_bounding);
+ yyy=((f_NW_x_bounding < f_SW_x_bounding) ? f_SW_x_bounding
+ : f_NW_x_bounding);
+ }
+ f_west_bounding = (float)yyy;
+ f_east_bounding = (float)xxx;
+ }
+
+ f_NW_x_bounding = f_west_bounding;
+ f_NW_y_bounding = f_north_bounding;
+
+ f_SW_x_bounding = f_west_bounding;
+ f_SW_y_bounding = f_south_bounding;
+
+ f_NE_x_bounding = f_east_bounding;
+ f_NE_y_bounding = f_north_bounding;
+
+ f_SE_x_bounding = f_east_bounding;
+ f_SE_y_bounding = f_south_bounding;
+
+
+ // Fill in the wgs84 variables so we can do a datum
+ // conversion but keep our original values also.
+ f_NW_x_bounding_wgs84 = f_NW_x_bounding;
+ f_NW_y_bounding_wgs84 = f_NW_y_bounding;
+
+ f_SW_x_bounding_wgs84 = f_SW_x_bounding;
+ f_SW_y_bounding_wgs84 = f_SW_y_bounding;
+
+ f_NE_x_bounding_wgs84 = f_NE_x_bounding;
+ f_NE_y_bounding_wgs84 = f_NE_y_bounding;
+
+ f_SE_x_bounding_wgs84 = f_SE_x_bounding;
+ f_SE_y_bounding_wgs84 = f_SE_y_bounding;
+
+
+ /* Get the datum */
+ // GTIFKeyGet( gtif, GeogGeodeticDatumGeoKey, &datum, 0, 1 );
+ // if (debug_level & 16)
+ // fprintf(stderr,"GeogGeodeticDatumGeoKey: %d\n", datum );
+
+
+ /* Get the tiepoints (in UTM coordinates always?)
+ * In our case they look like:
+ *
+ * 0.000000 Y
+ * 0.000000 X
+ * 0.000000 Z
+ * 572983.025771 Y in UTM (longitude for some maps?)
+ * 5331394.085064 X in UTM (latitude for some maps?)
+ * 0.000000 Z
+ *
+ */
+ /*
+ if (debug_level & 16) {
+ fprintf(stderr,"Tiepoints:\n");
+ if ( TIFFGetField( tif, TIFFTAG_GEOTIEPOINTS, &qty, &GeoTie ) ) {
+ for ( i = 0; i < qty; i++ ) {
+ fprintf(stderr,"%f\n", *(GeoTie + i) );
+ }
+ }
+ }
+ */
+
+
+ /* Get the geotiff horizontal datum name */
+ if ( defn.Datum != 32767 ) {
+ GTIFGetDatumInfo( defn.Datum, &datum_name, NULL );
+ if (debug_level & 16)
+ fprintf(stderr,"Datum: %d/%s\n", defn.Datum, datum_name );
+ }
+
+
+ /*
+ * Perform a datum shift on the bounding coordinates before we
+ * check whether the map is inside our viewport. At the moment
+ * this is still hard-coded to NAD27 datum. If the map is already
+ * in WGS84 or NAD83 datum, skip the datum conversion code.
+ */
+ if ( (defn.Datum != 6030) /* DatumE_WGS84 */
+ && (defn.Datum != 6326) /* Datum_WGS84 */
+ && (defn.Datum != 6269) ) /* Datum_North_American_Datum_1983 */ {
+
+ if (debug_level & 16)
+ fprintf(stderr,"***** Attempting Datum Conversions\n");
+
+
+ // This code uses datum.h/datum.c to do the conversion
+ // instead of the proj.4 library as we had before.
+ // Here we assume that if it's not one of the three datums
+ // listed above, it's NAD27.
+
+ // Convert NW corner to WGS84
+ wgs84_datum_shift(TO_WGS_84,
+ &f_NW_y_bounding_wgs84,
+ &f_NW_x_bounding_wgs84,
+ D_NAD_27_CONUS); // NAD27 CONUS
+
+ // Convert NE corner to WGS84
+ wgs84_datum_shift(TO_WGS_84,
+ &f_NE_y_bounding_wgs84,
+ &f_NE_x_bounding_wgs84,
+ D_NAD_27_CONUS); // NAD27 CONUS
+
+ // Convert SW corner to WGS84
+ wgs84_datum_shift(TO_WGS_84,
+ &f_SW_y_bounding_wgs84,
+ &f_SW_x_bounding_wgs84,
+ D_NAD_27_CONUS); // NAD27 CONUS
+
+ // Convert SE corner to WGS84
+ wgs84_datum_shift(TO_WGS_84,
+ &f_SE_y_bounding_wgs84,
+ &f_SE_x_bounding_wgs84,
+ D_NAD_27_CONUS); // NAD27 CONUS (131)
+ }
+ else
+ if (debug_level & 16)
+ fprintf(stderr,"***** Skipping Datum Conversion\n");
+
+
+ /*
+ * Convert new datum-translated bounding coordinates to the
+ * Xastir coordinate system.
+ * convert_to_xastir_coordinates( x,y,longitude,latitude )
+ */
+ // NW corner
+ if (!convert_to_xastir_coordinates( &NW_x_bounding_wgs84,
+ &NW_y_bounding_wgs84,
+ (float)f_NW_x_bounding_wgs84,
+ (float)f_NW_y_bounding_wgs84 ) ) {
+ fprintf(stderr,"draw_geotiff_image_map: Problem converting from lat/lon\n");
+ fprintf(stderr,"Did you follow the instructions for installing PROJ?\n");
+ return;
+ }
+
+ // NE corner
+ if (!convert_to_xastir_coordinates( &NE_x_bounding_wgs84,
+ &NE_y_bounding_wgs84,
+ (float)f_NE_x_bounding_wgs84,
+ (float)f_NE_y_bounding_wgs84 ) ) {
+ fprintf(stderr,"draw_geotiff_image_map: Problem converting from lat/lon\n");
+ fprintf(stderr,"Did you follow the instructions for installing PROJ?\n");
+
+ return;
+ }
+
+ // SW corner
+ if (!convert_to_xastir_coordinates( &SW_x_bounding_wgs84,
+ &SW_y_bounding_wgs84,
+ (float)f_SW_x_bounding_wgs84,
+ (float)f_SW_y_bounding_wgs84 ) ) {
+ fprintf(stderr,"draw_geotiff_image_map: Problem converting from lat/lon\n");
+ fprintf(stderr,"Did you follow the instructions for installing PROJ?\n");
+
+ return;
+ }
+
+ // SE corner
+ if (!convert_to_xastir_coordinates( &SE_x_bounding_wgs84,
+ &SE_y_bounding_wgs84,
+ (float)f_SE_x_bounding_wgs84,
+ (float)f_SE_y_bounding_wgs84 ) ) {
+ fprintf(stderr,"draw_geotiff_image_map: Problem converting from lat/lon\n");
+ fprintf(stderr,"Did you follow the instructions for installing PROJ?\n");
+
+ return;
+ }
+
+
+ /*
+ * Check whether map is inside our current view. These
+ * are the real datum-shifted bounding coordinates now,
+ * so this is the final decision as to whether the map
+ * should be loaded.
+ */
+
+ // Find the largest dimensions
+ if (NW_y_bounding_wgs84 <= NE_y_bounding_wgs84)
+ north_bounding_wgs84 = NW_y_bounding_wgs84;
+ else
+ north_bounding_wgs84 = NE_y_bounding_wgs84;
+
+ if (NW_x_bounding_wgs84 <= SW_x_bounding_wgs84)
+ west_bounding_wgs84 = NW_x_bounding_wgs84;
+ else
+ west_bounding_wgs84 = SW_x_bounding_wgs84;
+
+ if (SW_y_bounding_wgs84 >= SE_y_bounding_wgs84)
+ south_bounding_wgs84 = SW_y_bounding_wgs84;
+ else
+ south_bounding_wgs84 = SE_y_bounding_wgs84;
+
+ if (NE_x_bounding_wgs84 >= SE_x_bounding_wgs84)
+ east_bounding_wgs84 = NE_x_bounding_wgs84;
+ else
+ east_bounding_wgs84 = SE_x_bounding_wgs84;
+
+
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ langcode ("BBARSTA039"),
+ short_filenm);
+ statusline(map_it,0); // Indexing ...
+
+ // We're indexing only. Save the extents in the index.
+ index_update_xastir(filenm, // Filename only
+ south_bounding_wgs84, // Bottom
+ north_bounding_wgs84, // Top
+ west_bounding_wgs84, // Left
+ east_bounding_wgs84, // Right
+ 0); // Default Map Level
+
+ //Free any memory used and return
+ /* We're finished with the geoTIFF key parser, so get rid of it */
+ GTIFFree (gtif);
+
+ /* Close the TIFF file descriptor */
+ XTIFFClose (tif);
+
+ return; // Done indexing this file
+ }
+ else {
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ langcode ("BBARSTA028"),
+ short_filenm);
+ statusline(map_it,0); // Loading ...
+ }
+
+
+
+
+ // bottom top left right
+ if (!map_visible( south_bounding_wgs84,
+ north_bounding_wgs84,
+ west_bounding_wgs84,
+ east_bounding_wgs84 ) )
+ {
+ if (debug_level & 16) {
+ fprintf(stderr,"Map not within current view.\n");
+ fprintf(stderr,"Skipping map: %s\n", file);
+ }
+
+ /*
+ * Map isn't inside our current view. We're done.
+ * Free any memory used and return
+ */
+
+ /* We're finished with the geoTIFF key parser, so get rid of it */
+ GTIFFree (gtif);
+
+ /* Close the TIFF file descriptor */
+ XTIFFClose (tif);
+
+ return; /* Skip this map */
+ }
+
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ GTIFFree (gtif);
+ XTIFFClose (tif);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+
+/*
+From running in debug mode:
+ Width: 5493
+ Height: 6840
+ Rows Per Strip: 1
+ Bits Per Sample: 8
+Samples Per Pixel: 1
+ Planar Config: 1
+*/
+
+
+ /* Fetch a few TIFF fields for this image */
+ if ( !TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photometric) ) {
+ photometric = PHOTOMETRIC_RGB;
+ fprintf(stderr,"No photometric tag found in file, setting it to RGB\n");
+ }
+ if ( !TIFFGetField (tif, TIFFTAG_ROWSPERSTRIP, &rowsPerStrip) ) {
+ rowsPerStrip = 1;
+ fprintf(stderr,"No rowsPerStrip tag found in file, setting it to 1\n");
+ }
+
+ if ( !TIFFGetField (tif, TIFFTAG_BITSPERSAMPLE, &bitsPerSample) ) {
+ bitsPerSample = 8;
+ fprintf(stderr,"No bitsPerSample tag found in file, setting it to 8\n");
+ }
+
+ if ( !TIFFGetField (tif, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel) ) {
+ samplesPerPixel = 1;
+ fprintf(stderr,"No samplesPerPixel tag found in file, setting it to 1\n");
+ }
+
+ if ( !TIFFGetField (tif, TIFFTAG_PLANARCONFIG, &planarConfig) ) {
+ planarConfig = 1;
+ fprintf(stderr,"No planarConfig tag found in file, setting it to 1\n");
+ }
+
+
+ if (debug_level & 16) {
+ fprintf(stderr," Width: %ld\n", (long int)width);
+ fprintf(stderr," Height: %ld\n", (long int)height);
+ fprintf(stderr," Photometric: %d\n", photometric);
+ fprintf(stderr," Rows Per Strip: %ld\n", (long int)rowsPerStrip);
+ fprintf(stderr," Bits Per Sample: %d\n", bitsPerSample);
+ fprintf(stderr,"Samples Per Pixel: %d\n", samplesPerPixel);
+ fprintf(stderr," Planar Config: %d\n", planarConfig);
+ }
+
+
+ /*
+ * Check for properly formatted geoTIFF file. If it isn't
+ * in the standard format we're looking for, spit out an
+ * error message and return.
+ *
+ * Should we also check compression method here?
+ */
+ /* if ( ( rowsPerStrip != 1) */
+ if ( (samplesPerPixel != 1)
+ || ( bitsPerSample != 8)
+ || ( planarConfig != 1) )
+ {
+ fprintf(stderr,"*** geoTIFF file %s is not in the proper format:\n", file);
+ if (samplesPerPixel != 1)
+ fprintf(stderr,"***** Has %d samples per pixel instead of 1\n",
+ samplesPerPixel);
+ if (bitsPerSample != 8)
+ fprintf(stderr,"***** Has %d bits per sample instead of 8\n",
+ bitsPerSample);
+ if (planarConfig != 1)
+ fprintf(stderr,"***** Has planarConfig of %d instead of 1\n",
+ planarConfig);
+ fprintf(stderr,"*** Please reformat it and try again.\n");
+ XTIFFClose(tif);
+ return;
+ }
+
+
+ if (debug_level & 16)
+ fprintf(stderr,"Loading geoTIFF map: %s\n", file);
+
+
+ /*
+ * Snag the original map colors out of the colormap embedded
+ * inside the tiff file.
+ */
+ if (photometric == PHOTOMETRIC_PALETTE) {
+ if (!TIFFGetField(tif, TIFFTAG_COLORMAP, &red_orig, &green_orig, &blue_orig))
+ {
+ TIFFError(TIFFFileName(tif), "Missing required \"Colormap\" tag");
+ GTIFFree (gtif);
+ XTIFFClose (tif);
+ return;
+ }
+ }
+
+ /* Here are the number of possible colors. It turns out to
+ * be 256 for a USGS geotiff file, of which only the first
+ * 13 are used. Other types of geotiff's may use more
+ * colors (and do). A proposed revision to the USGS DRG spec
+ * allows using more colors.
+ */
+ num_colors = (1L << bitsPerSample);
+
+
+ /* Print out the colormap info */
+ //if (debug_level & 16) {
+ // int l;
+ //
+ // for (l = 0; l < num_colors; l++)
+ // fprintf(stderr," %5u: %5u %5u %5u\n",
+ // l,
+ // red_orig[l],
+ // green_orig[l],
+ // blue_orig[l]);
+ //}
+ // Example output from a USGS 7.5' map:
+ //
+ // 0: 0 0 0 black
+ // 1: 65280 65280 65280 light grey
+ // 2: 0 38656 41984
+ // 3: 51968 0 5888
+ // 4: 33536 16896 9472 contour lines, brownish-red
+ // 5: 51456 59904 40192 green
+ // 6: 35072 13056 32768 purple? freeways, some roads
+ // 7: 65280 59904 0
+ // 8: 42752 57856 57856 blue, bodies of water
+ // 9: 65280 47104 47104 red brick color, cities?
+ // 10: 55808 45824 54784 purple. freeways, some roads
+ // 11: 53504 53504 53504 grey
+ // 12: 52992 41984 36352 contour lines, tan, more dots/less lines
+ // 13: 0 0 0 black, unused slot?
+ // 14: 0 0 0 black, unused slot?
+ // 15: 0 0 0 black, unused slot?
+ // 16: 0 0 0 black, unused slot?
+ // The rest are all 0's.
+
+
+ if (crop_it) // USGS geoTIFF map
+ {
+ /*
+ * Next:
+ * Convert the map neat-line corners to image x/y coordinates.
+ * This will give the map neat-line coordinates in pixels.
+ * Use this data to chop the image at these boundaries
+ * and to stretch the shorter lines to fit a rectangle.
+ *
+ * Note that at this stage we're using the bounding coordinates
+ * that are in the map original datum so that the translations
+ * to pixel coordinates will be correct.
+ *
+ * Note that we already have the datum-shifted values for all
+ * the corners in the *_wgs84 variables. In short: We use the
+ * non datum-shifted values to work with the tiff file, and the
+ * datum-shifted values to plot the points in Xastir.
+ */
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ GTIFFree (gtif);
+ XTIFFClose (tif);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ if (debug_level & 16)
+ fprintf(stderr,"\nNW neat-line corner = %f\t%f\n",
+ f_NW_x_bounding,
+ f_NW_y_bounding);
+
+ xxx = (double)f_NW_x_bounding;
+ yyy = (double)f_NW_y_bounding;
+
+ /* Convert lat/long to projected coordinates */
+ if ( proj_is_latlong || my_GTIFProj4FromLatLong( &defn, 1, &xxx, &yyy ) ) { // Do all 4 in one call?
+
+ if (debug_level & 16)
+ fprintf(stderr,"%11.3f,%11.3f\n", xxx, yyy);
+
+ /* Convert from PCS coordinates to image pixel coordinates */
+ if ( GTIFPCSToImage( gtif, &xxx, &yyy ) ) { // Do all 4 in one call?
+
+ if (debug_level & 16)
+ fprintf(stderr,"X/Y Pixels: %f, %f\n", xxx, yyy);
+
+ NW_x = (int)(xxx + 0.5); /* Tricky way of rounding */
+ NW_y = (int)(yyy + 0.5); /* Tricky way of rounding */
+
+ if (debug_level & 16)
+ fprintf(stderr,"X/Y Pixels: %d, %d\n", NW_x, NW_y);
+
+ if (NW_x < 0 || NW_y < 0 || NW_x >= (int)width || NW_y >= (int)height) {
+
+ fprintf(stderr,
+ "\nWarning: NW Neat-line corner calculated at x:%d, y:%d, %s\n",
+ NW_x,
+ NW_y,
+ filenm);
+ fprintf(stderr,
+ "Limits are: 0,0 and %ld,%ld. Resetting corner position.\n",
+ (long int)width,
+ (long int)height);
+ fprintf(stderr,
+ "Map may appear in the wrong location or scale incorrectly.\n");
+
+ if (NW_x < 0)
+ NW_x = 0;
+
+ if (NW_x >= (int)width)
+ NW_x = width - 1;
+
+ if (NW_y < 0)
+ NW_y = 0;
+
+ if (NW_y >= (int)height)
+ NW_y = height -1;
+
+/*
+ //Free any memory used and return
+ // We're finished with the geoTIFF key parser, so get rid of it
+ GTIFFree (gtif);
+
+ // Close the TIFF file descriptor
+ XTIFFClose (tif);
+
+ return;
+*/
+ }
+ }
+ }
+ else {
+ fprintf(stderr,"Problem in translating\n");
+ }
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ GTIFFree (gtif);
+ XTIFFClose (tif);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),pixmap,XtWindow(da),gc,0,0,screen_width,screen_height,0,0);
+ return;
+ }
+
+ if (debug_level & 16)
+ fprintf(stderr,"NE neat-line corner = %f\t%f\n",
+ f_NE_x_bounding,
+ f_NE_y_bounding);
+
+ xxx = (double)f_NE_x_bounding;
+ yyy = (double)f_NE_y_bounding;
+
+ /* Convert lat/long to projected coordinates */
+ if ( proj_is_latlong || my_GTIFProj4FromLatLong( &defn, 1, &xxx, &yyy ) )
+ {
+ if (debug_level & 16)
+ fprintf(stderr,"%11.3f,%11.3f\n", xxx, yyy);
+
+ /* Convert from PCS coordinates to image pixel coordinates */
+ if ( GTIFPCSToImage( gtif, &xxx, &yyy ) )
+ {
+ if (debug_level & 16)
+ fprintf(stderr,"X/Y Pixels: %f, %f\n", xxx, yyy);
+
+ NE_x = (int)(xxx + 0.5); /* Tricky way of rounding */
+ NE_y = (int)(yyy + 0.5); /* Tricky way of rounding */
+
+ if (debug_level & 16)
+ fprintf(stderr,"X/Y Pixels: %d, %d\n", NE_x, NE_y);
+
+ if (NE_x < 0 || NE_y < 0 || NE_x >= (int)width || NE_y >= (int)height) {
+
+ fprintf(stderr,
+ "\nWarning: NE Neat-line corner calculated at x:%d, y:%d, %s\n",
+ NE_x,
+ NE_y,
+ filenm);
+ fprintf(stderr,
+ "Limits are: 0,0 and %ld,%ld. Resetting corner position.\n",
+ (long int)width,
+ (long int)height);
+ fprintf(stderr,
+ "Map may appear in the wrong location or scale incorrectly.\n");
+
+ if (NE_x < 0)
+ NE_x = 0;
+
+ if (NE_x >= (int)width)
+ NE_x = width - 1;
+
+ if (NE_y < 0)
+ NE_y = 0;
+
+ if (NE_y >= (int)height)
+ NE_y = height -1;
+
+/*
+ //Free any memory used and return
+ // We're finished with the geoTIFF key parser, so get rid of it
+ GTIFFree (gtif);
+
+ // Close the TIFF file descriptor
+ XTIFFClose (tif);
+
+ return;
+*/
+ }
+ }
+ }
+ else {
+ fprintf(stderr,"Problem in translating\n");
+ }
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ GTIFFree (gtif);
+ XTIFFClose (tif);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),pixmap,XtWindow(da),gc,0,0,screen_width,screen_height,0,0);
+ return;
+ }
+
+ if (debug_level & 16)
+ fprintf(stderr,"SW neat-line corner = %f\t%f\n",
+ f_SW_x_bounding,
+ f_SW_y_bounding);
+
+ xxx = (double)f_SW_x_bounding;
+ yyy = (double)f_SW_y_bounding;
+
+ /* Convert lat/long to projected coordinates */
+ if ( proj_is_latlong || my_GTIFProj4FromLatLong( &defn, 1, &xxx, &yyy ) )
+ {
+ if (debug_level & 16)
+ fprintf(stderr,"%11.3f,%11.3f\n", xxx, yyy);
+
+ /* Convert from PCS coordinates to image pixel coordinates */
+ if ( GTIFPCSToImage( gtif, &xxx, &yyy ) )
+ {
+ if (debug_level & 16)
+ fprintf(stderr,"X/Y Pixels: %f, %f\n", xxx, yyy);
+
+ SW_x = (int)(xxx + 0.5); /* Tricky way of rounding */
+ SW_y = (int)(yyy + 0.5); /* Tricky way of rounding */
+
+ if (debug_level & 16)
+ fprintf(stderr,"X/Y Pixels: %d, %d\n", SW_x, SW_y);
+
+ if (SW_x < 0 || SW_y < 0 || SW_x >= (int)width || SW_y >= (int)height) {
+
+ fprintf(stderr,
+ "\nWarning: SW Neat-line corner calculated at x:%d, y:%d, %s\n",
+ SW_x,
+ SW_y,
+ filenm);
+ fprintf(stderr,
+ "Limits are: 0,0 and %ld,%ld. Resetting corner position.\n",
+ (long int)width,
+ (long int)height);
+ fprintf(stderr,
+ "Map may appear in the wrong location or scale incorrectly.\n");
+
+ if (SW_x < 0)
+ SW_x = 0;
+
+ if (SW_x >= (int)width)
+ SW_x = width - 1;
+
+ if (SW_y < 0)
+ SW_y = 0;
+
+ if (SW_y >= (int)height)
+ SW_y = height -1;
+
+/*
+ //Free any memory used and return
+ // We're finished with the geoTIFF key parser, so get rid of it
+ GTIFFree (gtif);
+
+ // Close the TIFF file descriptor
+ XTIFFClose (tif);
+
+ return;
+*/
+ }
+ }
+ }
+ else {
+ fprintf(stderr,"Problem in translating\n");
+ }
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ GTIFFree (gtif);
+ XTIFFClose (tif);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),pixmap,XtWindow(da),gc,0,0,screen_width,screen_height,0,0);
+ return;
+ }
+
+ if (debug_level & 16)
+ fprintf(stderr,"SE neat-line corner = %f\t%f\n",
+ f_SE_x_bounding,
+ f_SE_y_bounding);
+
+ xxx = (double)f_SE_x_bounding;
+ yyy = (double)f_SE_y_bounding;
+
+ /* Convert lat/long to projected coordinates */
+ if ( proj_is_latlong || my_GTIFProj4FromLatLong( &defn, 1, &xxx, &yyy ) )
+ {
+ if (debug_level & 16)
+ fprintf(stderr,"%11.3f,%11.3f\n", xxx, yyy);
+
+ /* Convert from PCS coordinates to image pixel coordinates */
+ if ( GTIFPCSToImage( gtif, &xxx, &yyy ) )
+ {
+ if (debug_level & 16)
+ fprintf(stderr,"X/Y Pixels: %f, %f\n", xxx, yyy);
+
+ SE_x = (int)(xxx + 0.5); /* Tricky way of rounding */
+ SE_y = (int)(yyy + 0.5); /* Tricky way of rounding */
+
+ if (debug_level & 16)
+ fprintf(stderr,"X/Y Pixels: %d, %d\n", SE_x, SE_y);
+
+ if (SE_x < 0 || SE_y < 0 || SE_x >= (int)width || SE_y >= (int)height) {
+
+ fprintf(stderr,
+ "\nWarning: SE Neat-line corner calculated at x:%d, y:%d, %s\n",
+ SE_x,
+ SE_y,
+ filenm);
+ fprintf(stderr,
+ "Limits are: 0,0 and %ld,%ld. Resetting corner position.\n",
+ (long int)width,
+ (long int)height);
+ fprintf(stderr,
+ "Map may appear in the wrong location or scale incorrectly.\n");
+
+ if (SE_x < 0)
+ SE_x = 0;
+
+ if (SE_x >= (int)width)
+ SE_x = width - 1;
+
+ if (SE_y < 0)
+ SE_y = 0;
+
+ if (SE_y >= (int)height)
+ SE_y = height -1;
+
+/*
+ //Free any memory used and return
+ // We're finished with the geoTIFF key parser, so get rid of it
+ GTIFFree (gtif);
+
+ // Close the TIFF file descriptor
+ XTIFFClose (tif);
+
+ return;
+*/
+ }
+ }
+ }
+ else {
+ fprintf(stderr,"Problem in translating\n");
+ }
+ }
+ else /*
+ * No map collar to crop off, so we already know
+ * where the corner points are. This is for non-USGS
+ * maps.
+ */
+ {
+ NW_x = 0;
+ NW_y = 0;
+
+ NE_x = width - 1;
+ NE_y = 0;
+
+ SW_x = 0;
+ SW_y = height - 1;
+
+ SE_x = width - 1;
+ SE_y = height - 1;
+ }
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ GTIFFree (gtif);
+ XTIFFClose (tif);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),pixmap,XtWindow(da),gc,0,0,screen_width,screen_height,0,0);
+ return;
+ }
+
+ // Here's where we crop off part of the black border for USGS maps.
+ if (crop_it) // USGS maps only
+ {
+ int i = 3;
+
+ NW_x += i;
+ NW_y += i;
+ NE_x -= i;
+ NE_y += i;
+ SW_x += i;
+ SW_y -= i;
+ SE_x -= i;
+ SE_y -= i;
+ }
+
+
+ // Now figure out the rough pixel crop values from what we know.
+ // Image rotation means a simple rectangular crop isn't sufficient.
+ if (NW_y < NE_y)
+ top_crop = NW_y;
+ else
+ top_crop = NE_y;
+
+
+ if (SW_y > SE_y)
+ bottom_crop = SW_y;
+ else
+ bottom_crop = SE_y;
+
+
+ if (NE_x > SE_x)
+ right_crop = NE_x;
+ else
+ right_crop = SE_x;
+
+
+ if (NW_x < SW_x)
+ left_crop = NW_x;
+ else
+ left_crop = SW_x;
+
+
+ if (!crop_it) /* If we shouldn't crop the map collar... */
+ {
+ top_crop = 0;
+ bottom_crop = height - 1;
+ left_crop = 0;
+ right_crop = width - 1;
+ }
+
+ // The four crop variables are the maximum rectangle that we
+ // wish to keep, rotation notwithstanding (we may want to crop
+ // part of some lines due to rotation). Crop all lines/pixels
+ // outside these ranges.
+
+//WE7U
+if (top_crop < 0 || top_crop >= (int)height)
+top_crop = 0;
+
+if (bottom_crop < 0 || bottom_crop >= (int)height)
+bottom_crop = height - 1;
+
+if (left_crop < 0 || left_crop >= (int)width)
+left_crop = 0;
+
+if (right_crop < 0 || right_crop >= (int)width)
+right_crop = width - 1;
+
+ if (debug_level & 16) {
+ fprintf(stderr,"Crop points (pixels):\n");
+ fprintf(stderr,"Top: %d\tBottom: %d\tLeft: %d\tRight: %d\n",
+ top_crop,
+ bottom_crop,
+ left_crop,
+ right_crop);
+ }
+
+
+ /*
+ * The color map is embedded in the geoTIFF file as TIFF tags.
+ * We get those tags out of the file and translate to our own
+ * colormap.
+ * Allocate colors for the map image. We allow up to 256 colors
+ * and allow only 8-bits per pixel in the original map file. We
+ * get our 24-bit RGB colors right out of the map file itself, so
+ * the colors should look right.
+ * We're picking existing colormap colors that are closest to
+ * the original map colors, so we shouldn't run out of colors
+ * for other applications.
+ *
+ * Brightness adjust for the colors? Implemented in the
+ * "raster_map_intensity" variable below.
+ */
+
+ {
+ int l;
+
+ switch (photometric) {
+ case PHOTOMETRIC_PALETTE:
+ for (l = 0; l < num_colors; l++)
+ {
+ my_colors[l].red = (uint16)(red_orig[l] * raster_map_intensity);
+ my_colors[l].green = (uint16)(green_orig[l] * raster_map_intensity);
+ my_colors[l].blue = (uint16)(blue_orig[l] * raster_map_intensity);
+
+ if (visual_type == NOT_TRUE_NOR_DIRECT) {
+// XFreeColors(XtDisplay(w), cmap, &(my_colors[l].pixel),1,0);
+ XAllocColor(XtDisplay(w), cmap, &my_colors[l]);
+ }
+ else {
+ pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue,
+ &my_colors[l].pixel);
+ }
+ }
+ break;
+ case PHOTOMETRIC_MINISBLACK:
+ for (l = 0; l < num_colors; l++)
+ {
+ int v = (l * 255) / (num_colors-1);
+ my_colors[l].red = my_colors[l].green = my_colors[l].blue =
+ (uint16)(v * raster_map_intensity) << 8;
+
+ if (visual_type == NOT_TRUE_NOR_DIRECT) {
+// XFreeColors(XtDisplay(w), cmap, &(my_colors[l].pixel),1,0);
+ XAllocColor(XtDisplay(w), cmap, &my_colors[l]);
+ }
+ else {
+ pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue,
+ &my_colors[l].pixel);
+ }
+ }
+ break;
+ case PHOTOMETRIC_MINISWHITE:
+ for (l = 0; l < num_colors; l++)
+ {
+ int v = (((num_colors-1)-l) * 255) / (num_colors-1);
+ my_colors[l].red = my_colors[l].green = my_colors[l].blue =
+ (uint16)(v * raster_map_intensity) << 8;
+
+ if (visual_type == NOT_TRUE_NOR_DIRECT) {
+// XFreeColors(XtDisplay(w), cmap, &(my_colors[l].pixel),1,0);
+ XAllocColor(XtDisplay(w), cmap, &my_colors[l]);
+ }
+ else {
+ pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue,
+ &my_colors[l].pixel);
+ }
+ }
+ break;
+ }
+ }
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ GTIFFree (gtif);
+ XTIFFClose (tif);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),pixmap,XtWindow(da),gc,0,0,screen_width,screen_height,0,0);
+ return;
+ }
+
+ // Each data value should be an 8-bit value, which is a
+ // pointer into a color
+ // table. Later we perform a translation from the geoTIFF
+ // color table to our current color table (matching values
+ // as close as possible), at the point where we're writing
+ // the image to the pixmap.
+
+
+ /* We should be ready now to actually read in some
+ * pixels and deposit them on the screen. We will
+ * allocate memory for the data area based on the
+ * sizes of fields and data in the geoTIFF file.
+ */
+
+ bytesPerRow = TIFFScanlineSize(tif);
+
+ if (debug_level & 16) {
+ fprintf(stderr,"\nInitial Bytes Per Row: %d\n", bytesPerRow);
+ }
+
+
+ // Here's a tiny malloc that'll hold only one scanline worth of pixels
+ imageMemory = (u_char *) malloc(bytesPerRow + 2);
+ CHECKMALLOC(imageMemory);
+
+
+ // TODO: Figure out the middle boundary on each edge for
+ // lat/long and adjust the crop values to match the largest
+ // of either the middle or the corners for each edge. This
+ // will help to handle edges that are curved.
+
+
+ /*
+ * There are some optimizations that can still be done:
+ *
+ * 1) Read in all scanlines but throw away unneeded pixels,
+ * paying attention not to lose smaller details. Compare
+ * neighboring pixels?
+ *
+ * 3) Keep a map cache or a screenmap cache to reduce need
+ * for reading map files so often.
+ */
+
+
+
+ // Here we wish to start at the top line that may have
+ // some pixels of interest and proceed to the bottom line
+ // of interest. Process scanlines from top_crop to bottom_crop.
+ // Start at the left/right_crop pixels, compute the lat/long
+ // of each, using x/y increments so we can quickly scan across
+ // the line.
+ // Iterate across the line checking whether each pixel is
+ // within the viewport. If so, plot it on the pixmap at
+ // the correct scale.
+
+ // Later I may wish to get the lat/lon of each pixel and plot
+ // it at the correct point, to handle the curvature of each
+ // line (this might be VERY slow). Right now I treat them as
+ // straight lines.
+
+ // At this point we have these variables defined. The
+ // first column contains map corners in Xastir coordinates,
+ // the second column contains map corners in pixels:
+ //
+ // NW corner:
+ // NW_x_bounding_wgs84 <-> NW_x
+ // NW_y_bounding_wgs84 <-> NW_y
+ //
+ // NE corner:
+ // NE_x_bounding_wgs84 <-> NE_x
+ // NE_y_bounding_wgs84 <-> NE_y
+ //
+ // SW corner:
+ // SW_x_bounding_wgs84 <-> SW_x
+ // SW_y_bounding_wgs84 <-> SW_y
+ //
+ // SE corner:
+ // SE_x_bounding_wgs84 <-> SE_x
+ // SE_y_bounding_wgs84 <-> SE_y
+
+ // I should be able to use these variables to figure out
+ // the xastir coordinates of each scanline pixel using
+ // linear interpolation along each edge.
+ //
+ // I don't want to use the crop values in general. I'd
+ // rather crop properly along the neat line instead of a
+ // rectangular crop.
+ //
+ // Define lines along the left/right edges so that I can
+ // compute the Xastir coordinates of each pixel along these
+ // two lines. These will be the start/finish of each of my
+ // scanlines, and I can use these values to compute the
+ // x/y_increment values for each line. This way I can
+ // stretch short lines as I go along, and auto-crop the
+ // white border as well.
+
+ // Left_line goes from (top to bottom):
+ // NW_x,NW_y -> SW_x,SW_y
+ // and from:
+ // west_bounding_wgs84,north_bounding_wgs84 -> west_bounding_wgs84,south_bounding_wgs84
+ //
+ // Right_line goes from(top to bottom):
+ // NE_x,NE_y -> SE_x,SE-Y
+ // and from:
+ // east_bounding_wgs84,north_bounding_wgs84 -> east_bounding_wgs84,south_bounding_wgs84
+ //
+ // Simpler: Along each line, Xastir coordinates change how much
+ // and in what direction as we move down one scanline?
+
+
+ // These increments are how much we change in Xastir coordinates and
+ // in pixel coordinates as we move down either the left or right
+ // neatline one pixel.
+ // Be prepared for 0 angle of rotation as well (x-increments = 0).
+
+
+ // Xastir Coordinate System:
+ //
+ // 0 (90 deg. or 90N)
+ //
+ // 0 (-180 deg. or 180W) 129,600,000 (180 deg. or 180E)
+ //
+ // 64,800,000 (-90 deg. or 90S)
+
+
+ // Watch out for division by zero here.
+
+
+ //
+ // Left Edge X Increment Per Scanline (Going from top to bottom).
+ // This increment will help me to keep track of the left edge of
+ // the image, both in Xastir coordinates and in pixel coordinates.
+ //
+ if (SW_y != NW_y)
+ {
+ // Xastir coordinates
+ xastir_left_x_increment = (float)
+ (1.0 * abs(SW_x_bounding_wgs84 - NW_x_bounding_wgs84) // Need to add one pixel worth here yet
+ / abs(SW_y - NW_y));
+
+ // Pixel coordinates
+ left_x_increment = (float)(1.0 * abs(SW_x - NW_x)
+ / abs(SW_y - NW_y));
+
+ if (SW_x_bounding_wgs84 < NW_x_bounding_wgs84)
+ xastir_left_x_increment = -xastir_left_x_increment;
+
+ if (SW_x < NW_x)
+ left_x_increment = -left_x_increment;
+
+//WE7U
+//if (abs(left_x_increment) > (width/10)) {
+// left_x_increment = 0.0;
+// xastir_left_x_increment = 0.0;
+//}
+
+ if (debug_level & 16)
+ fprintf(stderr,"xastir_left_x_increment: %f %ld %ld %f %d %d %d %d\n",
+ xastir_left_x_increment,
+ SW_x_bounding_wgs84,
+ NW_x_bounding_wgs84,
+ left_x_increment,
+ SW_x,
+ NW_x,
+ bottom_crop,
+ top_crop);
+ }
+ else
+ {
+ // Xastir coordinates
+ xastir_left_x_increment = 0;
+
+ // Pixel coordinates
+ left_x_increment = 0;
+ }
+
+
+ //
+ // Left Edge Y Increment Per Scanline (Going from top to bottom)
+ // This increment will help me to keep track of the left edge of
+ // the image, both in Xastir coordinates and in pixel coordinates.
+ //
+ if (SW_y != NW_y)
+ {
+ // Xastir coordinates
+ xastir_left_y_increment = (float)
+ (1.0 * abs(SW_y_bounding_wgs84 - NW_y_bounding_wgs84) // Need to add one pixel worth here yet
+ / abs(SW_y - NW_y));
+
+ // Pixel coordinates
+ left_y_increment = (float)1.0; // Aren't we going down one pixel each time?
+
+ if (SW_y_bounding_wgs84 < NW_y_bounding_wgs84) // Ain't gonn'a happen
+ xastir_left_y_increment = -xastir_left_y_increment;
+
+//WE7U
+//if (abs(left_y_increment) > (width/10)) {
+// xastir_left_y_increment = 0.0;
+//}
+
+ if (debug_level & 16)
+ fprintf(stderr,"xastir_left_y_increment: %f %ld %ld %f %d %d %d %d\n",
+ xastir_left_y_increment,
+ SW_y_bounding_wgs84,
+ NW_y_bounding_wgs84,
+ left_y_increment,
+ SW_y,
+ NW_y,
+ bottom_crop,
+ top_crop);
+ }
+ else
+ {
+ // Xastir coordinates
+ xastir_left_y_increment = 0;
+
+ // Pixel coordinates
+ left_y_increment = 0;
+ }
+
+
+ //
+ // Right Edge X Increment Per Scanline (Going from top to bottom)
+ // This increment will help me to keep track of the right edge of
+ // the image, both in Xastir coordinates and image coordinates.
+ //
+ if (SE_y != NE_y)
+ {
+ // Xastir coordinates
+ xastir_right_x_increment = (float)
+ (1.0 * abs(SE_x_bounding_wgs84 - NE_x_bounding_wgs84) // Need to add one pixel worth here yet
+ / abs(SE_y - NE_y));
+
+ // Pixel coordinates
+ right_x_increment = (float)(1.0 * abs(SE_x - NE_x)
+ / abs(SE_y - NE_y));
+
+ if (SE_x_bounding_wgs84 < NE_x_bounding_wgs84)
+ xastir_right_x_increment = -xastir_right_x_increment;
+
+ if (SE_x < NE_x)
+ right_x_increment = -right_x_increment;
+
+//WE7U
+//if (abs(right_x_increment) > (width/10)) {
+// right_x_increment = 0.0;
+// xastir_right_x_increment = 0.0;
+//}
+
+ if (debug_level & 16)
+ fprintf(stderr,"xastir_right_x_increment: %f %ld %ld %f %d %d %d %d\n",
+ xastir_right_x_increment,
+ SE_x_bounding_wgs84,
+ NE_x_bounding_wgs84,
+ right_x_increment,
+ SE_x,
+ NE_x,
+ bottom_crop,
+ top_crop);
+ }
+ else
+ {
+ // Xastir coordinates
+ xastir_right_x_increment = 0;
+
+ // Pixel coordinates
+ right_x_increment = 0;
+ }
+
+
+ //
+ // Right Edge Y Increment Per Scanline (Going from top to bottom)
+ // This increment will help me to keep track of the right edge of
+ // the image, both in Xastir coordinates and in image coordinates.
+ //
+ if (SE_y != NE_y)
+ {
+ // Xastir coordinates
+ xastir_right_y_increment = (float)
+ (1.0 * abs(SE_y_bounding_wgs84 - NE_y_bounding_wgs84) // Need to add one pixel worth here yet
+ / abs(SE_y - NE_y));
+
+ // Pixel coordinates
+ right_y_increment = (float)1.0; // Aren't we going down one pixel each time?
+
+ if (SE_y_bounding_wgs84 < NE_y_bounding_wgs84) // Ain't gonn'a happen
+ xastir_right_y_increment = -xastir_right_y_increment;
+
+//WE7U
+//if (abs(right_y_increment) > (width/10)) {
+// xastir_right_y_increment = 0.0;
+//}
+
+ if (debug_level & 16)
+ fprintf(stderr,"xastir_right_y_increment: %f %ld %ld %f %d %d %d %d\n",
+ xastir_right_y_increment,
+ SE_y_bounding_wgs84,
+ NE_y_bounding_wgs84,
+ right_y_increment,
+ SE_y,
+ NE_y,
+ bottom_crop,
+ top_crop);
+ }
+ else
+ {
+ // Xastir coordinates
+ xastir_right_y_increment = 0;
+
+ // Pixel coordinates
+ right_y_increment = 0;
+ }
+
+
+ if (debug_level & 16) {
+ fprintf(stderr," Left x increments: %f %f\n", xastir_left_x_increment, left_x_increment);
+ fprintf(stderr," Left y increments: %f %f\n", xastir_left_y_increment, left_y_increment);
+ fprintf(stderr,"Right x increments: %f %f\n", xastir_right_x_increment, right_x_increment);
+ fprintf(stderr,"Right y increments: %f %f\n", xastir_right_y_increment, right_y_increment);
+ }
+
+
+ // Compute how much "y" changes per pixel as we traverse from left to right
+ // along a scanline along the top of the image.
+ //
+ // Top Edge Y Increment Per X-Pixel Width (Going from left to right).
+ // This increment will help me to get rid of image rotation.
+ //
+ if (NE_x != NW_x)
+ {
+ // Xastir coordinates
+ xastir_top_y_increment = (float)
+ (1.0 * abs(NE_y_bounding_wgs84 - NW_y_bounding_wgs84) // Need to add one pixel worth here yet
+ / abs(NE_x - NW_x)); // And a "+ 1.0" here?
+
+ // Pixel coordinates
+ top_y_increment = (float)(1.0 * abs(NE_y - NW_y)
+ / abs(NE_x - NW_x));
+
+ if (NE_y_bounding_wgs84 < NW_y_bounding_wgs84)
+ xastir_top_y_increment = -xastir_top_y_increment;
+
+ if (NE_y < NW_y)
+ top_y_increment = -top_y_increment;
+
+ if (debug_level & 16)
+ fprintf(stderr,"xastir_top_y_increment: %f %ld %ld %f %d %d %d %d\n",
+ xastir_top_y_increment,
+ NE_y_bounding_wgs84,
+ NW_y_bounding_wgs84,
+ top_y_increment,
+ NE_y,
+ NW_y,
+ right_crop,
+ left_crop);
+ }
+ else
+ {
+ // Xastir coordinates
+ xastir_top_y_increment = 0;
+
+ // Pixel coordinates
+ top_y_increment = 0;
+ }
+
+
+ // Compute how much "y" changes per pixel as you traverse from left to right
+ // along a scanline along the bottom of the image.
+ //
+ // Bottom Edge Y Increment Per X-Pixel Width (Going from left to right).
+ // This increment will help me to get rid of image rotation.
+ //
+ if (SE_x != SW_x)
+ {
+ // Xastir coordinates
+ xastir_bottom_y_increment = (float)
+ (1.0 * abs(SE_y_bounding_wgs84 - SW_y_bounding_wgs84) // Need to add one pixel worth here yet
+ / abs(SE_x - SW_x)); // And a "+ 1.0" here?
+
+ // Pixel coordinates
+ bottom_y_increment = (float)(1.0 * abs(SE_y - SW_y)
+ / abs(SE_x - SW_x));
+
+ if (SE_y_bounding_wgs84 < SW_y_bounding_wgs84)
+ xastir_bottom_y_increment = -xastir_bottom_y_increment;
+
+ if (SE_y < SW_y)
+ bottom_y_increment = -bottom_y_increment;
+
+ if (debug_level & 16)
+ fprintf(stderr,"xastir_bottom_y_increment: %f %ld %ld %f %d %d %d %d\n",
+ xastir_bottom_y_increment,
+ SE_y_bounding_wgs84,
+ SW_y_bounding_wgs84,
+ bottom_y_increment,
+ SE_y,
+ SW_y,
+ right_crop,
+ left_crop);
+ }
+ else
+ {
+ // Xastir coordinates
+ xastir_bottom_y_increment = 0;
+
+ // Pixel coordinates
+ bottom_y_increment = 0;
+ }
+
+
+ // Find the average change in Y as we traverse from left to right one pixel
+ xastir_avg_y_increment = (float)(xastir_top_y_increment + xastir_bottom_y_increment) / 2.0;
+ avg_y_increment = (float)(top_y_increment + bottom_y_increment) / 2.0;
+
+
+ // Find edges of current viewport in Xastir coordinates
+ //
+ view_min_x = NW_corner_longitude; // left edge of view
+ if (view_min_x > 129600000l)
+ view_min_x = 0;
+
+ view_max_x = SE_corner_longitude; // right edge of view
+ if (view_max_x > 129600000l)
+ view_max_x = 129600000l;
+
+ view_min_y = NW_corner_latitude; // top edge of view
+ if (view_min_y > 64800000l)
+ view_min_y = 0;
+
+ view_max_y = SE_corner_latitude; // bottom edge of view
+ if (view_max_y > 64800000l)
+ view_max_y = 64800000l;
+
+
+ /* Get the pixel scale */
+ have_PixelScale = TIFFGetField( tif, TIFFTAG_GEOPIXELSCALE, &qty, &PixelScale );
+ if (debug_level & 16) {
+ if (have_PixelScale) {
+ fprintf(stderr,"PixelScale: %f %f %f\n",
+ *PixelScale,
+ *(PixelScale + 1),
+ *(PixelScale + 2) );
+ }
+ else {
+ fprintf(stderr,"No PixelScale tag found in file\n");
+ }
+ }
+
+
+ // Use PixelScale to determine lines to skip at each
+ // zoom level?
+ // O-size map:
+ // ModelPixelScaleTag (1,3):
+ // 2.4384 2.4384 0
+ //
+ // F-size map:
+ // ModelPixelScaleTag (1,3):
+ // 10.16 10.16 0
+ //
+ // C-size map:
+ // ModelPixelScaleTag (1,3):
+ // 25.400001 25.400001 0
+ //
+
+ if (debug_level & 16)
+ fprintf(stderr,"Size: x %ld, y %ld\n", scale_x,scale_y);
+
+
+ // I tried to be very aggressive with the scaling factor
+ // below (3.15) in order to skip the most possible rows
+ // to speed things up. If you see diagonal lines across
+ // the maps, increase this number (up to a max of 4.0
+ // probably). A higher number means less rows skipped,
+ // which improves the look but slows the map drawing down.
+ //
+ // This needs modification somewhat when the raster is already in
+ // lat/long, and the PixelScale is already in degrees per pixel.
+ // The scale_y is the integer number of hundredths of seconds per pixel.
+ // The decision of how many rows to skip can simply be made by converting
+ // the PixelScale to the same units as scale_y, and skipping accordingly.
+
+ if (have_PixelScale) {
+ double coef;
+ if (!proj_is_latlong) {
+ coef = 3.15;
+ }
+ else {
+ coef=100*60*60; // xastir coords are in 1/100 of a second,
+ // and lat/lon pixel scales will be in degrees
+ }
+ SkipRows = (int)( ( scale_y / ( *PixelScale * coef ) ) + 0.5 );
+ if (SkipRows < 1)
+ SkipRows = 1;
+ if (SkipRows > (int)(height / 10) )
+ SkipRows = height / 10;
+ }
+ else {
+ SkipRows = 1;
+ }
+ if (debug_level & 16)
+ fprintf(stderr,"SkipRows: %d\n", SkipRows);
+
+ // Use SkipRows to set increments for the loops below.
+
+
+ if ( top_crop <= 0 )
+ top_crop = 0; // First row of image
+
+ if ( ( bottom_crop + 1) >= (int)height )
+ bottom_crop = height - 1; // Last row of image
+
+ // Here I pre-compute some of the values I'll need in the
+ // loops below in order to save some time.
+ NW_line_offset = (int)(NW_y - top_crop);
+ NE_line_offset = (int)(NE_y - top_crop);
+
+ NW_xastir_x_offset = (int)(xastir_left_x_increment * NW_line_offset);
+ NE_xastir_x_offset = (int)(xastir_right_x_increment * NE_line_offset);
+ NW_xastir_y_offset = (int)(xastir_left_y_increment * NW_line_offset);
+
+ NW_x_offset = (int)(1.0 * left_x_increment * NW_line_offset);
+ NE_x_offset = (int)(1.0 * right_x_increment * NE_line_offset);
+ xastir_avg_left_right_y_increment = (float)((xastir_right_y_increment + xastir_left_y_increment) / 2.0);
+ total_avg_y_increment = (float)(xastir_avg_left_right_y_increment * avg_y_increment);
+
+
+ // (Xastir bottom - Xastir top) / height
+ //steph = (double)( (left_y_increment + right_y_increment) / 2);
+ // NOTE: This one does not take into account current height
+ steph = (float)( (SW_y_bounding_wgs84 - NW_y_bounding_wgs84)
+ / (1.0 * (SW_y - NW_y) ) );
+
+ // Compute scaled pixel size for XFillRectangle
+ stephc = (int)( ( (1.50 * steph / scale_x) + 1.0) + 1.5);
+
+ view_top_minus_pixel_height = (unsigned long)(view_min_y - steph);
+
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ if (imageMemory)
+ free(imageMemory);
+ GTIFFree (gtif);
+ XTIFFClose (tif);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),pixmap,XtWindow(da),gc,0,0,screen_width,screen_height,0,0);
+ return;
+ }
+
+
+ // Set the bit-blitting function to XOR. This is only used if
+ // DRG_XOR_colors is set to a non-zero value, but we set it here
+ // outside the pixel loop for speed reasons.
+ //
+ if (DRG_XOR_colors) {
+ (void)XSetLineAttributes (XtDisplay (w), gc_tint, 1, LineSolid, CapButt,JoinMiter);
+
+// (void)XSetForeground (XtDisplay (w), gc_tint, colors[0x27]); // yellow
+// (void)XSetForeground (XtDisplay (w), gc_tint, colors[0x0f]); // White
+// (void)XSetForeground (XtDisplay (w), gc_tint, colors[0x03]); // cyan
+// (void)XSetForeground (XtDisplay (w), gc_tint, colors[0x06]); // orange
+
+ (void)XSetFunction (XtDisplay (da), gc_tint, GXxor);
+ }
+
+
+ // Iterate over the rows of interest only. Using the rectangular
+ // top/bottom crop values for these is ok at this point.
+ //
+ // Put row multipliers above loops. Try to get as many
+ // multiplications as possible outside the loops. Adds and
+ // subtracts are ok. Try to do as little floating point stuff
+ // as possible inside the loops. I also declared a lot of
+ // the inner loop stuff as register variables. Saved me about
+ // a second per map (not much, but I'll take what I can get!)
+ //
+ for ( row = top_crop; (int)row < bottom_crop + 1; row+= SkipRows )
+ {
+ int skip = 0;
+
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ if (imageMemory)
+ free(imageMemory);
+ GTIFFree (gtif);
+ XTIFFClose (tif);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),pixmap,XtWindow(da),gc,0,0,screen_width,screen_height,0,0);
+ return;
+ }
+
+ // Our offset from the top row of the map neatline
+ // (kind of... ignoring rotation anyway).
+ row_offset = row - top_crop;
+ //fprintf(stderr,"row_offset: %d\n", row_offset);
+
+
+ // Compute the line end-points in Xastir coordinates
+ // Initially was a problem here: Offsetting from NW_x_bounding but
+ // starting at top_crop line. Fixed by last term added to two
+ // equations below.
+
+ current_xastir_left = (unsigned long)
+ ( NW_x_bounding_wgs84
+ + ( 1.0 * xastir_left_x_increment * row_offset )
+ - NW_xastir_x_offset );
+
+ current_xastir_right = (unsigned long)
+ ( NE_x_bounding_wgs84
+ + ( 1.0 * xastir_right_x_increment * row_offset )
+ - NE_xastir_x_offset );
+
+
+ //if (debug_level & 16)
+ // fprintf(stderr,"Left: %ld Right: %ld\n",
+ // current_xastir_left,
+ // current_xastir_right);
+
+
+ // In pixel coordinates:
+ current_left = (int)
+ ( NW_x
+ + ( 1.0 * left_x_increment * row_offset ) + 0.5
+ - NW_x_offset );
+
+ current_right = (int)
+ ( NE_x
+ + ( 1.0 * right_x_increment * row_offset ) + 0.5
+ - NE_x_offset );
+
+//WE7U: This comparison is always false: current_left is unsigned
+//therefore always positive!
+//if (current_left < 0)
+// current_left = 0;
+
+if (current_right >= width)
+ current_right = width - 1;
+
+ current_line_width = current_right - current_left + 1; // Pixels
+
+
+ // if (debug_level & 16)
+ // fprintf(stderr,"Left: %ld Right: %ld Width: %ld\n",
+ // current_left,
+ // current_right, current_line_width);
+
+
+ // Compute original pixel size in Xastir coordinates. Note
+ // that this can change for each scanline in a USGS geoTIFF.
+
+ // (Xastir right - Xastir left) / width-of-line
+ // Need the "1.0 *" or the math will be incorrect (won't be a float)
+ stepw = (float)( (current_xastir_right - current_xastir_left)
+ / (1.0 * (current_right - current_left) ) );
+
+
+
+ // if (debug_level & 16)
+ // fprintf(stderr,"\t\t\t\t\t\tPixel Width: %f\n",stepw);
+
+ // Compute scaled pixel size for XFillRectangle
+ stepwc = (int)( ( (1.0 * stepw / scale_x) + 1.0) + 0.5);
+
+
+ // In Xastir coordinates
+ xastir_current_y = (unsigned long)(NW_y_bounding_wgs84
+ + (xastir_left_y_increment * row_offset) );
+
+ xastir_current_y = (unsigned long)(xastir_current_y - NW_xastir_y_offset);
+
+
+ view_left_minus_pixel_width = view_min_x - stepw;
+
+
+ // Check whether any part of the scanline will be within the
+ // view. If so, read the scanline from the file and iterate
+ // across the pixels. If not, skip this line altogether.
+
+ // Compute right edge of image
+ xastir_total_y = (unsigned long)
+ ( xastir_current_y
+ - ( total_avg_y_increment * (current_right - current_left) ) );
+
+ // Check left edge y-value then right edge y-value.
+ // If either are within view, process the line, else skip it.
+ if ( ( ( xastir_current_y <= view_max_y) && (xastir_total_y >= view_top_minus_pixel_height) )
+ || ( ( xastir_total_y <= view_max_y ) && ( xastir_total_y >= view_top_minus_pixel_height ) ) )
+ {
+ // Read one geoTIFF scanline
+ if (TIFFReadScanline(tif, imageMemory, row, 0) < 0)
+ break; // No more lines to read or we couldn't read the file at all
+
+
+ // Iterate over the columns of interest, skipping the left/right
+ // cropped pixels, looking for pixels that fit within our viewport.
+ //
+ for ( column = current_left; column < (current_right + 1); column++ )
+ {
+ skip = 0;
+
+
+ column_offset = column - current_left; // Pixels
+
+ //fprintf(stderr,"Column Offset: %ld\n", column_offset); // Pixels
+ //fprintf(stderr,"Current Left: %ld\n", current_left); // Pixels
+
+ xastir_current_x = (unsigned long)
+ current_xastir_left
+ + (stepw * column_offset); // In Xastir coordinates
+
+ // Left line y value minus
+ // avg y-increment per scanline * avg y-increment per x-pixel * column_offset
+ xastir_total_y = (unsigned long)
+ ( xastir_current_y
+ - ( total_avg_y_increment * column_offset ) );
+
+ //fprintf(stderr,"Xastir current: %ld %ld\n", xastir_current_x, xastir_current_y);
+
+
+ // Check whether pixel fits within boundary lines (USGS maps)
+ // This is how we get rid of the last bit of white border at
+ // the top and bottom of the image.
+ if (have_fgd) // USGS map
+ {
+ if ( (xastir_total_y > SW_y_bounding_wgs84)
+ || (xastir_total_y < NW_y_bounding_wgs84) )
+ skip++;
+
+
+ // Here's a trick to make it look like the map pages join better.
+ // If we're within a certain distance of a border, change any black
+ // pixels to white (changes map border to less obtrusive color).
+ if ( *(imageMemory + column) == 0x00 ) // If pixel is Black
+ {
+ if ( (xastir_total_y > (SW_y_bounding_wgs84 - 25) )
+ || (xastir_total_y < (NW_y_bounding_wgs84 + 25) )
+ || (xastir_current_x < (SW_x_bounding_wgs84 + 25) )
+ || (xastir_current_x > (SE_x_bounding_wgs84 - 25) ) )
+ {
+//WE7U: column is unsigned so "column >= 0" is always true
+// if ((int)column < bytesPerRow && column >= 0) {
+ if ((int)column < bytesPerRow) {
+
+ *(imageMemory + column) = 0x01; // Change to White
+ }
+ else {
+//WE7U
+// fprintf(stderr,"draw_geotiff_image_map: Bad fgd file for map?: %s\n", filenm);
+ }
+ }
+ }
+ }
+
+
+ /* Look for left or right map boundaries inside view */
+ if ( !skip
+ && ( xastir_current_x <= view_max_x )
+ && ( xastir_current_x >= view_left_minus_pixel_width )
+ && ( xastir_total_y <= view_max_y )
+ && ( xastir_total_y >= view_top_minus_pixel_height ) )
+ {
+ // Here are the corners of our viewport, using the Xastir
+ // coordinate system. Notice that Y is upside down:
+ //
+ // left edge of view = NW_corner_longitude
+ // right edge of view = SE_corner_longitude
+ // top edge of view = NW_corner_latitude
+ // bottom edge of view = SE_corner_latitude
+
+
+ // Compute the screen position of the pixel and scale it
+ sxx = (xastir_current_x - NW_corner_longitude) / scale_x;
+ syy = (xastir_total_y - NW_corner_latitude ) / scale_y;
+
+
+
+// If we wish some colors to be transparent, we could check for a
+// color match here and refuse to draw those that are on our list of
+// transparent colors. Might be useful for drawing say contour
+// lines on top of satellite images. Since the USGS topo's use the
+// same colormap for all of the topo's (I believe that is true) then
+// we could just compare on the index into the array instead of the
+// color contents in the array.
+//
+ // Example output from a USGS 7.5' map:
+ //
+ // 0: 0 0 0 black
+ // 1: 65280 65280 65280 light grey
+ // 2: 0 38656 41984
+ // 3: 51968 0 5888
+ // 4: 33536 16896 9472 contour lines, brownish-red
+ // 5: 51456 59904 40192 green
+ // 6: 35072 13056 32768 purple? freeways, some roads
+ // 7: 65280 59904 0
+ // 8: 42752 57856 57856 blue, bodies of water
+ // 9: 65280 47104 47104 red brick color, cities?
+ // 10: 55808 45824 54784 purple. freeways, some roads
+ // 11: 53504 53504 53504 grey
+ // 12: 52992 41984 36352 contour lines, tan, more dots/less lines
+ // 13: 0 0 0 black, unused slot?
+ // 14: 0 0 0 black, unused slot?
+ // 15: 0 0 0 black, unused slot?
+ // 16: 0 0 0 black, unused slot?
+ // The rest are all 0's.
+ // either show all colors (usgs_drg==0) or show selected
+ // colors (usgs_drg == 1)
+ if ( usgs_drg == 0 ||
+ (usgs_drg ==1 && (*(imageMemory + column) >= 13
+ || DRG_show_colors[*(imageMemory + column)] == 1))) {
+
+
+ // If this is set, use gc_tint for drawing
+ // with "GXxor" as the bit-blit operation.
+ //
+ if (DRG_XOR_colors) {
+
+ // Draw the pixel using "gc_tint"
+ // instead of "gc".
+
+ XSetForeground (XtDisplay (w), gc_tint, my_colors[*(imageMemory + column)].pixel);
+
+ XFillRectangle (XtDisplay (w), pixmap, gc_tint, sxx, syy, stepwc, stephc);
+ }
+ else {
+
+ // Set the color for the pixel
+ XSetForeground (XtDisplay (w), gc, my_colors[*(imageMemory + column)].pixel);
+
+ // And draw the pixel
+ XFillRectangle (XtDisplay (w), pixmap, gc, sxx, syy, stepwc, stephc);
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ /* Free up any malloc's that we did */
+ if (imageMemory)
+ free(imageMemory);
+
+
+ if (debug_level & 16)
+ fprintf(stderr,"%d rows read in\n", (int) row);
+
+ /* We're finished with the geoTIFF key parser, so get rid of it */
+ GTIFFree (gtif);
+
+ /* Close the TIFF file descriptor */
+ XTIFFClose (tif);
+
+ // Close the filehandles that are left open after the
+ // four GTIFImageToPCS calls.
+ //(void)CSVDeaccess(NULL);
+}
+#endif /* HAVE_LIBGEOTIFF */
+
+
diff --git a/src/map_tiger.c b/src/map_tiger.c
new file mode 100644
index 0000000..6cb917d
--- /dev/null
+++ b/src/map_tiger.c
@@ -0,0 +1,969 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: map_tiger.c,v 1.68 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <dirent.h>
+#include <netinet/in.h>
+#include <Xm/XmAll.h>
+
+#ifdef HAVE_X11_XPM_H
+#include <X11/xpm.h>
+#ifdef HAVE_LIBXPM // if we have both, prefer the extra library
+#undef HAVE_XM_XPMI_H
+#endif // HAVE_LIBXPM
+#endif // HAVE_X11_XPM_H
+
+#ifdef HAVE_XM_XPMI_H
+#include <Xm/XpmI.h>
+#endif // HAVE_XM_XPMI_H
+
+#include <X11/Xlib.h>
+
+#include <math.h>
+
+#include "xastir.h"
+#include "maps.h"
+#include "alert.h"
+#include "fetch_remote.h"
+#include "util.h"
+#include "main.h"
+#include "datum.h"
+#include "draw_symbols.h"
+#include "rotated.h"
+#include "color.h"
+#include "xa_config.h"
+
+#include "map_cache.h"
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+#ifdef HAVE_MAGICK
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+#undef RETSIGTYPE
+// TVR: "stupid ImageMagick"
+// The problem is that magick/api.h includes Magick's config.h file, and that
+// pulls in all the same autoconf-generated defines that we use.
+// plays those games below, but I don't think in the end that they actually
+// make usable macros with our own data in them.
+// Fortunately, we don't need them, so I'll just undef the ones that are
+// causing problems today. See main.c for fixes that preserve our values.
+#undef PACKAGE
+#undef VERSION
+/* JMT - stupid ImageMagick */
+#define XASTIR_PACKAGE_BUGREPORT PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#define XASTIR_PACKAGE_NAME PACKAGE_NAME
+#undef PACKAGE_NAME
+#define XASTIR_PACKAGE_STRING PACKAGE_STRING
+#undef PACKAGE_STRING
+#define XASTIR_PACKAGE_TARNAME PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#define XASTIR_PACKAGE_VERSION PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#ifdef HAVE_GRAPHICSMAGICK
+/*#include <GraphicsMagick/magick/api.h>*/
+#include <magick/api.h>
+#else // HAVE_GRAPHICSMAGICK
+#include <magick/api.h>
+#endif // HAVE_GRAPHICSMAGICK
+#undef PACKAGE_BUGREPORT
+#define PACKAGE_BUGREPORT XASTIR_PACKAGE_BUGREPORT
+#undef XASTIR_PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#define PACKAGE_NAME XASTIR_PACKAGE_NAME
+#undef XASTIR_PACKAGE_NAME
+#undef PACKAGE_STRING
+#define PACKAGE_STRING XASTIR_PACKAGE_STRING
+#undef XASTIR_PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#define PACKAGE_TARNAME XASTIR_PACKAGE_TARNAME
+#undef XASTIR_PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#define PACKAGE_VERSION XASTIR_PACKAGE_VERSION
+#undef XASTIR_PACKAGE_VERSION
+#endif // HAVE_MAGICK
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+extern int npoints; /* tsk tsk tsk -- globals */
+extern int mag;
+
+
+
+
+
+void get_tiger_local_file(char * local_filename, char * fileimg){
+#ifdef HAVE_MAGICK
+
+// char local_filename[MAX_FILENAME];
+
+// char fileimg[MAX_FILENAME]; // Ascii name of image file, read from GEO file
+
+
+ time_t query_start_time, query_end_time;
+
+#ifdef USE_MAP_CACHE
+ int map_cache_return = 1; // Default = cache miss
+ char *cache_file_id;
+#endif // USE_MAP_CACHE
+
+ char temp_file_path[MAX_VALUE];
+
+ if (debug_level & 512) {
+ query_start_time=time(&query_start_time);
+ }
+
+
+#ifdef USE_MAP_CACHE
+
+ if (!map_cache_fetch_disable) {
+
+ // Delete old copy from the cache
+ if (map_cache_fetch_disable && fileimg[0] != '\0') {
+ if (map_cache_del(fileimg)) {
+ if (debug_level & 512) {
+ fprintf(stderr,"Couldn't delete old map from cache\n");
+ }
+ }
+ }
+
+set_dangerous("map_tiger: map_cache_get");
+ map_cache_return = map_cache_get(fileimg,local_filename);
+clear_dangerous();
+ }
+
+ if (debug_level & 512) {
+ fprintf(stderr,"map_cache_return: <%d> bytes returned: %d\n",
+ map_cache_return,
+ (int) strlen(local_filename));
+ }
+
+ if (map_cache_return != 0 ) {
+
+set_dangerous("map_tiger: map_cache_fileid");
+ cache_file_id = map_cache_fileid();
+ xastir_snprintf(local_filename,
+ MAX_FILENAME, // hardcoded to avoid sizeof()
+ "%s/map_%s.%s",
+ get_user_base_dir("map_cache", temp_file_path, sizeof(temp_file_path)),
+ cache_file_id,
+ "gif");
+ free(cache_file_id);
+clear_dangerous();
+
+#else // USE_MAP_CACHE
+
+ xastir_snprintf(local_filename,
+ MAX_FILENAME, // hardcoded to avoid sizeof()
+ "%s/map.%s",
+ get_user_base_dir("tmp", temp_file_path, sizeof(temp_file_path)),
+ "gif");
+
+#endif // USE_MAP_CACHE
+
+
+ // Erase any previously existing local file by the same name.
+ // This avoids the problem of having an old map image here and
+ // the code trying to display it when the download fails.
+
+ unlink( local_filename );
+
+ if (fetch_remote_file(fileimg, local_filename)) {
+ // Had trouble getting the file. Abort.
+ return;
+ }
+
+ // For debugging the MagickError/MagickWarning segfaults.
+ //system("cat /dev/null >/var/tmp/xastir_hacker_map.gif");
+
+
+#ifdef USE_MAP_CACHE
+
+set_dangerous("map_tiger: map_cache_put");
+ map_cache_put(fileimg,local_filename);
+clear_dangerous();
+
+ } // end if is cached DHBROWN
+
+#endif // MAP_CACHE
+
+
+ if (debug_level & 512) {
+ fprintf (stderr, "Fetch or query took %d seconds\n",
+ (int) (time(&query_end_time) - query_start_time));
+ }
+
+ // Set permissions on the file so that any user can overwrite it.
+ chmod(local_filename, 0666);
+
+#endif //HAVE_MAGICK
+
+} // end get_tiger_local_file
+
+
+
+
+
+/**********************************************************
+ * draw_tiger_map()
+ * N0VH
+ **********************************************************/
+#ifdef HAVE_MAGICK
+void draw_tiger_map (Widget w,
+ char *filenm,
+ int destination_pixmap,
+ int nocache) { // For future implementation of a "refresh cached map" option
+ char file[MAX_FILENAME]; // Complete path/name of image file
+ char short_filenm[MAX_FILENAME];
+ FILE *f; // Filehandle of image file
+ char fileimg[MAX_FILENAME]; // Ascii name of image file, read from GEO file
+ char tigertmp[MAX_FILENAME*2]; // Used for putting together the tigermap query
+ int width, height;
+ tiepoint tp[2]; // Calibration points for map, read in from .geo file
+ register long map_c_T, map_c_L; // map delta NW edge coordinates, DNN: these should be signed
+ register long tp_c_dx, tp_c_dy; // tiepoint coordinate differences
+ unsigned long c_x_min, c_y_min;// top left coordinates of map inside screen
+ unsigned long c_y_max; // bottom right coordinates of map inside screen
+ double c_x; // Xastir coordinates 1/100 sec, 0 = 180�W
+ double c_y; // Xastir coordinates 1/100 sec, 0 = 90�N
+
+ long map_y_0; // map pixel pointer prior to TM adjustment
+ register long map_x, map_y; // map pixel pointers, DNN: this was a float, chg to long
+ long map_x_min, map_x_max; // map boundaries for in screen part of map
+ long map_y_min, map_y_max; //
+ long map_x_ctr; // half map width in pixel
+ long map_y_ctr; // half map height in pixel
+ int map_seen = 0;
+ int map_act;
+ int map_done;
+
+ long map_c_yc; // map center, vert coordinate
+ long map_c_xc; // map center, hor coordinate
+ double map_c_dx, map_c_dy; // map coordinates increment (pixel width)
+ double c_dx; // adjusted map pixel width
+
+ long scr_x, scr_y; // screen pixel plot positions
+ long scr_xp, scr_yp; // previous screen plot positions
+ int scr_dx, scr_dy; // increments in screen plot positions
+ long scr_x_mc; // map center in screen units
+
+ long scr_c_xr;
+
+ long scale_xa; // adjusted for topo maps
+ double scale_x_nm; // nm per Xastir coordinate unit
+ long scale_x0; // at widest map area
+
+ char local_filename[MAX_FILENAME];
+
+ ExceptionInfo exception;
+ Image *image;
+ ImageInfo *image_info;
+ PixelPacket *pixel_pack;
+ PixelPacket temp_pack;
+ IndexPacket *index_pack;
+ int l;
+ XColor my_colors[256];
+ double left, right, top, bottom, map_width, map_height;
+ double lat_center = 0;
+ double long_center = 0;
+
+ char map_it[MAX_FILENAME];
+ char tmpstr[100];
+ int geo_image_width; // Image width from GEO file
+ int geo_image_height; // Image height from GEO file
+
+ // initialize this
+ local_filename[0]='\0';
+
+ // Create a shorter filename for display (one that fits the
+ // status line more closely). Subtract the length of the
+ // "Indexing " and/or "Loading " strings as well.
+ if (strlen(filenm) > (41 - 9)) {
+ int avail = 41 - 11;
+ int new_len = strlen(filenm) - avail;
+
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "..%s",
+ &filenm[new_len]);
+ }
+ else {
+ xastir_snprintf(short_filenm,
+ sizeof(short_filenm),
+ "%s",
+ filenm);
+ }
+
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ langcode ("BBARSTA028"),
+ short_filenm);
+ statusline(map_it,0); // Loading ...
+
+
+
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ // We're indexing only. Save the extents in the index.
+ // Force the extents to the edges of the earth for the
+ // index file.
+ index_update_xastir(filenm, // Filename only
+ 64800000l, // Bottom
+ 0l, // Top
+ 0l, // Left
+ 129600000l, // Right
+ 0); // Default Map Level
+
+ // Update statusline
+ xastir_snprintf(map_it,
+ sizeof(map_it),
+ langcode ("BBARSTA039"),
+ short_filenm);
+ statusline(map_it,0); // Loading/Indexing ...
+
+ return; // Done indexing this file
+ }
+
+
+ // Tiepoint for upper left screen corner
+ //
+ tp[0].img_x = 0; // Pixel Coordinates
+ tp[0].img_y = 0; // Pixel Coordinates
+ tp[0].x_long = NW_corner_longitude; // Xastir Coordinates
+ tp[0].y_lat = NW_corner_latitude; // Xastir Coordinates
+
+ // Tiepoint for lower right screen corner
+ //
+ tp[1].img_x = screen_width - 1; // Pixel Coordinates
+ tp[1].img_y = screen_height - 1; // Pixel Coordinates
+
+ tp[1].x_long = SE_corner_longitude; // Xastir Coordinates
+ tp[1].y_lat = SE_corner_latitude; // Xastir Coordinates
+
+ left = (double)((NW_corner_longitude - 64800000l )/360000.0); // Lat/long Coordinates
+ top = (double)(-((NW_corner_latitude - 32400000l )/360000.0)); // Lat/long Coordinates
+ right = (double)((SE_corner_longitude - 64800000l)/360000.0);//Lat/long Coordinates
+ bottom = (double)(-((SE_corner_latitude - 32400000l)/360000.0));//Lat/long Coordinates
+
+ map_width = right - left; // Lat/long Coordinates
+ map_height = top - bottom; // Lat/long Coordinates
+
+ geo_image_width = screen_width;
+ geo_image_height = screen_height;
+
+ long_center = (left + right)/2.0l;
+ lat_center = (top + bottom)/2.0l;
+
+// Example query to the census map server....
+/* xastir_snprintf(fileimg, sizeof(fileimg),
+ "\'http://tiger.census.gov/cgi-bin/mapper/map.gif?on=CITIES&on=GRID&on=counties&on=majroads&on=places&&on=interstate&on=states&on=ushwy&on=statehwy&lat=%f\046lon=%f\046wid=%f\046ht=%f\046iwd=%i\046iht=%i\'",\
+ lat_center, long_center, map_width, map_height, tp[1].img_x + 1, tp[1].img_y + 1); */
+
+ xastir_snprintf(tigertmp, sizeof(tigertmp), "http://tiger.census.gov/cgi-bin/mapper/map.gif?");
+
+ if (tiger_show_grid)
+ strncat(tigertmp, "&on=GRID", sizeof(tigertmp) - 1 - strlen(tigertmp));
+ else
+ strncat(tigertmp, "&off=GRID", sizeof(tigertmp) - 1 - strlen(tigertmp));
+
+ if (tiger_show_counties)
+ strncat(tigertmp, "&on=counties", sizeof(tigertmp) - 1 - strlen(tigertmp));
+ else
+ strncat(tigertmp, "&off=counties", sizeof(tigertmp) - 1 - strlen(tigertmp));
+
+ if (tiger_show_cities)
+ strncat(tigertmp, "&on=CITIES", sizeof(tigertmp) - 1 - strlen(tigertmp));
+ else
+ strncat(tigertmp, "&off=CITIES", sizeof(tigertmp) - 1 - strlen(tigertmp));
+
+ if (tiger_show_places)
+ strncat(tigertmp, "&on=places", sizeof(tigertmp) - 1 - strlen(tigertmp));
+ else
+ strncat(tigertmp, "&off=places", sizeof(tigertmp) - 1 - strlen(tigertmp));
+
+ if (tiger_show_majroads)
+ strncat(tigertmp, "&on=majroads", sizeof(tigertmp) - 1 - strlen(tigertmp));
+ else
+ strncat(tigertmp, "&off=majroads", sizeof(tigertmp) - 1 - strlen(tigertmp));
+
+ if (tiger_show_streets)
+ strncat(tigertmp, "&on=streets", sizeof(tigertmp) - 1 - strlen(tigertmp));
+ // Don't turn streets off since this will automagically show up as you zoom in.
+
+ if (tiger_show_railroad)
+ strncat(tigertmp, "&on=railroad", sizeof(tigertmp) - 1 - strlen(tigertmp));
+ else
+ strncat(tigertmp, "&off=railroad", sizeof(tigertmp) - 1 - strlen(tigertmp));
+
+ if (tiger_show_states)
+ strncat(tigertmp, "&on=states", sizeof(tigertmp) - 1 - strlen(tigertmp));
+ else
+ strncat(tigertmp, "&off=states", sizeof(tigertmp) - 1 - strlen(tigertmp));
+
+ if (tiger_show_interstate)
+ strncat(tigertmp, "&on=interstate", sizeof(tigertmp) - 1 - strlen(tigertmp));
+ else
+ strncat(tigertmp, "&off=interstate", sizeof(tigertmp) - 1 - strlen(tigertmp));
+
+ if (tiger_show_ushwy)
+ strncat(tigertmp, "&on=ushwy", sizeof(tigertmp) - 1 - strlen(tigertmp));
+ else
+ strncat(tigertmp, "&off=ushwy", sizeof(tigertmp) - 1 - strlen(tigertmp));
+
+ if (tiger_show_statehwy)
+ strncat(tigertmp, "&on=statehwy", sizeof(tigertmp) - 1 - strlen(tigertmp));
+ else
+ strncat(tigertmp, "&off=statehwy", sizeof(tigertmp) - 1 - strlen(tigertmp));
+
+ if (tiger_show_water)
+ strncat(tigertmp, "&on=water", sizeof(tigertmp) - 1 - strlen(tigertmp));
+ else
+ strncat(tigertmp, "&off=water", sizeof(tigertmp) - 1 - strlen(tigertmp));
+
+ if (tiger_show_lakes)
+ strncat(tigertmp, "&on=shorelin", sizeof(tigertmp) - 1 - strlen(tigertmp));
+ else
+ strncat(tigertmp, "&off=shorelin", sizeof(tigertmp) - 1 - strlen(tigertmp));
+
+ if (tiger_show_misc)
+ strncat(tigertmp, "&on=miscell", sizeof(tigertmp) - 1 - strlen(tigertmp));
+ else
+ strncat(tigertmp, "&off=miscell", sizeof(tigertmp) - 1 - strlen(tigertmp));
+
+ xastir_snprintf(tmpstr, sizeof(tmpstr), "&lat=%f\046lon=%f\046", lat_center, long_center);
+ strncat (tigertmp, tmpstr, sizeof(tigertmp) - 1 - strlen(tigertmp));
+ xastir_snprintf(tmpstr, sizeof(tmpstr), "wid=%f\046ht=%f\046", map_width, map_height);
+ strncat (tigertmp, tmpstr, sizeof(tigertmp) - 1 - strlen(tigertmp));
+ xastir_snprintf(tmpstr, sizeof(tmpstr), "iwd=%i\046iht=%i", tp[1].img_x + 1, tp[1].img_y + 1);
+ strncat (tigertmp, tmpstr, sizeof(tigertmp) - 1 - strlen(tigertmp));
+ xastir_snprintf(fileimg, sizeof(fileimg), "%s", tigertmp);
+
+ if (debug_level & 512) {
+ fprintf(stderr,"left side is %f\n", left);
+ fprintf(stderr,"right side is %f\n", right);
+ fprintf(stderr,"top is %f\n", top);
+ fprintf(stderr,"bottom is %f\n", bottom);
+ fprintf(stderr,"lat center is %f\n", lat_center);
+ fprintf(stderr,"long center is %f\n", long_center);
+ fprintf(stderr,"screen width is %li\n", screen_width);
+ fprintf(stderr,"screen height is %li\n", screen_height);
+ fprintf(stderr,"map width is %f\n", map_width);
+ fprintf(stderr,"map height is %f\n", map_height);
+ fprintf(stderr,"fileimg is %s\n", fileimg);
+ fprintf(stderr,"ftp or http file: %s\n", fileimg);
+ }
+
+
+// Hopefully this will eventually allow us to get maps in the background
+// while (sometimeout !=0 && local_filename[0]==NULL){
+
+ if (local_filename[0]=='\0' ){
+
+ if (debug_level & 512 ) {
+ fprintf(stderr,"tiger_local_file=<%s>\n",local_filename);
+ }
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ get_tiger_local_file(local_filename,fileimg);
+
+ }
+
+// whackadoodle
+
+
+ // Tell ImageMagick where to find it
+ xastir_snprintf(file,
+ sizeof(file),
+ "%s",
+ local_filename);
+
+ GetExceptionInfo(&exception);
+
+ image_info=CloneImageInfo((ImageInfo *) NULL);
+
+ xastir_snprintf(image_info->filename,
+ sizeof(image_info->filename),
+ "%s",
+ file);
+
+ if (debug_level & 512) {
+ fprintf(stderr,"Copied %s into image info.\n", file);
+ fprintf(stderr,"image_info got: %s\n", image_info->filename);
+ fprintf(stderr,"Entered ImageMagick code.\n");
+ fprintf(stderr,"Attempting to open: %s\n", image_info->filename);
+ }
+
+ // We do a test read first to see if the file exists, so we
+ // don't kill Xastir in the ReadImage routine.
+ f = fopen (image_info->filename, "r");
+ if (f == NULL) {
+ if (debug_level & 512)
+ fprintf(stderr,"File could not be read\n");
+
+#ifdef USE_MAP_CACHE
+
+ // clear from cache if bad
+ if (map_cache_del(fileimg)) {
+ if (debug_level & 512) {
+ fprintf(stderr,"Couldn't delete unreadable map from cache\n");
+ }
+ }
+#endif
+
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+ (void)fclose (f);
+
+
+ image = ReadImage(image_info, &exception);
+
+ if (image == (Image *) NULL) {
+ MagickWarning(exception.severity, exception.reason, exception.description);
+ //fprintf(stderr,"MagickWarning\n");
+
+#ifdef USE_MAP_CACHE
+ // clear from cache if bad
+ if (map_cache_del(fileimg)) {
+ if (debug_level & 512) {
+ fprintf(stderr,"Couldn't delete map from cache\n");
+ }
+ }
+#endif
+
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+
+ if (debug_level & 512)
+ fprintf(stderr,"Color depth is %i \n", (int)image->depth);
+
+ if (image->colorspace != RGBColorspace) {
+ fprintf(stderr,"TBD: I don't think we can deal with colorspace != RGB");
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+ width = image->columns;
+ height = image->rows;
+
+ // Code to mute the image so it's not as bright.
+/* if (raster_map_intensity < 1.0) {
+ char tempstr[30];
+
+ if (debug_level & 512)
+ fprintf(stderr,"level=%s\n", tempstr);
+
+ xastir_snprintf(tempstr,
+ sizeof(tempstr),
+ "%d, 100, 100",
+ (int)(raster_map_intensity * 100.0));
+
+ ModulateImage(image, tempstr);
+ }
+*/
+
+
+ // If were are drawing to a low bpp display (typically < 8bpp)
+ // try to reduce the number of colors in an image.
+ // This may take some time, so it would be best to do ahead of
+ // time if it is a static image.
+#if (MagickLibVersion < 0x0540)
+ if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL) > 128) {
+#else // MagickLib >= 540
+ if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL, &exception) > 128) {
+#endif // MagickLib Version
+
+ if (image->storage_class == PseudoClass) {
+#if (MagickLibVersion < 0x0549)
+ CompressColormap(image); // Remove duplicate colors
+#else // MagickLib >= 0x0549
+ CompressImageColormap(image); // Remove duplicate colors
+#endif // MagickLibVersion < 0x0549
+ }
+
+ // Quantize down to 128 will go here...
+ }
+
+
+ pixel_pack = GetImagePixels(image, 0, 0, image->columns, image->rows);
+ if (!pixel_pack) {
+ fprintf(stderr,"pixel_pack == NULL!!!");
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+
+ index_pack = GetIndexes(image);
+ if (image->storage_class == PseudoClass && !index_pack) {
+ fprintf(stderr,"PseudoClass && index_pack == NULL!!!");
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+
+ if (image->storage_class == PseudoClass && image->colors <= 256) {
+ for (l = 0; l < (int)image->colors; l++) {
+ // Need to check how to do this for ANY image, as ImageMagick can read in all sorts
+ // of image files
+ temp_pack = image->colormap[l];
+ if (debug_level & 512)
+ fprintf(stderr,"Colormap color is %i %i %i \n",
+ temp_pack.red, temp_pack.green, temp_pack.blue);
+
+ // Here's a tricky bit: PixelPacket entries are defined as Quantum's. Quantum
+ // is defined in /usr/include/magick/image.h as either an unsigned short or an
+ // unsigned char, depending on what "configure" decided when ImageMagick was installed.
+ // We can determine which by looking at MaxRGB or QuantumDepth.
+ //
+ if (QuantumDepth == 16) { // Defined in /usr/include/magick/image.h
+ if (debug_level & 512)
+ fprintf(stderr,"Color quantum is [0..65535]\n");
+ my_colors[l].red = temp_pack.red * raster_map_intensity;
+ my_colors[l].green = temp_pack.green * raster_map_intensity;
+ my_colors[l].blue = temp_pack.blue * raster_map_intensity;
+ }
+ else { // QuantumDepth = 8
+ if (debug_level & 512)
+ fprintf(stderr,"Color quantum is [0..255]\n");
+ my_colors[l].red = (temp_pack.red << 8) * raster_map_intensity;
+ my_colors[l].green = (temp_pack.green << 8) * raster_map_intensity;
+ my_colors[l].blue = (temp_pack.blue << 8) * raster_map_intensity;
+ }
+
+ // Get the color allocated on < 8bpp displays. pixel color is written to my_colors.pixel
+ if (visual_type == NOT_TRUE_NOR_DIRECT) {
+// XFreeColors(XtDisplay(w), cmap, &(my_colors[l].pixel),1,0);
+ XAllocColor(XtDisplay(w), cmap, &my_colors[l]);
+ }
+ else {
+ pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue,
+ &my_colors[l].pixel);
+ }
+
+ if (debug_level & 512)
+ fprintf(stderr,"Color allocated is %li %i %i %i \n", my_colors[l].pixel,
+ my_colors[l].red, my_colors[l].blue, my_colors[l].green);
+ }
+ }
+
+
+
+ /*
+ * Here are the corners of our viewport, using the Xastir
+ * coordinate system. Notice that Y is upside down:
+ *
+ * left edge of view = NW_corner_longitude
+ * right edge of view = SE_corner_longitude
+ * top edge of view = NW_corner_latitude
+ * bottom edge of view = SE_corner_latitude
+ *
+ * The corners of our map will soon be (after translating the
+ * tiepoints to the corners if they're not already there):
+ *
+ * left edge of map = tp[0].x_long in Xastir format
+ * right edge of map = tp[1].x_long
+ * top edge of map = tp[0].y_lat
+ * bottom edge of map = tp[1].y_lat
+ *
+ */
+ map_c_L = tp[0].x_long - NW_corner_longitude; // map left coordinate
+ map_c_T = tp[0].y_lat - NW_corner_latitude; // map top coordinate
+
+ tp_c_dx = (long)(tp[1].x_long - tp[0].x_long);// Width between tiepoints
+ tp_c_dy = (long)(tp[1].y_lat - tp[0].y_lat); // Height between tiepoints
+
+
+ // Check for tiepoints being in wrong relation to one another
+ if (tp_c_dx < 0)
+ tp_c_dx = -tp_c_dx; // New width between tiepoints
+ if (tp_c_dy < 0)
+ tp_c_dy = -tp_c_dy; // New height between tiepoints
+
+ // Calculate step size per pixel
+ map_c_dx = ((double) tp_c_dx / abs(tp[1].img_x - tp[0].img_x));
+ map_c_dy = ((double) tp_c_dy / abs(tp[1].img_y - tp[0].img_y));
+
+ // Scaled screen step size for use with XFillRectangle below
+ scr_dx = (int) (map_c_dx / scale_x) + 1;
+ scr_dy = (int) (map_c_dy / scale_y) + 1;
+
+ // calculate top left map corner from tiepoints
+ if (tp[0].img_x != 0) {
+ tp[0].x_long -= (tp[0].img_x * map_c_dx); // map left edge longitude
+ map_c_L = tp[0].x_long - NW_corner_longitude; // delta ??
+ tp[0].img_x = 0;
+ if (debug_level & 512)
+ fprintf(stderr,"Translated tiepoint_0 x: %d\t%lu\n", tp[0].img_x, tp[0].x_long);
+ }
+ if (tp[0].img_y != 0) {
+ tp[0].y_lat -= (tp[0].img_y * map_c_dy); // map top edge latitude
+ map_c_T = tp[0].y_lat - NW_corner_latitude;
+ tp[0].img_y = 0;
+ if (debug_level & 512)
+ fprintf(stderr,"Translated tiepoint_0 y: %d\t%lu\n", tp[0].img_y, tp[0].y_lat);
+ }
+
+ // calculate bottom right map corner from tiepoints
+ // map size is geo_image_width / geo_image_height
+ if (tp[1].img_x != (geo_image_width - 1) ) {
+ tp[1].img_x = geo_image_width - 1;
+ tp[1].x_long = tp[0].x_long + (tp[1].img_x * map_c_dx); // right
+ if (debug_level & 512)
+ fprintf(stderr,"Translated tiepoint_1 x: %d\t%lu\n", tp[1].img_x, tp[1].x_long);
+ }
+ if (tp[1].img_y != (geo_image_height - 1) ) {
+ tp[1].img_y = geo_image_height - 1;
+ tp[1].y_lat = tp[0].y_lat + (tp[1].img_y * map_c_dy); // bottom
+ if (debug_level & 512)
+ fprintf(stderr,"Translated tiepoint_1 y: %d\t%lu\n", tp[1].img_y, tp[1].y_lat);
+ }
+
+ if (debug_level & 512) {
+ fprintf(stderr,"X tiepoint width: %ld\n", tp_c_dx);
+ fprintf(stderr,"Y tiepoint width: %ld\n", tp_c_dy);
+ fprintf(stderr,"Loading imagemap: %s\n", file);
+ fprintf(stderr,"\nImage: %s\n", file);
+ fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height);
+ fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n",
+ map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y));
+ fprintf(stderr,"Image size %d %d\n", width, height);
+#if (MagickLibVersion < 0x0540)
+ fprintf(stderr,"Unique colors = %d\n", GetNumberColors(image, NULL));
+#else // MagickLib < 540
+ fprintf(stderr,"Unique colors = %ld\n", GetNumberColors(image, NULL, &exception));
+#endif // MagickLib < 540
+ fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T,
+ map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y));
+ fprintf(stderr,"image matte is %i\n", image->matte);
+ } // debug_level & 512
+
+ // draw the image from the file out to the map screen
+
+ // Get the border values for the X and Y for loops used
+ // for the XFillRectangle call later.
+
+ map_c_yc = (tp[0].y_lat + tp[1].y_lat) / 2; // vert center of map as reference
+ map_y_ctr = (long)(height / 2 +0.499);
+ scale_x0 = get_x_scale(0,map_c_yc,scale_y); // reference scaling at vert map center
+
+ map_c_xc = (tp[0].x_long + tp[1].x_long) / 2; // hor center of map as reference
+ map_x_ctr = (long)(width / 2 +0.499);
+ scr_x_mc = (map_c_xc - NW_corner_longitude) / scale_x; // screen coordinates of map center
+
+ // calculate map pixel range in y direction that falls into screen area
+ c_y_max = 0ul;
+ map_y_min = map_y_max = 0l;
+ for (map_y_0 = 0, c_y = tp[0].y_lat; map_y_0 < (long)height; map_y_0++, c_y += map_c_dy) {
+ scr_y = (c_y - NW_corner_latitude) / scale_y; // current screen position
+ if (scr_y > 0) {
+ if (scr_y < screen_height) {
+ map_y_max = map_y_0; // update last map pixel in y
+ c_y_max = (unsigned long)c_y;// bottom map inside screen coordinate
+ } else
+ break; // done, reached bottom screen border
+ } else { // pixel is above screen
+ map_y_min = map_y_0; // update first map pixel in y
+ }
+ }
+ c_y_min = (unsigned long)(tp[0].y_lat + map_y_min * map_c_dy); // top map inside screen coordinate
+
+ map_x_min = map_x_max = 0l;
+ for (map_x = 0, c_x = tp[0].x_long; map_x < (long)width; map_x++, c_x += map_c_dx) {
+ scr_x = (c_x - NW_corner_longitude)/ scale_x; // current screen position
+ if (scr_x > 0) {
+ if (scr_x < screen_width)
+ map_x_max = map_x; // update last map pixel in x
+ else
+ break; // done, reached right screen border
+ } else { // pixel is left from screen
+ map_x_min = map_x; // update first map pixel in x
+ }
+ }
+ c_x_min = (unsigned long)(tp[0].x_long + map_x_min * map_c_dx); // left map inside screen coordinate
+
+ scr_yp = -1;
+ scr_c_xr = SE_corner_longitude;
+ c_dx = map_c_dx; // map pixel width
+ scale_xa = scale_x0; // the compiler likes it ;-)
+
+ map_done = 0;
+ map_act = 0;
+ map_seen = 0;
+ scr_y = screen_height - 1;
+
+
+ // loop over map pixel rows
+ for (map_y_0 = map_y_min, c_y = (double)c_y_min; (map_y_0 <= map_y_max); map_y_0++, c_y += map_c_dy) {
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ DestroyExceptionInfo(&exception);
+ return;
+ }
+
+ scr_y = (c_y - NW_corner_latitude) / scale_y;
+ if (scr_y != scr_yp) { // don't do a row twice
+ scr_yp = scr_y; // remember as previous y
+ scr_xp = -1;
+ // loop over map pixel columns
+ map_act = 0;
+ scale_x_nm = calc_dscale_x(0,(long)c_y) / 1852.0; // nm per Xastir coordinate
+ for (map_x = map_x_min, c_x = (double)c_x_min; map_x <= map_x_max; map_x++, c_x += c_dx) {
+ scr_x = (c_x - NW_corner_longitude) / scale_x;
+ if (scr_x != scr_xp) { // don't do a pixel twice
+ scr_xp = scr_x; // remember as previous x
+ map_y = map_y_0;
+
+ if (map_y >= 0 && map_y <= tp[1].img_y) { // check map boundaries in y direction
+ map_seen = 1;
+ map_act = 1; // detects blank screen rows (end of map)
+
+ // now copy a pixel from the map image to the screen
+ l = map_x + map_y * image->columns;
+ if (image->storage_class == PseudoClass) {
+ XSetForeground(XtDisplay(w), gc, my_colors[index_pack[l]].pixel);
+ }
+ else {
+ // It is not safe to assume that the red/green/blue
+ // elements of pixel_pack of type Quantum are the
+ // same as the red/green/blue of an XColor!
+ if (QuantumDepth==16) {
+ my_colors[0].red=pixel_pack[l].red;
+ my_colors[0].green=pixel_pack[l].green;
+ my_colors[0].blue=pixel_pack[l].blue;
+ }
+ else { // QuantumDepth=8
+ // shift the bits of the 8-bit quantity so that
+ // they become the high bigs of my_colors.*
+ my_colors[0].red=pixel_pack[l].red<<8;
+ my_colors[0].green=pixel_pack[l].green<<8;
+ my_colors[0].blue=pixel_pack[l].blue<<8;
+ }
+ // NOW my_colors has the right r,g,b range for
+ // pack_pixel_bits
+ pack_pixel_bits(my_colors[0].red * raster_map_intensity,
+ my_colors[0].green * raster_map_intensity,
+ my_colors[0].blue * raster_map_intensity,
+ &my_colors[0].pixel);
+ XSetForeground(XtDisplay(w), gc, my_colors[0].pixel);
+ }
+ (void)XFillRectangle (XtDisplay (w),pixmap,gc,scr_x,scr_y,scr_dx,scr_dy);
+ } // check map boundaries in y direction
+ }
+ } // loop over map pixel columns
+ if (map_seen && !map_act)
+ map_done = 1;
+ }
+ } // loop over map pixel rows
+
+ if (image)
+ DestroyImage(image);
+ if (image_info)
+ DestroyImageInfo(image_info);
+ DestroyExceptionInfo(&exception);
+}
+#endif //HAVE_MAGICK
+///////////////////////////////////////////// End of Tigermap code ///////////////////////////////////////
diff --git a/src/maps.c b/src/maps.c
new file mode 100644
index 0000000..153e9e3
--- /dev/null
+++ b/src/maps.c
@@ -0,0 +1,9061 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: maps.c,v 1.534 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+//#define GDAL_SHAPEFILES
+//#define MAP_SCALE_CHECK
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#ifdef HAVE_MAGICK
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+#undef RETSIGTYPE
+// TVR: "stupid ImageMagick"
+// The problem is that magick/api.h includes Magick's config.h file, and that
+// pulls in all the same autoconf-generated defines that we use.
+// plays those games below, but I don't think in the end that they actually
+// make usable macros with our own data in them.
+// Fortunately, we don't need them, so I'll just undef the ones that are
+// causing problems today. See main.c for fixes that preserve our values.
+#undef PACKAGE
+#undef VERSION
+/* JMT - stupid ImageMagick */
+#define XASTIR_PACKAGE_BUGREPORT PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#define XASTIR_PACKAGE_NAME PACKAGE_NAME
+#undef PACKAGE_NAME
+#define XASTIR_PACKAGE_STRING PACKAGE_STRING
+#undef PACKAGE_STRING
+#define XASTIR_PACKAGE_TARNAME PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#define XASTIR_PACKAGE_VERSION PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#ifdef HAVE_GRAPHICSMAGICK
+/*#include <GraphicsMagick/magick/api.h>*/
+#include <magick/api.h>
+#else // HAVE_GRAPHICSMAGICK
+#include <magick/api.h>
+#endif // HAVE_GRAPHICSMAGICK
+#undef PACKAGE_BUGREPORT
+#define PACKAGE_BUGREPORT XASTIR_PACKAGE_BUGREPORT
+#undef XASTIR_PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#define PACKAGE_NAME XASTIR_PACKAGE_NAME
+#undef XASTIR_PACKAGE_NAME
+#undef PACKAGE_STRING
+#define PACKAGE_STRING XASTIR_PACKAGE_STRING
+#undef XASTIR_PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#define PACKAGE_TARNAME XASTIR_PACKAGE_TARNAME
+#undef XASTIR_PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#define PACKAGE_VERSION XASTIR_PACKAGE_VERSION
+#undef XASTIR_PACKAGE_VERSION
+#endif // HAVE_MAGICK
+
+#include <dirent.h>
+#include <netinet/in.h>
+#include <Xm/XmAll.h>
+
+#ifdef HAVE_X11_XPM_H
+#include <X11/xpm.h>
+#ifdef HAVE_LIBXPM // if we have both, prefer the extra library
+#undef HAVE_XM_XPMI_H
+#endif // HAVE_LIBXPM
+#endif // HAVE_X11_XPM_H
+
+#ifdef HAVE_XM_XPMI_H
+#include <Xm/XpmI.h>
+#endif // HAVE_XM_XPMI_H
+
+#include <X11/Xlib.h>
+
+#include <math.h>
+
+#include "xastir.h"
+#include "maps.h"
+#include "alert.h"
+#include "util.h"
+#include "main.h"
+#include "datum.h"
+#include "draw_symbols.h"
+#include "rotated.h"
+#include "color.h"
+#include "xa_config.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+extern XmFontList fontlist1; // Menu/System fontlist
+
+#define GRID_MORE 5000
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+
+// Check for XPM and/or ImageMagick. We use "NO_GRAPHICS"
+// to disable some routines below if the support for them
+// is not compiled in.
+#if !(defined(HAVE_LIBXPM) || defined(HAVE_LIBXPM_IN_XM) || defined(HAVE_MAGICK))
+ #define NO_GRAPHICS 1
+#endif // !(HAVE_LIBXPM || HAVE_LIBXPM_IN_XM || HAVE_MAGICK)
+
+#if !(defined(HAVE_LIBXPM) || defined(HAVE_LIBXPM_IN_XM))
+ #define NO_XPM 1
+#endif // !(HAVE_LIBXPM || HAVE_LIBXPM_IN_XM)
+
+
+void draw_rotated_label_text_to_target (Widget w, int rotation, int x, int y, int label_length, int color, char *label_text, int fontsize, Pixmap target_pixmap, int draw_outline, int outline_bg_color);
+int get_rotated_label_text_height_pixels(Widget w, char *label_text, int fontsize);
+
+// Constants defining the color of the labeled grid border.
+int outline_border_labels = TRUE; // if true put an outline around the border labels
+int border_foreground_color = 0x20; // color of the map border, if shown
+ // 0x08 is black.
+ // 0x20 is white.
+int outline_border_labels_color = 0x20;
+ // outline_border_labels_color = border_foreground_color;
+ // color of outline to draw around border labels
+ // use color of border to help make text more legible.
+
+// Print options
+Widget print_properties_dialog = (Widget)NULL;
+static xastir_mutex print_properties_dialog_lock;
+Widget print_postscript_dialog = (Widget)NULL;
+static xastir_mutex print_postscript_dialog_lock;
+Widget printer_data;
+Widget previewer_data;
+
+Widget rotate_90 = (Widget)NULL;
+Widget auto_rotate = (Widget)NULL;
+//char print_paper_size[20] = "Letter"; // Displayed in dialog, but not used yet.
+int print_rotated = 0;
+int print_auto_rotation = 0;
+//float print_scale = 1.0; // Not used yet.
+int print_auto_scale = 0;
+//int print_blank_background_color = 0; // Not used yet.
+int print_in_monochrome = 0;
+int print_resolution = 150; // 72 dpi is normal for Postscript.
+ // 100 or 150 dpi work well with HP printer
+int print_invert = 0; // Reverses black/white
+
+char printer_program[MAX_FILENAME+1];
+char previewer_program[MAX_FILENAME+1];
+
+time_t last_snapshot = 0; // Used to determine when to take next snapshot
+time_t last_kmlsnapshot = 0; // Used to determine when to take next kml snapshot
+int doing_snapshot = 0;
+int snapshot_interval = 0;
+
+
+int mag;
+int npoints; /* number of points in a line */
+
+
+float raster_map_intensity = 0.65; // Raster map color intensity, set from Maps->Map Intensity
+float imagemagick_gamma_adjust = 0.0; // Additional imagemagick map gamma correction, set from Maps->Adjust Gamma
+
+// Storage for the index file timestamp
+time_t map_index_timestamp;
+
+int grid_size = 0;
+
+// Rounding
+#ifndef HAVE_ROUNDF
+// Poor man's rounding, but rounds away from zero as roundf is supposed to.
+
+float roundf(float x)
+{
+ int i;
+ i= (((x)>=0)?(((x)+.5)):(((x)-.5)));
+ return ((float)i);
+}
+
+#endif
+
+
+// UTM Grid stuff
+//
+//#define UTM_DEBUG
+//#define UTM_DEBUG_VERB
+//#define UTM_DEBUG_ALLOC
+//
+inline int max_i(int a, int b) { return (a > b ? a : b); }
+#define UTM_GRID_EQUATOR 10000000
+// the maximum number of UTM zones that will appear on a screen that has a
+// high enough resolution to display the within-zone utm grid
+#define UTM_GRID_MAX_ZONES 4
+// the maximum number of grid lines in each direction shown in each zone
+// on the screen at one time
+#define UTM_GRID_MAX_COLS_ROWS 64
+#define UTM_GRID_DEF_NALLOCED 8
+#define UTM_GRID_RC_EMPTY 0xffff
+
+// the hash stores the upper left and lower right boundaries of the
+// display of a utm grid to determine whether it matches the current
+// screen boundaries or whether the grid needs to be recalculated
+// for the current screen.
+typedef struct {
+ long ul_x;
+ long ul_y;
+ long lr_x;
+ long lr_y;
+} hash_t;
+
+// The utm grid is drawn by connecting a grid of points marking the
+// intersection of the easting and northing lines. col_or_row holds
+// this grid of points for the portion of a utm zone visible on the
+// screen. Zone boundaries are not directly represented here.
+// In particular, the parallels separating lettered zone rows are
+// not directly represented here.
+typedef struct {
+ int firstpoint;
+ int npoints;
+ int nalloced;
+ XPoint *points;
+} col_or_row_t;
+
+// The portion of a utm zone visible on the screen has some number of
+// visible easting lines and northing lines forming a grid that covers
+// part or all of the screen. Zone holds arrays of the coordinates
+// of the visible easting and northing intersections, and the next set
+// of intersections off screen. The coarseness of this grid is
+// determined by the current scale and stored in utm_grid_spacing_m.
+typedef struct {
+ unsigned int ncols;
+ col_or_row_t col[UTM_GRID_MAX_COLS_ROWS];
+ unsigned int nrows;
+ col_or_row_t row[UTM_GRID_MAX_COLS_ROWS];
+ int boundary_x;
+} zone_t;
+
+// A utm grid is represented by its hash (upper left and lower right coordinates)
+// which are used to check whether or not it fits the current screen or needs to
+// be recalculated, and an array of the zones visible on the screen, each containing
+// arrays of the points marking the easting/northing intersections of a zone (with
+// one or more lettered zone rows).
+typedef struct {
+ hash_t hash;
+ unsigned int nzones;
+ zone_t zone[UTM_GRID_MAX_ZONES];
+} utm_grid_t;
+
+utm_grid_t utm_grid;
+
+unsigned int utm_grid_spacing_m;
+// ^ the above is extern'ed in maps.h for use by draw_ruler_text in
+// db.c
+
+
+
+
+
+// Clear out/set up the UTM/MGRS minor grid intersection arrays.
+//
+// do_alloc = 0: Don't allocate memory
+// 1: Allocate memory for the points
+//
+// Returns: 0 if ok
+// 1 if malloc problem
+//
+int utm_grid_clear(int do_alloc)
+{
+ int i, j;
+
+ utm_grid.hash.ul_x = 0;
+ utm_grid.hash.ul_y = 0;
+ utm_grid.hash.lr_x = 0;
+ utm_grid.hash.lr_y = 0;
+ utm_grid.nzones = 0;
+
+ for (i=0; i < UTM_GRID_MAX_ZONES; i++) {
+
+ utm_grid.zone[i].ncols = utm_grid.zone[i].nrows = 0;
+ utm_grid.zone[i].boundary_x = 0;
+
+ for (j=0; j < UTM_GRID_MAX_COLS_ROWS; j++) {
+
+ //
+ // Clear out column arrays
+ //
+ utm_grid.zone[i].col[j].firstpoint = UTM_GRID_RC_EMPTY;
+ utm_grid.zone[i].col[j].npoints = 0;
+
+ if (utm_grid.zone[i].col[j].nalloced)
+ free(utm_grid.zone[i].col[j].points);
+
+ utm_grid.zone[i].col[j].nalloced = 0;
+ utm_grid.zone[i].col[j].points = NULL;
+
+ if (do_alloc) {
+
+ // Allocate enough space for 8 points
+ utm_grid.zone[i].col[j].points = calloc(UTM_GRID_DEF_NALLOCED, sizeof(XPoint));
+ if (!utm_grid.zone[i].col[j].points) {
+ fprintf(stderr,"calloc(%d, %d) for z=%d col=%d FAILED!\n",
+ UTM_GRID_DEF_NALLOCED,
+ (int)sizeof(XPoint),
+ i,
+ j);
+// abort(); // Causes a segfault
+ return(1);
+ }
+ utm_grid.zone[i].col[j].nalloced = UTM_GRID_DEF_NALLOCED;
+ }
+
+ //
+ // Clear out row arrays
+ //
+ utm_grid.zone[i].row[j].firstpoint = UTM_GRID_RC_EMPTY;
+ utm_grid.zone[i].row[j].npoints = 0;
+ utm_grid.zone[i].row[j].nalloced = 0;
+
+ if (utm_grid.zone[i].row[j].nalloced)
+ free(utm_grid.zone[i].row[j].points);
+
+ utm_grid.zone[i].row[j].nalloced = 0;
+ utm_grid.zone[i].row[j].points = NULL;
+
+ if (do_alloc) {
+
+ // Allocate enough space for 8 points
+ utm_grid.zone[i].row[j].points = calloc(UTM_GRID_DEF_NALLOCED, sizeof(XPoint));
+ if (!utm_grid.zone[i].row[j].points) {
+ fprintf(stderr,"calloc(%d, %d) for z=%d row=%d FAILED!\n",
+ UTM_GRID_DEF_NALLOCED,
+ (int)sizeof(XPoint),
+ i,
+ j);
+// abort(); // Causes a segfault
+ return(1);
+ }
+ utm_grid.zone[i].row[j].nalloced = UTM_GRID_DEF_NALLOCED;
+ }
+ }
+ }
+ return(0);
+}
+
+
+
+
+
+void maps_init(void)
+{
+ fprintf(stderr,"\n\nBuilt-in map types:\n");
+ fprintf(stderr,"%10s USGS GNIS Datapoints\n","gnis");
+ fprintf(stderr,"%10s USGS GNIS Datapoints w/population\n","pop");
+ fprintf(stderr,"%10s APRSdos Maps\n","map");
+ fprintf(stderr,"%10s WinAPRS/MacAPRS/X-APRS Maps\n","map");
+ fprintf(stderr,"%10s PocketAPRS Maps\n","pdb");
+
+ fprintf(stderr,"\nSupport for these additional map types has been compiled in: \n");
+
+#ifdef HAVE_MAGICK
+ fprintf(stderr,"%10s Image Map (ImageMagick/GraphicsMagick library, many formats allowed)\n","geo");
+#endif // HAVE_MAGICK
+
+#ifndef NO_GRAPHICS
+#ifdef HAVE_LIBCURL
+ fprintf(stderr,"%10s URL (Internet maps via libcurl library)\n","geo");
+ fprintf(stderr,"%10s URL (OpenStreetMaps via libcurl library\n","geo");
+ fprintf(stderr,"%10s Copyright OpenStreetMap and contributors, CC-BY-SA)\n", "");
+
+#else
+#ifdef HAVE_WGET
+ fprintf(stderr,"%10s URL (Internet maps via wget)\n","geo");
+ fprintf(stderr,"%10s URL (OpenStreetMaps via wget\n","geo");
+ fprintf(stderr,"%10s Copyright OpenStreetMap and contributors, CC-BY-SA)\n", "");
+#endif // HAVE_WGET
+#endif // HAVE_LIBCURL
+#endif // NO_GRAPHICS
+
+
+//#define GDAL_SHAPEFILES
+#ifdef GDAL_SHAPEFILES
+ #ifdef HAVE_LIBGDAL
+ fprintf(stderr,"%10s ESRI Shapefile Maps (GDAL/OGR library)\n","shp");
+ #endif // HAVE_LIBGDAL
+#else // GDAL_SHAPEFILES
+ #ifdef HAVE_LIBSHP
+ fprintf(stderr,"%10s ESRI Shapefile Maps (Shapelib library)\n","shp");
+ #endif // HAVE_LIBSHP
+#endif // GDAL_SHAPEFILES
+
+
+#ifdef HAVE_LIBGEOTIFF
+ fprintf(stderr,"%10s USGS DRG Geotiff Topographic Maps (libgeotiff/libproj)\n","tif");
+#endif // HAVE_LIBGEOTIFF
+
+#ifndef NO_XPM
+ fprintf(stderr,"%10s X Pixmap Maps (XPM library)\n","xpm");
+#endif // NO_XPM
+
+ init_critical_section( &print_properties_dialog_lock );
+ init_critical_section( &print_postscript_dialog_lock );
+
+ // Clear the minor UTM/MGRS grid arrays. Do _not_ allocate
+ // memory for the points.
+ (void)utm_grid_clear(0);
+}
+
+
+
+
+
+/*
+ * Calculate NS distance scale at a given location
+ * in meters per Xastir unit
+ */
+double calc_dscale_y(long x, long y) {
+
+ // approximation by looking at +/- 0.5 minutes offset
+ // (void)(calc_distance(y-3000, x, y+3000, x)/6000.0);
+ // but this scale is fixed at 1852/6000
+ return((double)(1852.0/6000.0));
+}
+
+
+
+
+
+/*
+ * Calculate EW distance scale at a given location
+ * in meters per Xastir unit
+ */
+double calc_dscale_x(long x, long y) {
+
+ // approximation by looking at +/- 0.5 minutes offset
+ // we should find a better formula...
+ return(calc_distance(y, x-3000, y, x+3000)/6000.0);
+}
+
+
+
+
+
+/*
+ * Calculate x map scaling for current location
+ * With that we could have equal distance scaling or a better
+ * view for pixel maps
+ */
+long get_x_scale(long x, long y, long ysc) {
+ long xsc;
+ double sc_x;
+ double sc_y;
+
+ sc_x = calc_dscale_x(x,y); // meter per Xastir unit
+ sc_y = calc_dscale_y(x,y);
+ if (sc_x < 0.01 || ysc > 50000)
+ // keep it near the poles (>88 deg) or if big parts of world seen
+ xsc = ysc;
+ else
+ // adjust y scale, so that the distance is identical in both directions:
+ xsc = (long)(ysc * sc_y / sc_x +0.4999);
+
+ //fprintf(stderr,"Scale: x %5.3fkm/deg, y %5.3fkm/deg, x %ld y %ld\n",sc_x*360,sc_y*360,xsc,ysc);
+ return(xsc);
+}
+
+
+
+
+
+/** MAP DRAWING ROUTINES **/
+
+
+
+// Function to perform 2D line-clipping Using the improved parametric
+// line-clipping algorithm by Liang, Barsky, and Slater published in
+// the paper: "Some Improvements to a Parametric Line Clipping
+// Algorithm", 1992. Called by clip2d() function below. This
+// function is set up for float values. See the clipt_long() and
+// clipt_int() functions for use with other types of values.
+//
+// Returns False if the line is rejected, True otherwise. May modify
+// t0 and t1.
+//
+int clipt(float p, float q, float *t0, float *t1) {
+ float r;
+ int accept = True;
+
+
+ if (p < 0) { // Entering visible region, so compute t0
+
+ if (q < 0) { // t0 will be non-negative, so continue
+
+ r = q / p;
+
+ if (r > *t1) { // t0 will exceed t1, so reject
+ accept = False;
+ }
+ else if (r > *t0) { // t0 is max of r's
+ *t0 = r;
+ }
+ }
+ }
+ else {
+
+ if (p > 0) { // Exiting visible region, so compute t1
+
+ if (q < p) { // t1 will be <= 1, so continue
+
+ r = q / p;
+
+ if (r < *t0) { // t1 will be <= t0, so reject
+ accept = False;
+ }
+ else if (r < *t1) { // t1 is min of r's
+ *t1 = r;
+ }
+ }
+ }
+ else { // p == 0
+
+ if (q < 0) { // Line parallel and outside, so reject
+ accept = False;
+ }
+ }
+ }
+ return(accept);
+}
+
+
+
+
+
+// Function to perform 2D line-clipping using the improved parametric
+// line-clipping algorithm by Liang, Barsky, and Slater published in
+// the paper: "Some Improvements to a Parametric Line Clipping
+// Algorithm", 1992. Uses the clipt() function above.
+//
+// Returns False if the line is rejected, True otherwise. x0, y0,
+// x1, y1 may get modified by this function. These will be the new
+// clipped line ends that fit inside the window.
+//
+// Clip 2D line segment with endpoints (x0,y0) and (x1,y1). The clip
+// window is x_left <= x <= x_right and y_bottom <= y <= y_top.
+//
+// This function is set up for float values. See the clip2d_long()
+// and clip2d_screen() functions for use with other types of values.
+//
+int clip2d(float *x0, float *y0, float *x1, float *y1) {
+ float t0, t1;
+ float delta_x, delta_y;
+ int visible = False;
+ float x_left, y_top; // NW corner of screen
+ float x_right, y_bottom; // SE corner of screen
+
+
+ // Assign floating point values for screen corners
+ y_top = f_NW_corner_latitude;
+ y_bottom = f_SE_corner_latitude;
+ x_left = f_NW_corner_longitude;
+ x_right = f_SE_corner_longitude;
+
+ if ( ((*x0 < x_left) && (*x1 < x_left))
+ || ((*x0 > x_right) && (*x1 > x_right))
+ || ((*y0 < y_bottom) && (*y1 < y_bottom))
+ || ((*y0 > y_top) && (*y1 > y_top)) ) {
+
+ // Both endpoints are on outside and same side of visible
+ // region, so reject.
+ return(visible);
+ }
+
+ t0 = 0;
+ t1 = 1;
+ delta_x = *x1 - *x0;
+
+ if ( clipt(-delta_x, *x0 - x_left, &t0, &t1) ) { // left
+
+ if ( clipt(delta_x, x_right - *x0, &t0, &t1) ) { // right
+
+ delta_y = *y1 - *y0;
+
+ if ( clipt(-delta_y, *y0 - y_bottom, &t0, &t1) ) { // bottom
+
+ if ( clipt(delta_y, y_top - *y0, &t0, &t1) ) { // top
+ // Compute coordinates
+
+ if (t1 < 1) { // Compute V1' (new x1,y1)
+ *x1 = *x0 + t1 * delta_x;
+ *y1 = *y0 + t1 * delta_y;
+ }
+
+ if (t0 > 0) { // Compute V0' (new x0,y0)
+ *x0 = *x0 + t0 * delta_x;
+ *y0 = *y0 + t0 * delta_y;
+ }
+ visible = True;
+ }
+ }
+ }
+ }
+ return(visible);
+}
+
+
+
+
+
+// Function to perform 2D line-clipping Using the improved parametric
+// line-clipping algorithm by Liang, Barsky, and Slater published in
+// the paper: "Some Improvements to a Parametric Line Clipping
+// Algorithm", 1992. Called by clip2d_long() function below. This
+// function is set up for Xastir coordinate values (unsigned longs).
+// See the clipt() and clipt_int() functions for use with other
+// types of values.
+//
+// Returns False if the line is rejected, True otherwise. May modify
+// t0 and t1.
+//
+int clipt_long(long p, long q, float *t0, float *t1) {
+ float r;
+ int accept = True;
+
+
+ if (p < 0) { // Entering visible region, so compute t0
+
+ if (q < 0) { // t0 will be non-negative, so continue
+
+ r = q / (p * 1.0);
+
+ if (r > *t1) { // t0 will exceed t1, so reject
+ accept = False;
+ }
+ else if (r > *t0) { // t0 is max of r's
+ *t0 = r;
+ }
+ }
+ }
+ else {
+
+ if (p > 0) { // Exiting visible region, so compute t1
+
+ if (q < p) { // t1 will be <= 1, so continue
+
+ r = q / (p * 1.0);
+
+ if (r < *t0) { // t1 will be <= t0, so reject
+ accept = False;
+ }
+ else if (r < *t1) { // t1 is min of r's
+ *t1 = r;
+ }
+ }
+ }
+ else { // p == 0
+
+ if (q < 0) { // Line parallel and outside, so reject
+ accept = False;
+ }
+ }
+ }
+ //fprintf(stderr,"clipt_long: %d\n",accept);
+ return(accept);
+}
+
+
+
+
+
+// Function to perform 2D line-clipping using the improved parametric
+// line-clipping algorithm by Liang, Barsky, and Slater published in
+// the paper: "Some Improvements to a Parametric Line Clipping
+// Algorithm", 1992. Uses the clipt_long() function above.
+//
+// Returns False if the line is rejected, True otherwise. x0, y0,
+// x1, y1 may get modified by this function. These will be the new
+// clipped line ends that fit inside the window.
+//
+// Clip 2D line segment with endpoints (x0,y0) and (x1,y1). The clip
+// window is x_left <= x <= x_right and y_bottom <= y <= y_top.
+//
+// This function uses the Xastir coordinate system. We had to flip
+// y_bottom/y_top below due to the coordinate system being
+// upside-down.
+//
+// This function is set up for Xastir coordinate values (unsigned
+// longs). See the clip2d() or clip2d_screen() functions for use
+// with other types of values.
+//
+int clip2d_long(unsigned long *x0, unsigned long *y0, unsigned long *x1, unsigned long *y1) {
+ float t0, t1;
+ long delta_x, delta_y;
+ int visible = False;
+ unsigned long x_left = NW_corner_longitude;
+ unsigned long x_right = SE_corner_longitude;
+ // Reverse the following two as our Xastir coordinate system is
+ // upside down. The algorithm requires this order.
+ unsigned long y_top = SE_corner_latitude;
+ unsigned long y_bottom = NW_corner_latitude;
+
+
+ if ( ( (*x0 < x_left ) && (*x1 < x_left ) )
+ || ( (*x0 > x_right ) && (*x1 > x_right ) )
+ || ( (*y0 < y_bottom) && (*y1 < y_bottom) )
+ || ( (*y0 > y_top ) && (*y1 > y_top ) ) ) {
+
+ // Both endpoints are on same side of visible region and
+ // outside of it, so reject.
+ //fprintf(stderr,"reject 1\n");
+ return(visible);
+ }
+
+ t0 = 0;
+ t1 = 1;
+ delta_x = *x1 - *x0;
+
+ if ( clipt_long(-delta_x, *x0 - x_left, &t0, &t1) ) { // left
+
+ if ( clipt_long(delta_x, x_right - *x0, &t0, &t1) ) { // right
+
+ delta_y = *y1 - *y0;
+
+ if ( clipt_long(-delta_y, *y0 - y_bottom, &t0, &t1) ) { // bottom
+
+ if ( clipt_long(delta_y, y_top - *y0, &t0, &t1) ) { // top
+ // Compute coordinates
+
+ if (t1 < 1) { // Compute V1' (new x1,y1)
+ *x1 = *x0 + t1 * delta_x;
+ *y1 = *y0 + t1 * delta_y;
+ }
+
+ if (t0 > 0) { // Compute V0' (new x0,y0)
+ *x0 = *x0 + t0 * delta_x;
+ *y0 = *y0 + t0 * delta_y;
+ }
+ visible = True;
+ }
+ else {
+ //fprintf(stderr,"reject top\n");
+ }
+ }
+ else {
+ //fprintf(stderr,"reject bottom\n");
+ }
+ }
+ else {
+ //fprintf(stderr,"reject right\n");
+ }
+ }
+ else {
+ //fprintf(stderr,"reject left\n");
+ }
+ return(visible);
+}
+
+
+
+
+
+// Function to perform 2D line-clipping Using the improved parametric
+// line-clipping algorithm by Liang, Barsky, and Slater published in
+// the paper: "Some Improvements to a Parametric Line Clipping
+// Algorithm", 1992. Called by clip2d_screen() function below. This
+// function is set up for screen coordinate values (unsigned ints).
+// See the clipt() and clipt_long functions for use with other types
+// of values.
+//
+// Returns False if the line is rejected, True otherwise. May modify
+// t0 and t1.
+//
+int clipt_int(int p, int q, float *t0, float *t1) {
+ float r;
+ int accept = True;
+
+
+ if (p < 0) { // Entering visible region, so compute t0
+
+ if (q < 0) { // t0 will be non-negative, so continue
+
+ r = q / (p * 1.0);
+
+ if (r > *t1) { // t0 will exceed t1, so reject
+ accept = False;
+ }
+ else if (r > *t0) { // t0 is max of r's
+ *t0 = r;
+ }
+ }
+ }
+ else {
+
+ if (p > 0) { // Exiting visible region, so compute t1
+
+ if (q < p) { // t1 will be <= 1, so continue
+
+ r = q / (p * 1.0);
+
+ if (r < *t0) { // t1 will be <= t0, so reject
+ accept = False;
+ }
+ else if (r < *t1) { // t1 is min of r's
+ *t1 = r;
+ }
+ }
+ }
+ else { // p == 0
+
+ if (q < 0) { // Line parallel and outside, so reject
+ accept = False;
+ }
+ }
+ }
+ //fprintf(stderr,"clipt_int: %d\n",accept);
+ return(accept);
+}
+
+
+
+
+
+// Function to perform 2D line-clipping using the improved parametric
+// line-clipping algorithm by Liang, Barsky, and Slater published in
+// the paper: "Some Improvements to a Parametric Line Clipping
+// Algorithm", 1992. Uses the clipt_int() function above.
+//
+// Returns False if the line is rejected, True otherwise. x0, y0,
+// x1, y1 may get modified by this function. These will be the new
+// clipped line ends that fit inside the window.
+//
+// Clip 2D line segment with endpoints (x0,y0) and (x1,y1). The clip
+// window is x_left <= x <= x_right and y_bottom <= y <= y_top.
+//
+// This function uses the screen coordinate system. We had to flip
+// y_bottom/y_top below due to the coordinate system being
+// upside-down.
+//
+// This function is set up for screen coordinate values (unsigned
+// ints). See the clip2d() and clip2d_long() functions for use
+// with other types of values.
+//
+int clip2d_screen(unsigned int *x0, unsigned int *y0, unsigned int *x1, unsigned int *y1) {
+ float t0, t1;
+ int delta_x, delta_y;
+ int visible = False;
+ unsigned int x_right = screen_width;
+ unsigned int x_left = 0;
+ // Reverse the following two as our screen coordinate system is
+ // upside down. The algorithm requires this order.
+ unsigned int y_top = screen_height;
+ unsigned int y_bottom = 0;
+
+
+ if ( ( (*x0 < x_left ) && (*x1 < x_left ) )
+ || ( (*x0 > x_right ) && (*x1 > x_right ) )
+ || ( (*y0 < y_bottom) && (*y1 < y_bottom) )
+ || ( (*y0 > y_top ) && (*y1 > y_top ) ) ) {
+
+ // Both endpoints are on same side of visible region and
+ // outside of it, so reject.
+ //fprintf(stderr,"reject 1\n");
+ return(visible);
+ }
+
+ t0 = 0;
+ t1 = 1;
+ delta_x = *x1 - *x0;
+
+ if ( clipt_int(-delta_x, *x0 - x_left, &t0, &t1) ) { // left
+
+ if ( clipt_int(delta_x, x_right - *x0, &t0, &t1) ) { // right
+
+ delta_y = *y1 - *y0;
+
+ if ( clipt_int(-delta_y, *y0 - y_bottom, &t0, &t1) ) { // bottom
+
+ if ( clipt_int(delta_y, y_top - *y0, &t0, &t1) ) { // top
+ // Compute coordinates
+
+ if (t1 < 1) { // Compute V1' (new x1,y1)
+ *x1 = *x0 + t1 * delta_x;
+ *y1 = *y0 + t1 * delta_y;
+ }
+
+ if (t0 > 0) { // Compute V0' (new x0,y0)
+ *x0 = *x0 + t0 * delta_x;
+ *y0 = *y0 + t0 * delta_y;
+ }
+ visible = True;
+ }
+ else {
+ //fprintf(stderr,"reject top\n");
+ }
+ }
+ else {
+ //fprintf(stderr,"reject bottom\n");
+ }
+ }
+ else {
+ //fprintf(stderr,"reject right\n");
+ }
+ }
+ else {
+ //fprintf(stderr,"reject left\n");
+ }
+ return(visible);
+}
+
+
+
+
+
+// Draws a point onto a pixmap. Assumes that the proper GC has
+// already been set up for drawing the correct color/width/linetype,
+// etc. If the bounding box containing the point doesn't intersect
+// with the current view, the point isn't drawn.
+//
+// Input point is in the Xastir coordinate system.
+//
+void draw_point(Widget w,
+ unsigned long x1,
+ unsigned long y1,
+ GC gc,
+ Pixmap which_pixmap,
+ int skip_duplicates) {
+
+ int x1i, y1i;
+ static int last_x1i;
+ static int last_y1i;
+
+
+ // Check whether the two bounding boxes intersect. If not, skip
+ // the rest of this function. Do we need to worry about
+ // special-case code here to handle vertical/horizontal lines
+ // (width or length of zero)?
+ //
+//
+// WE7U
+// Check to see if we can do this faster than map_visible() can. A
+// point is a special case that should take only four compares
+// against the map window boundaries.
+//
+ if (!map_visible(y1, y1, x1, x1)) {
+ // Skip this vector
+ //fprintf(stderr,"Point not visible\n");
+ return;
+ }
+
+ // Convert to screen coordinates. Careful here!
+ // The format conversions you'll need if you try to
+ // compress this into two lines will get you into
+ // trouble.
+ x1i = x1 - NW_corner_longitude;
+ x1i = x1i / scale_x;
+
+ y1i = y1 - NW_corner_latitude;
+ y1i = y1i / scale_y;
+
+ if (skip_duplicates) {
+ if (x1i == last_x1i && y1i == last_y1i) {
+ return;
+ }
+ }
+
+ // XDrawPoint uses 16-bit unsigned integers
+ // (shorts). Make sure we stay within the limits.
+ (void)XDrawPoint(XtDisplay(w),
+ which_pixmap,
+ gc,
+ l16(x1i),
+ l16(y1i));
+
+ last_x1i = x1i;
+ last_y1i = y1i;
+}
+
+
+
+
+
+// Draws a vector onto a pixmap. Assumes that the proper GC has
+// already been set up for drawing the correct color/width/linetype,
+// etc.
+//
+// Input points are in lat/long coordinates.
+//
+void draw_point_ll(Widget w,
+ float y1, // lat1
+ float x1, // long1
+ GC gc,
+ Pixmap which_pixmap,
+ int skip_duplicates) {
+
+ unsigned long x1L, y1L;
+
+//
+// WE7U
+// We should probably do four floating point compares against the
+// map boundaries here in order to speed up rejection of points that
+// don't fit our window. If we change to that, copy the conversion-
+// to-screen-coordinates and drawing stuff from draw_point() down to
+// this routine so that we don't go through the comparisons again
+// there.
+//
+ // Convert the point to the Xastir coordinate system.
+ convert_to_xastir_coordinates(&x1L,
+ &y1L,
+ x1,
+ y1);
+
+ // Call the draw routine above.
+ draw_point(w, x1L, y1L, gc, which_pixmap, skip_duplicates);
+}
+
+
+
+
+
+// Draws a vector onto a pixmap. Assumes that the proper GC has
+// already been set up for drawing the correct color/width/linetype,
+// etc. If the bounding box containing the vector doesn't intersect
+// with the current view, the line isn't drawn.
+//
+// Input points are in the Xastir coordinate system.
+//
+void draw_vector(Widget w,
+ unsigned long x1,
+ unsigned long y1,
+ unsigned long x2,
+ unsigned long y2,
+ GC gc,
+ Pixmap which_pixmap,
+ int skip_duplicates) {
+
+ int x1i, x2i, y1i, y2i;
+ static int last_x1i, last_x2i, last_y1i, last_y2i;
+
+
+ //fprintf(stderr,"%ld,%ld %ld,%ld\t",x1,y1,x2,y2);
+ if ( !clip2d_long(&x1, &y1, &x2, &y2) ) {
+ // Skip this vector
+ //fprintf(stderr,"Line not visible\n");
+ //fprintf(stderr,"%ld,%ld %ld,%ld\n",x1,y1,x2,y2);
+ return;
+ }
+ //fprintf(stderr,"%ld,%ld %ld,%ld\n",x1,y1,x2,y2);
+
+ // Convert to screen coordinates. Careful here!
+ // The format conversions you'll need if you try to
+ // compress this into two lines will get you into
+ // trouble.
+ x1i = x1 - NW_corner_longitude;
+ x1i = x1i / scale_x;
+
+ y1i = y1 - NW_corner_latitude;
+ y1i = y1i / scale_y;
+
+ x2i = x2 - NW_corner_longitude;
+ x2i = x2i / scale_x;
+
+ y2i = y2 - NW_corner_latitude;
+ y2i = y2i / scale_y;
+
+ if (skip_duplicates) {
+ if (last_x1i == x1i
+ && last_x2i == x2i
+ && last_y1i == y1i
+ && last_y2i == y2i) {
+ return;
+ }
+ }
+
+ // XDrawLine uses 16-bit unsigned integers
+ // (shorts). Make sure we stay within the limits.
+ // clip2d_long() should make sure of this anyway as it clips
+ // lines to fit the window.
+ //
+ (void)XDrawLine(XtDisplay(w),
+ which_pixmap,
+ gc,
+ l16(x1i),
+ l16(y1i),
+ l16(x2i),
+ l16(y2i));
+
+ last_x1i = x1i;
+ last_x2i = x2i;
+ last_y1i = y1i;
+ last_y2i = y2i;
+}
+
+
+
+
+
+// Draws a vector onto a pixmap. Assumes that the proper GC has
+// already been set up for drawing the correct color/width/linetype,
+// etc.
+//
+// Input points are in lat/long coordinates.
+//
+void draw_vector_ll(Widget w,
+ float y1, // lat1
+ float x1, // long1
+ float y2, // lat2
+ float x2, // long2
+ GC gc,
+ Pixmap which_pixmap,
+ int skip_duplicates) {
+
+ unsigned long x1L, x2L, y1L, y2L;
+ int x1i, x2i, y1i, y2i;
+ static int last_x1i, last_x2i, last_y1i, last_y2i;
+
+
+ //fprintf(stderr,"%lf,%lf %lf,%lf\t",x1,y1,x2,y2);
+ if ( !clip2d(&x1, &y1, &x2, &y2) ) {
+ // Skip this vector
+//fprintf(stderr,"Line not visible: %lf,%lf %lf,%lf\n",y1,x1,y2,x2);
+ return;
+ }
+//fprintf(stderr,"%lf,%lf %lf,%lf\n",x1,y1,x2,y2);
+
+ // Convert the points to the Xastir coordinate system.
+ convert_to_xastir_coordinates(&x1L,
+ &y1L,
+ x1,
+ y1);
+
+ convert_to_xastir_coordinates(&x2L,
+ &y2L,
+ x2,
+ y2);
+
+//fprintf(stderr,"%ld,%ld %ld,%ld\n",x1L,y1L,x2L,y2L);
+
+ // Convert to screen coordinates. Careful here!
+ // The format conversions you'll need if you try to
+ // compress this into two lines will get you into
+ // trouble.
+ x1i = (int)(x1L - NW_corner_longitude);
+ x1i = x1i / scale_x;
+
+ y1i = (int)(y1L - NW_corner_latitude);
+ y1i = y1i / scale_y;
+
+ x2i = (int)(x2L - NW_corner_longitude);
+ x2i = x2i / scale_x;
+
+ y2i = (int)(y2L - NW_corner_latitude);
+ y2i = y2i / scale_y;
+
+ if (skip_duplicates) {
+ if (last_x1i == x1i
+ && last_x2i == x2i
+ && last_y1i == y1i
+ && last_y2i == y2i) {
+// fprintf(stderr,"Duplicate line\n");
+ return;
+ }
+ }
+//fprintf(stderr,"NW_corner_latitude:%ld, NW_corner_longitude:%ld, scale_x:%ld, scale_y:%ld\n",
+// NW_corner_latitude,
+// NW_corner_longitude,
+// scale_x,
+// scale_y);
+
+//fprintf(stderr,"%d,%d %d,%d\n\n",x1i,y1i,x2i,y2i);
+
+ // XDrawLine uses 16-bit unsigned integers
+ // (shorts). Make sure we stay within the limits.
+ // clip2d() should make sure of this anyway as it clips lines to
+ // fit the window.
+ //
+ (void)XDrawLine(XtDisplay(w),
+ which_pixmap,
+ gc,
+ l16(x1i),
+ l16(y1i),
+ l16(x2i),
+ l16(y2i));
+
+ last_x1i = x1i;
+ last_x2i = x2i;
+ last_y1i = y1i;
+ last_y2i = y2i;
+}
+
+
+
+
+
+// Find length of a standard string of seven zeroes in the border font.
+// Supporting function for draw_grid() and the grid drawing functions.
+int get_standard_border_string_width_pixels(Widget w, int length) {
+ int string_width_pixels = 0; // Width of the unrotated seven_zeroes label string in pixels.
+ char seven_zeroes[8] = "0000000";
+ char five_zeroes[6] = "00000";
+
+ if (length==5)
+ string_width_pixels = get_rotated_label_text_length_pixels(w, five_zeroes, FONT_BORDER);
+
+ string_width_pixels = get_rotated_label_text_length_pixels(w, seven_zeroes, FONT_BORDER);
+ return string_width_pixels;
+}
+
+
+
+
+
+// Find height of a standard string in the border font
+// Supporting function for draw_grid() and the grid drawing functions.
+int get_standard_border_string_height_pixels(Widget w) {
+ int string_width_pixels = 0; // Width of the unrotated seven_zeroes label string in pixels.
+ char one_zero[2] = "0";
+
+ string_width_pixels = get_rotated_label_text_height_pixels(w, one_zero, FONT_BORDER);
+ return string_width_pixels;
+}
+
+
+
+
+
+// Find out the width to use for the border to apply when uing a labeled grid.
+// Border width is determined from the height of the border font.
+// Supporting function for draw_grid() and the grid drawing functions.
+int get_border_width(Widget w) {
+ int border_width = 14; // The width of the border to draw around the
+ // map to place labeled tick marks into
+ // should be an even number.
+ // The default here is overidden by size of the border font.
+ int string_height_pixels = 0; // Height of a string in the border font in pixels
+
+ string_height_pixels = get_standard_border_string_height_pixels(w);
+ // Rotated text functions used to draw the border text add some
+ // blank space at the bottom of the text so make the border wide enough
+ // to compensate for this.
+ border_width = string_height_pixels + (string_height_pixels/2) + 1;
+ // check to see if string_height_pixels is even
+ if ((float)string_height_pixels/2.0!=floor((float)string_height_pixels/2.0)) {
+ border_width++;
+ }
+ // we are using draw nice string to write the metadata in the top border, so
+ // make sure the border is wide enough for it, even if the grid labels are small.
+ if (border_width < 14) { border_width = 14; }
+ return border_width;
+}
+
+
+
+
+
+// ***********************************************************
+//
+// get_horizontal_datum()
+//
+// Provides the current map datum. Current default is WGS84.
+// Parameters: datum, character array ponter for the string
+// that will be filled with the current datum
+// sizeof_datum, the size of the datum character array.
+//
+//***********************************************************
+void get_horizontal_datum(char *datum, int sizeof_datum) {
+ char metadata_datum[6] = "WGS84"; // datum to display in metadata on top border
+ xastir_snprintf(datum, sizeof_datum, "%s", metadata_datum);
+ if (sizeof_datum<6)
+ fprintf(stderr,"Datum [%s] truncated to [%s]\n",metadata_datum,datum);
+}
+
+
+
+
+
+// Lat/Long coordinate system, draw lat/long lines. Called by
+// draw_grid() below.
+//
+void draw_complete_lat_lon_grid(Widget w) {
+
+ int coord;
+ char dash[2];
+ unsigned int x,x1,x2;
+ unsigned int y,y1,y2;
+ unsigned int stepsx; // spacing of grid lines
+ unsigned int stepsy; // spacing of grid lines
+ int coordinate_format; // Format to use for coordinates on border (e.g. decimal degrees).
+ char grid_label[25]; // String to draw labels on grid lines
+ int screen_width_xastir; // screen width in xastir units (1/100 of a second)
+ int screen_height_xastir; // screen height in xastir units (1/100 of a second)
+ int border_width; // the width of the labeled border in pixels.
+ int string_width_pixels = 0;// Width of a grid label string in pixels.
+ float screen_width_degrees; // Width of the screen in degrees
+ int log_screen_width_degrees; // Log10 of the screen width in degrees, used to scale degrees
+ long xx2, yy2;
+ long xx, yy;
+ unsigned int last_label_end; // cordinate of the end of the previous label
+ char metadata_datum[6]; // datum to display in metadata on top border
+ char grid_label1[25]; // String to draw latlong metadata
+ char grid_label2[25]; // String to draw latlong metadata
+ char top_label[180]; // String to draw metadata on top border
+
+ if (!long_lat_grid) // We don't wish to draw a map grid
+ return;
+
+ // convert between selected coordinate format constant and display format constants
+ if (coordinate_system == USE_DDDDDD) {
+ coordinate_format = CONVERT_DEC_DEG;
+ }
+ else if (coordinate_system == USE_DDMMSS) {
+ coordinate_format = CONVERT_DMS_NORMAL_FORMATED;
+ }
+ else {
+ coordinate_format = CONVERT_HP_NORMAL_FORMATED;
+ }
+ border_width = get_border_width(w);
+ // Find xastir coordinates of upper left and lower right corners.
+ xx = NW_corner_longitude + (border_width * scale_x);
+ yy = NW_corner_latitude + (border_width * scale_y);
+ xx2 = NW_corner_longitude + ((screen_width - border_width) * scale_x);
+ yy2 = NW_corner_latitude + ((screen_height - border_width) * scale_y);
+ screen_width_xastir = xx2 - xx;
+ screen_height_xastir = yy2 - yy;
+ // Determine some parameters used in drawing the border.
+ string_width_pixels = get_standard_border_string_width_pixels(w, 7);
+ // 1 xastir coordinate = 1/100 of a second
+ // 100*60*60 xastir coordinates (=360000 xastir coordinates) = 1 degree
+ // 64800000 xastir coordinates = 180 degrees
+ // 360000 xastir coordinates = 1 degree
+ // scale_x * (screen_width/10) = one tenth of the screen width in xastir coordinates
+ // scale_x number of xastir coordinates per pixel
+ screen_width_degrees = (float)(screen_width_xastir / (float)360000);
+ log_screen_width_degrees = (int)log10(screen_width_degrees);
+
+
+ if (draw_labeled_grid_border==TRUE) {
+ get_horizontal_datum(metadata_datum, sizeof(metadata_datum));
+
+ // Put metadata in top border.
+ // find location of upper left corner of map, convert to Lat/Long
+ convert_lon_l2s(xx, grid_label1, sizeof(grid_label1), coordinate_format);
+ convert_lat_l2s(yy, grid_label2, sizeof(grid_label2), coordinate_format);
+ xastir_snprintf(grid_label,
+ sizeof(grid_label),
+ "%s %s",
+ grid_label1,grid_label2);
+ // find location of lower right corner of map, convert to Lat/Long
+ convert_lon_l2s(xx2, grid_label1, sizeof(grid_label1), coordinate_format);
+ convert_lat_l2s(yy2, grid_label2, sizeof(grid_label2), coordinate_format);
+ //"XASTIR Map of %s (upper left) to %s %s (lower right). Lat/Long grid, %s datum. ",
+ xastir_snprintf(top_label,
+ sizeof(top_label),
+ langcode("MDATA002"),
+ grid_label,grid_label1,grid_label2,metadata_datum);
+ draw_rotated_label_text_to_target (w, 270,
+ border_width+2,
+ border_width-1,
+ sizeof(top_label),colors[0x10],top_label,FONT_BORDER,
+ pixmap_final,
+ outline_border_labels, colors[outline_border_labels_color]);
+ }
+
+ // A crude grid spacing can be obtained from scaling one tenth of the screen width.
+ // This works, but puts the grid lines at arbitrary increments of a degree.
+ //stepsx = (scale_x*(screen_width/10));
+
+ // Setting the grid using the base 10 log of the screen width in degrees allows
+ // both scaling the grid to the screen and spacing the grid lines at appropriately
+ // rounded increments of a degree.
+ //
+ // Set default grid to 0.1 degree. This will be used when the screen width is about 1 degree.
+ stepsx = 36000; // if (log_screen_width_degrees == 0)
+ // Work out an appropriate grid spacing for the screen size and coordinate system.
+ if (log_screen_width_degrees > 0) {
+ // grid spacing is rounded to 10 degree increment.
+ stepsx = ((int)(screen_width_degrees / (pow(10,log_screen_width_degrees)))*pow(10,log_screen_width_degrees)) * 36000;
+ }
+ if (log_screen_width_degrees < 0) {
+ // Grid spacing is rounded to less than one degree.
+ if (coordinate_system == USE_DDDDDD) {
+ // Round to tenths or hundrethds or thousanths of a degree.
+ stepsx = ((float)(int)(((float)screen_width_degrees / pow(10,log_screen_width_degrees)*10.0)))*pow(10,log_screen_width_degrees) * 3600;
+ }
+ else {
+ // For decimal minutes or minutes and seconds.
+ // Find screen width and log screen width in minutes.
+ screen_width_degrees = screen_width_degrees * 60.0;
+ log_screen_width_degrees = (int)log10(screen_width_degrees);
+ // round to minutes or tenths of minutes.
+ stepsx = ((float)(int)
+ ((float)(screen_width_degrees) / pow(10,log_screen_width_degrees) * 10.0)
+ )
+ * pow(10,log_screen_width_degrees) * 3600;
+ if (log_screen_width_degrees==0) {
+ stepsx = 600; // 6000 = 1 minute
+ }
+ }
+ }
+ // Grid should now be close to reasonable spacing for screen size, but
+ // may need to be tuned.
+ // Test for too tightly or too coarsely spaced grid.
+ if (stepsx<(unsigned int)(scale_x * string_width_pixels * 1.5)) {
+ stepsx = stepsx * 2.0;
+ }
+ if (stepsx<(unsigned int)(scale_x * string_width_pixels * 1.5)) {
+ stepsx = stepsx * 2.0;
+ }
+ if (stepsx>(unsigned int)((scale_x * screen_width)/3.5)) {
+ stepsx = stepsx / 2.0;
+ }
+ // Handle special case of very small screen - only draw a single grid line
+ if (screen_width < (string_width_pixels * 2)) {
+ stepsx = (scale_x*(screen_width/2));
+ }
+ // Make sure we don't pass an erronous stepsx of 0 on.
+ if (stepsx==0)
+ stepsx=36000;
+
+ // Use the same grid spacing for both latitude and longitude grids.
+ // We could use a scaling factor related to the screen height width ratio here.
+ stepsy = stepsx;
+
+ // protect against division by zero
+ if (scale_x==0) scale_x = 1;
+ if (scale_y==0) scale_y = 1;
+
+ // Now draw and label the grid.
+ // Draw vertical longitude lines
+ if (NW_corner_latitude >= 0)
+ y1 = 0;
+ else
+ y1 = -NW_corner_latitude/scale_y;
+
+ y2 = (180*60*60*100-NW_corner_latitude)/scale_y;
+
+ if (y2 > (unsigned int)screen_height)
+ y2 = screen_height-1;
+
+ coord = NW_corner_longitude+stepsx-(NW_corner_longitude%stepsx);
+ if (coord < 0)
+ coord = 0;
+
+ last_label_end = 0;
+ for (; coord < SE_corner_longitude && coord <= 360*60*60*100; coord += stepsx) {
+
+ x = (coord-NW_corner_longitude)/scale_x;
+
+ if ((coord%(648000*100)) == 0) {
+ (void)XSetLineAttributes (XtDisplay (w),
+ gc_tint,
+ 1,
+ LineSolid,
+ CapButt,
+ JoinMiter);
+ (void)XDrawLine (XtDisplay (w),
+ pixmap_final,
+ gc_tint,
+ l16(x),
+ l16(y1),
+ l16(x),
+ l16(y2));
+ (void)XSetLineAttributes (XtDisplay (w),
+ gc_tint,
+ 1,
+ LineOnOffDash,
+ CapButt,
+ JoinMiter);
+ continue; // Go to next iteration of for loop
+ }
+ else if ((coord%(72000*100)) == 0) {
+ dash[0] = dash[1] = 8;
+ (void)XSetDashes (XtDisplay (w), gc_tint, 0, dash, 2);
+ }
+ else if ((coord%(7200*100)) == 0) {
+ dash[0] = dash[1] = 4;
+ (void)XSetDashes (XtDisplay (w), gc_tint, 0, dash, 2);
+ }
+ else if ((coord%(300*100)) == 0) {
+ dash[0] = dash[1] = 2;
+ (void)XSetDashes (XtDisplay (w), gc_tint, 0, dash, 2);
+ }
+
+ (void)XDrawLine (XtDisplay (w),
+ pixmap_final,
+ gc_tint,
+ l16(x),
+ l16(y1),
+ l16(x),
+ l16(y2));
+
+ if (draw_labeled_grid_border==TRUE) {
+ // Label the longitudes in lower border.
+ convert_lon_l2s(coord, grid_label, sizeof(grid_label), coordinate_format);
+ if (log_screen_width_degrees > 0 && strlen(grid_label) > 5) {
+ // truncate the grid_label string
+ if (coordinate_system==USE_DDMMMM) {
+ // Add ' and move EW and null characters forward.
+ grid_label[strlen(grid_label)-5] = '\'';
+ grid_label[strlen(grid_label)-4] = grid_label[strlen(grid_label)-1];
+ grid_label[strlen(grid_label)-3] = grid_label[strlen(grid_label)];
+ }
+ else {
+ // Move EW and null characters forward.
+ grid_label[strlen(grid_label)-5] = grid_label[strlen(grid_label)-1];
+ grid_label[strlen(grid_label)-4] = grid_label[strlen(grid_label)];
+ }
+ }
+ string_width_pixels = get_rotated_label_text_length_pixels(w, grid_label, FONT_BORDER);
+ // test for overlap of label with previously printed label
+ if (x > last_label_end + 3 && x < (unsigned int)(screen_width - string_width_pixels)) {
+ draw_rotated_label_text_to_target (w, 270,
+ x,
+ screen_height,
+ sizeof(grid_label),colors[0x09],grid_label,FONT_BORDER,
+ pixmap_final,
+ outline_border_labels, colors[outline_border_labels_color]);
+ last_label_end = x + string_width_pixels;
+ }
+ }
+ }
+
+ // Draw horizontal latitude lines.
+ last_label_end = 0;
+ if (NW_corner_longitude >= 0)
+ x1 = 0;
+ else
+ x1 = -NW_corner_longitude/scale_x;
+
+ x2 = (360*60*60*100-NW_corner_longitude)/scale_x;
+ if (x2 > (unsigned int)screen_width)
+ x2 = screen_width-1;
+
+ coord = NW_corner_latitude+stepsy-(NW_corner_latitude%stepsy);
+ if (coord < 0)
+ coord = 0;
+
+ for (; coord < SE_corner_latitude && coord <= 180*60*60*100; coord += stepsy) {
+
+ y = (coord-NW_corner_latitude)/scale_y;
+
+ if ((coord%(324000*100)) == 0) {
+ (void)XSetLineAttributes (XtDisplay (w),
+ gc_tint,
+ 1,
+ LineSolid,
+ CapButt,
+ JoinMiter);
+ (void)XDrawLine (XtDisplay (w),
+ pixmap_final,
+ gc_tint,
+ l16(x1),
+ l16(y),
+ l16(x2),
+ l16(y));
+ (void)XSetLineAttributes (XtDisplay (w),
+ gc_tint,
+ 1,
+ LineOnOffDash,
+ CapButt,
+ JoinMiter);
+ continue; // Go to next iteration of for loop
+ }
+ else if ((coord%(36000*100)) == 0) {
+ dash[0] = dash[1] = 8;
+ (void)XSetDashes (XtDisplay (w), gc_tint, 4, dash, 2);
+ }
+ else if ((coord%(3600*100)) == 0) {
+ dash[0] = dash[1] = 4;
+ (void)XSetDashes (XtDisplay (w), gc_tint, 2, dash, 2);
+ }
+ else if ((coord%(150*100)) == 0) {
+ dash[0] = dash[1] = 2;
+ (void)XSetDashes (XtDisplay (w), gc_tint, 1, dash, 2);
+ }
+
+ (void)XDrawLine (XtDisplay (w),
+ pixmap_final,
+ gc_tint,
+ l16(x1),
+ l16(y),
+ l16(x2),
+ l16(y));
+
+ if (draw_labeled_grid_border==TRUE) {
+ // label the latitudes on left and right borders
+ // (unlike UTM where easting before northing order is important)
+ convert_lat_l2s(coord, grid_label, sizeof(grid_label), coordinate_format);
+ if (log_screen_width_degrees > 0 && strlen(grid_label) > 5) {
+ // truncate the grid_label string
+ if (coordinate_system==USE_DDMMMM) {
+ // Add ' and move EW and null characters forward.
+ grid_label[strlen(grid_label)-5] = '\'';
+ grid_label[strlen(grid_label)-4] = grid_label[strlen(grid_label)-1];
+ grid_label[strlen(grid_label)-3] = grid_label[strlen(grid_label)];
+ }
+ else {
+ // Move EW and null characters forward.
+ grid_label[strlen(grid_label)-5] = grid_label[strlen(grid_label)-1];
+ grid_label[strlen(grid_label)-4] = grid_label[strlen(grid_label)];
+ }
+ }
+ string_width_pixels = get_rotated_label_text_length_pixels(w, grid_label, FONT_BORDER);
+ // check to make sure we aren't overwriting the previous label text
+ if ((y > last_label_end+3) && (y > (unsigned int)string_width_pixels)) {
+ draw_rotated_label_text_to_target (w, 180,
+ screen_width,
+ y,
+ sizeof(grid_label),colors[0x09],grid_label,FONT_BORDER,
+ pixmap_final,
+ outline_border_labels, colors[outline_border_labels_color]);
+ draw_rotated_label_text_to_target (w, 180,
+ border_width,
+ y,
+ sizeof(grid_label),colors[0x09],grid_label,FONT_BORDER,
+ pixmap_final,
+ outline_border_labels, colors[outline_border_labels_color]);
+ last_label_end = y + string_width_pixels;
+ }
+ }
+ }
+} // End of draw_complete_lat_lon_grid()
+
+
+
+
+
+// Draw the major zones for UTM and MGRS. Called by draw_grid()
+// below.
+//
+// These are based off 6-degree lat/long lines, with a few irregular
+// zones that have to be special-cased. This part of the code
+// handles the irregular zones in SW Norway (31V/32V) and the
+// regions near Svalbard (31X/33X/35X/37X) just fine.
+
+// These are based off the central meridian running up the middle of
+// each zone (3 degrees from either side of the standard six-degree
+// zones). Even the irregular zones key off the same medians. UTM
+// grids are defined in terms of meters instead of lat/long, so they
+// don't line up with the left/right edges of the zones or with the
+// longitude lines.
+//
+// According to Peter Dana (Geographer's Craft web pages), even when
+// the major grid boundaries have been shifted, the meridian used
+// for drawing the subgrids is still based on six-degree boundaries
+// (as if the major grid hadn't been shifted at all). That means we
+// are drawing the subgrids correctly as it stands now for the
+// irregular grids (31V/32V/31X/33X/35X/37X). The irregular zones
+// have sizes of 3/9/12 degrees (width) instead of 6 degrees.
+//
+// UTM NOTES: 84 degrees North to 80 degrees South. 60 zones, each
+// covering six (6) degrees of longitude. Each zone extends three
+// degrees eastward and three degrees westward from its central
+// meridian. Zones are numbered consecutively west to east from the
+// 180 degree meridian. From 84 degrees North and 80 degrees South
+// to the respective poles, the Universal Polar Stereographic (UPS)
+// is used.
+//
+// For MGRS and UTM-Special grid only:
+// UTM Zone 32 has been widened to 9� (at the expense of zone 31)
+// between latitudes 56� and 64� (band V) to accommodate southwest
+// Norway. Thus zone 32 extends westwards to 3�E in the North Sea.
+// Similarly, between 72� and 84� (band X), zones 33 and 35 have
+// been widened to 12� to accommodate Svalbard. To compensate for
+// these 12� wide zones, zones 31 and 37 are widened to 9� and zones
+// 32, 34, and 36 are eliminated. Thus the W and E boundaries of
+// zones are 31: 0 - 9 E, 33: 9 - 21 E, 35: 21 - 33 E and 37: 33 -
+// 42 E.
+//
+// UTM is depending on the ellipsoid and the datum used. For our
+// purposes, we're always using WGS84 ellipsoid and datum, so it's a
+// non-issue.
+//
+// Horizontal bands corresponding to the NATO UTM/UPS lettering:
+// Zones go from A (south pole) to Z (north pole). South of -80 are
+// zones A/B, north of +84 are zones Y/Z. "I" and "O" are not used.
+// Zones from C to W are 8 degrees high. Zone X is 12 degrees high.
+//
+// We need these NATO letters or a N/S designator in order to
+// specify which hemisphere the UTM coordinates are in. Often, the
+// same coordinates can appear in either hemisphere. Some computer
+// software uses +/- to designate northings instead of N/S or the
+// NATO lettered bands.
+//
+// UPS system is used at the poles instead of UTM. UPS uses a false
+// northing and easting of 2,000,000 meters.
+//
+// An arbitrary false northing of 10,000,000 at the equator is used
+// for southern latitudes only. Northern latitudes assume the
+// equator northing is at zero. An arbitrary false easting of
+// 500,000 is along the meridian of each zone (3 degrees from each
+// side). The lettered grid lines are necessary due to some
+// coordinates being valid in both the northern and the southern
+// hemisphere.
+//
+// Y/Z 84N to 90N (UPS System) false N/E = 2,000,000
+// X 72N to 84N (12 degrees latitude, equator=0)
+// W 64N to 72N ( 8 degrees latitude, equator=0)
+// V 56N to 64N ( 8 degrees latitude, equator=0)
+// U 48N to 56N ( 8 degrees latitude, equator=0)
+// T 40N to 48N ( 8 degrees latitude, equator=0)
+// S 32N to 40N ( 8 degrees latitude, equator=0)
+// R 24N to 32N ( 8 degrees latitude, equator=0)
+// Q 16N to 24N ( 8 degrees latitude, equator=0)
+// P 8N to 16N ( 8 degrees latitude, equator=0)
+// N 0N to 8N ( 8 degrees latitude, equator=0)
+// M 0S to 8S ( 8 degrees latitude, equator=10,000,000)
+// L 8S to 16S ( 8 degrees latitude, equator=10,000,000)
+// K 16S to 24S ( 8 degrees latitude, equator=10,000,000)
+// J 24S to 32S ( 8 degrees latitude, equator=10,000,000)
+// H 32S to 40S ( 8 degrees latitude, equator=10,000,000)
+// G 40S to 48S ( 8 degrees latitude, equator=10,000,000)
+// F 48S to 56S ( 8 degrees latitude, equator=10,000,000)
+// E 56S to 64S ( 8 degrees latitude, equator=10,000,000)
+// D 64S to 72S ( 8 degrees latitude, equator=10,000,000)
+// C 72S to 80S ( 8 degrees latitude, equator=10,000,000)
+// A/B 80S to 90S (UPS System) false N/E = 2,000,000
+//
+void draw_major_utm_mgrs_grid(Widget w) {
+ int ii;
+
+// need to move metadata to its own function and put it up after grids have been drawn.
+//*******
+ // variables for metadata in grid border
+ long xx2, yy2; // coordinates of screen corners used for metadata
+ int border_width; // Width of the border to draw labels into.
+ double easting, northing; // Values used in border metadata.
+ int x, y; // Screen coordinates for border labels.
+ char zone_str[10];
+ char zone_str2[10];
+ char metadata_datum[6];
+ char grid_label[25]; // String to draw labels on grid lines
+ char grid_label1[25]; // String to draw latlong metadata
+ char top_label[180]; // String to draw metadata on top border
+
+ // variables to support components of MGRS strings in the metadata
+ char mgrs_zone[4] = " "; // MGRS zone letter
+ char mgrs_eastingL[3] = " ";
+ char mgrs_northingL[3] = " ";
+ unsigned int int_utmEasting;
+ unsigned int int_utmNorthing;
+ char mgrs_space_string[4] = " ";
+ int mgrs_single_digraph = FALSE; // mgrs_ul_digraph and mgrs_ur_digraph are the same.
+ char mgrs_ul_digraph[3] = " "; // MGRS digraph for upper left corner of screen
+ char mgrs_lr_digraph[3] = " "; // MGRS digraph for lower right corner of screen
+
+
+//fprintf(stderr,"draw_major_utm_mgrs_grid start\n");
+
+ if (!long_lat_grid) // We don't wish to draw a map grid
+ return;
+
+ // Vertical lines:
+
+ // Draw the vertical vectors (except for the irregular regions
+ // and the prime meridian). The polar areas only have two zones
+ // each, so we don't want to draw through those areas.
+
+ for (ii = -180; ii < 0; ii += 6) {
+ draw_vector_ll(w, -80.0, (float)ii, 84.0, (float)ii, gc_tint, pixmap_final, 0);
+ }
+ for (ii = 42; ii <= 180; ii += 6) {
+ draw_vector_ll(w, -80.0, (float)ii, 84.0, (float)ii, gc_tint, pixmap_final, 0);
+ }
+
+ // Draw the short vertical vectors in the polar regions
+ draw_vector_ll(w, -90.0, -180.0, -80.0, -180.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, -90.0, 180.0, -80.0, 180.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, 84.0, -180.0, 90.0, -180.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, 84.0, 180.0, 90.0, 180.0, gc_tint, pixmap_final, 0);
+
+ if (coordinate_system == USE_UTM_SPECIAL
+ || coordinate_system == USE_MGRS) {
+ // For MGRS, we need to draw irregular zones in certain
+ // areas.
+
+ // Draw the partial vectors from 80S to the irregular region
+ draw_vector_ll(w, -80.0, 6.0, 56.0, 6.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, -80.0, 12.0, 72.0, 12.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, -80.0, 18.0, 72.0, 18.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, -80.0, 24.0, 72.0, 24.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, -80.0, 30.0, 72.0, 30.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, -80.0, 36.0, 72.0, 36.0, gc_tint, pixmap_final, 0);
+
+ // Draw the short vertical vectors in the irregular region
+ draw_vector_ll(w, 56.0, 3.0, 64.0, 3.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, 64.0, 6.0, 72.0, 6.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, 72.0, 9.0, 84.0, 9.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, 72.0, 21.0, 84.0, 21.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, 72.0, 33.0, 84.0, 33.0, gc_tint, pixmap_final, 0);
+
+ // Draw the short vertical vectors above the irregular region
+ draw_vector_ll(w, 84.0, 6.0, 84.0, 6.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, 84.0, 12.0, 84.0, 12.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, 84.0, 18.0, 84.0, 18.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, 84.0, 24.0, 84.0, 24.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, 84.0, 30.0, 84.0, 30.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, 84.0, 36.0, 84.0, 36.0, gc_tint, pixmap_final, 0);
+ }
+ else {
+ // Draw normal zone boundaries used for civilian UTM
+ // grid.
+ for (ii = 6; ii < 42; ii += 6) {
+ draw_vector_ll(w, -80.0, (float)ii, 84.0, (float)ii, gc_tint, pixmap_final, 0);
+ }
+ }
+
+
+ // Horizontal lines:
+
+ // Draw the 8 degree spaced lines, except for the equator
+ for (ii = -80; ii < 0; ii += 8) {
+ draw_vector_ll(w, (float)ii, -180.0, (float)ii, 180.0, gc_tint, pixmap_final, 0);
+ }
+ // Draw the 8 degree spaced lines
+ for (ii = 8; ii <= 72; ii += 8) {
+ draw_vector_ll(w, (float)ii, -180.0, (float)ii, 180.0, gc_tint, pixmap_final, 0);
+ }
+
+ // Draw the one 12 degree spaced line
+ draw_vector_ll(w, 84.0, -180.0, 84.0, 180.0, gc_tint, pixmap_final, 0);
+
+ // Draw the pole lines
+ draw_vector_ll(w, -90.0, -180.0, -90.0, 180.0, gc_tint, pixmap_final, 0);
+ draw_vector_ll(w, 90.0, -180.0, 90.0, 180.0, gc_tint, pixmap_final, 0);
+
+ // Set to solid line for the equator. Make it extra wide as
+ // well.
+ (void)XSetLineAttributes (XtDisplay (w), gc_tint, 3, LineSolid, CapButt,JoinMiter);
+
+ // Draw the equator as a solid line
+ draw_vector_ll(w, 0.0, -180.0, 0.0, 180.0, gc_tint, pixmap_final, 0);
+
+ (void)XSetLineAttributes (XtDisplay (w), gc_tint, 2, LineSolid, CapButt,JoinMiter);
+
+ // Draw the prime meridian in the same manner
+ draw_vector_ll(w, -80.0, 0.0, 84.0, 0.0, gc_tint, pixmap_final, 0);
+
+ // add metadata and labels
+ if (draw_labeled_grid_border==TRUE && scale_x > 3000) {
+ // Determine the width of the border
+ border_width = get_border_width(w);
+ // Find out what the map datum is.
+ get_horizontal_datum(metadata_datum, sizeof(metadata_datum));
+
+ // Put metadata in top border.
+ // find location of upper left corner of map, convert to UTM
+ xx2 = NW_corner_longitude + (border_width * scale_x);
+ yy2 = NW_corner_latitude + (border_width * scale_y);
+ convert_xastir_to_UTM(&easting, &northing, zone_str, sizeof(zone_str),
+ xx2, yy2);
+ if (coordinate_system == USE_MGRS) {
+ convert_xastir_to_MGRS_str_components(mgrs_zone, strlen(mgrs_zone),
+ mgrs_eastingL, sizeof(mgrs_eastingL),
+ mgrs_northingL, sizeof(mgrs_northingL),
+ &int_utmEasting, &int_utmNorthing,
+ xx2, yy2,
+ 0, mgrs_space_string, strlen(mgrs_space_string));
+ xastir_snprintf(mgrs_ul_digraph, sizeof(mgrs_ul_digraph),
+ "%c%c", mgrs_eastingL[0], mgrs_northingL[0]);
+ xastir_snprintf(grid_label,
+ sizeof(grid_label),
+ "%s %s %05.0f %05.0f",
+ mgrs_zone,mgrs_ul_digraph,(float)int_utmEasting,(float)int_utmNorthing);
+ }
+ else {
+ xastir_snprintf(grid_label,
+ sizeof(grid_label),
+ "%s %07.0f %07.0f",
+ zone_str,easting,northing);
+ }
+ // find location of lower right corner of map, convert to UTM
+ xx2 = NW_corner_longitude + ((screen_width - border_width) * scale_x);
+ yy2 = NW_corner_latitude + ((screen_height - border_width) * scale_y);
+ convert_xastir_to_UTM(&easting, &northing, zone_str, sizeof(zone_str),
+ xx2, yy2);
+ if (coordinate_system == USE_MGRS) {
+ convert_xastir_to_MGRS_str_components(mgrs_zone, strlen(mgrs_zone),
+ mgrs_eastingL, sizeof(mgrs_eastingL),
+ mgrs_northingL, sizeof(mgrs_northingL),
+ &int_utmEasting, &int_utmNorthing,
+ xx2, yy2,
+ 0, mgrs_space_string, strlen(mgrs_space_string));
+ xastir_snprintf(mgrs_lr_digraph, sizeof(mgrs_lr_digraph),
+ "%c%c", mgrs_eastingL[0], mgrs_northingL[0]);
+ xastir_snprintf(grid_label1,
+ sizeof(grid_label1),
+ "%s %s %05.0f %05.0f",
+ mgrs_zone,mgrs_lr_digraph,(float)int_utmEasting,(float)int_utmNorthing);
+ if (strcmp(mgrs_lr_digraph,mgrs_ul_digraph)==0) {
+ mgrs_single_digraph = TRUE; // mgrs_ul_digraph and mgrs_ur_digraph are the same.
+ }
+ else {
+ mgrs_single_digraph = FALSE; // mgrs_ul_digraph and mgrs_ur_digraph are the same.
+ }
+ }
+ else {
+ xastir_snprintf(grid_label1,
+ sizeof(grid_label1),
+ "%s %07.0f %07.0f",
+ zone_str,easting,northing);
+ }
+ // Write metadata on upper border of map.
+ //"XASTIR Map of %s (upper left) to %s (lower right). UTM zones, %s datum. ",
+ xastir_snprintf(top_label,
+ sizeof(top_label),
+ langcode("MDATA003"),
+ grid_label,grid_label1,metadata_datum);
+ draw_rotated_label_text_to_target (w, 270,
+ border_width+2,
+ border_width-1,
+ sizeof(top_label),colors[0x10],top_label,FONT_BORDER,
+ pixmap_final,
+ outline_border_labels, colors[outline_border_labels_color]);
+ // Crudely identify zone boundaries by
+ // iterating across bottom border.
+ xastir_snprintf(zone_str2,
+ sizeof(zone_str2),
+ "%s"," ");
+ for (x=1; x<(screen_width - border_width); x++) {
+ xx2 = NW_corner_longitude + (x * scale_x);
+ yy2 = NW_corner_latitude + ((screen_height - border_width) * scale_y);
+ convert_xastir_to_UTM(&easting, &northing, zone_str, sizeof(zone_str),
+ xx2, yy2);
+ zone_str[strlen(zone_str)-1] = '\0';
+ if (strcmp(zone_str,zone_str2) !=0) {
+ draw_rotated_label_text_to_target (w, 270,
+ x + 1,
+ screen_height,
+ sizeof(zone_str),colors[0x10],zone_str,FONT_BORDER,
+ pixmap_final,
+ outline_border_labels, colors[outline_border_labels_color]);
+ }
+ xastir_snprintf(zone_str2,
+ sizeof(zone_str2),
+ "%s",zone_str);
+ }
+ // Crudely identify zone letters by iterating down left border
+ for (y=(border_width*2); y<(screen_height - border_width); y++) {
+ xx2 = NW_corner_longitude + (border_width * scale_x);
+ yy2 = NW_corner_latitude + (y * scale_y);
+ convert_xastir_to_UTM(&easting, &northing, zone_str, sizeof(zone_str),
+ xx2, yy2);
+ zone_str[0] = zone_str[strlen(zone_str)-1];
+ zone_str[1] = '\0';
+ if (strcmp(zone_str,zone_str2) !=0) {
+ draw_rotated_label_text_to_target (w, 270,
+ 1,
+ y,
+ sizeof(zone_str),colors[0x10],zone_str,FONT_BORDER,
+ pixmap_final,
+ outline_border_labels, colors[outline_border_labels_color]);
+ }
+ xastir_snprintf(zone_str2,
+ sizeof(zone_str2),
+ "%s",zone_str);
+ }
+ } // end if draw labeled border
+
+ // Set the line width and style in the GC to 1 pixel wide for
+ // drawing the smaller grid
+ (void)XSetLineAttributes (XtDisplay (w), gc_tint, 1, LineOnOffDash, CapButt,JoinMiter);
+
+//fprintf(stderr,"draw_major_utm_mgrs_grid end\n");
+
+} // End of draw_major_utm_mgrs_grid()
+
+
+
+
+
+// This is the function which actually draws a minor UTM grid.
+// Called by draw_minor_utm_mgrs_grid() function below.
+// draw_minor_utm_mgrs_grid() is the function which calculates the
+// grid points.
+//
+void actually_draw_utm_minor_grid(Widget w) {
+
+
+ int border_width; // Width of the border to draw labels into.
+ int numberofzones = 0; // number of elements in utm_grid.zone[] that are used
+ int Zone;
+ int ii;
+ int easting_color; // Colors for the grid labels
+ int northing_color;
+ int zone_color; // zone label color
+ int label_on_left; // if true, draw northing labels on left
+ long xx, yy, xx2, yy2;
+ char zone_str[10];
+ char zone_str2[10];
+ double easting, northing;
+ int short_width_pixels = 0; // Width of an unrotated string of five_zeroes in the border font in pixels.
+ int string_width_pixels = 0;// Width of an unrotated string of seven_zeroes in the border font in pixels.
+ char metadata_datum[6];
+ char grid_label[25]; // String to draw labels on grid lines
+ char grid_label1[25]; // String to draw latlong metadata
+ char top_label[180]; // String to draw metadata on top border
+ int grid_spacing_pixels; // Spacing of fine grid lines in pixels.
+ int bottom_point; // utm_grid.zone[].col[].npoints can extend past the
+ // bottom of the screen, this is the lowest point in the
+ // points array that is on the screen.
+ int skip_alternate_label; // Skip alternate easting and northing labels
+ // if they would overlap on the
+ // display.
+ int last_line_labeled; // Marks lines that were labeled
+ // when alternate lines are not
+ // being labeled.
+
+ // variables to support components of MGRS strings
+ char mgrs_zone[4] = " "; // MGRS zone letter
+ char mgrs_eastingL[3] = " ";
+ char mgrs_northingL[3] = " ";
+ unsigned int int_utmEasting;
+ unsigned int int_utmNorthing;
+ char mgrs_space_string[4] = " ";
+ int mgrs_single_digraph = FALSE; // mgrs_ul_digraph and mgrs_ur_digraph are the same.
+ char mgrs_ul_digraph[3] = " "; // MGRS digraph for upper left corner of screen
+ char mgrs_lr_digraph[3] = " "; // MGRS digraph for lower right corner of screen
+
+ if (!long_lat_grid) // We don't wish to draw a map grid
+ return;
+
+ // OLD: Draw grid in dashed white lines.
+ // NEW: Tint the lines as they go along, making them appear
+ // no matter what color is underneath.
+ (void)XSetForeground(XtDisplay(w), gc_tint, colors[0x27]);
+
+ // Note: npoints can be negative here! Make sure our code
+ // checks for that. Initially npoints was an unsigned int.
+ // Changed it to an int so that we can get and check for
+ // negative values, bypassing segfaults.
+ //
+ numberofzones = 0;
+
+ // Determine the width of the border
+ border_width = get_border_width(w);
+ // Determine some parameters used in drawing the border.
+ string_width_pixels = get_standard_border_string_width_pixels(w, 7);
+ short_width_pixels = get_standard_border_string_width_pixels(w,5);
+
+ for (Zone=0; Zone < UTM_GRID_MAX_ZONES; Zone++) {
+
+ if (utm_grid.zone[Zone].ncols > 0) {
+ // find out how many zones are actually drawn on the map
+ numberofzones++;
+ }
+ }
+
+ for (Zone=0; Zone < UTM_GRID_MAX_ZONES; Zone++) {
+
+ for (ii=0; ii < (int)utm_grid.zone[Zone].ncols; ii++) {
+ if (utm_grid.zone[Zone].col[ii].npoints > 1) {
+
+ // We need to check for points that are more
+ // than +/- 16383. If we have any, it can cause
+ // X11 to lock up for a while drawing lots of
+ // extra lines, due to bugs in X11. We do that
+ // checking above with xx and yy.
+ //
+ (void)XDrawLines(XtDisplay(w),
+ pixmap_final,
+ gc_tint,
+ utm_grid.zone[Zone].col[ii].points,
+ l16(utm_grid.zone[Zone].col[ii].npoints),
+ CoordModeOrigin);
+ }
+ }
+
+ for (ii=0; ii < (int)utm_grid.zone[Zone].nrows; ii++) {
+ if (utm_grid.zone[Zone].row[ii].npoints > 1) {
+
+ // We need to check for points that are more
+ // than +/- 16383. If we have any, it can cause
+ // X11 to lock up for a while drawing lots of
+ // extra lines, due to bugs in X11. We do that
+ // checking above with xx and yy.
+ //
+ (void)XDrawLines(XtDisplay(w),
+ pixmap_final,
+ gc_tint,
+ utm_grid.zone[Zone].row[ii].points,
+ l16(utm_grid.zone[Zone].row[ii].npoints),
+ CoordModeOrigin);
+ }
+ }
+
+ // Check each of the 4 possible utm_grid.zone array elements
+ // that might contain a grid, and label the grid if it exists.
+ if (utm_grid.zone[Zone].nrows>0 && utm_grid.zone[Zone].ncols>0) {
+ if (draw_labeled_grid_border==TRUE) {
+ // Label the UTM grid on the border.
+ // Since the coordinate of the current mouse pointer position is
+ // continually updated, labeling the grid is primarily for the
+ // purpose of printing maps and saving screenshots.
+ //
+ // ******* Doesn't work properly near poles when 3 zones are on screen
+ // ******* (e.g. 13,14,15) - overlaps northings for 14 and 15.
+ // ******* Doesn't clearly distinguish one zone with 2 lettered rows
+ // ******* (e.g. 18T,18U) needs color distinction between northings
+ // ******* to indicate which northings are in which lettered row.
+ //
+
+ // Default labels for just one zone on screen are black text for
+ // zone at lower left corner, eastings on bottom, and northings
+ // at right.
+ // Idea is to normally start at the lower left corner
+ // users can then easily follow left to right to get easting,
+ // and bottom to top to get northing.
+ // For two zones, second zone uses blue text for eastings and northings.
+ easting_color = 0x08; // black text
+ northing_color = 0x08; // black text
+ zone_color = 0x08; // black text
+ // 0x09=blue (0x0e=yellow works well with outline, but not without).
+ label_on_left = FALSE;
+
+ // Find out what the map datum is.
+ get_horizontal_datum(metadata_datum, sizeof(metadata_datum));
+
+ if (numberofzones>1) {
+ // check to see if the upper left and lower left corners are in the same zone
+ // if not, label the upper left corner
+ xx = (border_width * scale_x) + NW_corner_longitude;
+ yy = ((screen_height - border_width) * scale_y) + NW_corner_latitude;
+ convert_xastir_to_UTM(&easting, &northing, zone_str, sizeof(zone_str), xx, yy);
+ yy = (border_width * scale_y) + NW_corner_latitude;
+ convert_xastir_to_UTM(&easting, &northing, zone_str2, sizeof(zone_str2), xx, yy);
+ if (strcmp(zone_str,zone_str2)!=0) {
+ xastir_snprintf(grid_label,
+ sizeof(grid_label),
+ "%s",
+ zone_str2);
+ //draw_nice_string(w,pixmap_final,0,
+ // border_width+2,
+ // (2*border_width)+2,
+ // grid_label,
+ // 0x10,zone_color,(int)strlen(grid_label));
+ draw_rotated_label_text_to_target (w, 270,
+ border_width+2,
+ (2*border_width)+2,
+ sizeof(grid_label),colors[zone_color],grid_label,FONT_BORDER,
+ pixmap_final,
+ 1, colors[0x0f]);
+ }
+ if (strcmp(zone_str,zone_str2)!=0) {
+ xastir_snprintf(grid_label,
+ sizeof(grid_label),
+ "%s",
+ zone_str);
+ draw_rotated_label_text_to_target (w, 270,
+ border_width+2,
+ screen_height - (2*border_width) - 2,
+ sizeof(grid_label),colors[zone_color],grid_label,FONT_BORDER,
+ pixmap_final,
+ 1, colors[0x0f]);
+ }
+ zone_color = 0x09;
+ // likewise for upper and lower right corners
+ xx = ((screen_width - border_width) * scale_x) + NW_corner_longitude;
+ yy = ((screen_height - border_width) * scale_y) + NW_corner_latitude;
+ convert_xastir_to_UTM(&easting, &northing, zone_str, sizeof(zone_str), xx, yy);
+ yy = (border_width * scale_y) + NW_corner_latitude;
+ convert_xastir_to_UTM(&easting, &northing, zone_str2, sizeof(zone_str2), xx, yy);
+ if (strcmp(zone_str,zone_str2)!=0) {
+ xastir_snprintf(grid_label,
+ sizeof(grid_label),
+ "%s",
+ zone_str2);
+ //draw_nice_string(w,pixmap_final,0,
+ // screen_width - (border_width * 3) ,
+ // (2*border_width)+2,
+ // grid_label,
+ // 0x10,zone_color,(int)strlen(grid_label));
+ draw_rotated_label_text_to_target (w, 270,
+ screen_width - (border_width * 3) ,
+ (2*border_width)+2,
+ sizeof(grid_label),colors[zone_color],grid_label,FONT_BORDER,
+ pixmap_final,
+ 1, colors[0x0f]);
+ }
+ if (strcmp(zone_str,zone_str2)!=0) {
+ xastir_snprintf(grid_label,
+ sizeof(grid_label),
+ "%s",
+ zone_str);
+ draw_rotated_label_text_to_target (w, 270,
+ screen_width - (border_width * 3) ,
+ screen_height - (2*border_width) - 2,
+ sizeof(grid_label),colors[zone_color],grid_label,FONT_BORDER,
+ pixmap_final,
+ 1, colors[0x0f]);
+ }
+
+ // are we currently the same zone as the upper left corner
+ // if so, we need to place the northing labels on the left side
+ xx = (utm_grid.zone[Zone].col[0].points[0].x * scale_x) + NW_corner_longitude;
+ yy = (utm_grid.zone[Zone].col[0].points[0].y * scale_y) + NW_corner_latitude;
+ convert_xastir_to_UTM(&easting, &northing, zone_str, sizeof(zone_str), xx, yy);
+ convert_xastir_to_UTM(&easting, &northing, zone_str2, sizeof(zone_str2), NW_corner_longitude, NW_corner_latitude);
+ if (strcmp(zone_str,zone_str2)==0) {
+ northing_color = 0x08; // 0x08 = black, same as lower left easting
+ label_on_left = TRUE;
+ }
+
+ }
+ // check to see if there is a horizontal boundary
+ // compare xone of upper left and lower left corners
+ convert_xastir_to_UTM(&easting, &northing, zone_str, sizeof(zone_str), NW_corner_longitude, NW_corner_latitude);
+
+ // Overwrite defaults as appropriate and
+ // label zones differently if more than one appears on the screen.
+
+ if (Zone > 0) {
+ // write the zone label on the bottom border
+ zone_color = 0x09; // blue
+ easting_color = 0x09; // blue
+ northing_color = 0x09; // blue
+ xx2 = utm_grid.zone[Zone].col[0].points[0].x;
+ xx = (xx2 * scale_x) + NW_corner_longitude;
+ yy2 = utm_grid.zone[Zone].col[0].points[utm_grid.zone[Zone].col[0].npoints-1].y;
+ yy = (yy2 * scale_y) + NW_corner_latitude;
+ convert_xastir_to_UTM(&easting, &northing, zone_str, sizeof(zone_str), xx,yy);
+ xastir_snprintf(grid_label,
+ sizeof(grid_label),
+ "%s",
+ zone_str);
+ draw_rotated_label_text_to_target (w, 270,
+ xx2,
+ screen_height,
+ sizeof(grid_label),colors[easting_color],grid_label,FONT_BORDER,
+ pixmap_final,
+ outline_border_labels, colors[outline_border_labels_color]);
+ //draw_nice_string(w,pixmap_final,0,
+ // xx2,
+ // screen_height - 2,
+ // grid_label,
+ // 0x10,zone_color,(int)strlen(grid_label));
+ }
+
+ if (Zone==0) {
+ // write the zone of the lower left corner of the map
+ xx = (border_width * scale_x) + NW_corner_longitude;
+ yy = ((screen_height - border_width) * scale_y) + NW_corner_latitude;
+ convert_xastir_to_UTM(&easting, &northing, zone_str, sizeof(zone_str), xx, yy);
+ xastir_snprintf(grid_label,
+ sizeof(grid_label),
+ "%s",
+ zone_str);
+ draw_rotated_label_text_to_target (w, 270,
+ 1,
+ screen_height,
+ sizeof(grid_label),colors[easting_color],grid_label,FONT_BORDER,
+ pixmap_final,
+ outline_border_labels, colors[outline_border_labels_color]);
+ //draw_nice_string(w,pixmap_final,0,
+ // 1,
+ // screen_height - 2,
+ // grid_label,
+ // 0x10,0x20,(int)strlen(grid_label));
+ }
+ // Put metadata in top border.
+ // find location of upper left corner of map, convert to UTM
+ xx2 = NW_corner_longitude + (border_width * scale_x);
+ yy2 = NW_corner_latitude + (border_width * scale_y);
+ convert_xastir_to_UTM(&easting, &northing, zone_str, sizeof(zone_str),
+ xx2, yy2);
+ if (coordinate_system == USE_MGRS) {
+ convert_xastir_to_MGRS_str_components(mgrs_zone, strlen(mgrs_zone),
+ mgrs_eastingL, sizeof(mgrs_eastingL),
+ mgrs_northingL, sizeof(mgrs_northingL),
+ &int_utmEasting, &int_utmNorthing,
+ xx2, yy2,
+ 0, mgrs_space_string, strlen(mgrs_space_string));
+ xastir_snprintf(mgrs_ul_digraph, sizeof(mgrs_ul_digraph),
+ "%c%c", mgrs_eastingL[0], mgrs_northingL[0]);
+ xastir_snprintf(grid_label,
+ sizeof(grid_label),
+ "%s %s %05.0f %05.0f",
+ mgrs_zone,mgrs_ul_digraph,(float)int_utmEasting,(float)int_utmNorthing);
+ }
+ else {
+ xastir_snprintf(grid_label,
+ sizeof(grid_label),
+ "%s %07.0f %07.0f",
+ zone_str,easting,northing);
+ }
+ // find location of lower right corner of map, convert to UTM
+ xx2 = NW_corner_longitude + ((screen_width - border_width) * scale_x);
+ yy2 = NW_corner_latitude + ((screen_height - border_width) * scale_y);
+ convert_xastir_to_UTM(&easting, &northing, zone_str, sizeof(zone_str),
+ xx2, yy2);
+ if (coordinate_system == USE_MGRS) {
+ convert_xastir_to_MGRS_str_components(mgrs_zone, strlen(mgrs_zone),
+ mgrs_eastingL, sizeof(mgrs_eastingL),
+ mgrs_northingL, sizeof(mgrs_northingL),
+ &int_utmEasting, &int_utmNorthing,
+ xx2, yy2,
+ 0, mgrs_space_string, strlen(mgrs_space_string));
+ xastir_snprintf(mgrs_lr_digraph, sizeof(mgrs_lr_digraph),
+ "%c%c", mgrs_eastingL[0], mgrs_northingL[0]);
+ xastir_snprintf(grid_label1,
+ sizeof(grid_label1),
+ "%s %s %05.0f %05.0f",
+ mgrs_zone,mgrs_lr_digraph,(float)int_utmEasting,(float)int_utmNorthing);
+ if (strcmp(mgrs_lr_digraph,mgrs_ul_digraph)==0) {
+ mgrs_single_digraph = TRUE; // mgrs_ul_digraph and mgrs_ur_digraph are the same.
+ }
+ else {
+ mgrs_single_digraph = FALSE; // mgrs_ul_digraph and mgrs_ur_digraph are the same.
+ }
+ }
+ else {
+ xastir_snprintf(grid_label1,
+ sizeof(grid_label1),
+ "%s %07.0f %07.0f",
+ zone_str,easting,northing);
+ }
+ //"XASTIR Map of %s (upper left) to %s (lower right). UTM %d m grid, %s datum. ",
+ xastir_snprintf(top_label,
+ sizeof(top_label),
+ langcode("MDATA001"),
+ grid_label,grid_label1,utm_grid_spacing_m,metadata_datum);
+ //draw_nice_string(w,pixmap_final,0,
+ // border_width+2,
+ // border_width-2,
+ // top_label,
+ // 0x10,0x20,(int)strlen(top_label));
+ draw_rotated_label_text_to_target (w, 270,
+ border_width+2,
+ border_width-1,
+ sizeof(top_label),colors[0x10],top_label,FONT_BORDER,
+ pixmap_final,
+ outline_border_labels, colors[outline_border_labels_color]);
+
+ // deterimne whether the easting and northing strings will fit
+ // in a grid box, or whether easting strings in adjacent boxes
+ // will overlap (so that alternate strings can be skipped).
+ if (utm_grid.zone[Zone].ncols > 1) {
+ // find out the number of pixels beteen two grid lines
+ grid_spacing_pixels =
+ utm_grid.zone[Zone].col[1].points[0].x -
+ utm_grid.zone[Zone].col[0].points[0].x;
+
+ if (grid_spacing_pixels == 0)
+ grid_spacing_pixels = -1; // Skip
+
+ }
+ else {
+ // only one column in this zone, skip alternate doesn't matter
+ grid_spacing_pixels = -1;
+ }
+
+ // Is truncated easting or northing larger than grid spacing?
+ // If so, skip alternate labels
+ // short_width_pixels+2 seems to work well.
+ if (short_width_pixels+2>grid_spacing_pixels) {
+ skip_alternate_label = TRUE;
+ }
+ else {
+ skip_alternate_label = FALSE;
+ }
+
+ // Label the grid lines on the border.
+ // Put easting along the bottom for easier correct ordering of easting and northing
+ // by people who are reading the map.
+ last_line_labeled = FALSE;
+ for (ii=1; ii < (int)utm_grid.zone[Zone].ncols; ii++) {
+ // label meridianal grid lines with easting
+
+ if (utm_grid.zone[Zone].col[ii].npoints > 1) {
+
+ // adjust up in case npoints goes far below the screen
+ if (grid_spacing_pixels == 0)
+ continue; // Go to next iteration of for loop
+
+ bottom_point = (int)(screen_height/grid_spacing_pixels);
+
+ if (bottom_point >= utm_grid.zone[Zone].col[ii].npoints)
+ bottom_point = utm_grid.zone[Zone].col[ii].npoints - 1;
+ if (skip_alternate_label==TRUE && last_line_labeled==TRUE) {
+ last_line_labeled = FALSE;
+ }
+ else {
+ xx = (utm_grid.zone[Zone].col[ii].points[bottom_point].x * scale_x) + NW_corner_longitude;
+ yy = (utm_grid.zone[Zone].col[ii].points[bottom_point].y * scale_y) + NW_corner_latitude;
+ convert_xastir_to_UTM(&easting, &northing, zone_str, sizeof(zone_str), xx, yy);
+ // To display full precision to one meter, use:
+ //xastir_snprintf(grid_label,
+ // sizeof(grid_label),
+ // "%06.0f0",
+ // (float)((utm_grid_spacing_m/10) * roundf(easting/(utm_grid_spacing_m))));
+ //
+ // Divide easting by utm_grid_spacing to make sure the line is labeled
+ // correctly, and not a few meters off, and truncate to at least 100 m.
+ xastir_snprintf(grid_label,
+ sizeof(grid_label),
+ "%05.0f",
+ (float)((utm_grid_spacing_m/100) * roundf(easting/(utm_grid_spacing_m))));
+ // truncate the label to an appropriate level of precision for the grid
+ if (utm_grid_spacing_m ==1000)
+ grid_label[4] = ' ';
+ if (utm_grid_spacing_m ==10000) {
+ grid_label[3] = ' ';
+ grid_label[4] = ' ';
+ }
+ if (utm_grid_spacing_m ==100000) {
+ grid_label[2] = ' ';
+ grid_label[3] = ' ';
+ grid_label[4] = ' ';
+ }
+ if (coordinate_system == USE_MGRS) {
+ convert_xastir_to_MGRS_str_components(mgrs_zone, strlen(mgrs_zone),
+ mgrs_eastingL, sizeof(mgrs_eastingL),
+ mgrs_northingL, sizeof(mgrs_northingL),
+ &int_utmEasting, &int_utmNorthing,
+ xx, yy,
+ 0, mgrs_space_string, strlen(mgrs_space_string));
+ grid_label[0] = mgrs_eastingL[0];
+ grid_label[1] = mgrs_northingL[0];
+ if (mgrs_single_digraph==FALSE)
+ grid_label[1] = '_';
+ }
+ // draw each number at the bottom of the screen just to the right of the
+ // relevant grid line at its location at the bottom of the screen
+ //draw_nice_string(w,pixmap_final,0,
+ // utm_grid.zone[Zone].col[i].points[bottom_point].x+1,
+ // screen_height-2,
+ // grid_label,
+ // 0x10,easting_color,(int)strlen(grid_label));
+
+ // Don't overwrite the zone label, half the seven zeros string should give it room.
+ // Don't draw the label if it will go off the left edge fo the screen.
+ if ((utm_grid.zone[Zone].col[ii].points[bottom_point].x+1 > (string_width_pixels/2))
+ && (utm_grid.zone[Zone].col[ii].points[bottom_point].x+1 < (screen_width - string_width_pixels))
+ ) {
+ // ok to draw the label
+ last_line_labeled = TRUE;
+ draw_rotated_label_text_to_target (w, 270,
+ utm_grid.zone[Zone].col[ii].points[bottom_point].x+1,
+ screen_height,
+ sizeof(grid_label),colors[easting_color],grid_label,FONT_BORDER,
+ pixmap_final,
+ outline_border_labels, colors[outline_border_labels_color]);
+ }
+ }
+ }
+ }
+ last_line_labeled = FALSE;
+ // put northing along the right border, again for easier correct ordering of easting and northing.
+ for (ii=0; ii < (int)utm_grid.zone[Zone].nrows; ii++) {
+ // label latitudinal grid lines with northing
+ if (utm_grid.zone[Zone].row[ii].npoints > 1) {
+ if (skip_alternate_label==TRUE && last_line_labeled==TRUE) {
+ last_line_labeled = FALSE;
+ }
+ else {
+ if (label_on_left==TRUE) {
+ xx = (utm_grid.zone[Zone].row[ii].points[0].x * scale_x) + NW_corner_longitude;
+ }
+ else {
+ xx = (utm_grid.zone[Zone].row[ii].points[utm_grid.zone[Zone].row[ii].npoints-1].x * scale_x) + NW_corner_longitude;
+ }
+ yy = (utm_grid.zone[Zone].row[ii].points[utm_grid.zone[Zone].row[ii].npoints-1].y * scale_y) + NW_corner_latitude;
+ convert_xastir_to_UTM(&easting, &northing, zone_str, sizeof(zone_str), xx, yy);
+ // To display to full 1 meter precision use:
+ //xastir_snprintf(grid_label,
+ // sizeof(grid_label),
+ // "%06.0f0",
+ // (float)((utm_grid_spacing_m/10) * roundf(northing/(utm_grid_spacing_m))));
+ //
+ // Divide northing by utm grid spacing to make sure the line is labeled correctly
+ // and displays zeroes in its least significant digits, and truncate to 100 m
+ xastir_snprintf(grid_label,
+ sizeof(grid_label),
+ "%05.0f",
+ (float)((utm_grid_spacing_m/100) * roundf(northing/(utm_grid_spacing_m))));
+ if (utm_grid_spacing_m ==1000)
+ grid_label[4] = ' ';
+ if (utm_grid_spacing_m ==10000) {
+ grid_label[3] = ' ';
+ grid_label[4] = ' ';
+ }
+ if (utm_grid_spacing_m ==100000) {
+ grid_label[2] = ' ';
+ grid_label[3] = ' ';
+ grid_label[4] = ' ';
+ }
+ if (coordinate_system == USE_MGRS) {
+ convert_xastir_to_MGRS_str_components(mgrs_zone, strlen(mgrs_zone),
+ mgrs_eastingL, 3,
+ mgrs_northingL, 3,
+ &int_utmEasting, &int_utmNorthing,
+ xx, yy,
+ 0, mgrs_space_string, strlen(mgrs_space_string));
+ grid_label[0] = mgrs_eastingL[0];
+ if (mgrs_single_digraph==FALSE)
+ grid_label[0] = '_';
+ grid_label[1] = mgrs_northingL[0];
+ }
+ // Draw northing labels.
+ // Draw each number just above the relevant grid line along the right side
+ // of the screen. Don't write in the bottom border or off the top of the screen.
+ if (label_on_left==TRUE) {
+ // label northings on left border
+ // don't overwrite the zone designator in the lower left border
+ if ((utm_grid.zone[Zone].row[ii].points[0].y < (screen_height - border_width))
+ &&
+ (utm_grid.zone[Zone].row[ii].points[0].y > (string_width_pixels))
+ ) {
+ last_line_labeled = TRUE;
+ draw_rotated_label_text_to_target (w, 180,
+ border_width,
+ utm_grid.zone[Zone].row[ii].points[0].y,
+ sizeof(grid_label),colors[northing_color],grid_label,FONT_BORDER,
+ pixmap_final,
+ outline_border_labels, colors[outline_border_labels_color]);
+ }
+ }
+ else {
+ if (((utm_grid.zone[Zone].row[ii].points[utm_grid.zone[Zone].row[ii].npoints-1].y-1)
+ < (screen_height - border_width))
+ &&
+ ((utm_grid.zone[Zone].row[ii].points[utm_grid.zone[Zone].row[ii].npoints-1].y-1)
+ > (string_width_pixels))
+ ) {
+ // label northings on right border
+ last_line_labeled = TRUE;
+ draw_rotated_label_text_to_target (w, 180,
+ screen_width,
+ utm_grid.zone[Zone].row[ii].points[utm_grid.zone[Zone].row[ii].npoints-1].y-1,
+ sizeof(grid_label),colors[northing_color],grid_label,FONT_BORDER,
+ pixmap_final,
+ outline_border_labels, colors[outline_border_labels_color]);
+ }
+ }
+ }
+ }
+ } // for i=0 to nrows
+ } // if draw labeled grid border
+ } // if utm_grid.zone[Zone] is non-empty
+ } // for each zone in utm_grid.zone
+} // End of actually_draw_utm_minor_grid() function
+
+
+
+
+
+// Calculate the minor UTM grids. Called by draw_grid() below.
+// This function calculates and caches a within-zone UTM grid
+// for the current map view if one does not allready exist, it
+// then calls actually_draw_utm_minor_grid() function above to do
+// the drawing once the grid has been calculated. Zone boundaries
+// are drawn separately by draw_major_utm_mgrs_grid().
+//
+// This routine appears to draw most of the UTM/UPS grid ok, with
+// the exceptions of:
+//
+// 1) Sometimes fails to draw vertical lines nearest zone
+// boundaries.
+// 2) Lines connect across zone boundaries in an incorrect manner,
+// jumping up one grid interval across the boundary.
+// 3) Segfaults near the special zone intersections as you zoom in.
+//
+// The code currently creates a col and row array per zone visible,
+// with XPoints malloced that contain the grid intersections in
+// screen coordinates. If the screen is zoomed or panned they are
+// recalculated.
+//
+// Perhaps we could do the same but with lat/long coordinates in the
+// future so that we'd only have to recalculate when a new Zone came
+// into view. We'd use the lat/long vector drawing programs above
+// then, with a possible slowdown due to more calculations if we're
+// not moving around.
+//
+// Returns: 0 if successful or nothing to draw
+// 1 if malloc error
+// 2 if iterations error
+// 3 if out of zones
+// 4 if realloc failure
+//
+int draw_minor_utm_mgrs_grid(Widget w) {
+
+ long xx, yy, xx1, yy1;
+ double e[4], n[4];
+ char place_str[10], zone_str[10];
+ int done = 0;
+ int z1, z2, Zone, col, col_point, row, row_point, row_point_start;
+ int iterations = 0;
+ int finished_with_current_zone = 0;
+ int ii, jj;
+ float slope;
+ int coordinate_system_backup = coordinate_system;
+
+
+ col = 0;
+ row = 0;
+ col_point = 0;
+ row_point = 0;
+ row_point_start = 0;
+ Zone = 0;
+
+ // Set up for drawing zone grid(s)
+ if (scale_x < 15)
+ utm_grid_spacing_m = 100;
+ else if (scale_x < 150)
+ utm_grid_spacing_m = 1000;
+ else if (scale_x < 1500)
+ utm_grid_spacing_m = 10000;
+ else if (scale_x < 3000)
+ utm_grid_spacing_m = 100000;
+ else {
+ utm_grid_spacing_m = 0;
+ // All done! Don't draw the minor grids. Major grids
+ // have already been drawn by this point.
+ return(0);
+ }
+
+ // Check hash to see if utm_grid is already set up
+ if (utm_grid.hash.ul_x == NW_corner_longitude &&
+ utm_grid.hash.ul_y == NW_corner_latitude &&
+ utm_grid.hash.lr_x == SE_corner_longitude &&
+ utm_grid.hash.lr_y == SE_corner_latitude) {
+
+ // XPoint arrays are already set up. Go draw the grid.
+ actually_draw_utm_minor_grid(w);
+
+ return(0);
+ }
+
+
+// If we get to this point, we need to re-create the minor UTM/MGRS
+// grids as they haven't been set up yet or they don't match the
+// current view.
+
+
+ // Clear the minor UTM/MGRS grid arrays. Alloc space for
+ // the points in the grid structure.
+ if (utm_grid_clear(1)) {
+ // If we got here, we had a problem with malloc's
+ return(1);
+ }
+
+ // Find top left point of current view
+ xx = NW_corner_longitude;
+ yy = NW_corner_latitude;
+
+ // Note that the minor grid depends on the STANDARD six degree
+ // UTM zones, not the UTM-Special/MGRS zones. Force our
+ // calculations to use the standard zones.
+ coordinate_system = USE_UTM;
+ convert_xastir_to_UTM(&e[0], &n[0], place_str, sizeof(place_str), xx, yy);
+ coordinate_system = coordinate_system_backup;
+
+ n[0] += UTM_GRID_EQUATOR; // To work in southern hemisphere
+
+
+// Select starting point, NW corner of NW zone
+
+ // Move the coordinates to the nearest subgrid intersection,
+ // based on our current grid spacing. The grid intersection
+ // we calculate here is northwest of our view's northwest
+ // corner.
+ e[0] /= utm_grid_spacing_m;
+ e[0] = (double)((int)e[0] * utm_grid_spacing_m);
+ n[0] /= utm_grid_spacing_m;
+ n[0] = (double)((int)n[0] * utm_grid_spacing_m);
+ n[0] += utm_grid_spacing_m;
+
+
+//WE7U
+// It appears that the horizontal grid lines get messed up in cases
+// where the top horizontal line isn't in view on it's left end.
+// That's a major clue! Read the comment below (again with a "WE7U"
+// tag). The problem occurs at the point where we copy the last
+// point from the previous grid over to the first point of a new
+// grid. That can cause us to be off by one, as for the grid on the
+// left, the top horizontal line _is_ in view on the left. We end
+// up connecting the wrong horizontal lines together because of this
+// mismatch, but again, only if the top horizontal line on the left
+// grid is above the current view.
+//
+// It also appears that the vertical lines that are missing in some
+// cases are on the right of the zone boundary. This is probably
+// because the top of that line doesn't go to the top of the view.
+// On views where it does, the line is drawn. I assume this is
+// because we're drawing from NW corner to the right, and then down,
+// which would cause that line to be skipped if it's not present on
+// the first line?
+
+
+ e[1] = e[0];
+ n[1] = n[0];
+
+
+
+
+
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+ // Start filling in the row/column arrays of grid intersections
+ while (!done) {
+ XPoint *temp_point;
+
+
+ // Here's our escape in case we get stuck in this loop.
+ // We can go through this loop multiple times for each
+ // zone though, depending on our grid spacing. 64 rows * 64
+ // colums * 8 points each = 32768, which gives us our upper
+ // limit.
+ if (iterations++ > 32768) {
+ fprintf(stderr,
+ "draw_minor_utm_mgrs_grid() looped too many times, escaping.\n");
+ utm_grid_clear(1);
+ return(2);
+ }
+
+
+ if (finished_with_current_zone) {
+ // Set up to compute the next zone
+
+ xx = NW_corner_longitude + ((utm_grid.zone[Zone].boundary_x + 1) * scale_x);
+
+ yy = NW_corner_latitude;
+
+ // Note that the minor grid depends on the STANDARD six
+ // degree UTM zones, not the UTM-Special/MGRS zones.
+ // Force our calculations to use the standard zones.
+ coordinate_system = USE_UTM;
+ convert_xastir_to_UTM(&e[0], &n[0], place_str, sizeof(place_str), xx, yy);
+ coordinate_system = coordinate_system_backup;
+
+ n[0] += UTM_GRID_EQUATOR; // To work in southern hemisphere
+
+// Fix the coordinates to the nearest subgrid intersection based on
+// our current grid spacing. Bump both the easting and northing up
+// by one subgrid.
+ e[0] /= utm_grid_spacing_m;
+ e[0] = (double)((int)e[0] * utm_grid_spacing_m);
+ e[0] += utm_grid_spacing_m;
+ n[0] /= utm_grid_spacing_m;
+ n[0] = (double)((int)n[0] * utm_grid_spacing_m);
+ n[0] += utm_grid_spacing_m;
+
+ e[1] = e[0];
+ n[1] = n[0];
+
+#ifdef UTM_DEBUG
+ fprintf(stderr,"\nFinished Zone=%d\n", Zone);
+#endif
+
+ // We're all done with the current zone. Increment
+ // to the next zone and set up to calculate its
+ // points.
+ Zone++;
+
+#ifdef UTM_DEBUG
+ fprintf(stderr,"\nstarting Zone=%d, row_point_start=1\n", Zone);
+#endif
+
+ row_point = row_point_start = 1;
+ col = row = col_point = 0;
+ finished_with_current_zone = 0;
+
+ if (Zone >= UTM_GRID_MAX_ZONES) {
+ fprintf(stderr,"Error: Zone=%d: out of zones!\n", Zone);
+ Zone = 0;
+ done = 1;
+ utm_grid_clear(1);
+ return(3);
+ }
+ } // End of if(finished_with_current_zone)
+
+ // Note that the minor grid depends on the STANDARD six
+ // degree UTM zones, not the UTM-Special/MGRS zones. Force
+ // our calculations to use the standard zones.
+ coordinate_system = USE_UTM;
+ convert_UTM_to_xastir(e[1], n[1]-UTM_GRID_EQUATOR, place_str, &xx, &yy);
+ coordinate_system = coordinate_system_backup;
+
+ xx1 = xx; // Save
+ yy1 = yy; // Save
+
+ // Note that the minor grid depends on the STANDARD six
+ // degree UTM zones, not the UTM-Special/MGRS zones. Force
+ // our calculations to use the standard zones.
+ coordinate_system = USE_UTM;
+ convert_xastir_to_UTM(&e[2], &n[2], zone_str, sizeof(zone_str), xx, yy);
+ coordinate_system = coordinate_system_backup;
+
+ n[2] += UTM_GRID_EQUATOR;
+ xx = (xx - NW_corner_longitude) / scale_x;
+ yy = (yy - NW_corner_latitude) / scale_y;
+
+ // Not all columns (and maybe rows) will start at point
+ // 0
+ if (utm_grid.zone[Zone].col[col].firstpoint == UTM_GRID_RC_EMPTY) {
+ utm_grid.zone[Zone].col[col].firstpoint = l16(col_point);
+#ifdef UTM_DEBUG
+ fprintf(stderr,"col[%d] started at point %d\n", col, col_point);
+#endif
+ }
+ if (utm_grid.zone[Zone].row[row].firstpoint == UTM_GRID_RC_EMPTY) {
+ utm_grid.zone[Zone].row[row].firstpoint = l16(row_point);
+#ifdef UTM_DEBUG
+ fprintf(stderr,"row[%d] started at point %d\n", row, row_point);
+#endif
+ }
+
+ // Check to see if we need to alloc more space for
+ // column points
+ ii = utm_grid.zone[Zone].col[col].npoints +
+ utm_grid.zone[Zone].col[col].firstpoint + 1;
+ if (ii > utm_grid.zone[Zone].col[col].nalloced) {
+#ifdef UTM_DEBUG_ALLOC
+ fprintf(stderr,"i=%d n=%d realloc(utm_grid.zone[%d].col[%d].points, ",
+ ii, utm_grid.zone[Zone].col[col].nalloced, Zone, col);
+#endif
+ ii = ((ii / UTM_GRID_DEF_NALLOCED) + 1) * UTM_GRID_DEF_NALLOCED;
+#ifdef UTM_DEBUG_ALLOC
+ fprintf(stderr,"%d)\n", ii);
+#endif
+
+ temp_point = realloc(utm_grid.zone[Zone].col[col].points,
+ ii * sizeof(XPoint));
+
+ if (temp_point) {
+ utm_grid.zone[Zone].col[col].points = temp_point;
+ utm_grid.zone[Zone].col[col].nalloced = ii;
+ }
+ else {
+ puts("realloc FAILED!");
+ (void)utm_grid_clear(1); // Clear arrays and allocate memory for points
+ return(4);
+ }
+ }
+
+ // Check to see if we need to alloc more space for row
+ // points
+ ii = utm_grid.zone[Zone].row[row].npoints +
+ utm_grid.zone[Zone].row[row].firstpoint + 1;
+ if (ii > utm_grid.zone[Zone].row[row].nalloced) {
+#ifdef UTM_DEBUG_ALLOC
+ fprintf(stderr,"i=%d n=%d realloc(utm_grid.zone[%d].row[%d].points, ",
+ ii, utm_grid.zone[Zone].row[row].nalloced, Zone, row);
+#endif
+ ii = ((ii / UTM_GRID_DEF_NALLOCED) + 1) * UTM_GRID_DEF_NALLOCED;
+#ifdef UTM_DEBUG_ALLOC
+ fprintf(stderr,"%d)\n", ii);
+#endif
+
+ temp_point = realloc(utm_grid.zone[Zone].row[row].points,
+ ii * sizeof(XPoint));
+
+ if (temp_point) {
+ utm_grid.zone[Zone].row[row].points = temp_point;
+ utm_grid.zone[Zone].row[row].nalloced = ii;
+ }
+ else {
+ puts("realloc FAILED!");
+ (void)utm_grid_clear(1); // Clear arrays and allocate memory for points
+ return(4);
+ }
+ }
+
+ // Here we check to see whether we are inserting points
+ // that are greater than about +/- 32767. If so,
+ // truncate at that. This prevents XDrawLines() from
+ // going nuts and drawing hundreds of extra lines.
+ //
+ xx = l16(xx);
+ yy = l16(yy);
+
+ utm_grid.zone[Zone].col[col].points[col_point].x = l16(xx);
+ utm_grid.zone[Zone].col[col].points[col_point].y = l16(yy);
+ utm_grid.zone[Zone].col[col].npoints++;
+ utm_grid.zone[Zone].row[row].points[row_point].x = l16(xx);
+ utm_grid.zone[Zone].row[row].points[row_point].y = l16(yy);
+ utm_grid.zone[Zone].row[row].npoints++;
+
+#ifdef UTM_DEBUG
+ fprintf(stderr,"utm_grid.zone[%d].col[%d].points[%d] = [ %ld,%ld ] npoints=%d\n",
+ Zone, col, col_point, xx, yy, utm_grid.zone[Zone].col[col].npoints);
+ fprintf(stderr,"utm_grid.zone[%d].row[%d].points[%d] = [ %ld,%ld ]\n",
+ Zone, row, row_point, xx, yy);
+#endif
+
+ col++;
+ row_point++;
+ if (col >= UTM_GRID_MAX_COLS_ROWS)
+ finished_with_current_zone++;
+
+ z1 = atoi(place_str);
+ z2 = atoi(zone_str);
+ if (z1 != z2 || xx > screen_width) { // We hit a boundary
+
+#ifdef UTM_DEBUG_VERB
+ if (z1 != z2)
+ fprintf(stderr,"Zone boundary! \"%s\" -> \"%s\"\n", place_str, zone_str);
+ else
+ puts("Screen boundary!");
+#endif
+
+//#warning
+//#warning I suspect that I should not use just col for the following.
+//#warning
+ if (col-2 >= 0)
+ slope = (float)(yy - utm_grid.zone[Zone].col[col-2].points[col_point].y) /
+ (float)(xx - utm_grid.zone[Zone].col[col-2].points[col_point].x + 0.001);
+ else
+ slope = 0.0;
+
+ if (xx > screen_width)
+ xx1 = screen_width;
+ else {
+
+ // 360,000 Xastir units equals one degree. This
+ // code appears to be adjusting xx1 to a major
+ // zone edge.
+ xx1 = (xx1 / (6 * 360000)) * 6 * 360000;
+ xx1 = (xx1 - NW_corner_longitude) / scale_x;
+ }
+
+ utm_grid.zone[Zone].boundary_x = xx1;
+ yy1 = yy - (xx - xx1) * slope;
+
+#ifdef UTM_DEBUG
+ fprintf(stderr,"_tm_grid.zone[%d].col[%d].points[%d] = [ %ld,%ld ]\n",
+ Zone, col-1, col_point, xx1, yy1);
+ fprintf(stderr,"_tm_grid.zone[%d].row[%d].points[%d] = [ %ld,%ld ]\n",
+ Zone, row, row_point-1, xx1, yy1);
+#endif
+
+ if (col-1 >= 0 && row_point-1 >= 0) {
+ utm_grid.zone[Zone].col[col-1].points[col_point].x = l16(xx1);
+ utm_grid.zone[Zone].col[col-1].points[col_point].y = l16(yy1);
+ utm_grid.zone[Zone].row[row].points[row_point-1].x = l16(xx1);
+ utm_grid.zone[Zone].row[row].points[row_point-1].y = l16(yy1);
+ if (z1 != z2 && Zone+1 < UTM_GRID_MAX_ZONES) {
+ // copy over last points to start off new
+ // zone
+#ifdef UTM_DEBUG
+ fprintf(stderr,"ztm_grid.zone[%d].row[%d].points[%d] = [ %ld,%ld ]\n",
+ Zone+1, row, 0, xx1, yy1);
+#endif
+
+//WE7U
+// This is where we can end up linking up/down one grid width
+// between zones!!! Without it though, we end up have a blank
+// section to the right of the zone boundary. Perhaps we could do
+// this here, but when we get the next points calculated, we could
+// check to see if we're off by about one grid width in the vertical
+// direction. If so, shift the initial point by that amount?
+//
+// Another possibility might be to draw bottom-to-top if in northern
+// hemisphere, and top-to-bottom if in southern hemisphere. That
+// way we'd have the max amount of lines present when we start, and
+// some might peter out as we draw along N/S. Looking at the
+// southern hemisphere right now though, that method doesn't appear
+// to work. We get the same problems there even though we're
+// drawing top to bottom.
+//
+ utm_grid.zone[Zone+1].row[row].points[0].x = l16(xx1);
+ utm_grid.zone[Zone+1].row[row].points[0].y = l16(yy1);
+ utm_grid.zone[Zone+1].row[row].firstpoint = 0;
+ utm_grid.zone[Zone+1].row[row].npoints = 1;
+ }
+ }
+
+
+ // Check last built row to see if it is all off
+ // screen
+ finished_with_current_zone++; // Assume we're done with this zone
+ for (ii=0; ii < utm_grid.zone[Zone].row[row].npoints; ii++) {
+ if (utm_grid.zone[Zone].row[row].points[ii].y <= screen_height)
+ finished_with_current_zone = 0; // Some points were within the zone, keep computing
+ }
+
+
+ e[1] = e[0]; // carriage return
+ n[1] -= utm_grid_spacing_m; // line feed
+// Yea, your comments are real funny Olivier... Gets the point
+// across though!
+
+
+ row++;
+ if (row >= UTM_GRID_MAX_COLS_ROWS)
+ finished_with_current_zone++;
+
+ utm_grid.zone[Zone].ncols = max_i(col, utm_grid.zone[Zone].ncols);
+ utm_grid.zone[Zone].nrows = max_i(row, utm_grid.zone[Zone].nrows);
+ col = 0;
+ row_point = row_point_start;
+ col_point++;
+
+ if (n[1] < 0) {
+ fprintf(stderr,"n[1] < 0\n");
+ finished_with_current_zone++;
+ }
+
+ if (finished_with_current_zone && xx > screen_width)
+ done = 1;
+
+ // Go to next iteration of while loop (skip next statement)
+ continue;
+ }
+
+ e[1] += utm_grid_spacing_m;
+
+ } // End of while (done) loop
+
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+
+
+
+//fprintf(stderr, "After while loop\n");
+
+ // utm_grid.zone[] now contains an array of points marking fine grid
+ // line intersections for parts of 1 to 4 zones that appear on
+ // the screen. Each utm_grid.zone[] is a vertical stripe, and may include
+ // more than one zone letter, e.g. zone[0] might include 15U and 15T,
+ // while zone[1] might include 16U and 16T.
+
+//#define UTM_DEBUG_VERB
+
+ for (Zone=0; Zone < UTM_GRID_MAX_ZONES; Zone++) {
+
+#ifdef UTM_DEBUG_VERB
+ fprintf(stderr,"\nutm_grid.zone[%d].ncols=%d\nutm_grid.zone[%d].nrows=%d\n",
+ Zone, utm_grid.zone[Zone].ncols, Zone, utm_grid.zone[Zone].nrows);
+#endif
+
+ // Cleanup columns
+ for (ii=0; ii < (int)utm_grid.zone[Zone].ncols; ii++) {
+ int np = utm_grid.zone[Zone].col[ii].npoints;
+ int fp = utm_grid.zone[Zone].col[ii].firstpoint;
+ int nbp = 0;
+
+#ifdef UTM_DEBUG_VERB
+ fprintf(stderr,"utm_grid.zone[%d].col[%d].npoints=%d .firstpoint=%d\n",
+ Zone, ii, np, fp);
+ if (np < 2)
+ puts(" Not enough points!");
+ else
+ puts("");
+
+ for (jj=fp; jj < fp+np; jj++) {
+ fprintf(stderr," col[%d].points[%d] = [ %d, %d ]", ii, jj,
+ utm_grid.zone[Zone].col[ii].points[jj].x,
+ utm_grid.zone[Zone].col[ii].points[jj].y);
+ if (utm_grid.zone[Zone].col[ii].points[jj].x ==
+ utm_grid.zone[Zone].boundary_x)
+ puts(" Boundary");
+ else
+ puts("");
+ }
+#endif
+ for (jj=fp; jj < fp+np; jj++) {
+ if (utm_grid.zone[Zone].col[ii].points[jj].x ==
+ utm_grid.zone[Zone].boundary_x)
+ nbp++;
+ else if (nbp > 0) { // We had a boundary point, but not anymore
+ fp = utm_grid.zone[Zone].col[ii].firstpoint = l16(jj - 1);
+//fprintf(stderr,"np:%d, jj:%d\n",np,jj);
+ // This can result in negative numbers!
+ np = utm_grid.zone[Zone].col[ii].npoints = np - jj + 1;
+//fprintf(stderr,"new np:%d\n",np);
+ if (np < 0) {
+ np = 0; // Prevents segfaults in
+ // XDrawLines() and memmove()
+ // below.
+ }
+ break; // Exit from for loop
+ }
+ if (nbp == np) { // All points are boundary points
+ fp = utm_grid.zone[Zone].col[ii].firstpoint = 0;
+ np = utm_grid.zone[Zone].col[ii].npoints = 0;
+ }
+ }
+
+// What's the below code doing? Can get a segfault without this in
+// the XDrawLines() functions below (fixed by making npoints an int
+// instead of an unsigned int). Sometimes we get a segfault right
+// here due to the memmove() function. In one such case, np was -2.
+// Latest code keeps some lines from getting drawn, but at least we
+// don't get a segfault.
+//
+ if (fp > 0) {
+ if (np > 0) {
+ memmove(&utm_grid.zone[Zone].col[ii].points[0],
+ &utm_grid.zone[Zone].col[ii].points[fp], np * sizeof(XPoint));
+ fp = utm_grid.zone[Zone].col[ii].firstpoint = 0;
+ }
+ else {
+//fprintf(stderr,"draw_minor_utm_mgrs_grid: ii:%d, np:%d, size:%d\n",ii,np,sizeof(XPoint));
+//fprintf(stderr,"Problem1: in draw_minor_utm_mgrs_grid() memmove, np was %d. Skipping memmove.\n",np);
+ }
+ }
+
+#ifdef UTM_DEBUG_VERB
+ fprintf(stderr,"_tm_grid.zone[%d].col[%d].npoints=%d.firstpoint=%d\n",
+ Zone, ii, np, fp);
+ for (jj=fp; jj < fp+np; jj++) {
+ fprintf(stderr," col[%d].points[%d] = [ %d, %d ]", ii, jj,
+ utm_grid.zone[Zone].col[ii].points[jj].x,
+ utm_grid.zone[Zone].col[ii].points[jj].y);
+ if (utm_grid.zone[Zone].col[ii].points[jj].x ==
+ utm_grid.zone[Zone].boundary_x)
+ puts(" Boundary");
+ else
+ puts("");
+ }
+ puts("");
+#endif
+ }
+
+ // Cleanup rows
+ for (ii=0; ii < (int)utm_grid.zone[Zone].nrows; ii++) {
+ int np = utm_grid.zone[Zone].row[ii].npoints;
+ int fp = utm_grid.zone[Zone].row[ii].firstpoint;
+#ifdef UTM_DEBUG_VERB
+ fprintf(stderr,"utm_grid.zone[%d].row[%d].npoints=%d.firstpoint=%d\n",
+ Zone, ii, np, fp);
+ if (np < 2)
+ puts(" Not enough points!");
+ else
+ puts("");
+#endif
+// What's this doing? This appears to be important, as things get
+// really messed up if it's commented out.
+ if (fp > 0) {
+ if (np > 0) {
+ memmove(&utm_grid.zone[Zone].row[ii].points[0],
+ &utm_grid.zone[Zone].row[ii].points[fp], np * sizeof(XPoint));
+ fp = utm_grid.zone[Zone].row[ii].firstpoint = 0;
+ }
+ else {
+//fprintf(stderr,"draw_minor_utm_mgrs_grid: ii:%d, np:%d, size:%d\n",ii,np,sizeof(XPoint));
+//fprintf(stderr,"Problem2: in draw_minor_utm_mgrs_grid() memmove, np was %d. Skipping memmove.\n",np);
+ }
+
+ }
+#ifdef UTM_DEBUG_VERB
+ for (jj=fp; jj < fp+np; jj++) {
+ fprintf(stderr," row[%d].points[%d] = [ %d, %d ]\n", ii, jj,
+ utm_grid.zone[Zone].row[ii].points[jj].x,
+ utm_grid.zone[Zone].row[ii].points[jj].y);
+ }
+#endif
+ }
+ }
+
+ // Rows and columns ready to go so setup hash
+ utm_grid.hash.ul_x = NW_corner_longitude;
+ utm_grid.hash.ul_y = NW_corner_latitude;
+ utm_grid.hash.lr_x = SE_corner_longitude;
+ utm_grid.hash.lr_y = SE_corner_latitude;
+
+ // XPoint arrays are set up. Go draw the grid.
+ actually_draw_utm_minor_grid(w);
+
+ return(0);
+
+} // End of draw_minor_utm_mgrs_grid() function
+
+
+
+
+
+//*****************************************************************
+// draw_grid()
+//
+// Draws a lat/lon or UTM/UPS grid on top of the view.
+//
+//*****************************************************************
+void draw_grid(Widget w) {
+ int half; // Center of the white lines used to draw the borders
+ int border_width = 14; // The width of the border to draw around the
+ // map to place labeled tick marks into
+ // should be an even number.
+ // The default here is overidden by the border fontsize.
+
+
+ if (!long_lat_grid) // We don't wish to draw a map grid
+ return;
+
+ if (draw_labeled_grid_border==TRUE) {
+ // Determine how wide the border should be.
+ border_width = get_border_width(w);
+ half = border_width/2;
+ // draw a white border around the map.
+ (void)XSetLineAttributes(XtDisplay(w),
+ gc,
+ border_width,
+ LineSolid,
+ CapRound,
+ JoinRound);
+ (void)XSetForeground(XtDisplay(w),
+ gc,
+ colors[border_foreground_color]); // white
+ (void)XDrawLine(XtDisplay(w),
+ pixmap_final,
+ gc,
+ 0,
+ l16(half),
+ l16(screen_width),
+ l16(half));
+ (void)XDrawLine(XtDisplay(w),
+ pixmap_final,
+ gc,
+ l16(half),
+ 0,
+ l16(half),
+ l16(screen_height));
+ (void)XDrawLine(XtDisplay(w),
+ pixmap_final,
+ gc,
+ 0,
+ l16(screen_height-half),
+ l16(screen_width),
+ l16(screen_height-half));
+ (void)XDrawLine(XtDisplay(w),
+ pixmap_final,
+ gc,
+ l16(screen_width-half),
+ 0,
+ l16(screen_width-half),
+ l16(screen_height));
+ }
+
+ // Set the line width in the GC to 2 pixels wide for the larger
+ // UTM grid and the complete Lat/Long grid.
+ (void)XSetLineAttributes (XtDisplay (w), gc_tint, 2, LineOnOffDash, CapButt,JoinMiter);
+ (void)XSetForeground (XtDisplay (w), gc_tint, colors[0x27]);
+ (void)XSetFunction (XtDisplay (da), gc_tint, GXxor);
+
+ if (coordinate_system == USE_UTM
+ || coordinate_system == USE_UTM_SPECIAL
+ || coordinate_system == USE_MGRS) {
+
+ int ret_code;
+
+//draw_vector_ll(w, -5.0, -5.0, 5.0, 5.0, gc_tint, pixmap_final, 0);
+//draw_vector_ll(w, 5.0, 5.0, -5.0, -5.0, gc_tint, pixmap_final, 0);
+
+ // Draw major UTM/MGRS zones
+ draw_major_utm_mgrs_grid(w);
+
+ // Draw minor UTM/MGRS zones
+ ret_code = draw_minor_utm_mgrs_grid(w);
+ if (ret_code) {
+ fprintf(stderr,
+ "Encountered problem %d while calculating minor utm grid!\n",
+ ret_code);
+ }
+
+ } // End of UTM grid section
+ else { // Lat/Long coordinate system, draw lat/long lines
+ draw_complete_lat_lon_grid(w);
+ } // End of Lat/Long section
+} // End of draw_grid()
+
+
+
+
+
+/**********************************************************
+ * get_map_ext()
+ *
+ * Returns the extension for the filename. We use this to
+ * determine which sort of map file it is.
+ **********************************************************/
+char *get_map_ext (char *filename) {
+ int len;
+ int i;
+ char *ext;
+
+ ext = NULL;
+ len = (int)strlen (filename);
+ for (i = len; i >= 0; i--) {
+ if (filename[i] == '.') {
+ ext = filename + (i + 1);
+ break;
+ }
+ }
+ return (ext);
+}
+
+
+
+
+
+/**********************************************************
+ * get_map_dir()
+ *
+ * Used to snag just the pathname from a complete filename.
+ * Modifies input parameter "fullpath".
+ **********************************************************/
+char *get_map_dir (char *fullpath) {
+ int len;
+ int i;
+
+ len = (int)strlen (fullpath);
+ for (i = len; i >= 0; i--) {
+ if (fullpath[i] == '/') {
+ fullpath[i + 1] = '\0';
+ break;
+ }
+ }
+ return (fullpath);
+}
+
+
+
+
+
+/***********************************************************
+ * map_visible()
+ *
+ * Tests whether a particular path/filename is within our
+ * current view. We use this to decide whether to plot or
+ * skip a particular image file (major speed-up!).
+ * Input coordinates are in the Xastir coordinate system.
+ *
+ * Had to fix a bug here where the viewport glanced over the
+ * edge of the earth, causing strange results like this.
+ * Notice the View Edges Top value is out of range:
+ *
+ *
+ * Bottom Top Left Right
+ * View Edges: 31,017,956 4,290,923,492 35,971,339 90,104,075
+ * Map Edges: 12,818,482 12,655,818 64,079,859 64,357,110
+ *
+ * Left map boundary inside view
+ * Right map boundary inside view
+ * map_inside_view: 1 view_inside_map: 0 parallel_edges: 0
+ * Map not within current view.
+ * Skipping map: /usr/local/share/xastir/maps/tif/uk/425_0525_bng.tif
+ *
+ *
+ * I had to check for out-of-bounds numbers for the viewport and
+ * set them to min or max values so that this function always
+ * works properly. Here are the bounds of the earth (Xastir
+ * Coordinate System):
+ *
+ * 0 (90 deg. or 90N)
+ *
+ * 0 (-180 deg. or 180W) 129,600,000 (180 deg. or 180E)
+ *
+ * 64,800,000 (-90 deg. or 90S)
+ *
+ ***********************************************************/
+int map_visible (unsigned long map_max_y, // bottom_map_boundary
+ unsigned long map_min_y, // top_map_boundary
+ unsigned long map_min_x, // left_map_boundary
+ unsigned long map_max_x) { // right_map_boundary) {
+
+ //fprintf(stderr,"map_visible\n");
+
+ // From computation geometry equations, intersection of two line
+ // segments, they use the bounding box for two lines. This is
+ // the same as what we want to do:
+ //
+ // http://www.cs.kent.edu/~dragan/AdvAlg/CompGeom-2x1.pdfa
+ // http://www.gamedev.net/reference/articles/article735.asp
+ //
+ // The quick rejection algorithm:
+ //
+ if (NW_corner_latitude > (long)map_max_y) {
+ if (debug_level & 16) {
+ fprintf(stderr,
+ "map_visible, rejecting: NW_corner_latitude:%ld > map_max_y:%ld\n",
+ NW_corner_latitude,
+ map_max_y);
+ fprintf(stderr,
+ "\tmap or object is above viewport\n");
+ }
+ return(0);
+ }
+
+ if ((long)map_min_y > SE_corner_latitude) {
+ if (debug_level & 16) {
+ fprintf(stderr,
+ "map_visible, rejecting: map_min_y:%ld > SE_corner_latitude:%ld\n",
+ map_min_y,
+ SE_corner_latitude);
+ fprintf(stderr,
+ "\tmap or object is below viewport\n");
+ }
+ return(0);
+ }
+
+ if (NW_corner_longitude > (long)map_max_x) {
+ if (debug_level & 16) {
+ fprintf(stderr,
+ "map_visible, rejecting: NW_corner_longitude:%ld > map_max_x:%ld\n",
+ NW_corner_longitude,
+ map_max_x);
+ fprintf(stderr,
+ "\tmap or object is left of viewport\n");
+ }
+ return(0);
+ }
+
+ if ((long)map_min_x > SE_corner_longitude) {
+ if (debug_level & 16) {
+ fprintf(stderr,
+ "map_visible, rejecting: map_min_x:%ld > SE_corner_longitude:%ld\n",
+ map_min_x,
+ SE_corner_longitude);
+ fprintf(stderr,
+ "\tmap or object is right of viewport\n");
+ }
+ return(0);
+ }
+
+ return (1); // At least part of the map is on-screen
+}
+
+
+
+/////////////////////////////////////////////////////////////////////
+// get_viewport_lat_lon(double *xmin, double *ymin, double* xmax, double *ymax)
+// Simply returns the floating point corners of the map display.
+/////////////////////////////////////////////////////////////////////
+void get_viewport_lat_lon(double *xmin,
+ double *ymin,
+ double* xmax,
+ double *ymax) {
+
+ *xmin=(double)f_NW_corner_longitude;
+ *ymin=(double)f_SE_corner_latitude;
+ *xmax=(double)f_SE_corner_longitude;
+ *ymax=(double)f_NW_corner_latitude;
+}
+
+/////////////////////////////////////////////////////////////////////
+// map_inside_viewport_lat_lon()
+// Returns 1 if the given set of xmin,xmax, ymin,ymax defines a
+// rectangle entirely contained in the current viewport (as opposed to
+// merely partially overlapping it. Returns zero otherwise.
+/////////////////////////////////////////////////////////////////////
+int map_inside_viewport_lat_lon(double map_min_y,
+ double map_max_y,
+ double map_min_x,
+ double map_max_x) {
+ int retval=0;
+ if (map_min_x >= f_NW_corner_longitude &&
+ map_min_y >= f_SE_corner_latitude &&
+ map_max_x <= f_SE_corner_longitude &&
+ map_max_y <= f_NW_corner_latitude) {
+ retval=1;
+ }
+
+ return (retval);
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// map_visible_lat_lon()
+//
+// We have the center of the view in floating point format:
+//
+// float f_center_longitude; // Floating point map center longitude
+// float f_center_latitude; // Floating point map center latitude
+//
+// So we just need to compute the top/bottom/left/right using those
+// values and the scale_x/scale_y values before doing the compare.
+//
+// y scaling in 1/100 sec per pixel
+// x scaling in 1/100 sec per pixel, calculated from scale_y
+//
+//
+// 0 (90 deg. or 90N)
+//
+// 0 (-180 deg. or 180W) 129,600,000 (180 deg. or 180E)
+//
+// 64,800,000 (-90 deg. or 90S)
+//
+// ******************* ******************* max_y
+// *NW * + * * +
+// * * * *
+// * * * *
+// * View * latitude (y) * Map *
+// * * * *
+// * * * *
+// * SE* - * * -
+// ******************* ******************* min_y
+// - longitude(x) + - min_x max_x +
+
+/////////////////////////////////////////////////////////////////////
+int map_visible_lat_lon (double map_min_y, // f_bottom_map_boundary
+ double map_max_y, // f_top_map_boundary
+ double map_min_x, // f_left_map_boundary
+ double map_max_x) { // f_right_map_boundary
+
+//fprintf(stderr,"map_visible_lat_lon\n");
+
+ // From computation geometry equations, intersection of two line
+ // segments, they use the bounding box for two lines. This is
+ // the same as what we want to do:
+ //
+ // http://www.cs.kent.edu/~dragan/AdvAlg/CompGeom-2x1.pdfa
+ // http://www.gamedev.net/reference/articles/article735.asp
+ //
+ // The quick rejection algorithm:
+ //
+ if (map_max_y < f_SE_corner_latitude ) return(0); // map below view
+ if (map_max_x < f_NW_corner_longitude) return(0); // map left of view
+ if (map_min_y > f_NW_corner_latitude ) return(0); // view below map
+ if (map_min_x > f_SE_corner_longitude) return(0); // view left of map
+
+ return (1); // Draw this map onto the screen
+}
+
+
+
+
+
+/**********************************************************
+ * draw_label_text()
+ *
+ * Does what it says. Used to draw strings onto the
+ * display.
+ **********************************************************/
+void draw_label_text (Widget w, int x, int y, int label_length, int color, char *label_text) {
+
+ // This draws a gray background rectangle upon which we draw the text.
+ // Probably not needed. It ends up obscuring details underneath.
+ //(void)XSetForeground (XtDisplay (w), gc, colors[0x0ff]);
+ //(void)XFillRectangle (XtDisplay (w), pixmap, gc, x - 1, (y - 10),(label_length * 6) + 2, 11);
+
+ (void)XSetForeground (XtDisplay (w), gc, color);
+ (void)XDrawString (XtDisplay (w), pixmap, gc, x, y, label_text, label_length);
+}
+
+
+
+
+
+// Must make sure that fonts are not loaded again and again, as this
+// takes a big chunk of memory each time. Can you say "memory
+// leak"?
+
+XFontStruct *rotated_label_font[FONT_MAX]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
+char rotated_label_fontname[FONT_MAX][MAX_LABEL_FONTNAME];
+static char
+current_rotated_label_fontname[FONT_MAX][sizeof(rotated_label_fontname)] = {"","","","","","","","",""};
+
+/**********************************************************
+ * draw_rotated_label_text_common()
+ * call through wrappers:
+ * draw_rotated_label_text_to_pixmap()
+ * draw_rotated_label_text()
+ * draw_centered_label_text()
+ *
+ * Does what it says. Used to draw strings onto the
+ * display.
+ *
+ * Use "xfontsel" or other tools to figure out what fonts
+ * to use here.
+ *
+ * Paramenters:
+ * target_pixmap specifies the pixmap the text is to be drawn to.
+ * draw_outline specifies whether a 1 pixel outline around the
+ * text, TRUE to draw outline.
+ * outline_bg_color is the color of the outline.
+ * color is the color of the text inside the outline, or the
+ * color of the text itself if no outline is added.
+ **********************************************************/
+/* common code used by the two entries --- a result of retrofitting a new
+ feature (centered) */
+static void draw_rotated_label_text_common (Widget w, float my_rotation, int x, int y, int label_length, int color, char *label_text, int align, int fontsize, Pixmap target_pixmap, int draw_outline, int outline_bg_color) {
+// XPoint *corner;
+// int i;
+ int x_outline;
+ int y_outline;
+
+
+ // Do some sanity checking
+ if (fontsize < 0 || fontsize >= FONT_MAX) {
+ fprintf(stderr,"Font size is out of range: %d\n", fontsize);
+ return;
+ }
+
+ /* see if fontname has changed */
+ if (rotated_label_font[fontsize] &&
+ strcmp(rotated_label_fontname[fontsize],current_rotated_label_fontname[fontsize]) != 0) {
+ XFreeFont(XtDisplay(w),rotated_label_font[fontsize]);
+ rotated_label_font[fontsize] = NULL;
+ xastir_snprintf(current_rotated_label_fontname[fontsize],
+ sizeof(rotated_label_fontname),
+ "%s",
+ rotated_label_fontname[fontsize]);
+ }
+ /* load font */
+ if(!rotated_label_font[fontsize]) {
+ rotated_label_font[fontsize]=(XFontStruct *)XLoadQueryFont(XtDisplay (w),
+ rotated_label_fontname[fontsize]);
+ if (rotated_label_font[fontsize] == NULL) { // Couldn't get the font!!!
+ fprintf(stderr,"draw_rotated_label_text: Couldn't get font %s\n",
+ rotated_label_fontname[fontsize]);
+ return;
+ }
+ }
+
+ if (draw_outline) {
+ // make outline style
+ (void)XSetForeground(XtDisplay(w),gc,outline_bg_color);
+ // Draw the string repeatedly with 1 pixel offsets in the
+ // background color to make an outline.
+
+ for (x_outline=-1;x_outline<2;x_outline++) {
+ for (y_outline=-1;y_outline<2;y_outline++) {
+ // draws one extra copy at x,y
+ (void)XRotDrawAlignedString(XtDisplay (w),
+ rotated_label_font[fontsize],
+ my_rotation,
+ target_pixmap,
+ gc,
+ x+x_outline,
+ y+y_outline,
+ label_text,
+ align);
+ }
+ }
+ }
+
+
+ // Code to determine the bounding box corner points for the rotated text
+// corner = XRotTextExtents(w,rotated_label_font,my_rotation,x,y,label_text,BLEFT);
+// for (i=0;i<5;i++) {
+// fprintf(stderr,"%d,%d\t",corner[i].x,corner[i].y);
+// }
+// fprintf(stderr,"\n");
+
+ (void)XSetForeground (XtDisplay (w), gc, color);
+
+ //fprintf(stderr,"%0.1f\t%s\n",my_rotation,label_text);
+
+ (void)XRotDrawAlignedString(XtDisplay (w),
+ rotated_label_font[fontsize],
+ my_rotation,
+ target_pixmap,
+ gc,
+ x,
+ y,
+ label_text,
+ align);
+}
+
+
+
+
+
+// Find the pixel length of an unrotated string in the rotated_label_font.
+// Parameters:
+// w - the XtDisplay.
+// label_text - the string of which the length is to be found.
+// fontsize - the fontsize in the rotated_label_font in which the string
+// is to be rendered.
+// Returns: the length in pixels of the string, -1 on an error.
+int get_rotated_label_text_length_pixels(Widget w, char *label_text, int fontsize) {
+ int dir, asc, desc; // parameters returned by XTextExtents, but not used here.
+ XCharStruct overall; // description of the space occupied by the string.
+ int return_value; // value to return
+ int got_font; // flag indicating that a font is available
+
+ return_value = -1;
+ got_font = TRUE;
+
+ /* load font */
+ if(!rotated_label_font[fontsize]) {
+ rotated_label_font[fontsize]=(XFontStruct *)XLoadQueryFont(XtDisplay (w),
+ rotated_label_fontname[fontsize]);
+ if (rotated_label_font[fontsize] == NULL) { // Couldn't get the font!!!
+ fprintf(stderr,"get_rotated_label_text_length_pixels: Couldn't get font %s\n",
+ rotated_label_fontname[fontsize]);
+ got_font = FALSE;
+ }
+ }
+
+ if (got_font) {
+ // find out the width in pixels of the unrotated label_text string.
+ XTextExtents(rotated_label_font[fontsize], label_text, strlen(label_text), &dir, &asc, &desc,
+ &overall);
+ return_value = overall.width;
+ }
+
+ return return_value;
+}
+
+
+
+
+
+// Find the pixel height of an unrotated string in the rotated_label_font.
+// Parameters:
+// w - the XtDisplay.
+// label_text - the string of which the length is to be found.
+// fontsize - the fontsize in the rotated_label_font in which the string
+// is to be rendered.
+// Returns: the height in pixels of the string, -1 on an error.
+int get_rotated_label_text_height_pixels(Widget w, char *label_text, int fontsize) {
+ int dir, asc, desc; // parameters returned by XTextExtents, but not used here.
+ XCharStruct overall; // description of the space occupied by the string.
+ int return_value; // value to return
+ int got_font; // flag indicating that a font is available
+
+ return_value = -1;
+ got_font = TRUE;
+
+ /* load font */
+ if(!rotated_label_font[fontsize]) {
+ rotated_label_font[fontsize]=(XFontStruct *)XLoadQueryFont(XtDisplay (w),
+ rotated_label_fontname[fontsize]);
+ if (rotated_label_font[fontsize] == NULL) { // Couldn't get the font!!!
+ fprintf(stderr,"get_rotated_label_text_height_pixels: Couldn't get font %s\n",
+ rotated_label_fontname[fontsize]);
+ got_font = FALSE;
+ }
+ }
+
+ if (got_font) {
+ // find out the width in pixels of the unrotated label_text string.
+ XTextExtents(rotated_label_font[fontsize], label_text, strlen(label_text), &dir, &asc, &desc,
+ &overall);
+ return_value = overall.ascent + overall.descent;
+ }
+
+ return return_value;
+}
+
+
+
+
+
+// Draw a rotated label onto the specified pixmap.
+// Wrapper for draw_rotated_label_text-common().
+void draw_rotated_label_text_to_target (Widget w, int rotation, int x, int y, int label_length, int color, char *label_text, int fontsize, Pixmap target_pixmap, int draw_outline, int outline_bg_color) {
+ float my_rotation = (float)((-rotation)-90);
+
+ if ( ( (my_rotation < -90.0) && (my_rotation > -270.0) )
+ || ( (my_rotation > 90.0) && (my_rotation < 270.0) ) ) {
+ my_rotation = my_rotation + 180.0;
+ (void)draw_rotated_label_text_common(w,
+ my_rotation,
+ x,
+ y,
+ label_length,
+ color,
+ label_text,
+ BRIGHT,
+ fontsize,
+ target_pixmap,
+ draw_outline,
+ outline_bg_color);
+ }
+ else {
+ (void)draw_rotated_label_text_common(w,
+ my_rotation,
+ x,
+ y,
+ label_length,
+ color,
+ label_text,
+ BLEFT,
+ fontsize,
+ target_pixmap,
+ draw_outline,
+ outline_bg_color);
+ }
+}
+
+
+
+
+
+void draw_rotated_label_text (Widget w, int rotation, int x, int y, int label_length, int color, char *label_text, int fontsize) {
+ float my_rotation = (float)((-rotation)-90);
+
+ if ( ( (my_rotation < -90.0) && (my_rotation > -270.0) )
+ || ( (my_rotation > 90.0) && (my_rotation < 270.0) ) ) {
+ my_rotation = my_rotation + 180.0;
+ (void)draw_rotated_label_text_common(w,
+ my_rotation,
+ x,
+ y,
+ label_length,
+ color,
+ label_text,
+ BRIGHT,
+ fontsize,
+ pixmap, 0, 0);
+ }
+ else {
+ (void)draw_rotated_label_text_common(w,
+ my_rotation,
+ x,
+ y,
+ label_length,
+ color,
+ label_text,
+ BLEFT,
+ fontsize,
+ pixmap, 0, 0);
+ }
+}
+
+void draw_centered_label_text (Widget w, int rotation, int x, int y, int label_length, int color, char *label_text, int fontsize) {
+ float my_rotation = (float)((-rotation)-90);
+
+ (void)draw_rotated_label_text_common(w,
+ my_rotation,
+ x,
+ y,
+ label_length,
+ color,
+ label_text,
+ BCENTRE,
+ fontsize,
+ pixmap, 0, 0);
+}
+
+
+
+
+
+static void Print_postscript_destroy_shell(/*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ char *temp_ptr;
+
+
+ XtPopdown(shell);
+
+begin_critical_section(&print_postscript_dialog_lock, "maps.c:Print_postscript_destroy_shell" );
+
+ if (print_postscript_dialog) {
+ // Snag the path to the printer program from the print dialog
+ temp_ptr = XmTextFieldGetString(printer_data);
+ xastir_snprintf(printer_program,
+ sizeof(printer_program),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+ (void)remove_trailing_spaces(printer_program);
+
+ // Check for empty variable
+ if (printer_program[0] == '\0') {
+
+#ifdef LPR_PATH
+ // Path to LPR if defined
+ xastir_snprintf(printer_program,
+ sizeof(printer_program),
+ "%s",
+ LPR_PATH);
+#else // LPR_PATH
+ // Empty path
+ xastir_snprintf(printer_program,
+ sizeof(printer_program),
+ "");
+#endif // LPR_PATH
+ }
+
+//fprintf(stderr,"%s\n", printer_program);
+
+ // Snag the path to the previewer program from the print dialog
+ temp_ptr = XmTextFieldGetString(previewer_data);
+ xastir_snprintf(previewer_program,
+ sizeof(previewer_program),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+ (void)remove_trailing_spaces(previewer_program);
+
+ // Check for empty variable
+ if (previewer_program[0] == '\0') {
+
+#ifdef GV_PATH
+ // Path to GV if defined
+ xastir_snprintf(previewer_program,
+ sizeof(previewer_program),
+ "%s",
+ GV_PATH);
+#else // GV_PATH
+ // Empty string
+ previewer_program[0] = '\0';
+#endif // GV_PATH
+ }
+//fprintf(stderr,"%s\n", previewer_program);
+ }
+
+ XtDestroyWidget(shell);
+ print_postscript_dialog = (Widget)NULL;
+
+end_critical_section(&print_postscript_dialog_lock, "maps.c:Print_postscript_destroy_shell" );
+
+}
+
+
+
+
+
+static void Print_properties_destroy_shell(/*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+
+ if (!shell)
+ return;
+
+ XtPopdown(shell);
+
+begin_critical_section(&print_properties_dialog_lock, "maps.c:Print_properties_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ print_properties_dialog = (Widget)NULL;
+
+end_critical_section(&print_properties_dialog_lock, "maps.c:Print_properties_destroy_shell" );
+
+}
+
+
+
+
+
+// Print_window: Prints the drawing area to a Postscript file and
+// then sends it to the printer program (usually "lpr).
+//
+static void Print_window( Widget widget, XtPointer clientData, XtPointer callData ) {
+
+#ifdef NO_XPM
+// fprintf(stderr,"XPM or ImageMagick support not compiled into Xastir!\n");
+ popup_message_always(langcode("POPEM00035"),
+ "XPM or ImageMagick support not compiled into Xastir! Cannot Print!");
+#else // NO_XPM
+
+ char xpm_filename[MAX_FILENAME];
+ char ps_filename[MAX_FILENAME];
+ char command[MAX_FILENAME*2];
+ char temp[MAX_FILENAME];
+ int xpmretval;
+ char temp_base_dir[MAX_VALUE];
+
+ get_user_base_dir("tmp", temp_base_dir, sizeof(temp_base_dir));
+
+ xastir_snprintf(xpm_filename,
+ sizeof(xpm_filename),
+ "%s/print.xpm",
+ temp_base_dir);
+
+ xastir_snprintf(ps_filename,
+ sizeof(ps_filename),
+ "%s/print.ps",
+ temp_base_dir);
+
+ busy_cursor(appshell); // Show a busy cursor while we're doing all of this
+
+ // Get rid of the Print dialog
+ Print_postscript_destroy_shell(widget, print_postscript_dialog, NULL );
+
+ if ( debug_level & 512 )
+ fprintf(stderr,"Creating %s\n", xpm_filename );
+
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("PRINT0012") );
+ statusline(temp,1); // Dumping image to file...
+
+ chdir(temp_base_dir);
+ xpmretval=XpmWriteFileFromPixmap(XtDisplay(appshell),// Display *display
+ "print.xpm", // char *filename
+ pixmap_final, // Pixmap pixmap
+ (Pixmap)NULL, // Pixmap shapemask
+ NULL );
+
+ if (xpmretval != XpmSuccess) {
+ fprintf(stderr,"ERROR writing %s: %s\n", xpm_filename,
+ XpmGetErrorString(xpmretval));
+ popup_message_always(langcode("POPEM00035"),
+ "Error writing xpm image file! Cannot Print!");
+ return;
+ }
+ else { // We now have the xpm file created on disk
+
+ chmod( xpm_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
+
+ if ( debug_level & 512 )
+ fprintf(stderr,"Convert %s ==> %s\n", xpm_filename, ps_filename );
+
+
+ // Convert it to a postscript file for printing. This depends
+ // on the ImageMagick command "convert".
+ //
+
+ if (debug_level & 512)
+ fprintf(stderr,"Width: %ld\tHeight: %ld\n", screen_width, screen_height);
+
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("PRINT0013") );
+ statusline(temp,1); // Converting to Postscript...
+
+
+#ifdef HAVE_CONVERT
+ xastir_snprintf(command,
+ sizeof(command),
+ "%s -filter Point %s %s",
+ CONVERT_PATH,
+ xpm_filename,
+ ps_filename );
+
+ if ( debug_level & 512 )
+ fprintf(stderr,"%s\n", command );
+
+ if ( system( command ) != 0 ) {
+// fprintf(stderr,"\n\nPrint: Couldn't convert from XPM to PS!\n\n\n");
+ popup_message_always(langcode("POPEM00035"),
+ "Couldn't convert from XPM to PS!");
+ return;
+ }
+#endif // HAVE_CONVERT
+
+ chmod( ps_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
+
+ // Delete temporary xpm file
+ if ( !(debug_level & 512) )
+ unlink( xpm_filename );
+
+ if ( debug_level & 512 )
+ fprintf(stderr,"Printing postscript file %s\n", ps_filename);
+
+// Note: This needs to be changed to "lp" for Solaris.
+// Also need to have a field to configure the printer name. One
+// fill-in field could do both.
+//
+// Since we could be running SUID root, we don't want to be
+// calling "system" anyway. Several problems with it.
+
+ xastir_snprintf(command,
+ sizeof(command),
+ "%s %s",
+ printer_program,
+ ps_filename );
+
+ if ( debug_level & 512 )
+ fprintf(stderr,"%s\n", command);
+
+ if (printer_program[0] == '\0') {
+// fprintf(stderr,"\n\nPrint: No print program defined!\n\n\n");
+ popup_message_always(langcode("POPEM00035"),
+ "No print program defined!");
+ return;
+ }
+
+ if ( system( command ) != 0 ) {
+// fprintf(stderr,"\n\nPrint: Couldn't send to the printer!\n\n\n");
+ popup_message_always(langcode("POPEM00035"),
+ "Couldn't send to the printer!");
+ return;
+ }
+
+/*
+ if ( !(debug_level & 512) )
+ unlink( ps_filename );
+*/
+
+ if ( debug_level & 512 )
+ fprintf(stderr," Done printing.\n");
+ }
+
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("PRINT0014") );
+ statusline(temp,1); // Finished creating print file.
+
+ //popup_message( langcode("PRINT0015"), langcode("PRINT0014") );
+
+#endif // NO_XPM
+
+}
+
+
+
+
+
+// Print_preview: Prints the drawing area to a Postscript file. If
+// previewer_program has "gv" in it, then use the various options
+// selected by the user. If not, skip those options.
+//
+static void Print_preview( Widget widget, XtPointer clientData, XtPointer callData ) {
+
+#ifdef NO_XPM
+// fprintf(stderr,"XPM or ImageMagick support not compiled into Xastir!\n");
+ popup_message_always(langcode("POPEM00035"),
+ "XPM or ImageMagick support not compiled into Xastir! Cannot Print!");
+#else // NO_GRAPHICS
+
+ char xpm_filename[MAX_FILENAME];
+ char ps_filename[MAX_FILENAME];
+ char mono[50] = "";
+ char invert[50] = "";
+ char rotate[50] = "";
+ char scale[50] = "";
+ char density[50] = "";
+ char command[MAX_FILENAME*2];
+ char temp[MAX_FILENAME];
+ char format[100] = " ";
+ int xpmretval;
+ char temp_base_dir[MAX_VALUE];
+
+ get_user_base_dir("tmp", temp_base_dir, sizeof(temp_base_dir));
+
+
+ xastir_snprintf(xpm_filename,
+ sizeof(xpm_filename),
+ "%s/print.xpm",
+ temp_base_dir);
+
+ xastir_snprintf(ps_filename,
+ sizeof(ps_filename),
+ "%s/print.ps",
+ temp_base_dir);
+
+ busy_cursor(appshell); // Show a busy cursor while we're doing all of this
+
+ // Get rid of the Print Properties dialog if it exists
+ Print_properties_destroy_shell(widget, print_properties_dialog, NULL );
+
+ if ( debug_level & 512 )
+ fprintf(stderr,"Creating %s\n", xpm_filename );
+
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("PRINT0012") );
+ statusline(temp,1); // Dumping image to file...
+
+ chdir(temp_base_dir);
+ xpmretval=XpmWriteFileFromPixmap(XtDisplay(appshell),// Display *display
+ "print.xpm", // char *filename
+ pixmap_final, // Pixmap pixmap
+ (Pixmap)NULL, // Pixmap shapemask
+ NULL );
+
+ if (xpmretval != XpmSuccess) {
+ fprintf(stderr,"ERROR writing %s: %s\n", xpm_filename,
+ XpmGetErrorString(xpmretval));
+ popup_message_always(langcode("POPEM00035"),
+ "Error writing XPM file!");
+ return;
+ }
+ else { // We now have the xpm file created on disk
+
+ chmod( xpm_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
+
+ if ( debug_level & 512 )
+ fprintf(stderr,"Convert %s ==> %s\n", xpm_filename, ps_filename );
+
+
+ // If we're not using "gv", skip most of the code below and
+ // go straight to the previewer program portion of the code.
+ //
+ if ( strstr(previewer_program,"gv") ) {
+
+ // Convert it to a postscript file for printing. This
+ // depends on the ImageMagick command "convert".
+ //
+ // Other options to try in the future:
+ // -label
+ //
+ if ( print_auto_scale ) {
+// sprintf(scale, "-geometry 612x792 -page 612x792 "); // "Letter" size at 72 dpi
+// sprintf(scale, "-sample 612x792 -page 612x792 "); // "Letter" size at 72 dpi
+ xastir_snprintf(scale, sizeof(scale), "-page 1275x1650+0+0 "); // "Letter" size at 150 dpi
+ }
+ else
+ scale[0] = '\0'; // Empty string
+
+
+ if ( print_in_monochrome )
+ xastir_snprintf(mono, sizeof(mono), "-monochrome +dither " ); // Monochrome
+ else
+ xastir_snprintf(mono, sizeof(mono), "+dither "); // Color
+
+
+ if ( print_invert )
+ xastir_snprintf(invert, sizeof(invert), "-negate " ); // Reverse Colors
+ else
+ invert[0] = '\0'; // Empty string
+
+
+ if (debug_level & 512)
+ fprintf(stderr,"Width: %ld\tHeight: %ld\n", screen_width, screen_height);
+
+
+ if ( print_rotated ) {
+ xastir_snprintf(rotate, sizeof(rotate), "-rotate -90 " );
+
+#ifdef HAVE_OLD_GV
+ xastir_snprintf(format, sizeof(format), "-landscape " );
+#else // HAVE_OLD_GV
+ xastir_snprintf(format, sizeof(format), "--orientation=landscape " );
+#endif // HAVE_OLD_GV
+
+ }
+ else if ( print_auto_rotation ) {
+ // Check whether the width or the height of the
+ // pixmap is greater. If width is greater than
+ // height, rotate the image by 270 degrees.
+ if (screen_width > screen_height) {
+ xastir_snprintf(rotate, sizeof(rotate), "-rotate -90 " );
+
+#ifdef HAVE_OLD_GV
+ xastir_snprintf(format, sizeof(format), "-landscape " );
+#else // HAVE_OLD_GV
+ xastir_snprintf(format, sizeof(format), "--orientation=landscape " );
+#endif // HAVE_OLD_GV
+
+ if (debug_level & 512)
+ fprintf(stderr,"Rotating\n");
+ }
+ else {
+ rotate[0] = '\0'; // Empty string
+ if (debug_level & 512)
+ fprintf(stderr,"Not Rotating\n");
+ }
+ }
+ else {
+ rotate[0] = '\0'; // Empty string
+ if (debug_level & 512)
+ fprintf(stderr,"Not Rotating\n");
+ }
+
+
+ // Higher print densities require more memory and time
+ // to process
+ xastir_snprintf(density, sizeof(density), "-density %dx%d", print_resolution,
+ print_resolution );
+
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("PRINT0013") );
+ statusline(temp,1); // Converting to Postscript...
+
+
+ // Filters:
+ // Point (ok at higher dpi's)
+ // Box (not too bad)
+ // Triangle (no)
+ // Hermite (no)
+ // Hanning (no)
+ // Hamming (no)
+ // Blackman (better but still not good)
+ // Gaussian (no)
+ // Quadratic (no)
+ // Cubic (no)
+ // Catrom (not too bad)
+ // Mitchell (no)
+ // Lanczos (no)
+ // Bessel (no)
+ // Sinc (not too bad)
+
+ }
+
+#ifdef HAVE_CONVERT
+ xastir_snprintf(command,
+ sizeof(command),
+ "%s -filter Point %s%s%s%s%s %s %s",
+ CONVERT_PATH,
+ mono,
+ invert,
+ rotate,
+ scale,
+ density,
+ xpm_filename,
+ ps_filename );
+ if ( debug_level & 512 )
+ fprintf(stderr,"%s\n", command );
+
+ if ( system( command ) != 0 ) {
+// fprintf(stderr,"\n\nPrint: Couldn't convert from XPM to PS!\n\n\n");
+ popup_message_always(langcode("POPEM00035"),
+ "Couldn't convert from XPM to PS!");
+ return;
+ }
+#endif // HAVE_CONVERT
+
+ chmod( ps_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
+
+ // Delete temporary xpm file
+ if ( !(debug_level & 512) )
+ unlink( xpm_filename );
+
+ if ( debug_level & 512 )
+ fprintf(stderr,"Printing postscript file %s\n", ps_filename);
+
+// Since we could be running SUID root, we don't want to be
+// calling "system" anyway. Several problems with it.
+
+ // Bring up the postscript viewer
+ xastir_snprintf(command,
+ sizeof(command),
+ "%s %s %s &",
+ previewer_program,
+ format,
+ ps_filename );
+
+ if ( debug_level & 512 )
+ fprintf(stderr,"%s\n", command);
+
+ if (previewer_program[0] == '\0') {
+// fprintf(stderr,"\n\nPrint: No print previewer defined!\n\n\n");
+ popup_message_always(langcode("POPEM00035"),
+ "No print previewer defined!");
+ return;
+ }
+
+ if ( system( command ) != 0 ) {
+// fprintf(stderr,"\n\nPrint: Couldn't bring up the postscript viewer!\n\n\n");
+ popup_message_always(langcode("POPEM00035"),
+ "Couldn't bring up the viewer!");
+ return;
+ }
+
+/*
+ if ( !(debug_level & 512) )
+ unlink( ps_filename );
+*/
+
+ if ( debug_level & 512 )
+ fprintf(stderr," Done printing.\n");
+ }
+
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode("PRINT0014") );
+ statusline(temp,1); // Finished creating print file.
+
+ //popup_message( langcode("PRINT0015"), langcode("PRINT0014") );
+
+#endif // NO_XPM
+
+}
+
+
+
+
+
+/*
+ * Auto_rotate
+ *
+ */
+static void Auto_rotate( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ print_auto_rotation = atoi(which);
+ print_rotated = 0;
+ XmToggleButtonSetState(rotate_90, FALSE, FALSE);
+ }
+ else {
+ print_auto_rotation = 0;
+ }
+}
+
+
+
+
+
+/*
+ * Rotate_90
+ *
+ */
+static void Rotate_90( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ print_rotated = atoi(which);
+ print_auto_rotation = 0;
+ XmToggleButtonSetState(auto_rotate, FALSE, FALSE);
+ }
+ else {
+ print_rotated = 0;
+ }
+}
+
+
+
+
+
+/*
+ * Auto_scale
+ *
+ */
+static void Auto_scale( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ print_auto_scale = atoi(which);
+ }
+ else {
+ print_auto_scale = 0;
+ }
+}
+
+
+
+
+
+/*
+ * Monochrome
+ *
+ */
+void Monochrome( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ print_in_monochrome = atoi(which);
+ }
+ else {
+ print_in_monochrome = 0;
+ }
+}
+
+
+
+
+
+/*
+ * Invert
+ *
+ */
+static void Invert( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ print_invert = atoi(which);
+ }
+ else {
+ print_invert = 0;
+ }
+}
+
+
+
+
+
+// Print_properties: Prints the drawing area to a PostScript file.
+// Provides various togglebuttons for configuring the "gv" previewer
+// only.
+//
+// Perhaps later:
+// 1) Select an area on the screen to print
+// 2) -label
+//
+void Print_properties( Widget w, XtPointer clientData, XtPointer callData ) {
+ static Widget pane, form, button_ok, button_cancel,
+ sep, auto_scale,
+// paper_size, paper_size_data, scale, scale_data, blank_background,
+// res_label1, res_label2, res_x, res_y,
+ monochrome, invert;
+ Atom delw;
+
+ // Get rid of the Print dialog
+ Print_postscript_destroy_shell(w, print_postscript_dialog, NULL );
+
+
+ // If we're not using "gv", skip the entire dialog below and go
+ // straight to the actual previewer function.
+ //
+ if ( !strstr(previewer_program,"gv") ) {
+ Print_preview(w, NULL, NULL);
+ return;
+ }
+
+
+ if (!print_properties_dialog) {
+
+
+begin_critical_section(&print_properties_dialog_lock, "maps.c:Print_properties" );
+
+
+ print_properties_dialog = XtVaCreatePopupShell(langcode("PRINT0001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ pane = XtVaCreateWidget("Print_properties pane",xmPanedWindowWidgetClass, print_properties_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+
+ form = XtVaCreateWidget("Print_properties form",xmFormWidgetClass, pane,
+ XmNfractionBase, 2,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+
+/*
+ paper_size = XtVaCreateManagedWidget(langcode("PRINT0002"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+XtSetSensitive(paper_size,FALSE);
+
+
+ paper_size_data = XtVaCreateManagedWidget("Print_properties paper_size_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNwidth, ((15*7)+2),
+ XmNmaxLength, 15,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, paper_size,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+XtSetSensitive(paper_size_data,FALSE);
+*/
+
+
+ auto_rotate = XtVaCreateManagedWidget(langcode("PRINT0003"),xmToggleButtonWidgetClass,form,
+// XmNtopAttachment, XmATTACH_WIDGET,
+// XmNtopWidget, paper_size_data,
+// XmNtopOffset, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+XtAddCallback(auto_rotate,XmNvalueChangedCallback,Auto_rotate,"1");
+
+
+ rotate_90 = XtVaCreateManagedWidget(langcode("PRINT0004"),xmToggleButtonWidgetClass,form,
+// XmNtopAttachment, XmATTACH_WIDGET,
+// XmNtopWidget, paper_size_data,
+// XmNtopOffset, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, auto_rotate,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+XtAddCallback(rotate_90,XmNvalueChangedCallback,Rotate_90,"1");
+
+
+ auto_scale = XtVaCreateManagedWidget(langcode("PRINT0005"),xmToggleButtonWidgetClass,form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, auto_rotate,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+XtAddCallback(auto_scale,XmNvalueChangedCallback,Auto_scale,"1");
+
+
+/*
+ scale = XtVaCreateManagedWidget(langcode("PRINT0006"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, auto_rotate,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, auto_scale,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+XtSetSensitive(scale,FALSE);
+
+
+ scale_data = XtVaCreateManagedWidget("Print_properties scale_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNwidth, ((15*7)+2),
+ XmNmaxLength, 15,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, auto_rotate,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, scale,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+XtSetSensitive(scale_data,FALSE);
+*/
+
+
+/*
+ blank_background = XtVaCreateManagedWidget(langcode("PRINT0007"),xmToggleButtonWidgetClass,form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, scale_data,
+ XmNtopWidget, auto_rotate,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+XtSetSensitive(blank_background,FALSE);
+*/
+
+
+ monochrome = XtVaCreateManagedWidget(langcode("PRINT0008"),xmToggleButtonWidgetClass,form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+// XmNtopWidget, blank_background,
+ XmNtopWidget, auto_scale,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+XtAddCallback(monochrome,XmNvalueChangedCallback,Monochrome,"1");
+
+
+ invert = XtVaCreateManagedWidget(langcode("PRINT0016"),xmToggleButtonWidgetClass,form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, monochrome,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+XtAddCallback(invert,XmNvalueChangedCallback,Invert,"1");
+
+
+/*
+ res_label1 = XtVaCreateManagedWidget(langcode("PRINT0009"),xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, invert,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+XtSetSensitive(res_label1,FALSE);
+
+
+ res_x = XtVaCreateManagedWidget("Print_properties resx_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNwidth, ((15*7)+2),
+ XmNmaxLength, 15,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, invert,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, res_label1,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+XtSetSensitive(res_x,FALSE);
+
+
+ res_label2 = XtVaCreateManagedWidget("X",xmLabelWidgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, invert,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, res_x,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+XtSetSensitive(res_label2,FALSE);
+
+
+ res_y = XtVaCreateManagedWidget("Print_properties res_y_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNwidth, ((15*7)+2),
+ XmNmaxLength, 15,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, invert,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, res_label2,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+XtSetSensitive(res_y,FALSE);
+*/
+
+
+ sep = XtVaCreateManagedWidget("Print_properties sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+// XmNtopWidget, res_y,
+ XmNtopWidget, invert,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+// button_ok = XtVaCreateManagedWidget(langcode("PRINT0011"),xmPushButtonGadgetClass, form,
+ button_ok = XtVaCreateManagedWidget(langcode("PRINT0010"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNrightOffset, 2,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNleftOffset, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNrightOffset, 5,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ XtAddCallback(button_ok, XmNactivateCallback, Print_preview, NULL );
+ XtAddCallback(button_cancel, XmNactivateCallback, Print_properties_destroy_shell, print_properties_dialog);
+
+
+ XmToggleButtonSetState(rotate_90,FALSE,FALSE);
+ XmToggleButtonSetState(auto_rotate,TRUE,FALSE);
+
+
+ if (print_auto_rotation)
+ XmToggleButtonSetState(auto_rotate, TRUE, TRUE);
+ else
+ XmToggleButtonSetState(auto_rotate, FALSE, TRUE);
+
+
+ if (print_rotated)
+ XmToggleButtonSetState(rotate_90, TRUE, TRUE);
+ else
+ XmToggleButtonSetState(rotate_90, FALSE, TRUE);
+
+
+ if (print_in_monochrome)
+ XmToggleButtonSetState(monochrome, TRUE, FALSE);
+ else
+ XmToggleButtonSetState(monochrome, FALSE, FALSE);
+
+
+ if (print_invert)
+ XmToggleButtonSetState(invert, TRUE, FALSE);
+ else
+ XmToggleButtonSetState(invert, FALSE, FALSE);
+
+
+ if (print_auto_scale)
+ XmToggleButtonSetState(auto_scale, TRUE, TRUE);
+ else
+ XmToggleButtonSetState(auto_scale, FALSE, TRUE);
+
+
+// XmTextFieldSetString(paper_size_data,print_paper_size);
+
+
+end_critical_section(&print_properties_dialog_lock, "maps.c:Print_properties" );
+
+
+ pos_dialog(print_properties_dialog);
+
+
+ delw = XmInternAtom(XtDisplay(print_properties_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(print_properties_dialog, delw, Print_properties_destroy_shell, (XtPointer)print_properties_dialog);
+
+
+ XtManageChild(form);
+ XtManageChild(pane);
+
+
+ XtPopup(print_properties_dialog,XtGrabNone);
+ fix_dialog_size(print_properties_dialog);
+
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(print_properties_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+
+ }
+ else {
+ (void)XRaiseWindow(XtDisplay(print_properties_dialog), XtWindow(print_properties_dialog));
+ }
+}
+
+
+
+
+
+// General print dialog. From here we can either print Postscript
+// files to the device selected in this dialog, or head off to a
+// print preview program that might allow us a variety of print
+// options. From here we should be able to set the print device
+// and the print preview program & path.
+//
+void Print_Postscript( Widget w, XtPointer clientData, XtPointer callData ) {
+ static Widget pane, form, button_print, button_cancel,
+ sep, button_preview;
+ Atom delw;
+
+ if (!print_postscript_dialog) {
+
+
+begin_critical_section(&print_postscript_dialog_lock, "maps.c:Print_Postscript" );
+
+
+ print_postscript_dialog = XtVaCreatePopupShell(langcode("PULDNFI015"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ pane = XtVaCreateWidget("Print_postscript pane",xmPanedWindowWidgetClass, print_postscript_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+
+ form = XtVaCreateWidget("Print_postscript form",xmFormWidgetClass, pane,
+ XmNfractionBase, 3,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+
+ // "Direct to:"
+ button_print = XtVaCreateManagedWidget(langcode("PRINT1001"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ printer_data = XtVaCreateManagedWidget("Print_Postscript printer_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 40,
+ XmNwidth, ((40*7)+2),
+ XmNmaxLength, MAX_FILENAME,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, button_print,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ // "Via Previewer:"
+ button_preview = XtVaCreateManagedWidget(langcode("PRINT1002"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, button_print,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ previewer_data = XtVaCreateManagedWidget("Print_Postscript previewer_data", xmTextFieldWidgetClass, form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 40,
+ XmNwidth, ((40*7)+2),
+ XmNmaxLength, MAX_FILENAME,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, button_print,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, button_preview,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ sep = XtVaCreateManagedWidget("Print_postscript sep", xmSeparatorGadgetClass,form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, button_preview,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ XtAddCallback(button_preview, XmNactivateCallback, Print_properties, NULL );
+ XtAddCallback(button_print, XmNactivateCallback, Print_window, NULL );
+ XtAddCallback(button_cancel, XmNactivateCallback, Print_postscript_destroy_shell, print_postscript_dialog);
+
+ // Fill in the text fields from persistent variables out of the config file.
+ XmTextFieldSetString(printer_data, printer_program);
+ XmTextFieldSetString(previewer_data, previewer_program);
+
+end_critical_section(&print_postscript_dialog_lock, "maps.c:Print_Postscript" );
+
+
+ pos_dialog(print_postscript_dialog);
+
+
+ delw = XmInternAtom(XtDisplay(print_postscript_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(print_postscript_dialog, delw, Print_postscript_destroy_shell, (XtPointer)print_postscript_dialog);
+
+
+ XtManageChild(form);
+ XtManageChild(pane);
+
+
+ XtPopup(print_postscript_dialog,XtGrabNone);
+ fix_dialog_size(print_postscript_dialog);
+
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(print_postscript_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+
+ }
+ else {
+ (void)XRaiseWindow(XtDisplay(print_postscript_dialog), XtWindow(print_postscript_dialog));
+ }
+}
+
+
+
+
+
+// Create png image (for use in web browsers??). Requires that "convert"
+// from the ImageMagick package be installed on the system. At the
+// point this thread is started, the XPM file has already been
+// created. We now create a .geo file to go with the .png file.
+//
+#ifndef NO_XPM
+static void* snapshot_thread(void *arg) {
+ char xpm_filename[MAX_FILENAME];
+ char png_filename[MAX_FILENAME];
+ char geo_filename[MAX_FILENAME];
+ char kml_filename[MAX_FILENAME]; // filename for kml file that describes the png file in keyhole markup language
+ char timestring[101]; // string representation of the time heard or the current time
+ FILE *f;
+ FILE *fk; // file handle for kml file
+ time_t expire_time;
+#ifdef HAVE_CONVERT
+ char command[MAX_FILENAME*2];
+#endif // HAVE_CONVERT
+ char temp_base_dir[MAX_VALUE];
+
+ get_user_base_dir("tmp", temp_base_dir, sizeof(temp_base_dir));
+
+
+ // The pthread_detach() call means we don't care about the
+ // return code and won't use pthread_join() later. Makes
+ // threading more efficient.
+ (void)pthread_detach(pthread_self());
+
+ xastir_snprintf(xpm_filename,
+ sizeof(xpm_filename),
+ "%s/snapshot.xpm",
+ temp_base_dir);
+
+ xastir_snprintf(png_filename,
+ sizeof(png_filename),
+ "%s/snapshot.png",
+ temp_base_dir);
+
+ // Same for the .geo filename
+ xastir_snprintf(geo_filename,
+ sizeof(geo_filename),
+ "%s/snapshot.geo",
+ temp_base_dir);
+
+ // Same for the .kml filename
+ xastir_snprintf(kml_filename,
+ sizeof(kml_filename),
+ "%s/snapshot.kml",
+ temp_base_dir);
+
+
+ // Create a .geo file to match the new png image
+ // Likewise for a matching .kml file
+ f = fopen(geo_filename,"w"); // Overwrite whatever file
+ // is there.
+ fk = fopen(kml_filename,"w");
+
+ if (f == NULL || fk == NULL) {
+ if (f==NULL)
+ fprintf(stderr,"Couldn't open %s\n",geo_filename);
+ if (fk==NULL)
+ fprintf(stderr,"Couldn't open %s\n",kml_filename);
+ }
+ else {
+ float lat1, long1, lat2, long2;
+
+
+ long1 = f_NW_corner_longitude;
+ lat1 = f_NW_corner_latitude;
+ long2 = f_SE_corner_longitude;
+ lat2 = f_SE_corner_latitude;
+
+ // FILENAME world1.xpm
+ // # x y lon lat
+ // TIEPOINT 0 0 -180 90
+ // TIEPOINT 639 319 180 -90
+ // IMAGESIZE 640 320
+ // REFRESH 250
+
+ fprintf(f,"FILENAME snapshot.png\n");
+ fprintf(f,"# x y lon lat\n");
+ fprintf(f,"TIEPOINT 0 0 %8.5f %8.5f\n",
+ long1, lat1);
+ fprintf(f,"TIEPOINT %-4d %-4d %8.5f %8.5f\n",
+ (int)screen_width-1, (int)screen_height-1, long2, lat2);
+
+ fprintf(f,"IMAGESIZE %-4d %-4d\n",
+ (int)screen_width, (int)screen_height);
+ fprintf(f,"REFRESH 250\n");
+ fclose(f);
+
+ // Write a matching kml file that describes the location of the snapshot on
+ // the Earth's surface.
+ // Another kml file pointing to the location of this file with a networklinkcontrol element
+ // and an update element loaded into a kml application should be able to reload this file
+ // at regular intervals.
+ // See kml documentation of:
+ // <kml><NetworkLinkControl><linkName/><refreshMode/>
+ //
+ // <?xml version="1.0" encoding="UTF-8"?>
+ // <kml xmlns="http://earth.google.com/kml/2.1">
+ // <Document>
+ // <NetworkLink>
+ // <Link>
+ // <href>http://www.example.com/cgi-bin/screenshot.kml</href>
+ // <refreshMode>onExpire</refreshMode>
+ // </Link>
+ // </NetworkLink>
+ // </Document>
+ // </kml>
+ //
+ // TODO: Calculate a suitable range and tilt for viewing the snapshot draped on the
+ // underlying terrain.
+
+ fprintf(fk,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ fprintf(fk,"<kml xmlns=\"http://earth.google.com/kml/2.2\">\n");
+ // Add an expire time matching the time when the next snapshot should
+ // be produced, so that a network link with an onExpire refresh mode
+ // will check for the next snapshot.
+ expire_time = sec_now() + (time_t)(snapshot_interval * 60);
+ if (get_w3cdtf_datetime(expire_time, timestring, False, False)) {
+ if (strlen(timestring) > 0) {
+ fprintf(fk," <NetworkLinkControl>\n");
+ fprintf(fk," <expires>%s</expires>\n",timestring);
+ fprintf(fk," </NetworkLinkControl>\n");
+ }
+ }
+ fprintf(fk," <Document>\n");
+ fprintf(fk," <name>XASTIR Snapshot from %s</name>\n",my_callsign);
+ fprintf(fk," <open>1</open>\n");
+ fprintf(fk," <GroundOverlay>\n");
+ fprintf(fk," <name>Xastir snapshot</name>\n");
+ fprintf(fk," <visibility>1</visibility>\n");
+ // timestamp the overlay with the current time
+ if (get_w3cdtf_datetime(sec_now(), timestring, True, True)) {
+ if (strlen(timestring) > 0) {
+ fprintf(fk," <TimeStamp><when>%s</when></TimeStamp>\n",timestring);
+ fprintf(fk," <description>Overlay shows screen visible for %s in Xastir at %s.</description>\n",my_callsign,timestring);
+ }
+ } else {
+ fprintf(fk," <description>Overlay shows screen visible for %s in Xastir.</description>\n",my_callsign);
+ }
+ fprintf(fk," <LookAt>\n");
+ fprintf(fk," <longitude>%8.5f</longitude>\n",f_center_longitude);
+ fprintf(fk," <latitude>%8.5f</latitude>\n",f_center_latitude);
+ fprintf(fk," <altitude>0</altitude>\n");
+ fprintf(fk," <range>30350.36838438907</range>\n"); // range in meters from viewer to lookat point
+ fprintf(fk," <tilt>0</tilt>\n"); // 0 is looking straight down
+ fprintf(fk," <altitudeMode>clampToGround</altitudeMode>\n");
+ fprintf(fk," <heading>0</heading>\n"); // 0 is north at top, 90 east at top
+ fprintf(fk," </LookAt>\n");
+ fprintf(fk," <Icon>\n");
+ fprintf(fk," <href>snapshot.png</href>\n");
+ fprintf(fk," </Icon>\n");
+ fprintf(fk," <LatLonBox>\n");
+ fprintf(fk," <north>%8.5f</north>\n",lat1);
+ fprintf(fk," <south>%8.5f</south>\n",lat2);
+ fprintf(fk," <east>%8.5f</east>\n",long2);
+ fprintf(fk," <west>%8.5f</west>\n",long1);
+ fprintf(fk," <rotation>0</rotation>\n");
+ fprintf(fk," </LatLonBox>\n");
+ fprintf(fk," </GroundOverlay>\n");
+ fprintf(fk," </Document>\n");
+ fprintf(fk,"</kml>\n");
+
+ fclose(fk);
+
+ chmod( geo_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
+ chmod( kml_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
+ }
+
+
+ if ( debug_level & 512 )
+ fprintf(stderr,"Convert %s ==> %s\n", xpm_filename, png_filename );
+
+
+#ifdef HAVE_CONVERT
+ // Convert it to a png file. This depends upon having the
+ // ImageMagick command "convert" installed.
+ xastir_snprintf(command,
+ sizeof(command),
+ "%s -quality 100 -colors 256 %s %s",
+ CONVERT_PATH,
+ xpm_filename,
+ png_filename );
+
+ if ( system( command ) != 0 ) {
+ // We _may_ have had an error. Check errno to make
+ // sure.
+ if (errno) {
+ fprintf(stderr, "%s\n", strerror(errno));
+ fprintf(stderr,
+ "Failed to convert snapshot: %s -> %s\n",
+ xpm_filename,
+ png_filename);
+ }
+ else {
+ fprintf(stderr,
+ "System call return error: convert: %s -> %s\n",
+ xpm_filename,
+ png_filename);
+ }
+ }
+ else {
+ chmod( png_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
+
+// // Delete temporary xpm file
+// unlink( xpm_filename );
+
+ if ( debug_level & 512 )
+ fprintf(stderr," Done creating png.\n");
+ }
+
+#endif // HAVE_CONVERT
+
+ // Signify that we're all done and that another snapshot can
+ // occur.
+ doing_snapshot = 0;
+
+ return(NULL);
+}
+#endif // NO_XPM
+
+
+
+
+
+// Starts a separate thread that creates a png image from the
+// current displayed image.
+//
+void Snapshot(void) {
+#ifndef NO_XPM
+ pthread_t snapshot_thread_id;
+ char xpm_filename[MAX_FILENAME];
+ int xpmretval;
+#endif // NO_XPM
+ char temp_base_dir[MAX_VALUE];
+
+ get_user_base_dir("tmp", temp_base_dir, sizeof(temp_base_dir));
+
+
+ // Check whether we're already doing a snapshot
+ if (doing_snapshot)
+ return;
+
+ // Time to take another snapshot?
+ // New snapshot interval based on slider in Configure Timing
+ // dialog (in minutes)
+ if (sec_now() < (last_snapshot + (snapshot_interval * 60)) )
+ return;
+
+ last_snapshot = sec_now(); // Set up timer for next time
+
+
+#ifndef NO_XPM
+
+ if (debug_level & 512)
+ fprintf(stderr,"Taking Snapshot\n");
+
+ doing_snapshot++;
+
+ // Set up the XPM filename that we'll use
+ xastir_snprintf(xpm_filename,
+ sizeof(xpm_filename),
+ "%s/snapshot.xpm",
+ temp_base_dir);
+
+
+ if ( debug_level & 512 )
+ fprintf(stderr,"Creating %s\n", xpm_filename );
+
+ // Create an XPM file from pixmap_final.
+ chdir(temp_base_dir);
+ xpmretval=XpmWriteFileFromPixmap(XtDisplay(appshell), // Display *display
+ "snapshot.xpm", // char *filename
+ pixmap_final, // Pixmap pixmap
+ (Pixmap)NULL, // Pixmap shapemask
+ NULL );
+
+ if (xpmretval != XpmSuccess) {
+ fprintf(stderr,"ERROR writing %s: %s\n", xpm_filename,
+ XpmGetErrorString(xpmretval));
+ return;
+ }
+
+ chmod( xpm_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
+
+
+//----- Start New Thread -----
+
+ //
+ // Here we start a new thread. We'll communicate with the main
+ // thread via global variables. Use mutex locks if there might
+ // be a conflict as to when/how we're updating those variables.
+ //
+
+ if (pthread_create(&snapshot_thread_id, NULL, snapshot_thread, NULL)) {
+ fprintf(stderr,"Error creating snapshot thread\n");
+ }
+ else {
+ // We're off and running with the new thread!
+ }
+#endif // NO_XPM
+}
+
+
+
+
+
+// Function to remove double-quote characters and spaces that occur
+// outside of the double-quote characters.
+void clean_string(char *input) {
+ char *i;
+ char *j;
+
+
+ //fprintf(stderr,"|%s|\t",input);
+
+ // Remove any double quote characters
+ i = index(input,'"'); // Find first quote character, if any
+
+ if (i != NULL) {
+ j = index(i+1,'"'); // Find second quote character, if any
+
+ if (j != NULL) { // Found two quote characters
+ j[0] = '\0'; // Terminate the string at the 2nd quote
+ // Can't use strcpy here because it can't work with
+ // overlapping strings. strcpy is a dangerous function
+ // anyway and shouldn't be used.
+ memmove(input, i+1, j-i);
+ }
+ else { // We only found one quote character. What to do?
+// fprintf(stderr,"clean_string: Only one quote found!\n");
+ }
+ }
+ //fprintf(stderr,"|%s|\n",input);
+
+ // Remove leading/trailing spaces?
+}
+
+
+
+
+
+
+
+// Test map visibility (on screen)
+//
+// Input parameters are in Xastir coordinate system (fastest for us)
+// check_percentage:
+// 0 = don't check
+// 1 = check map size versus viewport scale. Return 0 if map
+// is too large/small (percentage-wise) to be displayed.
+//
+// Returns: MAP_NOT_VIS if map is _not_ visible
+// MAP_IS_VIS if map _is_ visible
+//
+// Xastir Coordinate System:
+//
+// 0 (90 deg. or 90N)
+//
+// 0 (-180 deg. or 180W) 129,600,000 (180 deg. or 180E)
+//
+// 64,800,000 (-90 deg. or 90S)
+//
+// Note that we already have map_visible() and map_visible_lat_lon()
+// routines.
+//
+enum map_onscreen_enum map_onscreen(long left,
+ long right,
+ long top,
+ long bottom,
+ int check_percentage) {
+
+ enum map_onscreen_enum in_window = MAP_NOT_VIS;
+
+
+ if (map_visible((unsigned long)bottom,
+ (unsigned long)top,
+ (unsigned long)left,
+ (unsigned long)right)) {
+ in_window = MAP_IS_VIS;
+ //fprintf(stderr,"map_onscreen:Map is visible\n");
+ }
+
+
+#ifdef MAP_SCALE_CHECK
+ // Check whether map is too large/small for our current scale?
+ // Check whether the map extents are < XX% of viewscreen size
+ // (both directions), or viewscreen is > XX% of map extents
+ // (either direction). This will knock out maps that are too
+ // large/small to be displayed at this zoom level.
+//WE7U
+ if (in_window && check_percentage) {
+ long map_x, map_y, view_x, view_y;
+ float percentage = 0.04;
+
+
+ map_x = right - left;
+ if (map_x < 0)
+ map_x = 0;
+
+ map_y = bottom - top;
+ if (map_y < 0)
+ map_y = 0;
+
+ view_x = max_NW_corner_longitude - NW_corner_longitude;
+ if (view_x < 0)
+ view_x = 0;
+
+ view_y = max_NW_corner_latitude - NW_corner_latitude;
+ if (view_y < 0)
+ view_y = 0;
+
+//fprintf(stderr,"\n map_x: %d\n", map_x);
+//fprintf(stderr," map_y: %d\n", map_y);
+//fprintf(stderr,"view_x: %d\n", view_x);
+//fprintf(stderr,"view_y: %d\n", view_y);
+
+ if ((map_x < (view_x * percentage )) && (map_y < (view_x * percentage))) {
+ in_window = 0; // Send back "not-visible" flag
+fprintf(stderr,"map too small for view: %d%%\n",(int)(percentage * 100));
+ }
+
+// if ((view_x < (map_x * percentage)) && (view_y < (map_x * percentage))) {
+// in_window = 0; // Send back "not-visible" flag
+//fprintf(stderr,"view too small for map: %d%%\n",(int)(percentage * 100));
+// }
+
+ }
+#endif // MAP_SCALE_CHECK
+
+ //fprintf(stderr,"map_onscreen returning %d\n", in_window);
+ return (in_window);
+}
+
+
+
+
+
+// Function which checks whether a map is onscreen, but does so by
+// finding the map boundaries from the map index. The only input
+// parameter is the complete path/filename.
+//
+// Returns: MAP_NOT_VIS if map is _not_ visible
+// MAP_IS_VIS if map _is_ visible
+// MAP_NOT_INDEXED if the map is not in the index
+//
+enum map_onscreen_enum map_onscreen_index(char *filename) {
+ unsigned long top, bottom, left, right;
+ enum map_onscreen_enum onscreen = MAP_NOT_INDEXED;
+ int max_zoom, min_zoom;
+ int map_layer, draw_filled, usgs_drg, auto_maps; // Unused in this function
+
+
+ if (index_retrieve(filename, &bottom, &top, &left, &right,
+ &max_zoom, &min_zoom, &map_layer,
+ &draw_filled, &usgs_drg, &auto_maps) ) {
+
+ //fprintf(stderr, "Map found in index: %s\n", filename);
+
+ // Map was in the index, check for visibility and scale
+ // Check whether the map extents are < XX% of viewscreen
+ // size (both directions), or viewscreen is > XX% of map
+ // extents (either direction). This will knock out maps
+ // that are too large/small to be displayed at this zoom
+ // level.
+ if (map_onscreen(left, right, top, bottom, 1)) {
+
+ //fprintf(stderr, "Map found in index and onscreen: %s\n", filename);
+
+ if (((max_zoom == 0) ||
+ ((max_zoom != 0) && (scale_y <= max_zoom))) &&
+ ((min_zoom == 0) ||
+ ((min_zoom != 0) && (scale_y >= min_zoom)))) {
+
+ onscreen = MAP_IS_VIS;
+ //fprintf(stderr,"Map in the zoom zone: %s\n",filename);
+ }
+ else {
+ onscreen = MAP_NOT_VIS;
+ //fprintf(stderr,"Map not in the zoom zone: %s\n",filename);
+ }
+
+// Check whether the map extents are < XX% of viewscreen size (both
+// directions), or viewscreen is > XX% of map extents (either
+// direction). This will knock out maps that are too large/small to
+// be displayed at this zoom level.
+
+
+ }
+ else { // Map is not visible
+ onscreen = MAP_NOT_VIS;
+ //fprintf(stderr,"Map found in index but not onscreen: %s\n",filename);
+ }
+ }
+ else { // Map is not in the index
+ onscreen = MAP_NOT_INDEXED;
+ //fprintf(stderr,"Map not found in index: %s\n",filename);
+ }
+ return(onscreen);
+}
+
+
+
+
+
+/**********************************************************
+ * draw_map()
+ *
+ * Function which tries to figure out what type of map or
+ * image file we're dealing with, and takes care of getting
+ * it onto the screen. Calls other functions to deal with
+ * .geo/.tif/.shp maps.
+ *
+ * If destination_pixmap == DRAW_NOT, then we'll not draw
+ * the map anywhere, but we'll determine the map extents
+ * and write them to the map index file.
+ **********************************************************/
+/* table of map drivers, selected by filename extension */
+extern void draw_dos_map(Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *draw_flags);
+
+extern void draw_palm_image_map(Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *draw_flags);
+
+#ifdef HAVE_LIBSHP
+extern void draw_shapefile_map (Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *draw_flags);
+#ifdef WITH_DBFAWK
+extern void clear_dbfawk_sigs(void);
+#endif /* WITH_DBFAWK */
+#endif /* HAVE_LIBSHP */
+#ifdef HAVE_LIBGEOTIFF
+extern void draw_geotiff_image_map(Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *draw_flags);
+#endif /* HAVE_LIBGEOTIFF */
+extern void draw_geo_image_map(Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *draw_flags);
+
+extern void draw_gnis_map(Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *draw_flags);
+
+extern void draw_pop_map(Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *draw_flags);
+
+#ifdef HAVE_LIBGDAL
+extern void draw_gdal_map(Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *draw_flags);
+
+extern void draw_ogr_map(Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *draw_flags);
+#endif /* HAVE_LIBGDAL */
+
+struct {
+ char *ext;
+ enum {none=0, map, pdb, tif, geo, gnis, shp, tiger, mapinfo, dgn, sdts, s57, pop} type;
+ void (*func)(Widget w,
+ char *dir,
+ char *filenm,
+ alert_entry *alert,
+ u_char alert_color,
+ int destination_pixmap,
+ map_draw_flags *draw_flags);
+} map_driver[] = {
+ {"map",map,draw_dos_map},
+ {"pdb",pdb,draw_palm_image_map},
+
+#ifdef HAVE_LIBGEOTIFF
+ {"tif",tif,draw_geotiff_image_map},
+#endif /* HAVE_LIBGEOTIFF */
+
+ {"geo",geo,draw_geo_image_map},
+ {"gnis",gnis,draw_gnis_map},
+ {"pop",pop,draw_pop_map},
+
+#ifdef HAVE_LIBSHP
+#ifndef GDAL_SHAPEFILES
+ {"shp",shp,draw_shapefile_map},
+#endif // GDAL_SHAPEFILES
+#endif /* HAVE_LIBSHP */
+
+#ifdef HAVE_LIBGDAL
+
+#ifdef GDAL_SHAPEFILES
+ {"shp",shp,draw_ogr_map},
+#endif // GDAL_SHAPEFILES
+
+ {"rt1",tiger,draw_ogr_map},
+// {"rt2",tiger,draw_ogr_map},
+// {"rt4",tiger,draw_ogr_map},
+// {"rt5",tiger,draw_ogr_map},
+// {"rt6",tiger,draw_ogr_map},
+// {"rt7",tiger,draw_ogr_map},
+// {"rt8",tiger,draw_ogr_map},
+// {"rta",tiger,draw_ogr_map},
+// {"rtc",tiger,draw_ogr_map},
+// {"rth",tiger,draw_ogr_map},
+// {"rti",tiger,draw_ogr_map},
+// {"rtp",tiger,draw_ogr_map},
+// {"rtr",tiger,draw_ogr_map},
+// {"rts",tiger,draw_ogr_map},
+// {"rtt",tiger,draw_ogr_map},
+// {"rtz",tiger,draw_ogr_map},
+ {"tab",mapinfo,draw_ogr_map}, // MapInfo
+ {"mid",mapinfo,draw_ogr_map}, // MapInfo
+ {"mif",mapinfo,draw_ogr_map}, // MapInfo
+ {"dgn",dgn,draw_ogr_map}, // DGN
+ {"ddf",sdts,draw_ogr_map}, // SDTS
+ {"s57",s57,draw_ogr_map}, // S57
+#endif // HAVE_LIBGDAL
+
+ {NULL,none,NULL}
+}, *map_driver_ptr;
+
+
+
+
+
+void draw_map (Widget w, char *dir, char *filenm, alert_entry *alert,
+ u_char alert_color, int destination_pixmap,
+ map_draw_flags *draw_flags) {
+ enum map_onscreen_enum onscreen;
+ char *ext;
+ char file[MAX_FILENAME];
+
+ if ((ext = get_map_ext(filenm)) == NULL)
+ return;
+
+ if (debug_level & 16)
+ fprintf(stderr,"draw_map: Searching for map driver\n");
+
+ for (map_driver_ptr = map_driver; map_driver_ptr->ext; map_driver_ptr++) {
+ if (strcasecmp(ext,map_driver_ptr->ext) == 0) {
+ if (debug_level & 16)
+ fprintf(stderr,
+ "draw_map: Found map driver: %s: %d\n",
+ ext,
+ map_driver_ptr->type);
+ break; /* found our map_driver */
+ }
+ }
+ if (map_driver_ptr->type == none) { /* fall thru: unknown map driver */
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap != INDEX_CHECK_TIMESTAMPS)
+ && (destination_pixmap != INDEX_NO_TIMESTAMPS) ) {
+ // We're drawing, not indexing. Output a warning
+ // message.
+ fprintf(stderr,"*** draw_map: Unknown map type: %s ***\n", filenm);
+ }
+ else { // We're indexing
+ if (debug_level & 16)
+ fprintf(stderr,"draw_map: No map driver found\n");
+ }
+ return;
+ }
+
+ onscreen = map_onscreen_index(filenm); // Check map index
+
+ // Check whether we're indexing or drawing the map
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+
+ // We're indexing maps
+ if (onscreen != MAP_NOT_INDEXED) // We already have an index entry for this map.
+ // This is where we pick up a big speed increase:
+ // Refusing to index a map that's already indexed.
+ return; // Skip it.
+ }
+ else { // We're drawing maps
+ // See if map is visible. If not, skip it.
+ if (onscreen == MAP_NOT_VIS) { // Map is not visible, skip it.
+ //fprintf(stderr,"map not visible\n");
+ if (alert) alert->flags[on_screen] = 'N';
+ return;
+ }
+ }
+
+
+ xastir_snprintf(file, sizeof(file), "%s/%s", dir, filenm);
+
+ // Used for debugging. If we get a segfault on a map, this is
+ // often the only way of finding out which map file we can't
+ // handle.
+ if (debug_level & 16)
+ fprintf(stderr,"draw_map: %s\n",file);
+
+ /* XXX - aren't alerts just shp maps? Why was there special case code? */
+
+ if (map_driver_ptr->func) {
+ map_driver_ptr->func(w,
+ dir,
+ filenm,
+ alert,
+ alert_color,
+ destination_pixmap,
+ draw_flags);
+ }
+
+ XmUpdateDisplay (XtParent (da));
+} // End of draw_map()
+
+
+
+
+
+static void index_update_directory(char *directory);
+static void index_update_accessed(char *filename);
+
+
+
+
+
+/////////////////////////////////////////////////////////////////////
+// map_search()
+//
+// Function which recurses through map directories, finding map
+// files. It's called from load_auto_maps and load_alert_maps. If
+// a map file is found, it is drawn. We can also call this function
+// in indexing mode rather than draw mode, specified by the
+// destination_pixmap parameter.
+//
+// If alert == NULL, we looking for a regular map file to draw.
+// If alert != NULL, we have a weather alert to draw.
+//
+// For alert maps, we need to do things a bit differently, as there
+// should be only a few maps that contain all of the alert maps, and we
+// can compute which map some of them might be in. We need to fill in
+// the alert structure with the filename that alert is found in.
+// For alerts we're not drawing the maps, we're just computing the
+// full filename for the alert and filling that struct field in.
+//
+// The "warn" parameter specifies whether to warn the operator about
+// the alert on the console as well. If it was received locally or
+// via local RF, then the answer is yes. The severe weather may be
+// nearby.
+//
+// We have the timestamp of the map_index.sys file stored away in
+// the global: time_t map_index_timestamp;
+// Use that timestamp to compare the map file or GEO file timestamps
+// to. Re-index the map if map_index_timestamp is older.
+//
+/////////////////////////////////////////////////////////////////////
+static void map_search (Widget w, char *dir, alert_entry * alert, int *alert_count,int warn, int destination_pixmap) {
+ struct dirent *dl = NULL;
+ DIR *dm;
+ char fullpath[MAX_FILENAME];
+ struct stat nfile;
+// const time_t *ftime;
+// char this_time[40];
+ char *ptr;
+ char *map_dir;
+ int map_dir_length;
+ map_draw_flags mdf;
+
+ // We'll use the weather alert directory if it's an alert
+ map_dir = alert ? ALERT_MAP_DIR : SELECTED_MAP_DIR;
+
+ map_dir_length = (int)strlen (map_dir);
+
+ if (alert) { // We're doing weather alerts
+ // First check whether the alert->filename variable is filled
+ // in. If so, we've already found the file and can just display
+ // that shape in the file
+ if (alert->filename[0] == '\0') { // No filename in struct, so will have
+ // to search for the shape in the files.
+ switch (alert->title[3]) {
+ case 'F': // 'F' in 4th char means fire alert
+ // Use fire alert file fz_??????
+ //fprintf(stderr,"%c:Fire Alert file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "fz");
+ break;
+
+ case 'C': // 'C' in 4th char means county
+ // Use County file c_??????
+ //fprintf(stderr,"%c:County file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "c_");
+ break;
+ case 'A': // 'A' in 4th char means county warning area
+ // Use County warning area w_?????
+ //fprintf(stderr,"%c:County warning area file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "w_");
+ break;
+ case 'Z':
+ // Zone, coastal or offshore marine zone file z_????? or mz?????? or oz??????
+ // oz: ANZ081-086,088,PZZ081-085
+ // mz: AM,AN,GM,LC,LE,LH,LM,LO,LS,PH,PK,PM,PS,PZ,SL
+ // z_: All others
+ if (strncasecmp(alert->title,"AM",2) == 0) {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ else if (strncasecmp(alert->title,"AN",2) == 0) {
+ // Need to check for Z081-Z086, Z088, if so use
+ // oz??????, else use mz??????
+ if ( (strncasecmp(&alert->title[3],"Z081",4) == 0)
+ || (strncasecmp(&alert->title[3],"Z082",4) == 0)
+ || (strncasecmp(&alert->title[3],"Z083",4) == 0)
+ || (strncasecmp(&alert->title[3],"Z084",4) == 0)
+ || (strncasecmp(&alert->title[3],"Z085",4) == 0)
+ || (strncasecmp(&alert->title[3],"Z086",4) == 0)
+ || (strncasecmp(&alert->title[3],"Z088",4) == 0) ) {
+ //fprintf(stderr,"%c:Offshore marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "oz");
+ }
+ else {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ }
+ else if (strncasecmp(alert->title,"GM",2) == 0) {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ else if (strncasecmp(alert->title,"LC",2) == 0) {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ else if (strncasecmp(alert->title,"LE",2) == 0) {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ else if (strncasecmp(alert->title,"LH",2) == 0) {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ else if (strncasecmp(alert->title,"LM",2) == 0) {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ else if (strncasecmp(alert->title,"LO",2) == 0) {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ else if (strncasecmp(alert->title,"LS",2) == 0) {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ else if (strncasecmp(alert->title,"PH",2) == 0) {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ else if (strncasecmp(alert->title,"PK",2) == 0) {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ else if (strncasecmp(alert->title,"PM",2) == 0) {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ else if (strncasecmp(alert->title,"PS",2) == 0) {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ else if (strncasecmp(alert->title,"PZ",2) == 0) {
+// Need to check for PZZ081-085, if so use oz??????, else use mz??????
+ if ( (strncasecmp(&alert->title[3],"Z081",4) == 0)
+ || (strncasecmp(&alert->title[3],"Z082",4) == 0)
+ || (strncasecmp(&alert->title[3],"Z083",4) == 0)
+ || (strncasecmp(&alert->title[3],"Z084",4) == 0)
+ || (strncasecmp(&alert->title[3],"Z085",4) == 0) ) {
+ //fprintf(stderr,"%c:Offshore marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "oz");
+ }
+ else {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ }
+ else if (strncasecmp(alert->title,"SL",2) == 0) {
+ //fprintf(stderr,"%c:Coastal marine zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "mz");
+ }
+ else {
+ // Must be regular zone file instead of coastal
+ // marine zone or offshore marine zone.
+ //fprintf(stderr,"%c:Zone file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "z_");
+ }
+ break;
+
+ default:
+// VK2XJG
+// This section could most likely be moved so that it's not called as part of the default, but in order
+// to get the shapefiles for BOM working this was the best spot at the time...
+ // Australian BOM alerts use the following shapefiles:
+ // PW = Public Warning = gfe_public_weather
+ // MW = Coastal Waters = gfe_coastal_waters
+ // CW = Coastal Waters Warnings = gfe_coastal_waters_warnings
+ // FW = Fire Weather = gfe_fire_weather
+ // ME = Metro Effects = gfe_metro_areas
+ // Note - Need to cater for both 2 and 3 character state designators
+ // Shapefile filenames are static - there is no datestamp in the filename.
+ if ((strncasecmp(&alert->title[4],"MW",2) == 0) || (strncasecmp(&alert->title[3],"MW",2) == 0)) {
+ //fprintf(stderr,"%c:BOM Coastal Waters file\n",alert->title[4]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "gfe_coastal_waters.shp");
+ }
+ else if ((strncasecmp(&alert->title[4],"CW",2) == 0) || (strncasecmp(&alert->title[3],"CW",2) == 0)) {
+ //fprintf(stderr,"%c:BOM Coastal waters warning file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "gfe_coastal_waters_warnings.shp");
+ }
+ else if ((strncasecmp(&alert->title[4],"PW",2) == 0) || (strncasecmp(&alert->title[3],"PW",2) == 0)) {
+ //fprintf(stderr,"%c:BOM Public Weather file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "gfe_public_weather.shp");
+ }
+ else if ((strncasecmp(&alert->title[4],"FW",2) == 0) || (strncasecmp(&alert->title[3],"FW",2) == 0)) {
+ //fprintf(stderr,"%c:BOM Fire Weather file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "gfe_fire_weather.shp");
+ }
+ else if ((strncasecmp(&alert->title[4],"ME",2) == 0) || (strncasecmp(&alert->title[3],"ME",2) == 0)) {
+ //fprintf(stderr,"%c:BOM Metro Areas file\n",alert->title[3]);
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "gfe_metro_areas.shp");
+ }
+
+
+
+ // Unknown type
+//fprintf(stderr,"%c:Can't match weather warning to a Shapefile:%s\n",alert->title[3],alert->title);
+ break;
+ }
+// fprintf(stderr,"%s\t%s\t%s\n",alert->activity,alert->alert_status,alert->title);
+ //fprintf(stderr,"File: %s\n",alert->filename);
+ }
+
+// NOTE: Need to skip this part if we have a full filename.
+
+ if (alert->filename[0]) { // We have at least a partial filename
+ int done = 0;
+
+ if (strlen(alert->filename) > 3)
+ done++; // We already have a filename
+
+ if (!done) { // We don't have a filename yet
+
+ // Look through the warning directory to find a match for
+ // the first few characters that we already figured out.
+ // This is designed so that we don't need to know the exact
+ // filename, but only the lead three characters in order to
+ // figure out which shapefile to use.
+ dm = opendir (dir);
+ if (!dm) { // Couldn't open directory
+ xastir_snprintf(fullpath, sizeof(fullpath), "aprsmap %s", dir);
+ // If local alert, warn the operator via the
+ // console as well.
+ if (warn)
+ perror (fullpath);
+ }
+ else { // We could open the directory just fine
+ while ( (dl = readdir(dm)) && !done ) {
+ int i;
+
+ // Check the file/directory name for control
+ // characters
+ for (i = 0; i < (int)strlen(dl->d_name); i++) {
+ // Dump out a warning if control
+ // characters other than LF or CR are
+ // found.
+ if ( (dl->d_name[i] != '\n')
+ && (dl->d_name[i] != '\r')
+ && (dl->d_name[i] < 0x20) ) {
+
+ fprintf(stderr,"\nmap_search: Found control char 0x%02x in alert file/alert directory name. Line was:\n",
+ dl->d_name[i]);
+ fprintf(stderr,"%s\n",dl->d_name);
+ }
+/*
+// This part might not work 'cuz we'd be changing a memory area that
+// we might have only read access to. Check this.
+ if (dl->d_name[i] < 0x20) {
+ // Terminate string at any control character
+ dl->d_name[i] = '\0';
+ }
+*/
+ }
+
+ xastir_snprintf(fullpath, sizeof(fullpath), "%s%s", dir, dl->d_name);
+ /*fprintf(stderr,"FULL PATH %s\n",fullpath); */
+ if (stat (fullpath, &nfile) == 0) {
+// ftime = (time_t *)&nfile.st_ctime;
+ switch (nfile.st_mode & S_IFMT) {
+ case (S_IFDIR): // It's a directory, skip it
+ break;
+
+ case (S_IFREG): // It's a file, check it
+ /*fprintf(stderr,"FILE %s\n",dl->d_name); */
+ // Here we look for a match for the
+ // first 2 characters of the filename.
+ //
+ if (strncasecmp(alert->filename,dl->d_name,2) == 0) {
+ // We have a match for the
+ // first few characters.
+ // Check that last three are
+ // "shp"
+
+ //fprintf(stderr,"%s\n",fullpath);
+
+ if ( (dl->d_name[strlen(dl->d_name)-3] == 's'
+ || dl->d_name[strlen(dl->d_name)-3] == 'S')
+ && (dl->d_name[strlen(dl->d_name)-2] == 'h'
+ || dl->d_name[strlen(dl->d_name)-2] == 'H')
+ && (dl->d_name[strlen(dl->d_name)-1] == 'p'
+ || dl->d_name[strlen(dl->d_name)-1] == 'P') ) {
+ // We have an exact match.
+ // Save the filename in the alert
+ xastir_snprintf(alert->filename,
+ sizeof(alert->filename),
+ "%s",
+ dl->d_name);
+ done++;
+ //fprintf(stderr,"%s\n",dl->d_name);
+ }
+ }
+ break;
+
+ default: // Not dir or file, skip it
+ break;
+ }
+ }
+ }
+ }
+ (void)closedir (dm);
+ }
+
+ if (done) { // We found a filename match for the alert
+ // Go draw the weather alert (kind'a)
+//WE7U
+ mdf.draw_filled=1;
+ mdf.usgs_drg=0;
+
+ if (debug_level & 16)
+ fprintf(stderr,"map_search: calling draw_map for an alert\n");
+
+ draw_map (w,
+ dir, // Alert directory
+ alert->filename, // Shapefile filename
+ alert,
+ -1, // Signifies "DON'T DRAW THE SHAPE"
+ destination_pixmap,
+ &mdf );
+
+ if (debug_level & 16)
+ fprintf(stderr,"map_search: returned from draw_map\n");
+
+ }
+ else { // No filename found that matches the first two
+ // characters that we already computed.
+
+ //
+ // Need code here
+ //
+
+ }
+ }
+ else { // Still no filename for the weather alert.
+ // Output an error message?
+ //
+ // Need code here
+ //
+
+ }
+ }
+
+
+// MAPS, not alerts
+
+ else { // We're doing regular maps, not weather alerts
+ time_t map_timestamp;
+
+
+ dm = opendir (dir);
+ if (!dm) { // Couldn't open directory
+ xastir_snprintf(fullpath, sizeof(fullpath), "aprsmap %s", dir);
+ if (warn)
+ perror (fullpath);
+ }
+ else {
+ int count = 0;
+ while ((dl = readdir (dm))) {
+ int i;
+
+ // Check the file/directory name for control
+ // characters
+ for (i = 0; i < (int)strlen(dl->d_name); i++) {
+ // Dump out a warning if control characters
+ // other than LF or CR are found.
+ if ( (dl->d_name[i] != '\n')
+ && (dl->d_name[i] != '\r')
+ && (dl->d_name[i] < 0x20) ) {
+
+ fprintf(stderr,"\nmap_search: Found control char 0x%02x in map file/map directory name. Line was:\n",
+ dl->d_name[i]);
+ fprintf(stderr,"%s\n",dl->d_name);
+ }
+/*
+// This part might not work 'cuz we'd be changing a memory area that
+// we might have only read access to. Check this.
+ if (dl->d_name[i] < 0x20) {
+ // Terminate string at any control character
+ dl->d_name[i] = '\0';
+ }
+*/
+ }
+
+ xastir_snprintf(fullpath, sizeof(fullpath), "%s/%s", dir, dl->d_name);
+ //fprintf(stderr,"FULL PATH %s\n",fullpath);
+ if (stat (fullpath, &nfile) == 0) {
+// ftime = (time_t *)&nfile.st_ctime;
+ switch (nfile.st_mode & S_IFMT) {
+ case (S_IFDIR): // It's a directory, recurse
+ //fprintf(stderr,"file %c letter %c\n",dl->d_name[0],letter);
+ if ((strcmp (dl->d_name, ".") != 0) && (strcmp (dl->d_name, "..") != 0)) {
+
+ //fprintf(stderr,"FULL PATH %s\n",fullpath);
+
+ // If we're indexing, throw the
+ // directory into the map index as
+ // well.
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {
+ char temp_dir[MAX_FILENAME];
+
+ // Drop off the base part of the
+ // path for the indexing,
+ // usually
+ // "/usr/local/share/xastir/maps".
+ // Add a '/' to the end.
+ xastir_snprintf(temp_dir,
+ sizeof(temp_dir),
+ "%s/",
+ &fullpath[map_dir_length+1]);
+
+ // Add the directory to the
+ // in-memory map index.
+ index_update_directory(temp_dir);
+ }
+
+// xastir_snprintf(this_time,
+// sizeof(this_time),
+// "%s",
+// ctime(ftime));
+ map_search(w, fullpath, alert, alert_count, warn, destination_pixmap);
+ }
+ break;
+
+ case (S_IFREG): // It's a file, draw the map
+ /*fprintf(stderr,"FILE %s\n",dl->d_name); */
+
+ // Get the last-modified timestamp for the map file
+ //map_timestamp = (time_t)nfile.st_mtime;
+ map_timestamp =
+ (time_t)( (nfile.st_mtime>nfile.st_ctime) ? nfile.st_mtime : nfile.st_ctime );
+
+
+ // Check whether we're doing indexing or
+ // map drawing. If indexing, we only
+ // want to index if the map timestamp is
+ // newer than the index timestamp.
+ if (destination_pixmap == INDEX_CHECK_TIMESTAMPS
+ || destination_pixmap == INDEX_NO_TIMESTAMPS) {
+ // We're doing indexing, not map drawing
+ char temp_dir[MAX_FILENAME];
+
+ // Drop off the base part of the
+ // path for the indexing, usually
+ // "/usr/local/share/xastir/maps".
+ xastir_snprintf(temp_dir,
+ sizeof(temp_dir),
+ "%s",
+ &fullpath[map_dir_length+1]);
+
+ // Update the "accessed"
+ // variable in the record
+ index_update_accessed(temp_dir);
+
+// Note: This is not as efficient as it should be, as we're looking
+// through the in-memory map index here just to update the
+// "accessed" variable, then in some cases looking through it again
+// in the next section for updated maps, or if we're ignoring
+// timestamps while indexing. Looking through a linear linked list
+// too many times overall.
+
+ if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
+ && (map_timestamp < map_index_timestamp) ) {
+ // Map is older than index _and_
+ // we're supposed to check
+ // timestamps.
+ count++;
+ break; // Skip indexing this file
+ }
+ else { // Map is newer or we're ignoring timestamps.
+ // We'll index the map
+ if (debug_level & 16) {
+ fprintf(stderr,"Indexing map: %s\n",fullpath);
+ }
+ }
+ }
+
+ // Check whether the file is in a subdirectory
+ if (strncmp (fullpath, map_dir, (size_t)map_dir_length) != 0) {
+
+ if (debug_level & 16) {
+ fprintf(stderr,"Calling draw_map\n");
+ }
+ mdf.draw_filled=1;
+ mdf.usgs_drg=0;
+
+ draw_map (w,
+ dir,
+ dl->d_name,
+ alert ? &alert[*alert_count] : NULL,
+ '\0',
+ destination_pixmap,
+ &mdf );
+
+ if (debug_level & 16) {
+ fprintf(stderr,"Returned from draw_map\n");
+ }
+ if (alert_count && *alert_count)
+ (*alert_count)--;
+ }
+ else {
+ // File is in the main map directory
+ // Find the '/' character
+ for (ptr = &fullpath[map_dir_length]; *ptr == '/'; ptr++) ;
+ mdf.draw_filled=1;
+ mdf.usgs_drg=0;
+
+ if (debug_level & 16)
+ fprintf(stderr,"Calling draw_map\n");
+
+ draw_map (w,
+ map_dir,
+ ptr,
+ alert ? &alert[*alert_count] : NULL,
+ '\0',
+ destination_pixmap,
+ &mdf );
+
+ if (alert_count && *alert_count)
+ (*alert_count)--;
+ }
+ count++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ if (debug_level & 16)
+ fprintf(stderr,"Number of maps queried: %d\n", count);
+
+ (void)closedir (dm);
+ }
+ }
+}
+
+
+
+
+
+// List pointer for the map index linked list.
+map_index_record *map_index_head = NULL;
+
+// Might wish to have another variable in the index which is used to
+// record that a file has been indexed recently. This could be used
+// to prune old entries out of the index if a full indexing didn't
+// touch a file entry. Could also delete an entry from the index
+// if/when a file can't be opened?
+
+
+
+
+
+// Function to dissect and free all of the records in a map index
+// linked list, leaving it totally empty.
+//
+static void free_map_index(map_index_record *index_list_head) {
+ map_index_record *current;
+ map_index_record *temp;
+
+
+ current = index_list_head;
+
+ while (current != NULL) {
+ temp = current;
+ if (current->XmStringPtr != NULL) {
+ XmStringFree(current->XmStringPtr);
+ }
+ current = current->next;
+ free(temp);
+ }
+
+ index_list_head = NULL;
+}
+
+
+
+
+
+// Function to copy just the properties fields from the backup map
+// index to the primary index. Must match each record before
+// copying. Once it's done, it frees the backup map index.
+//
+static void map_index_copy_properties(map_index_record *primary_index_head,
+ map_index_record *backup_index_head) {
+ map_index_record *primary;
+ map_index_record *backup;
+
+
+ backup = backup_index_head;
+
+ // Walk the backup list, comparing the filename field with the
+ // primary list. When a match is found, copy just the
+ // Properties fields (map_layer/draw_filled/auto_maps/selected)
+ // across to the primary record.
+ //
+ while (backup != NULL) {
+ int done = 0;
+
+ primary = primary_index_head;
+
+ while (!done && primary != NULL) {
+
+ if (strcmp(primary->filename, backup->filename) == 0) { // If match
+
+ if (debug_level & 16) {
+ fprintf(stderr,"Match: %s\t%s\n",
+ primary->filename,
+ backup->filename);
+ }
+
+ // Copy the Properties across
+ primary->max_zoom = backup->max_zoom;
+ primary->min_zoom = backup->min_zoom;
+ primary->map_layer = backup->map_layer;
+ primary->draw_filled = backup->draw_filled;
+ primary->usgs_drg = backup->usgs_drg;
+ primary->auto_maps = backup->auto_maps;
+ primary->selected = backup->selected;
+
+ // Done copying this backup record. Go on to the
+ // next. Skip the rest of the primary list for this
+ // iteration.
+ done++;
+ }
+ else { // No match, walk the primary list looking for one.
+ primary = primary->next;
+ }
+ }
+
+ // Walk the backup list
+ backup = backup->next;
+ }
+
+ // We're done copying. Free the backup list.
+ free_map_index(backup_index_head);
+}
+
+
+
+
+
+// Function used to add map directories to the in-memory map index.
+// Causes an update of the index list in memory. Input Records are
+// inserted in alphanumerical order. We mark directories in the
+// index with a '/' on the end of the name, and zero entries for
+// top/bottom/left/right.
+// The input directory to this routine MUST have a '/' character on
+// the end of it. This is how we differentiate directories from
+// files in the list.
+static void index_update_directory(char *directory) {
+
+ map_index_record *current = map_index_head;
+ map_index_record *previous = map_index_head;
+ map_index_record *temp_record = NULL;
+ int done = 0;
+ int i;
+
+
+ //fprintf(stderr,"index_update_directory: %s\n", directory );
+
+ // Check for initial bad input
+ if ( (directory == NULL)
+ || (directory[0] == '\0')
+ || (directory[strlen(directory) - 1] != '/')
+ || ( (directory[1] == '/') && (strlen(directory) == 1)) ) {
+ fprintf(stderr,"index_update_directory: Bad input: %s\n",directory);
+ return;
+ }
+ // Make sure there aren't any weird characters in the directory
+ // that might cause problems later. Look for control characters
+ // and convert them to string-end characters.
+ for ( i = 0; i < (int)strlen(directory); i++ ) {
+ // Change any control characters to '\0' chars
+ if (directory[i] < 0x20) {
+
+ fprintf(stderr,"\nindex_update_directory: Found control char 0x%02x in map file/map directory name:\n%s\n",
+ directory[i],
+ directory);
+
+ directory[i] = '\0'; // Terminate it here
+ }
+ }
+ // Check if the string is _now_ bogus
+ if ( (directory[0] == '\0')
+ || (directory[strlen(directory) - 1] != '/')
+ || ( (directory[1] == '/') && (strlen(directory) == 1))) {
+ fprintf(stderr,"index_update_directory: Bad input: %s\n",directory);
+ return;
+ }
+
+ //if (map_index_head == NULL)
+ // fprintf(stderr,"Empty list\n");
+
+ // Search for a matching directory name in the linked list
+ while ((current != NULL) && !done) {
+ int test;
+
+ //fprintf(stderr,"Comparing %s to\n %s\n",
+ // current->filename, directory);
+
+ test = strcmp(current->filename, directory);
+ if (test == 0) {
+ // Found a match!
+ //fprintf(stderr,"Found: Updating entry for %s\n",directory);
+ temp_record = current;
+ done++; // Exit loop, "current" points to found record
+ }
+ else if (test > 0) { // Found a string past us in the
+ // alphabet. Insert ahead of this
+ // last record.
+
+ //fprintf(stderr,"\n%s\n%s\n",current->filename,directory);
+
+ //fprintf(stderr,"Not Found: Inserting an index record for %s\n",directory);
+ temp_record = (map_index_record *)malloc(sizeof(map_index_record));
+ CHECKMALLOC(temp_record);
+
+ if (current == map_index_head) { // Start of list!
+ // Insert new record at head of list
+ temp_record->next = map_index_head;
+ map_index_head = temp_record;
+ //fprintf(stderr,"Inserting at head of list\n");
+ }
+ else { // Insert between "previous" and "current"
+ // Insert new record before "current"
+ previous->next = temp_record;
+ temp_record->next = current;
+ //fprintf(stderr,"Inserting before current\n");
+ }
+
+ //fprintf(stderr,"Adding:%d:%s\n",strlen(directory),directory);
+
+ // Fill in some default values for the new record.
+ temp_record->selected = 0;
+ temp_record->auto_maps = 0;
+ temp_record->XmStringPtr = NULL;
+
+ //current = current->next;
+ done++;
+ }
+ else { // Haven't gotten to the correct insertion point yet
+ previous = current; // Save ptr to last record
+ current = current->next;
+ }
+ }
+
+ if (!done) { // Matching record not found, add a record to
+ // the end of the list. "previous" points to
+ // the last record in the list or NULL (empty
+ // list).
+ //fprintf(stderr,"Not Found: Adding an index record for %s\n",directory);
+ temp_record = (map_index_record *)malloc(sizeof(map_index_record));
+ CHECKMALLOC(temp_record);
+
+ temp_record->next = NULL;
+
+ if (previous == NULL) { // Empty list
+ map_index_head = temp_record;
+ //fprintf(stderr,"First record in new list\n");
+ }
+ else { // Else at end of list
+ previous->next = temp_record;
+ //fprintf(stderr,"Adding to end of list: %s\n",directory);
+ }
+
+ //fprintf(stderr,"Adding:%d:%s\n",strlen(directory),directory);
+
+ // Fill in some default values for the new record.
+ temp_record->selected = 0;
+ temp_record->auto_maps = 0;
+ temp_record->XmStringPtr = NULL;
+ }
+
+ // Update the values. By this point we have a struct to fill
+ // in, whether it's a new or old struct doesn't matter. Convert
+ // the values from lat/long to Xastir coordinate system.
+ xastir_snprintf(temp_record->filename,MAX_FILENAME,"%s",directory);
+
+ temp_record->bottom = 0;
+ temp_record->top = 0;
+ temp_record->left = 0;
+ temp_record->right = 0;
+ temp_record->accessed = 1;
+ temp_record->max_zoom = 0;
+ temp_record->min_zoom = 0;
+ temp_record->map_layer = 0;
+ temp_record->draw_filled = 0;
+ temp_record->usgs_drg = 2;
+}
+
+
+
+
+
+// Function called by the various draw_* functions when in indexing
+// mode. Causes an update of the index list in memory. Input
+// parameters are in the Xastir coordinate system due to speed
+// considerations. Records are inserted in alphanumerical order.
+void index_update_xastir(char *filename,
+ unsigned long bottom,
+ unsigned long top,
+ unsigned long left,
+ unsigned long right,
+ int default_map_layer) {
+
+ map_index_record *current = map_index_head;
+ map_index_record *previous = map_index_head;
+ map_index_record *temp_record = NULL;
+ int done = 0;
+ int i;
+
+
+ // Check for initial bad input
+ if ( (filename == NULL)
+ || (filename[0] == '\0')
+ || (filename[strlen(filename) - 1] == '/') ) {
+ fprintf(stderr,"index_update_xastir: Bad input: %s\n",filename);
+ return;
+ }
+ // Make sure there aren't any weird characters in the filename
+ // that might cause problems later. Look for control characters
+ // and convert them to string-end characters.
+ for ( i = 0; i < (int)strlen(filename); i++ ) {
+ // Change any control characters to '\0' chars
+ if (filename[i] < 0x20) {
+
+ fprintf(stderr,"\nindex_update_xastir: Found control char 0x%02x in map file/map directory name:\n%s\n",
+ filename[i],
+ filename);
+
+ filename[i] = '\0'; // Terminate it here
+ }
+ }
+ // Check if the string is _now_ bogus
+ if (filename[0] == '\0') {
+ fprintf(stderr,"index_update_xastir: Bad input: %s\n",filename);
+ return;
+ }
+
+ //fprintf(stderr,"index_update_xastir: (%lu,%lu)\t(%lu,%lu)\t%s\n",
+ // bottom, top, left, right, filename );
+
+ //if (map_index_head == NULL)
+ // fprintf(stderr,"Empty list\n");
+
+ // Skip dbf and shx map extensions. Really should make this
+ // case-independent...
+ if ( strstr(filename,"shx")
+ || strstr(filename,"dbf")
+ || strstr(filename,"SHX")
+ || strstr(filename,"DBF") ) {
+ return;
+ }
+
+ // Search for a matching filename in the linked list
+ while ((current != NULL) && !done) {
+ int test;
+
+ //fprintf(stderr,"Comparing %s to\n %s\n",current->filename,filename);
+
+ test = strcmp(current->filename,filename);
+ if (test == 0) {
+ // Found a match!
+ //fprintf(stderr,"Found: Updating entry for %s\n",filename);
+ temp_record = current;
+ done++; // Exit the while loop
+ }
+ else if (test > 0) { // Found a string past us in the
+ // alphabet. Insert ahead of this
+ // last record.
+
+ //fprintf(stderr,"\n%s\n%s\n",current->filename,filename);
+
+ //fprintf(stderr,"Not Found: Inserting an index record for %s\n",filename);
+ temp_record = (map_index_record *)malloc(sizeof(map_index_record));
+ CHECKMALLOC(temp_record);
+
+ if (current == map_index_head) { // Start of list!
+ // Insert new record at head of list
+ temp_record->next = map_index_head;
+ map_index_head = temp_record;
+ //fprintf(stderr,"Inserting at head of list\n");
+ }
+ else {
+ // Insert new record before "current"
+ previous->next = temp_record;
+ temp_record->next = current;
+ //fprintf(stderr,"Inserting before current\n");
+ }
+
+ //fprintf(stderr,"Adding:%d:%s\n",strlen(filename),filename);
+
+ // Fill in some default values for the new record
+//WE7U
+// Here's where we might look at the file extension and assign
+// default map_layer fields based on that.
+ temp_record->max_zoom = 0;
+ temp_record->min_zoom = 0;
+ temp_record->map_layer = default_map_layer;
+ temp_record->selected = 0;
+ temp_record->XmStringPtr = NULL;
+
+ if ( strstr(filename,".geo")
+ || strstr(filename,".GEO")
+ || strstr(filename,".Geo")) {
+ temp_record->auto_maps = 0;
+ }
+ else {
+ temp_record->auto_maps = 1;
+ }
+
+ if ( strstr(filename,".shp")
+ || strstr(filename,".SHP")
+ || strstr(filename,".Shp") ) {
+ temp_record->draw_filled = 2; // Auto
+ }
+ else {
+ temp_record->draw_filled = 0; // No-Fill
+ }
+
+ if ( strstr(filename,".tif")
+ || strstr(filename,".TIF")
+ || strstr(filename,".Tif") ) {
+ temp_record->usgs_drg = 2; // Auto
+ }
+ else {
+ temp_record->usgs_drg = 0; // No
+ }
+
+ //current = current->next;
+ done++;
+ }
+ else { // Haven't gotten to the correct insertion point yet
+ previous = current; // Save ptr to last record
+ current = current->next;
+ }
+ }
+
+ if (!done) { // Matching record not found, add a
+ // record to the end of the list
+ //fprintf(stderr,"Not Found: Adding an index record for %s\n",filename);
+ temp_record = (map_index_record *)malloc(sizeof(map_index_record));
+ CHECKMALLOC(temp_record);
+
+ temp_record->next = NULL;
+
+ if (previous == NULL) { // Empty list
+ map_index_head = temp_record;
+ //fprintf(stderr,"First record in new list\n");
+ }
+ else { // Else at end of list
+ previous->next = temp_record;
+ //fprintf(stderr,"Adding to end of list: %s\n",filename);
+ }
+
+ //fprintf(stderr,"Adding:%d:%s\n",strlen(filename),filename);
+
+ // Fill in some default values for the new record
+//WE7U
+// Here's where we might look at the file extension and assign
+// default map_layer fields based on that.
+ temp_record->max_zoom = 0;
+ temp_record->min_zoom = 0;
+ temp_record->map_layer = default_map_layer;
+ temp_record->selected = 0;
+ temp_record->XmStringPtr = NULL;
+
+ if ( strstr(filename,".geo")
+ || strstr(filename,".GEO")
+ || strstr(filename,".Geo")) {
+ temp_record->auto_maps = 0;
+ }
+ else {
+ temp_record->auto_maps = 1;
+ }
+
+ if ( strstr(filename,".shp")
+ || strstr(filename,".SHP")
+ || strstr(filename,".Shp") ) {
+ temp_record->draw_filled = 2; // Auto
+ }
+ else {
+ temp_record->draw_filled = 0; // No-Fill
+ }
+
+ if ( strstr(filename,".tif")
+ || strstr(filename,".TIF")
+ || strstr(filename,".Tif") ) {
+ temp_record->usgs_drg = 2; // Auto
+ }
+ else {
+ temp_record->usgs_drg = 0; // No
+ }
+
+ }
+
+ // Update the values. By this point we have a struct to fill
+ // in, whether it's a new or old struct doesn't matter. Convert
+ // the values from lat/long to Xastir coordinate system.
+ xastir_snprintf(temp_record->filename,MAX_FILENAME,"%s",filename);
+
+ temp_record->bottom = bottom;
+ temp_record->top = top;
+ temp_record->left = left;
+ temp_record->right = right;
+ temp_record->accessed = 1;
+}
+
+
+
+
+
+// Function called by the various draw_* functions when in indexing
+// mode. Causes an update of the index list in memory. Input
+// parameters are in lat/long, which are converted to Xastir
+// coordinates for storage due to speed considerations. Records are
+// inserted in alphanumerical order.
+void index_update_ll(char *filename,
+ double bottom,
+ double top,
+ double left,
+ double right,
+ int default_map_layer) {
+
+ map_index_record *current = map_index_head;
+ map_index_record *previous = map_index_head;
+ map_index_record *temp_record = NULL;
+ int done = 0;
+ unsigned long temp_left, temp_right, temp_top, temp_bottom;
+ int ok;
+ int i;
+
+
+ // Check for initial bad input
+ if ( (filename == NULL)
+ || (filename[0] == '\0')
+ || (filename[strlen(filename) - 1] == '/') ) {
+ fprintf(stderr,"index_update_ll: Bad input: %s\n",filename);
+ return;
+ }
+ // Make sure there aren't any weird characters in the filename
+ // that might cause problems later. Look for control characters
+ // and convert them to string-end characters.
+ for ( i = 0; i < (int)strlen(filename); i++ ) {
+ // Change any control characters to '\0' chars
+ if (filename[i] < 0x20) {
+
+ fprintf(stderr,"\nindex_update_ll: Found control char 0x%02x in map file/map directory name:\n%s\n",
+ filename[i],
+ filename);
+
+ filename[i] = '\0'; // Terminate it here
+ }
+ }
+ // Check if the string is _now_ bogus
+ if (filename[0] == '\0') {
+ fprintf(stderr,"index_update_ll: Bad input: %s\n",filename);
+ return;
+ }
+
+ //fprintf(stderr,"index_update_ll: (%15.10g,%15.10g)\t(%15.10g,%15.10g)\t%s\n",
+ // bottom, top, left, right, filename );
+
+ //if (map_index_head == NULL)
+ // fprintf(stderr,"Empty list\n");
+
+ // Skip dbf and shx map extensions. Really should make this
+ // case-independent...
+ if ( strstr(filename,"shx")
+ || strstr(filename,"dbf")
+ || strstr(filename,"SHX")
+ || strstr(filename,"DBF") ) {
+ return;
+ }
+
+ // Search for a matching filename in the linked list
+ while ((current != NULL) && !done) {
+ int test;
+
+ //fprintf(stderr,"Comparing %s to\n %s\n",current->filename,filename);
+
+ test = strcmp(current->filename,filename);
+
+ if (test == 0) {
+ // Found a match!
+ //fprintf(stderr,"Found: Updating entry for %s\n",filename);
+ temp_record = current;
+ done++; // Exit the while loop
+ }
+
+ else if (test > 0) {
+ // Found a string past us in the alphabet. Insert ahead
+ // of this last record.
+
+ //fprintf(stderr,"\n%s\n%s\n",current->filename,filename);
+
+ //fprintf(stderr,"Not Found: Inserting an index record for %s\n",filename);
+ temp_record = (map_index_record *)malloc(sizeof(map_index_record));
+ CHECKMALLOC(temp_record);
+
+ if (current == map_index_head) { // Start of list!
+ // Insert new record at head of list
+ temp_record->next = map_index_head;
+ map_index_head = temp_record;
+ //fprintf(stderr,"Inserting at head of list\n");
+ }
+ else {
+ // Insert new record before "current"
+ previous->next = temp_record;
+ temp_record->next = current;
+ //fprintf(stderr,"Inserting before current\n");
+ }
+
+ //fprintf(stderr,"Adding:%d:%s\n",strlen(filename),filename);
+
+ // Fill in some default values for the new record
+//WE7U
+// Here's where we might look at the file extension and assign
+// default map_layer fields based on that.
+ temp_record->max_zoom = 0;
+ temp_record->min_zoom = 0;
+ temp_record->map_layer = default_map_layer;
+ temp_record->selected = 0;
+ temp_record->XmStringPtr = NULL;
+
+ if ( strstr(filename,".geo")
+ || strstr(filename,".GEO")
+ || strstr(filename,".Geo")) {
+ temp_record->auto_maps = 0;
+ }
+ else {
+ temp_record->auto_maps = 1;
+ }
+
+ if ( strstr(filename,".shp")
+ || strstr(filename,".SHP")
+ || strstr(filename,".Shp") ) {
+ temp_record->draw_filled = 2; // Auto
+ }
+ else {
+ temp_record->draw_filled = 0; // No-Fill
+ }
+
+ if ( strstr(filename,".tif")
+ || strstr(filename,".TIF")
+ || strstr(filename,".Tif") ) {
+ temp_record->usgs_drg = 2; // Auto
+ }
+ else {
+ temp_record->usgs_drg = 0; // No
+ }
+
+ //current = current->next;
+ done++;
+ }
+ else { // Haven't gotten to the correct insertion point yet
+ previous = current; // Save ptr to last record
+ current = current->next;
+ }
+ }
+
+ if (!done) { // Matching record not found, didn't find alpha
+ // chars after our string either, add record to
+ // the end of the list.
+
+ //fprintf(stderr,"Not Found: Adding an index record for %s\n",filename);
+ temp_record = (map_index_record *)malloc(sizeof(map_index_record));
+ CHECKMALLOC(temp_record);
+
+ temp_record->next = NULL;
+
+ if (previous == NULL) { // Empty list
+ map_index_head = temp_record;
+ //fprintf(stderr,"First record in new list\n");
+ }
+ else { // Else at end of list
+ previous->next = temp_record;
+ //fprintf(stderr,"Adding to end of list: %s\n",filename);
+ }
+
+ //fprintf(stderr,"Adding:%d:%s\n",strlen(filename),filename);
+
+ // Fill in some default values for the new record
+//WE7U
+// Here's where we might look at the file extension and assign
+// default map_layer fields based on that.
+ temp_record->max_zoom = 0;
+ temp_record->min_zoom = 0;
+ temp_record->map_layer = default_map_layer;
+ temp_record->selected = 0;
+ temp_record->XmStringPtr = NULL;
+
+ if ( strstr(filename,".geo")
+ || strstr(filename,".GEO")
+ || strstr(filename,".Geo")) {
+ temp_record->auto_maps = 0;
+ }
+ else {
+ temp_record->auto_maps = 1;
+ }
+
+ if ( strstr(filename,".shp")
+ || strstr(filename,".SHP")
+ || strstr(filename,".Shp") ) {
+ temp_record->draw_filled = 2; // Auto
+ }
+ else {
+ temp_record->draw_filled = 0; // No-Fill
+ }
+
+ if ( strstr(filename,".tif")
+ || strstr(filename,".TIF")
+ || strstr(filename,".Tif") ) {
+ temp_record->usgs_drg = 2; // Auto
+ }
+ else {
+ temp_record->usgs_drg = 0; // No
+ }
+
+ }
+
+ // Update the values. By this point we have a struct to fill
+ // in, whether it's a new or old struct doesn't matter. Convert
+ // the values from lat/long to Xastir coordinate system.
+
+ // In this case the struct uses MAX_FILENAME for the length of
+ // the field, so the below statement is ok.
+ xastir_snprintf(temp_record->filename,MAX_FILENAME,"%s",filename);
+
+ ok = convert_to_xastir_coordinates( &temp_left,
+ &temp_top,
+ (float)left,
+ (float)top);
+ if (!ok)
+ fprintf(stderr,"%s\n\n",filename);
+
+ ok = convert_to_xastir_coordinates( &temp_right,
+ &temp_bottom,
+ (float)right,
+ (float)bottom);
+ if (!ok)
+ fprintf(stderr,"%s\n\n",filename);
+
+ temp_record->bottom = temp_bottom;
+ temp_record->top = temp_top;
+ temp_record->left = temp_left;
+ temp_record->right = temp_right;
+ temp_record->accessed = 1;
+}
+
+
+
+
+
+// Function which will update the "accessed" variable on either a
+// directory or a filename in the map index.
+static void index_update_accessed(char *filename) {
+ map_index_record *current = map_index_head;
+ int done = 0;
+ int i;
+
+
+ // Check for initial bad input
+ if ( (filename == NULL) || (filename[0] == '\0') ) {
+ fprintf(stderr,"index_update_accessed: Bad input: %s\n",filename);
+ return;
+ }
+
+ // Make sure there aren't any weird characters in the filename
+ // that might cause problems later. Look for control characters
+ // and convert them to string-end characters.
+ for ( i = 0; i < (int)strlen(filename); i++ ) {
+ // Change any control characters to '\0' chars
+ if (filename[i] < 0x20) {
+
+ fprintf(stderr,"\nindex_update_accessed: Found control char 0x%02x in map file/map directory name:\n%s\n",
+ filename[i],
+ filename);
+
+ filename[i] = '\0'; // Terminate it here
+ }
+ }
+ // Check if the string is _now_ bogus
+ if (filename[0] == '\0') {
+ fprintf(stderr,"index_update_accessed: Bad input: %s\n",filename);
+ return;
+ }
+
+ // Skip dbf and shx map extensions. Really should make this
+ // case-independent...
+ if ( strstr(filename,"shx")
+ || strstr(filename,"dbf")
+ || strstr(filename,"SHX")
+ || strstr(filename,"DBF") ) {
+ return;
+ }
+
+ // Search for a matching filename in the linked list
+ while ((current != NULL) && !done) {
+ int test;
+
+//fprintf(stderr,"Comparing %s to\n %s\n",current->filename,filename);
+
+ test = strcmp(current->filename,filename);
+
+ if (test == 0) {
+ // Found a match!
+//fprintf(stderr,"Found: Updating entry for %s\n\n",filename);
+ current->accessed = 1;
+ done++; // Exit the while loop
+ }
+
+ else { // Haven't gotten to the correct insertion point yet
+ current = current->next;
+ }
+ }
+}
+
+
+
+
+
+// Function called by map_onscreen_index()
+//
+// This function returns:
+// 0 if the map isn't in the index
+// 1 if the map is listed in the index
+// Four parameters listing the extents of the map
+//
+// The updated parameters are in the Xastir coordinate system for
+// speed reasons.
+//
+// Note that the index retrieval could be made much faster by
+// storing the data in a hash instead of a linked list. This is
+// just an initial implementation to see what speedups are possible.
+// Hashing might be next. --we7u
+//
+// Note that since we've alphanumerically ordered the list, we can
+// stop when we hit something after this filename in the alphabet.
+// It speeds things up quite a bit.
+//
+// In order to speed this up slightly for the general case, we'll
+// assume that we'll be fetching indexes in alphabetical order, as
+// that's how we store them everywhere. We'll save the last map
+// index pointer away and start searching there each time. That
+// should make all but the _first_ lookup much faster.
+//
+map_index_record *last_index_lookup = NULL;
+
+int index_retrieve(char *filename,
+ unsigned long *bottom,
+ unsigned long *top,
+ unsigned long *left,
+ unsigned long *right,
+ int *max_zoom,
+ int *min_zoom,
+ int *map_layer,
+ int *draw_filled,
+ int *usgs_drg,
+ int *auto_maps) {
+
+ map_index_record *current;
+ int status = 0;
+
+
+ if ( (filename == NULL)
+ || (strlen(filename) >= MAX_FILENAME) ) {
+ return(status);
+ }
+
+ // Attempt to start where we left off last time
+ if (last_index_lookup != NULL) {
+ current = last_index_lookup;
+ }
+ else {
+ current = map_index_head;
+//fprintf(stderr,"Start at beginning:%s\t", filename);
+ }
+
+ // Check to see if we're past the correct area. If so, start at
+ // the beginning of the index instead.
+ //
+ if (current
+ && ((current->filename[0] > filename[0])
+ || (strcmp(current->filename, filename) > 0))) {
+ //
+ // We're past the correct point. Start at the beginning of
+ // the list unless we're already there.
+ //
+ if (current != map_index_head) {
+ current = map_index_head;
+ }
+//fprintf(stderr,"Start at beginning:%s\t", filename);
+ }
+
+ //
+ // Search for a matching filename in the linked list.
+ //
+
+ // Check the first char only. Loop until they match or go past.
+ // This is our high-speed method to get to the correct search
+ // area.
+ //
+ while (current && (current->filename[0] < filename[0])) {
+ // Save the pointer away for next time. There's a reason we
+ // save it before we increment the counter: For "z" weather
+ // alerts, it's nice to have it scan just the very last of
+ // the list before it fails, instead of scanning the entire
+ // list each time and then failing. Need to find out why
+ // weather alerts always fail, and therefore why this
+ // routine gets called every time for them.
+ //
+ last_index_lookup = current;
+ current = current->next;
+//fprintf(stderr,"1");
+ }
+
+ // Stay in this loop while the first char matches. This is our
+ // active search area.
+ //
+ while (current && (current->filename[0] == filename[0])) {
+ int result;
+
+ // Check the entire string
+ result = strcmp(current->filename, filename);
+
+ if (result == 0) {
+ // Found a match!
+ status = 1;
+ *bottom = current->bottom;
+ *top = current->top;
+ *left = current->left;
+ *right = current->right;
+ *max_zoom = current->max_zoom;
+ *min_zoom = current->min_zoom;
+ *map_layer = current->map_layer;
+ *draw_filled = current->draw_filled;
+ *usgs_drg = current->usgs_drg;
+ *auto_maps = current->auto_maps;
+//fprintf(stderr," Found it\n");
+ return(status);
+ }
+ else if (result > 0) {
+ // We're past it in the index. We didn't find it in the
+ // index.
+//fprintf(stderr," Did not find1\n");
+ return(status);
+ }
+ else { // Not found yet, look at the next
+ // Save the pointer away for next time. There's a
+ // reason we save it before we increment the counter:
+ // For "z" weather alerts, it's nice to have it scan
+ // just the very last of the list before it fails,
+ // instead of scanning the entire list each time and
+ // then failing. Need to find out why weather alerts
+ // always fail, and therefore why this routine gets
+ // called every time for them.
+ //
+ last_index_lookup = current;
+ current = current->next;
+//fprintf(stderr,"2");
+ }
+ }
+
+ // We're past the correct search area and didn't find it.
+//fprintf(stderr," Did not find2\n");
+
+ return(status);
+}
+
+
+
+
+
+// Saves the linked list pointed to by map_index_head to a file.
+// Keeps the same order as the memory linked list. Delete records
+// in the in-memory linked list for which the "accessed" variable is
+// 0 or filename is empty.
+//
+void index_save_to_file(void) {
+ FILE *f;
+ map_index_record *current;
+ map_index_record *last;
+ char out_string[MAX_FILENAME*2];
+ char map_index_path[MAX_VALUE];
+
+ get_user_base_dir(MAP_INDEX_DATA, map_index_path, sizeof(map_index_path));
+
+
+//fprintf(stderr,"Saving map index to file\n");
+
+ f = fopen( map_index_path, "w" );
+
+ if (f == NULL) {
+ fprintf(stderr,"Couldn't create/update map index file: %s\n",
+ map_index_path );
+ return;
+ }
+
+ current = map_index_head;
+ last = current;
+
+ while (current != NULL) {
+ int i;
+
+ // Make sure there aren't any weird characters in the
+ // filename that might cause problems later. Look for
+ // control characters and convert them to string-end
+ // characters.
+ for ( i = 0; i < (int)strlen(current->filename); i++ ) {
+ // Change any control characters to '\0' chars
+ if (current->filename[i] < 0x20) {
+
+ fprintf(stderr,"\nindex_save_to_file: Found control char 0x%02x in map name:\n%s\n",
+ current->filename[i],
+ current->filename);
+
+ current->filename[i] = '\0'; // Terminate it here
+ }
+ }
+
+ // Save to file if filename non-blank and record has the
+ // accessed field set.
+ if ( (current->filename[0] != '\0')
+ && (current->accessed != 0) ) {
+
+ // Write each object out to the file as one
+ // comma-delimited line
+ xastir_snprintf(out_string,
+ sizeof(out_string),
+ "%010lu,%010lu,%010lu,%010lu,%05d,%01d,%01d,%01d,%05d,%05d,%s\n",
+ current->bottom,
+ current->top,
+ current->left,
+ current->right,
+ current->map_layer,
+ current->draw_filled,
+ current->usgs_drg,
+ current->auto_maps,
+ current->max_zoom,
+ current->min_zoom,
+ current->filename);
+
+ if (fprintf(f,"%s",out_string) < (int)strlen(out_string)) {
+ // Failed to write
+ fprintf(stderr,"Couldn't write objects to map index file: %s\n",
+ map_index_path );
+ current = NULL; // All done
+ }
+ // Set up pointers for next loop iteration
+ last = current;
+
+ if (current != NULL)
+ current = current->next;
+ }
+
+
+ else {
+ last = current;
+ current = current->next;
+ }
+/*
+//WE7U
+ else { // Delete this record from our list! It's a record
+ // for a map file that doesn't exist in the
+ // filesystem anymore.
+ if (last == current) { // We're at the head of the list
+ map_index_head = current->next;
+
+// Remember to free the XmStringPtr if we use this bit of code
+// again.
+
+ free(current);
+
+ // Set up pointers for next loop iteration
+ current = map_index_head;
+ last = current;
+ }
+ else { // Not the first record in the list
+ map_index_record *gone;
+
+ gone = current; // Save ptr to record we wish to delete
+ last->next = current->next; // Unlink from list
+
+// Remember to free the XmStringPtr if we use this bit of code
+// again.
+
+ free(gone);
+
+ // Set up pointers for next loop iteration
+ // "last" is still ok
+ current = last->next;
+ }
+ }
+*/
+ }
+ (void)fclose(f);
+}
+
+
+
+
+
+// This function is currently not used.
+//
+// Function used to add map directories/files to the in-memory map
+// index. Causes an update of the index list in memory. Input
+// records are inserted in alphanumerical order. This function is
+// called from the index_restore_from_file() function below. When
+// this function is called the new record has all of the needed
+// information in it.
+//
+/*
+static void index_insert_sorted(map_index_record *new_record) {
+
+ map_index_record *current = map_index_head;
+ map_index_record *previous = map_index_head;
+ int done = 0;
+ int i;
+
+
+ //fprintf(stderr,"index_insert_sorted: %s\n", new_record->filename );
+
+ // Check for bad input.
+ if (new_record == NULL) {
+ fprintf(stderr,"index_insert_sorted: Bad input.\n");
+ return;
+ }
+ // Make sure there aren't any weird characters in the filename
+ // that might cause problems later. Look for any control
+ // characters and convert them to string-end characters.
+ for ( i = 0; i < (int)strlen(new_record->filename); i++ ) {
+ if (new_record->filename[i] < 0x20) {
+
+ fprintf(stderr,"\nindex_insert_sorted: Found control char 0x%02x in map name:\n%s\n",
+ new_record->filename[i],
+ new_record->filename);
+
+ new_record->filename[i] = '\0'; // Terminate it here
+ }
+ }
+ // Check if the string is _now_ bogus
+ if (new_record->filename[0] == '\0') {
+ fprintf(stderr,"index_insert_sorted: Bad input.\n");
+ return;
+ }
+
+ //if (map_index_head == NULL)
+ // fprintf(stderr,"Empty list\n");
+
+ // Search for a matching filename in the linked list
+ while ((current != NULL) && !done) {
+ int test;
+
+ //fprintf(stderr,"Comparing %s to\n %s\n",
+ // current->filename, new_record->filename);
+
+ test = strcmp(current->filename, new_record->filename);
+
+ if (test == 0) { // Found a match!
+ int selected;
+
+//fprintf(stderr,"Found a match: Updating entry for %s\n",new_record->filename);
+
+ // Save this away temporarily.
+ selected = current->selected;
+
+ // Copy the fields across and then free new_record. We
+ // overwrite the contents of the existing record.
+ xastir_snprintf(current->filename,
+ MAX_FILENAME,
+ "%s",
+ new_record->filename);
+ current->bottom = new_record->bottom;
+ current->top = new_record->top;
+ current->left = new_record->left;
+ current->right = new_record->right;
+ current->accessed = 1;
+ current->max_zoom = new_record->max_zoom;
+ current->min_zoom = new_record->min_zoom;
+ current->map_layer = new_record->map_layer;
+ current->draw_filled = new_record->draw_filled;
+ current->usgs_drg = new_record->usgs_drg;
+ current->selected = selected; // Restore it
+ current->auto_maps = new_record->auto_maps;
+
+// Remember to free the XmStringPtr if we use this bit of code
+// again.
+
+ free(new_record); // Don't need it anymore
+
+ done++; // Exit loop, "current" points to found record
+ }
+ else if (test > 0) { // Found a string past us in the
+ // alphabet. Insert ahead of this
+ // last record.
+
+//fprintf(stderr,"Not Found, inserting: %s\n", new_record->filename);
+//fprintf(stderr," Before record: %s\n", current->filename);
+
+ if (current == map_index_head) { // Start of list!
+ // Insert new record at head of list
+ new_record->next = map_index_head;
+ map_index_head = new_record;
+ //fprintf(stderr,"Inserting at head of list\n");
+ }
+ else { // Insert between "previous" and "current"
+ // Insert new record before "current"
+ previous->next = new_record;
+ new_record->next = current;
+ //fprintf(stderr,"Inserting before current\n");
+ }
+
+ //fprintf(stderr,"Adding:%d:%s\n",strlen(filename),filename);
+
+ // Fill in some default values for the new record that
+ // don't exist in the map_index.sys file.
+ new_record->selected = 0;
+
+ if ( strstr(new_record->filename,".geo")
+ || strstr(new_record->filename,".GEO")
+ || strstr(new_record->filename,".Geo") ) {
+ new_record->auto_maps = 0;
+ }
+ else {
+ new_record->auto_maps = 1;
+ }
+
+ //current = current->next;
+ done++;
+ }
+ else { // Haven't gotten to the correct insertion point yet
+ previous = current; // Save ptr to last record
+ current = current->next;
+ }
+ }
+
+ if (!done) { // Matching record not found, add the record to
+ // the end of the list. "previous" points to the last
+ // record in the list or NULL (empty list).
+
+//fprintf(stderr,"Not Found: Adding to end: %s\n",new_record->filename);
+
+ new_record->next = NULL;
+
+ if (previous == NULL) { // Empty list
+ map_index_head = new_record;
+ //fprintf(stderr,"First record in new list\n");
+ }
+ else { // Else at end of list
+ previous->next = new_record;
+ //fprintf(stderr,"Adding to end of list: %s\n",new_record->filename);
+ }
+
+ //fprintf(stderr,"Adding:%d:%s\n",strlen(new_record->filename),new_record->filename);
+
+ // Fill in some default values for the new record.
+ new_record->selected = 0;
+
+ if ( strstr(new_record->filename,".geo")
+ || strstr(new_record->filename,".GEO")
+ || strstr(new_record->filename,".Geo") ) {
+ new_record->auto_maps = 0;
+ }
+ else {
+ new_record->auto_maps = 1;
+ }
+ }
+}
+*/
+
+
+
+
+
+// sort map index
+// simple bubble sort, since we should be sorted already
+//
+static void index_sort(void) {
+ map_index_record *current, *previous, *next;
+ int changed = 1;
+ int loops = 0; // for debug stats
+
+ previous = map_index_head;
+ next = NULL;
+ // fprintf(stderr, "index_sort: start.\n");
+ // check if we have any records at all, and at least two
+ if ( (previous != NULL) && (previous->next != NULL) ) {
+ current = previous->next;
+ while ( changed == 1) {
+ changed = 0;
+ if (current->next != NULL) {next = current->next;}
+ if ( strcmp( previous->filename, current->filename) >= 0 ) {
+ // out of order - swap them
+ current->next = previous;
+ previous->next = next;
+ map_index_head = current;
+ current = previous;
+ previous = map_index_head;
+ changed = 1;
+ }
+
+ while ( next != NULL ) {
+ if ( strcmp( current->filename, next->filename) >= 0 ) {
+ // out of order - swap them
+ current->next = next->next;
+ previous->next = next;
+ next->next = current;
+ // get ready for the next iteration
+ previous = next; // current already moved ahead from the swap
+ next = current->next;
+ changed = 1;
+ }
+ else {
+ previous = current;
+ current = next;
+ next = current->next;
+ }
+ }
+ previous = map_index_head;
+ current = previous->next;
+ next = current->next;
+ loops++;
+ }
+ }
+ // debug stats
+ // fprintf(stderr, "index_sort: ran %d loops.\n", loops);
+}
+
+
+
+
+
+// Snags the file and creates the linked list pointed to by the
+// map_index_head pointer. The memory linked list keeps the same
+// order as the entries in the file.
+//
+// NOTE: If we're converting from the old format to the new, we
+// need to call index_save_to_file() in order to write out the new
+// format once we're done.
+//
+void index_restore_from_file(void) {
+ FILE *f;
+ map_index_record *temp_record;
+ map_index_record *last_record;
+ char in_string[MAX_FILENAME*2];
+ int doing_migration = 0;
+ char map_index_path[MAX_VALUE];
+
+ get_user_base_dir(MAP_INDEX_DATA, map_index_path, sizeof(map_index_path));
+
+
+//fprintf(stderr,"\nRestoring map index from file\n");
+
+ if (map_index_head != NULL) {
+ fprintf(stderr,"Warning: index_restore_from_file(): map_index_head was non-null!\n");
+ }
+
+ map_index_head = NULL; // Starting with empty list
+ last_record = NULL;
+
+ f = fopen( map_index_path, "r" );
+ if (f == NULL) // No map_index file yet
+ return;
+
+ while (!feof (f)) { // Loop through entire map_index file
+
+ // Read one line from the file
+ if ( get_line (f, in_string, MAX_FILENAME*2) ) {
+
+ if (strlen(in_string) >= 15) { // We have some data.
+ // Try to process the
+ // line.
+ char scanf_format[50];
+ char old_scanf_format[50];
+ char older_scanf_format[50];
+ int processed;
+ int i, jj;
+
+//fprintf(stderr,"%s\n",in_string);
+
+ // Tweaked the string below so that it will track
+ // along with MAX_FILENAME-1. We're constructing
+ // the string "%lu,%lu,%lu,%lu,%d,%d,%2000c", where
+ // the 2000 example number is from MAX_FILENAME.
+ xastir_snprintf(scanf_format,
+ sizeof(scanf_format),
+ "%s%d%s",
+ "%lu,%lu,%lu,%lu,%d,%d,%d,%d,%d,%d,%",
+ MAX_FILENAME,
+ "c");
+ //fprintf(stderr,"%s\n",scanf_format);
+
+ // index predates addition of usgs_drg flag (26 Jul 2005)
+ xastir_snprintf(old_scanf_format,
+ sizeof(old_scanf_format),
+ "%s%d%s",
+ "%lu,%lu,%lu,%lu,%d,%d,%d,%d,%d,%",
+ MAX_FILENAME,
+ "c");
+
+ // index predates addition of min/max zoom (29 Oct 2003)
+ xastir_snprintf(older_scanf_format,
+ sizeof(older_scanf_format),
+ "%s%d%s",
+ "%lu,%lu,%lu,%lu,%d,%d,%d,%",
+ MAX_FILENAME,
+ "c");
+
+ // Malloc an index record. We'll add it to the list
+ // only if the data looks reasonable.
+ temp_record = (map_index_record *)malloc(sizeof(map_index_record));
+ CHECKMALLOC(temp_record);
+
+ memset(temp_record->filename, 0, sizeof(temp_record->filename));
+ temp_record->next = NULL;
+ temp_record->bottom = 64800001l;// Too high
+ temp_record->top = 64800001l; // Too high
+ temp_record->left = 129600001l; // Too high
+ temp_record->right = 129600001l;// Too high
+ temp_record->map_layer = -1; // Too low
+ temp_record->draw_filled = -1; // Too low
+ temp_record->usgs_drg = -1; // Too low
+ temp_record->auto_maps = -1; // Too low
+ temp_record->max_zoom = -1; // Too low
+ temp_record->min_zoom = -1; // Too low
+ temp_record->filename[0] = '\0';// Empty
+
+ processed = sscanf(in_string,
+ scanf_format,
+ &temp_record->bottom,
+ &temp_record->top,
+ &temp_record->left,
+ &temp_record->right,
+ &temp_record->map_layer,
+ &temp_record->draw_filled,
+ &temp_record->usgs_drg,
+ &temp_record->auto_maps,
+ &temp_record->max_zoom,
+ &temp_record->min_zoom,
+ temp_record->filename);
+
+ if (processed < 11) {
+ // We're upgrading from an old format index file
+ // that doesn't have usgs_drg. Try the
+ // old_scanf_format string instead.
+
+ doing_migration = 1;
+
+ processed = sscanf(in_string,
+ old_scanf_format,
+ &temp_record->bottom,
+ &temp_record->top,
+ &temp_record->left,
+ &temp_record->right,
+ &temp_record->map_layer,
+ &temp_record->draw_filled,
+ &temp_record->auto_maps,
+ &temp_record->max_zoom,
+ &temp_record->min_zoom,
+ temp_record->filename);
+ if (processed < 10) {
+ // It's really old, doesn't have min/max zoom either
+ temp_record->max_zoom = -1; // Too low
+ temp_record->min_zoom = -1; // Too low
+
+ processed = sscanf(in_string,
+ older_scanf_format,
+ &temp_record->bottom,
+ &temp_record->top,
+ &temp_record->left,
+ &temp_record->right,
+ &temp_record->map_layer,
+ &temp_record->draw_filled,
+ &temp_record->auto_maps,
+ temp_record->filename);
+ }
+ // either way, it doesn't have usgs_drg, so add one
+ // defaulting to Auto if it's a tif file, no if not
+ if ( strstr(temp_record->filename,".tif")
+ || strstr(temp_record->filename,".TIF")
+ || strstr(temp_record->filename,".Tif") ) {
+ temp_record->usgs_drg = 2; // Auto
+ }
+ else {
+ temp_record->usgs_drg = 0; // No
+ }
+ }
+
+ temp_record->XmStringPtr = NULL;
+
+ // Do some reasonableness checking on the parameters
+ // we just parsed.
+//WE7U: First comparison here is always false
+// if ( (temp_record->bottom < 0l)
+// || (temp_record->bottom > 64800000l) ) {
+ if (temp_record->bottom > 64800000l) {
+
+ processed = 0; // Reject this record
+ fprintf(stderr,"\nindex_restore_from_file: bottom extent incorrect %lu in map name:\n%s\n",
+ temp_record->bottom,
+ temp_record->filename);
+ }
+
+
+//WE7U: First comparison here is always false
+// if ( (temp_record->top < 0l)
+// || (temp_record->top > 64800000l) ) {
+ if (temp_record->top > 64800000l) {
+
+ processed = 0; // Reject this record
+ fprintf(stderr,"\nindex_restore_from_file: top extent incorrect %lu in map name:\n%s\n",
+ temp_record->top,
+ temp_record->filename);
+ }
+
+//WE7U: First comparison here is always false
+// if ( (temp_record->left < 0l)
+// || (temp_record->left > 129600000l) ) {
+ if (temp_record->left > 129600000l) {
+
+ processed = 0; // Reject this record
+ fprintf(stderr,"\nindex_restore_from_file: left extent incorrect %lu in map name:\n%s\n",
+ temp_record->left,
+ temp_record->filename);
+ }
+
+//WE7U: First comparison here is always false
+// if ( (temp_record->right < 0l)
+// || (temp_record->right > 129600000l) ) {
+ if (temp_record->right > 129600000l) {
+
+ processed = 0; // Reject this record
+ fprintf(stderr,"\nindex_restore_from_file: right extent incorrect %lu in map name:\n%s\n",
+ temp_record->right,
+ temp_record->filename);
+ }
+
+ if ( (temp_record->max_zoom < 0)
+ || (temp_record->max_zoom > 99999) ) {
+// processed = 0; // Reject this record
+// fprintf(stderr,"\nindex_restore_from_file: max_zoom field incorrect %d in map name:\n%s\n",
+// temp_record->max_zoom,
+// temp_record->filename);
+ // Assign a reasonable value
+ temp_record->max_zoom = 0;
+ //fprintf(stderr,"Assigning max_zoom of 0\n");
+ }
+
+ if ( (temp_record->min_zoom < 0)
+ || (temp_record->min_zoom > 99999) ) {
+// processed = 0; // Reject this record
+// fprintf(stderr,"\nindex_restore_from_file: min_zoom field incorrect %d in map name:\n%s\n",
+// temp_record->min_zoom,
+// temp_record->filename);
+ // Assign a reasonable value
+ temp_record->min_zoom = 0;
+ //fprintf(stderr,"Assigning min_zoom of 0\n");
+ }
+
+ if ( (temp_record->map_layer < -99999)
+ || (temp_record->map_layer > 99999) ) {
+ processed = 0; // Reject this record
+ fprintf(stderr,"\nindex_restore_from_file: map_layer field incorrect %d in map name:\n%s\n",
+ temp_record->map_layer,
+ temp_record->filename);
+ }
+
+ if ( (temp_record->draw_filled < 0)
+ || (temp_record->draw_filled > 2) ) {
+ processed = 0; // Reject this record
+ fprintf(stderr,"\nindex_restore_from_file: draw_filled field incorrect %d in map name:\n%s\n",
+ temp_record->draw_filled,
+ temp_record->filename);
+ }
+
+ if ( (temp_record->usgs_drg < 0)
+ || (temp_record->usgs_drg > 2) ) {
+ processed = 0; // Reject this record
+ fprintf(stderr,"\nindex_restore_from_file: usgs_drg field incorrect %d in map name:\n%s\n",
+ temp_record->usgs_drg,
+ temp_record->filename);
+ }
+
+ if ( (temp_record->auto_maps < 0)
+ || (temp_record->auto_maps > 1) ) {
+ processed = 0; // Reject this record
+ fprintf(stderr,"\nindex_restore_from_file: auto_maps field incorrect %d in map name:\n%s\n",
+ temp_record->auto_maps,
+ temp_record->filename);
+ }
+
+ // Check whether the filename is empty
+ if (strlen(temp_record->filename) == 0) {
+ processed = 0; // Reject this record
+ }
+
+ // Check for control characters in the filename.
+ // Reject any that have them.
+ jj = (int)strlen(temp_record->filename);
+ for (i = 0; i < jj; i++)
+ {
+ if (temp_record->filename[i] < 0x20) {
+
+ processed = 0; // Reject this record
+ fprintf(stderr,"\nindex_restore_from_file: Found control char 0x%02x in map name:\n%s\n",
+ temp_record->filename[i],
+ temp_record->filename);
+ }
+ }
+
+
+ // Mark the record as accessed at this point.
+ // At the stage where we're writing this list off to
+ // disk, if the record hasn't been accessed by the
+ // re-indexing, it doesn't get written. This has
+ // the effect of flushes deleted files from the
+ // index quickly.
+ temp_record->accessed = 1;
+
+ // Default is not-selected. Later we read in the
+ // selected_maps.sys file and tweak some of these
+ // fields.
+ temp_record->selected = 0;
+
+ temp_record->filename[MAX_FILENAME-1] = '\0';
+
+ // If correct number of parameters for either old or
+ // new format
+ if (processed == 11 || processed == 10 || processed == 8) {
+
+ //fprintf(stderr,"Restored: %s\n",temp_record->filename);
+
+ // Insert the new record into the in-memory map
+ // list in sorted order.
+ // --slow for large lists
+ // index_insert_sorted(temp_record);
+ // -- so we just add it to the end of the list
+ // and sort it at the end tp make sure nobody
+ // messed us up by editting the file by hand
+ if ( last_record == NULL ) { // first record
+ map_index_head = temp_record;
+ }
+ else {
+ last_record->next = temp_record;
+ }
+ last_record = temp_record;
+
+
+ // Remember that we may just have attached the
+ // record to our in-memory map list, or we may
+ // have free'ed it in the above function call.
+ // Set the pointer to NULL to make sure we don't
+ // try to do anything else with the memory.
+ temp_record = NULL;
+ }
+ else { // sscanf didn't parse the proper number of
+ // items. Delete the record.
+
+// Remember to free the XmString pointer if necessary.
+
+ free(temp_record);
+// fprintf(stderr,"index_restore_from_file:sscanf parsing error\n");
+ }
+ }
+ }
+ }
+ (void)fclose(f);
+ // now that we have read the whole file, make sure it is sorted
+ index_sort(); // probably should check for dup records
+
+ if (doing_migration) {
+ // Save in new file format if we just did a migration from
+ // old format to new.
+ fprintf(stderr,"Migrating from old map_index.sys format to new format.\n");
+ index_save_to_file();
+ }
+}
+
+
+
+
+
+// map_indexer()
+//
+// Recurses through the map directories finding map extents
+// and recording them in the map index. Once the indexing is
+// complete, write the current index out to a file.
+//
+// It'd be nice to call index_restore_from_file() from main.c:main()
+// so that an earlier copy of the index is restored before the map
+// display is created.
+//
+// If we set the "accessed" variable in the in-memory index to 0 for
+// each record and then run the indexer, the save-to-file function
+// will delete those with a value of 0 when writing to disk. Those
+// maps no longer exist in the filesystem and should be deleted. We
+// could either wipe them from the in-memory database at that time
+// as well, or wipe the whole list and re-read it from disk to get
+// the current list.
+//
+// If parameter is 0, we'll do the smart timestamp-checking
+// indexing.
+// If 1, we'll erase the in-memory index and do full indexing.
+//
+void map_indexer(int parameter) {
+ struct stat nfile;
+ int check_times = 1;
+ FILE *f;
+ map_index_record *current;
+ map_index_record *backup_list_head = NULL;
+ char map_index_path[MAX_VALUE];
+
+ get_user_base_dir(MAP_INDEX_DATA, map_index_path, sizeof(map_index_path));
+
+
+ if (debug_level & 16)
+ fprintf(stderr,"map_indexer() start\n");
+
+ fprintf(stderr,"Indexing maps...\n");
+
+#ifdef HAVE_LIBSHP
+#ifdef WITH_DBFAWK
+ // get rid of stored dbfawk signatures and force reload.
+ clear_dbfawk_sigs();
+#endif
+#endif
+
+ // Find the timestamp on the index file first. Save it away so
+ // that the timestamp for each map file can be compared to it.
+ if (stat ( map_index_path, &nfile) != 0) {
+
+ // File doesn't exist yet. Create it.
+ f = fopen( map_index_path, "w" );
+ if (f != NULL)
+ (void)fclose(f);
+ else
+ fprintf(stderr,"Couldn't create map index file: %s\n",
+ map_index_path );
+
+ check_times = 0; // Don't check the timestamps. Do them all.
+ }
+ else { // File exists
+ map_index_timestamp = (time_t)nfile.st_mtime;
+ check_times = 1;
+ }
+
+
+ if (parameter == 1) { // Full indexing instead of timestamp-check indexing
+
+ // Move the in-memory index to a backup pointer
+ backup_list_head = map_index_head;
+ map_index_head = NULL;
+
+// // Set the timestamp to 0 so that everything gets indexed
+// map_index_timestamp = (time_t)0l;
+
+ check_times = 0;
+ }
+
+
+ // Set the "accessed" field to zero for every record in the
+ // index. Note that the list could be empty at this point.
+ current = map_index_head;
+ while (current != NULL) {
+ current->accessed = 0;
+ current = current->next;
+ }
+
+
+ if (check_times) {
+ if (debug_level & 16)
+ fprintf(stderr,"map_indexer: Calling map_search\n");
+
+ map_search (NULL, AUTO_MAP_DIR, NULL, NULL, (int)FALSE, INDEX_CHECK_TIMESTAMPS);
+
+ if (debug_level & 16)
+ fprintf(stderr,"map_indexer: Returned from map_search\n");
+ }
+ else {
+ if (debug_level & 16)
+ fprintf(stderr,"map_indexer: Calling map_search\n");
+
+ map_search (NULL, AUTO_MAP_DIR, NULL, NULL, (int)FALSE, INDEX_NO_TIMESTAMPS);
+
+ if (debug_level & 16)
+ fprintf(stderr,"map_indexer: Returned from map_search\n");
+ }
+
+ if (debug_level & 16)
+ fprintf(stderr,"map_indexer() middle\n");
+
+
+ if (parameter == 1) { // Full indexing instead of timestamp-check indexing
+ // Copy the Properties from the backup list to the new list,
+ // then free the backup list.
+ map_index_copy_properties(map_index_head, backup_list_head);
+ }
+
+
+ // Save the updated index to the file
+ index_save_to_file();
+
+ fprintf(stderr,"Finished indexing maps\n");
+
+ if (debug_level & 16)
+ fprintf(stderr,"map_indexer() end\n");
+}
+
+
+
+
+
+/* moved these here and made them static so it will function on FREEBSD */
+#define MAX_ALERT 7000
+// If we comment this out, we link, but get a segfault at runtime.
+// Take out the "static" and we get a segfault when we zoom out too
+// far with the lakes or counties shapefile loaded. No idea why
+// yet. --we7u
+//static alert_entry alert[MAX_ALERT];
+static int alert_count;
+
+
+
+
+
+/*******************************************************************
+ * fill_in_new_alert_entries()
+ *
+ * Fills in the index and filename portions of any alert entries
+ * that are missing them. This function should be called at the
+ * point where we've just received a new weather alert.
+ *
+
+//WE7U
+// Later we should change this so that it doesn't scan the entire
+// message list, but is passed the important info directly from the
+// decode routines in db.c, and the message should NOT be added to
+// the message list.
+//WE7U
+
+ *
+ * This function is designed to use ESRI Shapefile map files. The
+ * base directory where the Shapefiles are located is passed to us
+ * in the "dir" variable.
+ *
+ * map_search() fills in the filename field of the alert struct.
+ * draw_shapefile_map() fills in the index field.
+ *******************************************************************/
+void fill_in_new_alert_entries() {
+// int ii;
+ char alert_scan[MAX_FILENAME], *dir_ptr;
+ struct hashtable_itr *iterator = NULL;
+ alert_entry *temp;
+ char dir[MAX_FILENAME];
+
+
+ if (debug_level & 2)
+ fprintf(stderr,"fill_in_new_alert_entries start\n");
+
+ xastir_snprintf(dir,
+ sizeof(dir),
+ "%s",
+ ALERT_MAP_DIR);
+
+ alert_count = MAX_ALERT - 1;
+
+ // Set up our path to the wx alert maps
+ memset(alert_scan, 0, sizeof (alert_scan)); // Zero our alert_scan string
+ xastir_snprintf(alert_scan, // Fetch the base directory
+ sizeof(alert_scan),
+ "%s",
+ dir);
+ strncat(alert_scan, // Complete alert directory is now set up in the string
+ "/",
+ sizeof(alert_scan) - 1 - strlen(alert_scan));
+ dir_ptr = &alert_scan[strlen (alert_scan)]; // Point to end of path
+
+ // Iterate through the weather alerts. It looks like we wish to
+ // just fill in the alert struct and to determine whether the
+ // alert is within our viewport here. We don't wish to draw the
+ // alerts at this stage, that happens in the load_alert_maps()
+ // function below.
+
+ iterator = create_wx_alert_iterator();
+ temp = get_next_wx_alert(iterator);
+ while (iterator != NULL && temp) {
+
+ if (!temp->filename[0]) { // Filename is
+ // empty, we need to fill it in.
+
+// fprintf(stderr,"fill_in_new_alert_entries() Title: %s\n",temp->title);
+
+ // The last parameter denotes loading into
+ // pixmap_alerts instead of pixmap or pixmap_final.
+ // Note that just calling map_search does not get
+ // the alert areas drawn on the screen. The
+ // draw_map() function called by map_search just
+ // fills in the filename field in the struct and
+ // exits.
+ //
+ // The "warn" parameter (next to last) specifies whether
+ // to dump warnings out to the console as well. If the
+ // warning was received on local RF or locally, warn the
+ // operator (the weather must be near).
+ map_search (da,
+ alert_scan,
+ temp,
+ &alert_count,
+ (int)temp->flags[source],
+ DRAW_TO_PIXMAP_ALERTS);
+
+// fprintf(stderr,"fill_in_new_alert_entries() Title1:%s\n",temp->title);
+ }
+ temp = get_next_wx_alert(iterator);
+ }
+#ifndef USING_LIBGC
+//fprintf(stderr,"free iterator 4\n");
+ if (iterator) free(iterator);
+#endif // USING_LIBGC
+
+ if (debug_level & 2)
+ fprintf(stderr,"fill_in_new_alert_entries end\n");
+}
+
+
+
+
+/*******************************************************************
+ * load_alert_maps()
+ *
+ * Used to load weather alert maps, based on NWS weather alerts that
+ * are received. Called from create_image() and refresh_image().
+ * This function is designed to use ESRI Shapefile map files. The
+ * base directory where the Shapefiles are located is passed to us
+ * in the "dir" variable.
+ *
+ * map_search() fills in the filename field of the alert struct.
+ * draw_shapefile_map() fills in the index field.
+ *******************************************************************/
+void load_alert_maps (Widget w, char *dir) {
+// int ii;
+ int level;
+ unsigned char fill_color[] = { (unsigned char)0x69, // gray86
+ (unsigned char)0x4a, // red2
+ (unsigned char)0x63, // yellow2
+ (unsigned char)0x66, // cyan2
+ (unsigned char)0x61, // RoyalBlue
+ (unsigned char)0x64, // ForestGreen
+ (unsigned char)0x62 }; // orange3
+
+ struct hashtable_itr *iterator = NULL;
+ alert_entry *temp;
+ map_draw_flags mdf;
+
+
+//fprintf(stderr,"load_alert_maps\n");
+
+// TODO:
+// Figure out how to pass a quantity of zones off to the map drawing
+// routines, then we can draw them all with one pass through each
+// map file. Alphanumerically sort the zones to make it easier for
+// the map drawing functions? Note that the indexing routines fill
+// in both the filename and the shapefile index for each record.
+//
+// Alternative: Call map_draw for each filename listed and have the
+// draw_shapefile function iterate through the array looking for all
+// filename matches, pulling non-negative indexes out of each index
+// field for matches and drawing them. That should be fast and
+// require no sorting of the array. Downside: The alerts won't be
+// layered based on alert level unless we modify the above: Drawing
+// each file once for each alert-level in the proper layering order.
+// Perhaps we could keep a list of which filenames have been called,
+// and only call each one once per load_alert_maps() call.
+
+
+// Just for a test
+//draw_shapefile_map (w, dir, filenm, alert, alert_color, destination_pixmap);
+//draw_shapefile_map (w, dir, "c_16my01.shp", NULL, '\0', DRAW_TO_PIXMAP_ALERTS);
+
+
+// Are we drawing them in reverse order so that the important
+// alerts end up drawn on top of the less important alerts?
+// Actually, since the alert hash isn't ordered, perhaps we need to
+// order them by priority, then by map file, so that we can draw the
+// shapes from each map file in the correct order. This might cause
+// each map file to be drawn up to three times (once for each
+// priority level), but that's better than calling each map for each
+// zone as is done now.
+
+ iterator = create_wx_alert_iterator();
+ temp = get_next_wx_alert(iterator);
+ while (iterator != NULL && temp) {
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+#ifndef USING_LIBGC
+//fprintf(stderr,"free iterator 5\n");
+ if (iterator) free(iterator);
+#endif // USING_LIBGC
+ return;
+ }
+
+ if (disable_all_maps) {
+#ifndef USING_LIBGC
+//fprintf(stderr,"free iterator 6\n");
+ if (iterator) free(iterator);
+#endif // USING_LIBGC
+ return;
+ }
+
+ // Check whether the alert slot is filled/empty
+ if (temp->title[0] == '\0') { // Empty slot
+ temp = get_next_wx_alert(iterator);
+ continue;
+ }
+
+ if ( (level = alert_active(temp, ALERT_ALL) ) ) {
+ if (level >= (int)sizeof (fill_color))
+ level = 0;
+
+ // The last parameter denotes drawing into pixmap_alert
+ // instead of pixmap or pixmap_final.
+
+ if (debug_level & 16) {
+ fprintf(stderr,"load_alert_maps() Drawing %s\n",temp->filename);
+ fprintf(stderr,"load_alert_maps() Title4:%s\n",temp->title);
+ }
+
+ // Attempt to draw alert
+ if ( temp->index != -1 ) { // Shape found in shapefile
+
+ // Check whether we've ever tried to draw this alert
+ // before. If not, attempt it and get the boundary
+ // limits filled in.
+ //
+ if ( temp->bottom_boundary == 0.0
+ && temp->top_boundary == 0.0
+ && temp->left_boundary == 0.0
+ && temp->right_boundary == 0.0) {
+
+ if (temp->alert_level != 'C') {
+ draw_map (w, dir, temp->filename, temp,
+ fill_color[level], DRAW_TO_PIXMAP_ALERTS, &mdf); // draw filled
+ }
+ }
+
+ if (map_visible_lat_lon(temp->bottom_boundary, // Shape visible
+ temp->top_boundary,
+ temp->left_boundary,
+ temp->right_boundary) ) {
+
+ if (temp->alert_level != 'C') { // Alert not cancelled
+ mdf.draw_filled=1;
+ mdf.usgs_drg=0;
+
+ if (debug_level & 16)
+ fprintf(stderr,"load_alert_maps: Calling draw_map\n");
+
+ draw_map (w, dir, temp->filename, temp,
+ fill_color[level], DRAW_TO_PIXMAP_ALERTS, &mdf); // draw filled
+ }
+ if (temp) temp->flags[on_screen] = 'Y';
+ }
+ else {
+ // Not in our viewport, don't draw it!
+ if (debug_level & 16) fprintf(stderr,"load_alert_maps() Alert not visible\n");
+//fprintf(stderr,"B:%f T:%f L:%f R:%f\n", temp->bottom_boundary, temp->top_boundary, temp->left_boundary, temp->right_boundary);
+ if (temp) temp->flags[on_screen] = 'N';
+ }
+ }
+ else {
+ // Can't find this shape in the shapefile.
+ if (debug_level & 16) {
+ fprintf(stderr,
+ "load_alert_maps() Shape %s, strlen=%d, not found in %s\n",
+ temp->title,
+ (int)strlen(temp->title),
+ temp->filename );
+ }
+ }
+ }
+ temp = get_next_wx_alert(iterator);
+ }
+#ifndef USING_LIBGC
+//fprintf(stderr,"free iterator 7\n");
+ if (iterator) free(iterator);
+#endif // USING_LIBGC
+
+ if (debug_level & 16) fprintf(stderr,"load_alert_maps() Done drawing all active alerts\n");
+
+ if (alert_display_request()) {
+ alert_redraw_on_update = redraw_on_new_data = 2;
+ }
+}
+
+
+
+
+
+// Here's the head of our sorted-by-layer maps list
+static map_index_record *map_sorted_list_head = NULL;
+
+
+static void empty_map_sorted_list(void) {
+ map_index_record *current = map_sorted_list_head;
+
+ while (map_sorted_list_head != NULL) {
+ current = map_sorted_list_head;
+ map_sorted_list_head = current->next;
+ if (current->XmStringPtr != NULL) {
+ XmStringFree(current->XmStringPtr);
+ }
+ free(current);
+ }
+}
+
+
+
+
+
+// Insert a map into the list at the end of the maps with the same
+// layer number. We'll need to look up the parameters for it from
+// the master map_index list and then attach a new record to our new
+// sorted list in the proper place.
+//
+// This function should be called when we're first starting up
+// Xastir and anytime that selected_maps.sys is changed.
+//
+static void insert_map_sorted(char *filename){
+ map_index_record *current;
+ map_index_record *last;
+ map_index_record *temp_record;
+ unsigned long bottom;
+ unsigned long top;
+ unsigned long left;
+ unsigned long right;
+ int max_zoom;
+ int min_zoom;
+ int map_layer;
+ int draw_filled;
+ int usgs_drg;
+ int auto_maps;
+ int done;
+
+
+ if (index_retrieve(filename,
+ &bottom,
+ &top,
+ &left,
+ &right,
+ &max_zoom,
+ &min_zoom,
+ &map_layer,
+ &draw_filled,
+ &usgs_drg,
+ &auto_maps)) { // Found a match
+
+ // Allocate a new record
+ temp_record = (map_index_record *)malloc(sizeof(map_index_record));
+ CHECKMALLOC(temp_record);
+
+ // Fill in the values
+ xastir_snprintf(temp_record->filename,MAX_FILENAME,"%s",filename);
+ temp_record->bottom = bottom;
+ temp_record->top = top;
+ temp_record->left = left;
+ temp_record->right = right;
+ temp_record->max_zoom = max_zoom;
+ temp_record->min_zoom = min_zoom;
+ temp_record->map_layer = map_layer;
+ temp_record->draw_filled = draw_filled;
+ temp_record->usgs_drg = usgs_drg;
+ temp_record->auto_maps = auto_maps;
+ temp_record->selected = 1; // Always, we already know this!
+ temp_record->accessed = 0;
+ temp_record->next = NULL;
+ temp_record->XmStringPtr = NULL;
+
+ // Now find the proper place for it and insert it in
+ // layer-order into the list.
+ current = map_sorted_list_head;
+ last = map_sorted_list_head;
+ done = 0;
+
+ // Possible cases:
+ // Empty list
+ // insert at beginning of list
+ // insert at end of list
+ // insert between other entries
+
+ if (map_sorted_list_head == NULL) {
+ // Empty list. Insert record.
+ map_sorted_list_head = temp_record;
+ done++;
+ }
+ else if (map_layer < current->map_layer) {
+ // Insert at beginning of list
+ temp_record->next = current;
+ map_sorted_list_head = temp_record;
+ done++;
+ }
+ else { // Need to insert between records or at end of list
+ while (!done && (current != NULL) ) {
+ if (map_layer >= current->map_layer) { // Not to our layer yet
+ last = current;
+ current = current->next; // May point to NULL now
+ }
+ else if (map_layer < current->map_layer) {
+ temp_record->next = current;
+ last->next = temp_record;
+ done++;
+ }
+ }
+ }
+ // Handle running off the end of the list
+ if (!done && (current == NULL) ) {
+ last->next = temp_record;
+ }
+ }
+ else {
+ // We failed to find it in the map index
+ }
+}
+
+
+
+
+
+/**********************************************************
+ * load_auto_maps()
+ *
+ * NEW: Uses the in-memory map_index to scan through the
+ * maps.
+ *
+ * OLD: Recurses through the map directories looking for
+ * maps to load.
+ **********************************************************/
+void load_auto_maps (Widget w, char *dir) {
+ map_index_record *current = map_index_head;
+ map_draw_flags mdf;
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ return;
+ }
+
+ // Skip the sorting of the maps if we don't need to do it
+ if (re_sort_maps) {
+
+ //fprintf(stderr,"*** Sorting the selected maps by layer...\n");
+
+ // Empty the sorted list first. We'll create a new one.
+ empty_map_sorted_list();
+
+ // Run through the entire map_index linked list
+ while (current != NULL) {
+ if (auto_maps_skip_raster
+ && ( strstr(current->filename,".geo")
+ || strstr(current->filename,".GEO")
+ || strstr(current->filename,".Geo")
+ || strstr(current->filename,".tif")
+ || strstr(current->filename,".TIF")
+ || strstr(current->filename,".Tif"))) {
+ // Skip this map
+ }
+ else { // Draw this map
+
+ //fprintf(stderr,"Loading: %s/%s\n",SELECTED_MAP_DIR,current->filename);
+
+ //WE7U
+ insert_map_sorted(current->filename);
+
+/*
+ draw_map (w,
+ SELECTED_MAP_DIR,
+ current->filename,
+ NULL,
+ '\0',
+ DRAW_TO_PIXMAP);
+*/
+ }
+ current = current->next;
+ }
+
+ // All done sorting until something is changed in the Map
+ // Chooser.
+ re_sort_maps = 0;
+
+ //fprintf(stderr,"*** DONE sorting the selected maps.\n");
+ }
+
+ // We have the maps in sorted order. Run through the list and
+ // draw them. Only include those that have the auto_maps field
+ // set to 1.
+ current = map_sorted_list_head;
+ while (current != NULL) {
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ if (disable_all_maps) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ // Debug
+// fprintf(stderr,"Drawing level:%05d, file:%s\n",
+// current->map_layer,
+// current->filename);
+
+ // Draw the maps in sorted-by-layer order
+ if (current->auto_maps) {
+
+ mdf.draw_filled = current->draw_filled;
+ mdf.usgs_drg = current->usgs_drg;
+
+ if (debug_level & 16)
+ fprintf(stderr,"load_auto_maps: Calling draw_map\n");
+
+ draw_map (w,
+ SELECTED_MAP_DIR,
+ current->filename,
+ NULL,
+ '\0',
+ DRAW_TO_PIXMAP,
+ &mdf);
+ }
+
+ current = current->next;
+ }
+}
+
+
+
+
+
+/*******************************************************************
+ * load_maps()
+ *
+ * Loads maps, draws grid, updates the display.
+ *
+ * We now create a linked list of maps in layer-order and use this
+ * list to draw the maps. This preserves the correct ordering in
+ * all cases. The layer to draw each map is specified in the
+ * map_index.sys file (fifth parameter). Eventually code will be
+ * added to the Map Chooser in order to change the layer each map is
+ * drawn at.
+ *******************************************************************/
+void load_maps (Widget w) {
+ FILE *f;
+ char mapname[MAX_FILENAME];
+ int i;
+ char selected_dir[MAX_FILENAME];
+ map_index_record *current;
+ map_draw_flags mdf;
+ char selected_map_path[MAX_VALUE];
+
+ get_user_base_dir(SELECTED_MAP_DATA, selected_map_path, sizeof(selected_map_path));
+
+// int dummy;
+
+
+ if (debug_level & 16)
+ fprintf(stderr,"Load maps start\n");
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ // Skip the sorting of the maps if we don't need to do it
+ if (re_sort_maps) {
+
+ //fprintf(stderr,"*** Sorting the selected maps by layer...\n");
+
+ // Empty the sorted list first. We'll create a new one.
+ empty_map_sorted_list();
+
+ // Make sure the string is empty before we start
+ selected_dir[0] = '\0';
+
+ // Create empty file if it doesn't exist
+ (void)filecreate( selected_map_path );
+
+ f = fopen ( selected_map_path, "r" );
+ if (f != NULL) {
+ if (debug_level & 16)
+ fprintf(stderr,"Load maps Open map file\n");
+
+ while (!feof (f)) {
+
+ // Grab one line from the file
+ if ( fgets( mapname, MAX_FILENAME-1, f ) != NULL ) {
+
+ // Forced termination (just in case)
+ mapname[MAX_FILENAME-1] = '\0';
+
+ // Get rid of the newline at the end
+ for (i = strlen(mapname); i > 0; i--) {
+ if (mapname[i] == '\n')
+ mapname[i] = '\0';
+ }
+
+ if (debug_level & 16)
+ fprintf(stderr,"Found mapname: %s\n", mapname);
+
+ // Test for comment
+ if (mapname[0] != '#') {
+
+
+ // Check whether it's a directory that was
+ // selected. If so, save it in a special
+ // variable and use that to match all the files
+ // inside the directory. Note that with the way
+ // we have things ordered in the list, the
+ // directories appear before their member files.
+ if (mapname[strlen(mapname)-1] == '/') {
+ int len;
+
+ // Found a directory. Save the name.
+ xastir_snprintf(selected_dir,
+ sizeof(selected_dir),
+ "%s",
+ mapname);
+
+ len = strlen(mapname);
+
+//fprintf(stderr,"Selected %s directory\n",selected_dir);
+
+ // Here we need to run through the map_index
+ // list to find all maps that match the
+ // currently selected directory. Attempt to
+ // load all of those maps as well.
+
+//fprintf(stderr,"Load all maps under this directory: %s\n",selected_dir);
+
+ // Point to the start of the map_index list
+ current = map_index_head;
+
+ while (current != NULL) {
+
+ if (strncmp(current->filename,selected_dir,len) == 0) {
+
+ if (current->filename[strlen(current->filename)-1] != '/') {
+
+//fprintf(stderr,"Loading: %s\n",current->filename);
+
+ //WE7U
+ insert_map_sorted(current->filename);
+
+/*
+ draw_map (w,
+ SELECTED_MAP_DIR,
+ current->filename,
+ NULL,
+ '\0',
+ DRAW_TO_PIXMAP);
+*/
+
+ }
+ }
+ current = current->next;
+ }
+ }
+ // Else must be a regular map file
+ else {
+//fprintf(stderr,"%s\n",mapname);
+//start_timer();
+
+ //WE7U
+ insert_map_sorted(mapname);
+
+/*
+ draw_map (w,
+ SELECTED_MAP_DIR,
+ mapname,
+ NULL,
+ '\0',
+ DRAW_TO_PIXMAP);
+*/
+
+//stop_timer();
+//print_timer_results();
+
+ if (debug_level & 16)
+ fprintf(stderr,"Load maps -%s\n", mapname);
+
+ XmUpdateDisplay (da);
+ }
+ }
+ }
+ else { // We've hit EOF
+ break;
+ }
+
+ }
+ (void)fclose (f);
+ statusline(" ",1); // delete status line
+ }
+ else
+ fprintf(stderr,"Couldn't open file: %s\n", selected_map_path );
+
+ // All done sorting until something is changed in the Map
+ // Chooser.
+ re_sort_maps = 0;
+
+ //fprintf(stderr,"*** DONE sorting the selected maps.\n");
+ }
+
+
+ // We have the maps in sorted order. Run through the list and
+ // draw them.
+ current = map_sorted_list_head;
+ while (current != NULL) {
+
+ HandlePendingEvents(app_context);
+ if (interrupt_drawing_now) {
+ statusline(" ",1); // delete status line
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ if (disable_all_maps) {
+ // Update to screen
+ (void)XCopyArea(XtDisplay(da),
+ pixmap,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ return;
+ }
+
+ // Debug
+// fprintf(stderr,"Drawing level:%05d, file:%s\n",
+// current->map_layer,
+// current->filename);
+
+ // Draw the maps in sorted-by-layer order
+ mdf.draw_filled = current->draw_filled;
+ mdf.usgs_drg = current->usgs_drg;
+
+ if (debug_level & 16)
+ fprintf(stderr,"load_maps: Calling draw_map\n");
+
+// Map profiling, set up for 800x600 window at "Map Profile Test
+// Site" bookmark.
+//
+// Loading "rd011802.shp" 500 times takes
+// 302->256->264->269->115->116 seconds.
+//
+// 100 times on PP200 takes 192->183 seconds.
+//
+//start_timer();
+//fprintf(stderr,"Calling draw_map() 500 times...\n");
+//for (dummy = 0; dummy < 500; dummy++) {
+ draw_map (w,
+ SELECTED_MAP_DIR,
+ current->filename,
+ NULL,
+ '\0',
+ DRAW_TO_PIXMAP,
+ &mdf);
+//}
+//stop_timer(); print_timer_results();
+
+ current = current->next;
+ }
+
+ if (debug_level & 16)
+ fprintf(stderr,"Load maps stop\n");
+}
+
+
diff --git a/src/maps.h b/src/maps.h
new file mode 100644
index 0000000..d3c2582
--- /dev/null
+++ b/src/maps.h
@@ -0,0 +1,230 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: maps.h,v 1.75 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifndef __XASTIR_MAPS_H
+#define __XASTIR_MAPS_H
+
+#include <X11/Intrinsic.h>
+#include <Xm/Xm.h>
+
+#define MAX_OUTBOUND 900
+#define MAX_MAP_POINTS 100000
+#define MAX_FILENAME 2000
+
+#define DRAW_TO_PIXMAP 0
+#define DRAW_TO_PIXMAP_FINAL 1
+#define DRAW_TO_PIXMAP_ALERTS 2
+#define INDEX_CHECK_TIMESTAMPS 9998
+#define INDEX_NO_TIMESTAMPS 9999
+
+
+/* memory structs */
+
+typedef struct {
+ unsigned char vector_start_color;
+ unsigned char object_behavior;
+ unsigned long longitude;
+ unsigned long latitude;
+} map_vectors;
+
+typedef struct {
+ unsigned long longitude;
+ unsigned long latitude;
+ unsigned int mag;
+ char label_text[33];
+ unsigned char text_color_quad;
+} text_label;
+
+typedef struct {
+ unsigned long longitude;
+ unsigned long latitude;
+ unsigned int mag;
+ unsigned char symbol;
+ unsigned char aprs_symbol;
+ unsigned char text_color;
+ char label_text[30];
+} symbol_label;
+
+typedef struct _map_index_record{
+ char filename[MAX_FILENAME];
+ XmString XmStringPtr;
+ unsigned long bottom;
+ unsigned long top;
+ unsigned long left;
+ unsigned long right;
+ int accessed;
+ int max_zoom; // Specify maximum zoom at which this layer is drawn.
+ int min_zoom; // Specify minimum zoom at which this layer is drawn.
+ int map_layer; // Specify which layer to draw the map on.
+ int draw_filled; // Specify whether to fill polygons when drawing.
+ // 0 = Global No-Fill (Vector)
+ // 1 = Global Fill
+ // 2 = Auto (dbfawk controls it if present)
+ int usgs_drg; // Specify whether the map has USGS DRG colormap
+ // and should have color configuration applied
+ // 0 = No
+ // 1 = Yes
+ // 2 = Auto (detect from TIFFTAG_IMAGEDESCRIPTION)
+ int selected; // Specifies if map is currently selected
+ int temp_select; // Temporary selection used in map properties dialog
+ int auto_maps; // Specifies if map included in automaps function
+ struct _map_index_record *next;
+} map_index_record;
+extern map_index_record *map_index_head;
+
+typedef struct {
+ int img_x;
+ int img_y;
+ unsigned long x_long;
+ unsigned long y_lat;
+} tiepoint;
+
+void draw_point(Widget w,
+ unsigned long x1,
+ unsigned long y1,
+ GC gc,
+ Pixmap which_pixmap,
+ int skip_duplicates);
+
+void draw_point_ll(Widget w,
+ float y1,
+ float x1,
+ GC gc,
+ Pixmap which_pixmap,
+ int skip_duplicates);
+
+void draw_vector(Widget w,
+ unsigned long x1,
+ unsigned long y1,
+ unsigned long x2,
+ unsigned long y2,
+ GC gc,
+ Pixmap which_pixmap,
+ int skip_duplicates);
+
+void draw_vector_ll(Widget w,
+ float y1,
+ float x1,
+ float y2,
+ float x2,
+ GC gc,
+ Pixmap which_pixmap,
+ int skip_duplicates);
+
+char *get_map_ext (char *filename);
+char *get_map_dir (char *fullpath);
+void load_auto_maps(Widget w, char *dir);
+void load_maps(Widget w);
+void fill_in_new_alert_entries(void);
+void load_alert_maps(Widget w, char *dir);
+void index_update_xastir(char *filename, unsigned long bottom, unsigned long top, unsigned long left, unsigned long right, int default_map_layer);
+void index_update_ll(char *filename, double bottom, double top, double left, double right, int default_map_layer);
+extern void get_horizontal_datum(char *datum, int sizeof_datum);
+void draw_grid (Widget w);
+void Snapshot(void);
+extern int index_retrieve(char *filename, unsigned long *bottom,
+ unsigned long *top, unsigned long *left, unsigned long *right,
+ int *max_zoom, int *min_zoom, int *map_layer, int *draw_filled,
+ int *usgs_drg, int *automaps);
+extern void index_restore_from_file(void);
+extern void index_save_to_file(void);
+extern void map_indexer(int parameter);
+extern void get_viewport_lat_lon(double *xmin,
+ double *ymin,
+ double *xmax,
+ double *ymax);
+extern int map_visible (unsigned long bottom_map_boundary,
+ unsigned long top_map_boundary,
+ unsigned long left_map_boundary,
+ unsigned long right_map_boundary);
+extern int map_visible_lat_lon (double f_bottom_map_boundary,
+ double f_top_map_boundary,
+ double f_left_map_boundary,
+ double f_right_map_boundary);
+extern int map_inside_viewport_lat_lon(double map_min_y,
+ double map_max_y,
+ double map_min_x,
+ double map_max_x);
+extern void draw_label_text (Widget w, int x, int y, int label_length, int color, char *label_text);
+extern void draw_rotated_label_text (Widget w, int rotation, int x, int y, int label_length, int color, char *label_text, int fontsize);
+extern int get_rotated_label_text_length_pixels(Widget w, char *label_text, int fontsize);
+extern void draw_centered_label_text (Widget w, int rotation, int x, int y, int label_length, int color, char *label_text, int fontsize);
+extern void Monochrome( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData);
+extern void Snapshot(void);
+extern void clean_string(char *input);
+extern int print_rotated;
+extern int print_auto_rotation;
+extern int print_auto_scale;
+extern int print_in_monochrome;
+extern int print_invert;
+extern char printer_program[MAX_FILENAME+1];
+extern char previewer_program[MAX_FILENAME+1];
+
+extern int gnis_locate_place(Widget w, char *name, char *state,
+char *county, char *quad, char* type, char *filename, int
+follow_case, int get_match, char match_array_name[50][200], long
+match_array_lat[50], long match_array_long[50]);
+
+extern int pop_locate_place(Widget w, char *name, char *state,
+char *county, char *quad, char* type, char *filename, int
+follow_case, int get_match, char match_array_name[50][200], long
+match_array_lat[50], long match_array_long[50]);
+
+
+extern void maps_init(void);
+enum map_onscreen_enum {MAP_NOT_VIS=0,MAP_IS_VIS,MAP_NOT_INDEXED};
+extern enum map_onscreen_enum map_onscreen(long left, long right, long top, long bottom, int checkpercentage);
+extern enum map_onscreen_enum map_onscreen_index(char *filename);
+extern time_t last_snapshot;
+extern time_t last_kmlsnapshot;
+extern int snapshot_interval;
+
+extern int grid_size;
+
+#if !defined(NO_GRAPHICS)
+ #if defined(HAVE_MAGICK)
+ extern float imagemagick_gamma_adjust;
+ #endif // HAVE_MAGICK
+#endif // NO_GRAPHICS
+
+extern float raster_map_intensity;
+
+extern void Print_Postscript(Widget widget, XtPointer clientData, XtPointer callData);
+
+extern void map_plot (Widget w, long max_x, long max_y, long x_long_cord, long y_lat_cord, unsigned char color, long object_behavior, int destination_pixmap, int draw_filled);
+
+extern void map_gdal_init(void);
+
+// A struct to pass down in to map driver functions so they can have
+// driver-specific flags. Most drivers won't care about any (or even all)
+// of the flags, but this way we can just pass a single pointer rather than
+// adding new arguments to the generic interface each time we want new flags
+typedef struct {
+ int draw_filled;
+ int usgs_drg;
+} map_draw_flags;
+
+#endif /* __XASTIR_MAPS_H */
+
+
diff --git a/src/messages.c b/src/messages.c
new file mode 100644
index 0000000..b134964
--- /dev/null
+++ b/src/messages.c
@@ -0,0 +1,1480 @@
+/*
+ * $Id: messages.c,v 1.80 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <Xm/XmAll.h>
+#include <X11/Xatom.h>
+#include <X11/Shell.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+#include <ctype.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+#include "xastir.h"
+#include "main.h"
+#include "messages.h"
+#include "util.h"
+#include "interface.h"
+#include "xa_config.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+char group_data_file[400];
+char *group_data_list = NULL; // Need this NULL for Solaris!
+int group_data_count = 0;
+int group_data_max = 0;
+
+char message_counter[5+1];
+
+int auto_reply;
+char auto_reply_message[100];
+
+Message_Window mw[MAX_MESSAGE_WINDOWS+1]; // Send Message widgets
+
+Message_transmit message_pool[MAX_OUTGOING_MESSAGES+1]; // Transmit message queue
+
+
+
+
+
+void clear_message_windows(void) {
+ int i;
+
+begin_critical_section(&send_message_dialog_lock, "messages.c:clear_message_windows" );
+
+ for (i = 0; i < MAX_MESSAGE_WINDOWS; i++) {
+
+ if (mw[i].send_message_dialog)
+ XtDestroyWidget(mw[i].send_message_dialog);
+
+ mw[i].send_message_dialog = (Widget)NULL;
+ mw[i].to_call_sign[0] = '\0';
+ mw[i].send_message_call_data = (Widget)NULL;
+ mw[i].D700_mode = (Widget)NULL;
+ mw[i].D7_mode = (Widget)NULL;
+ mw[i].HamHUD_mode = (Widget)NULL;
+ mw[i].message_data_line1 = (Widget)NULL;
+ mw[i].message_data_line2 = (Widget)NULL;
+ mw[i].message_data_line3 = (Widget)NULL;
+ mw[i].message_data_line4 = (Widget)NULL;
+ mw[i].send_message_text = (Widget)NULL;
+ }
+
+end_critical_section(&send_message_dialog_lock, "messages.c:clear_message_windows" );
+
+}
+
+
+
+
+
+static int group_comp(const void *a, const void *b) {
+ if (!*(char *)a)
+ return ((int)(*(char *)b != '\0'));
+ return strcasecmp(a, b);
+}
+
+
+
+
+
+void group_build_list(char *filename) {
+ char *ptr;
+ FILE *f;
+ struct stat group_stat;
+ int i;
+
+ if (group_data_count == group_data_max) {
+ ptr = realloc(group_data_list, (size_t)(group_data_max+10)*10);
+
+ if (ptr) {
+ group_data_list = ptr;
+ group_data_max += 10;
+
+//fprintf(stderr, "group_data_max: %d\n", group_data_max);
+
+ }
+ else {
+ fprintf(stderr,
+ "Unable to allocate more memory for group_data_list (1)\n");
+ }
+ }
+
+
+// Make sure we always listen for ourself, XASTIR, & our Version groups
+ xastir_snprintf(&group_data_list[0],10,"%s",my_callsign);
+ xastir_snprintf(&group_data_list[10],10,"XASTIR");
+ xastir_snprintf(&group_data_list[20],10,"%s",XASTIR_TOCALL);
+ group_data_count = 3;
+// If we are in special group look for messages.
+ if (altnet) {
+ xastir_snprintf(&group_data_list[group_data_count*10],10,"%s",altnet_call);
+ group_data_count++;
+ }
+//
+
+ if (! stat(filename, &group_stat) )
+ f = fopen(filename, "r"); // File exists
+ else
+ f = fopen(filename, "w+"); // No file. Create it and open it.
+
+ if (f == NULL) {
+ fprintf(stderr,"Couldn't open file for reading -or- appending: %s\n", filename);
+ return;
+ }
+
+ while (!feof(f)) {
+ if (group_data_count == group_data_max) {
+ ptr = realloc(group_data_list, (size_t)(group_data_max+10)*10);
+ if (ptr) {
+ group_data_list = ptr;
+ group_data_max += 10;
+
+//fprintf(stderr, "group_data_max(2): %d\n", group_data_max);
+
+ }
+ else {
+ fprintf(stderr,
+ "Unable to allocate more memory for group_data_list (2)\n");
+ }
+ }
+ if (group_data_count < group_data_max) {
+ group_data_list[group_data_count*10] = '\0';
+ (void)fgets(&group_data_list[group_data_count*10], 10, f);
+ if ((ptr = strchr(&group_data_list[group_data_count*10], '\n')))
+ *ptr = '\0';
+ else
+ while ((i = fgetc(f)) != EOF && i != '\n'); // clean-up after long group name
+
+ // check for DOS EOL markup!
+ if ((ptr = strchr(&group_data_list[group_data_count*10], '\r')))
+ *ptr = '\0';
+ if (group_data_list[group_data_count*10])
+ group_data_count++;
+ }
+ }
+ (void)fclose(f);
+ qsort(group_data_list, (size_t)group_data_count, 10, group_comp);
+
+ if (debug_level & 2) {
+ for (i = 0; i < group_data_count; i++)
+ fprintf(stderr,"Group %2d: %s\n", i, &group_data_list[i*10]);
+ }
+}
+
+
+
+
+
+int group_active(char *from) {
+ static struct stat current_group_stat;
+ struct stat group_stat;
+ static char altgroup[10];
+ char group_data_path[MAX_VALUE];
+
+ get_user_base_dir(group_data_file, group_data_path,
+ sizeof(group_data_path));
+
+ (void)remove_trailing_spaces(from);
+
+ // If we cycle to/from special group or file changes, rebuild group list.
+ if ((!stat( group_data_path, &group_stat )
+ && (current_group_stat.st_size != group_stat.st_size
+ || current_group_stat.st_mtime != group_stat.st_mtime
+ || current_group_stat.st_ctime != group_stat.st_ctime))) {
+
+// altgroup equates to "address of altgroup" which always evaluates
+// as true. Commenting it out of the conditional. --we7u.
+// || (altgroup && strcasecmp(altgroup, VERSIONFRM))) {
+
+ group_build_list( group_data_path );
+ current_group_stat = group_stat;
+ xastir_snprintf(altgroup,sizeof(altgroup),"%s",VERSIONFRM);
+ }
+ if (group_data_list != NULL) // Causes segfault on Solaris 2.5 without this!
+ return (int)(bsearch(from, group_data_list, (size_t)group_data_count, (size_t)10, group_comp) != NULL);
+ else
+ return(0);
+}
+
+
+
+
+
+int look_for_open_group_data(char *to) {
+ int i,found;
+ char temp1[MAX_CALLSIGN+1];
+ char *temp_ptr;
+
+
+begin_critical_section(&send_message_dialog_lock, "messages.c:look_for_open_group_data" );
+
+ found = FALSE;
+ for(i = 0; i < MAX_MESSAGE_WINDOWS; i++) {
+ /* find station */
+ if(mw[i].send_message_dialog != NULL) {
+
+ temp_ptr = XmTextFieldGetString(mw[i].send_message_call_data);
+ xastir_snprintf(temp1,
+ sizeof(temp1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)to_upper(temp1);
+ /*fprintf(stderr,"Looking at call <%s> for <%s>\n",temp1,to);*/
+ if(strcmp(temp1,to)==0) {
+ found=(int)TRUE;
+ break;
+ }
+ }
+ }
+
+end_critical_section(&send_message_dialog_lock, "messages.c:look_for_open_group_data" );
+
+ return(found);
+}
+
+
+
+
+
+// What we wish to do here: Check for an active Send Message dialog
+// that contains the callsign of interest. If one doesn't exist,
+// create one and pop it up. We don't want to do this for duplicate
+// message lines or duplicate acks for any particular QSO. To do so
+// would cause the Send Message dialog to pop up on every such
+// received message, which is VERY annoying (that was the default in
+// Xastir for years, and nobody liked it!).
+//
+int check_popup_window(char *from_call_sign, int group) {
+ int i,found,j,ret;
+ char temp1[MAX_CALLSIGN+1];
+ char *temp_ptr;
+
+
+//fprintf(stderr,"\tcheck_popup_window()\n");
+
+ ret = -1;
+ found = -1;
+
+begin_critical_section(&send_message_dialog_lock, "messages.c:check_popup_window" );
+
+ // Check for an already-created dialog for talking to this
+ // particular call_sign.
+ //
+ for (i = 0; i < MAX_MESSAGE_WINDOWS; i++) {
+
+ if (mw[i].send_message_dialog != NULL) { // If dialog created
+
+ temp_ptr = XmTextFieldGetString(mw[i].send_message_call_data);
+ xastir_snprintf(temp1,
+ sizeof(temp1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ /*fprintf(stderr,"Looking at call <%s> for <%s>\n",temp1,from_call_sign);*/
+ if (strcasecmp(temp1, from_call_sign) == 0) {
+ // Found a call_sign match in a Send Message dialog!
+
+//fprintf(stderr,"\tFound a Send_message dialog match\n");
+
+ found = i;
+ break;
+ }
+ }
+ }
+
+end_critical_section(&send_message_dialog_lock, "messages.c:check_popup_window" );
+
+ // If found == -1 at this point, we haven't found a Send Message
+ // dialog that contains the call_sign of interest.
+ //
+ if (found == -1 && (group == 2 || group_active(from_call_sign))) {
+ /* no window found Open one! */
+
+//fprintf(stderr,"\tNo Send Message dialog found, creating one\n");
+
+begin_critical_section(&send_message_dialog_lock, "messages.c:check_popup_window2" );
+
+ i= -1;
+ for (j=0; j<MAX_MESSAGE_WINDOWS; j++) {
+ if (!mw[j].send_message_dialog) {
+ i=j;
+ break;
+ }
+ }
+
+end_critical_section(&send_message_dialog_lock, "messages.c:check_popup_window2" );
+
+ if (i!= -1) {
+
+ if (group == 1) {
+ temp1[0] = '*';
+ temp1[1] = '\0';
+ }
+ else {
+ temp1[0] = '\0';
+ }
+
+ strncat(temp1,
+ from_call_sign,
+ sizeof(temp1) - 1 - strlen(temp1));
+
+ if (!disable_all_popups) {
+ Send_message(appshell, temp1, NULL);
+ }
+
+ update_messages(1);
+
+ ret=i;
+ }
+ else {
+ fprintf(stderr,"No open windows!\n");
+ }
+ }
+ else {
+ /* window open! */
+ // Pop it up
+ ret=found;
+ }
+
+ if (found != -1) { // Already have a window
+ XtPopup(mw[i].send_message_dialog,XtGrabNone);
+ }
+
+ return(ret);
+}
+
+
+
+
+
+void clear_outgoing_message(int i) {
+ message_pool[i].active=MESSAGE_CLEAR;
+ message_pool[i].to_call_sign[0] = '\0';
+ message_pool[i].from_call_sign[0] = '\0';
+ message_pool[i].message_line[0] = '\0';
+ message_pool[i].seq[0] = '\0';
+ message_pool[i].active_time=0;;
+ message_pool[i].next_time=0l;
+ message_pool[i].tries=0;
+}
+
+
+
+
+
+// Clear all pending transmit messages that are from us and to the
+// callsign listed. Perhaps it'd be better to time it out instead
+// so that it still shows up in the message window? Here we just
+// erase it.
+//
+void clear_outgoing_messages_to(char *callsign) {
+ int ii;
+
+
+// fprintf(stderr,"Callsign: %s\n", callsign);
+
+ // Run through the entire outgoing message queue
+ for (ii = 0; ii < MAX_OUTGOING_MESSAGES; ii++) {
+
+ // If it matches the callsign we're talking to
+ if (strcasecmp(message_pool[ii].to_call_sign,callsign) == 0) {
+
+ // Record a fake ack and add "*CANCELLED*" to the
+ // message. This will be displayed in the Send Message
+ // dialog.
+ msg_record_ack(message_pool[ii].to_call_sign,
+ message_pool[ii].from_call_sign,
+ message_pool[ii].seq,
+ 0, // Not a timeout
+ 1); // Record a cancel
+
+ // Clear it out.
+ message_pool[ii].active=MESSAGE_CLEAR;
+ message_pool[ii].to_call_sign[0] = '\0';
+ message_pool[ii].from_call_sign[0] = '\0';
+ message_pool[ii].message_line[0] = '\0';
+ message_pool[ii].seq[0] = '\0';
+ message_pool[ii].active_time=0;;
+ message_pool[ii].next_time=0l;
+ message_pool[ii].tries=0;
+ }
+ }
+}
+
+
+
+
+
+// Change path on all pending transmit messages that are from us and
+// to the callsign listed.
+//
+void change_path_outgoing_messages_to(char *callsign, char *new_path) {
+ int ii;
+ char my_callsign[20];
+
+
+//fprintf(stderr,
+// "Changing all outgoing msgs to %s to new path: %s\n",
+// callsign,
+// new_path);
+
+ xastir_snprintf(my_callsign,
+ sizeof(my_callsign),
+ "%s",
+ callsign);
+
+ remove_trailing_spaces(my_callsign);
+
+ // Run through the entire outgoing message queue
+ for (ii = 0; ii < MAX_OUTGOING_MESSAGES; ii++) {
+
+ if (message_pool[ii].active == MESSAGE_ACTIVE) {
+
+//fprintf(stderr,"\t'%s'\n\t'%s'\n",
+// message_pool[ii].to_call_sign,
+// my_callsign);
+
+ // If it matches the callsign we're talking to
+ if (strcasecmp(message_pool[ii].to_call_sign,my_callsign) == 0) {
+
+//fprintf(stderr,"\tFound an outgoing queued msg to change path on.\n");
+
+ xastir_snprintf(message_pool[ii].path,
+ sizeof(message_pool[ii].path),
+ "%s",
+ new_path);
+ }
+ }
+ }
+}
+
+
+
+
+
+time_t last_check_and_transmit = (time_t)0l;
+
+
+// Kick the interval timer back to 7 and tries back to 1 for
+// messages in this QSO. Used to get a QSO going again when the
+// interval timer has gotten large, but the message is important to
+// get through quickly.
+//
+void kick_outgoing_timer(char *callsign) {
+ int ii;
+
+
+// fprintf(stderr,"Callsign: %s\n", callsign);
+
+ // Run through the entire outgoing message queue
+ for (ii = 0; ii < MAX_OUTGOING_MESSAGES; ii++) {
+
+ // If it matches the callsign we're talking to
+ if (strcasecmp(message_pool[ii].to_call_sign,callsign) == 0) {
+ message_pool[ii].next_time = (time_t)7l;
+ message_pool[ii].tries = 0;
+ message_pool[ii].active_time = (time_t)0l;
+ }
+ }
+
+ // Cause the transmit routine to get called again
+ last_check_and_transmit = (time_t)0l;
+}
+
+
+
+
+
+void reset_outgoing_messages(void) {
+ int i;
+
+ for(i=0;i<MAX_OUTGOING_MESSAGES;i++)
+ clear_outgoing_message(i);
+}
+
+
+
+
+
+void clear_outgoing_messages(void) {
+ int i;
+
+ for (i=0;i<MAX_OUTGOING_MESSAGES;i++)
+ clear_outgoing_message(i);
+
+begin_critical_section(&send_message_dialog_lock, "messages.c:clear_outgoing_messages" );
+
+ /* clear message send buttons */
+ for (i=0;i<MAX_MESSAGE_WINDOWS;i++) {
+ /* find station */
+// if (mw[i].send_message_dialog!=NULL) /* clear submit */
+// XtSetSensitive(mw[i].button_ok,TRUE);
+ }
+
+end_critical_section(&send_message_dialog_lock, "messages.c:clear_outgoing_messages" );
+
+}
+
+
+
+
+
+// Bumps message sequence ID up to the next value.
+//
+// Roll over message_counter if we hit the max. Now with Reply/Ack
+// protocol the max is only two characters worth. We changed to
+// sending the sequence number in Base-?? format in order to get
+// more range from the 2-character variable.
+//
+int bump_message_counter(char *message_counter) {
+
+ int bump_warning = 0;
+ message_counter[2] = '\0'; // Terminate at 2 chars
+
+ // Increment the least significant digit
+ message_counter[1]++;
+
+ // Span the gaps between the correct ranges
+ if (message_counter[1] == ':')
+ message_counter[1] = 'A';
+
+ if (message_counter[1] == '[')
+ message_counter[1] = 'a';
+
+ if (message_counter[1] == '{') {
+ message_counter[1] = '0';
+ message_counter[0]++; // Roll over to next char
+ }
+
+ // Span the gaps between the correct ranges
+ if (message_counter[0] == ':')
+ message_counter[0] = 'A';
+
+ if (message_counter[0] == '[')
+ message_counter[0] = 'a';
+
+ if (message_counter[0] == '{') {
+ message_counter[0] = '0';
+ bump_warning = 1;
+ }
+ return bump_warning;
+}
+
+
+
+
+
+// Adds a message to the outgoing message queue. Doesn't actually
+// cause a transmit. "check_and_transmit_messages()" is the
+// function which actually gets things moving.
+//
+// We also stuff the message into the main message queue so that the
+// queued messages will appear in the Send Message box.
+//
+void output_message(char *from, char *to, char *message, char *path) {
+ int ok,i,j;
+ char message_out[MAX_MESSAGE_OUTPUT_LENGTH+1+5+1]; // +'{' +msg_id +terminator
+ int last_space, message_ptr, space_loc;
+ int wait_on_first_ack;
+ int error;
+ long record;
+
+
+//fprintf(stderr,"output_message:%s\n", message);
+
+ message_ptr=0;
+ last_space=0;
+ ok=0;
+ error=0;
+
+ if (debug_level & 2)
+ fprintf(stderr,"Output Message from <%s> to <%s>\n",from,to);
+
+ // Repeat until we process the entire message. We'll process it
+ // a chunk at a time, size of chunk to correspond to max APRS
+ // message line length.
+ //
+ while (!error && (message_ptr < (int)strlen(message))) {
+ ok=0;
+ space_loc=0;
+
+ // Break a long message into smaller chunks that can be
+ // processed into APRS messages. Break at a space character
+ // if possible.
+ //
+ for (j=0; j<MAX_MESSAGE_OUTPUT_LENGTH; j++) {
+
+ if(message[j+message_ptr] != '\0') {
+
+ if(message[j+message_ptr]==' ') {
+ last_space=j+message_ptr+1;
+ space_loc=j;
+ }
+
+ if (j!=MAX_MESSAGE_OUTPUT_LENGTH) {
+ message_out[j]=message[j+message_ptr];
+ message_out[j+1] = '\0';
+ }
+ else {
+
+ if(space_loc!=0)
+ message_out[space_loc] = '\0';
+ else
+ last_space=j+message_ptr;
+ }
+ }
+ else {
+ j=MAX_MESSAGE_OUTPUT_LENGTH+1;
+ last_space=strlen(message)+1;
+ }
+ }
+
+//fprintf(stderr,"message_out: %s\n", message_out);
+
+ if (debug_level & 2)
+ fprintf(stderr,"MESSAGE <%s> %d %d\n",message_out,message_ptr,last_space);
+
+ if (j >= MAX_MESSAGE_OUTPUT_LENGTH) {
+ message_ptr = MAX_MESSAGE_OUTPUT_LENGTH;
+ }
+ else {
+ message_ptr=last_space;
+ }
+
+ /* check for others in the queue */
+ wait_on_first_ack=0;
+ for (i=0; i<MAX_OUTGOING_MESSAGES; i++) {
+ if (message_pool[i].active == MESSAGE_ACTIVE
+ && strcmp(to, message_pool[i].to_call_sign) == 0
+ && strcmp(from, "***") != 0) {
+ wait_on_first_ack=1;
+ i=MAX_OUTGOING_MESSAGES+1; // Done with loop
+ }
+ }
+
+ for (i=0; i<MAX_OUTGOING_MESSAGES && !ok ;i++) {
+ /* Check for clear position*/
+ if (message_pool[i].active==MESSAGE_CLEAR) {
+ /* found a spot */
+ ok=1;
+
+ // Increment the message sequence ID variable
+ if (bump_message_counter(message_counter))
+ fprintf(stderr, "!WARNING!: Wrap around Message Counter");
+
+
+// Note that Xastir's messaging can lock up if we do a rollover and
+// have unacked messages on each side of the rollover. This is due
+// to the logic in db.c that looks for the lowest numbered unacked
+// message. We get stuck on both sides of the fence at once. To
+// avoid this condition we could reduce the compare number (8100) to
+// a smaller value, and only roll over when there are no unacked
+// messages? Another way to do it would be to write a "0" to the
+// config file if we're more than 1000 when we quit Xastir? That
+// would probably be easier. It's still possible to get to 8100
+// messages during one runtime though. Unlikely, but possible.
+
+ message_pool[i].active = MESSAGE_ACTIVE;
+ message_pool[i].wait_on_first_ack = wait_on_first_ack;
+ xastir_snprintf(message_pool[i].to_call_sign,
+ sizeof(message_pool[i].to_call_sign),
+ "%s",
+ to);
+ xastir_snprintf(message_pool[i].from_call_sign,
+ sizeof(message_pool[i].from_call_sign),
+ "%s",
+ from);
+ xastir_snprintf(message_pool[i].message_line,
+ sizeof(message_pool[i].message_line),
+ "%s",
+ message_out);
+
+ if (path != NULL)
+ xastir_snprintf(message_pool[i].path,
+ sizeof(message_pool[i].path),
+ "%s",
+ path);
+ else
+ message_pool[i].path[0] = '\0';
+
+// // We compute the base-90 sequence number here
+// // This allows it to range from "!!" to "zz"
+// xastir_snprintf(message_pool[i].seq,
+// sizeof(message_pool[i].seq),
+// "%c%c",
+// (char)(((message_counter / 90) % 90) + 33),
+// (char)((message_counter % 90) + 33));
+
+ xastir_snprintf(message_pool[i].seq,
+ sizeof(message_pool[i].seq),
+ "%c%c",
+ message_counter[0],
+ message_counter[1]);
+
+ message_pool[i].active_time=0;
+ message_pool[i].next_time = (time_t)7l;
+
+ if (strcmp(from,"***")!= 0)
+ message_pool[i].tries = 0;
+ else
+ message_pool[i].tries = MAX_TRIES-1;
+
+ // Cause the message to get added to the main
+ // message queue as well, with the proper sequence
+ // number, so queued messages will appear in the
+ // Send Message box as unacked messages.
+ //
+
+// We must get rid of the lock we already have for a moment, as
+// update_messages(), which is called by msg_data_add(), also snags
+// this lock.
+end_critical_section(&send_message_dialog_lock, "db.c:update_messages" );
+
+ (void)msg_data_add(to,
+ from,
+ message_out,
+ message_pool[i].seq,
+ MESSAGE_MESSAGE,
+ 'L', // From the Local system
+ &record);
+/*
+ fprintf(stderr,"msg_data_add %s %s %s %s\n",
+ to,
+ from,
+ message_out,
+ message_pool[i].seq);
+*/
+
+// Regain the lock we had before
+begin_critical_section(&send_message_dialog_lock, "db.c:update_messages" );
+
+ }
+ }
+ if(!ok) {
+ fprintf(stderr,"Output message queue is full!\n");
+ error=1;
+ }
+ }
+}
+
+
+
+
+
+// Here we're doing some routing of the transmitted packets. We
+// want to keep Xastir from transmitting on ports that aren't
+// actively being used in the QSO, but also cover the case where
+// ports can go up/down during the QSO.
+//
+// Note that igates might get into the act quite a bit for RF<->RF
+// QSO's if we're sending to the internet too, but that's a bug in
+// the igate software, and not something that Xastir should try to
+// correct itself.
+//
+void transmit_message_data(char *to, char *message, char *path) {
+ DataRow *p_station;
+
+ if (debug_level & 2)
+ fprintf(stderr,"Transmitting data to %s : %s\n",to,message);
+
+ p_station = NULL;
+
+
+ if (strcmp(to, my_callsign) == 0) { // My station message
+
+ // Send out all active ports
+
+ if (debug_level & 2)
+ fprintf(stderr,"My call VIA any way\n");
+
+ output_my_data(message,-1,0,0,0,path);
+
+ // All done
+ return;
+ }
+
+
+ if (!search_station_name(&p_station,to,1)) {
+
+ // No data record found for this station. Send to all
+ // active ports.
+
+ if (debug_level & 2)
+ fprintf(stderr,"VIA any way\n");
+
+ output_my_data(message,-1,0,0,0,path);
+
+ // All done
+ return;
+ }
+
+
+ if (debug_level & 2)
+ fprintf(stderr,"found station %s\n",p_station->call_sign);
+
+
+ // It's not being sent to my callsign but to somebody else
+ // "out there". Because the truth is...
+
+
+ if ( ((p_station->flag & ST_VIATNC) != 0)
+ && (heard_via_tnc_in_past_hour(to)) ) {
+
+ int port_num;
+
+
+ // Station was heard via a TNC port within the previous
+ // hour. Send to TNC port it was heard on.
+ //
+ output_my_data(message,p_station->heard_via_tnc_port,0,0,0,path);
+
+ // Send to all internet ports. Iterate through the port
+ // definitions looking for internet ports, send the message
+ // out once to each.
+ //
+ for (port_num = 0; port_num < MAX_IFACE_DEVICES; port_num++) {
+
+ // If it's an internet port, send the message.
+ if (port_data[port_num].device_type == DEVICE_NET_STREAM) {
+ output_my_data(message,port_num,0,0,0,path);
+ }
+ }
+
+ // All done
+ return;
+ }
+
+ else if (p_station->data_via==DATA_VIA_NET) {
+ int port_num;
+ int active_internet_ports_found = 0;
+
+
+ // Station was heard over an internet interface. Check
+ // whether we have any internet interfaces available with TX
+ // enabled. If so, send out those ports. Else drop through
+ // and hit the TRANSMIT-ALL clause at the end of this
+ // function.
+
+ // Iterate through the port definitions looking for internet
+ // ports with transmit enabled. Send the message out once
+ // to each.
+ //
+ for (port_num = 0; port_num < MAX_IFACE_DEVICES; port_num++) {
+
+ // If it's an internet port and transmit is enabled,
+ // send the message and set the flag.
+ if ( (port_data[port_num].device_type == DEVICE_NET_STREAM)
+ && (port_data[port_num].active == DEVICE_IN_USE)
+ && (port_data[port_num].status == DEVICE_UP)
+ && (devices[port_num].transmit_data == 1) ) {
+
+ // Found a tx-enabled internet port that was up and
+ // running. Send the message out this port.
+ output_my_data(message,port_num,0,0,0,path);
+
+ active_internet_ports_found++;
+ }
+ }
+
+ if (active_internet_ports_found) {
+ // We found at least one tx-enabled internet interface
+ // that was up and running.
+
+ // All done.
+ return;
+ }
+ else { // No active tx-enabled internet ports were found.
+ // Drop through to the TRANSMIT-ALL clause below.
+ }
+ }
+
+
+ // We've NOT heard this station on a TNC port within the
+ // last hour and have no active tx-enabled internet ports to
+ // send to. Send to ALL active ports.
+
+ if (debug_level & 2)
+ fprintf(stderr,"VIA any way\n");
+
+ output_my_data(message,-1,0,0,0,path);
+}
+
+
+
+
+
+// The below variables and functions implement the capability to
+// schedule ACK's some number of seconds out from the current time.
+// We use it to schedule duplicate ACK's at 30/60/120 seconds out,
+// but only if we see duplicate message lines from remote stations.
+//
+// Create a struct to hold the delayed ack's.
+typedef struct _delayed_ack_record {
+ char to_call_sign[MAX_CALLSIGN+1];
+ char message_line[MAX_MESSAGE_OUTPUT_LENGTH+1+5+1];
+ char path[200];
+ time_t active_time;
+ struct _delayed_ack_record *next;
+} delayed_ack_record, *delayed_ack_record_p;
+
+// And a pointer to a list of them.
+ delayed_ack_record_p delayed_ack_list_head = NULL;
+
+
+void transmit_message_data_delayed(char *to, char *message,
+ char *path, time_t when) {
+ delayed_ack_record_p ptr = delayed_ack_list_head;
+
+
+ // We need to run down the current list looking for any records
+ // that are identical and within 30 seconds time-wise of this
+ // one. If so, don't allocate a new record. This keeps the
+ // dupes down on transmit so that at the most we transmit one
+ // ack per 30 seconds per QSO, except of course for real-time
+ // ack's which don't go through this function.
+
+ // Run through the queue and check each record
+ while (ptr != NULL) {
+
+ if ( strcmp(ptr->to_call_sign,to) == 0
+ && strcmp(ptr->message_line,message) == 0 ) {
+
+ //
+ // We have matches on call_sign and message. Check the
+ // time next.
+ //
+ if (abs(when - ptr->active_time) < 30) {
+ //
+ // We're within 30 seconds of an identical ack.
+ // Drop this new one (don't add it).
+ //
+
+//fprintf(stderr,"Dropping delayed ack: Too close timewise to another: %s, %s\n",
+// to, message);
+
+ return; // Don't allocate new record on queue
+ }
+ }
+ ptr = ptr->next;
+ }
+
+ // If we made it to here, there aren't any queued ACK's that are
+ // close enough in time to drop this new one. Add it to the
+ // queue.
+
+//fprintf(stderr, "Queuing ACK for delayed transmit: %s, %s\n",
+// to, message);
+
+ // Allocate a record to hold it
+ ptr = (delayed_ack_record_p)malloc(sizeof(delayed_ack_record));
+
+ // Fill in the record
+ xastir_snprintf(ptr->to_call_sign,
+ sizeof(ptr->to_call_sign),
+ "%s",
+ to);
+
+ xastir_snprintf(ptr->message_line,
+ sizeof(ptr->message_line),
+ "%s",
+ message);
+
+ if (path == NULL) {
+ ptr->path[0] = '\0';
+ }
+ else {
+ xastir_snprintf(ptr->path,
+ sizeof(ptr->path),
+ "%s",
+ path);
+ }
+
+ ptr->active_time = when;
+
+ // Add the record to the head of the list
+ ptr->next = delayed_ack_list_head;
+ delayed_ack_list_head = ptr;
+}
+
+
+
+
+
+time_t delayed_transmit_last_check = (time_t)0;
+
+
+void check_delayed_transmit_queue(int curr_sec) {
+ delayed_ack_record_p ptr = delayed_ack_list_head;
+ int active_records = 0;
+
+
+ // Skip this function if we did it during this second already.
+ if (delayed_transmit_last_check == curr_sec) {
+ return;
+ }
+ delayed_transmit_last_check = curr_sec;
+
+//fprintf(stderr, "Checking delayed TX queue for something to transmit.\n");
+//fprintf(stderr, ".");
+
+ // Run down the linked list checking every record.
+ while (ptr != NULL) {
+ if (ptr->active_time != 0) { // Active record
+ char new_path[MAX_LINE_SIZE+1];
+
+
+//fprintf(stderr, "Found active record\n");
+
+ active_records++;
+
+
+ // Check for a custom path having been set in the Send
+ // Message dialog. If so, use this for our outgoing
+ // path instead and reset all of the queued message
+ // paths to this station to this new path.
+ //
+ get_send_message_path(ptr->to_call_sign,
+ new_path,
+ sizeof(new_path));
+
+ if (new_path[0] != '\0'
+ && strcmp(new_path, ptr->path) != 0) {
+
+ // We have a custom path set which is different than
+ // the path saved with the outgoing message. Change
+ // the path to match the new path.
+ //
+//fprintf(stderr,
+// "Changing queued ack's to new path: %s\n",
+// new_path);
+
+ xastir_snprintf(ptr->path,
+ sizeof(ptr->path),
+ "%s",
+ new_path);
+ }
+
+
+ if (ptr->active_time <= sec_now()) {
+ // Transmit it
+//fprintf(stderr,"Found something delayed to transmit! %ld\n",sec_now());
+
+ if (ptr->path[0] == '\0') {
+ transmit_message_data(ptr->to_call_sign,
+ ptr->message_line,
+ NULL);
+ }
+ else {
+ transmit_message_data(ptr->to_call_sign,
+ ptr->message_line,
+ ptr->path);
+ }
+
+ ptr->active_time = (time_t)0;
+ }
+ }
+ ptr = ptr->next;
+ }
+
+ // Check if entire list contains inactive records. If so,
+ // delete the list.
+ //
+ if (!active_records && (delayed_ack_list_head != NULL)) {
+ // No active records, but the list isn't empty. Reclaim the
+ // records in the list.
+ while (delayed_ack_list_head != NULL) {
+ ptr = delayed_ack_list_head->next;
+ free(delayed_ack_list_head);
+//fprintf(stderr,"Free'ing delayed_ack record\n");
+ delayed_ack_list_head = ptr;
+ }
+ }
+}
+
+
+
+
+
+void check_and_transmit_messages(time_t time) {
+ int i;
+ char temp[200];
+ char to_call[40];
+
+
+ // Skip this function if we did it during this second already.
+ if (last_check_and_transmit == time) {
+ return;
+ }
+ last_check_and_transmit = time;
+
+ for (i=0; i<MAX_OUTGOING_MESSAGES;i++) {
+ if (message_pool[i].active==MESSAGE_ACTIVE) {
+ if (message_pool[i].wait_on_first_ack!=1) { // Tx only if 0
+ if (message_pool[i].active_time < time) {
+ char *last_ack_ptr;
+ char last_ack[5+1];
+
+
+ if (message_pool[i].tries < MAX_TRIES) {
+ char new_path[MAX_LINE_SIZE+1];
+
+
+ /* sending message let the tnc and net transmits check to see if we should */
+ if (debug_level & 2)
+ fprintf(stderr,
+ "Time %ld Active time %ld next time %ld\n",
+ (long)time,
+ (long)message_pool[i].active_time,
+ (long)message_pool[i].next_time);
+
+ if (debug_level & 2)
+ fprintf(stderr,"Send message#%d to <%s> from <%s>:%s-%s\n",
+ message_pool[i].tries,
+ message_pool[i].to_call_sign,
+ message_pool[i].from_call_sign,
+ message_pool[i].message_line,
+ message_pool[i].seq);
+
+ pad_callsign(to_call,message_pool[i].to_call_sign);
+
+ // Add Leading ":" as per APRS Spec.
+ // Add trailing '}' to signify that we're
+ // Reply/Ack protocol capable.
+ last_ack_ptr = get_most_recent_ack(to_call);
+ if (last_ack_ptr != NULL)
+ xastir_snprintf(last_ack,
+ sizeof(last_ack),
+ "%s",
+ last_ack_ptr);
+ else
+ last_ack[0] = '\0';
+
+ xastir_snprintf(temp, sizeof(temp), ":%s:%s{%s}%s",
+ to_call,
+ message_pool[i].message_line,
+ message_pool[i].seq,
+ last_ack);
+
+ if (debug_level & 2)
+ fprintf(stderr,"MESSAGE OUT>%s<\n",temp);
+
+
+ // Check for a custom path having been set
+ // in the Send Message dialog. If so, use
+ // this for our outgoing path instead and
+ // reset all of the queued message paths to
+ // this station to this new path.
+ //
+ get_send_message_path(to_call,
+ new_path,
+ sizeof(new_path));
+
+//fprintf(stderr,"get_send_message_path(%s) returned: %s\n",to_call,new_path);
+
+ if (new_path[0] != '\0'
+ && strcmp(new_path,message_pool[i].path) != 0) {
+
+ // We have a custom path set which is
+ // different than the path saved with
+ // the outgoing message.
+ //
+ // Change all messages to that callsign
+ // to match the new path.
+ //
+ change_path_outgoing_messages_to(to_call,new_path);
+ }
+
+
+ // Transmit the message
+ transmit_message_data(message_pool[i].to_call_sign,
+ temp,
+ message_pool[i].path);
+
+
+ message_pool[i].active_time = time + message_pool[i].next_time;
+
+ //fprintf(stderr,"%d\n",(int)message_pool[i].next_time);
+ }
+
+/*
+fprintf(stderr,
+ "Msg Interval = %3ld seconds or %4.1f minutes\n",
+ message_pool[i].next_time,
+ message_pool[i].next_time / 60.0);
+*/
+
+ // Record the interval we're using. Put it with
+ // the message in the general message pool, so
+ // that the Send Message dialog can display it.
+ // It will only display it if the message is
+ // actively being transmitted. If it has been
+ // cancelled, timed out, or hasn't made it to
+ // the transmit position yet, it won't be shown.
+ //
+ msg_record_interval_tries(message_pool[i].to_call_sign,
+ message_pool[i].from_call_sign,
+ message_pool[i].seq,
+ message_pool[i].next_time, // Interval
+ message_pool[i].tries); // Tries
+
+ // Start at 7 seconds for the interval. We set
+ // it to 7 seconds in output_message() above.
+ // Double the interval each retry until we hit
+ // 10 minutes. Keep transmitting at 10 minute
+ // intervals until we hit MAX_TRIES.
+
+ // Double the interval between messages
+ message_pool[i].next_time = message_pool[i].next_time * 2;
+
+ // Limit the max interval to 10 minutes
+ if (message_pool[i].next_time > (time_t)600l)
+ message_pool[i].next_time = (time_t)600l;
+
+ message_pool[i].tries++;
+
+ // Expire it if we hit the limit
+ if (message_pool[i].tries > MAX_TRIES) {
+ char temp[150];
+ char temp_to[20];
+
+ xastir_snprintf(temp,sizeof(temp),"To: %s, Msg: %s",
+ message_pool[i].to_call_sign,
+ message_pool[i].message_line);
+ //popup_message(langcode("POPEM00004"),langcode("POPEM00017"));
+ popup_message( "Retries Exceeded!", temp );
+
+ // Fake the system out: We're pretending
+ // that we got an ACK back from it so that
+ // we can either release the next message to
+ // go out, or at least make the send button
+ // sensitive again.
+ // We need to copy the to_call_sign into
+ // another variable because the
+ // clear_acked_message() function clears out
+ // the message then needs this parameter to
+ // do another compare (to enable the Send Msg
+ // button again).
+ xastir_snprintf(temp_to,
+ sizeof(temp_to),
+ "%s",
+ message_pool[i].to_call_sign);
+
+ // Record a fake ack and add "*TIMEOUT*" to
+ // the message. This will be displayed in
+ // the Send Message dialog.
+ msg_record_ack(temp_to,
+ message_pool[i].from_call_sign,
+ message_pool[i].seq,
+ 1, // "1" specifies a timeout
+ 0); // Not a cancel
+
+ clear_acked_message(temp_to,
+ message_pool[i].from_call_sign,
+ message_pool[i].seq);
+
+// if (mw[i].send_message_dialog!=NULL) /* clear submit */
+// XtSetSensitive(mw[i].button_ok,TRUE);
+ }
+ }
+ } else {
+ if (debug_level & 2)
+ fprintf(stderr,"Message #%s is waiting to have a previous one cleared\n",message_pool[i].seq);
+ }
+ }
+ }
+}
+
+
+
+
+
+// Function which marks a message as ack'ed in the transmit queue
+// and releases the next message to allow it to be transmitted.
+// Handles REPLY-ACK format or normal ACK format just fine.
+//
+void clear_acked_message(char *from, char *to, char *seq) {
+ int i,ii;
+ int found;
+ char lowest[3];
+ char temp1[MAX_CALLSIGN+1];
+ char *temp_ptr;
+ char msg_id[5+1];
+
+
+ // Copy seq into local variable
+ xastir_snprintf(msg_id,
+ sizeof(msg_id),
+ "%s",
+ seq);
+
+ // Check for REPLY-ACK protocol. If found, terminate at the end
+ // of the first ack.
+ temp_ptr = strchr(msg_id, '}');
+ if (temp_ptr)
+ *temp_ptr = '\0';
+
+ (void)remove_trailing_spaces(msg_id); // This is IMPORTANT here!!!
+
+ //lowest=100000;
+ // Highest Base-90 2-char string
+ xastir_snprintf(lowest,sizeof(lowest),"zz");
+ found= -1;
+ for (i=0; i<MAX_OUTGOING_MESSAGES;i++) {
+ if (message_pool[i].active==MESSAGE_ACTIVE) {
+
+ if (debug_level & 1)
+ fprintf(stderr,
+ "TO <%s> <%s> from <%s> <%s> seq <%s> <%s>\n",
+ to,
+ message_pool[i].to_call_sign,
+ from,
+ message_pool[i].from_call_sign,
+ msg_id,
+ message_pool[i].seq);
+
+ if (strcmp(message_pool[i].to_call_sign,from)==0) {
+ if (debug_level & 1)
+ fprintf(stderr,"Matched message to_call_sign\n");
+ if (strcmp(message_pool[i].from_call_sign,to)==0) {
+ if (debug_level & 1)
+ fprintf(stderr,"Matched message from_call_sign\n");
+ if (strcmp(message_pool[i].seq,msg_id)==0) {
+ if (debug_level & 2)
+ fprintf(stderr,"Found and cleared\n");
+
+ clear_outgoing_message(i);
+ // now find and release next message, look for the lowest sequence?
+// What about when the sequence rolls over?
+ for (i=0; i<MAX_OUTGOING_MESSAGES;i++) {
+ if (message_pool[i].active==MESSAGE_ACTIVE) {
+ if (strcmp(message_pool[i].to_call_sign,from)==0) {
+// Need to change this to a string compare instead of an integer
+// compare. We are using base-90 encoding now.
+ //if (atoi(message_pool[i].seq)<lowest) {
+ if (strncmp(message_pool[i].seq,lowest,2) < 0) {
+ //lowest=atoi(message_pool[i].seq);
+ xastir_snprintf(lowest,
+ sizeof(lowest),
+ "%s",
+ message_pool[i].seq);
+ found=i;
+ }
+ }
+ }
+ }
+ // Release the next message in the queue for transmission
+ if (found!= -1) {
+ message_pool[found].wait_on_first_ack=0;
+ }
+ else {
+ /* if no more clear the send button */
+
+begin_critical_section(&send_message_dialog_lock, "messages.c:clear_acked_message" );
+
+ for (ii=0;ii<MAX_MESSAGE_WINDOWS;ii++) {
+ /* find station */
+ if (mw[ii].send_message_dialog!=NULL) {
+
+ temp_ptr = XmTextFieldGetString(mw[ii].send_message_call_data);
+ xastir_snprintf(temp1,
+ sizeof(temp1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)to_upper(temp1);
+ //fprintf(stderr,"%s\t%s\n",temp1,from);
+// if (strcmp(temp1,from)==0) {
+ /*clear submit*/
+// XtSetSensitive(mw[ii].button_ok,TRUE);
+// }
+ }
+ }
+
+end_critical_section(&send_message_dialog_lock, "messages.c:clear_acked_message" );
+
+ }
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"Sequences didn't match: %s %s\n",message_pool[i].seq,msg_id);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+
+
+// This routine is not currently used.
+//
+void send_queued(char *to) {
+ int i;
+
+ for (i=0; i<MAX_OUTGOING_MESSAGES ;i++) {
+ /* Check for messages to call */
+ if (message_pool[i].active==MESSAGE_ACTIVE)
+ if (strcmp(to,message_pool[i].to_call_sign)==0)
+ message_pool[i].active_time=0;
+
+ }
+}
+
diff --git a/src/messages.h b/src/messages.h
new file mode 100644
index 0000000..a372dfd
--- /dev/null
+++ b/src/messages.h
@@ -0,0 +1,123 @@
+/*
+ * $Id: messages.h,v 1.31 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifndef XASTIR_MESSAGES_H
+#define XASTIR_MESSAGES_H
+
+/*
+ * Message structures
+ *
+ */
+
+/* define MESSAGE STATUS */
+#define MESSAGE_ACTIVE 'A'
+#define MESSAGE_CLEAR 'C'
+
+#define MAX_OUTGOING_MESSAGES 100
+#define MAX_MESSAGE_OUTPUT_LENGTH 67
+#define MAX_MESSAGE_ORDER 10
+
+// Max tries to get a message through
+#define MAX_TRIES 18
+
+typedef struct {
+ char active;
+ char to_call_sign[MAX_CALLSIGN+1];
+ char from_call_sign[MAX_CALLSIGN+1];
+ char message_line[MAX_MESSAGE_OUTPUT_LENGTH+1];
+ char path[200];
+ char seq[MAX_MESSAGE_ORDER+1];
+ time_t active_time;
+ time_t next_time;
+ int tries;
+ int wait_on_first_ack;
+} Message_transmit;
+
+#define MAX_MESSAGE_WINDOWS 25
+
+typedef struct {
+ char win[10];
+ char to_call_sign[MAX_CALLSIGN+1];
+ int message_group;
+ Widget send_message_dialog;
+ Widget send_message_call_data;
+ Widget D700_mode;
+ Widget D7_mode;
+ Widget HamHUD_mode;
+ Widget message_data_line1;
+ Widget message_data_line2;
+ Widget message_data_line3;
+ Widget message_data_line4;
+ Widget send_message_text;
+ Widget send_message_path;
+ Widget send_message_reverse_path;
+ Widget send_message_change_path;
+ Widget pane, form, button_ok, button_cancel;
+ Widget button_clear_old_msgs, button_submit_call;
+ Widget button_clear_pending_msgs;
+ Widget button_kick_timer;
+ Widget call, message, path, reverse_path_label;
+} Message_Window;
+
+
+extern Message_transmit message_pool[MAX_OUTGOING_MESSAGES+1];
+
+extern Widget auto_msg_on, auto_msg_off;
+
+extern int auto_reply;
+extern char auto_reply_message[100];
+extern char group_data_file[400];
+
+extern void clear_acked_message(char *from, char *to, char *seq);
+extern void transmit_message_data(char *to, char *message, char *path);
+extern void transmit_message_data_delayed(char *to, char *message, char *path, time_t when);
+extern void check_delayed_transmit_queue(int curr_sec);
+
+
+//extern void output_message(char *from, char *to, char *message);
+extern int check_popup_window(char *from_call_sign, int group);
+extern int look_for_open_group_data(char *to);
+extern int group_active(char *from);
+extern void send_queued(char *to);
+extern void clear_outgoing_messages_to(char *callsign);
+extern void change_path_outgoing_messages_to(char *callsign, char *new_path);
+
+/* from messages_gui.c */
+extern xastir_mutex send_message_dialog_lock;
+extern void messages_gui_init(void);
+extern void get_send_message_path(char *callsign, char *path, int path_size);
+extern void Send_message(Widget w, XtPointer clientData, XtPointer callData);
+extern void Show_pending_messages(Widget w, XtPointer clientData, XtPointer callData);
+extern void Clear_messages(Widget w, XtPointer clientData, XtPointer callData);
+void kick_outgoing_timer(char *callsign);
+extern void Send_message_call(Widget w, XtPointer clientData, XtPointer callData);
+
+// view_message_gui.c
+extern int vm_range;
+extern int view_message_limit;
+extern int Read_messages_packet_data_type;
+extern int Read_messages_mine_only;
+
+#endif /* XASTIR_MESSAGES_H */
+
diff --git a/src/messages_gui.c b/src/messages_gui.c
new file mode 100644
index 0000000..96154de
--- /dev/null
+++ b/src/messages_gui.c
@@ -0,0 +1,2673 @@
+/*
+ * $Id: messages_gui.c,v 1.87 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdlib.h>
+#include <stdio.h> // printf
+#include <stdint.h>
+
+#include <Xm/XmAll.h>
+
+#include "xastir.h"
+#include "main.h"
+#include "lang.h"
+#include "xa_config.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+extern XmFontList fontlist1; // Menu/System fontlist
+
+#if defined(__LSB__) || defined(LESSTIF_VERSION)
+ #define NO_DYNAMIC_WIDGETS 1
+#endif
+
+
+#define MAX_PATH 200
+
+
+Widget auto_msg_on, auto_msg_off;
+Widget auto_msg_dialog = (Widget)NULL;
+Widget auto_msg_set_data = (Widget)NULL;
+
+static xastir_mutex auto_msg_dialog_lock;
+xastir_mutex send_message_dialog_lock;
+
+void select_station_type(int ii);
+
+
+
+
+
+void messages_gui_init(void)
+{
+ init_critical_section( &auto_msg_dialog_lock );
+ init_critical_section( &send_message_dialog_lock );
+}
+
+
+
+
+
+/**** Send Message ******/
+
+
+
+// This function chops off the first callsign, then returns a string
+// containing the same string in reversed callsign order. Note that
+// if RELAY was used by the sending station and that RELAY did _not_
+// do callsign substitution, that part of the path will be chopped
+// heading back. If the sending station really needed that relay
+// station in order to receive the reply, he/she should have put in
+// a callsign instead of RELAY. We can't in good conscience use
+// RELAY on the end of the return path.
+//
+// We also chop off anything after comma "q" two letters, and a
+// comma. This is the injection-ID called the Q-construct, which
+// lets us know how a signal was injected into the NET and by whom.
+//
+void reverse_path(char *input_string) {
+ char reverse_path[200];
+ int indexes[20];
+ int i, j, len;
+ char temp[MAX_CALLSIGN+1];
+
+
+ // Check for NULL pointer
+ if (input_string == NULL)
+ return;
+
+ // Check for zero-length string
+ len = strlen(input_string);
+ if (len == 0)
+ return;
+
+ // Initialize
+ reverse_path[0] = '\0';
+ for (i = 0; i < 20; i++)
+ indexes[i] = -1;
+
+ // Add a comma onto the end (makes later code easier)
+ input_string[len++] = ',';
+ input_string[len] = '\0'; // Terminate it
+
+ // Find each comma
+ j = 0;
+ for (i = 0; i < (int)strlen(input_string); i++) {
+ if (input_string[i] == ',') {
+ indexes[j++] = i;
+ //fprintf(stderr,"%d\n",i); // Debug code
+ }
+ }
+
+ // Get rid of asterisks and commas in the original string:
+ for (i = 0; i < len; i++) {
+ if (input_string[i] == '*' || input_string[i] == ',') {
+ input_string[i] = '\0';
+ }
+ }
+
+ // Go left to right looking for a 3-letter callsign starting
+ // with 'q'. If found readjust 'j' to skip that callsign and
+ // everything after it.
+ //
+ for ( i = 0; i < j; i++) {
+ char *c = &input_string[indexes[i] + 1];
+
+//fprintf(stderr,"'%s'\t", c );
+
+ if (c[0] == 'q') {
+ if ( strlen(c) == 3 ) { // "qAR"
+
+//fprintf(stderr,"Found:%s\n", c);
+
+ j = i;
+ }
+ }
+ }
+
+ // Convert used "WIDEn-N"/"TRACEn-N" paths back to their
+ // original glory. Convert "TRACE" to "WIDE" as well. We could
+ // also choose to change "WIDEn-N" to a slimmer version based on
+ // how many digi's were used, for instance "WIDE7-6" could
+ // change to "WIDE1-1" or "WIDE7-1", and "WIDE5-2" could change
+ // to "WIDE3-3" or "WIDE5-3".
+// for ()
+
+ // j now tells us how many were found. Now go in the reverse
+ // order and concatenate the substrings together. Get rid of
+ // "RELAY" and "TCPIP" calls as we're doing it.
+ input_string[0] = '\0'; // Clear out the old string first
+ for ( i = j - 1; i >= 0; i-- ) {
+ if ( (input_string[indexes[i]+1] != '\0')
+ && (strncasecmp(&input_string[indexes[i]+1],"RELAY",5) != 0)
+ && (strncasecmp(&input_string[indexes[i]+1],"TCPIP",5) != 0) ) {
+
+ // Snag each callsign into temp:
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ &input_string[indexes[i]+1]);
+
+ // Massage temp until it resembles something we want to
+ // use.
+ // "WIDEn" -> "WIDEn-N,"
+ // "TRACEn" -> "WIDEn-N,"
+ // "TRACE" -> "WIDE,"
+ if (strncasecmp(temp,"WIDE",4) == 0) {
+ if ( (temp[4] != ',') && is_num_chr(temp[4]) ) {
+//fprintf(stderr,"Found a WIDEn-N\n");
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "WIDE%c-%c",
+ temp[4],
+ temp[4]);
+ }
+ else {
+//fprintf(stderr,"Found a WIDE\n");
+ // Leave temp alone, it's just a WIDE
+ }
+ }
+ else if (strncasecmp(temp,"TRACE",5) == 0) {
+ if ( (temp[5] != ',') && is_num_chr(temp[5]) ) {
+//fprintf(stderr,"Found a TRACEn-N\n");
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "WIDE%c-%c",
+ temp[5],
+ temp[5]);
+ }
+ else {
+//fprintf(stderr,"Found a TRACE\n");
+ // Convert it from TRACE to WIDE
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "WIDE");
+ }
+ }
+
+ // Add temp to the end of our path:
+ strncat(reverse_path,temp,sizeof(temp));
+
+ strncat(reverse_path,",",1);
+ }
+ }
+
+ // Remove the ending comma
+ reverse_path[strlen(reverse_path) - 1] = '\0';
+
+ // Save the new path back into the string we were given.
+ strncat(input_string, reverse_path, len);
+}
+
+
+
+
+
+void get_path_data(char *callsign, char *path, int max_length) {
+ DataRow *p_station;
+
+
+ if (search_station_name(&p_station,callsign,1)) { // Found callsign
+ char new_path[200];
+
+ if (p_station->node_path_ptr) {
+ xastir_snprintf(new_path,sizeof(new_path), "%s", p_station->node_path_ptr);
+
+ if(debug_level & 2)
+ fprintf(stderr,"\nPath from %s: %s\n",
+ callsign,
+ new_path);
+
+ // We need to chop off the first call, remove asterisks
+ // and injection ID's, and reverse the order of the
+ // callsigns. We need to do the same thing in the
+ // callback for button_submit_call, so that we get a new
+ // path whenever the callsign is changed. Create a new
+ // TextFieldWidget to hold the path info, which gets
+ // filled in here (and the callback) but can be changed by
+ // the user. Must find a nice way to use this path from
+ // output_my_data() as well.
+
+ reverse_path(new_path);
+
+ if (debug_level & 2)
+ fprintf(stderr," Path to %s: %s\n",
+ callsign,
+ new_path);
+
+ xastir_snprintf(path,
+ max_length,
+ "%s",
+ new_path);
+ } else {
+ if (debug_level & 2)
+ fprintf(stderr," Path from %s is (null)\n",callsign);
+ path[0]='\0';
+ }
+ }
+ else { // Couldn't find callsign. It's
+ // not in our station database.
+ if(debug_level & 2)
+ fprintf(stderr,"Path from %s: No Path Known\n",callsign);
+
+ path[0] = '\0';
+ }
+
+}
+
+
+
+
+
+static Widget change_path_dialog = NULL;
+static Widget current_path = NULL;
+
+
+
+
+
+void Send_message_change_path_destroy_shell(Widget widget, XtPointer clientData, XtPointer callData) {
+
+ if (change_path_dialog) {
+ XtPopdown(change_path_dialog);
+
+ XtDestroyWidget(change_path_dialog);
+ }
+ change_path_dialog = (Widget)NULL;
+}
+
+
+
+
+
+// Apply button
+// Fetch the text from the "current_path" widget and place it into
+// the mw[ii].send_message_path widget.
+//
+void Send_message_change_path_apply(Widget widget, XtPointer clientData, XtPointer callData) {
+ char path[MAX_PATH+1];
+ char *temp_ptr;
+
+
+ if (current_path != NULL && clientData != NULL) {
+
+ temp_ptr = XmTextFieldGetString(current_path);
+ xastir_snprintf(path,
+ sizeof(path),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(path);
+ (void)to_upper(path);
+
+
+// Check here for "DIRECT PATH" or "DEFAULT PATH". If one of them,
+// do some special processing if need be so that lower layers will
+// interpret it correctly.
+
+ XmTextFieldSetString(clientData, path);
+
+ Send_message_change_path_destroy_shell(NULL, NULL, NULL);
+ }
+}
+
+
+
+
+
+// "Direct Path" button
+//
+// Put "DIRECT PATH" in the widgets. We pass "DIRECT PATH" all the
+// way to the transmit routines, then change it to an empty path
+// when the transmit actually goes out.
+//
+void Send_message_change_path_direct(Widget widget, XtPointer clientData, XtPointer callData) {
+
+ if (current_path == NULL || clientData == NULL) {
+ Send_message_change_path_destroy_shell(NULL, NULL, NULL);
+ }
+
+ // Change current_path widget
+ XmTextFieldSetString(current_path, "DIRECT PATH");
+
+ Send_message_change_path_apply(NULL, clientData, NULL);
+}
+
+
+
+
+
+// "Default Path(s)" button
+//
+// Blank out the path so the default paths get used. We pass
+// "DEFAULT PATH" all the way to the transmit routines, then change
+// it there to be a blank.
+//
+void Send_message_change_path_default(Widget widget, XtPointer clientData, XtPointer callData) {
+
+ if (current_path == NULL || clientData == NULL) {
+ Send_message_change_path_destroy_shell(NULL, NULL, NULL);
+ }
+
+ // Change current_path widget
+ XmTextFieldSetString(current_path, "DEFAULT PATH");
+
+ Send_message_change_path_apply(NULL, clientData, NULL);
+}
+
+
+
+
+
+// TODO: Change the "Path:" box so that clicking or double-clicking
+// on it will bring up a "Change Path" dialog. Could also use a
+// "Change" or "Change Path" button if easier. This new dialog
+// should have the current path (editable), the reverse path (not
+// editable), and these buttons:
+//
+// "DIRECT path"
+// "DEFAULT path(s)"
+// "Apply"
+// "Cancel"
+//
+// Of course the underlying code will have to tweaked to be able to
+// pass an EMPTY path all the way down through the layers. We can't
+// currently do that. We'll have to define a specific string for
+// that. Insert the text "--DEFAULT--", "--BLANK--", or the actual
+// path in the editable box and in the "Path:" box on the Send
+// Message dialog so that the user knows which one is in effect.
+//
+// Remember to close the Change Path dialog if we close the Send
+// Message dialog which corresponds to it.
+//
+// Adding this new CHANGE PATH dialog will allow us to get rid of
+// three bugs on the active bug-list: #1499820, #1326975, and
+// #1326973.
+//
+void Send_message_change_path( Widget widget, XtPointer clientData, XtPointer callData) {
+ int ii;
+ Atom delw;
+ Widget pane, form, current_path_label, reverse_path_label,
+ reverse_path, button_default, button_direct, button_apply,
+ button_cancel;
+ Widget button_wide11, button_wide21, button_wide22, button_nogate;
+ char *temp_ptr;
+ char temp1[MAX_LINE_SIZE+1];
+ char path[MAX_PATH+1];
+
+
+//begin_critical_section(&send_message_dialog_lock, "messages_gui.c:Send_message_change_path" );
+
+ if (clientData == NULL) {
+ return;
+ }
+
+ if (change_path_dialog) {
+ // Destroy the old one before creating a new one
+ Send_message_change_path_destroy_shell(NULL, NULL, NULL);
+ }
+
+ // Fetch Send Message dialog number from clientData, store in
+ // "ii".
+ //
+ ii = atoi(clientData);
+
+ // "Change Path"
+ change_path_dialog = XtVaCreatePopupShell(langcode("WPUPMSB019"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNtitleString,"Change Path",
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Send_message_change_path pane",
+ xmPanedWindowWidgetClass,
+ change_path_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ form = XtVaCreateWidget("Send_message_change_path form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 4,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // "Path:"
+ current_path_label = XtVaCreateManagedWidget(langcode("WPUPMSB010"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ current_path = XtVaCreateManagedWidget("Send_message_change_path path",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 26,
+ XmNwidth, ((26*7)+2),
+ XmNmaxLength, 199,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, current_path_label,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Reverse Path:"
+ reverse_path_label = XtVaCreateManagedWidget(langcode("WPUPMSB022"),
+ xmLabelWidgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, current_path,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ reverse_path = XtVaCreateManagedWidget("Send_message_change_path reverse path",
+ xmTextFieldWidgetClass,
+ form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 26,
+ XmNwidth, ((26*7)+2),
+ XmNmaxLength, 199,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, reverse_path_label,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_wide11 = XtVaCreateManagedWidget("WIDE1-1",
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, current_path_label,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_wide21 = XtVaCreateManagedWidget("WIDE2-1",
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, current_path_label,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_wide22 = XtVaCreateManagedWidget("WIDE2-2",
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, current_path_label,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_nogate = XtVaCreateManagedWidget("NOGATE",
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, current_path_label,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+XtSetSensitive(button_wide11, FALSE);
+XtSetSensitive(button_wide21, FALSE);
+XtSetSensitive(button_wide22, FALSE);
+XtSetSensitive(button_nogate, FALSE);
+
+ // "Use Default Path(s)"
+ button_default = XtVaCreateManagedWidget(langcode("WPUPMSB020"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, button_wide11,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Direct (No path)"
+ button_direct = XtVaCreateManagedWidget(langcode("WPUPMSB021"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, button_wide11,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Apply"
+ button_apply = XtVaCreateManagedWidget(langcode("UNIOP00032"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, button_wide11,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Close"
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, button_wide11,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_default, XmNactivateCallback, Send_message_change_path_default, (XtPointer)mw[ii].send_message_path);
+ XtAddCallback(button_direct, XmNactivateCallback, Send_message_change_path_direct, (XtPointer)mw[ii].send_message_path);
+ XtAddCallback(button_apply, XmNactivateCallback, Send_message_change_path_apply, (XtPointer)mw[ii].send_message_path);
+ XtAddCallback(button_cancel, XmNactivateCallback, Send_message_change_path_destroy_shell,(XtPointer)mw[ii].win);
+
+ // Fill in the fields
+ if(mw[ii].send_message_dialog != NULL) {
+ char call_sign[MAX_CALLSIGN+1];
+
+ temp_ptr = XmTextFieldGetString(mw[ii].send_message_path);
+ xastir_snprintf(temp1,
+ sizeof(temp1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+ (void)to_upper(temp1);
+ XmTextFieldSetString(current_path, temp1);
+
+ // Go get the reverse path. Start with the callsign.
+ temp_ptr = XmTextFieldGetString(mw[ii].send_message_call_data);
+ xastir_snprintf(call_sign,
+ sizeof(call_sign),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_dash_zero(call_sign);
+
+ // Try lowercase
+ get_path_data(call_sign, path, MAX_PATH);
+ if (strlen(path) == 0) {
+ // Try uppercase
+ (void)to_upper(call_sign);
+ get_path_data(call_sign, path, MAX_PATH);
+ }
+ XmTextFieldSetString(reverse_path, path);
+ }
+
+ pos_dialog(change_path_dialog);
+
+ delw = XmInternAtom(XtDisplay(change_path_dialog),"WM_DELETE_WINDOW", FALSE);
+// XmAddWMProtocolCallback(change_path_dialog, delw, Send_message_destroy_shell, (XtPointer)mw[ii].win);
+
+ XtManageChild(form);
+ XtManageChild(pane);
+
+ XtPopup(change_path_dialog,XtGrabNone);
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(change_path_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+//end_critical_section(&send_message_dialog_lock, "messages_gui.c:Send_message_change_path" );
+
+}
+
+
+
+
+
+// Find a custom path set in a Send Message dialog, using the remote
+// callsign as the key. If no custom path, sets path to '\0'.
+//
+void get_send_message_path(char *callsign, char *path, int path_size) {
+ int ii;
+ int found = -1;
+ char *temp_ptr;
+ char temp1[MAX_LINE_SIZE+1];
+ char my_callsign[20];
+
+
+ xastir_snprintf(my_callsign,sizeof(my_callsign),"%s",callsign);
+ remove_trailing_spaces(my_callsign);
+
+//fprintf(stderr,"Looking for %s\n", my_callsign);
+ for(ii = 0; ii < MAX_MESSAGE_WINDOWS; ii++) {
+
+ // find matching callsign
+ if(mw[ii].send_message_dialog != NULL) {
+
+ temp_ptr = XmTextFieldGetString(mw[ii].send_message_call_data);
+ xastir_snprintf(temp1,
+ sizeof(temp1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_dash_zero(temp1);
+ (void)to_upper(temp1);
+
+ if(strcmp(temp1,my_callsign)==0) {
+ found = ii;
+ break;
+ }
+ }
+ }
+
+ if (found == -1) {
+//fprintf(stderr,"Didn't find dialog\n");
+ path[0] = '\0';
+ return;
+ }
+
+ // We have the correct Send Message dialog. Snag the path.
+ //
+ temp_ptr = XmTextFieldGetString(mw[ii].send_message_path);
+ xastir_snprintf(temp1,
+ sizeof(temp1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)to_upper(temp1);
+ (void)remove_leading_spaces(temp1);
+ (void)remove_trailing_spaces(temp1);
+
+ // Path empty?
+ if (temp1[0] == '\0') {
+//fprintf(stderr,"Didn't find custom path\n");
+ path[0] = '\0';
+ return;
+ }
+
+ // We have a real path! Stuff it into the path variable.
+ xastir_snprintf(path,
+ path_size,
+ "%s",
+ temp1);
+//fprintf(stderr,"Found custom path: %s\n", path);
+}
+
+
+
+
+
+void Send_message_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ int ii;
+// char *temp_ptr;
+// char temp1[MAX_LINE_SIZE+1];
+
+//fprintf(stderr,"3Send_message_destroy_shell() start\n");
+
+ ii=atoi((char *)clientData);
+
+begin_critical_section(&send_message_dialog_lock, "messages_gui.c:Send_message_destroy_shell" );
+
+ if (mw[ii].send_message_dialog) {
+
+/*
+ // Check whether the send_message_call_data field has a
+ // custom path entered.
+ temp_ptr = XmTextFieldGetString(mw[ii].send_message_call_data);
+ xastir_snprintf(temp1,
+ sizeof(temp1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_leading_spaces(temp1);
+ (void)remove_trailing_spaces(temp1);
+ (void)remove_trailing_dash_zero(temp1);
+
+ if(temp1[0] != '\0') {
+ // Yep, we have a custom path. Warn the user that
+ // they're going to lose this path by destroying the
+ // dialog.
+ popup_message_always(langcode("POPEM00036"),
+ langcode("POPEM00040"));
+ }
+*/
+
+ XtPopdown(mw[ii].send_message_dialog);
+ XtDestroyWidget(mw[ii].send_message_dialog);
+ }
+
+
+ mw[ii].send_message_dialog = (Widget)NULL;
+ mw[ii].to_call_sign[0] = '\0';
+ mw[ii].send_message_call_data = (Widget)NULL;
+ mw[ii].D700_mode = (Widget)NULL;
+ mw[ii].D7_mode = (Widget)NULL;
+ mw[ii].HamHUD_mode = (Widget)NULL;
+ mw[ii].message_data_line1 = (Widget)NULL;
+ mw[ii].message_data_line2 = (Widget)NULL;
+ mw[ii].message_data_line3 = (Widget)NULL;
+ mw[ii].message_data_line4 = (Widget)NULL;
+ mw[ii].send_message_text = (Widget)NULL;
+
+ Send_message_change_path_destroy_shell(NULL, NULL, NULL);
+
+end_critical_section(&send_message_dialog_lock, "messages_gui.c:Send_message_destroy_shell" );
+
+//fprintf(stderr,"3Send_message_destroy_shell() finished\n");
+
+}
+
+
+
+
+
+void Check_new_call_messages( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ int pos;
+ intptr_t i;
+
+ i=(intptr_t)clientData;
+
+ /* clear window*/
+ pos=0;
+
+begin_critical_section(&send_message_dialog_lock, "messages_gui.c:Check_new_call_messages" );
+
+ if (mw[i].send_message_dialog) {
+ // If we have a dialog already, clear out the message area
+ // from 0 to the last text position.
+
+ // Known to have memory leaks with some versions of Motif:
+ //XmTextSetString(mw[i].send_message_text,"");
+
+ XmTextReplace(mw[i].send_message_text, (XmTextPosition) 0,
+ XmTextGetLastPosition(mw[i].send_message_text), "");
+
+ // Set the cursor position to 0
+ XtVaSetValues(mw[i].send_message_text,XmNcursorPosition,pos,NULL);
+ }
+
+end_critical_section(&send_message_dialog_lock, "messages_gui.c:Check_new_call_messages" );
+
+ update_messages(1); // Force an immediate update
+
+ if (mw[i].send_message_dialog) {
+ // Re-arrange the outgoing message boxes based on the type of device we're talking to.
+ select_station_type(i);
+ }
+}
+
+
+
+
+
+void Clear_messages( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ clear_outgoing_messages();
+}
+
+
+
+
+
+void Send_message_now( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char temp1[MAX_CALLSIGN+1];
+ char temp2[68];
+ char temp_line1[68] = "";
+
+#ifndef NO_DYNAMIC_WIDGETS
+ char temp_line2[23] = "";
+ char temp_line3[23] = "";
+ char temp_line4[10] = "";
+#endif // NO_DYNAMIC_WIDGETS
+
+ char path[200];
+ int ii, jj;
+ char *temp_ptr;
+ int substitution_made = 0;
+ int d700;
+ int d7;
+ int hamhud;
+ char temp_file_path[MAX_VALUE];
+
+ ii=atoi((char *)clientData);
+
+begin_critical_section(&send_message_dialog_lock, "messages_gui.c:Send_message_now" );
+
+ if (mw[ii].send_message_dialog) {
+
+ d700 = XmToggleButtonGetState(mw[ii].D700_mode);
+ d7 = XmToggleButtonGetState(mw[ii].D7_mode);
+ hamhud = XmToggleButtonGetState(mw[ii].HamHUD_mode);
+
+ temp_ptr = XmTextFieldGetString(mw[ii].send_message_call_data);
+ xastir_snprintf(temp1,
+ sizeof(temp1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(temp1);
+ (void)to_upper(temp1);
+ (void)remove_trailing_dash_zero(temp1);
+
+ // Fetch message_data_line1 in all cases
+ temp_ptr = XmTextFieldGetString(mw[ii].message_data_line1);
+ xastir_snprintf(temp_line1,
+ sizeof(temp_line1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+#ifndef NO_DYNAMIC_WIDGETS
+
+ // If D700/D7 mode, fetch message_data_line2
+ if (d700 || d7) {
+ temp_ptr = XmTextFieldGetString(mw[ii].message_data_line2);
+ xastir_snprintf(temp_line2,
+ sizeof(temp_line2),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+ }
+
+ // If D700/D7 mode, fetch message_data_line3
+ if (d700 || d7) {
+ temp_ptr = XmTextFieldGetString(mw[ii].message_data_line3);
+ xastir_snprintf(temp_line3,
+ sizeof(temp_line3),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+ }
+
+ // If D7 mode, fetch message_data_line4
+ if (d7) {
+ temp_ptr = XmTextFieldGetString(mw[ii].message_data_line4);
+ xastir_snprintf(temp_line4,
+ sizeof(temp_line4),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+ }
+
+ // Construct the entire message now
+ if (hamhud) { // Combine two lines together
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%-20s%-47s",
+ temp_line1,
+ temp_line2);
+ }
+ else if (d700) { // Combine three lines together
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%-22s%-22s%-20s",
+ temp_line1,
+ temp_line2,
+ temp_line3);
+ }
+ else if (d7) { // Combine four lines together
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%-12s%-12s%-12s%-9s",
+ temp_line1,
+ temp_line2,
+ temp_line3,
+ temp_line4);
+ }
+ else
+
+#endif // NO_DYNAMIC_WIDGETS
+
+ { // Use line1 only
+ xastir_snprintf(temp2,
+ sizeof(temp2),
+ "%s",
+ temp_line1);
+ }
+
+ // We have the message text now. Check it for illegal
+ // characters, remove them and substitute '.' if found.
+ // Illegal characters are '|', '{', and '~' for messaging.
+ for (jj = 0; jj < (int)strlen(temp2); jj++) {
+ if ( temp2[jj] == '|'
+ || temp2[jj] == '{'
+ || temp2[jj] == '~' ) {
+ temp2[jj] = '.'; // Replace with a dot
+ substitution_made++;
+ }
+ }
+ if (substitution_made) {
+ popup_message_always(langcode("POPEM00022"),
+ langcode("POPEM00039"));
+ }
+
+ (void)remove_trailing_spaces(temp2);
+
+ temp_ptr = XmTextFieldGetString(mw[ii].send_message_path);
+ xastir_snprintf(path,
+ sizeof(path),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(path);
+ (void)to_upper(path);
+
+ if(debug_level & 2)
+ fprintf(stderr,
+ "Send message to <%s> from <%s> :%s\n",
+ temp1,
+ mw[ii].to_call_sign,
+ temp2);
+
+ if ( (strlen(temp1) != 0) // Callsign field is not blank
+ && (strlen(temp2) != 0) // Message field is not blank
+ && (strcmp(temp1,my_callsign) ) ) { // And not my own callsign
+ /* if you're sending a message you must be at the keyboard */
+ auto_reply=0;
+ XmToggleButtonSetState(auto_msg_toggle,FALSE,FALSE);
+ statusline(langcode("BBARSTA011"),0); // Auto Reply Messages OFF
+ output_message(mw[ii].to_call_sign,temp1,temp2,path);
+
+//fprintf(stderr," 1111111111222222222233333333334444444444555555555566666666\n");
+//fprintf(stderr,"1234567890123456789012345678901234567890123456789012345678901234567\n");
+//fprintf(stderr,"%s\n",temp2);
+
+ XmTextFieldSetString(mw[ii].message_data_line1,"");
+
+ if (mw[ii].message_data_line2) // If exists, blank it
+ XmTextFieldSetString(mw[ii].message_data_line2,"");
+
+ if (mw[ii].message_data_line3) // If exists, blank it
+ XmTextFieldSetString(mw[ii].message_data_line3,"");
+
+ if (mw[ii].message_data_line4) // If exists, blank it
+ XmTextFieldSetString(mw[ii].message_data_line4,"");
+
+// if (mw[ii].message_group!=1)
+// XtSetSensitive(mw[ii].button_ok,FALSE);
+
+ // Do message logging if that feature is enabled.
+ if (log_message_data) {
+ char temp_msg[MAX_MESSAGE_LENGTH+1];
+
+ xastir_snprintf(temp_msg,
+ sizeof(temp_msg),
+ "%s>%s,%s:%s",
+ mw[ii].to_call_sign, // To
+ temp1, // From
+ path, // Path
+ temp2); // Message
+ log_data( get_user_base_dir(LOGFILE_MESSAGE, temp_file_path,
+ sizeof(temp_file_path)),
+ temp_msg );
+ }
+ }
+ else {
+ if ( strcmp(temp1,my_callsign) == 0 ) { // It's my own callsign
+ popup_message_always(langcode("POPEM00022"),
+ langcode("POPEM00054")); // We're trying to talk to ourselves!
+ }
+ else if ( strlen(temp1) == 0 ) { // Callsign field is blank
+ popup_message_always(langcode("POPEM00022"),
+ langcode("POPEM00052")); // Callsign is EMPTY!
+ }
+ else if ( strlen(temp2) == 0 ) { // Message field is blank
+ popup_message_always(langcode("POPEM00022"),
+ langcode("POPEM00053")); // Message is EMPTY!
+ }
+ }
+ }
+
+ // Move focus to the first message box to make typing the next
+ // message easier.
+ XmProcessTraversal(mw[ii].message_data_line1, XmTRAVERSE_CURRENT);
+
+end_critical_section(&send_message_dialog_lock, "messages_gui.c:Send_message_now" );
+
+}
+
+
+
+
+
+void Clear_message_from( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char temp1[MAX_CALLSIGN+1];
+ int i;
+ char *temp_ptr;
+/* int pos;*/
+
+
+ i=atoi((char *)clientData);
+
+begin_critical_section(&send_message_dialog_lock, "messages_gui.c:Clear_message_from" );
+
+ if (mw[i].send_message_dialog) {
+
+ temp_ptr = XmTextFieldGetString(mw[i].send_message_call_data);
+ xastir_snprintf(temp1,
+ sizeof(temp1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(temp1);
+ (void)to_upper(temp1);
+ (void)remove_trailing_dash_zero(temp1);
+
+ /*fprintf(stderr,"Clear message from <%s> to <%s>\n",temp1,my_callsign);*/
+ mdelete_messages_from(temp1);
+ new_message_data=1;
+ }
+
+end_critical_section(&send_message_dialog_lock, "messages_gui.c:Clear_message_from" );
+
+}
+
+
+
+
+
+void Clear_message_to( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char temp1[MAX_CALLSIGN+1];
+ int i;
+ char *temp_ptr;
+
+
+ i=atoi((char *)clientData);
+
+begin_critical_section(&send_message_dialog_lock, "messages_gui.c:Clear_message_to" );
+
+ if (mw[i].send_message_dialog) {
+
+ temp_ptr = XmTextFieldGetString(mw[i].send_message_call_data);
+ xastir_snprintf(temp1,
+ sizeof(temp1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(temp1);
+ (void)to_upper(temp1);
+ (void)remove_trailing_dash_zero(temp1);
+
+ /*fprintf(stderr,"Clear message to <%s>\n",temp1);*/
+ mdelete_messages_to(temp1);
+ new_message_data=1;
+ }
+
+end_critical_section(&send_message_dialog_lock, "messages_gui.c:Clear_message_to" );
+
+}
+
+
+
+
+
+void Clear_message_to_from( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ int i, pos;
+
+ Clear_message_to(w, clientData, callData);
+ Clear_message_from(w, clientData, callData);
+
+ i=atoi((char *)clientData);
+ /* clear window*/
+ pos=0;
+
+begin_critical_section(&send_message_dialog_lock, "messages_gui.c:Clear_message_to_from" );
+
+ if (mw[i].send_message_dialog) {
+
+ // Known to have memory leaks with some versions of Motif:
+ //XmTextSetString(mw[i].send_message_text,"");
+
+ // Clear out the message window
+ XmTextReplace(mw[i].send_message_text, (XmTextPosition) 0,
+ XmTextGetLastPosition(mw[i].send_message_text), "");
+
+ // Set the cursor position to 0
+ XtVaSetValues(mw[i].send_message_text,XmNcursorPosition,pos,NULL);
+
+end_critical_section(&send_message_dialog_lock, "messages_gui.c:Clear_message_to_from" );
+
+ update_messages(1); // Force an update to clear the window
+
+begin_critical_section(&send_message_dialog_lock, "messages_gui.c:Clear_message_to_from" );
+
+ }
+
+end_critical_section(&send_message_dialog_lock, "messages_gui.c:Clear_message_to_from" );
+
+}
+
+
+
+
+
+void Kick_timer( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char *temp_ptr;
+ char temp1[MAX_CALLSIGN+1];
+
+
+ temp_ptr = XmTextFieldGetString(mw[atoi(clientData)].send_message_call_data);
+ xastir_snprintf(temp1,
+ sizeof(temp1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(temp1);
+ (void)to_upper(temp1);
+ (void)remove_trailing_dash_zero(temp1);
+
+ kick_outgoing_timer(temp1);
+}
+
+
+
+
+
+void Clear_messages_to( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char *temp_ptr;
+ char temp1[MAX_CALLSIGN+1];
+
+
+ temp_ptr = XmTextFieldGetString(mw[atoi(clientData)].send_message_call_data);
+ xastir_snprintf(temp1,
+ sizeof(temp1),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(temp1);
+ (void)to_upper(temp1);
+ (void)remove_trailing_dash_zero(temp1);
+
+ clear_outgoing_messages_to(temp1);
+ update_messages(1); // Force an update to the window
+}
+
+
+
+
+
+void Send_message_call( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char call[20];
+
+ if(clientData != NULL) {
+ xastir_snprintf(call,
+ sizeof(call),
+ "%s",
+ (char *)clientData);
+ Send_message(appshell, call, NULL);
+ }
+}
+
+
+
+
+
+// These are used for callbacks below so that we have a unique
+// identifier for the XtRemoveCallback() function to work with. The
+// last two parameters of an XtAddCallback() or XtRemoveCallback()
+// must be unique.
+//
+void Send_message_now_1( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Send_message_now( w, clientData, callData);
+}
+void Send_message_now_2( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Send_message_now( w, clientData, callData);
+}
+void Send_message_now_3( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Send_message_now( w, clientData, callData);
+}
+void Send_message_now_4( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Send_message_now( w, clientData, callData);
+}
+
+
+
+
+
+void build_send_message_input_boxes(int i, int hamhud, int d700, int d7) {
+
+//fprintf(stderr, "\n build: i:%d hamhud:%d d700:%d d7:%d\n", i, hamhud, d700, d7);
+
+
+// Skip most of these sections and go to the default section if
+// using LSB. We have problems with Lesstif segfaulting on us
+// otherwise.
+
+#ifndef NO_DYNAMIC_WIDGETS
+
+ // HamHUD mode (Here we're assuming the 4x20 LCD in the HamHUD-II)
+ if (hamhud) {
+ // Draw a textfield widget of size 20
+ mw[i].message_data_line1 = XtVaCreateManagedWidget("Send_message smmd",
+ xmTextFieldWidgetClass,
+ mw[i].form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 22,
+ XmNwidth, ((22*7)),
+ XmNmaxLength, 20,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].button_clear_old_msgs,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].message,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+// HamHUD will display all 67 chars, but only stores the first 20,
+// therefore if you want the recipient to be able to look at it
+// later, only send them 20 chars per message.
+/*
+ // Draw another textfield widget of size 47
+ mw[i].message_data_line2 = XtVaCreateManagedWidget("Send_message line2",
+ xmTextFieldWidgetClass,
+ mw[i].form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 43,
+ XmNwidth, ((43*7)),
+ XmNmaxLength, 47,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].button_clear_old_msgs,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].message_data_line1,
+ XmNleftOffset, 2,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+*/
+ }
+
+ // D700A mode
+ else if (d700) {
+
+ // Draw a textfield widget of size 22
+ mw[i].message_data_line1 = XtVaCreateManagedWidget("Send_message smmd",
+ xmTextFieldWidgetClass,
+ mw[i].form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 22,
+ XmNwidth, ((22*7)),
+ XmNmaxLength, 22,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].button_clear_old_msgs,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].message,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Draw another textfield widget of size 22
+ mw[i].message_data_line2 = XtVaCreateManagedWidget("Send_message line2",
+ xmTextFieldWidgetClass,
+ mw[i].form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 22,
+ XmNwidth, ((22*7)),
+ XmNmaxLength, 22,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].button_clear_old_msgs,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].message_data_line1,
+ XmNleftOffset, 2,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Draw another textfield widget of size 20
+ mw[i].message_data_line3 = XtVaCreateManagedWidget("Send_message line3",
+ xmTextFieldWidgetClass,
+ mw[i].form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 21,
+ XmNwidth, ((21*7)),
+ XmNmaxLength, 20,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].button_clear_old_msgs,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].message_data_line2,
+ XmNleftOffset, 2,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+ }
+
+ // D7A/D7E Mode
+ else if (d7) {
+
+ // Draw a textfield widget of size 12
+ mw[i].message_data_line1 = XtVaCreateManagedWidget("Send_message smmd",
+ xmTextFieldWidgetClass,
+ mw[i].form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 12,
+ XmNwidth, ((12*7)+4),
+ XmNmaxLength, 12,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].button_clear_old_msgs,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].message,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Draw a textfield widget of size 12
+ mw[i].message_data_line2 = XtVaCreateManagedWidget("Send_message line2",
+ xmTextFieldWidgetClass,
+ mw[i].form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 12,
+ XmNwidth, ((12*7)+4),
+ XmNmaxLength, 12,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].button_clear_old_msgs,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].message_data_line1,
+ XmNleftOffset, 2,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+// Separate the next two from the previous two for a bit, to help
+// indicate that the first two are one screen on a TH-D7, the next
+// two are another screen.
+
+ // Draw a textfield widget of size 12
+ mw[i].message_data_line3 = XtVaCreateManagedWidget("Send_message line3",
+ xmTextFieldWidgetClass,
+ mw[i].form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 12,
+ XmNwidth, ((12*7)+4),
+ XmNmaxLength, 12,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].button_clear_old_msgs,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].message_data_line2,
+ XmNleftOffset, 15,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Draw a textfield widget of size 9
+ mw[i].message_data_line4 = XtVaCreateManagedWidget("Send_message line4",
+ xmTextFieldWidgetClass,
+ mw[i].form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 9,
+ XmNwidth, ((10*7)+0),
+ XmNmaxLength, 9,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].button_clear_old_msgs,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].message_data_line3,
+ XmNleftOffset, 2,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+ }
+
+ // Standard APRS Mode
+ else // Standard APRS message box size (67)
+
+#endif // NO_DYNAMIC_WIDGETS
+
+ {
+
+ mw[i].message_data_line1 = XtVaCreateManagedWidget("Send_message smmd",
+ xmTextFieldWidgetClass,
+ mw[i].form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 67,
+ XmNwidth, ((65*7)+2),
+ XmNmaxLength, 67,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].button_clear_old_msgs,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].message,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+ }
+
+
+//fprintf(stderr,"Starting to add callbacks\n");
+
+
+ if (mw[i].message_data_line1) // If exists, add another callback
+ XtAddCallback(mw[i].message_data_line1, XmNactivateCallback, Send_message_now_1, (XtPointer)mw[i].win);
+
+ if (mw[i].message_data_line2) // If exists, add another callback
+ XtAddCallback(mw[i].message_data_line2, XmNactivateCallback, Send_message_now_2, (XtPointer)mw[i].win);
+
+ if (mw[i].message_data_line3) // If exists, add another callback
+ XtAddCallback(mw[i].message_data_line3, XmNactivateCallback, Send_message_now_3, (XtPointer)mw[i].win);
+
+ if (mw[i].message_data_line4) // If exists, add another callback
+ XtAddCallback(mw[i].message_data_line4, XmNactivateCallback, Send_message_now_4, (XtPointer)mw[i].win);
+
+//fprintf(stderr,"Exiting build_send_message_input_boxes()\n");
+
+}
+
+
+
+
+
+void rebuild_send_message_input_boxes(int ii, int hamhud, int d700, int d7) {
+
+//fprintf(stderr, "\nrebuild: ii:%d hamhud:%d d700:%d d7:%d\n", ii, hamhud, d700, d7);
+
+
+// Lesstif appears to have a problem with removing/adding widgets to
+// a dialog that's already been created and will segfault in this
+// case. In order to make LSB-Xastir more reliable we disable the
+// dynamically-created widget code here and stick with the default
+// setup (one long TextField widget for input).
+//
+// Perhaps we need to do a Lesstif detect and do the same thing
+// anytime Lesstif is used as well?
+
+#ifndef NO_DYNAMIC_WIDGETS
+
+ // Remove the current message widgets
+ if (mw[ii].message_data_line4) {
+ XtDestroyWidget(mw[ii].message_data_line4);
+ }
+
+ if (mw[ii].message_data_line3) {
+ XtDestroyWidget(mw[ii].message_data_line3);
+ }
+
+ if (mw[ii].message_data_line2) {
+ XtDestroyWidget(mw[ii].message_data_line2);
+ }
+
+ if (mw[ii].message_data_line1) {
+ XtDestroyWidget(mw[ii].message_data_line1);
+ }
+
+
+ mw[ii].message_data_line1 = (Widget)NULL;
+ mw[ii].message_data_line2 = (Widget)NULL;
+ mw[ii].message_data_line3 = (Widget)NULL;
+ mw[ii].message_data_line4 = (Widget)NULL;
+
+
+ // Build the new boxes
+ build_send_message_input_boxes(ii, hamhud, d700, d7);
+
+#endif // NO_DYNAMIC_WIDGETS
+
+}
+
+
+
+
+
+void HamHUD_Msg( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ intptr_t ii =(intptr_t)clientData;
+ int hamhud;
+
+ hamhud = XmToggleButtonGetState(mw[ii].HamHUD_mode);
+
+ if (hamhud) {
+ XmToggleButtonSetState(mw[ii].D700_mode,FALSE,FALSE);
+ XmToggleButtonSetState(mw[ii].D7_mode,FALSE,FALSE);
+ }
+ rebuild_send_message_input_boxes(ii, hamhud, 0, 0);
+}
+
+
+
+
+
+void D700_Msg( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ intptr_t ii = (intptr_t)clientData;
+ int d700;
+
+ d700 = XmToggleButtonGetState(mw[ii].D700_mode);
+
+ if (d700) {
+ XmToggleButtonSetState(mw[ii].HamHUD_mode,FALSE,FALSE);
+ XmToggleButtonSetState(mw[ii].D7_mode,FALSE,FALSE);
+ }
+ rebuild_send_message_input_boxes(ii, 0, d700, 0);
+}
+
+
+
+
+
+void D7_Msg( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ intptr_t ii = (intptr_t)clientData;
+ int d7;
+
+ d7 = XmToggleButtonGetState(mw[ii].D7_mode);
+
+ if (d7) {
+ XmToggleButtonSetState(mw[ii].HamHUD_mode,FALSE,FALSE);
+ XmToggleButtonSetState(mw[ii].D700_mode,FALSE,FALSE);
+ }
+ rebuild_send_message_input_boxes(ii, 0, 0, d7);
+}
+
+
+
+
+
+// Select HamHUD/D7/D700/Normal APRS messaging based on info
+// available in the station record. Change the Send Message dialog
+// to match.
+//
+// Only call this when the Send Message dialog is first constructed
+// or when we hit the New/Refresh Call button. We don't want to
+// have the user fighting against this function every sent or
+// received packet if this function happens to guess wrong.
+//
+void select_station_type(int ii) {
+ DataRow *p_station;
+ char call_sign[MAX_CALLSIGN+1];
+ char *temp_ptr;
+
+
+ if (mw[ii].send_message_call_data == NULL) {
+ fprintf(stderr,"messages_gui.c:select_station_type():mw[ii].send_message_call_data is NULL\n");
+ return;
+ }
+
+ temp_ptr = XmTextFieldGetString(mw[ii].send_message_call_data);
+ xastir_snprintf(call_sign,
+ sizeof(call_sign),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(call_sign);
+ (void)to_upper(call_sign);
+
+ // We have the callsign. See if we have the station name in our
+ // database.
+ if (call_sign[0] != '\0'
+ && search_station_name(&p_station, call_sign, 1) ) { // Exact match
+
+ int hamhud = 0;
+ int d700 = 0;
+ int d7 = 0;
+// int tx_only = 0;
+
+
+//fprintf(stderr,"Found callsign: %s\n", call_sign);
+
+ // check if station appears to be a transmit only station such as the TinyTrak and OpenTrak trackers.
+// ********* wrong test **********
+//if (p_station->aprs_symbol != NULL) {
+// if (p_station->aprs_symbol.aprs_type != NULL) {
+// fprintf(stderr,"Has Type: %s\n", p_station->aprs_symbol.aprs_type);
+// if is_tx_only(p_station) {
+// tx_only++;
+// }
+// }
+//}
+
+ // Check first two comment records, if they exist
+ if (p_station->comment_data != NULL) {
+
+ // Check first comment record
+ if (strstr(p_station->comment_data->text_ptr,"TM-D700")) {
+ d700++;
+ }
+ else if (strstr(p_station->comment_data->text_ptr,"TH-D7")) {
+ d7++;
+ }
+ else if (p_station->comment_data->next) {
+ // Check second comment record
+ if (strstr(p_station->comment_data->next->text_ptr,"TM-D700")) {
+ d700++;
+ }
+ else if (strstr(p_station->comment_data->next->text_ptr,"TH-D7")) {
+ d7++;
+ }
+ }
+ }
+
+ // If not D700 or D7, check for HamHUD in the TOCALL.
+ // APHH2/APRHH2. We'll skip the version number so-as to
+ // catch future versions as well.
+ //
+ if (!d700 && !d7) {
+ if (p_station->node_path_ptr) {
+ if (strncmp(p_station->node_path_ptr,"APRHH",5) == 0
+ || strncmp(p_station->node_path_ptr,"APHH",4) == 0) {
+ hamhud++;
+ }
+ }
+ }
+
+
+ if (hamhud) {
+// fprintf(stderr,"HamHUD found\n");
+ XmToggleButtonSetState(mw[ii].HamHUD_mode,TRUE,FALSE);
+ XmToggleButtonSetState(mw[ii].D700_mode,FALSE,FALSE);
+ XmToggleButtonSetState(mw[ii].D7_mode,FALSE,FALSE);
+ rebuild_send_message_input_boxes(ii, hamhud, 0, 0);
+ }
+ else if (d700) {
+// fprintf(stderr,"D700 found\n");
+ XmToggleButtonSetState(mw[ii].HamHUD_mode,FALSE,FALSE);
+ XmToggleButtonSetState(mw[ii].D700_mode,TRUE,FALSE);
+ XmToggleButtonSetState(mw[ii].D7_mode,FALSE,FALSE);
+ rebuild_send_message_input_boxes(ii, 0, d700, 0);
+ }
+ else if (d7) {
+// fprintf(stderr,"D7 found\n");
+ XmToggleButtonSetState(mw[ii].HamHUD_mode,FALSE,FALSE);
+ XmToggleButtonSetState(mw[ii].D700_mode,FALSE,FALSE);
+ XmToggleButtonSetState(mw[ii].D7_mode,TRUE,FALSE);
+ rebuild_send_message_input_boxes(ii, 0, 0, d7);
+ }
+ else {
+// fprintf(stderr,"Standard APRS found\n");
+ XmToggleButtonSetState(mw[ii].HamHUD_mode,FALSE,FALSE);
+ XmToggleButtonSetState(mw[ii].D700_mode,FALSE,FALSE);
+ XmToggleButtonSetState(mw[ii].D7_mode,FALSE,FALSE);
+ rebuild_send_message_input_boxes(ii, 0, 0, d7);
+ }
+ }
+}
+
+
+
+
+
+// The main Send Message dialog. db.c:update_messages() is the
+// function which fills in the message history information.
+//
+// The underlying code has been tweaked so that we can pass an EMPTY
+// path all the way down through the layers. We defined special
+// strings for that and for setting default paths, and display these
+// to the user in this and the Change Path dialogs:
+//
+// "DEFAULT PATH"
+// "DIRECT PATH"
+//
+// A note from Jim Fuller, N7VR:
+//
+// "I just set a test setup to my TH-D7GA. First Display shows
+// two lines 12 characters each, with the a third line of 12
+// character and fourth line of 9 characters on the second display
+// by pressing ok. This means 45 characters for max message.
+//
+// On my D-700, main first display is like the TH-D7GA. But when
+// I go to the message display it displays three lines. The first
+// two are 22 characters and the last is 20 characters. This
+// means 64 characters total.
+//
+// I would only send a 24 character message to field troops, based
+// on first read capability."
+//
+//
+void Send_message( /*@unused@*/ Widget w, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Arg args[50];
+ char temp[60];
+ unsigned int n;
+ int j;
+ intptr_t i;
+ char group[MAX_CALLSIGN+1];
+ int groupon;
+ int box_len;
+ Atom delw;
+
+
+//fprintf(stderr,"\n1Send_message\n");
+
+ groupon=0;
+ box_len=105;
+ i=0;
+
+begin_critical_section(&send_message_dialog_lock, "messages_gui.c:Send_message" );
+
+ for(j=0; j<MAX_MESSAGE_WINDOWS; j++) {
+ if(!mw[j].send_message_dialog) {
+ i=j;
+ break;
+ }
+ }
+
+ if(!mw[i].send_message_dialog) {
+
+ if (clientData != NULL) {
+ substr(group,(char *)clientData, MAX_CALLSIGN);
+ if (group[0] == '*') {
+ xastir_snprintf(mw[i].to_call_sign,
+ sizeof(mw[i].to_call_sign),
+ "***");
+ mw[i].to_call_sign[3] = '\0'; // Terminate it
+ memmove(group, &group[1], strlen(group));
+ groupon=1;
+ box_len=100;
+ } else {
+ xastir_snprintf(mw[i].to_call_sign,
+ sizeof(mw[i].to_call_sign),
+ "%s",
+ my_callsign);
+ mw[i].to_call_sign[MAX_CALLSIGN] = '\0'; // Terminate it
+ }
+ } else {
+ xastir_snprintf(mw[i].to_call_sign,
+ sizeof(mw[i].to_call_sign),
+ "%s",
+ my_callsign);
+ mw[i].to_call_sign[MAX_CALLSIGN] = '\0'; // Terminate it
+ }
+
+ xastir_snprintf(temp, sizeof(temp), langcode(groupon==0 ? "WPUPMSB001": "WPUPMSB002"),
+ (i+1));
+
+ mw[i].message_group = groupon;
+ mw[i].send_message_dialog = XtVaCreatePopupShell(temp,
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNtitleString,"Send Message",
+ XmNfontList, fontlist1,
+ NULL);
+
+ mw[i].pane = XtVaCreateWidget("Send_message pane",
+ xmPanedWindowWidgetClass,
+ mw[i].send_message_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ mw[i].form = XtVaCreateWidget("Send_message form",
+ xmFormWidgetClass,
+ mw[i].pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// Row 1 (bottom)
+ mw[i].button_clear_old_msgs = XtVaCreateManagedWidget(langcode("WPUPMSB007"),
+ xmPushButtonGadgetClass,
+ mw[i].form,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ mw[i].button_clear_pending_msgs = XtVaCreateManagedWidget(langcode("WPUPMSB011"),
+ xmPushButtonGadgetClass,
+ mw[i].form,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ mw[i].button_kick_timer = XtVaCreateManagedWidget(langcode("WPUPMSB012"),
+ xmPushButtonGadgetClass,
+ mw[i].form,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ mw[i].button_ok = XtVaCreateManagedWidget(langcode("WPUPMSB009"),
+ xmPushButtonGadgetClass,
+ mw[i].form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ mw[i].button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ mw[i].form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 4,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 5,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// Row 2 (1 up from bottom row)
+
+ // If D700 or D7 mode is enabled we break up the message
+ // box into 3 or 4 boxes with the lengths appropriate for
+ // those devices, else we use a single box which is 67 chars
+ // long, the maximum for an APRS message.
+ //
+ // Size of Kenwood screens:
+ // TH-D7A/E: Arranged as 12,12,12,9 (45 chars)
+ // TM-D700A: Arranged as 22,22,20 (64 chars)
+ //
+ // Size of HamHUD screen:
+ // 20 char fits on one screen, any more gets scrolled.
+ //
+
+// First have radio buttons to change how we'll draw the message
+// input widgets:
+
+ mw[i].D7_mode =XtVaCreateManagedWidget("D7",
+ xmToggleButtonGadgetClass,
+ mw[i].form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].button_clear_old_msgs,
+ XmNbottomOffset, 0,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+#ifndef NO_DYNAMIC_WIDGETS
+ XtAddCallback(mw[i].D7_mode,XmNvalueChangedCallback,D7_Msg,(XtPointer)i);
+#else // NO_DYNAMIC_WIDGETS
+ XtSetSensitive(mw[i].D7_mode, FALSE);
+#endif // NO_DYNAMIC_WIDGETS
+
+ mw[i].D700_mode =XtVaCreateManagedWidget("D700",
+ xmToggleButtonGadgetClass,
+ mw[i].form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].D7_mode,
+ XmNbottomOffset, 0,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+#ifndef NO_DYNAMIC_WIDGETS
+ XtAddCallback(mw[i].D700_mode,XmNvalueChangedCallback,D700_Msg,(XtPointer)i);
+#else // NO_DYNAMIC_WIDGETS
+ XtSetSensitive(mw[i].D700_mode, FALSE);
+#endif // NO_DYNAMIC_WIDGETS
+
+ mw[i].HamHUD_mode =XtVaCreateManagedWidget("HamHUD",
+ xmToggleButtonGadgetClass,
+ mw[i].form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].D700_mode,
+ XmNbottomOffset, 0,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+#ifndef NO_DYNAMIC_WIDGETS
+ XtAddCallback(mw[i].HamHUD_mode,XmNvalueChangedCallback,HamHUD_Msg,(XtPointer)i);
+#else // NO_DYNAMIC_WIDGETS
+ XtSetSensitive(mw[i].HamHUD_mode, FALSE);
+#endif // NO_DYNAMIC_WIDGETS
+
+ mw[i].message = XtVaCreateManagedWidget(langcode("WPUPMSB008"),
+ xmLabelWidgetClass,
+ mw[i].form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].button_clear_old_msgs,
+ XmNbottomOffset, 10,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].HamHUD_mode,
+ XmNleftOffset, 3,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+// Default: No D700 or D7 mode selected. Standard APRS mode.
+// Go build the proper input box for standard APRS mode, 67
+// chars long.
+//
+ build_send_message_input_boxes(i, 0, 0, 0);
+
+
+// Row 3 (2 up from bottom row)
+ mw[i].call = XtVaCreateManagedWidget(langcode(groupon == 0 ? "WPUPMSB003": "WPUPMSB004"),
+ xmLabelWidgetClass, mw[i].form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].message,
+ XmNbottomOffset, 15,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].HamHUD_mode,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ mw[i].send_message_call_data = XtVaCreateManagedWidget("Send_message smcd",
+ xmTextFieldWidgetClass,
+ mw[i].form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 10,
+ XmNwidth, ((10*7)+2),
+ XmNmaxLength, 10,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].message,
+ XmNbottomOffset, 10,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].call,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ xastir_snprintf(temp, sizeof(temp), "%s", langcode(groupon == 0 ? "WPUPMSB005": "WPUPMSB006"));
+
+ mw[i].button_submit_call = XtVaCreateManagedWidget(temp,
+ xmPushButtonGadgetClass,
+ mw[i].form,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].send_message_call_data,
+ XmNleftOffset, 10,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].message,
+ XmNbottomOffset, 12,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ mw[i].path = XtVaCreateManagedWidget(langcode("WPUPMSB010"),
+ xmLabelWidgetClass, mw[i].form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].message,
+ XmNbottomOffset, 15,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].button_submit_call,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ mw[i].send_message_change_path = XtVaCreateManagedWidget(langcode("WPUPMSB019"),
+ xmPushButtonGadgetClass,
+ mw[i].form,
+ XmNleftAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].message,
+ XmNbottomOffset, 12,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ mw[i].send_message_path = XtVaCreateManagedWidget("Send_message path",
+ xmTextFieldWidgetClass,
+ mw[i].form,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 26,
+ XmNwidth, ((26*7)+2),
+ XmNmaxLength, 199,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, mw[i].message,
+ XmNbottomOffset, 10,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, mw[i].path,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_WIDGET,
+ XmNrightWidget, mw[i].send_message_change_path,
+ XmNrightOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, FALSE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+// Row 4 (3 up from bottom row). Message area.
+ n=0;
+ XtSetArg(args[n], XmNrows, 10); n++;
+ XtSetArg(args[n], XmNmaxHeight, 170); n++;
+ XtSetArg(args[n], XmNcolumns, box_len); n++;
+ XtSetArg(args[n], XmNeditable, FALSE); n++;
+ XtSetArg(args[n], XmNtraversalOn, FALSE); n++;
+ XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
+ XtSetArg(args[n], XmNwordWrap, TRUE); n++;
+ XtSetArg(args[n], XmNshadowThickness, 3); n++;
+ XtSetArg(args[n], XmNscrollHorizontal, FALSE); n++;
+ XtSetArg(args[n], XmNcursorPositionVisible, FALSE); n++;
+ XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNtopOffset, 5); n++;
+ XtSetArg(args[n], XmNbottomAttachment,XmATTACH_WIDGET); n++;
+ XtSetArg(args[n], XmNbottomWidget,mw[i].call); n++;
+ XtSetArg(args[n], XmNbottomOffset, 10); n++;
+ XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNleftOffset, 5); n++;
+ XtSetArg(args[n], XmNrightAttachment,XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNrightOffset,5); n++;
+ XtSetArg(args[n], XmNautoShowCursorPosition, FALSE); n++;
+ XtSetArg(args[n], XmNforeground, MY_FG_COLOR); n++;
+ XtSetArg(args[n], XmNfontList, fontlist1); n++;
+
+// This one causes segfaults, why? Answer: args[] was set to 20
+// (too small)
+// XtSetArg(args[n], XmNbackground, MY_BG_COLOR); n++;
+
+ mw[i].send_message_text = XmCreateScrolledText(mw[i].form,
+ "Send_message smt",
+ args,
+ n);
+
+ xastir_snprintf(mw[i].win, sizeof(mw[i].win), "%ld", i);
+
+ XtAddCallback(mw[i].send_message_change_path, XmNactivateCallback, Send_message_change_path, (XtPointer)mw[i].win);
+
+ XtAddCallback(mw[i].button_ok, XmNactivateCallback, Send_message_now, (XtPointer)mw[i].win);
+
+ XtAddCallback(mw[i].button_cancel, XmNactivateCallback, Send_message_destroy_shell, (XtPointer)mw[i].win);
+
+// Note group messages isn't implemented fully yet. When it is, the following might have
+// to change again:
+// XtAddCallback(mw[i].button_clear_old_msgs, XmNactivateCallback, groupon == 0 ? Clear_message_from: Clear_message_to,
+// (XtPointer)mw[i].win);
+ XtAddCallback(mw[i].button_clear_old_msgs, XmNactivateCallback, Clear_message_to_from, (XtPointer)mw[i].win);
+
+ XtAddCallback(mw[i].button_clear_pending_msgs, XmNactivateCallback, Clear_messages_to, (XtPointer)mw[i].win);
+
+ XtAddCallback(mw[i].button_kick_timer, XmNactivateCallback, Kick_timer, (XtPointer)mw[i].win);
+
+ XtAddCallback(mw[i].button_submit_call, XmNactivateCallback, Check_new_call_messages, (XtPointer)i);
+
+ if (clientData != NULL) {
+ XmTextFieldSetString(mw[i].send_message_call_data, group);
+ }
+
+ // Set "DEFAULT PATH" into the path field
+ XmTextFieldSetString(mw[i].send_message_path,"DEFAULT PATH");
+
+ pos_dialog(mw[i].send_message_dialog);
+
+ delw = XmInternAtom(XtDisplay(mw[i].send_message_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(mw[i].send_message_dialog, delw, Send_message_destroy_shell, (XtPointer)mw[i].win);
+
+ XtManageChild(mw[i].form);
+ XtManageChild(mw[i].send_message_text);
+ XtVaSetValues(mw[i].send_message_text, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(mw[i].pane);
+
+ XtPopup(mw[i].send_message_dialog,XtGrabNone);
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(mw[i].send_message_dialog);
+ XmProcessTraversal(mw[i].button_cancel, XmTRAVERSE_CURRENT);
+
+ }
+
+//fprintf(stderr,"2calling select_station_type()\n");
+
+ // Re-arrange the outgoing message boxes based on the type of
+ // device we're talking to.
+ select_station_type(i);
+
+//fprintf(stderr,"2returned from select_station_type()\n");
+//fprintf(stderr,"1end of Send_message()\n");
+
+end_critical_section(&send_message_dialog_lock, "messages_gui.c:Send_message" );
+
+}
+
+
+
+
+
+// Bring up a Send Message dialog for each QSO that has pending
+// outbound messages.
+//
+void Show_pending_messages( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ intptr_t ii;
+ int msgs_found = 0;
+
+
+ // Look through the outgoing message queue. Find all callsigns
+ // that we're currently trying to send messages to.
+ //
+ for (ii = 0; ii < MAX_OUTGOING_MESSAGES; ii++) {
+
+ // If it matches the callsign we're talking to
+ if (message_pool[ii].active==MESSAGE_ACTIVE) {
+
+ msgs_found++;
+
+ // Bring up a Send Message box for each callsign found.
+ Send_message_call(NULL, message_pool[ii].to_call_sign, NULL);
+
+ // Fill in the old data in case it doesn't auto-fill
+ Check_new_call_messages(NULL, (XtPointer)ii, NULL);
+ }
+ }
+
+ if (msgs_found == 0) {
+ fprintf(stderr, "No Pending Messages.\n");
+ }
+}
+
+
+
+
+
+/************************* Auto msg **************************************/
+/*************************************************************************/
+void Auto_msg_option( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer calldata) {
+ int item_no = XTPOINTER_TO_INT(clientData);
+
+ if (item_no)
+ auto_reply = 1;
+ else
+ auto_reply = 0;
+}
+
+
+
+
+
+void Auto_msg_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+
+begin_critical_section(&auto_msg_dialog_lock, "messages_gui.c:Auto_msg_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ auto_msg_dialog = (Widget)NULL;
+
+end_critical_section(&auto_msg_dialog_lock, "messages_gui.c:Auto_msg_destroy_shell" );
+
+}
+
+
+
+
+
+void Auto_msg_set_now(Widget w, XtPointer clientData, XtPointer callData) {
+ char temp[110];
+ char *temp_ptr;
+
+
+ temp_ptr = XmTextFieldGetString(auto_msg_set_data);
+ substr(temp, temp_ptr, 99);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(temp);
+ xastir_snprintf(auto_reply_message,
+ sizeof(auto_reply_message),
+ "%s",
+ temp);
+ Auto_msg_destroy_shell(w, clientData, callData);
+}
+
+
+
+
+
+void Auto_msg_set( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, my_form, button_ok, button_cancel, reply;
+ Atom delw;
+
+begin_critical_section(&auto_msg_dialog_lock, "messages_gui.c:Auto_msg_set" );
+
+ if(!auto_msg_dialog) {
+
+ auto_msg_dialog = XtVaCreatePopupShell(langcode("WPUPARM001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Auto_msg_set pane",
+ xmPanedWindowWidgetClass,
+ auto_msg_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ my_form = XtVaCreateWidget("Auto_msg_set my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ reply = XtVaCreateManagedWidget(langcode("WPUPARM002"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ auto_msg_set_data = XtVaCreateManagedWidget("Auto_msg_set auto_msg_set_data",
+ xmTextFieldWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 40,
+ XmNwidth, ((40*7)+2),
+ XmNmaxLength, 100,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, reply,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("UNIOP00001"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, auto_msg_set_data,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, auto_msg_set_data,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Auto_msg_set_now, auto_msg_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Auto_msg_destroy_shell, auto_msg_dialog);
+
+ pos_dialog(auto_msg_dialog);
+
+ delw = XmInternAtom(XtDisplay(auto_msg_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(auto_msg_dialog, delw, Auto_msg_destroy_shell, (XtPointer)auto_msg_dialog);
+ XmTextFieldSetString(auto_msg_set_data,auto_reply_message);
+
+ XtManageChild(my_form);
+ XtManageChild(pane);
+
+ XtPopup(auto_msg_dialog,XtGrabNone);
+ fix_dialog_size(auto_msg_dialog);
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(auto_msg_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(auto_msg_dialog), XtWindow(auto_msg_dialog));
+
+end_critical_section(&auto_msg_dialog_lock, "messages_gui.c:Auto_msg_set" );
+
+}
+
+
diff --git a/src/objects.c b/src/objects.c
new file mode 100644
index 0000000..f7c1d38
--- /dev/null
+++ b/src/objects.c
@@ -0,0 +1,11106 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: objects.c,v 1.67 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+//#include <stdio.h>
+//#include <stdlib.h>
+#include <stdint.h>
+//#include <assert.h>
+#include <ctype.h>
+#include <math.h>
+//#include <sys/stat.h>
+//#include <sys/file.h>
+//#include <unistd.h>
+//#include <dirent.h>
+//#include <signal.h>
+//#include <termios.h>
+//#include <pwd.h>
+//#include <locale.h>
+
+// Needed for Solaris
+//#ifdef HAVE_STRINGS_H
+//#include <strings.h>
+//#endif // HAVE_STRINGS_H
+
+//#include <sys/wait.h>
+//#include <errno.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+//#ifdef HAVE_MAGICK
+//#include <sys/types.h>
+//#undef RETSIGTYPE
+///* JMT - stupid ImageMagick */
+//#define XASTIR_PACKAGE_BUGREPORT PACKAGE_BUGREPORT
+//#undef PACKAGE_BUGREPORT
+//#define XASTIR_PACKAGE_NAME PACKAGE_NAME
+//#undef PACKAGE_NAME
+//#define XASTIR_PACKAGE_STRING PACKAGE_STRING
+//#undef PACKAGE_STRING
+//#define XASTIR_PACKAGE_TARNAME PACKAGE_TARNAME
+//#undef PACKAGE_TARNAME
+//#define XASTIR_PACKAGE_VERSION PACKAGE_VERSION
+//#undef PACKAGE_VERSION
+//#ifdef HAVE_GRAPHICSMAGICK
+//#include <GraphicsMagick/magick/api.h>
+//#else // HAVE_GRAPHICSMAGICK
+//#include <magick/api.h>
+//#endif // HAVE_GRAPHICSMAGICK
+//#undef PACKAGE_BUGREPORT
+//#define PACKAGE_BUGREPORT XASTIR_PACKAGE_BUGREPORT
+//#undef XASTIR_PACKAGE_BUGREPORT
+//#undef PACKAGE_NAME
+//#define PACKAGE_NAME XASTIR_PACKAGE_NAME
+//#undef XASTIR_PACKAGE_NAME
+//#undef PACKAGE_STRING
+//#define PACKAGE_STRING XASTIR_PACKAGE_STRING
+//#undef XASTIR_PACKAGE_STRING
+//#undef PACKAGE_TARNAME
+//#define PACKAGE_TARNAME XASTIR_PACKAGE_TARNAME
+//#undef XASTIR_PACKAGE_TARNAME
+//#undef PACKAGE_VERSION
+//#define PACKAGE_VERSION XASTIR_PACKAGE_VERSION
+//#undef XASTIR_PACKAGE_VERSION
+//#endif // HAVE_MAGICK
+
+//#ifdef HAVE_LIBINTL_H
+//#include <libintl.h>
+//#define _(x) gettext(x)
+//#else // HAVE_LIBINTL_H
+//#define _(x) (x)
+//#endif // HAVE_LIBINTL_H
+
+//#ifdef HAVE_NETAX25_AXLIB_H
+//#include <netax25/axlib.h>
+//#endif // HAVE_NETAX25_AXLIB_H
+
+//#ifdef HAVE_LIBCURL
+//#include <curl/curl.h>
+//#endif
+
+//#ifdef HAVE_LIBGDAL
+//// WE7U - stupid ImageMagick
+//#define XASTIR_PACKAGE_BUGREPORT PACKAGE_BUGREPORT
+//#undef PACKAGE_BUGREPORT
+//#define XASTIR_PACKAGE_NAME PACKAGE_NAME
+//#undef PACKAGE_NAME
+//#define XASTIR_PACKAGE_STRING PACKAGE_STRING
+//#undef PACKAGE_STRING
+//#define XASTIR_PACKAGE_TARNAME PACKAGE_TARNAME
+//#undef PACKAGE_TARNAME
+//#define XASTIR_PACKAGE_VERSION PACKAGE_VERSION
+//#undef PACKAGE_VERSION
+//#include <ogr_api.h>
+//#undef PACKAGE_BUGREPORT
+//#define PACKAGE_BUGREPORT XASTIR_PACKAGE_BUGREPORT
+//#undef XASTIR_PACKAGE_BUGREPORT
+//#undef PACKAGE_NAME
+//#define PACKAGE_NAME XASTIR_PACKAGE_NAME
+//#undef XASTIR_PACKAGE_NAME
+//#undef PACKAGE_STRING
+//#define PACKAGE_STRING XASTIR_PACKAGE_STRING
+//#undef XASTIR_PACKAGE_STRING
+//#undef PACKAGE_TARNAME
+//#define PACKAGE_TARNAME XASTIR_PACKAGE_TARNAME
+//#undef XASTIR_PACKAGE_TARNAME
+//#undef PACKAGE_VERSION
+//#define PACKAGE_VERSION XASTIR_PACKAGE_VERSION
+//#undef XASTIR_PACKAGE_VERSION
+//#include <gdal.h>
+//#endif
+
+#include "xastir.h"
+#include "draw_symbols.h"
+#include "main.h"
+#include "xa_config.h"
+#include "maps.h"
+//#include "alert.h"
+#include "interface.h"
+//#include "wx.h"
+//#include "popup.h"
+//#include "track_gui.h"
+//#include "list_gui.h"
+//#include "util.h"
+//#include "color.h"
+//#include "gps.h"
+//#include "bulletin_gui.h"
+//#include "rotated.h"
+//#include "datum.h"
+//#include "igate.h"
+#include "objects.h"
+
+//#include "database.h"
+// in lieu of the above, just declare one function:
+void move_station_time(DataRow *p_curr, DataRow *p_time);
+
+//#ifdef HAVE_LIBSHP
+// #include "shp_hash.h"
+//#endif // HAVE_LIBSHP
+
+//#include "x_spider.h"
+//#include "map_cache.h"
+
+
+#include <Xm/XmAll.h>
+#include <X11/cursorfont.h>
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+extern XmFontList fontlist1; // Menu/System fontlist
+
+// lesstif (at least as of version 0.94 in 2008), doesn't
+// have full implementation of combo boxes.
+#ifndef USE_COMBO_BOX
+#if (XmVERSION >= 2 && !defined(LESSTIF_VERSION))
+# define USE_COMBO_BOX 1
+#endif
+#endif // USE_COMBO_BOX
+
+
+// ---------------------------- object -------------------------------
+Widget object_dialog = (Widget)NULL;
+Widget df_object_dialog = (Widget)NULL;
+Widget object_name_data,
+ object_lat_data_deg, object_lat_data_min, object_lat_data_ns,
+ object_lon_data_deg, object_lon_data_min, object_lon_data_ew,
+ object_group_data, object_symbol_data, object_icon,
+ object_comment_data, ob_frame, ob_group, ob_symbol,
+ ob_option_frame,
+ signpost_frame, area_frame, area_toggle, signpost_toggle,
+ df_bearing_toggle, map_view_toggle, probabilities_toggle,
+ ob_bearing_data, frameomni, framebeam,
+ ob_speed, ob_speed_data, ob_course, ob_course_data,
+ ob_comment,
+ ob_altitude, ob_altitude_data, signpost_data,
+ probability_data_min, probability_data_max,
+ open_filled_toggle, ob_lat_offset_data, ob_lon_offset_data,
+ ob_corridor, ob_corridor_data, ob_corridor_miles,
+ omni_antenna_toggle, beam_antenna_toggle;
+Pixmap Ob_icon0, Ob_icon;
+void Set_Del_Object(Widget w, XtPointer clientData, XtPointer calldata);
+// Array to hold predefined objects to display on Create/Move popup menu.
+predefinedObject predefinedObjects[MAX_NUMBER_OF_PREDEFINED_OBJECTS];
+void Populate_predefined_objects(predefinedObject *predefinedObjects);
+int number_of_predefined_objects;
+char predefined_object_definition_filename[256] = "predefined_SAR.sys";
+int predefined_menu_from_file = 0;
+
+int Area_object_enabled = 0;
+int Map_View_object_enabled = 0;
+int Area_type = 0;
+char Area_color[3] = "/0";
+int Area_bright = 0;
+int Area_filled = 0;
+int Signpost_object_enabled = 0;
+int Probability_circles_enabled = 0;
+int DF_object_enabled = 0;
+int Omni_antenna_enabled = 0;
+int Beam_antenna_enabled = 0;
+char object_shgd[5] = "0000\0";
+char object_NRQ[4] = "960\0";
+XtPointer global_parameter1 = (XtPointer)NULL;
+XtPointer global_parameter2 = (XtPointer)NULL;
+
+int polygon_last_x = -1; // Draw CAD Objects functions
+int polygon_last_y = -1; // Draw CAD Objects functions
+
+int doing_move_operation = 0;
+
+Widget draw_CAD_objects_dialog = (Widget)NULL;
+Widget cad_dialog = (Widget)NULL;
+Widget cad_label_data,
+ cad_comment_data,
+ cad_probability_data,
+ cad_line_style_data;
+ // Values entered in the cad_dialog
+int draw_CAD_objects_flag = 0;
+void Draw_All_CAD_Objects(Widget w);
+void Save_CAD_Objects_to_file(void);
+Widget cad_erase_dialog;
+Widget list_of_existing_CAD_objects = (Widget)NULL;
+Widget cad_list_dialog = (Widget)NULL;
+Widget list_of_existing_CAD_objects_edit = (Widget)NULL;
+void Format_area_for_output(double *area_km2, char *area_description, int sizeof_area_description);
+void Update_CAD_objects_list_dialog(void);
+void CAD_object_set_raw_probability(CADRow *object_ptr, float probability, int as_percent);
+int CAD_draw_objects = TRUE;
+int CAD_show_label = TRUE;
+int CAD_show_raw_probability = TRUE;
+int CAD_show_comment = TRUE;
+int CAD_show_area = TRUE;
+void Draw_CAD_Objects_erase_dialog_close(Widget w, XtPointer clientData, XtPointer callData);
+void Draw_CAD_Objects_list_dialog_close(Widget w, XtPointer clientData, XtPointer callData);
+#ifndef USE_COMBO_BOX
+int clsd_value; // replacement value for cad line type combo box
+#endif // !USE_COMBO_BOX
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Init values for Objects dialog
+char last_object[9+1];
+char last_obj_grp;
+char last_obj_sym;
+char last_obj_overlay;
+char last_obj_comment[34+1];
+
+
+
+/////////////////////////////////////////////////////////////////////////
+
+
+
+/*
+ * Check for a valid object name
+ */
+int valid_object(char *name) {
+ int len, i;
+
+ // max 9 printable ASCII characters, case sensitive [APRS
+ // Reference]
+ len = (int)strlen(name);
+ if (len > 9 || len == 0)
+ return(0); // wrong size
+
+ for (i=0;i<len;i++)
+ if (!isprint((int)name[i]))
+ return(0); // not printable
+
+ return(1);
+}
+
+
+
+
+
+/*
+ * Check for a valid item name (3-9 chars, any printable ASCII
+ * except '!' or '_')
+ */
+int valid_item(char *name) {
+ int len, i;
+
+ // min 3, max 9 printable ASCII characters, case sensitive
+ // [APRS Reference]
+ len = (int)strlen(name);
+ if (len > 9 || len < 3)
+ return(0); // Wrong size
+
+ for (i=0;i<len;i++) {
+ if (!isprint((int)name[i])) {
+ return(0); // Not printable
+ }
+ if ( (name[i] == '!') || (name[i] == '_') ) {
+ return(0); // Contains '!' or '_'
+ }
+ }
+
+ return(1);
+}
+
+
+
+
+
+/*
+ * Clear out object/item history log file
+ */
+void Object_History_Clear( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char *file;
+ FILE *f;
+ char temp_file_path[MAX_VALUE];
+
+ file = get_user_base_dir("config/object.log", temp_file_path, sizeof(temp_file_path));
+
+ f=fopen(file,"w");
+ if (f!=NULL) {
+ (void)fclose(f);
+
+ if (debug_level & 1)
+ fprintf(stderr,"Clearing Object/Item history file...\n");
+ }
+ else {
+ fprintf(stderr,"Couldn't open file for writing: %s\n", file);
+ }
+}
+
+
+
+
+
+/*
+ * Re-read object/item history log file
+ */
+void Object_History_Refresh( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+
+ // Reload saved objects and items from previous runs.
+ reload_object_item();
+}
+
+
+
+
+
+// We have a lot of code duplication between Setup_object_data,
+// Setup_item_data, and Create_object_item_tx_string.
+//
+// Make sure to look at the "transmit_compressed_objects_items"
+// variable
+// to decide whether to send a compressed packet.
+/*
+ * Create the transmit string for Objects/Items.
+ * Input is a DataRow struct, output is both an integer that says
+ * whether it completed successfully, and a char* that has the
+ * output tx string in it.
+ *
+ * Returns 0 if there's a problem.
+ */
+int Create_object_item_tx_string(DataRow *p_station, char *line, int line_length) {
+ int i, done;
+ char lat_str[MAX_LAT];
+ char lon_str[MAX_LONG];
+ char comment[43+1]; // max 43 characters of comment
+ char comment2[43+1];
+ char time[7+1];
+ struct tm *day_time;
+ time_t sec;
+ char complete_area_color[3];
+ int complete_area_type;
+ int lat_offset, lon_offset;
+ char complete_corridor[6];
+ char altitude[10];
+ char speed_course[8];
+ int speed;
+ int course;
+ int temp;
+ long temp2;
+ char signpost[6];
+ int bearing;
+ char tempstr[50];
+ char object_group;
+ char object_symbol;
+ int killed = 0;
+
+
+ (void)remove_trailing_spaces(p_station->call_sign);
+ //(void)to_upper(p_station->call_sign); Not per spec. Don't
+ //use this.
+
+ if ((p_station->flag & ST_OBJECT) != 0) { // We have an object
+ if (!valid_object(p_station->call_sign)) {
+ line[0] = '\0';
+ return(0);
+ }
+ }
+ else if ((p_station->flag & ST_ITEM) != 0) { // We have an item
+ xastir_snprintf(tempstr,
+ sizeof(tempstr),
+ "%s",
+ p_station->call_sign);
+ if (strlen(tempstr) == 1) // Add two spaces (to make 3 minimum chars)
+ xastir_snprintf(p_station->call_sign, sizeof(p_station->call_sign), "%s ",tempstr);
+ else if (strlen(tempstr) == 2) // Add one space (to make 3 minimum chars)
+ xastir_snprintf(p_station->call_sign, sizeof(p_station->call_sign), "%s ",tempstr);
+
+ if (!valid_item(p_station->call_sign)) {
+ line[0] = '\0';
+ return(0);
+ }
+ }
+ else { // Not an item or an object, what are we doing here!
+ line[0] = '\0';
+ return(0);
+ }
+
+ // Lat/lon are in Xastir coordinates, so we need to convert
+ // them to APRS string format here.
+ convert_lat_l2s(p_station->coord_lat, lat_str, sizeof(lat_str), CONVERT_LP_NOSP);
+ convert_lon_l2s(p_station->coord_lon, lon_str, sizeof(lon_str), CONVERT_LP_NOSP);
+
+ // Check for an overlay character. Replace the group character
+ // (table char) with the overlay if present.
+ if (p_station->aprs_symbol.special_overlay != '\0') {
+ // Overlay character found
+ object_group = p_station->aprs_symbol.special_overlay;
+ if ( (object_group >= '0' && object_group <= '9')
+ || (object_group >= 'A' && object_group <= 'Z') ) {
+ // Valid overlay character, use what we have
+ }
+ else {
+ // Bad overlay character, throw it away
+ object_group = '\\';
+ }
+ }
+ else { // No overlay character
+ object_group = p_station->aprs_symbol.aprs_type;
+ }
+
+ object_symbol = p_station->aprs_symbol.aprs_symbol;
+
+ // In this case we grab only the first comment field (if it
+ // exists) for the object/item
+ if ( (p_station->comment_data != NULL)
+ && (p_station->comment_data->text_ptr != NULL) ){
+ xastir_snprintf(comment,
+ sizeof(comment),
+ "%s",
+ p_station->comment_data->text_ptr);
+ }
+ else {
+ comment[0] = '\0'; // Empty string
+ }
+
+ if ( (p_station->probability_min[0] != '\0')
+ || (p_station->probability_max[0] != '\0') ) {
+
+ if (p_station->probability_max[0] == '\0') {
+ // Only have probability_min
+ xastir_snprintf(comment2,
+ sizeof(comment2),"Pmin%s,%s",
+ p_station->probability_min,
+ comment);
+ }
+ else if (p_station->probability_min[0] == '\0') {
+ // Only have probability_max
+ xastir_snprintf(comment2,
+ sizeof(comment2),"Pmax%s,%s",
+ p_station->probability_max,
+ comment);
+ }
+ else { // Have both
+ xastir_snprintf(comment2,
+ sizeof(comment2),"Pmin%s,Pmax%s,%s",
+ p_station->probability_min,
+ p_station->probability_max,
+ comment);
+ }
+ xastir_snprintf(comment,sizeof(comment), "%s", comment2);
+ }
+
+
+ // Put RNG or PHG at the beginning of the comment
+ xastir_snprintf(comment2,
+ sizeof(comment2),
+ "%s%s",
+ p_station->power_gain,
+ comment);
+ xastir_snprintf(comment,
+ sizeof(comment),
+ "%s",
+ comment2);
+
+
+ (void)remove_trailing_spaces(comment);
+
+
+ // This is for objects only, not items. Uses current time but
+ // should use the transmitted time from the DataRow struct.
+ // Which time field in the struct would that be? Have to find
+ // out
+ // from the extract_?? code.
+ if ((p_station->flag & ST_OBJECT) != 0) {
+ sec = sec_now();
+ day_time = gmtime(&sec);
+ xastir_snprintf(time,
+ sizeof(time),
+ "%02d%02d%02dz",
+ day_time->tm_mday,
+ day_time->tm_hour,
+ day_time->tm_min);
+ }
+
+
+// Handle Generic Options
+
+
+ // Speed/Course Fields
+ xastir_snprintf(speed_course, sizeof(speed_course), ".../"); // Start with invalid-data string
+ course = 0;
+ if (strlen(p_station->course) != 0) { // Course was entered
+ // Need to check for 1 to three digits only, and 001-360
+ // degrees)
+ temp = atoi(p_station->course);
+ if ( (temp >= 1) && (temp <= 360) ) {
+ xastir_snprintf(speed_course, sizeof(speed_course), "%03d/",temp);
+ course = temp;
+ }
+ else if (temp == 0) { // Spec says 001 to 360 degrees...
+ xastir_snprintf(speed_course, sizeof(speed_course), "360/");
+ }
+ }
+ speed = 0;
+ if (strlen(p_station->speed) != 0) { // Speed was entered (we only handle knots currently)
+ // Need to check for 1 to three digits, no alpha characters
+ temp = atoi(p_station->speed);
+ if ( (temp >= 0) && (temp <= 999) ) {
+ long x_long, y_lat;
+
+ xastir_snprintf(tempstr, sizeof(tempstr), "%03d",temp);
+ strncat(speed_course,
+ tempstr,
+ sizeof(speed_course) - 1 - strlen(speed_course));
+ speed = temp;
+
+ // Speed is non-zero. Compute the current dead-reckoned
+ // position and use that instead.
+ compute_current_DR_position(p_station,
+ &x_long,
+ &y_lat);
+
+ // Lat/lon are in Xastir coordinates, so we need to
+ // convert them to APRS string format here.
+ //
+ convert_lat_l2s(y_lat,
+ lat_str,
+ sizeof(lat_str),
+ CONVERT_LP_NOSP);
+
+ convert_lon_l2s(x_long,
+ lon_str,
+ sizeof(lon_str),
+ CONVERT_LP_NOSP);
+
+//fprintf(stderr,"\t%s %s\n", lat_str, lon_str);
+
+ }
+ else {
+ strncat(speed_course,
+ "...",
+ sizeof(speed_course) - 1 - strlen(speed_course));
+ }
+ }
+ else { // No speed entered, blank it out
+ strncat(speed_course,
+ "...",
+ sizeof(speed_course) - 1 - strlen(speed_course));
+ }
+ if ( (speed_course[0] == '.') && (speed_course[4] == '.') ) {
+ speed_course[0] = '\0'; // No speed or course entered, so blank it
+ }
+ if (p_station->aprs_symbol.area_object.type != AREA_NONE) { // It's an area object
+ speed_course[0] = '\0'; // Course/Speed not allowed if Area Object
+ }
+
+ // Altitude Field
+ altitude[0] = '\0'; // Start with empty string
+ if (strlen(p_station->altitude) != 0) { // Altitude was entered (we only handle feet currently)
+ // Need to check for all digits, and 1 to 6 digits
+ if (isdigit((int)p_station->altitude[0])) {
+ // Must convert from meters to feet before transmitting
+ temp2 = (int)( (atof(p_station->altitude) / 0.3048) + 0.5);
+ if ( (temp2 >= 0) && (temp2 <= 99999l) ) {
+ xastir_snprintf(altitude, sizeof(altitude), "/A=%06ld",temp2);
+ }
+ }
+ }
+
+
+// Handle Specific Options
+
+
+ // Area Objects
+ if (p_station->aprs_symbol.area_object.type != AREA_NONE) { // It's an area object
+
+ // Note that transmitted color consists of two characters,
+ // from "/0" to "15"
+ xastir_snprintf(complete_area_color, sizeof(complete_area_color), "%02d", p_station->aprs_symbol.area_object.color);
+ if (complete_area_color[0] == '0')
+ complete_area_color[0] = '/';
+
+ complete_area_type = p_station->aprs_symbol.area_object.type;
+
+ lat_offset = p_station->aprs_symbol.area_object.sqrt_lat_off;
+ lon_offset = p_station->aprs_symbol.area_object.sqrt_lon_off;
+
+ // Corridor
+ complete_corridor[0] = '\0';
+ if ( (complete_area_type == 1) || (complete_area_type == 6)) {
+ if (p_station->aprs_symbol.area_object.corridor_width > 0) {
+ xastir_snprintf(complete_corridor, sizeof(complete_corridor), "{%d}",
+ p_station->aprs_symbol.area_object.corridor_width);
+ }
+ }
+
+ if ((p_station->flag & ST_OBJECT) != 0) { // It's an object
+
+ if (transmit_compressed_objects_items) {
+ char temp_group = object_group;
+ long x_long, y_lat;
+
+ // If we have a numeric overlay, we need to convert
+ // it to 'a-j' for compressed objects.
+ if (temp_group >= '0' && temp_group <= '9') {
+ temp_group = temp_group + 'a';
+ }
+
+ if (speed == 0) {
+ x_long = p_station->coord_lon;
+ y_lat = p_station->coord_lat;
+ }
+ else {
+ // Speed is non-zero. Compute the current
+ // dead-reckoned position and use that instead.
+ compute_current_DR_position(p_station,
+ &x_long,
+ &y_lat);
+ }
+
+ // We need higher precision lat/lon strings than
+ // those created above.
+ convert_lat_l2s(y_lat, lat_str, sizeof(lat_str), CONVERT_HP_NOSP);
+ convert_lon_l2s(x_long, lon_str, sizeof(lon_str), CONVERT_HP_NOSP);
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%1d%02d%2s%02d%s%s%s",
+ p_station->call_sign,
+ time,
+ compress_posit(lat_str,
+ temp_group,
+ lon_str,
+ object_symbol,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank
+ complete_area_type,
+ lat_offset,
+ complete_area_color,
+ lon_offset,
+ speed_course,
+ complete_corridor,
+ altitude);
+
+ }
+ else { // Non-compressed posit object
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%c%s%c%1d%02d%2s%02d%s%s%s",
+ p_station->call_sign,
+ time,
+ lat_str,
+ object_group,
+ lon_str,
+ object_symbol,
+ complete_area_type,
+ lat_offset,
+ complete_area_color,
+ lon_offset,
+ speed_course,
+ complete_corridor,
+ altitude);
+ }
+ }
+ else { // It's an item
+
+ if (transmit_compressed_objects_items) {
+ char temp_group = object_group;
+ long x_long, y_lat;
+
+ // If we have a numeric overlay, we need to convert
+ // it to 'a-j' for compressed objects.
+ if (temp_group >= '0' && temp_group <= '9') {
+ temp_group = temp_group + 'a';
+ }
+
+ if (speed == 0) {
+ x_long = p_station->coord_lon;
+ y_lat = p_station->coord_lat;
+ }
+ else {
+ // Speed is non-zero. Compute the current
+ // dead-reckoned position and use that instead.
+ compute_current_DR_position(p_station,
+ &x_long,
+ &y_lat);
+ }
+
+ // We need higher precision lat/lon strings than
+ // those created above.
+ convert_lat_l2s(y_lat, lat_str, sizeof(lat_str), CONVERT_HP_NOSP);
+ convert_lon_l2s(x_long, lon_str, sizeof(lon_str), CONVERT_HP_NOSP);
+
+ xastir_snprintf(line, line_length, ")%s!%s%1d%02d%2s%02d%s%s%s",
+ p_station->call_sign,
+ compress_posit(lat_str,
+ temp_group,
+ lon_str,
+ object_symbol,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank
+ complete_area_type,
+ lat_offset,
+ complete_area_color,
+ lon_offset,
+ speed_course,
+ complete_corridor,
+ altitude);
+ }
+ else { // Non-compressed item
+
+ xastir_snprintf(line, line_length, ")%s!%s%c%s%c%1d%02d%2s%02d%s%s%s",
+ p_station->call_sign,
+ lat_str,
+ object_group,
+ lon_str,
+ object_symbol,
+ complete_area_type,
+ lat_offset,
+ complete_area_color,
+ lon_offset,
+ speed_course,
+ complete_corridor,
+ altitude);
+ }
+ }
+ }
+
+ else if ( (p_station->aprs_symbol.aprs_type == '\\') // We have a signpost object
+ && (p_station->aprs_symbol.aprs_symbol == 'm' ) ) {
+ if (strlen(p_station->signpost) > 0) {
+ xastir_snprintf(signpost, sizeof(signpost), "{%s}", p_station->signpost);
+ }
+ else { // No signpost data entered, blank it out
+ signpost[0] = '\0';
+ }
+ if ((p_station->flag & ST_OBJECT) != 0) { // It's an object
+
+ if (transmit_compressed_objects_items) {
+ char temp_group = object_group;
+ long x_long, y_lat;
+
+ // If we have a numeric overlay, we need to convert
+ // it to 'a-j' for compressed objects.
+ if (temp_group >= '0' && temp_group <= '9') {
+ temp_group = temp_group + 'a';
+ }
+
+ if (speed == 0) {
+ x_long = p_station->coord_lon;
+ y_lat = p_station->coord_lat;
+ }
+ else {
+ // Speed is non-zero. Compute the current
+ // dead-reckoned position and use that instead.
+ compute_current_DR_position(p_station,
+ &x_long,
+ &y_lat);
+ }
+
+ // We need higher precision lat/lon strings than
+ // those created above.
+ convert_lat_l2s(y_lat, lat_str, sizeof(lat_str), CONVERT_HP_NOSP);
+ convert_lon_l2s(x_long, lon_str, sizeof(lon_str), CONVERT_HP_NOSP);
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%s%s",
+ p_station->call_sign,
+ time,
+ compress_posit(lat_str,
+ temp_group,
+ lon_str,
+ object_symbol,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank
+ altitude,
+ signpost);
+ }
+ else { // Non-compressed posit object
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%c%s%c%s%s%s",
+ p_station->call_sign,
+ time,
+ lat_str,
+ object_group,
+ lon_str,
+ object_symbol,
+ speed_course,
+ altitude,
+ signpost);
+ }
+ }
+ else { // It's an item
+
+ if (transmit_compressed_objects_items) {
+ char temp_group = object_group;
+ long x_long, y_lat;
+
+ // If we have a numeric overlay, we need to convert
+ // it to 'a-j' for compressed objects.
+ if (temp_group >= '0' && temp_group <= '9') {
+ temp_group = temp_group + 'a';
+ }
+
+ if (speed == 0) {
+ x_long = p_station->coord_lon;
+ y_lat = p_station->coord_lat;
+ }
+ else {
+ // Speed is non-zero. Compute the current
+ // dead-reckoned position and use that instead.
+ compute_current_DR_position(p_station,
+ &x_long,
+ &y_lat);
+ }
+
+ // We need higher precision lat/lon strings than
+ // those created above.
+ convert_lat_l2s(y_lat, lat_str, sizeof(lat_str), CONVERT_HP_NOSP);
+ convert_lon_l2s(x_long, lon_str, sizeof(lon_str), CONVERT_HP_NOSP);
+
+ xastir_snprintf(line, line_length, ")%s!%s%s%s",
+ p_station->call_sign,
+ compress_posit(lat_str,
+ temp_group,
+ lon_str,
+ object_symbol,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank
+ altitude,
+ signpost);
+ }
+ else { // Non-compressed item
+
+ xastir_snprintf(line, line_length, ")%s!%s%c%s%c%s%s%s",
+ p_station->call_sign,
+ lat_str,
+ object_group,
+ lon_str,
+ object_symbol,
+ speed_course,
+ altitude,
+ signpost);
+ }
+ }
+ }
+
+ else if (p_station->signal_gain[0] != '\0') { // Must be an Omni-DF object/item
+
+ if ((p_station->flag & ST_OBJECT) != 0) { // It's an object
+
+ if (transmit_compressed_objects_items) {
+ char temp_group = object_group;
+ long x_long, y_lat;
+
+ // If we have a numeric overlay, we need to convert
+ // it to 'a-j' for compressed objects.
+ if (temp_group >= '0' && temp_group <= '9') {
+ temp_group = temp_group + 'a';
+ }
+
+ if (speed == 0) {
+ x_long = p_station->coord_lon;
+ y_lat = p_station->coord_lat;
+ }
+ else {
+ // Speed is non-zero. Compute the current
+ // dead-reckoned position and use that instead.
+ compute_current_DR_position(p_station,
+ &x_long,
+ &y_lat);
+ }
+
+ // We need higher precision lat/lon strings than
+ // those created above.
+ convert_lat_l2s(y_lat, lat_str, sizeof(lat_str), CONVERT_HP_NOSP);
+ convert_lon_l2s(x_long, lon_str, sizeof(lon_str), CONVERT_HP_NOSP);
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%s/%s%s",
+ p_station->call_sign,
+ time,
+ compress_posit(lat_str,
+ temp_group,
+ lon_str,
+ object_symbol,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank
+ p_station->signal_gain,
+ speed_course,
+ altitude);
+ }
+ else { // Non-compressed posit object
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%c%s%c%s/%s%s",
+ p_station->call_sign,
+ time,
+ lat_str,
+ object_group,
+ lon_str,
+ object_symbol,
+ p_station->signal_gain,
+ speed_course,
+ altitude);
+ }
+ }
+ else { // It's an item
+
+ if (transmit_compressed_objects_items) {
+ char temp_group = object_group;
+ long x_long, y_lat;
+
+ // If we have a numeric overlay, we need to convert
+ // it to 'a-j' for compressed objects.
+ if (temp_group >= '0' && temp_group <= '9') {
+ temp_group = temp_group + 'a';
+ }
+
+ if (speed == 0) {
+ x_long = p_station->coord_lon;
+ y_lat = p_station->coord_lat;
+ }
+ else {
+ // Speed is non-zero. Compute the current
+ // dead-reckoned position and use that instead.
+ compute_current_DR_position(p_station,
+ &x_long,
+ &y_lat);
+ }
+
+ // We need higher precision lat/lon strings than
+ // those created above.
+ convert_lat_l2s(y_lat, lat_str, sizeof(lat_str), CONVERT_HP_NOSP);
+ convert_lon_l2s(x_long, lon_str, sizeof(lon_str), CONVERT_HP_NOSP);
+
+ xastir_snprintf(line, line_length, ")%s!%s%s/%s%s",
+ p_station->call_sign,
+ compress_posit(lat_str,
+ temp_group,
+ lon_str,
+ object_symbol,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank
+ p_station->signal_gain,
+ speed_course,
+ altitude);
+ }
+ else { // Non-compressed item
+
+ xastir_snprintf(line, line_length, ")%s!%s%c%s%c%s/%s%s",
+ p_station->call_sign,
+ lat_str,
+ object_group,
+ lon_str,
+ object_symbol,
+ p_station->signal_gain,
+ speed_course,
+ altitude);
+ }
+ }
+ }
+ else if (p_station->NRQ[0] != 0) { // It's a Beam Heading DFS object/item
+
+ if (strlen(speed_course) != 7)
+ xastir_snprintf(speed_course,
+ sizeof(speed_course),
+ "000/000");
+
+ bearing = atoi(p_station->bearing);
+ if ( (bearing < 1) || (bearing > 360) )
+ bearing = 360;
+
+ if ((p_station->flag & ST_OBJECT) != 0) { // It's an object
+
+ if (transmit_compressed_objects_items) {
+ char temp_group = object_group;
+ long x_long, y_lat;
+
+ // If we have a numeric overlay, we need to convert
+ // it to 'a-j' for compressed objects.
+ if (temp_group >= '0' && temp_group <= '9') {
+ temp_group = temp_group + 'a';
+ }
+
+ if (speed == 0) {
+ x_long = p_station->coord_lon;
+ y_lat = p_station->coord_lat;
+ }
+ else {
+ // Speed is non-zero. Compute the current
+ // dead-reckoned position and use that instead.
+ compute_current_DR_position(p_station,
+ &x_long,
+ &y_lat);
+ }
+
+ // We need higher precision lat/lon strings than
+ // those created above.
+ convert_lat_l2s(y_lat, lat_str, sizeof(lat_str), CONVERT_HP_NOSP);
+ convert_lon_l2s(x_long, lon_str, sizeof(lon_str), CONVERT_HP_NOSP);
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s/%03i/%s%s",
+ p_station->call_sign,
+ time,
+ compress_posit(lat_str,
+ temp_group,
+ lon_str,
+ object_symbol,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank
+ bearing,
+ p_station->NRQ,
+ altitude);
+ }
+ else { // Non-compressed posit object
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%c%s%c%s/%03i/%s%s",
+ p_station->call_sign,
+ time,
+ lat_str,
+ object_group,
+ lon_str,
+ object_symbol,
+ speed_course,
+ bearing,
+ p_station->NRQ,
+ altitude);
+ }
+ }
+ else { // It's an item
+
+ if (transmit_compressed_objects_items) {
+ char temp_group = object_group;
+ long x_long, y_lat;
+
+ // If we have a numeric overlay, we need to convert
+ // it to 'a-j' for compressed objects.
+ if (temp_group >= '0' && temp_group <= '9') {
+ temp_group = temp_group + 'a';
+ }
+
+ if (speed == 0) {
+ x_long = p_station->coord_lon;
+ y_lat = p_station->coord_lat;
+ }
+ else {
+ // Speed is non-zero. Compute the current
+ // dead-reckoned position and use that instead.
+ compute_current_DR_position(p_station,
+ &x_long,
+ &y_lat);
+ }
+
+ // We need higher precision lat/lon strings than
+ // those created above.
+ convert_lat_l2s(y_lat, lat_str, sizeof(lat_str), CONVERT_HP_NOSP);
+ convert_lon_l2s(x_long, lon_str, sizeof(lon_str), CONVERT_HP_NOSP);
+
+ xastir_snprintf(line, line_length, ")%s!%s/%03i/%s%s",
+ p_station->call_sign,
+ compress_posit(lat_str,
+ temp_group,
+ lon_str,
+ object_symbol,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank
+ bearing,
+ p_station->NRQ,
+ altitude);
+ }
+ else { // Non-compressed item
+
+ xastir_snprintf(line, line_length, ")%s!%s%c%s%c%s/%03i/%s%s",
+ p_station->call_sign,
+ lat_str,
+ object_group,
+ lon_str,
+ object_symbol,
+ speed_course,
+ bearing,
+ p_station->NRQ,
+ altitude);
+ }
+ }
+ }
+
+ else { // Else it's a normal object/item
+
+ if ((p_station->flag & ST_OBJECT) != 0) { // It's an object
+
+ if (transmit_compressed_objects_items) {
+ char temp_group = object_group;
+ long x_long, y_lat;
+
+ // If we have a numeric overlay, we need to convert
+ // it to 'a-j' for compressed objects.
+ if (temp_group >= '0' && temp_group <= '9') {
+ temp_group = temp_group + 'a';
+ }
+
+ if (speed == 0) {
+ x_long = p_station->coord_lon;
+ y_lat = p_station->coord_lat;
+ }
+ else {
+ // Speed is non-zero. Compute the current
+ // dead-reckoned position and use that instead.
+ compute_current_DR_position(p_station,
+ &x_long,
+ &y_lat);
+ }
+
+ // We need higher precision lat/lon strings than
+ // those created above.
+ convert_lat_l2s(y_lat, lat_str, sizeof(lat_str), CONVERT_HP_NOSP);
+ convert_lon_l2s(x_long, lon_str, sizeof(lon_str), CONVERT_HP_NOSP);
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%s",
+ p_station->call_sign,
+ time,
+ compress_posit(lat_str,
+ temp_group,
+ lon_str,
+ object_symbol,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank
+ altitude);
+ }
+ else { // Non-compressed posit object
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%c%s%c%s%s",
+ p_station->call_sign,
+ time,
+ lat_str,
+ object_group,
+ lon_str,
+ object_symbol,
+ speed_course,
+ altitude);
+ }
+ }
+ else { // It's an item
+
+ if (transmit_compressed_objects_items) {
+ char temp_group = object_group;
+ long x_long, y_lat;
+
+ // If we have a numeric overlay, we need to convert
+ // it to 'a-j' for compressed objects.
+ if (temp_group >= '0' && temp_group <= '9') {
+ temp_group = temp_group + 'a';
+ }
+
+ if (speed == 0) {
+ x_long = p_station->coord_lon;
+ y_lat = p_station->coord_lat;
+ }
+ else {
+ // Speed is non-zero. Compute the current
+ // dead-reckoned position and use that instead.
+ compute_current_DR_position(p_station,
+ &x_long,
+ &y_lat);
+ }
+
+ // We need higher precision lat/lon strings than
+ // those created above.
+ convert_lat_l2s(y_lat, lat_str, sizeof(lat_str), CONVERT_HP_NOSP);
+ convert_lon_l2s(x_long, lon_str, sizeof(lon_str), CONVERT_HP_NOSP);
+
+ xastir_snprintf(line, line_length, ")%s!%s%s",
+ p_station->call_sign,
+ compress_posit(lat_str,
+ temp_group,
+ lon_str,
+ object_symbol,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank
+ altitude);
+ }
+ else { // Non-compressed item
+ xastir_snprintf(line, line_length, ")%s!%s%c%s%c%s%s",
+ p_station->call_sign,
+ lat_str,
+ object_group,
+ lon_str,
+ object_symbol,
+ speed_course,
+ altitude);
+ }
+ }
+ }
+
+ // If it's a "killed" object, change '*' to an '_'
+ if ((p_station->flag & ST_OBJECT) != 0) { // It's an object
+ if ((p_station->flag & ST_ACTIVE) != ST_ACTIVE) { // It's been killed
+ line[10] = '_';
+ killed++;
+ }
+ }
+ // If it's a "killed" item, change '!' to an '_'
+ else { // It's an item
+ if ((p_station->flag & ST_ACTIVE) != ST_ACTIVE) { // It's been killed
+ killed++;
+ done = 0;
+ i = 0;
+ while ( (!done) && (i < 11) ) {
+ if (line[i] == '!') {
+ line[i] = '_'; // mark as deleted object
+ done++; // Exit from loop
+ }
+ i++;
+ }
+ }
+ }
+
+ // Check whether we need to stop transmitting particular killed
+ // object/items now.
+ if (killed) {
+ // Check whether we should decrement the object_retransmit
+ // counter so that we will eventually stop sending this
+ // object/item.
+ if (p_station->object_retransmit == 0) {
+ // We shouldn't be transmitting this killed object/item
+ // anymore. We're already done transmitting it.
+
+//fprintf(stderr, "Done transmitting this object: %s, %d\n",
+//p_station->call_sign,
+//p_station->object_retransmit);
+
+ return(0);
+ }
+
+ // Check whether the timeout has been set yet on this killed
+ // object/item. If not, change it from -1 (continuous
+ // transmit of non-killed objects) to
+ // MAX_KILLED_OBJECT_RETRANSMIT.
+ if (p_station->object_retransmit <= -1) {
+
+//fprintf(stderr, "Killed object %s, setting retries, %d -> %d\n",
+//p_station->call_sign,
+//p_station->object_retransmit,
+//MAX_KILLED_OBJECT_RETRANSMIT - 1);
+
+ if ((MAX_KILLED_OBJECT_RETRANSMIT - 1) < 0) {
+ p_station->object_retransmit = 0;
+ return(0); // No retransmits desired
+ }
+ else {
+ p_station->object_retransmit = MAX_KILLED_OBJECT_RETRANSMIT - 1;
+ }
+ }
+ else {
+ // Decrement the timeout if it is a positive number.
+ if (p_station->object_retransmit > 0) {
+
+//fprintf(stderr, "Killed object %s, decrementing retries, %d ->
+//%d\n",
+//p_station->call_sign,
+//p_station->object_retransmit,
+//p_station->object_retransmit - 1);
+
+ p_station->object_retransmit--;
+ }
+ }
+ }
+
+ // We need to tack the comment on the end, but need to make
+ // sure we don't go over the maximum length for an object/item.
+ if (strlen(comment) != 0) {
+ temp = 0;
+ if ((p_station->flag & ST_OBJECT) != 0) {
+ while ( (strlen(line) < 80) && (temp < (int)strlen(comment)) ) {
+ //fprintf(stderr,"temp: %d->%d\t%c\n", temp,
+ //strlen(line), comment[temp]);
+ line[strlen(line) + 1] = '\0';
+ line[strlen(line)] = comment[temp++];
+ }
+ }
+ else { // It's an item
+ while ( (strlen(line) < (64 + strlen(p_station->call_sign))) && (temp < (int)strlen(comment)) ) {
+ //fprintf(stderr,"temp: %d->%d\t%c\n", temp,
+ //strlen(line), comment[temp]);
+ line[strlen(line) + 1] = '\0';
+ line[strlen(line)] = comment[temp++];
+ }
+ }
+ }
+
+ //fprintf(stderr,"line: %s\n",line);
+
+// NOTE: Compressed mode will be shorter still. Account
+// for that when compressed mode is implemented for objects/items.
+
+ return(1);
+}
+
+
+
+
+
+// check_and_transmit_objects_items
+//
+// This function checks the last_transmit_time for each
+// locally-owned object/item. If it has been at least the
+// transmit_time_increment since the last transmit, the increment is
+// doubled and the object/item transmitted.
+//
+// Killed objects/items are transmitted for
+// MAX_KILLED_OBJECT_RETRANSMIT times and then transmitting of those
+// objects ceases.
+//
+// This would be a good place to implement auto-expiration of
+// objects that's been discussed on the mailing lists.
+//
+// This function depends on the local loopback that is in
+// interface.c. If we don't hear & decode our own packets, we won't
+// have our own objects/items in our list.
+//
+// We need to check DataRow objects for ST_OBJECT or ST_ITEM types
+// that were transmitted by our callsign & SSID. We might also need
+// to modify the remove_time() and check_station_remove functions in
+// order not to delete our own objects/items too quickly.
+//
+// insert_time/remove_time/next_station_time/prev_station_time
+//
+// It would be nice if the create/modify object dialog and this
+// routine went
+// through the same functions to create the transmitted packets:
+// objects.c:Setup_object_data
+// objects.c:Setup_item_data
+// Unfortunately those routines snag their data directly from the
+// dialog.
+// In order to make them use the same code we'd have to separate out
+// the
+// fetch-from-dialog code from the create-transmit-packet code.
+//
+// This is what aprsDOS does, from Bob's APRS.TXT file: "a
+// fundamental precept is that old data is less important than new
+// data." "Each new packet is transmitted immediately, then 20
+// seconds later. After every transmission, the period is doubled.
+// After 20 minutes only six packets have been transmitted. From
+// then on the rate remains at 10 minutes times the number of
+// digipeater hops you are using."
+// Actually, talking to Bob, he's used a period of 15 seconds as his
+// base unit. We now do the same using the OBJECT_CHECK_RATE define
+// to set the initial timing.
+
+//
+// Added these to database.h:DataRow struct:
+// time_t last_transmit_time; // Time we last transmitted
+// an object/item. Used to
+// // implement decaying
+// transmit time algorithm
+// short transmit_time_increment; // Seconds to add to transmit
+// next time around. Used
+// // to implement decaying
+// transmit time algorithm
+//
+// The earlier code here transmitted objects/items at a specified
+// rate. This can cause large transmissions every OBJECT_rate
+// seconds, as all objects/items are transmitted at once. With the
+// new code, the objects/items may be spaced a bit from each other
+// time-wise, plus they are transmitted less and less often with
+// each transmission until they hit the max interval specified by
+// the "Object/Item TX Interval" slider. When they hit that max
+// interval, they are transmitted at the constant interval until
+// killed. When they are killed, they are transmitted for
+// MAX_KILLED_OBJECT_RETRANSMIT iterations using the decaying
+// algorithm, then transmissions cease.
+//
+void check_and_transmit_objects_items(time_t time) {
+ DataRow *p_station; // pointer to station data
+ char line[256];
+ int first = 1; // Used to output debug message only once
+ int increment;
+
+
+ // Time to re-transmit objects/items?
+ // Check every OBJECT_CHECK_RATE seconds - 20%. No faster else
+ // we'll be running through the station list too often and
+ // wasting cycles.
+ if (time < (last_object_check + (int)(4.0 * OBJECT_CHECK_RATE/5.0 + 1.0) ) )
+ return;
+
+//fprintf(stderr,"check_and_transmit_objects_items\n");
+
+ // Set up timer for next go-around
+ last_object_check = time;
+
+ if (debug_level & 1)
+ fprintf(stderr,"Checking whether to retransmit any objects/items\n");
+
+// We could speed things up quite a bit here by either keeping a
+// separate list of our own objects/items, or going through the list
+// of stations by time instead of by name (If by time, only check
+// backwards from the current time by the max transmit interval plus
+// some increment. Watch out for the user changing the slider).
+
+ for (p_station = n_first; p_station != NULL; p_station = p_station->n_next) {
+
+ //fprintf(stderr,"%s\t%s\n",p_station->call_sign,p_station->origin);
+
+ // If station is owned by me (Exact match includes SSID)
+// if (is_my_call(p_station->origin,1)) {
+ // and it's an object or item
+ if ((p_station->flag & (ST_OBJECT|ST_ITEM)) && is_my_object_item(p_station)) {
+
+ long x_long_save, y_lat_save;
+
+ // If dead-reckoning, we need to send out a new
+ // position for this object instead of just
+ // overwriting the old position, which will cause
+ // the track to skip. Here we save the old position
+ // away so we can save it back to the record later.
+ //
+ x_long_save = p_station->coord_lon;
+ y_lat_save = p_station->coord_lat;
+
+ if (debug_level & 1) {
+ fprintf(stderr,
+ "Found a locally-owned object or item: %s\n",
+ p_station->call_sign);
+ }
+
+ // Call the DR function to compute a new lat/long
+ // and change the object's lat/long to match so that
+ // we move the object along each time we transmit
+ // it.
+ //
+// WE7U
+// Here we should log the new position to file if it's not done
+// automatically.
+ //
+ if (p_station->speed[0] != '\0') {
+ long x_long, y_lat;
+
+ compute_current_DR_position(p_station, &x_long, &y_lat);
+
+ // Put the new position into the record
+ // temporarily so that we can
+ p_station->coord_lon = x_long;
+ p_station->coord_lat = y_lat;
+ }
+
+ // Keep the timestamp current on my own
+ // objects/items so they don't expire.
+ p_station->sec_heard = sec_now();
+ move_station_time(p_station,NULL);
+
+// Implementing sped-up transmission of new objects, regular
+// transmission of old objects (decaying algorithm). We'll do this
+// by keeping a last_transmit_time variable and a
+// transmit_time_increment with each DataRow struct. If the
+// last_transmit_time is older than the transmit_time_increment, we
+// transmit the object and double the increment variable, until we
+// hit the OBJECT_rate limit for the increment. This will make
+// newer objects/items transmit more often, and will also space out
+// the transmissions of old objects so they're not transmitted all
+// at once in a group. Each time a new object/item is created that
+// is owned by us, it needs to have it's timer set to 20 (seconds).
+// If an object/item is touched, it needs to again be set to 20
+// seconds.
+///////////////////////////////////
+
+// Run through the station list.
+
+// Transmit any objects/items that have equalled or gone past
+// (last_transmit_time + transmit_time_increment). Update the
+// last_transmit_time to current time.
+//
+// Double the transmit_time_increment. If it has gone beyond
+// OBJECT_rate, set it to OBJECT_rate instead.
+//
+///////////////////////////////////
+
+
+ // Check for the case where the timing slider has
+ // been reduced and the expire time is too long.
+ // Reset it to the current max expire time so that
+ // it'll get transmitted more quickly.
+ if (p_station->transmit_time_increment > OBJECT_rate)
+ p_station->transmit_time_increment = OBJECT_rate;
+
+
+ increment = p_station->transmit_time_increment;
+
+ if ( ( p_station->last_transmit_time + increment) <= time ) {
+ // We should transmit this object/item as it has
+ // hit its transmit interval.
+
+ float randomize;
+ int one_fifth_increment;
+ int new_increment;
+
+
+ if (first && !object_tx_disable) { // "Transmitting objects/items"
+ statusline(langcode("BBARSTA042"),1);
+ first = 0;
+ }
+
+ // Set up the new doubling increment
+ increment = increment * 2;
+ if (increment > OBJECT_rate) {
+ increment = OBJECT_rate;
+ }
+
+ // Randomize the distribution a bit, so that all
+ // objects are not transmitted at the same time.
+ // Allow the random number to vary over 20%
+ // (one-fifth) of the newly computed increment.
+ one_fifth_increment = (int)((increment / 5) + 0.5);
+//fprintf(stderr,"one_fifth_increment: %d\n", one_fifth_increment);
+
+ // Scale the random number from 0.0 to 1.0.
+ // Must convert at least one of the numbers to a
+ // float else randomize will be zero every time.
+ randomize = rand() / (float)RAND_MAX;
+//fprintf(stderr,"randomize: %f\n", randomize);
+
+ // Scale it to the range we want (0% to 20% of
+ // the interval)
+ randomize = randomize * one_fifth_increment;
+//fprintf(stderr,"scaled randomize: %f\n", randomize);
+
+ // Subtract it from the increment, use
+ // poor-man's rounding to turn the random number
+ // into an int (so we get the full range).
+ new_increment = increment - (int)(randomize + 0.5);
+ p_station->transmit_time_increment = (short)new_increment;
+
+//fprintf(stderr,"check_and_transmit_objects_items():Setting
+//tx_increment to %d:%s\n",
+// new_increment,
+// p_station->call_sign);
+
+ // Set the last transmit time into the object.
+ // Keep this based off the time the object was
+ // last created/modified/deleted, so that we
+ // don't end up with a bunch of them transmitted
+ // together.
+ p_station->last_transmit_time = p_station->last_transmit_time + new_increment;
+
+ // Here we need to re-assemble and re-transmit
+ // the object or item
+ // Check whether it is a "live" or "killed"
+ // object and vary the
+ // number of retransmits accordingly. Actually
+ // we should be able
+ // to keep retransmitting "killed" objects until
+ // they expire out of
+ // our station queue with no problems. If
+ // someone wants to ressurect
+ // the object we'll get new info into our struct
+ // and this function will
+ // ignore that object from then on, unless we
+ // again snatch control of
+ // the object.
+
+ // if signpost, area object, df object, or
+ // generic object
+ // check p_station->APRS_Symbol->aprs_type:
+ // APRS_OBJECT
+ // APRS_ITEM
+ // APRS_DF (looks like I didn't use this one
+ // when I implemented DF objects)
+
+ // Whether area, df, signpost.
+ // Check ->signpost for signpost data. Check
+ // ->df_color also.
+
+ // call_sign, sec_heard, coord_lon, coord_lat,
+ // packet_time, origin,
+ // aprs_symbol, pos_time, altitude, speed,
+ // course, bearing, NRQ,
+ // power_gain, signal_gain, signpost,
+ // station_time, station_time_type,
+ // comments, df_color
+ if (Create_object_item_tx_string(p_station, line, sizeof(line)) ) {
+
+ // Restore the original lat/long before we
+ // transmit the (possibly) new position.
+ //
+ p_station->coord_lon = x_long_save;
+ p_station->coord_lat = y_lat_save;
+
+//fprintf(stderr,"Transmitting: %s\n",line);
+ // Attempt to transmit the object/item again
+ if (object_tx_disable || transmit_disable) { // Send to loopback only
+ output_my_data(line,-1,0,1,0,NULL); // Local loopback only, not igating
+ }
+ else { // Send to all active tx-enabled interfaces
+ output_my_data(line,-1,0,0,0,NULL); // Transmit/loopback object data, not igating
+ }
+ }
+ else {
+//fprintf(stderr,"Create_object_item_tx_string returned a 0\n");
+ // Don't transmit it.
+ }
+ }
+ else { // Not time to transmit it yet
+//fprintf(stderr,"Not time to TX yet:
+//%s\t%s\t",p_station->call_sign,p_station->origin);
+//fprintf(stderr, "%ld secs to go\n", p_station->last_transmit_time
+//+ increment - time );
+ }
+ }
+ }
+//fprintf(stderr,"Exiting check_and_transmit_objects_items\n");
+}
+
+
+
+//////////////////// Draw CAD Objects Functions ////////////////////
+
+
+
+//#define CAD_DEBUG
+
+// Allocate a new vertice along the polygon. If the vertice is very
+// close to the first vertice, ask the operator if they wish to
+// close the polygon. If closing, ask for a raw probability?
+//
+// As each vertice is allocated, write it out to file? We'd then
+// need to edit the file and comment vertices out if we're deleting
+// vertices in memory. We could also write out an entire object
+// when we select "Close Polygon".
+//
+void CAD_vertice_allocate(long latitude, long longitude) {
+
+#ifdef CAD_DEBUG
+ fprintf(stderr,"Allocating a new vertice\n");
+#endif
+
+ // Check whether a line segment will cross another?
+
+ // We use the CAD_list_head variable, as it will be pointing to
+ // the top of the list, where the current object we're working
+ // on will be placed. Check whether that pointer is NULL
+ // though, just in case.
+ if (CAD_list_head) { // We have at least one object defined
+ VerticeRow *p_new;
+
+ // Allocate area to hold the vertice
+ p_new = (VerticeRow *)malloc(sizeof(VerticeRow));
+
+ if (!p_new) {
+ fprintf(stderr,"Couldn't allocate memory in CAD_vertice_allocate()\n");
+ return;
+ }
+
+ p_new->latitude = latitude;
+ p_new->longitude = longitude;
+
+ // Link it in at the top of the vertice chain.
+ p_new->next = CAD_list_head->start;
+ CAD_list_head->start = p_new;
+ }
+
+ // Call redraw_symbols outside this function, as
+ // verticies may be allocated both when loading lots of them from a file
+ // and when the user is drawing objects in the user interface
+ // Reload symbols/tracks/CAD objects
+ //redraw_symbols(da);
+}
+
+
+
+
+
+// Allocate a struct for a new object and add one vertice to it.
+// When do we name it and place the label? Assign probability to
+// it? We should keep a pointer to the current polygon we're
+// working on, so that we can modify it easily as we draw.
+// Actually, it'll be pointed to by CAD_list_head, so we already
+// have it!
+//
+// As each object is allocated, write it out to file?
+//
+// Compute a default label of date/time?
+//
+void CAD_object_allocate(long latitude, long longitude) {
+ CADRow *p_new;
+
+#ifdef CAD_DEBUG
+ fprintf(stderr,"Allocating a new CAD object\n");
+#endif
+
+ // Allocate memory and link it to the top of the singly-linked
+ // list of CADRow objects.
+ p_new = (CADRow *)malloc(sizeof(CADRow));
+
+ if (!p_new) {
+ fprintf(stderr,"Couldn't allocate memory in CAD_object_allocate()\n");
+ return;
+ }
+
+ // Fill in default values
+ p_new->creation_time = sec_now();
+ p_new->start = NULL;
+ p_new->line_color = colors[0x27];
+ p_new->line_type = 2; // LineOnOffDash;
+ p_new->line_width = 4;
+ p_new->computed_area = 0;
+ CAD_object_set_raw_probability(p_new,0.0,FALSE);
+ p_new->label_latitude = 0l;
+ p_new->label_longitude = 0l;
+ p_new->label[0] = '\0';
+ p_new->comment[0] = '\0';
+
+ // Allocate area to hold the first vertice
+
+#ifdef CAD_DEBUG
+ fprintf(stderr,"Allocating a new vertice\n");
+#endif
+
+ p_new->start = (VerticeRow *)malloc(sizeof(VerticeRow));
+ if (!p_new->start) {
+ fprintf(stderr,"Couldn't allocate memory in CAD_object_allocate(2)\n");
+ free(p_new);
+ return;
+ }
+
+ p_new->start->next = NULL;
+ p_new->start->latitude = latitude;
+ p_new->start->longitude = longitude;
+
+ // Hook it into the linked list of objects
+ p_new->next = CAD_list_head;
+ CAD_list_head = p_new;
+
+/*
+//
+// Note: It was too confusing to have these two dialogs close and
+// get redrawn when we click on the first vertice. The net result
+// is that we may have two dialogs move on top of the drawing area
+// to the spot we're trying to draw. Commented out this section due
+// to that. We'll get the two dialogs updated when we click on
+// either the DONE or CANCEL button on the Close Polygon dialog.
+//
+ // Here we update the erase cad objects dialog if it is up on
+ // the screen. We get rid of it and re-establish it, which will
+ // usually make the dialog move, but this is better than having
+ // it be out-of-date.
+ //
+ if (cad_erase_dialog != NULL) {
+ Draw_CAD_Objects_erase_dialog_close(da, NULL, NULL);
+ Draw_CAD_Objects_erase_dialog(da, NULL, NULL);
+ }
+
+ // Here we update the edit cad objects dialog by getting rid of
+ // it and then re-establishing it if it is active when we start.
+ // This will usually make the dialog move, but it's better than
+ // having it be out-of-date.
+ //
+ if (cad_list_dialog!=NULL) {
+ // Update the Edit CAD Objects list
+ Draw_CAD_Objects_list_dialog_close(da, NULL, NULL);
+ Draw_CAD_Objects_list_dialog(da, NULL, NULL);
+ }
+*/
+}
+
+
+
+
+
+// Delete all vertices associated with a CAD object and free the
+// memory. We really should pass a pointer to the object here
+// instead of a vertice, and set the start pointer to NULL when
+// done.
+//
+void CAD_vertice_delete_all(VerticeRow *v) {
+ VerticeRow *tmp;
+
+ // Call CAD_vertice_delete() for each vertice, then unlink this
+ // CAD object from the linked list and free its memory.
+
+ // Iterate through each vertice, deleting as we go
+ while (v != NULL) {
+ tmp = v;
+ v = v->next;
+ free(tmp);
+
+#ifdef CAD_DEBUG
+ fprintf(stderr,"Free'ing a vertice\n");
+#endif
+
+ }
+}
+
+
+
+
+
+// Delete _all_ CAD objects and all associated vertices. Loop
+// through the entire list of CAD objects, calling
+// CAD_vertice_delete_all() and then free'ing the CAD object. When
+// done, set the start pointer to NULL.
+//
+// We also need to wipe the persistent CAD object file.
+//
+void CAD_object_delete_all(void) {
+ CADRow *p = CAD_list_head;
+ CADRow *tmp;
+
+ while (p != NULL) {
+ VerticeRow *v = p->start;
+
+ // Remove all of the vertices
+ if (v != NULL) {
+
+ // Delete/free the vertices
+ CAD_vertice_delete_all(v);
+ }
+
+ // Remove the object and free its memory
+ tmp = p;
+ p = p->next;
+ free(tmp);
+
+#ifdef CAD_DEBUG
+ fprintf(stderr,"Free'ing an object\n");
+#endif
+
+ }
+
+ // Zero the CAD linked list head
+ CAD_list_head = NULL;
+}
+
+
+
+
+
+// Remove a vertice, thereby joining two segments into one?
+//
+// Recompute the raw probability if need be, or make it an invalid
+// value so that we know we need to recompute it.
+//
+//void CAD_vertice_delete(CADrow *object) {
+// VerticeRow *v = object->start;
+
+ // Unlink the vertice from the linked list and free its memory.
+ // Allow removing a vertice in the middle or end of a chain. If
+ // removing the vertice turns the polygon into an open polygon,
+ // alert the user of that fact and ask if they wish to close it.
+//}
+
+
+
+
+
+/* Test to see if a CAD object of the name (label) provided exists.
+ Parameter: label, the label text to be checked.
+ Returns 0 if no CAD object with a name matching the
+ provided name is found.
+ Returns 1 if a CAD object with a name matching the
+ provided name is found. */
+int exists_CAD_object_by_label(char *label) {
+ CADRow *object_pointer = CAD_list_head;
+ int result = 0; // function return value
+ int done = 0; // flag to stop loop when a match is found
+ while (object_pointer != NULL && done==0) {
+ if (strcmp(object_pointer->label,label)==0) {
+ // a matching name was found
+ result = 1;
+ done = 1;
+ }
+ object_pointer = object_pointer->next;
+ }
+ return result;
+}
+
+
+
+
+
+/* Counts to see how many CAD objects of the name (label) provided exist.
+ Parameter: label, the label text to be checked.
+ Returns 0 if no CAD object with a name matching the
+ provided name is found.
+ Returns count of the number of CAD objects with a matching label if
+ one or more is found. */
+int count_CAD_object_with_matching_label(char *label) {
+ CADRow *object_pointer = CAD_list_head;
+ int result = 0;
+ while (object_pointer != NULL) {
+ // iterate through all CAD objects
+ if (strcmp(object_pointer->label,label)==0) {
+ // a matching name was found
+ result++;
+ object_pointer = object_pointer->next;
+ }
+ }
+ return result;
+}
+
+
+
+
+
+/* Delete one CAD object and all of its vertices. */
+void CAD_object_delete(CADRow *object) {
+ CADRow *all_objects_ptr = CAD_list_head;
+ CADRow *previous_object_ptr = CAD_list_head;
+ VerticeRow *v = object->start;
+ int done = 0;
+
+#ifdef CAD_DEBUG
+ fprintf(stderr,"Deleting CAD object %s\n",object->label);
+#endif
+ // check to see if the object we were given was the first object
+ if (object==all_objects_ptr) {
+#ifdef CAD_DEBUG
+ fprintf(stderr,"Deleting first CAD object %s\n",object->label);
+#endif
+ CAD_vertice_delete_all(v); // Frees the memory also
+
+ // Unlink the object from the chain and free the memory.
+ CAD_list_head = object->next; // Unlink
+ free(object); // Free the object memory
+ }
+ else {
+#ifdef CAD_DEBUG
+ fprintf(stderr,"Deleting other than first CAD object %s\n",object->label);
+#endif
+ // walk through the list and delete the object when found
+ while (all_objects_ptr != NULL && done==0) {
+ if (object==all_objects_ptr) {
+ v = object->start;
+ CAD_vertice_delete_all(v);
+ previous_object_ptr->next = object->next;
+ free(object);
+ done = 1;
+ }
+ else {
+ all_objects_ptr = all_objects_ptr->next;
+ }
+ }
+ }
+}
+
+
+
+
+
+// Split an existing CAD object into two objects. Can we trigger
+// this by drawing a line across a closed polygon?
+void CAD_object_split_existing(void) {
+}
+
+// Join two existing polygons into one larger polygon.
+void CAD_object_join_two(void) {
+}
+
+// Move an entire CAD object, with all it's vertices, somewhere
+// else. Move the label along with it as well.
+void CAD_object_move(void) {
+}
+
+
+
+
+
+// Determine if a CAD object is a closed polygon.
+//
+// Takes a pointer to a CAD object as an argument.
+// Returns 1 if the object is closed.
+// Returns 0 if the object is not closed.
+//
+int is_CAD_object_open(CADRow *cad_object) {
+ VerticeRow *vertex_pointer;
+ int vertex_count = 0;
+ int result = 1;
+ int atleast_one_different = 0;
+ long start_lat, start_long;
+ long stop_lat, stop_long;
+
+ vertex_pointer = cad_object->start;
+ if (vertex_pointer!=NULL) {
+ // greater than zero points, get first point.
+ start_lat = vertex_pointer->latitude;
+ start_long = vertex_pointer->longitude;
+ stop_lat = vertex_pointer->latitude;
+ stop_long = vertex_pointer->longitude;
+ vertex_pointer = vertex_pointer->next;
+ while (vertex_pointer != NULL) {
+ //greater than one point, get current point.
+ stop_lat = vertex_pointer->latitude;
+ stop_long = vertex_pointer->longitude;
+ if (stop_lat!=start_lat || stop_long!=start_long)
+ atleast_one_different = 1;
+ vertex_pointer = vertex_pointer->next;
+ vertex_count++;
+ }
+ if (vertex_count>2 && start_lat==stop_lat && start_long==stop_long && atleast_one_different > 0) {
+ // more than two points, and they aren't in the same place
+ result = 0;
+ }
+ }
+ return result;
+}
+
+
+
+
+
+// Compute the area enclosed by a CAD object. Check that it is a
+// closed, non-intersecting polygon first.
+//
+double CAD_object_compute_area(CADRow *CAD_list_head) {
+ VerticeRow *tmp;
+ double area;
+ char temp_course[20];
+ // Walk the linked list again, computing the area of the
+ // polygon. Greene's Theorem is how we can compute the area of
+ // a polygon using the vertices. We could also compute whether
+ // we're going clockwise or counter-clockwise around the polygon
+ // using Greene's Theorem. In fact I think we do that for
+ // Shapefile hole polygons. Remember that here we're walking
+ // around the vertices backwards due to the ordering of the
+ // list. Shouldn't matter for our purposes though.
+ //
+ area = 0.0;
+ tmp = CAD_list_head->start;
+ if (is_CAD_object_open(CAD_list_head)==0) {
+ // Only compute the area if CAD object is a closed polygon,
+ // that is, not an open polygon.
+ while (tmp->next != NULL) {
+ double dx0, dy0, dx1, dy1;
+
+ // Because lat/long units can vary drastically w.r.t. real
+ // units, we need to multiply the terms by the real units in
+ // order to get real area.
+
+ // Compute real distances from a fixed point. Convert to
+ // the current measurement units. We'll use the starting
+ // vertice as our fixed point.
+ //
+ dx0 = calc_distance_course(
+ CAD_list_head->start->latitude,
+ CAD_list_head->start->longitude,
+ CAD_list_head->start->latitude,
+ tmp->longitude,
+ temp_course,
+ sizeof(temp_course));
+
+ if (tmp->longitude < CAD_list_head->start->longitude)
+ dx0 = -dx0;
+
+ dy0 = calc_distance_course(
+ CAD_list_head->start->latitude,
+ CAD_list_head->start->longitude,
+ tmp->latitude,
+ CAD_list_head->start->longitude,
+ temp_course,
+ sizeof(temp_course));
+
+ if (tmp->latitude < CAD_list_head->start->latitude)
+ dx0 = -dx0;
+
+ dx1 = calc_distance_course(
+ CAD_list_head->start->latitude,
+ CAD_list_head->start->longitude,
+ CAD_list_head->start->latitude,
+ tmp->next->longitude,
+ temp_course,
+ sizeof(temp_course));
+
+ if (tmp->next->longitude < CAD_list_head->start->longitude)
+ dx0 = -dx0;
+
+ dy1 = calc_distance_course(
+ CAD_list_head->start->latitude,
+ CAD_list_head->start->longitude,
+ tmp->next->latitude,
+ CAD_list_head->start->longitude,
+ temp_course,
+ sizeof(temp_course));
+
+ // Add the minus signs back in, if any
+ if (tmp->longitude < CAD_list_head->start->longitude)
+ dx0 = -dx0;
+ if (tmp->latitude < CAD_list_head->start->latitude)
+ dy0 = -dy0;
+ if (tmp->next->longitude < CAD_list_head->start->longitude)
+ dx1 = -dx1;
+ if (tmp->next->latitude < CAD_list_head->start->latitude)
+ dy1 = -dy1;
+
+ // Greene's Theorem: Summation of the following, then
+ // divide by two:
+ //
+ // A = X Y - X Y
+ // i i i+1 i+1 i
+ //
+ area += (dx0 * dy1) - (dx1 * dy0);
+
+ tmp = tmp->next;
+ }
+ area = 0.5 * area;
+ }
+
+ if (area < 0.0)
+ area = -area;
+
+ return area;
+
+
+}
+
+
+
+
+
+// Allocate a label for an object, and place it according to the
+// user's requests. Keep track of where from the origin to place
+// the label, font to use, color, etc.
+void CAD_object_allocate_label(void) {
+}
+
+
+
+
+
+// Set the probability for an object. We should probably allocate
+// the raw probability to small "buckets" within the closed polygon.
+// This will allow us to split/join polygons later without messing
+// up the probablity assigned to each area originally. Check that
+// it is a closed polygon first.
+// if as_percent==TRUE, then probability is treated as a percent
+// (expected to be a value between 0 and 100).
+// otherwise, then probability is treated as a probability
+// (expected to be a value between 0 and 1).
+//
+void CAD_object_set_raw_probability(CADRow *object_ptr, float probability, int as_percent) {
+ // initial implementation just assigns a single raw probability to the whole polygon.
+ // internal storage is as a probability between 0 and 1
+ // users will usually want to manipulate this as a percent (between 0 and 100)
+ // thus the get and set functions are aware of both internal storage and
+ // the user's request and return an appropriately scaled value.
+ if (as_percent==TRUE) {
+ // convert from a percent to a probability between 0 and 1
+ object_ptr->raw_probability = (probability/100.00);
+ }
+ else {
+ // treat as in internal storage form
+ object_ptr->raw_probability = probability;
+ }
+}
+
+
+
+
+
+// Get the raw probability for an object. Sum up the raw
+// probability "buckets" contained within the closed polygon. Check
+// that it _is_ a closed polygon first.
+//
+float CAD_object_get_raw_probability(CADRow *object_ptr, int as_percent) {
+ float result = 0.0;
+ // not checking yet for closure
+ if (object_ptr != NULL) {
+ // initial implementation returns just the single raw probability
+ result = object_ptr->raw_probability;
+ if (as_percent > 0) {
+ // raw probability is a probability between 0 an 1,
+ // this may be desired as a percent.
+ result = result * 100;
+ }
+ }
+#ifdef CAD_DEBUG
+ fprintf(stderr,"Getting Probability: %01.5f\n",result);
+#endif
+ return result;
+}
+
+
+
+
+
+void CAD_object_set_line_width(void) {
+}
+
+
+
+
+
+void CAD_object_set_color(void) {
+}
+
+
+
+
+
+void CAD_object_set_linetype(void) {
+}
+
+
+
+
+
+// Used to break a line segment into two. Can then move the vertice
+// if needed. Recompute the raw probability if need be, or make it
+// an invalid value so that we know we need to recompute it.
+void CAD_vertice_insert_new(void) {
+ // Check whether a line segment will cross another?
+}
+
+
+
+
+
+// Move an existing vertice. Recompute the raw probability if need
+// be, or make it an invalid value so that we know we need to
+// recompute it.
+void CAD_vertice_move(void) {
+ // Check whether a line segment will cross another?
+}
+
+
+
+
+
+// Set the location for drawing the label of an area to the center
+// of the area. Takes a pointer to a CAD object as a parameter.
+// Sets the label_latitude and label_longitude attributes of the CAD
+// object to the center of the region described by the vertices of
+// the object.
+//
+void CAD_object_set_label_at_centroid(CADRow *CAD_object) {
+ // *** current implementation approximates the center as the
+ // average of the largest and smallest of each of latitude
+ // and longitude rather than correctly computing the centroid,
+ // that is, it places the label at the centroid of a bounding
+ // box for the area. ***
+ // We can't use a simple x=sum(x)/n, y=sum(y)/n as the
+ // points on the outline shouldn't be weighted equally.
+ // Ideal would be to place the label at the central point within
+ // the area itslef, apparently this is a hard prbolem.
+ // alternative would be to use the centroid, which like the
+ // average of maximum and minimum values may lie outside of
+ // the area.
+ VerticeRow *vertex_pointer;
+ long min_lat, min_long;
+ long max_lat, max_long;
+ // Walk the linked list and compute the centroid of the bounding box.
+ vertex_pointer = CAD_object->start;
+ min_lat = 0.0;
+ min_long = 0.0;
+
+ // Set the latitude and longitude of the label to the
+ // centroid of the bounding box.
+ // Start by setting lat and long of label to first point.
+ CAD_object->label_latitude = vertex_pointer->latitude;
+ CAD_object->label_longitude = vertex_pointer->longitude;
+ if (vertex_pointer != NULL) {
+ // Iterate through the vertices and calculate the center x and y position
+ // based on an average of the largest and smallest latitudes and longitudes.
+ min_lat = vertex_pointer->latitude;
+ min_long = vertex_pointer->longitude;
+ max_lat = vertex_pointer->latitude;
+ max_long = vertex_pointer->longitude;
+ while (vertex_pointer != NULL) {
+ if (vertex_pointer->next != NULL) {
+ if (vertex_pointer->longitude < min_long )
+ min_long = vertex_pointer->longitude;
+ if (vertex_pointer->latitude < min_lat )
+ min_lat = vertex_pointer->latitude;
+ if (vertex_pointer->longitude > max_long )
+ max_long = vertex_pointer->longitude;
+ if (vertex_pointer->latitude > max_lat )
+ max_lat = vertex_pointer->latitude;
+ }
+ vertex_pointer = vertex_pointer->next;
+ }
+ CAD_object->label_latitude = (max_lat + min_lat)/2.0;
+ CAD_object->label_longitude = (max_long + min_long)/2.0;
+ }
+}
+
+
+
+
+
+// This is the callback for the CAD objects parameters dialog. It
+// takes the values entered in the dialog and stores them in the
+// most recently created object.
+//
+void Set_CAD_object_parameters (Widget widget,
+ XtPointer clientData,
+ XtPointer calldata) {
+
+ float probability = 0.0;
+ CADRow *target_object = NULL;
+ int cb_selected;
+ // need to find out object to edit from clientData rather than
+ // using the first object in list as the one to edit.
+ //target_object = CAD_list_head;
+ target_object = (CADRow *)clientData;
+
+ // set label, comment, and probability for area
+ xastir_snprintf(target_object->label,
+ sizeof(target_object->label),
+ "%s", XmTextGetString(cad_label_data)
+ );
+ xastir_snprintf(target_object->comment,
+ sizeof(target_object->comment),
+ "%s", XmTextGetString(cad_comment_data)
+ );
+ // Is more error checking needed? atof appears to correctly handle
+ // empty input, reasonable probability values, and text (0.00).
+ // User side probabilities are expressed as percent.
+ probability = atof(XmTextGetString(cad_probability_data));
+ CAD_object_set_raw_probability(target_object, probability, TRUE);
+
+ // Use the selected line type, default is dashed
+ cb_selected = FALSE;
+
+#ifdef USE_COMBO_BOX
+ XtVaGetValues(cad_line_style_data,
+ XmNselectedPosition,
+ &cb_selected,
+ NULL);
+#else
+ cb_selected = clsd_value;
+#endif // USE_COMBO_BOX
+
+ if (cb_selected) {
+ target_object->line_type = cb_selected;
+ }
+ else {
+ target_object->line_type = 2; // LineOnOffDash
+ }
+
+ if (cad_list_dialog) {
+ Update_CAD_objects_list_dialog();
+ }
+
+ // close object_parameters dialog
+ XtPopdown(cad_dialog);
+ XtDestroyWidget(cad_dialog);
+ cad_dialog = (Widget)NULL;
+
+ Save_CAD_Objects_to_file();
+ // Reload symbols/tracks/CAD objects so that object name will show on map.
+ redraw_symbols(da);
+
+ // Here we update the erase cad objects dialog if it is up on
+ // the screen. We get rid of it and re-establish it, which will
+ // usually make the dialog move, but this is better than having
+ // it be out-of-date.
+ //
+ if (cad_erase_dialog != NULL) {
+ Draw_CAD_Objects_erase_dialog_close(widget,clientData,calldata);
+ Draw_CAD_Objects_erase_dialog(widget,clientData,calldata);
+ }
+
+ // Here we update the edit cad objects dialog by getting rid of
+ // it and then re-establishing it if it is active when we start.
+ // This will usually make the dialog move, but it's better than
+ // having it be out-of-date.
+ //
+ if (cad_list_dialog!=NULL) {
+ // Update the Edit CAD Objects list
+ Draw_CAD_Objects_list_dialog_close(widget, clientData, calldata);
+ Draw_CAD_Objects_list_dialog(widget, clientData, calldata);
+ }
+}
+
+
+
+
+
+// Update the list of existing CAD objects on the cad list dialog to
+// reflect the current list of objects.
+//
+void Update_CAD_objects_list_dialog() {
+ CADRow *object_ptr = CAD_list_head;
+ int counter = 1;
+ XmString cb_item;
+
+ if (list_of_existing_CAD_objects_edit!=NULL && cad_list_dialog) {
+ XmListDeleteAllItems(list_of_existing_CAD_objects_edit);
+
+ // iterate through list of objects to populate scrolled list
+ while (object_ptr != NULL) {
+
+ // If no label, use the string "<Empty Label>" instead
+ if (object_ptr->label == NULL || object_ptr->label[0] == '\0')
+ cb_item = XmStringCreateLtoR("<Empty Label>", XmFONTLIST_DEFAULT_TAG);
+ else
+ cb_item = XmStringCreateLtoR(object_ptr->label, XmFONTLIST_DEFAULT_TAG);
+
+ XmListAddItem(list_of_existing_CAD_objects_edit,
+ cb_item,
+ counter);
+ counter++;
+ XmStringFree(cb_item);
+ object_ptr = object_ptr->next;
+ }
+ }
+}
+
+
+
+
+
+void close_object_params_dialog(Widget widget, XtPointer clientData, XtPointer calldata) {
+ XtPopdown(cad_dialog);
+ XtDestroyWidget(cad_dialog);
+ cad_dialog = (Widget)NULL;
+
+ // Here we update the erase cad objects dialog if it is up on
+ // the screen. We get rid of it and re-establish it, which will
+ // usually make the dialog move, but this is better than having
+ // it be out-of-date.
+ //
+ if (cad_erase_dialog != NULL) {
+ Draw_CAD_Objects_erase_dialog_close(widget,clientData,calldata);
+ Draw_CAD_Objects_erase_dialog(widget,clientData,calldata);
+ }
+
+ // Here we update the edit cad objects dialog by getting rid of
+ // it and then re-establishing it if it is active when we start.
+ // This will usually make the dialog move, but it's better than
+ // having it be out-of-date.
+ //
+ if (cad_list_dialog!=NULL) {
+ // Update the Edit CAD Objects list
+ Draw_CAD_Objects_list_dialog_close(widget, clientData, calldata);
+ Draw_CAD_Objects_list_dialog(widget, clientData, calldata);
+ }
+}
+
+
+#ifndef USE_COMBO_BOX
+void clsd_menuCallback(Widget widget, XtPointer ptr, XtPointer callData) {
+ //XmPushButtonCallbackStruct *data = (XmPushButtonCallbackStruct *)callData;
+ XtPointer userData;
+
+ XtVaGetValues(widget, XmNuserData, &userData, NULL);
+
+ //clsd_menu is zero based, cad_line_style_data constants are one based.
+ clsd_value = (int)userData + 1;
+ if (debug_level & 1)
+ fprintf(stderr,"Selected value on cad line type pulldown: %d\n",clsd_value);
+}
+#endif // !USE_COMBO_BOX
+
+
+
+// Create a dialog to obtain information about a newly created CAD
+// object from the user. Values of probability, name, and comment
+// are initially blank. Takes as a parameter a string describing
+// the area of the object. There is a single button with a callback
+// to Set_CAD_object_parameters, which stores values from the dialog
+// in the object's struct. Should be generalized to allow editing
+// of a pre-existing CAD object (except for the name). Parameter
+// should be a pointer to the object.
+//
+void Set_CAD_object_parameters_dialog(char *area_description, CADRow *CAD_object) {
+ Widget cad_pane, cad_form,
+ cad_label,
+ cad_comment,
+ cad_probability,
+ cad_line_style,
+ button_done,
+ button_cancel;
+ char probability_string[5];
+ int i; // loop counters
+ //XmString cb_item; // used to create picklist of line styles
+ XmString cb_items[3];
+#ifndef USE_COMBO_BOX
+ Widget clsd_menuPane;
+ Widget clsd_button;
+ Widget clsd_buttons[3];
+ Widget clsd_menu;
+ char buf[18];
+ int x;
+ Arg args[12]; // available for XtSetArguments
+#endif // !USE_COMBO_BOX
+ Widget clsd_widget;
+
+
+ if (cad_dialog) {
+ (void)XRaiseWindow(XtDisplay(cad_dialog), XtWindow(cad_dialog));
+ }
+ else {
+
+ // Area Object"
+ cad_dialog = XtVaCreatePopupShell(langcode("CADPUD001"),
+ xmDialogShellWidgetClass,
+ appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ cad_pane = XtVaCreateWidget("Set_Del_Object pane",
+ xmPanedWindowWidgetClass,
+ cad_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ cad_form = XtVaCreateWidget("Set_Del_Object ob_form",
+ xmFormWidgetClass,
+ cad_pane,
+ XmNfractionBase, 2,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+ // Area of polygon, already scaled and internationalized.
+ cad_label = XtVaCreateManagedWidget(area_description,
+ xmLabelWidgetClass,
+ cad_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // "Area Label:"
+ cad_label = XtVaCreateManagedWidget(langcode("CADPUD002"),
+ xmLabelWidgetClass,
+ cad_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 50,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // label text field
+ cad_label_data = XtVaCreateManagedWidget("Set_Del_Object name_data",
+ xmTextFieldWidgetClass,
+ cad_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 20,
+ XmNmaxLength, CAD_LABEL_MAX_SIZE - 1,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 50,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, cad_label,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+ // "Comment"
+ cad_comment = XtVaCreateManagedWidget(langcode("CADPUD003"),
+ xmLabelWidgetClass,
+ cad_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 90,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // comment text field
+ cad_comment_data = XtVaCreateManagedWidget("Set_Del_Object name_data",
+ xmTextFieldWidgetClass,
+ cad_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 40,
+ XmNmaxLength, CAD_COMMENT_MAX_SIZE - 1,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 90,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, cad_comment,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+ // "Probability (as %)"
+ cad_probability = XtVaCreateManagedWidget(langcode("CADPUD004"),
+ xmLabelWidgetClass,
+ cad_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 130,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // probability field
+ cad_probability_data = XtVaCreateManagedWidget("Set_Del_Object name_data",
+ xmTextFieldWidgetClass,
+ cad_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 5,
+ XmNmaxLength, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 130,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, cad_probability,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+ // Boundary Line Type
+ cad_line_style = XtVaCreateManagedWidget("Line Type:",
+ xmLabelWidgetClass,
+ cad_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, cad_probability_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // lesstif as of 0.95 in 2008 doesn't fully support combo boxes
+ //
+ // Need to replace combo boxes with a pull down menu when lesstif is used.
+ // See xpdf's XPDFViewer.cc/XPDFViewer.h for an example.
+ //cb_items = (XmString *) XtMalloc ( sizeof (XmString) * 4 );
+ // Solid
+ cb_items[0] = XmStringCreateLtoR( langcode("CADPUD012"), XmFONTLIST_DEFAULT_TAG);
+ // Dashed
+ cb_items[1] = XmStringCreateLtoR( langcode("CADPUD013"), XmFONTLIST_DEFAULT_TAG);
+ // Double Dash
+ cb_items[2] = XmStringCreateLtoR( langcode("CADPUD014"), XmFONTLIST_DEFAULT_TAG);
+
+ clsd_widget = cad_line_style_data;
+
+#ifdef USE_COMBO_BOX
+ // Combo box to pick line style
+ cad_line_style_data = XtVaCreateManagedWidget("select line style",
+ xmComboBoxWidgetClass,
+ cad_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, cad_probability_data,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, cad_line_style,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNcomboBoxType, XmDROP_DOWN_LIST,
+ XmNpositionMode, XmONE_BASED,
+ XmNvisibleItemCount, 3,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmComboBoxAddItem(cad_line_style_data,cb_items[0],1,1);
+ XmComboBoxAddItem(cad_line_style_data,cb_items[1],2,1);
+ XmComboBoxAddItem(cad_line_style_data,cb_items[2],3,1);
+
+ clsd_widget = cad_line_style_data;
+#else
+ // menu replacement for combo box when using lesstif
+ x = 0;
+ XtSetArg(args[x], XmNmarginWidth, 0); ++x;
+ XtSetArg(args[x], XmNmarginHeight, 0); ++x;
+ XtSetArg(args[x], XmNfontList, fontlist1); ++x;
+ clsd_menuPane = XmCreatePulldownMenu(cad_form,"sddd_menuPane", args, x);
+ //sddd_menu is zero based, constants for database types are one based.
+ //sddd_value is set to match constants in callback.
+ for (i=0;i<3;i++) {
+ x = 0;
+ XtSetArg(args[x], XmNlabelString, cb_items[i]); x++;
+ XtSetArg(args[x], XmNuserData, (XtPointer)i); x++;
+ XtSetArg(args[x], XmNfontList, fontlist1); ++x;
+ sprintf(buf,"button%d",i);
+ clsd_button = XmCreatePushButton(clsd_menuPane, buf, args, x);
+ XtManageChild(clsd_button);
+ XtAddCallback(clsd_button, XmNactivateCallback, clsd_menuCallback, Set_CAD_object_parameters_dialog);
+ clsd_buttons[i] = clsd_button;
+ }
+ x = 0;
+ XtSetArg(args[x], XmNleftAttachment, XmATTACH_WIDGET); ++x;
+ XtSetArg(args[x], XmNleftWidget, cad_line_style); ++x;
+ XtSetArg(args[x], XmNtopAttachment, XmATTACH_WIDGET); ++x;
+ XtSetArg(args[x], XmNtopWidget, cad_probability_data); ++x;
+ XtSetArg(args[x], XmNmarginWidth, 0); ++x;
+ XtSetArg(args[x], XmNmarginHeight, 0); ++x;
+ XtSetArg(args[x], XmNtopOffset, 5); ++x;
+ XtSetArg(args[x], XmNleftOffset, 10); ++x;
+ XtSetArg(args[x], XmNsubMenuId, clsd_menuPane); ++x;
+ XtSetArg(args[x], XmNfontList, fontlist1); ++x;
+ clsd_menu = XmCreateOptionMenu(cad_form, "sddd_Menu", args, x);
+ XtManageChild(clsd_menu);
+ clsd_value = 2; // set a default value (line on off dash)
+ clsd_widget = clsd_menu;
+#endif // USE_COMBO_BOX
+ // free up space from combo box strings
+ for (i=0;i<3;i++) {
+ XmStringFree(cb_items[i]);
+ }
+
+
+ // "OK"
+ button_done = XtVaCreateManagedWidget(langcode("CADPUD005"),
+ xmPushButtonGadgetClass,
+ cad_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, clsd_widget,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Cancel"
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),
+ xmPushButtonGadgetClass,
+ cad_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, clsd_widget,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ // callback depends on whether this is a new or old object
+ //XtAddCallback(button_done, XmNactivateCallback, Set_CAD_object_parameters, Set_CAD_object_parameters_dialog);
+
+ if (CAD_object!=NULL) {
+ XtAddCallback(button_done, XmNactivateCallback, Set_CAD_object_parameters, (XtPointer *)CAD_object);
+ }
+ else {
+ // called to get information for a newly created cad object
+ // pass pointer to the head of the list, which contains
+ // the most recently created cad object.
+ XtAddCallback(button_done, XmNactivateCallback, Set_CAD_object_parameters, CAD_list_head);
+ }
+
+ XtAddCallback(button_cancel, XmNactivateCallback, close_object_params_dialog, NULL);
+
+ pos_dialog(cad_dialog);
+ XmInternAtom(XtDisplay(cad_dialog),"WM_DELETE_WINDOW", FALSE);
+
+ XtManageChild(cad_form);
+ XtManageChild(cad_pane);
+
+ XtPopup(cad_dialog,XtGrabNone);
+ } // end if ! caddialog
+
+ if (CAD_object!=NULL) {
+ XmString tempSelection;
+
+ // given an existing object, fill form with its information
+ XmTextFieldSetString(cad_label_data,CAD_object->label);
+ XmTextFieldSetString(cad_comment_data,CAD_object->comment);
+ xastir_snprintf(probability_string,
+ sizeof(probability_string),
+ "%01.2f",
+ CAD_object_get_raw_probability(CAD_object,1));
+ XmTextFieldSetString(cad_probability_data,probability_string);
+
+ switch(CAD_object->line_type) {
+
+ case 1: // Solid
+#ifndef USE_COMBO_BOX
+ i = 0;
+#endif // !USE_COMBO_BOX
+ tempSelection = XmStringCreateLtoR( langcode("CADPUD012"),
+ XmFONTLIST_DEFAULT_TAG);
+ break;
+
+ case 2: // Dashed
+#ifndef USE_COMBO_BOX
+ i = 1;
+#endif // !USE_COMBO_BOX
+ tempSelection = XmStringCreateLtoR( langcode("CADPUD013"),
+ XmFONTLIST_DEFAULT_TAG);
+ break;
+
+ case 3: // Double Dash
+#ifndef USE_COMBO_BOX
+ i = 2;
+#endif // !USE_COMBO_BOX
+ tempSelection = XmStringCreateLtoR( langcode("CADPUD014"),
+ XmFONTLIST_DEFAULT_TAG);
+ break;
+
+ default:
+#ifndef USE_COMBO_BOX
+ i = 1;
+#endif // !USE_COMBO_BOX
+ tempSelection = XmStringCreateLtoR( langcode("CADPUD013"),
+ XmFONTLIST_DEFAULT_TAG);
+ break;
+ }
+#ifdef USE_COMBO_BOX
+ XmComboBoxSelectItem(cad_line_style_data, tempSelection);
+#else
+ clsd_value = i+1;
+ //clsd_menu is zero based, line types are one based.
+ //clsd_value matches line types (1-3).
+ XtVaSetValues(clsd_menu, XmNmenuHistory, clsd_buttons[i], NULL);
+#endif // USE_COMBO_BOX
+ XmStringFree(tempSelection);
+ }
+}
+
+
+
+
+
+static Cursor cs_CAD = (Cursor)NULL;
+
+void free_cs_CAD(void)
+{
+ XFreeCursor(XtDisplay(da), cs_CAD);
+ cs_CAD = (Cursor)NULL;
+}
+
+// This is the callback for the Draw togglebutton
+//
+void Draw_CAD_Objects_mode( /*@unused@*/ Widget widget,
+ XtPointer clientData,
+ XtPointer callData) {
+
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+
+ if(state->set) {
+ draw_CAD_objects_flag = 1;
+
+ // Create the "pencil" cursor so we know what mode we're in.
+ //
+ if(!cs_CAD) {
+ cs_CAD=XCreateFontCursor(XtDisplay(da),XC_pencil);
+ atexit(free_cs_CAD);
+ }
+
+ // enable the close polygon button on an open CAD menu
+ if (CAD_close_polygon_menu_item) {
+ XtSetSensitive(CAD_close_polygon_menu_item,TRUE);
+ }
+
+ (void)XDefineCursor(XtDisplay(da),XtWindow(da),cs_CAD);
+ (void)XFlush(XtDisplay(da));
+
+ draw_CAD_objects_flag = 1;
+ polygon_last_x = -1; // Invalid position
+ polygon_last_y = -1; // Invalid position
+ }
+ else {
+ draw_CAD_objects_flag = 0;
+ polygon_last_x = -1; // Invalid position
+ polygon_last_y = -1; // Invalid position
+
+ Save_CAD_Objects_to_file();
+
+ // Remove the special "pencil" cursor.
+ (void)XUndefineCursor(XtDisplay(da),XtWindow(da));
+ (void)XFlush(XtDisplay(da));
+
+ // disable the close polygon button on an open CAD menu.
+ if (CAD_close_polygon_menu_item) {
+ XtSetSensitive(CAD_close_polygon_menu_item,FALSE);
+ }
+ }
+}
+
+
+
+
+
+// Called when we complete a new CAD object. Save the object to
+// disk so that we can recover in the case of a crash or power
+// failure. Save any old file to a backup file. Perhaps write them
+// to numbered backup files so that we keep several on-hand?
+//
+void Save_CAD_Objects_to_file(void) {
+ FILE *f;
+ char *file;
+ CADRow *object_ptr = CAD_list_head;
+ char temp_file_path[MAX_VALUE];
+
+ fprintf(stderr,"Saving CAD objects to file\n");
+
+ // Save in ~/.xastir/config/CAD_object.log
+ file = get_user_base_dir("config/CAD_object.log", temp_file_path, sizeof(temp_file_path));
+ f = fopen(file,"w+");
+
+ if (f == NULL) {
+ fprintf(stderr,
+ "Couldn't open config/CAD_object.log file for writing!\n");
+ return;
+ }
+
+ while (object_ptr != NULL) {
+ VerticeRow *vertice = object_ptr->start;
+
+ // Write out the main object info:
+ fprintf(f,"\nCAD_Object\n");
+ fprintf(f,"creation_time: %lu\n",(unsigned long)object_ptr->creation_time);
+ fprintf(f,"line_color: %d\n",object_ptr->line_color);
+ fprintf(f,"line_type: %d\n",object_ptr->line_type);
+ fprintf(f,"line_width: %d\n",object_ptr->line_width);
+ fprintf(f,"computed_area: %f\n",object_ptr->computed_area);
+ fprintf(f,"raw_probability: %f\n",CAD_object_get_raw_probability(object_ptr,TRUE));
+ fprintf(f,"label_latitude: %lu\n",object_ptr->label_latitude);
+ fprintf(f,"label_longitude: %lu\n",object_ptr->label_longitude);
+ fprintf(f,"label: %s\n",object_ptr->label);
+ if (strlen(object_ptr->comment)>1) {
+ fprintf(f,"comment: %s\n",object_ptr->comment);
+ }
+ else {
+ fprintf(f,"comment: NULL\n");
+ }
+
+ // Iterate through the vertices:
+ while (vertice != NULL) {
+
+ fprintf(f,"Vertice: %lu %lu\n",
+ vertice->latitude,
+ vertice->longitude);
+
+ vertice = vertice->next;
+ }
+ object_ptr = object_ptr->next;
+ }
+ (void)fclose(f);
+}
+
+
+
+
+
+// Called by main() when we start Xastir. Restores CAD objects
+// created in earlier Xastir sessions.
+//
+void Restore_CAD_Objects_from_file(void) {
+ FILE *f;
+ char *file;
+ char line[MAX_FILENAME];
+ char temp_file_path[MAX_VALUE];
+#ifdef CAD_DEBUG
+ fprintf(stderr,"Restoring CAD objects from file\n");
+#endif
+
+ // Restore from ~/.xastir/config/CAD_object.log
+ file = get_user_base_dir("config/CAD_object.log", temp_file_path, sizeof(temp_file_path));
+ f = fopen(file,"r");
+
+ if (f == NULL) {
+#ifdef CAD_DEBUG
+ fprintf(stderr,
+ "Couldn't open config/CAD_object.log file for reading!\n");
+#endif
+ return;
+ }
+
+ while (!feof (f)) {
+ (void)get_line(f, line, MAX_FILENAME);
+ if (strncasecmp(line,"CAD_Object",10) == 0) {
+ // Found a new CAD Object declaration!
+
+ //fprintf(stderr,"Found CAD_Object\n");
+
+ // Malloc a new object, add it to the linked list, start
+ // filling in the fields.
+ //
+ // This gives us a default object with one vertice. We
+ // can replace all of the fields in it as we parse them.
+ CAD_object_allocate(0l, 0l);
+
+ // Remove the one vertice from the newly allocated
+ // object so that we don't end up with one too many
+ // vertices when all done.
+ CAD_vertice_delete_all(CAD_list_head->start);
+ CAD_list_head->start = NULL;
+
+ }
+ else if (strncasecmp(line,"creation_time:",14) == 0) {
+ //fprintf(stderr,"Found creation_time:\n");
+ unsigned long temp_time;
+ if (1 != sscanf(line+15, "%lu",&temp_time)) {
+ fprintf(stderr,"Restore_CAD_Objects_from_file:sscanf parsing error [creation_time]\n");
+ }
+ CAD_list_head->creation_time=(time_t)temp_time;
+ }
+ else if (strncasecmp(line,"line_color:",11) == 0) {
+ //fprintf(stderr,"Found line_color:\n");
+ if (1 != sscanf(line+12,"%d",
+ &CAD_list_head->line_color)) {
+ fprintf(stderr,"Restore_CAD_Objects_from_file:sscanf parsing error [line_color]\n");
+ }
+ }
+ else if (strncasecmp(line,"line_type:",10) == 0) {
+ //fprintf(stderr,"Found line_type:\n");
+ if (1 != sscanf(line+11,"%d",
+ &CAD_list_head->line_type)) {
+ fprintf(stderr,"Restore_CAD_Objects_from_file:sscanf parsing error [line_type]\n");
+ }
+ }
+ else if (strncasecmp(line,"line_width:",11) == 0) {
+ //fprintf(stderr,"Found line_width:\n");
+ if (1 != sscanf(line+12,"%d",
+ &CAD_list_head->line_width)) {
+ fprintf(stderr,"Restore_CAD_Objects_from_file:sscanf parsing error [line_width]\n");
+ }
+ }
+ else if (strncasecmp(line,"computed_area:",14) == 0) {
+ //fprintf(stderr,"Found computed_area:\n");
+ if (1 != sscanf(line+15,"%f",
+ &CAD_list_head->computed_area)) {
+ fprintf(stderr,"Restore_CAD_Objects_from_file:sscanf parsing error [computed_area]\n");
+ }
+ }
+ else if (strncasecmp(line,"raw_probability:",16) == 0) {
+ //fprintf(stderr,"Found raw_probability:\n");
+ if (1 != sscanf(line+17,"%f",
+ &CAD_list_head->raw_probability)) {
+ fprintf(stderr,"Restore_CAD_Objects_from_file:sscanf parsing error [raw_probability]\n");
+ }
+ else {
+ // External storage is as percent, need to make sure that this
+ // fits the expected internal storage format.
+ // Thus take given value and store using method that knows
+ // how to handle percents
+ CAD_object_set_raw_probability(CAD_list_head,CAD_list_head->raw_probability,TRUE);
+ }
+ }
+ else if (strncasecmp(line,"label_latitude:",15) == 0) {
+ //fprintf(stderr,"Found label_latitude:\n");
+ if (1 != sscanf(line+16,"%lu",
+ (unsigned long *)&CAD_list_head->label_latitude)) {
+ fprintf(stderr,"Restore_CAD_Objects_from_file:sscanf parsing error [label_latitude]\n");
+ }
+ }
+ else if (strncasecmp(line,"label_longitude:",16) == 0) {
+ //fprintf(stderr,"Found label_longitude:\n");
+ if (1 != sscanf(line+17,"%lu",
+ (unsigned long *)&CAD_list_head->label_longitude)) {
+ fprintf(stderr,"Restore_CAD_Objects_from_file:sscanf parsing error [label_longitude]\n");
+ }
+ }
+ else if (strncasecmp(line,"label:",6) == 0) {
+ //fprintf(stderr,"Found label:\n");
+ xastir_snprintf(CAD_list_head->label,
+ sizeof(CAD_list_head->label),
+ "%s",
+ line+7);
+ }
+ else if (strncasecmp(line,"comment:",8) == 0) {
+ //fprintf(stderr,"Found comment:\n");
+ xastir_snprintf(CAD_list_head->comment,
+ sizeof(CAD_list_head->comment),
+ "%s",
+ line+9);
+
+ if (strcmp(CAD_list_head->comment,"NULL")==0) {
+ xastir_snprintf(CAD_list_head->comment,
+ sizeof(CAD_list_head->comment),
+ "%c",
+ '\0'
+ );
+ }
+ }
+ else if (strncasecmp(line,"Vertice:",8) == 0) {
+ long latitude, longitude;
+
+ //fprintf(stderr,"Found Vertice:\n");
+ if (2 != sscanf(line+9,"%lu %lu",
+ (unsigned long *)&latitude,
+ (unsigned long *)&longitude)) {
+ fprintf(stderr,"Restore_CAD_Objects_from_file:sscanf parsing error [vertex]\n");
+ }
+ CAD_vertice_allocate(latitude,longitude);
+ }
+ else {
+ // Else not recognized, do nothing with it!
+ //fprintf(stderr,"Found unrecognized line\n");
+ }
+ }
+ (void)fclose(f);
+ // Reload symbols/tracks/CAD objects to draw the loaded objects
+ redraw_symbols(da);
+}
+
+
+
+
+
+// popdown and destroy the cad_erase_dialog.
+//
+void Draw_CAD_Objects_erase_dialog_close ( /*@unused@*/ Widget w,
+ /*@unused@*/ XtPointer clientData,
+ /*@unused@*/ XtPointer callData) {
+
+ if (cad_erase_dialog!=NULL) {
+ // close cad_erase_dialog
+ XtPopdown(cad_erase_dialog);
+ XtDestroyWidget(cad_erase_dialog);
+ cad_erase_dialog = (Widget)NULL;
+ }
+
+}
+
+
+
+
+
+// Call back for delete selected button on
+// Draw_CAD_Objects_erase_dialog. Iterates through the list of
+// selected CAD objects and deletes them.
+//
+void Draw_CAD_Objects_erase_selected ( /*@unused@*/ Widget w,
+ /*@unused@*/ XtPointer clientData,
+ /*@unused@*/ XtPointer callData) {
+ int itemCount; // number of items in list of CAD objects.
+ XmString *listItems; // names of CAD objects on list
+ char *cadName; // the text name of a CAD object
+ Position x; // position on list
+ char *selectedName; // the text name of a selected CAD object
+ CADRow *object_ptr = CAD_list_head; // pointer to the linked list of CAD objects
+ int done = 0; // has a cad object with a name matching the current selection been found
+
+ // For more than a few objects this loop/save/redraw will need to move
+ // off to a separate thread.
+
+ XtVaGetValues(list_of_existing_CAD_objects,
+ XmNitemCount,&itemCount,
+ XmNitems,&listItems,
+ NULL);
+ // iterate through list and delete each first object with a name matching
+ // those that are selected on the list.
+ //
+ // *** Note: If names are not unique the results may not be what the user expects.
+ // The first match to a selection will be deleted, not necessarily the selection.
+ //
+ for (x=1; x<=itemCount;x++) {
+
+ if (done)
+ break;
+
+ if (XmListPosSelected(list_of_existing_CAD_objects,x)) {
+ int no_label = 0;
+
+ XmStringGetLtoR(listItems[(x-1)],XmFONTLIST_DEFAULT_TAG,&selectedName);
+
+ // Check for our own definition of no label for the CAD
+ // objects, which is "<Empty Label>"
+ if (strcmp(selectedName,"<Empty Label>") == 0)
+ no_label++;
+
+ object_ptr = CAD_list_head;
+ done = 0;
+
+ while (object_ptr != NULL && done == 0) {
+
+ cadName = object_ptr->label;
+
+ if (strcmp(cadName,selectedName)==0
+ || ( (cadName == NULL || cadName[0] == '\0') && no_label) ) {
+ // delete CAD object matching the selected name
+ CAD_object_delete(object_ptr);
+ done = 1;
+ }
+ else {
+ object_ptr = object_ptr->next;
+ }
+ }
+ }
+ }
+
+ Draw_CAD_Objects_erase_dialog_close(w,clientData,callData);
+
+ // Save the altered list to file.
+ Save_CAD_Objects_to_file();
+ // Reload symbols/tracks/CAD objects
+ redraw_symbols(da);
+
+ // Here we update the edit cad objects dialog by getting rid of it and
+ // then re-establishing it if it is active when we start. This will
+ // usually make the dialog move, but it's better than having it be
+ // out-of-date.
+ //
+ if (cad_list_dialog!=NULL) {
+ // Update the Edit CAD Objects list
+ Draw_CAD_Objects_list_dialog_close(w, clientData, callData);
+ Draw_CAD_Objects_list_dialog(w, clientData, callData);
+ }
+}
+
+
+
+
+
+// Callback for delete CAD objects menu option. Dialog to allow
+// users to delete all CAD objects or select individual CAD objects
+// to delete.
+//
+void Draw_CAD_Objects_erase_dialog( /*@unused@*/ Widget w,
+ /*@unused@*/ XtPointer clientData,
+ /*@unused@*/ XtPointer callData) {
+
+ Widget cad_erase_pane, cad_erase_form, cad_erase_label,
+ button_delete_all, button_delete_selected, button_cancel;
+ Arg al[100]; /* Arg List */
+ unsigned int ac; /* Arg Count */
+ CADRow *object_ptr = CAD_list_head;
+ int counter = 1;
+ XmString cb_item;
+
+ if (cad_erase_dialog) {
+ (void)XRaiseWindow(XtDisplay(cad_erase_dialog), XtWindow(cad_erase_dialog));
+ } else {
+
+ // Delete CAD Objects
+ cad_erase_dialog = XtVaCreatePopupShell("Delete CAD Objects",
+ xmDialogShellWidgetClass,
+ appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ cad_erase_pane = XtVaCreateWidget("CAD erase Object pane",
+ xmPanedWindowWidgetClass,
+ cad_erase_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ cad_erase_form = XtVaCreateWidget("Cad erase Object form",
+ xmFormWidgetClass,
+ cad_erase_pane,
+ XmNfractionBase, 3,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // heading: Delete CAD Objects
+ cad_erase_label = XtVaCreateManagedWidget(langcode("CADPUD009"),
+ xmLabelWidgetClass,
+ cad_erase_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // *** need to handle the special case of no CAD objects ? ***
+
+ // scrolled pick list to allow selection of current objects
+ /*set args for list */
+ ac=0;
+ XtSetArg(al[ac], XmNvisibleItemCount, 11); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNshadowThickness, 3); ac++;
+ XtSetArg(al[ac], XmNselectionPolicy, XmEXTENDED_SELECT); ac++;
+ XtSetArg(al[ac], XmNscrollBarPlacement, XmBOTTOM_RIGHT); ac++;
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopWidget, cad_erase_label); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 5); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 5); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 5); ac++;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ //XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, colors[0x0f]); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ list_of_existing_CAD_objects = XmCreateScrolledList(cad_erase_form,
+ "CAD objects for deletion scrolled list",
+ al,
+ ac);
+ // make sure list is empty
+ XmListDeleteAllItems(list_of_existing_CAD_objects);
+
+ // iterate through list of objects to populate scrolled list
+ while (object_ptr != NULL) {
+
+ // If no label, use the string "<Empty Label>" instead
+ if (object_ptr->label == NULL || object_ptr->label[0] == '\0')
+ cb_item = XmStringCreateLtoR("<Empty Label>", XmFONTLIST_DEFAULT_TAG);
+ else
+ cb_item = XmStringCreateLtoR(object_ptr->label, XmFONTLIST_DEFAULT_TAG);
+
+
+ XmListAddItem(list_of_existing_CAD_objects,
+ cb_item,
+ counter);
+ counter++;
+ XmStringFree(cb_item);
+ object_ptr = object_ptr->next;
+ }
+
+ // "Delete All"
+ button_delete_all = XtVaCreateManagedWidget(langcode("CADPUD010"),
+ xmPushButtonGadgetClass,
+ cad_erase_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, list_of_existing_CAD_objects,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_delete_all, XmNactivateCallback, Draw_CAD_Objects_erase, Draw_CAD_Objects_erase_dialog);
+
+ // "Delete Selected"
+ button_delete_selected = XtVaCreateManagedWidget(langcode("CADPUD011"),
+ xmPushButtonGadgetClass,
+ cad_erase_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, list_of_existing_CAD_objects,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, button_delete_all,
+ XmNleftOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_delete_selected, XmNactivateCallback, Draw_CAD_Objects_erase_selected, Draw_CAD_Objects_erase_dialog);
+
+ // "Cancel"
+ button_cancel = XtVaCreateManagedWidget(langcode("CADPUD008"),
+ xmPushButtonGadgetClass,
+ cad_erase_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, list_of_existing_CAD_objects,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, button_delete_selected,
+ XmNleftOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_cancel, XmNactivateCallback, Draw_CAD_Objects_erase_dialog_close, Draw_CAD_Objects_erase_dialog);
+ pos_dialog(cad_erase_dialog);
+ XmInternAtom(XtDisplay(cad_erase_dialog),"WM_DELETE_WINDOW", FALSE);
+
+ XtManageChild(cad_erase_form);
+ XtManageChild(list_of_existing_CAD_objects);
+ XtManageChild(cad_erase_pane);
+
+ XtPopup(cad_erase_dialog,XtGrabNone);
+ }
+}
+
+
+
+
+
+// popdown and destroy the cad_list_dialog
+//
+void Draw_CAD_Objects_list_dialog_close ( /*@unused@*/ Widget w,
+ /*@unused@*/ XtPointer clientData,
+ /*@unused@*/ XtPointer callData) {
+
+ if (cad_list_dialog!=NULL) {
+ // close cad_list_dialog
+ XtPopdown(cad_list_dialog);
+ XtDestroyWidget(cad_list_dialog);
+ cad_list_dialog = (Widget)NULL;
+ }
+
+}
+
+
+
+
+
+// Show details for selected CAD object. Callback for the show/edit
+// details button on the Draw_CAD_Objects_list dialog.
+//
+void Show_selected_CAD_object_details ( /*@unused@*/ Widget w,
+ /*@unused@*/ XtPointer clientData,
+ /*@unused@*/ XtPointer callData) {
+
+ static int sizeof_area_description = 200;
+ int itemCount; // number of items in list of CAD objects.
+ XmString *listItems; // names of CAD objects on list
+ char *cadName; // the text name of a CAD object
+ Position x; // position on list
+ char *selectedName; // the text name of a selected CAD object
+ CADRow *object_ptr = CAD_list_head; // pointer to the linked list of CAD objects
+ int done = 0; // has a cad object with a name matching the current selection been found
+ double area;
+ char area_description[sizeof_area_description];
+ xastir_snprintf(area_description, sizeof_area_description, "Area");
+
+ if (cad_list_dialog!=NULL) {
+ // get the selected object
+ XtVaGetValues(list_of_existing_CAD_objects_edit,
+ XmNitemCount,&itemCount,
+ XmNitems,&listItems,
+ NULL);
+ // iterate through list and find each object with a name
+ // matching one selected on the list.
+ //
+ // *** Note: If names are not unique the results may not be what the user expects.
+ // The first match to a selection will be used, not necessarily the selection.
+ //
+ for (x=1; x<=itemCount;x++) {
+ if (XmListPosSelected(list_of_existing_CAD_objects_edit,x)) {
+ int no_label = 0;
+
+ XmStringGetLtoR(listItems[(x-1)],XmFONTLIST_DEFAULT_TAG,&selectedName);
+
+ // Check for our own definition of no label for the CAD
+ // objects, which is "<Empty Label>"
+ if (strcmp(selectedName,"<Empty Label>") == 0)
+ no_label++;
+
+ object_ptr = CAD_list_head;
+ done = 0;
+
+ while (object_ptr != NULL && done == 0) {
+
+ cadName = object_ptr->label;
+
+ if (strcmp(cadName,selectedName)==0
+ || ( (cadName == NULL || cadName[0] == '\0') && no_label) ) {
+
+ // get the area for the CAD object matching the selected name
+ // and format it as a localized string.
+ area = object_ptr->computed_area;
+ Format_area_for_output(&area, area_description,sizeof_area_description);
+ // open the CAD object details dialog for the matching CAD object
+ Set_CAD_object_parameters_dialog(area_description,object_ptr);
+ done = 1;
+ } else {
+ object_ptr = object_ptr->next;
+ }
+ }
+ }
+ }
+
+ // leave the list dialog open
+ }
+}
+
+
+
+
+
+// Callback for edit CAD objects menu option. Dialog to allow users
+// to select individual CAD objects in order to edit their metadata.
+//
+void Draw_CAD_Objects_list_dialog( /*@unused@*/ Widget w,
+ /*@unused@*/ XtPointer clientData,
+ /*@unused@*/ XtPointer callData) {
+
+ Widget cad_list_pane, cad_list_form, cad_list_label,
+ button_list_selected, button_close;
+ Arg al[100]; /* Arg List */
+ unsigned int ac; /* Arg Count */
+ CADRow *object_ptr = CAD_list_head;
+ int counter = 1;
+ XmString cb_item;
+
+ if (cad_list_dialog) {
+ (void)XRaiseWindow(XtDisplay(cad_list_dialog), XtWindow(cad_list_dialog));
+ }
+ else {
+
+ // List CAD Objects
+ cad_list_dialog = XtVaCreatePopupShell("List CAD Objects",
+ xmDialogShellWidgetClass,
+ appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ cad_list_pane = XtVaCreateWidget("CAD list Object pane",
+ xmPanedWindowWidgetClass,
+ cad_list_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ cad_list_form = XtVaCreateWidget("Cad list Object form",
+ xmFormWidgetClass,
+ cad_list_pane,
+ XmNfractionBase, 3,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // heading: CAD Objects
+ cad_list_label = XtVaCreateManagedWidget(langcode("CADPUD006"),
+ xmLabelWidgetClass,
+ cad_list_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // *** need to handle the special case of no CAD objects ? ***
+
+ // scrolled pick list to allow selection of current objects
+ /*set args for list */
+ ac=0;
+ XtSetArg(al[ac], XmNvisibleItemCount, 11); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNshadowThickness, 3); ac++;
+ XtSetArg(al[ac], XmNselectionPolicy, XmSINGLE_SELECT); ac++;
+ XtSetArg(al[ac], XmNscrollBarPlacement, XmBOTTOM_RIGHT); ac++;
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopWidget, cad_list_label); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 5); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 5); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 5); ac++;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ //XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, colors[0x0f]); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ list_of_existing_CAD_objects_edit = XmCreateScrolledList(cad_list_form,
+ "CAD objects for deletion scrolled list",
+ al,
+ ac);
+ // make sure list is empty
+ XmListDeleteAllItems(list_of_existing_CAD_objects_edit);
+
+ // iterate through list of objects to populate scrolled list
+ while (object_ptr != NULL) {
+
+ // If no label, use the string "<Empty Label>" instead
+ if (object_ptr->label == NULL || object_ptr->label[0] == '\0')
+ cb_item = XmStringCreateLtoR("<Empty Label>", XmFONTLIST_DEFAULT_TAG);
+ else
+ cb_item = XmStringCreateLtoR(object_ptr->label, XmFONTLIST_DEFAULT_TAG);
+
+ XmListAddItem(list_of_existing_CAD_objects_edit,
+ cb_item,
+ counter);
+ counter++;
+ XmStringFree(cb_item);
+ object_ptr = object_ptr->next;
+ }
+
+ // "Show/edit details"
+ button_list_selected = XtVaCreateManagedWidget(langcode("CADPUD007"),
+ xmPushButtonGadgetClass,
+ cad_list_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, list_of_existing_CAD_objects_edit,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_list_selected, XmNactivateCallback, Show_selected_CAD_object_details, Draw_CAD_Objects_list_dialog);
+
+ // "Close"
+ button_close = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ cad_list_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, list_of_existing_CAD_objects_edit,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, button_list_selected,
+ XmNleftOffset, 10,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(button_close, XmNactivateCallback, Draw_CAD_Objects_list_dialog_close, Draw_CAD_Objects_erase_dialog);
+ pos_dialog(cad_list_dialog);
+ XmInternAtom(XtDisplay(cad_list_dialog),"WM_DELETE_WINDOW", FALSE);
+
+ XtManageChild(cad_list_form);
+ XtManageChild(list_of_existing_CAD_objects_edit);
+ XtManageChild(cad_list_pane);
+
+ XtPopup(cad_list_dialog,XtGrabNone);
+ }
+}
+
+
+
+
+
+// Free the object and vertice lists then do a screen update.
+// callback from delete all button on cad_erase_dialog.
+//
+void Draw_CAD_Objects_erase( /*@unused@*/ Widget w,
+ /*@unused@*/ XtPointer clientData,
+ /*@unused@*/ XtPointer callData) {
+
+ // if we were called from the cad_erase_dialog, make sure it is closed properly
+ if (cad_erase_dialog)
+ Draw_CAD_Objects_erase_dialog_close(w,clientData,callData);
+
+ CAD_object_delete_all();
+ polygon_last_x = -1; // Invalid position
+ polygon_last_y = -1; // Invalid position
+
+ // Save the empty list out to file
+ Save_CAD_Objects_to_file();
+
+ // Reload symbols/tracks/CAD objects
+ redraw_symbols(da);
+}
+
+
+
+
+
+// Formats an area in square kilometers as a string in english or
+// metric units, converting to feet or meters if the area is less
+// than 0.1 square kilometers and adding localized text.
+// Parameters: area: an area in square kilometers.
+// area_description: area reformatted as a localized text string.
+// sizeof_area_description: array length of area_description.
+//
+void Format_area_for_output(double *area_km2, char *area_description, int sizeof_area_description) {
+ double area;
+ // Format it for output and dump it out. We're using square
+ // terms, so apply the conversion factor twice to convert from
+ // nautical square miles to the units of interest.
+ area = *area_km2 * cvt_kn2len * cvt_kn2len;
+
+ // We could be measuring a very small or a very large object.
+ // In the case of very small, convert it to square feet or
+ // square meters.
+ if (area < 0.1) {
+
+ // Small area. Convert to square feet or square meters
+
+ if (english_units) { // Square feet
+ area = area * 5280 * 5280;
+ xastir_snprintf(area_description,
+ sizeof_area_description,
+ "A:%0.2f %s %s",
+ area,
+ langcode("POPUPMA052"), // sq
+ langcode("POPUPMA053") ); // ft
+ //popup_message_always(langcode("POPUPMA020"),area_description);
+ }
+ else { // Square meters
+ area = area * 1000 * 1000; // Square meters
+ xastir_snprintf(area_description,
+ sizeof_area_description,
+ "A:%0.2f %s %s",
+ area,
+ langcode("POPUPMA052"), // sq
+ langcode("POPUPMA054") ); // meters
+ //popup_message_always(langcode("POPUPMA020"),area_description);
+ }
+ }
+ else { // Not small
+ xastir_snprintf(area_description,
+ sizeof_area_description,
+ "A:%0.2f %s %s",
+ area,
+ langcode("POPUPMA052"), // sq
+ un_dst);
+ //popup_message_always(langcode("POPUPMA020"),area_description);
+ }
+}
+
+
+
+
+
+// Add an ending vertice that is the same as the starting vertice.
+// Best not to use the screen coordinates we captured first, as the
+// user may have zoomed or panned since then. Better to copy the
+// first vertice that we recorded in our linked list.
+//
+// Compute the area of the closed polygon. Write it out to STDERR,
+// the computed_area field in the Object, and to a dialog that pops
+// up on the screen.
+//
+void Draw_CAD_Objects_close_polygon( /*@unused@*/ Widget widget,
+ XtPointer clientData,
+ /*@unused@*/ XtPointer callData) {
+ static int sizeof_area_description = 200;
+ VerticeRow *tmp;
+ double area;
+ int n;
+ //char temp_course[20];
+ char area_description[sizeof_area_description];
+ xastir_snprintf(area_description, sizeof_area_description, "Area");
+
+ // Check whether we're currently working on a polygon. If not,
+ // get out of here.
+ if (polygon_last_x == -1 || polygon_last_y == -1) {
+
+ // Tell the code that we're starting a new polygon by wiping
+ // out the first position.
+ polygon_last_x = -1; // Invalid position
+ polygon_last_y = -1; // Invalid position
+
+ return;
+ }
+
+ // Find the last vertice in the linked list. That will be the
+ // first vertice we recorded for the object.
+
+ // Check for at least three vertices. We don't need to check
+ // that the first/last point are equal: We force it below by
+ // copying the first vertice to the last.
+ //
+ n = 0;
+ if (CAD_list_head != NULL) {
+
+ // Walk the linked list. Stop at the last record.
+ tmp = CAD_list_head->start;
+ if (tmp != NULL) {
+ n++;
+ while (tmp->next != NULL) {
+ tmp = tmp->next;
+ n++;
+ }
+ if (n > 2) {
+ // We have more than a point or a line, therefore
+ // can copy the first point to the last, closing the
+ // polygon.
+ CAD_vertice_allocate(tmp->latitude, tmp->longitude);
+ }
+ }
+ }
+ // Reload symbols/tracks/CAD objects and redraw the polygon
+ redraw_symbols(da);
+
+#ifdef CAD_DEBUG
+ fprintf(stderr,"Points in closed polygon: n = %d\n",n);
+#endif
+
+ if (n < 3) {
+ // Not enough points to compute an area.
+
+ // Tell the code that we're starting a new polygon by wiping
+ // out the first position.
+ polygon_last_x = -1; // Invalid position
+ polygon_last_y = -1; // Invalid position
+
+ return;
+ }
+ area = CAD_object_compute_area(CAD_list_head);
+
+ // Save it in the object. Convert nautical square miles to
+ // square kilometers.
+ area = area * 1.852 * 1.852; //km2
+ CAD_list_head->computed_area = area;
+
+ Format_area_for_output(&area, area_description, sizeof_area_description);
+
+#ifdef CAD_DEBUG
+ // Also write the area to stderr
+ fprintf(stderr,"New CAD object %s\n",area_description);
+#endif
+
+ // Tell the code that we're starting a new polygon by wiping out
+ // the first position.
+ polygon_last_x = -1; // Invalid position
+ polygon_last_y = -1; // Invalid position
+
+ CAD_object_set_label_at_centroid(CAD_list_head);
+ // CAD object vertices are ready, needs associated data
+ // obtain label, comment, and probability for this polygon
+ // from user through a dialog.
+ Set_CAD_object_parameters_dialog(area_description,NULL);
+}
+
+
+
+
+
+// Function called by UpdateTime when doing screen refresh. Draws
+// all CAD objects onto the screen again.
+//
+void Draw_All_CAD_Objects(Widget w) {
+ CADRow *object_ptr = CAD_list_head;
+ long x_long, y_lat;
+ long x_offset, y_offset;
+ float probability;
+ char probability_string[8];
+ VerticeRow *vertice;
+ double area;
+ int actual_line_type = LineOnOffDash;
+ static int sizeof_area_description = 50; // define here as local static to limit size of display on map
+ // independent of size as shown on form
+ char area_description[sizeof_area_description];
+ char dash[2];
+
+ // Start at CAD_list_head, iterate through entire linked list,
+ // drawing as we go. Respect the line
+ // width/line_color/line_type variables for each object.
+
+//fprintf(stderr,"Drawing CAD objects\n");
+ if (CAD_draw_objects==TRUE) {
+ while (object_ptr != NULL) {
+ probability = CAD_object_get_raw_probability(object_ptr,1);
+ xastir_snprintf(probability_string,
+ sizeof(probability_string),
+ "%01.1f%%",
+ probability);
+
+ // find point at which to draw label and other descriptive text
+ x_long = object_ptr->label_longitude;
+ y_lat = object_ptr->label_latitude;
+ #ifdef CAD_DEBUG
+ fprintf(stderr,"Drawing object %s\n", (object_ptr->label) ? object_ptr->label : "NULL" );
+ #endif
+ //fprintf(stderr,"Lat: %d\n", y_lat);
+ //fprintf(stderr,"Long: %d\n", x_long);
+// if ((x_long+10>=0) && (x_long-10<=129600000l)) { // 360 deg
+
+// if ((y_lat+10>=0) && (y_lat-10<=64800000l)) { // 180 deg
+
+ if ((x_long>NW_corner_longitude) && (x_long<SE_corner_longitude)) {
+
+ if ((y_lat>NW_corner_latitude) && (y_lat<SE_corner_latitude)) {
+
+ // ok to draw label and assocated data, point is on screen
+ x_offset=((x_long-NW_corner_longitude)/scale_x)-(10);
+ y_offset=((y_lat -NW_corner_latitude) /scale_y)-(10);
+ // ****** ?? use -10 or point ??
+ x_offset=((x_long-NW_corner_longitude)/scale_x);
+ y_offset=((y_lat -NW_corner_latitude) /scale_y);
+
+ if ((object_ptr->label!=NULL) & ((int)strlen(object_ptr->label)>0) & (CAD_show_label==TRUE)) {
+ // Draw Label
+ // 0x08 is background color
+ // 0x40 is foreground color (yellow)
+ draw_nice_string(w,pixmap_final,letter_style,x_offset,y_offset,object_ptr->label,0x08,0x40,strlen(object_ptr->label));
+
+ x_offset=x_offset+12;
+ y_offset=y_offset+15;
+ }
+
+ if (CAD_show_raw_probability==TRUE) {
+ // draw probability
+ draw_nice_string(w,pixmap_final,letter_style,x_offset,y_offset,probability_string,0x08,0x40,strlen(probability_string));
+ y_offset=y_offset+15;
+ }
+
+ if ((CAD_show_comment==TRUE) & (object_ptr->comment!=NULL) & ((int)strlen(object_ptr->comment)>0)) {
+ // draw comment
+ draw_nice_string(w,pixmap_final,letter_style,x_offset,y_offset,object_ptr->comment,0x08,0x40,strlen(object_ptr->comment));
+ y_offset=y_offset+15;
+ }
+
+
+ if (CAD_show_area==TRUE) {
+ area = object_ptr->computed_area;
+ Format_area_for_output(&area, area_description, sizeof_area_description);
+ draw_nice_string(w,pixmap_final,letter_style,x_offset,y_offset,area_description,0x08,0x40,strlen(area_description));
+ y_offset=y_offset+15;
+ }
+
+ }
+ }
+// }
+// }
+
+ // Iterate through the vertices and draw the lines
+ vertice = object_ptr->start;
+
+ switch (object_ptr->line_type) {
+
+ case 1:
+ actual_line_type = LineSolid;
+ break;
+
+ case 2:
+ actual_line_type = LineOnOffDash;
+ dash[0] = dash[1] = 8;
+ break;
+
+ case 3:
+ actual_line_type = LineDoubleDash;
+ dash[0] = dash[1] = 16;
+ break;
+
+ default:
+ actual_line_type = LineOnOffDash;
+ dash[0] = dash[1] = 8;
+ break;
+ }
+
+ // Set up line color/width/type here
+ (void)XSetLineAttributes (XtDisplay (da),
+ gc_tint,
+ object_ptr->line_width,
+ actual_line_type,
+ CapButt,
+ JoinMiter);
+
+ if (object_ptr->line_type != 1) {
+ (void)XSetDashes (XtDisplay (da),
+ gc_tint,
+ 0, // dash offset
+ dash, // dash list[]
+ 2); // elements in dash lista
+ }
+
+ (void)XSetForeground (XtDisplay (da),
+ gc_tint,
+ object_ptr->line_color);
+
+ (void)XSetFunction (XtDisplay (da),
+ gc_tint,
+ GXxor);
+
+ while (vertice != NULL) {
+ if (vertice->next != NULL) {
+ // Use the draw_vector function from maps.c
+ draw_vector(w,
+ vertice->longitude,
+ vertice->latitude,
+ vertice->next->longitude,
+ vertice->next->latitude,
+ gc_tint,
+ pixmap_final,
+ 0);
+ }
+ vertice = vertice->next;
+ }
+ object_ptr = object_ptr->next;
+ }
+ }
+}
+
+
+
+///////////////////////////////////////// Object Dialog //////////////////////////////////////////
+
+
+
+/*
+ * Destroy Object Dialog Popup Window
+ */
+void Object_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+ (void)XFreePixmap(XtDisplay(appshell),Ob_icon0);
+ (void)XFreePixmap(XtDisplay(appshell),Ob_icon);
+ XtDestroyWidget(shell);
+ object_dialog = (Widget)NULL;
+
+ // Take down the symbol selection dialog as well (if it's up)
+ if (select_symbol_dialog) {
+ Select_symbol_destroy_shell( widget, select_symbol_dialog, callData);
+ }
+
+ // NULL out the dialog field in the global struct used for
+ // Coordinate Calculator. Prevents segfaults if the calculator is
+ // still up and trying to write to us.
+ coordinate_calc_array.calling_dialog = NULL;
+}
+
+
+
+
+
+// Snag the latest DR'ed position for an object/item and create the
+// types of strings that we need for Setup_object_data() and
+// Setup_item_data() for APRS and Base-91 compressed formats.
+//
+void fetch_current_DR_strings(DataRow *p_station, char *lat_str,
+ char *lon_str, char *ext_lat_str, char *ext_lon_str) {
+
+ long x_long, y_lat;
+
+
+ // Fetch the latest position for a DR'ed object. Returns the
+ // values in two longs, x_long and y_lat.
+ compute_current_DR_position(p_station, &x_long, &y_lat);
+
+ // Normal precision for APRS format
+ convert_lat_l2s(y_lat,
+ lat_str,
+ MAX_LAT,
+ CONVERT_LP_NOSP);
+
+ convert_lon_l2s(x_long,
+ lon_str,
+ MAX_LONG,
+ CONVERT_LP_NOSP);
+
+ // Extended precision for Base-91 compressed format
+ convert_lat_l2s(y_lat,
+ ext_lat_str,
+ MAX_LAT,
+ CONVERT_HP_NOSP);
+
+ convert_lon_l2s(x_long,
+ ext_lon_str,
+ MAX_LONG,
+ CONVERT_HP_NOSP);
+}
+
+
+
+
+
+// Convert this eventually to populate a DataRow struct, then call
+// data.c:Create_object_item_tx_string(). Right now we have a lot
+// of code duplication between Setup_object_data, Setup_item_data,
+// and Create_object_item_tx_string.
+//
+// Make sure to look at the "transmit_compressed_objects_items" variable
+// to decide whether to send a compressed packet.
+/*
+ * Setup APRS Information Field for Objects
+ */
+int Setup_object_data(char *line, int line_length, DataRow *p_station) {
+ char lat_str[MAX_LAT];
+ char lon_str[MAX_LONG];
+ char ext_lat_str[20]; // Extended precision for base91 compression
+ char ext_lon_str[20]; // Extended precision for base91 compression
+ char comment[43+1]; // max 43 characters of comment
+ char time[7+1];
+ struct tm *day_time;
+ time_t sec;
+ char complete_area_color[3];
+ int complete_area_type;
+ int lat_offset, lon_offset;
+ char complete_corridor[6];
+ char altitude[10];
+ char speed_course[8];
+ int speed;
+ int course;
+ int temp;
+ long temp2;
+ float temp3;
+ char signpost[6];
+ char prob_min[20+1];
+ char prob_max[20+1];
+ int bearing;
+ char *temp_ptr;
+ char *temp_ptr2;
+ int DR = 0; // Dead-reckoning flag
+ int comment_field_used = 0; // Amount of comment field used up
+
+
+ //fprintf(stderr,"Setup_object_data\n");
+
+ // If speed for the original object was non-zero, then we need
+ // to snag the updated DR'ed position for the object. Snag the
+ // current DR position and build the strings we need // for
+ // position transmit.
+ //
+ if (p_station != NULL) {
+
+ speed = atoi(p_station->speed);
+
+ if (speed > 0 && !doing_move_operation) {
+
+ fetch_current_DR_strings(p_station,
+ lat_str,
+ lon_str,
+ ext_lat_str,
+ ext_lon_str);
+ DR++; // Set the dead-reckoning flag
+ }
+
+ // Keep the time current for our own objects.
+ p_station->sec_heard = sec_now();
+ move_station_time(p_station,NULL);
+ }
+
+ temp_ptr = XmTextFieldGetString(object_name_data);
+ xastir_snprintf(line,
+ line_length,
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(line);
+ //(void)to_upper(line); Not per spec. Don't use this.
+ if (!valid_object(line))
+ return(0);
+
+ // Copy object name into "last_object"
+ xastir_snprintf(last_object,
+ sizeof(last_object),
+ "%s",
+ line);
+
+
+ if (!DR) { // We're not doing dead-reckoning, so proceed
+
+ temp_ptr = XmTextFieldGetString(object_lat_data_ns);
+ if((char)toupper((int)temp_ptr[0]) == 'S')
+ line[0] = 'S';
+ else
+ line[0] = 'N';
+ XtFree(temp_ptr);
+
+ // Check latitude for out-of-bounds
+ temp_ptr = XmTextFieldGetString(object_lat_data_deg);
+ temp = atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ if ( (temp > 90) || (temp < 0) )
+ return(0);
+
+ temp_ptr = XmTextFieldGetString(object_lat_data_min);
+ temp3 = atof(temp_ptr);
+ XtFree(temp_ptr);
+
+ if ( (temp3 >= 60.0) || (temp3 < 0.0) )
+ return(0);
+ if ( (temp == 90) && (temp3 != 0.0) )
+ return(0);
+
+ temp_ptr = XmTextFieldGetString(object_lat_data_deg);
+ temp_ptr2 = XmTextFieldGetString(object_lat_data_min);
+ xastir_snprintf(lat_str, sizeof(lat_str), "%02d%05.2f%c",
+ atoi(temp_ptr),
+// An attempt was made to round here, adding 0.001 to the minutes
+// value. Problems arise if it goes above 59 minutes as the degrees
+// value would need to bump up also. This then gets into problems
+// at 90.0 degrees. The correct method would be to convert it to
+// decimal at a higher precision and then convert it back to DD
+// MM.MM format.
+// atof(temp_ptr2) + 0.001,
+ atof(temp_ptr2),
+ line[0]);
+ XtFree(temp_ptr);
+ XtFree(temp_ptr2);
+
+ temp_ptr = XmTextFieldGetString(object_lat_data_deg);
+ temp_ptr2 = XmTextFieldGetString(object_lat_data_min);
+ xastir_snprintf(ext_lat_str, sizeof(ext_lat_str), "%02d%05.3f%c",
+ atoi(temp_ptr),
+// An attempt was made to round here, adding 0.0001 to the minutes
+// value. Problems arise if it goes above 59 minutes as the degrees
+// value would need to bump up also. This then gets into problems
+// at 90.0 degrees. The correct method would be to convert it to
+// decimal at a higher precision and then convert it back to DD
+// MM.MM format.
+// atof(temp_ptr2) + 0.0001,
+ atof(temp_ptr2),
+ line[0]);
+ XtFree(temp_ptr);
+ XtFree(temp_ptr2);
+
+ temp_ptr = XmTextFieldGetString(object_lon_data_ew);
+ xastir_snprintf(line,
+ line_length,
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ if((char)toupper((int)line[0]) == 'E')
+ line[0] = 'E';
+ else
+ line[0] = 'W';
+
+ // Check longitude for out-of-bounds
+ temp_ptr = XmTextFieldGetString(object_lon_data_deg);
+ temp = atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ if ( (temp > 180) || (temp < 0) )
+ return(0);
+
+ temp_ptr = XmTextFieldGetString(object_lon_data_min);
+ temp3 = atof(temp_ptr);
+ XtFree(temp_ptr);
+
+ if ( (temp3 >= 60.0) || (temp3 < 0.0) )
+ return(0);
+
+ if ( (temp == 180) && (temp3 != 0.0) )
+ return(0);
+
+ temp_ptr = XmTextFieldGetString(object_lon_data_deg);
+ temp_ptr2 = XmTextFieldGetString(object_lon_data_min);
+ xastir_snprintf(lon_str, sizeof(lon_str), "%03d%05.2f%c",
+ atoi(temp_ptr),
+// An attempt was made to round here, adding 0.001 to the minutes
+// value. Problems arise if it goes above 59 minutes as the degrees
+// value would need to bump up also. This then gets into problems
+// at 90.0 degrees. The correct method would be to convert it to
+// decimal at a higher precision and then convert it back to DD
+// MM.MM format.
+// atof(temp_ptr2) + 0.001,
+ atof(temp_ptr2),
+ line[0]);
+ XtFree(temp_ptr);
+ XtFree(temp_ptr2);
+
+ temp_ptr = XmTextFieldGetString(object_lon_data_deg);
+ temp_ptr2 = XmTextFieldGetString(object_lon_data_min);
+ xastir_snprintf(ext_lon_str, sizeof(ext_lon_str), "%03d%05.3f%c",
+ atoi(temp_ptr),
+// An attempt was made to round here, adding 0.0001 to the minutes
+// value. Problems arise if it goes above 59 minutes as the degrees
+// value would need to bump up also. This then gets into problems
+// at 90.0 degrees. The correct method would be to convert it to
+// decimal at a higher precision and then convert it back to DD
+// MM.MM format.
+// atof(temp_ptr2) + 0.0001,
+ atof(temp_ptr2),
+ line[0]);
+ XtFree(temp_ptr);
+ XtFree(temp_ptr2);
+ }
+
+
+ temp_ptr = XmTextFieldGetString(object_group_data);
+ xastir_snprintf(line,
+ line_length,
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ last_obj_grp = line[0];
+ if(isalpha((int)last_obj_grp))
+ last_obj_grp = toupper((int)line[0]); // todo: toupper in dialog
+
+ // Check for overlay character
+ if (last_obj_grp != '/' && last_obj_grp != '\\') {
+ // Found an overlay character. Check that it's within the
+ // proper range
+ if ( (last_obj_grp >= '0' && last_obj_grp <= '9')
+ || (last_obj_grp >= 'A' && last_obj_grp <= 'Z') ) {
+ last_obj_overlay = last_obj_grp;
+ last_obj_grp = '\\';
+ }
+ else {
+ last_obj_overlay = '\0';
+ }
+ }
+ else {
+ last_obj_overlay = '\0';
+ }
+
+ temp_ptr = XmTextFieldGetString(object_symbol_data);
+ xastir_snprintf(line,
+ line_length,
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ last_obj_sym = line[0];
+
+ temp_ptr = XmTextFieldGetString(object_comment_data);
+ xastir_snprintf(comment,
+ sizeof(comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(comment);
+ //fprintf(stderr,"Comment Field was: %s\n",comment);
+
+ sec = sec_now();
+ day_time = gmtime(&sec);
+ xastir_snprintf(time, sizeof(time), "%02d%02d%02dz", day_time->tm_mday, day_time->tm_hour,
+ day_time->tm_min);
+
+ // Handle Generic Options
+
+ // Speed/Course Fields
+ temp_ptr = XmTextFieldGetString(ob_course_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ xastir_snprintf(speed_course, sizeof(speed_course), "%s", ".../");
+ course = 0;
+ if (strlen(line) != 0) { // Course was entered
+ // Need to check for 1 to three digits only, and 001-360 degrees)
+ temp = atoi(line);
+ if ( (temp >= 1) && (temp <= 360) ) {
+ xastir_snprintf(speed_course, sizeof(speed_course), "%03d/", temp);
+ course = temp;
+ } else if (temp == 0) { // Spec says 001 to 360 degrees...
+ xastir_snprintf(speed_course, sizeof(speed_course), "%s", "360/");
+ }
+ }
+ temp_ptr = XmTextFieldGetString(ob_speed_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ speed = 0;
+ if (strlen(line) != 0) { // Speed was entered (we only handle knots currently)
+ // Need to check for 1 to three digits, no alpha characters
+ temp = atoi(line);
+ if ( (temp >= 0) && (temp <= 999) ) {
+ xastir_snprintf(line, line_length, "%03d", temp);
+ strncat(speed_course,
+ line,
+ sizeof(speed_course) - 1 - strlen(speed_course));
+ speed = temp;
+ }
+ else {
+ strncat(speed_course,
+ "...",
+ sizeof(speed_course) - 1 - strlen(speed_course));
+ }
+ }
+ else { // No speed entered, blank it out
+ strncat(speed_course,
+ "...",
+ sizeof(speed_course) - 1 - strlen(speed_course));
+ }
+ if ( (speed_course[0] == '.') && (speed_course[4] == '.') ) {
+ speed_course[0] = '\0'; // No speed or course entered, so blank it
+ }
+ if (Area_object_enabled) {
+ speed_course[0] = '\0'; // Course/Speed not allowed if Area Object
+ }
+
+ // Altitude Field
+ temp_ptr = XmTextFieldGetString(ob_altitude_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ //fprintf(stderr,"Altitude entered: %s\n", line);
+ altitude[0] = '\0'; // Start with empty string
+ if (strlen(line) != 0) { // Altitude was entered (we only handle feet currently)
+ // Need to check for all digits, and 1 to 6 digits
+ if (isdigit((int)line[0])) {
+ temp2 = atoi(line);
+ if ( (temp2 >= 0) && (temp2 <= 999999) ) {
+ xastir_snprintf(altitude, sizeof(altitude), "/A=%06ld", temp2);
+ //fprintf(stderr,"Altitude string: %s\n",altitude);
+ }
+ }
+ }
+
+ // Handle Specific Options
+
+ // Area Objects
+ if (Area_object_enabled) {
+ //fprintf(stderr,"Area_bright: %d\n", Area_bright);
+ //fprintf(stderr,"Area_filled: %d\n", Area_filled);
+ if (Area_bright) { // Bright color
+ xastir_snprintf(complete_area_color, sizeof(complete_area_color), "%2s", Area_color);
+ } else { // Dim color
+ xastir_snprintf(complete_area_color, sizeof(complete_area_color), "%02d",
+ atoi(&Area_color[1]) + 8);
+
+ if ( (Area_color[1] == '0') || (Area_color[1] == '1') ) {
+ complete_area_color[0] = '/';
+ }
+ }
+ if ( (Area_filled) && (Area_type != 1) && (Area_type != 6) ) {
+ complete_area_type = Area_type + 5;
+ } else { // Can't fill in a line
+ complete_area_type = Area_type;
+ }
+ temp_ptr = XmTextFieldGetString(ob_lat_offset_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ lat_offset = (int)sqrt(atof(line));
+ if (lat_offset > 99)
+ lat_offset = 99;
+ //fprintf(stderr,"Line: %s\tlat_offset: %d\n", line, lat_offset);
+
+ temp_ptr = XmTextFieldGetString(ob_lon_offset_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ lon_offset = (int)sqrt(atof(line));
+ if (lon_offset > 99)
+ lon_offset = 99;
+ //fprintf(stderr,"Line: %s\tlon_offset: %d\n", line, lon_offset);
+
+ //fprintf(stderr,"Corridor Field: %s\n", XmTextFieldGetString(ob_corridor_data) );
+ // Corridor
+ complete_corridor[0] = '\0';
+ if ( (Area_type == 1) || (Area_type == 6) ) {
+
+ temp_ptr = XmTextFieldGetString(ob_corridor_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ if (strlen(line) != 0) { // We have a line and some corridor data
+ // Need to check for 1 to three digits only
+ temp = atoi(line);
+ if ( (temp > 0) && (temp <= 999) ) {
+ xastir_snprintf(complete_corridor, sizeof(complete_corridor), "{%d}", temp);
+ //fprintf(stderr,"%s\n",complete_corridor);
+ }
+ }
+ }
+
+ //fprintf(stderr,"Complete_corridor: %s\n", complete_corridor);
+
+ if (transmit_compressed_objects_items) {
+ char temp_overlay = last_obj_overlay;
+
+
+// Need to compute "csT" at some point and add it to the object.
+// Until we do that we'll have no course/speed/altitude. Looks like
+// we can have course/speed or altitude, but not both. Must have to
+// add the "/A=000123" stuff to the end if we want both.
+//
+// If we have course and/or speed, use course/speed csT bytes. If
+// no course/speed but we have altitude, use altitude csT bytes. We
+// can cheat right now and just always use course/speed, adding
+// altitude with the altitude extension. Not as efficient, but it
+// gets the job done.
+//
+// Later we should change compress_posit() to accept an altitude
+// parameter, and have it decide which csT set of bytes to add, and
+// whether to add altitude as an uncompressed extension if
+// necessary.
+
+
+ // Need to handle the conversion of numeric overlay
+ // chars to "a-j" here.
+ if (last_obj_overlay >= '0' && last_obj_overlay <= '9') {
+ temp_overlay = last_obj_overlay + 'a';
+ }
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%1d%02d%2s%02d%s%s%s",
+ last_object,
+ time,
+ compress_posit(ext_lat_str,
+ (temp_overlay) ? temp_overlay : last_obj_grp,
+ ext_lon_str,
+ last_obj_sym,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank in this case
+ complete_area_type, // In comment field
+ lat_offset, // In comment field
+ complete_area_color,// In comment field
+ lon_offset, // In comment field
+ speed_course, // In comment field
+ complete_corridor, // In comment field
+ altitude); // In comment field
+
+ comment_field_used = strlen(line) - 31;
+
+ }
+ else {
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%c%s%c%1d%02d%2s%02d%s%s%s",
+ last_object,
+ time,
+ lat_str,
+ last_obj_grp,
+ lon_str,
+ last_obj_sym,
+ complete_area_type, // In comment field
+ lat_offset, // In comment field
+ complete_area_color,// In comment field
+ lon_offset, // In comment field
+ speed_course, // In comment field
+ complete_corridor, // In comment field
+ altitude); // In comment field
+
+ comment_field_used = strlen(line) - 37;
+ }
+
+ //fprintf(stderr,"String is: %s\n", line);
+
+ } else if (Signpost_object_enabled) {
+ temp_ptr = XmTextFieldGetString(signpost_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ //fprintf(stderr,"Signpost entered: %s\n", line);
+ if (strlen(line) != 0) { // Signpost data was entered
+ // Need to check for between one and three characters
+ temp = strlen(line);
+ if ( (temp >= 0) && (temp <= 3) ) {
+ xastir_snprintf(signpost, sizeof(signpost), "{%s}", line);
+ } else {
+ signpost[0] = '\0';
+ }
+ } else { // No signpost data entered, blank it out
+ signpost[0] = '\0';
+ }
+
+
+ if (transmit_compressed_objects_items) {
+ char temp_overlay = last_obj_overlay;
+
+
+// Need to compute "csT" at some point and add it to the object.
+// Until we do that we'll have no course/speed/altitude. Looks like
+// we can have course/speed or altitude, but not both. Must have to
+// add the "/A=000123" stuff to the end if we want both.
+//
+// If we have course and/or speed, use course/speed csT bytes. If
+// no course/speed but we have altitude, use altitude csT bytes. We
+// can cheat right now and just always use course/speed, adding
+// altitude with the altitude extension. Not as efficient, but it
+// gets the job done.
+//
+// Later we should change compress_posit() to accept an altitude
+// parameter, and have it decide which csT set of bytes to add, and
+// whether to add altitude as an uncompressed extension if
+// necessary.
+
+
+ // Need to handle the conversion of numeric overlay
+ // chars to "a-j" here.
+ if (last_obj_overlay >= '0' && last_obj_overlay <= '9') {
+ temp_overlay = last_obj_overlay + 'a';
+ }
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%s%s",
+ last_object,
+ time,
+ compress_posit(ext_lat_str,
+ (temp_overlay) ? temp_overlay : last_obj_grp,
+ ext_lon_str,
+ last_obj_sym,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank in this case
+ altitude,
+ signpost);
+
+ comment_field_used = strlen(line) - 31;
+
+ }
+ else {
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%c%s%c%s%s%s",
+ last_object,
+ time,
+ lat_str,
+ last_obj_grp,
+ lon_str,
+ last_obj_sym,
+ speed_course,
+ altitude,
+ signpost);
+
+ comment_field_used = strlen(line) - 37;
+ }
+
+ } else if (DF_object_enabled) { // A DF'ing object of some type
+ if (Omni_antenna_enabled) {
+
+ if (transmit_compressed_objects_items) {
+ char temp_overlay = last_obj_overlay;
+
+
+// Need to compute "csT" at some point and add it to the object.
+// Until we do that we'll have no course/speed/altitude. Looks like
+// we can have course/speed or altitude, but not both. Must have to
+// add the "/A=000123" stuff to the end if we want both.
+//
+// If we have course and/or speed, use course/speed csT bytes. If
+// no course/speed but we have altitude, use altitude csT bytes. We
+// can cheat right now and just always use course/speed, adding
+// altitude with the altitude extension. Not as efficient, but it
+// gets the job done.
+//
+// Later we should change compress_posit() to accept an altitude
+// parameter, and have it decide which csT set of bytes to add, and
+// whether to add altitude as an uncompressed extension if
+// necessary.
+
+
+ // Need to handle the conversion of numeric overlay
+ // chars to "a-j" here.
+ if (last_obj_overlay >= '0' && last_obj_overlay <= '9') {
+ temp_overlay = last_obj_overlay + 'a';
+ }
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%sDFS%s/%s%s",
+ last_object,
+ time,
+ compress_posit(ext_lat_str,
+ (temp_overlay) ? temp_overlay : last_obj_grp,
+ ext_lon_str,
+ last_obj_sym,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank in this case
+ object_shgd,
+ speed_course,
+ altitude);
+
+ comment_field_used = strlen(line) - 31;
+
+ }
+ else {
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%c%s%cDFS%s/%s%s",
+ last_object,
+ time,
+ lat_str,
+ last_obj_grp,
+ lon_str,
+ last_obj_sym,
+ object_shgd,
+ speed_course,
+ altitude);
+
+ comment_field_used = strlen(line) - 37;
+ }
+
+ } else { // Beam Heading DFS object
+ if (strlen(speed_course) != 7)
+ xastir_snprintf(speed_course,
+ sizeof(speed_course),
+ "000/000");
+
+ temp_ptr = XmTextFieldGetString(ob_bearing_data);
+ bearing = atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ if ( (bearing < 1) || (bearing > 360) )
+ bearing = 360;
+
+ if (transmit_compressed_objects_items) {
+ char temp_overlay = last_obj_overlay;
+
+
+// Need to compute "csT" at some point and add it to the object.
+// Until we do that we'll have no course/speed/altitude. Looks like
+// we can have course/speed or altitude, but not both. Must have to
+// add the "/A=000123" stuff to the end if we want both.
+//
+// If we have course and/or speed, use course/speed csT bytes. If
+// no course/speed but we have altitude, use altitude csT bytes. We
+// can cheat right now and just always use course/speed, adding
+// altitude with the altitude extension. Not as efficient, but it
+// gets the job done.
+//
+// Later we should change compress_posit() to accept an altitude
+// parameter, and have it decide which csT set of bytes to add, and
+// whether to add altitude as an uncompressed extension if
+// necessary.
+
+
+ // Need to handle the conversion of numeric overlay
+ // chars to "a-j" here.
+ if (last_obj_overlay >= '0' && last_obj_overlay <= '9') {
+ temp_overlay = last_obj_overlay + 'a';
+ }
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s/%03i/%s%s",
+ last_object,
+ time,
+ compress_posit(ext_lat_str,
+ (temp_overlay) ? temp_overlay : last_obj_grp,
+ ext_lon_str,
+ last_obj_sym,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank in this case
+ bearing,
+ object_NRQ,
+ altitude);
+
+ comment_field_used = strlen(line) - 31;
+
+ }
+ else {
+
+
+ xastir_snprintf(line, line_length, ";%-9s*%s%s%c%s%c%s/%03i/%s%s",
+ last_object,
+ time,
+ lat_str,
+ last_obj_grp,
+ lon_str,
+ last_obj_sym,
+ speed_course,
+ bearing,
+ object_NRQ,
+ altitude);
+
+ comment_field_used = strlen(line) - 37;
+ }
+
+ }
+ } else { // Else it's a normal object
+
+ prob_min[0] = '\0';
+ prob_max[0] = '\0';
+
+ if (Probability_circles_enabled) {
+
+ temp_ptr = XmTextFieldGetString(probability_data_min);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ //fprintf(stderr,"Probability min circle entered: %s\n", line);
+ if (strlen(line) != 0) { // Probability circle data was entered
+ xastir_snprintf(prob_min, sizeof(prob_min), "Pmin%s,", line);
+ }
+
+ temp_ptr = XmTextFieldGetString(probability_data_max);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ //fprintf(stderr,"Probability max circle entered: %s\n", line);
+ if (strlen(line) != 0) { // Probability circle data was entered
+ xastir_snprintf(prob_max, sizeof(prob_max), "Pmax%s,", line);
+ }
+ }
+
+ if (transmit_compressed_objects_items) {
+ char temp_overlay = last_obj_overlay;
+
+
+// Need to compute "csT" at some point and add it to the object.
+// Until we do that we'll have no course/speed/altitude. Looks like
+// we can have course/speed or altitude, but not both. Must have to
+// add the "/A=000123" stuff to the end if we want both.
+//
+// If we have course and/or speed, use course/speed csT bytes. If
+// no course/speed but we have altitude, use altitude csT bytes. We
+// can cheat right now and just always use course/speed, adding
+// altitude with the altitude extension. Not as efficient, but it
+// gets the job done.
+//
+// Later we should change compress_posit() to accept an altitude
+// parameter, and have it decide which csT set of bytes to add, and
+// whether to add altitude as an uncompressed extension if
+// necessary.
+
+
+ // Need to handle the conversion of numeric overlay
+ // chars to "a-j" here.
+ if (last_obj_overlay >= '0' && last_obj_overlay <= '9') {
+ temp_overlay = last_obj_overlay + 'a';
+ }
+
+ xastir_snprintf(line,
+ line_length,
+ ";%-9s*%s%s%s%s%s",
+ last_object,
+ time,
+ compress_posit(ext_lat_str,
+ (temp_overlay) ? temp_overlay : last_obj_grp,
+ ext_lon_str,
+ last_obj_sym,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank in this case
+ altitude,
+ prob_min,
+ prob_max);
+
+ comment_field_used = strlen(line) - 31;
+
+ }
+ else {
+ xastir_snprintf(line,
+ line_length,
+ ";%-9s*%s%s%c%s%c%s%s%s%s",
+ last_object,
+ time,
+ lat_str,
+ last_obj_overlay ? last_obj_overlay : last_obj_grp,
+ lon_str,
+ last_obj_sym,
+ speed_course,
+ altitude,
+ prob_min,
+ prob_max);
+
+ comment_field_used = strlen(line) - 37;
+
+ }
+ }
+
+
+ // We need to tack the comment on the end, but need to make
+ // sure we don't go over the maximum length for an object. The
+ // maximum comment field is 43 chars. "comment_field_used"
+ // tells us how many chars of that field we've used up already
+ // with other parameters before adding the comment chars to the
+ // end.
+ //
+ //fprintf(stderr,"Comment: %s\n",comment);
+ if (strlen(comment) != 0) {
+
+ if (comment[0] == '}') {
+ // May be a multipoint polygon string at the start of
+ // the comment field. Add a space before this special
+ // character as multipoints have to start with " }" to
+ // be valid.
+ line[strlen(line) + 1] = '\0';
+ line[strlen(line)] = ' ';
+
+ comment_field_used++;
+ }
+
+ temp = 0;
+// while ( (strlen(line) < 80) && (temp < (int)strlen(comment)) ) {
+ while ((comment_field_used < 43) && (temp < (int)strlen(comment)) ) {
+ //fprintf(stderr,"temp: %d->%d\t%c\n", temp, strlen(line), comment[temp]);
+ line[strlen(line) + 1] = '\0';
+ line[strlen(line)] = comment[temp++];
+ comment_field_used++;
+ }
+ }
+ //fprintf(stderr,"line: %s\n",line);
+
+// NOTE: Compressed mode will be shorter still. Account
+// for that when compressed mode is implemented for objects.
+
+ return(1);
+}
+
+
+
+
+
+// Convert this eventually to populate a DataRow struct, then call
+// data.c:Create_object_item_tx_string(). Right now we have a lot
+// of code duplication between Setup_object_data, Setup_item_data,
+// and Create_object_item_tx_string.
+//
+// Make sure to look at the "transmit_compressed_objects_items" variable
+// to decide whether to send a compressed packet.
+/*
+ * Setup APRS Information Field for Items
+ */
+int Setup_item_data(char *line, int line_length, DataRow *p_station) {
+ char lat_str[MAX_LAT];
+ char lon_str[MAX_LONG];
+ char ext_lat_str[20]; // Extended precision for base91 compression
+ char ext_lon_str[20]; // Extended precision for base91 compression
+ char comment[43+1]; // max 43 characters of comment
+ char complete_area_color[3];
+ int complete_area_type;
+ int lat_offset, lon_offset;
+ char complete_corridor[6];
+ char altitude[10];
+ char speed_course[8];
+ int speed;
+ int course;
+ int temp;
+ long temp2;
+ float temp3;
+ char tempstr[MAX_CALLSIGN+1];
+ char signpost[6];
+ char prob_min[20+1];
+ char prob_max[20+1];
+ int bearing;
+ char *temp_ptr;
+ char *temp_ptr2;
+ int DR = 0; // Dead-reckoning flag
+ int comment_field_used = 0; // Amount of comment field used up
+
+
+ // If speed for the original object was non-zero, then we need
+ // to snag the updated DR'ed position for the object. Snag the
+ // current DR position and build the strings we need // for
+ // position transmit.
+ //
+ if (p_station != NULL) {
+
+ speed = atoi(p_station->speed);
+
+ if (speed > 0 && !doing_move_operation) {
+
+ fetch_current_DR_strings(p_station,
+ lat_str,
+ lon_str,
+ ext_lat_str,
+ ext_lon_str);
+ DR++; // Set the dead-reckoning flag
+ }
+
+ // Keep the time current for our own items.
+ p_station->sec_heard = sec_now();
+ move_station_time(p_station,NULL);
+ }
+
+ temp_ptr = XmTextFieldGetString(object_name_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(line);
+ //(void)to_upper(line); Not per spec. Don't use this.
+
+ xastir_snprintf(tempstr,
+ sizeof(tempstr),
+ "%s",
+ line);
+
+ if (strlen(line) == 1) // Add two spaces (to make 3 minimum chars)
+ xastir_snprintf(line, line_length, "%s ", tempstr);
+
+ else if (strlen(line) == 2) // Add one space (to make 3 minimum chars)
+ xastir_snprintf(line, line_length, "%s ", tempstr);
+
+ if (!valid_item(line))
+ return(0);
+
+ xastir_snprintf(last_object,
+ sizeof(last_object),
+ "%s",
+ line);
+
+
+ if (!DR) { // We're not doing dead-reckoning, so proceed
+
+ temp_ptr = XmTextFieldGetString(object_lat_data_ns);
+ if((char)toupper((int)temp_ptr[0]) == 'S')
+ line[0] = 'S';
+ else
+ line[0] = 'N';
+ XtFree(temp_ptr);
+
+ // Check latitude for out-of-bounds
+ temp_ptr = XmTextFieldGetString(object_lat_data_deg);
+ temp = atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ if ( (temp > 90) || (temp < 0) )
+ return(0);
+
+ temp_ptr = XmTextFieldGetString(object_lat_data_min);
+ temp3 = atof(temp_ptr);
+ XtFree(temp_ptr);
+
+ if ( (temp3 >= 60.0) || (temp3 < 0.0) )
+ return(0);
+
+ if ( (temp == 90) && (temp3 != 0.0) )
+ return(0);
+
+ temp_ptr = XmTextFieldGetString(object_lat_data_deg);
+ temp_ptr2 = XmTextFieldGetString(object_lat_data_min);
+ xastir_snprintf(lat_str, sizeof(lat_str), "%02d%05.2f%c",
+ atoi(temp_ptr),
+// An attempt was made to round here, adding 0.001 to the minutes
+// value. Problems arise if it goes above 59 minutes as the degrees
+// value would need to bump up also. This then gets into problems
+// at 90.0 degrees. The correct method would be to convert it to
+// decimal at a higher precision and then convert it back to DD
+// MM.MM format.
+// atof(temp_ptr2) + 0.001,
+ atof(temp_ptr2),
+ line[0]);
+ XtFree(temp_ptr);
+ XtFree(temp_ptr2);
+
+ temp_ptr = XmTextFieldGetString(object_lat_data_deg);
+ temp_ptr2 = XmTextFieldGetString(object_lat_data_min);
+ xastir_snprintf(ext_lat_str, sizeof(ext_lat_str), "%02d%05.3f%c",
+ atoi(temp_ptr),
+// An attempt was made to round here, adding 0.0001 to the minutes
+// value. Problems arise if it goes above 59 minutes as the degrees
+// value would need to bump up also. This then gets into problems
+// at 90.0 degrees. The correct method would be to convert it to
+// decimal at a higher precision and then convert it back to DD
+// MM.MM format.
+// atof(temp_ptr2) + 0.0001,
+ atof(temp_ptr2),
+ line[0]);
+ XtFree(temp_ptr);
+ XtFree(temp_ptr2);
+
+ temp_ptr = XmTextFieldGetString(object_lon_data_ew);
+ if((char)toupper((int)temp_ptr[0]) == 'E')
+ line[0] = 'E';
+ else
+ line[0] = 'W';
+ XtFree(temp_ptr);
+
+ // Check longitude for out-of-bounds
+ temp_ptr = XmTextFieldGetString(object_lon_data_deg);
+ temp = atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ if ( (temp > 180) || (temp < 0) )
+ return(0);
+
+ temp_ptr = XmTextFieldGetString(object_lon_data_min);
+ temp3 = atof(temp_ptr);
+ XtFree(temp_ptr);
+
+ if ( (temp3 >= 60.0) || (temp3 < 0.0) )
+ return(0);
+
+ if ( (temp == 180) && (temp3 != 0.0) )
+ return(0);
+
+ temp_ptr = XmTextFieldGetString(object_lon_data_deg);
+ temp_ptr2 = XmTextFieldGetString(object_lon_data_min);
+ xastir_snprintf(lon_str, sizeof(lon_str), "%03d%05.2f%c",
+ atoi(temp_ptr),
+// An attempt was made to round here, adding 0.001 to the minutes
+// value. Problems arise if it goes above 59 minutes as the degrees
+// value would need to bump up also. This then gets into problems
+// at 90.0 degrees. The correct method would be to convert it to
+// decimal at a higher precision and then convert it back to DD
+// MM.MM format.
+// atof(temp_ptr2) + 0.001,
+ atof(temp_ptr2),
+ line[0]);
+ XtFree(temp_ptr);
+ XtFree(temp_ptr2);
+
+ temp_ptr = XmTextFieldGetString(object_lon_data_deg);
+ temp_ptr2 = XmTextFieldGetString(object_lon_data_min);
+ xastir_snprintf(ext_lon_str, sizeof(ext_lon_str), "%03d%05.3f%c",
+ atoi(temp_ptr),
+// An attempt was made to round here, adding 0.0001 to the minutes
+// value. Problems arise if it goes above 59 minutes as the degrees
+// value would need to bump up also. This then gets into problems
+// at 90.0 degrees. The correct method would be to convert it to
+// decimal at a higher precision and then convert it back to DD
+// MM.MM format.
+// atof(temp_ptr2) + 0.0001,
+ atof(temp_ptr2),
+ line[0]);
+ XtFree(temp_ptr);
+ XtFree(temp_ptr2);
+ }
+
+
+ temp_ptr = XmTextFieldGetString(object_group_data);
+ last_obj_grp = temp_ptr[0];
+ if(isalpha((int)last_obj_grp))
+ last_obj_grp = toupper((int)temp_ptr[0]); // todo: toupper in dialog
+ XtFree(temp_ptr);
+
+ // Check for overlay character
+ if (last_obj_grp != '/' && last_obj_grp != '\\') {
+ // Found an overlay character. Check that it's within the
+ // proper range
+ if ( (last_obj_grp >= '0' && last_obj_grp <= '9')
+ || (last_obj_grp >= 'A' && last_obj_grp <= 'Z') ) {
+ last_obj_overlay = last_obj_grp;
+ last_obj_grp = '\\';
+ }
+ else {
+ last_obj_overlay = '\0';
+ }
+ }
+ else {
+ last_obj_overlay = '\0';
+ }
+
+ temp_ptr = XmTextFieldGetString(object_symbol_data);
+ last_obj_sym = temp_ptr[0];
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(object_comment_data);
+ xastir_snprintf(comment,
+ sizeof(comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(comment);
+
+ // Handle Generic Options
+
+ // Speed/Course Fields
+ temp_ptr = XmTextFieldGetString(ob_course_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ sprintf(speed_course,".../"); // Start with invalid-data string
+ course = 0;
+ if (strlen(line) != 0) { // Course was entered
+ // Need to check for 1 to three digits only, and 001-360 degrees)
+ temp = atoi(line);
+ if ( (temp >= 1) && (temp <= 360) ) {
+ xastir_snprintf(speed_course, sizeof(speed_course), "%03d/", temp);
+ course = temp;
+ } else if (temp == 0) { // Spec says 001 to 360 degrees...
+ sprintf(speed_course, "360/");
+ }
+ }
+ temp_ptr = XmTextFieldGetString(ob_speed_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ speed = 0;
+ if (strlen(line) != 0) { // Speed was entered (we only handle knots currently)
+ // Need to check for 1 to three digits, no alpha characters
+ temp = atoi(line);
+ if ( (temp >= 0) && (temp <= 999) ) {
+ xastir_snprintf(line, line_length, "%03d", temp);
+ strncat(speed_course,
+ line,
+ sizeof(speed_course) - 1 - strlen(speed_course));
+ speed = temp;
+ } else {
+ strncat(speed_course,
+ "...",
+ sizeof(speed_course) - 1 - strlen(speed_course));
+ }
+ } else { // No speed entered, blank it out
+ strncat(speed_course,
+ "...",
+ sizeof(speed_course) - 1 - strlen(speed_course));
+ }
+ if ( (speed_course[0] == '.') && (speed_course[4] == '.') ) {
+ speed_course[0] = '\0'; // No speed or course entered, so blank it
+ }
+
+ if (Area_object_enabled) {
+ speed_course[0] = '\0'; // Course/Speed not allowed if Area Object
+ }
+
+ // Altitude Field
+ temp_ptr = XmTextFieldGetString(ob_altitude_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ //fprintf(stderr,"Altitude entered: %s\n", line);
+ altitude[0] = '\0'; // Start with empty string
+ if (strlen(line) != 0) { // Altitude was entered (we only handle feet currently)
+ // Need to check for all digits, and 1 to 6 digits
+ if (isdigit((int)line[0])) {
+ temp2 = atoi(line);
+ if ((temp2 >= 0) && (temp2 <= 999999)) {
+ xastir_snprintf(altitude, sizeof(altitude), "/A=%06ld",temp2);
+ }
+ }
+ }
+
+ // Handle Specific Options
+
+ // Area Items
+ if (Area_object_enabled) {
+ if (Area_bright) { // Bright color
+ xastir_snprintf(complete_area_color, sizeof(complete_area_color), "%2s",
+ Area_color);
+ } else { // Dim color
+ xastir_snprintf(complete_area_color, sizeof(complete_area_color), "%02d",
+ atoi(&Area_color[1]) + 8);
+ if ((Area_color[1] == '0') || (Area_color[1] == '1')) {
+ complete_area_color[0] = '/';
+ }
+ }
+ if ( (Area_filled) && (Area_type != 1) && (Area_type != 6) ) {
+ complete_area_type = Area_type + 5;
+ } else { // Can't fill in a line
+ complete_area_type = Area_type;
+ }
+ temp_ptr = XmTextFieldGetString(ob_lat_offset_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ lat_offset = (int)sqrt(atof(line));
+ if (lat_offset > 99)
+ lat_offset = 99;
+ //fprintf(stderr,"Line: %s\tlat_offset: %d\n", line, lat_offset);
+ temp_ptr = XmTextFieldGetString(ob_lon_offset_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ lon_offset = (int)sqrt(atof(line));
+ if (lon_offset > 99)
+ lon_offset = 99;
+ //fprintf(stderr,"Line: %s\tlon_offset: %d\n", line, lon_offset);
+
+ // Corridor
+ complete_corridor[0] = '\0';
+ if ( (Area_type == 1) || (Area_type == 6) ) {
+
+ temp_ptr = XmTextFieldGetString(ob_corridor_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ if (strlen(line) != 0) { // We have a line and some corridor data
+ // Need to check for 1 to three digits only
+ temp = atoi(line);
+ if ( (temp > 0) && (temp <= 999) ) {
+ xastir_snprintf(complete_corridor, sizeof(complete_corridor), "{%d}", temp);
+ //fprintf(stderr,"%s\n",complete_corridor);
+ }
+ }
+ }
+
+ if (transmit_compressed_objects_items) {
+ char temp_overlay = last_obj_overlay;
+
+
+// Need to compute "csT" at some point and add it to the object.
+// Until we do that we'll have no course/speed/altitude. Looks like
+// we can have course/speed or altitude, but not both. Must have to
+// add the "/A=000123" stuff to the end if we want both.
+//
+// If we have course and/or speed, use course/speed csT bytes. If
+// no course/speed but we have altitude, use altitude csT bytes. We
+// can cheat right now and just always use course/speed, adding
+// altitude with the altitude extension. Not as efficient, but it
+// gets the job done.
+//
+// Later we should change compress_posit() to accept an altitude
+// parameter, and have it decide which csT set of bytes to add, and
+// whether to add altitude as an uncompressed extension if
+// necessary.
+
+
+ // Need to handle the conversion of numeric overlay
+ // chars to "a-j" here.
+ if (last_obj_overlay >= '0' && last_obj_overlay <= '9') {
+ temp_overlay = last_obj_overlay + 'a';
+ }
+
+ xastir_snprintf(line, line_length, ")%s!%s%1d%02d%2s%02d%s%s%s",
+ last_object,
+ compress_posit(ext_lat_str,
+ (temp_overlay) ? temp_overlay : last_obj_grp,
+ ext_lon_str,
+ last_obj_sym,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank in this case
+ complete_area_type,
+ lat_offset,
+ complete_area_color,
+ lon_offset,
+ speed_course,
+ complete_corridor,
+ altitude);
+
+ comment_field_used = strlen(line) - 15 - strlen(last_object);
+
+ }
+ else {
+
+ xastir_snprintf(line, line_length, ")%s!%s%c%s%c%1d%02d%2s%02d%s%s%s",
+ last_object,
+ lat_str,
+ last_obj_grp,
+ lon_str,
+ last_obj_sym,
+ complete_area_type,
+ lat_offset,
+ complete_area_color,
+ lon_offset,
+ speed_course,
+ complete_corridor,
+ altitude);
+
+ comment_field_used = strlen(line) - 21 - strlen(last_object);
+ }
+
+ } else if (Signpost_object_enabled) {
+ temp_ptr = XmTextFieldGetString(signpost_data);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ //fprintf(stderr,"Signpost entered: %s\n", line);
+ if (strlen(line) != 0) { // Signpost data was entered
+ // Need to check for between one and three characters
+ temp = strlen(line);
+ if ( (temp >= 0) && (temp <= 3) ) {
+ xastir_snprintf(signpost, sizeof(signpost), "{%s}", line);
+ } else {
+ signpost[0] = '\0';
+ }
+ } else { // No signpost data entered, blank it out
+ signpost[0] = '\0';
+ }
+
+ if (transmit_compressed_objects_items) {
+ char temp_overlay = last_obj_overlay;
+
+
+// Need to compute "csT" at some point and add it to the object.
+// Until we do that we'll have no course/speed/altitude. Looks like
+// we can have course/speed or altitude, but not both. Must have to
+// add the "/A=000123" stuff to the end if we want both.
+//
+// If we have course and/or speed, use course/speed csT bytes. If
+// no course/speed but we have altitude, use altitude csT bytes. We
+// can cheat right now and just always use course/speed, adding
+// altitude with the altitude extension. Not as efficient, but it
+// gets the job done.
+//
+// Later we should change compress_posit() to accept an altitude
+// parameter, and have it decide which csT set of bytes to add, and
+// whether to add altitude as an uncompressed extension if
+// necessary.
+
+
+ // Need to handle the conversion of numeric overlay
+ // chars to "a-j" here.
+ if (last_obj_overlay >= '0' && last_obj_overlay <= '9') {
+ temp_overlay = last_obj_overlay + 'a';
+ }
+
+ xastir_snprintf(line, line_length, ")%s!%s%s%s",
+ last_object,
+ compress_posit(ext_lat_str,
+ (temp_overlay) ? temp_overlay : last_obj_grp,
+ ext_lon_str,
+ last_obj_sym,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank in this case
+ altitude,
+ signpost);
+
+ comment_field_used = strlen(line) - 15 - strlen(last_object);
+
+ }
+ else {
+
+ xastir_snprintf(line, line_length, ")%s!%s%c%s%c%s%s%s",
+ last_object,
+ lat_str,
+ last_obj_grp,
+ lon_str,
+ last_obj_sym,
+ speed_course,
+ altitude,
+ signpost);
+
+ comment_field_used = strlen(line) - 21 - strlen(last_object);
+ }
+
+ } else if (DF_object_enabled) { // A DF'ing item of some type
+ if (Omni_antenna_enabled) {
+
+ if (transmit_compressed_objects_items) {
+ char temp_overlay = last_obj_overlay;
+
+
+// Need to compute "csT" at some point and add it to the object.
+// Until we do that we'll have no course/speed/altitude. Looks like
+// we can have course/speed or altitude, but not both. Must have to
+// add the "/A=000123" stuff to the end if we want both.
+//
+// If we have course and/or speed, use course/speed csT bytes. If
+// no course/speed but we have altitude, use altitude csT bytes. We
+// can cheat right now and just always use course/speed, adding
+// altitude with the altitude extension. Not as efficient, but it
+// gets the job done.
+//
+// Later we should change compress_posit() to accept an altitude
+// parameter, and have it decide which csT set of bytes to add, and
+// whether to add altitude as an uncompressed extension if
+// necessary.
+
+
+ // Need to handle the conversion of numeric overlay
+ // chars to "a-j" here.
+ if (last_obj_overlay >= '0' && last_obj_overlay <= '9') {
+ temp_overlay = last_obj_overlay + 'a';
+ }
+
+ xastir_snprintf(line, line_length, ")%s!%sDFS%s/%s%s",
+ last_object,
+ compress_posit(ext_lat_str,
+ (temp_overlay) ? temp_overlay : last_obj_grp,
+ ext_lon_str,
+ last_obj_sym,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank in this case
+ object_shgd,
+ speed_course,
+ altitude);
+
+ comment_field_used = strlen(line) - 15 - strlen(last_object);
+
+ }
+ else {
+
+ xastir_snprintf(line, line_length, ")%s!%s%c%s%cDFS%s/%s%s",
+ last_object,
+ lat_str,
+ last_obj_grp,
+ lon_str,
+ last_obj_sym,
+ object_shgd,
+ speed_course,
+ altitude);
+
+ comment_field_used = strlen(line) - 21 - strlen(last_object);
+
+ }
+
+ } else { // Beam Heading DFS item
+ if (strlen(speed_course) != 7)
+ xastir_snprintf(speed_course,
+ sizeof(speed_course),
+ "000/000");
+
+ temp_ptr = XmTextFieldGetString(ob_bearing_data);
+ bearing = atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ if ( (bearing < 1) || (bearing > 360) )
+ bearing = 360;
+
+ if (transmit_compressed_objects_items) {
+ char temp_overlay = last_obj_overlay;
+
+
+// Need to compute "csT" at some point and add it to the object.
+// Until we do that we'll have no course/speed/altitude. Looks like
+// we can have course/speed or altitude, but not both. Must have to
+// add the "/A=000123" stuff to the end if we want both.
+//
+// If we have course and/or speed, use course/speed csT bytes. If
+// no course/speed but we have altitude, use altitude csT bytes. We
+// can cheat right now and just always use course/speed, adding
+// altitude with the altitude extension. Not as efficient, but it
+// gets the job done.
+//
+// Later we should change compress_posit() to accept an altitude
+// parameter, and have it decide which csT set of bytes to add, and
+// whether to add altitude as an uncompressed extension if
+// necessary.
+
+
+ // Need to handle the conversion of numeric overlay
+ // chars to "a-j" here.
+ if (last_obj_overlay >= '0' && last_obj_overlay <= '9') {
+ temp_overlay = last_obj_overlay + 'a';
+ }
+
+ xastir_snprintf(line, line_length, ")%s!%s/%03i/%s%s",
+ last_object,
+ compress_posit(ext_lat_str,
+ (temp_overlay) ? temp_overlay : last_obj_grp,
+ ext_lon_str,
+ last_obj_sym,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank in this case
+ bearing,
+ object_NRQ,
+ altitude);
+
+ comment_field_used = strlen(line) - 15 - strlen(last_object);
+
+ }
+ else {
+
+ xastir_snprintf(line, line_length, ")%s!%s%c%s%c%s/%03i/%s%s",
+ last_object,
+ lat_str,
+ last_obj_grp,
+ lon_str,
+ last_obj_sym,
+ speed_course,
+ bearing,
+ object_NRQ,
+ altitude);
+
+ comment_field_used = strlen(line) - 21 - strlen(last_object);
+ }
+
+ }
+ } else { // Else it's a normal item
+
+ prob_min[0] = '\0';
+ prob_max[0] = '\0';
+
+ if (Probability_circles_enabled) {
+
+ temp_ptr = XmTextFieldGetString(probability_data_min);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ //fprintf(stderr,"Probability min circle entered: %s\n",
+ //line);
+ if (strlen(line) != 0) { // Probability circle data was entered
+ xastir_snprintf(prob_min, sizeof(prob_min), "Pmin%s,", line);
+ }
+
+ temp_ptr = XmTextFieldGetString(probability_data_max);
+ xastir_snprintf(line, line_length, "%s", temp_ptr);
+ XtFree(temp_ptr);
+
+ //fprintf(stderr,"Probability max circle entered: %s\n",
+ //line);
+ if (strlen(line) != 0) { // Probability circle data was entered
+ xastir_snprintf(prob_max, sizeof(prob_max), "Pmax%s,", line);
+ }
+ }
+
+
+ if (transmit_compressed_objects_items) {
+ char temp_overlay = last_obj_overlay;
+
+
+// Need to compute "csT" at some point and add it to the object.
+// Until we do that we'll have no course/speed/altitude. Looks like
+// we can have course/speed or altitude, but not both. Must have to
+// add the "/A=000123" stuff to the end if we want both.
+//
+// If we have course and/or speed, use course/speed csT bytes. If
+// no course/speed but we have altitude, use altitude csT bytes. We
+// can cheat right now and just always use course/speed, adding
+// altitude with the altitude extension. Not as efficient, but it
+// gets the job done.
+//
+// Later we should change compress_posit() to accept an altitude
+// parameter, and have it decide which csT set of bytes to add, and
+// whether to add altitude as an uncompressed extension if
+// necessary.
+
+
+ // Need to handle the conversion of numeric overlay
+ // chars to "a-j" here.
+ if (last_obj_overlay >= '0' && last_obj_overlay <= '9') {
+ temp_overlay = last_obj_overlay + 'a';
+ }
+
+ xastir_snprintf(line,
+ line_length,
+ ")%s!%s%s%s%s",
+ last_object,
+ compress_posit(ext_lat_str,
+ (temp_overlay) ? temp_overlay : last_obj_grp,
+ ext_lon_str,
+ last_obj_sym,
+ course,
+ speed, // In knots
+ ""), // PHG, must be blank in this case
+ altitude,
+ prob_min,
+ prob_max);
+
+ comment_field_used = strlen(line) - 15 - strlen(last_object);
+
+ }
+ else {
+ xastir_snprintf(line,
+ line_length,
+ ")%s!%s%c%s%c%s%s%s%s",
+ last_object,
+ lat_str,
+ last_obj_overlay ? last_obj_overlay : last_obj_grp,
+ lon_str,
+ last_obj_sym,
+ speed_course,
+ altitude,
+ prob_min,
+ prob_max);
+
+ comment_field_used = strlen(line) - 21 - strlen(last_object);
+
+ }
+ }
+
+
+ // We need to tack the comment on the end, but need to make
+ // sure we don't go over the maximum length for an item.
+ //fprintf(stderr,"Comment: %s\n",comment);
+ if (strlen(comment) != 0) {
+
+ if (comment[0] == '}') {
+ // May be a multipoint polygon string at the start of
+ // the comment field. Add a space before this special
+ // character as multipoints have to start with " }" to
+ // be valid.
+ line[strlen(line) + 1] = '\0';
+ line[strlen(line)] = ' ';
+ comment_field_used++;
+ }
+
+ temp = 0;
+// while ( (strlen(line) < (64 + strlen(last_object))) && (temp < (int)strlen(comment)) ) {
+ while ( (comment_field_used < 43) && (temp < (int)strlen(comment)) ) {
+ //fprintf(stderr,"temp: %d->%d\t%c\n", temp, strlen(line), comment[temp]);
+ line[strlen(line) + 1] = '\0';
+ line[strlen(line)] = comment[temp++];
+ comment_field_used++;
+ }
+ }
+ //fprintf(stderr,"line: %s\n",line);
+
+// NOTE: Compressed mode will be shorter still. Account
+// for that when compressed mode is implemented for items.
+
+ return(1);
+}
+
+
+
+
+
+
+/*
+ * Set an Object
+ */
+void Object_change_data_set(/*@unused@*/ Widget widget, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char line[43+1+40]; // ???
+ DataRow *p_station = global_parameter1;
+
+ //fprintf(stderr,"Object_change_data_set\n");
+
+ // p_station will be NULL if the object is new.
+ if (Setup_object_data(line, sizeof(line), p_station)) {
+
+ // Update this object in our save file
+ log_object_item(line,0,last_object);
+
+ // Set up the timer properly for the decaying algorithm
+ if (p_station != NULL) {
+ p_station->transmit_time_increment = OBJECT_CHECK_RATE;
+ p_station->last_transmit_time = sec_now();
+
+ // Keep the time current for our own objects.
+ p_station->sec_heard = sec_now();
+ move_station_time(p_station,NULL);
+
+// p_station->last_modified_time = sec_now(); // For dead-reckoning
+//fprintf(stderr,"Object_change_data_set(): Setting transmit increment to %d\n", OBJECT_CHECK_RATE);
+ }
+
+ if (object_tx_disable || transmit_disable)
+ output_my_data(line,-1,0,1,0,NULL); // Local loopback only, not igating
+ else
+ output_my_data(line,-1,0,0,0,NULL); // Transmit/loopback object data, not igating
+
+ sched_yield(); // Wait for transmitted data to get processed
+ Object_destroy_shell(widget,clientData,NULL);
+ // Getting a segfault here on a Move operation, so just
+ // comment it out. A redraw will occur shortly anyway.
+ //redraw_symbols(da);
+ (void)XCopyArea(XtDisplay(da),
+ pixmap_final,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ } else {
+ // error message
+ popup_message_always(langcode("POPEM00022"),langcode("POPEM00027"));
+ }
+}
+
+
+
+
+
+/*
+ * Set an Item
+ */
+void Item_change_data_set(/*@unused@*/ Widget widget, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char line[43+1+40]; // ???
+ DataRow *p_station = global_parameter1;
+
+
+ if (Setup_item_data(line,sizeof(line), p_station)) {
+
+ // Update this item in our save file
+ log_object_item(line,0,last_object);
+
+ // Set up the timer properly for the decaying algorithm
+ if (p_station != NULL) {
+ p_station->transmit_time_increment = OBJECT_CHECK_RATE;
+ p_station->last_transmit_time = sec_now();
+
+ // Keep the time current for our own items.
+ p_station->sec_heard = sec_now();
+ move_station_time(p_station,NULL);
+
+// p_station->last_modified_time = sec_now(); // For dead-reckoning
+//fprintf(stderr,"Item_change_data_set(): Setting transmit increment to %d\n", OBJECT_CHECK_RATE);
+ }
+
+ if (object_tx_disable || transmit_disable)
+ output_my_data(line,-1,0,1,0,NULL); // Local loopback only, not igating
+ else
+ output_my_data(line,-1,0,0,0,NULL); // Transmit/loopback item data, not igating
+
+ sched_yield(); // Wait for transmitted data to get processed
+ Object_destroy_shell(widget,clientData,NULL);
+ // Getting a segfault here on a Move operation, so just
+ // comment it out. A redraw will occur shortly anyway.
+ //redraw_symbols(da);
+ (void)XCopyArea(XtDisplay(da),
+ pixmap_final,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ } else {
+ // error message
+ popup_message_always(langcode("POPEM00022"),langcode("POPEM00027"));
+ }
+}
+
+
+
+
+
+// Check the name of a new Object. If it already exists in our
+// database, warn the user. Confirmation dialog to continue?
+//
+void Object_confirm_data_set(Widget widget, XtPointer clientData, XtPointer callData) {
+ char *temp_ptr;
+ char line[MAX_CALLSIGN+1];
+ DataRow *p_station;
+
+
+ temp_ptr = XmTextFieldGetString(object_name_data);
+ xastir_snprintf(line,
+ sizeof(line),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_leading_spaces(line);
+ (void)remove_trailing_spaces(line);
+
+ //fprintf(stderr,"Object name:%s\n", line);
+
+ // We have the name now. Check it against our database of
+ // stations/objects/items. Do an exact match.
+ //
+ if (search_station_name(&p_station,line,1)
+ && (p_station->flag & ST_ACTIVE)) {
+ // Found a live object with that name. Don't allow Object
+ // creation. Bring up a warning message instead.
+ popup_message_always(langcode("POPEM00035"), langcode("POPEM00038"));
+ }
+ else {
+
+ // Not found. Allow the Object to be created.
+ Object_change_data_set(widget, clientData, callData);
+ }
+}
+
+
+
+
+
+// Check the name of a new Item. If it already exists in our
+// database, warn the user. Confirmation dialog to continue?
+//
+void Item_confirm_data_set(Widget widget, XtPointer clientData, XtPointer callData) {
+ char *temp_ptr;
+ char line[MAX_CALLSIGN+1];
+ DataRow *p_station;
+
+
+ temp_ptr = XmTextFieldGetString(object_name_data);
+ xastir_snprintf(line,
+ sizeof(line),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_leading_spaces(line);
+ (void)remove_trailing_spaces(line);
+
+ //fprintf(stderr,"Item name:%s\n", line);
+
+ // We have the name now. Check it against our database of
+ // stations/objects/items. Do an exact match.
+ //
+ if (search_station_name(&p_station,line,1)
+ && (p_station->flag & ST_ACTIVE)) {
+ // Found a live object with that name. Don't allow Object
+ // creation. Bring up a warning message instead.
+ popup_message_always(langcode("POPEM00035"), langcode("POPEM00038"));
+ }
+ else {
+
+ // Not found. Allow the Item to be created.
+ Item_change_data_set(widget, clientData, callData);
+ }
+}
+
+
+
+
+
+/*
+ * Delete an Object
+ */
+void Object_change_data_del(/*@unused@*/ Widget widget, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char line[43+1+40]; // ???
+ DataRow *p_station = global_parameter1;
+
+
+ if (Setup_object_data(line, sizeof(line), p_station)) {
+
+ line[10] = '_'; // mark as deleted object
+
+ // Update this object in our save file, then comment all
+ // instances out in the file.
+ log_object_item(line,1,last_object);
+
+ // Set up the timer properly for the decaying algorithm
+ if (p_station != NULL) {
+ p_station->transmit_time_increment = OBJECT_CHECK_RATE;
+ p_station->last_transmit_time = sec_now();
+// p_station->last_modified_time = sec_now(); // For dead-reckoning
+//fprintf(stderr,"Object_change_data_del(): Setting transmit increment to %d\n", OBJECT_CHECK_RATE);
+ }
+
+ if (object_tx_disable || transmit_disable)
+ output_my_data(line,-1,0,1,0,NULL); // Local loopback only, not igating
+ else
+ output_my_data(line,-1,0,0,0,NULL); // Transmit object data, not igating
+
+ Object_destroy_shell(widget,clientData,NULL);
+ }
+}
+
+
+
+
+
+/*
+ * Delete an Item
+ */
+void Item_change_data_del(/*@unused@*/ Widget widget, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char line[43+1+40]; // ???
+ int i, done;
+ DataRow *p_station = global_parameter1;
+
+
+ if (Setup_item_data(line,sizeof(line), p_station)) {
+
+ done = 0;
+ i = 0;
+ while ( (!done) && (i < 11) ) {
+ if (line[i] == '!') {
+ line[i] = '_'; // mark as deleted object
+ done++; // Exit from loop
+ }
+ i++;
+ }
+
+ // Update this item in our save file, then comment all
+ // instances out in the file.
+ log_object_item(line,1,last_object);
+
+ // Set up the timer properly for the decaying algorithm
+ if (p_station != NULL) {
+ p_station->transmit_time_increment = OBJECT_CHECK_RATE;
+ p_station->last_transmit_time = sec_now();
+// p_station->last_modified_time = sec_now(); // For dead-reckoning
+//fprintf(stderr,"Item_change_data_del(): Setting transmit increment to %d\n", OBJECT_CHECK_RATE);
+ }
+
+ if (object_tx_disable || transmit_disable)
+ output_my_data(line,-1,0,1,0,NULL); // Local loopback only, not igating
+ else
+ output_my_data(line,-1,0,0,0,NULL); // Transmit item data, not igating
+
+ Object_destroy_shell(widget,clientData,NULL);
+ }
+}
+
+
+
+
+
+/*
+ * Select a symbol graphically
+ */
+void Ob_change_symbol(/*@unused@*/ Widget widget, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ //fprintf(stderr,"Trying to change a symbol\n");
+ symbol_change_requested_from = 2; // Tell Select_symbol who to return the data to
+ Select_symbol(widget, clientData, callData);
+}
+
+
+
+
+
+/*
+ * Update symbol picture for changed symbol or table
+ */
+void updateObjectPictureCallback(/*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ char table, overlay;
+ char symb, group;
+ char *temp_ptr;
+
+
+ XtVaSetValues(object_icon, XmNlabelPixmap, Ob_icon0, NULL); // clear old icon
+ XtManageChild(object_icon);
+
+ temp_ptr = XmTextFieldGetString(object_group_data);
+ group = temp_ptr[0];
+ XtFree(temp_ptr);
+
+ temp_ptr = XmTextFieldGetString(object_symbol_data);
+ symb = temp_ptr[0];
+ XtFree(temp_ptr);
+
+ if (group == '/' || group == '\\') {
+ // No overlay character
+ table = group;
+ overlay = ' ';
+ } else {
+ // Found overlay character. Check that it's a valid
+ // overlay.
+ if ( (group >= '0' && group <= '9')
+ || (group >= 'A' && group <= 'Z') ) {
+ // Valid overlay character
+ table = '\\';
+ overlay = group;
+ }
+ else {
+ // Bad overlay character
+ table = '\\';
+ overlay = ' ';
+ }
+ }
+ symbol(object_icon,0,table,symb,overlay,Ob_icon,0,0,0,' '); // create icon
+
+ XtVaSetValues(object_icon,XmNlabelPixmap,Ob_icon,NULL); // draw new icon
+ XtManageChild(object_icon);
+}
+
+
+
+
+
+// Handler for "Signpost" toggle button
+void Signpost_object_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+ char temp_data[40];
+ char comment[43+1]; // max 43 characters of comment
+ char signpost_name[10];
+ char *temp_ptr;
+
+
+ // Save name and comment fields temporarily
+ temp_ptr = XmTextFieldGetString(object_name_data);
+ xastir_snprintf(signpost_name,
+ sizeof(signpost_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(signpost_name);
+
+ temp_ptr = XmTextFieldGetString(object_comment_data);
+ xastir_snprintf(comment,
+ sizeof(comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(comment);
+
+
+ if(state->set) {
+ Signpost_object_enabled = 1;
+ Area_object_enabled = 0;
+ DF_object_enabled = 0;
+ Map_View_object_enabled = 0;
+ Probability_circles_enabled = 0;
+
+ //fprintf(stderr,"Signpost Objects are ENABLED\n");
+
+ // Call Set_Del_Object again, causing it to redraw with the new options.
+ //Set_Del_Object( widget, clientData, callData );
+ Set_Del_Object( widget, global_parameter1, global_parameter2 );
+
+ XmToggleButtonSetState(area_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(df_bearing_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(map_view_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(probabilities_toggle, FALSE, FALSE);
+
+ temp_data[0] = '\\';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = 'm';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ XtSetSensitive(ob_frame,FALSE);
+
+ // update symbol picture
+ (void)updateObjectPictureCallback((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
+ }
+ else {
+ Signpost_object_enabled = 0;
+
+ //fprintf(stderr,"Signpost Objects are DISABLED\n");
+
+ // Call Set_Del_Object again, causing it to redraw with the new options.
+ //Set_Del_Object( widget, clientData, callData );
+ Set_Del_Object( widget, global_parameter1, global_parameter2 );
+
+
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ XtSetSensitive(ob_frame,TRUE);
+
+ // update symbol picture
+ (void)updateObjectPictureCallback((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
+ }
+
+ // Restore name and comment fields
+ XmTextFieldSetString(object_name_data,signpost_name);
+ XmTextFieldSetString(object_comment_data,comment);
+}
+
+
+
+
+
+// Handler for "Probability Circles" toggle button
+void Probability_circle_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+ char temp_data[40];
+ char comment[43+1]; // max 43 characters of comment
+ char signpost_name[10];
+ char *temp_ptr;
+
+
+ // Save name and comment fields temporarily
+ temp_ptr = XmTextFieldGetString(object_name_data);
+ xastir_snprintf(signpost_name,
+ sizeof(signpost_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(signpost_name);
+
+ temp_ptr = XmTextFieldGetString(object_comment_data);
+ xastir_snprintf(comment,
+ sizeof(comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(comment);
+
+
+ if(state->set) {
+ Signpost_object_enabled = 0;
+ Area_object_enabled = 0;
+ DF_object_enabled = 0;
+ Map_View_object_enabled = 0;
+ Probability_circles_enabled = 1;
+
+ //fprintf(stderr,"Probability Circles are ENABLED\n");
+
+ // Call Set_Del_Object again, causing it to redraw with the new options.
+ //Set_Del_Object( widget, clientData, callData );
+ Set_Del_Object( widget, global_parameter1, global_parameter2 );
+
+ XmToggleButtonSetState(area_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(df_bearing_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(map_view_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(signpost_toggle, FALSE, FALSE);
+
+ // Set to hiker symbol by default, but can be changed by
+ // user to something else.
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = '[';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ // update symbol picture
+ (void)updateObjectPictureCallback((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
+ }
+ else {
+ Probability_circles_enabled = 0;
+
+ //fprintf(stderr,"Signpost Objects are DISABLED\n");
+
+ // Call Set_Del_Object again, causing it to redraw with the new options.
+ //Set_Del_Object( widget, clientData, callData );
+ Set_Del_Object( widget, global_parameter1, global_parameter2 );
+
+
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ XtSetSensitive(ob_frame,TRUE);
+
+ // update symbol picture
+ (void)updateObjectPictureCallback((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
+ }
+
+ // Restore name and comment fields
+ XmTextFieldSetString(object_name_data,signpost_name);
+ XmTextFieldSetString(object_comment_data,comment);
+}
+
+
+
+
+
+// Handler for "Enable Area Type" toggle button
+void Area_object_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+ char temp_data[40];
+ char comment[43+1]; // max 43 characters of comment
+ char signpost_name[10];
+ char *temp_ptr;
+
+
+ // Save name and comment fields temporarily
+ temp_ptr = XmTextFieldGetString(object_name_data);
+ xastir_snprintf(signpost_name,
+ sizeof(signpost_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(signpost_name);
+
+ temp_ptr = XmTextFieldGetString(object_comment_data);
+ xastir_snprintf(comment,
+ sizeof(comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(comment);
+
+
+ if(state->set) {
+ Area_object_enabled = 1;
+ Signpost_object_enabled = 0;
+ DF_object_enabled = 0;
+ Map_View_object_enabled = 0;
+ Probability_circles_enabled = 0;
+
+ //fprintf(stderr,"Area Objects are ENABLED\n");
+
+ // Call Set_Del_Object again, causing it to redraw with the new options.
+ //Set_Del_Object( widget, clientData, callData );
+ Set_Del_Object( widget, global_parameter1, global_parameter2 );
+
+
+ XmToggleButtonSetState(signpost_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(df_bearing_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(map_view_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(probabilities_toggle, FALSE, FALSE);
+
+ XtSetSensitive(ob_speed,FALSE);
+ XtSetSensitive(ob_speed_data,FALSE);
+ XtSetSensitive(ob_course,FALSE);
+ XtSetSensitive(ob_course_data,FALSE);
+
+ temp_data[0] = '\\';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = 'l';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ XtSetSensitive(ob_frame,FALSE);
+
+ // update symbol picture
+ (void)updateObjectPictureCallback((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
+ }
+ else {
+ Area_object_enabled = 0;
+
+ //fprintf(stderr,"Area Objects are DISABLED\n");
+
+ // Call Set_Del_Object again, causing it to redraw with the new options.
+ //Set_Del_Object( widget, clientData, callData );
+ Set_Del_Object( widget, global_parameter1, global_parameter2 );
+
+
+ XtSetSensitive(ob_speed,TRUE);
+ XtSetSensitive(ob_speed_data,TRUE);
+ XtSetSensitive(ob_course,TRUE);
+ XtSetSensitive(ob_course_data,TRUE);
+
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ XtSetSensitive(ob_frame,TRUE);
+
+ // update symbol picture
+ (void)updateObjectPictureCallback((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
+ }
+
+ // Restore name and comment fields
+ XmTextFieldSetString(object_name_data,signpost_name);
+ XmTextFieldSetString(object_comment_data,comment);
+}
+
+
+
+
+
+// Handler for "DF Bearing Object" toggle button
+void DF_bearing_object_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+ char temp_data[40];
+ char comment[43+1]; // max 43 characters of comment
+ char signpost_name[10];
+ char *temp_ptr;
+
+
+ // Save name and comment fields temporarily
+ temp_ptr = XmTextFieldGetString(object_name_data);
+ xastir_snprintf(signpost_name,
+ sizeof(signpost_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(signpost_name);
+
+ temp_ptr = XmTextFieldGetString(object_comment_data);
+ xastir_snprintf(comment,
+ sizeof(comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+ (void)remove_trailing_spaces(comment);
+
+
+ if(state->set) {
+ Area_object_enabled = 0;
+ Signpost_object_enabled = 0;
+ DF_object_enabled = 1;
+ Map_View_object_enabled = 0;
+ Probability_circles_enabled = 0;
+
+ //fprintf(stderr,"DF Objects are ENABLED\n");
+
+ // Call Set_Del_Object again, causing it to redraw with the new options.
+ //Set_Del_Object( widget, clientData, callData );
+ Set_Del_Object( widget, global_parameter1, global_parameter2 );
+
+
+ XmToggleButtonSetState(signpost_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(area_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(map_view_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(probabilities_toggle, FALSE, FALSE);
+
+ XtSetSensitive(ob_speed,TRUE);
+ XtSetSensitive(ob_speed_data,TRUE);
+ XtSetSensitive(ob_course,TRUE);
+ XtSetSensitive(ob_course_data,TRUE);
+ XtSetSensitive(frameomni,FALSE);
+ XtSetSensitive(framebeam,FALSE);
+ Omni_antenna_enabled = 0;
+ Beam_antenna_enabled = 0;
+
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = '\\';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ XtSetSensitive(ob_frame,FALSE);
+
+ // update symbol picture
+ (void)updateObjectPictureCallback((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
+ }
+ else {
+ DF_object_enabled = 0;
+
+ //fprintf(stderr,"DF Objects are DISABLED\n");
+
+ // Call Set_Del_Object again, causing it to redraw with the new options.
+ //Set_Del_Object( widget, clientData, callData );
+ Set_Del_Object( widget, global_parameter1, global_parameter2 );
+
+
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ XtSetSensitive(ob_frame,TRUE);
+
+ // update symbol picture
+ (void)updateObjectPictureCallback((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
+ }
+
+ // Restore name and comment fields
+ XmTextFieldSetString(object_name_data,signpost_name);
+ XmTextFieldSetString(object_comment_data,comment);
+}
+
+
+
+
+
+// Handler for "Map View Object" toggle button
+void Map_View_object_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+ char temp_data[40];
+ char comment[43+1]; // max 43 characters of comment
+ char signpost_name[10];
+ char *temp_ptr;
+
+
+ // Save name and comment fields temporarily
+ temp_ptr = XmTextFieldGetString(object_name_data);
+ xastir_snprintf(signpost_name,
+ sizeof(signpost_name),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(signpost_name);
+
+ temp_ptr = XmTextFieldGetString(object_comment_data);
+ xastir_snprintf(comment,
+ sizeof(comment),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+ (void)remove_trailing_spaces(comment);
+
+
+ if(state->set) {
+ // Make a bunch of the fields insensitive that we don't use
+ // here.
+
+ Area_object_enabled = 0;
+ Signpost_object_enabled = 0;
+ DF_object_enabled = 0;
+ Map_View_object_enabled = 1;
+ Probability_circles_enabled = 0;
+
+ //fprintf(stderr,"Map View Objects are ENABLED\n");
+
+
+// Make a bunch of the fields insensitive that we don't use here?
+
+
+ // Call Set_Del_Object again, causing it to redraw with the new options.
+ //Set_Del_Object( widget, clientData, callData );
+ Set_Del_Object( widget, global_parameter1, global_parameter2 );
+
+ XmToggleButtonSetState(signpost_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(area_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(df_bearing_toggle, FALSE, FALSE);
+ XmToggleButtonSetState(probabilities_toggle, FALSE, FALSE);
+
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = 'E'; // Eyeball symbol
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ XtSetSensitive(ob_frame,FALSE);
+ XtSetSensitive(ob_option_frame,FALSE);
+
+ // update symbol picture
+ (void)updateObjectPictureCallback((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
+ }
+ else {
+ Map_View_object_enabled = 0;
+
+ //fprintf(stderr,"Map View Objects are DISABLED\n");
+
+ // Call Set_Del_Object again, causing it to redraw with the new options.
+ //Set_Del_Object( widget, clientData, callData );
+ Set_Del_Object( widget, global_parameter1, global_parameter2 );
+
+
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ XtSetSensitive(ob_frame,TRUE);
+ XtSetSensitive(ob_option_frame,TRUE);
+
+ // update symbol picture
+ (void)updateObjectPictureCallback((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
+ }
+
+ // Restore name and comment fields
+ XmTextFieldSetString(object_name_data,signpost_name);
+
+ // Don't want to restore the comment if it is a Map View object,
+ // as Set_Del_Object() changes that field in that case.
+ if (!Map_View_object_enabled) {
+ XmTextFieldSetString(object_comment_data,comment);
+ }
+}
+
+
+
+
+
+/* Area object type radio buttons */
+void Area_type_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ Area_type = atoi(which); // Set to shape desired
+ if ( (Area_type == 1) || (Area_type == 6) ) { // If either line type
+ //fprintf(stderr,"Line type: %d\n", Area_type);
+ XtSetSensitive(ob_corridor,TRUE);
+ XtSetSensitive(ob_corridor_data,TRUE);
+ XtSetSensitive(ob_corridor_miles,TRUE);
+ XtSetSensitive(open_filled_toggle,FALSE);
+ }
+ else { // Not line type
+ //fprintf(stderr,"Not line type: %d\n", Area_type);
+ XtSetSensitive(ob_corridor,FALSE);
+ XtSetSensitive(ob_corridor_data,FALSE);
+ XtSetSensitive(ob_corridor_miles,FALSE);
+ XtSetSensitive(open_filled_toggle,TRUE);
+ }
+ }
+ else {
+ Area_type = 0; // Open circle
+ //fprintf(stderr,"Type zero\n");
+ }
+ //fprintf(stderr,"Area type: %d\n", Area_type);
+}
+
+
+
+
+
+/* Area object color radio buttons */
+void Area_color_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ Area_color[0] = which[0]; // Set to color desired.
+ Area_color[1] = which[1];
+ Area_color[2] = '\0';
+ }
+ else {
+ Area_color[0] = '/';
+ Area_color[1] = '0'; // Black
+ Area_color[2] = '\0';
+ }
+ //fprintf(stderr,"Area color: %s\n", Area_color);
+}
+
+
+
+
+
+/* Area bright color enable button */
+void Area_bright_dim_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ Area_bright = atoi(which);
+ //fprintf(stderr,"Bright colors are ENABLED: %d\n", Area_bright);
+ }
+ else {
+ Area_bright = 0;
+ //fprintf(stderr,"Bright colors are DISABLED: %d\n", Area_bright);
+ }
+}
+
+
+
+
+
+/* Area filled enable button */
+void Area_open_filled_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ Area_filled = atoi(which);
+ //fprintf(stderr,"Filled shapes ENABLED: %d\n", Area_filled);
+ }
+ else {
+ Area_filled = 0;
+ //fprintf(stderr,"Filled shapes DISABLED: %d\n", Area_filled);
+ }
+}
+
+
+
+
+
+// Handler for "Omni Antenna" toggle button
+void Omni_antenna_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ //fprintf(stderr,"Omni Antenna ENABLED\n");
+ XmToggleButtonSetState(beam_antenna_toggle, FALSE, FALSE);
+ XtSetSensitive(frameomni,TRUE);
+ XtSetSensitive(framebeam,FALSE);
+ Omni_antenna_enabled = 1;
+ Beam_antenna_enabled = 0;
+ }
+ else {
+ //fprintf(stderr,"Omni Antenna DISABLED\n");
+ XtSetSensitive(frameomni,FALSE);
+ Omni_antenna_enabled = 0;
+ }
+}
+
+
+
+
+
+// Handler for "Beam Antenna" toggle button
+void Beam_antenna_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ //fprintf(stderr,"Beam Antenna ENABLED\n");
+ XmToggleButtonSetState(omni_antenna_toggle, FALSE, FALSE);
+ XtSetSensitive(frameomni,FALSE);
+ XtSetSensitive(framebeam,TRUE);
+ Omni_antenna_enabled = 0;
+ Beam_antenna_enabled = 1;
+ }
+ else {
+ //fprintf(stderr,"Beam Antenna DISABLED\n");
+ XtSetSensitive(framebeam,FALSE);
+ Beam_antenna_enabled = 0;
+ }
+}
+
+
+
+
+
+/* Object signal radio buttons */
+void Ob_signal_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ object_shgd[0] = which[0]; // Set to signal quality heard
+ }
+ else {
+ object_shgd[0] = '0'; // 0 (Signal not heard)
+ }
+ object_shgd[4] = '\0';
+
+ //fprintf(stderr,"SHGD: %s\n",object_shgd);
+}
+
+
+
+
+
+/* Object height radio buttons */
+void Ob_height_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ object_shgd[1] = which[0]; // Set to height desired
+ }
+ else {
+ object_shgd[1] = '0'; // 0 (10ft HAAT)
+ }
+ object_shgd[4] = '\0';
+
+ //fprintf(stderr,"SHGD: %s\n",object_shgd);
+}
+
+
+
+
+
+/* Object gain radio buttons */
+void Ob_gain_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ object_shgd[2] = which[0]; // Set to antenna gain desired
+ }
+ else {
+ object_shgd[2] = '0'; // 0dB gain
+ }
+ object_shgd[4] = '\0';
+
+ //fprintf(stderr,"SHGD: %s\n",object_shgd);
+}
+
+
+
+
+
+/* Object directivity radio buttons */
+void Ob_directivity_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ object_shgd[3] = which[0]; // Set to antenna pattern desired
+ }
+ else {
+ object_shgd[3] = '0'; // Omni-directional pattern
+ }
+ object_shgd[4] = '\0';
+
+ //fprintf(stderr,"SHGD: %s\n",object_shgd);
+}
+
+
+
+
+
+/* Object beamwidth radio buttons */
+void Ob_width_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ object_NRQ[2] = which[0]; // Set to antenna beamwidth desired
+ }
+ else {
+ object_NRQ[2] = '0'; // Beamwidth = "Useless"
+ }
+ object_NRQ[3] = '\0';
+
+ //fprintf(stderr,"NRQ: %s\n", object_NRQ);
+}
+
+
+
+
+
+/* populate predefined object (SAR) struct */
+void Populate_predefined_objects(predefinedObject *predefinedObjects) {
+ // The number of objects you are defining below must be
+ // exactly equal to number_of_predefined_objects
+ // and less than MAX_NUMBER_OF_PREDEFINED_OBJECTS.
+ // using counter j for this seems inelegant **
+
+ // A set of predefined SAR objects are hardcoded and used by default
+ // other sets of predefined objects (SAR in km, public service event,
+ // and user defined objects) can be loaded from a file.
+ //
+ // Detailed instructions for the format of the files can be found in
+ // the two example files provided: predefined_SAR.sys and
+ // predefined_EVENT.sys
+ char predefined_object_definition_file[263];
+ int read_file_ok = 0;
+ int line_max_length = 255;
+ int object_read_ok = 0;
+ char line[line_max_length];
+ char *value;
+ char *variable;
+ FILE *fp_file;
+ int j = 0;
+ char error_correct_location[256];
+ char predef_obj_path[MAX_VALUE];
+ char temp_file_path[MAX_VALUE];
+
+
+ xastir_snprintf(line,sizeof(line),"%s","\0");
+ xastir_snprintf(predefined_object_definition_file,sizeof(predefined_object_definition_file),"config/%s",predefined_object_definition_filename);
+
+ get_user_base_dir(predefined_object_definition_file, predef_obj_path,
+ sizeof(predef_obj_path));
+
+ number_of_predefined_objects = 0;
+
+ if (predefined_menu_from_file == 1 ) {
+ // Check to see if a file containing predefined object definitions
+ // exists, if it does, open it and try to read the definitions
+ // if this fails, use the hardcoded SAR default instead.
+// fprintf(stderr,"Checking for predefined objects menu file\n");
+#ifdef OBJECT_DEF_FILE_USER_BASE
+ if (filethere(predef_obj_path)) {
+ fp_file = fopen(predef_obj_path,"r");
+#else // OBJECT_DEF_FILE_USER_BASE
+ if (filethere(get_data_base_dir(predefined_object_definition_file))) {
+ fp_file = fopen(get_data_base_dir(predefined_object_definition_file),"r");
+#endif // OBJECT_DEF_FILE_USER_BASE
+
+ xastir_snprintf(error_correct_location,
+ sizeof(error_correct_location),
+ "Loading from %s/%s \n",
+#ifdef OBJECT_DEF_FILE_USER_BASE
+ get_user_base_dir("config", temp_file_path, sizeof(temp_file_path)),
+#else // OBJECT_DEF_FILE_USER_BASE
+ get_data_base_dir("config"),
+#endif // OBJECT_DEF_FILE_USER_BASE
+ predefined_object_definition_file);
+ fprintf(stderr, "%s", error_correct_location);
+ while (!feof(fp_file)) {
+ // read lines to end of file
+ (void)get_line(fp_file, line, line_max_length);
+ // ignore blank lines and lines starting with #
+ if ((strncmp("#",line,1)!=0) && (strlen(line) > 2)) {
+ // if line starts "NAME" begin an object
+ // next five lines should be PAGE, SYMBOL, DATA, MENU, HIDDENCHILD
+ // NAME, PAGE, SYMBOL, MENU, and HIDDENCHILD are required.
+ // HIDDENCHILD must come last (it is being used to identify the
+ // end of one object).
+ // split line into variable/value pairs on tab
+ // See predefined_SAR.sys and predefined_event.sys for more details.
+ variable = strtok((char *)&line,"\t");
+ if (strcmp("NAME",variable)==0) {
+ value = strtok(NULL,"\t\r\n");
+ if (value != NULL) {
+ xastir_snprintf(predefinedObjects[j].call,sizeof(predefinedObjects[j].call), "%s", value);
+ // by default, set data to an empty string, allowing DATA to be ommitted
+ xastir_snprintf(predefinedObjects[j].data,sizeof(predefinedObjects[j].data),"%c",'\0');
+ object_read_ok ++;
+ }
+ }
+ if (strcmp("PAGE",variable)==0) {
+ value = strtok(NULL,"\t\r\n");
+ if (value != NULL) {
+ xastir_snprintf(predefinedObjects[j].page,sizeof(predefinedObjects[j].page), "%s", value);
+ object_read_ok ++;
+ }
+ }
+ if (strcmp("SYMBOL",variable)==0) {
+ value = strtok(NULL,"\t\r\n");
+ if (value != NULL) {
+ xastir_snprintf(predefinedObjects[j].symbol,sizeof(predefinedObjects[j].symbol), "%s", value);
+ object_read_ok ++;
+ }
+ }
+ if (strcmp("DATA",variable)==0) {
+ value = strtok(NULL,"\t\r\n");
+ if (value == NULL || strcmp(value,"NULL")==0) {
+ xastir_snprintf(predefinedObjects[j].data,sizeof(predefinedObjects[j].data),"%c",'\0');
+ } else {
+ xastir_snprintf(predefinedObjects[j].data,sizeof(predefinedObjects[j].data), "%s", value);
+ }
+ }
+ if (strcmp("MENU",variable)==0) {
+ value = strtok(NULL,"\t\r\n");
+ if (value != NULL) {
+ xastir_snprintf(predefinedObjects[j].menu_call,sizeof(predefinedObjects[j].menu_call), "%s", value);
+ object_read_ok ++;
+ }
+ }
+ if (strcmp("HIDDENCHILD",variable)==0) {
+ value = strtok(NULL,"\t\r\n");
+ if (strcmp(value,"YES")==0) {
+ predefinedObjects[j].show_on_menu = 0;
+ predefinedObjects[j].index_of_child = j - 1;
+ predefinedObjects[j].index = j;
+ } else {
+ predefinedObjects[j].show_on_menu = 1;
+ predefinedObjects[j].index_of_child = -1;
+ predefinedObjects[j].index = j;
+ }
+ if (object_read_ok == 4) {
+ // All elements for an object were read correctly.
+ // Begin filling next element in array.
+ j++;
+ // Read of at least one object was successful,
+ // don't display default hardcoded menu items.
+ read_file_ok = 1;
+ // Reset value counter for next object.
+ object_read_ok = 0;
+ } else {
+ // Something was missing or HIDDENCHILD was out of order.
+ // Don't increment array (overwrite a partly filled entry).
+ fprintf(stderr,"Error in reading predefined object menu file:\nAn object is not correctly defined.\n");
+ }
+ }
+ }
+ } // end while !feof()
+ fclose(fp_file);
+ if (read_file_ok==0) {
+ fprintf(stderr,"Error in reading predefined objects menu file:\nNo valid objects found.\n");
+ }
+ }
+ else {
+
+ fprintf(stderr,"Error: Predefined objects menu file not found.\n");
+
+ xastir_snprintf(error_correct_location,
+ sizeof(error_correct_location),
+ "File should be in %s\n",
+#ifdef OBJECT_DEF_FILE_USER_BASE
+ get_user_base_dir("config", temp_file_path, sizeof(temp_file_path)));
+#else // OBJECT_DEF_FILE_USER_BASE
+ get_data_base_dir("config"));
+#endif // OBJECT_DEF_FILE_USER_BASE
+ fprintf(stderr, "%s", error_correct_location);
+ }
+ }
+
+ if (read_file_ok==0) {
+ // file read failed or was not requested, display default SAR menu
+
+ // command post
+ xastir_snprintf(predefinedObjects[j].call,sizeof(predefinedObjects[j].call),"ICP");
+ xastir_snprintf(predefinedObjects[j].page,sizeof(predefinedObjects[j].page),"/");
+ xastir_snprintf(predefinedObjects[j].symbol,sizeof(predefinedObjects[j].symbol),"c");
+ xastir_snprintf(predefinedObjects[j].data,sizeof(predefinedObjects[j].data),"%c",'\0');
+ xastir_snprintf(predefinedObjects[j].menu_call,sizeof(predefinedObjects[j].menu_call),"ICP: Command Post");
+ predefinedObjects[j].show_on_menu = 1;
+ predefinedObjects[j].index_of_child = -1;
+ predefinedObjects[j].index = j;
+ j++;
+
+ // Staging area
+ xastir_snprintf(predefinedObjects[j].call,sizeof(predefinedObjects[j].call),"Staging");
+ xastir_snprintf(predefinedObjects[j].page,sizeof(predefinedObjects[j].page),"S");
+ xastir_snprintf(predefinedObjects[j].symbol,sizeof(predefinedObjects[j].symbol),"0");
+ xastir_snprintf(predefinedObjects[j].data,sizeof(predefinedObjects[j].data),"%c",'\0');
+ xastir_snprintf(predefinedObjects[j].menu_call,sizeof(predefinedObjects[j].menu_call),"Staging");
+ predefinedObjects[j].show_on_menu = 1;
+ predefinedObjects[j].index_of_child = -1;
+ predefinedObjects[j].index = j;
+ j++;
+
+ // Initial Planning Point
+ // set up to draw as two objects with different probability circles
+ xastir_snprintf(predefinedObjects[j].call,sizeof(predefinedObjects[j].call),"IPP_");
+ xastir_snprintf(predefinedObjects[j].page,sizeof(predefinedObjects[j].page),"/");
+ xastir_snprintf(predefinedObjects[j].symbol,sizeof(predefinedObjects[j].symbol),"/");
+ xastir_snprintf(predefinedObjects[j].data,sizeof(predefinedObjects[j].data)," Pmin0.75,Pmax1.0");
+ xastir_snprintf(predefinedObjects[j].menu_call,sizeof(predefinedObjects[j].menu_call),"[not shown]");
+ // show on menu = 0 will hide this entry on menu
+ predefinedObjects[j].show_on_menu = 0;
+ predefinedObjects[j].index_of_child = -1;
+ predefinedObjects[j].index = j;
+ j++;
+ xastir_snprintf(predefinedObjects[j].call,sizeof(predefinedObjects[j].call),"IPP");
+ xastir_snprintf(predefinedObjects[j].page,sizeof(predefinedObjects[j].page),"/");
+ xastir_snprintf(predefinedObjects[j].symbol,sizeof(predefinedObjects[j].symbol),"/");
+ xastir_snprintf(predefinedObjects[j].data,sizeof(predefinedObjects[j].data)," Pmin0.25,Pmax0.5");
+ xastir_snprintf(predefinedObjects[j].menu_call,sizeof(predefinedObjects[j].menu_call),"IPP: InitialPlanningPoint");
+ predefinedObjects[j].show_on_menu = 1;
+ // index of child j - 1 will add additional callback to IPP_
+ predefinedObjects[j].index_of_child = j - 1;
+ predefinedObjects[j].index = j;
+ j++;
+
+ // Point last seen
+ xastir_snprintf(predefinedObjects[j].call,sizeof(predefinedObjects[j].call),"PLS");
+ xastir_snprintf(predefinedObjects[j].page,sizeof(predefinedObjects[j].page),"/");
+ xastir_snprintf(predefinedObjects[j].symbol,sizeof(predefinedObjects[j].symbol),"/");
+ xastir_snprintf(predefinedObjects[j].data,sizeof(predefinedObjects[j].data),"%c",'\0');
+ xastir_snprintf(predefinedObjects[j].menu_call,sizeof(predefinedObjects[j].menu_call),"PLS: Point Last Seen");
+ predefinedObjects[j].show_on_menu = 1;
+ predefinedObjects[j].index_of_child = -1;
+ predefinedObjects[j].index = j;
+ j++;
+
+
+ // Last known point
+ xastir_snprintf(predefinedObjects[j].call,sizeof(predefinedObjects[j].call),"LKP");
+ xastir_snprintf(predefinedObjects[j].page,sizeof(predefinedObjects[j].page),"/");
+ xastir_snprintf(predefinedObjects[j].symbol,sizeof(predefinedObjects[j].symbol),".");
+ xastir_snprintf(predefinedObjects[j].data,sizeof(predefinedObjects[j].data),"%c",'\0');
+ xastir_snprintf(predefinedObjects[j].menu_call,sizeof(predefinedObjects[j].menu_call),"LKP: Last Known Point");
+ predefinedObjects[j].show_on_menu = 1;
+ predefinedObjects[j].index_of_child = -1;
+ predefinedObjects[j].index = j;
+ j++;
+
+ // Base
+ xastir_snprintf(predefinedObjects[j].call,sizeof(predefinedObjects[j].call),"Base");
+ xastir_snprintf(predefinedObjects[j].page,sizeof(predefinedObjects[j].page),"B");
+ xastir_snprintf(predefinedObjects[j].symbol,sizeof(predefinedObjects[j].symbol),"0");
+ xastir_snprintf(predefinedObjects[j].data,sizeof(predefinedObjects[j].data),"%c",'\0');
+ xastir_snprintf(predefinedObjects[j].menu_call,sizeof(predefinedObjects[j].menu_call),"Base");
+ predefinedObjects[j].show_on_menu = 1;
+ predefinedObjects[j].index_of_child = -1;
+ predefinedObjects[j].index = j;
+ j++;
+
+ // Helibase (helicopter support base)
+ xastir_snprintf(predefinedObjects[j].call,sizeof(predefinedObjects[j].call),"Helibase");
+ xastir_snprintf(predefinedObjects[j].page,sizeof(predefinedObjects[j].page),"H");
+ xastir_snprintf(predefinedObjects[j].symbol,sizeof(predefinedObjects[j].symbol),"0");
+ xastir_snprintf(predefinedObjects[j].data,sizeof(predefinedObjects[j].data),"%c",'\0');
+ xastir_snprintf(predefinedObjects[j].menu_call,sizeof(predefinedObjects[j].menu_call),"Helibase");
+ predefinedObjects[j].show_on_menu = 1;
+ predefinedObjects[j].index_of_child = -1;
+ predefinedObjects[j].index = j;
+ j++;
+
+ // Helispot (helicopter landing spot)
+ // Heli- will be created as Heli-1, Heli-2, Heli-3, etc.
+ // terminal - on a call is a magic character. see Create_SAR+Object.
+ xastir_snprintf(predefinedObjects[j].call,sizeof(predefinedObjects[j].call),"Heli-");
+ xastir_snprintf(predefinedObjects[j].page,sizeof(predefinedObjects[j].page),"/");
+ xastir_snprintf(predefinedObjects[j].symbol,sizeof(predefinedObjects[j].symbol),"/");
+ xastir_snprintf(predefinedObjects[j].data,sizeof(predefinedObjects[j].data),"%c",'\0');
+ xastir_snprintf(predefinedObjects[j].menu_call,sizeof(predefinedObjects[j].menu_call),"Heli-n: Helispot");
+ predefinedObjects[j].show_on_menu = 1;
+ predefinedObjects[j].index_of_child = -1;
+ predefinedObjects[j].index = j;
+ j++;
+
+ // Camp
+ xastir_snprintf(predefinedObjects[j].call,sizeof(predefinedObjects[j].call),"Camp");
+ xastir_snprintf(predefinedObjects[j].page,sizeof(predefinedObjects[j].page),"C");
+ xastir_snprintf(predefinedObjects[j].symbol,sizeof(predefinedObjects[j].symbol),"0");
+ xastir_snprintf(predefinedObjects[j].data,sizeof(predefinedObjects[j].data),"%c",'\0');
+ xastir_snprintf(predefinedObjects[j].menu_call,sizeof(predefinedObjects[j].menu_call),"Camp");
+ predefinedObjects[j].show_on_menu = 1;
+ predefinedObjects[j].index_of_child = -1;
+ predefinedObjects[j].index = j;
+ j++;
+
+ }
+
+ // Could read additional entries from a file here.
+ // The total number of entries should be left fairly small
+ // to prevent the menu from becoming too large and unweildy.
+
+ number_of_predefined_objects = j;
+ if (number_of_predefined_objects>MAX_NUMBER_OF_PREDEFINED_OBJECTS) {
+ // need beter handling of this - we will allready have run
+ // past the end of the array if we have reached here.
+ number_of_predefined_objects=MAX_NUMBER_OF_PREDEFINED_OBJECTS;
+ }
+}
+
+
+
+
+
+/* Create a predefined SAR/Public Event object
+ Create an object of the specified type at the current mouse position
+ without a dialog.
+ Current undesirable behavior: If an object of the same name exists,
+ takes control of that object and moves it to the current mouse position.
+
+ clientData is pointer to an integer representing the index of a
+ predefined object in the predefinedObjects array
+ */
+void Create_SAR_Object(/*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, XtPointer calldata) {
+ Dimension width, height;
+ char call[MAX_CALLSIGN+1];
+ long x_lat,x_lon;
+ char origin[MAX_CALLSIGN+1]; // mycall
+ char data[MAX_LINE_SIZE];
+ char page[2];
+ // reserve space for probability circle as well as symbol /Pmin0.25,Pmax0.5,
+ char symbol_plus[PREDEFINED_OBJECT_DATA_LENGTH];
+ char symbol[2];
+ char c_lon[10];
+ char c_lat[10];
+ char time[7];
+ intptr_t i;
+ DataRow *p_station;
+ int done = 0;
+ int iterations_left = 1000; // Max iterations of while loop below
+ int extra_num = 1;
+ char orig_call[MAX_CALLSIGN+1];
+
+
+ // set some defaults in case of a non-matched value
+ xastir_snprintf(page,sizeof(page),"/");
+ xastir_snprintf(symbol,sizeof(symbol),"/");
+ xastir_snprintf(call, sizeof(call), "Marker");
+
+ //for (i=0;i<number_of_predefined_objects;i++) {
+ // if (strcmp((char *)clientData,predefinedObjects[i].call)==0) {
+ i = (intptr_t)clientData;
+ if (i > -1) {
+ if (i <= number_of_predefined_objects) {
+ xastir_snprintf(page,sizeof(page), "%s", predefinedObjects[i].page);
+ xastir_snprintf(symbol,sizeof(symbol), "%s", predefinedObjects[i].symbol);
+ xastir_snprintf(call, sizeof(call), "%s", predefinedObjects[i].call);
+ xastir_snprintf(symbol_plus, sizeof(symbol_plus), "%s%s",symbol,predefinedObjects[i].data);
+ }
+ }
+
+ // Get mouse position.
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ x_lon = center_longitude - ((width *scale_x)/2) + (menu_x*scale_x);
+ x_lat = center_latitude - ((height*scale_y)/2) + (menu_y*scale_y);
+ if(debug_level & 1)
+ fprintf(stderr, "Creating symbol %s %s at: %lu %lu with calldata: [%li]\n",
+ page,
+ symbol,
+ x_lat,
+ x_lon,
+ (intptr_t)clientData);
+
+ // CONVERT_LP_NOSP = DDMM.MMN
+ convert_lat_l2s(x_lat, (char *)c_lat, sizeof(c_lat), CONVERT_LP_NOSP);
+ convert_lon_l2s(x_lon, (char *)c_lon, sizeof(c_lon), CONVERT_LP_NOSP);
+
+
+ // Save "call" away in "orig_call" so that we can use it again
+ // and again as we try to come up with a unique name for the
+ // object.
+ //
+ xastir_snprintf(orig_call,
+ sizeof(orig_call),
+ "%s",
+ call);
+
+ // '-' is a magic character.
+ //
+ // If the last character in call is a "-", the symbol is expected
+ // to be a numeric series starting with call-1, so change call to
+ // call-1. This lets us describe Heli- and create Heli-1, Heli-2
+ // and similar series. Storing call to orig_call before appending
+ // the number should allow the sequence to increment normally.
+ if ((int)'-'==(int)*(call+(strlen(call)-1))) {
+ // make sure that we don't write past the end of call
+ if (strlen(call)<MAX_CALLSIGN) {
+ strncat(call,"1",1);
+ }
+ }
+ // Check object names against our station database until we find
+ // a unique name or a killed object name we can use.
+ //
+ while (!done && iterations_left) {
+
+ // Create object as owned by own station, or take control of
+ // object if it has another owner. Taking control of a
+ // received object is probably not a desirable behavior.
+
+ if (!search_station_name(&p_station,call,1)) {
+ //
+ // No match found with the original name, so the name
+ // for our object is ok to use. Get out of the while
+ // loop and create the object.
+ //
+ done++;
+ continue; // Next loop iteration (Exit the while loop)
+ }
+
+
+ // If we get to here, a station with this name exists. We
+ // have a pointer to it with p_station.
+ //
+ // If object or item and killed, use the old name to create
+ // a new object.
+ //
+ // If not killed or not object/item, pick a new name by
+ // adding digits onto the end of the old name until we don't
+ // have a name collision or we find an old object or item by
+ // that name that has been killed.
+
+
+ // Check whether object or item. If so, check whether killed.
+ if ((p_station->flag & (ST_OBJECT | ST_ITEM)) != 0) { // It's an object or item
+
+ // Check whether object/item has been killed already
+ if ((p_station->flag & ST_ACTIVE) != ST_ACTIVE) {
+ //
+ // The object or item has been killed. Ok to use
+ // this object name. Get out of the while loop and
+ // create the object.
+ //
+ done++;
+ continue; // Next loop iteration (Exit the while loop)
+ }
+ }
+
+
+// If we get to this point we have an object name that matches
+// another in our database. We must come up with a new name. We
+// add digits to the end of the original name until we get one that
+// works for us.
+
+
+
+/*
+ // If my_callsign (Exact match includes SSID)
+// if (is_my_call(p_station->origin,1)) {
+ if (is_my_object_item(p_station)) {
+
+ // The previous object with the same name is owned by
+ // me.
+ // a) MOVE the EXISTING object (default), perhaps with the option
+ // to clear the track. Clearing the track would only take
+ // effect on our local map screen, not on everyone else's.
+ // b) RENAME the NEW object, perhaps tacking a number
+ // onto the end until we get to an unused name.
+ // c) CANCEL request
+
+
+fprintf(stderr, "Object with same name exists, owned by me\n");
+
+// Pop up a new dialog with the various options on it. Save our
+// state here so that we can create the object in the callbacks for
+// the next dialog.
+//
+// Code goes here...
+
+
+ else {
+ // The previous object with the same name is NOT owned
+ // by me.
+ // a) ADOPT the existing object and MOVE it (a very
+ // poor idea).
+ // Same track-clearing as option 1a.
+ // b) RENAME the NEW object (default), perhaps tacking
+ // a number onto the end until we get to an unused
+ // name.
+ // c) CANCEL request
+
+
+fprintf(stderr, "Object with same name exists, owned by %s\n", p_station->origin);
+
+// Pop up a new dialog with the various options on it. Save our
+// state here so that we can create the object in the callbacks for
+// the next dialog.
+//
+// Code goes here...
+
+
+ }
+*/
+
+
+ extra_num++;
+
+ // Append extra_num to the object name (starts at "2"), try
+ // again to see if it is unique.
+ //
+ xastir_snprintf(call,
+ sizeof(call),
+ "%s%d",
+ orig_call,
+ extra_num);
+// ****** Bug ********
+// need to check length of call - if it has gone over 9 characters only
+// the first 9 will be treated as unique, thus FirstAid11 will become FirstAid1
+// and become new position for existing FirstAid1.
+// MAX_CALLSIGN is the constraining global.
+// In that case, need to fail gracefully and throw an error message.
+ iterations_left--;
+
+ } // End of while loop
+
+
+ if (iterations_left == 0) {
+// Pop up a message stating that we couldn't find an empty name in
+// 1000 iterations. Call popup_message_always()
+
+fprintf(stderr, "No more iterations left\n");
+
+ }
+
+
+ xastir_snprintf(origin,
+ sizeof(origin),
+ "%s", my_callsign);
+ xastir_snprintf(time, sizeof(time), "%02d%02d%02d",
+ get_hours(),
+ get_minutes(),
+ get_seconds() );
+ // Prepare APRS data string using latitude and longitude from mouse click location
+ // and page, symbol, and any additional data from the prepared object.
+ xastir_snprintf(data,
+ sizeof(data),
+ ";%-9s*%sh%s%s%s%s",
+ call,
+ time,
+ c_lat,
+ page,
+ c_lon,
+ symbol_plus);
+
+//fprintf(stderr,"Packet:%s\n", data);
+
+ log_object_item(data,0,last_object);
+
+// *********** New objects not being displayed on map untill restart
+
+
+ if (object_tx_disable || transmit_disable)
+ output_my_data(data,-1,0,1,0,NULL); // Local loopback only, not igating
+ else
+ output_my_data(data,-1,0,0,0,NULL); // Transmit/loopback object data, not igating
+}
+
+
+
+
+
+// Fill in fields from an existing object/item or create the proper
+// transmit string for a new object/item from these fields.
+/*
+ * Setup Object/Item Dialog
+ * clientData = pointer to object struct, if it's a modify or a move operation,
+ * else it's NULL.
+ * If calldata = 2, then we're doing a move object operation. We want in that
+ * case to fill in the new values for lat/long and make them take effect.
+ * If calldata = 1, then we've dropped through Station_info/Station_data
+ * on the way to Modify->Object.
+ * Need to put the tests for the different types of objects
+ * at the top of this function, then the dialog will build properly for
+ * the type of object initially.
+ */
+void Set_Del_Object( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, XtPointer calldata) {
+ Dimension width, height;
+ long lat,lon;
+ char lat_str[MAX_LAT];
+ char lon_str[MAX_LONG];
+ static Widget ob_pane, ob_form,
+ ob_name,ob_latlon_frame,ob_latlon_form,ob_latlon_ts,
+ ob_lat, ob_lat_deg, ob_lat_min, ob_lat_ns,
+ ob_lon, ob_lon_deg, ob_lon_min, ob_lon_ew,
+ ob_form1, ob_ts,
+ signpost_form,signpost_ts,
+ signpost_label,
+ probability_frame,probability_form,probability_ts,
+ probability_label_min, probability_label_max,
+ ob_option_ts,ob_option_form,
+ area_ts, area_form,
+ bright_dim_toggle,
+ shape_box,toption1,toption2,toption3,toption4,toption5,
+ color_box,coption1,coption2,coption3,coption4,coption5,coption6,coption7,coption8,
+ omnilabel,formomni,
+ signal_box,soption0,soption1,soption2,soption3,soption4,soption5,soption6,soption7,soption8,soption9,
+ height_box,hoption0,hoption1,hoption2,hoption3,hoption4,hoption5,hoption6,hoption7,hoption8,hoption9,
+ gain_box,goption0,goption1,goption2,goption3,goption4,goption5,goption6,goption7,goption8,goption9,
+ directivity_box,doption0,doption1,doption2,doption3,doption4,doption5,doption6,doption7,doption8,
+ beamlabel,formbeam,
+ width_box,woption0,woption1,woption2,woption3,woption4,woption5,woption6,woption7,woption8,woption9,
+ ob_bearing,
+ ob_lat_offset,ob_lon_offset,
+ ob_sep, ob_button_set,ob_button_del,ob_button_cancel,it_button_set,
+ ob_button_symbol,
+ compute_button;
+ char temp_data[40];
+ Atom delw;
+ DataRow *p_station = (DataRow *)clientData;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac; /* Arg Count */
+ long x,y;
+
+
+/*
+ if (p_station != NULL)
+ fprintf(stderr,"Have a pointer to an object. ");
+ else
+ fprintf(stderr,"No pointer, new object? ");
+ if (calldata != NULL) {
+ if (strcmp(calldata,"2") == 0)
+ fprintf(stderr,"Set_Del_Object: calldata: 2. Move object.\n");
+ else if (strcmp(calldata,"1") == 0)
+ fprintf(stderr,"Set_Del_Object: calldata: 1. Modify object.\n");
+ else if (strcmp(calldata,"0") == 0)
+ fprintf(stderr,"Set_Del_Object: calldata: 0. New object.\n");
+ else
+ fprintf(stderr,"Set_Del_Object: calldata: invalid. New object.\n");
+ }
+*/
+
+ // Save the data so that other routines can access it. Some of the
+ // callbacks can only handle one parameter, and we need two.
+ if (p_station != NULL)
+ global_parameter1 = clientData;
+ else
+ global_parameter1 = NULL;
+ global_parameter2 = calldata;
+
+
+
+ // This function can be invoked from the mouse menus or by being called
+ // directly by other routines. We look at the p_station pointer to decide
+ // how we were called.
+ //
+ if (p_station != NULL) { // We were called from the Modify_object()
+ // or Move() functions
+ //fprintf(stderr,"Got a pointer!\n");
+ lon = p_station->coord_lon; // Fill in values from the original object
+ lat = p_station->coord_lat;
+ }
+ else {
+ // We were called from the "Create New Object" mouse menu or
+ // by the "Move" option get default position for object, the
+ // position we have clicked at. For the special case of a
+ // Map View object, we instead want the screen center for
+ // this new object.
+ //
+ if (Map_View_object_enabled) {
+ // Get center of screen
+ lon = center_longitude;
+ lat = center_latitude;
+ }
+ else {
+ // Get mouse position
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+ lon = center_longitude - ((width *scale_x)/2) + (menu_x*scale_x);
+ lat = center_latitude - ((height*scale_y)/2) + (menu_y*scale_y);
+ }
+ }
+
+
+ // If the object dialog is up, we need to kill it and draw a new
+ // one so that we have the correct values filled in.
+ if (object_dialog)
+ Object_destroy_shell( w, object_dialog, NULL);
+
+
+ // Check for the three "Special" types of objects we deal with and set
+ // the global variables for them here. This will result in the correct
+ // type of dialog being drawn for each type of object.
+// Question: What about for Modify->Object where we're trying to change
+// the type of the object?
+
+ if (p_station != NULL) {
+/*
+ if (calldata != NULL) {
+ if (strcmp(calldata,"2") == 0)
+ fprintf(stderr,"Set_Del_Object: calldata: 2. Move object.\n");
+ else if (strcmp(calldata,"1") == 0)
+ fprintf(stderr,"Set_Del_Object: calldata: 1. Modify object.\n");
+ else if (strcmp(calldata,"0") == 0)
+ fprintf(stderr,"Set_Del_Object: calldata: 0. New object.\n");
+ else
+ fprintf(stderr,"Set_Del_Object: calldata: invalid. New object.\n");
+ }
+*/
+
+ // Check to see whether we should even be here at all!
+ if ( !(p_station->flag & ST_OBJECT)
+ && !(p_station->flag & ST_ITEM)) { // Not an object or item
+ //fprintf(stderr,"flag: %i\n", (int)p_station->flag);
+ popup_message_always(langcode("POPEM00022"),
+ langcode("POPEM00043") ); // "Not an Object/Item!"
+ return;
+ }
+
+ // Set to known defaults first
+ Area_object_enabled = 0;
+ Signpost_object_enabled = 0;
+ DF_object_enabled = 0;
+ Map_View_object_enabled = 0;
+ Probability_circles_enabled = 0;
+
+ if (p_station->aprs_symbol.area_object.type != AREA_NONE) { // Found an area object
+ Area_object_enabled = 1;
+ }
+ else if ( (p_station->aprs_symbol.aprs_symbol == 'm') // Found a signpost object
+ && (p_station->aprs_symbol.aprs_type == '\\') ) {
+ Signpost_object_enabled = 1;
+ }
+ else if ( (p_station->aprs_symbol.aprs_symbol == '\\') // Found a DF object
+ && (p_station->aprs_symbol.aprs_type == '/')
+ && ((strlen(p_station->signal_gain) == 7) // That has data associated with it
+ || (strlen(p_station->bearing) == 3)
+ || (strlen(p_station->NRQ) == 3) ) ) {
+ DF_object_enabled = 1;
+ }
+ else if ( (p_station->aprs_symbol.aprs_symbol == 'E') // Found a Map View object
+ && (p_station->aprs_symbol.aprs_type == '/')
+ && (strstr(p_station->power_gain,"RNG") != 0) ) { // Has a range value
+
+ //fprintf(stderr,"Found a range\n");
+ Map_View_object_enabled = 1;
+ }
+
+ else if (p_station->probability_min[0] != '\0' // Found some data
+ || p_station->probability_max[0] != '\0') { // Found some data
+ Probability_circles_enabled = 1;
+ }
+ }
+
+ //fprintf(stderr,"Area:Signpost:DF %i:%i:%i\n",Area_object_enabled,Signpost_object_enabled,DF_object_enabled);
+
+// Ok. The stage is now set to draw the proper type of dialog for the
+// type of object we're interested in currently.
+
+
+ if(object_dialog) // it is already open
+ (void)XRaiseWindow(XtDisplay(object_dialog), XtWindow(object_dialog));
+ else { // create new popup window
+ object_dialog = XtVaCreatePopupShell(langcode("POPUPOB001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ ob_pane = XtVaCreateWidget("Set_Del_Object pane",
+ xmPanedWindowWidgetClass,
+ object_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ ob_form = XtVaCreateWidget("Set_Del_Object ob_form",
+ xmFormWidgetClass,
+ ob_pane,
+ XmNfractionBase, 3,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Name"
+ ob_name = XtVaCreateManagedWidget(langcode("POPUPOB002"),
+ xmLabelWidgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // object name
+ object_name_data = XtVaCreateManagedWidget("Set_Del_Object name_data",
+ xmTextFieldWidgetClass,
+ ob_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 9,
+ XmNmaxLength, 9,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_name,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+//----- Frame for table / symbol
+ ob_frame = XtVaCreateManagedWidget("Set_Del_Object ob_frame",
+ xmFrameWidgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, object_name_data,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // "Station Symbol"
+ ob_ts = XtVaCreateManagedWidget(langcode("WPUPCFS009"),
+ xmLabelWidgetClass,
+ ob_frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ ob_form1 = XtVaCreateWidget("Set_Del_Object form1",
+ xmFormWidgetClass,
+ ob_frame,
+ XmNfractionBase, 5,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Group/overlay"
+ ob_group = XtVaCreateManagedWidget(langcode("WPUPCFS010"),
+ xmLabelWidgetClass,
+ ob_form1,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 10,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // table
+ object_group_data = XtVaCreateManagedWidget("Set_Del_Object group",
+ xmTextFieldWidgetClass,
+ ob_form1,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 1,
+ XmNmaxLength, 1,
+ XmNtopOffset, 3,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_group,
+ XmNleftOffset, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Symbol"
+ ob_symbol = XtVaCreateManagedWidget(langcode("WPUPCFS011"),
+ xmLabelWidgetClass,
+ ob_form1,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, object_group_data,
+ XmNleftOffset, 20,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // symbol
+ object_symbol_data = XtVaCreateManagedWidget("Set_Del_Object symbol",
+ xmTextFieldWidgetClass,
+ ob_form1,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 1,
+ XmNmaxLength, 1,
+ XmNtopOffset, 3,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_symbol,
+ XmNleftOffset, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // icon
+ Ob_icon0 = XCreatePixmap(XtDisplay(appshell),
+ RootWindowOfScreen(XtScreen(appshell)),
+ 20,
+ 20,
+ DefaultDepthOfScreen(XtScreen(appshell)));
+ Ob_icon = XCreatePixmap(XtDisplay(appshell),
+ RootWindowOfScreen(XtScreen(appshell)),
+ 20,
+ 20,
+ DefaultDepthOfScreen(XtScreen(appshell)));
+ object_icon = XtVaCreateManagedWidget("Set_Del_Object icon",
+ xmLabelWidgetClass,
+ ob_form1,
+ XmNlabelType, XmPIXMAP,
+ XmNlabelPixmap, Ob_icon,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, object_symbol_data,
+ XmNleftOffset, 15,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ ob_button_symbol = XtVaCreateManagedWidget(langcode("WPUPCFS028"),
+ xmPushButtonGadgetClass,
+ ob_form1,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, object_icon,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ob_button_symbol, XmNactivateCallback, Ob_change_symbol, object_dialog);
+
+//----- Frame for Lat/Long
+ ob_latlon_frame = XtVaCreateManagedWidget("Set_Del_Object ob_latlon_frame",
+ xmFrameWidgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_frame,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // "Location"
+ ob_latlon_ts = XtVaCreateManagedWidget(langcode("POPUPOB028"),
+ xmLabelWidgetClass,
+ ob_latlon_frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ ob_latlon_form = XtVaCreateWidget("Set_Del_Object ob_latlon_form",
+ xmFormWidgetClass,
+ ob_latlon_frame,
+ XmNfractionBase, 5,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "LAT"
+ ob_lat = XtVaCreateManagedWidget(langcode("WPUPCFS003"),
+ xmLabelWidgetClass,
+ ob_latlon_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 15,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // lat deg
+ object_lat_data_deg = XtVaCreateManagedWidget("Set_Del_Object lat_deg",
+ xmTextFieldWidgetClass,
+ ob_latlon_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 3,
+ XmNmaxLength, 2,
+ XmNtopOffset, 5,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_lat,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+ // "deg"
+ ob_lat_deg = XtVaCreateManagedWidget(langcode("WPUPCFS004"),
+ xmLabelWidgetClass,
+ ob_latlon_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, object_lat_data_deg,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // lat min
+ object_lat_data_min = XtVaCreateManagedWidget("Set_Del_Object lat_min",
+ xmTextFieldWidgetClass,
+ ob_latlon_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNmaxLength, 6,
+ XmNtopOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_lat_deg,
+ XmNleftOffset, 10,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+ // "min"
+ ob_lat_min = XtVaCreateManagedWidget(langcode("WPUPCFS005"),
+ xmLabelWidgetClass,
+ ob_latlon_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, object_lat_data_min,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // N/S
+ object_lat_data_ns = XtVaCreateManagedWidget("Set_Del_Object lat_ns",
+ xmTextFieldWidgetClass,
+ ob_latlon_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 1,
+ XmNmaxLength, 1,
+ XmNtopOffset, 5,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_lat_min,
+ XmNleftOffset, 10,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+ // "(N/S)"
+ ob_lat_ns = XtVaCreateManagedWidget(langcode("WPUPCFS006"),
+ xmLabelWidgetClass,
+ ob_latlon_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, object_lat_data_ns,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "LONG"
+ ob_lon = XtVaCreateManagedWidget(langcode("WPUPCFS007"),
+ xmLabelWidgetClass,
+ ob_latlon_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_lat,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // long
+ object_lon_data_deg = XtVaCreateManagedWidget("Set_Del_Object long_deg",
+ xmTextFieldWidgetClass,
+ ob_latlon_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 3,
+ XmNmaxLength, 3,
+ XmNtopOffset, 14,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_lat,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_lon,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+ // "deg"
+ ob_lon_deg = XtVaCreateManagedWidget(langcode("WPUPCFS004"),
+ xmLabelWidgetClass,
+ ob_latlon_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_lat,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, object_lon_data_deg,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // min
+ object_lon_data_min = XtVaCreateManagedWidget("Set_Del_Object long_min",
+ xmTextFieldWidgetClass,
+ ob_latlon_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNmaxLength, 6,
+ XmNtopOffset, 14,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_lon_deg,
+ XmNleftOffset, 10,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_lat,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+ // "min"
+ ob_lon_min = XtVaCreateManagedWidget(langcode("WPUPCFS005"),
+ xmLabelWidgetClass,
+ ob_latlon_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_lat,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, object_lon_data_min,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // E/W
+ object_lon_data_ew = XtVaCreateManagedWidget("Set_Del_Object long_ew",
+ xmTextFieldWidgetClass,
+ ob_latlon_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 1,
+ XmNmaxLength, 1,
+ XmNtopOffset, 14,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_lon_min,
+ XmNleftOffset, 10,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_lat,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+ // "(E/W)"
+ ob_lon_ew = XtVaCreateManagedWidget(langcode("WPUPCFS008"),
+ xmLabelWidgetClass,
+ ob_latlon_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_lat,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, object_lon_data_ew,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ compute_button = XtVaCreateManagedWidget(langcode("COORD002"),
+ xmPushButtonGadgetClass,
+ ob_latlon_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_lat,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_lon_ew,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // Fill in the pointers to our input textfields so that the coordinate
+ // calculator can fiddle with them.
+ coordinate_calc_array.calling_dialog = object_dialog;
+ coordinate_calc_array.input_lat_deg = object_lat_data_deg;
+ coordinate_calc_array.input_lat_min = object_lat_data_min;
+ coordinate_calc_array.input_lat_dir = object_lat_data_ns;
+ coordinate_calc_array.input_lon_deg = object_lon_data_deg;
+ coordinate_calc_array.input_lon_min = object_lon_data_min;
+ coordinate_calc_array.input_lon_dir = object_lon_data_ew;
+// XtAddCallback(compute_button, XmNactivateCallback, Coordinate_calc, ob_latlon_form);
+// XtAddCallback(compute_button, XmNactivateCallback, Coordinate_calc, "Set_Del_Object");
+ XtAddCallback(compute_button, XmNactivateCallback, Coordinate_calc, langcode("POPUPOB001"));
+
+//----- Frame for generic options
+ ob_option_frame = XtVaCreateManagedWidget("Set_Del_Object ob_option_frame",
+ xmFrameWidgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_frame,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // "Generic Options"
+ ob_option_ts = XtVaCreateManagedWidget(langcode("POPUPOB027"),
+ xmLabelWidgetClass,
+ ob_option_frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ ob_option_form = XtVaCreateWidget("Set_Del_Object ob_option_form",
+ xmFormWidgetClass,
+ ob_option_frame,
+ XmNfractionBase, 5,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Speed"
+ ob_speed = XtVaCreateManagedWidget(langcode("POPUPOB036"),
+ xmLabelWidgetClass,
+ ob_option_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 10,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ ob_speed_data = XtVaCreateManagedWidget("Set_Del_Object ob_speed_data",
+ xmTextFieldWidgetClass,
+ ob_option_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 3,
+ XmNmaxLength, 3,
+ XmNtopOffset, 3,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_speed,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Course"
+ ob_course = XtVaCreateManagedWidget(langcode("POPUPOB037"),
+ xmLabelWidgetClass,
+ ob_option_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 10,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_speed_data,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ ob_course_data = XtVaCreateManagedWidget("Set_Del_Object ob_course_data",
+ xmTextFieldWidgetClass,
+ ob_option_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 3,
+ XmNmaxLength, 3,
+ XmNtopOffset, 3,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_course,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Altitude"
+ ob_altitude = XtVaCreateManagedWidget(langcode("POPUPOB035"),
+ xmLabelWidgetClass,
+ ob_option_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 10,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_course_data,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ ob_altitude_data = XtVaCreateManagedWidget("Set_Del_Object ob_altitude_data",
+ xmTextFieldWidgetClass,
+ ob_option_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNmaxLength, 6,
+ XmNtopOffset, 3,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_altitude,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+//----- Comment Field
+ // "Comment:"
+ ob_comment = XtVaCreateManagedWidget(langcode("WPUPCFS017"),
+ xmLabelWidgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_option_frame,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ object_comment_data = XtVaCreateManagedWidget("Set_Del_Object comment",
+ xmTextFieldWidgetClass,
+ ob_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 43, // max 43 without Data Extension
+ XmNmaxLength, 43,
+ XmNtopOffset, 6,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_comment,
+ XmNleftOffset, 5,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_option_frame,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ // "Probability Circles"
+ probabilities_toggle = XtVaCreateManagedWidget(langcode("POPUPOB047"),
+ xmToggleButtonGadgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_latlon_frame,
+ XmNtopOffset, 2,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNbottomOffset, 0,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_option_frame,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(probabilities_toggle,XmNvalueChangedCallback,Probability_circle_toggle,(XtPointer)p_station);
+
+
+ // "Signpost Enable"
+ signpost_toggle = XtVaCreateManagedWidget(langcode("POPUPOB029"),
+ xmToggleButtonGadgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, probabilities_toggle,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNbottomOffset, 0,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_option_frame,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(signpost_toggle,XmNvalueChangedCallback,Signpost_object_toggle,(XtPointer)p_station);
+
+
+ // "Area Enable"
+ area_toggle = XtVaCreateManagedWidget(langcode("POPUPOB008"),
+ xmToggleButtonGadgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, signpost_toggle,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNbottomOffset, 0,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_option_frame,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(area_toggle,XmNvalueChangedCallback,Area_object_toggle,(XtPointer)p_station);
+
+
+
+ // "Area Enable"
+ df_bearing_toggle = XtVaCreateManagedWidget(langcode("POPUPOB038"),
+ xmToggleButtonGadgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, area_toggle,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNbottomOffset, 0,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_option_frame,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(df_bearing_toggle,XmNvalueChangedCallback,DF_bearing_object_toggle,(XtPointer)p_station);
+
+
+
+ // "Map View Object"
+ map_view_toggle = XtVaCreateManagedWidget(langcode("POPUPOB048"),
+ xmToggleButtonGadgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, df_bearing_toggle,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNbottomOffset, 0,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_option_frame,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(map_view_toggle,XmNvalueChangedCallback,Map_View_object_toggle,(XtPointer)p_station);
+
+
+
+//----- Frame for Probability Circles info
+if (Probability_circles_enabled) {
+
+ //fprintf(stderr,"Drawing probability circle data\n");
+
+ probability_frame = XtVaCreateManagedWidget("Set_Del_Object probability_frame",
+ xmFrameWidgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, map_view_toggle,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Probability Circles"
+ probability_ts = XtVaCreateManagedWidget(langcode("POPUPOB047"),
+ xmLabelWidgetClass,
+ probability_frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ probability_form = XtVaCreateWidget("Set_Del_Object probability_form",
+ xmFormWidgetClass,
+ probability_frame,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Min (mi):"
+ probability_label_min = XtVaCreateManagedWidget(langcode("POPUPOB049"),
+ xmLabelWidgetClass,
+ probability_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ probability_data_min = XtVaCreateManagedWidget("Set_Del_Object probability_data_min",
+ xmTextFieldWidgetClass,
+ probability_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 10,
+ XmNmaxLength, 10,
+ XmNtopOffset, 3,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, probability_label_min,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Max (mi):"
+ probability_label_max = XtVaCreateManagedWidget(langcode("POPUPOB050"),
+ xmLabelWidgetClass,
+ probability_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, probability_label_min,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNbottomOffset, 10,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ probability_data_max = XtVaCreateManagedWidget("Set_Del_Object probability_data_max",
+ xmTextFieldWidgetClass,
+ probability_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 10,
+ XmNmaxLength, 10,
+ XmNtopOffset, 3,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, probability_label_max,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, probability_label_min,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+
+ ob_sep = XtVaCreateManagedWidget("Set_Del_Object ob_sep",
+ xmSeparatorGadgetClass,
+ ob_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, probability_frame,
+ XmNtopOffset, 14,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+}
+
+
+
+//----- Frame for signpost info
+else if (Signpost_object_enabled) {
+
+ //fprintf(stderr,"Drawing signpost data\n");
+
+ signpost_frame = XtVaCreateManagedWidget("Set_Del_Object signpost_frame",
+ xmFrameWidgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, map_view_toggle,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // "Signpost"
+ signpost_ts = XtVaCreateManagedWidget(langcode("POPUPOB031"),
+ xmLabelWidgetClass,
+ signpost_frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ signpost_form = XtVaCreateWidget("Set_Del_Object signpost_form",
+ xmFormWidgetClass,
+ signpost_frame,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Signpost Data"
+ signpost_label = XtVaCreateManagedWidget(langcode("POPUPOB030"),
+ xmLabelWidgetClass,
+ signpost_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 10,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ signpost_data = XtVaCreateManagedWidget("Set_Del_Object signpost_data",
+ xmTextFieldWidgetClass,
+ signpost_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 3,
+ XmNmaxLength, 3,
+ XmNtopOffset, 3,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, signpost_label,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ ob_sep = XtVaCreateManagedWidget("Set_Del_Object ob_sep",
+ xmSeparatorGadgetClass,
+ ob_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, signpost_frame,
+ XmNtopOffset, 14,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+}
+
+
+
+//----- Frame for area info
+else if (Area_object_enabled) {
+
+ //fprintf(stderr,"Drawing Area data\n");
+
+ area_frame = XtVaCreateManagedWidget("Set_Del_Object area_frame",
+ xmFrameWidgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, map_view_toggle,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // "Area Options"
+ area_ts = XtVaCreateManagedWidget(langcode("POPUPOB007"),
+ xmLabelWidgetClass,
+ area_frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ area_form = XtVaCreateWidget("Set_Del_Object area_form",
+ xmFormWidgetClass,
+ area_frame,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ // "Bright Color Enable"
+ bright_dim_toggle = XtVaCreateManagedWidget(langcode("POPUPOB009"),
+ xmToggleButtonGadgetClass,
+ area_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNset, FALSE, // Select default to be OFF
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(bright_dim_toggle,XmNvalueChangedCallback,Area_bright_dim_toggle,"1");
+ Area_bright = 0; // Set to default each time dialog is created
+
+ // "Color-Fill Enable"
+ open_filled_toggle = XtVaCreateManagedWidget(langcode("POPUPOB010"),
+ xmToggleButtonGadgetClass,
+ area_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, bright_dim_toggle,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNset, FALSE, // Select default to be OFF
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(open_filled_toggle,XmNvalueChangedCallback,Area_open_filled_toggle,"1");
+ Area_filled = 0; // Set to default each time dialog is created
+
+
+// Shape of object
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+
+ shape_box = XmCreateRadioBox(area_form,
+ "Set_Del_Object Shape Options box",
+ al,
+ ac);
+
+ XtVaSetValues(shape_box,
+ XmNpacking, XmPACK_TIGHT,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, bright_dim_toggle,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnumColumns,1,
+ NULL);
+
+
+ // "Circle"
+ toption1 = XtVaCreateManagedWidget(langcode("POPUPOB011"),
+ xmToggleButtonGadgetClass,
+ shape_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(toption1,XmNvalueChangedCallback,Area_type_toggle,"0");
+
+ // "Line-Right '/'"
+ toption2 = XtVaCreateManagedWidget(langcode("POPUPOB013"),
+ xmToggleButtonGadgetClass,
+ shape_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(toption2,XmNvalueChangedCallback,Area_type_toggle,"1");
+
+ // "Line-Left '\'
+ toption3 = XtVaCreateManagedWidget(langcode("POPUPOB012"),
+ xmToggleButtonGadgetClass,
+ shape_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(toption3,XmNvalueChangedCallback,Area_type_toggle,"6");
+
+ // "Triangle"
+ toption4 = XtVaCreateManagedWidget(langcode("POPUPOB014"),
+ xmToggleButtonGadgetClass,
+ shape_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(toption4,XmNvalueChangedCallback,Area_type_toggle,"3");
+
+ // "Rectangle"
+ toption5 = XtVaCreateManagedWidget(langcode("POPUPOB015"),
+ xmToggleButtonGadgetClass,
+ shape_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(toption5,XmNvalueChangedCallback,Area_type_toggle,"4");
+
+
+// Color of object
+ color_box = XmCreateRadioBox(area_form,
+ "Set_Del_Object Color Options box",
+ al,
+ ac);
+
+ XtVaSetValues(color_box,
+ XmNpacking, XmPACK_TIGHT,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, shape_box,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ NULL);
+
+
+ XtVaSetValues(color_box,
+ XmNnumColumns,4,
+ NULL);
+
+ // "Black"
+ coption1 = XtVaCreateManagedWidget(langcode("POPUPOB016"),
+ xmToggleButtonGadgetClass,
+ color_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coption1,XmNvalueChangedCallback,Area_color_toggle,"/0");
+
+ // "Blue"
+ coption2 = XtVaCreateManagedWidget(langcode("POPUPOB017"),
+ xmToggleButtonGadgetClass,
+ color_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coption2,XmNvalueChangedCallback,Area_color_toggle,"/1");
+
+ // "Green"
+ coption3 = XtVaCreateManagedWidget(langcode("POPUPOB018"),
+ xmToggleButtonGadgetClass,
+ color_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coption3,XmNvalueChangedCallback,Area_color_toggle,"/2");
+
+ // "Cyan"
+ coption4 = XtVaCreateManagedWidget(langcode("POPUPOB019"),
+ xmToggleButtonGadgetClass,
+ color_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coption4,XmNvalueChangedCallback,Area_color_toggle,"/3");
+
+ // "Red"
+ coption5 = XtVaCreateManagedWidget(langcode("POPUPOB020"),
+ xmToggleButtonGadgetClass,
+ color_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coption5,XmNvalueChangedCallback,Area_color_toggle,"/4");
+
+ // "Violet"
+ coption6 = XtVaCreateManagedWidget(langcode("POPUPOB021"),
+ xmToggleButtonGadgetClass,
+ color_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coption6,XmNvalueChangedCallback,Area_color_toggle,"/5");
+
+ // "Yellow"
+ coption7 = XtVaCreateManagedWidget(langcode("POPUPOB022"),
+ xmToggleButtonGadgetClass,
+ color_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coption7,XmNvalueChangedCallback,Area_color_toggle,"/6");
+
+ // "Grey"
+ coption8 = XtVaCreateManagedWidget(langcode("POPUPOB023"),
+ xmToggleButtonGadgetClass,
+ color_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(coption8,XmNvalueChangedCallback,Area_color_toggle,"/7");
+
+// Latitude offset
+ // "Offset Up"
+ ob_lat_offset = XtVaCreateManagedWidget(langcode("POPUPOB024"),
+ xmLabelWidgetClass,
+ area_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, color_box,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 10,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ ob_lat_offset_data = XtVaCreateManagedWidget("Set_Del_Object lat offset",
+ xmTextFieldWidgetClass,
+ area_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 4,
+ XmNmaxLength, 4,
+ XmNtopOffset, 5,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_lat_offset,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, color_box,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+// Longitude offset
+ // "Offset Left (except for '/')"
+ ob_lon_offset = XtVaCreateManagedWidget(langcode("POPUPOB025"),
+ xmLabelWidgetClass,
+ area_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, color_box,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 10,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_lat_offset_data,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ ob_lon_offset_data = XtVaCreateManagedWidget("Set_Del_Object long offset",
+ xmTextFieldWidgetClass,
+ area_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 4,
+ XmNmaxLength, 4,
+ XmNtopOffset, 5,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_lon_offset,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, color_box,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Corridor (Lines only)"
+ ob_corridor = XtVaCreateManagedWidget(langcode("POPUPOB026"),
+ xmLabelWidgetClass,
+ area_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, color_box,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 10,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_lon_offset_data,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ ob_corridor_data = XtVaCreateManagedWidget("Set_Del_Object lat offset",
+ xmTextFieldWidgetClass,
+ area_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 3,
+ XmNmaxLength, 3,
+ XmNtopOffset, 5,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_corridor,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, color_box,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ // "Miles"
+ ob_corridor_miles = XtVaCreateManagedWidget(langcode("UNIOP00004"),
+ xmLabelWidgetClass,
+ area_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, color_box,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 10,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_corridor_data,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtSetSensitive(ob_corridor,FALSE);
+ XtSetSensitive(ob_corridor_data,FALSE);
+ XtSetSensitive(ob_corridor_miles,FALSE);
+
+
+ ob_sep = XtVaCreateManagedWidget("Set_Del_Object ob_sep",
+ xmSeparatorGadgetClass,
+ ob_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, area_frame,
+ XmNtopOffset, 14,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+}
+
+
+
+//----- Frame for DF-omni info
+else if (DF_object_enabled) {
+
+ //fprintf(stderr,"Drawing DF data\n");
+
+ // "Omni Antenna"
+ omni_antenna_toggle = XtVaCreateManagedWidget(langcode("POPUPOB041"),
+ xmToggleButtonGadgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, signpost_toggle,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNbottomOffset, 0,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, area_toggle,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(omni_antenna_toggle,XmNvalueChangedCallback,Omni_antenna_toggle,(XtPointer)p_station);
+
+
+ // "Beam Antenna"
+ beam_antenna_toggle = XtVaCreateManagedWidget(langcode("POPUPOB042"),
+ xmToggleButtonGadgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, omni_antenna_toggle,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNbottomOffset, 0,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, area_toggle,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(beam_antenna_toggle,XmNvalueChangedCallback,Beam_antenna_toggle,(XtPointer)p_station);
+
+
+ frameomni = XtVaCreateManagedWidget("Set_Del_Object frameomni",
+ xmFrameWidgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, map_view_toggle,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ omnilabel = XtVaCreateManagedWidget(langcode("POPUPOB039"),
+ xmLabelWidgetClass,
+ frameomni,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ formomni = XtVaCreateWidget("Set_Del_Object formomni",
+ xmFormWidgetClass,
+ frameomni,
+ XmNfractionBase, 5,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ // Power
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+
+ signal_box = XmCreateRadioBox(formomni,
+ "Set_Del_Object Power Radio Box",
+ al,
+ ac);
+
+ XtVaSetValues(signal_box,
+ XmNpacking, XmPACK_TIGHT,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnumColumns, 11,
+ NULL);
+
+ // No signal detected what-so-ever
+ soption0 = XtVaCreateManagedWidget("0",
+ xmToggleButtonGadgetClass,
+ signal_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(soption0,XmNvalueChangedCallback,Ob_signal_toggle,"0");
+
+ // Detectible signal (Maybe)
+ soption1 = XtVaCreateManagedWidget("1",
+ xmToggleButtonGadgetClass,
+ signal_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(soption1,XmNvalueChangedCallback,Ob_signal_toggle,"1");
+
+ // Detectible signal (certain but not copyable)
+ soption2 = XtVaCreateManagedWidget("2",
+ xmToggleButtonGadgetClass,
+ signal_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(soption2,XmNvalueChangedCallback,Ob_signal_toggle,"2");
+
+ // Weak signal marginally readable
+ soption3 = XtVaCreateManagedWidget("3",
+ xmToggleButtonGadgetClass,
+ signal_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(soption3,XmNvalueChangedCallback,Ob_signal_toggle,"3");
+
+ // Noisy but copyable
+ soption4 = XtVaCreateManagedWidget("4",
+ xmToggleButtonGadgetClass,
+ signal_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(soption4,XmNvalueChangedCallback,Ob_signal_toggle,"4");
+
+ // Some noise but easy to copy
+ soption5 = XtVaCreateManagedWidget("5",
+ xmToggleButtonGadgetClass,
+ signal_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(soption5,XmNvalueChangedCallback,Ob_signal_toggle,"5");
+
+ // Good signal with detectible noise
+ soption6 = XtVaCreateManagedWidget("6",
+ xmToggleButtonGadgetClass,
+ signal_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(soption6,XmNvalueChangedCallback,Ob_signal_toggle,"6");
+
+ // Near full-quieting signal
+ soption7 = XtVaCreateManagedWidget("7",
+ xmToggleButtonGadgetClass,
+ signal_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(soption7,XmNvalueChangedCallback,Ob_signal_toggle,"7");
+
+ // Dead full-quieting signal, no noise detectible
+ soption8 = XtVaCreateManagedWidget("8",
+ xmToggleButtonGadgetClass,
+ signal_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(soption8,XmNvalueChangedCallback,Ob_signal_toggle,"8");
+
+ // Extremely strong signal "pins the meter"
+ soption9 = XtVaCreateManagedWidget("9",
+ xmToggleButtonGadgetClass,
+ signal_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(soption9,XmNvalueChangedCallback,Ob_signal_toggle,"9");
+
+
+ // Height
+ height_box = XmCreateRadioBox(formomni,
+ "Set_Del_Object Height Radio Box",
+ al,
+ ac);
+
+ XtVaSetValues(height_box,
+ XmNpacking, XmPACK_TIGHT,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget,signal_box,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnumColumns,10,
+ NULL);
+
+
+ // 10 Feet
+ hoption0 = XtVaCreateManagedWidget(
+ (english_units) ? "10ft" : "3m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption0,XmNvalueChangedCallback,Ob_height_toggle,"0");
+
+ // 20 Feet
+ hoption1 = XtVaCreateManagedWidget(
+ (english_units) ? "20ft" : "6m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption1,XmNvalueChangedCallback,Ob_height_toggle,"1");
+
+ // 40 Feet
+ hoption2 = XtVaCreateManagedWidget(
+ (english_units) ? "40ft" : "12m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption2,XmNvalueChangedCallback,Ob_height_toggle,"2");
+
+ // 80 Feet
+ hoption3 = XtVaCreateManagedWidget(
+ (english_units) ? "80ft" : "24m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption3,XmNvalueChangedCallback,Ob_height_toggle,"3");
+
+ // 160 Feet
+ hoption4 = XtVaCreateManagedWidget(
+ (english_units) ? "160ft" : "49m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption4,XmNvalueChangedCallback,Ob_height_toggle,"4");
+
+ // 320 Feet
+ hoption5 = XtVaCreateManagedWidget(
+ (english_units) ? "320ft" : "98m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption5,XmNvalueChangedCallback,Ob_height_toggle,"5");
+
+ // 640 Feet
+ hoption6 = XtVaCreateManagedWidget(
+ (english_units) ? "640ft" : "195m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption6,XmNvalueChangedCallback,Ob_height_toggle,"6");
+
+ // 1280 Feet
+ hoption7 = XtVaCreateManagedWidget(
+ (english_units) ? "1280ft" : "390m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption7,XmNvalueChangedCallback,Ob_height_toggle,"7");
+
+ // 2560 Feet
+ hoption8 = XtVaCreateManagedWidget(
+ (english_units) ? "2560ft" : "780m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption8,XmNvalueChangedCallback,Ob_height_toggle,"8");
+
+ // 5120 Feet
+ hoption9 = XtVaCreateManagedWidget(
+ (english_units) ? "5120ft" : "1561m",
+ xmToggleButtonGadgetClass,
+ height_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(hoption9,XmNvalueChangedCallback,Ob_height_toggle,"9");
+
+
+ // Gain
+ gain_box = XmCreateRadioBox(formomni,
+ "Set_Del_Object Gain Radio Box",
+ al,
+ ac);
+
+ XtVaSetValues(gain_box,
+ XmNpacking, XmPACK_TIGHT,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget,height_box,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnumColumns,10,
+ NULL);
+
+
+ // 0 dB
+ goption0 = XtVaCreateManagedWidget("0dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption0,XmNvalueChangedCallback,Ob_gain_toggle,"0");
+
+ // 1 dB
+ goption1 = XtVaCreateManagedWidget("1dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption1,XmNvalueChangedCallback,Ob_gain_toggle,"1");
+
+ // 2 dB
+ goption2 = XtVaCreateManagedWidget("2dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption2,XmNvalueChangedCallback,Ob_gain_toggle,"2");
+
+ // 3 dB
+ goption3 = XtVaCreateManagedWidget("3dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption3,XmNvalueChangedCallback,Ob_gain_toggle,"3");
+
+ // 4 dB
+ goption4 = XtVaCreateManagedWidget("4dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption4,XmNvalueChangedCallback,Ob_gain_toggle,"4");
+
+ // 5 dB
+ goption5 = XtVaCreateManagedWidget("5dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption5,XmNvalueChangedCallback,Ob_gain_toggle,"5");
+
+ // 6 dB
+ goption6 = XtVaCreateManagedWidget("6dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption6,XmNvalueChangedCallback,Ob_gain_toggle,"6");
+
+ // 7 dB
+ goption7 = XtVaCreateManagedWidget("7dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption7,XmNvalueChangedCallback,Ob_gain_toggle,"7");
+
+ // 8 dB
+ goption8 = XtVaCreateManagedWidget("8dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption8,XmNvalueChangedCallback,Ob_gain_toggle,"8");
+
+ // 9 dB
+ goption9 = XtVaCreateManagedWidget("9dB",
+ xmToggleButtonGadgetClass,
+ gain_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(goption9,XmNvalueChangedCallback,Ob_gain_toggle,"9");
+
+
+ // Gain
+ directivity_box = XmCreateRadioBox(formomni,
+ "Set_Del_Object Directivity Radio Box",
+ al,
+ ac);
+
+ XtVaSetValues(directivity_box,
+ XmNpacking, XmPACK_TIGHT,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget,gain_box,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnumColumns,10,
+ NULL);
+
+
+ // Omni-directional
+ doption0 = XtVaCreateManagedWidget(langcode("WPUPCFS016"),
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption0,XmNvalueChangedCallback,Ob_directivity_toggle,"0");
+
+ // 45 NE
+ doption1 = XtVaCreateManagedWidget("45�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption1,XmNvalueChangedCallback,Ob_directivity_toggle,"1");
+
+ // 90 E
+ doption2 = XtVaCreateManagedWidget("90�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption2,XmNvalueChangedCallback,Ob_directivity_toggle,"2");
+
+ // 135 SE
+ doption3 = XtVaCreateManagedWidget("135�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption3,XmNvalueChangedCallback,Ob_directivity_toggle,"3");
+
+ // 180 S
+ doption4 = XtVaCreateManagedWidget("180�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption4,XmNvalueChangedCallback,Ob_directivity_toggle,"4");
+
+ // 225 SW
+ doption5 = XtVaCreateManagedWidget("225�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption5,XmNvalueChangedCallback,Ob_directivity_toggle,"5");
+
+ // 270 W
+ doption6 = XtVaCreateManagedWidget("270�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption6,XmNvalueChangedCallback,Ob_directivity_toggle,"6");
+
+ // 315 NW
+ doption7 = XtVaCreateManagedWidget("315�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption7,XmNvalueChangedCallback,Ob_directivity_toggle,"7");
+
+ // 360 N
+ doption8 = XtVaCreateManagedWidget("360�",
+ xmToggleButtonGadgetClass,
+ directivity_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(doption8,XmNvalueChangedCallback,Ob_directivity_toggle,"8");
+
+
+//----- Frame for DF-beam info
+ framebeam = XtVaCreateManagedWidget("Set_Del_Object framebeam",
+ xmFrameWidgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frameomni,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ beamlabel = XtVaCreateManagedWidget(langcode("POPUPOB040"),
+ xmLabelWidgetClass,
+ framebeam,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ formbeam = XtVaCreateWidget("Set_Del_Object formbeam",
+ xmFormWidgetClass,
+ framebeam,
+ XmNfractionBase, 5,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+
+ // Beam width
+ ac = 0;
+ XtSetArg(al[ac], XmNforeground, MY_FG_COLOR); ac++;
+ XtSetArg(al[ac], XmNbackground, MY_BG_COLOR); ac++;
+
+ width_box = XmCreateRadioBox(formbeam,
+ "Set_Del_Object Width Box",
+ al,
+ ac);
+
+ XtVaSetValues(width_box,
+ XmNpacking, XmPACK_TIGHT,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNnumColumns, 11,
+ NULL);
+
+ // Useless
+ woption0 = XtVaCreateManagedWidget(langcode("POPUPOB043"),
+ xmToggleButtonGadgetClass,
+ width_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(woption0,XmNvalueChangedCallback,Ob_width_toggle,"0");
+
+ // < 240 Degrees
+ woption1 = XtVaCreateManagedWidget("<240�",
+ xmToggleButtonGadgetClass,
+ width_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(woption1,XmNvalueChangedCallback,Ob_width_toggle,"1");
+
+ // < 120 Degrees
+ woption2 = XtVaCreateManagedWidget("<120�",
+ xmToggleButtonGadgetClass,
+ width_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(woption2,XmNvalueChangedCallback,Ob_width_toggle,"2");
+
+ // < 64 Degrees
+ woption3 = XtVaCreateManagedWidget("<64�",
+ xmToggleButtonGadgetClass,
+ width_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(woption3,XmNvalueChangedCallback,Ob_width_toggle,"3");
+
+ // < 32 Degrees
+ woption4 = XtVaCreateManagedWidget("<32�",
+ xmToggleButtonGadgetClass,
+ width_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(woption4,XmNvalueChangedCallback,Ob_width_toggle,"4");
+
+ // < 16 Degrees
+ woption5 = XtVaCreateManagedWidget("<16�",
+ xmToggleButtonGadgetClass,
+ width_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(woption5,XmNvalueChangedCallback,Ob_width_toggle,"5");
+
+ // < 8 Degrees
+ woption6 = XtVaCreateManagedWidget("<8�",
+ xmToggleButtonGadgetClass,
+ width_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(woption6,XmNvalueChangedCallback,Ob_width_toggle,"6");
+
+ // < 4 Degrees
+ woption7 = XtVaCreateManagedWidget("<4�",
+ xmToggleButtonGadgetClass,
+ width_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(woption7,XmNvalueChangedCallback,Ob_width_toggle,"7");
+
+ // < 2 Degrees
+ woption8 = XtVaCreateManagedWidget("<2�",
+ xmToggleButtonGadgetClass,
+ width_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(woption8,XmNvalueChangedCallback,Ob_width_toggle,"8");
+
+ // < 1 Degrees
+ woption9 = XtVaCreateManagedWidget("<1�",
+ xmToggleButtonGadgetClass,
+ width_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(woption9,XmNvalueChangedCallback,Ob_width_toggle,"9");
+
+
+ // "Bearing"
+ ob_bearing = XtVaCreateManagedWidget(langcode("POPUPOB046"),
+ xmLabelWidgetClass,
+ formbeam,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, width_box,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ // Bearing data
+ ob_bearing_data = XtVaCreateManagedWidget("Set_Del_Object ob_bearing_data",
+ xmTextFieldWidgetClass,
+ formbeam,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 9,
+ XmNmaxLength, 9,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, width_box,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, ob_bearing,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ XtSetSensitive(frameomni,FALSE);
+ XtSetSensitive(framebeam,FALSE);
+ Omni_antenna_enabled = 0;
+ Beam_antenna_enabled = 0;
+
+
+ ob_sep = XtVaCreateManagedWidget("Set_Del_Object ob_sep",
+ xmSeparatorGadgetClass,
+ ob_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, framebeam,
+ XmNtopOffset, 14,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+}
+// End of DF-specific widgets
+
+
+
+//----- No Special options selected. We need a widget here for the next widget to attach to.
+ if (!DF_object_enabled
+ && !Area_object_enabled
+ && !Signpost_object_enabled
+ && !Probability_circles_enabled) {
+
+ //fprintf(stderr,"No special object types\n");
+
+ ob_sep = XtVaCreateManagedWidget("Set_Del_Object ob_sep",
+ xmSeparatorGadgetClass,
+ ob_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, map_view_toggle,
+ XmNtopOffset, 0,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ }
+
+
+
+//----- Buttons
+ if (p_station != NULL) { // We were called from the Modify_object() or Move function
+
+ // Change the buttons/callbacks based on whether we're dealing with an item or an object
+ if ((p_station->flag & ST_ITEM) != 0) { // Modifying an Item
+ // Here we need Modify Item/Delete Item/Cancel buttons
+ ob_button_set = XtVaCreateManagedWidget(langcode("POPUPOB034"),
+ xmPushButtonGadgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ob_button_set, XmNactivateCallback, Item_change_data_set, object_dialog);
+
+ // Check whether we own this item
+ if (strcasecmp(p_station->origin,my_callsign)==0) {
+
+ // We own this item, set up the "Delete"
+ // button.
+ ob_button_del = XtVaCreateManagedWidget(langcode("POPUPOB033"),
+ xmPushButtonGadgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ob_button_del, XmNactivateCallback, Item_change_data_del, object_dialog);
+ }
+ else {
+
+ // Somebody else owns this item, set up the
+ // "Adopt" button.
+ ob_button_del = XtVaCreateManagedWidget(langcode("POPUPOB045"),
+ xmPushButtonGadgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ob_button_del, XmNactivateCallback, Item_change_data_set, object_dialog);
+ }
+ }
+ else { // Modifying an Object
+ // Here we need Modify Object/Delete Object/Cancel buttons
+ ob_button_set = XtVaCreateManagedWidget(langcode("POPUPOB005"),
+ xmPushButtonGadgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ob_button_set, XmNactivateCallback, Object_change_data_set, object_dialog);
+
+ // Check whether we own this Object
+ if (strcasecmp(p_station->origin,my_callsign)==0) {
+
+ // We own this object, set up the "Delete"
+ // button.
+ ob_button_del = XtVaCreateManagedWidget(langcode("POPUPOB004"),
+ xmPushButtonGadgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ob_button_del, XmNactivateCallback, Object_change_data_del, object_dialog);
+ }
+ else {
+
+ // Somebody else owns this object, set up the
+ // "Adopt" button.
+ ob_button_del = XtVaCreateManagedWidget(langcode("POPUPOB044"),
+ xmPushButtonGadgetClass,
+ ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ob_button_del, XmNactivateCallback, Object_change_data_set, object_dialog);
+ }
+ }
+ }
+ else { // We were called from Create->Object mouse menu
+ ob_button_set = XtVaCreateManagedWidget(langcode("POPUPOB003"),xmPushButtonGadgetClass, ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ it_button_set = XtVaCreateManagedWidget(langcode("POPUPOB006"),xmPushButtonGadgetClass, ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ // Changed to different callback routines here which
+ // check the new object/item name against our internal
+ // database then call
+ // Object_change_data_set/Item_change_data_set if all
+ // ok. If a conflict (object/item already exists), do a
+ // popup_message() instead or bring up a confirmation
+ // dialog before creating the object/item.
+ //
+ //XtAddCallback(ob_button_set,
+ // XmNactivateCallback,
+ // Object_change_data_set,
+ // object_dialog);
+ //XtAddCallback(it_button_set,
+ // XmNactivateCallback,
+ // Item_change_data_set,
+ // object_dialog);
+ XtAddCallback(ob_button_set,
+ XmNactivateCallback,
+ Object_confirm_data_set,
+ object_dialog);
+ XtAddCallback(it_button_set,
+ XmNactivateCallback,
+ Item_confirm_data_set,
+ object_dialog);
+ }
+
+ ob_button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),xmPushButtonGadgetClass, ob_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, ob_sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XtAddCallback(ob_button_cancel, XmNactivateCallback, Object_destroy_shell, object_dialog);
+
+
+ // Set ToggleButtons for the current state. Don't notify the callback
+ // functions associated with them or we'll be in an infinite loop.
+ if (Area_object_enabled)
+ XmToggleButtonSetState(area_toggle, TRUE, FALSE);
+ if (Signpost_object_enabled)
+ XmToggleButtonSetState(signpost_toggle, TRUE, FALSE);
+ if (DF_object_enabled)
+ XmToggleButtonSetState(df_bearing_toggle, TRUE, FALSE);
+ if (Map_View_object_enabled)
+ XmToggleButtonSetState(map_view_toggle, TRUE, FALSE);
+ if (Probability_circles_enabled)
+ XmToggleButtonSetState(probabilities_toggle, TRUE, FALSE);
+
+
+// Fill in current data if object already exists
+ if (p_station != NULL) { // We were called from the Modify_object() or Move functions
+
+ // Don't allow changing types if the object is already created.
+ // Already tried allowing it, and it causes other problems.
+ XtSetSensitive(area_toggle, FALSE);
+ XtSetSensitive(signpost_toggle, FALSE);
+ XtSetSensitive(df_bearing_toggle, FALSE);
+ XtSetSensitive(map_view_toggle, FALSE);
+ XtSetSensitive(probabilities_toggle, FALSE);
+
+ XmTextFieldSetString(object_name_data,p_station->call_sign);
+ // Need to make the above field non-editable 'cuz we're trying to modify
+ // _parameters_ of the object and the name has to stay the same in order
+ // to do this. Change the name and we'll be creating a new object instead
+ // of modifying an old one.
+ XtSetSensitive(object_name_data, FALSE);
+ // Would be nice to change the colors too
+
+ // Check for overlay character
+ if (p_station->aprs_symbol.special_overlay) {
+ // Found an overlay character
+ temp_data[0] = p_station->aprs_symbol.special_overlay;
+ }
+ else { // No overlay character
+ temp_data[0] = p_station->aprs_symbol.aprs_type;
+ }
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = p_station->aprs_symbol.aprs_symbol;
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ // We only check the first possible comment string in
+ // the record
+ //if (strlen(p_station->comments) > 0)
+ if (Map_View_object_enabled) {
+
+ if ( (p_station->comment_data != NULL)
+ && (p_station->comment_data->text_ptr != NULL) ) {
+ char temp[100];
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s%s",
+ p_station->power_gain,
+ p_station->comment_data->text_ptr);
+ XmTextFieldSetString(object_comment_data,temp);
+ }
+ else {
+ XmTextFieldSetString(object_comment_data,p_station->power_gain);
+ }
+ }
+
+ else if ( (p_station->comment_data != NULL)
+ && (p_station->comment_data->text_ptr != NULL) ) {
+ XmTextFieldSetString(object_comment_data,p_station->comment_data->text_ptr);
+ }
+
+ else {
+ XmTextFieldSetString(object_comment_data,"");
+ }
+
+
+// if ( (p_station->aprs_symbol.area_object.type != AREA_NONE) // Found an area object
+// && Area_object_enabled ) {
+if (Area_object_enabled) {
+
+ XtSetSensitive(ob_frame,FALSE);
+ XtSetSensitive(area_frame,TRUE);
+
+ switch (p_station->aprs_symbol.area_object.type) {
+ case (1): // Line '/'
+ XmToggleButtonSetState(toption2, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(open_filled_toggle, FALSE, TRUE);
+ if (p_station->aprs_symbol.area_object.corridor_width > 0)
+ xastir_snprintf(temp_data, sizeof(temp_data), "%d",
+ p_station->aprs_symbol.area_object.corridor_width );
+ else
+ temp_data[0] = '\0'; // Empty string
+
+ XmTextFieldSetString( ob_corridor_data, temp_data );
+ break;
+ case (6): // Line '\'
+ XmToggleButtonGadgetSetState(toption3, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(open_filled_toggle, FALSE, TRUE);
+ if (p_station->aprs_symbol.area_object.corridor_width > 0)
+ xastir_snprintf(temp_data, sizeof(temp_data), "%d",
+ p_station->aprs_symbol.area_object.corridor_width );
+ else
+ temp_data[0] = '\0'; // Empty string
+
+ XmTextFieldSetString( ob_corridor_data, temp_data );
+ break;
+ case (3): // Open Triangle
+ XmToggleButtonGadgetSetState(toption4, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(open_filled_toggle, FALSE, TRUE);
+ break;
+ case (4): // Open Rectangle
+ XmToggleButtonGadgetSetState(toption5, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(open_filled_toggle, FALSE, TRUE);
+ break;
+ case (5): // Filled Circle
+ XmToggleButtonGadgetSetState(toption1, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(open_filled_toggle, TRUE, TRUE);
+ break;
+ case (8): // Filled Triangle
+ XmToggleButtonGadgetSetState(toption4, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(open_filled_toggle, TRUE, TRUE);
+ break;
+ case (9): // Filled Rectangle
+ XmToggleButtonGadgetSetState(toption5, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(open_filled_toggle, TRUE, TRUE);
+ break;
+ case (0): // Open Circle
+ default:
+ XmToggleButtonGadgetSetState(toption1, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(open_filled_toggle, FALSE, TRUE);
+ break;
+ }
+
+ switch (p_station->aprs_symbol.area_object.color) {
+ case (1): // Blue Bright
+ XmToggleButtonGadgetSetState(coption2, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, TRUE, TRUE);
+ break;
+ case (2): // Green Bright
+ XmToggleButtonGadgetSetState(coption3, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, TRUE, TRUE);
+ break;
+ case (3): // Cyan Bright
+ XmToggleButtonGadgetSetState(coption4, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, TRUE, TRUE);
+ break;
+ case (4): // Red Bright
+ XmToggleButtonGadgetSetState(coption5, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, TRUE, TRUE);
+ break;
+ case (5): // Violet Bright
+ XmToggleButtonGadgetSetState(coption6, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, TRUE, TRUE);
+ break;
+ case (6): // Yellow Bright
+ XmToggleButtonGadgetSetState(coption7, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, TRUE, TRUE);
+ break;
+ case (7): // Gray Bright
+ XmToggleButtonGadgetSetState(coption8, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, TRUE, TRUE);
+ break;
+ case (8): // Black Dim
+ XmToggleButtonGadgetSetState(coption1, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, FALSE, TRUE);
+ break;
+ case (9): // Blue Dim
+ XmToggleButtonGadgetSetState(coption2, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, FALSE, TRUE);
+ break;
+ case (10): // Green Dim
+ XmToggleButtonGadgetSetState(coption3, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, FALSE, TRUE);
+ break;
+ case (11): // Cyan Dim
+ XmToggleButtonGadgetSetState(coption4, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, FALSE, TRUE);
+ break;
+ case (12): // Red Dim
+ XmToggleButtonGadgetSetState(coption5, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, FALSE, TRUE);
+ break;
+ case (13): // Violet Dim
+ XmToggleButtonGadgetSetState(coption6, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, FALSE, TRUE);
+ break;
+ case (14): // Yellow Dim
+ XmToggleButtonGadgetSetState(coption7, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, FALSE, TRUE);
+ break;
+ case (15): // Gray Dim
+ XmToggleButtonGadgetSetState(coption8, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, FALSE, TRUE);
+ break;
+ case (0): // Black Bright
+ default:
+ XmToggleButtonGadgetSetState(coption1, TRUE, TRUE);
+ XmToggleButtonGadgetSetState(bright_dim_toggle, TRUE, TRUE);
+ break;
+ }
+
+ xastir_snprintf(temp_data, sizeof(temp_data), "%d",
+ p_station->aprs_symbol.area_object.sqrt_lat_off
+ * p_station->aprs_symbol.area_object.sqrt_lat_off );
+
+ XmTextFieldSetString( ob_lat_offset_data, temp_data );
+
+ xastir_snprintf(temp_data, sizeof(temp_data), "%d",
+ p_station->aprs_symbol.area_object.sqrt_lon_off
+ * p_station->aprs_symbol.area_object.sqrt_lon_off );
+
+ XmTextFieldSetString( ob_lon_offset_data, temp_data );
+
+ } // Done with filling in Area Objects
+
+ else { // Signpost/Probability/Normal Object
+
+ // Handle Generic Options (common to Signpost/Normal Objects)
+ if (strlen(p_station->speed) != 0) {
+ xastir_snprintf(temp_data, sizeof(temp_data), "%d",
+ (int)(atof(p_station->speed) + 0.5) );
+
+ XmTextFieldSetString( ob_speed_data, temp_data );
+ } else
+ XmTextFieldSetString( ob_speed_data, "" );
+
+ if (strlen(p_station->course) != 0)
+ XmTextFieldSetString( ob_course_data, p_station->course);
+ else
+ XmTextFieldSetString( ob_course_data, "" );
+
+// if ( (p_station->aprs_symbol.aprs_symbol == 'm') // Found a signpost object
+// && (p_station->aprs_symbol.aprs_type == '\\')
+// && Signpost_object_enabled) {
+ if (Signpost_object_enabled) {
+ XtSetSensitive(ob_frame,FALSE);
+ XtSetSensitive(signpost_frame,TRUE);
+ XmTextFieldSetString( signpost_data, p_station->signpost);
+ } // Done with filling in Signpost Objects
+
+
+ if (Probability_circles_enabled) {
+ // Fetch the min/max fields from the object data and
+ // write that data into the input fields.
+ XmTextFieldSetString( probability_data_min, p_station->probability_min );
+ XmTextFieldSetString( probability_data_max, p_station->probability_max );
+ }
+
+
+// else if ( (p_station->aprs_symbol.aprs_type == '/') // Found a DF object
+// && (p_station->aprs_symbol.aprs_symbol == '\\' )) {
+ if (DF_object_enabled) {
+ XtSetSensitive(ob_frame,FALSE);
+ //fprintf(stderr,"Found a DF object\n");
+
+ // Decide if it was an omni-DF object or a beam heading object
+ if (p_station->NRQ[0] == '\0') { // Must be an omni-DF object
+ //fprintf(stderr,"omni-DF\n");
+ //fprintf(stderr,"Signal_gain: %s\n", p_station->signal_gain);
+
+ XmToggleButtonSetState(omni_antenna_toggle, TRUE, TRUE);
+
+ // Set the received signal quality toggle
+ switch (p_station->signal_gain[3]) {
+ case ('1'): // 1
+ XmToggleButtonGadgetSetState(soption1, TRUE, TRUE);
+ break;
+ case ('2'): // 2
+ XmToggleButtonGadgetSetState(soption2, TRUE, TRUE);
+ break;
+ case ('3'): // 3
+ XmToggleButtonGadgetSetState(soption3, TRUE, TRUE);
+ break;
+ case ('4'): // 4
+ XmToggleButtonGadgetSetState(soption4, TRUE, TRUE);
+ break;
+ case ('5'): // 5
+ XmToggleButtonGadgetSetState(soption5, TRUE, TRUE);
+ break;
+ case ('6'): // 6
+ XmToggleButtonGadgetSetState(soption6, TRUE, TRUE);
+ break;
+ case ('7'): // 7
+ XmToggleButtonGadgetSetState(soption7, TRUE, TRUE);
+ break;
+ case ('8'): // 8
+ XmToggleButtonGadgetSetState(soption8, TRUE, TRUE);
+ break;
+ case ('9'): // 9
+ XmToggleButtonGadgetSetState(soption9, TRUE, TRUE);
+ break;
+ case ('0'): // 0
+ default:
+ XmToggleButtonGadgetSetState(soption0, TRUE, TRUE);
+ break;
+ }
+
+ // Set the HAAT toggle
+ switch (p_station->signal_gain[4]) {
+ case ('1'): // 20ft
+ XmToggleButtonGadgetSetState(hoption1, TRUE, TRUE);
+ break;
+ case ('2'): // 40ft
+ XmToggleButtonGadgetSetState(hoption2, TRUE, TRUE);
+ break;
+ case ('3'): // 80ft
+ XmToggleButtonGadgetSetState(hoption3, TRUE, TRUE);
+ break;
+ case ('4'): // 160ft
+ XmToggleButtonGadgetSetState(hoption4, TRUE, TRUE);
+ break;
+ case ('5'): // 320ft
+ XmToggleButtonGadgetSetState(hoption5, TRUE, TRUE);
+ break;
+ case ('6'): // 640ft
+ XmToggleButtonGadgetSetState(hoption6, TRUE, TRUE);
+ break;
+ case ('7'): // 1280ft
+ XmToggleButtonGadgetSetState(hoption7, TRUE, TRUE);
+ break;
+ case ('8'): // 2560ft
+ XmToggleButtonGadgetSetState(hoption8, TRUE, TRUE);
+ break;
+ case ('9'): // 5120ft
+ XmToggleButtonGadgetSetState(hoption9, TRUE, TRUE);
+ break;
+ case ('0'): // 10ft
+ default:
+ XmToggleButtonGadgetSetState(hoption0, TRUE, TRUE);
+ break;
+ }
+
+ // Set the antenna gain toggle
+ switch (p_station->signal_gain[5]) {
+ case ('1'): // 1dB
+ XmToggleButtonGadgetSetState(goption1, TRUE, TRUE);
+ break;
+ case ('2'): // 2dB
+ XmToggleButtonGadgetSetState(goption2, TRUE, TRUE);
+ break;
+ case ('3'): // 3dB
+ XmToggleButtonGadgetSetState(goption3, TRUE, TRUE);
+ break;
+ case ('4'): // 4dB
+ XmToggleButtonGadgetSetState(goption4, TRUE, TRUE);
+ break;
+ case ('5'): // 5dB
+ XmToggleButtonGadgetSetState(goption5, TRUE, TRUE);
+ break;
+ case ('6'): // 6dB
+ XmToggleButtonGadgetSetState(goption6, TRUE, TRUE);
+ break;
+ case ('7'): // 7dB
+ XmToggleButtonGadgetSetState(goption7, TRUE, TRUE);
+ break;
+ case ('8'): // 8dB
+ XmToggleButtonGadgetSetState(goption8, TRUE, TRUE);
+ break;
+ case ('9'): // 9dB
+ XmToggleButtonGadgetSetState(goption9, TRUE, TRUE);
+ break;
+ case ('0'): // 0dB
+ default:
+ XmToggleButtonGadgetSetState(goption0, TRUE, TRUE);
+ break;
+ }
+
+ // Set the antenna directivity toggle
+ switch (p_station->signal_gain[6]) {
+ case ('1'): // 45
+ XmToggleButtonGadgetSetState(doption1, TRUE, TRUE);
+ break;
+ case ('2'): // 90
+ XmToggleButtonGadgetSetState(doption2, TRUE, TRUE);
+ break;
+ case ('3'): // 135
+ XmToggleButtonGadgetSetState(doption3, TRUE, TRUE);
+ break;
+ case ('4'): // 180
+ XmToggleButtonGadgetSetState(doption4, TRUE, TRUE);
+ break;
+ case ('5'): // 225
+ XmToggleButtonGadgetSetState(doption5, TRUE, TRUE);
+ break;
+ case ('6'): // 270
+ XmToggleButtonGadgetSetState(doption6, TRUE, TRUE);
+ break;
+ case ('7'): // 315
+ XmToggleButtonGadgetSetState(doption7, TRUE, TRUE);
+ break;
+ case ('8'): // 360
+ XmToggleButtonGadgetSetState(doption8, TRUE, TRUE);
+ break;
+ case ('0'): // Omni
+ default:
+ XmToggleButtonGadgetSetState(doption0, TRUE, TRUE);
+ break;
+ }
+ }
+ else { // Must be a beam-heading object
+ //fprintf(stderr,"beam-heading\n");
+
+ XmToggleButtonSetState(beam_antenna_toggle, TRUE, TRUE);
+
+ XmTextFieldSetString(ob_bearing_data, p_station->bearing);
+
+ switch (p_station->NRQ[2]) {
+ case ('1'): // 240�
+ XmToggleButtonGadgetSetState(woption1, TRUE, TRUE);
+ break;
+ case ('2'): // 120�
+ XmToggleButtonGadgetSetState(woption2, TRUE, TRUE);
+ break;
+ case ('3'): // 64�
+ XmToggleButtonGadgetSetState(woption3, TRUE, TRUE);
+ break;
+ case ('4'): // 32�
+ XmToggleButtonGadgetSetState(woption4, TRUE, TRUE);
+ break;
+ case ('5'): // 16�
+ XmToggleButtonGadgetSetState(woption5, TRUE, TRUE);
+ break;
+ case ('6'): // 8�
+ XmToggleButtonGadgetSetState(woption6, TRUE, TRUE);
+ break;
+ case ('7'): // 4�
+ XmToggleButtonGadgetSetState(woption7, TRUE, TRUE);
+ break;
+ case ('8'): // 2�
+ XmToggleButtonGadgetSetState(woption8, TRUE, TRUE);
+ break;
+ case ('9'): // 1�
+ XmToggleButtonGadgetSetState(woption9, TRUE, TRUE);
+ break;
+ case ('0'): // Useless
+ default:
+ XmToggleButtonGadgetSetState(woption0, TRUE, TRUE);
+ break;
+ }
+ }
+ } else { // Found a normal object
+ // Nothing needed in this block currently
+ } // Done with filling in Normal objects
+
+ } // Done with filling in Signpost, DF, or Normal Objects
+
+ // Handle Generic Options (common to all)
+ // Convert altitude from meters to feet
+ if (strlen(p_station->altitude) != 0) {
+ xastir_snprintf(temp_data, sizeof(temp_data), "%d",
+ (int)((atof(p_station->altitude) / 0.3048) + 0.5) );
+
+ XmTextFieldSetString( ob_altitude_data, temp_data );
+ } else
+ XmTextFieldSetString( ob_altitude_data, "" );
+ }
+
+// Else we're creating a new object from scratch: p_station == NULL
+ else {
+ if (Area_object_enabled) {
+ XmToggleButtonGadgetSetState(coption1, TRUE, TRUE); // Black
+ XmToggleButtonGadgetSetState(bright_dim_toggle, FALSE, TRUE); // Dim
+ XmToggleButtonGadgetSetState(toption1, TRUE, TRUE); // Circle
+ }
+
+ XmTextFieldSetString(object_name_data,"");
+
+
+ // Set the symbol type based on the global variables
+ if (Area_object_enabled) {
+ temp_data[0] = '\\';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = 'l';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ XtSetSensitive(ob_frame,FALSE);
+
+
+ } else if (Signpost_object_enabled) {
+ temp_data[0] = '\\';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = 'm';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ XmTextFieldSetString( signpost_data, "" );
+
+ XtSetSensitive(ob_frame,FALSE);
+
+
+ } else if (Probability_circles_enabled) {
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = '[';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ XmTextFieldSetString( probability_data_min, "" );
+ XmTextFieldSetString( probability_data_max, "" );
+
+
+ } else if (DF_object_enabled) {
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = '\\';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ // Defaults Omni-DF
+ XmToggleButtonGadgetSetState(soption0, TRUE, TRUE); // Nothing heard
+ XmToggleButtonGadgetSetState(hoption1, TRUE, TRUE); // 20 feet HAAT
+ XmToggleButtonGadgetSetState(goption3, TRUE, TRUE); // 3dB gain antenna
+ XmToggleButtonGadgetSetState(doption0, TRUE, TRUE); // No directivity
+
+ // Defaults Beam-DF
+ XmToggleButtonGadgetSetState(woption5, TRUE, TRUE); // 16 degree beamwidth
+
+ XtSetSensitive(ob_frame,FALSE);
+
+
+ } else if (Map_View_object_enabled){
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = 'E';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+
+ XtSetSensitive(ob_frame,FALSE);
+ XtSetSensitive(ob_option_frame,FALSE);
+
+
+ } else { // Normal object/item
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_group_data,temp_data);
+
+ temp_data[0] = '/';
+ temp_data[1] = '\0';
+ XmTextFieldSetString(object_symbol_data,temp_data);
+ }
+
+ // Compute the range for the Map View object and store
+ // it in the comment field.
+ if (Map_View_object_enabled) {
+ double top_range, left_range, max_range;
+ char range[10];
+ Dimension width, height;
+
+
+ // Get the display parameters
+ XtVaGetValues(da,XmNwidth, &width,XmNheight, &height, NULL);
+
+ // Find distance from center to top of screen.
+ // top_range = distance from center_longitude,
+ // center_latitude to center_longitude,
+ // center_latitude-((height*scale_y)/2).
+ top_range = calc_distance(center_latitude,
+ center_longitude,
+ NW_corner_latitude,
+ center_longitude);
+//fprintf(stderr," top_range:%1.0f meters\n", top_range);
+ // Find distance from center to left of screen.
+ // left_range = distance from center_longitude,
+ // center_latitude to
+ // center_longitude-((width*scale_x)/2),
+ // center_latitude.
+ left_range = calc_distance(center_latitude,
+ center_longitude,
+ center_latitude,
+ NW_corner_longitude);
+//fprintf(stderr,"left_range:%1.0f meters\n", left_range);
+
+ // Compute greater of the two. This is our range in
+ // meters.
+ if (top_range > left_range)
+ max_range = top_range;
+ else
+ max_range = left_range;
+
+ // Convert from meters to miles
+ max_range = max_range / 1000.0; // kilometers
+ max_range = max_range * 0.62137; // miles
+
+ // Restrict it to four digits.
+ if (max_range > 9999.0)
+ max_range = 9999.0;
+
+//fprintf(stderr,"Range:%04d miles\n", (int)(max_range + 0.5));
+
+ xastir_snprintf(range,
+ sizeof(range),
+ "RNG%04d",
+ (int)(max_range + 0.5)); // Poor man's rounding
+
+ XmTextFieldSetString(object_comment_data, range);
+ }
+ else {
+ XmTextFieldSetString(object_comment_data,"");
+ }
+ }
+
+
+
+ if (strcmp(calldata,"2") != 0) { // Normal Modify->Object or Create->Object behavior
+ // Fill in original lat/lon values
+ convert_lat_l2s(lat, lat_str, sizeof(lat_str), CONVERT_HP_NOSP);
+ substr(temp_data,lat_str,2);
+ XmTextFieldSetString(object_lat_data_deg,temp_data);
+ substr(temp_data,lat_str+2,6);
+ XmTextFieldSetString(object_lat_data_min,temp_data);
+ substr(temp_data,lat_str+8,1);
+ XmTextFieldSetString(object_lat_data_ns,temp_data);
+
+ convert_lon_l2s(lon, lon_str, sizeof(lon_str), CONVERT_HP_NOSP);
+ substr(temp_data,lon_str,3);
+ XmTextFieldSetString(object_lon_data_deg,temp_data);
+ substr(temp_data,lon_str+3,6);
+ XmTextFieldSetString(object_lon_data_min,temp_data);
+ substr(temp_data,lon_str+9,1);
+ XmTextFieldSetString(object_lon_data_ew,temp_data);
+ }
+
+ else { // We're in the middle of moving an object, calldata was "2"
+ // Fill in new lat/long values
+ //fprintf(stderr,"Here we will fill in the new lat/long values\n");
+ x = (center_longitude - ((screen_width * scale_x)/2) + (input_x * scale_x));
+ y = (center_latitude - ((screen_height * scale_y)/2) + (input_y * scale_y));
+ if (x < 0)
+ x = 0l; // 180�W
+
+ if (x > 129600000l)
+ x = 129600000l; // 180�E
+
+ if (y < 0)
+ y = 0l; // 90�N
+
+ if (y > 64800000l)
+ y = 64800000l; // 90�S
+
+ convert_lat_l2s(y, lat_str, sizeof(lat_str), CONVERT_HP_NOSP);
+ substr(temp_data,lat_str,2);
+ XmTextFieldSetString(object_lat_data_deg,temp_data);
+ substr(temp_data,lat_str+2,6);
+ XmTextFieldSetString(object_lat_data_min,temp_data);
+ substr(temp_data,lat_str+8,1);
+ XmTextFieldSetString(object_lat_data_ns,temp_data);
+
+ convert_lon_l2s(x, lon_str, sizeof(lon_str), CONVERT_HP_NOSP);
+ substr(temp_data,lon_str,3);
+ XmTextFieldSetString(object_lon_data_deg,temp_data);
+ substr(temp_data,lon_str+3,6);
+ XmTextFieldSetString(object_lon_data_min,temp_data);
+ substr(temp_data,lon_str+9,1);
+ XmTextFieldSetString(object_lon_data_ew,temp_data);
+ }
+
+ XtAddCallback(object_group_data, XmNvalueChangedCallback, updateObjectPictureCallback, object_dialog);
+ XtAddCallback(object_symbol_data, XmNvalueChangedCallback, updateObjectPictureCallback, object_dialog);
+
+ // update symbol picture
+ (void)updateObjectPictureCallback((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
+
+ pos_dialog(object_dialog);
+
+ delw = XmInternAtom(XtDisplay(object_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(object_dialog, delw, Object_destroy_shell, (XtPointer)object_dialog);
+
+ if (Signpost_object_enabled) {
+ XtManageChild(signpost_form);
+ } else if (Probability_circles_enabled) {
+ XtManageChild(probability_form);
+ } else if (Area_object_enabled) {
+ XtManageChild(shape_box);
+ XtManageChild(color_box);
+ XtManageChild(area_form);
+ } else if (DF_object_enabled) {
+ XtManageChild(signal_box);
+ XtManageChild(height_box);
+ XtManageChild(gain_box);
+ XtManageChild(directivity_box);
+ XtManageChild(width_box);
+ XtManageChild(formomni);
+ XtManageChild(formbeam);
+ }
+
+ XtManageChild(ob_latlon_form);
+ XtManageChild(ob_option_form);
+ XtManageChild(ob_form1);
+ XtManageChild(ob_form);
+ XtManageChild(ob_pane);
+
+ XtPopup(object_dialog,XtGrabNone);
+ fix_dialog_size(object_dialog); // don't allow a resize
+
+ // Move focus to the Cancel button. This appears to highlight t
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(object_dialog);
+ XmProcessTraversal(ob_button_cancel, XmTRAVERSE_CURRENT);
+ }
+
+ // This will cause the move to happen quickly without any button presses.
+ if (calldata != NULL) { // If we're doing a "move" operation
+ if (strcmp(calldata,"2") == 0) {
+ if ((p_station->flag & ST_ITEM) != 0) { // Moving an Item
+//fprintf(stderr,"Calling Item_change_data_set()\n");
+ Item_change_data_set(w,object_dialog,object_dialog); // Move it now!
+//fprintf(stderr,"Done with call\n");
+ }
+ else { // Moving an Object
+//fprintf(stderr,"Calling Object_change_data_set()\n");
+ Object_change_data_set(w,object_dialog,object_dialog); // Move it now!
+//fprintf(stderr,"Done with call\n");
+ }
+ }
+ }
+
+} // End of Set_Del_Object
+
+
+
+
+
+/*
+ * Change data for current object
+ * If calldata = 2, we're doing a move object operation. Pass the
+ * value on through to Set_Del_Object.
+ */
+void Modify_object( Widget w, XtPointer clientData, XtPointer calldata) {
+ DataRow *p_station = clientData;
+
+ //if (calldata != NULL)
+ // fprintf(stderr,"Modify_object: calldata: %s\n", (char *)calldata);
+
+ //fprintf(stderr,"Object Name: %s\n", p_station->call_sign);
+
+ // Only move the object if it is our callsign, else force the
+ // user to adopt the object first, then move it.
+ //
+ // Not exact match (this one is useful for testing)
+//// if (!is_my_call(p_station->origin,0)) {
+// if (!is_my_object_item(p_station)) {
+ //
+ // Exact match includes SSID (this one is for production code)
+// if (!is_my_call(p_station->origin,1)) {
+ if (!is_my_object_item(p_station)) {
+
+ // It's not from my callsign
+ if (strncmp(calldata,"2",1) == 0) {
+
+ // We're doing a Move Object operation
+ //fprintf(stderr,"Modify_object: Object not owned by
+ //me!\n");
+ popup_message_always(langcode("POPEM00035"),
+ langcode("POPEM00042"));
+ return;
+ }
+ }
+
+ Set_Del_Object( w, p_station, calldata );
+}
+
+
+
+
+
+//
+// Disown function called by object/item decode routines.
+// If an object/item is received that matches something in our
+// object.log file, we immediately cease to transmit that object and
+// we mark each line containing that object in our log file with a
+// hash mark ('#'). This comments out that object so that the next
+// time we reboot, we won't start transmitting it again.
+
+// Note that the length of "line" can be up to MAX_DEVICE_BUFFER,
+// which is currently set to 4096.
+//
+void disown_object_item(char *call_sign, char *new_owner) {
+ char *ptr;
+ char file[200];
+ char file_temp[200];
+ FILE *f;
+ FILE *f_temp;
+ char line[300];
+ char name[15];
+ int ret;
+
+
+//fprintf(stderr,"disown_object_item, object: %s, new_owner: %s\n",
+// call_sign,
+// new_owner);
+
+
+ // If it's my call in the new_owner field, then I must have just
+ // deleted the object and am transmitting a killed object for
+ // it. If it's not my call, someone else has assumed control of
+ // the object.
+ //
+ // Comment out any references to the object in the log file so
+ // that we don't start retransmitting it on a restart.
+
+ if (is_my_call(new_owner,1)) { // Exact match includes SSID
+ //fprintf(stderr,"Commenting out %s in object.log\n",
+ //call_sign);
+ }
+ else {
+ fprintf(stderr,"Disowning '%s': '%s' is taking over control of it.\n",
+ call_sign, new_owner);
+ }
+
+ get_user_base_dir("config/object.log", file, sizeof(file));
+
+ get_user_base_dir("config/object-temp.log", file_temp, sizeof(file_temp));
+
+ //fprintf(stderr,"%s\t%s\n",file,file_temp);
+
+ // Our own internal function from util.c
+ ret = copy_file(file, file_temp);
+ if (ret) {
+ fprintf(stderr,"\n\nCouldn't create temp file %s!\n\n\n",
+ file_temp);
+ return;
+ }
+
+ // Open the temp file and write to the original file, with hash
+ // marks in front of the appropriate lines.
+ f_temp=fopen(file_temp,"r");
+ f=fopen(file,"w");
+
+ if (f == NULL) {
+ fprintf(stderr,"Couldn't open %s\n",file);
+ return;
+ }
+ if (f_temp == NULL) {
+ fprintf(stderr,"Couldn't open %s\n",file_temp);
+ return;
+ }
+
+ // Read lines from the temp file and write them to the standard
+ // file, modifying them as necessary.
+ while (fgets(line, 300, f_temp) != NULL) {
+
+ // Need to check that the length matches for both! Best way
+ // is to parse the object/item name out of the string and
+ // then do a normal string compare between the two.
+
+ if (line[0] == ';') { // Object
+ substr(name,&line[1],9);
+ name[9] = '\0';
+ remove_trailing_spaces(name);
+ }
+
+ else if (line[0] == ')') { // Item
+ int i;
+
+ // 3-9 char name
+ for (i = 1; i <= 9; i++) {
+ if (line[i] == '!' || line[i] == '_') {
+ name[i-1] = '\0';
+ break;
+ }
+ name[i-1] = line[i];
+ }
+ name[9] = '\0'; // In case we never saw '!' || '_'
+
+ // Don't remove trailing spaces for Items, else we won't
+ // get a match.
+ }
+
+ else if (line[1] == ';') { // Commented out Object
+ substr(name,&line[2],10);
+ name[9] = '\0';
+ remove_trailing_spaces(name);
+
+ }
+
+ else if (line[1] == ')') { // Commented out Item
+ int i;
+
+ // 3-9 char name
+ for (i = 2; i <= 10; i++) {
+ if (line[i] == '!' || line[i] == '_') {
+ name[i-1] = '\0';
+ break;
+ }
+ name[i-1] = line[i];
+ }
+ name[9] = '\0'; // In case we never saw '!' || '_'
+
+ // Don't remove trailing spaces for Items, else we won't
+ // get a match.
+ }
+
+
+ //fprintf(stderr,"'%s'\t'%s'\n", name, call_sign);
+
+ if (valid_object(name)) {
+
+ if ( strcmp(name,call_sign) == 0 ) {
+ // Match. Comment it out in the file unless it's
+ // already commented out.
+ if (line[0] != '#') {
+ fprintf(f,"#%s",line);
+ //fprintf(stderr,"#%s",line);
+ }
+ else {
+ fprintf(f,"%s",line);
+ //fprintf(stderr,"%s",line);
+ }
+ }
+ else {
+ // No match. Copy the line verbatim unless it's
+ // just a
+ // blank line.
+ if (line[0] != '\n') {
+ fprintf(f,"%s",line);
+ //fprintf(stderr,"%s",line);
+ }
+ }
+ }
+ }
+ fclose(f);
+ fclose(f_temp);
+}
+
+
+
+
+
+//
+// Logging function called by object/item create/modify routines.
+// We log each object/item as one line in a file.
+//
+// We need to check for objects of the same name in the file,
+// deleting lines that have the same name, and adding new records to
+// the end. Actually BAD IDEA! We want to keep the history of the
+// object so that we can trace its movements later.
+//
+// Note that the length of "line" can be up to MAX_DEVICE_BUFFER,
+// which is currently set to 4096.
+//
+// Change this function so that deleted objects/items get disowned
+// instead (commented out in the file so that they're not
+// transmitted again after a restart). See disown_object_item().
+//
+void log_object_item(char *line, int disable_object, char *object_name) {
+ char file[MAX_VALUE];
+ FILE *f;
+
+ get_user_base_dir("config/object.log", file, sizeof(file));
+
+ f=fopen(file,"a");
+ if (f!=NULL) {
+ fprintf(f,"%s\n",line);
+ (void)fclose(f);
+
+ if (debug_level & 1)
+ fprintf(stderr,"Saving object/item to file: %s",line);
+
+ // Comment out all instances of the object/item in the log
+ // file. This will make sure that the object is not
+ // retransmitted again when Xastir is restarted.
+ if (disable_object) {
+ disown_object_item(object_name, my_callsign);
+ }
+
+ }
+ else {
+ fprintf(stderr,"Couldn't open file for appending: %s\n", file);
+ }
+}
+
+
+
+
+
+//
+// Function to load saved objects and items back into Xastir. This
+// is called on startup. This implements persistent objects/items
+// across Xastir restarts.
+//
+// Note that the length of "line" can be up to MAX_DEVICE_BUFFER,
+// which is currently set to 4096.
+//
+// This appears to skip the loading of killed objects/items. We may
+// instead want to begin transmitting them again until they time
+// out, then mark them with a '#' in the log file at that point.
+//
+void reload_object_item(void) {
+ char file[MAX_VALUE];
+ FILE *f;
+ char line[300+1];
+ char line2[300+1];
+ int save_state;
+
+
+ get_user_base_dir("config/object.log", file, sizeof(file));
+
+ f=fopen(file,"r");
+ if (f!=NULL) {
+
+ // Turn off duplicate point checking (need this in order to
+ // work with SAR objects). Save state so that we don't mess
+ // it up.
+ save_state = skip_dupe_checking;
+ skip_dupe_checking++;
+
+ while (fgets(line, 300, f) != NULL) {
+
+ if (debug_level & 1)
+ fprintf(stderr,"Loading object/item from file: %s",line);
+
+ if (line[0] != '#') { // Skip comment lines
+ xastir_snprintf(line2,
+ sizeof(line2),
+ "%s>%s:%s",
+ my_callsign,
+ VERSIONFRM,
+ line);
+
+ // Decode this packet. This will put it into our
+ // station database and cause it to be transmitted
+ // at
+ // regular intervals. Port is set to -1 here.
+ decode_ax25_line( line2, DATA_VIA_LOCAL, -1, 1);
+
+// Right about here we could do a lookup for the object/item
+// matching the name and change the timing on it. This could serve
+// to spread the transmit timing out a bit so that all objects/items
+// are not transmitted together. Another easier option would be to
+// change the routine which chooses when to transmit, having it
+// randomize the numbers a bit each time. I chose the second
+// option.
+
+ }
+ }
+ (void)fclose(f);
+
+ // Restore the skip_dupe_checking state
+ skip_dupe_checking = save_state;
+
+ // Update the screen
+ redraw_symbols(da);
+ (void)XCopyArea(XtDisplay(da),
+ pixmap_final,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ screen_width,
+ screen_height,
+ 0,
+ 0);
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"Couldn't open file for reading: %s\n", file);
+ }
+
+ // Start transmitting these objects in about 30 seconds.
+ // Prevent transmission of objects until sometime after we're
+ // done with our initial load.
+ last_object_check = sec_now() + 30;
+}
+
+
diff --git a/src/objects.h b/src/objects.h
new file mode 100644
index 0000000..118dfe4
--- /dev/null
+++ b/src/objects.h
@@ -0,0 +1,160 @@
+/*
+ * $Id: objects.h,v 1.14 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifndef XASTIR_OBJECTS_H
+#define XASTIR_OBJECTS_H
+
+#include <X11/Intrinsic.h>
+#include <stdint.h>
+
+
+// For mutex debugging with Linux threads only
+#ifdef __linux__
+ #define MUTEX_DEBUG 1
+#endif // __linux__
+
+
+#ifdef __LCLINT__
+#define PACKAGE "xastir"
+#define VERSION "lclint"
+#define VERSIONTXT "xastir lclint debug version"
+#else // __LCLINT__
+#define VERSIONTXT PACKAGE " " VERSION
+#endif // __LCLINT__
+
+
+extern Widget object_dialog;
+extern Widget object_group_data;
+extern Widget object_symbol_data;
+extern void updateObjectPictureCallback(Widget w,XtPointer clientData,XtPointer callData);
+
+extern void Draw_All_CAD_Objects(Widget w);
+extern void Draw_CAD_Objects_erase_dialog(Widget w, XtPointer clientData, XtPointer callData);
+extern void Draw_CAD_Objects_list_dialog(Widget w, XtPointer clientData, XtPointer callData);
+extern int draw_CAD_objects_flag;
+extern int polygon_last_x;
+extern int polygon_last_y;
+extern int doing_move_operation;
+extern char last_object[9+1];
+extern char last_obj_grp;
+extern char last_obj_sym;
+extern int CAD_draw_objects;
+extern int CAD_show_label;
+extern int CAD_show_raw_probability;
+extern int CAD_show_comment;
+extern int CAD_show_area;
+
+
+/* JMT - works in FreeBSD */
+#define DISABLE_SETUID_PRIVILEGE do { \
+seteuid(getuid()); \
+setegid(getgid()); \
+if (debug_level & 4) { fprintf(stderr, "Changing euid to %d and egid to %d\n", (int)getuid(), (int)getgid()); } \
+} while(0)
+#define ENABLE_SETUID_PRIVILEGE do { \
+seteuid(euid); \
+setegid(egid); \
+if (debug_level & 4) { fprintf(stderr, "Changing euid to %d and egid to %d\n", (int)euid, (int)egid); } \
+} while(0)
+
+
+
+// --------------------------------------------------------------------
+//
+// Function protypes and globals to support predefined SAR/Public service
+// objects.
+//
+//
+// MAX_NUMBER_OF_PREDEFINED_OBJECTS is the maximum number of predefined
+// objects that can appear on the Create/Move Here popup menu.
+#define MAX_NUMBER_OF_PREDEFINED_OBJECTS 11
+//
+// PREDEFINED_OBJECT_DATA_LENGTH is the maximum length of a string
+// that can follow the symbol specifier in a predefined object (such
+// as a probability circle definition) plus one (for the terminator).
+#define PREDEFINED_OBJECT_DATA_LENGTH 44
+//
+// number_of_predefined_objects holds the actual number of predefined
+// objects available to display on the Create/Move popup menu.
+int number_of_predefined_objects;
+// File name of ~/.xastir/config file containing definitions for
+// a predefined object menu.
+extern char predefined_object_definition_filename[256];
+// Flag to indicate whether or not to load the predefined objects menu
+// from the file specified by predefined_object_definition_filename or
+// to use the hardcoded SAR object set. 0=use hardcoded SAR
+// 1=use predefined_object_definition_filename
+extern int predefined_menu_from_file;
+
+//extern void Set_Del_Object(Widget w, XtPointer clientData, XtPointer calldata);
+extern void Create_SAR_Object(Widget w, XtPointer clientData, XtPointer calldata);
+
+typedef struct {
+ char call[MAX_CALLSIGN+1]; // Callsign = object name.
+ char page[2]; // APRS symbol code page.
+ char symbol[2]; // APRS symbol specifier.
+ char data[PREDEFINED_OBJECT_DATA_LENGTH];
+ // Data following the symbol.
+ char menu_call[26]; // Name to display on menu.
+ intptr_t index; // Index of this object
+ // in the predefinedObjects array.
+ int show_on_menu; // !=1 to hide on menu.
+ int index_of_child; // > -1 to create two objects
+ // in the same place at the
+ // same time, value is the
+ // index of the second object
+ // in the predefinedObjects array.
+} predefinedObject;
+
+
+// predefinedObjects is an array of predefined object definitions,
+// once filled using Populate_predefined_objects it can be traversed
+// to build a list of predefined objects for menus, picklists, or
+// other user interface controls.
+//
+extern predefinedObject predefinedObjects[MAX_NUMBER_OF_PREDEFINED_OBJECTS];
+extern void Populate_predefined_objects(predefinedObject *predefinedObjects);
+
+// --------------------------------------------------------------------
+
+extern int valid_object(char *name);
+extern int valid_item(char *name);
+extern void Object_History_Refresh( Widget w, XtPointer clientData, XtPointer callData);
+extern void Object_History_Clear( Widget w, XtPointer clientData, XtPointer callData);
+extern void Move_Object( Widget widget, XtPointer clientData, XtPointer callData);
+extern void Draw_CAD_Objects_mode( Widget widget, XtPointer clientData, XtPointer callData);
+extern void Draw_CAD_Objects_close_polygon(Widget w, XtPointer clientData, XtPointer calldata);
+extern void Draw_CAD_Objects_erase(Widget w, XtPointer clientData, XtPointer calldata);
+extern void CAD_vertice_allocate(long latitude, long longitude);
+extern void CAD_object_allocate(long latitude, long longitude);
+extern void Modify_object( Widget w, XtPointer clientData, XtPointer calldata);
+extern void Restore_CAD_Objects_from_file(void);
+extern void disown_object_item(char *call_sign, char *new_owner);
+extern void log_object_item(char *line, int disable_object, char *object_name);
+extern void reload_object_item(void);
+extern void check_and_transmit_objects_items(time_t time);
+
+#endif /* XASTIR_OBJECTS_H */
+
+
diff --git a/src/popup.h b/src/popup.h
new file mode 100644
index 0000000..0a4c344
--- /dev/null
+++ b/src/popup.h
@@ -0,0 +1,47 @@
+/*
+ * $Id: popup.h,v 1.12 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifndef XASTIR_POPUP_H
+#define XASTIR_POPUP_H
+
+#define MAX_POPUPS 30
+#define MAX_POPUPS_TIME 600 /* Max time popups will display 600=10min*/
+
+typedef struct
+{
+ char name[10];
+ Widget popup_message_dialog;
+ Widget popup_message_data;
+ Widget pane, form, button_close;
+ time_t sec_opened;
+
+} Popup_Window;
+
+/* from popup_gui.c */
+extern void popup_gui_init(void);
+extern void clear_popup_message_windows(void);
+extern void popup_time_out_check(int curr_sec);
+
+#endif /* XASTIR_POPUP_H */
+
diff --git a/src/popup_gui.c b/src/popup_gui.c
new file mode 100644
index 0000000..9f0215a
--- /dev/null
+++ b/src/popup_gui.c
@@ -0,0 +1,382 @@
+/*
+ * $Id: popup_gui.c,v 1.35 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <Xm/XmAll.h>
+
+#include "xastir.h"
+#include "main.h"
+#include "popup.h"
+#include "main.h"
+#include "lang.h"
+#include "rotated.h"
+#include "snprintf.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+extern XmFontList fontlist1; // Menu/System fontlist
+
+static Popup_Window pw[MAX_POPUPS];
+static Popup_Window pwb;
+
+static xastir_mutex popup_message_dialog_lock;
+
+
+
+
+
+void popup_gui_init(void)
+{
+ init_critical_section( &popup_message_dialog_lock );
+}
+
+
+
+
+
+/**** Popup Message ******/
+
+void clear_popup_message_windows(void) {
+ int i;
+
+begin_critical_section(&popup_message_dialog_lock, "popup_gui.c:clear_popup_message_windows" );
+
+ for (i=0;i<MAX_POPUPS;i++) {
+ pw[i].popup_message_dialog=(Widget)NULL;
+ pw[i].popup_message_data=(Widget)NULL;
+ }
+
+end_critical_section(&popup_message_dialog_lock, "popup_gui.c:clear_popup_message_windows" );
+
+ pwb.popup_message_dialog=(Widget)NULL;
+ pwb.popup_message_data=(Widget)NULL;
+}
+
+
+
+
+
+static void popup_message_destroy_shell(/*@unused@*/ Widget w,
+ XtPointer clientData,
+ /*@unused@*/ XtPointer callData) {
+ int i;
+
+ i=atoi((char *)clientData);
+ XtPopdown(pw[i].popup_message_dialog);
+
+begin_critical_section(&popup_message_dialog_lock, "popup_gui.c:popup_message_destroy_shell" );
+
+ XtDestroyWidget(pw[i].popup_message_dialog);
+ pw[i].popup_message_dialog = (Widget)NULL;
+ pw[i].popup_message_data = (Widget)NULL;
+
+end_critical_section(&popup_message_dialog_lock, "popup_gui.c:popup_message_destroy_shell" );
+
+}
+
+
+
+
+
+time_t popup_time_out_check_last = (time_t)0l;
+
+void popup_time_out_check(int curr_sec) {
+ int i;
+
+ // Check only every two minutes or so
+ if (popup_time_out_check_last + 120 < curr_sec) {
+ popup_time_out_check_last = curr_sec;
+
+ for (i=0;i<MAX_POPUPS;i++) {
+ if (pw[i].popup_message_dialog!=NULL) {
+ if ((sec_now()-pw[i].sec_opened)>MAX_POPUPS_TIME) {
+ XtPopdown(pw[i].popup_message_dialog);
+
+begin_critical_section(&popup_message_dialog_lock, "popup_gui.c:popup_time_out_check" );
+
+ XtDestroyWidget(pw[i].popup_message_dialog);
+ pw[i].popup_message_dialog = (Widget)NULL;
+ pw[i].popup_message_data = (Widget)NULL;
+
+end_critical_section(&popup_message_dialog_lock, "popup_gui.c:popup_time_out_check" );
+
+ }
+
+ }
+ }
+ }
+}
+
+
+
+
+
+void popup_message_always(char *banner, char *message) {
+ XmString msg_str;
+ int j,i;
+ Atom delw;
+
+
+ if (disable_all_popups)
+ return;
+
+ if (banner == NULL || message == NULL)
+ return;
+
+ i=0;
+ for (j=0; j<MAX_POPUPS; j++) {
+ if (!pw[j].popup_message_dialog) {
+ i=j;
+ j=MAX_POPUPS+1;
+ }
+ }
+
+ if(!pw[i].popup_message_dialog) {
+ if (banner!=NULL && message!=NULL) {
+
+begin_critical_section(&popup_message_dialog_lock, "popup_gui.c:popup_message" );
+
+ pw[i].popup_message_dialog = XtVaCreatePopupShell(banner,
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNtitleString,banner,
+// An half-hearted attempt at fixing the problem where a popup
+// comes up extremely small. Setting a minimum size for the popup.
+XmNminWidth, 220,
+XmNminHeight, 80,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pw[i].pane = XtVaCreateWidget("popup_message pane",xmPanedWindowWidgetClass, pw[i].popup_message_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ pw[i].form = XtVaCreateWidget("popup_message form",xmFormWidgetClass, pw[i].pane,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ pw[i].popup_message_data = XtVaCreateManagedWidget("popup_message message",xmLabelWidgetClass, pw[i].form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ pw[i].button_close = XtVaCreateManagedWidget(langcode("UNIOP00003"),xmPushButtonGadgetClass, pw[i].form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, pw[i].popup_message_data,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ sprintf(pw[i].name,"%d",i);
+
+ msg_str=XmStringCreateLtoR(message,XmFONTLIST_DEFAULT_TAG);
+ XtVaSetValues(pw[i].popup_message_data,XmNlabelString,msg_str,NULL);
+ XmStringFree(msg_str);
+
+ XtAddCallback(pw[i].button_close, XmNactivateCallback, popup_message_destroy_shell,(XtPointer)pw[i].name);
+
+ delw = XmInternAtom(XtDisplay(pw[i].popup_message_dialog),"WM_DELETE_WINDOW", FALSE);
+
+ XmAddWMProtocolCallback(pw[i].popup_message_dialog, delw, popup_message_destroy_shell, (XtPointer)pw[i].name);
+
+ pos_dialog(pw[i].popup_message_dialog);
+
+ XtManageChild(pw[i].form);
+ XtManageChild(pw[i].pane);
+
+end_critical_section(&popup_message_dialog_lock, "popup_gui.c:popup_message" );
+
+ XtPopup(pw[i].popup_message_dialog,XtGrabNone);
+
+// An half-hearted attempt at fixing the problem where a popup
+// comes up extremely small. Commenting out the below so we can
+// change the size if necessary to read the message.
+// fix_dialog_size(pw[i].popup_message_dialog);
+
+ pw[i].sec_opened=sec_now();
+ }
+ }
+}
+
+
+
+
+
+#ifndef HAVE_ERROR_POPUPS
+//
+// We'll write to STDERR instead since the user doesn't want to see
+// any error popups. Add a timestamp to the front so we know when
+// the errors happened.
+//
+void popup_message(char *banner, char *message) {
+ char timestring[110];
+
+
+ if (disable_all_popups)
+ return;
+
+ if (banner == NULL || message == NULL)
+ return;
+
+ get_timestamp(timestring);
+ fprintf(stderr, "%s:\n\t%s %s\n\n", timestring, banner, message);
+}
+#else // HAVE_ERROR_POPUPS
+//
+// The user wishes to see popup error messages. Call the routine
+// above which does so.
+//
+void popup_message(char *banner, char *message) {
+ popup_message_always(banner, message);
+}
+#endif // HAVE_ERROR_POPUPS
+
+
+
+
+
+
+// Must make sure that fonts are not loaded again and again, as this
+// takes a big chunk of memory each time. Can you say "memory
+// leak"?
+//
+static XFontStruct *id_font=NULL;
+
+
+
+
+
+// Routine which pops up a large message for a few seconds in the
+// middle of the screen, then removes it.
+//
+void popup_ID_message(char *banner, char *message) {
+ float my_rotation = 0.0;
+ int x = (int)(screen_width/10);
+ int y = (int)(screen_height/2);
+
+ if (ATV_screen_ID) {
+
+ // Fill the pixmap with grey so that the black ID text will
+ // be seen.
+ (void)XSetForeground(XtDisplay(da),gc,MY_BG_COLOR); // Not a mistake!
+ (void)XSetBackground(XtDisplay(da),gc,MY_BG_COLOR);
+ (void)XFillRectangle(XtDisplay(appshell),
+ pixmap_alerts,
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height);
+
+ /* load font */
+ if(!id_font) {
+ id_font=(XFontStruct *)XLoadQueryFont (XtDisplay(da), rotated_label_fontname[FONT_ATV_ID]);
+
+ if (id_font == NULL) { // Couldn't get the font!!!
+ fprintf(stderr,"popup_ID_message: Couldn't get ATV ID font %s\n",
+ rotated_label_fontname[FONT_ATV_ID]);
+ pending_ID_message = 0;
+ return;
+ }
+ }
+
+ (void)XSetForeground (XtDisplay(da), gc, colors[0x08]);
+
+ //fprintf(stderr,"%0.1f\t%s\n",my_rotation,label_text);
+
+ if ( ( (my_rotation < -90.0) && (my_rotation > -270.0) )
+ || ( (my_rotation > 90.0) && (my_rotation < 270.0) ) ) {
+ my_rotation = my_rotation + 180.0;
+ (void)XRotDrawAlignedString(XtDisplay(da),
+ id_font,
+ my_rotation,
+ pixmap_alerts,
+ gc,
+ x,
+ y,
+ message,
+ BRIGHT);
+ }
+ else {
+ (void)XRotDrawAlignedString(XtDisplay(da),
+ id_font,
+ my_rotation,
+ pixmap_alerts,
+ gc,
+ x,
+ y,
+ message,
+ BLEFT);
+ }
+
+ // Schedule a screen update in roughly 3 seconds
+ remove_ID_message_time = sec_now() + 3;
+ pending_ID_message = 1;
+
+ // Write it to the screen. Symbols/tracks will disappear during
+ // this short interval time.
+ (void)XCopyArea(XtDisplay(da),
+ pixmap_alerts,
+ XtWindow(da),
+ gc,
+ 0,
+ 0,
+ (unsigned int)screen_width,
+ (unsigned int)screen_height,
+ 0,
+ 0);
+ }
+ else { // ATV Screen ID is not enabled
+ pending_ID_message = 0;
+ }
+}
+
+
diff --git a/src/rac_data.c b/src/rac_data.c
new file mode 100644
index 0000000..cde28ad
--- /dev/null
+++ b/src/rac_data.c
@@ -0,0 +1,386 @@
+/*
+* $Id: rac_data.c,v 1.23 2012/09/23 16:19:22 tvrusso Exp $
+*
+* XASTIR, Amateur Station Tracking and Information Reporting
+* Copyright (C) 1999,2000 Frank Giannandrea
+* Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+//====================================================================
+// Canadian Callsign Lookup
+// Richard Hagemeyer, VE3UNW
+// GNU COPYLEFT applies
+// 1999-11-08
+//
+// For use with XASTIR by Frank Giannandrea
+//********************************************************************
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+#include <Xm/XmAll.h>
+
+#include "xastir.h"
+#include "rac_data.h"
+#include "xa_config.h"
+#include "main.h"
+#include "snprintf.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+
+
+/* ==================================================================== */
+/* my version of chomp from perl, removes spaces and dashes */
+/* */
+/* ******************************************************************** */
+int chomp(char *input, unsigned int i) {
+ unsigned int x;
+
+ for (x=i; input[x] == ' ' || input[x] == '-'; x--)
+ input[x] = '\0';
+
+ return ( (int)(i-x) );
+}
+
+
+
+
+
+/* ==================================================================== */
+/* build a new (or newer if I check the file date) index file */
+/* check for current ic index file */
+/* FG: added a date check in case the RAC file has been updated. */
+/* AMACALL.LST must have a time stamp newer than the index file */
+/* time stamp. Use the touch command on the AMACALL.LST file to */
+/* make the time current if necessary. */
+/* ******************************************************************** */
+int build_rac_index(void) {
+ FILE *fdb;
+ FILE *fndx;
+ unsigned long call_offset = 0;
+ unsigned long x = 0;
+ char racdata[RAC_DATA_LEN+8];
+ char amacall_path[MAX_VALUE];
+
+ get_user_base_dir("data/AMACALL.ndx", amacall_path, sizeof(amacall_path));
+
+ /* ==================================================================== */
+ /* If the index file is there, exit */
+ /* */
+ if (filethere(amacall_path)) {
+ /* if file is there make sure the index date is newer */
+ if(file_time(amacall_path)<=file_time(amacall_path)) {
+ return(1);
+ } else {
+
+ // RAC index old, rebuilding
+ statusline(langcode("STIFCC0103"), 1);
+
+ fprintf(stderr,"RAC index is old. Rebuilding index.\n");
+// XmTextFieldSetString(text,"RAC Index old rebuilding");
+// XtManageChild(text);
+// XmUpdateDisplay(XtParent(text));
+ }
+ }
+ /* ==================================================================== */
+ /* Open the database and index file */
+ /* */
+ fdb=fopen(get_data_base_dir("fcc/AMACALL.LST"),"rb");
+ if (fdb==NULL) {
+ fprintf(stderr,"Build:Could not open RAC data base: %s\n", get_data_base_dir("fcc/AMACALL.LST") );
+ return(0);
+ }
+
+ fndx=fopen(amacall_path,"w");
+ if (fndx==NULL) {
+ fprintf(stderr,"Build:Could not open/create RAC data base index: %s\n", amacall_path );
+ (void)fclose(fdb);
+ return(0);
+ }
+ /* ==================================================================== */
+ /* Skip past the header to the first callsign (VA2AA) */
+ /* */
+ memset(racdata, 0, sizeof(racdata));
+ while (!feof(fdb) && strncmp(racdata,"VA",2)) {
+ call_offset = (unsigned long)ftell(fdb);
+ if (fgets(racdata, (int)sizeof(racdata), fdb)==NULL) {
+ fprintf(stderr,"Build:header:Unable to read data base\n");
+ (void)fclose(fdb);
+ (void)fclose(fndx);
+ fprintf(stderr,"rc=0\n");
+ return (0);
+ }
+ }
+
+ /* ==================================================================== */
+ /* write out the current callsign and RBA of the db file */
+ /* skip 100 records and do it again until no more */
+ /* */
+ while (!feof(fdb)) {
+ fprintf(fndx,"%6.6s%li\n",racdata,(long)call_offset);
+ call_offset = (unsigned long)ftell(fdb);
+ for (x=0;x<=100 && !feof(fdb);x++)
+ if (fgets(racdata, (int)sizeof(racdata), fdb)==NULL)
+ break;
+ }
+ (void)fclose(fdb);
+ (void)fclose(fndx);
+
+// XmTextFieldSetString(text,"");
+// XtManageChild(text);
+
+ return(1);
+}
+
+
+
+
+
+/* ==================================================================== */
+/* Check for ic data base file */
+/* Check/build the index */
+/* */
+/* ******************************************************************** */
+int check_rac_data(void) {
+ int rac_data_available = 0;
+ if( filethere( get_data_base_dir("fcc/AMACALL.LST") ) ) {
+ if (build_rac_index())
+ rac_data_available=1;
+ else {
+ fprintf(stderr,"Check:Could not build ic data base index\n");
+ rac_data_available=0;
+ }
+ }
+ return(rac_data_available);
+}
+
+
+
+
+
+/* ==================================================================== */
+/* The real work. Pass the callsign, get the info */
+/* */
+/* ******************************************************************** */
+int search_rac_data(char *callsign, rac_record *data) {
+ FILE *fdb;
+ FILE *fndx;
+ char *rc;
+ long call_offset = 0l;
+ char char_offset[16];
+ char index[32];
+ int found = 0;
+ rac_record racdata;
+ /*char filler[8];*/
+ char amacall_path[MAX_VALUE];
+
+ get_user_base_dir("data/AMACALL.ndx", amacall_path, sizeof(amacall_path));
+
+
+ xastir_snprintf(index, sizeof(index)," ");
+ xastir_snprintf(racdata.callsign, sizeof(racdata.callsign)," ");
+
+ /* ==================================================================== */
+ /* Search thru the index, get the RBA */
+ /* */
+
+ fndx = fopen(amacall_path, "r");
+ if(fndx != NULL) {
+ rc = fgets(index, (int)sizeof(index), fndx);
+ xastir_snprintf(char_offset, sizeof(char_offset), "%s", &index[6]);
+ while (!feof(fndx) && strncmp(callsign, index, 6) > 0) {
+ xastir_snprintf(char_offset, sizeof(char_offset), "%s", &index[6]);
+ rc = fgets(index, (int)sizeof(index), fndx);
+ }
+ } else {
+ fprintf(stderr,
+ "Search:Could not open RAC data base index: %s\n",
+ amacall_path );
+
+ return (0);
+ }
+ call_offset = atol(char_offset);
+
+ (void)fclose(fndx);
+
+ /* ==================================================================== */
+ /* Now we have our pointer into the main database (text) file. */
+ /* Start from there and linear search the data. */
+ /* This will take an avg of 1/2 of the # skipped making the index */
+ /* */
+
+ fdb = fopen(get_data_base_dir("fcc/AMACALL.LST"), "r");
+ if (fdb != NULL) {
+ (void)fseek(fdb, call_offset, SEEK_SET);
+ if (callsign[5] == '-')
+ (void)chomp(callsign,5);
+
+ while (!feof(fdb) && strncmp((char *)&racdata, callsign, 6) < 0)
+
+//WE7U
+// Problem here: We're sticking 8 bytes too many into racdata!
+ rc = fgets((char *)&racdata, sizeof(racdata), fdb);
+
+ } else
+ fprintf(stderr,"Search:Could not open RAC data base: %s\n", get_data_base_dir("fcc/AMACALL.LST") );
+
+ /* || (callsign[5] == '-' && strncmp((char *)&racdata,callsign,5) < 0)) */
+ (void)chomp(racdata.callsign, 6);
+
+ if (!strncmp((char *)racdata.callsign, callsign, 6)) {
+ found = 1;
+
+// Some of these cause problems on 64-bit processors, so commented
+// them out for now.
+// (void)chomp(racdata.first_name, 35);
+// (void)chomp(racdata.last_name, 35);
+// (void)chomp(racdata.address, 70);
+// (void)chomp(racdata.city, 35);
+// (void)chomp(racdata.province, 2);
+// (void)chomp(racdata.postal_code, 10);
+// (void)chomp(racdata.qual_a, 1);
+// (void)chomp(racdata.qual_b, 1);
+// (void)chomp(racdata.qual_c, 1);
+// (void)chomp(racdata.qual_d, 1);
+// (void)chomp(racdata.club_name, 141);
+// (void)chomp(racdata.club_address, 70);
+// (void)chomp(racdata.club_city, 35);
+// (void)chomp(racdata.club_province, 2);
+// (void)chomp(racdata.club_postal_code, 9);
+
+ xastir_snprintf(data->callsign,
+ sizeof(data->callsign),
+ "%s",
+ racdata.callsign);
+
+ xastir_snprintf(data->first_name,
+ sizeof(data->first_name),
+ "%s",
+ racdata.first_name);
+
+ xastir_snprintf(data->last_name,
+ sizeof(data->last_name),
+ "%s",
+ racdata.last_name);
+
+ xastir_snprintf(data->address,
+ sizeof(data->address),
+ "%s",
+ racdata.address);
+
+ xastir_snprintf(data->city,
+ sizeof(data->city),
+ "%s",
+ racdata.city);
+
+ xastir_snprintf(data->province,
+ sizeof(data->province),
+ "%s",
+ racdata.province);
+
+ xastir_snprintf(data->postal_code,
+ sizeof(data->postal_code),
+ "%s",
+ racdata.postal_code);
+
+ xastir_snprintf(data->qual_a,
+ sizeof(data->qual_a),
+ "%s",
+ racdata.qual_a);
+
+ xastir_snprintf(data->qual_b,
+ sizeof(data->qual_b),
+ "%s",
+ racdata.qual_b);
+
+ xastir_snprintf(data->qual_c,
+ sizeof(data->qual_c),
+ "%s",
+ racdata.qual_c);
+
+ xastir_snprintf(data->qual_d,
+ sizeof(data->qual_d),
+ "%s",
+ racdata.qual_d);
+
+ xastir_snprintf(data->club_name,
+ sizeof(data->club_name),
+ "%s",
+ racdata.club_name);
+
+ xastir_snprintf(data->club_address,
+ sizeof(data->club_address),
+ "%s",
+ racdata.club_address);
+
+ xastir_snprintf(data->club_city,
+ sizeof(data->club_city),
+ "%s",
+ racdata.club_city);
+
+ xastir_snprintf(data->club_province,
+ sizeof(data->club_province),
+ "%s",
+ racdata.club_province);
+
+ xastir_snprintf(data->club_postal_code,
+ sizeof(data->club_postal_code),
+ "%s",
+ racdata.club_postal_code);
+
+ }
+ (void)fclose(fdb);
+
+ if (!found) {
+
+ // "Callsign Search", "Callsign Not Found!"
+ popup_message_always(langcode("STIFCC0101"),
+ langcode("STIFCC0102") );
+ }
+
+ return(found);
+}
+
+
diff --git a/src/rac_data.h b/src/rac_data.h
new file mode 100644
index 0000000..1cdcbe7
--- /dev/null
+++ b/src/rac_data.h
@@ -0,0 +1,63 @@
+/*
+ * $Id: rac_data.h,v 1.11 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+/*
+ * Industry Canada/RAC Database structure
+ * 472 bytes -- filler is club info
+ * qual fields represent basic, 5wpm, 12wpm, advanced
+ */
+
+#ifndef __XASTIR_RAC_DATA_H
+#define __XASTIR_RAC_DATA_H
+
+#define RAC_DATA_LEN 472
+
+typedef struct {
+ char callsign[7];
+ char first_name[36];
+ char last_name[36];
+ char address[71];
+ char city[36];
+ char province[3];
+ char postal_code[11];
+ char qual_a[2];
+ char qual_b[2];
+ char qual_c[2];
+ char qual_d[2];
+ char club_name[142];
+ char club_address[71];
+ char club_city[36];
+ char club_province[3];
+ char club_postal_code[10];
+ char crlf[2];
+ char filler[8]; // To prevent overruns
+} rac_record;
+
+extern int search_rac_data(char *callsign, rac_record *data);
+extern int search_rac_data_appl(char *callsign, rac_record *data);
+extern int check_rac_data(void);
+
+
+#endif /* __XASTIR_RAC_DATA_H */
+
diff --git a/src/rotated.c b/src/rotated.c
new file mode 100644
index 0000000..03df773
--- /dev/null
+++ b/src/rotated.c
@@ -0,0 +1,1618 @@
+
+// $Id: rotated.c,v 1.24 2012/08/25 16:38:29 tvrusso Exp $
+//
+// Portions Copyright (C) 2000-2012 The Xastir Group
+//
+// Note that this version has been changed since xvertext 5.0 in order
+// to get rid of compiler warnings and such. The original 5.0 notice
+// is below. --we7u
+
+
+/* ********************************************************************** */
+
+/* xvertext 5.0, Copyright (c) 1993 Alan Richardson (mppa3 at uk.ac.sussex.syma)
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both the
+ * copyright notice and this permission notice appear in supporting
+ * documentation. All work developed as a consequence of the use of
+ * this program should duly acknowledge such use. No representations are
+ * made about the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/* ********************************************************************** */
+
+
+/* BETTER: xvertext now does rotation at any angle!!
+ *
+ * BEWARE: function arguments have CHANGED since version 2.0!!
+ */
+
+/* ********************************************************************** */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "rotated.h"
+#include "snprintf.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/* Make sure cache size is set */
+
+#ifndef CACHE_SIZE_LIMIT
+#define CACHE_SIZE_LIMIT 0
+#endif /*CACHE_SIZE_LIMIT */
+
+/* Make sure a cache method is specified */
+
+#ifndef CACHE_XIMAGES
+#ifndef CACHE_BITMAPS
+#define CACHE_BITMAPS
+#endif /*CACHE_BITMAPS*/
+#endif /*CACHE_XIMAGES*/
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/* Debugging macros */
+
+#ifdef DEBUG
+static int debug=1;
+#else // DEBUG
+static int debug=0;
+#endif /*DEBUG*/
+
+#define DEBUG_PRINT1(a) if (debug) fprintf(stderr, a)
+#define DEBUG_PRINT2(a, b) if (debug) fprintf(stderr, a, b)
+#define DEBUG_PRINT3(a, b, c) if (debug) fprintf(stderr, a, b, c)
+#define DEBUG_PRINT4(a, b, c, d) if (debug) fprintf(stderr, a, b, c, d)
+#define DEBUG_PRINT5(a, b, c, d, e) if (debug) fprintf(stderr, a, b, c, d, e)
+
+
+/* ---------------------------------------------------------------------- */
+
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif // M_PI
+
+// constants used to check for approximate equality with 90, 180, and 270 degrees
+// (int)((M_PI/2)*1000)
+#define INT_M_PI_2_1000 1570
+// (int)(M_PI*1000)
+#define INT_M_PI_1000 3141
+// (int)((3*M_PI/2)*1000)
+#define INT_3_M_PI_2_1000 4712
+
+/* ---------------------------------------------------------------------- */
+
+
+/* A structure holding everything needed for a rotated string */
+
+typedef struct rotated_text_item_template {
+ Pixmap bitmap;
+ XImage *ximage;
+
+ char *text;
+ char *font_name;
+ Font fid;
+ float angle;
+ int align;
+ float magnify;
+
+ int cols_in;
+ int rows_in;
+ int cols_out;
+ int rows_out;
+
+ int nl;
+ int max_width;
+ float *corners_x;
+ float *corners_y;
+
+ long int size;
+ int cached;
+
+ struct rotated_text_item_template *next;
+} RotatedTextItem;
+
+RotatedTextItem *first_text_item=NULL;
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/* A structure holding current magnification and bounding box padding */
+
+static struct style_template {
+ float magnify;
+ int bbx_pad;
+} style={
+ 1.,
+ 0
+ };
+
+
+/* ---------------------------------------------------------------------- */
+
+
+static char *my_strdup(char *);
+
+static char *my_strtok(char *, char *);
+
+static XImage *MakeXImage(Display *, int, int);
+
+static int XRotPaintAlignedString(Display *,XFontStruct *,float, Drawable, GC, int, int, char*, int, int);
+
+static int XRotDrawHorizontalString(Display *, XFontStruct *, Drawable, GC, int, int, char*, int, int);
+
+static RotatedTextItem *XRotRetrieveFromCache(Display *, XFontStruct *, float, char *, int);
+
+static RotatedTextItem *XRotCreateTextItem(Display *, XFontStruct *, float, char *, int);
+
+static void XRotAddToLinkedList(Display *, RotatedTextItem *);
+
+static void XRotFreeTextItem(Display *, RotatedTextItem *);
+
+static XImage *XRotMagnifyImage(Display *, XImage *);
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Routine to mimic `strdup()' (some machines don't have it) */
+/**************************************************************************/
+//
+// This function allocates some memory without freeing it.
+//
+static char *my_strdup(char *str) {
+ char *s;
+
+ if(str==NULL)
+ return NULL;
+
+ s=(char *)malloc((unsigned)(strlen(str)+1));
+
+ if(s!=NULL) {
+ xastir_snprintf(s,
+ strlen(str)+1,
+ "%s",
+ str);
+ }
+ else {
+ fprintf(stderr,"Couldn't allocate memory in my_strdup()\n");
+ }
+
+ return s;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Routine to replace `strtok' : this one returns a zero length string if */
+/* it encounters two consecutive delimiters */
+/**************************************************************************/
+
+static char *my_strtok(char *str1, char *str2) {
+ char *ret;
+ int i, j, stop;
+ static int start, len;
+ static char *stext;
+
+ if(str2==NULL)
+ return NULL;
+
+ /* initialise if str1 not NULL */
+ if(str1!=NULL) {
+ start=0;
+ stext=str1;
+ len=strlen(str1);
+ }
+
+ /* run out of tokens ? */
+ if(start>=len)
+ return NULL;
+
+ /* loop through characters */
+ for(i=start; i<len; i++) {
+ /* loop through delimiters */
+ stop=0;
+ for(j=0; j < (int)strlen(str2); j++)
+ if(stext[i]==str2[j])
+ stop=1;
+
+ if(stop)
+ break;
+ }
+
+ stext[i]='\0';
+
+ ret=stext+start;
+
+ start=i+1;
+
+ return ret;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Return version/copyright information */
+/**************************************************************************/
+
+float XRotVersion(char *str, int n) {
+ if(str!=NULL)
+ xastir_snprintf(str, n, "%s", XV_COPYRIGHT);
+ return XV_VERSION;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Set the font magnification factor for all subsequent operations */
+/**************************************************************************/
+
+void XRotSetMagnification(float m) {
+ if(m>0.)
+ style.magnify=m;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Set the padding used when calculating bounding boxes */
+/**************************************************************************/
+
+void XRotSetBoundingBoxPad(int p) {
+ if(p>=0)
+ style.bbx_pad=p;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Create an XImage structure and allocate memory for it */
+/**************************************************************************/
+//
+// Function does not free the memory.
+//
+static XImage *MakeXImage(Display *dpy, int w, int h) {
+ XImage *I;
+ char *data;
+
+ /* reserve memory for image */
+ data=(char *)calloc((unsigned)(((w-1)/8+1)*h), 1);
+ if(data==NULL) {
+ fprintf(stderr,"Couldn't allocate memory in MakeXImage()\n");
+ return NULL;
+ }
+
+ /* create the XImage */
+ I=XCreateImage(dpy, DefaultVisual(dpy, DefaultScreen(dpy)), 1, XYBitmap,
+ 0, data, w, h, 8, 0);
+ if(I==NULL)
+ return NULL;
+
+ I->byte_order=I->bitmap_bit_order=MSBFirst;
+ return I;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* A front end to XRotPaintAlignedString: */
+/* -no alignment, no background */
+/**************************************************************************/
+
+int XRotDrawString( Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *str) {
+ return (XRotPaintAlignedString(dpy, font, angle, drawable, gc,
+ x, y, str, NONE, 0));
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* A front end to XRotPaintAlignedString: */
+/* -no alignment, paints background */
+/**************************************************************************/
+
+int XRotDrawImageString( Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *str) {
+ return(XRotPaintAlignedString(dpy, font, angle, drawable, gc,
+ x, y, str, NONE, 1));
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* A front end to XRotPaintAlignedString: */
+/* -does alignment, no background */
+/**************************************************************************/
+
+int XRotDrawAlignedString( Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *text, int align) {
+ return(XRotPaintAlignedString(dpy, font, angle, drawable, gc,
+ x, y, text, align, 0));
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* A front end to XRotPaintAlignedString: */
+/* -does alignment, paints background */
+/**************************************************************************/
+
+int XRotDrawAlignedImageString( Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *text, int align) {
+ return(XRotPaintAlignedString(dpy, font, angle, drawable, gc,
+ x, y, text, align, 1));
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Aligns and paints a rotated string */
+/**************************************************************************/
+//
+// This function allocates some memory but appears to free it
+// properly.
+//
+static int XRotPaintAlignedString( Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *text, int align, int bg) {
+ int i;
+ GC my_gc;
+ int xp, yp;
+ float hot_x, hot_y;
+ float hot_xp, hot_yp;
+ float sin_angle, cos_angle;
+ RotatedTextItem *item;
+ Pixmap bitmap_to_paint;
+
+ /* return early for NULL/empty strings */
+ if(text==NULL)
+ return 0;
+
+ if(strlen(text)==0)
+ return 0;
+
+ /* manipulate angle to 0<=angle<360 degrees */
+ while(angle<0)
+ angle+=360;
+
+ while(angle>=360)
+ angle-=360;
+
+ angle*=M_PI/180;
+
+ /* horizontal text made easy */
+ if(angle==0. && style.magnify==1.)
+ return(XRotDrawHorizontalString(dpy, font, drawable, gc, x, y,
+ text, align, bg));
+
+ /* get a rotated bitmap */
+ item=XRotRetrieveFromCache(dpy, font, angle, text, align);
+ if(item==NULL)
+ return(0);
+
+ /* this gc has similar properties to the user's gc */
+ my_gc=XCreateGC(dpy, drawable, 0, 0);
+ XCopyGC(dpy, gc, GCForeground|GCBackground|GCFunction|GCPlaneMask,
+ my_gc);
+
+ /* alignment : which point (hot_x, hot_y) relative to bitmap centre
+ coincides with user's specified point? */
+
+ /* y position */
+ if(align==TLEFT || align==TCENTRE || align==TRIGHT)
+ hot_y=(float)item->rows_in/2*style.magnify;
+ else if(align==MLEFT || align==MCENTRE || align==MRIGHT)
+ hot_y=0;
+ else if(align==BLEFT || align==BCENTRE || align==BRIGHT)
+ hot_y=-(float)item->rows_in/2*style.magnify;
+ else
+ hot_y=-((float)item->rows_in/2-(float)font->descent)*style.magnify;
+
+ /* x position */
+ if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
+ hot_x=-(float)item->max_width/2*style.magnify;
+ else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
+ hot_x=0;
+ else
+ hot_x=(float)item->max_width/2*style.magnify;
+
+ /* pre-calculate sin and cos */
+ sin_angle=sin(angle);
+ cos_angle=cos(angle);
+
+ /* rotate hot_x and hot_y around bitmap centre */
+ hot_xp= hot_x*cos_angle - hot_y*sin_angle;
+ hot_yp= hot_x*sin_angle + hot_y*cos_angle;
+
+ /* text background will be drawn using XFillPolygon */
+ if(bg) {
+ GC depth_one_gc;
+ XPoint *xpoints;
+ Pixmap empty_stipple;
+
+ /* reserve space for XPoints, free'd later */
+ xpoints=(XPoint *)malloc((unsigned)(4*item->nl*sizeof(XPoint)));
+ if(!xpoints) {
+ fprintf(stderr,"Couldn't allocate memory in XRotPaintAlignedString()\n");
+ return 1;
+ }
+
+ /* rotate corner positions */
+ for(i=0; i<4*item->nl; i++) {
+ xpoints[i].x=(float)x + ( (item->corners_x[i]-hot_x)*cos_angle +
+ (item->corners_y[i]+hot_y)*sin_angle);
+ xpoints[i].y=(float)y + (-(item->corners_x[i]-hot_x)*sin_angle +
+ (item->corners_y[i]+hot_y)*cos_angle);
+ }
+
+ /* we want to swap foreground and background colors here;
+ XGetGCValues() is only available in R4+ */
+
+ empty_stipple=XCreatePixmap(dpy, drawable, 1, 1, 1);
+
+ depth_one_gc=XCreateGC(dpy, empty_stipple, 0, 0);
+ XSetForeground(dpy, depth_one_gc, 0);
+ XFillRectangle(dpy, empty_stipple, depth_one_gc, 0, 0, 2, 2);
+
+ XSetStipple(dpy, my_gc, empty_stipple);
+ XSetFillStyle(dpy, my_gc, FillOpaqueStippled);
+
+ if (item->nl >= 1) {
+ XFillPolygon(dpy, drawable, my_gc, xpoints, 4*item->nl, Nonconvex,
+ CoordModeOrigin);
+ }
+ else {
+ fprintf(stderr,
+ "XRotPaintAlignedString: Points too few:%d, skipping XFillPolygon",
+ item->nl);
+ }
+
+ /* free our resources */
+ free((char *)xpoints);
+ XFreeGC(dpy, depth_one_gc);
+ XFreePixmap(dpy, empty_stipple);
+ }
+
+ /* where should top left corner of bitmap go ? */
+ xp=(float)x-((float)item->cols_out/2 +hot_xp);
+ yp=(float)y-((float)item->rows_out/2 -hot_yp);
+
+ /* by default we draw the rotated bitmap, solid */
+ bitmap_to_paint=item->bitmap;
+
+ /* handle user stippling */
+#ifndef X11R3
+ {
+ GC depth_one_gc;
+ XGCValues values;
+ Pixmap new_bitmap, inverse;
+
+ /* try and get some GC properties */
+ if(XGetGCValues(dpy, gc,
+ GCStipple|GCFillStyle|GCForeground|GCBackground|
+ GCTileStipXOrigin|GCTileStipYOrigin,
+ &values)) {
+
+ /* only do this if stippling requested */
+ if((values.fill_style==FillStippled ||
+ values.fill_style==FillOpaqueStippled) && !bg) {
+
+ /* opaque stipple: draw rotated text in background colour */
+ if(values.fill_style==FillOpaqueStippled) {
+ XSetForeground(dpy, my_gc, values.background);
+ XSetFillStyle(dpy, my_gc, FillStippled);
+ XSetStipple(dpy, my_gc, item->bitmap);
+ XSetTSOrigin(dpy, my_gc, xp, yp);
+ XFillRectangle(dpy, drawable, my_gc, xp, yp,
+ item->cols_out, item->rows_out);
+ XSetForeground(dpy, my_gc, values.foreground);
+ }
+
+ /* this will merge the rotated text and the user's stipple */
+ new_bitmap=XCreatePixmap(dpy, drawable,
+ item->cols_out, item->rows_out, 1);
+
+ /* create a GC */
+ depth_one_gc=XCreateGC(dpy, new_bitmap, 0, 0);
+ XSetForeground(dpy, depth_one_gc, 1);
+ XSetBackground(dpy, depth_one_gc, 0);
+
+ /* set the relative stipple origin */
+ XSetTSOrigin(dpy, depth_one_gc,
+ values.ts_x_origin-xp, values.ts_y_origin-yp);
+
+ /* fill the whole bitmap with the user's stipple */
+ XSetStipple(dpy, depth_one_gc, values.stipple);
+ XSetFillStyle(dpy, depth_one_gc, FillOpaqueStippled);
+ XFillRectangle(dpy, new_bitmap, depth_one_gc,
+ 0, 0, item->cols_out, item->rows_out);
+
+ /* set stipple origin back to normal */
+ XSetTSOrigin(dpy, depth_one_gc, 0, 0);
+
+ /* this will contain an inverse copy of the rotated text */
+ inverse=XCreatePixmap(dpy, drawable,
+ item->cols_out, item->rows_out, 1);
+
+ /* invert text */
+ XSetFillStyle(dpy, depth_one_gc, FillSolid);
+ XSetFunction(dpy, depth_one_gc, GXcopyInverted);
+ XCopyArea(dpy, item->bitmap, inverse, depth_one_gc,
+ 0, 0, item->cols_out, item->rows_out, 0, 0);
+
+ /* now delete user's stipple everywhere EXCEPT on text */
+ XSetForeground(dpy, depth_one_gc, 0);
+ XSetBackground(dpy, depth_one_gc, 1);
+ XSetStipple(dpy, depth_one_gc, inverse);
+ XSetFillStyle(dpy, depth_one_gc, FillStippled);
+ XSetFunction(dpy, depth_one_gc, GXcopy);
+ XFillRectangle(dpy, new_bitmap, depth_one_gc,
+ 0, 0, item->cols_out, item->rows_out);
+
+ /* free resources */
+ XFreePixmap(dpy, inverse);
+ XFreeGC(dpy, depth_one_gc);
+
+ /* this is the new bitmap */
+ bitmap_to_paint=new_bitmap;
+ }
+ }
+ }
+#endif /*X11R3*/
+
+ /* paint text using stipple technique */
+ XSetFillStyle(dpy, my_gc, FillStippled);
+ XSetStipple(dpy, my_gc, bitmap_to_paint);
+ XSetTSOrigin(dpy, my_gc, xp, yp);
+ XFillRectangle(dpy, drawable, my_gc, xp, yp,
+ item->cols_out, item->rows_out);
+
+ /* free our resources */
+ XFreeGC(dpy, my_gc);
+
+ /* stippled bitmap no longer needed */
+ if(bitmap_to_paint!=item->bitmap)
+ XFreePixmap(dpy, bitmap_to_paint);
+
+#ifdef CACHE_XIMAGES
+ XFreePixmap(dpy, item->bitmap);
+#endif /*CACHE_XIMAGES*/
+
+ /* if item isn't cached, destroy it completely */
+ if(!item->cached)
+ XRotFreeTextItem(dpy,item);
+
+ /* we got to the end OK! */
+ return 0;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Draw a horizontal string in a quick fashion */
+/**************************************************************************/
+//
+// This function allocates some memory but appears to free it
+// properly.
+//
+static int XRotDrawHorizontalString( Display *dpy, XFontStruct *font, Drawable drawable, GC gc, int x, int y, char *text, int align, int bg) {
+ GC my_gc;
+ int nl=1, i;
+ int height;
+ int xp, yp;
+ char *str1, *str2, *str3;
+ char *str2_a="\0", *str2_b="\n\0";
+ int dir, asc, desc;
+ XCharStruct overall;
+
+ DEBUG_PRINT1("**\nHorizontal text.\n");
+
+ /* this gc has similar properties to the user's gc (including stipple) */
+ my_gc=XCreateGC(dpy, drawable, 0, 0);
+ XCopyGC(dpy, gc,
+ GCForeground|GCBackground|GCFunction|GCStipple|GCFillStyle|
+ GCTileStipXOrigin|GCTileStipYOrigin|GCPlaneMask, my_gc);
+ XSetFont(dpy, my_gc, font->fid);
+
+ /* count number of sections in string */
+ if(align!=NONE)
+ for(i=0; i < (int)(strlen(text)-1); i++)
+ if(text[i]=='\n')
+ nl++;
+
+ /* ignore newline characters if not doing alignment */
+ if(align==NONE)
+ str2=str2_a;
+ else
+ str2=str2_b;
+
+ /* overall font height */
+ height=font->ascent+font->descent;
+
+ /* y position */
+ if(align==TLEFT || align==TCENTRE || align==TRIGHT)
+ yp=y+font->ascent;
+ else if(align==MLEFT || align==MCENTRE || align==MRIGHT)
+ yp=y-nl*height/2+font->ascent;
+ else if(align==BLEFT || align==BCENTRE || align==BRIGHT)
+ yp=y-nl*height+font->ascent;
+ else
+ yp=y;
+
+// Allocates some memory
+ str1=my_strdup(text);
+ if(str1==NULL)
+ return 1;
+
+ str3=my_strtok(str1, str2);
+
+ /* loop through each section in the string */
+ do {
+ XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+ &overall);
+
+ /* where to draw section in x ? */
+ if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
+ xp=x;
+ else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
+ xp=x-overall.rbearing/2;
+ else
+ xp=x-overall.rbearing;
+
+ /* draw string onto bitmap */
+ if(!bg)
+ XDrawString(dpy, drawable, my_gc, xp, yp, str3, strlen(str3));
+ else
+ XDrawImageString(dpy, drawable, my_gc, xp, yp, str3, strlen(str3));
+
+ /* move to next line */
+ yp+=height;
+
+ str3=my_strtok((char *)NULL, str2);
+ }
+ while(str3!=NULL);
+
+ free(str1);
+ XFreeGC(dpy, my_gc);
+
+ return 0;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Query cache for a match with this font/text/angle/alignment */
+/* request, otherwise arrange for its creation */
+/**************************************************************************/
+
+static RotatedTextItem *XRotRetrieveFromCache( Display *dpy, XFontStruct *font, float angle, char *text, int align) {
+ Font fid;
+ char *font_name=NULL;
+ unsigned long name_value;
+ RotatedTextItem *item=NULL;
+ RotatedTextItem *i1=first_text_item;
+
+ /* get font name, if it exists */
+ if(XGetFontProperty(font, XA_FONT, &name_value)) {
+ DEBUG_PRINT1("got font name OK\n");
+ font_name=XGetAtomName(dpy, name_value);
+ fid=0;
+ }
+#ifdef CACHE_FID
+ /* otherwise rely (unreliably?) on font ID */
+ else {
+ DEBUG_PRINT1("can't get fontname, caching FID\n");
+ font_name=NULL;
+ fid=font->fid;
+ }
+#else // CACHE_FID
+ /* not allowed to cache font ID's */
+ else {
+ DEBUG_PRINT1("can't get fontname, can't cache\n");
+ font_name=NULL;
+ fid=0;
+ }
+#endif /*CACHE_FID*/
+
+ /* look for a match in cache */
+
+ /* matching formula:
+ identical text;
+ identical fontname (if defined, font ID's if not);
+ angles close enough (<0.00001 here, could be smaller);
+ HORIZONTAL alignment matches, OR it's a one line string;
+ magnifications the same */
+
+ while(i1 && !item) {
+ /* match everything EXCEPT fontname/ID */
+ if(strcmp(text, i1->text)==0 &&
+ fabs(angle-i1->angle)<0.00001 &&
+ style.magnify==i1->magnify &&
+ (i1->nl==1 ||
+ ((align==0)?9:(align-1))%3==
+ ((i1->align==0)?9:(i1->align-1))%3)) {
+
+ /* now match fontname/ID */
+ if(font_name!=NULL && i1->font_name!=NULL) {
+ if(strcmp(font_name, i1->font_name)==0) {
+ item=i1;
+ DEBUG_PRINT1("Matched against font names\n");
+ }
+ else
+ i1=i1->next;
+ }
+#ifdef CACHE_FID
+ else if(font_name==NULL && i1->font_name==NULL) {
+ if(fid==i1->fid) {
+ item=i1;
+ DEBUG_PRINT1("Matched against FID's\n");
+ }
+ else
+ i1=i1->next;
+ }
+#endif /*CACHE_FID*/
+ else
+ i1=i1->next;
+ }
+ else
+ i1=i1->next;
+ }
+
+ if(item)
+ DEBUG_PRINT1("**\nFound target in cache.\n");
+ if(!item)
+ DEBUG_PRINT1("**\nNo match in cache.\n");
+
+ /* no match */
+ if(!item) {
+ /* create new item */
+ item=XRotCreateTextItem(dpy, font, angle, text, align);
+ if(!item)
+ return NULL;
+
+ /* record what it shows */
+// Allocates some memory
+ item->text=my_strdup(text);
+
+ /* fontname or ID */
+ if(font_name!=NULL) {
+// Allocates some memory
+ item->font_name=my_strdup(font_name);
+ item->fid=0;
+ }
+ else {
+ item->font_name=NULL;
+ item->fid=fid;
+ }
+
+ item->angle=angle;
+ item->align=align;
+ item->magnify=style.magnify;
+
+ /* cache it */
+ XRotAddToLinkedList(dpy, item);
+ }
+
+ if(font_name)
+ XFree(font_name);
+
+ /* if XImage is cached, need to recreate the bitmap */
+
+#ifdef CACHE_XIMAGES
+ {
+ GC depth_one_gc;
+
+ /* create bitmap to hold rotated text */
+ item->bitmap=XCreatePixmap(dpy, DefaultRootWindow(dpy),
+ item->cols_out, item->rows_out, 1);
+
+ /* depth one gc */
+ depth_one_gc=XCreateGC(dpy, item->bitmap, NULL, 0);
+ XSetBackground(dpy, depth_one_gc, 0);
+ XSetForeground(dpy, depth_one_gc, 1);
+
+ /* make the text bitmap from XImage */
+ XPutImage(dpy, item->bitmap, depth_one_gc, item->ximage, 0, 0, 0, 0,
+ item->cols_out, item->rows_out);
+
+ XFreeGC(dpy, depth_one_gc);
+ }
+#endif /*CACHE_XIMAGES*/
+
+ return item;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Create a rotated text item */
+/**************************************************************************/
+//
+// This function allocates some memory but appears to free it
+// properly.
+//
+static RotatedTextItem *XRotCreateTextItem( Display *dpy, XFontStruct *font, float angle, char *text, int align) {
+ RotatedTextItem *item=NULL;
+ Pixmap canvas;
+ GC font_gc;
+ XImage *I_in;
+ register int i, j;
+ char *str1, *str2, *str3;
+ char *str2_a="\0", *str2_b="\n\0";
+ int height;
+ int byte_w_in, byte_w_out;
+ int xp, yp;
+ float sin_angle, cos_angle;
+ int it, jt;
+ float di, dj;
+ int ic=0;
+ float xl, xr, xinc;
+ int byte_out;
+ int dir, asc, desc;
+ XCharStruct overall;
+ int old_cols_in=0, old_rows_in=0;
+ int cols_in2, rows_in2;
+ int intAngle1000; // stores first few digits of angle,
+ // used to avoid problems with rounding error in
+ // recognition of 90 degree angles
+
+ /* allocate memory */
+ item=(RotatedTextItem *)malloc((unsigned)sizeof(RotatedTextItem));
+ if(!item) {
+ fprintf(stderr,"Couldn't allocate memory in RotatedTextItem()\n");
+ return NULL;
+ }
+
+ /* count number of sections in string */
+ item->nl=1;
+ if(align!=NONE)
+ for(i=0; i < (int)(strlen(text)-1); i++)
+ if(text[i]=='\n')
+ item->nl++;
+
+ /* ignore newline characters if not doing alignment */
+ if(align==NONE)
+ str2=str2_a;
+ else
+ str2=str2_b;
+
+ /* find width of longest section */
+// Allocates some memory
+ str1=my_strdup(text);
+ if(str1==NULL)
+ return NULL;
+
+ str3=my_strtok(str1, str2);
+
+ XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+ &overall);
+
+ item->max_width=overall.rbearing;
+
+ /* loop through each section */
+ do {
+ str3=my_strtok((char *)NULL, str2);
+
+ if(str3!=NULL) {
+ XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+ &overall);
+
+ if(overall.rbearing>item->max_width)
+ item->max_width=overall.rbearing;
+ }
+ }
+ while(str3!=NULL);
+
+ free(str1);
+
+ /* overall font height */
+ height=font->ascent+font->descent;
+
+ /* dimensions horizontal text will have */
+ item->cols_in=item->max_width;
+ item->rows_in=item->nl*height;
+
+ /* bitmap for drawing on */
+ canvas=XCreatePixmap(dpy, DefaultRootWindow(dpy),
+ item->cols_in, item->rows_in, 1);
+
+ /* create a GC for the bitmap */
+ font_gc=XCreateGC(dpy, canvas, 0, 0);
+ XSetBackground(dpy, font_gc, 0);
+ XSetFont(dpy, font_gc, font->fid);
+
+ /* make sure the bitmap is blank */
+ XSetForeground(dpy, font_gc, 0);
+ XFillRectangle(dpy, canvas, font_gc, 0, 0,
+ item->cols_in+1, item->rows_in+1);
+ XSetForeground(dpy, font_gc, 1);
+
+ /* pre-calculate sin and cos */
+ sin_angle=sin(angle);
+ cos_angle=cos(angle);
+
+ /* text background will be drawn using XFillPolygon */
+ item->corners_x=
+ (float *)malloc((unsigned)(4*item->nl*sizeof(float)));
+ if(!item->corners_x) {
+ fprintf(stderr,"Couldn't allocate memory in RotatedTextItem()\n");
+ return NULL;
+ }
+
+ item->corners_y=
+ (float *)malloc((unsigned)(4*item->nl*sizeof(float)));
+ if(!item->corners_y) {
+ fprintf(stderr,"Couldn't allocate memory in RotatedTextItem()\n");
+ return NULL;
+ }
+
+ /* draw text horizontally */
+
+ /* start at top of bitmap */
+ yp=font->ascent;
+
+// Allocates some memory
+ str1=my_strdup(text);
+ if(str1==NULL)
+ return NULL;
+
+ str3=my_strtok(str1, str2);
+
+ /* loop through each section in the string */
+ do {
+ XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+ &overall);
+
+ /* where to draw section in x ? */
+ if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
+ xp=0;
+ else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
+ xp=(item->max_width-overall.rbearing)/2;
+ else
+ xp=item->max_width-overall.rbearing;
+
+ /* draw string onto bitmap */
+ XDrawString(dpy, canvas, font_gc, xp, yp, str3, strlen(str3));
+
+ /* keep a note of corner positions of this string */
+ item->corners_x[ic]=((float)xp-(float)item->cols_in/2)*style.magnify;
+ item->corners_y[ic]=((float)(yp-font->ascent)-(float)item->rows_in/2)
+ *style.magnify;
+ item->corners_x[ic+1]=item->corners_x[ic];
+ item->corners_y[ic+1]=item->corners_y[ic]+(float)height*style.magnify;
+ item->corners_x[item->nl*4-1-ic]=item->corners_x[ic]+
+ (float)overall.rbearing*style.magnify;
+ item->corners_y[item->nl*4-1-ic]=item->corners_y[ic];
+ item->corners_x[item->nl*4-2-ic]=
+ item->corners_x[item->nl*4-1-ic];
+ item->corners_y[item->nl*4-2-ic]=item->corners_y[ic+1];
+
+ ic+=2;
+
+ /* move to next line */
+ yp+=height;
+
+ str3=my_strtok((char *)NULL, str2);
+ }
+ while(str3!=NULL);
+
+ free(str1);
+
+ /* create image to hold horizontal text */
+ I_in=MakeXImage(dpy, item->cols_in, item->rows_in);
+ if(I_in==NULL)
+ return NULL;
+
+ /* extract horizontal text */
+ XGetSubImage(dpy, canvas, 0, 0, item->cols_in, item->rows_in,
+ 1, XYPixmap, I_in, 0, 0);
+ I_in->format=XYBitmap;
+
+ /* magnify horizontal text */
+ if(style.magnify!=1.) {
+ I_in=XRotMagnifyImage(dpy, I_in);
+
+ old_cols_in=item->cols_in;
+ old_rows_in=item->rows_in;
+ item->cols_in=(float)item->cols_in*style.magnify;
+ item->rows_in=(float)item->rows_in*style.magnify;
+ }
+
+ /* how big will rotated text be ? */
+ item->cols_out=fabs((float)item->rows_in*sin_angle) +
+ fabs((float)item->cols_in*cos_angle) +0.99999 +2;
+
+ item->rows_out=fabs((float)item->rows_in*cos_angle) +
+ fabs((float)item->cols_in*sin_angle) +0.99999 +2;
+
+ if(item->cols_out%2==0)
+ item->cols_out++;
+
+ if(item->rows_out%2==0)
+ item->rows_out++;
+
+ /* create image to hold rotated text */
+ item->ximage=MakeXImage(dpy, item->cols_out, item->rows_out);
+ if(item->ximage==NULL)
+ return NULL;
+
+ byte_w_in=(item->cols_in-1)/8+1;
+ byte_w_out=(item->cols_out-1)/8+1;
+
+ /* we try to make this bit as fast as possible - which is why it looks
+ a bit over-the-top */
+
+ /* vertical distance from centre */
+ dj=0.5-(float)item->rows_out/2;
+
+ /* where abouts does text actually lie in rotated image? */
+ intAngle1000 = (int)(angle*1000);
+ if ( intAngle1000==0
+ || intAngle1000==INT_M_PI_2_1000
+ || intAngle1000==INT_M_PI_1000
+ || intAngle1000==INT_3_M_PI_2_1000 ) {
+ // 0, 90, 180, 270 degrees are special cases
+ // floating point errors may prevent recognition of them unless
+ // we round off, that is a value that started as 180 may not be
+ // recognized as == M_PI/2. Rounding to .001 radian seems a
+ // reasonable choice for the purpose of orienting text strings.
+ xl=0;
+ xr=(float)item->cols_out;
+ xinc=0;
+ }
+ else if(angle<M_PI) {
+ xl=(float)item->cols_out/2+
+ (dj-(float)item->rows_in/(2*cos_angle))/
+ tan(angle)-2;
+ xr=(float)item->cols_out/2+
+ (dj+(float)item->rows_in/(2*cos_angle))/
+ tan(angle)+2;
+ xinc=1./tan(angle);
+ }
+ else {
+ xl=(float)item->cols_out/2+
+ (dj+(float)item->rows_in/(2*cos_angle))/
+ tan(angle)-2;
+ xr=(float)item->cols_out/2+
+ (dj-(float)item->rows_in/(2*cos_angle))/
+ tan(angle)+2;
+
+ xinc=1./tan(angle);
+ }
+
+
+ // Set up some constants for loops below
+ cols_in2 = item->cols_in / 2;
+ rows_in2 = item->rows_in / 2;
+
+ // Handle special cases of 90 degree rotation
+ if ( intAngle1000 == INT_M_PI_2_1000 ) {
+ // angle is 180 degrees, text is rotated 90 degrees from horizontal and runs up x axis
+ for(j=0; j<item->rows_out; j++) {
+ di=(float)((xl<0)?0:(int)xl)+0.5-(float)item->cols_out/2;
+ byte_out=(item->rows_out-j-1)*byte_w_out;
+ for(i=((xl<0)?0:(int)xl);
+ i<((xr>=item->cols_out)?item->cols_out:(int)xr); i++) {
+ jt=(float)rows_in2 + di;
+ it=(float)cols_in2 + dj;
+ if(it>=0 && it<item->cols_in && jt>=0 && jt<item->rows_in)
+ if((I_in->data[jt*byte_w_in+it/8] & 128>>(it%8))>0)
+ item->ximage->data[byte_out+i/8]|=128>>i%8;
+
+ di+=1;
+ }
+ dj+=1;
+ xl+=xinc;
+ xr+=xinc;
+ }
+ // handling for special cases of 90 and 270 not written yet.
+ // need elseif clauses here.
+ } else {
+ // not a 90 degree rotation, use sin/cos transform
+ /* loop through all relevent bits in rotated image */
+ for(j=0; j<item->rows_out; j++) {
+ float dj_sin, dj_cos;
+ float temp_it, temp_jt;
+
+
+ /* no point re-calculating these every pass */
+ di=(float)((xl<0)?0:(int)xl)+0.5-(float)item->cols_out/2;
+ byte_out=(item->rows_out-j-1)*byte_w_out;
+
+ // New code: Calculate these outside the inner loop for
+ // major speed gains.
+ dj_sin = dj * sin_angle;
+ dj_cos = dj * cos_angle;
+ temp_it = (float)cols_in2 + dj_sin;
+ temp_jt = (float)rows_in2 - dj_cos;
+
+ /* loop through meaningful columns */
+ for(i=((xl<0)?0:(int)xl);
+ i<((xr>=item->cols_out)?item->cols_out:(int)xr); i++) {
+
+ // rotate coordinates
+
+ // Original code (very slow)
+ //it=(float)item->cols_in/2 + ( di*cos_angle + dj*sin_angle);
+ //jt=(float)item->rows_in/2 - (-di*sin_angle + dj*cos_angle);
+
+ // New code (much faster)
+ //it=(float)cols_in2 + ( di*cos_angle + dj_sin);
+ //jt=(float)rows_in2 - (-di*sin_angle + dj_cos);
+ it=(float)temp_it + di*cos_angle;
+ jt=(float)temp_jt + di*sin_angle;
+
+ /* set pixel if required */
+ if(it>=0 && it<item->cols_in && jt>=0 && jt<item->rows_in)
+ if((I_in->data[jt*byte_w_in+it/8] & 128>>(it%8))>0)
+ item->ximage->data[byte_out+i/8]|=128>>i%8;
+
+ di+=1;
+ }
+ dj+=1;
+ xl+=xinc;
+ xr+=xinc;
+ }
+ }
+ XDestroyImage(I_in);
+
+ if(style.magnify!=1.) {
+ item->cols_in=old_cols_in;
+ item->rows_in=old_rows_in;
+ }
+
+
+#ifdef CACHE_BITMAPS
+
+ /* create a bitmap to hold rotated text */
+ item->bitmap=XCreatePixmap(dpy, DefaultRootWindow(dpy),
+ item->cols_out, item->rows_out, 1);
+
+ /* make the text bitmap from XImage */
+ XPutImage(dpy, item->bitmap, font_gc, item->ximage, 0, 0, 0, 0,
+ item->cols_out, item->rows_out);
+
+ XDestroyImage(item->ximage);
+
+#endif /*CACHE_BITMAPS*/
+
+ XFreeGC(dpy, font_gc);
+ XFreePixmap(dpy, canvas);
+
+ return item;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Adds a text item to the end of the cache, removing as many items */
+/* from the front as required to keep cache size below limit */
+/**************************************************************************/
+
+static void XRotAddToLinkedList( Display *dpy, RotatedTextItem *item) {
+
+ static long int current_size=0;
+ static RotatedTextItem *last=NULL;
+ RotatedTextItem *i1=first_text_item, *i2=NULL;
+
+#ifdef CACHE_BITMAPS
+
+ /* I don't know how much memory a pixmap takes in the server -
+ probably this + a bit more we can't account for */
+
+ item->size=((item->cols_out-1)/8+1)*item->rows_out;
+
+#else // CACHE_BITMAPS
+
+ /* this is pretty much the size of a RotatedTextItem */
+
+ item->size=((item->cols_out-1)/8+1)*item->rows_out +
+ sizeof(XImage) + strlen(item->text) +
+ item->nl*8*sizeof(float) + sizeof(RotatedTextItem);
+
+ if(item->font_name!=NULL)
+ item->size+=strlen(item->font_name);
+ else
+ item->size+=sizeof(Font);
+
+#endif /*CACHE_BITMAPS */
+
+#ifdef DEBUG
+ /* count number of items in cache, for debugging */
+ {
+ int i=0;
+
+ while(i1) {
+ i++;
+ i1=i1->next;
+ }
+ DEBUG_PRINT2("Cache has %d items.\n", i);
+ i1=first_text_item;
+ }
+#endif // DEBUG
+
+ DEBUG_PRINT4("current cache size=%ld, new item=%ld, limit=%ld\n",
+ current_size, item->size, (long)(CACHE_SIZE_LIMIT*1024));
+
+ /* if this item is bigger than whole cache, forget it */
+ if(item->size>CACHE_SIZE_LIMIT*1024) {
+ DEBUG_PRINT1("Too big to cache\n\n");
+ item->cached=0;
+ return;
+ }
+
+ /* remove elements from cache as needed */
+ while(i1 && current_size+item->size>CACHE_SIZE_LIMIT*1024) {
+
+ DEBUG_PRINT2("Removed %d bytes\n", (int)i1->size);
+
+ if(i1->font_name!=NULL)
+ DEBUG_PRINT5(" (`%s'\n %s\n angle=%f align=%d)\n",
+ i1->text, i1->font_name, i1->angle, i1->align);
+
+#ifdef CACHE_FID
+ if(i1->font_name==NULL)
+ DEBUG_PRINT5(" (`%s'\n FID=%ld\n angle=%f align=%d)\n",
+ i1->text, i1->fid, i1->angle, i1->align);
+#endif /*CACHE_FID*/
+
+ current_size-=i1->size;
+
+ i2=i1->next;
+
+ /* free resources used by the unlucky item */
+ XRotFreeTextItem(dpy, i1);
+
+ /* remove it from linked list */
+ first_text_item=i2;
+ i1=i2;
+ }
+
+ /* add new item to end of linked list */
+ if(first_text_item==NULL) {
+ item->next=NULL;
+ first_text_item=item;
+ last=item;
+ }
+ else {
+ item->next=NULL;
+ last->next=item;
+ last=item;
+ }
+
+ /* new cache size */
+ current_size+=item->size;
+
+ item->cached=1;
+
+ DEBUG_PRINT1("Added item to cache.\n");
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Free the resources used by a text item */
+/**************************************************************************/
+
+static void XRotFreeTextItem( Display *dpy, RotatedTextItem *item) {
+ free(item->text);
+
+ if(item->font_name!=NULL)
+ free(item->font_name);
+
+ free((char *)item->corners_x);
+ free((char *)item->corners_y);
+
+#ifdef CACHE_BITMAPS
+ XFreePixmap(dpy, item->bitmap);
+#else // CACHE_BITMAPS
+ XDestroyImage(item->ximage);
+#endif /* CACHE_BITMAPS */
+
+ free((char *)item);
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Magnify an XImage using bilinear interpolation */
+/**************************************************************************/
+
+static XImage *XRotMagnifyImage( Display *dpy, XImage *ximage) {
+ int i, j;
+ float x, y;
+ float u,t;
+ XImage *I_out;
+ int cols_in, rows_in;
+ int cols_out, rows_out;
+ register int i2, j2;
+ float z1, z2, z3, z4;
+ int byte_width_in, byte_width_out;
+ float mag_inv;
+
+ /* size of input image */
+ cols_in=ximage->width;
+ rows_in=ximage->height;
+
+ /* size of final image */
+ cols_out=(float)cols_in*style.magnify;
+ rows_out=(float)rows_in*style.magnify;
+
+ /* this will hold final image */
+ I_out=MakeXImage(dpy, cols_out, rows_out);
+ if(I_out==NULL)
+ return NULL;
+
+ /* width in bytes of input, output images */
+ byte_width_in=(cols_in-1)/8+1;
+ byte_width_out=(cols_out-1)/8+1;
+
+ /* for speed */
+ mag_inv=1./style.magnify;
+
+ y=0.;
+
+ /* loop over magnified image */
+ for(j2=0; j2<rows_out; j2++) {
+ x=0;
+ j=y;
+
+ for(i2=0; i2<cols_out; i2++) {
+ i=x;
+
+ /* bilinear interpolation - where are we on bitmap ? */
+ /* right edge */
+ if(i==cols_in-1 && j!=rows_in-1) {
+ t=0;
+ u=y-(float)j;
+
+ z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
+ z2=z1;
+ z3=(ximage->data[(j+1)*byte_width_in+i/8] & 128>>(i%8))>0;
+ z4=z3;
+ }
+ /* top edge */
+ else if(i!=cols_in-1 && j==rows_in-1) {
+ t=x-(float)i;
+ u=0;
+
+ z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
+ z2=(ximage->data[j*byte_width_in+(i+1)/8] & 128>>((i+1)%8))>0;
+ z3=z2;
+ z4=z1;
+ }
+ /* top right corner */
+ else if(i==cols_in-1 && j==rows_in-1) {
+ u=0;
+ t=0;
+
+ z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
+ z2=z1;
+ z3=z1;
+ z4=z1;
+ }
+ /* somewhere `safe' */
+ else {
+ t=x-(float)i;
+ u=y-(float)j;
+
+ z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
+ z2=(ximage->data[j*byte_width_in+(i+1)/8] & 128>>((i+1)%8))>0;
+ z3=(ximage->data[(j+1)*byte_width_in+(i+1)/8] &
+ 128>>((i+1)%8))>0;
+ z4=(ximage->data[(j+1)*byte_width_in+i/8] & 128>>(i%8))>0;
+ }
+
+ /* if interpolated value is greater than 0.5, set bit */
+ if(((1-t)*(1-u)*z1 + t*(1-u)*z2 + t*u*z3 + (1-t)*u*z4)>0.5)
+ I_out->data[j2*byte_width_out+i2/8]|=128>>i2%8;
+
+ x+=mag_inv;
+ }
+ y+=mag_inv;
+ }
+
+ /* destroy original */
+ XDestroyImage(ximage);
+
+ /* return big image */
+ return I_out;
+}
+
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Calculate the bounding box some text will have when painted */
+/**************************************************************************/
+//
+// This function allocates some memory, frees all but xp_out which
+// is returned.
+//
+XPoint *XRotTextExtents( Display *dpy, XFontStruct *font, float angle, int x, int y, char *text, int align) {
+ register int i;
+ char *str1, *str2, *str3;
+ char *str2_a="\0", *str2_b="\n\0";
+ int height;
+ float sin_angle, cos_angle;
+ int nl, max_width;
+ int cols_in, rows_in;
+ float hot_x, hot_y;
+ XPoint *xp_in, *xp_out;
+ int dir, asc, desc;
+ XCharStruct overall;
+
+ /* manipulate angle to 0<=angle<360 degrees */
+ while(angle<0)
+ angle+=360;
+
+ while(angle>360)
+ angle-=360;
+
+ angle*=M_PI/180;
+
+ /* count number of sections in string */
+ nl=1;
+ if(align!=NONE) {
+ for (i=0; i < (int)(strlen(text)-1); i++) {
+ if(text[i]=='\n') {
+ nl++;
+ }
+ }
+ }
+
+ /* ignore newline characters if not doing alignment */
+ if(align==NONE)
+ str2=str2_a;
+ else
+ str2=str2_b;
+
+ /* find width of longest section */
+// Allocates some memory, free'd below
+ str1=my_strdup(text);
+ if(str1==NULL)
+ return NULL;
+
+ str3=my_strtok(str1, str2);
+
+ XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc, &overall);
+
+ max_width=overall.rbearing;
+
+ /* loop through each section */
+ do {
+ str3=my_strtok((char *)NULL, str2);
+
+ if(str3!=NULL) {
+ XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc, &overall);
+
+ if(overall.rbearing>max_width)
+ max_width=overall.rbearing;
+ }
+ }
+ while(str3!=NULL);
+
+ free(str1);
+
+ /* overall font height */
+ height=font->ascent+font->descent;
+
+ /* dimensions horizontal text will have */
+ cols_in=max_width;
+ rows_in=nl*height;
+
+ /* pre-calculate sin and cos */
+ sin_angle=sin(angle);
+ cos_angle=cos(angle);
+
+ /* y position */
+ if(align==TLEFT || align==TCENTRE || align==TRIGHT)
+ hot_y=(float)rows_in/2*style.magnify;
+ else if(align==MLEFT || align==MCENTRE || align==MRIGHT)
+ hot_y=0;
+ else if(align==BLEFT || align==BCENTRE || align==BRIGHT)
+ hot_y=-(float)rows_in/2*style.magnify;
+ else
+ hot_y=-((float)rows_in/2-(float)font->descent)*style.magnify;
+
+ /* x position */
+ if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
+ hot_x=-(float)max_width/2*style.magnify;
+ else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
+ hot_x=0;
+ else
+ hot_x=(float)max_width/2*style.magnify;
+
+ /* reserve space for XPoints */
+ xp_in=(XPoint *)malloc((unsigned)(5*sizeof(XPoint)));
+ if(!xp_in) {
+ fprintf(stderr,"Couldn't allocate memory in XRotTextExtents()\n");
+ return NULL;
+ }
+
+ xp_out=(XPoint *)malloc((unsigned)(5*sizeof(XPoint)));
+ if(!xp_out) {
+ fprintf(stderr,"Couldn't allocate memory in XRotTextExtents()\n");
+ return NULL;
+ }
+
+ /* bounding box when horizontal, relative to bitmap centre */
+ xp_in[0].x=-(float)cols_in*style.magnify/2-style.bbx_pad;
+ xp_in[0].y= (float)rows_in*style.magnify/2+style.bbx_pad;
+ xp_in[1].x= (float)cols_in*style.magnify/2+style.bbx_pad;
+ xp_in[1].y= (float)rows_in*style.magnify/2+style.bbx_pad;
+ xp_in[2].x= (float)cols_in*style.magnify/2+style.bbx_pad;
+ xp_in[2].y=-(float)rows_in*style.magnify/2-style.bbx_pad;
+ xp_in[3].x=-(float)cols_in*style.magnify/2-style.bbx_pad;
+ xp_in[3].y=-(float)rows_in*style.magnify/2-style.bbx_pad;
+ xp_in[4].x=xp_in[0].x;
+ xp_in[4].y=xp_in[0].y;
+
+ /* rotate and translate bounding box */
+ for(i=0; i<5; i++) {
+ xp_out[i].x=(float)x + ( ((float)xp_in[i].x-hot_x)*cos_angle +
+ ((float)xp_in[i].y+hot_y)*sin_angle);
+ xp_out[i].y=(float)y + (-((float)xp_in[i].x-hot_x)*sin_angle +
+ ((float)xp_in[i].y+hot_y)*cos_angle);
+ }
+
+ free((char *)xp_in);
+
+ return xp_out;
+}
+
+
diff --git a/src/rotated.h b/src/rotated.h
new file mode 100644
index 0000000..8501cde
--- /dev/null
+++ b/src/rotated.h
@@ -0,0 +1,89 @@
+
+// $Id: rotated.h,v 1.12 2012/11/01 18:57:19 we7u Exp $
+//
+// Portions Copyright (C) 2000-2012 The Xastir Group
+//
+
+/* ************************************************************************ */
+
+
+/* Header file for the `xvertext 5.0' routines.
+
+ Copyright (c) 1993 Alan Richardson (mppa3 at uk.ac.sussex.syma) */
+
+
+/* ************************************************************************ */
+
+#ifndef _XVERTEXT_INCLUDED_
+#define _XVERTEXT_INCLUDED_
+
+
+#define XV_VERSION 5.0
+#define XV_COPYRIGHT \
+ "xvertext routines Copyright (c) 1993 Alan Richardson"
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/* text alignment */
+
+#define NONE 0
+#define TLEFT 1
+#define TCENTRE 2
+#define TRIGHT 3
+#define MLEFT 4
+#define MCENTRE 5
+#define MRIGHT 6
+#define BLEFT 7
+#define BCENTRE 8
+#define BRIGHT 9
+
+
+/* ---------------------------------------------------------------------- */
+
+/* this shoulf be C++ compliant, thanks to
+ vlp at latina.inesc.pt (Vasco Lopes Paulo) */
+
+#if defined(__cplusplus) || defined(c_plusplus)
+
+extern "C" {
+float XRotVersion(char*, int);
+void XRotSetMagnification(float);
+void XRotSetBoundingBoxPad(int);
+int XRotDrawString(Display*, XFontStruct*, float,
+ Drawable, GC, int, int, char*);
+int XRotDrawImageString(Display*, XFontStruct*, float,
+ Drawable, GC, int, int, char*);
+int XRotDrawAlignedString(Display*, XFontStruct*, float,
+ Drawable, GC, int, int, char*, int);
+int XRotDrawAlignedImageString(Display*, XFontStruct*, float,
+ Drawable, GC, int, int, char*, int);
+XPoint *XRotTextExtents(Display*, XFontStruct*, float,
+ int, int, char*, int);
+}
+
+#else // _cplusplus || c_plusplus
+
+extern float XRotVersion(char *, int);
+extern void XRotSetMagnification(float);
+extern void XRotSetBoundingBoxPad(int);
+extern int XRotDrawString(Display *, XFontStruct*, float,
+ Drawable, GC, int, int, char*);
+extern int XRotDrawImageString(Display*, XFontStruct*, float,
+ Drawable, GC, int, int, char*);
+extern int XRotDrawAlignedString(Display*, XFontStruct*, float,
+ Drawable, GC, int, int, char*, int);
+extern int XRotDrawAlignedImageString(Display*, XFontStruct*, float,
+ Drawable, GC, int, int, char*, int);
+extern XPoint *XRotTextExtents(Display*, XFontStruct*, float,
+ int, int, char*, int);
+
+#endif /* __cplusplus */
+
+/* ---------------------------------------------------------------------- */
+
+
+#endif /* _XVERTEXT_INCLUDED_ */
+
+
diff --git a/src/rpl_malloc.c b/src/rpl_malloc.c
new file mode 100644
index 0000000..a64c09a
--- /dev/null
+++ b/src/rpl_malloc.c
@@ -0,0 +1,59 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: rpl_malloc.c,v 1.7 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+/*
+//
+// We DON'T want config.h to redefine malloc in this file else we'll
+// get an infinite loop.
+//
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+*/
+
+#include <stdlib.h>
+
+#include "rpl_malloc.h"
+
+//
+// Work around bug on some systems where malloc (0) fails.
+// written by Jim Meyering
+//
+// configure.ac calls out AC_FUNC_MALLOC which checks the malloc()
+// function. If malloc() is determined to do the wrong thing when
+// passed a 0 value, the Autoconf macro will do this:
+// #define malloc rpl_malloc
+// We then need to have an rpl_malloc function defined. Here it is:
+//
+// Allocate an N-byte block of memory from the heap.
+// If N is zero, allocate a 1-byte block.
+//
+void *rpl_malloc (size_t size) {
+ if (size == 0)
+ size++;
+ return malloc (size);
+}
+
+
diff --git a/src/rpl_malloc.h b/src/rpl_malloc.h
new file mode 100644
index 0000000..df7f4a6
--- /dev/null
+++ b/src/rpl_malloc.h
@@ -0,0 +1,37 @@
+/*
+ * $Id: rpl_malloc.h,v 1.6 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifndef __XASTIR_RPL_MALLOC_H
+#define __XASTIR_RPL_MALLOC_H
+
+
+
+
+extern void *rpl_malloc (size_t size);
+
+
+#endif // __XASTIR_RPL_MALLOC_H
+
+
diff --git a/src/rtree/Makefile.am b/src/rtree/Makefile.am
new file mode 100644
index 0000000..b9062a9
--- /dev/null
+++ b/src/rtree/Makefile.am
@@ -0,0 +1,13 @@
+
+# $Id: Makefile.am,v 1.8 2012/11/01 18:57:19 we7u Exp $
+# Copyright (C) 2004-2012 The Xastir Group
+
+noinst_LIBRARIES=librtree.a
+librtree_a_SOURCES=index.c \
+ index.h \
+ rect.c \
+ node.c \
+ card.c \
+ card.h \
+ split_l.c \
+ split_l.h
diff --git a/src/rtree/Makefile.in b/src/rtree/Makefile.in
new file mode 100644
index 0000000..1922d71
--- /dev/null
+++ b/src/rtree/Makefile.in
@@ -0,0 +1,476 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+# $Id: Makefile.am,v 1.8 2012/11/01 18:57:19 we7u Exp $
+# Copyright (C) 2004-2012 The Xastir Group
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/rtree
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+librtree_a_AR = $(AR) $(ARFLAGS)
+librtree_a_LIBADD =
+am_librtree_a_OBJECTS = index.$(OBJEXT) rect.$(OBJEXT) node.$(OBJEXT) \
+ card.$(OBJEXT) split_l.$(OBJEXT)
+librtree_a_OBJECTS = $(am_librtree_a_OBJECTS)
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(librtree_a_SOURCES)
+DIST_SOURCES = $(librtree_a_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTSHP = @CONTSHP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GMAGIC_BIN = @GMAGIC_BIN@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBCOMPAT = @LIBCOMPAT@
+LIBOBJS = @LIBOBJS@
+LIBRTREE = @LIBRTREE@
+LIBS = @LIBS@
+LIBSHP = @LIBSHP@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LWPOSTGIS = @LWPOSTGIS@
+MAGIC_BIN = @MAGIC_BIN@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PG_CONFIG = @PG_CONFIG@
+POW_LIB = @POW_LIB@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUBRTREE = @SUBRTREE@
+SUBSHP = @SUBSHP@
+VERSION = @VERSION@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+convert = @convert@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+festival = @festival@
+found_gdal_config = @found_gdal_config@
+gm = @gm@
+gpsman = @gpsman@
+gv = @gv@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lpr = @lpr@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+mv = @mv@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sed = @sed@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+wget = @wget@
+xfontsel = @xfontsel@
+noinst_LIBRARIES = librtree.a
+librtree_a_SOURCES = index.c \
+ index.h \
+ rect.c \
+ node.c \
+ card.c \
+ card.h \
+ split_l.c \
+ split_l.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/rtree/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/rtree/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+librtree.a: $(librtree_a_OBJECTS) $(librtree_a_DEPENDENCIES)
+ -rm -f librtree.a
+ $(librtree_a_AR) librtree.a $(librtree_a_OBJECTS) $(librtree_a_LIBADD)
+ $(RANLIB) librtree.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/card.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/index.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/node.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/rect.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/split_l.Po at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES ctags distclean distclean-compile \
+ distclean-generic distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/rtree/card.c b/src/rtree/card.c
new file mode 100644
index 0000000..2e7c655
--- /dev/null
+++ b/src/rtree/card.c
@@ -0,0 +1,52 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: card.c,v 1.10 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+/****************************************************************************
+ * MODULE: R-Tree library
+ *
+ * AUTHOR(S): Antonin Guttman - original code
+ * Melinda Green (melinda at superliminal.com) - major clean-up
+ * and implementation of bounding spheres
+ *
+ * PURPOSE: Multidimensional index
+ *
+ */
+
+#include "index.h"
+#include "card.h"
+
+int Xastir_NODECARD = MAXCARD;
+int Xastir_LEAFCARD = MAXCARD;
+
+static int set_max(int *which, int new_max)
+{
+ if(2 > new_max || new_max > MAXCARD)
+ return 0;
+ *which = new_max;
+ return 1;
+}
+
+int Xastir_RTreeSetNodeMax(int new_max) { return set_max(&Xastir_NODECARD, new_max); }
+int Xastir_RTreeSetLeafMax(int new_max) { return set_max(&Xastir_LEAFCARD, new_max); }
+int Xastir_RTreeGetNodeMax(void) { return Xastir_NODECARD; }
+int Xastir_RTreeGetLeafMax(void) { return Xastir_LEAFCARD; }
diff --git a/src/rtree/card.h b/src/rtree/card.h
new file mode 100644
index 0000000..ad84659
--- /dev/null
+++ b/src/rtree/card.h
@@ -0,0 +1,49 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: card.h,v 1.9 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+/****************************************************************************
+ * MODULE: R-Tree library
+ *
+ * AUTHOR(S): Antonin Guttman - original code
+ * Melinda Green (melinda at superliminal.com) - major clean-up
+ * and implementation of bounding spheres
+ *
+ * PURPOSE: Multidimensional index
+ *
+ */
+
+#ifndef __CARD__
+#define __CARD__
+
+extern int Xastir_NODECARD;
+extern int Xastir_LEAFCARD;
+
+/* balance criteria for node splitting */
+/* NOTE: can be changed if needed. */
+#define MinNodeFill (Xastir_NODECARD / 2)
+#define MinLeafFill (Xastir_LEAFCARD / 2)
+
+#define MAXKIDS(n) ((n)->level > 0 ? Xastir_NODECARD : Xastir_LEAFCARD)
+#define MINFILL(n) ((n)->level > 0 ? MinNodeFill : MinLeafFill)
+
+#endif
diff --git a/src/rtree/index.c b/src/rtree/index.c
new file mode 100644
index 0000000..31f1475
--- /dev/null
+++ b/src/rtree/index.c
@@ -0,0 +1,367 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: index.c,v 1.12 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+/****************************************************************************
+ * MODULE: R-Tree library
+ *
+ * AUTHOR(S): Antonin Guttman - original code
+ * Melinda Green (melinda at superliminal.com) - major clean-up
+ * and implementation of bounding spheres
+ *
+ * PURPOSE: Multidimensional index
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "assert.h"
+#include "index.h"
+#include "card.h"
+
+
+// Make a new index, empty. Consists of a single node.
+//
+struct Node * Xastir_RTreeNewIndex(void)
+{
+ struct Node *x;
+ x = Xastir_RTreeNewNode();
+ x->level = 0; /* leaf */
+ return x;
+}
+
+
+
+// Search in an index tree or subtree for all data retangles that
+// overlap the argument rectangle.
+// Return the number of qualifying data rects.
+//
+int Xastir_RTreeSearch(struct Node *N, struct Rect *R, SearchHitCallback shcb, void* cbarg)
+{
+ register struct Node *n = N;
+ register struct Rect *r = R; // NOTE: Suspected bug was R sent in as Node* and cast to Rect* here. Fix not yet tested.
+ register int hitCount = 0;
+ register int i;
+
+ assert(n);
+ assert(n->level >= 0);
+ assert(r);
+
+ if (n->level > 0) /* this is an internal node in the tree */
+ {
+ for (i=0; i<Xastir_NODECARD; i++)
+ if (n->branch[i].child &&
+ Xastir_RTreeOverlap(r,&n->branch[i].rect))
+ {
+ hitCount += Xastir_RTreeSearch(n->branch[i].child, R, shcb, cbarg);
+ }
+ }
+ else /* this is a leaf node */
+ {
+ for (i=0; i<Xastir_LEAFCARD; i++)
+ if (n->branch[i].child &&
+ Xastir_RTreeOverlap(r,&n->branch[i].rect))
+ {
+ hitCount++;
+ if(shcb) // call the user-provided callback
+ if( ! shcb(n->branch[i].child, cbarg))
+ return hitCount; // callback wants to terminate search early
+ }
+ }
+ return hitCount;
+}
+
+
+
+// Inserts a new data rectangle into the index structure.
+// Recursively descends tree, propagates splits back up.
+// Returns 0 if node was not split. Old node updated.
+// If node was split, returns 1 and sets the pointer pointed to by
+// new_node to point to the new node. Old node updated to become one of two.
+// The level argument specifies the number of steps up from the leaf
+// level to insert; e.g. a data rectangle goes in at level = 0.
+//
+static int Xastir_RTreeInsertRect2(struct Rect *r,
+ void *tid, struct Node *n, struct Node **new_node, int level)
+{
+/*
+ register struct Rect *r = R;
+ register int tid = Tid;
+ register struct Node *n = N, **new_node = New_node;
+ register int level = Level;
+*/
+
+ register int i;
+ struct Branch b;
+ struct Node *n2;
+
+ assert(r && n && new_node);
+ assert(level >= 0 && level <= n->level);
+
+ // Still above level for insertion, go down tree recursively
+ //
+ if (n->level > level)
+ {
+ i = Xastir_RTreePickBranch(r, n);
+ if (!Xastir_RTreeInsertRect2(r, tid, n->branch[i].child, &n2, level))
+ {
+ // child was not split
+ //
+ n->branch[i].rect =
+ Xastir_RTreeCombineRect(r,&(n->branch[i].rect));
+ return 0;
+ }
+ else // child was split
+ {
+ n->branch[i].rect = Xastir_RTreeNodeCover(n->branch[i].child);
+ b.child = n2;
+ b.rect = Xastir_RTreeNodeCover(n2);
+ return Xastir_RTreeAddBranch(&b, n, new_node);
+ }
+ }
+
+ // Have reached level for insertion. Add rect, split if necessary
+ //
+ else if (n->level == level)
+ {
+ b.rect = *r;
+ b.child = (struct Node *) tid;
+ /* child field of leaves contains tid of data record */
+ return Xastir_RTreeAddBranch(&b, n, new_node);
+ }
+ else
+ {
+ /* Not supposed to happen */
+ assert (FALSE);
+ return 0;
+ }
+}
+
+
+
+// Insert a data rectangle into an index structure.
+// Xastir_RTreeInsertRect provides for splitting the root;
+// returns 1 if root was split, 0 if it was not.
+// The level argument specifies the number of steps up from the leaf
+// level to insert; e.g. a data rectangle goes in at level = 0.
+// Xastir_RTreeInsertRect2 does the recursion.
+//
+int Xastir_RTreeInsertRect(struct Rect *R, void *Tid, struct Node **Root, int Level)
+{
+ register struct Rect *r = R;
+ register void *tid = Tid;
+ register struct Node **root = Root;
+ register int level = Level;
+ register int i;
+ register struct Node *newroot;
+ struct Node *newnode;
+ struct Branch b;
+ int result;
+
+ assert(r && root);
+ assert(level >= 0 && level <= (*root)->level);
+ for (i=0; i<NUMDIMS; i++)
+ assert(r->boundary[i] <= r->boundary[NUMDIMS+i]);
+
+ if (Xastir_RTreeInsertRect2(r, tid, *root, &newnode, level)) /* root split */
+ {
+ newroot = Xastir_RTreeNewNode(); /* grow a new root, & tree taller */
+ newroot->level = (*root)->level + 1;
+ b.rect = Xastir_RTreeNodeCover(*root);
+ b.child = *root;
+ Xastir_RTreeAddBranch(&b, newroot, NULL);
+ b.rect = Xastir_RTreeNodeCover(newnode);
+ b.child = newnode;
+ Xastir_RTreeAddBranch(&b, newroot, NULL);
+ *root = newroot;
+ result = 1;
+ }
+ else
+ result = 0;
+
+ return result;
+}
+
+
+
+
+// Allocate space for a node in the list used in DeletRect to
+// store Nodes that are too empty.
+//
+static struct ListNode * Xastir_RTreeNewListNode(void)
+{
+ return (struct ListNode *) malloc(sizeof(struct ListNode));
+ //return new ListNode;
+}
+
+
+static void Xastir_RTreeFreeListNode(struct ListNode *p)
+{
+ free(p);
+ //delete(p);
+}
+
+
+
+// Add a node to the reinsertion list. All its branches will later
+// be reinserted into the index structure.
+//
+static void Xastir_RTreeReInsert(struct Node *n, struct ListNode **ee)
+{
+ register struct ListNode *l;
+
+ l = Xastir_RTreeNewListNode();
+ l->node = n;
+ l->next = *ee;
+ *ee = l;
+}
+
+
+// Delete a rectangle from non-root part of an index structure.
+// Called by Xastir_RTreeDeleteRect. Descends tree recursively,
+// merges branches on the way back up.
+// Returns 1 if record not found, 0 if success.
+//
+static int
+Xastir_RTreeDeleteRect2(struct Rect *R, void *Tid, struct Node *N, struct ListNode **Ee)
+{
+ register struct Rect *r = R;
+ register void *tid = Tid;
+ register struct Node *n = N;
+ register struct ListNode **ee = Ee;
+ register int i;
+
+ assert(r && n && ee);
+ assert(tid >= (void *)0);
+ assert(n->level >= 0);
+
+ if (n->level > 0) // not a leaf node
+ {
+ for (i = 0; i < Xastir_NODECARD; i++)
+ {
+ if (n->branch[i].child && Xastir_RTreeOverlap(r, &(n->branch[i].rect)))
+ {
+ if (!Xastir_RTreeDeleteRect2(r, tid, n->branch[i].child, ee))
+ {
+ if (n->branch[i].child->count >= MinNodeFill)
+ n->branch[i].rect = Xastir_RTreeNodeCover(
+ n->branch[i].child);
+ else
+ {
+ // not enough entries in child,
+ // eliminate child node
+ //
+ Xastir_RTreeReInsert(n->branch[i].child, ee);
+ Xastir_RTreeDisconnectBranch(n, i);
+ }
+ return 0;
+ }
+ }
+ }
+ return 1;
+ }
+ else // a leaf node
+ {
+ for (i = 0; i < Xastir_LEAFCARD; i++)
+ {
+ if (n->branch[i].child &&
+ n->branch[i].child == (struct Node *) tid)
+ {
+ Xastir_RTreeDisconnectBranch(n, i);
+ return 0;
+ }
+ }
+ return 1;
+ }
+}
+
+
+
+// Delete a data rectangle from an index structure.
+// Pass in a pointer to a Rect, the tid of the record, ptr to ptr to root node.
+// Returns 1 if record not found, 0 if success.
+// Xastir_RTreeDeleteRect provides for eliminating the root.
+//
+int Xastir_RTreeDeleteRect(struct Rect *R, void *Tid, struct Node**Nn)
+{
+ register struct Rect *r = R;
+ register void *tid = Tid;
+ register struct Node **nn = Nn;
+ register int i;
+ register struct Node *tmp_nptr=NULL; // Original superliminal.com
+ // source did not initialize.
+ // Code analysis says shouldn't
+ // matter, but let's initialize
+ // to shut up GCC
+ struct ListNode *reInsertList = NULL;
+ register struct ListNode *e;
+
+ assert(r && nn);
+ assert(*nn);
+ assert(tid >= (void *)0);
+
+ if (!Xastir_RTreeDeleteRect2(r, tid, *nn, &reInsertList))
+ {
+ /* found and deleted a data item */
+
+ /* reinsert any branches from eliminated nodes */
+ while (reInsertList)
+ {
+ tmp_nptr = reInsertList->node;
+ for (i = 0; i < MAXKIDS(tmp_nptr); i++)
+ {
+ if (tmp_nptr->branch[i].child)
+ {
+ Xastir_RTreeInsertRect(
+ &(tmp_nptr->branch[i].rect),
+ tmp_nptr->branch[i].child,
+ nn,
+ tmp_nptr->level);
+ }
+ }
+ e = reInsertList;
+ reInsertList = reInsertList->next;
+ Xastir_RTreeFreeNode(e->node);
+ Xastir_RTreeFreeListNode(e);
+ }
+
+ /* check for redundant root (not leaf, 1 child) and eliminate
+ */
+ if ((*nn)->count == 1 && (*nn)->level > 0)
+ {
+ for (i = 0; i < Xastir_NODECARD; i++)
+ {
+ tmp_nptr = (*nn)->branch[i].child;
+ if(tmp_nptr)
+ break;
+ }
+ assert(tmp_nptr);
+ Xastir_RTreeFreeNode(*nn);
+ *nn = tmp_nptr;
+ }
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
diff --git a/src/rtree/index.h b/src/rtree/index.h
new file mode 100644
index 0000000..7ab212b
--- /dev/null
+++ b/src/rtree/index.h
@@ -0,0 +1,130 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: index.h,v 1.12 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+/****************************************************************************
+ * MODULE: R-Tree library
+ *
+ * AUTHOR(S): Antonin Guttman - original code
+ * Melinda Green (melinda at superliminal.com) - major clean-up
+ * and implementation of bounding spheres
+ *
+ * PURPOSE: Multidimensional index
+ *
+ */
+#ifndef _INDEX_
+#define _INDEX_
+
+/* PGSIZE is normally the natural page size of the machine */
+#define PGSIZE 512
+#define NUMDIMS 2 /* number of dimensions */
+#define NDEBUG
+
+// This is what GRASS does
+//typedef double RectReal;
+// but this is the original, and saves lots of RAM --- these indices are
+// huge for big shapefiles!
+typedef float RectReal;
+
+
+/*-----------------------------------------------------------------------------
+| Global definitions.
+-----------------------------------------------------------------------------*/
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define NUMSIDES 2*NUMDIMS
+
+struct Rect
+{
+ RectReal boundary[NUMSIDES]; /* xmin,ymin,...,xmax,ymax,... */
+};
+
+struct Node;
+
+struct Branch
+{
+ struct Rect rect;
+ struct Node *child;
+};
+
+/* max branching factor of a node */
+#define MAXCARD (int)((PGSIZE-(2*sizeof(int))) / sizeof(struct Branch))
+
+struct Node
+{
+ int count;
+ int level; /* 0 is leaf, others positive */
+ struct Branch branch[MAXCARD];
+};
+
+struct ListNode
+{
+ struct ListNode *next;
+ struct Node *node;
+};
+
+/*
+ * If passed to a tree search, this callback function will be called
+ * with the ID of each data rect that overlaps the search rect
+ * plus whatever user specific pointer was passed to the search.
+ * It can terminate the search early by returning 0 in which case
+ * the search will return the number of hits found up to that point.
+ */
+typedef int (*SearchHitCallback)(void *id, void* arg);
+
+
+extern int Xastir_RTreeSearch(struct Node*, struct Rect*, SearchHitCallback, void*);
+extern int Xastir_RTreeInsertRect(struct Rect*, void *, struct Node**, int depth);
+extern int Xastir_RTreeDeleteRect(struct Rect*, void *, struct Node**);
+extern struct Node * Xastir_RTreeNewIndex(void);
+extern struct Node * Xastir_RTreeNewNode(void);
+extern void Xastir_RTreeInitNode(struct Node*);
+extern void Xastir_RTreeFreeNode(struct Node *);
+extern void Xastir_RTreePrintNode(struct Node *, int);
+extern void Xastir_RTreeDestroyNode(struct Node*);
+extern void Xastir_RTreeTabIn(int);
+extern struct Rect Xastir_RTreeNodeCover(struct Node *);
+extern void Xastir_RTreeInitRect(struct Rect*);
+extern struct Rect Xastir_RTreeNullRect(void);
+extern RectReal Xastir_RTreeRectArea(struct Rect*);
+extern RectReal Xastir_RTreeRectSphericalVolume(struct Rect *R);
+extern RectReal Xastir_RTreeRectVolume(struct Rect *R);
+extern struct Rect Xastir_RTreeCombineRect(struct Rect*, struct Rect*);
+extern int Xastir_RTreeOverlap(struct Rect*, struct Rect*);
+extern void Xastir_RTreePrintRect(struct Rect*, int);
+extern int Xastir_RTreeAddBranch(struct Branch *, struct Node *, struct Node **);
+extern int Xastir_RTreePickBranch(struct Rect *, struct Node *);
+extern void Xastir_RTreeDisconnectBranch(struct Node *, int);
+extern void Xastir_RTreeSplitNode(struct Node*, struct Branch*, struct Node**);
+
+extern int Xastir_RTreeSetNodeMax(int);
+extern int Xastir_RTreeSetLeafMax(int);
+extern int Xastir_RTreeGetNodeMax(void);
+extern int Xastir_RTreeGetLeafMax(void);
+
+#endif /* _INDEX_ */
diff --git a/src/rtree/node.c b/src/rtree/node.c
new file mode 100644
index 0000000..eb4c2b7
--- /dev/null
+++ b/src/rtree/node.c
@@ -0,0 +1,285 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: node.c,v 1.13 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+/****************************************************************************
+ * MODULE: R-Tree library
+ *
+ * AUTHOR(S): Antonin Guttman - original code
+ * Melinda Green (melinda at superliminal.com) - major clean-up
+ * and implementation of bounding spheres
+ *
+ * PURPOSE: Multidimensional index
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "assert.h"
+#include "index.h"
+#include "card.h"
+//static int nnodes_alloced=0;
+//static long int bytes_malloced=0;
+
+// Initialize one branch cell in a node.
+//
+static void Xastir_RTreeInitBranch(struct Branch *b)
+{
+ Xastir_RTreeInitRect(&(b->rect));
+ b->child = NULL;
+}
+
+
+
+// Initialize a Node structure.
+//
+void Xastir_RTreeInitNode(struct Node *N)
+{
+ register struct Node *n = N;
+ register int i;
+ n->count = 0;
+ n->level = -1;
+ for (i = 0; i < MAXCARD; i++)
+ Xastir_RTreeInitBranch(&(n->branch[i]));
+}
+
+
+
+// Make a new node and initialize to have all branch cells empty.
+//
+struct Node * Xastir_RTreeNewNode(void)
+{
+ register struct Node *n;
+
+ //n = new Node;
+ n = (struct Node*)malloc(sizeof(struct Node));
+ assert(n);
+ // nnodes_alloced++;
+ // bytes_malloced+= sizeof(struct Node);
+ // fprintf(stderr," Currently %d nodes (%ld bytes) in all rtrees\n",nnodes_alloced, bytes_malloced);
+ Xastir_RTreeInitNode(n);
+ return n;
+}
+
+
+void Xastir_RTreeFreeNode(struct Node *p)
+{
+ assert(p);
+ //delete p;
+ // nnodes_alloced--;
+ // bytes_malloced-= sizeof(struct Node);
+ free(p);
+}
+
+
+
+static void Xastir_RTreePrintBranch(struct Branch *b, int depth)
+{
+ Xastir_RTreePrintRect(&(b->rect), depth);
+ Xastir_RTreePrintNode(b->child, depth);
+}
+
+
+extern void Xastir_RTreeTabIn(int depth)
+{
+ int i;
+ for(i=0; i<depth; i++)
+ putchar('\t');
+}
+
+
+// Print out the data in a node.
+//
+void Xastir_RTreePrintNode(struct Node *n, int depth)
+{
+ int i;
+ assert(n);
+
+ Xastir_RTreeTabIn(depth);
+ printf("node");
+ if (n->level == 0)
+ printf(" LEAF");
+ else if (n->level > 0)
+ printf(" NONLEAF");
+ else
+ printf(" TYPE=?");
+ // Original superliminal.com implementation had no cast before
+ // n, gcc gripes about "int format, pointer arg"
+ printf(" level=%d count=%d address=%lx\n", n->level, n->count, (unsigned long) n);
+
+ for (i=0; i<n->count; i++)
+ {
+ if(n->level == 0) {
+ // Xastir_RTreeTabIn(depth);
+ // printf("\t%d: data = %d\n", i, n->branch[i].child);
+ }
+ else {
+ Xastir_RTreeTabIn(depth);
+ printf("branch %d\n", i);
+ Xastir_RTreePrintBranch(&n->branch[i], depth+1);
+ }
+ }
+}
+
+
+
+// Find the smallest rectangle that includes all rectangles in
+// branches of a node.
+//
+struct Rect Xastir_RTreeNodeCover(struct Node *N)
+{
+ register struct Node *n = N;
+ register int i, first_time=1;
+ struct Rect r;
+ assert(n);
+
+ Xastir_RTreeInitRect(&r);
+ for (i = 0; i < MAXKIDS(n); i++)
+ if (n->branch[i].child)
+ {
+ if (first_time)
+ {
+ r = n->branch[i].rect;
+ first_time = 0;
+ }
+ else
+ r = Xastir_RTreeCombineRect(&r, &(n->branch[i].rect));
+ }
+ return r;
+}
+
+
+
+// Pick a branch. Pick the one that will need the smallest increase
+// in area to accomodate the new rectangle. This will result in the
+// least total area for the covering rectangles in the current node.
+// In case of a tie, pick the one which was smaller before, to get
+// the best resolution when searching.
+//
+int Xastir_RTreePickBranch(struct Rect *R, struct Node *N)
+{
+ register struct Rect *r = R;
+ register struct Node *n = N;
+ register struct Rect *rr;
+ register int i, first_time=1;
+ // Although it is impossible for bestArea and best to be used
+ // unininitialized the way the code is structured, gcc complains
+ // about possible uninitialized usage. Let's keep it happy.
+ // Original superliminal.com had no initializers here.
+ RectReal increase, bestIncr=(RectReal)-1, area, bestArea=0.0;
+ int best=0;
+ struct Rect tmp_rect;
+ assert(r && n);
+
+ for (i=0; i<MAXKIDS(n); i++)
+ {
+ if (n->branch[i].child)
+ {
+ rr = &n->branch[i].rect;
+ area = Xastir_RTreeRectSphericalVolume(rr);
+ tmp_rect = Xastir_RTreeCombineRect(r, rr);
+ increase = Xastir_RTreeRectSphericalVolume(&tmp_rect) - area;
+ if (increase < bestIncr || first_time)
+ {
+ best = i;
+ bestArea = area;
+ bestIncr = increase;
+ first_time = 0;
+ }
+ else if (increase == bestIncr && area < bestArea)
+ {
+ best = i;
+ bestArea = area;
+ bestIncr = increase;
+ }
+ }
+ }
+ return best;
+}
+
+
+
+// Add a branch to a node. Split the node if necessary.
+// Returns 0 if node not split. Old node updated.
+// Returns 1 if node split, sets *new_node to address of new node.
+// Old node updated, becomes one of two.
+//
+int Xastir_RTreeAddBranch(struct Branch *B, struct Node *N, struct Node **New_node)
+{
+ register struct Branch *b = B;
+ register struct Node *n = N;
+ register struct Node **new_node = New_node;
+ register int i;
+
+ assert(b);
+ assert(n);
+
+ if (n->count < MAXKIDS(n)) /* split won't be necessary */
+ {
+ for (i = 0; i < MAXKIDS(n); i++) /* find empty branch */
+ {
+ if (n->branch[i].child == NULL)
+ {
+ n->branch[i] = *b;
+ n->count++;
+ break;
+ }
+ }
+ return 0;
+ }
+ else
+ {
+ assert(new_node);
+ Xastir_RTreeSplitNode(n, b, new_node);
+ return 1;
+ }
+}
+
+
+
+// Disconnect a dependent node.
+//
+void Xastir_RTreeDisconnectBranch(struct Node *n, int i)
+{
+ assert(n && i>=0 && i<MAXKIDS(n));
+ assert(n->branch[i].child);
+
+ Xastir_RTreeInitBranch(&(n->branch[i]));
+ n->count--;
+}
+
+// Destroy (free) node recursively.
+void Xastir_RTreeDestroyNode (struct Node *n)
+{
+ int i;
+ // fprintf(stderr," Freeing node %lx\n",(unsigned long int) n);
+ if (n->level > 0) { //it is not leaf -> destroy childs
+ for ( i = 0; i < Xastir_NODECARD; i++) {
+ if ( n->branch[i].child ) {
+ Xastir_RTreeDestroyNode ( n->branch[i].child );
+ }
+ }
+ }
+
+ //
+ Xastir_RTreeFreeNode( n );
+}
diff --git a/src/rtree/rect.c b/src/rtree/rect.c
new file mode 100644
index 0000000..d7dc263
--- /dev/null
+++ b/src/rtree/rect.c
@@ -0,0 +1,393 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: rect.c,v 1.11 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+/****************************************************************************
+ * MODULE: R-Tree library
+ *
+ * AUTHOR(S): Antonin Guttman - original code
+ * Melinda Green (melinda at superliminal.com) - major clean-up
+ * and implementation of bounding spheres
+ *
+ * PURPOSE: Multidimensional index
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "assert.h"
+#include "index.h"
+
+#include <float.h>
+#include <math.h>
+
+#define BIG_NUM (FLT_MAX/4.0)
+
+
+#define Undefined(x) ((x)->boundary[0] > (x)->boundary[NUMDIMS])
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+
+/*-----------------------------------------------------------------------------
+| Initialize a rectangle to have all 0 coordinates.
+-----------------------------------------------------------------------------*/
+void Xastir_RTreeInitRect(struct Rect *R)
+{
+ register struct Rect *r = R;
+ register int i;
+ for (i=0; i<NUMSIDES; i++)
+ r->boundary[i] = (RectReal)0;
+}
+
+
+/*-----------------------------------------------------------------------------
+| Return a rect whose first low side is higher than its opposite side -
+| interpreted as an undefined rect.
+-----------------------------------------------------------------------------*/
+struct Rect Xastir_RTreeNullRect(void)
+{
+ struct Rect r;
+ register int i;
+
+ r.boundary[0] = (RectReal)1;
+ r.boundary[NUMDIMS] = (RectReal)-1;
+ for (i=1; i<NUMDIMS; i++)
+ r.boundary[i] = r.boundary[i+NUMDIMS] = (RectReal)0;
+ return r;
+}
+
+
+#if 0
+
+/*-----------------------------------------------------------------------------
+| Fills in random coordinates in a rectangle.
+| The low side is guaranteed to be less than the high side.
+-----------------------------------------------------------------------------*/
+void Xastir_RTreeRandomRect(struct Rect *R)
+{
+ register struct Rect *r = R;
+ register int i;
+ register RectReal width;
+ for (i = 0; i < NUMDIMS; i++)
+ {
+ /* width from 1 to 1000 / 4, more small ones
+ */
+ width = drand48() * (1000 / 4) + 1;
+
+ /* sprinkle a given size evenly but so they stay in [0,100]
+ */
+ r->boundary[i] = drand48() * (1000-width); /* low side */
+ r->boundary[i + NUMDIMS] = r->boundary[i] + width; // high side
+ }
+}
+
+
+/*-----------------------------------------------------------------------------
+| Fill in the boundaries for a random search rectangle.
+| Pass in a pointer to a rect that contains all the data,
+| and a pointer to the rect to be filled in.
+| Generated rect is centered randomly anywhere in the data area,
+| and has size from 0 to the size of the data area in each dimension,
+| i.e. search rect can stick out beyond data area.
+-----------------------------------------------------------------------------*/
+void Xastir_RTreeSearchRect(struct Rect *Search, struct Rect *Data)
+{
+ register struct Rect *search = Search, *data = Data;
+ register int i, j;
+ register RectReal size, center;
+
+ assert(search);
+ assert(data);
+
+ for (i=0; i<NUMDIMS; i++)
+ {
+ j = i + NUMDIMS; // index for high side boundary
+ if (data->boundary[i] > -BIG_NUM &&
+ data->boundary[j] < BIG_NUM)
+ {
+ size = (drand48() * (data->boundary[j] -
+ data->boundary[i] + 1)) / 2;
+ center = data->boundary[i] + drand48() *
+ (data->boundary[j] - data->boundary[i] + 1);
+ search->boundary[i] = center - size/2;
+ search->boundary[j] = center + size/2;
+ }
+ else // some open boundary, search entire dimension
+ {
+ search->boundary[i] = -BIG_NUM;
+ search->boundary[j] = BIG_NUM;
+ }
+ }
+}
+
+#endif
+
+/*-----------------------------------------------------------------------------
+| Print out the data for a rectangle.
+-----------------------------------------------------------------------------*/
+void Xastir_RTreePrintRect(struct Rect *R, int depth)
+{
+ register struct Rect *r = R;
+ register int i;
+ assert(r);
+
+ Xastir_RTreeTabIn(depth);
+ printf("rect:\n");
+ for (i = 0; i < NUMDIMS; i++) {
+ Xastir_RTreeTabIn(depth+1);
+ printf("%f\t%f\n", r->boundary[i], r->boundary[i + NUMDIMS]);
+ }
+}
+
+/*-----------------------------------------------------------------------------
+| Calculate the n-dimensional volume of a rectangle
+-----------------------------------------------------------------------------*/
+RectReal Xastir_RTreeRectVolume(struct Rect *R)
+{
+ register struct Rect *r = R;
+ register int i;
+ register RectReal volume = (RectReal)1;
+
+ assert(r);
+ if (Undefined(r))
+ return (RectReal)0;
+
+ for(i=0; i<NUMDIMS; i++)
+ volume *= r->boundary[i+NUMDIMS] - r->boundary[i];
+ assert(volume >= 0.0);
+ return volume;
+}
+
+
+/*-----------------------------------------------------------------------------
+| Define the NUMDIMS-dimensional volume the unit sphere in that dimension into
+| the symbol "Xastir_UnitSphereVolume"
+| Note that if the gamma function is available in the math library and if the
+| compiler supports static initialization using functions, this is
+| easily computed for any dimension. If not, the value can be precomputed and
+| taken from a table. The following code can do it either way.
+-----------------------------------------------------------------------------*/
+
+#ifdef gamma
+
+/* computes the volume of an N-dimensional sphere. */
+/* derived from formule in "Regular Polytopes" by H.S.M Coxeter */
+static double sphere_volume(double dimension)
+{
+ static const double log_pi = log(3.1415926535);
+ double log_gamma, log_volume;
+ log_gamma = gamma(dimension/2.0 + 1);
+ log_volume = dimension/2.0 * log_pi - log_gamma;
+ return exp(log_volume);
+}
+static const double Xastir_UnitSphereVolume = sphere_volume(NUMDIMS);
+
+#else
+
+/* Precomputed volumes of the unit spheres for the first few dimensions */
+const double Xastir_UnitSphereVolumes[] = {
+ 0.000000, /* dimension 0 */
+ 2.000000, /* dimension 1 */
+ 3.141593, /* dimension 2 */
+ 4.188790, /* dimension 3 */
+ 4.934802, /* dimension 4 */
+ 5.263789, /* dimension 5 */
+ 5.167713, /* dimension 6 */
+ 4.724766, /* dimension 7 */
+ 4.058712, /* dimension 8 */
+ 3.298509, /* dimension 9 */
+ 2.550164, /* dimension 10 */
+ 1.884104, /* dimension 11 */
+ 1.335263, /* dimension 12 */
+ 0.910629, /* dimension 13 */
+ 0.599265, /* dimension 14 */
+ 0.381443, /* dimension 15 */
+ 0.235331, /* dimension 16 */
+ 0.140981, /* dimension 17 */
+ 0.082146, /* dimension 18 */
+ 0.046622, /* dimension 19 */
+ 0.025807, /* dimension 20 */
+};
+#if NUMDIMS > 20
+# error "not enough precomputed sphere volumes"
+#endif
+#define Xastir_UnitSphereVolume Xastir_UnitSphereVolumes[NUMDIMS]
+
+#endif
+
+
+/*-----------------------------------------------------------------------------
+| Calculate the n-dimensional volume of the bounding sphere of a rectangle
+-----------------------------------------------------------------------------*/
+
+#if 0
+/*
+ * A fast approximation to the volume of the bounding sphere for the
+ * given Rect. By Paul B.
+ */
+RectReal Xastir_RTreeRectSphericalVolume(struct Rect *R)
+{
+ register struct Rect *r = R;
+ register int i;
+ RectReal maxsize=(RectReal)0, c_size;
+
+ assert(r);
+ if (Undefined(r))
+ return (RectReal)0;
+ for (i=0; i<NUMDIMS; i++) {
+ c_size = r->boundary[i+NUMDIMS] - r->boundary[i];
+ if (c_size > maxsize)
+ maxsize = c_size;
+ }
+ return (RectReal)(pow(maxsize/2, NUMDIMS) * Xastir_UnitSphereVolume);
+}
+#endif
+
+/*
+ * The exact volume of the bounding sphere for the given Rect.
+ */
+RectReal Xastir_RTreeRectSphericalVolume(struct Rect *R)
+{
+ register struct Rect *r = R;
+ register int i;
+ register double sum_of_squares=0, radius;
+
+ assert(r);
+ if (Undefined(r))
+ return (RectReal)0;
+ for (i=0; i<NUMDIMS; i++) {
+ double half_extent =
+ (r->boundary[i+NUMDIMS] - r->boundary[i]) / 2;
+ sum_of_squares += half_extent * half_extent;
+ }
+ radius = sqrt(sum_of_squares);
+ return (RectReal)(pow(radius, NUMDIMS) * Xastir_UnitSphereVolume);
+}
+
+
+/*-----------------------------------------------------------------------------
+| Calculate the n-dimensional surface area of a rectangle
+-----------------------------------------------------------------------------*/
+RectReal Xastir_RTreeRectSurfaceArea(struct Rect *R)
+{
+ register struct Rect *r = R;
+ register int i, j;
+ register RectReal sum = (RectReal)0;
+
+ assert(r);
+ if (Undefined(r))
+ return (RectReal)0;
+
+ for (i=0; i<NUMDIMS; i++) {
+ RectReal face_area = (RectReal)1;
+ for (j=0; j<NUMDIMS; j++)
+ /* exclude i extent from product in this dimension */
+ if(i != j) {
+ RectReal j_extent =
+ r->boundary[j+NUMDIMS] - r->boundary[j];
+ face_area *= j_extent;
+ }
+ sum += face_area;
+ }
+ return 2 * sum;
+}
+
+
+
+/*-----------------------------------------------------------------------------
+| Combine two rectangles, make one that includes both.
+-----------------------------------------------------------------------------*/
+struct Rect Xastir_RTreeCombineRect(struct Rect *R, struct Rect *Rr)
+{
+ register struct Rect *r = R, *rr = Rr;
+ register int i, j;
+ struct Rect new_rect;
+ assert(r && rr);
+
+ if (Undefined(r))
+ return *rr;
+
+ if (Undefined(rr))
+ return *r;
+
+ for (i = 0; i < NUMDIMS; i++)
+ {
+ new_rect.boundary[i] = MIN(r->boundary[i], rr->boundary[i]);
+ j = i + NUMDIMS;
+ new_rect.boundary[j] = MAX(r->boundary[j], rr->boundary[j]);
+ }
+ return new_rect;
+}
+
+
+/*-----------------------------------------------------------------------------
+| Decide whether two rectangles overlap.
+-----------------------------------------------------------------------------*/
+int Xastir_RTreeOverlap(struct Rect *R, struct Rect *S)
+{
+ register struct Rect *r = R, *s = S;
+ register int i, j;
+ assert(r && s);
+
+ for (i=0; i<NUMDIMS; i++)
+ {
+ j = i + NUMDIMS; /* index for high sides */
+ if (r->boundary[i] > s->boundary[j] ||
+ s->boundary[i] > r->boundary[j])
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+
+/*-----------------------------------------------------------------------------
+| Decide whether rectangle r is contained in rectangle s.
+-----------------------------------------------------------------------------*/
+int Xastir_RTreeContained(struct Rect *R, struct Rect *S)
+{
+ register struct Rect *r = R, *s = S;
+ register int i, j, result;
+ assert(r && s);
+
+ // undefined rect is contained in any other
+ //
+ if (Undefined(r))
+ return TRUE;
+
+ // no rect (except an undefined one) is contained in an undef rect
+ //
+ if (Undefined(s))
+ return FALSE;
+
+ result = TRUE;
+ for (i = 0; i < NUMDIMS; i++)
+ {
+ j = i + NUMDIMS; /* index for high sides */
+ result = result
+ && r->boundary[i] >= s->boundary[i]
+ && r->boundary[j] <= s->boundary[j];
+ }
+ return result;
+}
diff --git a/src/rtree/split_l.c b/src/rtree/split_l.c
new file mode 100644
index 0000000..8246faf
--- /dev/null
+++ b/src/rtree/split_l.c
@@ -0,0 +1,408 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: split_l.c,v 1.12 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+/****************************************************************************
+ * MODULE: R-Tree library
+ *
+ * AUTHOR(S): Antonin Guttman - original code
+ * Melinda Green (melinda at superliminal.com) - major clean-up
+ * and implementation of bounding spheres
+ *
+ * PURPOSE: Multidimensional index
+ *
+ */
+
+#include <stdio.h>
+#include "assert.h"
+#include "index.h"
+#include "card.h"
+#include "split_l.h"
+
+
+/*-----------------------------------------------------------------------------
+| Load branch buffer with branches from full node plus the extra branch.
+-----------------------------------------------------------------------------*/
+static void Xastir_RTreeGetBranches(struct Node *N, struct Branch *B)
+{
+ register struct Node *n = N;
+ register struct Branch *b = B;
+ register int i;
+
+ assert(n);
+ assert(b);
+
+ /* load the branch buffer */
+ for (i=0; i<MAXKIDS(n); i++)
+ {
+ assert(n->branch[i].child); /* every entry should be full */
+ Xastir_BranchBuf[i] = n->branch[i];
+ }
+ Xastir_BranchBuf[MAXKIDS(n)] = *b;
+ Xastir_BranchCount = MAXKIDS(n) + 1;
+
+ /* calculate rect containing all in the set */
+ Xastir_CoverSplit = Xastir_BranchBuf[0].rect;
+ for (i=1; i<MAXKIDS(n)+1; i++)
+ {
+ Xastir_CoverSplit = Xastir_RTreeCombineRect(&Xastir_CoverSplit, &Xastir_BranchBuf[i].rect);
+ }
+
+ Xastir_RTreeInitNode(n);
+}
+
+
+
+/*-----------------------------------------------------------------------------
+| Initialize a PartitionVars structure.
+-----------------------------------------------------------------------------*/
+static void Xastir_RTreeInitPVars(struct PartitionVars *P, int maxrects, int minfill)
+{
+ register struct PartitionVars *p = P;
+ register int i;
+ assert(p);
+
+ p->count[0] = p->count[1] = 0;
+ p->total = maxrects;
+ p->minfill = minfill;
+ for (i=0; i<maxrects; i++)
+ {
+ p->taken[i] = FALSE;
+ p->partition[i] = -1;
+ }
+}
+
+
+
+/*-----------------------------------------------------------------------------
+| Put a branch in one of the groups.
+-----------------------------------------------------------------------------*/
+static void Xastir_RTreeClassify(int i, int group, struct PartitionVars *p)
+{
+ assert(p);
+ assert(!p->taken[i]);
+
+ p->partition[i] = group;
+ p->taken[i] = TRUE;
+
+ if (p->count[group] == 0)
+ p->cover[group] = Xastir_BranchBuf[i].rect;
+ else
+ p->cover[group] = Xastir_RTreeCombineRect(&Xastir_BranchBuf[i].rect,
+ &p->cover[group]);
+ p->area[group] = Xastir_RTreeRectSphericalVolume(&p->cover[group]);
+ p->count[group]++;
+}
+
+
+
+/*-----------------------------------------------------------------------------
+| Pick two rects from set to be the first elements of the two groups.
+| Pick the two that are separated most along any dimension, or overlap least.
+| Distance for separation or overlap is measured modulo the width of the
+| space covered by the entire set along that dimension.
+-----------------------------------------------------------------------------*/
+static void Xastir_RTreePickSeeds(struct PartitionVars *P)
+{
+ register struct PartitionVars *p = P;
+ register int i, dim, high;
+ register struct Rect *r, *rlow, *rhigh;
+ // Original superliminal.com implementation had no initializers here.
+ // They are not strictly necessary, as the variables are initialized
+ // in the first iteration of the first for loop, but GCC complains
+ // anyway. Initializers added to keep it happy.
+ register float w, separation, bestSep=0.0;
+ RectReal width[NUMDIMS];
+ int leastUpper[NUMDIMS], greatestLower[NUMDIMS];
+ int seed0=0, seed1=0;
+ assert(p);
+
+ for (dim=0; dim<NUMDIMS; dim++)
+ {
+ high = dim + NUMDIMS;
+
+ /* find the rectangles farthest out in each direction
+ * along this dimens */
+ greatestLower[dim] = leastUpper[dim] = 0;
+ for (i=1; i<Xastir_NODECARD+1; i++)
+ {
+ r = &Xastir_BranchBuf[i].rect;
+ if (r->boundary[dim] >
+ Xastir_BranchBuf[greatestLower[dim]].rect.boundary[dim])
+ {
+ greatestLower[dim] = i;
+ }
+ if (r->boundary[high] <
+ Xastir_BranchBuf[leastUpper[dim]].rect.boundary[high])
+ {
+ leastUpper[dim] = i;
+ }
+ }
+
+ /* find width of the whole collection along this dimension */
+ width[dim] = Xastir_CoverSplit.boundary[high] -
+ Xastir_CoverSplit.boundary[dim];
+ }
+
+ /* pick the best separation dimension and the two seed rects */
+ for (dim=0; dim<NUMDIMS; dim++)
+ {
+ high = dim + NUMDIMS;
+
+ /* divisor for normalizing by width */
+ assert(width[dim] >= 0);
+ if (width[dim] == 0)
+ w = (RectReal)1;
+ else
+ w = width[dim];
+
+ rlow = &Xastir_BranchBuf[leastUpper[dim]].rect;
+ rhigh = &Xastir_BranchBuf[greatestLower[dim]].rect;
+ if (dim == 0)
+ {
+ seed0 = leastUpper[0];
+ seed1 = greatestLower[0];
+ separation = bestSep =
+ (rhigh->boundary[0] -
+ rlow->boundary[NUMDIMS]) / w;
+ }
+ else
+ {
+ separation =
+ (rhigh->boundary[dim] -
+ rlow->boundary[dim+NUMDIMS]) / w;
+ if (separation > bestSep)
+ {
+ seed0 = leastUpper[dim];
+ seed1 = greatestLower[dim];
+ bestSep = separation;
+ }
+ }
+ }
+
+ if (seed0 != seed1)
+ {
+ Xastir_RTreeClassify(seed0, 0, p);
+ Xastir_RTreeClassify(seed1, 1, p);
+ }
+}
+
+
+
+/*-----------------------------------------------------------------------------
+| Put each rect that is not already in a group into a group.
+| Process one rect at a time, using the following hierarchy of criteria.
+| In case of a tie, go to the next test.
+| 1) If one group already has the max number of elements that will allow
+| the minimum fill for the other group, put r in the other.
+| 2) Put r in the group whose cover will expand less. This automatically
+| takes care of the case where one group cover contains r.
+| 3) Put r in the group whose cover will be smaller. This takes care of the
+| case where r is contained in both covers.
+| 4) Put r in the group with fewer elements.
+| 5) Put in group 1 (arbitrary).
+|
+| Also update the covers for both groups.
+-----------------------------------------------------------------------------*/
+static void Xastir_RTreePigeonhole(struct PartitionVars *P)
+{
+ register struct PartitionVars *p = P;
+ struct Rect newCover[2];
+ register int i, group;
+ RectReal newArea[2], increase[2];
+
+ for (i=0; i<Xastir_NODECARD+1; i++)
+ {
+ if (!p->taken[i])
+ {
+ /* if one group too full, put rect in the other */
+ if (p->count[0] >= p->total - p->minfill)
+ {
+ Xastir_RTreeClassify(i, 1, p);
+ continue;
+ }
+ else if (p->count[1] >= p->total - p->minfill)
+ {
+ Xastir_RTreeClassify(i, 0, p);
+ continue;
+ }
+
+ /* find areas of the two groups' old and new covers */
+ for (group=0; group<2; group++)
+ {
+ if (p->count[group]>0)
+ newCover[group] = Xastir_RTreeCombineRect(
+ &Xastir_BranchBuf[i].rect,
+ &p->cover[group]);
+ else
+ newCover[group] = Xastir_BranchBuf[i].rect;
+ newArea[group] = Xastir_RTreeRectSphericalVolume(
+ &newCover[group]);
+ increase[group] = newArea[group]-p->area[group];
+ }
+
+ /* put rect in group whose cover will expand less */
+ if (increase[0] < increase[1])
+ Xastir_RTreeClassify(i, 0, p);
+ else if (increase[1] < increase[0])
+ Xastir_RTreeClassify(i, 1, p);
+
+ /* put rect in group that will have a smaller cover */
+ else if (p->area[0] < p->area[1])
+ Xastir_RTreeClassify(i, 0, p);
+ else if (p->area[1] < p->area[0])
+ Xastir_RTreeClassify(i, 1, p);
+
+ /* put rect in group with fewer elements */
+ else if (p->count[0] < p->count[1])
+ Xastir_RTreeClassify(i, 0, p);
+ else
+ Xastir_RTreeClassify(i, 1, p);
+ }
+ }
+ assert(p->count[0] + p->count[1] == Xastir_NODECARD + 1);
+}
+
+
+
+/*-----------------------------------------------------------------------------
+| Method 0 for finding a partition:
+| First find two seeds, one for each group, well separated.
+| Then put other rects in whichever group will be smallest after addition.
+-----------------------------------------------------------------------------*/
+static void Xastir_RTreeMethodZero(struct PartitionVars *p, int minfill)
+{
+ Xastir_RTreeInitPVars(p, Xastir_BranchCount, minfill);
+ Xastir_RTreePickSeeds(p);
+ Xastir_RTreePigeonhole(p);
+}
+
+
+
+
+/*-----------------------------------------------------------------------------
+| Copy branches from the buffer into two nodes according to the partition.
+-----------------------------------------------------------------------------*/
+static void Xastir_RTreeLoadNodes(struct Node *N, struct Node *Q,
+ struct PartitionVars *P)
+{
+ register struct Node *n = N, *q = Q;
+ register struct PartitionVars *p = P;
+ register int i;
+ assert(n);
+ assert(q);
+ assert(p);
+
+ for (i=0; i<Xastir_NODECARD+1; i++)
+ {
+ if (p->partition[i] == 0)
+ Xastir_RTreeAddBranch(&Xastir_BranchBuf[i], n, NULL);
+ else if (p->partition[i] == 1)
+ Xastir_RTreeAddBranch(&Xastir_BranchBuf[i], q, NULL);
+ else
+ assert(FALSE);
+ }
+}
+
+
+
+/*-----------------------------------------------------------------------------
+| Split a node.
+| Divides the nodes branches and the extra one between two nodes.
+| Old node is one of the new ones, and one really new one is created.
+-----------------------------------------------------------------------------*/
+void Xastir_RTreeSplitNode(struct Node *n, struct Branch *b, struct Node **nn)
+{
+ register struct PartitionVars *p;
+ register int level;
+ RectReal area;
+
+ assert(n);
+ assert(b);
+
+ /* load all the branches into a buffer, initialize old node */
+ level = n->level;
+ Xastir_RTreeGetBranches(n, b);
+
+ /* find partition */
+ p = &Xastir_Partitions[0];
+
+ /* Note: can't use MINFILL(n) below since n was cleared by GetBranches() */
+ Xastir_RTreeMethodZero(p, level>0 ? MinNodeFill : MinLeafFill);
+
+ /* record how good the split was for statistics */
+ area = p->area[0] + p->area[1];
+
+ /* put branches from buffer in 2 nodes according to chosen partition */
+ *nn = Xastir_RTreeNewNode();
+ (*nn)->level = n->level = level;
+ Xastir_RTreeLoadNodes(n, *nn, p);
+ assert(n->count + (*nn)->count == Xastir_NODECARD+1);
+}
+
+
+
+/*-----------------------------------------------------------------------------
+| Print out data for a partition from PartitionVars struct.
+-----------------------------------------------------------------------------*/
+
+// This is not used at the moment, and because it's declared static gcc
+// warns us it's not used. Commented out to shut gcc up
+#if 0
+static void Xastir_RTreePrintPVars(struct PartitionVars *p)
+{
+ int i;
+ assert(p);
+
+ printf("\npartition:\n");
+ for (i=0; i<Xastir_NODECARD+1; i++)
+ {
+ printf("%3d\t", i);
+ }
+ printf("\n");
+ for (i=0; i<Xastir_NODECARD+1; i++)
+ {
+ if (p->taken[i])
+ printf(" t\t");
+ else
+ printf("\t");
+ }
+ printf("\n");
+ for (i=0; i<Xastir_NODECARD+1; i++)
+ {
+ printf("%3d\t", p->partition[i]);
+ }
+ printf("\n");
+
+ printf("count[0] = %d area = %f\n", p->count[0], p->area[0]);
+ printf("count[1] = %d area = %f\n", p->count[1], p->area[1]);
+ printf("total area = %f effectiveness = %3.2f\n",
+ p->area[0] + p->area[1],
+ Xastir_RTreeRectSphericalVolume(&Xastir_CoverSplit)/(p->area[0]+p->area[1]));
+
+ printf("cover[0]:\n");
+ Xastir_RTreePrintRect(&p->cover[0], 0);
+
+ printf("cover[1]:\n");
+ Xastir_RTreePrintRect(&p->cover[1], 0);
+}
+#endif // shut up GCC
diff --git a/src/rtree/split_l.h b/src/rtree/split_l.h
new file mode 100644
index 0000000..b3c7a75
--- /dev/null
+++ b/src/rtree/split_l.h
@@ -0,0 +1,54 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: split_l.h,v 1.11 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+/****************************************************************************
+ * MODULE: R-Tree library
+ *
+ * AUTHOR(S): Antonin Guttman - original code
+ * Melinda Green (melinda at superliminal.com) - major clean-up
+ * and implementation of bounding spheres
+ *
+ * PURPOSE: Multidimensional index
+ *
+ */
+
+/*-----------------------------------------------------------------------------
+| Definitions and global variables used in linear split code.
+-----------------------------------------------------------------------------*/
+
+#define METHODS 1
+
+struct Branch Xastir_BranchBuf[MAXCARD+1];
+int Xastir_BranchCount;
+struct Rect Xastir_CoverSplit;
+
+/* variables for finding a partition */
+struct PartitionVars
+{
+ int partition[MAXCARD+1];
+ int total, minfill;
+ int taken[MAXCARD+1];
+ int count[2];
+ struct Rect cover[2];
+ RectReal area[2];
+} Xastir_Partitions[METHODS];
diff --git a/src/shapelib/ChangeLog b/src/shapelib/ChangeLog
new file mode 100644
index 0000000..0675b70
--- /dev/null
+++ b/src/shapelib/ChangeLog
@@ -0,0 +1,204 @@
+2003-04-07 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Issue 1.2.10 Release.
+
+2003-03-10 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c: modified DBFWriteAttribute call so that it returns FALSE
+ if it has to truncate the input value.
+
+2003-01-28 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shptree.c: avoid build warnings.
+
+2002-05-07 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c: Added DBFWriteAttributeDirectly() from the AVCE00
+ distribution to simplify AVC integration in GDAL.
+
+ * shptree.c: added use of qsort() in place of bubble sort as
+ submitted by Bernhard Herzog.
+
+2002-04-10 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c: Added SHPRewindObject() to correct ring winding.
+
+ * shprewind.c: New utility program.
+
+2002-03-12 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shapelib.def: added DBFWriteNULLAttribute.
+
+2002-01-17 Frank Warmerdam <warmerdam at pobox.com>
+
+ * contrib/ShapeFileII.pas: Contributed Delphi Pascal interface
+ to Shapelib.
+
+2002-01-15 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shapelib.h: Added support for SHAPELIB_DLLEXPORT macro, and write
+ up material attempting to explain the use of SHPAPI_CALL macros.
+
+ * dbfopen.c: Compute nHeaderLength in DBFCloneEmpty() instead of
+ copying it from the source file so we don't have quirks when copying
+ from files with extra bytes of spacers in the header that don't
+ themselves get copied properly.
+
+2001-12-07 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c: Fix fclose() of SHX file if SHX file fails to open.
+ Should be closing SHP file. Reported by Ben Discoe.
+
+2001-11-28 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c: two fixes for compiler warnings as suggested by
+ Richard Hash.
+
+2001-11-01 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c/shapefil.h: Move record buffer into SHPInfo so that
+ different threads can safely access separate files. Other threading
+ issues may remain.
+
+2001-08-28 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Issue Shapelib 1.2.9
+
+ * shputils.c: DBFAddField() call should check for -1 return value
+ for failure.
+
+2001-07-03 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c: cleanup better if SHX missing, provided by
+ Riccardo Cohen.
+
+2001-06-21 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c: Fixed NULL support with patches from Jim Matthews.
+
+ * shpopen.c: Be more careful of establishing initial file bounds in
+ face of possible NULL shapes.
+
+2001-06-01 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c: ensure binary mode open.
+
+2001-05-31 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c: Add support for writing null shapes.
+
+ * dbfopen.c: added DBFGetFieldIndex(), contributed by Jim Matthews.
+
+ * dbfopen.c/shapefil.h/dbf_api.h: added support for NULL fields
+ in .dbf files.
+
+2001-05-28 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c: add some checking on the record count to ensure it
+ is reasonable.
+
+2001-05-23 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shapefile.h, shpopen.c, dbfopen.c, shptree.c: added the SHPAPI_CALL
+ macro to allow compilation with _stdcall conventions.
+
+2001-02-06 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Fixed a few memory leaks when SHPOpen() fails.
+
+2000-12-05 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Fix from Craig Bruce (Cubewerx) for DBFReadAttribute() for
+ the white space trimming code to avoid reading outside allocated
+ memory.
+
+2000-11-02 Frank Warmerdam <warmerda at cs46980-c>
+
+ * Checked in upgraded shputils.c from Bill Miller.
+
+2000-10-05 Frank Warmerdam <warmerda at cs46980-c>
+
+ * Fixed DBFWriteAttribute() to ensure we can't overwrite the
+ end of the szSField buffer even if the width is set large.
+ Bug report by Kirk Benell <kirk at rsinc.com>.
+
+2000-09-25 Frank Warmerdam <warmerda at cs46980-c>
+
+ * Added DBFGetNativeFieldType() (contributed by Daniel) to dbfopen.c.
+
+2000-07-18 Frank Warmerdam <warmerda at cs46980-c>
+
+ * added better enforcement of -1 for append in SHPWriteObject().
+
+2000-07-07 Frank Warmerdam <warmerda at cs46980-c>
+
+ * Added stdlib.h and string.h where needed, and removed lots of
+ unused variables, mainly from example mainlines at the suggestion
+ of Bill Hughes.
+
+2000-05-24 Frank Warmerdam <warmerda at cs46980-c>
+
+ * Added logic to shpadd to grow vertex lists at the suggestion of
+ Santiago Nullo <sn at softhome.net>.
+
+2000-05-23 Frank Warmerdam <warmerda at cs46980-c>
+
+ * Added checks in dbfopen.c on return result of fseek() and fread().
+
+ * Avoid crashing in DBReadIntegerAttribute() or DBFReadDoubleAttribte()
+ if the field or record are out of range.
+
+2000-03-28 Frank Warmerdam <warmerda at cs46980-c>
+
+ * Release as 1.2.8.
+
+ * Incorporated a -version-info fix and added mkinstalldirs from Jan.
+
+2000-03-17 Frank Warmerdam <warmerda at cs46980-c>
+
+ * Added shared library hack to Makefile.
+
+ * Fixed up test scripts to look in ./ for executables.
+
+Wed Feb 16 11:20:29 2000 Frank Warmerdam <warmerda at gdal.velocet.ca>
+
+ * Release 1.2.7.
+
+ * Modified SHPReadObject() so that will return NULL (type 0) shapes
+ in a sort of sensible way.
+
+Wed Dec 15 08:49:53 1999 Frank Warmerdam <warmerda at gdal.velocet.ca>
+
+ * Fixed record size written at beginning of records in .shp
+ file. It was 4 bytes to long (thanks to Mikko Syrja of 3D-system Oy)
+
+ * Use atof() instead of sscanf() in dbfopen.c, and add stdlib.h.
+
+Mon Dec 13 12:29:01 1999 Frank Warmerdam <warmerda at gdal.velocet.ca>
+
+ * Added support for uppercase .DBF extention c/o
+ Dennis Christopher <dennis at avenza.com>
+
+Fri Nov 5 09:12:31 1999 Frank Warmerdam <warmerda at gdal.velocet.ca>
+
+ * Updated license headers to include the option of use of the code
+ under the LGPL.
+
+1999-09-15 <warmerda at CS46980-B>
+
+ * Added shapelib.dll target to makefile.vc.
+
+Mon May 10 23:19:42 1999 Frank Warmerdam <warmerda at gdal.velocet.ca>
+
+ * Added candrsn's improvements to extension handling in dbfopen.c
+
+ * Added ``raw tuple'' api to dbfopen.c, still not in dbf_api.html.
+ From candrsn.
+
+
+Tue May 4 11:04:31 1999 Frank Warmerdam <warmerda at gdal.velocet.ca>
+
+ * Prepare 1.2.5 release.
+
+ * Added support for 'F' fields.
+
diff --git a/src/shapelib/LICENSE.LGPL b/src/shapelib/LICENSE.LGPL
new file mode 100644
index 0000000..0b643ac
--- /dev/null
+++ b/src/shapelib/LICENSE.LGPL
@@ -0,0 +1,483 @@
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
diff --git a/src/shapelib/Makefile.am b/src/shapelib/Makefile.am
new file mode 100644
index 0000000..2d41535
--- /dev/null
+++ b/src/shapelib/Makefile.am
@@ -0,0 +1,42 @@
+
+# $Id: Makefile.am,v 1.16 2012/11/01 18:57:19 we7u Exp $
+# Copyright (C) 2004-2012 The Xastir Group
+
+noinst_LIBRARIES=libshape.a
+
+noinst_PROGRAMS=dbfadd \
+ dbfcreate \
+ dbfdump \
+ shpadd \
+ shpcreate \
+ shpdump \
+ shprewind \
+ shptest \
+ shptreedump \
+ shputils
+
+libshape_a_SOURCES=shpopen.c \
+ shptree.c \
+ dbfopen.c \
+ shapefil.h
+
+dbfadd_LDADD=libshape.a
+dbfcreate_LDADD=libshape.a
+dbfdump_LDADD=libshape.a
+shpadd_LDADD=libshape.a
+shpcreate_LDADD=libshape.a
+shpdump_LDADD=libshape.a
+shprewind_LDADD=libshape.a
+shptest_LDADD=libshape.a
+shptreedump_LDADD=libshape.a
+shputils_LDADD=libshape.a
+
+EXTRA_DIST=ChangeLog LICENSE.LGPL README README.tree dbf_api.html \
+ dbfadd.c dbfcreate.c dbfdump.c libtool makefile.vc makeshape.sh \
+ mkinstalldirs shapelib.def shapelib.html shp_api.html \
+ shpadd.c shpcreate.c shpdump.c shprewind.c shptest.c shptreedump.c \
+ shputils.c stream1.out stream1.sh stream2.out stream2.sh stream3.out
+DIST_SUBDIRS=contrib
+SUBDIRS=contrib
+
+
diff --git a/src/shapelib/Makefile.in b/src/shapelib/Makefile.in
new file mode 100644
index 0000000..55189f1
--- /dev/null
+++ b/src/shapelib/Makefile.in
@@ -0,0 +1,724 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+# $Id: Makefile.am,v 1.16 2012/11/01 18:57:19 we7u Exp $
+# Copyright (C) 2004-2012 The Xastir Group
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = dbfadd$(EXEEXT) dbfcreate$(EXEEXT) dbfdump$(EXEEXT) \
+ shpadd$(EXEEXT) shpcreate$(EXEEXT) shpdump$(EXEEXT) \
+ shprewind$(EXEEXT) shptest$(EXEEXT) shptreedump$(EXEEXT) \
+ shputils$(EXEEXT)
+subdir = src/shapelib
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ ChangeLog mkinstalldirs
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libshape_a_AR = $(AR) $(ARFLAGS)
+libshape_a_LIBADD =
+am_libshape_a_OBJECTS = shpopen.$(OBJEXT) shptree.$(OBJEXT) \
+ dbfopen.$(OBJEXT)
+libshape_a_OBJECTS = $(am_libshape_a_OBJECTS)
+PROGRAMS = $(noinst_PROGRAMS)
+dbfadd_SOURCES = dbfadd.c
+dbfadd_OBJECTS = dbfadd.$(OBJEXT)
+dbfadd_DEPENDENCIES = libshape.a
+dbfcreate_SOURCES = dbfcreate.c
+dbfcreate_OBJECTS = dbfcreate.$(OBJEXT)
+dbfcreate_DEPENDENCIES = libshape.a
+dbfdump_SOURCES = dbfdump.c
+dbfdump_OBJECTS = dbfdump.$(OBJEXT)
+dbfdump_DEPENDENCIES = libshape.a
+shpadd_SOURCES = shpadd.c
+shpadd_OBJECTS = shpadd.$(OBJEXT)
+shpadd_DEPENDENCIES = libshape.a
+shpcreate_SOURCES = shpcreate.c
+shpcreate_OBJECTS = shpcreate.$(OBJEXT)
+shpcreate_DEPENDENCIES = libshape.a
+shpdump_SOURCES = shpdump.c
+shpdump_OBJECTS = shpdump.$(OBJEXT)
+shpdump_DEPENDENCIES = libshape.a
+shprewind_SOURCES = shprewind.c
+shprewind_OBJECTS = shprewind.$(OBJEXT)
+shprewind_DEPENDENCIES = libshape.a
+shptest_SOURCES = shptest.c
+shptest_OBJECTS = shptest.$(OBJEXT)
+shptest_DEPENDENCIES = libshape.a
+shptreedump_SOURCES = shptreedump.c
+shptreedump_OBJECTS = shptreedump.$(OBJEXT)
+shptreedump_DEPENDENCIES = libshape.a
+shputils_SOURCES = shputils.c
+shputils_OBJECTS = shputils.$(OBJEXT)
+shputils_DEPENDENCIES = libshape.a
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libshape_a_SOURCES) dbfadd.c dbfcreate.c dbfdump.c \
+ shpadd.c shpcreate.c shpdump.c shprewind.c shptest.c \
+ shptreedump.c shputils.c
+DIST_SOURCES = $(libshape_a_SOURCES) dbfadd.c dbfcreate.c dbfdump.c \
+ shpadd.c shpcreate.c shpdump.c shprewind.c shptest.c \
+ shptreedump.c shputils.c
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTSHP = @CONTSHP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GMAGIC_BIN = @GMAGIC_BIN@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBCOMPAT = @LIBCOMPAT@
+LIBOBJS = @LIBOBJS@
+LIBRTREE = @LIBRTREE@
+LIBS = @LIBS@
+LIBSHP = @LIBSHP@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LWPOSTGIS = @LWPOSTGIS@
+MAGIC_BIN = @MAGIC_BIN@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PG_CONFIG = @PG_CONFIG@
+POW_LIB = @POW_LIB@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUBRTREE = @SUBRTREE@
+SUBSHP = @SUBSHP@
+VERSION = @VERSION@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+convert = @convert@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+festival = @festival@
+found_gdal_config = @found_gdal_config@
+gm = @gm@
+gpsman = @gpsman@
+gv = @gv@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lpr = @lpr@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+mv = @mv@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sed = @sed@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+wget = @wget@
+xfontsel = @xfontsel@
+noinst_LIBRARIES = libshape.a
+libshape_a_SOURCES = shpopen.c \
+ shptree.c \
+ dbfopen.c \
+ shapefil.h
+
+dbfadd_LDADD = libshape.a
+dbfcreate_LDADD = libshape.a
+dbfdump_LDADD = libshape.a
+shpadd_LDADD = libshape.a
+shpcreate_LDADD = libshape.a
+shpdump_LDADD = libshape.a
+shprewind_LDADD = libshape.a
+shptest_LDADD = libshape.a
+shptreedump_LDADD = libshape.a
+shputils_LDADD = libshape.a
+EXTRA_DIST = ChangeLog LICENSE.LGPL README README.tree dbf_api.html \
+ dbfadd.c dbfcreate.c dbfdump.c libtool makefile.vc makeshape.sh \
+ mkinstalldirs shapelib.def shapelib.html shp_api.html \
+ shpadd.c shpcreate.c shpdump.c shprewind.c shptest.c shptreedump.c \
+ shputils.c stream1.out stream1.sh stream2.out stream2.sh stream3.out
+
+DIST_SUBDIRS = contrib
+SUBDIRS = contrib
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/shapelib/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/shapelib/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libshape.a: $(libshape_a_OBJECTS) $(libshape_a_DEPENDENCIES)
+ -rm -f libshape.a
+ $(libshape_a_AR) libshape.a $(libshape_a_OBJECTS) $(libshape_a_LIBADD)
+ $(RANLIB) libshape.a
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+dbfadd$(EXEEXT): $(dbfadd_OBJECTS) $(dbfadd_DEPENDENCIES)
+ @rm -f dbfadd$(EXEEXT)
+ $(LINK) $(dbfadd_OBJECTS) $(dbfadd_LDADD) $(LIBS)
+dbfcreate$(EXEEXT): $(dbfcreate_OBJECTS) $(dbfcreate_DEPENDENCIES)
+ @rm -f dbfcreate$(EXEEXT)
+ $(LINK) $(dbfcreate_OBJECTS) $(dbfcreate_LDADD) $(LIBS)
+dbfdump$(EXEEXT): $(dbfdump_OBJECTS) $(dbfdump_DEPENDENCIES)
+ @rm -f dbfdump$(EXEEXT)
+ $(LINK) $(dbfdump_OBJECTS) $(dbfdump_LDADD) $(LIBS)
+shpadd$(EXEEXT): $(shpadd_OBJECTS) $(shpadd_DEPENDENCIES)
+ @rm -f shpadd$(EXEEXT)
+ $(LINK) $(shpadd_OBJECTS) $(shpadd_LDADD) $(LIBS)
+shpcreate$(EXEEXT): $(shpcreate_OBJECTS) $(shpcreate_DEPENDENCIES)
+ @rm -f shpcreate$(EXEEXT)
+ $(LINK) $(shpcreate_OBJECTS) $(shpcreate_LDADD) $(LIBS)
+shpdump$(EXEEXT): $(shpdump_OBJECTS) $(shpdump_DEPENDENCIES)
+ @rm -f shpdump$(EXEEXT)
+ $(LINK) $(shpdump_OBJECTS) $(shpdump_LDADD) $(LIBS)
+shprewind$(EXEEXT): $(shprewind_OBJECTS) $(shprewind_DEPENDENCIES)
+ @rm -f shprewind$(EXEEXT)
+ $(LINK) $(shprewind_OBJECTS) $(shprewind_LDADD) $(LIBS)
+shptest$(EXEEXT): $(shptest_OBJECTS) $(shptest_DEPENDENCIES)
+ @rm -f shptest$(EXEEXT)
+ $(LINK) $(shptest_OBJECTS) $(shptest_LDADD) $(LIBS)
+shptreedump$(EXEEXT): $(shptreedump_OBJECTS) $(shptreedump_DEPENDENCIES)
+ @rm -f shptreedump$(EXEEXT)
+ $(LINK) $(shptreedump_OBJECTS) $(shptreedump_LDADD) $(LIBS)
+shputils$(EXEEXT): $(shputils_OBJECTS) $(shputils_DEPENDENCIES)
+ @rm -f shputils$(EXEEXT)
+ $(LINK) $(shputils_OBJECTS) $(shputils_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/dbfadd.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/dbfcreate.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/dbfdump.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/dbfopen.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shpadd.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shpcreate.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shpdump.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shpopen.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shprewind.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shptest.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shptree.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shptreedump.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shputils.Po at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LIBRARIES) $(PROGRAMS)
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES clean-noinstPROGRAMS ctags \
+ ctags-recursive distclean distclean-compile distclean-generic \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
+ ps ps-am tags tags-recursive uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/shapelib/README b/src/shapelib/README
new file mode 100755
index 0000000..ad5faa3
--- /dev/null
+++ b/src/shapelib/README
@@ -0,0 +1,35 @@
+
+Please read shapelib.html.
+
+Building on Unix
+----------------
+
+1) Edit Makefile, and set CFLAGS, and CC macros as required for the
+ target system. Often the defaults will work fine.
+
+2) "type make"
+
+The result should be:
+
+Core shapelib support.
+ shpopen.o
+ dbfopen.o
+
+Utility/demonstration programs:
+ shpcreate, shpdump, shpadd, dbfcreate, dbfdump, dbfadd
+
+To test type:
+ make test
+
+
+Building on Windows
+-------------------
+
+If you have run the VC++ VCVARS32.BAT, you should be able to type the
+following in a command window to build the code and executables:
+
+C:> nmake /f makefile.vc
+
+Otherwise create your own VC++ project. There aren't many files to deal with
+here!
+
diff --git a/src/shapelib/README.tree b/src/shapelib/README.tree
new file mode 100644
index 0000000..434c648
--- /dev/null
+++ b/src/shapelib/README.tree
@@ -0,0 +1,172 @@
+Venkat,
+
+I have completed the planned Shapefile quadtree mechanism. The additions
+to the traditional Shapelib are found in shptree.c (functions supporting
+quad tree searching and query). There are also some new prototypes for
+the tree stuff in shapefil.h ... including some prototypes for functions
+you don't require and hence that I haven't implemented at this time.
+
+I have also prepared a demonstration program using the API. That is
+the ``shpdumptree'' program, with the source code in shpdumptree.c. The
+shpdumptree program has two functions. One is to dump an ASCII rendering
+of the internal quadtree, and the other is example use of a quad tree
+searching function.
+
+Dumping the Tree
+----------------
+
+The tree dumping is done as shown below. The "-maxdepth" commandline
+switch can be used to control the maximum depth, otherwise it internally
+computes a ``reasonable depth'' to use based on the number of structures
+in the shapefile.
+
+warmerda at gdal[207]% shptreedump -maxdepth 6 eg_data/polygon.shp
+( SHPTreeNode
+ Min = (471127.19,4751545.00)
+ Max = (489292.31,4765610.50)
+ Shapes(0):
+ ( SHPTreeNode
+ Min = (471127.19,4751545.00)
+ Max = (481118.01,4765610.50)
+ Shapes(0):
+ ( SHPTreeNode
+ Min = (471127.19,4751545.00)
+ Max = (481118.01,4759281.03)
+ Shapes(0):
+ ( SHPTreeNode
+ Min = (471127.19,4751545.00)
+ Max = (476622.14,4759281.03)
+ Shapes(0):
+ ( SHPTreeNode
+ Min = (471127.19,4751545.00)
+ Max = (476622.14,4755799.81)
+ Shapes(0):
+ ( SHPTreeNode
+ Min = (471127.19,4751545.00)
+ Max = (474149.41,4755799.81)
+ Shapes(6): 395 397 402 404 405 422
+ )
+ ( SHPTreeNode
+ Min = (473599.92,4751545.00)
+ Max = (476622.14,4755799.81)
+ Shapes(10): 392 394 403 413 414 417 426 433 434 447
+ )
+ )
+...
+
+A structure like the following represents one node in the tree. In
+this case it cover the region of 473599.92 < X < 476622.14,and
+4751545.0 < Y < 4755799.81. There are ten shapes within this region
+who's shapeids are 392, 394 ... 447. This node has no children nodes.
+
+ ( SHPTreeNode
+ Min = (473599.92,4751545.00)
+ Max = (476622.14,4755799.81)
+ Shapes(10): 392 394 403 413 414 417 426 433 434 447
+ )
+
+The heirarchy of indentation is intended to show the parent, child
+relationship between nodes, with the tree being deeper the further to the
+right you go.
+
+The `-v' flag to the program can be used to expand the report to include
+the full information about shapes, not just their shapeid. This can result
+in a report looking more like this:
+
+ ...
+ ( SHPTreeNode
+ Min = (478095.78,4751545.00)
+ Max = (481118.01,4755799.81)
+ Shapes(3):
+ ( Shape
+ ShapeId = 448
+ Min = (479988.09,4753300.00)
+ Max = (480705.59,4754236.50)
+ Vertex[0] = (480136.59,4754174.50)
+ Vertex[1] = (480229.97,4754182.00)
+ Vertex[2] = (480370.09,4754200.50)
+ Vertex[3] = (480695.12,4754236.50)
+ Vertex[4] = (480687.97,4754129.50)
+ Vertex[5] = (480650.47,4754075.50)
+ Vertex[6] = (480520.62,4753948.00)
+ Vertex[7] = (480490.00,4753900.00)
+ Vertex[8] = (480499.78,4753840.50)
+ Vertex[9] = (480500.97,4753820.50)
+ Vertex[10] = (480534.75,4753660.50)
+ Vertex[11] = (480560.00,4753565.00)
+ Vertex[12] = (480574.91,4753550.50)
+ ...
+
+While it is possible to part the output of the shptreedump program, and
+insert it into your database, my intention was that the shptreedump program
+would serve as an example of how to pre-order traversal of the quad tree,
+and collect the information you will need to insert into your database.
+I would then expect you to write a new program based on shptreedump that
+calls a C API for your database to insert objects instead of printing them
+out. Alternatively there may be an ASCII format for loading tables that
+you could modify the program to output.
+
+Searching
+---------
+
+The other thing that you can do with the shptreedump program is to
+perform a search on the quadtree. For instance the following shows
+searching on a small region.
+
+% shptreedump -search 471127 4751545 476622 4759281 eg_data/polygon.shp
+Shape 17: not in area of interest, but fetched.
+Shape 31: not in area of interest, but fetched.
+Shape 52: not in area of interest, but fetched.
+Shape 76: not in area of interest, but fetched.
+Shape 82: not in area of interest, but fetched.
+Shape 104: not in area of interest, but fetched.
+Shape 124: not in area of interest, but fetched.
+Shape 134: not in area of interest, but fetched.
+Shape 139: not in area of interest, but fetched.
+Shape 154: not in area of interest, but fetched.
+Shape 175: not in area of interest, but fetched.
+Shape 177: not in area of interest, but fetched.
+Shape 185: not in area of interest, but fetched.
+Shape 192: not in area of interest, but fetched.
+Shape 196: appears to be in area of interest.
+....
+
+
+I have included this capability (and the SHPTreeFindLikelyShapes() function)
+so that you can see a working example of how to search this quad tree.
+Note that searching is a multi-stage affair.
+
+First a pass is made over the quadtree, collecting the shapeids of all
+shapes contained in a quadtree node for which the bounding rectangle overlaps
+the search rectangle. This is all accomplished by SHPTreeFindLikelyShapes()
+in shptree.c.
+
+The second phase is to fetch the actual shapes, and verify if their bounding
+box falls within the area of interest. This is necessary because the shape
+will tend to have a significantly smaller bounding rectangle than the tree
+node in which it is found. This can result ``false positives'' on the first
+phase search, as indicated by teh ``not in area of interest, but fetched''
+messages above. This stage is done in the SHPTreeNodeSearchAndDump()
+function in shptreedump.c.
+
+A possible third phase is to verify that the actualy line segments in the
+shape actually cross the area of interest. I don't both with this as it
+is complicated, and assuming that the drawing engine takes care of clipping
+it is quite a bit easier to let it fall through.
+
+Building
+--------
+
+I have added a makefile.vc to the shapelib distribution. After you have
+unpacked the shapefile you should have a shapelib subdirectory. If you
+cd to that directory, and enter ``nmake -f makefile.vc'' in a DOS window
+you should be able to build everything with VC++ (assuming it is properly
+installed and in your path).
+
+You can also create a project in VC just including the files
+shpopen.c, shptree.c and shptreedump.c, building as a Win32 console
+application.
+
+For your convenience I am including prebuild .obj files, and .exe files
+in the distribution.
+
diff --git a/src/shapelib/contrib/Makefile.am b/src/shapelib/contrib/Makefile.am
new file mode 100644
index 0000000..efc9635
--- /dev/null
+++ b/src/shapelib/contrib/Makefile.am
@@ -0,0 +1,51 @@
+
+# $Id: Makefile.am,v 1.13 2012/11/01 18:57:19 we7u Exp $
+# C2pyright (C) 2004-2012 The Xastir Group
+
+EXTRA_DIST=Makefile_orig ShapeFileII.pas dbfcat.c dbfinfo.c makefile.vc \
+ my_nan.h shpcat.c shpcentrd.c shpdata.c shpdxf.c shpfix.c \
+ shpgeo.c shpgeo.h shpinfo.c shpproj.c shpwkb.c
+
+noinst_LIBRARIES=libshape.a
+
+noinst_PROGRAMS=dbfcat \
+ dbfinfo \
+ shpcat \
+ shpdxf \
+ shpfix \
+ shpinfo @CONTSHP@
+
+EXTRA_PROGRAMS = shpcentrd shpproj shpdata shpwkb
+libshape_a_SOURCES=../shpopen.c \
+ ../shptree.c \
+ ../dbfopen.c \
+ ../shapefil.h
+
+shpcentrd_SOURCES=shpcentrd.c \
+ shpgeo.c \
+ shpgeo.h
+
+shpdata_SOURCES=shpdata.c \
+ shpgeo.c \
+ shpgeo.h
+
+shpproj_SOURCES=shpproj.c \
+ shpgeo.c \
+ shpgeo.h
+
+shpwkb_SOURCES=shpwkb.c \
+ shpgeo.c \
+ shpgeo.h
+
+dbfcat_LDADD=libshape.a
+dbfinfo_LDADD=libshape.a
+shpcat_LDADD=libshape.a
+shpcentrd_LDADD=libshape.a
+shpdata_LDADD=libshape.a
+shpdxf_LDADD=libshape.a
+shpfix_LDADD=libshape.a
+shpinfo_LDADD=libshape.a
+shpproj_LDADD=libshape.a
+shpwkb_LDADD=libshape.a
+
+
diff --git a/src/shapelib/contrib/Makefile.in b/src/shapelib/contrib/Makefile.in
new file mode 100644
index 0000000..668ee0a
--- /dev/null
+++ b/src/shapelib/contrib/Makefile.in
@@ -0,0 +1,627 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+# $Id: Makefile.am,v 1.13 2012/11/01 18:57:19 we7u Exp $
+# C2pyright (C) 2004-2012 The Xastir Group
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = dbfcat$(EXEEXT) dbfinfo$(EXEEXT) shpcat$(EXEEXT) \
+ shpdxf$(EXEEXT) shpfix$(EXEEXT) shpinfo$(EXEEXT) @CONTSHP@
+EXTRA_PROGRAMS = shpcentrd$(EXEEXT) shpproj$(EXEEXT) shpdata$(EXEEXT) \
+ shpwkb$(EXEEXT)
+subdir = src/shapelib/contrib
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libshape_a_AR = $(AR) $(ARFLAGS)
+libshape_a_LIBADD =
+am_libshape_a_OBJECTS = shpopen.$(OBJEXT) shptree.$(OBJEXT) \
+ dbfopen.$(OBJEXT)
+libshape_a_OBJECTS = $(am_libshape_a_OBJECTS)
+PROGRAMS = $(noinst_PROGRAMS)
+dbfcat_SOURCES = dbfcat.c
+dbfcat_OBJECTS = dbfcat.$(OBJEXT)
+dbfcat_DEPENDENCIES = libshape.a
+dbfinfo_SOURCES = dbfinfo.c
+dbfinfo_OBJECTS = dbfinfo.$(OBJEXT)
+dbfinfo_DEPENDENCIES = libshape.a
+shpcat_SOURCES = shpcat.c
+shpcat_OBJECTS = shpcat.$(OBJEXT)
+shpcat_DEPENDENCIES = libshape.a
+am_shpcentrd_OBJECTS = shpcentrd.$(OBJEXT) shpgeo.$(OBJEXT)
+shpcentrd_OBJECTS = $(am_shpcentrd_OBJECTS)
+shpcentrd_DEPENDENCIES = libshape.a
+am_shpdata_OBJECTS = shpdata.$(OBJEXT) shpgeo.$(OBJEXT)
+shpdata_OBJECTS = $(am_shpdata_OBJECTS)
+shpdata_DEPENDENCIES = libshape.a
+shpdxf_SOURCES = shpdxf.c
+shpdxf_OBJECTS = shpdxf.$(OBJEXT)
+shpdxf_DEPENDENCIES = libshape.a
+shpfix_SOURCES = shpfix.c
+shpfix_OBJECTS = shpfix.$(OBJEXT)
+shpfix_DEPENDENCIES = libshape.a
+shpinfo_SOURCES = shpinfo.c
+shpinfo_OBJECTS = shpinfo.$(OBJEXT)
+shpinfo_DEPENDENCIES = libshape.a
+am_shpproj_OBJECTS = shpproj.$(OBJEXT) shpgeo.$(OBJEXT)
+shpproj_OBJECTS = $(am_shpproj_OBJECTS)
+shpproj_DEPENDENCIES = libshape.a
+am_shpwkb_OBJECTS = shpwkb.$(OBJEXT) shpgeo.$(OBJEXT)
+shpwkb_OBJECTS = $(am_shpwkb_OBJECTS)
+shpwkb_DEPENDENCIES = libshape.a
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libshape_a_SOURCES) dbfcat.c dbfinfo.c shpcat.c \
+ $(shpcentrd_SOURCES) $(shpdata_SOURCES) shpdxf.c shpfix.c \
+ shpinfo.c $(shpproj_SOURCES) $(shpwkb_SOURCES)
+DIST_SOURCES = $(libshape_a_SOURCES) dbfcat.c dbfinfo.c shpcat.c \
+ $(shpcentrd_SOURCES) $(shpdata_SOURCES) shpdxf.c shpfix.c \
+ shpinfo.c $(shpproj_SOURCES) $(shpwkb_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTSHP = @CONTSHP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GMAGIC_BIN = @GMAGIC_BIN@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBCOMPAT = @LIBCOMPAT@
+LIBOBJS = @LIBOBJS@
+LIBRTREE = @LIBRTREE@
+LIBS = @LIBS@
+LIBSHP = @LIBSHP@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LWPOSTGIS = @LWPOSTGIS@
+MAGIC_BIN = @MAGIC_BIN@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PG_CONFIG = @PG_CONFIG@
+POW_LIB = @POW_LIB@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUBRTREE = @SUBRTREE@
+SUBSHP = @SUBSHP@
+VERSION = @VERSION@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+convert = @convert@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+festival = @festival@
+found_gdal_config = @found_gdal_config@
+gm = @gm@
+gpsman = @gpsman@
+gv = @gv@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lpr = @lpr@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+mv = @mv@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sed = @sed@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+wget = @wget@
+xfontsel = @xfontsel@
+EXTRA_DIST = Makefile_orig ShapeFileII.pas dbfcat.c dbfinfo.c makefile.vc \
+ my_nan.h shpcat.c shpcentrd.c shpdata.c shpdxf.c shpfix.c \
+ shpgeo.c shpgeo.h shpinfo.c shpproj.c shpwkb.c
+
+noinst_LIBRARIES = libshape.a
+libshape_a_SOURCES = ../shpopen.c \
+ ../shptree.c \
+ ../dbfopen.c \
+ ../shapefil.h
+
+shpcentrd_SOURCES = shpcentrd.c \
+ shpgeo.c \
+ shpgeo.h
+
+shpdata_SOURCES = shpdata.c \
+ shpgeo.c \
+ shpgeo.h
+
+shpproj_SOURCES = shpproj.c \
+ shpgeo.c \
+ shpgeo.h
+
+shpwkb_SOURCES = shpwkb.c \
+ shpgeo.c \
+ shpgeo.h
+
+dbfcat_LDADD = libshape.a
+dbfinfo_LDADD = libshape.a
+shpcat_LDADD = libshape.a
+shpcentrd_LDADD = libshape.a
+shpdata_LDADD = libshape.a
+shpdxf_LDADD = libshape.a
+shpfix_LDADD = libshape.a
+shpinfo_LDADD = libshape.a
+shpproj_LDADD = libshape.a
+shpwkb_LDADD = libshape.a
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/shapelib/contrib/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/shapelib/contrib/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libshape.a: $(libshape_a_OBJECTS) $(libshape_a_DEPENDENCIES)
+ -rm -f libshape.a
+ $(libshape_a_AR) libshape.a $(libshape_a_OBJECTS) $(libshape_a_LIBADD)
+ $(RANLIB) libshape.a
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+dbfcat$(EXEEXT): $(dbfcat_OBJECTS) $(dbfcat_DEPENDENCIES)
+ @rm -f dbfcat$(EXEEXT)
+ $(LINK) $(dbfcat_OBJECTS) $(dbfcat_LDADD) $(LIBS)
+dbfinfo$(EXEEXT): $(dbfinfo_OBJECTS) $(dbfinfo_DEPENDENCIES)
+ @rm -f dbfinfo$(EXEEXT)
+ $(LINK) $(dbfinfo_OBJECTS) $(dbfinfo_LDADD) $(LIBS)
+shpcat$(EXEEXT): $(shpcat_OBJECTS) $(shpcat_DEPENDENCIES)
+ @rm -f shpcat$(EXEEXT)
+ $(LINK) $(shpcat_OBJECTS) $(shpcat_LDADD) $(LIBS)
+shpcentrd$(EXEEXT): $(shpcentrd_OBJECTS) $(shpcentrd_DEPENDENCIES)
+ @rm -f shpcentrd$(EXEEXT)
+ $(LINK) $(shpcentrd_OBJECTS) $(shpcentrd_LDADD) $(LIBS)
+shpdata$(EXEEXT): $(shpdata_OBJECTS) $(shpdata_DEPENDENCIES)
+ @rm -f shpdata$(EXEEXT)
+ $(LINK) $(shpdata_OBJECTS) $(shpdata_LDADD) $(LIBS)
+shpdxf$(EXEEXT): $(shpdxf_OBJECTS) $(shpdxf_DEPENDENCIES)
+ @rm -f shpdxf$(EXEEXT)
+ $(LINK) $(shpdxf_OBJECTS) $(shpdxf_LDADD) $(LIBS)
+shpfix$(EXEEXT): $(shpfix_OBJECTS) $(shpfix_DEPENDENCIES)
+ @rm -f shpfix$(EXEEXT)
+ $(LINK) $(shpfix_OBJECTS) $(shpfix_LDADD) $(LIBS)
+shpinfo$(EXEEXT): $(shpinfo_OBJECTS) $(shpinfo_DEPENDENCIES)
+ @rm -f shpinfo$(EXEEXT)
+ $(LINK) $(shpinfo_OBJECTS) $(shpinfo_LDADD) $(LIBS)
+shpproj$(EXEEXT): $(shpproj_OBJECTS) $(shpproj_DEPENDENCIES)
+ @rm -f shpproj$(EXEEXT)
+ $(LINK) $(shpproj_OBJECTS) $(shpproj_LDADD) $(LIBS)
+shpwkb$(EXEEXT): $(shpwkb_OBJECTS) $(shpwkb_DEPENDENCIES)
+ @rm -f shpwkb$(EXEEXT)
+ $(LINK) $(shpwkb_OBJECTS) $(shpwkb_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/dbfcat.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/dbfinfo.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/dbfopen.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shpcat.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shpcentrd.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shpdata.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shpdxf.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shpfix.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shpgeo.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shpinfo.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shpopen.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shpproj.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shptree.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shpwkb.Po at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+shpopen.o: ../shpopen.c
+ at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT shpopen.o -MD -MP -MF $(DEPDIR)/shpopen.Tpo -c -o shpopen.o `test -f '../shpopen.c' || echo '$(srcdir)/'`../shpopen.c
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/shpopen.Tpo $(DEPDIR)/shpopen.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../shpopen.c' object='shpopen.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o shpopen.o `test -f '../shpopen.c' || echo '$(srcdir)/'`../shpopen.c
+
+shpopen.obj: ../shpopen.c
+ at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT shpopen.obj -MD -MP -MF $(DEPDIR)/shpopen.Tpo -c -o shpopen.obj `if test -f '../shpopen.c'; then $(CYGPATH_W) '../shpopen.c'; else $(CYGPATH_W) '$(srcdir)/../shpopen.c'; fi`
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/shpopen.Tpo $(DEPDIR)/shpopen.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../shpopen.c' object='shpopen.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o shpopen.obj `if test -f '../shpopen.c'; then $(CYGPATH_W) '../shpopen.c'; else $(CYGPATH_W) '$(srcdir)/../shpopen.c'; fi`
+
+shptree.o: ../shptree.c
+ at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT shptree.o -MD -MP -MF $(DEPDIR)/shptree.Tpo -c -o shptree.o `test -f '../shptree.c' || echo '$(srcdir)/'`../shptree.c
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/shptree.Tpo $(DEPDIR)/shptree.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../shptree.c' object='shptree.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o shptree.o `test -f '../shptree.c' || echo '$(srcdir)/'`../shptree.c
+
+shptree.obj: ../shptree.c
+ at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT shptree.obj -MD -MP -MF $(DEPDIR)/shptree.Tpo -c -o shptree.obj `if test -f '../shptree.c'; then $(CYGPATH_W) '../shptree.c'; else $(CYGPATH_W) '$(srcdir)/../shptree.c'; fi`
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/shptree.Tpo $(DEPDIR)/shptree.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../shptree.c' object='shptree.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o shptree.obj `if test -f '../shptree.c'; then $(CYGPATH_W) '../shptree.c'; else $(CYGPATH_W) '$(srcdir)/../shptree.c'; fi`
+
+dbfopen.o: ../dbfopen.c
+ at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dbfopen.o -MD -MP -MF $(DEPDIR)/dbfopen.Tpo -c -o dbfopen.o `test -f '../dbfopen.c' || echo '$(srcdir)/'`../dbfopen.c
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dbfopen.Tpo $(DEPDIR)/dbfopen.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../dbfopen.c' object='dbfopen.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dbfopen.o `test -f '../dbfopen.c' || echo '$(srcdir)/'`../dbfopen.c
+
+dbfopen.obj: ../dbfopen.c
+ at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dbfopen.obj -MD -MP -MF $(DEPDIR)/dbfopen.Tpo -c -o dbfopen.obj `if test -f '../dbfopen.c'; then $(CYGPATH_W) '../dbfopen.c'; else $(CYGPATH_W) '$(srcdir)/../dbfopen.c'; fi`
+ at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dbfopen.Tpo $(DEPDIR)/dbfopen.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../dbfopen.c' object='dbfopen.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dbfopen.obj `if test -f '../dbfopen.c'; then $(CYGPATH_W) '../dbfopen.c'; else $(CYGPATH_W) '$(srcdir)/../dbfopen.c'; fi`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES clean-noinstPROGRAMS ctags distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/shapelib/contrib/Makefile_orig b/src/shapelib/contrib/Makefile_orig
new file mode 100644
index 0000000..ab0ab13
--- /dev/null
+++ b/src/shapelib/contrib/Makefile_orig
@@ -0,0 +1,59 @@
+
+#LINKOPT = /usr/local/lib/libdbmalloc.a
+#CFLAGS = -g
+
+# Endian: define either _LITTLE_ENDIAN or _BIG_ENDIAN
+ENDIAN = -D_LITTLE_ENDIAN
+
+CFLAGS = -g -I.. -DPROJ4 $(ENDIAN) -DDEBUG -DDEBUG2
+
+SHPOBJ = ../shpopen.o ../dbfopen.o
+
+SHPGOBJ = ../shpopen.o ../dbfopen.o shpgeo.o
+
+GEOOBJ = ./shpgeo.o -lm -lproj
+
+default: all
+
+all: shpdxf shpproj dbfinfo shpcentrd shpdata shpwkb dbfinfo dbfcat shpinfo shpfix shpcat
+
+clean:
+ rm -f shpdxf shpproj dbfinfo shpcentrd shpdata shpwkb dbfcat dbfinfo shpinfo shpfix shpcat *.o
+
+shpgeo.o: shpgeo.c shpgeo.h
+ $(CC) $(CFLAGS) -c shpgeo.c
+
+shpdxf: shpdxf.c $(SHPOBJ)
+ $(CC) $(CFLAGS) shpdxf.c ${SHPOBJ} $(LINKOPT) -o shpdxf
+
+shpcentrd: shpcentrd.c $(SHPGOBJ)
+ $(CC) $(CFLAGS) shpcentrd.c ${SHPOBJ} $(LINKOPT) $(GEOOBJ) -o shpcentrd
+
+shpdata: shpdata.c $(SHPGOBJ)
+ $(CC) $(CFLAGS) shpdata.c ${SHPOBJ} $(LINKOPT) $(GEOOBJ) -o shpdata
+
+shpinfo: shpinfo.c $(SHPOBJ)
+ $(CC) $(CFLAGS) shpinfo.c ${SHPOBJ} $(LINKOPT) $(GEOOBJ) -o shpinfo
+
+shpfix: shpfix.c $(SHPOBJ)
+ $(CC) $(CFLAGS) shpfix.c ${SHPOBJ} $(LINKOPT) -o shpfix
+
+shpcat: shpcat.c $(SHPOBJ)
+ $(CC) $(CFLAGS) shpcat.c ${SHPOBJ} $(LINKOPT) -o shpcat
+
+shpwkb: shpwkb.c $(SHPGOBJ)
+ $(CC) $(CFLAGS) shpwkb.c ${SHPOBJ} $(LINKOPT) $(GEOOBJ) -o shpwkb
+
+shpproj: shpproj.c $(SHPGOBJ)
+ $(CC) $(CFLAGS) shpproj.c $(SHPOBJ) $(GEOOBJ) -lm -lproj $(LINKOPT) -o shpproj
+
+dbfinfo: dbfinfo.c $(SHPOBJ)
+ $(CC) $(CFLAGS) dbfinfo.c $(SHPOBJ) $(LINKOPT) -o dbfinfo
+
+dbfcat: dbfcat.c $(SHPOBJ)
+ $(CC) $(CFLAGS) dbfcat.c $(SHPOBJ) $(LINKOPT) -o dbfcat
+
+check: testproj
+
+testproj:
+ tests/shpproj.sh
diff --git a/src/shapelib/contrib/ShapeFileII.pas b/src/shapelib/contrib/ShapeFileII.pas
new file mode 100644
index 0000000..d386adf
--- /dev/null
+++ b/src/shapelib/contrib/ShapeFileII.pas
@@ -0,0 +1,254 @@
+{
+/******************************************************************************
+ * $Id: ShapeFileII.pas,v 1.1 2006/11/10 21:48:10 tvrusso Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Delphi Pascal interface to Shapelib.
+ * Author: Kevin Meyer (Kevin at CyberTracker.co.za)
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, Keven Meyer (Kevin at CyberTracker.co.za)
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: ShapeFileII.pas,v $
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.2 2002/01/21 14:09:26 warmerda
+ * Fixed name.
+ *
+ * Revision 1.1 2002/01/17 14:30:37 warmerda
+ * New
+ *
+ */
+}
+unit ShapeFileII;
+
+interface
+//uses { uses clause }
+// ;
+{ Set compiler to pack on byte boundaries only }
+{$ALIGN OFF}
+{$OVERFLOWCHECKS OFF}
+{$J-}
+const
+ SHPT_NULL = 0;
+ SHPT_POINT = 1;
+ SHPT_ARC = 3;
+ SHPT_POLYGON = 5;
+ SHPT_MULTIPOINT = 8;
+ SHPT_POINTZ = 11;
+ SHPT_ARCZ = 13;
+ SHPT_POLYGONZ = 15;
+ SHPT_MULTIPOINTZ = 18;
+ SHPT_POINTM = 21;
+ SHPT_ARCM = 23;
+ SHPT_POLYGONM = 25;
+ SHPT_MULTIPOINTM = 28;
+ SHPT_MULTIPATCH = 31;
+ XBASE_FLDHDR_SZ = 32;
+ szAccessBRW = 'rb+';
+
+// *********************** SHP support ************************
+
+type
+SHPObject = record
+ nSHPType,
+ nShapeId,
+ nParts : LongWord;
+ panPartStart,
+ panPartType : array of LongWord;
+ nVertices : LongWord;
+ padfX, padfY, padfZ, padfM : array of double;
+ dfXMin, dfYMin, dfZMin, dfMMin : double;
+ dfXMax, dfYMax, dfZMax, dfMMax : double;
+end;
+SHPObjectHandle = ^SHPObject;
+
+SHPBoundsArr = double;
+
+SHPInfo = record
+ fpSHP,
+ fpSHX : FILE;
+
+ nShapeType,
+ nFileSize,
+ nRecords,
+ nMaxRecords : LongWord;
+ panRecOffset,
+ panRecSize : array of LongWord;
+ adBoundsMin, adBoundsMax : SHPBoundsArr;
+ bUpdated : LongWord;
+end;
+SHPHandle = ^SHPInfo;
+
+// *********************** DBF support ************************
+
+DBFInfo = record
+ fp : FILE;
+ nRecords,
+ nRecordLength,
+ nHeaderLength,
+ nFields : LongWord;
+
+ panFieldOffset,
+ panFieldSize,
+ panFieldDecimals : array of LongWord;
+
+ pachFieldType : LongWord;
+ pszHeader : PChar;
+ nCurrentRecord,
+ bCurrentRecordModified : LongWord;
+ pszCurrentRecord : PChar;
+
+ bNoHeader,
+ bUpdated : LongWord;
+end;
+DBFHandle = ^DBFInfo;
+
+DBFFieldType = (DBFTString, DBFTInteger, DBFTDouble, DBFTInvalid) ;
+
+// *********************** SHP func declarations ************************
+
+{$ALIGN ON}
+
+function SHPOpen(pszShapeFile, pszAccess : PChar) : SHPHandle;cdecl;
+procedure SHPGetInfo(hSHP : SHPHandle; var pnEntities, pnShapeType : LongWord; var padfMinBoud, padfMaxBound : SHPBoundsArr);cdecl;
+procedure SHPClose(hSHP : SHPHandle);cdecl;
+function SHPReadObject(hSHP : SHPHandle; iShape : LongWord): SHPObjectHandle;cdecl;
+function SHPCreate(pszShapeFile : PChar; nShapeType : LongWord):SHPHandle;cdecl;
+function SHPWriteObject(hSHP : SHPHandle; iShape : LongWord; psObject : SHPObjectHandle): LongWord;cdecl;
+function SHPCreateSimpleObject(nSHPType, nVertices : LongWord; var padfX, padfY, padfZ : double):SHPObjectHandle;cdecl;
+procedure SHPDestroy(psObject : SHPObjectHandle);cdecl;
+
+procedure SHPComputeExtents(psObject : SHPObjectHandle);cdecl;
+function SHPCreateObject(nSHPType, iShape, nParts : LongWord; var panPartStart, panPartType : LongWord; nVertices : LongWord; var padfX, padfY, padfZ, padfM : SHPBoundsArr): SHPObjectHandle;cdecl;
+
+function SHPTypeStr(pnShapeType : LongWord): string;
+
+// *********************** DBF func declarations ************************
+
+function DBFOpen(pszDBFFile, pszAccess : PChar): DBFHandle;cdecl;
+function DBFCreate(pszDBFFile : PChar): DBFHandle ;cdecl;
+function DBFGetFieldCount(hDBF : DBFHandle) : LongWord ;cdecl;
+function DBFGetRecordCount(hDBF : DBFHandle) : LongWord;cdecl;
+function DBFGetFieldIndex(hDBF: DBFHandle; pszFieldName : PChar): LongWord;cdecl;
+function DBFGetFieldInfo(hDBF : DBFHandle; iField : LongWord; pszFieldName : PChar;
+ var pnWidth, pnDecimals : LongWord): DBFFieldType;cdecl;
+function DBFAddField(hDBF : DBFHandle; pszFieldName : PChar;
+ eType : DBFFieldType; nWidth, nDecimals : LongWord): LongWord;cdecl;
+
+function DBFReadIntegerAttribute(hDBF : DBFHandle;iShape, iField : LongWord ): LongWord;cdecl;
+function DBFReadDoubleAttribute(hDBF : DBFHandle; iShape, iField : LongWord ):double;cdecl;
+function DBFReadStringAttribute(hDBF : DBFHandle; iShape, iField : LongWord ) : pchar;cdecl;
+function DBFIsAttributeNULL(hDBF : DBFHandle; iShape, iField : LongWord ): LongWord;cdecl;
+function DBFWriteIntegerAttribute(hDBF : DBFHandle;iShape, iField, nFieldValue : LongWord): LongWord;cdecl;
+function DBFWriteDoubleAttribute(hDBF : DBFHandle;iShape, iField : LongWord;
+ dFieldValue : double): LongWord ;cdecl;
+function DBFWriteStringAttribute(hDBF : DBFHandle;iShape, iField : LongWord;
+ pszFieldValue : PChar): LongWord ;cdecl;
+function DBFWriteNULLAttribute(hDBF : DBFHandle; iShape, iField : LongWord ) : LongWord;cdecl;
+procedure DBFClose(hDBF : DBFHandle);cdecl;
+function DBFGetNativeFieldType(hDBF : DBFHandle; iField : LongWord) : Char;cdecl;
+
+// *********************** SHP implementation ************************
+implementation
+// *****************************************************************************
+function SHPCreateSimpleObject(nSHPType, nVertices : LongWord; var padfX, padfY, padfZ : double):SHPObjectHandle;external 'shapelib.dll' name 'SHPCreateSimpleObject';
+function SHPOpen(pszShapeFile, pszAccess : PChar) : SHPHandle; external 'shapelib.dll' name 'SHPOpen';
+procedure SHPGetInfo(hSHP : SHPHandle; var pnEntities, pnShapeType : LongWord; var padfMinBoud, padfMaxBound : SHPBoundsArr);external 'shapelib.dll' name 'SHPGetInfo';
+procedure SHPClose(hSHP : SHPHandle);external 'shapelib.dll' name 'SHPClose';
+function SHPReadObject(hSHP : SHPHandle; iShape : LongWord) : SHPObjectHandle;external 'shapelib.dll' name 'SHPReadObject';
+function SHPCreate(pszShapeFile : PChar; nShapeType : LongWord):SHPHandle;external 'shapelib.dll' name 'SHPCreate';
+function SHPWriteObject(hSHP : SHPHandle; iShape : LongWord; psObject : SHPObjectHandle): LongWord;cdecl;external 'shapelib.dll' name 'SHPWriteObject';
+procedure SHPDestroy(psObject : SHPObjectHandle);external 'shapelib.dll' name 'SHPDestroyObject';
+procedure SHPComputeExtents(psObject : SHPObjectHandle);external 'shapelib.dll' name 'SHPComputeExtents';
+function SHPCreateObject(nSHPType, iShape, nParts : LongWord; var panPartStart, panPartType : LongWord; nVertices : LongWord; var padfX, padfY, padfZ, padfM : SHPBoundsArr): SHPObjectHandle;external 'shapelib.dll' name 'SHPCreateObject';
+// *****************************************************************************
+function SHPTypeStr(pnShapeType : LongWord): string;
+begin
+ case pnShapeType of
+ SHPT_NULL : result := 'NULL';
+ SHPT_POINT : result := 'POINT';
+ SHPT_ARC : result := 'ARC';
+ SHPT_POLYGON : result := 'POLYGON';
+ SHPT_MULTIPOINT : result := 'MULTIPOINT';
+ SHPT_POINTZ : result := 'POINTZ';
+ SHPT_ARCZ : result := 'ARCZ';
+ SHPT_POLYGONZ : result := 'POLYGONZ';
+ SHPT_MULTIPOINTZ : result := 'MULTIPOINTZ';
+ SHPT_POINTM : result := 'POINTM';
+ SHPT_ARCM : result := 'ARCM';
+ SHPT_POLYGONM : result := 'POLYGONM';
+ SHPT_MULTIPOINTM : result := 'MULTIPOINTM';
+ SHPT_MULTIPATCH : result := 'MULTIPATCH';
+ else
+ result := '--unknown--';
+ end;
+end;
+// *****************************************************************************
+// *****************************************************************************
+function DBFOpen(pszDBFFile, pszAccess : PChar): DBFHandle;external 'shapelib.dll';
+function DBFCreate(pszDBFFile : PChar): DBFHandle ;external 'shapelib.dll';
+function DBFGetFieldCount(hDBF : DBFHandle) : LongWord ;external 'shapelib.dll';
+function DBFGetRecordCount(hDBF : DBFHandle) : LongWord;external 'shapelib.dll';
+function DBFGetFieldIndex(hDBF: DBFHandle; pszFieldName : PChar): LongWord;external 'shapelib.dll';
+function DBFGetFieldInfo(hDBF : DBFHandle; iField : LongWord; pszFieldName : PChar; var pnWidth, pnDecimals : LongWord): DBFFieldType;external 'shapelib.dll';
+function DBFAddField(hDBF : DBFHandle; pszFieldName : PChar; eType : DBFFieldType; nWidth, nDecimals : LongWord): LongWord;external 'shapelib.dll';
+function DBFReadIntegerAttribute(hDBF : DBFHandle;iShape, iField : LongWord ): LongWord;external 'shapelib.dll';
+function DBFReadDoubleAttribute(hDBF : DBFHandle; iShape, iField : LongWord ):double;external 'shapelib.dll';
+function DBFReadStringAttribute(hDBF : DBFHandle; iShape, iField : LongWord ) : pchar;external 'shapelib.dll';
+function DBFIsAttributeNULL(hDBF : DBFHandle; iShape, iField : LongWord ): LongWord;external 'shapelib.dll';
+function DBFWriteIntegerAttribute(hDBF : DBFHandle;iShape, iField, nFieldValue : LongWord): LongWord;external 'shapelib.dll';
+function DBFWriteDoubleAttribute(hDBF : DBFHandle;iShape, iField : LongWord; dFieldValue : double): LongWord ;external 'shapelib.dll';
+function DBFWriteStringAttribute(hDBF : DBFHandle;iShape, iField : LongWord; pszFieldValue : PChar): LongWord ;external 'shapelib.dll';
+function DBFWriteNULLAttribute(hDBF : DBFHandle; iShape, iField : LongWord ) : LongWord;external 'shapelib.dll';
+procedure DBFClose(hDBF : DBFHandle);external 'shapelib.dll';
+function DBFGetNativeFieldType(hDBF : DBFHandle; iField : LongWord) : Char;external 'shapelib.dll';
+// *****************************************************************************
+
+end.
diff --git a/src/shapelib/contrib/dbfcat.c b/src/shapelib/contrib/dbfcat.c
new file mode 100644
index 0000000..48806a2
--- /dev/null
+++ b/src/shapelib/contrib/dbfcat.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 1995 Frank Warmerdam
+ *
+ * This code is in the public domain.
+ *
+ * $Log: dbfcat.c,v $
+ * Revision 1.4 2010/07/11 20:30:00 we7u
+ * More minor tweaks to get rid of compiler warnings. Of particular note are
+ * some TODO entries added to a couple of files for two enumerated values that
+ * weren't being handled in "switch" statements. There still isn't any code
+ * for those case statements, but the compiler warnings are gone.
+ *
+ * Revision 1.3 2010/07/11 07:24:37 we7u
+ * Fixing multiple minor warnings with Shapelib. Still plenty left.
+ *
+ * Revision 1.2 2007/07/25 15:45:27 we7u
+ * Adding includes necessary for warning-free compiles.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.1 1999/05/26 02:56:31 candrsn
+ * updates to shpdxf, dbfinfo, port from Shapelib 1.1.5 of dbfcat and shpinfo
+ *
+ * Revision 1.3 1995/10/21 03:15:01 warmerda
+ * Changed to use binary file access.
+ *
+ * Revision 1.2 1995/08/04 03:16:22 warmerda
+ * Added header.
+ *
+ */
+
+//static char rcsid[] =
+// "$Id: dbfcat.c,v 1.4 2010/07/11 20:30:00 we7u Exp $";
+
+#include "shapefil.h"
+#include <stdlib.h>
+#include <string.h>
+
+int main( int argc, char ** argv )
+
+{
+ DBFHandle hDBF;
+// int *panWidth;
+ int i, iRecord;
+// char szFormat[32], szField[1024];
+ char cTitle[32], nTitle[32];
+ int nWidth, nDecimals;
+ int cnWidth, cnDecimals;
+ DBFHandle cDBF;
+ DBFFieldType hType,cType;
+ int ci, ciRecord;
+ char tfile[160];
+ int hflds, cflds;
+// int j;
+ int verbose = 0;
+ int force = 0;
+ int mismatch = 0;
+ int matches = 0;
+ char fld_m[256];
+ int shift = 0;
+ char type_names[4][15] = {"integer", "string", "double", "double"};
+
+ if( argc < 3 )
+ {
+ printf( "dbfcat [-v] [-f] from_DBFfile to_DBFfile\n" );
+ exit( 1 );
+ }
+
+
+ if ( strcmp ("-v", argv[1] ) == 0 ) { shift = 1; verbose = 1; }
+ if ( strcmp ("-f", argv[1 + shift] ) == 0 ) { shift ++; force = 1; }
+ if ( strcmp ("-v", argv[1 + shift] ) == 0 ) { shift ++; verbose = 1; }
+ strcpy (tfile, argv[1 + shift]);
+ strcat (tfile, ".dbf");
+ hDBF = DBFOpen( tfile, "rb" );
+ if( hDBF == NULL )
+ {
+ printf( "DBFOpen(%s.dbf,\"r\") failed for From_DBF.\n", tfile );
+ exit( 2 );
+ }
+
+ strcpy (tfile, argv[2 + shift]);
+ strcat (tfile, ".dbf");
+
+ cDBF = DBFOpen( tfile, "rb+" );
+ if( cDBF == NULL )
+ {
+ printf( "DBFOpen(%s.dbf,\"rb+\") failed for To_DBF.\n", tfile );
+ exit( 2 );
+ }
+
+
+ if( DBFGetFieldCount(hDBF) == 0 )
+ {
+ printf( "There are no fields in this table!\n" );
+ exit( 3 );
+ }
+
+ hflds = DBFGetFieldCount(hDBF);
+ cflds = DBFGetFieldCount(cDBF);
+
+ matches = 0;
+ for( i = 0; i < hflds; i++ )
+ {
+ char szTitle[18];
+ char cname[18];
+ int j;
+ hType = DBFGetFieldInfo( hDBF, i, szTitle, &nWidth, &nDecimals );
+ fld_m[i] = -1;
+ for ( j = 0; j < cflds; j ++ )
+ {
+ cType = DBFGetFieldInfo( cDBF, j, cname, &cnWidth, &cnDecimals );
+ if ( strcmp (cname, szTitle) == 0 )
+ {
+ if ( hType != cType )
+ { printf ("Incompatible fields %s(%s) != %s(%s),\n",
+ type_names[hType],nTitle,type_names[cType],cTitle);
+ mismatch = 1;
+ }
+ fld_m[i] = j;
+ if ( verbose )
+ { printf("%s %s(%d,%d) <- %s %s(%d,%d)\n", cname, type_names[cType],
+ cnWidth, cnDecimals,
+ szTitle, type_names[hType], nWidth, nDecimals); }
+ j = cflds;
+ matches = 1;
+ }
+ }
+ }
+
+ if ( (matches == 0 ) && !force ) {
+ printf ("ERROR: No field names match for tables, cannot proceed\n use -f to force processing using blank records\n");
+ exit(-1); }
+ if ( mismatch && !force ) {
+ printf ("ERROR: field type mismatch cannot proceed\n use -f to force processing using attempted conversions\n");
+ exit(-1); }
+
+ for( iRecord = 0; iRecord < DBFGetRecordCount(hDBF); iRecord++ )
+ {
+ ciRecord = DBFGetRecordCount( cDBF );
+ for ( i = 0; i < hflds;i ++ )
+ {
+// double cf;
+ ci = fld_m[i];
+ if ( ci != -1 )
+ {
+ cType = DBFGetFieldInfo( cDBF, ci, cTitle, &cnWidth, &cnDecimals );
+ hType = DBFGetFieldInfo( hDBF, i, nTitle, &nWidth, &nDecimals );
+
+ switch( cType )
+ {
+ case FTString:
+ DBFWriteStringAttribute(cDBF, ciRecord, ci,
+ (char *) DBFReadStringAttribute( hDBF, iRecord, i ) );
+ break;
+
+ case FTInteger:
+ DBFWriteIntegerAttribute(cDBF, ciRecord, ci,
+ (int) DBFReadIntegerAttribute( hDBF, iRecord, i ) );
+ break;
+
+ case FTDouble:
+/* cf = DBFReadDoubleAttribute( hDBF, iRecord, i );
+ printf ("%s <- %s (%f)\n", cTitle, nTitle, cf);
+*/
+ DBFWriteDoubleAttribute(cDBF, ciRecord, ci,
+ (double) DBFReadDoubleAttribute( hDBF, iRecord, i ) );
+ break;
+
+ case FTLogical:
+// TODO: Add code here
+ break;
+
+ case FTInvalid:
+// TODO: Add code here
+ break;
+
+ }
+ }
+ } /* fields names match */
+ }
+
+ if ( verbose ) { printf (" %d records appended \n\n", iRecord); }
+ DBFClose( hDBF );
+ DBFClose( cDBF );
+
+ return( 0 );
+}
diff --git a/src/shapelib/contrib/dbfinfo.c b/src/shapelib/contrib/dbfinfo.c
new file mode 100644
index 0000000..45cfe47
--- /dev/null
+++ b/src/shapelib/contrib/dbfinfo.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 1999 Carl Anderson
+ *
+ * This code is in the public domain.
+ *
+ * This code is based in part on the earlier work of Frank Warmerdam
+ *
+ * requires shapelib 1.2
+ * gcc dbfinfo dbfopen.o dbfinfo
+ *
+ *
+ * $Log: dbfinfo.c,v $
+ * Revision 1.3 2010/07/11 07:24:37 we7u
+ * Fixing multiple minor warnings with Shapelib. Still plenty left.
+ *
+ * Revision 1.2 2007/07/25 15:45:27 we7u
+ * Adding includes necessary for warning-free compiles.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.2 1999/05/26 02:56:31 candrsn
+ * updates to shpdxf, dbfinfo, port from Shapelib 1.1.5 of dbfcat and shpinfo
+ *
+ *
+ */
+
+
+#include "shapefil.h"
+#include <stdlib.h>
+#include <string.h>
+
+int main( int argc, char ** argv )
+
+{
+ DBFHandle hDBF;
+ int *panWidth, i;
+// int iRecord;
+// char szFormat[32], szField[1024];
+ char ftype[15];
+// char cTitle[32], nTitle[32];
+ int nWidth, nDecimals;
+// int cnWidth, cnDecimals;
+// DBFHandle cDBF;
+// DBFFieldType hType,cType;
+// int ci, ciRecord;
+
+/* -------------------------------------------------------------------- */
+/* Display a usage message. */
+/* -------------------------------------------------------------------- */
+ if( argc != 2 )
+ {
+ printf( "dbfinfo xbase_file\n" );
+ exit( 1 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Open the file. */
+/* -------------------------------------------------------------------- */
+ hDBF = DBFOpen( argv[1], "rb" );
+ if( hDBF == NULL )
+ {
+ printf( "DBFOpen(%s,\"r\") failed.\n", argv[1] );
+ exit( 2 );
+ }
+
+ printf ("Info for %s\n",argv[1]);
+
+/* -------------------------------------------------------------------- */
+/* If there is no data in this file let the user know. */
+/* -------------------------------------------------------------------- */
+ i = DBFGetFieldCount(hDBF);
+ printf ("%d Columns, %d Records in file\n",i,DBFGetRecordCount(hDBF));
+
+/* -------------------------------------------------------------------- */
+/* Compute offsets to use when printing each of the field */
+/* values. We make each field as wide as the field title+1, or */
+/* the field value + 1. */
+/* -------------------------------------------------------------------- */
+ panWidth = (int *) malloc( DBFGetFieldCount( hDBF ) * sizeof(int) );
+
+ for( i = 0; i < DBFGetFieldCount(hDBF); i++ )
+ {
+ char szTitle[12];
+// DBFFieldType eType;
+
+ switch ( DBFGetFieldInfo( hDBF, i, szTitle, &nWidth, &nDecimals )) {
+ case FTString:
+ strcpy (ftype, "string");;
+ break;
+
+ case FTInteger:
+ strcpy (ftype, "integer");
+ break;
+
+ case FTDouble:
+ strcpy (ftype, "float");
+ break;
+
+ case FTInvalid:
+ strcpy (ftype, "invalid/unsupported");
+ break;
+
+ default:
+ strcpy (ftype, "unknown");
+ break;
+ }
+ printf ("%15.15s\t%15s (%d,%d)\n",szTitle, ftype, nWidth, nDecimals);
+
+ }
+
+ DBFClose( hDBF );
+
+ return( 0 );
+}
diff --git a/src/shapelib/contrib/makefile.vc b/src/shapelib/contrib/makefile.vc
new file mode 100644
index 0000000..ff3ce16
--- /dev/null
+++ b/src/shapelib/contrib/makefile.vc
@@ -0,0 +1,29 @@
+PROJ_DIR = D:\warmerda\proj
+
+CFLAGS = /I.. /I$(PROJ_DIR)\src /D_LITTLE_ENDIAN -DPROJ4
+
+LINKARGS = shpgeo.obj ..\shpopen.obj ..\dbfopen.obj \
+ D:\warmerda\proj\src\proj_i.lib
+
+default: all
+
+all: shpcat.exe shpcentrd.exe shpdxf.exe shpinfo.exe shpproj.exe
+
+shpcat.exe: shpcat.obj shpgeo.obj
+ $(CC) $(CFLAGS) shpcat.obj $(LINKARGS)
+
+shpcentrd.exe: shpcentrd.obj shpgeo.obj
+ $(CC) $(CFLAGS) shpcentrd.obj $(LINKARGS)
+
+shpproj.exe: shpproj.obj shpgeo.obj
+ $(CC) $(CFLAGS) shpproj.obj $(LINKARGS)
+
+shpdxf.exe: shpdxf.obj shpgeo.obj
+ $(CC) $(CFLAGS) shpdxf.obj $(LINKARGS)
+
+shpinfo.exe: shpinfo.obj shpgeo.obj
+ $(CC) $(CFLAGS) shpinfo.obj $(LINKARGS)
+
+clean:
+ del *.obj *.exe
+
diff --git a/src/shapelib/contrib/my_nan.h b/src/shapelib/contrib/my_nan.h
new file mode 100644
index 0000000..640dc3c
--- /dev/null
+++ b/src/shapelib/contrib/my_nan.h
@@ -0,0 +1,56 @@
+/* `NAN' constant for IEEE 754 machines.
+ Copyright (C) 1992, 1996 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef _GNU_NAN_H
+
+#define _GNU_NAN_H 1
+
+#include <endian.h>
+
+/* hacked to define NAN on Solaris 2.7 if it wasn't defined */
+
+/* IEEE Not A Number. */
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+# warning "*** Big Endian ***"
+#else
+# if __BYTE_ORDER == __SMALL_ENDIAN
+# warning "*** Small Endian ***"
+# else
+# warning "*** Endian-ness unknown ***"
+# endif
+#endif
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+# define __nan_bytes { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 }
+#else
+# define __nan_bytes { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f }
+#endif
+
+#ifdef __GNUC__
+# define NAN \
+ (__extension__ ((union { unsigned char __c[8]; \
+ double __d; }) \
+ { __nan_bytes }).__d)
+#else /* Not GCC. */
+ static const char __nan[8] = __nan_bytes;
+# define NAN (*(const double *) __nan)
+#endif
+
+#endif /* gnu_nan.h */
diff --git a/src/shapelib/contrib/shpcat.c b/src/shapelib/contrib/shpcat.c
new file mode 100644
index 0000000..16568bd
--- /dev/null
+++ b/src/shapelib/contrib/shpcat.c
@@ -0,0 +1,99 @@
+/******************************************************************************
+ * Copyright (c) 1999, Carl Anderson
+ *
+ * This code is based in part on the earlier work of Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * shpcat
+ *
+ * gcc shpcat.c ../shpopen.o -o shpcat
+ *
+ * Utility program to concatenate two shapefiles
+ * Must be used in concert with dbfcat
+ *
+ */
+
+#include "shapefil.h"
+#include <stdlib.h>
+
+int dbfcat_main( int argc, char ** argv );
+
+int main( int argc, char ** argv )
+
+{
+ SHPHandle hSHP, cSHP;
+ int nShapeType, i, nEntities, nShpInFile;
+ SHPObject *shape;
+
+/* -------------------------------------------------------------------- */
+/* Display a usage message. */
+/* -------------------------------------------------------------------- */
+ if( argc != 3 )
+ {
+ printf( "shpcat from_shpfile to_shpfile\n" );
+ exit( 1 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Open the passed shapefile. */
+/* -------------------------------------------------------------------- */
+ hSHP = SHPOpen( argv[1], "rb" );
+
+ if( hSHP == NULL )
+ {
+ printf( "Unable to open:%s\n", argv[1] );
+ exit( 1 );
+ }
+
+ SHPGetInfo( hSHP, &nEntities, &nShapeType, NULL, NULL );
+ fprintf(stderr,"Opened From File %s, with %d shapes\n",argv[1],nEntities);
+
+/* -------------------------------------------------------------------- */
+/* Open the passed shapefile. */
+/* -------------------------------------------------------------------- */
+ cSHP = SHPOpen( argv[2], "rb+" );
+
+ if( cSHP == NULL )
+ {
+ printf( "Unable to open:%s\n", argv[2] );
+ exit( 1 );
+ }
+
+ SHPGetInfo( cSHP, &nShpInFile, NULL, NULL, NULL );
+ fprintf(stderr,"Opened to file %s with %d shapes, ready to add %d\n",
+ argv[2],nShpInFile,nEntities);
+
+/* -------------------------------------------------------------------- */
+/* Skim over the list of shapes, printing all the vertices. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < nEntities; i++ )
+ {
+ shape = SHPReadObject( hSHP, i );
+ SHPWriteObject( cSHP, -1, shape );
+ SHPDestroyObject ( shape );
+
+ }
+
+ SHPClose( hSHP );
+ SHPClose( cSHP );
+
+ exit( 0 );
+}
diff --git a/src/shapelib/contrib/shpcentrd.c b/src/shapelib/contrib/shpcentrd.c
new file mode 100644
index 0000000..9af9895
--- /dev/null
+++ b/src/shapelib/contrib/shpcentrd.c
@@ -0,0 +1,190 @@
+/******************************************************************************
+ * Copyright (c) 1999, Carl Anderson
+ *
+ * this code is based in part on the earlier work of Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * shpcentrd.c - compute XY centroid for complex shapes
+ * and create a new SHPT_PT file of then
+ * specifically undo compound objects but not complex ones
+ *
+ *
+ * $Log: shpcentrd.c,v $
+ * Revision 1.4 2010/07/11 07:51:03 we7u
+ * Fixing more compiler warnings. There are a few left yet.
+ *
+ * Revision 1.3 2010/07/11 07:24:37 we7u
+ * Fixing multiple minor warnings with Shapelib. Still plenty left.
+ *
+ * Revision 1.2 2007/07/25 15:45:27 we7u
+ * Adding includes necessary for warning-free compiles.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.2 1999/05/26 02:56:31 candrsn
+ * updates to shpdxf, dbfinfo, port from Shapelib 1.1.5 of dbfcat and shpinfo
+ *
+ *
+ *
+ */
+
+
+/* the centroid is defined as
+ *
+ * Cx = sum (x dArea ) / Total Area
+ * and
+ * Cy = sum (y dArea ) / Total Area
+ */
+
+#include "shapefil.h"
+#include "shpgeo.h"
+#include <string.h>
+
+int main( int argc, char ** argv )
+
+{
+ SHPHandle old_SHP, new_SHP;
+ DBFHandle old_DBF, new_DBF;
+ int nShapeType, nEntities, i;
+// int nVertices, nParts, *panParts, iPart;
+// double *padVertices, adBounds[4];
+// const char *pszPlus;
+// DBFFieldType idfld_type;
+// int idfld, nflds;
+// char kv[257] = "";
+// char idfldName[120] = "";
+// char fldName[120] = "";
+// char shpFileName[120] = "";
+// char dbfFileName[120] = "";
+// double apeture[4];
+ char *DBFRow = NULL;
+// int Cpan[2] = { 0,0 };
+ int byRing = 1;
+ PT Centrd;
+ SHPObject *psCShape, *cent_pt;
+
+
+ if( argc < 3 )
+ {
+ printf( "shpcentrd shp_file new_shp_file\n" );
+ exit( 1 );
+ }
+
+ old_SHP = SHPOpen (argv[1], "rb" );
+ old_DBF = DBFOpen (argv[1], "rb");
+ if( old_SHP == NULL || old_DBF == NULL )
+ {
+ printf( "Unable to open old files:%s\n", argv[1] );
+ exit( 1 );
+ }
+
+ SHPGetInfo( old_SHP, &nEntities, &nShapeType, NULL, NULL );
+ new_SHP = SHPCreate ( argv[2], SHPT_POINT );
+
+ new_DBF = DBFCloneEmpty (old_DBF, argv[2]);
+ if( new_SHP == NULL || new_DBF == NULL )
+ {
+ printf( "Unable to create new files:%s\n", argv[2] );
+ exit( 1 );
+ }
+
+ DBFRow = (char *) malloc ( (old_DBF->nRecordLength) + 15 );
+
+
+#ifdef DEBUG
+ printf ("ShpCentrd using shpgeo \n");
+#endif
+
+ for( i = 0; i < nEntities; i++ )
+ {
+// int res ;
+
+ psCShape = SHPReadObject( old_SHP, i );
+
+ if ( byRing == 1 ) {
+ int ring;
+ for ( ring = 0; ring < psCShape->nParts; ring ++ ) {
+ SHPObject *psO;
+ psO = SHPClone ( psCShape, ring, ring + 1 );
+
+ Centrd = SHPCentrd_2d ( psO );
+
+ cent_pt = SHPCreateSimpleObject ( SHPT_POINT, 1,
+ (double*) &(Centrd.x), (double*) &(Centrd.y), NULL );
+
+ SHPWriteObject ( new_SHP, -1, cent_pt );
+
+ memcpy ( DBFRow, DBFReadTuple ( old_DBF, i ),
+ old_DBF->nRecordLength );
+ DBFWriteTuple ( new_DBF, new_DBF->nRecords, DBFRow );
+
+ SHPDestroyObject ( cent_pt );
+
+ SHPDestroyObject ( psO );
+ }
+
+ }
+ else {
+
+ Centrd = SHPCentrd_2d ( psCShape );
+
+ cent_pt = SHPCreateSimpleObject ( SHPT_POINT, 1,
+ (double*) &(Centrd.x), (double*) &(Centrd.y), NULL );
+
+ SHPWriteObject ( new_SHP, -1, cent_pt );
+
+ memcpy ( DBFRow, DBFReadTuple ( old_DBF, i ),
+ old_DBF->nRecordLength );
+ DBFWriteTuple ( new_DBF, new_DBF->nRecords, DBFRow );
+
+ SHPDestroyObject ( cent_pt );
+ }
+ }
+
+ SHPClose( old_SHP );
+ SHPClose( new_SHP );
+ DBFClose( old_DBF );
+ DBFClose( new_DBF );
+ printf ("\n");
+ return(0);
+}
+
diff --git a/src/shapelib/contrib/shpdata.c b/src/shapelib/contrib/shpdata.c
new file mode 100644
index 0000000..f1b6dba
--- /dev/null
+++ b/src/shapelib/contrib/shpdata.c
@@ -0,0 +1,164 @@
+/******************************************************************************
+ * Copyright (c) 1999, Carl Anderson
+ *
+ * this code is based in part on the earlier work of Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * shpdata.c - utility program for testing elements of the libraries
+ *
+ *
+ * $Log: shpdata.c,v $
+ * Revision 1.3 2010/07/11 07:51:03 we7u
+ * Fixing more compiler warnings. There are a few left yet.
+ *
+ * Revision 1.2 2010/07/11 07:24:37 we7u
+ * Fixing multiple minor warnings with Shapelib. Still plenty left.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.2 1999/05/26 02:56:31 candrsn
+ * updates to shpdxf, dbfinfo, port from Shapelib 1.1.5 of dbfcat and shpinfo
+ *
+ *
+ *
+ */
+
+
+#include "shapefil.h"
+#include "shpgeo.h"
+
+int main( int argc, char ** argv )
+
+{
+ SHPHandle old_SHP;
+// SHPHandle new_SHP;
+ DBFHandle old_DBF;
+// DBFHandle new_DBF;
+ int nShapeType, nEntities, i;
+// int nVertices, nParts, *panParts, iPart;
+// double *padVertices, adBounds[4];
+// const char *pszPlus;
+// DBFFieldType idfld_type;
+// int idfld, nflds;
+// char kv[257] = "";
+// char idfldName[120] = "";
+// char fldName[120] = "";
+// char shpFileName[120] = "";
+// char dbfFileName[120] = "";
+// char *DBFRow = NULL;
+// int Cpan[2] = { 0,0 };
+ int byRing = 1;
+ PT oCentrd, ringCentrd;
+ SHPObject *psCShape;
+// SHPObject *cent_pt;
+ double oArea = 0.0, oLen = 0.0;
+
+ if( argc < 2 )
+ {
+ printf( "shpdata shp_file \n" );
+ exit( 1 );
+ }
+
+ old_SHP = SHPOpen (argv[1], "rb" );
+ old_DBF = DBFOpen (argv[1], "rb");
+ if( old_SHP == NULL || old_DBF == NULL )
+ {
+ printf( "Unable to open old files:%s\n", argv[1] );
+ exit( 1 );
+ }
+
+ SHPGetInfo( old_SHP, &nEntities, &nShapeType, NULL, NULL );
+ for( i = 0; i < nEntities; i++ )
+ {
+// int res ;
+
+ psCShape = SHPReadObject( old_SHP, i );
+
+ if ( byRing == 1 ) {
+ int ring, prevStart, ringDir;
+ double ringArea;
+
+ prevStart = psCShape->nVertices;
+ for ( ring = (psCShape->nParts - 1); ring >= 0; ring-- ) {
+ SHPObject *psO;
+ int numVtx, rStart;
+// int j;
+
+ rStart = psCShape->panPartStart[ring];
+ if ( ring == (psCShape->nParts -1) )
+ { numVtx = psCShape->nVertices - rStart; }
+ else
+ { numVtx = psCShape->panPartStart[ring+1] - rStart; }
+
+ printf ("(shpdata) Ring(%d) (%d for %d) \n", ring, rStart, numVtx);
+ psO = SHPClone ( psCShape, ring, ring + 1 );
+
+ ringDir = SHPRingDir_2d ( psO, 0 );
+ ringArea = RingArea_2d (psO->nVertices,(double*) psO->padfX,
+ (double*) psO->padfY);
+ RingCentroid_2d ( psO->nVertices, (double*) psO->padfX,
+ (double*) psO->padfY, &ringCentrd, &ringArea);
+
+
+ printf ("(shpdata) Ring %d, %f Area %d dir \n",
+ ring, ringArea, ringDir );
+
+ SHPDestroyObject ( psO );
+ printf ("(shpdata) End Ring \n");
+ } /* (ring) [0,nParts */
+
+ } /* by ring */
+
+ oArea = SHPArea_2d ( psCShape );
+ oLen = SHPLength_2d ( psCShape );
+ oCentrd = SHPCentrd_2d ( psCShape );
+ printf ("(shpdata) Part (%d) %f Area %f length, C (%f,%f)\n",
+ i, oArea, oLen, oCentrd.x, oCentrd.y );
+ }
+
+ SHPClose( old_SHP );
+
+ DBFClose( old_DBF );
+
+ printf ("\n");
+ return(0);
+}
diff --git a/src/shapelib/contrib/shpdxf.c b/src/shapelib/contrib/shpdxf.c
new file mode 100644
index 0000000..975aa4c
--- /dev/null
+++ b/src/shapelib/contrib/shpdxf.c
@@ -0,0 +1,328 @@
+/******************************************************************************
+ * Copyright (c) 1999, Carl Anderson
+ *
+ * This code is based in part on the earlier work of Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * shp2dxf.c
+ *
+ * derived from a ESRI Avenue Script
+ * and DXF specification from AutoCad 3 (yes 1984)
+ *
+ * modifications Carl Andrson 11/96
+ * modifications Carl Andrson 3/97
+ *
+ * converted to C code 12/98
+ *
+ * requires shapelib 1.2
+ * gcc shpdxf.c shpopen.o dbfopen.o -o shpdxf
+ *
+ */
+
+#include "shapefil.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define FLOAT_PREC "%16.5f\r\n"
+
+void dxf_hdr (double x1, double y1, double x2, double y2, FILE *df)
+{
+/* Create HEADER section */
+
+ fprintf( df, " 0\r\n");
+ fprintf( df, "SECTION\r\n");
+ fprintf( df, " 2\r\n" );
+ fprintf( df, "HEADER\r\n" );
+ fprintf( df, " 9\r\n" );
+ fprintf( df, "$EXTMAX\r\n" );
+ fprintf( df, " 10\r\n" );
+ fprintf( df, FLOAT_PREC, x2 );
+ fprintf( df, " 20\r\n" );
+ fprintf( df, FLOAT_PREC, y2 );
+ fprintf( df, " 9\r\n" );
+ fprintf( df, "$EXTMIN\r\n" );
+ fprintf( df, " 10\r\n" );
+ fprintf( df, FLOAT_PREC, x1 );
+ fprintf( df, " 20\r\n" );
+ fprintf( df, FLOAT_PREC, y1 );
+ fprintf( df, " 9\r\n" );
+ fprintf( df, "$LUPREC\r\n" );
+ fprintf( df, " 70\r\n" );
+ fprintf( df, " 14\r\n" );
+ fprintf( df, " 0\r\n" );
+ fprintf( df, "ENDSEC\r\n" );
+
+/* ' Create TABLES section */
+
+ fprintf( df, " 0\r\n" );
+ fprintf( df, "SECTION\r\n" );
+ fprintf( df, " 2\r\n" );
+ fprintf( df, "TABLES\r\n" );
+/* ' Table 1 - set up line type */
+ fprintf( df, " 0\r\n" );
+ fprintf( df, "TABLE\r\n" );
+ fprintf( df, " 2\r\n" );
+ fprintf( df, "LTYPE\r\n" );
+ fprintf( df, " 70\r\n" );
+ fprintf( df, "2\r\n" );
+/* ' Entry 1 of Table 1 */
+ fprintf( df, " 0\r\n" );
+ fprintf( df, "LTYPE\r\n" );
+ fprintf( df, " 2\r\n" );
+ fprintf( df, "CONTINUOUS\r\n" );
+ fprintf( df, " 70\r\n" );
+ fprintf( df, "64\r\n" );
+ fprintf( df, " 3\r\n" );
+ fprintf( df, "Solid line\r\n" );
+ fprintf( df, " 72\r\n" );
+ fprintf( df, "65\r\n" );
+ fprintf( df, " 73\r\n" );
+ fprintf( df, "0\r\n" );
+ fprintf( df, " 40\r\n" );
+ fprintf( df, "0.0\r\n" );
+ fprintf( df, " 0\r\n" );
+ fprintf( df, "ENDTAB\r\n" );
+ /* End of TABLES section */
+ fprintf( df, " 0\r\n" );
+ fprintf( df, "ENDSEC\r\n" );
+
+ /* Create BLOCKS section */
+
+ fprintf( df, " 0\r\n" );
+ fprintf( df, "SECTION\r\n" );
+ fprintf( df, " 2\r\n" );
+ fprintf( df, "BLOCKS\r\n" );
+ fprintf( df, " 0\r\n" );
+ fprintf( df, "ENDSEC\r\n" );
+ fprintf( df, " 0\r\n" );
+ fprintf( df, "SECTION\r\n" );
+ fprintf( df, " 2\r\n" );
+ fprintf( df, "ENTITIES\r\n" );
+
+}
+
+
+void dxf_ent_preamble (int dxf_type, char *id, FILE *df)
+{
+
+ fprintf( df, " 0\r\n" );
+
+ switch (dxf_type) {
+ case SHPT_POLYGON:
+ case SHPT_ARC: fprintf (df, "POLYLINE\r\n");
+ break;
+ default: fprintf(df, "POINT\r\n");
+ }
+
+ fprintf( df, " 8\r\n");
+ fprintf( df, "%s\r\n", id );
+ switch ( dxf_type ) {
+ case SHPT_ARC:
+ fprintf( df, " 6\r\n" );
+ fprintf( df, "CONTINUOUS\r\n" );
+ fprintf( df, " 66\r\n" );
+ fprintf( df, "1\r\n" );
+ break;
+ case SHPT_POLYGON:
+ fprintf( df, " 6\r\n" );
+ fprintf( df, "CONTINUOUS\r\n" );
+ fprintf( df, " 66\r\n" );
+ fprintf( df, "1\r\n" );
+ fprintf( df, " 70\r\n");
+ fprintf (df, "1\r\n");
+ default: break;
+ }
+
+}
+
+void dxf_ent (char *id, double x, double y, double z, int dxf_type, FILE *df)
+{
+ if ((dxf_type == SHPT_ARC) || ( dxf_type == SHPT_POLYGON)) {
+ fprintf( df, " 0\r\n");
+ fprintf( df, "VERTEX\r\n");
+ fprintf( df, " 8\r\n");
+ fprintf( df, "%s\r\n", id);
+ }
+ fprintf( df, " 10\r\n" );
+ fprintf( df, FLOAT_PREC, x );
+ fprintf( df, " 20\r\n" );
+ fprintf( df, FLOAT_PREC, y );
+ fprintf( df, " 30\r\n" );
+ if ( z != 0 )
+ fprintf( df, FLOAT_PREC, z );
+ else
+ fprintf( df, "0.0\r\n" );
+}
+
+
+void dxf_ent_postamble (int dxf_type, FILE *df)
+{
+ if ((dxf_type == SHPT_ARC) || ( dxf_type == SHPT_POLYGON))
+ fprintf( df, " 0\r\nSEQEND\r\n 8\r\n0\r\n");
+}
+
+
+int
+main (int argc, char **argv)
+
+{
+ char shpFileName[80] = "", dbfFileName[80] = "";
+ char dxfFileName[80] = "";
+ char idfldName[15];
+ char zfldName[6] = "ELEV";
+ char fldName[15];
+ char id[255];
+ double elev;
+ int *panParts, nParts, nVertices;
+// int parts;
+ FILE *dxf;
+ SHPHandle shp;
+ DBFHandle dbf;
+ DBFFieldType idfld_type = FTInvalid;
+ double adfBoundsMin[4], adfBoundsMax[4];
+ int vrtx, shp_type, shp_numrec, zfld, idfld, nflds, recNum, part;
+ int MaxElem = 0;
+
+ if ( argc < 2 ) {
+ printf ("usage: shpdxf shapefile {idfield}\r\n");
+ exit (-1);
+ }
+
+ strcpy (shpFileName,argv[1]);
+ strncpy (dbfFileName, shpFileName, strlen(shpFileName)-3);
+ strcat (dbfFileName,"dbf");
+
+ strncpy (dxfFileName, shpFileName,strlen(shpFileName)-3);
+ strcat( dxfFileName, "dxf");
+
+ shp = SHPOpen (shpFileName, "rb");
+ dbf = DBFOpen (dbfFileName, "rb");
+ dxf = fopen( dxfFileName, "w");
+
+ printf("Starting conversion %s(%s) -> %s\r\n",
+ shpFileName,dbfFileName,dxfFileName);
+
+ SHPGetInfo (shp, &shp_numrec, &shp_type, adfBoundsMin, adfBoundsMax );
+ printf ("file has %d objects\r\n", shp_numrec);
+ dxf_hdr(adfBoundsMin[0], adfBoundsMin[1], adfBoundsMax[0], adfBoundsMax[1],
+ dxf);
+
+/* Before proceeding, allow the user to specify the ID field to use or default to the record number.... */
+
+ if ( argc > 3 ) MaxElem = atoi(argv[3]);
+
+ nflds = DBFGetFieldCount(dbf);
+ if ( argc > 2 ) {
+ strcpy (idfldName, argv[2]);
+ for ( idfld=0; idfld < nflds; idfld++ ) {
+ idfld_type = DBFGetFieldInfo( dbf, idfld, fldName, NULL, NULL);
+ if (!strcmp (idfldName, fldName ))
+ break;
+ }
+ if ( idfld >= nflds ) {
+ printf ("Id field %s not found, using default\r\n",idfldName);
+ idfld = -1;
+ } else
+ printf ("proceeding with field %s for LayerNames\r\n",fldName);
+ }
+ else
+ idfld = -1;
+
+ for ( zfld=0; zfld < nflds; zfld++ ) {
+ DBFGetFieldInfo( dbf, zfld, fldName, NULL, NULL);
+ if (!strcmp (zfldName, fldName ))
+ break;
+ }
+ if ( zfld >= nflds )
+ zfld = -1;
+// printf ("proceeding with id = %d, elevation = %d\r\n",idfld, zfld);
+
+/* Proceed to process data..... */
+
+ for ( recNum = 0; (recNum < shp_numrec) && (recNum < MaxElem); recNum++) {
+
+ SHPObject *shape;
+
+ if ( idfld >= 0 )
+ switch (idfld_type) {
+ case FTString: sprintf (id, "lvl_%s",DBFReadStringAttribute ( dbf, recNum, idfld ));
+ break;
+ default: sprintf(id, "%-20.0lf", DBFReadDoubleAttribute (dbf, recNum, idfld));
+ }
+ else
+ sprintf (id,"lvl_%-20d",(recNum +1 ));
+
+
+ if ( zfld >= 0 )
+ elev = 0;
+ else
+ elev = DBFReadDoubleAttribute ( dbf, recNum, zfld );
+
+#ifdef DEBUG
+ printf("\r\nworking on obj %d", recNum);
+#endif
+
+ shape = SHPReadObject( shp, recNum );
+
+ nVertices = shape->nVertices;
+ nParts = shape->nParts;
+ panParts = shape->panPartStart;
+ part = 0;
+ for (vrtx=0; vrtx < nVertices; vrtx ++ ) {
+#ifdef DEBUG
+ printf("\rworking on part %d, vertex %d", part,vrtx);
+#endif
+ if ( panParts[part] == vrtx ) {
+#ifdef DEBUG
+ printf ("object preamble\r\n");
+#endif
+ dxf_ent_preamble (shp_type, id, dxf);
+ }
+
+ dxf_ent (id, shape->padfX[vrtx], shape->padfY[vrtx],
+ elev, shp_type, dxf);
+
+ if ((panParts[part] == (vrtx + 1))|| (vrtx == (nVertices -1)) ) {
+ dxf_ent_postamble (shp_type, dxf);
+ part ++;
+ }
+ }
+ SHPDestroyObject( shape );
+ }
+
+/* close out DXF file */
+ fprintf( dxf, "0\r\n" );
+ fprintf( dxf, "ENDSEC\r\n" );
+ fprintf( dxf, "0\r\n" );
+ fprintf( dxf, "EOF\r\n" );
+
+
+ SHPClose (shp);
+ DBFClose (dbf);
+ fclose (dxf);
+ return(0);
+}
+
+
+
+
+
+
diff --git a/src/shapelib/contrib/shpfix.c b/src/shapelib/contrib/shpfix.c
new file mode 100644
index 0000000..a24ab6e
--- /dev/null
+++ b/src/shapelib/contrib/shpfix.c
@@ -0,0 +1,111 @@
+/******************************************************************************
+ * Copyright (c) 1999, Carl Anderson
+ *
+ * This code is based in part on the earlier work of Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ * shpfix
+ *
+ *
+ * gcc -c shpfix.c shpopen.c -o shpfix
+ *
+ * Utility program to fix nulls and inconsistencies in Shapefiles
+ * as happens from time to time
+ *
+ * Simply load and rewrite each record, parameter fixrex allow user to null
+ * a particularly nasty record if needed
+ *
+ */
+
+#include "shapefil.h"
+#include <stdlib.h>
+
+int main( int argc, char ** argv )
+
+{
+ SHPHandle hSHP, cSHP;
+ int nShapeType, cShapeType, nEntities, i;
+ double adBounds[4];
+ SHPObject *shape;
+ int fix_rec;
+
+/* -------------------------------------------------------------------- */
+/* Display a usage message. */
+/* -------------------------------------------------------------------- */
+ if( argc <= 3 )
+ {
+ printf( "shpfix shpfile new_file <Record# to Blank>\n" );
+ exit( 1 );
+ }
+
+ fix_rec = atoi (argv[3]);
+ fix_rec --;
+
+/* -------------------------------------------------------------------- */
+/* Open the passed shapefile. */
+/* -------------------------------------------------------------------- */
+ hSHP = SHPOpen( argv[1], "rb+" );
+
+ if( hSHP == NULL )
+ {
+ printf( "Unable to open:%s\n", argv[1] );
+ exit( 1 );
+ }
+
+ SHPGetInfo( hSHP, &nEntities, &nShapeType, NULL, NULL );
+
+
+/* -------------------------------------------------------------------- */
+/* Open the passed shapefile. */
+/* -------------------------------------------------------------------- */
+ cSHP = SHPCreate( argv[2], nShapeType );
+
+ if( cSHP == NULL )
+ {
+ printf( "Unable to open:%s\n", argv[2] );
+ exit( 1 );
+ }
+
+ SHPGetInfo( cSHP, NULL, &cShapeType, &(adBounds[0]), &(adBounds[2]) );
+
+
+/* -------------------------------------------------------------------- */
+/* Skim over the list of shapes, printing all the vertices. */
+/* -------------------------------------------------------------------- */
+
+ for( i = 0; i < nEntities; i++ )
+ {
+
+ shape = SHPReadObject( hSHP, i );
+ if ( i == fix_rec )
+ { shape->nParts = 0;
+ shape->nVertices = 0;
+ }
+ SHPWriteObject( cSHP, -1, shape );
+ SHPDestroyObject ( shape );
+
+ }
+
+
+ SHPClose ( hSHP );
+ SHPClose ( cSHP );
+ return(0);
+}
+
diff --git a/src/shapelib/contrib/shpgeo.c b/src/shapelib/contrib/shpgeo.c
new file mode 100644
index 0000000..2b7162e
--- /dev/null
+++ b/src/shapelib/contrib/shpgeo.c
@@ -0,0 +1,1642 @@
+/******************************************************************************
+ * Copyright (c) 1999, Carl Anderson
+ *
+ * This code is based in part on the earlier work of Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * requires shapelib 1.2
+ * gcc shpproj shpopen.o dbfopen.o -lm -lproj -o shpproj
+ *
+ * this may require linking with the PROJ4 projection library available from
+ *
+ * http://www.remotesensing.org/proj
+ *
+ * use -DPROJ4 to compile in Projection support
+ *
+ * $Log: shpgeo.c,v $
+ * Revision 1.5 2010/07/13 06:12:22 we7u
+ * Attempting to fix the "endian-ness" tests.
+ *
+ * Revision 1.4 2010/07/11 20:30:00 we7u
+ * More minor tweaks to get rid of compiler warnings. Of particular note are
+ * some TODO entries added to a couple of files for two enumerated values that
+ * weren't being handled in "switch" statements. There still isn't any code
+ * for those case statements, but the compiler warnings are gone.
+ *
+ * Revision 1.3 2010/07/11 07:24:37 we7u
+ * Fixing multiple minor warnings with Shapelib. Still plenty left.
+ *
+ * Revision 1.2 2007/07/25 15:45:27 we7u
+ * Adding includes necessary for warning-free compiles.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.8 2002/01/15 14:36:56 warmerda
+ * upgrade to use proj_api.h
+ *
+ * Revision 1.7 2002/01/11 15:22:04 warmerda
+ * fix many warnings. Lots of this code is cruft.
+ *
+ * Revision 1.6 2001/08/30 13:42:31 warmerda
+ * avoid use of auto initialization of PT for VC++
+ *
+ * Revision 1.5 2000/04/26 13:24:06 warmerda
+ * made projUV handling safer
+ *
+ * Revision 1.4 2000/04/26 13:17:15 warmerda
+ * check if projUV or UV
+ *
+ * Revision 1.3 2000/03/17 14:15:16 warmerda
+ * Don't try to use system nan.h ... doesn't always exist.
+ *
+ * Revision 1.2 1999/05/26 02:56:31 candrsn
+ * updates to shpdxf, dbfinfo, port from Shapelib 1.1.5 of dbfcat and shpinfo
+ *
+ */
+
+#include "shapefil.h"
+#include <string.h>
+#include <math.h>
+
+#ifndef NAN
+#include "my_nan.h"
+#endif
+
+#include "shpgeo.h"
+
+
+ /* I'm using some shorthand throughout this file
+ * R+ is a Clockwise Ring and is the positive portion of an object
+ * R- is a CounterClockwise Ring and is a hole in a R+
+ * A complex object is one having at least one R-
+ * A compound object is one having more than one R+
+ * A simple object has one and only one element (R+ or R-)
+ *
+ * The closed ring constraint is for polygons and assumed here
+ * Arcs or LineStrings I am calling Rings (generically open or closed)
+ * Point types are vertices or lists of vertices but not Rings
+ *
+ * SHPT_POLYGON, SHPT_POLYGONZ, SHPT_POLYGONM and SHPT_MULTIPATCH
+ * can have SHPObjects that are compound as well as complex
+ *
+ * SHP_POINT and its Z and M derivatives are strictly simple
+ * MULTI_POINT, SHPT_ARC and their derivatives may be simple or compound
+ *
+ */
+
+
+/* **************************************************************************
+ * asFileName
+ *
+ * utility function, toss part of filename after last dot
+ *
+ * **************************************************************************/
+char * asFileName ( const char *fil, char *ext ) {
+ char pszBasename[120];
+ static char pszFullname[120];
+ int i;
+/* -------------------------------------------------------------------- */
+/* Compute the base (layer) name. If there is any extension */
+/* on the passed in filename we will strip it off. */
+/* -------------------------------------------------------------------- */
+// pszFullname = (char*) malloc(( strlen(fil)+5 ));
+// pszBasename = (char *) malloc(strlen(fil)+5);
+ strcpy( pszBasename, fil );
+ for( i = strlen(pszBasename)-1;
+ i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+ && pszBasename[i] != '\\';
+ i-- ) {}
+
+ if( pszBasename[i] == '.' )
+ pszBasename[i] = '\0';
+
+/* -------------------------------------------------------------------- */
+/* Note that files pulled from */
+/* a PC to Unix with upper case filenames won't work! */
+/* -------------------------------------------------------------------- */
+// pszFullname = (char *) malloc(strlen(pszBasename) + 5);
+ sprintf( pszFullname, "%s.%s", pszBasename, ext );
+
+ return ( pszFullname );
+}
+
+
+/************************************************************************/
+/* SfRealloc() */
+/* */
+/* A realloc cover function that will access a NULL pointer as */
+/* a valid input. */
+/************************************************************************/
+/* copied directly from shpopen.c -- maybe expose this in shapefil.h */
+static void * SfRealloc( void * pMem, int nNewSize )
+
+{
+ if( pMem == NULL )
+ return( (void *) malloc(nNewSize) );
+ else
+ return( (void *) realloc(pMem,nNewSize) );
+}
+
+
+/* **************************************************************************
+ * SHPPRoject
+ *
+ * Project points using projection handles, for use with PROJ4.3
+ *
+ * act as a wrapper to protect against library changes in PROJ
+ *
+ * **************************************************************************/
+int SHPProject ( SHPObject *psCShape, projPJ inproj, projPJ outproj ) {
+#ifdef PROJ4
+ int j;
+ projUV p; /* struct { double u, double v } */
+
+ /* for each vertex project it and stuff the projeted point back into */
+ /* same SHPObject. Proj assumes data is in radians so convert it. */
+ /* Proj will convert Geographic -> <proj> and <proj> -> Geographic */
+ /* so <proj1> -> <proj2> requires bouncing though geographic */
+
+ for ( j=0; j < psCShape->nVertices; j++ ) {
+ p.u = psCShape->padfX[j];
+ p.v = psCShape->padfY[j];
+
+ if ( inproj )
+ p = pj_inv ( p, inproj );
+ else
+ { p.u *= DEG_TO_RAD;
+ p.v *= DEG_TO_RAD;
+ }
+
+ if ( outproj )
+ p = pj_fwd ( p, outproj );
+ else
+ { p.u *= RAD_TO_DEG;
+ p.v *= RAD_TO_DEG;
+ }
+
+ psCShape->padfX[j] = p.u;
+ psCShape->padfY[j] = p.v;
+ }
+
+ /* Recompute new Extents of projected Object */
+ SHPComputeExtents ( psCShape );
+#endif
+
+ return ( 1 );
+}
+
+
+/* **************************************************************************
+ * SHPSetProjection
+ *
+ * establish a projection handle for use with PROJ4.3
+ *
+ * act as a wrapper to protect against library changes in PROJ
+ *
+ * **************************************************************************/
+projPJ SHPSetProjection ( int param_cnt, char **params ) {
+#ifdef PROJ4
+ projPJ *p = NULL;
+
+ if ( param_cnt > 0 && params[0] )
+ { p = pj_init ( param_cnt, params ); }
+
+ return ( p );
+#else
+ return ( NULL );
+#endif
+}
+
+
+/* **************************************************************************
+ * SHPFreeProjection
+ *
+ * release a projection handle for use with PROJ4.3
+ *
+ * act as a wrapper to protect against library changes in PROJ
+ *
+ * **************************************************************************/
+int SHPFreeProjection ( projPJ p) {
+#ifdef PROJ4
+ if ( p )
+ pj_free ( p );
+#endif
+ return ( 1 );
+}
+
+
+/* **************************************************************************
+ * SHPOGisType
+ *
+ * Convert Both ways from and to OGIS Geometry Types
+ *
+ * **************************************************************************/
+int SHPOGisType ( int GeomType, int toOGis) {
+
+ if ( toOGis == 0 ) /* connect OGis -> SHP types */
+ switch (GeomType) {
+ case (OGIST_POINT): return ( SHPT_POINT ); break;
+ case (OGIST_LINESTRING): return ( SHPT_ARC ); break;
+ case (OGIST_POLYGON): return ( SHPT_POLYGON ); break;
+ case (OGIST_MULTIPOINT): return ( SHPT_MULTIPOINT ); break;
+ case (OGIST_MULTILINE): return ( SHPT_ARC ); break;
+ case (OGIST_MULTIPOLYGON): return ( SHPT_POLYGON ); break;
+ }
+ else /* ok so its SHP->OGis types */
+ switch (GeomType) {
+ case (SHPT_POINT): return ( OGIST_POINT ); break;
+ case (SHPT_POINTM): return ( OGIST_POINT ); break;
+ case (SHPT_POINTZ): return ( OGIST_POINT ); break;
+ case (SHPT_ARC): return ( OGIST_LINESTRING );break;
+ case (SHPT_ARCZ): return ( OGIST_LINESTRING );break;
+ case (SHPT_ARCM): return ( OGIST_LINESTRING );break;
+ case (SHPT_POLYGON): return ( OGIST_MULTIPOLYGON );break;
+ case (SHPT_POLYGONZ): return ( OGIST_MULTIPOLYGON );break;
+ case (SHPT_POLYGONM): return ( OGIST_MULTIPOLYGON );break;
+ case (SHPT_MULTIPOINT): return ( OGIST_MULTIPOINT );break;
+ case (SHPT_MULTIPOINTZ): return ( OGIST_MULTIPOINT );break;
+ case (SHPT_MULTIPOINTM): return ( OGIST_MULTIPOINT );break;
+ case (SHPT_MULTIPATCH): return ( OGIST_GEOMCOLL ); break;
+ }
+
+ return 0;
+}
+
+
+/* **************************************************************************
+ * SHPReadSHPStream
+ *
+ * Encapsulate entire SHPObject for use with Postgresql
+ *
+ * **************************************************************************/
+int SHPReadSHPStream ( SHPObject *psCShape, char *stream_obj) {
+
+//int obj_storage;
+int my_order, need_swap =0, GeoType =0 ;
+int use_Z = 0;
+int use_M = 0;
+
+ need_swap = stream_obj[0];
+ my_order = 1;
+ my_order = ((char*) (&my_order))[0];
+ need_swap = need_swap & my_order;
+
+ if ( need_swap )
+ swapW (stream_obj, (void*) &GeoType, sizeof (GeoType) );
+ else
+ memcpy (stream_obj, &GeoType, sizeof (GeoType) );
+
+
+ if ( need_swap ) {
+
+ } else {
+ memcpy (stream_obj, &(psCShape->nSHPType), sizeof (psCShape->nSHPType) );
+ memcpy (stream_obj, &(psCShape->nShapeId), sizeof (psCShape->nShapeId) );
+ memcpy (stream_obj, &(psCShape->nVertices), sizeof (psCShape->nVertices) );
+ memcpy (stream_obj, &(psCShape->nParts), sizeof (psCShape->nParts) );
+ memcpy (stream_obj, &(psCShape->dfXMin), sizeof (psCShape->dfXMin) );
+ memcpy (stream_obj, &(psCShape->dfYMin), sizeof (psCShape->dfYMin) );
+ memcpy (stream_obj, &(psCShape->dfXMax), sizeof (psCShape->dfXMax) );
+ memcpy (stream_obj, &(psCShape->dfYMax), sizeof (psCShape->dfYMax) );
+ if ( use_Z ) {
+ memcpy (stream_obj, &(psCShape->dfZMin), sizeof (psCShape->dfZMin) );
+ memcpy (stream_obj, &(psCShape->dfZMax), sizeof (psCShape->dfZMax) );
+ }
+
+ memcpy (stream_obj, psCShape->panPartStart, psCShape->nParts * sizeof (int) );
+ memcpy (stream_obj, psCShape->panPartType, psCShape->nParts * sizeof (int) );
+
+/* get X and Y coordinate arrarys */
+ memcpy (stream_obj, psCShape->padfX, psCShape->nVertices * 2 * sizeof (double) );
+
+/* get Z coordinate array if used */
+ if ( use_Z )
+ memcpy (stream_obj, psCShape->padfZ, psCShape->nVertices * 2 * sizeof (double) );
+/* get Measure coordinate array if used */
+ if ( use_M )
+ memcpy (stream_obj, psCShape->padfM, psCShape->nVertices * 2 * sizeof (double) );
+ } /* end put data without swap */
+
+ return (0);
+}
+
+
+/* **************************************************************************
+ * SHPWriteSHPStream
+ *
+ * Encapsulate entire SHPObject for use with Postgresql
+ *
+ * **************************************************************************/
+int SHPWriteSHPStream ( WKBStreamObj *stream_obj, SHPObject *psCShape ) {
+
+int obj_storage = 0;
+int need_swap = 0;
+//int my_order, GeoType;
+int use_Z = 0;
+int use_M = 0;
+
+ need_swap = 1;
+ need_swap = ((char*) (&need_swap))[0];
+
+ if ( !realloc (stream_obj, obj_storage ) ) {
+ return(1);
+ }
+
+ if ( need_swap ) {
+
+ } else {
+ memcpy (stream_obj, psCShape, 4 * sizeof (int) );
+ memcpy (stream_obj, psCShape, 4 * sizeof (double) );
+ if ( use_Z )
+ memcpy (stream_obj, psCShape, 2 * sizeof (double) );
+ if ( use_M )
+ memcpy (stream_obj, psCShape, 2 * sizeof (double) );
+
+ memcpy (stream_obj, psCShape, psCShape->nParts * 2 * sizeof (int) );
+ memcpy (stream_obj, psCShape, psCShape->nVertices * 2 * sizeof (double) );
+ if ( use_Z )
+ memcpy (stream_obj, psCShape, psCShape->nVertices * 2 * sizeof (double) );
+ if ( use_M )
+ memcpy (stream_obj, psCShape, psCShape->nVertices * 2 * sizeof (double) );
+ }
+
+ return (0);
+}
+
+
+/* **************************************************************************
+ * WKBStreamWrite
+ *
+ * Encapsulate entire SHPObject for use with Postgresql
+ *
+ * **************************************************************************/
+int WKBStreamWrite ( WKBStreamObj* wso, void* this, int tcount, int tsize ) {
+
+ if ( wso->NeedSwap )
+ SwapG ( &(wso->wStream[wso->StreamPos]), this, tcount, tsize );
+ else
+ memcpy ( &(wso->wStream[wso->StreamPos]), this, tsize * tcount );
+
+ wso->StreamPos += tsize;
+
+ return 0;
+}
+
+
+
+/* **************************************************************************
+ * WKBStreamRead
+ *
+ * Encapsulate entire SHPObject for use with Postgresql
+ *
+ * **************************************************************************/
+int WKBStreamRead ( WKBStreamObj* wso, void* this, int tcount, int tsize ) {
+
+ if ( wso->NeedSwap )
+ SwapG ( this, &(wso->wStream[wso->StreamPos]), tcount, tsize );
+ else
+ memcpy ( this, &(wso->wStream[wso->StreamPos]), tsize * tcount );
+
+ wso->StreamPos += tsize;
+
+ return 0;
+}
+
+
+
+/* **************************************************************************
+ * SHPReadOGisWKB
+ *
+ * Encapsulate entire SHPObject for use with Postgresql
+ *
+ * **************************************************************************/
+SHPObject* SHPReadOGisWKB ( WKBStreamObj *stream_obj) {
+ SHPObject *psCShape;
+ char WKB_order;
+// int need_swap = 0;
+ int my_order, GeoType = 0;
+// int use_Z = 0, use_M = 0;
+ int nSHPType, thisDim;
+
+ WKBStreamRead ( stream_obj, &WKB_order, 1, sizeof(char));
+ my_order = 1;
+ my_order = ((char*) (&my_order))[0];
+ stream_obj->NeedSwap = !(WKB_order & my_order);
+
+ /* convert OGis Types to SHP types */
+ nSHPType = SHPOGisType ( GeoType, 0 );
+
+ WKBStreamRead ( stream_obj, &GeoType, 1, sizeof(int));
+
+ thisDim = SHPDimension ( nSHPType );
+
+ if ( thisDim && SHPD_AREA )
+ { psCShape = SHPReadOGisPolygon ( stream_obj ); }
+ else {
+ if ( thisDim && SHPD_LINE )
+ { psCShape = SHPReadOGisLine ( stream_obj ); }
+ else {
+ if ( thisDim && SHPD_POINT )
+ { psCShape = SHPReadOGisPoint ( stream_obj ); }
+ }
+ }
+
+
+ return (0);
+}
+
+
+
+/* **************************************************************************
+ * SHPWriteOGisWKB
+ *
+ * Encapsulate entire SHPObject for use with Postgresql
+ *
+ * **************************************************************************/
+int SHPWriteOGisWKB ( WKBStreamObj* stream_obj, SHPObject *psCShape ) {
+
+// int need_swap = 0;
+ int my_order, GeoType, thisDim;
+// int use_Z = 0, use_M = 0;
+ char LSB = 1;
+ /* indicate that this WKB is in LSB Order */
+
+ /* OGis WKB can handle either byte order, but if I get to choose I'd
+ * rather have it predicatable system-to-system */
+
+ if ( stream_obj ) {
+ if ( stream_obj->wStream )
+ free ( stream_obj->wStream );
+ } else
+ { stream_obj = calloc ( 3, sizeof (int ) ); }
+
+ /* object size needs to be 9 bytes for the wrapper, and for each polygon */
+ /* another 9 bytes all plus twice the total number of vertices */
+ /* times the sizeof (double) and just pad with 10 more chars for fun */
+ stream_obj->wStream = calloc (1, (9 * (psCShape->nParts + 1)) +
+ ( sizeof(double) * 2 * psCShape->nVertices ) + 10 );
+
+ #ifdef DEBUG2
+ printf (" I just allocated %d bytes to wkbObj \n",
+ sizeof (int) + sizeof (int) + sizeof(int) +
+ ( sizeof(int) * psCShape->nParts + 1 ) +
+ ( sizeof(double) * 2 * psCShape->nVertices ) + 10 );
+ #endif
+
+ my_order = 1;
+ my_order = ((char*) (&my_order))[0];
+ /* Need to swap if this system is not LSB (Intel Order) */
+ stream_obj->NeedSwap = ( my_order != LSB );
+
+ stream_obj->StreamPos = 0;
+
+
+ #ifdef DEBUG2
+ printf ("this system is (%d) LSB recorded as needSwap %d\n",my_order, stream_obj->NeedSwap);
+ #endif
+
+ WKBStreamWrite ( stream_obj, & LSB, 1, sizeof(char) );
+
+ #ifdef DEBUG2
+ printf ("this system in (%d) LSB \n");
+ #endif
+
+
+ /* convert SHP Types to OGis types */
+ GeoType = SHPOGisType ( psCShape->nSHPType, 1 );
+ WKBStreamWrite ( stream_obj, &GeoType, 1, sizeof(int) );
+
+ thisDim = SHPDimension ( psCShape->nSHPType );
+
+ if ( thisDim && SHPD_AREA )
+ { SHPWriteOGisPolygon ( stream_obj, psCShape ); }
+ else {
+ if ( thisDim && SHPD_LINE )
+ { SHPWriteOGisLine ( stream_obj, psCShape ); }
+ else {
+ if ( thisDim && SHPD_POINT )
+ { SHPWriteOGisPoint ( stream_obj, psCShape ); }
+ }
+ }
+
+#ifdef DEBUG2
+ printf("(SHPWriteOGisWKB) outta here when stream pos is %d \n", stream_obj->StreamPos);
+#endif
+ return (0);
+}
+
+
+/* **************************************************************************
+ * SHPWriteOGisPolygon
+ *
+ * for this pass code to more generic OGis MultiPolygon Type
+ * later add support for OGis Polygon Type
+ *
+ * Encapsulate entire SHPObject for use with Postgresql
+ *
+ * **************************************************************************/
+int SHPWriteOGisPolygon ( WKBStreamObj *stream_obj, SHPObject *psCShape ) {
+ SHPObject **ppsC;
+ SHPObject *psC;
+ int rPart, ring, rVertices, cpart, cParts, nextring, j;
+// int i;
+ char Flag = 1;
+ int GeoType = OGIST_POLYGON;
+
+ /* cant have more than nParts complex objects in this object */
+ ppsC = calloc ( psCShape->nParts, sizeof(int) );
+
+
+ nextring = 0;
+ cParts=0;
+ while ( nextring >= 0 ) {
+ ppsC[cParts] = SHPUnCompound ( psCShape, &nextring );
+ cParts++;
+ }
+
+#ifdef DEBUG2
+ printf ("(SHPWriteOGisPolygon) Uncompounded into %d parts \n", cParts);
+#endif
+
+ WKBStreamWrite ( stream_obj, &cParts, 1, sizeof(int) );
+
+ for ( cpart = 0; cpart < cParts; cpart++) {
+
+ WKBStreamWrite ( stream_obj, & Flag, 1, sizeof(char) );
+ WKBStreamWrite ( stream_obj, & GeoType, 1, sizeof(int) );
+
+ psC = (SHPObject*) ppsC[cpart];
+ WKBStreamWrite ( stream_obj, &(psC->nParts), 1, sizeof(int) );
+
+ for ( ring = 0; (ring < (psC->nParts)) && (psC->nParts > 0); ring ++) {
+ if ( ring < (psC->nParts-2) )
+ { rVertices = psC->panPartStart[ring+1] - psC->panPartStart[ring]; }
+ else
+ { rVertices = psC->nVertices - psC->panPartStart[ring]; }
+#ifdef DEBUG2
+ printf ("(SHPWriteOGisPolygon) scanning part %d, ring %d %d vtxs \n",
+ cpart, ring, rVertices);
+#endif
+ rPart = psC->panPartStart[ring];
+ WKBStreamWrite ( stream_obj, &rVertices, 1, sizeof(int) );
+ for ( j=rPart; j < (rPart + rVertices); j++ ) {
+ WKBStreamWrite ( stream_obj, &(psC->padfX[j]), 1, sizeof(double) );
+ WKBStreamWrite ( stream_obj, &(psC->padfY[j]), 1, sizeof(double) );
+ } /* for each vertex */
+ } /* for each ring */
+ } /* for each complex part */
+
+#ifdef DEBUG2
+ printf ("(SHPWriteOGisPolygon) outta here \n");
+#endif
+ return (1);
+}
+
+
+/* **************************************************************************
+ * SHPWriteOGisLine
+ *
+ * for this pass code to more generic OGis MultiXXXXXXX Type
+ * later add support for OGis LineString Type
+ *
+ * Encapsulate entire SHPObject for use with Postgresql
+ *
+ * **************************************************************************/
+int SHPWriteOGisLine ( WKBStreamObj *stream_obj, SHPObject *psCShape ) {
+
+ return ( SHPWriteOGisPolygon( stream_obj, psCShape ));
+}
+
+
+/* **************************************************************************
+ * SHPWriteOGisPoint
+ *
+ * for this pass code to more generic OGis MultiPoint Type
+ * later add support for OGis Point Type
+ *
+ * Encapsulate entire SHPObject for use with Postgresql
+ *
+ * **************************************************************************/
+int SHPWriteOGisPoint ( WKBStreamObj *stream_obj, SHPObject *psCShape ) {
+ int j;
+
+ WKBStreamWrite ( stream_obj, &(psCShape->nVertices), 1, sizeof(int) );
+
+ for ( j=0; j < psCShape->nVertices; j++ ) {
+ WKBStreamWrite ( stream_obj, &(psCShape->padfX[j]), 1, sizeof(double) );
+ WKBStreamWrite ( stream_obj, &(psCShape->padfY[j]), 1, sizeof(double) );
+ } /* for each vertex */
+
+ return (1);
+}
+
+
+
+/* **************************************************************************
+ * SHPReadOGisPolygon
+ *
+ * for this pass code to more generic OGis MultiPolygon Type
+ * later add support for OGis Polygon Type
+ *
+ * Encapsulate entire SHPObject for use with Postgresql
+ *
+ * **************************************************************************/
+SHPObject* SHPReadOGisPolygon ( WKBStreamObj *stream_obj ) {
+// SHPObject **ppsC;
+ SHPObject *psC;
+ int rPart, ring, rVertices, cpart, cParts, j;
+// int i, nextring;
+ int totParts, totVertices, pRings, nParts;
+
+ psC = SHPCreateObject ( SHPT_POLYGON, -1, 0, NULL, NULL, 0,
+ NULL, NULL, NULL, NULL );
+ /* initialize a blank SHPObject */
+
+ WKBStreamRead ( stream_obj, &cParts, 1, sizeof(char) );
+
+ totParts = cParts;
+ totVertices = 0;
+
+ SfRealloc ( psC->panPartStart, cParts * sizeof(int));
+ SfRealloc ( psC->panPartType, cParts * sizeof(int));
+
+ for ( cpart = 0; cpart < cParts; cpart++) {
+ WKBStreamRead ( stream_obj, &nParts, 1, sizeof(int) );
+ pRings = nParts;
+ /* pRings is the number of rings prior to the Ring loop below */
+
+ if ( nParts > 1 ) {
+ totParts += nParts - 1;
+ SfRealloc ( psC->panPartStart, totParts * sizeof(int));
+ SfRealloc ( psC->panPartType, totParts * sizeof(int));
+ }
+
+ rPart = 0;
+ for ( ring = 0; ring < (nParts - 1); ring ++) {
+ WKBStreamRead ( stream_obj, &rVertices, 1, sizeof(int) );
+ totVertices += rVertices;
+
+ psC->panPartStart[ring+pRings] = rPart;
+ if ( ring == 0 )
+ { psC->panPartType[ring + pRings] = SHPP_OUTERRING; }
+ else
+ { psC->panPartType[ring + pRings] = SHPP_INNERRING; }
+
+ SfRealloc ( psC->padfX, totVertices * sizeof (double));
+ SfRealloc ( psC->padfY, totVertices * sizeof (double));
+
+ for ( j=rPart; j < (rPart + rVertices); j++ ) {
+ WKBStreamRead ( stream_obj, &(psC->padfX[j]), 1, sizeof(double) );
+ WKBStreamRead ( stream_obj, &(psC->padfY[j]), 1, sizeof(double) );
+ } /* for each vertex */
+ rPart += rVertices;
+
+ } /* for each ring */
+
+ } /* for each complex part */
+
+ return ( psC );
+
+}
+
+
+/* **************************************************************************
+ * SHPReadOGisLine
+ *
+ * for this pass code to more generic OGis MultiLineString Type
+ * later add support for OGis LineString Type
+ *
+ * Encapsulate entire SHPObject for use with Postgresql
+ *
+ * **************************************************************************/
+SHPObject* SHPReadOGisLine ( WKBStreamObj *stream_obj ) {
+// SHPObject **ppsC;
+ SHPObject *psC;
+ int rPart, ring, rVertices, cpart, cParts, j;
+// int i, nextring;
+ int totParts, totVertices, pRings, nParts;
+
+ psC = SHPCreateObject ( SHPT_ARC, -1, 0, NULL, NULL, 0,
+ NULL, NULL, NULL, NULL );
+ /* initialize a blank SHPObject */
+
+ WKBStreamRead ( stream_obj, &cParts, 1, sizeof(int) );
+
+ totParts = cParts;
+ totVertices = 0;
+
+ SfRealloc ( psC->panPartStart, cParts * sizeof(int));
+ SfRealloc ( psC->panPartType, cParts * sizeof(int));
+
+ for ( cpart = 0; cpart < cParts; cpart++) {
+ WKBStreamRead ( stream_obj, &nParts, 1, sizeof(int) );
+ pRings = totParts;
+ /* pRings is the number of rings prior to the Ring loop below */
+
+ if ( nParts > 1 ) {
+ totParts += nParts - 1;
+ SfRealloc ( psC->panPartStart, totParts * sizeof(int));
+ SfRealloc ( psC->panPartType, totParts * sizeof(int));
+ }
+
+ rPart = 0;
+ for ( ring = 0; ring < (nParts - 1); ring ++) {
+ WKBStreamRead ( stream_obj, &rVertices, 1, sizeof(int) );
+ totVertices += rVertices;
+
+ psC->panPartStart[ring+pRings] = rPart;
+ if ( ring == 0 )
+ { psC->panPartType[ring + pRings] = SHPP_OUTERRING; }
+ else
+ { psC->panPartType[ring + pRings] = SHPP_INNERRING; }
+
+ SfRealloc ( psC->padfX, totVertices * sizeof (double));
+ SfRealloc ( psC->padfY, totVertices * sizeof (double));
+
+ for ( j=rPart; j < (rPart + rVertices); j++ ) {
+ WKBStreamRead ( stream_obj, &(psC->padfX[j]), 1, sizeof(double) );
+ WKBStreamRead ( stream_obj, &(psC->padfY[j]), 1, sizeof(double) );
+ } /* for each vertex */
+ rPart += rVertices;
+
+ } /* for each ring */
+
+ } /* for each complex part */
+
+ return ( psC );
+}
+
+
+/* **************************************************************************
+ * SHPReadOGisPoint
+ *
+ * Encapsulate entire SHPObject for use with Postgresql
+ *
+ * **************************************************************************/
+SHPObject* SHPReadOGisPoint ( WKBStreamObj *stream_obj ) {
+ SHPObject *psC;
+ int nVertices, j;
+
+ psC = SHPCreateObject ( SHPT_MULTIPOINT, -1, 0, NULL, NULL, 0,
+ NULL, NULL, NULL, NULL );
+ /* initialize a blank SHPObject */
+
+ WKBStreamRead ( stream_obj, &nVertices, 1, sizeof(int) );
+
+ SfRealloc ( psC->padfX, nVertices * sizeof (double));
+ SfRealloc ( psC->padfY, nVertices * sizeof (double));
+
+ for ( j=0; j < nVertices; j++ ) {
+ WKBStreamRead ( stream_obj, &(psC->padfX[j]), 1, sizeof(double) );
+ WKBStreamRead ( stream_obj, &(psC->padfY[j]), 1, sizeof(double) );
+ } /* for each vertex */
+
+ return ( psC );
+}
+
+
+
+
+/* **************************************************************************
+ * RingReadOGisWKB
+ *
+ * this accepts OGisLineStrings which are basic building blocks
+ *
+ * Encapsulate entire SHPObject for use with Postgresql
+ *
+ * **************************************************************************/
+int RingReadOgisWKB ( SHPObject *psCShape, char *stream_obj) {
+ return 0;
+}
+
+
+/* **************************************************************************
+ * RingWriteOGisWKB
+ *
+ * this emits OGisLineStrings which are basic building blocks
+ *
+ * Encapsulate entire SHPObject for use with Postgresql
+ *
+ * **************************************************************************/
+int RingWriteOgisWKB ( SHPObject *psCShape, char *stream_obj) {
+
+ return 0;
+}
+
+
+/* **************************************************************************
+ * SHPDimension
+ *
+ * Return the Dimensionality of the SHPObject
+ * a handy utility function
+ *
+ * **************************************************************************/
+int SHPDimension ( int SHPType ) {
+ int dimension;
+
+ dimension = 0;
+
+ switch ( SHPType ) {
+ case SHPT_POINT : dimension = SHPD_POINT ;
+ case SHPT_ARC : dimension = SHPD_LINE;
+ case SHPT_POLYGON : dimension = SHPD_AREA;
+ case SHPT_MULTIPOINT : dimension = SHPD_POINT;
+ case SHPT_POINTZ : dimension = SHPD_POINT | SHPD_Z;
+ case SHPT_ARCZ : dimension = SHPD_LINE | SHPD_Z;
+ case SHPT_POLYGONZ : dimension = SHPD_AREA | SHPD_Z;
+ case SHPT_MULTIPOINTZ : dimension = SHPD_POINT | SHPD_Z;
+ case SHPT_POINTM : dimension = SHPD_POINT | SHPD_MEASURE;
+ case SHPT_ARCM : dimension = SHPD_LINE | SHPD_MEASURE;
+ case SHPT_POLYGONM : dimension = SHPD_AREA | SHPD_MEASURE;
+ case SHPT_MULTIPOINTM : dimension = SHPD_POINT | SHPD_MEASURE;
+ case SHPT_MULTIPATCH : dimension = SHPD_AREA;
+ }
+
+ return ( dimension );
+}
+
+
+/* **************************************************************************
+ * SHPPointinPoly_2d
+ *
+ * Return a Point inside an R+ of a potentially
+ * complex/compound SHPObject suitable for labelling
+ * return only one point even if if is a compound object
+ *
+ * reject non area SHP Types
+ *
+ * **************************************************************************/
+PT SHPPointinPoly_2d ( SHPObject *psCShape ) {
+ PT *sPT, rPT;
+
+ if ( !(SHPDimension (psCShape->nSHPType) & SHPD_AREA) )
+ {
+ rPT.x = NAN;
+ rPT.y = NAN;
+ return rPT;
+ }
+
+ sPT = SHPPointsinPoly_2d ( psCShape );
+
+ if ( sPT ) {
+ rPT.x = sPT[0].x;
+ rPT.y = sPT[0].y;
+ } else {
+ rPT.x = NAN;
+ rPT.y = NAN;
+ }
+ return ( rPT );
+}
+
+
+/* **************************************************************************
+ * SHPPointsinPoly_2d
+ *
+ * Return a Point inside each R+ of a potentially
+ * complex/compound SHPObject suitable for labelling
+ * return one point for each R+ even if it is a compound object
+ *
+ * reject non area SHP Types
+ *
+ * **************************************************************************/
+PT* SHPPointsinPoly_2d ( SHPObject *psCShape ) {
+ PT *PIP = NULL;
+ int cRing;
+ SHPObject *psO, *psInt, *CLine;
+ double *CLx, *CLy;
+ int *CLstt, *CLst, nPIP =0, ring, rMpart =0, ring_vtx, ring_nVertices;
+ double rLen =0.0, rLenMax =0.0;
+
+ if ( !(SHPDimension (psCShape->nSHPType) & SHPD_AREA) )
+ return ( NULL );
+
+ while ( (psO = SHPUnCompound(psCShape, &cRing)) != 0 ) {
+ CLx = calloc ( 4, sizeof(double));
+ CLy = calloc ( 4, sizeof(double));
+ CLst = calloc ( 2, sizeof(int));
+ CLstt = calloc ( 2, sizeof(int));
+
+ /* a horizontal & vertical compound line though the middle of the */
+ /* extents */
+ CLx [0] = psO->dfXMin;
+ CLy [0] = (psO->dfYMin + psO->dfYMax ) * 0.5;
+ CLx [1] = psO->dfXMax;
+ CLy [1] = (psO->dfYMin + psO->dfYMax ) * 0.5;
+
+ CLx [2] = (psO->dfXMin + psO->dfXMax ) * 0.5;
+ CLy [2] = psO->dfYMin;
+ CLx [3] = (psO->dfXMin + psO->dfXMax ) * 0.5;
+ CLy [3] = psO->dfYMax;
+
+ CLst[0] = 0; CLst[1] = 2;
+ CLstt[0] = SHPP_RING; CLstt[1] = SHPP_RING;
+
+ CLine = SHPCreateObject ( SHPT_POINT, -1, 2, CLst, CLstt, 4,
+ CLx, CLy, NULL, NULL );
+
+ /* with the H & V centrline compound object, intersect it with the OBJ */
+ psInt = SHPIntersect_2d ( CLine, psO );
+ /* return SHP type is lowest common dimensionality of the input types */
+
+
+ /* find the longest linestring returned by the intersection */
+ ring_vtx = psInt->nVertices ;
+ for ( ring = (psInt->nParts - 1); ring >= 0; ring-- ) {
+ ring_nVertices = ring_vtx - psInt->panPartStart[ring];
+
+ rLen += RingLength_2d ( ring_nVertices,
+ (double*) &(psInt->padfX [psInt->panPartStart[ring]]),
+ (double*) &(psInt->padfY [psInt->panPartStart[ring]]) );
+
+ if ( rLen > rLenMax )
+ { rLenMax = rLen;
+ rMpart = psInt->panPartStart[ring];
+ }
+ ring_vtx = psInt->panPartStart[ring];
+ }
+
+ /* add the centerpoint of the longest ARC of the intersection to the */
+ /* PIP list */
+ nPIP ++;
+ SfRealloc ( PIP, sizeof(double) * 2 * nPIP);
+ PIP[nPIP].x = (psInt ->padfX [rMpart] + psInt ->padfX [rMpart]) * 0.5;
+ PIP[nPIP].y = (psInt ->padfY [rMpart] + psInt ->padfY [rMpart]) * 0.5;
+
+ SHPDestroyObject ( psO );
+ SHPDestroyObject ( CLine );
+
+ /* does SHPCreateobject use preallocated memory or does it copy the */
+ /* contents. To be safe conditionally release CLx, CLy, CLst, CLstt */
+ if ( CLx ) free ( CLx );
+ if ( CLy ) free ( CLy );
+ if ( CLst ) free ( CLst );
+ if ( CLstt ) free ( CLstt );
+ }
+
+ return ( PIP );
+}
+
+
+/* **************************************************************************
+ * SHPCentrd_2d
+ *
+ * Return the single mathematical / geometric centroid of a potentially
+ * complex/compound SHPObject
+ *
+ * reject non area SHP Types
+ *
+ * **************************************************************************/
+PT SHPCentrd_2d ( SHPObject *psCShape ) {
+ int ring, ringPrev, ring_nVertices, rStart;
+ double Area, ringArea;
+ PT ringCentrd, C;
+
+
+ if ( !(SHPDimension (psCShape->nSHPType) & SHPD_AREA) )
+ {
+ C.x = NAN;
+ C.y = NAN;
+ return C;
+ }
+
+#ifdef DEBUG
+ printf ("for Object with %d vtx, %d parts [ %d, %d] \n",
+ psCShape->nVertices, psCShape->nParts,
+ psCShape->panPartStart[0],psCShape->panPartStart[1]);
+#endif
+
+ Area = 0;
+ C.x = 0.0;
+ C.y = 0.0;
+
+ /* for each ring in compound / complex object calc the ring cntrd */
+
+ ringPrev = psCShape->nVertices;
+ for ( ring = (psCShape->nParts - 1); ring >= 0; ring-- ) {
+ rStart = psCShape->panPartStart[ring];
+ ring_nVertices = ringPrev - rStart;
+
+ RingCentroid_2d ( ring_nVertices, (double*) &(psCShape->padfX [rStart]),
+ (double*) &(psCShape->padfY [rStart]), &ringCentrd, &ringArea);
+
+#ifdef DEBUG
+ printf ("(SHPCentrd_2d) Ring %d, vtxs %d, area: %f, ring centrd %f, %f \n",
+ ring, ring_nVertices, ringArea, ringCentrd.x, ringCentrd.y);
+#endif
+
+ /* use Superposition of these rings to build a composite Centroid */
+ /* sum the ring centrds * ringAreas, at the end divide by total area */
+ C.x += ringCentrd.x * ringArea;
+ C.y += ringCentrd.y * ringArea;
+ Area += ringArea;
+ ringPrev = rStart;
+ }
+
+ /* hold on the division by AREA until were at the end */
+ C.x = C.x / Area;
+ C.y = C.y / Area;
+#ifdef DEBUG
+ printf ("SHPCentrd_2d) Overall Area: %f, Centrd %f, %f \n",
+ Area, C.x, C.y);
+#endif
+ return ( C );
+}
+
+
+/* **************************************************************************
+ * RingCentroid_2d
+ *
+ * Return the mathematical / geometric centroid of a single closed ring
+ *
+ * **************************************************************************/
+int RingCentroid_2d ( int nVertices, double *a, double *b, PT *C, double *Area ) {
+ int iv;
+// int jv;
+// int sign_x, sign_y;
+ double dx_Area, Cx_accum, Cy_accum, ppx, ppy;
+// double dy_Area;
+ double x_base, y_base, x, y;
+
+/* the centroid of a closed Ring is defined as
+ *
+ * Cx = sum (cx * dArea ) / Total Area
+ * and
+ * Cy = sum (cy * dArea ) / Total Area
+ */
+
+ x_base = a[0];
+ y_base = b[0];
+
+ Cy_accum = 0.0;
+ Cx_accum = 0.0;
+
+ ppx = a[1] - x_base;
+ ppy = b[1] - y_base;
+ *Area = 0;
+
+/* Skip the closing vector */
+ for ( iv = 2; iv <= nVertices - 2; iv++ ) {
+ x = a[iv] - x_base;
+ y = b[iv] - y_base;
+
+ /* calc the area and centroid of triangle built out of an arbitrary */
+ /* base_point on the ring and each successive pair on the ring */
+
+ /* Area of a triangle is the cross product of its defining vectors */
+ /* Centroid of a triangle is the average of its vertices */
+
+ dx_Area = ((x * ppy) - (y * ppx)) * 0.5;
+ *Area += dx_Area;
+
+ Cx_accum += ( ppx + x ) * dx_Area;
+ Cy_accum += ( ppy + y ) * dx_Area;
+#ifdef DEBUG2
+ printf("(ringcentrd_2d) Pp( %f, %f), P(%f, %f)\n", ppx, ppy, x, y);
+ printf("(ringcentrd_2d) dA: %f, sA: %f, Cx: %f, Cy: %f \n",
+ dx_Area, *Area, Cx_accum, Cy_accum);
+#endif
+ ppx = x;
+ ppy = y;
+ }
+
+#ifdef DEBUG2
+ printf("(ringcentrd_2d) Cx: %f, Cy: %f \n",
+ ( Cx_accum / ( *Area * 3) ), ( Cy_accum / (*Area * 3) ));
+#endif
+
+ /* adjust back to world coords */
+ C->x = ( Cx_accum / ( *Area * 3)) + x_base;
+ C->y = ( Cy_accum / ( *Area * 3)) + y_base;
+
+ return ( 1 );
+}
+
+
+
+
+/* **************************************************************************
+ * SHPRingDir_2d
+ *
+ * Test Polygon for CW / CCW ( R+ / R- )
+ *
+ * return 1 for R+
+ * return -1 for R-
+ * return 0 for error
+ * **************************************************************************/
+int SHPRingDir_2d ( SHPObject *psCShape, int Ring ) {
+ int ti = 0;
+ int i, last_vtx;
+ double tX;
+ double *a, *b;
+ double dx0, dx1, dy0, dy1, v3;
+// double v1, v2;
+
+ tX = 0.0;
+ a = psCShape->padfX;
+ b = psCShape->padfY;
+
+ if ( Ring >= psCShape->nParts ) return ( 0 );
+
+ if ( Ring >= psCShape->nParts -1 )
+ { last_vtx = psCShape->nVertices; }
+ else
+ { last_vtx = psCShape->panPartStart[Ring + 1]; }
+
+ /* All vertices at the corners of the extrema (rightmost lowest, leftmost lowest, */
+ /* topmost rightest, ...) must be less than pi wide. If they werent they couldnt be */
+ /* extrema. */
+ /* of course the following will fail if the Extents are even a little wrong */
+
+ for ( i = psCShape->panPartStart[Ring]; i < last_vtx; i++ ) {
+ if ( b[i] == psCShape->dfYMax && a[i] > tX )
+ { ti = i; }
+ }
+
+#ifdef DEBUG2
+ printf ("(shpgeo:SHPRingDir) highest Rightmost Pt is vtx %d (%f, %f)\n", ti, a[ti], b[ti]);
+#endif
+
+ /* cross product */
+ /* the sign of the cross product of two vectors indicates the right or left half-plane */
+ /* which we can use to indicate Ring Dir */
+ if ( (ti > psCShape->panPartStart[Ring]) && (ti < last_vtx) )
+ { dx0 = a[ti-1] - a[ti];
+ dx1 = a[ti+1] - a[ti];
+ dy0 = b[ti-1] - b[ti];
+ dy1 = b[ti+1] - b[ti];
+ }
+ else
+ /* if the tested vertex is at the origin then continue from 0 */
+ { dx1 = a[1] - a[0];
+ dx0 = a[last_vtx] - a[0];
+ dy1 = b[1] - b[0];
+ dy0 = b[last_vtx] - b[0];
+ }
+
+// v1 = ( (dy0 * 0) - (0 * dy1) );
+// v2 = ( (0 * dx1) - (dx0 * 0) );
+/* these above are always zero so why do the math */
+ v3 = ( (dx0 * dy1) - (dx1 * dy0) );
+
+#ifdef DEBUG2
+ printf ("(shpgeo:SHPRingDir) cross product for vtx %d was %f \n", ti, v3);
+#endif
+
+ if ( v3 > 0 )
+ { return (1); }
+ else
+ { return (-1); }
+}
+
+
+
+/* **************************************************************************
+ * SHPArea_2d
+ *
+ * Calculate the XY Area of Polygon ( can be compound / complex )
+ *
+ * **************************************************************************/
+double SHPArea_2d ( SHPObject *psCShape ) {
+ double cArea;
+ int ring, ring_vtx, ring_nVertices;
+// int ringDir;
+
+ cArea = 0;
+ if ( !(SHPDimension (psCShape->nSHPType) & SHPD_AREA) )
+ return ( -1 );
+
+
+ /* Walk each ring adding its signed Area, R- will return a negative */
+ /* area, so we don't have to test for them */
+
+ /* I just start at the last ring and work down to the first */
+ ring_vtx = psCShape->nVertices ;
+ for ( ring = (psCShape->nParts - 1); ring >= 0; ring-- ) {
+ ring_nVertices = ring_vtx - psCShape->panPartStart[ring];
+
+#ifdef DEBUG2
+ printf("(shpgeo:SHPArea_2d) part %d, vtx %d \n", ring, ring_nVertices);
+#endif
+ cArea += RingArea_2d ( ring_nVertices,
+ (double*) &(psCShape->padfX [psCShape->panPartStart[ring]]),
+ (double*) &(psCShape->padfY [psCShape->panPartStart[ring]]) );
+
+ ring_vtx = psCShape->panPartStart[ring];
+ }
+
+#ifdef DEBUG2
+ printf ("(shpgeo:SHPArea_2d) Area = %f \n", cArea);
+#endif
+
+ /* Area is signed, negative Areas are R- */
+ return ( cArea );
+
+}
+
+
+/* **************************************************************************
+ * SHPLength_2d
+ *
+ * Calculate the Planar ( XY ) Length of Polygon ( can be compound / complex )
+ * or Polyline ( can be compound ). Length on Polygon is its Perimeter
+ *
+ * **************************************************************************/
+double SHPLength_2d ( SHPObject *psCShape ) {
+ double Length;
+ int i, j;
+ double dx, dy;
+
+ if ( !(SHPDimension (psCShape->nSHPType) & (SHPD_AREA || SHPD_LINE)) )
+ return ( (double) -1 );
+
+ Length = 0;
+ j = 1;
+ for ( i = 1; i < psCShape->nVertices; i++ ) {
+ if ( psCShape->panPartStart[j] == i )
+ { j ++; }
+ /* skip the moves with "pen up" from ring to ring */
+ else
+ {
+ dx = psCShape->padfX[i] - psCShape->padfX[i-1];
+ dy = psCShape->padfY[i] - psCShape->padfY[i-1];
+ Length += sqrt ( ( dx * dx ) + ( dy * dy ) );
+ }
+ /* simplify this equation */
+ }
+
+ return ( Length );
+}
+
+
+/* **************************************************************************
+ * RingLength_2d
+ *
+ * Calculate the Planar ( XY ) Length of Polygon ( can be compound / complex )
+ * or Polyline ( can be compound ). Length of Polygon is its Perimeter
+ *
+ * **************************************************************************/
+double RingLength_2d ( int nVertices, double *a, double *b ) {
+ double Length;
+ int i, j;
+ double dx, dy;
+
+ Length = 0;
+ j = 1;
+ for ( i = 1; i < nVertices; i++ ) {
+ dx = a[i] - b[i-1];
+ dy = b[i] - b[i-1];
+ Length += sqrt ( ( dx * dx ) + ( dy * dy ) );
+ /* simplify this equation */
+ }
+
+ return ( Length );
+}
+
+
+/* **************************************************************************
+ * RingArea_2d
+ *
+ * Calculate the Planar Area of a single closed ring
+ *
+ * **************************************************************************/
+double RingArea_2d ( int nVertices, double *a, double *b ) {
+ int iv;
+// int jv;
+ double ppx, ppy;
+ static double Area;
+ double dx_Area;
+ double x_base, y_base, x, y;
+
+ x_base = a[0];
+ y_base = b[0];
+
+ ppx = a[1] - x_base;
+ ppy = b[1] - y_base;
+ Area = 0.0;
+#ifdef DEBUG2
+ printf("(shpgeo:RingArea) %d vertices \n", nVertices);
+#endif
+ for ( iv = 2; iv <= ( nVertices - 1 ); iv++ ) {
+ x = a[iv] - x_base;
+ y = b[iv] - y_base;
+
+ /* Area of a triangle is the cross product of its defining vectors */
+
+ dx_Area = ((x * ppy) - (y * ppx)) * 0.5;
+
+ Area += dx_Area;
+#ifdef DEBUG2
+ printf ("(shpgeo:RingArea) dxArea %f sArea %f for pt(%f, %f)\n",
+ dx_Area, Area, x, y);
+#endif
+
+ ppx = x;
+ ppy = y;
+ }
+
+#ifdef DEBUG2
+ printf ("(shpgeo:RingArea) total RingArea %f \n", Area);
+#endif
+ return ( Area );
+
+}
+
+
+
+/* **************************************************************************
+ * SHPUnCompound
+ *
+ * ESRI calls this function explode
+ * Return a non compound ( possibly complex ) object
+ *
+ * ring_number is R+ number corresponding to object
+ *
+ *
+ * ignore complexity in Z dimension for now
+ *
+ * **************************************************************************/
+SHPObject* SHPUnCompound ( SHPObject *psCShape, int * ringNumber ) {
+ int ringDir, ring, lRing;
+
+ if ( (*ringNumber >= psCShape->nParts) || *ringNumber == -1 ) {
+ *ringNumber = -1;
+ return (NULL);
+ }
+
+
+ if ( *ringNumber == (psCShape->nParts - 1) ) {
+ *ringNumber = -1;
+ return ( SHPClone(psCShape, (psCShape->nParts - 1), -1) );
+ }
+
+ lRing = *ringNumber;
+ ringDir = -1;
+ for ( ring = (lRing + 1); (ring < psCShape->nParts) && ( ringDir < 0 ); ring ++)
+ ringDir = SHPRingDir_2d ( psCShape, ring);
+
+ if ( ring == psCShape->nParts )
+ *ringNumber = -1;
+ else
+ *ringNumber = ring;
+/* I am strictly assuming that all R- parts of a complex object
+ * directly follow their R+, so when we hit a new R+ its a
+ * new part of a compound object
+ * a SHPClean may be needed to enforce this as it is not part
+ * of ESRI's definition of a SHPfile
+ */
+
+#ifdef DEBUG2
+ printf ("(SHPUnCompound) asked for ring %d, lastring is %d \n", lRing, ring);
+#endif
+ return ( SHPClone(psCShape, lRing, ring ) );
+
+}
+
+
+/* **************************************************************************
+ * SHPIntersect_2d
+ *
+ *
+ * prototype only for now
+ *
+ * return object with lowest common dimensionality of objects
+ *
+ * **************************************************************************/
+SHPObject* SHPIntersect_2d ( SHPObject* a, SHPObject* b ) {
+ SHPObject *C;
+
+ if ( (SHPDimension(a->nSHPType) && SHPD_POINT) || ( SHPDimension(b->nSHPType) && SHPD_POINT ) )
+ return ( NULL );
+ /* there is no intersect function like this for points */
+
+ C = SHPClone ( a, 0 , -1 );
+
+ return ( C);
+
+}
+
+
+
+/* **************************************************************************
+ * SHPClean
+ *
+ * Test and fix normalization problems in shapes
+ * Different tests need to be implemented for different SHPTypes
+ * SHPT_POLYGON check ring directions CW / CCW ( R+ / R- )
+ * put all R- after the R+ they are members of
+ * i.e. each complex object is completed before the
+ * next object is started
+ * check for closed rings
+ * ring must not intersect itself, even on edge
+ *
+ * no other types implemented yet
+ *
+ * not sure why but return object in place
+ * use for object casting and object verification
+ * **************************************************************************/
+int SHPClean ( SHPObject *psCShape ) {
+
+
+ return (0);
+}
+
+
+/* **************************************************************************
+ * SHPClone
+ *
+ * Clone a SHPObject, replicating all data
+ *
+ * **************************************************************************/
+SHPObject* SHPClone ( SHPObject *psCShape, int lowPart, int highPart ) {
+ SHPObject *psObject;
+ int newParts, newVertices;
+#ifdef DEBUG
+ int i;
+#endif
+
+ if ( highPart >= psCShape->nParts || highPart == -1 )
+ highPart = psCShape->nParts ;
+
+#ifdef DEBUG
+ printf (" cloning SHP (%d parts) from ring %d upto ring %d \n",
+ psCShape->nParts, lowPart, highPart);
+#endif
+
+ newParts = highPart - lowPart;
+ if ( newParts == 0 ) { return ( NULL ); }
+
+ psObject = (SHPObject *) calloc(1,sizeof(SHPObject));
+ psObject->nSHPType = psCShape->nSHPType;
+ psObject->nShapeId = psCShape->nShapeId;
+
+ psObject->nParts = newParts;
+ if ( psCShape->padfX ) {
+ psObject->panPartStart = (int*) calloc (newParts, sizeof (int));
+ memcpy ( psObject->panPartStart, psCShape->panPartStart,
+ newParts * sizeof (int) );
+ }
+ if ( psCShape->padfX ) {
+ psObject->panPartType = (int*) calloc (newParts, sizeof (int));
+ memcpy ( psObject->panPartType,
+ (int *) &(psCShape->panPartType[lowPart]),
+ newParts * sizeof (int) );
+ }
+
+ if ( highPart != psCShape->nParts ) {
+ newVertices = psCShape->panPartStart[highPart] -
+ psCShape->panPartStart[lowPart];
+ }
+ else
+ { newVertices = psCShape->nVertices - psCShape->panPartStart[lowPart]; }
+
+
+#ifdef DEBUG
+ if ( highPart = psCShape->nParts )
+ i = psCShape->nVertices;
+ else
+ i = psCShape->panPartStart[highPart];
+ printf (" from part %d (%d) to %d (%d) is %d vertices \n",
+ lowPart, psCShape->panPartStart[lowPart], highPart,
+ i, newVertices);
+#endif
+ psObject->nVertices = newVertices;
+ if ( psCShape->padfX ) {
+ psObject->padfX = (double*) calloc (newVertices, sizeof (double));
+ memcpy ( psObject->padfX,
+ (double *) &(psCShape->padfX[psCShape->panPartStart[lowPart]]),
+ newVertices * sizeof (double) );
+ }
+ if ( psCShape->padfY ) {
+ psObject->padfY = (double*) calloc (newVertices, sizeof (double));
+ memcpy ( psObject->padfY,
+ (double *) &(psCShape->padfY[psCShape->panPartStart[lowPart]]),
+ newVertices * sizeof (double) );
+ }
+ if ( psCShape->padfZ ) {
+ psObject->padfZ = (double*) calloc (newVertices, sizeof (double));
+ memcpy ( psObject->padfZ,
+ (double *) &(psCShape->padfZ[psCShape->panPartStart[lowPart]]),
+ newVertices * sizeof (double) );
+ }
+ if ( psCShape->padfM ) {
+ psObject->padfM = (double*) calloc (newVertices, sizeof (double));
+ memcpy ( psObject->padfM,
+ (double *) &(psCShape->padfM[psCShape->panPartStart[lowPart]]),
+ newVertices * sizeof (double) );
+ }
+
+ psObject->dfXMin = psCShape->dfXMin;
+ psObject->dfYMin = psCShape->dfYMin;
+ psObject->dfZMin = psCShape->dfZMin;
+ psObject->dfMMin = psCShape->dfMMin;
+
+ psObject->dfXMax = psCShape->dfXMax;
+ psObject->dfYMax = psCShape->dfYMax;
+ psObject->dfZMax = psCShape->dfZMax;
+ psObject->dfMMax = psCShape->dfMMax;
+
+ SHPComputeExtents ( psObject );
+ return ( psObject );
+}
+
+
+
+/************************************************************************/
+/* SwapG */
+/* */
+/* Swap a 2, 4 or 8 byte word. */
+/************************************************************************/
+void SwapG( void *so, void *in, int this_cnt, int this_size ) {
+ int i, j;
+// unsigned char temp;
+
+/* return to a new pointer otherwise it would invalidate existing data */
+/* as prevent further use of it */
+
+ for( j=0; j < this_cnt; j++ )
+ {
+ for( i=0; i < this_size/2; i++ )
+ {
+ ((unsigned char *) so)[i] = ((unsigned char *) in)[this_size-i-1];
+ ((unsigned char *) so)[this_size-i-1] = ((unsigned char *) in)[i];
+ }
+ }
+}
+
+
+/* **************************************************************************
+ * SwapW
+ *
+ * change byte order on an array of 16 bit words
+ * need to change this over to shapelib, Frank Warmerdam's functions
+ *
+ * **************************************************************************/
+void swapW (void *so, unsigned char *in, long bytes) {
+ int i, j;
+ unsigned char map[4] = {3,2,1,0};
+ unsigned char *out;
+
+ out = so;
+ for (i=0; i <= (bytes/4); i++)
+ for (j=0; j < 4; j++)
+ out[(i*4)+map[j]] = in[(i*4)+j];
+}
+
+
+/* **************************************************************************
+ * SwapD
+ *
+ * change byte order on an array of (double) 32 bit words
+ * need to change this over to shapelib, Frank Warmerdam's functons
+ *
+ * **************************************************************************/
+void swapD (void *so, unsigned char *in, long bytes) {
+ int i, j;
+ unsigned char map[8] = {7,6,5,4,3,2,1,0};
+ unsigned char *out;
+
+ out = so;
+ for (i=0; i <= (bytes/8); i++)
+ for (j=0; j < 8; j++)
+ out[(i*8)+map[j]] = in[(i*8)+j];
+}
+
diff --git a/src/shapelib/contrib/shpgeo.h b/src/shapelib/contrib/shpgeo.h
new file mode 100644
index 0000000..92078ad
--- /dev/null
+++ b/src/shapelib/contrib/shpgeo.h
@@ -0,0 +1,177 @@
+/******************************************************************************
+ * Copyright (c) 1999, Carl Anderson
+ *
+ * This code is based in part on the earlier work of Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ * shpgeo.h
+ *
+ * support for geometric and other additions to shapelib
+ *
+ *
+ * $Log: shpgeo.h,v $
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.3 2002/01/15 14:36:56 warmerda
+ * upgrade to use proj_api.h
+ *
+ * Revision 1.2 1999/05/26 02:56:31 candrsn
+ * updates to shpdxf, dbfinfo, port from Shapelib 1.1.5 of dbfcat and shpinfo
+ *
+ *
+ */
+
+
+
+ /* I'm using some shorthand throughout this file
+ * R+ is a Clockwise Ring and is the positive portion of an object
+ * R- is a CounterClockwise Ring and is a hole in a R+
+ * A complex object is one having at least one R-
+ * A compound object is one having more than one R+
+ * A simple object has one and only one element (R+ or R-)
+ *
+ * The closed ring constraint is for polygons and assumed here
+ * Arcs or LineStrings I am calling Rings (generically open or closed)
+ * Point types are vertices or lists of vertices but not Rings
+ *
+ * SHPT_POLYGON, SHPT_POLYGONZ, SHPT_POLYGONM and SHPT_MULTIPATCH
+ * can have SHPObjects that are compound as well as complex
+ *
+ * SHP_POINT and its Z and M derivatives are strictly simple
+ * MULTI_POINT, SHPT_ARC and their derivatives may be simple or compound
+ *
+ */
+
+
+#ifndef SHPGEO_H
+
+#define SHPGEO_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "proj_api.h"
+
+
+#define SHPD_POINT 1
+#define SHPD_LINE 2
+#define SHPD_AREA 4
+#define SHPD_Z 8
+#define SHPD_MEASURE 16
+
+
+/* move these into a ogis header file ogis.h */
+#define OGIST_UNKNOWN 0
+#define OGIST_POINT 1
+#define OGIST_LINESTRING 2
+#define OGIST_POLYGON 3
+#define OGIST_MULTIPOINT 4
+#define OGIST_MULTILINE 5
+#define OGIST_MULTIPOLYGON 6
+#define OGIST_GEOMCOLL 7
+
+typedef struct { int StreamPos;
+ int NeedSwap;
+ char *wStream;
+ } WKBStreamObj;
+
+typedef struct { double x; double y; } PT;
+
+
+typedef struct { int cParts;
+ SHPObject *SHPObj;
+ } SHPObjectList;
+
+
+#define LSB_ORDER (int) 1
+
+
+extern char * asFileName ( const char *fil, char *ext );
+extern int SHPProject ( SHPObject *psCShape,
+ projPJ inproj, projPJ outproj );
+extern projPJ SHPSetProjection ( int param_cnt, char **params );
+extern int SHPFreeProjection ( projPJ p);
+
+extern int SHPDimension ( int SHPType );
+
+extern double SHPArea_2d ( SHPObject *psCShape );
+extern int SHPRingDir_2d ( SHPObject *psCShape, int Ring );
+extern double SHPLength_2d ( SHPObject *psCShape );
+extern PT SHPCentrd_2d ( SHPObject *psCShape );
+extern PT SHPPointinPoly_2d ( SHPObject *psCShape );
+extern PT* SHPPointsinPoly_2d ( SHPObject *psCShape );
+
+extern int RingCentroid_2d ( int nVertices, double *a, double *b, PT *C,
+ double *Area );
+extern double RingLength_2d ( int nVertices, double *a, double *b );
+extern int RingDir_2d ( int nVertices, double *a, double *b );
+extern double RingArea_2d ( int nVertices, double *a, double *b );
+
+extern SHPObject* SHPClone ( SHPObject *psCShape, int lowPart, int highPart );
+extern SHPObject* SHPUnCompound ( SHPObject *psCShape, int * ringNumber );
+extern SHPObject* SHPIntersect_2d ( SHPObject* a, SHPObject* b );
+
+extern int SHPWriteOGisWKB ( WKBStreamObj *stream_obj, SHPObject *psCShape );
+extern SHPObject* SHPReadOGisWKB ( WKBStreamObj *stream_obj );
+
+int SHPWriteOGisPolygon ( WKBStreamObj *stream_obj, SHPObject *psCShape );
+int SHPWriteOGisLine ( WKBStreamObj *stream_obj, SHPObject *psCShape );
+int SHPWriteOGisPoint ( WKBStreamObj *stream_obj, SHPObject *psCShape );
+
+SHPObject* SHPReadOGisPolygon ( WKBStreamObj *stream_obj );
+SHPObject* SHPReadOGisLine ( WKBStreamObj *stream_obj );
+SHPObject* SHPReadOGisPoint ( WKBStreamObj *stream_obj );
+
+extern int SHPClean ( SHPObject *psCShape );
+extern int SHPOGisType ( int GeomType, int toOGis);
+
+void swapD (void *so, unsigned char *in, long bytes);
+void swapW (void *so, unsigned char *in, long bytes);
+void SwapG( void *so, void *in, int this_cnt, int this_size );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ndef SHPGEO_H */
diff --git a/src/shapelib/contrib/shpinfo.c b/src/shapelib/contrib/shpinfo.c
new file mode 100644
index 0000000..2885deb
--- /dev/null
+++ b/src/shapelib/contrib/shpinfo.c
@@ -0,0 +1,147 @@
+/******************************************************************************
+ * Copyright (c) 1999, Carl Anderson
+ *
+ * This code is based in part on the earlier work of Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * requires shapelib 1.2
+ * gcc shpinfoj shpopen.o -o shpinfo
+ *
+ *
+ * $Log: shpinfo.c,v $
+ * Revision 1.4 2010/07/11 07:51:03 we7u
+ * Fixing more compiler warnings. There are a few left yet.
+ *
+ * Revision 1.3 2010/07/11 07:24:37 we7u
+ * Fixing multiple minor warnings with Shapelib. Still plenty left.
+ *
+ * Revision 1.2 2007/07/25 15:45:27 we7u
+ * Adding includes necessary for warning-free compiles.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.3 2002/04/15 21:33:03 warmerda
+ * Avoid dereference arrays.
+ *
+ * Revision 1.2 2002/04/15 18:40:31 warmerda
+ * Fixed size of adfBnds{Min,Max} as per bug from David Fowler.
+ *
+ * Revision 1.1 1999/05/26 02:56:31 candrsn
+ * updates to shpdxf, dbfinfo, port from Shapelib 1.1.5 of dbfcat and shpinfo
+ *
+ *
+ */
+
+#include "shapefil.h"
+#include <stdlib.h>
+#include <string.h>
+
+int main( int argc, char ** argv )
+
+{
+ SHPHandle hSHP;
+// SHPHandle cSHP;
+ int nShapeType, nEntities;
+// int nVertices, nParts, *panParts, i, iPart;
+ double adfBndsMin[4], adfBndsMax[4];
+// double *padVertices;
+// const char *pszPlus;
+// int cShapeType, cEntities, cVertices, cParts, *cpanParts, ci, cPart;
+// double *cpadVertices, cadBounds[4];
+// const char *cpszPlus;
+ char sType [15]= "";
+/* -------------------------------------------------------------------- */
+/* Display a usage message. */
+/* -------------------------------------------------------------------- */
+ if( argc != 2 )
+ {
+ printf( "shpinfo shp_file\n" );
+ exit( 1 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Open the passed shapefile. */
+/* -------------------------------------------------------------------- */
+ hSHP = SHPOpen( argv[1], "rb" );
+
+ if( hSHP == NULL )
+ {
+ printf( "Unable to open:%s\n", argv[1] );
+ exit( 1 );
+ }
+
+ SHPGetInfo( hSHP, &nEntities, &nShapeType, adfBndsMin, adfBndsMax );
+
+ switch ( nShapeType ) {
+ case SHPT_POINT:
+ strcpy(sType,"Point");
+ break;
+
+ case SHPT_ARC:
+ strcpy(sType,"Polyline");
+ break;
+
+ case SHPT_POLYGON:
+ strcpy(sType,"Polygon");
+ break;
+
+ case SHPT_MULTIPOINT:
+ strcpy(sType,"MultiPoint");
+ break;
+ }
+
+/* -------------------------------------------------------------------- */
+ printf ("Info for %s\n",argv[1]);
+ printf ("%s(%d), %d Records in file\n",sType,nShapeType,nEntities);
+
+/* -------------------------------------------------------------------- */
+/* Print out the file bounds. */
+/* -------------------------------------------------------------------- */
+ printf( "File Bounds: (%15.10lg,%15.10lg)\n\t(%15.10lg,%15.10lg)\n",
+ adfBndsMin[0], adfBndsMin[1], adfBndsMax[0], adfBndsMax[1] );
+
+
+
+ SHPClose( hSHP );
+ return(0);
+}
+
diff --git a/src/shapelib/contrib/shpproj.c b/src/shapelib/contrib/shpproj.c
new file mode 100644
index 0000000..229b073
--- /dev/null
+++ b/src/shapelib/contrib/shpproj.c
@@ -0,0 +1,297 @@
+/******************************************************************************
+ * Copyright (c) 1999, Carl Anderson
+ *
+ * This code is based in part on the earlier work of Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *******************************************************************************
+ *
+ * requires shapelib 1.2
+ * gcc shpproj ../shpopen.o ../dbfopen.o shpgeo.o -lm -lproj -o shpproj
+ *
+ * this requires linking with the PROJ4.3 projection library available from
+ *
+ * ftp://kai.er.usgs.gov/ftp/PROJ.4
+ *
+ *
+ * SHPGeo must be compiled with -DPROJ4 support
+ *
+ * $Log: shpproj.c,v $
+ * Revision 1.5 2010/07/11 20:30:00 we7u
+ * More minor tweaks to get rid of compiler warnings. Of particular note are
+ * some TODO entries added to a couple of files for two enumerated values that
+ * weren't being handled in "switch" statements. There still isn't any code
+ * for those case statements, but the compiler warnings are gone.
+ *
+ * Revision 1.4 2010/07/11 07:51:03 we7u
+ * Fixing more compiler warnings. There are a few left yet.
+ *
+ * Revision 1.3 2010/07/11 07:24:37 we7u
+ * Fixing multiple minor warnings with Shapelib. Still plenty left.
+ *
+ * Revision 1.2 2007/07/25 15:45:27 we7u
+ * Adding includes necessary for warning-free compiles.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.9 2002/01/15 14:37:08 warmerda
+ * upgrade to use proj_api.h
+ *
+ * Revision 1.8 2002/01/11 15:47:26 warmerda
+ * several fixes
+ *
+ * Revision 1.7 2002/01/11 15:23:28 warmerda
+ * use text mode reading and writing .prj files
+ *
+ * Revision 1.6 1999/05/26 02:56:31 candrsn
+ * updates to shpdxf, dbfinfo, port from Shapelib 1.1.5 of dbfcat and shpinfo
+ *
+ * Revision 1.2 1999/05/13 19:30:52 warmerda
+ * Removed libgen.h, added url for PROJ.4, and corrected unsafe return of
+ * local variable in asFileName().
+ *
+ */
+
+
+#include "shapefil.h"
+#include "shpgeo.h"
+#include <stdarg.h>
+#include <string.h>
+
+int main( int argc, char ** argv )
+{
+ SHPHandle old_SHP, new_SHP;
+ DBFHandle old_DBF, new_DBF;
+ int nShapeType, nEntities, i;
+ unsigned int j;
+// int nVertices, nParts *panParts, iPart;
+// double *padVertices, adBounds[4];
+// const char *pszPlus;
+// DBFFieldType idfld_type;
+ SHPObject *psCShape;
+ FILE *ifp = NULL;
+// int idfld, nflds;
+// char kv[257] = "";
+// char idfldName[120] = "";
+// char fldName[120] = "";
+// char shpFileName[120] = "";
+// char dbfFileName[120] = "";
+ char prjFileName[120] = "";
+ char parg[80];
+// double apeture[4];
+ int inarg, outarg;
+ char *DBFRow = NULL;
+
+/* for testing only
+ char *in_args[] = { "init=nad83:1002", "units=us-ft" };
+ char *out_args[] = { "proj=utm", "zone=16", "units=m" };
+*/
+
+ char *in_args[16];
+ char *out_args[16];
+ int in_argc = 0 , out_argc = 0, outf_arg;
+ char *arglst;
+ projPJ orig_prj, new_prj;
+// va_list myargs, moargs;
+
+ if( argc < 4)
+ {
+ printf( "shpproj shp_file new_shp ( -i=in_proj_file | -i=\"in_params\" | -i=geographic ) ( -o=out_info_file | -o=\"out_params\" | -o=geographic ) \n" );
+ exit( 1 );
+ }
+
+ old_SHP = SHPOpen( argv[1], "rb" );
+ old_DBF = DBFOpen( argv[1], "rb" );
+ if( old_SHP == NULL || old_DBF == NULL )
+ {
+ printf( "Unable to open old files:%s\n", argv[1] );
+ exit( 1 );
+ }
+
+ outf_arg = 2;
+ inarg = 0;
+ outarg = 0;
+ for ( i = 3; i < argc; i++ ) {
+ if ( !strncmp ("-i=", argv[i], 3 )) inarg = i;
+ if ( !strncmp ("-o=", argv[i], 3 )) outarg = i;
+ }
+
+
+/* if shapefile has a prj component then use that
+ else try for a file then read args as list */
+
+ if( inarg == 0 )
+ {
+ strcpy( prjFileName, argv[1] );
+ ifp = fopen( asFileName ( prjFileName, "prj" ),"rt");
+ }
+ else
+ {
+ ifp = fopen( asFileName ( argv[inarg] + 3, "prj" ),"rt");
+ }
+
+ i = 0;
+ if ( ifp ) {
+ if( inarg == 0 )
+ printf ("using default file proj params from <- %s\n",
+ asFileName ( prjFileName, "prj" ) );
+ else
+ printf ("using file proj params from <- %s\n",
+ asFileName ( argv[inarg] + 3, "prj" ) );
+
+ while( fscanf( ifp, "%s", parg) != EOF ) {
+ in_args[i] = malloc ( strlen(parg)+1 );
+ strcpy ( in_args[i], parg);
+ i++;
+ }
+
+ in_argc = i;
+ fclose (ifp);
+ }
+ else {
+ if ( inarg > 0 ) {
+ arglst = argv[inarg] + 3;
+ j = 0;
+ i = 0;
+ while ( j < strlen (arglst) ) {
+ in_argc += sscanf ( arglst + j, "%s", parg);
+
+ in_args[i] = malloc( strlen (parg)+1);
+ strcpy (in_args[i], parg);
+ i++;
+ j += strlen (parg) +1;
+ if ( arglst[j] + 1 == 0 ) j = strlen (argv[inarg]);
+ }
+ }
+ }
+
+ i = 0;
+ if ( outarg > 0 ) ifp = fopen( asFileName ( argv[outarg] + 3, "prj" ),"rt");
+ if ( ifp ) {
+ while( fscanf( ifp, "%s", parg) != EOF ) {
+ out_args[i] = malloc ( strlen(parg));
+ strcpy ( out_args[i], parg);
+ i++;
+ }
+ out_argc = i;
+ fclose (ifp);
+ }
+ else {
+ if ( outarg > 0 ) {
+ arglst = argv[outarg] + 3;
+ j = 0;
+ i = 0;
+ while ( j < strlen (arglst) ) {
+ out_argc += sscanf ( arglst + j, "%s", parg);
+
+ out_args[i] = malloc( strlen (parg)+1);
+ strcpy (out_args[i], parg);
+ i++;
+ j += strlen (parg) +1;
+ if ( arglst[j] + 1 == 0 ) j = strlen (argv[outarg]);
+ }
+ }
+ }
+
+ if ( !strcmp( argv[inarg], "-i=geographic" )) in_argc = 0;
+ if ( !strcmp( argv[outarg], "-o=geographic" )) out_argc = 0;
+
+ orig_prj = SHPSetProjection ( in_argc, in_args );
+ new_prj = SHPSetProjection ( out_argc, out_args );
+
+ if ( !(( (!in_argc) || orig_prj) && ( (!out_argc) || new_prj) )) {
+ fprintf (stderr, "unable to process projection, exiting...\n");
+ exit(1);
+ }
+
+
+ SHPGetInfo( old_SHP, &nEntities, &nShapeType, NULL, NULL);
+ new_SHP = SHPCreate ( argv[outf_arg], nShapeType );
+
+ new_DBF = DBFCloneEmpty (old_DBF, argv[outf_arg]);
+ if( new_SHP == NULL || new_DBF == NULL )
+ {
+ printf( "Unable to create new files:%s\n", argv[outf_arg] );
+ exit( 1 );
+ }
+
+ DBFRow = (char *) malloc ( (old_DBF->nRecordLength) + 15 );
+
+ for( i = 0; i < nEntities; i++ )
+ {
+// int j;
+
+ psCShape = SHPReadObject ( old_SHP, i );
+
+ SHPProject (psCShape, orig_prj, new_prj );
+
+ SHPWriteObject ( new_SHP, -1, psCShape );
+ SHPDestroyObject ( psCShape );
+
+ memcpy ( DBFRow, DBFReadTuple ( old_DBF, i ), old_DBF->nRecordLength );
+ DBFWriteTuple ( new_DBF, new_DBF->nRecords, DBFRow );
+
+ }
+
+ SHPFreeProjection ( orig_prj );
+ SHPFreeProjection ( new_prj );
+
+ /* store projection params into prj file */
+ ifp = fopen( asFileName ( argv[outf_arg], "prj" ),"wt");
+ if ( ifp ) {
+
+ if ( out_argc == 0 )
+ { fprintf( ifp, "proj=geographic\n" ); }
+ else
+ { for ( i = 0; i < out_argc; i++ )
+ fprintf( ifp, "%s\n", out_args[i]);
+ }
+ fclose (ifp);
+ }
+
+ SHPClose( old_SHP );
+ SHPClose( new_SHP );
+ DBFClose( old_DBF );
+ DBFClose( new_DBF );
+ printf ("\n");
+ return(0);
+}
+
+
diff --git a/src/shapelib/contrib/shpwkb.c b/src/shapelib/contrib/shpwkb.c
new file mode 100644
index 0000000..977a562
--- /dev/null
+++ b/src/shapelib/contrib/shpwkb.c
@@ -0,0 +1,160 @@
+/******************************************************************************
+ * Copyright (c) 1999, Carl Anderson
+ *
+ * this code is based in part on the earlier work of Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * shpwkb.c - test WKB binary Input / Output
+ *
+ *
+ * $Log: shpwkb.c,v $
+ * Revision 1.3 2010/07/11 07:51:03 we7u
+ * Fixing more compiler warnings. There are a few left yet.
+ *
+ * Revision 1.2 2010/07/11 07:24:37 we7u
+ * Fixing multiple minor warnings with Shapelib. Still plenty left.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.1 1999/05/26 02:29:36 candrsn
+ * OGis Well Known Binary test program (output only)
+ *
+ *
+ *
+ */
+
+#include "shapefil.h"
+#include "shpgeo.h"
+
+int main( int argc, char ** argv )
+{
+ SHPHandle old_SHP;
+// SHPHandle new_SHP;
+ DBFHandle old_DBF;
+// DBFHandle new_DBF;
+ int nShapeType, nEntities, i;
+// int nVertices, nParts, *panParts, iPart;
+// double *padVertices, adBounds[4];
+// const char *pszPlus;
+// DBFFieldType idfld_type;
+// int idfld, nflds;
+// char kv[257] = "";
+// char idfldName[120] = "";
+// char fldName[120] = "";
+// char shpFileName[120] = "";
+// char dbfFileName[120] = "";
+// char *DBFRow = NULL;
+// int Cpan[2] = { 0,0 };
+ int byRing = 0;
+// PT oCentrd, ringCentrd;
+ SHPObject *psCShape;
+// SHPObject *cent_pt;
+// double oArea = 0.0, oLen = 0.0;
+ WKBStreamObj *wkbObj = NULL;
+ FILE *wkb_file = NULL;
+
+ if( argc < 3 )
+ {
+ printf( "shpwkb shp_file wkb_file\n" );
+ exit( 1 );
+ }
+
+ old_SHP = SHPOpen (argv[1], "rb" );
+ old_DBF = DBFOpen (argv[1], "rb");
+ if( old_SHP == NULL || old_DBF == NULL )
+ {
+ printf( "Unable to open old files:%s\n", argv[1] );
+ exit( 1 );
+ }
+
+ wkb_file = fopen ( argv[2], "wb");
+ wkbObj = calloc ( 3, sizeof (int) );
+
+ SHPGetInfo( old_SHP, &nEntities, &nShapeType, NULL, NULL );
+ for( i = 0; i < nEntities; i++ )
+ {
+ int res ;
+
+ psCShape = SHPReadObject( old_SHP, i );
+
+ if ( byRing == 1 ) {
+ int ring, prevStart;
+// int ringDir;
+// double ringArea;
+
+ prevStart = psCShape->nVertices;
+ for ( ring = (psCShape->nParts - 1); ring >= 0; ring-- ) {
+ SHPObject *psO;
+ int numVtx, rStart;
+// int j;
+
+ rStart = psCShape->panPartStart[ring];
+ if ( ring == (psCShape->nParts -1) )
+ { numVtx = psCShape->nVertices - rStart; }
+ else
+ { numVtx = psCShape->panPartStart[ring+1] - rStart; }
+
+ printf ("(shpdata) Ring(%d) (%d for %d) \n", ring, rStart, numVtx);
+ psO = SHPClone ( psCShape, ring, ring + 1 );
+
+ SHPDestroyObject ( psO );
+ printf ("(shpdata) End Ring \n");
+ } /* (ring) [0,nParts */
+
+ } /* by ring */
+
+ printf ("gonna build a wkb \n");
+ res = SHPWriteOGisWKB ( wkbObj, psCShape );
+ printf ("gonna write a wkb that is %d bytes long \n", wkbObj->StreamPos );
+ fwrite ( (void*) wkbObj->wStream, 1, wkbObj->StreamPos, wkb_file );
+ }
+
+
+ free ( wkbObj );
+ SHPClose( old_SHP );
+ DBFClose( old_DBF );
+ if ( wkb_file ) fclose ( wkb_file );
+
+ printf ("\n");
+ return(0);
+}
+
diff --git a/src/shapelib/dbf_api.html b/src/shapelib/dbf_api.html
new file mode 100644
index 0000000..b0fa373
--- /dev/null
+++ b/src/shapelib/dbf_api.html
@@ -0,0 +1,408 @@
+<html>
+<head>
+<title>Attribute (.DBF) API</title>
+</head>
+<body>
+<h1>Attribute (.DBF) API</h1>
+
+The Attribute (DBF) API uses DBFHandle to represent a handle for access
+to one .dbf file. The contents of the DBFHandle are visible (see shapefil.h)
+but should be ignored by the application. It is intended that all information
+be accessed by API functions. Note that there should be exactly one record
+in the .dbf file for each shape in the .shp/.shx files. This constraint
+must be maintained by the application.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFOpen()</h2>
+
+<pre>
+DBFHandle DBFOpen( const char * pszDBFFile, const char * pszAccess );
+
+ pszDBFFile: The name of the xBase (.dbf) file to access.
+
+ pszAccess: The fopen() style access string. At this time only
+ "rb" (read-only binary) and "rb+" (read/write binary)
+ should be used.
+</pre>
+
+ The DBFOpen() function should be used to establish access to an existing
+ xBase format table file. The returned DBFHandle is passed to other
+ access functions, and DBFClose() should be invoked to recover resources, and
+ flush changes to disk when complete. The DBFCreate() function should
+ called to create new xBase files. As a convenience, DBFOpen() can be
+ called with the name of a .shp or .shx file, and it will figure out the
+ name of the related .dbf file.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFCreate()</h2>
+
+<pre>
+DBFHandle DBFCreate( const char * pszDBFFile );
+
+ pszDBFFile: The name of the xBase (.dbf) file to create.
+</pre>
+
+ The DBFCreate() function creates a new xBase format file with the given
+ name, and returns an access handle that can be used with other DBF functions.
+ The newly created file will have no fields, and no records. Fields should
+ be added with DBFAddField() before any records add written.
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFGetFieldCount()</h2>
+
+<pre>
+int DBFGetFieldCount( DBFHandle hDBF );
+
+ hDBF: The access handle for the file to be queried, as returned
+ by DBFOpen(), or DBFCreate().
+</pre>
+
+ The DBFGetFieldCount() function returns the number of fields currently
+ defined for the indicated xBase file.
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFGetRecordCount()</h2>
+
+<pre>
+int DBFGetRecordCount( DBFHandle hDBF );
+
+ hDBF: The access handle for the file to be queried, as returned by
+ DBFOpen(), or DBFCreate().
+</pre>
+
+ The DBFGetRecordCount() function returns the number of records that
+ exist on the xBase file currently. Note that with shape files one xBase
+ record exists for each shape in the .shp/.shx files.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFGetFieldIndex()</h2>
+
+<pre>
+int DBFGetFieldIndex( DBFHandle hDBF, const char *pszFieldName );
+
+ hDBF: The access handle for the file to be queried, as returned by
+ DBFOpen(), or DBFCreate().
+
+ pszFieldName: Name of the field to search for.
+</pre>
+
+ Returns the index of the field matching this name, or -1 on failure. The
+ comparison is case insensitive. However, lengths must match exactly.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFGetFieldInfo()</h2>
+
+<pre>
+DBFFieldType DBFGetFieldInfo( DBFHandle hDBF, int iField, char * pszFieldName,
+ int * pnWidth, int * pnDecimals );
+
+ hDBF: The access handle for the file to be queried, as returned by
+ DBFOpen(), or DBFCreate().
+
+ iField: The field to be queried. This should be a number between
+ 0 and n-1, where n is the number fields on the file, as
+ returned by DBFGetFieldCount().
+
+ pszFieldName: If this pointer is not NULL the name of the requested field
+ will be written to this location. The pszFieldName buffer
+ should be at least 12 character is size in order to hold
+ the longest possible field name of 11 characters plus a
+ terminating zero character.
+
+ pnWidth: If this pointer is not NULL, the width of the requested field
+ will be returned in the int pointed to by pnWidth. This is
+ the width in characters.
+
+ pnDecimals: If this pointer is not NULL, the number of decimal places
+ precision defined for the field will be returned. This is
+ zero for integer fields, or non-numeric fields.
+</pre>
+
+ The DBFGetFieldInfo() returns the type of the requested field, which is
+ one of the DBFFieldType enumerated values. As well, the field name, and
+ field width information can optionally be returned. The field type returned
+ does not correspond one to one with the xBase field types. For instance
+ the xBase field type for Date will just be returned as being FTInteger. <p>
+
+<pre>
+ typedef enum {
+ FTString, /* fixed length string field */
+ FTInteger, /* numeric field with no decimals */
+ FTDouble, /* numeric field with decimals */
+ FTLogical, /* logical field. */
+ FTInvalid /* not a recognised field type */
+ } DBFFieldType;
+</pre>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFAddField()</h2>
+
+<pre>
+int DBFAddField( DBFHandle hDBF, const char * pszFieldName,
+ DBFFieldType eType, int nWidth, int nDecimals );
+
+ hDBF: The access handle for the file to be updated, as returned by
+ DBFOpen(), or DBFCreate().
+
+ pszFieldName: The name of the new field. At most 11 character will be used.
+ In order to use the xBase file in some packages it may be
+ necessary to avoid some special characters in the field names
+ such as spaces, or arithmetic operators.
+
+ eType: One of FTString, FTInteger or FTDouble in order to establish
+ the type of the new field. Note that some valid xBase field
+ types cannot be created such as date fields.
+
+ nWidth: The width of the field to be created. For FTString fields this
+ establishes the maximum length of string that can be stored.
+ For FTInteger this establishes the number of digits of the
+ largest number that can
+ be represented. For FTDouble fields this in combination
+ with the nDecimals value establish the size, and precision
+ of the created field.
+
+ nDecimals: The number of decimal places to reserve for FTDouble fields.
+ For all other field types this should be zero. For instance
+ with nWidth=7, and nDecimals=3 numbers would be formatted
+ similarly to `123.456'.
+</pre>
+
+ The DBFAddField() function is used to add new fields to an existing xBase
+ file opened with DBFOpen(), or created with DBFCreate(). Note that fields
+ can only be added to xBase files with no records, though this is limitation
+ of this API, not of the file format.<p>
+
+ The DBFAddField() return value is the field number of the new field, or
+ -1 if the addition of the field failed.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFReadIntegerAttribute()</h2>
+
+<pre>
+int DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
+
+ hDBF: The access handle for the file to be queried, as returned by
+ DBFOpen(), or DBFCreate().
+
+ iShape: The record number (shape number) from which the field value
+ should be read.
+
+ iField: The field within the selected record that should be read.
+</pre>
+
+ The DBFReadIntegerAttribute() will read the value of one field and return
+ it as an integer. This can be used even with FTString fields, though the
+ returned value will be zero if not interpretable as a number.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFReadDoubleAttribute()</h2>
+
+<pre>
+double DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
+
+ hDBF: The access handle for the file to be queried, as returned by
+ DBFOpen(), or DBFCreate().
+
+ iShape: The record number (shape number) from which the field value
+ should be read.
+
+ iField: The field within the selected record that should be read.
+</pre>
+
+ The DBFReadDoubleAttribute() will read the value of one field and return
+ it as a double. This can be used even with FTString fields, though the
+ returned value will be zero if not interpretable as a number.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFReadStringAttribute()</h2>
+
+<pre>
+const char *DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
+
+ hDBF: The access handle for the file to be queried, as returned by
+ DBFOpen(), or DBFCreate().
+
+ iShape: The record number (shape number) from which the field value
+ should be read.
+
+ iField: The field within the selected record that should be read.
+</pre>
+
+ The DBFReadStringAttribute() will read the value of one field and return
+ it as a string. This function may be used on any field type (including
+ FTInteger and FTDouble) and will return the string representation stored
+ in the .dbf file. The returned pointer is to an internal buffer
+ which is only valid untill the next DBF function call. It's contents may
+ be copied with normal string functions such as strcpy(), or strdup(). If
+ the TRIM_DBF_WHITESPACE macro is defined in shapefil.h (it is by default)
+ then all leading and trailing space (ASCII 32) characters will be stripped
+ before the string is returned.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFIsAttributeNULL()</h2>
+
+<pre>
+int DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
+
+ hDBF: The access handle for the file to be queried, as returned by
+ DBFOpen(), or DBFCreate().
+
+ iShape: The record number (shape number) from which the field value
+ should be read.
+
+ iField: The field within the selected record that should be read.
+</pre>
+
+ This function will return TRUE if the indicated field is NULL valued
+ otherwise FALSE. Note that NULL fields are represented in the .dbf file
+ as having all spaces in the field. Reading NULL fields will result in
+ a value of 0.0 or an empty string with the other DBFRead*Attribute()
+ functions.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFWriteIntegerAttribute</h2>
+
+<pre>
+int DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField,
+ int nFieldValue );
+
+ hDBF: The access handle for the file to be written, as returned by
+ DBFOpen(), or DBFCreate().
+
+ iShape: The record number (shape number) to which the field value
+ should be written.
+
+ iField: The field within the selected record that should be written.
+
+ nFieldValue: The integer value that should be written.
+</pre>
+
+The DBFWriteIntegerAttribute() function is used to write a value to a numeric
+field (FTInteger, or FTDouble). If the write succeeds the value TRUE will
+be returned, otherwise FALSE will be returned. If the value is too large to
+fit in the field, it will be truncated and FALSE returned.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFWriteDoubleAttribute()</h2>
+
+<pre>
+int DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
+ double dFieldValue );
+
+ hDBF: The access handle for the file to be written, as returned by
+ DBFOpen(), or DBFCreate().
+
+ iShape: The record number (shape number) to which the field value
+ should be written.
+
+ iField: The field within the selected record that should be written.
+
+ dFieldValue: The floating point value that should be written.
+</pre>
+
+The DBFWriteDoubleAttribute() function is used to write a value to a numeric
+field (FTInteger, or FTDouble). If the write succeeds the value TRUE will
+be returned, otherwise FALSE will be returned. If the value is too large to
+fit in the field, it will be truncated and FALSE returned.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFWriteStringAttribute()</h2>
+
+<pre>
+int DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
+ const char * pszFieldValue );
+
+ hDBF: The access handle for the file to be written, as returned by
+ DBFOpen(), or DBFCreate().
+
+ iShape: The record number (shape number) to which the field value
+ should be written.
+
+ iField: The field within the selected record that should be written.
+
+ pszFieldValue: The string to be written to the field.
+</pre>
+
+The DBFWriteStringAttribute() function is used to write a value to a string
+field (FString). If the write succeeds the value TRUE willbe returned,
+otherwise FALSE will be returned. If the value is too large to
+fit in the field, it will be truncated and FALSE returned.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFWriteNULLAttribute()</h2>
+
+<pre>
+int DBFWriteNULLAttribute( DBFHandle hDBF, int iShape, int iField );
+
+ hDBF: The access handle for the file to be written, as returned by
+ DBFOpen(), or DBFCreate().
+
+ iShape: The record number (shape number) to which the field value
+ should be written.
+
+ iField: The field within the selected record that should be written.
+</pre>
+
+The DBFWriteNULLAttribute() function is used to clear the indicated field
+to a NULL value. In the .dbf file this is represented by setting the entire
+field to spaces. If the write succeeds the value TRUE willbe returned,
+otherwise FALSE will be returned.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFClose()</h2>
+
+<pre>
+void DBFClose( DBFHandle hDBF );
+
+ hDBF: The access handle for the file to be closed.
+</pre>
+
+ The DBFClose() function will close the indicated xBase file (opened with
+ DBFOpen(), or DBFCreate()), flushing out all information to the file on
+ disk, and recovering any resources associated with having the file open.
+ The file handle (hDBF) should not be used again with the DBF API after
+ calling DBFClose().<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFGetNativeFieldType()</h2>
+
+<pre>
+char DBFGetNativeFieldType( DBFHandle hDBF, int iField );
+
+ hDBF: The access handle for the file.
+ iField: The field index to query.
+
+</pre>
+
+ This function returns the DBF type code of the indicated field. It will
+ be one of:<p>
+
+<ul>
+<li> 'C' (String)
+<li> 'D' (Date)
+<li> 'F' (Float)
+<li> 'N' (Numeric, with or without decimal)
+<li> 'L' (Logical)
+<li> 'M' (Memo: 10 digits .DBT block ptr)
+<li> ' ' (field out of range)
+</ul>
+
+</body>
+</html>
diff --git a/src/shapelib/dbfadd.c b/src/shapelib/dbfadd.c
new file mode 100644
index 0000000..2dd2b01
--- /dev/null
+++ b/src/shapelib/dbfadd.c
@@ -0,0 +1,151 @@
+/******************************************************************************
+ * $Id: dbfadd.c,v 1.3 2009/06/04 04:25:19 we7u Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Sample application for adding a record to an existing .dbf file.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: dbfadd.c,v $
+ * Revision 1.3 2009/06/04 04:25:19 we7u
+ * Getting rid of compiler warnings due to unused variable.
+ *
+ * Revision 1.2 2009/06/03 22:24:19 we7u
+ * Adding includes for string.h to get rid of compiler warnings.
+ *
+ * Revision 1.1 2006/11/10 21:48:09 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.7 2002/01/15 14:36:07 warmerda
+ * updated email address
+ *
+ * Revision 1.6 2001/05/31 18:15:40 warmerda
+ * Added support for NULL fields in DBF files
+ *
+ * Revision 1.5 1999/11/05 14:12:04 warmerda
+ * updated license terms
+ *
+ * Revision 1.4 1998/12/03 16:36:06 warmerda
+ * Added stdlib.h and math.h to get atof() prototype.
+ *
+ * Revision 1.3 1995/10/21 03:13:23 warmerda
+ * Use binary mode..
+ *
+ * Revision 1.2 1995/08/04 03:15:59 warmerda
+ * Added header.
+ *
+ */
+
+//static char rcsid[] =
+// "$Id: dbfadd.c,v 1.3 2009/06/04 04:25:19 we7u Exp $";
+
+#include "shapefil.h"
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main( int argc, char ** argv )
+
+{
+ DBFHandle hDBF;
+ int i, iRecord;
+
+/* -------------------------------------------------------------------- */
+/* Display a usage message. */
+/* -------------------------------------------------------------------- */
+ if( argc < 3 )
+ {
+ printf( "dbfadd xbase_file field_values\n" );
+
+ exit( 1 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Create the database. */
+/* -------------------------------------------------------------------- */
+ hDBF = DBFOpen( argv[1], "r+b" );
+ if( hDBF == NULL )
+ {
+ printf( "DBFOpen(%s,\"rb+\") failed.\n", argv[1] );
+ exit( 2 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Do we have the correct number of arguments? */
+/* -------------------------------------------------------------------- */
+ if( DBFGetFieldCount( hDBF ) != argc - 2 )
+ {
+ printf( "Got %d fields, but require %d\n",
+ argc - 2, DBFGetFieldCount( hDBF ) );
+ exit( 3 );
+ }
+
+ iRecord = DBFGetRecordCount( hDBF );
+
+/* -------------------------------------------------------------------- */
+/* Loop assigning the new field values. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < DBFGetFieldCount(hDBF); i++ )
+ {
+ if( strcmp( argv[i+2], "" ) == 0 )
+ DBFWriteNULLAttribute(hDBF, iRecord, i );
+ else if( DBFGetFieldInfo( hDBF, i, NULL, NULL, NULL ) == FTString )
+ DBFWriteStringAttribute(hDBF, iRecord, i, argv[i+2] );
+ else
+ DBFWriteDoubleAttribute(hDBF, iRecord, i, atof(argv[i+2]) );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Close and cleanup. */
+/* -------------------------------------------------------------------- */
+ DBFClose( hDBF );
+
+ return( 0 );
+}
diff --git a/src/shapelib/dbfcreate.c b/src/shapelib/dbfcreate.c
new file mode 100644
index 0000000..4cb21d0
--- /dev/null
+++ b/src/shapelib/dbfcreate.c
@@ -0,0 +1,150 @@
+/******************************************************************************
+ * $Id: dbfcreate.c,v 1.2 2009/06/04 04:25:19 we7u Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Sample application for creating a new .dbf file.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: dbfcreate.c,v $
+ * Revision 1.2 2009/06/04 04:25:19 we7u
+ * Getting rid of compiler warnings due to unused variable.
+ *
+ * Revision 1.1 2006/11/10 21:48:09 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.6 2002/01/15 14:36:07 warmerda
+ * updated email address
+ *
+ * Revision 1.5 2000/07/07 13:39:45 warmerda
+ * removed unused variables, and added system include files
+ *
+ * Revision 1.4 1999/11/05 14:12:04 warmerda
+ * updated license terms
+ *
+ * Revision 1.3 1999/04/01 18:47:44 warmerda
+ * Fixed DBFAddField() call convention.
+ *
+ * Revision 1.2 1995/08/04 03:17:11 warmerda
+ * Added header.
+ *
+ */
+
+//static char rcsid[] =
+// "$Id: dbfcreate.c,v 1.2 2009/06/04 04:25:19 we7u Exp $";
+
+#include <stdlib.h>
+#include <string.h>
+#include "shapefil.h"
+
+int main( int argc, char ** argv )
+
+{
+ DBFHandle hDBF;
+ int i;
+
+/* -------------------------------------------------------------------- */
+/* Display a usage message. */
+/* -------------------------------------------------------------------- */
+ if( argc < 2 )
+ {
+ printf( "dbfcreate xbase_file [[-s field_name width],[-n field_name width decimals]]...\n" );
+
+ exit( 1 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Create the database. */
+/* -------------------------------------------------------------------- */
+ hDBF = DBFCreate( argv[1] );
+ if( hDBF == NULL )
+ {
+ printf( "DBFCreate(%s) failed.\n", argv[1] );
+ exit( 2 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Loop over the field definitions adding new fields. */
+/* -------------------------------------------------------------------- */
+ for( i = 2; i < argc; i++ )
+ {
+ if( strcmp(argv[i],"-s") == 0 && i < argc-2 )
+ {
+ if( DBFAddField( hDBF, argv[i+1], FTString, atoi(argv[i+2]), 0 )
+ == -1 )
+ {
+ printf( "DBFAddField(%s,FTString,%d,0) failed.\n",
+ argv[i+1], atoi(argv[i+2]) );
+ exit( 4 );
+ }
+ i = i + 2;
+ }
+ else if( strcmp(argv[i],"-n") == 0 && i < argc-3 )
+ {
+ if( DBFAddField( hDBF, argv[i+1], FTDouble, atoi(argv[i+2]),
+ atoi(argv[i+3]) ) == -1 )
+ {
+ printf( "DBFAddField(%s,FTDouble,%d,%d) failed.\n",
+ argv[i+1], atoi(argv[i+2]), atoi(argv[i+3]) );
+ exit( 4 );
+ }
+ i = i + 3;
+ }
+ else
+ {
+ printf( "Argument incomplete, or unrecognised:%s\n", argv[i] );
+ exit( 3 );
+ }
+ }
+
+ DBFClose( hDBF );
+
+ return( 0 );
+}
diff --git a/src/shapelib/dbfdump.c b/src/shapelib/dbfdump.c
new file mode 100644
index 0000000..eba2fef
--- /dev/null
+++ b/src/shapelib/dbfdump.c
@@ -0,0 +1,305 @@
+/******************************************************************************
+ * $Id: dbfdump.c,v 1.3 2010/07/11 20:30:00 we7u Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Sample application for dumping .dbf files to the terminal.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: dbfdump.c,v $
+ * Revision 1.3 2010/07/11 20:30:00 we7u
+ * More minor tweaks to get rid of compiler warnings. Of particular note are
+ * some TODO entries added to a couple of files for two enumerated values that
+ * weren't being handled in "switch" statements. There still isn't any code
+ * for those case statements, but the compiler warnings are gone.
+ *
+ * Revision 1.2 2010/07/11 07:24:37 we7u
+ * Fixing multiple minor warnings with Shapelib. Still plenty left.
+ *
+ * Revision 1.1 2006/11/10 21:48:09 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.9 2002/01/15 14:36:07 warmerda
+ * updated email address
+ *
+ * Revision 1.8 2001/05/31 18:15:40 warmerda
+ * Added support for NULL fields in DBF files
+ *
+ * Revision 1.7 2000/09/20 13:13:55 warmerda
+ * added break after default:
+ *
+ * Revision 1.6 2000/07/07 13:39:45 warmerda
+ * removed unused variables, and added system include files
+ *
+ * Revision 1.5 1999/11/05 14:12:04 warmerda
+ * updated license terms
+ *
+ * Revision 1.4 1998/12/31 15:30:13 warmerda
+ * Added -m, -r, and -h commandline options.
+ *
+ * Revision 1.3 1995/10/21 03:15:01 warmerda
+ * Changed to use binary file access.
+ *
+ * Revision 1.2 1995/08/04 03:16:22 warmerda
+ * Added header.
+ *
+ */
+
+//static char rcsid[] =
+// "$Id: dbfdump.c,v 1.3 2010/07/11 20:30:00 we7u Exp $";
+
+#include <stdlib.h>
+#include <string.h>
+#include "shapefil.h"
+
+int main( int argc, char ** argv )
+
+{
+ DBFHandle hDBF;
+ int *panWidth, i, iRecord;
+ char szFormat[32], *pszFilename = NULL;
+ int nWidth, nDecimals;
+ int bHeader = 0;
+ int bRaw = 0;
+ int bMultiLine = 0;
+ char szTitle[12];
+
+/* -------------------------------------------------------------------- */
+/* Handle arguments. */
+/* -------------------------------------------------------------------- */
+ for( i = 1; i < argc; i++ )
+ {
+ if( strcmp(argv[i],"-h") == 0 )
+ bHeader = 1;
+ else if( strcmp(argv[i],"-r") == 0 )
+ bRaw = 1;
+ else if( strcmp(argv[i],"-m") == 0 )
+ bMultiLine = 1;
+ else
+ pszFilename = argv[i];
+ }
+
+/* -------------------------------------------------------------------- */
+/* Display a usage message. */
+/* -------------------------------------------------------------------- */
+ if( pszFilename == NULL )
+ {
+ printf( "dbfdump [-h] [-r] [-m] xbase_file\n" );
+ printf( " -h: Write header info (field descriptions)\n" );
+ printf( " -r: Write raw field info, numeric values not reformatted\n" );
+ printf( " -m: Multiline, one line per field.\n" );
+ exit( 1 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Open the file. */
+/* -------------------------------------------------------------------- */
+ hDBF = DBFOpen( pszFilename, "rb" );
+ if( hDBF == NULL )
+ {
+ printf( "DBFOpen(%s,\"r\") failed.\n", argv[1] );
+ exit( 2 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* If there is no data in this file let the user know. */
+/* -------------------------------------------------------------------- */
+ if( DBFGetFieldCount(hDBF) == 0 )
+ {
+ printf( "There are no fields in this table!\n" );
+ exit( 3 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Dump header definitions. */
+/* -------------------------------------------------------------------- */
+ if( bHeader )
+ {
+ for( i = 0; i < DBFGetFieldCount(hDBF); i++ )
+ {
+ DBFFieldType eType;
+ const char *pszTypeName;
+
+ eType = DBFGetFieldInfo( hDBF, i, szTitle, &nWidth, &nDecimals );
+ if( eType == FTString )
+ pszTypeName = "String";
+ else if( eType == FTInteger )
+ pszTypeName = "Integer";
+ else if( eType == FTDouble )
+ pszTypeName = "Double";
+ else if( eType == FTInvalid )
+ pszTypeName = "Invalid";
+ else
+ pszTypeName = "Unknown";
+
+ printf( "Field %d: Type=%s, Title=`%s', Width=%d, Decimals=%d\n",
+ i, pszTypeName, szTitle, nWidth, nDecimals );
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Compute offsets to use when printing each of the field */
+/* values. We make each field as wide as the field title+1, or */
+/* the field value + 1. */
+/* -------------------------------------------------------------------- */
+ panWidth = (int *) malloc( DBFGetFieldCount( hDBF ) * sizeof(int) );
+
+ for( i = 0; i < DBFGetFieldCount(hDBF) && !bMultiLine; i++ )
+ {
+ DBFFieldType eType;
+
+ eType = DBFGetFieldInfo( hDBF, i, szTitle, &nWidth, &nDecimals );
+ if( (int)strlen(szTitle) > nWidth )
+ panWidth[i] = strlen(szTitle);
+ else
+ panWidth[i] = nWidth;
+
+ if( eType == FTString )
+ sprintf( szFormat, "%%-%ds ", panWidth[i] );
+ else
+ sprintf( szFormat, "%%%ds ", panWidth[i] );
+ printf( szFormat, szTitle );
+ }
+ printf( "\n" );
+
+/* -------------------------------------------------------------------- */
+/* Read all the records */
+/* -------------------------------------------------------------------- */
+ for( iRecord = 0; iRecord < DBFGetRecordCount(hDBF); iRecord++ )
+ {
+ if( bMultiLine )
+ printf( "Record: %d\n", iRecord );
+
+ for( i = 0; i < DBFGetFieldCount(hDBF); i++ )
+ {
+ DBFFieldType eType;
+
+ eType = DBFGetFieldInfo( hDBF, i, szTitle, &nWidth, &nDecimals );
+
+ if( bMultiLine )
+ {
+ printf( "%s: ", szTitle );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Print the record according to the type and formatting */
+/* information implicit in the DBF field description. */
+/* -------------------------------------------------------------------- */
+ if( !bRaw )
+ {
+ if( DBFIsAttributeNULL( hDBF, iRecord, i ) )
+ {
+ if( eType == FTString )
+ sprintf( szFormat, "%%-%ds", nWidth );
+ else
+ sprintf( szFormat, "%%%ds", nWidth );
+
+ printf( szFormat, "(NULL)" );
+ }
+ else
+ {
+ switch( eType )
+ {
+ case FTString:
+ sprintf( szFormat, "%%-%ds", nWidth );
+ printf( szFormat,
+ DBFReadStringAttribute( hDBF, iRecord, i ) );
+ break;
+
+ case FTInteger:
+ sprintf( szFormat, "%%%dd", nWidth );
+ printf( szFormat,
+ DBFReadIntegerAttribute( hDBF, iRecord, i ) );
+ break;
+
+ case FTDouble:
+ sprintf( szFormat, "%%%d.%dlf", nWidth, nDecimals );
+ printf( szFormat,
+ DBFReadDoubleAttribute( hDBF, iRecord, i ) );
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Just dump in raw form (as formatted in the file). */
+/* -------------------------------------------------------------------- */
+ else
+ {
+ sprintf( szFormat, "%%-%ds", nWidth );
+ printf( szFormat,
+ DBFReadStringAttribute( hDBF, iRecord, i ) );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Write out any extra spaces required to pad out the field */
+/* width. */
+/* -------------------------------------------------------------------- */
+ if( !bMultiLine )
+ {
+ sprintf( szFormat, "%%%ds", panWidth[i] - nWidth + 1 );
+ printf( szFormat, "" );
+ }
+
+ if( bMultiLine )
+ printf( "\n" );
+
+ fflush( stdout );
+ }
+ printf( "\n" );
+ }
+
+ DBFClose( hDBF );
+
+ return( 0 );
+}
diff --git a/src/shapelib/dbfopen.c b/src/shapelib/dbfopen.c
new file mode 100644
index 0000000..4de1e30
--- /dev/null
+++ b/src/shapelib/dbfopen.c
@@ -0,0 +1,1526 @@
+/******************************************************************************
+ * $Id: dbfopen.c,v 1.3 2006/11/14 21:30:18 we7u Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Implementation of .dbf access API documented in dbf_api.html.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: dbfopen.c,v $
+ * Revision 1.3 2006/11/14 21:30:18 we7u
+ * The last revision also commented out an unused variable that I forgot to
+ * mention in the cvs log.
+ *
+ * Revision 1.2 2006/11/14 21:28:02 we7u
+ * Casting a couple of variables to int's to get rid of compiler warnings.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.48 2003/03/10 14:51:27 warmerda
+ * DBFWrite* calls now return FALSE if they have to truncate
+ *
+ * Revision 1.47 2002/11/20 03:32:22 warmerda
+ * Ensure field name in DBFGetFieldIndex() is properly terminated.
+ *
+ * Revision 1.46 2002/10/09 13:10:21 warmerda
+ * Added check that width is positive.
+ *
+ * Revision 1.45 2002/09/29 00:00:08 warmerda
+ * added FTLogical and logical attribute read/write calls
+ *
+ * Revision 1.44 2002/05/07 13:46:11 warmerda
+ * Added DBFWriteAttributeDirectly().
+ *
+ * Revision 1.43 2002/02/13 19:39:21 warmerda
+ * Fix casting issues in DBFCloneEmpty().
+ *
+ * Revision 1.42 2002/01/15 14:36:07 warmerda
+ * updated email address
+ *
+ * Revision 1.41 2002/01/15 14:31:49 warmerda
+ * compute rather than copying nHeaderLength in DBFCloneEmpty()
+ *
+ * Revision 1.40 2002/01/09 04:32:35 warmerda
+ * fixed to read correct amount of header
+ *
+ * Revision 1.39 2001/12/11 22:41:03 warmerda
+ * improve io related error checking when reading header
+ *
+ * Revision 1.38 2001/11/28 16:07:31 warmerda
+ * Cleanup to avoid compiler warnings as suggested by Richard Hash.
+ *
+ * Revision 1.37 2001/07/04 05:18:09 warmerda
+ * do last fix properly
+ *
+ * Revision 1.36 2001/07/04 05:16:09 warmerda
+ * fixed fieldname comparison in DBFGetFieldIndex
+ *
+ * Revision 1.35 2001/06/22 02:10:06 warmerda
+ * fixed NULL shape support with help from Jim Matthews
+ *
+ * Revision 1.33 2001/05/31 19:20:13 warmerda
+ * added DBFGetFieldIndex()
+ *
+ * Revision 1.32 2001/05/31 18:15:40 warmerda
+ * Added support for NULL fields in DBF files
+ *
+ * Revision 1.31 2001/05/23 13:36:52 warmerda
+ * added use of SHPAPI_CALL
+ *
+ * Revision 1.30 2000/12/05 14:43:38 warmerda
+ * DBReadAttribute() white space trimming bug fix
+ *
+ * Revision 1.29 2000/10/05 14:36:44 warmerda
+ * fix bug with writing very wide numeric fields
+ *
+ * Revision 1.28 2000/09/25 14:18:07 warmerda
+ * Added some casts of strlen() return result to fix warnings on some
+ * systems, as submitted by Daniel.
+ *
+ * Revision 1.27 2000/09/25 14:15:51 warmerda
+ * added DBFGetNativeFieldType()
+ *
+ * Revision 1.26 2000/07/07 13:39:45 warmerda
+ * removed unused variables, and added system include files
+ *
+ * Revision 1.25 2000/05/29 18:19:13 warmerda
+ * avoid use of uchar, and adding casting fix
+ *
+ * Revision 1.24 2000/05/23 13:38:27 warmerda
+ * Added error checks on return results of fread() and fseek().
+ *
+ * Revision 1.23 2000/05/23 13:25:49 warmerda
+ * Avoid crashing if field or record are out of range in dbfread*attribute().
+ *
+ * Revision 1.22 1999/12/15 13:47:24 warmerda
+ * Added stdlib.h to ensure that atof() is prototyped.
+ *
+ * Revision 1.21 1999/12/13 17:25:46 warmerda
+ * Added support for upper case .DBF extention.
+ *
+ * Revision 1.20 1999/11/30 16:32:11 warmerda
+ * Use atof() instead of sscanf().
+ *
+ * Revision 1.19 1999/11/05 14:12:04 warmerda
+ * updated license terms
+ *
+ * Revision 1.18 1999/07/27 00:53:28 warmerda
+ * ensure that whole old field value clear on write of string
+ *
+ * Revision 1.1 1999/07/05 18:58:07 warmerda
+ * New
+ *
+ * Revision 1.17 1999/06/11 19:14:12 warmerda
+ * Fixed some memory leaks.
+ *
+ * Revision 1.16 1999/06/11 19:04:11 warmerda
+ * Remoted some unused variables.
+ *
+ * Revision 1.15 1999/05/11 03:19:28 warmerda
+ * added new Tuple api, and improved extension handling - add from candrsn
+ *
+ * Revision 1.14 1999/05/04 15:01:48 warmerda
+ * Added 'F' support.
+ *
+ * Revision 1.13 1999/03/23 17:38:59 warmerda
+ * DBFAddField() now actually does return the new field number, or -1 if
+ * it fails.
+ *
+ * Revision 1.12 1999/03/06 02:54:46 warmerda
+ * Added logic to convert shapefile name to dbf filename in DBFOpen()
+ * for convenience.
+ *
+ * Revision 1.11 1998/12/31 15:30:34 warmerda
+ * Improved the interchangability of numeric and string attributes. Add
+ * white space trimming option for attributes.
+ *
+ * Revision 1.10 1998/12/03 16:36:44 warmerda
+ * Use r+b instead of rb+ for binary access.
+ *
+ * Revision 1.9 1998/12/03 15:34:23 warmerda
+ * Updated copyright message.
+ *
+ * Revision 1.8 1997/12/04 15:40:15 warmerda
+ * Added newline character after field definitions.
+ *
+ * Revision 1.7 1997/03/06 14:02:10 warmerda
+ * Ensure bUpdated is initialized.
+ *
+ * Revision 1.6 1996/02/12 04:54:41 warmerda
+ * Ensure that DBFWriteAttribute() returns TRUE if it succeeds.
+ *
+ * Revision 1.5 1995/10/21 03:15:12 warmerda
+ * Changed to use binary file access, and ensure that the
+ * field name field is zero filled, and limited to 10 chars.
+ *
+ * Revision 1.4 1995/08/24 18:10:42 warmerda
+ * Added use of SfRealloc() to avoid pre-ANSI realloc() functions such
+ * as on the Sun.
+ *
+ * Revision 1.3 1995/08/04 03:15:16 warmerda
+ * Fixed up header.
+ *
+ * Revision 1.2 1995/08/04 03:14:43 warmerda
+ * Added header.
+ */
+
+//static char rcsid[] =
+// "$Id: dbfopen.c,v 1.3 2006/11/14 21:30:18 we7u Exp $";
+
+
+#include "shapefil.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#ifndef FALSE
+# define FALSE 0
+# define TRUE 1
+#endif
+
+static int nStringFieldLen = 0;
+static char * pszStringField = NULL;
+
+/************************************************************************/
+/* SfRealloc() */
+/* */
+/* A realloc cover function that will access a NULL pointer as */
+/* a valid input. */
+/************************************************************************/
+
+static void * SfRealloc( void * pMem, int nNewSize )
+
+{
+ if( pMem == NULL )
+ return( (void *) malloc(nNewSize) );
+ else
+ return( (void *) realloc(pMem,nNewSize) );
+}
+
+/************************************************************************/
+/* DBFWriteHeader() */
+/* */
+/* This is called to write out the file header, and field */
+/* descriptions before writing any actual data records. This */
+/* also computes all the DBFDataSet field offset/size/decimals */
+/* and so forth values. */
+/************************************************************************/
+
+static void DBFWriteHeader(DBFHandle psDBF)
+
+{
+ unsigned char abyHeader[XBASE_FLDHDR_SZ];
+ int i;
+
+ if( !psDBF->bNoHeader )
+ return;
+
+ psDBF->bNoHeader = FALSE;
+
+/* -------------------------------------------------------------------- */
+/* Initialize the file header information. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
+ abyHeader[i] = 0;
+
+ abyHeader[0] = 0x03; /* memo field? - just copying */
+
+ /* date updated on close, record count preset at zero */
+
+ abyHeader[8] = psDBF->nHeaderLength % 256;
+ abyHeader[9] = psDBF->nHeaderLength / 256;
+
+ abyHeader[10] = psDBF->nRecordLength % 256;
+ abyHeader[11] = psDBF->nRecordLength / 256;
+
+/* -------------------------------------------------------------------- */
+/* Write the initial 32 byte file header, and all the field */
+/* descriptions. */
+/* -------------------------------------------------------------------- */
+ fseek( psDBF->fp, 0, 0 );
+ fwrite( abyHeader, XBASE_FLDHDR_SZ, 1, psDBF->fp );
+ fwrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields, psDBF->fp );
+
+/* -------------------------------------------------------------------- */
+/* Write out the newline character if there is room for it. */
+/* -------------------------------------------------------------------- */
+ if( psDBF->nHeaderLength > 32*psDBF->nFields + 32 )
+ {
+ char cNewline;
+
+ cNewline = 0x0d;
+ fwrite( &cNewline, 1, 1, psDBF->fp );
+ }
+}
+
+/************************************************************************/
+/* DBFFlushRecord() */
+/* */
+/* Write out the current record if there is one. */
+/************************************************************************/
+
+static void DBFFlushRecord( DBFHandle psDBF )
+
+{
+ int nRecordOffset;
+
+ if( psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1 )
+ {
+ psDBF->bCurrentRecordModified = FALSE;
+
+ nRecordOffset = psDBF->nRecordLength * psDBF->nCurrentRecord
+ + psDBF->nHeaderLength;
+
+ fseek( psDBF->fp, nRecordOffset, 0 );
+ fwrite( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+ }
+}
+
+/************************************************************************/
+/* DBFOpen() */
+/* */
+/* Open a .dbf file. */
+/************************************************************************/
+
+DBFHandle SHPAPI_CALL
+DBFOpen( const char * pszFilename, const char * pszAccess )
+
+{
+ DBFHandle psDBF;
+ unsigned char *pabyBuf;
+ int nFields, nHeadLen, nRecLen, iField, i;
+ char *pszBasename, *pszFullname;
+
+/* -------------------------------------------------------------------- */
+/* We only allow the access strings "rb" and "r+". */
+/* -------------------------------------------------------------------- */
+ if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0
+ && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"rb+") != 0
+ && strcmp(pszAccess,"r+b") != 0 )
+ return( NULL );
+
+ if( strcmp(pszAccess,"r") == 0 )
+ pszAccess = "rb";
+
+ if( strcmp(pszAccess,"r+") == 0 )
+ pszAccess = "rb+";
+
+/* -------------------------------------------------------------------- */
+/* Compute the base (layer) name. If there is any extension */
+/* on the passed in filename we will strip it off. */
+/* -------------------------------------------------------------------- */
+ pszBasename = (char *) malloc(strlen(pszFilename)+5);
+ strcpy( pszBasename, pszFilename );
+ for( i = strlen(pszBasename)-1;
+ i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+ && pszBasename[i] != '\\';
+ i-- ) {}
+
+ if( pszBasename[i] == '.' )
+ pszBasename[i] = '\0';
+
+ pszFullname = (char *) malloc(strlen(pszBasename) + 5);
+ sprintf( pszFullname, "%s.dbf", pszBasename );
+
+ psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
+ psDBF->fp = fopen( pszFullname, pszAccess );
+
+ if( psDBF->fp == NULL )
+ {
+ sprintf( pszFullname, "%s.DBF", pszBasename );
+ psDBF->fp = fopen(pszFullname, pszAccess );
+ }
+
+ free( pszBasename );
+ free( pszFullname );
+
+ if( psDBF->fp == NULL )
+ {
+ free( psDBF );
+ return( NULL );
+ }
+
+ psDBF->bNoHeader = FALSE;
+ psDBF->nCurrentRecord = -1;
+ psDBF->bCurrentRecordModified = FALSE;
+
+/* -------------------------------------------------------------------- */
+/* Read Table Header info */
+/* -------------------------------------------------------------------- */
+ pabyBuf = (unsigned char *) malloc(500);
+ if( fread( pabyBuf, 32, 1, psDBF->fp ) != 1 )
+ {
+ fclose( psDBF->fp );
+ free( pabyBuf );
+ free( psDBF );
+ return NULL;
+ }
+
+ psDBF->nRecords =
+ pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256;
+
+ psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
+ psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256;
+
+ psDBF->nFields = nFields = (nHeadLen - 32) / 32;
+
+ psDBF->pszCurrentRecord = (char *) malloc(nRecLen);
+
+/* -------------------------------------------------------------------- */
+/* Read in Field Definitions */
+/* -------------------------------------------------------------------- */
+
+ pabyBuf = (unsigned char *) SfRealloc(pabyBuf,nHeadLen);
+ psDBF->pszHeader = (char *) pabyBuf;
+
+ fseek( psDBF->fp, 32, 0 );
+ if( fread( pabyBuf, nHeadLen-32, 1, psDBF->fp ) != 1 )
+ {
+ fclose( psDBF->fp );
+ free( pabyBuf );
+ free( psDBF );
+ return NULL;
+ }
+
+ psDBF->panFieldOffset = (int *) malloc(sizeof(int) * nFields);
+ psDBF->panFieldSize = (int *) malloc(sizeof(int) * nFields);
+ psDBF->panFieldDecimals = (int *) malloc(sizeof(int) * nFields);
+ psDBF->pachFieldType = (char *) malloc(sizeof(char) * nFields);
+
+ for( iField = 0; iField < nFields; iField++ )
+ {
+ unsigned char *pabyFInfo;
+
+ pabyFInfo = pabyBuf+iField*32;
+
+ if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' )
+ {
+ psDBF->panFieldSize[iField] = pabyFInfo[16];
+ psDBF->panFieldDecimals[iField] = pabyFInfo[17];
+ }
+ else
+ {
+ psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256;
+ psDBF->panFieldDecimals[iField] = 0;
+ }
+
+ psDBF->pachFieldType[iField] = (char) pabyFInfo[11];
+ if( iField == 0 )
+ psDBF->panFieldOffset[iField] = 1;
+ else
+ psDBF->panFieldOffset[iField] =
+ psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
+ }
+
+ return( psDBF );
+}
+
+/************************************************************************/
+/* DBFClose() */
+/************************************************************************/
+
+void SHPAPI_CALL
+DBFClose(DBFHandle psDBF)
+{
+/* -------------------------------------------------------------------- */
+/* Write out header if not already written. */
+/* -------------------------------------------------------------------- */
+ if( psDBF->bNoHeader )
+ DBFWriteHeader( psDBF );
+
+ DBFFlushRecord( psDBF );
+
+/* -------------------------------------------------------------------- */
+/* Update last access date, and number of records if we have */
+/* write access. */
+/* -------------------------------------------------------------------- */
+ if( psDBF->bUpdated )
+ {
+ unsigned char abyFileHeader[32];
+
+ fseek( psDBF->fp, 0, 0 );
+ fread( abyFileHeader, 32, 1, psDBF->fp );
+
+ abyFileHeader[1] = 95; /* YY */
+ abyFileHeader[2] = 7; /* MM */
+ abyFileHeader[3] = 26; /* DD */
+
+ abyFileHeader[4] = psDBF->nRecords % 256;
+ abyFileHeader[5] = (psDBF->nRecords/256) % 256;
+ abyFileHeader[6] = (psDBF->nRecords/(256*256)) % 256;
+ abyFileHeader[7] = (psDBF->nRecords/(256*256*256)) % 256;
+
+ fseek( psDBF->fp, 0, 0 );
+ fwrite( abyFileHeader, 32, 1, psDBF->fp );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Close, and free resources. */
+/* -------------------------------------------------------------------- */
+ fclose( psDBF->fp );
+
+ if( psDBF->panFieldOffset != NULL )
+ {
+ free( psDBF->panFieldOffset );
+ free( psDBF->panFieldSize );
+ free( psDBF->panFieldDecimals );
+ free( psDBF->pachFieldType );
+ }
+
+ free( psDBF->pszHeader );
+ free( psDBF->pszCurrentRecord );
+
+ free( psDBF );
+
+ if( pszStringField != NULL )
+ {
+ free( pszStringField );
+ pszStringField = NULL;
+ nStringFieldLen = 0;
+ }
+}
+
+/************************************************************************/
+/* DBFCreate() */
+/* */
+/* Create a new .dbf file. */
+/************************************************************************/
+
+DBFHandle SHPAPI_CALL
+DBFCreate( const char * pszFilename )
+
+{
+ DBFHandle psDBF;
+ FILE *fp;
+ char *pszFullname, *pszBasename;
+ int i;
+
+/* -------------------------------------------------------------------- */
+/* Compute the base (layer) name. If there is any extension */
+/* on the passed in filename we will strip it off. */
+/* -------------------------------------------------------------------- */
+ pszBasename = (char *) malloc(strlen(pszFilename)+5);
+ strcpy( pszBasename, pszFilename );
+ for( i = strlen(pszBasename)-1;
+ i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+ && pszBasename[i] != '\\';
+ i-- ) {}
+
+ if( pszBasename[i] == '.' )
+ pszBasename[i] = '\0';
+
+ pszFullname = (char *) malloc(strlen(pszBasename) + 5);
+ sprintf( pszFullname, "%s.dbf", pszBasename );
+ free( pszBasename );
+
+/* -------------------------------------------------------------------- */
+/* Create the file. */
+/* -------------------------------------------------------------------- */
+ fp = fopen( pszFullname, "wb" );
+ if( fp == NULL )
+ return( NULL );
+
+ fputc( 0, fp );
+ fclose( fp );
+
+ fp = fopen( pszFullname, "rb+" );
+ if( fp == NULL )
+ return( NULL );
+
+ free( pszFullname );
+
+/* -------------------------------------------------------------------- */
+/* Create the info structure. */
+/* -------------------------------------------------------------------- */
+ psDBF = (DBFHandle) malloc(sizeof(DBFInfo));
+
+ psDBF->fp = fp;
+ psDBF->nRecords = 0;
+ psDBF->nFields = 0;
+ psDBF->nRecordLength = 1;
+ psDBF->nHeaderLength = 33;
+
+ psDBF->panFieldOffset = NULL;
+ psDBF->panFieldSize = NULL;
+ psDBF->panFieldDecimals = NULL;
+ psDBF->pachFieldType = NULL;
+ psDBF->pszHeader = NULL;
+
+ psDBF->nCurrentRecord = -1;
+ psDBF->bCurrentRecordModified = FALSE;
+ psDBF->pszCurrentRecord = NULL;
+
+ psDBF->bNoHeader = TRUE;
+
+ return( psDBF );
+}
+
+/************************************************************************/
+/* DBFAddField() */
+/* */
+/* Add a field to a newly created .dbf file before any records */
+/* are written. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFAddField(DBFHandle psDBF, const char * pszFieldName,
+ DBFFieldType eType, int nWidth, int nDecimals )
+
+{
+ char *pszFInfo;
+ int i;
+
+/* -------------------------------------------------------------------- */
+/* Do some checking to ensure we can add records to this file. */
+/* -------------------------------------------------------------------- */
+ if( psDBF->nRecords > 0 )
+ return( -1 );
+
+ if( !psDBF->bNoHeader )
+ return( -1 );
+
+ if( eType != FTDouble && nDecimals != 0 )
+ return( -1 );
+
+ if( nWidth < 1 )
+ return -1;
+
+/* -------------------------------------------------------------------- */
+/* SfRealloc all the arrays larger to hold the additional field */
+/* information. */
+/* -------------------------------------------------------------------- */
+ psDBF->nFields++;
+
+ psDBF->panFieldOffset = (int *)
+ SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
+
+ psDBF->panFieldSize = (int *)
+ SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
+
+ psDBF->panFieldDecimals = (int *)
+ SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
+
+ psDBF->pachFieldType = (char *)
+ SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
+
+/* -------------------------------------------------------------------- */
+/* Assign the new field information fields. */
+/* -------------------------------------------------------------------- */
+ psDBF->panFieldOffset[psDBF->nFields-1] = psDBF->nRecordLength;
+ psDBF->nRecordLength += nWidth;
+ psDBF->panFieldSize[psDBF->nFields-1] = nWidth;
+ psDBF->panFieldDecimals[psDBF->nFields-1] = nDecimals;
+
+ if( eType == FTLogical )
+ psDBF->pachFieldType[psDBF->nFields-1] = 'L';
+ else if( eType == FTString )
+ psDBF->pachFieldType[psDBF->nFields-1] = 'C';
+ else
+ psDBF->pachFieldType[psDBF->nFields-1] = 'N';
+
+/* -------------------------------------------------------------------- */
+/* Extend the required header information. */
+/* -------------------------------------------------------------------- */
+ psDBF->nHeaderLength += 32;
+ psDBF->bUpdated = FALSE;
+
+ psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,psDBF->nFields*32);
+
+ pszFInfo = psDBF->pszHeader + 32 * (psDBF->nFields-1);
+
+ for( i = 0; i < 32; i++ )
+ pszFInfo[i] = '\0';
+
+ if( (int) strlen(pszFieldName) < 10 )
+ strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
+ else
+ strncpy( pszFInfo, pszFieldName, 10);
+
+ pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields-1];
+
+ if( eType == FTString )
+ {
+ pszFInfo[16] = nWidth % 256;
+ pszFInfo[17] = nWidth / 256;
+ }
+ else
+ {
+ pszFInfo[16] = nWidth;
+ pszFInfo[17] = nDecimals;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Make the current record buffer appropriately larger. */
+/* -------------------------------------------------------------------- */
+ psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
+ psDBF->nRecordLength);
+
+ return( psDBF->nFields-1 );
+}
+
+/************************************************************************/
+/* DBFReadAttribute() */
+/* */
+/* Read one of the attribute fields of a record. */
+/************************************************************************/
+
+static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
+ char chReqType )
+
+{
+ int nRecordOffset;
+ unsigned char *pabyRec;
+ void *pReturnField = NULL;
+
+ static double dDoubleField;
+
+/* -------------------------------------------------------------------- */
+/* Verify selection. */
+/* -------------------------------------------------------------------- */
+ if( hEntity < 0 || hEntity >= psDBF->nRecords )
+ return( NULL );
+
+ if( iField < 0 || iField >= psDBF->nFields )
+ return( NULL );
+
+/* -------------------------------------------------------------------- */
+/* Have we read the record? */
+/* -------------------------------------------------------------------- */
+ if( psDBF->nCurrentRecord != hEntity )
+ {
+ DBFFlushRecord( psDBF );
+
+ nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+ if( fseek( psDBF->fp, nRecordOffset, 0 ) != 0 )
+ {
+ fprintf( stderr, "fseek(%d) failed on DBF file.\n",
+ nRecordOffset );
+ return NULL;
+ }
+
+ if( fread( psDBF->pszCurrentRecord, psDBF->nRecordLength,
+ 1, psDBF->fp ) != 1 )
+ {
+ fprintf( stderr, "fread(%d) failed on DBF file.\n",
+ psDBF->nRecordLength );
+ return NULL;
+ }
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+ pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+/* -------------------------------------------------------------------- */
+/* Ensure our field buffer is large enough to hold this buffer. */
+/* -------------------------------------------------------------------- */
+ if( psDBF->panFieldSize[iField]+1 > nStringFieldLen )
+ {
+ nStringFieldLen = psDBF->panFieldSize[iField]*2 + 10;
+ pszStringField = (char *) SfRealloc(pszStringField,nStringFieldLen);
+ }
+
+/* -------------------------------------------------------------------- */
+/* Extract the requested field. */
+/* -------------------------------------------------------------------- */
+ strncpy( pszStringField,
+ ((const char *) pabyRec) + psDBF->panFieldOffset[iField],
+ psDBF->panFieldSize[iField] );
+ pszStringField[psDBF->panFieldSize[iField]] = '\0';
+
+ pReturnField = pszStringField;
+
+/* -------------------------------------------------------------------- */
+/* Decode the field. */
+/* -------------------------------------------------------------------- */
+ if( chReqType == 'N' )
+ {
+ dDoubleField = atof(pszStringField);
+
+ pReturnField = &dDoubleField;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Should we trim white space off the string attribute value? */
+/* -------------------------------------------------------------------- */
+#ifdef TRIM_DBF_WHITESPACE
+ else
+ {
+ char *pchSrc, *pchDst;
+
+ pchDst = pchSrc = pszStringField;
+ while( *pchSrc == ' ' )
+ pchSrc++;
+
+ while( *pchSrc != '\0' )
+ *(pchDst++) = *(pchSrc++);
+ *pchDst = '\0';
+
+ while( pchDst != pszStringField && *(--pchDst) == ' ' )
+ *pchDst = '\0';
+ }
+#endif
+
+ return( pReturnField );
+}
+
+/************************************************************************/
+/* DBFReadIntAttribute() */
+/* */
+/* Read an integer attribute. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+ double *pdValue;
+
+ pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
+
+ if( pdValue == NULL )
+ return 0;
+ else
+ return( (int) *pdValue );
+}
+
+/************************************************************************/
+/* DBFReadDoubleAttribute() */
+/* */
+/* Read a double attribute. */
+/************************************************************************/
+
+double SHPAPI_CALL
+DBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+ double *pdValue;
+
+ pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
+
+ if( pdValue == NULL )
+ return 0.0;
+ else
+ return( *pdValue );
+}
+
+/************************************************************************/
+/* DBFReadStringAttribute() */
+/* */
+/* Read a string attribute. */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+DBFReadStringAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+ return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'C' ) );
+}
+
+/************************************************************************/
+/* DBFReadLogicalAttribute() */
+/* */
+/* Read a logical attribute. */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+DBFReadLogicalAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+ return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'L' ) );
+}
+
+/************************************************************************/
+/* DBFIsAttributeNULL() */
+/* */
+/* Return TRUE if value for field is NULL. */
+/* */
+/* Contributed by Jim Matthews. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
+
+{
+ const char *pszValue;
+
+ pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
+
+ switch(psDBF->pachFieldType[iField])
+ {
+ case 'N':
+ case 'F':
+ /* NULL numeric fields have value "****************" */
+ return pszValue[0] == '*';
+
+ case 'D':
+ /* NULL date fields have value "00000000" */
+ return strncmp(pszValue,"00000000",8) == 0;
+
+ case 'L':
+ /* NULL boolean fields have value "?" */
+ return pszValue[0] == '?';
+
+ default:
+ /* empty string fields are considered NULL */
+ return strlen(pszValue) == 0;
+ }
+}
+
+/************************************************************************/
+/* DBFGetFieldCount() */
+/* */
+/* Return the number of fields in this table. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFGetFieldCount( DBFHandle psDBF )
+
+{
+ return( psDBF->nFields );
+}
+
+/************************************************************************/
+/* DBFGetRecordCount() */
+/* */
+/* Return the number of records in this table. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFGetRecordCount( DBFHandle psDBF )
+
+{
+ return( psDBF->nRecords );
+}
+
+/************************************************************************/
+/* DBFGetFieldInfo() */
+/* */
+/* Return any requested information about the field. */
+/************************************************************************/
+
+DBFFieldType SHPAPI_CALL
+DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
+ int * pnWidth, int * pnDecimals )
+
+{
+ if( iField < 0 || iField >= psDBF->nFields )
+ return( FTInvalid );
+
+ if( pnWidth != NULL )
+ *pnWidth = psDBF->panFieldSize[iField];
+
+ if( pnDecimals != NULL )
+ *pnDecimals = psDBF->panFieldDecimals[iField];
+
+ if( pszFieldName != NULL )
+ {
+ int i;
+
+ strncpy( pszFieldName, (char *) psDBF->pszHeader+iField*32, 11 );
+ pszFieldName[11] = '\0';
+ for( i = 10; i > 0 && pszFieldName[i] == ' '; i-- )
+ pszFieldName[i] = '\0';
+ }
+
+ if ( psDBF->pachFieldType[iField] == 'L' )
+ return( FTLogical);
+
+ else if( psDBF->pachFieldType[iField] == 'N'
+ || psDBF->pachFieldType[iField] == 'F'
+ || psDBF->pachFieldType[iField] == 'D' )
+ {
+ if( psDBF->panFieldDecimals[iField] > 0 )
+ return( FTDouble );
+ else
+ return( FTInteger );
+ }
+ else
+ {
+ return( FTString );
+ }
+}
+
+/************************************************************************/
+/* DBFWriteAttribute() */
+/* */
+/* Write an attribute record to the file. */
+/************************************************************************/
+
+static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
+ void * pValue )
+
+{
+ int nRecordOffset, i, j, nRetResult = TRUE;
+ unsigned char *pabyRec;
+ char szSField[400], szFormat[20];
+
+/* -------------------------------------------------------------------- */
+/* Is this a valid record? */
+/* -------------------------------------------------------------------- */
+ if( hEntity < 0 || hEntity > psDBF->nRecords )
+ return( FALSE );
+
+ if( psDBF->bNoHeader )
+ DBFWriteHeader(psDBF);
+
+/* -------------------------------------------------------------------- */
+/* Is this a brand new record? */
+/* -------------------------------------------------------------------- */
+ if( hEntity == psDBF->nRecords )
+ {
+ DBFFlushRecord( psDBF );
+
+ psDBF->nRecords++;
+ for( i = 0; i < psDBF->nRecordLength; i++ )
+ psDBF->pszCurrentRecord[i] = ' ';
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Is this an existing record, but different than the last one */
+/* we accessed? */
+/* -------------------------------------------------------------------- */
+ if( psDBF->nCurrentRecord != hEntity )
+ {
+ DBFFlushRecord( psDBF );
+
+ nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+ fseek( psDBF->fp, nRecordOffset, 0 );
+ fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+ pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+ psDBF->bCurrentRecordModified = TRUE;
+ psDBF->bUpdated = TRUE;
+
+/* -------------------------------------------------------------------- */
+/* Translate NULL value to valid DBF file representation. */
+/* */
+/* Contributed by Jim Matthews. */
+/* -------------------------------------------------------------------- */
+ if( pValue == NULL )
+ {
+ switch(psDBF->pachFieldType[iField])
+ {
+ case 'N':
+ case 'F':
+ /* NULL numeric fields have value "****************" */
+ memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '*',
+ psDBF->panFieldSize[iField] );
+ break;
+
+ case 'D':
+ /* NULL date fields have value "00000000" */
+ memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '0',
+ psDBF->panFieldSize[iField] );
+ break;
+
+ case 'L':
+ /* NULL boolean fields have value "?" */
+ memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '?',
+ psDBF->panFieldSize[iField] );
+ break;
+
+ default:
+ /* empty string fields are considered NULL */
+ memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '\0',
+ psDBF->panFieldSize[iField] );
+ break;
+ }
+ return TRUE;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Assign all the record fields. */
+/* -------------------------------------------------------------------- */
+ switch( psDBF->pachFieldType[iField] )
+ {
+ case 'D':
+ case 'N':
+ case 'F':
+ if( psDBF->panFieldDecimals[iField] == 0 )
+ {
+ int nWidth = psDBF->panFieldSize[iField];
+
+ if( (int)sizeof(szSField)-2 < nWidth )
+ nWidth = sizeof(szSField)-2;
+
+ sprintf( szFormat, "%%%dd", nWidth );
+ sprintf(szSField, szFormat, (int) *((double *) pValue) );
+ if( (int)strlen(szSField) > psDBF->panFieldSize[iField] )
+ {
+ szSField[psDBF->panFieldSize[iField]] = '\0';
+ nRetResult = FALSE;
+ }
+
+ strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
+ szSField, strlen(szSField) );
+ }
+ else
+ {
+ int nWidth = psDBF->panFieldSize[iField];
+
+ if( (int)sizeof(szSField)-2 < nWidth )
+ nWidth = sizeof(szSField)-2;
+
+ sprintf( szFormat, "%%%d.%df",
+ nWidth, psDBF->panFieldDecimals[iField] );
+ sprintf(szSField, szFormat, *((double *) pValue) );
+ if( (int) strlen(szSField) > psDBF->panFieldSize[iField] )
+ {
+ szSField[psDBF->panFieldSize[iField]] = '\0';
+ nRetResult = FALSE;
+ }
+ strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
+ szSField, strlen(szSField) );
+ }
+ break;
+
+ case 'L':
+ if (psDBF->panFieldSize[iField] >= 1 &&
+ (*(char*)pValue == 'F' || *(char*)pValue == 'T'))
+ *(pabyRec+psDBF->panFieldOffset[iField]) = *(char*)pValue;
+ break;
+
+ default:
+ if( (int) strlen((char *) pValue) > psDBF->panFieldSize[iField] )
+ {
+ j = psDBF->panFieldSize[iField];
+ nRetResult = FALSE;
+ }
+ else
+ {
+ memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
+ psDBF->panFieldSize[iField] );
+ j = strlen((char *) pValue);
+ }
+
+ strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
+ (char *) pValue, j );
+ break;
+ }
+
+ return( nRetResult );
+}
+
+/************************************************************************/
+/* DBFWriteAttributeDirectly() */
+/* */
+/* Write an attribute record to the file, but without any */
+/* reformatting based on type. The provided buffer is written */
+/* as is to the field position in the record. */
+/************************************************************************/
+
+int DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
+ void * pValue )
+
+{
+ int nRecordOffset, i, j;
+ unsigned char *pabyRec;
+
+/* -------------------------------------------------------------------- */
+/* Is this a valid record? */
+/* -------------------------------------------------------------------- */
+ if( hEntity < 0 || hEntity > psDBF->nRecords )
+ return( FALSE );
+
+ if( psDBF->bNoHeader )
+ DBFWriteHeader(psDBF);
+
+/* -------------------------------------------------------------------- */
+/* Is this a brand new record? */
+/* -------------------------------------------------------------------- */
+ if( hEntity == psDBF->nRecords )
+ {
+ DBFFlushRecord( psDBF );
+
+ psDBF->nRecords++;
+ for( i = 0; i < psDBF->nRecordLength; i++ )
+ psDBF->pszCurrentRecord[i] = ' ';
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Is this an existing record, but different than the last one */
+/* we accessed? */
+/* -------------------------------------------------------------------- */
+ if( psDBF->nCurrentRecord != hEntity )
+ {
+ DBFFlushRecord( psDBF );
+
+ nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+ fseek( psDBF->fp, nRecordOffset, 0 );
+ fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+ pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+/* -------------------------------------------------------------------- */
+/* Assign all the record fields. */
+/* -------------------------------------------------------------------- */
+ if( (int)strlen((char *) pValue) > psDBF->panFieldSize[iField] )
+ j = psDBF->panFieldSize[iField];
+ else
+ {
+ memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
+ psDBF->panFieldSize[iField] );
+ j = strlen((char *) pValue);
+ }
+
+ strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
+ (char *) pValue, j );
+
+ psDBF->bCurrentRecordModified = TRUE;
+ psDBF->bUpdated = TRUE;
+
+ return( TRUE );
+}
+
+/************************************************************************/
+/* DBFWriteDoubleAttribute() */
+/* */
+/* Write a double attribute. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField,
+ double dValue )
+
+{
+ return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
+}
+
+/************************************************************************/
+/* DBFWriteIntegerAttribute() */
+/* */
+/* Write a integer attribute. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField,
+ int nValue )
+
+{
+ double dValue = nValue;
+
+ return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
+}
+
+/************************************************************************/
+/* DBFWriteStringAttribute() */
+/* */
+/* Write a string attribute. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteStringAttribute( DBFHandle psDBF, int iRecord, int iField,
+ const char * pszValue )
+
+{
+ return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) pszValue ) );
+}
+
+/************************************************************************/
+/* DBFWriteNULLAttribute() */
+/* */
+/* Write a string attribute. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteNULLAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+ return( DBFWriteAttribute( psDBF, iRecord, iField, NULL ) );
+}
+
+/************************************************************************/
+/* DBFWriteLogicalAttribute() */
+/* */
+/* Write a logical attribute. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteLogicalAttribute( DBFHandle psDBF, int iRecord, int iField,
+ const char lValue)
+
+{
+ return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) (&lValue) ) );
+}
+
+/************************************************************************/
+/* DBFWriteTuple() */
+/* */
+/* Write an attribute record to the file. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
+
+{
+ int nRecordOffset, i;
+ unsigned char *pabyRec;
+
+/* -------------------------------------------------------------------- */
+/* Is this a valid record? */
+/* -------------------------------------------------------------------- */
+ if( hEntity < 0 || hEntity > psDBF->nRecords )
+ return( FALSE );
+
+ if( psDBF->bNoHeader )
+ DBFWriteHeader(psDBF);
+
+/* -------------------------------------------------------------------- */
+/* Is this a brand new record? */
+/* -------------------------------------------------------------------- */
+ if( hEntity == psDBF->nRecords )
+ {
+ DBFFlushRecord( psDBF );
+
+ psDBF->nRecords++;
+ for( i = 0; i < psDBF->nRecordLength; i++ )
+ psDBF->pszCurrentRecord[i] = ' ';
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Is this an existing record, but different than the last one */
+/* we accessed? */
+/* -------------------------------------------------------------------- */
+ if( psDBF->nCurrentRecord != hEntity )
+ {
+ DBFFlushRecord( psDBF );
+
+ nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+ fseek( psDBF->fp, nRecordOffset, 0 );
+ fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+ pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+ memcpy ( pabyRec, pRawTuple, psDBF->nRecordLength );
+
+ psDBF->bCurrentRecordModified = TRUE;
+ psDBF->bUpdated = TRUE;
+
+ return( TRUE );
+}
+
+/************************************************************************/
+/* DBFReadTuple() */
+/* */
+/* Read one of the attribute fields of a record. */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+DBFReadTuple(DBFHandle psDBF, int hEntity )
+
+{
+ int nRecordOffset;
+ unsigned char *pabyRec;
+ static char *pReturnTuple = NULL;
+
+ static int nTupleLen = 0;
+
+/* -------------------------------------------------------------------- */
+/* Have we read the record? */
+/* -------------------------------------------------------------------- */
+ if( hEntity < 0 || hEntity >= psDBF->nRecords )
+ return( NULL );
+
+ if( psDBF->nCurrentRecord != hEntity )
+ {
+ DBFFlushRecord( psDBF );
+
+ nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+ fseek( psDBF->fp, nRecordOffset, 0 );
+ fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+ pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+ if ( nTupleLen < psDBF->nRecordLength) {
+ nTupleLen = psDBF->nRecordLength;
+ pReturnTuple = (char *) SfRealloc(pReturnTuple, psDBF->nRecordLength);
+ }
+
+ memcpy ( pReturnTuple, pabyRec, psDBF->nRecordLength );
+
+ return( pReturnTuple );
+}
+
+/************************************************************************/
+/* DBFCloneEmpty() */
+/* */
+/* Read one of the attribute fields of a record. */
+/************************************************************************/
+
+DBFHandle SHPAPI_CALL
+DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
+{
+ DBFHandle newDBF;
+
+ newDBF = DBFCreate ( pszFilename );
+ if ( newDBF == NULL ) return ( NULL );
+
+ newDBF->pszHeader = (char *) malloc ( 32 * psDBF->nFields );
+ memcpy ( newDBF->pszHeader, psDBF->pszHeader, 32 * psDBF->nFields );
+
+ newDBF->nFields = psDBF->nFields;
+ newDBF->nRecordLength = psDBF->nRecordLength;
+ newDBF->nHeaderLength = 32 * (psDBF->nFields+1);
+
+ newDBF->panFieldOffset = (int *) malloc ( sizeof(int) * psDBF->nFields );
+ memcpy ( newDBF->panFieldOffset, psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
+ newDBF->panFieldSize = (int *) malloc ( sizeof(int) * psDBF->nFields );
+ memcpy ( newDBF->panFieldSize, psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
+ newDBF->panFieldDecimals = (int *) malloc ( sizeof(int) * psDBF->nFields );
+ memcpy ( newDBF->panFieldDecimals, psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
+ newDBF->pachFieldType = (char *) malloc ( sizeof(int) * psDBF->nFields );
+ memcpy ( newDBF->pachFieldType, psDBF->pachFieldType, sizeof(int) * psDBF->nFields );
+
+ newDBF->bNoHeader = TRUE;
+ newDBF->bUpdated = TRUE;
+
+ DBFWriteHeader ( newDBF );
+ DBFClose ( newDBF );
+
+ newDBF = DBFOpen ( pszFilename, "rb+" );
+
+ return ( newDBF );
+}
+
+/************************************************************************/
+/* DBFGetNativeFieldType() */
+/* */
+/* Return the DBase field type for the specified field. */
+/* */
+/* Value can be one of: 'C' (String), 'D' (Date), 'F' (Float), */
+/* 'N' (Numeric, with or without decimal), */
+/* 'L' (Logical), */
+/* 'M' (Memo: 10 digits .DBT block ptr) */
+/************************************************************************/
+
+char SHPAPI_CALL
+DBFGetNativeFieldType( DBFHandle psDBF, int iField )
+
+{
+ if( iField >=0 && iField < psDBF->nFields )
+ return psDBF->pachFieldType[iField];
+
+ return ' ';
+}
+
+/************************************************************************/
+/* str_to_upper() */
+/************************************************************************/
+
+static void str_to_upper (char *string)
+{
+ int len;
+ short i = -1;
+
+ len = strlen (string);
+
+ while (++i < len)
+ if (isalpha(string[i]) && islower(string[i]))
+ string[i] = toupper ((int)string[i]);
+}
+
+/************************************************************************/
+/* DBFGetFieldIndex() */
+/* */
+/* Get the index number for a field in a .dbf file. */
+/* */
+/* Contributed by Jim Matthews. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
+
+{
+ char name[12], name1[12], name2[12];
+ int i;
+
+ strncpy(name1, pszFieldName,11);
+ name1[11] = '\0';
+ str_to_upper(name1);
+
+ for( i = 0; i < DBFGetFieldCount(psDBF); i++ )
+ {
+ DBFGetFieldInfo( psDBF, i, name, NULL, NULL );
+ strncpy(name2,name,11);
+ str_to_upper(name2);
+
+ if(!strncmp(name1,name2,10))
+ return(i);
+ }
+ return(-1);
+}
diff --git a/src/shapelib/libtool b/src/shapelib/libtool
new file mode 100755
index 0000000..7706a8c
--- /dev/null
+++ b/src/shapelib/libtool
@@ -0,0 +1,4149 @@
+#! /bin/sh
+
+# libtool - Provide generalized library-building support services.
+# Generated automatically by ltconfig (GNU libtool 1.3 (1.385.2.117 1999/04/29 13:07:13))
+# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh.
+#
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Gordon Matzigkeit <gord at gnu.ai.mit.edu>, 1996
+#
+# 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.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="sed -e s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi
+
+### BEGIN LIBTOOL CONFIG
+# Libtool was configured as follows, on host cs46980-c:
+#
+# CC="gcc" CFLAGS="-g -O2" CPPFLAGS="" \
+# LD="/usr/bin/ld" LDFLAGS="" LIBS="" \
+# NM="/usr/bin/nm -B" RANLIB="ranlib" LN_S="ln -s" \
+# DLLTOOL="" OBJDUMP="" AS="" \
+# ./ltconfig --cache-file=./config.cache --with-gcc --with-gnu-ld --no-verify ./ltmain.sh i586-pc-linux-gnu
+#
+# Compiler and other test output produced by ltconfig, useful for
+# debugging ltconfig, is in ./config.log if it exists.
+
+# The version of ltconfig that generated this script.
+LTCONFIG_VERSION="1.3"
+
+# Shell to use when invoking shell scripts.
+SHELL="/bin/sh"
+
+# Whether or not to build shared libraries.
+build_libtool_libs=yes
+
+# Whether or not to build static libraries.
+build_old_libs=yes
+
+# Whether or not to optimize for fast installation.
+fast_install=yes
+
+# The host system.
+host_alias=i586-pc-linux-gnu
+host=i586-pc-linux-gnu
+
+# An echo program that does not interpret backslashes.
+echo="echo"
+
+# The archiver.
+AR="ar"
+
+# The default C compiler.
+CC="gcc"
+
+# The linker used to build libraries.
+LD="/usr/bin/ld"
+
+# Whether we need hard or soft links.
+LN_S="ln -s"
+
+# A BSD-compatible nm program.
+NM="/usr/bin/nm -B"
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="dlltool"
+
+# Used on cygwin: object dumper.
+OBJDUMP="objdump"
+
+# Used on cygwin: assembler.
+AS="as"
+
+# The name of the directory that contains temporary libtool files.
+objdir=.libs
+
+# How to create reloadable object files.
+reload_flag=" -r"
+reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs"
+
+# How to pass a linker flag through the compiler.
+wl="-Wl,"
+
+# Object file suffix (normally "o").
+objext="o"
+
+# Old archive suffix (normally "a").
+libext="a"
+
+# Additional compiler flags for building library objects.
+pic_flag=" -fPIC"
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o="yes"
+
+# Can we write directly to a .lo ?
+compiler_o_lo="yes"
+
+# Must we lock files when doing compilation ?
+need_locks="no"
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=no
+
+# Do we need a version for libraries?
+need_version=no
+
+# Whether dlopen is supported.
+dlopen=unknown
+
+# Whether dlopen of programs is supported.
+dlopen_self=unknown
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=unknown
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag="-static"
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=" -fno-builtin -fno-rtti -fno-exceptions"
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec="\${wl}--export-dynamic"
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec="\${wl}--whole-archive\$convenience \${wl}--no-whole-archive"
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=""
+
+# Library versioning type.
+version_type=linux
+
+# Format of library name prefix.
+libname_spec="lib\$name"
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec="\${libname}\${release}.so\$versuffix \${libname}\${release}.so\$major \$libname.so"
+
+# The coded name of the library, if different from the real name.
+soname_spec="\${libname}\${release}.so\$major"
+
+# Commands used to build and install an old-style archive.
+RANLIB="ranlib"
+old_archive_cmds="\$AR cru \$oldlib\$oldobjs~\$RANLIB \$oldlib"
+old_postinstall_cmds="\$RANLIB \$oldlib~chmod 644 \$oldlib"
+old_postuninstall_cmds=""
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=""
+
+# Commands used to build and install a shared archive.
+archive_cmds="\$CC -shared \$libobjs \$deplibs \$linkopts \${wl}-soname \$wl\$soname -o \$lib"
+archive_expsym_cmds="\$CC -shared \$libobjs \$deplibs \$linkopts \${wl}-soname \$wl\$soname \${wl}-retain-symbols-file \$wl\$export_symbols -o \$lib"
+postinstall_cmds=""
+postuninstall_cmds=""
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )"
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd="/usr/bin/file"
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=""
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=""
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds="PATH=\\\"\\\$PATH:/sbin\\\" ldconfig -n \$libdir"
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=""
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe="sed -n -e 's/^.*[ ]\\([ABCDGISTW]\\)[ ][ ]*\\(\\)\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2\\3 \\3/p'"
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl="sed -n -e 's/^. .* \\(.*\\)\$/extern char \\1;/p'"
+
+# This is the shared library runtime path variable.
+runpath_var=LD_RUN_PATH
+
+# This is the shared library path variable.
+shlibpath_var=LD_LIBRARY_PATH
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=no
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=immediate
+
+# Flag to hardcode $libdir into a binary during linking.
+# This must work even if $libdir does not exist.
+hardcode_libdir_flag_spec="\${wl}--rpath \${wl}\$libdir"
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=""
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=no
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=no
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=unsupported
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+
+# Fix the shell variable $srcfile for the compiler.
+fix_srcfile_path=""
+
+# Set to yes if exported symbols are required.
+always_export_symbols=no
+
+# The commands to list exported symbols.
+export_symbols_cmds="\$NM \$libobjs | \$global_symbol_pipe | sed 's/.* //' | sort | uniq > \$export_symbols"
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+
+# Symbols that must always be exported.
+include_expsyms=""
+
+### END LIBTOOL CONFIG
+
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun ltconfig.
+#
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord at gnu.ai.mit.edu>, 1996
+#
+# 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.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell, and then maybe $echo will work.
+ exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# The name of this program.
+progname=`$echo "$0" | sed 's%^.*/%%'`
+modename="$progname"
+
+# Constants.
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.3
+TIMESTAMP=" (1.385.2.117 1999/04/29 13:07:13)"
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+SP2NL='tr \040 \012'
+NL2SP='tr \012 \040'
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+if test "${LC_ALL+set}" = set; then
+ save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
+fi
+if test "${LANG+set}" = set; then
+ save_LANG="$LANG"; LANG=C; export LANG
+fi
+
+if test "$LTCONFIG_VERSION" != "$VERSION"; then
+ echo "$modename: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+fi
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ echo "$modename: not configured to build any kind of library" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+
+# Parse our command line options once, thoroughly.
+while test $# -gt 0
+do
+ arg="$1"
+ shift
+
+ case "$arg" in
+ -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case "$prev" in
+ execute_dlfiles)
+ eval "$prev=\"\$$prev \$arg\""
+ ;;
+ *)
+ eval "$prev=\$arg"
+ ;;
+ esac
+
+ prev=
+ prevopt=
+ continue
+ fi
+
+ # Have we seen a non-optional argument yet?
+ case "$arg" in
+ --help)
+ show_help=yes
+ ;;
+
+ --version)
+ echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+ exit 0
+ ;;
+
+ --config)
+ sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0
+ exit 0
+ ;;
+
+ --debug)
+ echo "$progname: enabling shell trace mode"
+ set -x
+ ;;
+
+ --dry-run | -n)
+ run=:
+ ;;
+
+ --features)
+ echo "host: $host"
+ if test "$build_libtool_libs" = yes; then
+ echo "enable shared libraries"
+ else
+ echo "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; then
+ echo "enable static libraries"
+ else
+ echo "disable static libraries"
+ fi
+ exit 0
+ ;;
+
+ --finish) mode="finish" ;;
+
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
+ --quiet | --silent)
+ show=:
+ ;;
+
+ -dlopen)
+ prevopt="-dlopen"
+ prev=execute_dlfiles
+ ;;
+
+ -*)
+ $echo "$modename: unrecognized option \`$arg'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *)
+ nonopt="$arg"
+ break
+ ;;
+ esac
+done
+
+if test -n "$prevopt"; then
+ $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+fi
+
+if test -z "$show_help"; then
+
+ # Infer the operation mode.
+ if test -z "$mode"; then
+ case "$nonopt" in
+ *cc | *++ | gcc* | *-gcc*)
+ mode=link
+ for arg
+ do
+ case "$arg" in
+ -c)
+ mode=compile
+ break
+ ;;
+ esac
+ done
+ ;;
+ *db | *dbx | *strace | *truss)
+ mode=execute
+ ;;
+ *install*|cp|mv)
+ mode=install
+ ;;
+ *rm)
+ mode=uninstall
+ ;;
+ *)
+ # If we have no mode, but dlfiles were specified, then do execute mode.
+ test -n "$execute_dlfiles" && mode=execute
+
+ # Just use the default operation mode.
+ if test -z "$mode"; then
+ if test -n "$nonopt"; then
+ $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+ else
+ $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ fi
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; then
+ $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help="$help"
+ help="Try \`$modename --help --mode=$mode' for more information."
+
+ # These modes are in order of execution frequency so that they run quickly.
+ case "$mode" in
+ # libtool compile mode
+ compile)
+ modename="$modename: compile"
+ # Get the compilation command and the source file.
+ base_compile=
+ lastarg=
+ srcfile="$nonopt"
+ suppress_output=
+
+ user_target=no
+ for arg
+ do
+ # Accept any command-line options.
+ case "$arg" in
+ -o)
+ if test "$user_target" != "no"; then
+ $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+ exit 1
+ fi
+ user_target=next
+ ;;
+
+ -static)
+ build_old_libs=yes
+ continue
+ ;;
+ esac
+
+ case "$user_target" in
+ next)
+ # The next one is the -o target name
+ user_target=yes
+ continue
+ ;;
+ yes)
+ # We got the output file
+ user_target=set
+ libobj="$arg"
+ continue
+ ;;
+ esac
+
+ # Accept the current argument as the source file.
+ lastarg="$srcfile"
+ srcfile="$arg"
+
+ # Aesthetically quote the previous argument.
+
+ # Backslashify any backslashes, double quotes, and dollar signs.
+ # These are the only characters that are still specially
+ # interpreted inside of double-quoted scrings.
+ lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly in scan
+ # sets, so we specify it separately.
+ case "$lastarg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ lastarg="\"$lastarg\""
+ ;;
+ esac
+
+ # Add the previous argument to base_compile.
+ if test -z "$base_compile"; then
+ base_compile="$lastarg"
+ else
+ base_compile="$base_compile $lastarg"
+ fi
+ done
+
+ case "$user_target" in
+ set)
+ ;;
+ no)
+ # Get the name of the library object.
+ libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+ ;;
+ *)
+ $echo "$modename: you must specify a target with \`-o'" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ xform='[cCFSfmso]'
+ case "$libobj" in
+ *.ada) xform=ada ;;
+ *.adb) xform=adb ;;
+ *.ads) xform=ads ;;
+ *.asm) xform=asm ;;
+ *.c++) xform=c++ ;;
+ *.cc) xform=cc ;;
+ *.cpp) xform=cpp ;;
+ *.cxx) xform=cxx ;;
+ *.f90) xform=f90 ;;
+ *.for) xform=for ;;
+ esac
+
+ libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+ case "$libobj" in
+ *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+ *)
+ $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test -z "$base_compile"; then
+ $echo "$modename: you must specify a compilation command" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Delete any leftover library objects.
+ if test "$build_old_libs" = yes; then
+ removelist="$obj $libobj"
+ else
+ removelist="$libobj"
+ fi
+
+ $run $rm $removelist
+ trap "$run $rm $removelist; exit 1" 1 2 15
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test "$compiler_c_o" = no; then
+ output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext}
+ lockfile="$output_obj.lock"
+ removelist="$removelist $output_obj $lockfile"
+ trap "$run $rm $removelist; exit 1" 1 2 15
+ else
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test "$need_locks" = yes; then
+ until ln "$0" "$lockfile" 2>/dev/null; do
+ $show "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test "$need_locks" = warn; then
+ if test -f "$lockfile"; then
+ echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+ echo $srcfile > "$lockfile"
+ fi
+
+ if test -n "$fix_srcfile_path"; then
+ eval srcfile=\"$fix_srcfile_path\"
+ fi
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ # All platforms use -DPIC, to notify preprocessed assembler code.
+ command="$base_compile $pic_flag -DPIC $srcfile"
+ if test "$build_old_libs" = yes; then
+ lo_libobj="$libobj"
+ dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$libobj"; then
+ dir="$objdir"
+ else
+ dir="$dir/$objdir"
+ fi
+ libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
+
+ if test -d "$dir"; then
+ $show "$rm $libobj"
+ $run $rm $libobj
+ else
+ $show "$mkdir $dir"
+ $run $mkdir $dir
+ status=$?
+ if test $status -ne 0 && test ! -d $dir; then
+ exit $status
+ fi
+ fi
+ fi
+ if test "$compiler_o_lo" = yes; then
+ output_obj="$libobj"
+ command="$command -o $output_obj"
+ elif test "$compiler_c_o" = yes; then
+ output_obj="$obj"
+ command="$command -o $output_obj"
+ fi
+
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ test -n "$output_obj" && $run $rm $removelist
+ exit 1
+ fi
+
+ if test "$need_locks" = warn &&
+ test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
+ echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test x"$output_obj" != x"$libobj"; then
+ $show "$mv $output_obj $libobj"
+ if $run $mv $output_obj $libobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # If we have no pic_flag, then copy the object into place and finish.
+ if test -z "$pic_flag" && test "$build_old_libs" = yes; then
+ # Rename the .lo from within objdir to obj
+ if test -f $obj; then
+ $show $rm $obj
+ $run $rm $obj
+ fi
+
+ $show "$mv $libobj $obj"
+ if $run $mv $libobj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+
+ # Now arrange that obj and lo_libobj become the same file
+ $show "$LN_S $obj $lo_libobj"
+ if $run $LN_S $obj $lo_libobj; then
+ exit 0
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Allow error messages only from the first compilation.
+ suppress_output=' >/dev/null 2>&1'
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ command="$base_compile $srcfile"
+ if test "$compiler_c_o" = yes; then
+ command="$command -o $obj"
+ output_obj="$obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ command="$command$suppress_output"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ $run $rm $removelist
+ exit 1
+ fi
+
+ if test "$need_locks" = warn &&
+ test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
+ echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+
+ # Just move the object if needed
+ if test x"$output_obj" != x"$obj"; then
+ $show "$mv $output_obj $obj"
+ if $run $mv $output_obj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we do not
+ # accidentally link it into a program.
+ if test "$build_libtool_libs" != yes; then
+ $show "echo timestamp > $libobj"
+ $run eval "echo timestamp > \$libobj" || exit $?
+ else
+ # Move the .lo from within objdir
+ $show "$mv $libobj $lo_libobj"
+ if $run $mv $libobj $lo_libobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+ fi
+
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ $rm "$lockfile"
+ fi
+
+ exit 0
+ ;;
+
+ # libtool link mode
+ link)
+ modename="$modename: link"
+ C_compiler="$CC" # save it, to compile generated C sources
+ CC="$nonopt"
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # which system we are compiling for in order to pass an extra
+ # flag for every libtool invokation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll which has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+
+ # This is a source program that is used to create dlls on Windows
+ # Don't remove nor modify the starting and closing comments
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+# __hDllInstance_base = hInst;
+# return TRUE;
+# }
+# /* ltdll.c ends here */
+ # This is a source program that is used to create import libraries
+ # on Windows for dlls which lack them. Don't remove nor modify the
+ # starting and closing comments
+# /* impgen.c starts here */
+# /* Copyright (C) 1999 Free Software Foundation, Inc.
+#
+# This file is part of GNU libtool.
+#
+# 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> /* for printf() */
+# #include <unistd.h> /* for open(), lseek(), read() */
+# #include <fcntl.h> /* for O_RDONLY, O_BINARY */
+# #include <string.h> /* for strdup() */
+#
+# static unsigned int
+# pe_get16 (fd, offset)
+# int fd;
+# int offset;
+# {
+# unsigned char b[2];
+# lseek (fd, offset, SEEK_SET);
+# read (fd, b, 2);
+# return b[0] + (b[1]<<8);
+# }
+#
+# static unsigned int
+# pe_get32 (fd, offset)
+# int fd;
+# int offset;
+# {
+# unsigned char b[4];
+# lseek (fd, offset, SEEK_SET);
+# read (fd, b, 4);
+# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# static unsigned int
+# pe_as32 (ptr)
+# void *ptr;
+# {
+# unsigned char *b = ptr;
+# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# int
+# main (argc, argv)
+# int argc;
+# char *argv[];
+# {
+# int dll;
+# unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
+# unsigned long export_rva, export_size, nsections, secptr, expptr;
+# unsigned long name_rvas, nexp;
+# unsigned char *expdata, *erva;
+# char *filename, *dll_name;
+#
+# filename = argv[1];
+#
+# dll = open(filename, O_RDONLY|O_BINARY);
+# if (!dll)
+# return 1;
+#
+# dll_name = filename;
+#
+# for (i=0; filename[i]; i++)
+# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':')
+# dll_name = filename + i +1;
+#
+# pe_header_offset = pe_get32 (dll, 0x3c);
+# opthdr_ofs = pe_header_offset + 4 + 20;
+# num_entries = pe_get32 (dll, opthdr_ofs + 92);
+#
+# if (num_entries < 1) /* no exports */
+# return 1;
+#
+# export_rva = pe_get32 (dll, opthdr_ofs + 96);
+# export_size = pe_get32 (dll, opthdr_ofs + 100);
+# nsections = pe_get16 (dll, pe_header_offset + 4 +2);
+# secptr = (pe_header_offset + 4 + 20 +
+# pe_get16 (dll, pe_header_offset + 4 + 16));
+#
+# expptr = 0;
+# for (i = 0; i < nsections; i++)
+# {
+# char sname[8];
+# unsigned long secptr1 = secptr + 40 * i;
+# unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
+# unsigned long vsize = pe_get32 (dll, secptr1 + 16);
+# unsigned long fptr = pe_get32 (dll, secptr1 + 20);
+# lseek(dll, secptr1, SEEK_SET);
+# read(dll, sname, 8);
+# if (vaddr <= export_rva && vaddr+vsize > export_rva)
+# {
+# expptr = fptr + (export_rva - vaddr);
+# if (export_rva + export_size > vaddr + vsize)
+# export_size = vsize - (export_rva - vaddr);
+# break;
+# }
+# }
+#
+# expdata = (unsigned char*)malloc(export_size);
+# lseek (dll, expptr, SEEK_SET);
+# read (dll, expdata, export_size);
+# erva = expdata - export_rva;
+#
+# nexp = pe_as32 (expdata+24);
+# name_rvas = pe_as32 (expdata+32);
+#
+# printf ("EXPORTS\n");
+# for (i = 0; i<nexp; i++)
+# {
+# unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
+# printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
+# }
+#
+# return 0;
+# }
+# /* impgen.c ends here */
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ compile_command="$CC"
+ finalize_command="$CC"
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ linkopts=
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval lib_search_path=\`\$echo \"X \${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+ else
+ lib_search_path=
+ fi
+ # now prepend the system-specific ones
+ eval lib_search_path=\"$sys_lib_search_path_spec\$lib_search_path\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ avoid_version=no
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ link_against_libtool_libs=
+ ltlibs=
+ module=no
+ objs=
+ prefer_static_libs=no
+ preload=no
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case "$arg" in
+ -all-static | -static)
+ if test "X$arg" = "X-all-static"; then
+ if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ else
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ fi
+ build_libtool_libs=no
+ build_old_libs=yes
+ prefer_static_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test $# -gt 0; do
+ arg="$1"
+ shift
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case "$prev" in
+ output)
+ compile_command="$compile_command @OUTPUT@"
+ finalize_command="$finalize_command @OUTPUT@"
+ ;;
+ esac
+
+ case "$prev" in
+ dlfiles|dlprefiles)
+ if test "$preload" = no; then
+ # Add the symbol object into the linking commands.
+ compile_command="$compile_command @SYMFILE@"
+ finalize_command="$finalize_command @SYMFILE@"
+ preload=yes
+ fi
+ case "$arg" in
+ *.la | *.lo) ;; # We handle these cases below.
+ self)
+ if test "$prev" = dlprefiles; then
+ dlself=yes
+ elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ else
+ dlprefiles="$dlprefiles $arg"
+ fi
+ prev=
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols="$arg"
+ if test ! -f "$arg"; then
+ $echo "$modename: symbol file \`$arg' does not exist"
+ exit 1
+ fi
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex="$arg"
+ prev=
+ continue
+ ;;
+ release)
+ release="-$arg"
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case "$arg" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit 1
+ ;;
+ esac
+ if test "$prev" = rpath; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) rpath="$rpath $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) xrpath="$xrpath $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi
+
+ prevarg="$arg"
+
+ case "$arg" in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+ continue
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: not more than one -exported-symbols argument allowed"
+ exit 1
+ fi
+ if test "X$arg" = "X-export-symbols"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -L*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+ # We need an absolute path.
+ case "$dir" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+ exit 1
+ fi
+ dir="$absdir"
+ ;;
+ esac
+ case " $deplibs " in
+ *" $arg "*) ;;
+ *) deplibs="$deplibs $arg";;
+ esac
+ case " $lib_search_path " in
+ *" $dir "*) ;;
+ *) lib_search_path="$lib_search_path $dir";;
+ esac
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2*)
+ dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
+ case ":$dllsearchpath:" in
+ ::) dllsearchpath="$dllsearchdir";;
+ *":$dllsearchdir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$dllsearchdir";;
+ esac
+ ;;
+ esac
+ ;;
+
+ -l*)
+ if test "$arg" = "-lc"; then
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
+ # These systems don't actually have c library (as such)
+ continue
+ ;;
+ esac
+ elif test "$arg" = "-lm"; then
+ case "$host" in
+ *-*-cygwin* | *-*-beos*)
+ # These systems don't actually have math library (as such)
+ continue
+ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+ # We need an absolute path.
+ case "$dir" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit 1
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ continue
+ ;;
+
+ -static)
+ # If we have no pic_flag, then this is the same as -all-static.
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+
+ *.o | *.obj | *.a | *.lib)
+ # A standard object.
+ objs="$objs $arg"
+ ;;
+
+ *.lo)
+ # A library object.
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"`
+ prev=
+ fi
+ libobjs="$libobjs $arg"
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ dlname=
+ libdir=
+ library_names=
+ old_library=
+
+ # Check to see that this really is a libtool archive.
+ if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variable installed.
+ installed=yes
+
+ # Read the .la file
+ # If there is no directory component, then add one.
+ case "$arg" in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ # Get the name of the library we link against.
+ linklib=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+
+ if test -z "$linklib"; then
+ $echo "$modename: cannot find name of link library for \`$arg'" 1>&2
+ exit 1
+ fi
+
+ # Find the relevant object directory and library name.
+ name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'`
+
+ if test "X$installed" = Xyes; then
+ dir="$libdir"
+ else
+ dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$arg"; then
+ dir="$objdir"
+ else
+ dir="$dir/$objdir"
+ fi
+ fi
+
+ if test -n "$dependency_libs"; then
+ # Extract -R from dependency_libs
+ temp_deplibs=
+ for deplib in $dependency_libs; do
+ case "$deplib" in
+ -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+ case " $rpath $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) xrpath="$xrpath $temp_xrpath";;
+ esac;;
+ -L*) case "$compile_command $temp_deplibs " in
+ *" $deplib "*) ;;
+ *) temp_deplibs="$temp_deplibs $deplib";;
+ esac;;
+ *) temp_deplibs="$temp_deplibs $deplib";;
+ esac
+ done
+ dependency_libs="$temp_deplibs"
+ fi
+
+ if test -z "$libdir"; then
+ # It is a libtool convenience library, so add in its objects.
+ convenience="$convenience $dir/$old_library"
+ old_convenience="$old_convenience $dir/$old_library"
+ deplibs="$deplibs$dependency_libs"
+ compile_command="$compile_command $dir/$old_library$dependency_libs"
+ finalize_command="$finalize_command $dir/$old_library$dependency_libs"
+ continue
+ fi
+
+ # This library was specified with -dlopen.
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlname, no dlopen support or we're linking statically,
+ # we need to preload.
+ prev=dlprefiles
+ else
+ # We should not create a dependency on this library, but we
+ # may need any libraries it requires.
+ compile_command="$compile_command$dependency_libs"
+ finalize_command="$finalize_command$dependency_libs"
+ prev=
+ continue
+ fi
+ fi
+
+ # The library was specified with -dlpreopen.
+ if test "$prev" = dlprefiles; then
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ dlprefiles="$dlprefiles $dir/$old_library"
+ else
+ dlprefiles="$dlprefiles $dir/$linklib"
+ fi
+ prev=
+ fi
+
+ if test -n "$library_names" &&
+ { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+ link_against_libtool_libs="$link_against_libtool_libs $arg"
+ if test -n "$shlibpath_var"; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *) temp_rpath="$temp_rpath $dir" ;;
+ esac
+ fi
+
+ # We need an absolute path.
+ case "$dir" in
+ [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+ exit 1
+ fi
+ ;;
+ esac
+
+ # This is the magic to use -rpath.
+ # Skip directories that are in the system default run-time
+ # search path, unless they have been requested with -R.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+
+ lib_linked=yes
+ case "$hardcode_action" in
+ immediate | unsupported)
+ if test "$hardcode_direct" = no; then
+ compile_command="$compile_command $dir/$linklib"
+ deplibs="$deplibs $dir/$linklib"
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2*)
+ dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
+ if test -n "$dllsearchpath"; then
+ dllsearchpath="$dllsearchpath:$dllsearchdir"
+ else
+ dllsearchpath="$dllsearchdir"
+ fi
+ ;;
+ esac
+ elif test "$hardcode_minus_L" = no; then
+ case "$host" in
+ *-*-sunos*)
+ compile_shlibpath="$compile_shlibpath$dir:"
+ ;;
+ esac
+ case "$compile_command " in
+ *" -L$dir "*) ;;
+ *) compile_command="$compile_command -L$dir";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -L$dir -l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ case ":$compile_shlibpath:" in
+ *":$dir:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$dir:";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+
+ relink)
+ if test "$hardcode_direct" = yes; then
+ compile_command="$compile_command $absdir/$linklib"
+ deplibs="$deplibs $absdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ case "$compile_command " in
+ *" -L$absdir "*) ;;
+ *) compile_command="$compile_command -L$absdir";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -L$absdir -l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case ":$compile_shlibpath:" in
+ *":$absdir:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$absdir:";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+
+ *)
+ lib_linked=no
+ ;;
+ esac
+
+ if test "$lib_linked" != yes; then
+ $echo "$modename: configuration error: unsupported hardcode properties"
+ exit 1
+ fi
+
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes; then
+ finalize_command="$finalize_command $libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ case "$finalize_command " in
+ *" -L$libdir "*) ;;
+ *) finalize_command="$finalize_command -L$libdir";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case ":$finalize_shlibpath:" in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ case "$finalize_command " in
+ *" -L$dir "*) ;;
+ *) finalize_command="$finalize_command -L$libdir";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ fi
+ else
+ # Transform directly to old archives if we don't build new libraries.
+ if test -n "$pic_flag" && test -z "$old_library"; then
+ $echo "$modename: cannot find static library for \`$arg'" 1>&2
+ exit 1
+ fi
+
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test "$hardcode_direct" != unsupported; then
+ test -n "$old_library" && linklib="$old_library"
+ compile_command="$compile_command $dir/$linklib"
+ finalize_command="$finalize_command $dir/$linklib"
+ else
+ case "$compile_command " in
+ *" -L$dir "*) ;;
+ *) compile_command="$compile_command -L$dir";;
+ esac
+ compile_command="$compile_command -l$name"
+ case "$finalize_command " in
+ *" -L$dir "*) ;;
+ *) finalize_command="$finalize_command -L$dir";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ fi
+ fi
+
+ # Add in any libraries that this one depends upon.
+ compile_command="$compile_command$dependency_libs"
+ finalize_command="$finalize_command$dependency_libs"
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+ esac
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+ done
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+
+ oldlibs=
+ # calculate the name of the file, without its directory
+ outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+ libobjs_save="$libobjs"
+
+ case "$output" in
+ "")
+ $echo "$modename: you must specify an output file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *.a | *.lib)
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$modename: error: cannot link libtool libraries into archives" 1>&2
+ exit 1
+ fi
+
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+ fi
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs="$output"
+ ;;
+
+ *.la)
+ # Make sure we only generate libraries of the form `libNAME.la'.
+ case "$outputname" in
+ lib*)
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ if test "$module" = no; then
+ $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+ if test "$need_lib_prefix" != no; then
+ # Add the "lib" prefix for modules if required
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ eval libname=\"$libname_spec\"
+ else
+ libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ fi
+ ;;
+ esac
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+
+ if test -n "$objs"; then
+ $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1
+ exit 1
+ fi
+
+ # How the heck are we supposed to write a wrapper for a shared library?
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2
+ exit 1
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2
+ fi
+
+ set dummy $rpath
+ if test $# -gt 2; then
+ $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+ fi
+ install_libdir="$2"
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test "$build_libtool_libs" = yes; then
+ # Building a libtool convenience library.
+ libext=al
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+ dependency_libs="$deplibs"
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+ fi
+ else
+
+ # Parse the version information argument.
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo 0 0 0
+ IFS="$save_ifs"
+
+ if test -n "$8"; then
+ $echo "$modename: too many parameters to \`-version-info'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ current="$2"
+ revision="$3"
+ age="$4"
+
+ # Check that each of the things are valid numbers.
+ case "$current" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case "$revision" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case "$age" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test $age -gt $current; then
+ $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case "$version_type" in
+ none) ;;
+
+ irix)
+ major=`expr $current - $age + 1`
+ versuffix="$major.$revision"
+ verstring="sgi$major.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test $loop != 0; do
+ iface=`expr $revision - $loop`
+ loop=`expr $loop - 1`
+ verstring="sgi$major.$iface:$verstring"
+ done
+ ;;
+
+ linux)
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ ;;
+
+ osf)
+ major=`expr $current - $age`
+ versuffix=".$current.$age.$revision"
+ verstring="$current.$age.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test $loop != 0; do
+ iface=`expr $current - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring:${iface}.0"
+ done
+
+ # Make executables depend on our current version.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ sunos)
+ major=".$current"
+ versuffix=".$current.$revision"
+ ;;
+
+ freebsd-aout)
+ major=".$current"
+ versuffix=".$current.$revision";
+ ;;
+
+ freebsd-elf)
+ major=".$current"
+ versuffix=".$current";
+ ;;
+
+ windows)
+ # Like Linux, but with '-' rather than '.', since we only
+ # want one extension on Windows 95.
+ major=`expr $current - $age`
+ versuffix="-$major-$age-$revision"
+ ;;
+
+ *)
+ $echo "$modename: unknown library version type \`$version_type'" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ verstring="0.0"
+ if test "$need_version" = no; then
+ versuffix=
+ else
+ versuffix=".0.0"
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test "$avoid_version" = yes && test "$need_version" = no; then
+ major=
+ versuffix=
+ verstring=""
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag="$no_undefined_flag"
+ fi
+
+ dependency_libs="$deplibs"
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *)
+ # Add libc to deplibs on all other systems.
+ deplibs="$deplibs -lc"
+ ;;
+ esac
+ fi
+
+ # Create the output directory, or remove our outputs if we need to.
+ if test -d $output_objdir; then
+ $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*"
+ $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*
+ else
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ status=$?
+ if test $status -ne 0 && test ! -d $output_objdir; then
+ exit $status
+ fi
+ fi
+
+ # Now set the variables for building old libraries.
+ if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+ oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+ fi
+
+ if test "$build_libtool_libs" = yes; then
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=""
+ versuffix=""
+ major=""
+ newdeplibs=
+ droppeddeps=no
+ case "$deplibs_check_method" in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behaviour.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $rm conftest.c
+ cat > conftest.c <<EOF
+ int main() { return 0; }
+EOF
+ $rm conftest
+ $C_compiler -o conftest conftest.c $deplibs
+ if test $? -eq 0 ; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning: This library needs some functionality provided by $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ else
+ # Error occured in the first compile. Let's try to salvage the situation:
+ # Compile a seperate program for each library.
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" ; then
+ $rm conftest
+ $C_compiler -o conftest conftest.c $i
+ # Did it work?
+ if test $? -eq 0 ; then
+ ldd_output=`ldd conftest`
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning: This library needs some functionality provided by $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ fi
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning! Library $i is needed by this library but I was not able to"
+ echo "*** make it link in! You will probably need to install it or some"
+ echo "*** library that it depends on before this library will be fully"
+ echo "*** functional. Installing it before continuing would be even better."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method
+ file_magic_regex="`expr \"$deplibs_check_method\" : \"$2 \(.*\)\"`"
+ for a_deplib in $deplibs; do
+ name="`expr $a_deplib : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potlib" 2>/dev/null \
+ | grep " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib="$potent_lib"
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | sed 's/.* -> //'`
+ case "$potliblink" in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+ *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+ | sed 10q \
+ | egrep "$file_magic_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ echo
+ echo "*** Warning: This library needs some functionality provided by $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=""
+ if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+ -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' |
+ grep . >/dev/null; then
+ echo
+ if test "X$deplibs_check_method" = "Xnone"; then
+ echo "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ echo "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ echo "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ fi
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ if test "$droppeddeps" = yes; then
+ if test "$module" = yes; then
+ echo
+ echo "*** Warning: libtool could not satisfy all declared inter-library"
+ echo "*** dependencies of module $libname. Therefore, libtool will create"
+ echo "*** a static module, that should work as long as the dlopening"
+ echo "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ echo
+ echo "*** However, this would only work if libtool was able to extract symbol"
+ echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ echo "*** not find such a program. So, this module is probably useless."
+ echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ echo "*** The inter-library dependencies that have been dropped here will be"
+ echo "*** automatically added whenever a program is linked with this library"
+ echo "*** or is declared to -dlopen it."
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test "$build_libtool_libs" = yes; then
+ # Get the real and link names of the library.
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+
+ lib="$output_objdir/$realname"
+ for link
+ do
+ linknames="$linknames $link"
+ done
+
+ # Ensure that we have .o objects for linkers which dislike .lo
+ # (e.g. aix) incase we are running --disable-static
+ for obj in $libobjs; do
+ oldobj=`$echo "X$obj" | $Xsed -e "$lo2o"`
+ if test ! -f $oldobj; then
+ $show "${LN_S} $obj $oldobj"
+ $run ${LN_S} $obj $oldobj || exit $?
+ fi
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+ if test -n "$whole_archive_flag_spec"; then
+ if test -n "$convenience"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ fi
+ else
+ gentop="$output_objdir/${outputname}x"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "mkdir $gentop"
+ $run mkdir "$gentop"
+ status=$?
+ if test $status -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ for xlib in $convenience; do
+ # Extract the objects.
+ case "$xlib" in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "mkdir $xdir"
+ $run mkdir "$xdir"
+ status=$?
+ if test $status -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+ libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+
+ if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ linkopts="$linkopts $flag"
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ eval cmds=\"$export_symbols_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ if test -n "$export_symbols_regex"; then
+ $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+ $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+ $run eval '$mv "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+ fi
+
+ # Do each of the archive commands.
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval cmds=\"$archive_expsym_cmds\"
+ else
+ eval cmds=\"$archive_cmds\"
+ fi
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test "$module" = yes || test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ *.lo | *.o | *.obj)
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$modename: error: cannot link libtool libraries into objects" 1>&2
+ exit 1
+ fi
+
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+ fi
+
+ case "$output" in
+ *.lo)
+ if test -n "$objs"; then
+ $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+ exit 1
+ fi
+ libobj="$output"
+ obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+ ;;
+ *)
+ libobj=
+ obj="$output"
+ ;;
+ esac
+
+ # Delete the old objects.
+ $run $rm $obj $libobj
+
+ # Create the old-style object.
+ reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
+
+ output="$obj"
+ eval cmds=\"$reload_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Exit if we aren't doing a library object file.
+ test -z "$libobj" && exit 0
+
+ if test "$build_libtool_libs" != yes; then
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ $show "echo timestamp > $libobj"
+ $run eval "echo timestamp > $libobj" || exit $?
+ exit 0
+ fi
+
+ if test -n "$pic_flag"; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs"
+ output="$libobj"
+ eval cmds=\"$reload_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ else
+ # Just create a symlink.
+ $show $rm $libobj
+ $run $rm $libobj
+ $show "$LN_S $obj $libobj"
+ $run $LN_S $obj $libobj || exit $?
+ fi
+
+ exit 0
+ ;;
+
+ # Anything else should be a program.
+ *)
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+ fi
+
+ if test "$preload" = yes; then
+ if test "$dlopen" = unknown && test "$dlopen_self" = unknown &&
+ test "$dlopen_self_static" = unknown; then
+ $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+ fi
+ fi
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$compile_rpath " in
+ *" $libdir "*) ;;
+ *) compile_rpath="$compile_rpath $libdir" ;;
+ esac
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath="$rpath"
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath="$rpath"
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+
+ # Create the binary in the object directory, then wrap it.
+ if test ! -d $output_objdir; then
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ status=$?
+ if test $status -ne 0 && test ! -d $output_objdir; then
+ exit $status
+ fi
+ fi
+
+ if test -n "$libobjs" && test "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ fi
+
+ dlsyms=
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" = yes; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ dlsyms="${outputname}S.c"
+ else
+ $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+ fi
+ fi
+
+ if test -n "$dlsyms"; then
+ case "$dlsyms" in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist="$output_objdir/${outputname}.nm"
+
+ $show "$rm $nlist ${nlist}S ${nlist}T"
+ $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+ # Parse the name list into a source file.
+ $show "creating $output_objdir/$dlsyms"
+
+ test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test "$dlself" = yes; then
+ $show "generating symbol list for \`$output'"
+
+ test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ for arg in $progfiles; do
+ $show "extracting global C symbols from \`$arg'"
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols="$output_objdir/$output.exp"
+ $run $rm $export_symbols
+ $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ else
+ $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
+ $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
+ $run eval 'mv "$nlist"T "$nlist"'
+ fi
+ fi
+
+ for arg in $dlprefiles; do
+ $show "extracting global C symbols from \`$arg'"
+ name=`echo "$arg" | sed -e 's%^.*/%%'`
+ $run eval 'echo ": $name " >> "$nlist"'
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -z "$run"; then
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $mv "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then
+ :
+ else
+ grep -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+ else
+ echo '/* NONE */' >> "$output_objdir/$dlsyms"
+ fi
+
+ $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+ sed -n -e 's/^: \([^ ]*\) $/ {\"\1\", (lt_ptr_t) 0},/p' \
+ -e 's/^. \([^ ]*\) \([^ ]*\)$/ {"\2", (lt_ptr_t) \&\2},/p' \
+ < "$nlist" >> "$output_objdir/$dlsyms"
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ {0, (lt_ptr_t) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ fi
+
+ pic_flag_for_symtable=
+ case "$host" in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2*|*-*-freebsd3.0*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";;
+ esac
+ esac
+
+ # Now compile the dynamic symbol file.
+ $show "(cd $output_objdir && $C_compiler -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+ $run eval '(cd $output_objdir && $C_compiler -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+ # Clean up the generated files.
+ $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+ $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+ # Transform the symbol file into the correct name.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ ;;
+ *)
+ $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+ exit 1
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+ fi
+
+ if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then
+ # Replace the output file specification.
+ compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ link_command="$compile_command$compile_rpath"
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ $show "$link_command"
+ $run eval "$link_command"
+ status=$?
+
+ # Delete the generated files.
+ if test -n "$dlsyms"; then
+ $show "$rm $output_objdir/${outputname}S.${objext}"
+ $run $rm "$output_objdir/${outputname}S.${objext}"
+ fi
+
+ exit $status
+ fi
+
+ if test -n "$shlibpath_var"; then
+ # We should set the shlibpath_var
+ rpath=
+ for dir in $temp_rpath; do
+ case "$dir" in
+ [\\/]* | [A-Za-z]:[\\/]*)
+ # Absolute path.
+ rpath="$rpath$dir:"
+ ;;
+ *)
+ # Relative path: add a thisdir entry.
+ rpath="$rpath\$thisdir/$dir:"
+ ;;
+ esac
+ done
+ temp_rpath="$rpath"
+ fi
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+ $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+ $echo "$modename: \`$output' will be relinked during installation" 1>&2
+ else
+ if test "$fast_install" != no; then
+ link_command="$finalize_var$compile_command$finalize_rpath"
+ if test "$fast_install" = yes; then
+ relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+ else
+ # fast_install is set to needless
+ relink_command=
+ fi
+ else
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+ fi
+ fi
+
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+
+ # Now create the wrapper script.
+ $show "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Quote $echo for shipping.
+ if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
+ case "$0" in
+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
+ *) qecho="$SHELL `pwd`/$0 --fallback-echo";;
+ esac
+ qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+ else
+ qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Only actually do things if our run command is non-null.
+ if test -z "$run"; then
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) output=`echo $output|sed 's,.exe$,,'` ;;
+ esac
+ $rm $output
+ trap "$rm $output; exit 1" 1 2 15
+
+ $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test \"\${CDPATH+set}\" = set; then CDPATH=; export CDPATH; fi
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variable:
+ link_against_libtool_libs='$link_against_libtool_libs'
+else
+ # When we are sourced in execute mode, \$file and \$echo are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ echo=\"$qecho\"
+ file=\"\$0\"
+ # Make sure echo works.
+ if test \"X\$1\" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+ # Yippee, \$echo works!
+ :
+ else
+ # Restart under the correct shell, and then maybe \$echo will work.
+ exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+ fi
+ fi\
+"
+ $echo >> $output "\
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\`
+ done
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test "$fast_install" = yes; then
+ echo >> $output "\
+ program=lt-'$outputname'
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" || \\
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $mkdir \"\$progdir\"
+ else
+ $rm \"\$progdir/\$file\"
+ fi"
+
+ echo >> $output "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if (cd \"\$thisdir\" && eval \$relink_command); then :
+ else
+ $rm \"\$progdir/\$file\"
+ exit 1
+ fi
+ fi
+
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $rm \"\$progdir/\$program\";
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $rm \"\$progdir/\$file\"
+ fi"
+ else
+ echo >> $output "\
+ program='$outputname'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ echo >> $output "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # Export our shlibpath_var if we have one.
+ if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $echo >> $output "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 sed
+ $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ # fixup the dll searchpath if we need to.
+ if test -n "$dllsearchpath"; then
+ $echo >> $output "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ $echo >> $output "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+"
+ case $host in
+ *-*-cygwin* | *-*-mingw | *-*-os2*)
+ # win32 systems need to use the prog path for dll
+ # lookup to work
+ $echo >> $output "\
+ exec \$progdir\\\\\$program \${1+\"\$@\"}
+"
+ ;;
+ *)
+ $echo >> $output "\
+ # Export the path to the program.
+ PATH=\"\$progdir:\$PATH\"
+ export PATH
+
+ exec \$program \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $echo >> $output "\
+ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+ exit 1
+ fi
+ else
+ # The program doesn't exist.
+ \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
+ \$echo \"This script is just a wrapper for \$program.\" 1>&2
+ echo \"See the $PACKAGE documentation for more information.\" 1>&2
+ exit 1
+ fi
+fi\
+"
+ chmod +x $output
+ fi
+ exit 0
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ if test "$build_libtool_libs" = convenience; then
+ oldobjs="$libobjs_save"
+ addlibs="$convenience"
+ build_libtool_libs=no
+ else
+ if test "$build_libtool_libs" = module; then
+ oldobjs="$libobjs_save"
+ build_libtool_libs=no
+ else
+ oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
+ fi
+ addlibs="$old_convenience"
+ fi
+
+ if test -n "$addlibs"; then
+ gentop="$output_objdir/${outputname}x"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "mkdir $gentop"
+ $run mkdir "$gentop"
+ status=$?
+ if test $status -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ # Add in members from convenience archives.
+ for xlib in $addlibs; do
+ # Extract the objects.
+ case "$xlib" in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "mkdir $xdir"
+ $run mkdir "$xdir"
+ status=$?
+ if test $status -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+ oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ eval cmds=\"$old_archive_from_new_cmds\"
+ else
+ # Ensure that we have .o objects in place incase we decided
+ # not to build a shared library, and have fallen back to building
+ # static libs even though --disable-static was passed!
+ for oldobj in $oldobjs; do
+ if test ! -f $oldobj; then
+ obj=`$echo "X$oldobj" | $Xsed -e "$o2lo"`
+ $show "${LN_S} $obj $oldobj"
+ $run ${LN_S} $obj $oldobj || exit $?
+ fi
+ done
+
+ eval cmds=\"$old_archive_cmds\"
+ fi
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$generated"; then
+ $show "${rm}r$generated"
+ $run ${rm}r$generated
+ fi
+
+ # Now create the libtool archive.
+ case "$output" in
+ *.la)
+ old_library=
+ test "$build_old_libs" = yes && old_library="$libname.$libext"
+ $show "creating $output"
+
+ if test -n "$xrpath"; then
+ temp_xrpath=
+ for libdir in $xrpath; do
+ temp_xrpath="$temp_xrpath -R$libdir"
+ done
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+
+ # Only create the output if not a dry run.
+ if test -z "$run"; then
+ for installed in no yes; do
+ if test "$installed" = yes; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output="$output_objdir/$outputname"i
+ fi
+ $rm $output
+ $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$dlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'\
+"
+ done
+ fi
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+ $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $?
+ ;;
+ esac
+ exit 0
+ ;;
+
+ # libtool install mode
+ install)
+ modename="$modename: install"
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh; then
+ # Aesthetically quote it.
+ arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$arg "
+ arg="$1"
+ shift
+ else
+ install_prog=
+ arg="$nonopt"
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog$arg"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=no
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest="$arg"
+ continue
+ fi
+
+ case "$arg" in
+ -d) isdir=yes ;;
+ -f) prev="-f" ;;
+ -g) prev="-g" ;;
+ -m) prev="-m" ;;
+ -o) prev="-o" ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*) ;;
+
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest="$arg"
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog $arg"
+ done
+
+ if test -z "$install_prog"; then
+ $echo "$modename: you must specify an install program" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prev' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ $echo "$modename: no file or destination specified" 1>&2
+ else
+ $echo "$modename: you must specify a destination" 1>&2
+ fi
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Strip any trailing slash from the destination.
+ dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=yes
+ if test "$isdir" = yes; then
+ destdir="$dest"
+ destname=
+ else
+ destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$destdir" = "X$dest" && destdir=.
+ destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files
+ if test $# -gt 2; then
+ $echo "$modename: \`$dest' is not a directory" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+ fi
+ case "$destdir" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case "$file" in
+ *.lo) ;;
+ *)
+ $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case "$file" in
+ *.a | *.lib)
+ # Do the static libraries later.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ library_names=
+ old_library=
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/"
+ test "X$dir" = "X$file/" && dir=
+ dir="$dir$objdir"
+
+ # See the names of the shared library.
+ set dummy $library_names
+ if test -n "$2"; then
+ realname="$2"
+ shift
+ shift
+
+ # Install the shared library and build the symlinks.
+ $show "$install_prog $dir/$realname $destdir/$realname"
+ $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $?
+ test "X$dlname" = "X$realname" && dlname=
+
+ if test $# -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ for linkname
+ do
+ test "X$dlname" = "X$linkname" && dlname=
+ if test "$linkname" != "$realname"; then
+ $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ fi
+ done
+ fi
+
+ if test -n "$dlname"; then
+ # Install the dynamically-loadable library.
+ $show "$install_prog $dir/$dlname $destdir/$dlname"
+ $run eval "$install_prog $dir/$dlname $destdir/$dlname" || exit $?
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ eval cmds=\"$postinstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Install the pseudo-library for information purposes.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ instname="$dir/$name"i
+ $show "$install_prog $instname $destdir/$name"
+ $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case "$destfile" in
+ *.lo)
+ staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+ ;;
+ *.o | *.obj)
+ staticdest="$destfile"
+ destfile=
+ ;;
+ *)
+ $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ if test -n "$destfile"; then
+ $show "$install_prog $file $destfile"
+ $run eval "$install_prog $file $destfile" || exit $?
+ fi
+
+ # Install the old object if enabled.
+ if test "$build_old_libs" = yes; then
+ # Deduce the name of the old-style object file.
+ staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+ $show "$install_prog $staticobj $staticdest"
+ $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+ fi
+ exit 0
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Do a test to see if this is really a libtool program.
+ if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ link_against_libtool_libs=
+ relink_command=
+
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Check the variables that should have been set.
+ if test -z "$link_against_libtool_libs"; then
+ $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2
+ exit 1
+ fi
+
+ finalize=yes
+ for lib in $link_against_libtool_libs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ # If there is no directory component, then add one.
+ case "$lib" in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ fi
+ libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`"
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+ finalize=no
+ fi
+ done
+
+ outputname=
+ if test "$fast_install" = no && test -n "$relink_command"; then
+ if test "$finalize" = yes && test -z "$run"; then
+ tmpdir="/tmp"
+ test -n "$TMPDIR" && tmpdir="$TMPDIR"
+ tmpdir="$tmpdir/libtool-$$"
+ if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
+ else
+ $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
+ continue
+ fi
+ outputname="$tmpdir/$file"
+ # Replace the output file specification.
+ relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ ${rm}r "$tmpdir"
+ continue
+ fi
+ file="$outputname"
+ else
+ $echo "$modename: warning: cannot relink \`$file'" 1>&2
+ fi
+ else
+ # Install the binary that we compiled earlier.
+ file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ $show "$install_prog$stripme $file $destfile"
+ $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+ test -n "$outputname" && ${rm}r "$tmpdir"
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ # Set up the ranlib parameters.
+ oldlib="$destdir/$name"
+
+ $show "$install_prog $file $oldlib"
+ $run eval "$install_prog \$file \$oldlib" || exit $?
+
+ # Do each command in the postinstall commands.
+ eval cmds=\"$old_postinstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$future_libdirs"; then
+ $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+ fi
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ test -n "$run" && current_libdirs=" -n$current_libdirs"
+ exec $SHELL $0 --finish$current_libdirs
+ exit 1
+ fi
+
+ exit 0
+ ;;
+
+ # libtool finish mode
+ finish)
+ modename="$modename: finish"
+ libdirs="$nonopt"
+ admincmds=
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ eval cmds=\"$finish_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || admincmds="$admincmds
+ $cmd"
+ done
+ IFS="$save_ifs"
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $run eval "$cmds" || admincmds="$admincmds
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ test "$show" = : && exit 0
+
+ echo "----------------------------------------------------------------------"
+ echo "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ echo " $libdir"
+ done
+ echo
+ echo "If you ever happen to want to link against installed libraries"
+ echo "in a given directory, LIBDIR, you must either use libtool, and"
+ echo "specify the full pathname of the library, or use \`-LLIBDIR'"
+ echo "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
+ echo " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ echo " - add LIBDIR to the \`$runpath_var' environment variable"
+ echo " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ echo " - use the \`$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ echo " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+ fi
+ echo
+ echo "See any operating system documentation about shared libraries for"
+ echo "more information, such as the ld(1) and ld.so(8) manual pages."
+ echo "----------------------------------------------------------------------"
+ exit 0
+ ;;
+
+ # libtool execute mode
+ execute)
+ modename="$modename: execute"
+
+ # The first argument is the command name.
+ cmd="$nonopt"
+ if test -z "$cmd"; then
+ $echo "$modename: you must specify a COMMAND" 1>&2
+ $echo "$help"
+ exit 1
+ fi
+
+ # Handle -dlopen flags immediately.
+ for file in $execute_dlfiles; do
+ if test ! -f "$file"; then
+ $echo "$modename: \`$file' is not a file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ dir=
+ case "$file" in
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+ continue
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+
+ if test -f "$dir/$objdir/$dlname"; then
+ dir="$dir/$objdir"
+ else
+ $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+ exit 1
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ ;;
+
+ *)
+ $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir="$absdir"
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic="$magic"
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case "$file" in
+ -*) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+ args="$args \"$file\""
+ done
+
+ if test -z "$run"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+
+ # Restore saved enviroment variables
+ if test "${save_LC_ALL+set}" = set; then
+ LC_ALL="$save_LC_ALL"; export LC_ALL
+ fi
+ if test "${save_LANG+set}" = set; then
+ LANG="$save_LANG"; export LANG
+ fi
+
+ # Now actually exec the command.
+ eval "exec \$cmd$args"
+
+ $echo "$modename: cannot exec \$cmd$args"
+ exit 1
+ else
+ # Display what would be done.
+ eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+ $echo "export $shlibpath_var"
+ $echo "$cmd$args"
+ exit 0
+ fi
+ ;;
+
+ # libtool uninstall mode
+ uninstall)
+ modename="$modename: uninstall"
+ rm="$nonopt"
+ files=
+
+ for arg
+ do
+ case "$arg" in
+ -*) rm="$rm $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ if test -z "$rm"; then
+ $echo "$modename: you must specify an RM program" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ for file in $files; do
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ rmfiles="$file"
+
+ case "$name" in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ . $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ rmfiles="$rmfiles $dir/$n"
+ test "X$n" = "X$dlname" && dlname=
+ done
+ test -n "$dlname" && rmfiles="$rmfiles $dir/$dlname"
+ test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library"
+
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles
+
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ eval cmds=\"$postuninstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd"
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ eval cmds=\"$old_postuninstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd"
+ done
+ IFS="$save_ifs"
+ fi
+
+ # FIXME: should reinstall the best remaining shared library.
+ fi
+ ;;
+
+ *.lo)
+ if test "$build_old_libs" = yes; then
+ oldobj=`$echo "X$name" | $Xsed -e "$lo2o"`
+ rmfiles="$rmfiles $dir/$oldobj"
+ fi
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles
+ ;;
+
+ *)
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles
+ ;;
+ esac
+ done
+ exit 0
+ ;;
+
+ "")
+ $echo "$modename: you must specify a MODE" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+fi # test -z "$show_help"
+
+# We need to display help for each of the modes.
+case "$mode" in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+ --config show all configuration variables
+ --debug enable verbose shell tracing
+-n, --dry-run display commands without modifying any files
+ --features display basic configuration information and exit
+ --finish same as \`--mode=finish'
+ --help display this help message and exit
+ --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --version print version information
+
+MODE must be one of the following:
+
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE."
+ exit 0
+ ;;
+
+compile)
+ $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -static always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+ ;;
+
+execute)
+ $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+finish)
+ $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the \`--dry-run' option if you just want to see what would be executed."
+ ;;
+
+install)
+ $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+link)
+ $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -static do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename. Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+uninstall)
+ $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+*)
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+esac
+
+echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/src/shapelib/makefile.vc b/src/shapelib/makefile.vc
new file mode 100644
index 0000000..0819a21
--- /dev/null
+++ b/src/shapelib/makefile.vc
@@ -0,0 +1,55 @@
+
+#CFLAGS = /DSHPAPI_CALL=__stdcall
+
+default: all
+
+all: shpcreate.exe shpadd.exe shpdump.exe shprewind.exe dbfcreate.exe \
+ dbfadd.exe dbfdump.exe shptest.exe shptreedump.exe shapelib.dll
+
+shpopen.obj: shpopen.c shapefil.h
+ $(CC) $(CFLAGS) -c shpopen.c
+
+shptree.obj: shptree.c shapefil.h
+ $(CC) $(CFLAGS) -c shptree.c
+
+dbfopen.obj: dbfopen.c shapefil.h
+ $(CC) $(CFLAGS) -c dbfopen.c
+
+shpcreate.exe: shpcreate.c shpopen.obj
+ $(CC) $(CFLAGS) shpcreate.c shpopen.obj $(LINKOPT) -o shpcreate
+
+shpadd.exe: shpadd.c shpopen.obj
+ $(CC) $(CFLAGS) shpadd.c shpopen.obj $(LINKOPT)
+
+shpdump.exe: shpdump.c shpopen.obj
+ $(CC) $(CFLAGS) shpdump.c shpopen.obj $(LINKOPT)
+
+shprewind.exe: shprewind.c shpopen.obj
+ $(CC) $(CFLAGS) shprewind.c shpopen.obj $(LINKOPT)
+
+dbfcreate.exe: dbfcreate.c dbfopen.obj
+ $(CC) $(CFLAGS) dbfcreate.c dbfopen.obj $(LINKOPT)
+
+dbfadd.exe: dbfadd.c dbfopen.obj
+ $(CC) $(CFLAGS) dbfadd.c dbfopen.obj $(LINKOPT)
+
+dbfdump.exe: dbfdump.c dbfopen.obj
+ $(CC) $(CFLAGS) dbfdump.c dbfopen.obj $(LINKOPT)
+
+shptest.exe: shptest.c shpopen.obj
+ $(CC) $(CFLAGS) shptest.c shpopen.obj $(LINKOPT)
+
+shputils.exe: shputils.c shpopen.obj dbfopen.obj
+ $(CC) $(CFLAGS) shputils.c shpopen.obj dbfopen.obj $(LINKOPT)
+
+shptreedump.exe: shptreedump.c shptree.obj shpopen.obj
+ $(CC) $(CFLAGS) shptreedump.c shptree.obj shpopen.obj $(LINKOPT)
+
+clean:
+ -del *.obj dbfdump dbfcreate dbfadd shpdump shpcreate shpadd shputils
+ -del *.lib
+ -del *.dll
+
+shapelib.dll: shpopen.obj dbfopen.obj shptree.obj shapelib.def
+ link /dll /def:shapelib.def /out:shapelib.dll /implib:shapelib.lib \
+ shpopen.obj dbfopen.obj shptree.obj
diff --git a/src/shapelib/makeshape.sh b/src/shapelib/makeshape.sh
new file mode 100755
index 0000000..6e5f271
--- /dev/null
+++ b/src/shapelib/makeshape.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+#
+# Use example programs to create a very simple dataset that
+# should display in ARCView II.
+#
+
+shpcreate test polygon
+dbfcreate test.dbf -s Description 30 -n TestInt 6 0 -n TestDouble 16 5
+
+shpadd test 0 0 100 0 100 100 0 100 0 0 + 20 20 20 30 30 30 20 20
+dbfadd test.dbf "Square with triangle missing" 1.5 2.5
+
+shpadd test 150 150 160 150 180 170 150 150
+dbfadd test.dbf "Smaller triangle" 100 1000.25
+
+shpadd test 150 150 160 150 180 170 150 150
+dbfadd test.dbf "" "" ""
+
+shpdump test.shp
+dbfdump test.dbf
diff --git a/src/shapelib/mkinstalldirs b/src/shapelib/mkinstalldirs
new file mode 100644
index 0000000..5e17cd3
--- /dev/null
+++ b/src/shapelib/mkinstalldirs
@@ -0,0 +1,38 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman at prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/src/shapelib/shapefil.h b/src/shapelib/shapefil.h
new file mode 100644
index 0000000..b47660b
--- /dev/null
+++ b/src/shapelib/shapefil.h
@@ -0,0 +1,507 @@
+#ifndef _SHAPEFILE_H_INCLUDED
+#define _SHAPEFILE_H_INCLUDED
+
+/******************************************************************************
+ * $Id: shapefil.h,v 1.1 2006/11/10 21:48:10 tvrusso Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Primary include file for Shapelib.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: shapefil.h,v $
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.26 2002/09/29 00:00:08 warmerda
+ * added FTLogical and logical attribute read/write calls
+ *
+ * Revision 1.25 2002/05/07 13:46:30 warmerda
+ * added DBFWriteAttributeDirectly().
+ *
+ * Revision 1.24 2002/04/10 16:59:54 warmerda
+ * added SHPRewindObject
+ *
+ * Revision 1.23 2002/01/15 14:36:07 warmerda
+ * updated email address
+ *
+ * Revision 1.22 2002/01/15 14:32:00 warmerda
+ * try to improve SHPAPI_CALL docs
+ *
+ * Revision 1.21 2001/11/01 16:29:55 warmerda
+ * move pabyRec into SHPInfo for thread safety
+ *
+ * Revision 1.20 2001/07/20 13:06:02 warmerda
+ * fixed SHPAPI attribute for SHPTreeFindLikelyShapes
+ *
+ * Revision 1.19 2001/05/31 19:20:13 warmerda
+ * added DBFGetFieldIndex()
+ *
+ * Revision 1.18 2001/05/31 18:15:40 warmerda
+ * Added support for NULL fields in DBF files
+ *
+ * Revision 1.17 2001/05/23 13:36:52 warmerda
+ * added use of SHPAPI_CALL
+ *
+ * Revision 1.16 2000/09/25 14:15:59 warmerda
+ * added DBFGetNativeFieldType()
+ *
+ * Revision 1.15 2000/02/16 16:03:51 warmerda
+ * added null shape support
+ *
+ * Revision 1.14 1999/11/05 14:12:05 warmerda
+ * updated license terms
+ *
+ * Revision 1.13 1999/06/02 18:24:21 warmerda
+ * added trimming code
+ *
+ * Revision 1.12 1999/06/02 17:56:12 warmerda
+ * added quad'' subnode support for trees
+ *
+ * Revision 1.11 1999/05/18 19:11:11 warmerda
+ * Added example searching capability
+ *
+ * Revision 1.10 1999/05/18 17:49:38 warmerda
+ * added initial quadtree support
+ *
+ * Revision 1.9 1999/05/11 03:19:28 warmerda
+ * added new Tuple api, and improved extension handling - add from candrsn
+ *
+ * Revision 1.8 1999/03/23 17:22:27 warmerda
+ * Added extern "C" protection for C++ users of shapefil.h.
+ *
+ * Revision 1.7 1998/12/31 15:31:07 warmerda
+ * Added the TRIM_DBF_WHITESPACE and DISABLE_MULTIPATCH_MEASURE options.
+ *
+ * Revision 1.6 1998/12/03 15:48:15 warmerda
+ * Added SHPCalculateExtents().
+ *
+ * Revision 1.5 1998/11/09 20:57:16 warmerda
+ * Altered SHPGetInfo() call.
+ *
+ * Revision 1.4 1998/11/09 20:19:33 warmerda
+ * Added 3D support, and use of SHPObject.
+ *
+ * Revision 1.3 1995/08/23 02:24:05 warmerda
+ * Added support for reading bounds.
+ *
+ * Revision 1.2 1995/08/04 03:17:39 warmerda
+ * Added header.
+ *
+ */
+
+#include <stdio.h>
+
+#ifdef USE_DBMALLOC
+#include <dbmalloc.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/************************************************************************/
+/* Configuration options. */
+/************************************************************************/
+
+/* -------------------------------------------------------------------- */
+/* Should the DBFReadStringAttribute() strip leading and */
+/* trailing white space? */
+/* -------------------------------------------------------------------- */
+#define TRIM_DBF_WHITESPACE
+
+/* -------------------------------------------------------------------- */
+/* Should we write measure values to the Multipatch object? */
+/* Reportedly ArcView crashes if we do write it, so for now it */
+/* is disabled. */
+/* -------------------------------------------------------------------- */
+#define DISABLE_MULTIPATCH_MEASURE
+
+/* -------------------------------------------------------------------- */
+/* SHPAPI_CALL */
+/* */
+/* The following two macros are present to allow forcing */
+/* various calling conventions on the Shapelib API. */
+/* */
+/* To force __stdcall conventions (needed to call Shapelib */
+/* from Visual Basic and/or Dephi I believe) the makefile could */
+/* be modified to define: */
+/* */
+/* /DSHPAPI_CALL=__stdcall */
+/* */
+/* If it is desired to force export of the Shapelib API without */
+/* using the shapelib.def file, use the following definition. */
+/* */
+/* /DSHAPELIB_DLLEXPORT */
+/* */
+/* To get both at once it will be necessary to hack this */
+/* include file to define: */
+/* */
+/* #define SHPAPI_CALL __declspec(dllexport) __stdcall */
+/* #define SHPAPI_CALL1 __declspec(dllexport) * __stdcall */
+/* */
+/* The complexity of the situtation is partly caused by the */
+/* peculiar requirement of Visual C++ that __stdcall appear */
+/* after any "*"'s in the return value of a function while the */
+/* __declspec(dllexport) must appear before them. */
+/* -------------------------------------------------------------------- */
+
+#ifdef SHAPELIB_DLLEXPORT
+# define SHPAPI_CALL __declspec(dllexport)
+# define SHPAPI_CALL1(x) __declspec(dllexport) x
+#endif
+
+#ifndef SHPAPI_CALL
+# define SHPAPI_CALL
+#endif
+
+#ifndef SHPAPI_CALL1
+# define SHPAPI_CALL1(x) x SHPAPI_CALL
+#endif
+
+/************************************************************************/
+/* SHP Support. */
+/************************************************************************/
+typedef struct
+{
+ FILE *fpSHP;
+ FILE *fpSHX;
+
+ int nShapeType; /* SHPT_* */
+
+ int nFileSize; /* SHP file */
+
+ int nRecords;
+ int nMaxRecords;
+ int *panRecOffset;
+ int *panRecSize;
+
+ double adBoundsMin[4];
+ double adBoundsMax[4];
+
+ int bUpdated;
+
+ unsigned char *pabyRec;
+ int nBufSize;
+} SHPInfo;
+
+typedef SHPInfo * SHPHandle;
+
+/* -------------------------------------------------------------------- */
+/* Shape types (nSHPType) */
+/* -------------------------------------------------------------------- */
+#define SHPT_NULL 0
+#define SHPT_POINT 1
+#define SHPT_ARC 3
+#define SHPT_POLYGON 5
+#define SHPT_MULTIPOINT 8
+#define SHPT_POINTZ 11
+#define SHPT_ARCZ 13
+#define SHPT_POLYGONZ 15
+#define SHPT_MULTIPOINTZ 18
+#define SHPT_POINTM 21
+#define SHPT_ARCM 23
+#define SHPT_POLYGONM 25
+#define SHPT_MULTIPOINTM 28
+#define SHPT_MULTIPATCH 31
+
+
+/* -------------------------------------------------------------------- */
+/* Part types - everything but SHPT_MULTIPATCH just uses */
+/* SHPP_RING. */
+/* -------------------------------------------------------------------- */
+
+#define SHPP_TRISTRIP 0
+#define SHPP_TRIFAN 1
+#define SHPP_OUTERRING 2
+#define SHPP_INNERRING 3
+#define SHPP_FIRSTRING 4
+#define SHPP_RING 5
+
+/* -------------------------------------------------------------------- */
+/* SHPObject - represents on shape (without attributes) read */
+/* from the .shp file. */
+/* -------------------------------------------------------------------- */
+typedef struct
+{
+ int nSHPType;
+
+ int nShapeId; /* -1 is unknown/unassigned */
+
+ int nParts;
+ int *panPartStart;
+ int *panPartType;
+
+ int nVertices;
+ double *padfX;
+ double *padfY;
+ double *padfZ;
+ double *padfM;
+
+ double dfXMin;
+ double dfYMin;
+ double dfZMin;
+ double dfMMin;
+
+ double dfXMax;
+ double dfYMax;
+ double dfZMax;
+ double dfMMax;
+} SHPObject;
+
+/* -------------------------------------------------------------------- */
+/* SHP API Prototypes */
+/* -------------------------------------------------------------------- */
+SHPHandle SHPAPI_CALL
+ SHPOpen( const char * pszShapeFile, const char * pszAccess );
+SHPHandle SHPAPI_CALL
+ SHPCreate( const char * pszShapeFile, int nShapeType );
+void SHPAPI_CALL
+ SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
+ double * padfMinBound, double * padfMaxBound );
+
+SHPObject SHPAPI_CALL1(*)
+ SHPReadObject( SHPHandle hSHP, int iShape );
+int SHPAPI_CALL
+ SHPWriteObject( SHPHandle hSHP, int iShape, SHPObject * psObject );
+
+void SHPAPI_CALL
+ SHPDestroyObject( SHPObject * psObject );
+void SHPAPI_CALL
+ SHPComputeExtents( SHPObject * psObject );
+SHPObject SHPAPI_CALL1(*)
+ SHPCreateObject( int nSHPType, int nShapeId,
+ int nParts, int * panPartStart, int * panPartType,
+ int nVertices, double * padfX, double * padfY,
+ double * padfZ, double * padfM );
+SHPObject SHPAPI_CALL1(*)
+ SHPCreateSimpleObject( int nSHPType, int nVertices,
+ double * padfX, double * padfY, double * padfZ );
+
+int SHPAPI_CALL
+ SHPRewindObject( SHPHandle hSHP, SHPObject * psObject );
+
+void SHPAPI_CALL
+ SHPClose( SHPHandle hSHP );
+
+const char SHPAPI_CALL1(*)
+ SHPTypeName( int nSHPType );
+const char SHPAPI_CALL1(*)
+ SHPPartTypeName( int nPartType );
+
+/* -------------------------------------------------------------------- */
+/* Shape quadtree indexing API. */
+/* -------------------------------------------------------------------- */
+
+/* this can be two or four for binary or quad tree */
+#define MAX_SUBNODE 4
+
+typedef struct shape_tree_node
+{
+ /* region covered by this node */
+ double adfBoundsMin[4];
+ double adfBoundsMax[4];
+
+ /* list of shapes stored at this node. The papsShapeObj pointers
+ or the whole list can be NULL */
+ int nShapeCount;
+ int *panShapeIds;
+ SHPObject **papsShapeObj;
+
+ int nSubNodes;
+ struct shape_tree_node *apsSubNode[MAX_SUBNODE];
+
+} SHPTreeNode;
+
+typedef struct
+{
+ SHPHandle hSHP;
+
+ int nMaxDepth;
+ int nDimension;
+
+ SHPTreeNode *psRoot;
+} SHPTree;
+
+SHPTree SHPAPI_CALL1(*)
+ SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
+ double *padfBoundsMin, double *padfBoundsMax );
+void SHPAPI_CALL
+ SHPDestroyTree( SHPTree * hTree );
+
+int SHPAPI_CALL
+ SHPWriteTree( SHPTree *hTree, const char * pszFilename );
+SHPTree SHPAPI_CALL
+ SHPReadTree( const char * pszFilename );
+
+int SHPAPI_CALL
+ SHPTreeAddObject( SHPTree * hTree, SHPObject * psObject );
+int SHPAPI_CALL
+ SHPTreeAddShapeId( SHPTree * hTree, SHPObject * psObject );
+int SHPAPI_CALL
+ SHPTreeRemoveShapeId( SHPTree * hTree, int nShapeId );
+
+void SHPAPI_CALL
+ SHPTreeTrimExtraNodes( SHPTree * hTree );
+
+int SHPAPI_CALL1(*)
+ SHPTreeFindLikelyShapes( SHPTree * hTree,
+ double * padfBoundsMin,
+ double * padfBoundsMax,
+ int * );
+int SHPAPI_CALL
+ SHPCheckBoundsOverlap( double *, double *, double *, double *, int );
+
+/************************************************************************/
+/* DBF Support. */
+/************************************************************************/
+typedef struct
+{
+ FILE *fp;
+
+ int nRecords;
+
+ int nRecordLength;
+ int nHeaderLength;
+ int nFields;
+ int *panFieldOffset;
+ int *panFieldSize;
+ int *panFieldDecimals;
+ char *pachFieldType;
+
+ char *pszHeader;
+
+ int nCurrentRecord;
+ int bCurrentRecordModified;
+ char *pszCurrentRecord;
+
+ int bNoHeader;
+ int bUpdated;
+} DBFInfo;
+
+typedef DBFInfo * DBFHandle;
+
+typedef enum {
+ FTString,
+ FTInteger,
+ FTDouble,
+ FTLogical,
+ FTInvalid
+} DBFFieldType;
+
+#define XBASE_FLDHDR_SZ 32
+
+DBFHandle SHPAPI_CALL
+ DBFOpen( const char * pszDBFFile, const char * pszAccess );
+DBFHandle SHPAPI_CALL
+ DBFCreate( const char * pszDBFFile );
+
+int SHPAPI_CALL
+ DBFGetFieldCount( DBFHandle psDBF );
+int SHPAPI_CALL
+ DBFGetRecordCount( DBFHandle psDBF );
+int SHPAPI_CALL
+ DBFAddField( DBFHandle hDBF, const char * pszFieldName,
+ DBFFieldType eType, int nWidth, int nDecimals );
+
+DBFFieldType SHPAPI_CALL
+ DBFGetFieldInfo( DBFHandle psDBF, int iField,
+ char * pszFieldName, int * pnWidth, int * pnDecimals );
+
+int SHPAPI_CALL
+ DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName);
+
+int SHPAPI_CALL
+ DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
+double SHPAPI_CALL
+ DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
+const char SHPAPI_CALL1(*)
+ DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
+const char SHPAPI_CALL1(*)
+ DBFReadLogicalAttribute( DBFHandle hDBF, int iShape, int iField );
+int SHPAPI_CALL
+ DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
+
+int SHPAPI_CALL
+ DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField,
+ int nFieldValue );
+int SHPAPI_CALL
+ DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
+ double dFieldValue );
+int SHPAPI_CALL
+ DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
+ const char * pszFieldValue );
+int SHPAPI_CALL
+ DBFWriteNULLAttribute( DBFHandle hDBF, int iShape, int iField );
+
+int SHPAPI_CALL
+ DBFWriteLogicalAttribute( DBFHandle hDBF, int iShape, int iField,
+ const char lFieldValue);
+int SHPAPI_CALL
+ DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
+ void * pValue );
+const char SHPAPI_CALL1(*)
+ DBFReadTuple(DBFHandle psDBF, int hEntity );
+int SHPAPI_CALL
+ DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple );
+
+DBFHandle SHPAPI_CALL
+ DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename );
+
+void SHPAPI_CALL
+ DBFClose( DBFHandle hDBF );
+char SHPAPI_CALL
+ DBFGetNativeFieldType( DBFHandle hDBF, int iField );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ndef _SHAPEFILE_H_INCLUDED */
diff --git a/src/shapelib/shapelib.def b/src/shapelib/shapelib.def
new file mode 100644
index 0000000..01964c4
--- /dev/null
+++ b/src/shapelib/shapelib.def
@@ -0,0 +1,42 @@
+LIBRARY shapelib
+EXPORTS SHPOpen
+ SHPCreate
+ SHPGetInfo
+ SHPReadObject
+ SHPWriteObject
+ SHPDestroyObject
+ SHPComputeExtents
+ SHPCreateObject
+ SHPCreateSimpleObject
+ SHPClose
+ SHPTypeName
+ SHPPartTypeName
+ SHPCreateTree
+ SHPDestroyTree
+ SHPTreeAddShapeId
+ SHPTreeTrimExtraNodes
+ SHPTreeFindLikelyShapes
+ SHPCheckBoundsOverlap
+ DBFOpen
+ DBFCreate
+ DBFGetFieldCount
+ DBFGetRecordCount
+ DBFAddField
+ DBFGetFieldInfo
+ DBFReadIntegerAttribute
+ DBFReadDoubleAttribute
+ DBFReadStringAttribute
+ DBFWriteIntegerAttribute
+ DBFWriteDoubleAttribute
+ DBFWriteStringAttribute
+ DBFReadTuple
+ DBFWriteTuple
+ DBFCloneEmpty
+ DBFClose
+ DBFWriteNULLAttribute
+ DBFGetFieldIndex
+ DBFIsAttributeNULL
+ DBFWriteLogicalAttribute
+ DBFReadLogicalAttribute
+
+
diff --git a/src/shapelib/shapelib.html b/src/shapelib/shapelib.html
new file mode 100644
index 0000000..4372d1d
--- /dev/null
+++ b/src/shapelib/shapelib.html
@@ -0,0 +1,334 @@
+<html>
+<head>
+<title>Shapefile C Library V1.2</title>
+</head>
+
+<body>
+<h1>Shapefile C Library V1.2</h1>
+
+<h2>Purpose</h2>
+
+The Shapefile C Library provides the ability to write simple C programs
+for reading, writing and updating (to a limited extent) ESRI Shapefiles,
+and the associated attribute file (.dbf).<p>
+
+<h2>Manifest</h2>
+
+<ul>
+<li> <b>shapelib.html</b>: This file - general documentation on the
+Shapefile C Library.<p>
+
+<li> <b><a href="shp_api.html">shp_api.html</a></b>: Documentation
+for the API for accessing the .shp/.shx files. <p>
+
+<li> <b><a href="dbf_api.html">dbf_api.html</a></b>: Documentation
+for the API for accessing the .dbf attribute files. <p>
+
+<li> <b>shpopen.c</b>: C code for access to .shp/.shx vertex files.<p>
+
+<li> <b>dbfopen.c</b>: C code for access to .dbf attribute file.<p>
+
+<li> <b>shapefil.h</b>: Include file defining all the services of dbfopen.c
+and shpopen.c.<p>
+
+<li> <b>contrib/</b>: A directory of "in progress" contributed programs
+from Carl Anderson.<p>
+
+<li> <b>dbfcreate.c</b>: Simple example program for creating a new .dbf file.
+ <p>
+
+<li> <b>dbfadd.c</b>:
+ Simple example program for adding a record to a .dbf file.<p>
+
+<li> <b>dbfdump.c</b>: Simple example program for displaying the contents of
+ a .dbf file.<p>
+
+<li> <b>shpcreate.c</b>: Simple example program for creating a new .shp and
+.shx file.<p>
+
+<li> <b>shpadd.c</b>: Simple example program for adding a shape to an existing
+ shape file.<p>
+
+<li> <b>shpdump.c</b>: Simple program for dumping all the vertices in a
+ shapefile with an indicating of the parts.<p>
+
+<li> <b>shputils.c</b>: Complex contributed program capable of clipping and
+ appending
+ shapefiles as well as a few other things. Type shputils
+ after building to get a full usage message.<p>
+
+<li> <b>Makefile</b>: A simple makefile to compile the library and example
+ programs.<p>
+
+<li> <b>makeshape.sh</b>: A simple script for running some of the example
+programs.<p>
+
+<li> <b>shptest.c</b>: A simple test harnass to generate each of the supported
+ types of shapefiles. <p>
+
+
+<li> <b>shptree.c</b>: Implements a simple quadtree algorithm for fast
+spatial searches of shapefiles.<p>
+
+<li> <b>shptreedump.c</b>: A simple mainly showing information on quad
+trees build using the quad tree api.<p>
+
+<li> <b>stream1.sh</b> - A test script, which should produce stream1.out.
+Note this will only work if you have the example data downloaded.<p>
+
+<li> <b>stream1.out</b>: Expected output of stream1.sh test script.<p>
+
+<li> <b>stream2.sh</b>: A test script, which should produce stream2.out.<p>
+
+<li> <b>stream2.out</b>: Expected output of stream2.sh test script.<p>
+
+<li> <b>pyshapelib-0.1</b>: Prototype contributed Python bindings.<p>
+
+</ul>
+
+<h2>What is a Shapefile?</h2>
+
+If you don't know, you probably don't need this library. The Shapefile
+format is a new working and interchange format promulagated by ESRI
+(http://www.esri.com/) for simple vector data with attributes. It is
+apparently the only file format that can be edited in ARCView 2/3, and can
+also be exported and imported in Arc/Info. <p>
+
+An excellent white paper on the shapefile format is available from ESRI,
+but it is .pdf format, so you will need Adobe Acrobat to browse it.<p>
+
+The file format actually consists of three files.<p>
+
+<pre>
+XXX.shp - holds the actual vertices.
+XXX.shx - hold index data pointing to the structures in the .shp file.
+XXX.dbf - holds the attributes in xBase (dBase) format.
+</pre>
+
+<h2>Release Notes</h2>
+
+To get notification of new releases of Shapelib <i>subscribe</i> to
+the project at www.freshmeat.net. This is currently the only reliable
+way of finding out about new releases since there is no shapelib specific
+mailing list.<p>
+
+<b>Release 1.2.10</b>: Added SHPRewindObject() function, and shprewind utility
+program. Added FTLogical, DBFReadLogicalAttribute() and
+DBFWriteLogicalAttribute() (thanks to Olek Neyman). <p>
+
+<b>Release 1.2.9</b>: Good support for reading and writing NULL fields
+in .dbf files, good support for NULL shapes and addition of the
+DBFGetFieldIndex() functions (all contributed by Jim Matthews).<p>
+
+An upgraded shputils.c has been contributed by Bill Miller. Daniel
+Morissette contributed DBFGetNativeFieldType(). Better error checking
+for disk errors in dbfopen.c. Various other bug fixes and safety improvements.
+<p>
+
+<b>Release 1.2.8</b>: Added hacked libtool support (supplied by Jan)
+and "rpm ready" install logic.<p>
+
+<b>Release 1.2.7</b>: Fix record size (was 4 bytes too long). Modify
+SHPReadObject() to handle null shapes properly. Use atof() instead of
+sscanf(). Support .DBF as well as .dbf.<p>
+
+<b>Release 1.2.6</b>: Now available under old MIT style license, or at the
+users option, LGPL. Added the contrib directory of stuff from Carl Anderson
+and the shptree.c API for quadtree based spatial searches.<p>
+
+<b>Release 1.2.5</b>: SHPOpen() now forcably uses "rb" or "r+b" access string
+to avoid common mistakes on Windows. Also fixed a serious bug with .dbf
+files with a 'F' field type.<p>
+
+<b>Release 1.2.4</b>: DBFOpen() will now automatically translate a .shp
+extension to .dbf for convenience. SHPOpen() will try datasets with lower
+and uppercase extension. DBFAddField() now returns the field number,
+not TRUE/FALSE.<p>
+
+<b>Release 1.2.3</b>: Disable writing measures to multi-patches as ArcView
+seems to puke on them (as reported by Monika Sester). Add white space
+trimming, and string/numeric attribute interchangability in DBF API
+as suggested by Steve Lime. Dbfdump was updated to include several
+reporting options.<p>
+
+<b>Release 1.2.2</b>: Added proper support for multipatch (reading and
+writing) - this release just for testing purposes.<p>
+
+<b>Release 1.2</b> is mostly a rewrite of the .shp/.shx access API to account
+for ArcView 3.x 3D shapes, and to encapsulate the shapes in a structure.
+Existing code using the shapefile library will require substantial changes
+to use release 1.2.<p>
+
+<b>Release V1.1</b> has been built on a number of platforms, and used by a
+number of people successfully. V1.1 is the first release with the xBase API
+documentation.<p>
+
+
+<h2>Maintainer</h2>
+
+This library is maintained by me (Frank Warmerdam) on my own time. Please
+send me bug patches and suggestions for the library. Email can be sent to
+warmerdam at pobox.com.<p>
+
+The current status of the Shapelib code can be found at
+<a href="http://pobox.com/~warmerdam/root/projects/shapelib/">
+http://pobox.com/~warmerdam/root/projects/shapelib/</a>. To find out about
+new releases of Shapelib, select the "Subscribe to new releases" option
+from the link at
+<a href="http://freshmeat.net/projects/shapelib/">Freshmeat</a>.<p>
+
+The shputils.c module was contributed by Bill Miller (NC-DOT) who can be
+reached at bmiller at doh.dot.state.nc.us. I had to modify it substantially
+to work with the 1.2 API, and I am not sure that it works as well as it
+did when it was originally provided by Bill.<p>
+
+<h2>Credits</h2>
+
+I didn't start this section anywhere near soon enough, so alot of earlier
+contributors to Shapelib are lost in pre-history.
+
+<ul>
+<li> Bill Miller (NY-DOT) for shputils.c
+<li> Carl Anderson for the contents of the contrib directory, and
+the "tuple" additions to dbfopen.c.
+<li> Andrea Giacomelli for patches for dbfopen.c.
+<li> Doug Matthews for portability improvements.
+<li> Jan-Oliver Wagner for convincing me to make it available under LGPL,
+shared library support, and various other patches.
+<li> Dennis Christopher (of Avenza) for testing and bug fixes.
+<li> Miko Syrj� (of 3D-system Oy) for a record size bug fix.
+<li> Steven Lime and Curtis Hill for help with NULL shapes.
+<li> Jim Matthews for support of NULL attributes in dbf files.
+<li> <a href="http://www.pcigeomatics.com/">PCI Geomatics</a> who let me
+release a modified version of their shapefile code in the beginning and
+who hosted shapelib for years.
+</ul>
+
+<h2>In Memorium</h2>
+
+I would like to dedicate Shapelib to the memory of Sol Katz. While I never
+met him in person, his generous contributions to the GIS community took
+many forms, including free distribution of a variety of GIS translators
+with source. The fact that he used this Shapelib in some of his utilities,
+and thanked me was a great encouragement to me. I hope I can do his memory
+honour by trying to contribute in a similar fashion.<p>
+
+<h2>Portability</h2>
+
+The Shapefile C Library should port easily to 32bit systems with ANSI C
+compilers. It should work on 64 bit architectures (such as the DEC AXP).<p>
+
+Care should also be taken to pass the binary access flag into SHPOpen()
+and DBFOpen() when operating on systems with special text file translation
+such as MSDOS.<p>
+
+The shputils.c module is contributed, and may not take the same approach
+to portability as the rest of the package.<p>
+
+On Linux, and most unix systems it should be possible to build and
+install shapefile support as a shared library using the "lib" and "lib_install"
+targets of the Makefile. Note that this Makefile doesn't use autoconf
+mechanisms and will generally require some hand tailoring for your environment.
+
+<h2>Limitations</h2>
+
+<ul>
+
+<li> You can't modify the vertices of existing structures (though you
+ can update the attributes of existing structures, and create new
+ structures).<p>
+
+<li> Not written in such a way as to be particularly fast. This is
+particularly true of the 1.2 API. For applications more concerned with
+speed it may be worth using the V1.1 API.<p>
+
+<li> Doesn't set the last access time properly in the .dbf files.<p>
+
+<li> There is no way to synchronize information to the file except to close it.
+<p>
+
+<li> Poor error checking and reporting.<p>
+
+<li> Not professionally supported (well it can be, if you want to pay).<p>
+
+<li> Some aspects of xBase files not supported, though I believe they are
+not used by ESRI.<p>
+
+<li> The application must keep the .dbf file in sync with the .shp/.shx
+files through appropriate use of the DBF and SHP APIs.<p>
+
+<li> No support for the undocumented .sbn/.sbx spatial index files.<p>
+
+</ul>
+
+<h2>Copyright</h2>
+
+The source for the Shapefile C Library is (c) 1998 Frank Warmerdam,
+and released under the following conditions. The intent is that anyone
+can do anything with the code, but that I do not assume any liability, nor
+express any warranty for this code. <p>
+
+As of Shapelib 1.2.6 the core portions of the library are made available
+under two possible licenses. The licensee can choose to use the code
+under either the Library GNU Public License (LGPL) described in
+LICENSE.LGPL or under the following MIT style license. Any files in
+the Shapelib distribution without explicit copyright license terms
+(such as this documentation, the Makefile and so forth) should be
+considered to have the following licensing terms. Some auxilary portions
+of Shapelib, notably some of the components in the contrib directory
+come under slightly different license restrictions. Check the source
+files that you are actually using for conditions.<p>
+
+<h3>Default License Terms</h3>
+
+<quote>
+Copyright (c) 1999, Frank Warmerdam<p>
+
+This software is available under the following "MIT Style" license,
+or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+option is discussed in more detail in shapelib.html.<p>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:<p>
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.<p>
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.<p>
+</quote>
+
+<h3>Shapelib Modifications</h3>
+
+I am pleased to receive bug fixes, and improvements for Shapelib. Unless
+the submissions indicate otherwise I will assume that changes submitted to
+me remain under the the above "dual license" terms. If changes are made
+to the library with the intention that those changes should be protected by
+the LGPL then I should be informed upon submission. Note that I will not
+generally incorporate changes into the core of Shapelib that are protected
+under the LGPL as this would effectively limit the whole file and
+distribution to LGPL terms.<p>
+
+<h3>Opting for LGPL</h3>
+
+For licensee's opting to use Shapelib under LGPL as opposed to the MIT
+Style license above, and wishing to redistribute the software based on
+Shapelib, I would ask that all "dual license" modules be updated to
+indicate that only the LGPL (and not the MIT Style license) applies. This
+action represents opting for the LGPL, and thereafter LGPL terms apply to
+any redistribution and modification of the affected modules.<p>
+
+</body>
+</html>
+
+
+
diff --git a/src/shapelib/shp_api.html b/src/shapelib/shp_api.html
new file mode 100644
index 0000000..d773e3e
--- /dev/null
+++ b/src/shapelib/shp_api.html
@@ -0,0 +1,376 @@
+<html>
+<head>
+<title>.SHP File API</title>
+</head>
+<body>
+
+<h1>.SHP File API</h1>
+
+The .SHP API uses a SHPHandle to represent an open .shp/.shx file pair.
+The contents of the SHPHandle are visible (see shapefile.h) but should
+be ignored by the application. It is intended that all information be
+accessed by the API functions. <p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>Shape Types</h2>
+
+Shapes have types associated with them. The following is a list of the
+different shapetypes supported by Shapefiles. At this time all shapes in
+a Shapefile must be of the same type (with the exception of NULL shapes). <p>
+
+<pre>
+ #define SHPT_NULL 0
+
+ 2D Shape Types (pre ArcView 3.x):
+
+ #define SHPT_POINT 1 Points
+ #define SHPT_ARC 3 Arcs (Polylines, possible in parts)
+ #define SHPT_POLYGON 5 Polygons (possible in parts)
+ #define SHPT_MULTIPOINT 8 MultiPoint (related points)
+
+ 3D Shape Types (may include "measure" values for vertices):
+
+ #define SHPT_POINTZ 11
+ #define SHPT_ARCZ 13
+ #define SHPT_POLYGONZ 15
+ #define SHPT_MULTIPOINTZ 18
+
+ 2D + Measure Types:
+
+ #define SHPT_POINTM 21
+ #define SHPT_ARCM 23
+ #define SHPT_POLYGONM 25
+ #define SHPT_MULTIPOINTM 28
+
+ Complex (TIN-like) with Z, and Measure:
+
+ #define SHPT_MULTIPATCH 31
+</pre>
+
+<!-------------------------------------------------------------------------->
+
+<h2>SHPObject</h2>
+
+An individual shape is represented by the SHPObject structure. SHPObject's
+created with SHPCreateObject(), SHPCreateSimpleObject(), or SHPReadObject()
+should be disposed of with SHPDestroyObject().<p>
+
+<pre>
+ typedef struct
+ {
+ int nSHPType; Shape Type (SHPT_* - see list above)
+
+ int nShapeId; Shape Number (-1 is unknown/unassigned)
+
+ int nParts; # of Parts (0 implies single part with no info)
+ int *panPartStart; Start Vertex of part
+ int *panPartType; Part Type (SHPP_RING if not SHPT_MULTIPATCH)
+
+ int nVertices; Vertex list
+ double *padfX;
+ double *padfY;
+ double *padfZ; (all zero if not provided)
+ double *padfM; (all zero if not provided)
+
+ double dfXMin; Bounds in X, Y, Z and M dimensions
+ double dfYMin;
+ double dfZMin;
+ double dfMMin;
+
+ double dfXMax;
+ double dfYMax;
+ double dfZMax;
+ double dfMMax;
+ } SHPObject;
+</pre>
+
+<!-------------------------------------------------------------------------->
+
+<h2>SHPOpen()</h2>
+
+<pre>
+SHPHandle SHPOpen( const char * pszShapeFile, const char * pszAccess );
+
+ pszShapeFile: The name of the layer to access. This can be the
+ name of either the .shp or the .shx file or can
+ just be the path plus the basename of the pair.
+
+ pszAccess: The fopen() style access string. At this time only
+ "rb" (read-only binary) and "rb+" (read/write binary)
+ should be used.
+</pre>
+
+ The SHPOpen() function should be used to establish access to the two files
+ for accessing vertices (.shp and .shx). Note that both files have to
+ be in the indicated directory, and must have the expected extensions in
+ lower case. The returned SHPHandle is passed to other access functions,
+ and SHPClose() should be invoked to recover resources, and flush changes
+ to disk when complete.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>SHPGetInfo()</h2>
+
+<pre>
+void SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
+ double * padfMinBound, double * padfMaxBound );
+
+ hSHP: The handle previously returned by SHPOpen()
+ or SHPCreate().
+
+ pnEntities: A pointer to an integer into which the number of
+ entities/structures should be placed. May be NULL.
+
+ pnShapetype: A pointer to an integer into which the shapetype
+ of this file should be placed. Shapefiles may contain
+ either SHPT_POINT, SHPT_ARC, SHPT_POLYGON or
+ SHPT_MULTIPOINT entities. This may be NULL.
+
+ padfMinBound: The X, Y, Z and M minimum values will be placed into
+ this four entry array. This may be NULL.
+
+ padfMaxBound: The X, Y, Z and M maximum values will be placed into
+ this four entry array. This may be NULL.
+</pre>
+
+ The SHPGetInfo() function retrieves various information about shapefile
+ as a whole. The bounds are read from the file header, and may be
+ inaccurate if the file was improperly generated. <p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>SHPReadObject()</h2>
+
+<pre>
+SHPObject *SHPReadObject( SHPHandle hSHP, int iShape );
+
+ hSHP: The handle previously returned by SHPOpen()
+ or SHPCreate().
+
+ iShape: The entity number of the shape to read. Entity
+ numbers are between 0 and nEntities-1 (as returned
+ by SHPGetInfo()).
+</pre>
+
+ The SHPReadObject() call is used to read a single structure, or entity
+ from the shapefile. See the definition of the SHPObject structure for
+ detailed information on fields of a SHPObject. SHPObject's returned from
+ SHPReadObject() should be deallocated with SHPDestroyShape().
+ SHPReadObject() will return NULL if an illegal iShape value is requested.<p>
+
+ Note that the bounds placed into the SHPObject are those read from the
+ file, and may not be correct. For points the bounds are generated from
+ the single point since bounds aren't normally provided for point types.<p>
+
+ Generally the shapes returned will be of the type of the file as a whole.
+ However, any file may also contain type SHPT_NULL shapes which will have
+ no geometry. Generally speaking applications should skip rather than
+ preserve them, as they usually represented interactively deleted shapes.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>SHPClose()</h2>
+
+<pre>
+void SHPClose( SHPHandle hSHP );
+
+ hSHP: The handle previously returned by SHPOpen()
+ or SHPCreate().
+</pre>
+
+ The SHPClose() function will close the .shp and .shx files, and flush
+ all outstanding header information to the files. It will also recover
+ resources associated with the handle. After this call the hSHP handle
+ cannot be used again.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>SHPCreate()</h2>
+
+<pre>
+SHPHandle SHPCreate( const char * pszShapeFile, int nShapeType );
+
+ pszShapeFile: The name of the layer to access. This can be the
+ name of either the .shp or the .shx file or can
+ just be the path plus the basename of the pair.
+
+ nShapeType: The type of shapes to be stored in the newly created
+ file. It may be either SHPT_POINT, SHPT_ARC,
+ SHPT_POLYGON or SHPT_MULTIPOINT.
+</pre>
+
+ The SHPCreate() function will create a new .shp and .shx file of the
+ desired type.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>SHPCreateSimpleObject()</h2>
+
+<pre>
+SHPObject *
+ SHPCreateSimpleObject( int nSHPType, int nVertices,
+ double *padfX, double * padfY, double *padfZ, );
+
+ nSHPType: The SHPT_ type of the object to be created, such
+ as SHPT_POINT, or SHPT_POLYGON.
+
+ nVertices: The number of vertices being passed in padfX,
+ padfY, and padfZ.
+
+ padfX: An array of nVertices X coordinates of the vertices
+ for this object.
+
+ padfY: An array of nVertices Y coordinates of the vertices
+ for this object.
+
+ padfZ: An array of nVertices Z coordinates of the vertices
+ for this object. This may be NULL in which case
+ they are all assumed to be zero.
+</pre>
+
+ The SHPCreateSimpleObject() allows for the convenient creation of
+ simple objects. This is normally used so that the SHPObject can be
+ passed to SHPWriteObject() to write it to the file. The simple object
+ creation API assumes an M (measure) value of zero for each vertex. For
+ complex objects (such as polygons) it is assumed that there is only one
+ part, and that it is of the default type (SHPP_RING). <p>
+
+ Use the SHPCreateObject() function for more sophisticated objects. The
+ SHPDestroyObject() function should be used to free resources associated with
+ an object allocated with SHPCreateSimpleObject(). <p>
+
+ This function computes a bounding box for the SHPObject from the given
+ vertices.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>SHPCreateObject()</h2>
+
+<pre>
+SHPObject *
+ SHPCreateObject( int nSHPType, int iShape,
+ int nParts, int * panPartStart, int * panPartType,
+ int nVertices, double *padfX, double * padfY,
+ double *padfZ, double *padfM );
+
+ nSHPType: The SHPT_ type of the object to be created, such
+ as SHPT_POINT, or SHPT_POLYGON.
+
+ iShape: The shapeid to be recorded with this shape.
+
+ nParts: The number of parts for this object. If this is
+ zero for ARC, or POLYGON type objects, a single
+ zero valued part will be created internally.
+
+ panPartStart: The list of zero based start vertices for the rings
+ (parts) in this object. The first should always be
+ zero. This may be NULL if nParts is 0.
+
+ panPartType: The type of each of the parts. This is only meaningful
+ for MULTIPATCH files. For all other cases this may
+ be NULL, and will be assumed to be SHPP_RING.
+
+ nVertices: The number of vertices being passed in padfX,
+ padfY, and padfZ.
+
+ padfX: An array of nVertices X coordinates of the vertices
+ for this object.
+
+ padfY: An array of nVertices Y coordinates of the vertices
+ for this object.
+
+ padfZ: An array of nVertices Z coordinates of the vertices
+ for this object. This may be NULL in which case
+ they are all assumed to be zero.
+
+ padfM: An array of nVertices M (measure values) of the
+ vertices for this object. This may be NULL in which
+ case they are all assumed to be zero.
+</pre>
+
+ The SHPCreateSimpleObject() allows for the creation of objects (shapes).
+ This is normally used so that the SHPObject can be passed to
+ SHPWriteObject() to write it to the file. <p>
+
+ The SHPDestroyObject() function should be used to free resources associated
+ with an object allocated with SHPCreateObject(). <p>
+
+ This function computes a bounding box for the SHPObject from the given
+ vertices.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>SHPComputeExtents()</h2>
+
+<pre>
+void SHPComputeExtents( SHPObject * psObject );
+
+ psObject: An existing shape object to be updated in place.
+</pre>
+
+ This function will recompute the extents of this shape, replacing the
+ existing values of the dfXMin, dfYMin, dfZMin, dfMMin, dfXMax, dfYMax,
+ dfZMax, and dfMMax values based on the current set of vertices for the
+ shape. This function is automatically called by SHPCreateObject() but
+ if the vertices of an existing object are altered it should be called again
+ to fix up the extents.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>SHPWriteObject()</h2>
+
+<pre>
+int SHPWriteObject( SHPHandle hSHP, int iShape, SHPObject *psObject );
+
+ hSHP: The handle previously returned by SHPOpen("r+")
+ or SHPCreate().
+
+ iShape: The entity number of the shape to write. A value of
+ -1 should be used for new shapes.
+
+ psObject: The shape to write to the file. This should have
+ been created with SHPCreateObject(), or
+ SHPCreateSimpleObject().
+</pre>
+
+ The SHPWriteObject() call is used to write a single structure, or entity
+ to the shapefile. See the definition of the SHPObject structure for
+ detailed information on fields of a SHPObject. The return value is the
+ entity number of the written shape. <p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>SHPDestroyObject()</h2>
+
+<pre>
+void SHPDestroyObject( SHPObject *psObject );
+
+ psObject: The object to deallocate.
+</pre>
+
+ This function should be used to deallocate the resources associated with
+ a SHPObject when it is no longer needed, including those created with
+ SHPCreateSimpleObject(), SHPCreateObject() and returned from SHPReadObject().
+ <p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>SHPRewindObject()</h2>
+
+<pre>
+int SHPRewindObject( SHPHandle hSHP, SHPObject *psObject );
+
+ hSHP: The shapefile (not used at this time).
+ psObject: The object to deallocate.
+</pre>
+
+ This function will reverse any rings necessary in order to enforce the
+ shapefile restrictions on the required order of inner and outer rings in
+ the Shapefile specification. It returns TRUE if a change is made and FALSE
+ if no change is made. Only polygon objects will be affected though any
+ object may be passed.
+ <p>
+
+</body>
+</html>
diff --git a/src/shapelib/shpadd.c b/src/shapelib/shpadd.c
new file mode 100644
index 0000000..f0009b3
--- /dev/null
+++ b/src/shapelib/shpadd.c
@@ -0,0 +1,197 @@
+/******************************************************************************
+ * $Id: shpadd.c,v 1.2 2009/06/04 04:25:19 we7u Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Sample application for adding a shape to a shapefile.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: shpadd.c,v $
+ * Revision 1.2 2009/06/04 04:25:19 we7u
+ * Getting rid of compiler warnings due to unused variable.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.13 2002/01/15 14:36:07 warmerda
+ * updated email address
+ *
+ * Revision 1.12 2001/05/31 19:35:29 warmerda
+ * added support for writing null shapes
+ *
+ * Revision 1.11 2000/07/07 13:39:45 warmerda
+ * removed unused variables, and added system include files
+ *
+ * Revision 1.10 2000/05/24 15:09:22 warmerda
+ * Added logic to graw vertex lists of needed.
+ *
+ * Revision 1.9 1999/11/05 14:12:04 warmerda
+ * updated license terms
+ *
+ * Revision 1.8 1998/12/03 16:36:26 warmerda
+ * Use r+b rather than rb+ for binary access.
+ *
+ * Revision 1.7 1998/11/09 20:57:04 warmerda
+ * Fixed SHPGetInfo() call.
+ *
+ * Revision 1.6 1998/11/09 20:19:16 warmerda
+ * Changed to use SHPObject based API.
+ *
+ * Revision 1.5 1997/03/06 14:05:02 warmerda
+ * fixed typo.
+ *
+ * Revision 1.4 1997/03/06 14:01:16 warmerda
+ * added memory allocation checking, and free()s.
+ *
+ * Revision 1.3 1995/10/21 03:14:37 warmerda
+ * Changed to use binary file access
+ *
+ * Revision 1.2 1995/08/04 03:18:01 warmerda
+ * Added header.
+ *
+ */
+
+//static char rcsid[] =
+// "$Id: shpadd.c,v 1.2 2009/06/04 04:25:19 we7u Exp $";
+
+#include <stdlib.h>
+#include <string.h>
+#include "shapefil.h"
+
+int main( int argc, char ** argv )
+
+{
+ SHPHandle hSHP;
+ int nShapeType, nVertices, nParts, *panParts, i, nVMax;
+ double *padfX, *padfY;
+ SHPObject *psObject;
+
+/* -------------------------------------------------------------------- */
+/* Display a usage message. */
+/* -------------------------------------------------------------------- */
+ if( argc < 2 )
+ {
+ printf( "shpadd shp_file [[x y] [+]]*\n" );
+ exit( 1 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Open the passed shapefile. */
+/* -------------------------------------------------------------------- */
+ hSHP = SHPOpen( argv[1], "r+b" );
+
+ if( hSHP == NULL )
+ {
+ printf( "Unable to open:%s\n", argv[1] );
+ exit( 1 );
+ }
+
+ SHPGetInfo( hSHP, NULL, &nShapeType, NULL, NULL );
+
+ if( argc == 2 )
+ nShapeType = SHPT_NULL;
+
+/* -------------------------------------------------------------------- */
+/* Build a vertex/part list from the command line arguments. */
+/* -------------------------------------------------------------------- */
+ nVMax = 1000;
+ padfX = (double *) malloc(sizeof(double) * nVMax);
+ padfY = (double *) malloc(sizeof(double) * nVMax);
+
+ nVertices = 0;
+
+ if( (panParts = (int *) malloc(sizeof(int) * 1000 )) == NULL )
+ {
+ printf( "Out of memory\n" );
+ exit( 1 );
+ }
+
+ nParts = 1;
+ panParts[0] = 0;
+
+ for( i = 2; i < argc; )
+ {
+ if( argv[i][0] == '+' )
+ {
+ panParts[nParts++] = nVertices;
+ i++;
+ }
+ else if( i < argc-1 )
+ {
+ if( nVertices == nVMax )
+ {
+ nVMax = nVMax * 2;
+ padfX = (double *) realloc(padfX,sizeof(double)*nVMax);
+ padfY = (double *) realloc(padfY,sizeof(double)*nVMax);
+ }
+
+ sscanf( argv[i], "%lg", padfX+nVertices );
+ sscanf( argv[i+1], "%lg", padfY+nVertices );
+ nVertices += 1;
+ i += 2;
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Write the new entity to the shape file. */
+/* -------------------------------------------------------------------- */
+ psObject = SHPCreateObject( nShapeType, -1, nParts, panParts, NULL,
+ nVertices, padfX, padfY, NULL, NULL );
+ SHPWriteObject( hSHP, -1, psObject );
+ SHPDestroyObject( psObject );
+
+ SHPClose( hSHP );
+
+ free( panParts );
+ free( padfX );
+ free( padfY );
+
+ return 0;
+}
diff --git a/src/shapelib/shpcreate.c b/src/shapelib/shpcreate.c
new file mode 100644
index 0000000..8ff617e
--- /dev/null
+++ b/src/shapelib/shpcreate.c
@@ -0,0 +1,138 @@
+/******************************************************************************
+ * $Id: shpcreate.c,v 1.4 2009/06/04 04:25:19 we7u Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Sample application for creating a new shapefile.
+ * Author: Frank Warmerdam, warmerdm at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: shpcreate.c,v $
+ * Revision 1.4 2009/06/04 04:25:19 we7u
+ * Getting rid of compiler warnings due to unused variable.
+ *
+ * Revision 1.3 2009/06/03 22:24:19 we7u
+ * Adding includes for string.h to get rid of compiler warnings.
+ *
+ * Revision 1.2 2007/07/25 15:37:50 we7u
+ * Added shprewind.c to the "clean" target of the original Makefile. Added
+ * stdlib.h includes to some of the utilities to get a clean compile.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.5 2002/01/15 14:36:07 warmerda
+ * updated email address
+ *
+ * Revision 1.4 2000/07/07 13:39:45 warmerda
+ * removed unused variables, and added system include files
+ *
+ * Revision 1.3 1999/11/05 14:12:04 warmerda
+ * updated license terms
+ *
+ * Revision 1.2 1995/08/04 03:16:43 warmerda
+ * Added header.
+ *
+ */
+
+//static char rcsid[] =
+// "$Id: shpcreate.c,v 1.4 2009/06/04 04:25:19 we7u Exp $";
+
+#include "shapefil.h"
+#include <stdlib.h>
+
+#include <string.h>
+
+int main( int argc, char ** argv )
+
+{
+ SHPHandle hSHP;
+ int nShapeType;
+
+/* -------------------------------------------------------------------- */
+/* Display a usage message. */
+/* -------------------------------------------------------------------- */
+ if( argc != 3 )
+ {
+ printf( "shpcreate shp_file [point/arc/polygon/multipoint]\n" );
+ exit( 1 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Figure out the shape type. */
+/* -------------------------------------------------------------------- */
+ if( strcmp(argv[2],"POINT") == 0 || strcmp(argv[2],"point") == 0 )
+ nShapeType = SHPT_POINT;
+ else if( strcmp(argv[2],"ARC") == 0 || strcmp(argv[2],"arc") == 0 )
+ nShapeType = SHPT_ARC;
+ else if( strcmp(argv[2],"POLYGON") == 0 || strcmp(argv[2],"polygon") == 0 )
+ nShapeType = SHPT_POLYGON;
+ else if( strcmp(argv[2],"MULTIPOINT")==0 ||strcmp(argv[2],"multipoint")==0)
+ nShapeType = SHPT_MULTIPOINT;
+ else
+ {
+ printf( "Shape Type `%s' not recognised.\n", argv[2] );
+ exit( 2 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Create the requested layer. */
+/* -------------------------------------------------------------------- */
+ hSHP = SHPCreate( argv[1], nShapeType );
+
+ if( hSHP == NULL )
+ {
+ printf( "Unable to create:%s\n", argv[1] );
+ exit( 3 );
+ }
+
+ SHPClose( hSHP );
+
+ return 0;
+}
diff --git a/src/shapelib/shpdump.c b/src/shapelib/shpdump.c
new file mode 100644
index 0000000..feec2d1
--- /dev/null
+++ b/src/shapelib/shpdump.c
@@ -0,0 +1,234 @@
+/******************************************************************************
+ * $Id: shpdump.c,v 1.4 2010/07/11 07:57:02 we7u Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Sample application for dumping contents of a shapefile to
+ * the terminal in human readable form.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: shpdump.c,v $
+ * Revision 1.4 2010/07/11 07:57:02 we7u
+ * Fixing a few more compiler warnings.
+ *
+ * Revision 1.3 2009/06/04 04:25:19 we7u
+ * Getting rid of compiler warnings due to unused variable.
+ *
+ * Revision 1.2 2007/07/25 15:37:50 we7u
+ * Added shprewind.c to the "clean" target of the original Makefile. Added
+ * stdlib.h includes to some of the utilities to get a clean compile.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.10 2002/04/10 16:59:29 warmerda
+ * added -validate switch
+ *
+ * Revision 1.9 2002/01/15 14:36:07 warmerda
+ * updated email address
+ *
+ * Revision 1.8 2000/07/07 13:39:45 warmerda
+ * removed unused variables, and added system include files
+ *
+ * Revision 1.7 1999/11/05 14:12:04 warmerda
+ * updated license terms
+ *
+ * Revision 1.6 1998/12/03 15:48:48 warmerda
+ * Added report of shapefile type, and total number of shapes.
+ *
+ * Revision 1.5 1998/11/09 20:57:36 warmerda
+ * use SHPObject.
+ *
+ * Revision 1.4 1995/10/21 03:14:49 warmerda
+ * Changed to use binary file access.
+ *
+ * Revision 1.3 1995/08/23 02:25:25 warmerda
+ * Added support for bounds.
+ *
+ * Revision 1.2 1995/08/04 03:18:11 warmerda
+ * Added header.
+ *
+ */
+
+//static char rcsid[] =
+// "$Id: shpdump.c,v 1.4 2010/07/11 07:57:02 we7u Exp $";
+
+#include "shapefil.h"
+#include <stdlib.h>
+#include <string.h>
+
+int main( int argc, char ** argv )
+
+{
+ SHPHandle hSHP;
+ int nShapeType, nEntities, i, iPart, bValidate = 0,nInvalidCount=0;
+ const char *pszPlus;
+ double adfMinBound[4], adfMaxBound[4];
+
+ if( argc > 1 && strcmp(argv[1],"-validate") == 0 )
+ {
+ bValidate = 1;
+ argv++;
+ argc--;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Display a usage message. */
+/* -------------------------------------------------------------------- */
+ if( argc != 2 )
+ {
+ printf( "shpdump [-validate] shp_file\n" );
+ exit( 1 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Open the passed shapefile. */
+/* -------------------------------------------------------------------- */
+ hSHP = SHPOpen( argv[1], "rb" );
+
+ if( hSHP == NULL )
+ {
+ printf( "Unable to open:%s\n", argv[1] );
+ exit( 1 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Print out the file bounds. */
+/* -------------------------------------------------------------------- */
+ SHPGetInfo( hSHP, &nEntities, &nShapeType, adfMinBound, adfMaxBound );
+
+ printf( "Shapefile Type: %s # of Shapes: %d\n\n",
+ SHPTypeName( nShapeType ), nEntities );
+
+ printf( "File Bounds: (%12.3f,%12.3f,%g,%g)\n"
+ " to (%12.3f,%12.3f,%g,%g)\n",
+ adfMinBound[0],
+ adfMinBound[1],
+ adfMinBound[2],
+ adfMinBound[3],
+ adfMaxBound[0],
+ adfMaxBound[1],
+ adfMaxBound[2],
+ adfMaxBound[3] );
+
+/* -------------------------------------------------------------------- */
+/* Skim over the list of shapes, printing all the vertices. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < nEntities; i++ )
+ {
+ int j;
+ SHPObject *psShape;
+
+ psShape = SHPReadObject( hSHP, i );
+
+ printf( "\nShape:%d (%s) nVertices=%d, nParts=%d\n"
+ " Bounds:(%12.3f,%12.3f, %g, %g)\n"
+ " to (%12.3f,%12.3f, %g, %g)\n",
+ i, SHPTypeName(psShape->nSHPType),
+ psShape->nVertices, psShape->nParts,
+ psShape->dfXMin, psShape->dfYMin,
+ psShape->dfZMin, psShape->dfMMin,
+ psShape->dfXMax, psShape->dfYMax,
+ psShape->dfZMax, psShape->dfMMax );
+
+ for( j = 0, iPart = 1; j < psShape->nVertices; j++ )
+ {
+ const char *pszPartType = "";
+
+ if( j == 0 && psShape->nParts > 0 )
+ pszPartType = SHPPartTypeName( psShape->panPartType[0] );
+
+ if( iPart < psShape->nParts
+ && psShape->panPartStart[iPart] == j )
+ {
+ pszPartType = SHPPartTypeName( psShape->panPartType[iPart] );
+ iPart++;
+ pszPlus = "+";
+ }
+ else
+ pszPlus = " ";
+
+ printf(" %s (%12.3f,%12.3f, %g, %g) %s \n",
+ pszPlus,
+ psShape->padfX[j],
+ psShape->padfY[j],
+ psShape->padfZ[j],
+ psShape->padfM[j],
+ pszPartType );
+ }
+
+ if( bValidate )
+ {
+ int nAltered = SHPRewindObject( hSHP, psShape );
+
+ if( nAltered > 0 )
+ {
+ printf( " %d rings wound in the wrong direction.\n",
+ nAltered );
+ nInvalidCount++;
+ }
+ }
+
+ SHPDestroyObject( psShape );
+ }
+
+ SHPClose( hSHP );
+
+ if( bValidate )
+ {
+ printf( "%d object has invalid ring orderings.\n", nInvalidCount );
+ }
+
+#ifdef USE_DBMALLOC
+ malloc_dump(2);
+#endif
+
+ exit( 0 );
+}
diff --git a/src/shapelib/shpopen.c b/src/shapelib/shpopen.c
new file mode 100644
index 0000000..95322de
--- /dev/null
+++ b/src/shapelib/shpopen.c
@@ -0,0 +1,1892 @@
+/******************************************************************************
+ * $Id: shpopen.c,v 1.2 2006/11/14 21:28:48 we7u Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Implementation of core Shapefile read/write functions.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, 2001, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: shpopen.c,v $
+ * Revision 1.2 2006/11/14 21:28:48 we7u
+ * Commenting out some variables that give off compiler warnings.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.39 2002/08/26 06:46:56 warmerda
+ * avoid c++ comments
+ *
+ * Revision 1.38 2002/05/07 16:43:39 warmerda
+ * Removed debugging printf.
+ *
+ * Revision 1.37 2002/04/10 17:35:22 warmerda
+ * fixed bug in ring reversal code
+ *
+ * Revision 1.36 2002/04/10 16:59:54 warmerda
+ * added SHPRewindObject
+ *
+ * Revision 1.35 2001/12/07 15:10:44 warmerda
+ * fix if .shx fails to open
+ *
+ * Revision 1.34 2001/11/01 16:29:55 warmerda
+ * move pabyRec into SHPInfo for thread safety
+ *
+ * Revision 1.33 2001/07/03 12:18:15 warmerda
+ * Improved cleanup if SHX not found, provied by Riccardo Cohen.
+ *
+ * Revision 1.32 2001/06/22 01:58:07 warmerda
+ * be more careful about establishing initial bounds in face of NULL shapes
+ *
+ * Revision 1.31 2001/05/31 19:35:29 warmerda
+ * added support for writing null shapes
+ *
+ * Revision 1.30 2001/05/28 12:46:29 warmerda
+ * Add some checking on reasonableness of record count when opening.
+ *
+ * Revision 1.29 2001/05/23 13:36:52 warmerda
+ * added use of SHPAPI_CALL
+ *
+ * Revision 1.28 2001/02/06 22:25:06 warmerda
+ * fixed memory leaks when SHPOpen() fails
+ *
+ * Revision 1.27 2000/07/18 15:21:33 warmerda
+ * added better enforcement of -1 for append in SHPWriteObject
+ *
+ * Revision 1.26 2000/02/16 16:03:51 warmerda
+ * added null shape support
+ *
+ * Revision 1.25 1999/12/15 13:47:07 warmerda
+ * Fixed record size settings in .shp file (was 4 words too long)
+ * Added stdlib.h.
+ *
+ * Revision 1.24 1999/11/05 14:12:04 warmerda
+ * updated license terms
+ *
+ * Revision 1.23 1999/07/27 00:53:46 warmerda
+ * added support for rewriting shapes
+ *
+ * Revision 1.22 1999/06/11 19:19:11 warmerda
+ * Cleanup pabyRec static buffer on SHPClose().
+ *
+ * Revision 1.21 1999/06/02 14:57:56 kshih
+ * Remove unused variables
+ *
+ * Revision 1.20 1999/04/19 21:04:17 warmerda
+ * Fixed syntax error.
+ *
+ * Revision 1.19 1999/04/19 21:01:57 warmerda
+ * Force access string to binary in SHPOpen().
+ *
+ * Revision 1.18 1999/04/01 18:48:07 warmerda
+ * Try upper case extensions if lower case doesn't work.
+ *
+ * Revision 1.17 1998/12/31 15:29:39 warmerda
+ * Disable writing measure values to multipatch objects if
+ * DISABLE_MULTIPATCH_MEASURE is defined.
+ *
+ * Revision 1.16 1998/12/16 05:14:33 warmerda
+ * Added support to write MULTIPATCH. Fixed reading Z coordinate of
+ * MULTIPATCH. Fixed record size written for all feature types.
+ *
+ * Revision 1.15 1998/12/03 16:35:29 warmerda
+ * r+b is proper binary access string, not rb+.
+ *
+ * Revision 1.14 1998/12/03 15:47:56 warmerda
+ * Fixed setting of nVertices in SHPCreateObject().
+ *
+ * Revision 1.13 1998/12/03 15:33:54 warmerda
+ * Made SHPCalculateExtents() separately callable.
+ *
+ * Revision 1.12 1998/11/11 20:01:50 warmerda
+ * Fixed bug writing ArcM/Z, and PolygonM/Z for big endian machines.
+ *
+ * Revision 1.11 1998/11/09 20:56:44 warmerda
+ * Fixed up handling of file wide bounds.
+ *
+ * Revision 1.10 1998/11/09 20:18:51 warmerda
+ * Converted to support 3D shapefiles, and use of SHPObject.
+ *
+ * Revision 1.9 1998/02/24 15:09:05 warmerda
+ * Fixed memory leak.
+ *
+ * Revision 1.8 1997/12/04 15:40:29 warmerda
+ * Fixed byte swapping of record number, and record length fields in the
+ * .shp file.
+ *
+ * Revision 1.7 1995/10/21 03:15:58 warmerda
+ * Added support for binary file access, the magic cookie 9997
+ * and tried to improve the int32 selection logic for 16bit systems.
+ *
+ * Revision 1.6 1995/09/04 04:19:41 warmerda
+ * Added fix for file bounds.
+ *
+ * Revision 1.5 1995/08/25 15:16:44 warmerda
+ * Fixed a couple of problems with big endian systems ... one with bounds
+ * and the other with multipart polygons.
+ *
+ * Revision 1.4 1995/08/24 18:10:17 warmerda
+ * Switch to use SfRealloc() to avoid problems with pre-ANSI realloc()
+ * functions (such as on the Sun).
+ *
+ * Revision 1.3 1995/08/23 02:23:15 warmerda
+ * Added support for reading bounds, and fixed up problems in setting the
+ * file wide bounds.
+ *
+ * Revision 1.2 1995/08/04 03:16:57 warmerda
+ * Added header.
+ *
+ */
+
+//static char rcsid[] =
+// "$Id: shpopen.c,v 1.2 2006/11/14 21:28:48 we7u Exp $";
+
+#include "shapefil.h"
+
+#include <math.h>
+#include <limits.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef unsigned char uchar;
+
+#if UINT_MAX == 65535
+typedef long int32;
+#else
+typedef int int32;
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+# define TRUE 1
+#endif
+
+#define ByteCopy( a, b, c ) memcpy( b, a, c )
+#ifndef MAX
+# define MIN(a,b) ((a<b) ? a : b)
+# define MAX(a,b) ((a>b) ? a : b)
+#endif
+
+static int bBigEndian;
+
+
+/************************************************************************/
+/* SwapWord() */
+/* */
+/* Swap a 2, 4 or 8 byte word. */
+/************************************************************************/
+
+static void SwapWord( int length, void * wordP )
+
+{
+ int i;
+ uchar temp;
+
+ for( i=0; i < length/2; i++ )
+ {
+ temp = ((uchar *) wordP)[i];
+ ((uchar *)wordP)[i] = ((uchar *) wordP)[length-i-1];
+ ((uchar *) wordP)[length-i-1] = temp;
+ }
+}
+
+/************************************************************************/
+/* SfRealloc() */
+/* */
+/* A realloc cover function that will access a NULL pointer as */
+/* a valid input. */
+/************************************************************************/
+
+static void * SfRealloc( void * pMem, int nNewSize )
+
+{
+ if( pMem == NULL )
+ return( (void *) malloc(nNewSize) );
+ else
+ return( (void *) realloc(pMem,nNewSize) );
+}
+
+/************************************************************************/
+/* SHPWriteHeader() */
+/* */
+/* Write out a header for the .shp and .shx files as well as the */
+/* contents of the index (.shx) file. */
+/************************************************************************/
+
+static void SHPWriteHeader( SHPHandle psSHP )
+
+{
+ uchar abyHeader[100];
+ int i;
+ int32 i32;
+ double dValue;
+ int32 *panSHX;
+
+/* -------------------------------------------------------------------- */
+/* Prepare header block for .shp file. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < 100; i++ )
+ abyHeader[i] = 0;
+
+ abyHeader[2] = 0x27; /* magic cookie */
+ abyHeader[3] = 0x0a;
+
+ i32 = psSHP->nFileSize/2; /* file size */
+ ByteCopy( &i32, abyHeader+24, 4 );
+ if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+
+ i32 = 1000; /* version */
+ ByteCopy( &i32, abyHeader+28, 4 );
+ if( bBigEndian ) SwapWord( 4, abyHeader+28 );
+
+ i32 = psSHP->nShapeType; /* shape type */
+ ByteCopy( &i32, abyHeader+32, 4 );
+ if( bBigEndian ) SwapWord( 4, abyHeader+32 );
+
+ dValue = psSHP->adBoundsMin[0]; /* set bounds */
+ ByteCopy( &dValue, abyHeader+36, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+36 );
+
+ dValue = psSHP->adBoundsMin[1];
+ ByteCopy( &dValue, abyHeader+44, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+44 );
+
+ dValue = psSHP->adBoundsMax[0];
+ ByteCopy( &dValue, abyHeader+52, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+52 );
+
+ dValue = psSHP->adBoundsMax[1];
+ ByteCopy( &dValue, abyHeader+60, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+60 );
+
+ dValue = psSHP->adBoundsMin[2]; /* z */
+ ByteCopy( &dValue, abyHeader+68, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+68 );
+
+ dValue = psSHP->adBoundsMax[2];
+ ByteCopy( &dValue, abyHeader+76, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+76 );
+
+ dValue = psSHP->adBoundsMin[3]; /* m */
+ ByteCopy( &dValue, abyHeader+84, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+84 );
+
+ dValue = psSHP->adBoundsMax[3];
+ ByteCopy( &dValue, abyHeader+92, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+92 );
+
+/* -------------------------------------------------------------------- */
+/* Write .shp file header. */
+/* -------------------------------------------------------------------- */
+ fseek( psSHP->fpSHP, 0, 0 );
+ fwrite( abyHeader, 100, 1, psSHP->fpSHP );
+
+/* -------------------------------------------------------------------- */
+/* Prepare, and write .shx file header. */
+/* -------------------------------------------------------------------- */
+ i32 = (psSHP->nRecords * 2 * sizeof(int32) + 100)/2; /* file size */
+ ByteCopy( &i32, abyHeader+24, 4 );
+ if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+
+ fseek( psSHP->fpSHX, 0, 0 );
+ fwrite( abyHeader, 100, 1, psSHP->fpSHX );
+
+/* -------------------------------------------------------------------- */
+/* Write out the .shx contents. */
+/* -------------------------------------------------------------------- */
+ panSHX = (int32 *) malloc(sizeof(int32) * 2 * psSHP->nRecords);
+
+ for( i = 0; i < psSHP->nRecords; i++ )
+ {
+ panSHX[i*2 ] = psSHP->panRecOffset[i]/2;
+ panSHX[i*2+1] = psSHP->panRecSize[i]/2;
+ if( !bBigEndian ) SwapWord( 4, panSHX+i*2 );
+ if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 );
+ }
+
+ fwrite( panSHX, sizeof(int32) * 2, psSHP->nRecords, psSHP->fpSHX );
+
+ free( panSHX );
+}
+
+/************************************************************************/
+/* SHPOpen() */
+/* */
+/* Open the .shp and .shx files based on the basename of the */
+/* files or either file name. */
+/************************************************************************/
+
+SHPHandle SHPAPI_CALL
+SHPOpen( const char * pszLayer, const char * pszAccess )
+
+{
+ char *pszFullname, *pszBasename;
+ SHPHandle psSHP;
+
+ uchar *pabyBuf;
+ int i;
+ double dValue;
+
+/* -------------------------------------------------------------------- */
+/* Ensure the access string is one of the legal ones. We */
+/* ensure the result string indicates binary to avoid common */
+/* problems on Windows. */
+/* -------------------------------------------------------------------- */
+ if( strcmp(pszAccess,"rb+") == 0 || strcmp(pszAccess,"r+b") == 0
+ || strcmp(pszAccess,"r+") == 0 )
+ pszAccess = "r+b";
+ else
+ pszAccess = "rb";
+
+/* -------------------------------------------------------------------- */
+/* Establish the byte order on this machine. */
+/* -------------------------------------------------------------------- */
+ i = 1;
+ if( *((uchar *) &i) == 1 )
+ bBigEndian = FALSE;
+ else
+ bBigEndian = TRUE;
+
+/* -------------------------------------------------------------------- */
+/* Initialize the info structure. */
+/* -------------------------------------------------------------------- */
+ psSHP = (SHPHandle) calloc(sizeof(SHPInfo),1);
+
+ psSHP->bUpdated = FALSE;
+
+/* -------------------------------------------------------------------- */
+/* Compute the base (layer) name. If there is any extension */
+/* on the passed in filename we will strip it off. */
+/* -------------------------------------------------------------------- */
+ pszBasename = (char *) malloc(strlen(pszLayer)+5);
+ strcpy( pszBasename, pszLayer );
+ for( i = strlen(pszBasename)-1;
+ i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+ && pszBasename[i] != '\\';
+ i-- ) {}
+
+ if( pszBasename[i] == '.' )
+ pszBasename[i] = '\0';
+
+/* -------------------------------------------------------------------- */
+/* Open the .shp and .shx files. Note that files pulled from */
+/* a PC to Unix with upper case filenames won't work! */
+/* -------------------------------------------------------------------- */
+ pszFullname = (char *) malloc(strlen(pszBasename) + 5);
+ sprintf( pszFullname, "%s.shp", pszBasename );
+ psSHP->fpSHP = fopen(pszFullname, pszAccess );
+ if( psSHP->fpSHP == NULL )
+ {
+ sprintf( pszFullname, "%s.SHP", pszBasename );
+ psSHP->fpSHP = fopen(pszFullname, pszAccess );
+ }
+
+ if( psSHP->fpSHP == NULL )
+ {
+ free( psSHP );
+ free( pszBasename );
+ free( pszFullname );
+ return( NULL );
+ }
+
+ sprintf( pszFullname, "%s.shx", pszBasename );
+ psSHP->fpSHX = fopen(pszFullname, pszAccess );
+ if( psSHP->fpSHX == NULL )
+ {
+ sprintf( pszFullname, "%s.SHX", pszBasename );
+ psSHP->fpSHX = fopen(pszFullname, pszAccess );
+ }
+
+ if( psSHP->fpSHX == NULL )
+ {
+ fclose( psSHP->fpSHP );
+ free( psSHP );
+ free( pszBasename );
+ free( pszFullname );
+ return( NULL );
+ }
+
+ free( pszFullname );
+ free( pszBasename );
+
+/* -------------------------------------------------------------------- */
+/* Read the file size from the SHP file. */
+/* -------------------------------------------------------------------- */
+ pabyBuf = (uchar *) malloc(100);
+ fread( pabyBuf, 100, 1, psSHP->fpSHP );
+
+ psSHP->nFileSize = (pabyBuf[24] * 256 * 256 * 256
+ + pabyBuf[25] * 256 * 256
+ + pabyBuf[26] * 256
+ + pabyBuf[27]) * 2;
+
+/* -------------------------------------------------------------------- */
+/* Read SHX file Header info */
+/* -------------------------------------------------------------------- */
+ fread( pabyBuf, 100, 1, psSHP->fpSHX );
+
+ if( pabyBuf[0] != 0
+ || pabyBuf[1] != 0
+ || pabyBuf[2] != 0x27
+ || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
+ {
+ fclose( psSHP->fpSHP );
+ fclose( psSHP->fpSHX );
+ free( psSHP );
+
+ return( NULL );
+ }
+
+ psSHP->nRecords = pabyBuf[27] + pabyBuf[26] * 256
+ + pabyBuf[25] * 256 * 256 + pabyBuf[24] * 256 * 256 * 256;
+ psSHP->nRecords = (psSHP->nRecords*2 - 100) / 8;
+
+ psSHP->nShapeType = pabyBuf[32];
+
+ if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 )
+ {
+ /* this header appears to be corrupt. Give up. */
+ fclose( psSHP->fpSHP );
+ fclose( psSHP->fpSHX );
+ free( psSHP );
+
+ return( NULL );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Read the bounds. */
+/* -------------------------------------------------------------------- */
+ if( bBigEndian ) SwapWord( 8, pabyBuf+36 );
+ memcpy( &dValue, pabyBuf+36, 8 );
+ psSHP->adBoundsMin[0] = dValue;
+
+ if( bBigEndian ) SwapWord( 8, pabyBuf+44 );
+ memcpy( &dValue, pabyBuf+44, 8 );
+ psSHP->adBoundsMin[1] = dValue;
+
+ if( bBigEndian ) SwapWord( 8, pabyBuf+52 );
+ memcpy( &dValue, pabyBuf+52, 8 );
+ psSHP->adBoundsMax[0] = dValue;
+
+ if( bBigEndian ) SwapWord( 8, pabyBuf+60 );
+ memcpy( &dValue, pabyBuf+60, 8 );
+ psSHP->adBoundsMax[1] = dValue;
+
+ if( bBigEndian ) SwapWord( 8, pabyBuf+68 ); /* z */
+ memcpy( &dValue, pabyBuf+68, 8 );
+ psSHP->adBoundsMin[2] = dValue;
+
+ if( bBigEndian ) SwapWord( 8, pabyBuf+76 );
+ memcpy( &dValue, pabyBuf+76, 8 );
+ psSHP->adBoundsMax[2] = dValue;
+
+ if( bBigEndian ) SwapWord( 8, pabyBuf+84 ); /* z */
+ memcpy( &dValue, pabyBuf+84, 8 );
+ psSHP->adBoundsMin[3] = dValue;
+
+ if( bBigEndian ) SwapWord( 8, pabyBuf+92 );
+ memcpy( &dValue, pabyBuf+92, 8 );
+ psSHP->adBoundsMax[3] = dValue;
+
+ free( pabyBuf );
+
+/* -------------------------------------------------------------------- */
+/* Read the .shx file to get the offsets to each record in */
+/* the .shp file. */
+/* -------------------------------------------------------------------- */
+ psSHP->nMaxRecords = psSHP->nRecords;
+
+ psSHP->panRecOffset =
+ (int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
+ psSHP->panRecSize =
+ (int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
+
+ pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) );
+ fread( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX );
+
+ for( i = 0; i < psSHP->nRecords; i++ )
+ {
+ int32 nOffset, nLength;
+
+ memcpy( &nOffset, pabyBuf + i * 8, 4 );
+ if( !bBigEndian ) SwapWord( 4, &nOffset );
+
+ memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
+ if( !bBigEndian ) SwapWord( 4, &nLength );
+
+ psSHP->panRecOffset[i] = nOffset*2;
+ psSHP->panRecSize[i] = nLength*2;
+ }
+ free( pabyBuf );
+
+ return( psSHP );
+}
+
+/************************************************************************/
+/* SHPClose() */
+/* */
+/* Close the .shp and .shx files. */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPClose(SHPHandle psSHP )
+
+{
+/* -------------------------------------------------------------------- */
+/* Update the header if we have modified anything. */
+/* -------------------------------------------------------------------- */
+ if( psSHP->bUpdated )
+ {
+ SHPWriteHeader( psSHP );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Free all resources, and close files. */
+/* -------------------------------------------------------------------- */
+ free( psSHP->panRecOffset );
+ free( psSHP->panRecSize );
+
+ fclose( psSHP->fpSHX );
+ fclose( psSHP->fpSHP );
+
+ if( psSHP->pabyRec != NULL )
+ {
+ free( psSHP->pabyRec );
+ }
+
+ free( psSHP );
+}
+
+/************************************************************************/
+/* SHPGetInfo() */
+/* */
+/* Fetch general information about the shape file. */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
+ double * padfMinBound, double * padfMaxBound )
+
+{
+ int i;
+
+ if( pnEntities != NULL )
+ *pnEntities = psSHP->nRecords;
+
+ if( pnShapeType != NULL )
+ *pnShapeType = psSHP->nShapeType;
+
+ for( i = 0; i < 4; i++ )
+ {
+ if( padfMinBound != NULL )
+ padfMinBound[i] = psSHP->adBoundsMin[i];
+ if( padfMaxBound != NULL )
+ padfMaxBound[i] = psSHP->adBoundsMax[i];
+ }
+}
+
+/************************************************************************/
+/* SHPCreate() */
+/* */
+/* Create a new shape file and return a handle to the open */
+/* shape file with read/write access. */
+/************************************************************************/
+
+SHPHandle SHPAPI_CALL
+SHPCreate( const char * pszLayer, int nShapeType )
+
+{
+ char *pszBasename, *pszFullname;
+ int i;
+ FILE *fpSHP, *fpSHX;
+ uchar abyHeader[100];
+ int32 i32;
+ double dValue;
+
+/* -------------------------------------------------------------------- */
+/* Establish the byte order on this system. */
+/* -------------------------------------------------------------------- */
+ i = 1;
+ if( *((uchar *) &i) == 1 )
+ bBigEndian = FALSE;
+ else
+ bBigEndian = TRUE;
+
+/* -------------------------------------------------------------------- */
+/* Compute the base (layer) name. If there is any extension */
+/* on the passed in filename we will strip it off. */
+/* -------------------------------------------------------------------- */
+ pszBasename = (char *) malloc(strlen(pszLayer)+5);
+ strcpy( pszBasename, pszLayer );
+ for( i = strlen(pszBasename)-1;
+ i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+ && pszBasename[i] != '\\';
+ i-- ) {}
+
+ if( pszBasename[i] == '.' )
+ pszBasename[i] = '\0';
+
+/* -------------------------------------------------------------------- */
+/* Open the two files so we can write their headers. */
+/* -------------------------------------------------------------------- */
+ pszFullname = (char *) malloc(strlen(pszBasename) + 5);
+ sprintf( pszFullname, "%s.shp", pszBasename );
+ fpSHP = fopen(pszFullname, "wb" );
+ if( fpSHP == NULL )
+ return( NULL );
+
+ sprintf( pszFullname, "%s.shx", pszBasename );
+ fpSHX = fopen(pszFullname, "wb" );
+ if( fpSHX == NULL )
+ return( NULL );
+
+ free( pszFullname );
+ free( pszBasename );
+
+/* -------------------------------------------------------------------- */
+/* Prepare header block for .shp file. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < 100; i++ )
+ abyHeader[i] = 0;
+
+ abyHeader[2] = 0x27; /* magic cookie */
+ abyHeader[3] = 0x0a;
+
+ i32 = 50; /* file size */
+ ByteCopy( &i32, abyHeader+24, 4 );
+ if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+
+ i32 = 1000; /* version */
+ ByteCopy( &i32, abyHeader+28, 4 );
+ if( bBigEndian ) SwapWord( 4, abyHeader+28 );
+
+ i32 = nShapeType; /* shape type */
+ ByteCopy( &i32, abyHeader+32, 4 );
+ if( bBigEndian ) SwapWord( 4, abyHeader+32 );
+
+ dValue = 0.0; /* set bounds */
+ ByteCopy( &dValue, abyHeader+36, 8 );
+ ByteCopy( &dValue, abyHeader+44, 8 );
+ ByteCopy( &dValue, abyHeader+52, 8 );
+ ByteCopy( &dValue, abyHeader+60, 8 );
+
+/* -------------------------------------------------------------------- */
+/* Write .shp file header. */
+/* -------------------------------------------------------------------- */
+ fwrite( abyHeader, 100, 1, fpSHP );
+
+/* -------------------------------------------------------------------- */
+/* Prepare, and write .shx file header. */
+/* -------------------------------------------------------------------- */
+ i32 = 50; /* file size */
+ ByteCopy( &i32, abyHeader+24, 4 );
+ if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+
+ fwrite( abyHeader, 100, 1, fpSHX );
+
+/* -------------------------------------------------------------------- */
+/* Close the files, and then open them as regular existing files. */
+/* -------------------------------------------------------------------- */
+ fclose( fpSHP );
+ fclose( fpSHX );
+
+ return( SHPOpen( pszLayer, "r+b" ) );
+}
+
+/************************************************************************/
+/* _SHPSetBounds() */
+/* */
+/* Compute a bounds rectangle for a shape, and set it into the */
+/* indicated location in the record. */
+/************************************************************************/
+
+static void _SHPSetBounds( uchar * pabyRec, SHPObject * psShape )
+
+{
+ ByteCopy( &(psShape->dfXMin), pabyRec + 0, 8 );
+ ByteCopy( &(psShape->dfYMin), pabyRec + 8, 8 );
+ ByteCopy( &(psShape->dfXMax), pabyRec + 16, 8 );
+ ByteCopy( &(psShape->dfYMax), pabyRec + 24, 8 );
+
+ if( bBigEndian )
+ {
+ SwapWord( 8, pabyRec + 0 );
+ SwapWord( 8, pabyRec + 8 );
+ SwapWord( 8, pabyRec + 16 );
+ SwapWord( 8, pabyRec + 24 );
+ }
+}
+
+/************************************************************************/
+/* SHPComputeExtents() */
+/* */
+/* Recompute the extents of a shape. Automatically done by */
+/* SHPCreateObject(). */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPComputeExtents( SHPObject * psObject )
+
+{
+ int i;
+
+/* -------------------------------------------------------------------- */
+/* Build extents for this object. */
+/* -------------------------------------------------------------------- */
+ if( psObject->nVertices > 0 )
+ {
+ psObject->dfXMin = psObject->dfXMax = psObject->padfX[0];
+ psObject->dfYMin = psObject->dfYMax = psObject->padfY[0];
+ psObject->dfZMin = psObject->dfZMax = psObject->padfZ[0];
+ psObject->dfMMin = psObject->dfMMax = psObject->padfM[0];
+ }
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ psObject->dfXMin = MIN(psObject->dfXMin, psObject->padfX[i]);
+ psObject->dfYMin = MIN(psObject->dfYMin, psObject->padfY[i]);
+ psObject->dfZMin = MIN(psObject->dfZMin, psObject->padfZ[i]);
+ psObject->dfMMin = MIN(psObject->dfMMin, psObject->padfM[i]);
+
+ psObject->dfXMax = MAX(psObject->dfXMax, psObject->padfX[i]);
+ psObject->dfYMax = MAX(psObject->dfYMax, psObject->padfY[i]);
+ psObject->dfZMax = MAX(psObject->dfZMax, psObject->padfZ[i]);
+ psObject->dfMMax = MAX(psObject->dfMMax, psObject->padfM[i]);
+ }
+}
+
+/************************************************************************/
+/* SHPCreateObject() */
+/* */
+/* Create a shape object. It should be freed with */
+/* SHPDestroyObject(). */
+/************************************************************************/
+
+SHPObject SHPAPI_CALL1(*)
+SHPCreateObject( int nSHPType, int nShapeId, int nParts,
+ int * panPartStart, int * panPartType,
+ int nVertices, double * padfX, double * padfY,
+ double * padfZ, double * padfM )
+
+{
+ SHPObject *psObject;
+ int i, bHasM, bHasZ;
+
+ psObject = (SHPObject *) calloc(1,sizeof(SHPObject));
+ psObject->nSHPType = nSHPType;
+ psObject->nShapeId = nShapeId;
+
+/* -------------------------------------------------------------------- */
+/* Establish whether this shape type has M, and Z values. */
+/* -------------------------------------------------------------------- */
+ if( nSHPType == SHPT_ARCM
+ || nSHPType == SHPT_POINTM
+ || nSHPType == SHPT_POLYGONM
+ || nSHPType == SHPT_MULTIPOINTM )
+ {
+ bHasM = TRUE;
+ bHasZ = FALSE;
+ }
+ else if( nSHPType == SHPT_ARCZ
+ || nSHPType == SHPT_POINTZ
+ || nSHPType == SHPT_POLYGONZ
+ || nSHPType == SHPT_MULTIPOINTZ
+ || nSHPType == SHPT_MULTIPATCH )
+ {
+ bHasM = TRUE;
+ bHasZ = TRUE;
+ }
+ else
+ {
+ bHasM = FALSE;
+ bHasZ = FALSE;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Capture parts. Note that part type is optional, and */
+/* defaults to ring. */
+/* -------------------------------------------------------------------- */
+ if( nSHPType == SHPT_ARC || nSHPType == SHPT_POLYGON
+ || nSHPType == SHPT_ARCM || nSHPType == SHPT_POLYGONM
+ || nSHPType == SHPT_ARCZ || nSHPType == SHPT_POLYGONZ
+ || nSHPType == SHPT_MULTIPATCH )
+ {
+ psObject->nParts = MAX(1,nParts);
+
+ psObject->panPartStart = (int *)
+ malloc(sizeof(int) * psObject->nParts);
+ psObject->panPartType = (int *)
+ malloc(sizeof(int) * psObject->nParts);
+
+ psObject->panPartStart[0] = 0;
+ psObject->panPartType[0] = SHPP_RING;
+
+ for( i = 0; i < nParts; i++ )
+ {
+ psObject->panPartStart[i] = panPartStart[i];
+ if( panPartType != NULL )
+ psObject->panPartType[i] = panPartType[i];
+ else
+ psObject->panPartType[i] = SHPP_RING;
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Capture vertices. Note that Z and M are optional, but X and */
+/* Y are not. */
+/* -------------------------------------------------------------------- */
+ if( nVertices > 0 )
+ {
+ psObject->padfX = (double *) calloc(sizeof(double),nVertices);
+ psObject->padfY = (double *) calloc(sizeof(double),nVertices);
+ psObject->padfZ = (double *) calloc(sizeof(double),nVertices);
+ psObject->padfM = (double *) calloc(sizeof(double),nVertices);
+
+ assert( padfX != NULL );
+ assert( padfY != NULL );
+
+ for( i = 0; i < nVertices; i++ )
+ {
+ psObject->padfX[i] = padfX[i];
+ psObject->padfY[i] = padfY[i];
+ if( padfZ != NULL && bHasZ )
+ psObject->padfZ[i] = padfZ[i];
+ if( padfM != NULL && bHasM )
+ psObject->padfM[i] = padfM[i];
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Compute the extents. */
+/* -------------------------------------------------------------------- */
+ psObject->nVertices = nVertices;
+ SHPComputeExtents( psObject );
+
+ return( psObject );
+}
+
+/************************************************************************/
+/* SHPCreateSimpleObject() */
+/* */
+/* Create a simple (common) shape object. Destroy with */
+/* SHPDestroyObject(). */
+/************************************************************************/
+
+SHPObject SHPAPI_CALL1(*)
+SHPCreateSimpleObject( int nSHPType, int nVertices,
+ double * padfX, double * padfY,
+ double * padfZ )
+
+{
+ return( SHPCreateObject( nSHPType, -1, 0, NULL, NULL,
+ nVertices, padfX, padfY, padfZ, NULL ) );
+}
+
+/************************************************************************/
+/* SHPWriteObject() */
+/* */
+/* Write out the vertices of a new structure. Note that it is */
+/* only possible to write vertices at the end of the file. */
+/************************************************************************/
+
+int SHPAPI_CALL
+SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
+
+{
+ int nRecordOffset, i, nRecordSize;
+ uchar *pabyRec;
+ int32 i32;
+
+ psSHP->bUpdated = TRUE;
+
+/* -------------------------------------------------------------------- */
+/* Ensure that shape object matches the type of the file it is */
+/* being written to. */
+/* -------------------------------------------------------------------- */
+ assert( psObject->nSHPType == psSHP->nShapeType
+ || psObject->nSHPType == SHPT_NULL );
+
+/* -------------------------------------------------------------------- */
+/* Ensure that -1 is used for appends. Either blow an */
+/* assertion, or if they are disabled, set the shapeid to -1 */
+/* for appends. */
+/* -------------------------------------------------------------------- */
+ assert( nShapeId == -1
+ || (nShapeId >= 0 && nShapeId < psSHP->nRecords) );
+
+ if( nShapeId != -1 && nShapeId >= psSHP->nRecords )
+ nShapeId = -1;
+
+/* -------------------------------------------------------------------- */
+/* Add the new entity to the in memory index. */
+/* -------------------------------------------------------------------- */
+ if( nShapeId == -1 && psSHP->nRecords+1 > psSHP->nMaxRecords )
+ {
+ psSHP->nMaxRecords =(int) ( psSHP->nMaxRecords * 1.3 + 100);
+
+ psSHP->panRecOffset = (int *)
+ SfRealloc(psSHP->panRecOffset,sizeof(int) * psSHP->nMaxRecords );
+ psSHP->panRecSize = (int *)
+ SfRealloc(psSHP->panRecSize,sizeof(int) * psSHP->nMaxRecords );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Initialize record. */
+/* -------------------------------------------------------------------- */
+ pabyRec = (uchar *) malloc(psObject->nVertices * 4 * sizeof(double)
+ + psObject->nParts * 8 + 128);
+
+/* -------------------------------------------------------------------- */
+/* Extract vertices for a Polygon or Arc. */
+/* -------------------------------------------------------------------- */
+ if( psObject->nSHPType == SHPT_POLYGON
+ || psObject->nSHPType == SHPT_POLYGONZ
+ || psObject->nSHPType == SHPT_POLYGONM
+ || psObject->nSHPType == SHPT_ARC
+ || psObject->nSHPType == SHPT_ARCZ
+ || psObject->nSHPType == SHPT_ARCM
+ || psObject->nSHPType == SHPT_MULTIPATCH )
+ {
+ int32 nPoints, nParts;
+ int i;
+
+ nPoints = psObject->nVertices;
+ nParts = psObject->nParts;
+
+ _SHPSetBounds( pabyRec + 12, psObject );
+
+ if( bBigEndian ) SwapWord( 4, &nPoints );
+ if( bBigEndian ) SwapWord( 4, &nParts );
+
+ ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
+ ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
+
+ nRecordSize = 52;
+
+ /*
+ * Write part start positions.
+ */
+ ByteCopy( psObject->panPartStart, pabyRec + 44 + 8,
+ 4 * psObject->nParts );
+ for( i = 0; i < psObject->nParts; i++ )
+ {
+ if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i );
+ nRecordSize += 4;
+ }
+
+ /*
+ * Write multipatch part types if needed.
+ */
+ if( psObject->nSHPType == SHPT_MULTIPATCH )
+ {
+ memcpy( pabyRec + nRecordSize, psObject->panPartType,
+ 4*psObject->nParts );
+ for( i = 0; i < psObject->nParts; i++ )
+ {
+ if( bBigEndian ) SwapWord( 4, pabyRec + nRecordSize );
+ nRecordSize += 4;
+ }
+ }
+
+ /*
+ * Write the (x,y) vertex values.
+ */
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ ByteCopy( psObject->padfX + i, pabyRec + nRecordSize, 8 );
+ ByteCopy( psObject->padfY + i, pabyRec + nRecordSize + 8, 8 );
+
+ if( bBigEndian )
+ SwapWord( 8, pabyRec + nRecordSize );
+
+ if( bBigEndian )
+ SwapWord( 8, pabyRec + nRecordSize + 8 );
+
+ nRecordSize += 2 * 8;
+ }
+
+ /*
+ * Write the Z coordinates (if any).
+ */
+ if( psObject->nSHPType == SHPT_POLYGONZ
+ || psObject->nSHPType == SHPT_ARCZ
+ || psObject->nSHPType == SHPT_MULTIPATCH )
+ {
+ ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+ }
+ }
+
+ /*
+ * Write the M values, if any.
+ */
+ if( psObject->nSHPType == SHPT_POLYGONM
+ || psObject->nSHPType == SHPT_ARCM
+#ifndef DISABLE_MULTIPATCH_MEASURE
+ || psObject->nSHPType == SHPT_MULTIPATCH
+#endif
+ || psObject->nSHPType == SHPT_POLYGONZ
+ || psObject->nSHPType == SHPT_ARCZ )
+ {
+ ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+ }
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Extract vertices for a MultiPoint. */
+/* -------------------------------------------------------------------- */
+ else if( psObject->nSHPType == SHPT_MULTIPOINT
+ || psObject->nSHPType == SHPT_MULTIPOINTZ
+ || psObject->nSHPType == SHPT_MULTIPOINTM )
+ {
+ int32 nPoints;
+ int i;
+
+ nPoints = psObject->nVertices;
+
+ _SHPSetBounds( pabyRec + 12, psObject );
+
+ if( bBigEndian ) SwapWord( 4, &nPoints );
+ ByteCopy( &nPoints, pabyRec + 44, 4 );
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ ByteCopy( psObject->padfX + i, pabyRec + 48 + i*16, 8 );
+ ByteCopy( psObject->padfY + i, pabyRec + 48 + i*16 + 8, 8 );
+
+ if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 + 8 );
+ }
+
+ nRecordSize = 48 + 16 * psObject->nVertices;
+
+ if( psObject->nSHPType == SHPT_MULTIPOINTZ )
+ {
+ ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+ }
+ }
+
+ if( psObject->nSHPType == SHPT_MULTIPOINTZ
+ || psObject->nSHPType == SHPT_MULTIPOINTM )
+ {
+ ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+ }
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Write point. */
+/* -------------------------------------------------------------------- */
+ else if( psObject->nSHPType == SHPT_POINT
+ || psObject->nSHPType == SHPT_POINTZ
+ || psObject->nSHPType == SHPT_POINTM )
+ {
+ ByteCopy( psObject->padfX, pabyRec + 12, 8 );
+ ByteCopy( psObject->padfY, pabyRec + 20, 8 );
+
+ if( bBigEndian ) SwapWord( 8, pabyRec + 12 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
+
+ nRecordSize = 28;
+
+ if( psObject->nSHPType == SHPT_POINTZ )
+ {
+ ByteCopy( psObject->padfZ, pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+ }
+
+ if( psObject->nSHPType == SHPT_POINTZ
+ || psObject->nSHPType == SHPT_POINTM )
+ {
+ ByteCopy( psObject->padfM, pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Not much to do for null geometries. */
+/* -------------------------------------------------------------------- */
+ else if( psObject->nSHPType == SHPT_NULL )
+ {
+ nRecordSize = 12;
+ }
+
+ else
+ {
+ /* unknown type */
+ assert( FALSE );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Establish where we are going to put this record. If we are */
+/* rewriting and existing record, and it will fit, then put it */
+/* back where the original came from. Otherwise write at the end. */
+/* -------------------------------------------------------------------- */
+ if( nShapeId == -1 || psSHP->panRecSize[nShapeId] < nRecordSize-8 )
+ {
+ if( nShapeId == -1 )
+ nShapeId = psSHP->nRecords++;
+
+ psSHP->panRecOffset[nShapeId] = nRecordOffset = psSHP->nFileSize;
+ psSHP->panRecSize[nShapeId] = nRecordSize-8;
+ psSHP->nFileSize += nRecordSize;
+ }
+ else
+ {
+ nRecordOffset = psSHP->panRecOffset[nShapeId];
+ }
+
+/* -------------------------------------------------------------------- */
+/* Set the shape type, record number, and record size. */
+/* -------------------------------------------------------------------- */
+ i32 = nShapeId+1; /* record # */
+ if( !bBigEndian ) SwapWord( 4, &i32 );
+ ByteCopy( &i32, pabyRec, 4 );
+
+ i32 = (nRecordSize-8)/2; /* record size */
+ if( !bBigEndian ) SwapWord( 4, &i32 );
+ ByteCopy( &i32, pabyRec + 4, 4 );
+
+ i32 = psObject->nSHPType; /* shape type */
+ if( bBigEndian ) SwapWord( 4, &i32 );
+ ByteCopy( &i32, pabyRec + 8, 4 );
+
+/* -------------------------------------------------------------------- */
+/* Write out record. */
+/* -------------------------------------------------------------------- */
+ if( fseek( psSHP->fpSHP, nRecordOffset, 0 ) != 0
+ || fwrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 )
+ {
+ printf( "Error in fseek() or fwrite().\n" );
+ free( pabyRec );
+ return -1;
+ }
+
+ free( pabyRec );
+
+/* -------------------------------------------------------------------- */
+/* Expand file wide bounds based on this shape. */
+/* -------------------------------------------------------------------- */
+ if( psSHP->adBoundsMin[0] == 0.0
+ && psSHP->adBoundsMax[0] == 0.0
+ && psSHP->adBoundsMin[1] == 0.0
+ && psSHP->adBoundsMax[1] == 0.0
+ && psObject->nSHPType != SHPT_NULL )
+ {
+ psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0];
+ psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0];
+ psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0];
+ psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0];
+ }
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ psSHP->adBoundsMin[0] = MIN(psSHP->adBoundsMin[0],psObject->padfX[i]);
+ psSHP->adBoundsMin[1] = MIN(psSHP->adBoundsMin[1],psObject->padfY[i]);
+ psSHP->adBoundsMin[2] = MIN(psSHP->adBoundsMin[2],psObject->padfZ[i]);
+ psSHP->adBoundsMin[3] = MIN(psSHP->adBoundsMin[3],psObject->padfM[i]);
+ psSHP->adBoundsMax[0] = MAX(psSHP->adBoundsMax[0],psObject->padfX[i]);
+ psSHP->adBoundsMax[1] = MAX(psSHP->adBoundsMax[1],psObject->padfY[i]);
+ psSHP->adBoundsMax[2] = MAX(psSHP->adBoundsMax[2],psObject->padfZ[i]);
+ psSHP->adBoundsMax[3] = MAX(psSHP->adBoundsMax[3],psObject->padfM[i]);
+ }
+
+ return( nShapeId );
+}
+
+/************************************************************************/
+/* SHPReadObject() */
+/* */
+/* Read the vertices, parts, and other non-attribute information */
+/* for one shape. */
+/************************************************************************/
+
+SHPObject SHPAPI_CALL1(*)
+SHPReadObject( SHPHandle psSHP, int hEntity )
+
+{
+ SHPObject *psShape;
+
+/* -------------------------------------------------------------------- */
+/* Validate the record/entity number. */
+/* -------------------------------------------------------------------- */
+ if( hEntity < 0 || hEntity >= psSHP->nRecords )
+ return( NULL );
+
+/* -------------------------------------------------------------------- */
+/* Ensure our record buffer is large enough. */
+/* -------------------------------------------------------------------- */
+ if( psSHP->panRecSize[hEntity]+8 > psSHP->nBufSize )
+ {
+ psSHP->nBufSize = psSHP->panRecSize[hEntity]+8;
+ psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,psSHP->nBufSize);
+ }
+
+/* -------------------------------------------------------------------- */
+/* Read the record. */
+/* -------------------------------------------------------------------- */
+ fseek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 );
+ fread( psSHP->pabyRec, psSHP->panRecSize[hEntity]+8, 1, psSHP->fpSHP );
+
+/* -------------------------------------------------------------------- */
+/* Allocate and minimally initialize the object. */
+/* -------------------------------------------------------------------- */
+ psShape = (SHPObject *) calloc(1,sizeof(SHPObject));
+ psShape->nShapeId = hEntity;
+
+ memcpy( &psShape->nSHPType, psSHP->pabyRec + 8, 4 );
+ if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) );
+
+/* ==================================================================== */
+/* Extract vertices for a Polygon or Arc. */
+/* ==================================================================== */
+ if( psShape->nSHPType == SHPT_POLYGON || psShape->nSHPType == SHPT_ARC
+ || psShape->nSHPType == SHPT_POLYGONZ
+ || psShape->nSHPType == SHPT_POLYGONM
+ || psShape->nSHPType == SHPT_ARCZ
+ || psShape->nSHPType == SHPT_ARCM
+ || psShape->nSHPType == SHPT_MULTIPATCH )
+ {
+ int32 nPoints, nParts;
+ int i, nOffset;
+
+/* -------------------------------------------------------------------- */
+/* Get the X/Y bounds. */
+/* -------------------------------------------------------------------- */
+ memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
+ memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
+ memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
+ memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
+
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
+
+/* -------------------------------------------------------------------- */
+/* Extract part/point count, and build vertex and part arrays */
+/* to proper size. */
+/* -------------------------------------------------------------------- */
+ memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
+ memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
+
+ if( bBigEndian ) SwapWord( 4, &nPoints );
+ if( bBigEndian ) SwapWord( 4, &nParts );
+
+ psShape->nVertices = nPoints;
+ psShape->padfX = (double *) calloc(nPoints,sizeof(double));
+ psShape->padfY = (double *) calloc(nPoints,sizeof(double));
+ psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
+ psShape->padfM = (double *) calloc(nPoints,sizeof(double));
+
+ psShape->nParts = nParts;
+ psShape->panPartStart = (int *) calloc(nParts,sizeof(int));
+ psShape->panPartType = (int *) calloc(nParts,sizeof(int));
+
+ for( i = 0; i < nParts; i++ )
+ psShape->panPartType[i] = SHPP_RING;
+
+/* -------------------------------------------------------------------- */
+/* Copy out the part array from the record. */
+/* -------------------------------------------------------------------- */
+ memcpy( psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
+ for( i = 0; i < nParts; i++ )
+ {
+ if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
+ }
+
+ nOffset = 44 + 8 + 4*nParts;
+
+/* -------------------------------------------------------------------- */
+/* If this is a multipatch, we will also have parts types. */
+/* -------------------------------------------------------------------- */
+ if( psShape->nSHPType == SHPT_MULTIPATCH )
+ {
+ memcpy( psShape->panPartType, psSHP->pabyRec + nOffset, 4*nParts );
+ for( i = 0; i < nParts; i++ )
+ {
+ if( bBigEndian ) SwapWord( 4, psShape->panPartType+i );
+ }
+
+ nOffset += 4*nParts;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Copy out the vertices from the record. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < nPoints; i++ )
+ {
+ memcpy(psShape->padfX + i,
+ psSHP->pabyRec + nOffset + i * 16,
+ 8 );
+
+ memcpy(psShape->padfY + i,
+ psSHP->pabyRec + nOffset + i * 16 + 8,
+ 8 );
+
+ if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
+ if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
+ }
+
+ nOffset += 16*nPoints;
+
+/* -------------------------------------------------------------------- */
+/* If we have a Z coordinate, collect that now. */
+/* -------------------------------------------------------------------- */
+ if( psShape->nSHPType == SHPT_POLYGONZ
+ || psShape->nSHPType == SHPT_ARCZ
+ || psShape->nSHPType == SHPT_MULTIPATCH )
+ {
+ memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
+ memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
+
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
+
+ for( i = 0; i < nPoints; i++ )
+ {
+ memcpy( psShape->padfZ + i,
+ psSHP->pabyRec + nOffset + 16 + i*8, 8 );
+ if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
+ }
+
+ nOffset += 16 + 8*nPoints;
+ }
+
+/* -------------------------------------------------------------------- */
+/* If we have a M measure value, then read it now. We assume */
+/* that the measure can be present for any shape if the size is */
+/* big enough, but really it will only occur for the Z shapes */
+/* (options), and the M shapes. */
+/* -------------------------------------------------------------------- */
+ if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
+ {
+ memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
+ memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
+
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
+
+ for( i = 0; i < nPoints; i++ )
+ {
+ memcpy( psShape->padfM + i,
+ psSHP->pabyRec + nOffset + 16 + i*8, 8 );
+ if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
+ }
+ }
+
+ }
+
+/* ==================================================================== */
+/* Extract vertices for a MultiPoint. */
+/* ==================================================================== */
+ else if( psShape->nSHPType == SHPT_MULTIPOINT
+ || psShape->nSHPType == SHPT_MULTIPOINTM
+ || psShape->nSHPType == SHPT_MULTIPOINTZ )
+ {
+ int32 nPoints;
+ int i, nOffset;
+
+ memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
+ if( bBigEndian ) SwapWord( 4, &nPoints );
+
+ psShape->nVertices = nPoints;
+ psShape->padfX = (double *) calloc(nPoints,sizeof(double));
+ psShape->padfY = (double *) calloc(nPoints,sizeof(double));
+ psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
+ psShape->padfM = (double *) calloc(nPoints,sizeof(double));
+
+ for( i = 0; i < nPoints; i++ )
+ {
+ memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
+ memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
+
+ if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
+ if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
+ }
+
+ nOffset = 48 + 16*nPoints;
+
+/* -------------------------------------------------------------------- */
+/* Get the X/Y bounds. */
+/* -------------------------------------------------------------------- */
+ memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
+ memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
+ memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
+ memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
+
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
+
+/* -------------------------------------------------------------------- */
+/* If we have a Z coordinate, collect that now. */
+/* -------------------------------------------------------------------- */
+ if( psShape->nSHPType == SHPT_MULTIPOINTZ )
+ {
+ memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
+ memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
+
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
+
+ for( i = 0; i < nPoints; i++ )
+ {
+ memcpy( psShape->padfZ + i,
+ psSHP->pabyRec + nOffset + 16 + i*8, 8 );
+ if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
+ }
+
+ nOffset += 16 + 8*nPoints;
+ }
+
+/* -------------------------------------------------------------------- */
+/* If we have a M measure value, then read it now. We assume */
+/* that the measure can be present for any shape if the size is */
+/* big enough, but really it will only occur for the Z shapes */
+/* (options), and the M shapes. */
+/* -------------------------------------------------------------------- */
+ if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
+ {
+ memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
+ memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
+
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
+
+ for( i = 0; i < nPoints; i++ )
+ {
+ memcpy( psShape->padfM + i,
+ psSHP->pabyRec + nOffset + 16 + i*8, 8 );
+ if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
+ }
+ }
+ }
+
+/* ==================================================================== */
+/* Extract vertices for a point. */
+/* ==================================================================== */
+ else if( psShape->nSHPType == SHPT_POINT
+ || psShape->nSHPType == SHPT_POINTM
+ || psShape->nSHPType == SHPT_POINTZ )
+ {
+ int nOffset;
+
+ psShape->nVertices = 1;
+ psShape->padfX = (double *) calloc(1,sizeof(double));
+ psShape->padfY = (double *) calloc(1,sizeof(double));
+ psShape->padfZ = (double *) calloc(1,sizeof(double));
+ psShape->padfM = (double *) calloc(1,sizeof(double));
+
+ memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 );
+ memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 );
+
+ if( bBigEndian ) SwapWord( 8, psShape->padfX );
+ if( bBigEndian ) SwapWord( 8, psShape->padfY );
+
+ nOffset = 20 + 8;
+
+/* -------------------------------------------------------------------- */
+/* If we have a Z coordinate, collect that now. */
+/* -------------------------------------------------------------------- */
+ if( psShape->nSHPType == SHPT_POINTZ )
+ {
+ memcpy( psShape->padfZ, psSHP->pabyRec + nOffset, 8 );
+
+ if( bBigEndian ) SwapWord( 8, psShape->padfZ );
+
+ nOffset += 8;
+ }
+
+/* -------------------------------------------------------------------- */
+/* If we have a M measure value, then read it now. We assume */
+/* that the measure can be present for any shape if the size is */
+/* big enough, but really it will only occur for the Z shapes */
+/* (options), and the M shapes. */
+/* -------------------------------------------------------------------- */
+ if( psSHP->panRecSize[hEntity]+8 >= nOffset + 8 )
+ {
+ memcpy( psShape->padfM, psSHP->pabyRec + nOffset, 8 );
+
+ if( bBigEndian ) SwapWord( 8, psShape->padfM );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Since no extents are supplied in the record, we will apply */
+/* them from the single vertex. */
+/* -------------------------------------------------------------------- */
+ psShape->dfXMin = psShape->dfXMax = psShape->padfX[0];
+ psShape->dfYMin = psShape->dfYMax = psShape->padfY[0];
+ psShape->dfZMin = psShape->dfZMax = psShape->padfZ[0];
+ psShape->dfMMin = psShape->dfMMax = psShape->padfM[0];
+ }
+
+ return( psShape );
+}
+
+/************************************************************************/
+/* SHPTypeName() */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+SHPTypeName( int nSHPType )
+
+{
+ switch( nSHPType )
+ {
+ case SHPT_NULL:
+ return "NullShape";
+
+ case SHPT_POINT:
+ return "Point";
+
+ case SHPT_ARC:
+ return "Arc";
+
+ case SHPT_POLYGON:
+ return "Polygon";
+
+ case SHPT_MULTIPOINT:
+ return "MultiPoint";
+
+ case SHPT_POINTZ:
+ return "PointZ";
+
+ case SHPT_ARCZ:
+ return "ArcZ";
+
+ case SHPT_POLYGONZ:
+ return "PolygonZ";
+
+ case SHPT_MULTIPOINTZ:
+ return "MultiPointZ";
+
+ case SHPT_POINTM:
+ return "PointM";
+
+ case SHPT_ARCM:
+ return "ArcM";
+
+ case SHPT_POLYGONM:
+ return "PolygonM";
+
+ case SHPT_MULTIPOINTM:
+ return "MultiPointM";
+
+ case SHPT_MULTIPATCH:
+ return "MultiPatch";
+
+ default:
+ return "UnknownShapeType";
+ }
+}
+
+/************************************************************************/
+/* SHPPartTypeName() */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+SHPPartTypeName( int nPartType )
+
+{
+ switch( nPartType )
+ {
+ case SHPP_TRISTRIP:
+ return "TriangleStrip";
+
+ case SHPP_TRIFAN:
+ return "TriangleFan";
+
+ case SHPP_OUTERRING:
+ return "OuterRing";
+
+ case SHPP_INNERRING:
+ return "InnerRing";
+
+ case SHPP_FIRSTRING:
+ return "FirstRing";
+
+ case SHPP_RING:
+ return "Ring";
+
+ default:
+ return "UnknownPartType";
+ }
+}
+
+/************************************************************************/
+/* SHPDestroyObject() */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPDestroyObject( SHPObject * psShape )
+
+{
+ if( psShape == NULL )
+ return;
+
+ if( psShape->padfX != NULL )
+ free( psShape->padfX );
+ if( psShape->padfY != NULL )
+ free( psShape->padfY );
+ if( psShape->padfZ != NULL )
+ free( psShape->padfZ );
+ if( psShape->padfM != NULL )
+ free( psShape->padfM );
+
+ if( psShape->panPartStart != NULL )
+ free( psShape->panPartStart );
+ if( psShape->panPartType != NULL )
+ free( psShape->panPartType );
+
+ free( psShape );
+}
+
+/************************************************************************/
+/* SHPRewindObject() */
+/* */
+/* Reset the winding of polygon objects to adhere to the */
+/* specification. */
+/************************************************************************/
+
+int SHPAPI_CALL
+SHPRewindObject( SHPHandle hSHP, SHPObject * psObject )
+
+{
+ int iOpRing, bAltered = 0;
+
+/* -------------------------------------------------------------------- */
+/* Do nothing if this is not a polygon object. */
+/* -------------------------------------------------------------------- */
+ if( psObject->nSHPType != SHPT_POLYGON
+ && psObject->nSHPType != SHPT_POLYGONZ
+ && psObject->nSHPType != SHPT_POLYGONM )
+ return 0;
+
+/* -------------------------------------------------------------------- */
+/* Process each of the rings. */
+/* -------------------------------------------------------------------- */
+ for( iOpRing = 0; iOpRing < psObject->nParts; iOpRing++ )
+ {
+ int bInner, iVert, nVertCount, nVertStart, iCheckRing;
+ double dfSum, dfTestX, dfTestY;
+
+/* -------------------------------------------------------------------- */
+/* Determine if this ring is an inner ring or an outer ring */
+/* relative to all the other rings. For now we assume the */
+/* first ring is outer and all others are inner, but eventually */
+/* we need to fix this to handle multiple island polygons and */
+/* unordered sets of rings. */
+/* -------------------------------------------------------------------- */
+ dfTestX = psObject->padfX[psObject->panPartStart[iOpRing]];
+ dfTestY = psObject->padfY[psObject->panPartStart[iOpRing]];
+
+ bInner = FALSE;
+ for( iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++ )
+ {
+ int iEdge;
+
+ if( iCheckRing == iOpRing )
+ continue;
+
+ nVertStart = psObject->panPartStart[iCheckRing];
+
+ if( iCheckRing == psObject->nParts-1 )
+ nVertCount = psObject->nVertices
+ - psObject->panPartStart[iCheckRing];
+ else
+ nVertCount = psObject->panPartStart[iCheckRing+1]
+ - psObject->panPartStart[iCheckRing];
+
+ for( iEdge = 0; iEdge < nVertCount; iEdge++ )
+ {
+ int iNext;
+
+ if( iEdge < nVertCount-1 )
+ iNext = iEdge+1;
+ else
+ iNext = 0;
+
+ if( (psObject->padfY[iEdge+nVertStart] < dfTestY
+ && psObject->padfY[iNext+nVertStart] >= dfTestY)
+ || (psObject->padfY[iNext+nVertStart] < dfTestY
+ && psObject->padfY[iEdge+nVertStart] >= dfTestY) )
+ {
+ if( psObject->padfX[iEdge+nVertStart]
+ + (dfTestY - psObject->padfY[iEdge+nVertStart])
+ / (psObject->padfY[iNext+nVertStart]
+ - psObject->padfY[iEdge+nVertStart])
+ * (psObject->padfX[iNext+nVertStart]
+ - psObject->padfX[iEdge+nVertStart]) < dfTestX )
+ bInner = !bInner;
+ }
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Determine the current order of this ring so we will know if */
+/* it has to be reversed. */
+/* -------------------------------------------------------------------- */
+ nVertStart = psObject->panPartStart[iOpRing];
+
+ if( iOpRing == psObject->nParts-1 )
+ nVertCount = psObject->nVertices - psObject->panPartStart[iOpRing];
+ else
+ nVertCount = psObject->panPartStart[iOpRing+1]
+ - psObject->panPartStart[iOpRing];
+
+ dfSum = 0.0;
+ for( iVert = nVertStart; iVert < nVertStart+nVertCount-1; iVert++ )
+ {
+ dfSum += psObject->padfX[iVert] * psObject->padfY[iVert+1]
+ - psObject->padfY[iVert] * psObject->padfX[iVert+1];
+ }
+
+ dfSum += psObject->padfX[iVert] * psObject->padfY[nVertStart]
+ - psObject->padfY[iVert] * psObject->padfX[nVertStart];
+
+/* -------------------------------------------------------------------- */
+/* Reverse if necessary. */
+/* -------------------------------------------------------------------- */
+ if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) )
+ {
+ int i;
+
+ bAltered++;
+ for( i = 0; i < nVertCount/2; i++ )
+ {
+ double dfSaved;
+
+ /* Swap X */
+ dfSaved = psObject->padfX[nVertStart+i];
+ psObject->padfX[nVertStart+i] =
+ psObject->padfX[nVertStart+nVertCount-i-1];
+ psObject->padfX[nVertStart+nVertCount-i-1] = dfSaved;
+
+ /* Swap Y */
+ dfSaved = psObject->padfY[nVertStart+i];
+ psObject->padfY[nVertStart+i] =
+ psObject->padfY[nVertStart+nVertCount-i-1];
+ psObject->padfY[nVertStart+nVertCount-i-1] = dfSaved;
+
+ /* Swap Z */
+ if( psObject->padfZ )
+ {
+ dfSaved = psObject->padfZ[nVertStart+i];
+ psObject->padfZ[nVertStart+i] =
+ psObject->padfZ[nVertStart+nVertCount-i-1];
+ psObject->padfZ[nVertStart+nVertCount-i-1] = dfSaved;
+ }
+
+ /* Swap M */
+ if( psObject->padfM )
+ {
+ dfSaved = psObject->padfM[nVertStart+i];
+ psObject->padfM[nVertStart+i] =
+ psObject->padfM[nVertStart+nVertCount-i-1];
+ psObject->padfM[nVertStart+nVertCount-i-1] = dfSaved;
+ }
+ }
+ }
+ }
+
+ return bAltered;
+}
diff --git a/src/shapelib/shprewind.c b/src/shapelib/shprewind.c
new file mode 100644
index 0000000..590313e
--- /dev/null
+++ b/src/shapelib/shprewind.c
@@ -0,0 +1,140 @@
+/******************************************************************************
+ * $Id: shprewind.c,v 1.3 2010/07/11 07:24:37 we7u Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Utility to validate and reset the winding order of rings in
+ * polygon geometries to match the ordering required by spec.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: shprewind.c,v $
+ * Revision 1.3 2010/07/11 07:24:37 we7u
+ * Fixing multiple minor warnings with Shapelib. Still plenty left.
+ *
+ * Revision 1.2 2007/07/25 15:37:50 we7u
+ * Added shprewind.c to the "clean" target of the original Makefile. Added
+ * stdlib.h includes to some of the utilities to get a clean compile.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.2 2002/04/10 17:23:11 warmerda
+ * copy from source to destination now
+ *
+ * Revision 1.1 2002/04/10 16:56:36 warmerda
+ * New
+ *
+ */
+
+#include "shapefil.h"
+#include <stdlib.h>
+
+int main( int argc, char ** argv )
+
+{
+ SHPHandle hSHP, hSHPOut;
+ int nShapeType, nEntities, i, nInvalidCount=0;
+ double adfMinBound[4], adfMaxBound[4];
+
+/* -------------------------------------------------------------------- */
+/* Display a usage message. */
+/* -------------------------------------------------------------------- */
+ if( argc != 3 )
+ {
+ printf( "shprewind in_shp_file out_shp_file\n" );
+ exit( 1 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Open the passed shapefile. */
+/* -------------------------------------------------------------------- */
+ hSHP = SHPOpen( argv[1], "rb" );
+
+ if( hSHP == NULL )
+ {
+ printf( "Unable to open:%s\n", argv[1] );
+ exit( 1 );
+ }
+
+ SHPGetInfo( hSHP, &nEntities, &nShapeType, adfMinBound, adfMaxBound );
+
+/* -------------------------------------------------------------------- */
+/* Create output shapefile. */
+/* -------------------------------------------------------------------- */
+ hSHPOut = SHPCreate( argv[2], nShapeType );
+
+ if( hSHPOut == NULL )
+ {
+ printf( "Unable to create:%s\n", argv[2] );
+ exit( 1 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Skim over the list of shapes, printing all the vertices. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < nEntities; i++ )
+ {
+// int j;
+ SHPObject *psShape;
+
+ psShape = SHPReadObject( hSHP, i );
+ if( SHPRewindObject( hSHP, psShape ) )
+ nInvalidCount++;
+ SHPWriteObject( hSHPOut, -1, psShape );
+ SHPDestroyObject( psShape );
+ }
+
+ SHPClose( hSHP );
+ SHPClose( hSHPOut );
+
+ printf( "%d objects rewound.\n", nInvalidCount );
+
+ exit( 0 );
+}
diff --git a/src/shapelib/shptest.c b/src/shapelib/shptest.c
new file mode 100644
index 0000000..6ca23e5
--- /dev/null
+++ b/src/shapelib/shptest.c
@@ -0,0 +1,333 @@
+/******************************************************************************
+ * $Id: shptest.c,v 1.2 2009/06/04 04:25:19 we7u Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Application for generating sample Shapefiles of various types.
+ * Used by the stream2.sh test script.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: shptest.c,v $
+ * Revision 1.2 2009/06/04 04:25:19 we7u
+ * Getting rid of compiler warnings due to unused variable.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.6 2002/01/15 14:36:07 warmerda
+ * updated email address
+ *
+ * Revision 1.5 2001/06/22 02:18:20 warmerda
+ * Added null shape support
+ *
+ * Revision 1.4 2000/07/07 13:39:45 warmerda
+ * removed unused variables, and added system include files
+ *
+ * Revision 1.3 1999/11/05 14:12:05 warmerda
+ * updated license terms
+ *
+ * Revision 1.2 1998/12/16 05:15:20 warmerda
+ * Added support for writing multipatch.
+ *
+ * Revision 1.1 1998/11/09 20:18:42 warmerda
+ * Initial revision
+ *
+ */
+
+//static char rcsid[] =
+// "$Id: shptest.c,v 1.2 2009/06/04 04:25:19 we7u Exp $";
+
+#include <stdlib.h>
+#include <string.h>
+#include "shapefil.h"
+
+/************************************************************************/
+/* Test_WritePoints() */
+/* */
+/* Write a small point file. */
+/************************************************************************/
+
+static void Test_WritePoints( int nSHPType, const char *pszFilename )
+
+{
+ SHPHandle hSHPHandle;
+ SHPObject *psShape;
+ double x, y, z, m;
+
+ hSHPHandle = SHPCreate( pszFilename, nSHPType );
+
+ x = 1.0;
+ y = 2.0;
+ z = 3.0;
+ m = 4.0;
+ psShape = SHPCreateObject( nSHPType, -1, 0, NULL, NULL,
+ 1, &x, &y, &z, &m );
+ SHPWriteObject( hSHPHandle, -1, psShape );
+ SHPDestroyObject( psShape );
+
+ x = 10.0;
+ y = 20.0;
+ z = 30.0;
+ m = 40.0;
+ psShape = SHPCreateObject( nSHPType, -1, 0, NULL, NULL,
+ 1, &x, &y, &z, &m );
+ SHPWriteObject( hSHPHandle, -1, psShape );
+ SHPDestroyObject( psShape );
+
+ SHPClose( hSHPHandle );
+}
+
+/************************************************************************/
+/* Test_WriteMultiPoints() */
+/* */
+/* Write a small multipoint file. */
+/************************************************************************/
+
+static void Test_WriteMultiPoints( int nSHPType, const char *pszFilename )
+
+{
+ SHPHandle hSHPHandle;
+ SHPObject *psShape;
+ double x[4], y[4], z[4], m[4];
+ int i, iShape;
+
+ hSHPHandle = SHPCreate( pszFilename, nSHPType );
+
+ for( iShape = 0; iShape < 3; iShape++ )
+ {
+ for( i = 0; i < 4; i++ )
+ {
+ x[i] = iShape * 10 + i + 1.15;
+ y[i] = iShape * 10 + i + 2.25;
+ z[i] = iShape * 10 + i + 3.35;
+ m[i] = iShape * 10 + i + 4.45;
+ }
+
+ psShape = SHPCreateObject( nSHPType, -1, 0, NULL, NULL,
+ 4, x, y, z, m );
+ SHPWriteObject( hSHPHandle, -1, psShape );
+ SHPDestroyObject( psShape );
+ }
+
+ SHPClose( hSHPHandle );
+}
+
+/************************************************************************/
+/* Test_WriteArcPoly() */
+/* */
+/* Write a small arc or polygon file. */
+/************************************************************************/
+
+static void Test_WriteArcPoly( int nSHPType, const char *pszFilename )
+
+{
+ SHPHandle hSHPHandle;
+ SHPObject *psShape;
+ double x[100], y[100], z[100], m[100];
+ int anPartStart[100];
+ int anPartType[100], *panPartType;
+ int i, iShape;
+
+ hSHPHandle = SHPCreate( pszFilename, nSHPType );
+
+ if( nSHPType == SHPT_MULTIPATCH )
+ panPartType = anPartType;
+ else
+ panPartType = NULL;
+
+ for( iShape = 0; iShape < 3; iShape++ )
+ {
+ x[0] = 1.0;
+ y[0] = 1.0+iShape*3;
+ x[1] = 2.0;
+ y[1] = 1.0+iShape*3;
+ x[2] = 2.0;
+ y[2] = 2.0+iShape*3;
+ x[3] = 1.0;
+ y[3] = 2.0+iShape*3;
+ x[4] = 1.0;
+ y[4] = 1.0+iShape*3;
+
+ for( i = 0; i < 5; i++ )
+ {
+ z[i] = iShape * 10 + i + 3.35;
+ m[i] = iShape * 10 + i + 4.45;
+ }
+
+ psShape = SHPCreateObject( nSHPType, -1, 0, NULL, NULL,
+ 5, x, y, z, m );
+ SHPWriteObject( hSHPHandle, -1, psShape );
+ SHPDestroyObject( psShape );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Do a multi part polygon (shape). We close it, and have two */
+/* inner rings. */
+/* -------------------------------------------------------------------- */
+ x[0] = 0.0;
+ y[0] = 0.0;
+ x[1] = 0;
+ y[1] = 100;
+ x[2] = 100;
+ y[2] = 100;
+ x[3] = 100;
+ y[3] = 0;
+ x[4] = 0;
+ y[4] = 0;
+
+ x[5] = 10;
+ y[5] = 20;
+ x[6] = 30;
+ y[6] = 20;
+ x[7] = 30;
+ y[7] = 40;
+ x[8] = 10;
+ y[8] = 40;
+ x[9] = 10;
+ y[9] = 20;
+
+ x[10] = 60;
+ y[10] = 20;
+ x[11] = 90;
+ y[11] = 20;
+ x[12] = 90;
+ y[12] = 40;
+ x[13] = 60;
+ y[13] = 40;
+ x[14] = 60;
+ y[14] = 20;
+
+ for( i = 0; i < 15; i++ )
+ {
+ z[i] = i;
+ m[i] = i*2;
+ }
+
+ anPartStart[0] = 0;
+ anPartStart[1] = 5;
+ anPartStart[2] = 10;
+
+ anPartType[0] = SHPP_RING;
+ anPartType[1] = SHPP_INNERRING;
+ anPartType[2] = SHPP_INNERRING;
+
+ psShape = SHPCreateObject( nSHPType, -1, 3, anPartStart, panPartType,
+ 15, x, y, z, m );
+ SHPWriteObject( hSHPHandle, -1, psShape );
+ SHPDestroyObject( psShape );
+
+
+ SHPClose( hSHPHandle );
+}
+
+/************************************************************************/
+/* main() */
+/************************************************************************/
+int main( int argc, char ** argv )
+
+{
+/* -------------------------------------------------------------------- */
+/* Display a usage message. */
+/* -------------------------------------------------------------------- */
+ if( argc != 2 )
+ {
+ printf( "shptest test_number\n" );
+ exit( 1 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Figure out which test to run. */
+/* -------------------------------------------------------------------- */
+
+ if( atoi(argv[1]) == 0 )
+ Test_WritePoints( SHPT_NULL, "test0.shp" );
+
+ else if( atoi(argv[1]) == 1 )
+ Test_WritePoints( SHPT_POINT, "test1.shp" );
+ else if( atoi(argv[1]) == 2 )
+ Test_WritePoints( SHPT_POINTZ, "test2.shp" );
+ else if( atoi(argv[1]) == 3 )
+ Test_WritePoints( SHPT_POINTM, "test3.shp" );
+
+ else if( atoi(argv[1]) == 4 )
+ Test_WriteMultiPoints( SHPT_MULTIPOINT, "test4.shp" );
+ else if( atoi(argv[1]) == 5 )
+ Test_WriteMultiPoints( SHPT_MULTIPOINTZ, "test5.shp" );
+ else if( atoi(argv[1]) == 6 )
+ Test_WriteMultiPoints( SHPT_MULTIPOINTM, "test6.shp" );
+
+ else if( atoi(argv[1]) == 7 )
+ Test_WriteArcPoly( SHPT_ARC, "test7.shp" );
+ else if( atoi(argv[1]) == 8 )
+ Test_WriteArcPoly( SHPT_ARCZ, "test8.shp" );
+ else if( atoi(argv[1]) == 9 )
+ Test_WriteArcPoly( SHPT_ARCM, "test9.shp" );
+
+ else if( atoi(argv[1]) == 10 )
+ Test_WriteArcPoly( SHPT_POLYGON, "test10.shp" );
+ else if( atoi(argv[1]) == 11 )
+ Test_WriteArcPoly( SHPT_POLYGONZ, "test11.shp" );
+ else if( atoi(argv[1]) == 12 )
+ Test_WriteArcPoly( SHPT_POLYGONM, "test12.shp" );
+
+ else if( atoi(argv[1]) == 13 )
+ Test_WriteArcPoly( SHPT_MULTIPATCH, "test13.shp" );
+ else
+ {
+ printf( "Test `%s' not recognised.\n", argv[1] );
+ exit( 10 );
+ }
+
+#ifdef USE_DBMALLOC
+ malloc_dump(2);
+#endif
+
+ exit( 0 );
+}
diff --git a/src/shapelib/shptree.c b/src/shapelib/shptree.c
new file mode 100644
index 0000000..dd6b2c7
--- /dev/null
+++ b/src/shapelib/shptree.c
@@ -0,0 +1,705 @@
+/******************************************************************************
+ * $Id: shptree.c,v 1.2 2006/11/14 21:28:48 we7u Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Implementation of quadtree building and searching functions.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: shptree.c,v $
+ * Revision 1.2 2006/11/14 21:28:48 we7u
+ * Commenting out some variables that give off compiler warnings.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.9 2003/01/28 15:53:41 warmerda
+ * Avoid build warnings.
+ *
+ * Revision 1.8 2002/05/07 13:07:45 warmerda
+ * use qsort() - patch from Bernhard Herzog
+ *
+ * Revision 1.7 2002/01/15 14:36:07 warmerda
+ * updated email address
+ *
+ * Revision 1.6 2001/05/23 13:36:52 warmerda
+ * added use of SHPAPI_CALL
+ *
+ * Revision 1.5 1999/11/05 14:12:05 warmerda
+ * updated license terms
+ *
+ * Revision 1.4 1999/06/02 18:24:21 warmerda
+ * added trimming code
+ *
+ * Revision 1.3 1999/06/02 17:56:12 warmerda
+ * added quad'' subnode support for trees
+ *
+ * Revision 1.2 1999/05/18 19:11:11 warmerda
+ * Added example searching capability
+ *
+ * Revision 1.1 1999/05/18 17:49:20 warmerda
+ * New
+ *
+ */
+
+//static char rcsid[] =
+// "$Id: shptree.c,v 1.2 2006/11/14 21:28:48 we7u Exp $";
+
+#include "shapefil.h"
+
+#include <math.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef TRUE
+# define TRUE 1
+# define FALSE 0
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/* If the following is 0.5, nodes will be split in half. If it */
+/* is 0.6 then each subnode will contain 60% of the parent */
+/* node, with 20% representing overlap. This can be help to */
+/* prevent small objects on a boundary from shifting too high */
+/* up the tree. */
+/* -------------------------------------------------------------------- */
+
+#define SHP_SPLIT_RATIO 0.55
+
+/************************************************************************/
+/* SfRealloc() */
+/* */
+/* A realloc cover function that will access a NULL pointer as */
+/* a valid input. */
+/************************************************************************/
+
+static void * SfRealloc( void * pMem, int nNewSize )
+
+{
+ if( pMem == NULL )
+ return( (void *) malloc(nNewSize) );
+ else
+ return( (void *) realloc(pMem,nNewSize) );
+}
+
+/************************************************************************/
+/* SHPTreeNodeInit() */
+/* */
+/* Initialize a tree node. */
+/************************************************************************/
+
+static SHPTreeNode *SHPTreeNodeCreate( double * padfBoundsMin,
+ double * padfBoundsMax )
+
+{
+ SHPTreeNode *psTreeNode;
+
+ psTreeNode = (SHPTreeNode *) malloc(sizeof(SHPTreeNode));
+
+ psTreeNode->nShapeCount = 0;
+ psTreeNode->panShapeIds = NULL;
+ psTreeNode->papsShapeObj = NULL;
+
+ psTreeNode->nSubNodes = 0;
+
+ if( padfBoundsMin != NULL )
+ memcpy( psTreeNode->adfBoundsMin, padfBoundsMin, sizeof(double) * 4 );
+
+ if( padfBoundsMax != NULL )
+ memcpy( psTreeNode->adfBoundsMax, padfBoundsMax, sizeof(double) * 4 );
+
+ return psTreeNode;
+}
+
+
+/************************************************************************/
+/* SHPCreateTree() */
+/************************************************************************/
+
+SHPTree SHPAPI_CALL1(*)
+SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
+ double *padfBoundsMin, double *padfBoundsMax )
+
+{
+ SHPTree *psTree;
+
+ if( padfBoundsMin == NULL && hSHP == NULL )
+ return NULL;
+
+/* -------------------------------------------------------------------- */
+/* Allocate the tree object */
+/* -------------------------------------------------------------------- */
+ psTree = (SHPTree *) malloc(sizeof(SHPTree));
+
+ psTree->hSHP = hSHP;
+ psTree->nMaxDepth = nMaxDepth;
+ psTree->nDimension = nDimension;
+
+/* -------------------------------------------------------------------- */
+/* If no max depth was defined, try to select a reasonable one */
+/* that implies approximately 8 shapes per node. */
+/* -------------------------------------------------------------------- */
+ if( psTree->nMaxDepth == 0 && hSHP != NULL )
+ {
+ int nMaxNodeCount = 1;
+ int nShapeCount;
+
+ SHPGetInfo( hSHP, &nShapeCount, NULL, NULL, NULL );
+ while( nMaxNodeCount*4 < nShapeCount )
+ {
+ psTree->nMaxDepth += 1;
+ nMaxNodeCount = nMaxNodeCount * 2;
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Allocate the root node. */
+/* -------------------------------------------------------------------- */
+ psTree->psRoot = SHPTreeNodeCreate( padfBoundsMin, padfBoundsMax );
+
+/* -------------------------------------------------------------------- */
+/* Assign the bounds to the root node. If none are passed in, */
+/* use the bounds of the provided file otherwise the create */
+/* function will have already set the bounds. */
+/* -------------------------------------------------------------------- */
+ if( padfBoundsMin == NULL )
+ {
+ SHPGetInfo( hSHP, NULL, NULL,
+ psTree->psRoot->adfBoundsMin,
+ psTree->psRoot->adfBoundsMax );
+ }
+
+/* -------------------------------------------------------------------- */
+/* If we have a file, insert all it's shapes into the tree. */
+/* -------------------------------------------------------------------- */
+ if( hSHP != NULL )
+ {
+ int iShape, nShapeCount;
+
+ SHPGetInfo( hSHP, &nShapeCount, NULL, NULL, NULL );
+
+ for( iShape = 0; iShape < nShapeCount; iShape++ )
+ {
+ SHPObject *psShape;
+
+ psShape = SHPReadObject( hSHP, iShape );
+ SHPTreeAddShapeId( psTree, psShape );
+ SHPDestroyObject( psShape );
+ }
+ }
+
+ return psTree;
+}
+
+/************************************************************************/
+/* SHPDestroyTreeNode() */
+/************************************************************************/
+
+static void SHPDestroyTreeNode( SHPTreeNode * psTreeNode )
+
+{
+ int i;
+
+ for( i = 0; i < psTreeNode->nSubNodes; i++ )
+ {
+ if( psTreeNode->apsSubNode[i] != NULL )
+ SHPDestroyTreeNode( psTreeNode->apsSubNode[i] );
+ }
+
+ if( psTreeNode->panShapeIds != NULL )
+ free( psTreeNode->panShapeIds );
+
+ if( psTreeNode->papsShapeObj != NULL )
+ {
+ for( i = 0; i < psTreeNode->nShapeCount; i++ )
+ {
+ if( psTreeNode->papsShapeObj[i] != NULL )
+ SHPDestroyObject( psTreeNode->papsShapeObj[i] );
+ }
+
+ free( psTreeNode->papsShapeObj );
+ }
+
+ free( psTreeNode );
+}
+
+/************************************************************************/
+/* SHPDestroyTree() */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPDestroyTree( SHPTree * psTree )
+
+{
+ SHPDestroyTreeNode( psTree->psRoot );
+ free( psTree );
+}
+
+/************************************************************************/
+/* SHPCheckBoundsOverlap() */
+/* */
+/* Do the given boxes overlap at all? */
+/************************************************************************/
+
+int SHPAPI_CALL
+SHPCheckBoundsOverlap( double * padfBox1Min, double * padfBox1Max,
+ double * padfBox2Min, double * padfBox2Max,
+ int nDimension )
+
+{
+ int iDim;
+
+ for( iDim = 0; iDim < nDimension; iDim++ )
+ {
+ if( padfBox2Max[iDim] < padfBox1Min[iDim] )
+ return FALSE;
+
+ if( padfBox1Max[iDim] < padfBox2Min[iDim] )
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* SHPCheckObjectContained() */
+/* */
+/* Does the given shape fit within the indicated extents? */
+/************************************************************************/
+
+static int SHPCheckObjectContained( SHPObject * psObject, int nDimension,
+ double * padfBoundsMin, double * padfBoundsMax )
+
+{
+ if( psObject->dfXMin < padfBoundsMin[0]
+ || psObject->dfXMax > padfBoundsMax[0] )
+ return FALSE;
+
+ if( psObject->dfYMin < padfBoundsMin[1]
+ || psObject->dfYMax > padfBoundsMax[1] )
+ return FALSE;
+
+ if( nDimension == 2 )
+ return TRUE;
+
+ if( psObject->dfZMin < padfBoundsMin[2]
+ || psObject->dfZMax < padfBoundsMax[2] )
+ return FALSE;
+
+ if( nDimension == 3 )
+ return TRUE;
+
+ if( psObject->dfMMin < padfBoundsMin[3]
+ || psObject->dfMMax < padfBoundsMax[3] )
+ return FALSE;
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* SHPTreeSplitBounds() */
+/* */
+/* Split a region into two subregion evenly, cutting along the */
+/* longest dimension. */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPTreeSplitBounds( double *padfBoundsMinIn, double *padfBoundsMaxIn,
+ double *padfBoundsMin1, double * padfBoundsMax1,
+ double *padfBoundsMin2, double * padfBoundsMax2 )
+
+{
+/* -------------------------------------------------------------------- */
+/* The output bounds will be very similar to the input bounds, */
+/* so just copy over to start. */
+/* -------------------------------------------------------------------- */
+ memcpy( padfBoundsMin1, padfBoundsMinIn, sizeof(double) * 4 );
+ memcpy( padfBoundsMax1, padfBoundsMaxIn, sizeof(double) * 4 );
+ memcpy( padfBoundsMin2, padfBoundsMinIn, sizeof(double) * 4 );
+ memcpy( padfBoundsMax2, padfBoundsMaxIn, sizeof(double) * 4 );
+
+/* -------------------------------------------------------------------- */
+/* Split in X direction. */
+/* -------------------------------------------------------------------- */
+ if( (padfBoundsMaxIn[0] - padfBoundsMinIn[0])
+ > (padfBoundsMaxIn[1] - padfBoundsMinIn[1]) )
+ {
+ double dfRange = padfBoundsMaxIn[0] - padfBoundsMinIn[0];
+
+ padfBoundsMax1[0] = padfBoundsMinIn[0] + dfRange * SHP_SPLIT_RATIO;
+ padfBoundsMin2[0] = padfBoundsMaxIn[0] - dfRange * SHP_SPLIT_RATIO;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Otherwise split in Y direction. */
+/* -------------------------------------------------------------------- */
+ else
+ {
+ double dfRange = padfBoundsMaxIn[1] - padfBoundsMinIn[1];
+
+ padfBoundsMax1[1] = padfBoundsMinIn[1] + dfRange * SHP_SPLIT_RATIO;
+ padfBoundsMin2[1] = padfBoundsMaxIn[1] - dfRange * SHP_SPLIT_RATIO;
+ }
+}
+
+/************************************************************************/
+/* SHPTreeNodeAddShapeId() */
+/************************************************************************/
+
+static int
+SHPTreeNodeAddShapeId( SHPTreeNode * psTreeNode, SHPObject * psObject,
+ int nMaxDepth, int nDimension )
+
+{
+ int i;
+
+/* -------------------------------------------------------------------- */
+/* If there are subnodes, then consider wiether this object */
+/* will fit in them. */
+/* -------------------------------------------------------------------- */
+ if( nMaxDepth > 1 && psTreeNode->nSubNodes > 0 )
+ {
+ for( i = 0; i < psTreeNode->nSubNodes; i++ )
+ {
+ if( SHPCheckObjectContained(psObject, nDimension,
+ psTreeNode->apsSubNode[i]->adfBoundsMin,
+ psTreeNode->apsSubNode[i]->adfBoundsMax))
+ {
+ return SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[i],
+ psObject, nMaxDepth-1,
+ nDimension );
+ }
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Otherwise, consider creating four subnodes if could fit into */
+/* them, and adding to the appropriate subnode. */
+/* -------------------------------------------------------------------- */
+#if MAX_SUBNODE == 4
+ else if( nMaxDepth > 1 && psTreeNode->nSubNodes == 0 )
+ {
+ double adfBoundsMinH1[4], adfBoundsMaxH1[4];
+ double adfBoundsMinH2[4], adfBoundsMaxH2[4];
+ double adfBoundsMin1[4], adfBoundsMax1[4];
+ double adfBoundsMin2[4], adfBoundsMax2[4];
+ double adfBoundsMin3[4], adfBoundsMax3[4];
+ double adfBoundsMin4[4], adfBoundsMax4[4];
+
+ SHPTreeSplitBounds( psTreeNode->adfBoundsMin,
+ psTreeNode->adfBoundsMax,
+ adfBoundsMinH1, adfBoundsMaxH1,
+ adfBoundsMinH2, adfBoundsMaxH2 );
+
+ SHPTreeSplitBounds( adfBoundsMinH1, adfBoundsMaxH1,
+ adfBoundsMin1, adfBoundsMax1,
+ adfBoundsMin2, adfBoundsMax2 );
+
+ SHPTreeSplitBounds( adfBoundsMinH2, adfBoundsMaxH2,
+ adfBoundsMin3, adfBoundsMax3,
+ adfBoundsMin4, adfBoundsMax4 );
+
+ if( SHPCheckObjectContained(psObject, nDimension,
+ adfBoundsMin1, adfBoundsMax1)
+ || SHPCheckObjectContained(psObject, nDimension,
+ adfBoundsMin2, adfBoundsMax2)
+ || SHPCheckObjectContained(psObject, nDimension,
+ adfBoundsMin3, adfBoundsMax3)
+ || SHPCheckObjectContained(psObject, nDimension,
+ adfBoundsMin4, adfBoundsMax4) )
+ {
+ psTreeNode->nSubNodes = 4;
+ psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
+ adfBoundsMax1 );
+ psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
+ adfBoundsMax2 );
+ psTreeNode->apsSubNode[2] = SHPTreeNodeCreate( adfBoundsMin3,
+ adfBoundsMax3 );
+ psTreeNode->apsSubNode[3] = SHPTreeNodeCreate( adfBoundsMin4,
+ adfBoundsMax4 );
+
+ /* recurse back on this node now that it has subnodes */
+ return( SHPTreeNodeAddShapeId( psTreeNode, psObject,
+ nMaxDepth, nDimension ) );
+ }
+ }
+#endif /* MAX_SUBNODE == 4 */
+
+/* -------------------------------------------------------------------- */
+/* Otherwise, consider creating two subnodes if could fit into */
+/* them, and adding to the appropriate subnode. */
+/* -------------------------------------------------------------------- */
+#if MAX_SUBNODE == 2
+ else if( nMaxDepth > 1 && psTreeNode->nSubNodes == 0 )
+ {
+ double adfBoundsMin1[4], adfBoundsMax1[4];
+ double adfBoundsMin2[4], adfBoundsMax2[4];
+
+ SHPTreeSplitBounds( psTreeNode->adfBoundsMin, psTreeNode->adfBoundsMax,
+ adfBoundsMin1, adfBoundsMax1,
+ adfBoundsMin2, adfBoundsMax2 );
+
+ if( SHPCheckObjectContained(psObject, nDimension,
+ adfBoundsMin1, adfBoundsMax1))
+ {
+ psTreeNode->nSubNodes = 2;
+ psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
+ adfBoundsMax1 );
+ psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
+ adfBoundsMax2 );
+
+ return( SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[0], psObject,
+ nMaxDepth - 1, nDimension ) );
+ }
+ else if( SHPCheckObjectContained(psObject, nDimension,
+ adfBoundsMin2, adfBoundsMax2) )
+ {
+ psTreeNode->nSubNodes = 2;
+ psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
+ adfBoundsMax1 );
+ psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
+ adfBoundsMax2 );
+
+ return( SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[1], psObject,
+ nMaxDepth - 1, nDimension ) );
+ }
+ }
+#endif /* MAX_SUBNODE == 2 */
+
+/* -------------------------------------------------------------------- */
+/* If none of that worked, just add it to this nodes list. */
+/* -------------------------------------------------------------------- */
+ psTreeNode->nShapeCount++;
+
+ psTreeNode->panShapeIds =
+ SfRealloc( psTreeNode->panShapeIds,
+ sizeof(int) * psTreeNode->nShapeCount );
+ psTreeNode->panShapeIds[psTreeNode->nShapeCount-1] = psObject->nShapeId;
+
+ if( psTreeNode->papsShapeObj != NULL )
+ {
+ psTreeNode->papsShapeObj =
+ SfRealloc( psTreeNode->papsShapeObj,
+ sizeof(void *) * psTreeNode->nShapeCount );
+ psTreeNode->papsShapeObj[psTreeNode->nShapeCount-1] = NULL;
+ }
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* SHPTreeAddShapeId() */
+/* */
+/* Add a shape to the tree, but don't keep a pointer to the */
+/* object data, just keep the shapeid. */
+/************************************************************************/
+
+int SHPAPI_CALL
+SHPTreeAddShapeId( SHPTree * psTree, SHPObject * psObject )
+
+{
+ return( SHPTreeNodeAddShapeId( psTree->psRoot, psObject,
+ psTree->nMaxDepth, psTree->nDimension ) );
+}
+
+/************************************************************************/
+/* SHPTreeCollectShapesIds() */
+/* */
+/* Work function implementing SHPTreeFindLikelyShapes() on a */
+/* tree node by tree node basis. */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPTreeCollectShapeIds( SHPTree *hTree, SHPTreeNode * psTreeNode,
+ double * padfBoundsMin, double * padfBoundsMax,
+ int * pnShapeCount, int * pnMaxShapes,
+ int ** ppanShapeList )
+
+{
+ int i;
+
+/* -------------------------------------------------------------------- */
+/* Does this node overlap the area of interest at all? If not, */
+/* return without adding to the list at all. */
+/* -------------------------------------------------------------------- */
+ if( !SHPCheckBoundsOverlap( psTreeNode->adfBoundsMin,
+ psTreeNode->adfBoundsMax,
+ padfBoundsMin,
+ padfBoundsMax,
+ hTree->nDimension ) )
+ return;
+
+/* -------------------------------------------------------------------- */
+/* Grow the list to hold the shapes on this node. */
+/* -------------------------------------------------------------------- */
+ if( *pnShapeCount + psTreeNode->nShapeCount > *pnMaxShapes )
+ {
+ *pnMaxShapes = (*pnShapeCount + psTreeNode->nShapeCount) * 2 + 20;
+ *ppanShapeList = (int *)
+ SfRealloc(*ppanShapeList,sizeof(int) * *pnMaxShapes);
+ }
+
+/* -------------------------------------------------------------------- */
+/* Add the local nodes shapeids to the list. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < psTreeNode->nShapeCount; i++ )
+ {
+ (*ppanShapeList)[(*pnShapeCount)++] = psTreeNode->panShapeIds[i];
+ }
+
+/* -------------------------------------------------------------------- */
+/* Recurse to subnodes if they exist. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < psTreeNode->nSubNodes; i++ )
+ {
+ if( psTreeNode->apsSubNode[i] != NULL )
+ SHPTreeCollectShapeIds( hTree, psTreeNode->apsSubNode[i],
+ padfBoundsMin, padfBoundsMax,
+ pnShapeCount, pnMaxShapes,
+ ppanShapeList );
+ }
+}
+
+/************************************************************************/
+/* SHPTreeFindLikelyShapes() */
+/* */
+/* Find all shapes within tree nodes for which the tree node */
+/* bounding box overlaps the search box. The return value is */
+/* an array of shapeids terminated by a -1. The shapeids will */
+/* be in order, as hopefully this will result in faster (more */
+/* sequential) reading from the file. */
+/************************************************************************/
+
+/* helper for qsort */
+static int
+compare_ints( const void * a, const void * b)
+{
+ return (*(int*)a) - (*(int*)b);
+}
+
+int SHPAPI_CALL1(*)
+SHPTreeFindLikelyShapes( SHPTree * hTree,
+ double * padfBoundsMin, double * padfBoundsMax,
+ int * pnShapeCount )
+
+{
+ int *panShapeList=NULL, nMaxShapes = 0;
+
+/* -------------------------------------------------------------------- */
+/* Perform the search by recursive descent. */
+/* -------------------------------------------------------------------- */
+ *pnShapeCount = 0;
+
+ SHPTreeCollectShapeIds( hTree, hTree->psRoot,
+ padfBoundsMin, padfBoundsMax,
+ pnShapeCount, &nMaxShapes,
+ &panShapeList );
+
+/* -------------------------------------------------------------------- */
+/* Sort the id array */
+/* -------------------------------------------------------------------- */
+
+ qsort(panShapeList, *pnShapeCount, sizeof(int), compare_ints);
+
+ return panShapeList;
+}
+
+/************************************************************************/
+/* SHPTreeNodeTrim() */
+/* */
+/* This is the recurve version of SHPTreeTrimExtraNodes() that */
+/* walks the tree cleaning it up. */
+/************************************************************************/
+
+static int SHPTreeNodeTrim( SHPTreeNode * psTreeNode )
+
+{
+ int i;
+
+/* -------------------------------------------------------------------- */
+/* Trim subtrees, and free subnodes that come back empty. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < psTreeNode->nSubNodes; i++ )
+ {
+ if( SHPTreeNodeTrim( psTreeNode->apsSubNode[i] ) )
+ {
+ SHPDestroyTreeNode( psTreeNode->apsSubNode[i] );
+
+ psTreeNode->apsSubNode[i] =
+ psTreeNode->apsSubNode[psTreeNode->nSubNodes-1];
+
+ psTreeNode->nSubNodes--;
+
+ i--; /* process the new occupant of this subnode entry */
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* We should be trimmed if we have no subnodes, and no shapes. */
+/* -------------------------------------------------------------------- */
+ return( psTreeNode->nSubNodes == 0 && psTreeNode->nShapeCount == 0 );
+}
+
+/************************************************************************/
+/* SHPTreeTrimExtraNodes() */
+/* */
+/* Trim empty nodes from the tree. Note that we never trim an */
+/* empty root node. */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPTreeTrimExtraNodes( SHPTree * hTree )
+
+{
+ SHPTreeNodeTrim( hTree->psRoot );
+}
+
diff --git a/src/shapelib/shptreedump.c b/src/shapelib/shptreedump.c
new file mode 100644
index 0000000..c6347fb
--- /dev/null
+++ b/src/shapelib/shptreedump.c
@@ -0,0 +1,430 @@
+/******************************************************************************
+ * $Id: shptreedump.c,v 1.4 2010/07/11 07:57:02 we7u Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Mainline for creating and dumping an ASCII representation of
+ * a quadtree.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: shptreedump.c,v $
+ * Revision 1.4 2010/07/11 07:57:02 we7u
+ * Fixing a few more compiler warnings.
+ *
+ * Revision 1.3 2010/07/11 07:51:03 we7u
+ * Fixing more compiler warnings. There are a few left yet.
+ *
+ * Revision 1.2 2009/06/04 04:25:19 we7u
+ * Getting rid of compiler warnings due to unused variable.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.7 2002/04/10 16:59:12 warmerda
+ * fixed email
+ *
+ * Revision 1.6 1999/11/05 14:12:05 warmerda
+ * updated license terms
+ *
+ * Revision 1.5 1999/06/02 18:24:21 warmerda
+ * added trimming code
+ *
+ * Revision 1.4 1999/06/02 17:56:12 warmerda
+ * added quad'' subnode support for trees
+ *
+ * Revision 1.3 1999/05/18 19:13:13 warmerda
+ * Use fabs() instead of abs().
+ *
+ * Revision 1.2 1999/05/18 19:11:11 warmerda
+ * Added example searching capability
+ *
+ * Revision 1.1 1999/05/18 17:49:20 warmerda
+ * New
+ *
+ */
+
+//static char rcsid[] =
+// "$Id: shptreedump.c,v 1.4 2010/07/11 07:57:02 we7u Exp $";
+
+#include "shapefil.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+static void SHPTreeNodeDump( SHPTree *, SHPTreeNode *, const char *, int );
+static void SHPTreeNodeSearchAndDump( SHPTree *, double *, double * );
+
+/************************************************************************/
+/* Usage() */
+/************************************************************************/
+
+static void Usage(void)
+{
+ printf( "shptreedump [-maxdepth n] [-search xmin ymin xmax ymax]\n"
+ " [-v] shp_file\n" );
+ exit( 1 );
+}
+
+
+
+/************************************************************************/
+/* main() */
+/************************************************************************/
+int main( int argc, char ** argv )
+
+{
+ SHPHandle hSHP;
+ SHPTree *psTree;
+ int nExpandShapes = 0;
+ int nMaxDepth = 0;
+ int nDoSearch = 0;
+ double adfSearchMin[4], adfSearchMax[4];
+
+
+/* -------------------------------------------------------------------- */
+/* Consume flags. */
+/* -------------------------------------------------------------------- */
+ while( argc > 1 )
+ {
+ if( strcmp(argv[1],"-v") == 0 )
+ {
+ nExpandShapes = 1;
+ argv++;
+ argc--;
+ }
+ else if( strcmp(argv[1],"-maxdepth") == 0 && argc > 2 )
+ {
+ nMaxDepth = atoi(argv[2]);
+ argv += 2;
+ argc -= 2;
+ }
+ else if( strcmp(argv[1],"-search") == 0 && argc > 5 )
+ {
+ nDoSearch = 1;
+
+ adfSearchMin[0] = atof(argv[2]);
+ adfSearchMin[1] = atof(argv[3]);
+ adfSearchMax[0] = atof(argv[4]);
+ adfSearchMax[1] = atof(argv[5]);
+
+ adfSearchMin[2] = adfSearchMax[2] = 0.0;
+ adfSearchMin[3] = adfSearchMax[3] = 0.0;
+
+ if( adfSearchMin[0] > adfSearchMax[0]
+ || adfSearchMin[1] > adfSearchMax[1] )
+ {
+ printf( "Min greater than max in search criteria.\n" );
+ Usage();
+ }
+
+ argv += 5;
+ argc -= 5;
+ }
+ else
+ break;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Display a usage message. */
+/* -------------------------------------------------------------------- */
+ if( argc < 2 )
+ {
+ Usage();
+ }
+
+/* -------------------------------------------------------------------- */
+/* Open the passed shapefile. */
+/* -------------------------------------------------------------------- */
+ hSHP = SHPOpen( argv[1], "rb" );
+
+ if( hSHP == NULL )
+ {
+ printf( "Unable to open:%s\n", argv[1] );
+ exit( 1 );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Build a quadtree structure for this file. */
+/* -------------------------------------------------------------------- */
+ psTree = SHPCreateTree( hSHP, 2, nMaxDepth, NULL, NULL );
+
+/* -------------------------------------------------------------------- */
+/* Trim unused nodes from the tree. */
+/* -------------------------------------------------------------------- */
+ SHPTreeTrimExtraNodes( psTree );
+
+/* -------------------------------------------------------------------- */
+/* Dump tree by recursive descent. */
+/* -------------------------------------------------------------------- */
+ if( !nDoSearch )
+ SHPTreeNodeDump( psTree, psTree->psRoot, "", nExpandShapes );
+
+/* -------------------------------------------------------------------- */
+/* or do a search instead. */
+/* -------------------------------------------------------------------- */
+ else
+ SHPTreeNodeSearchAndDump( psTree, adfSearchMin, adfSearchMax );
+
+/* -------------------------------------------------------------------- */
+/* cleanup */
+/* -------------------------------------------------------------------- */
+ SHPDestroyTree( psTree );
+
+ SHPClose( hSHP );
+
+#ifdef USE_DBMALLOC
+ malloc_dump(2);
+#endif
+
+ exit( 0 );
+}
+
+/************************************************************************/
+/* EmitCoordinate() */
+/************************************************************************/
+
+static void EmitCoordinate( double * padfCoord, int nDimension )
+
+{
+ const char *pszFormat;
+
+ if( fabs(padfCoord[0]) < 180 && fabs(padfCoord[1]) < 180 )
+ pszFormat = "%.9f";
+ else
+ pszFormat = "%.2f";
+
+ printf( pszFormat, padfCoord[0] );
+ printf( "," );
+ printf( pszFormat, padfCoord[1] );
+
+ if( nDimension > 2 )
+ {
+ printf( "," );
+ printf( pszFormat, padfCoord[2] );
+ }
+ if( nDimension > 3 )
+ {
+ printf( "," );
+ printf( pszFormat, padfCoord[3] );
+ }
+}
+
+/************************************************************************/
+/* EmitShape() */
+/************************************************************************/
+
+static void EmitShape( SHPObject * psObject, const char * pszPrefix,
+ int nDimension )
+
+{
+ int i;
+
+ printf( "%s( Shape\n", pszPrefix );
+ printf( "%s ShapeId = %d\n", pszPrefix, psObject->nShapeId );
+
+ printf( "%s Min = (", pszPrefix );
+ EmitCoordinate( &(psObject->dfXMin), nDimension );
+ printf( ")\n" );
+
+ printf( "%s Max = (", pszPrefix );
+ EmitCoordinate( &(psObject->dfXMax), nDimension );
+ printf( ")\n" );
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ double adfVertex[4];
+
+ printf( "%s Vertex[%d] = (", pszPrefix, i );
+
+ adfVertex[0] = psObject->padfX[i];
+ adfVertex[1] = psObject->padfY[i];
+ adfVertex[2] = psObject->padfZ[i];
+ adfVertex[3] = psObject->padfM[i];
+
+ EmitCoordinate( adfVertex, nDimension );
+ printf( ")\n" );
+ }
+ printf( "%s)\n", pszPrefix );
+}
+
+/************************************************************************/
+/* SHPTreeNodeDump() */
+/* */
+/* Dump a tree node in a readable form. */
+/************************************************************************/
+
+static void SHPTreeNodeDump( SHPTree * psTree,
+ SHPTreeNode * psTreeNode,
+ const char * pszPrefix,
+ int nExpandShapes )
+
+{
+ char szNextPrefix[150];
+ int i;
+
+ strcpy( szNextPrefix, pszPrefix );
+ if( strlen(pszPrefix) < sizeof(szNextPrefix) - 3 )
+ strcat( szNextPrefix, " " );
+
+ printf( "%s( SHPTreeNode\n", pszPrefix );
+
+/* -------------------------------------------------------------------- */
+/* Emit the bounds. */
+/* -------------------------------------------------------------------- */
+ printf( "%s Min = (", pszPrefix );
+ EmitCoordinate( psTreeNode->adfBoundsMin, psTree->nDimension );
+ printf( ")\n" );
+
+ printf( "%s Max = (", pszPrefix );
+ EmitCoordinate( psTreeNode->adfBoundsMax, psTree->nDimension );
+ printf( ")\n" );
+
+/* -------------------------------------------------------------------- */
+/* Emit the list of shapes on this node. */
+/* -------------------------------------------------------------------- */
+ if( nExpandShapes )
+ {
+ printf( "%s Shapes(%d):\n", pszPrefix, psTreeNode->nShapeCount );
+ for( i = 0; i < psTreeNode->nShapeCount; i++ )
+ {
+ SHPObject *psObject;
+
+ psObject = SHPReadObject( psTree->hSHP,
+ psTreeNode->panShapeIds[i] );
+ assert( psObject != NULL );
+ if( psObject != NULL )
+ {
+ EmitShape( psObject, szNextPrefix, psTree->nDimension );
+ }
+
+ SHPDestroyObject( psObject );
+ }
+ }
+ else
+ {
+ printf( "%s Shapes(%d): ", pszPrefix, psTreeNode->nShapeCount );
+ for( i = 0; i < psTreeNode->nShapeCount; i++ )
+ {
+ printf( "%d ", psTreeNode->panShapeIds[i] );
+ }
+ printf( "\n" );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Emit subnodes. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < psTreeNode->nSubNodes; i++ )
+ {
+ if( psTreeNode->apsSubNode[i] != NULL )
+ SHPTreeNodeDump( psTree, psTreeNode->apsSubNode[i],
+ szNextPrefix, nExpandShapes );
+ }
+
+ printf( "%s)\n", pszPrefix );
+
+ return;
+}
+
+/************************************************************************/
+/* SHPTreeNodeSearchAndDump() */
+/************************************************************************/
+
+static void SHPTreeNodeSearchAndDump( SHPTree * hTree,
+ double *padfBoundsMin,
+ double *padfBoundsMax )
+
+{
+ int *panHits, nShapeCount, i;
+
+/* -------------------------------------------------------------------- */
+/* Perform the search for likely candidates. These are shapes */
+/* that fall into a tree node whose bounding box intersects our */
+/* area of interest. */
+/* -------------------------------------------------------------------- */
+ panHits = SHPTreeFindLikelyShapes( hTree, padfBoundsMin, padfBoundsMax,
+ &nShapeCount );
+
+/* -------------------------------------------------------------------- */
+/* Read all of these shapes, and establish whether the shape's */
+/* bounding box actually intersects the area of interest. Note */
+/* that the bounding box could intersect the area of interest, */
+/* and the shape itself still not cross it but we don't try to */
+/* address that here. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < nShapeCount; i++ )
+ {
+ SHPObject *psObject;
+
+ psObject = SHPReadObject( hTree->hSHP, panHits[i] );
+ if( psObject == NULL )
+ continue;
+
+ if( !SHPCheckBoundsOverlap( padfBoundsMin, padfBoundsMax,
+ &(psObject->dfXMin),
+ &(psObject->dfXMax),
+ hTree->nDimension ) )
+ {
+ printf( "Shape %d: not in area of interest, but fetched.\n",
+ panHits[i] );
+ }
+ else
+ {
+ printf( "Shape %d: appears to be in area of interest.\n",
+ panHits[i] );
+ }
+
+ SHPDestroyObject( psObject );
+ }
+
+ if( nShapeCount == 0 )
+ printf( "No shapes found in search.\n" );
+}
diff --git a/src/shapelib/shputils.c b/src/shapelib/shputils.c
new file mode 100644
index 0000000..4f5c80b
--- /dev/null
+++ b/src/shapelib/shputils.c
@@ -0,0 +1,1124 @@
+/******************************************************************************
+ * $Id: shputils.c,v 1.7 2010/07/11 20:30:00 we7u Exp $
+ *
+ * Project: Shapelib
+ * Purpose:
+ * Altered "shpdump" and "dbfdump" to allow two files to be appended.
+ * Other Functions:
+ * Selecting from the DBF before the write occurs.
+ * Change the UNITS between Feet and Meters and Shift X,Y.
+ * Clip and Erase boundary. The program only passes thru the
+ * data once.
+ *
+ * Bill Miller North Carolina - Department of Transporation
+ * Feb. 1997 -- bmiller at dot.state.nc.us
+ * There was not a lot of time to debug hidden problems;
+ * And the code is not very well organized or documented.
+ * The clip/erase function was not well tested.
+ * Oct. 2000 -- bmiller at dot.state.nc.us
+ * Fixed the problem when select is using numbers
+ * larger than short integer. It now reads long integer.
+ * NOTE: DBF files created using windows NT will read as a string with
+ * a length of 381 characters. This is a bug in "dbfopen".
+ *
+ *
+ * Author: Bill Miller (bmiller at dot.state.nc.us)
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: shputils.c,v $
+ * Revision 1.7 2010/07/11 20:30:00 we7u
+ * More minor tweaks to get rid of compiler warnings. Of particular note are
+ * some TODO entries added to a couple of files for two enumerated values that
+ * weren't being handled in "switch" statements. There still isn't any code
+ * for those case statements, but the compiler warnings are gone.
+ *
+ * Revision 1.6 2010/07/11 08:01:27 we7u
+ * Adding some braces for some "if" statements so that the enclosed else
+ * clause won't be ambiguous.
+ *
+ * Revision 1.5 2010/07/11 07:51:03 we7u
+ * Fixing more compiler warnings. There are a few left yet.
+ *
+ * Revision 1.4 2010/07/11 07:24:37 we7u
+ * Fixing multiple minor warnings with Shapelib. Still plenty left.
+ *
+ * Revision 1.3 2010/07/11 06:22:55 we7u
+ * Setting up the rest of shapelib and shapelib/contrib so that everything
+ * compiles. Had to add an include to shputils.c and add a "1" parameter to
+ * exit() in one spot.
+ *
+ * Revision 1.2 2009/06/04 04:25:19 we7u
+ * Getting rid of compiler warnings due to unused variable.
+ *
+ * Revision 1.1 2006/11/10 21:48:10 tvrusso
+ * Add shapelib as an internal library, and use it if we don't find an external
+ * one.
+ *
+ * Make a loud warning if we do so, because the result of this is that we'll
+ * have a bigger executable.
+ *
+ * This commit is bigger than it needs to be, because it includes all of
+ * shapelib, including the contrib directory.
+ *
+ * Added an automake-generated Makefile for this thing.
+ *
+ * Builds only a static library, and calls it "libshape.a" instead of
+ * "libshp.a" so that if we use ask to use the static one while there is
+ * also an external one installed, the linker doesn't pull in the shared
+ * library one unbidden.
+ *
+ * This stuff can be tested on a system with libshp installed by configuring with
+ * "--without-shapelib"
+ *
+ * I will be removing Makefile.in because it's not supposed to be in CVS. My
+ * mistake.
+ *
+ * Revision 1.7 2003/02/25 17:20:22 warmerda
+ * Set psCShape to NULL after SHPDestroyObject() to avoid multi-frees of
+ * the same memory ... as submitted by Fred Fox.
+ *
+ * Revision 1.6 2001/08/28 13:57:14 warmerda
+ * fixed DBFAddField return value check
+ *
+ * Revision 1.5 2000/11/02 13:52:48 warmerda
+ * major upgrade from Bill Miller
+ *
+ * Revision 1.4 1999/11/05 14:12:05 warmerda
+ * updated license terms
+ *
+ * Revision 1.3 1998/12/03 15:47:39 warmerda
+ * Did a bunch of rewriting to make it work with the V1.2 API.
+ *
+ * Revision 1.2 1998/06/18 01:19:49 warmerda
+ * Made C++ compilable.
+ *
+ * Revision 1.1 1997/05/27 20:40:27 warmerda
+ * Initial revision
+ */
+
+//static char rcsid[] =
+// "$Id: shputils.c,v 1.7 2010/07/11 20:30:00 we7u Exp $";
+
+#include "shapefil.h"
+#include "string.h"
+#include <stdlib.h>
+
+#ifndef FALSE
+# define FALSE 0
+# define TRUE 1
+#endif
+
+char infile[80], outfile[80], temp[400];
+
+/* Variables for shape files */
+SHPHandle hSHP;
+SHPHandle hSHPappend;
+int nShapeType, nEntities, iPart;
+int nShapeTypeAppend, nEntitiesAppend;
+SHPObject *psCShape;
+double adfBoundsMin[4], adfBoundsMax[4];
+
+
+/* Variables for DBF files */
+DBFHandle hDBF;
+DBFHandle hDBFappend;
+
+DBFFieldType iType;
+DBFFieldType jType;
+
+char iszTitle[12];
+char jszTitle[12];
+
+int *pt;
+char iszFormat[32], iszField[1024];
+char jszFormat[32], jszField[1024];
+int i, ti, iWidth, iDecimals, iRecord;
+int j, tj, jWidth, jDecimals, jRecord;
+int found, newdbf;
+
+
+void openfiles(void);
+void setext(char *pt, char *ext);
+int strncasecmp2(char *s1, char *s2, int n);
+void mergefields(void);
+void findselect(void);
+void showitems(void);
+int selectrec(void);
+void check_theme_bnd(void);
+int clip_boundary(void);
+void error(void);
+int findunit(char *unit);
+
+
+/* -------------------------------------------------------------------- */
+/* Variables for the DESCRIBE function */
+/* -------------------------------------------------------------------- */
+ int ilist = FALSE, iall = FALSE;
+/* -------------------------------------------------------------------- */
+/* Variables for the SELECT function */
+/* -------------------------------------------------------------------- */
+ int found = FALSE, newdbf = FALSE;
+ char selectitem[40], *cpt;
+ long int selectvalues[150], selcount=0;
+ int iselect = FALSE, iselectitem = -1;
+ int iunselect = FALSE;
+
+/* -------------------------------------------------------------------- */
+/* Variables for the CLIP and ERASE functions */
+/* -------------------------------------------------------------------- */
+ double cxmin, cymin, cxmax, cymax;
+ int iclip = FALSE, ierase = FALSE;
+ int itouch = FALSE, iinside = FALSE, icut = FALSE;
+ int ibound = FALSE, ipoly = FALSE;
+ char clipfile[80];
+
+/* -------------------------------------------------------------------- */
+/* Variables for the FACTOR function */
+/* -------------------------------------------------------------------- */
+ double infactor,outfactor,factor = 0; /* NO FACTOR */
+ int iunit = FALSE;
+ int ifactor = FALSE;
+
+
+/* -------------------------------------------------------------------- */
+/* Variables for the SHIFT function */
+/* -------------------------------------------------------------------- */
+ double xshift = 0, yshift = 0; /* NO SHIFT */
+
+int main( int argc, char ** argv )
+{
+
+/* -------------------------------------------------------------------- */
+/* Check command line usage. */
+/* -------------------------------------------------------------------- */
+ if( argc < 2 ) error();
+ strcpy(infile, argv[1]);
+ if (argc > 2) {
+ strcpy(outfile,argv[2]);
+ if (strncasecmp2(outfile, "LIST",0) == 0) { ilist = TRUE; }
+ if (strncasecmp2(outfile, "ALL",0) == 0) { iall = TRUE; }
+ }
+ if (ilist || iall || argc == 2 ) {
+ setext(infile, "shp");
+ printf("DESCRIBE: %s\n",infile);
+ strcpy(outfile,"");
+ }
+/* -------------------------------------------------------------------- */
+/* Look for other functions on the command line. (SELECT, UNIT) */
+/* -------------------------------------------------------------------- */
+ for (i = 3; i < argc; i++)
+ {
+ if ((strncasecmp2(argv[i], "SEL",3) == 0) ||
+ (strncasecmp2(argv[i], "UNSEL",5) == 0))
+ {
+ if (strncasecmp2(argv[i], "UNSEL",5) == 0) iunselect=TRUE;
+ i++;
+ if (i >= argc) error();
+ strcpy(selectitem,argv[i]);
+ i++;
+ if (i >= argc) error();
+ selcount=0;
+ strcpy(temp,argv[i]);
+ cpt=temp;
+ tj = atoi(cpt);
+ ti = 0;
+ while (tj>0) {
+ selectvalues[selcount] = tj;
+ while( *cpt >= '0' && *cpt <= '9')
+ cpt++;
+ while( *cpt > '\0' && (*cpt < '0' || *cpt > '9') )
+ cpt++;
+ tj=atoi(cpt);
+ selcount++;
+ }
+ iselect=TRUE;
+ } /*** End SEL & UNSEL ***/
+ else
+ if ((strncasecmp2(argv[i], "CLIP",4) == 0) ||
+ (strncasecmp2(argv[i], "ERASE",5) == 0))
+ {
+ if (strncasecmp2(argv[i], "ERASE",5) == 0) ierase=TRUE;
+ i++;
+ if (i >= argc) error();
+ strcpy(clipfile,argv[i]);
+ sscanf(argv[i],"%lf",&cxmin);
+ i++;
+ if (i >= argc) error();
+ if (strncasecmp2(argv[i], "BOUND",5) == 0) {
+ setext(clipfile, "shp");
+ hSHP = SHPOpen( clipfile, "rb" );
+ if( hSHP == NULL )
+ {
+ printf( "ERROR: Unable to open the clip shape file:%s\n", clipfile );
+ exit( 1 );
+ }
+ SHPGetInfo( hSHPappend, NULL, NULL,
+ adfBoundsMin, adfBoundsMax );
+ cxmin = adfBoundsMin[0];
+ cymin = adfBoundsMin[1];
+ cxmax = adfBoundsMax[0];
+ cymax = adfBoundsMax[1];
+ printf("Theme Clip Boundary: (%lf,%lf) - (%lf,%lf)\n",
+ cxmin, cymin, cxmax, cymax);
+ ibound=TRUE;
+ } else { /*** xmin,ymin,xmax,ymax ***/
+ sscanf(argv[i],"%lf",&cymin);
+ i++;
+ if (i >= argc) error();
+ sscanf(argv[i],"%lf",&cxmax);
+ i++;
+ if (i >= argc) error();
+ sscanf(argv[i],"%lf",&cymax);
+ printf("Clip Box: (%lf,%lf) - (%lf,%lf)\n",cxmin, cymin, cxmax, cymax);
+ }
+ i++;
+ if (i >= argc) error();
+ if (strncasecmp2(argv[i], "CUT",3) == 0) icut=TRUE;
+ else if (strncasecmp2(argv[i], "TOUCH",5) == 0) itouch=TRUE;
+ else if (strncasecmp2(argv[i], "INSIDE",6) == 0) iinside=TRUE;
+ else error();
+ iclip=TRUE;
+ } /*** End CLIP & ERASE ***/
+ else if (strncasecmp2(argv[i], "FACTOR",0) == 0)
+ {
+ i++;
+ if (i >= argc) error();
+ infactor=findunit(argv[i]);
+ if (infactor == 0) error();
+ iunit=TRUE;
+ i++;
+ if (i >= argc) error();
+ outfactor=findunit(argv[i]);
+ if (outfactor == 0)
+ {
+ sscanf(argv[i],"%lf",&factor);
+ if (factor == 0) error();
+ }
+ if (factor == 0)
+ {
+ if (infactor ==0)
+ { puts("ERROR: Input unit must be defined before output unit"); exit(1); }
+ factor=infactor/outfactor;
+ }
+ printf("Output file coordinate values will be factored by %lg\n",factor);
+ ifactor=(factor != 1); /* True if a valid factor */
+ } /*** End FACTOR ***/
+ else if (strncasecmp2(argv[i],"SHIFT",5) == 0)
+ {
+ i++;
+ if (i >= argc) error();
+ sscanf(argv[i],"%lf",&xshift);
+ i++;
+ if (i >= argc) error();
+ sscanf(argv[i],"%lf",&yshift);
+ iunit=TRUE;
+ printf("X Shift: %lg Y Shift: %lg\n",xshift,yshift);
+ } /*** End SHIFT ***/
+ else {
+ printf("ERROR: Unknown function %s\n",argv[i]); error();
+ }
+ }
+/* -------------------------------------------------------------------- */
+/* If there is no data in this file let the user know. */
+/* -------------------------------------------------------------------- */
+ openfiles(); /* Open the infile and the outfile for shape and dbf. */
+ if( DBFGetFieldCount(hDBF) == 0 )
+ {
+ puts( "There are no fields in this table!" );
+ exit( 1 );
+ }
+/* -------------------------------------------------------------------- */
+/* Print out the file bounds. */
+/* -------------------------------------------------------------------- */
+ iRecord = DBFGetRecordCount( hDBF );
+ SHPGetInfo( hSHP, NULL, NULL, adfBoundsMin, adfBoundsMax );
+
+ printf( "Input Bounds: (%lg,%lg) - (%lg,%lg) Entities: %d DBF: %d\n",
+ adfBoundsMin[0], adfBoundsMin[1],
+ adfBoundsMax[0], adfBoundsMax[1],
+ nEntities, iRecord );
+
+ if (strcmp(outfile,"") == 0) /* Describe the shapefile; No other functions */
+ {
+ ti = DBFGetFieldCount( hDBF );
+ showitems();
+ exit(0);
+ }
+
+ if (iclip) check_theme_bnd();
+
+ jRecord = DBFGetRecordCount( hDBFappend );
+ SHPGetInfo( hSHPappend, NULL, NULL, adfBoundsMin, adfBoundsMax );
+ if (nEntitiesAppend == 0)
+ puts("New Output File\n");
+ else
+ printf( "Append Bounds: (%lg,%lg)-(%lg,%lg) Entities: %d DBF: %d\n",
+ adfBoundsMin[0], adfBoundsMin[1],
+ adfBoundsMax[0], adfBoundsMax[1],
+ nEntitiesAppend, jRecord );
+
+/* -------------------------------------------------------------------- */
+/* Find matching fields in the append file or add new items. */
+/* -------------------------------------------------------------------- */
+ mergefields();
+/* -------------------------------------------------------------------- */
+/* Find selection field if needed. */
+/* -------------------------------------------------------------------- */
+ if (iselect) findselect();
+
+/* -------------------------------------------------------------------- */
+/* Read all the records */
+/* -------------------------------------------------------------------- */
+ jRecord = DBFGetRecordCount( hDBFappend );
+ for( iRecord = 0; iRecord < nEntities; iRecord++) /** DBFGetRecordCount(hDBF) **/
+ {
+/* -------------------------------------------------------------------- */
+/* SELECT for values if needed. (Can the record be skipped.) */
+/* -------------------------------------------------------------------- */
+ if (iselect)
+ if (selectrec() == 0) goto SKIP_RECORD; /** SKIP RECORD **/
+
+/* -------------------------------------------------------------------- */
+/* Read a Shape record */
+/* -------------------------------------------------------------------- */
+ psCShape = SHPReadObject( hSHP, iRecord );
+
+/* -------------------------------------------------------------------- */
+/* Clip coordinates of shapes if needed. */
+/* -------------------------------------------------------------------- */
+ if (iclip)
+ if (clip_boundary() == 0) goto SKIP_RECORD; /** SKIP RECORD **/
+
+/* -------------------------------------------------------------------- */
+/* Read a DBF record and copy each field. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < DBFGetFieldCount(hDBF); i++ )
+ {
+/* -------------------------------------------------------------------- */
+/* Store the record according to the type and formatting */
+/* information implicit in the DBF field description. */
+/* -------------------------------------------------------------------- */
+ if (pt[i] > -1) /* if the current field exists in output file */
+ {
+ switch( DBFGetFieldInfo( hDBF, i, NULL, &iWidth, &iDecimals ) )
+ {
+ case FTString:
+ DBFWriteStringAttribute(hDBFappend, jRecord, pt[i],
+ (DBFReadStringAttribute( hDBF, iRecord, i )) );
+ break;
+
+ case FTInteger:
+ DBFWriteIntegerAttribute(hDBFappend, jRecord, pt[i],
+ (DBFReadIntegerAttribute( hDBF, iRecord, i )) );
+ break;
+
+ case FTDouble:
+ DBFWriteDoubleAttribute(hDBFappend, jRecord, pt[i],
+ (DBFReadDoubleAttribute( hDBF, iRecord, i )) );
+ break;
+
+ case FTLogical:
+// TODO: Add code here
+ break;
+
+ case FTInvalid:
+// TODO: Add code here
+ break;
+
+ }
+ }
+ }
+ jRecord++;
+/* -------------------------------------------------------------------- */
+/* Change FACTOR and SHIFT coordinates of shapes if needed. */
+/* -------------------------------------------------------------------- */
+ if (iunit)
+ {
+ for( j = 0; j < psCShape->nVertices; j++ )
+ {
+ psCShape->padfX[j] = psCShape->padfX[j] * factor + xshift;
+ psCShape->padfY[j] = psCShape->padfY[j] * factor + yshift;
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Write the Shape record after recomputing current extents. */
+/* -------------------------------------------------------------------- */
+ SHPComputeExtents( psCShape );
+ SHPWriteObject( hSHPappend, -1, psCShape );
+
+ SKIP_RECORD:
+ SHPDestroyObject( psCShape );
+ psCShape = NULL;
+ j=0;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Print out the # of Entities and the file bounds. */
+/* -------------------------------------------------------------------- */
+ jRecord = DBFGetRecordCount( hDBFappend );
+ SHPGetInfo( hSHPappend, &nEntitiesAppend, &nShapeTypeAppend,
+ adfBoundsMin, adfBoundsMax );
+
+ printf( "Output Bounds: (%lg,%lg) - (%lg,%lg) Entities: %d DBF: %d\n\n",
+ adfBoundsMin[0], adfBoundsMin[1],
+ adfBoundsMax[0], adfBoundsMax[1],
+ nEntitiesAppend, jRecord );
+
+/* -------------------------------------------------------------------- */
+/* Close the both shapefiles. */
+/* -------------------------------------------------------------------- */
+ SHPClose( hSHP );
+ SHPClose( hSHPappend );
+ DBFClose( hDBF );
+ DBFClose( hDBFappend );
+ if (nEntitiesAppend == 0) {
+ puts("Remove the output files.");
+ setext(outfile, "dbf");
+ remove(outfile);
+ setext(outfile, "shp");
+ remove(outfile);
+ setext(outfile, "shx");
+ remove(outfile);
+ }
+ return( 0 );
+}
+
+
+/************************************************************************/
+/* openfiles() */
+/************************************************************************/
+
+void openfiles() {
+/* -------------------------------------------------------------------- */
+/* Open the DBF file. */
+/* -------------------------------------------------------------------- */
+ setext(infile, "dbf");
+ hDBF = DBFOpen( infile, "rb" );
+ if( hDBF == NULL )
+ {
+ printf( "ERROR: Unable to open the input DBF:%s\n", infile );
+ exit( 1 );
+ }
+/* -------------------------------------------------------------------- */
+/* Open the append DBF file. */
+/* -------------------------------------------------------------------- */
+ if (strcmp(outfile,"")) {
+ setext(outfile, "dbf");
+ hDBFappend = DBFOpen( outfile, "rb+" );
+ newdbf=0;
+ if( hDBFappend == NULL )
+ {
+ newdbf=1;
+ hDBFappend = DBFCreate( outfile );
+ if( hDBFappend == NULL )
+ {
+ printf( "ERROR: Unable to open the append DBF:%s\n", outfile );
+ exit( 1 );
+ }
+ }
+ }
+/* -------------------------------------------------------------------- */
+/* Open the passed shapefile. */
+/* -------------------------------------------------------------------- */
+ setext(infile, "shp");
+ hSHP = SHPOpen( infile, "rb" );
+
+ if( hSHP == NULL )
+ {
+ printf( "ERROR: Unable to open the input shape file:%s\n", infile );
+ exit( 1 );
+ }
+
+ SHPGetInfo( hSHP, &nEntities, &nShapeType, NULL, NULL );
+
+/* -------------------------------------------------------------------- */
+/* Open the passed append shapefile. */
+/* -------------------------------------------------------------------- */
+ if (strcmp(outfile,"")) {
+ setext(outfile, "shp");
+ hSHPappend = SHPOpen( outfile, "rb+" );
+
+ if( hSHPappend == NULL )
+ {
+ hSHPappend = SHPCreate( outfile, nShapeType );
+ if( hSHPappend == NULL )
+ {
+ printf( "ERROR: Unable to open the append shape file:%s\n",
+ outfile );
+ exit( 1 );
+ }
+ }
+ SHPGetInfo( hSHPappend, &nEntitiesAppend, &nShapeTypeAppend,
+ NULL, NULL );
+
+ if (nShapeType != nShapeTypeAppend)
+ {
+ puts( "ERROR: Input and Append shape files are of different types.");
+ exit( 1 );
+ }
+ }
+}
+
+/* -------------------------------------------------------------------- */
+/* Change the extension. If there is any extension on the */
+/* filename, strip it off and add the new extension */
+/* -------------------------------------------------------------------- */
+void setext(char *pt, char *ext)
+{
+int i;
+ for( i = strlen(pt)-1;
+ i > 0 && pt[i] != '.' && pt[i] != '/' && pt[i] != '\\';
+ i-- ) {}
+
+ if( pt[i] == '.' )
+ pt[i] = '\0';
+
+ strcat(pt,".");
+ strcat(pt,ext);
+}
+
+
+
+/* -------------------------------------------------------------------- */
+/* Find matching fields in the append file. */
+/* Output file must have zero records to add any new fields. */
+/* -------------------------------------------------------------------- */
+void mergefields()
+{
+ int i,j;
+ ti = DBFGetFieldCount( hDBF );
+ tj = DBFGetFieldCount( hDBFappend );
+ /* Create a pointer array for the max # of fields in the output file */
+ pt = (int *) malloc( (ti+tj+1) * sizeof(int) );
+
+ for( i = 0; i < ti; i++ )
+ {
+ pt[i]= -1; /* Initial pt values to -1 */
+ }
+ /* DBF must be empty before adding items */
+ jRecord = DBFGetRecordCount( hDBFappend );
+ for( i = 0; i < ti; i++ )
+ {
+ iType = DBFGetFieldInfo( hDBF, i, iszTitle, &iWidth, &iDecimals );
+ found=FALSE;
+ {
+ for( j = 0; j < tj; j++ ) /* Search all field names for a match */
+ {
+ jType = DBFGetFieldInfo( hDBFappend, j, jszTitle, &jWidth, &jDecimals );
+ if (iType == jType && (strcmp(iszTitle, jszTitle) == 0) )
+ {
+ if (found || newdbf)
+ {
+ if (i == j) pt[i]=j;
+ printf("Warning: Duplicate field name found (%s)\n",iszTitle);
+ /* Duplicate field name
+ (Try to guess the correct field by position) */
+ }
+ else
+ {
+ pt[i]=j; found=TRUE;
+ }
+ }
+ }
+ }
+
+ if (pt[i] == -1 && (! found) ) /* Try to force into an existing field */
+ { /* Ignore the field name, width, and decimal places */
+ jType = DBFGetFieldInfo( hDBFappend, j, jszTitle, &jWidth, &jDecimals );
+ if (iType == jType)
+ {
+ pt[i]=i; found=1;
+ }
+ }
+ if ( (! found) && jRecord == 0) /* Add missing field to the append table */
+ { /* The output DBF must be is empty */
+ pt[i]=tj;
+ tj++;
+ if( DBFAddField( hDBFappend, iszTitle, iType, iWidth, iDecimals )
+ == -1 )
+ {
+ printf( "Warning: DBFAddField(%s, TYPE:%d, WIDTH:%d DEC:%d, ITEM#:%d of %d) failed.\n",
+ iszTitle, iType, iWidth, iDecimals, (i+1), (ti+1) );
+ pt[i]=-1;
+ }
+ }
+ }
+}
+
+
+void findselect()
+{
+ /* Find the select field name */
+ iselectitem = -1;
+ for( i = 0; i < ti && iselectitem < 0; i++ )
+ {
+ iType = DBFGetFieldInfo( hDBF, i, iszTitle, &iWidth, &iDecimals );
+ if (strncasecmp2(iszTitle, selectitem, 0) == 0) iselectitem = i;
+ }
+ if (iselectitem == -1)
+ {
+ printf("Warning: Item not found for selection (%s)\n",selectitem);
+ iselect = FALSE;
+ iall = FALSE;
+ showitems();
+ printf("Continued... (Selecting entire file)\n");
+ }
+ /* Extract all of the select values (by field type) */
+
+}
+
+void showitems()
+{
+char stmp[40],slow[40],shigh[40];
+double dtmp,dlow,dhigh,dsum,mean;
+long int itmp,ilow,ihigh,isum;
+long int maxrec;
+char *pt;
+
+ printf("Available Items: (%d)",ti);
+ maxrec = DBFGetRecordCount(hDBF);
+ if (maxrec > 5000 && ! iall)
+ { maxrec=5000; printf(" ** ESTIMATED RANGES (MEAN) For more records use \"All\""); }
+ else { printf(" RANGES (MEAN)"); }
+
+ for( i = 0; i < ti; i++ )
+ {
+ switch( DBFGetFieldInfo( hDBF, i, iszTitle, &iWidth, &iDecimals ) )
+ {
+ case FTString:
+ strcpy(slow, "~");
+ strcpy(shigh,"\0");
+ printf("\n String %3d %-16s",iWidth,iszTitle);
+ for( iRecord = 0; iRecord < maxrec; iRecord++ ) {
+ strncpy(stmp,DBFReadStringAttribute( hDBF, iRecord, i ),39);
+ if (strcmp(stmp,"!!") > 0) {
+ if (strncasecmp2(stmp,slow,0) < 0) strncpy(slow, stmp,39);
+ if (strncasecmp2(stmp,shigh,0) > 0) strncpy(shigh,stmp,39);
+ }
+ }
+ pt=slow+strlen(slow)-1;
+ while(*pt == ' ') { *pt='\0'; pt--; }
+ pt=shigh+strlen(shigh)-1;
+ while(*pt == ' ') { *pt='\0'; pt--; }
+ if (strncasecmp2(slow,shigh,0) < 0) printf("%s to %s",slow,shigh);
+ else if (strncasecmp2(slow,shigh,0) == 0) printf("= %s",slow);
+ else printf("No Values");
+ break;
+ case FTInteger:
+ printf("\n Integer %3d %-16s",iWidth,iszTitle);
+ ilow = 1999999999;
+ ihigh= -1999999999;
+ isum = 0;
+ for( iRecord = 0; iRecord < maxrec; iRecord++ ) {
+ itmp = DBFReadIntegerAttribute( hDBF, iRecord, i );
+ if (ilow > itmp) ilow = itmp;
+ if (ihigh < itmp) ihigh = itmp;
+ isum = isum + itmp;
+ }
+ mean=isum/maxrec;
+ if (ilow < ihigh) printf("%ld to %ld \t(%.1f)",ilow,ihigh,mean);
+ else if (ilow == ihigh) printf("= %ld",ilow);
+ else printf("No Values");
+ break;
+
+ case FTDouble:
+ printf("\n Real %3d,%d %-16s",iWidth,iDecimals,iszTitle);
+ dlow = 999999999999999.0;
+ dhigh= -999999999999999.0;
+ dsum = 0;
+ for( iRecord = 0; iRecord < maxrec; iRecord++ ) {
+ dtmp = DBFReadDoubleAttribute( hDBF, iRecord, i );
+ if (dlow > dtmp) dlow = dtmp;
+ if (dhigh < dtmp) dhigh = dtmp;
+ dsum = dsum + dtmp;
+ }
+ mean=dsum/maxrec;
+ sprintf(stmp,"%%.%df to %%.%df \t(%%.%df)",iDecimals,iDecimals,iDecimals);
+ if (dlow < dhigh) printf(stmp,dlow,dhigh,mean);
+ else if (dlow == dhigh) {
+ sprintf(stmp,"= %%.%df",iDecimals);
+ printf(stmp,dlow);
+ }
+ else printf("No Values");
+ break;
+
+ case FTLogical:
+// TODO: Add code here
+ break;
+
+ case FTInvalid:
+// TODO: Add code here
+ break;
+
+ }
+
+ }
+ printf("\n");
+}
+
+int selectrec()
+{
+long int value, ty;
+
+ ty = DBFGetFieldInfo( hDBF, iselectitem, NULL, &iWidth, &iDecimals);
+ switch(ty)
+ {
+ case FTString:
+ puts("Invalid Item");
+ iselect=FALSE;
+ break;
+ case FTInteger:
+ value = DBFReadIntegerAttribute( hDBF, iRecord, iselectitem );
+ for (j = 0; j<selcount; j++)
+ {
+ if (selectvalues[j] == value)
+ {
+ if (iunselect) return(0); /* Keep this record */
+ else return(1); /* Skip this record */
+ }
+ }
+ break;
+ case FTDouble:
+ puts("Invalid Item");
+ iselect=FALSE;
+ break;
+ }
+ if (iunselect) return(1); /* Skip this record */
+ else return(0); /* Keep this record */
+}
+
+
+void check_theme_bnd()
+{
+ if ( (adfBoundsMin[0] >= cxmin) && (adfBoundsMax[0] <= cxmax) &&
+ (adfBoundsMin[1] >= cymin) && (adfBoundsMax[1] <= cymax) )
+ { /** Theme is totally inside clip area **/
+ if (ierase) nEntities=0; /** SKIP THEME **/
+ else iclip=FALSE; /** WRITE THEME (Clip not needed) **/
+ }
+
+ if ( ( (adfBoundsMin[0] < cxmin) && (adfBoundsMax[0] < cxmin) ) ||
+ ( (adfBoundsMin[1] < cymin) && (adfBoundsMax[1] < cymin) ) ||
+ ( (adfBoundsMin[0] > cxmax) && (adfBoundsMax[0] > cxmax) ) ||
+ ( (adfBoundsMin[1] > cymax) && (adfBoundsMax[1] > cymax) ) )
+ { /** Theme is totally outside clip area **/
+ if (ierase) iclip=FALSE; /** WRITE THEME (Clip not needed) **/
+ else nEntities=0; /** SKIP THEME **/
+ }
+
+ if (nEntities == 0)
+ puts("WARNING: Theme is outside the clip area."); /** SKIP THEME **/
+}
+
+int clip_boundary()
+{
+ int inside;
+ int prev_outside;
+ int i2;
+ int j2;
+
+ /*** FIRST check the boundary of the feature ***/
+ if ( ( (psCShape->dfXMin < cxmin) && (psCShape->dfXMax < cxmin) ) ||
+ ( (psCShape->dfYMin < cymin) && (psCShape->dfYMax < cymin) ) ||
+ ( (psCShape->dfXMin > cxmax) && (psCShape->dfXMax > cxmax) ) ||
+ ( (psCShape->dfYMin > cymax) && (psCShape->dfYMax > cymax) ) )
+ { /** Feature is totally outside clip area **/
+ if (ierase) return(1); /** WRITE RECORD **/
+ else return(0); /** SKIP RECORD **/
+ }
+
+ if ( (psCShape->dfXMin >= cxmin) && (psCShape->dfXMax <= cxmax) &&
+ (psCShape->dfYMin >= cymin) && (psCShape->dfYMax <= cymax) )
+ { /** Feature is totally inside clip area **/
+ if (ierase) return(0); /** SKIP RECORD **/
+ else return(1); /** WRITE RECORD **/
+ }
+
+ if (iinside)
+ { /** INSIDE * Feature might touch the boundary or could be outside **/
+ if (ierase) return(1); /** WRITE RECORD **/
+ else return(0); /** SKIP RECORD **/
+ }
+
+ if (itouch)
+ { /** TOUCH **/
+ if ( ( (psCShape->dfXMin <= cxmin) || (psCShape->dfXMax >= cxmax) ) &&
+ (psCShape->dfYMin >= cymin) && (psCShape->dfYMax <= cymax) )
+ { /** Feature intersects the clip boundary only on the X axis **/
+ if (ierase) return(0); /** SKIP RECORD **/
+ else return(1); /** WRITE RECORD **/
+ }
+
+ if ( (psCShape->dfXMin >= cxmin) && (psCShape->dfXMax <= cxmax) &&
+ ( (psCShape->dfYMin <= cymin) || (psCShape->dfYMax >= cymax) ) )
+ { /** Feature intersects the clip boundary only on the Y axis **/
+ if (ierase) return(0); /** SKIP RECORD **/
+ else return(1); /** WRITE RECORD **/
+ }
+
+ for( j2 = 0; j2 < psCShape->nVertices; j2++ )
+ { /** At least one vertex must be inside the clip boundary **/
+ if ( (psCShape->padfX[j2] >= cxmin && psCShape->padfX[j2] <= cxmax) ||
+ (psCShape->padfY[j2] >= cymin && psCShape->padfY[j2] <= cymax) )
+ {
+ if (ierase) return(0); /** SKIP RECORD **/
+ else return(1); /** WRITE RECORD **/
+ }
+ }
+
+ /** All vertices are outside the clip boundary **/
+ if (ierase) return(1); /** WRITE RECORD **/
+ else return(0); /** SKIP RECORD **/
+ } /** End TOUCH **/
+
+ if (icut)
+ { /** CUT **/
+ /*** Check each vertex in the feature with the Boundary and "CUT" ***/
+ /*** THIS CODE WAS NOT COMPLETED! READ NOTE AT THE BOTTOM ***/
+ i2=0;
+ prev_outside=FALSE;
+ for( j2 = 0; j2 < psCShape->nVertices; j2++ )
+ {
+ inside = psCShape->padfX[j2] >= cxmin && psCShape->padfX[j2] <= cxmax &&
+ psCShape->padfY[j2] >= cymin && psCShape->padfY[j2] <= cymax ;
+
+ if (ierase) inside=(! inside);
+ if (inside)
+ {
+ if (i2 != j2)
+ {
+ if (prev_outside)
+ {
+ // AddIntersection(i2); /*** Add intersection ***/
+ prev_outside=FALSE;
+ }
+ psCShape->padfX[i2]=psCShape->padfX[j2]; /** move vertex **/
+ psCShape->padfY[i2]=psCShape->padfY[j2];
+ }
+ i2++;
+ } else {
+ if ( (! prev_outside) && (j2 > 0) )
+ {
+ // AddIntersection(i2); /*** Add intersection (Watch out for j2==i2-1) ***/
+ /*** Also a polygon may overlap twice and will split into a several parts ***/
+ prev_outside=TRUE;
+ }
+ }
+ }
+
+ printf("Vertices:%d OUT:%d Number of Parts:%d\n",
+ psCShape->nVertices,i2, psCShape->nParts );
+
+ psCShape->nVertices = i2;
+
+ if (i2 < 2) return(0); /** SKIP RECORD **/
+ /*** (WE ARE NOT CREATING INTERESECTIONS and some lines could be reduced to one point) **/
+
+ if (i2 == 0) return(0); /** SKIP RECORD **/
+ else return(1); /** WRITE RECORD **/
+ } /** End CUT **/
+
+//WE7U added this to remove a compiler warning
+ return(0);
+}
+
+
+/************************************************************************/
+/* strncasecmp2() */
+/* */
+/* Compare two strings up to n characters */
+/* If n=0 then s1 and s2 must be an exact match */
+/************************************************************************/
+
+int strncasecmp2(char *s1, char *s2, int n)
+
+{
+int j,i;
+ if (n<1) n=strlen(s1)+1;
+ for (i=0; i<n; i++)
+ {
+ if (*s1 != *s2)
+ {
+ if (*s1 >= 'a' && *s1 <= 'z') {
+ j=*s1-32;
+ if (j != *s2) return(*s1-*s2);
+ } else {
+ if (*s1 >= 'A' && *s1 <= 'Z') { j=*s1+32; }
+ else { j=*s1; }
+ if (j != *s2) return(*s1-*s2);
+ }
+ }
+ s1++;
+ s2++;
+ }
+ return(0);
+}
+
+
+#define NKEYS (sizeof(unitkeytab) / sizeof(struct unitkey))
+int findunit(char *unit)
+ {
+
+ struct unitkey {
+ char *name;
+ double value;
+ } unitkeytab[] = {
+ { "CM", 39.37 },
+ { "CENTIMETER", 39.37 },
+ { "CENTIMETERS", 39.37 }, /** # of inches * 100 in unit **/
+ { "METER", 3937 },
+ { "METERS", 3937 },
+ { "KM", 3937000 },
+ { "KILOMETER", 3937000 },
+ { "KILOMETERS", 3937000 },
+ { "INCH", 100 },
+ { "INCHES", 100 },
+ { "FEET", 1200 },
+ { "FOOT", 1200 },
+ { "YARD", 3600 },
+ { "YARDS", 3600 },
+ { "MILE", 6336000 },
+ { "MILES", 6336000 }
+ };
+
+ double unitfactor=0;
+ for (j = 0; j < (int)NKEYS; j++) {
+ if (strncasecmp2(unit, unitkeytab[j].name, 0) == 0) unitfactor=unitkeytab[j].value;
+ }
+ return(unitfactor);
+}
+
+/* -------------------------------------------------------------------- */
+/* Display a usage message. */
+/* -------------------------------------------------------------------- */
+void error()
+ {
+ puts( "The program will append to an existing shape file or it will" );
+ puts( "create a new file if needed." );
+ puts( "Only the items in the first output file will be preserved." );
+ puts( "When an item does not match with the append theme then the item");
+ puts( "might be placed to an existing item at the same position and type." );
+ puts( " OTHER FUNCTIONS:" );
+ puts( " - Describe all items in the dbase file (Use ALL for more than 5000 recs.)");
+ puts( " - Select a group of shapes from a comma separated selection list.");
+ puts( " - UnSelect a group of shapes from a comma separated selection list.");
+ puts( " - Clip boundary extent or by theme boundary." );
+ puts( " Touch writes all the shapes that touch the boundary.");
+ puts( " Inside writes all the shapes that are completely within the boundary.");
+ puts( " Boundary clips are only the min and max of a theme boundary." );
+ puts( " - Erase boundary extent or by theme boundary." );
+ puts( " Erase is the direct opposite of the Clip function." );
+ puts( " - Change coordinate value units between meters and feet.");
+ puts( " There is no way to determine the input unit of a shape file.");
+ puts( " Skip this function if the shape file is already in the correct unit.");
+ puts( " Clip and Erase will be done before the unit is changed.");
+ puts( " A shift will be done after the unit is changed.");
+ puts( " - Shift X and Y coordinates.\n" );
+ puts( "Finally, There can only be one select or unselect in the command line.");
+ puts( " There can only be one clip or erase in the command line.");
+ puts( " There can only be one unit and only one shift in the command line.\n");
+ puts( "Ex: shputils in.shp out.shp SELECT countycode 3,5,9,13,17,27");
+ puts( " shputils in.shp out.shp CLIP 10 10 90 90 Touch FACTOR Meter Feet");
+ puts( " shputils in.shp out.shp FACTOR Meter 3.0");
+ puts( " shputils in.shp out.shp CLIP clip.shp Boundary Touch SHIFT 40 40");
+ puts( " shputils in.shp out.shp SELECT co 112 CLIP clip.shp Boundary Touch\n");
+ puts( "USAGE: shputils <DescribeShape> {ALL}");
+ puts( "USAGE: shputils <InputShape> <OutShape|AppendShape>" );
+ puts( " { <FACTOR> <FEET|MILES|METERS|KM> <FEET|MILES|METERS|KM|factor> }" );
+ puts( " { <SHIFT> <xshift> <yshift> }" );
+ puts( " { <SELECT|UNSEL> <Item> <valuelist> }" );
+ puts( " { <CLIP|ERASE> <xmin> <ymin> <xmax> <ymax> <TOUCH|INSIDE|CUT> }" );
+ puts( " { <CLIP|ERASE> <theme> <BOUNDARY> <TOUCH|INSIDE|CUT> }" );
+ puts( " Note: CUT is not complete and does not create intersections.");
+ puts( " For more information read programmer comment.");
+
+ /**** Clip functions for Polygon and Cut is not supported
+ There are several web pages that describe methods of doing this function.
+ It seem easy to impliment until you start writting code. I don't have the
+ time to add these functions but a did leave a simple cut routine in the
+ program that can be called by using CUT instead of TOUCH in the
+ CLIP or ERASE functions. It does not add the intersection of the line and
+ the clip box, so polygons could look incomplete and lines will come up short.
+
+ Information about clipping lines with a box:
+ http://www.csclub.uwaterloo.ca/u/mpslager/articles/sutherland/wr.html
+ Information about finding the intersection of two lines:
+ http://www.whisqu.se/per/docs/math28.htm
+
+THE CODE LOOKS LIKE THIS:
+ ********************************************************
+void Intersect_Lines(float x0,float y0,float x1,float y1,
+ float x2,float y2,float x3,float y3,
+ float *xi,float *yi)
+ {
+// this function computes the intersection of the sent lines
+// and returns the intersection point, note that the function assumes
+// the lines intersect. the function can handle vertical as well
+// as horizontal lines. note the function isn't very clever, it simply
+// applies the math, but we don't need speed since this is a
+// pre-processing step
+// The Intersect_lines program came from (http://www.whisqu.se/per/docs/math28.htm)
+
+float a1,b1,c1, // constants of linear equations
+ a2,b2,c2,
+ det_inv, // the inverse of the determinant of the coefficientmatrix
+ m1,m2; // the slopes of each line
+
+// compute slopes, note the cludge for infinity, however, this will
+// be close enough
+if ((x1-x0)!=0)
+ m1 = (y1-y0)/(x1-x0);
+else
+ m1 = (float)1e+10; // close enough to infinity
+
+
+if ((x3-x2)!=0)
+ m2 = (y3-y2)/(x3-x2);
+else
+ m2 = (float)1e+10; // close enough to infinity
+
+// compute constants
+a1 = m1;
+a2 = m2;
+b1 = -1;
+b2 = -1;
+c1 = (y0-m1*x0);
+c2 = (y2-m2*x2);
+// compute the inverse of the determinate
+det_inv = 1/(a1*b2 - a2*b1);
+// use Kramers rule to compute xi and yi
+*xi=((b1*c2 - b2*c1)*det_inv);
+*yi=((a2*c1 - a1*c2)*det_inv);
+} // end Intersect_Lines
+ **********************************************************/
+
+ exit( 1 );
+ }
diff --git a/src/shapelib/stream1.out b/src/shapelib/stream1.out
new file mode 100644
index 0000000..de59c44
--- /dev/null
+++ b/src/shapelib/stream1.out
@@ -0,0 +1,1465 @@
+-------------------------------------------------------------------------
+Test 1: dump anno.shp
+-------------------------------------------------------------------------
+Shapefile Type: Polygon # of Shapes: 201
+
+File Bounds: ( 471276.281, 4751595.500,0,0)
+ to ( 492683.536, 4765390.413,0,0)
+
+Shape:0 (Polygon) nVertices=5, nParts=1
+ Bounds:( 486019.130, 4764549.500, 0, 0)
+ to ( 486356.183, 4765212.744, 0, 0)
+ ( 486089.531, 4764549.500, 0, 0) Ring
+ ( 486019.130, 4764579.128, 0, 0)
+ ( 486285.782, 4765212.744, 0, 0)
+ ( 486356.183, 4765183.116, 0, 0)
+ ( 486089.531, 4764549.500, 0, 0)
+
+Shape:1 (Polygon) nVertices=5, nParts=1
+ Bounds:( 484948.275, 4763866.500, 0, 0)
+ to ( 485333.012, 4764070.376, 0, 0)
+ ( 484974.719, 4763866.500, 0, 0) Ring
+ ( 484948.275, 4763938.159, 0, 0)
+ ( 485306.569, 4764070.376, 0, 0)
+ ( 485333.012, 4763998.717, 0, 0)
+ ( 484974.719, 4763866.500, 0, 0)
+
+Shape:2 (Polygon) nVertices=5, nParts=1
+ Bounds:( 485577.021, 4764106.500, 0, 0)
+ to ( 485818.355, 4764259.305, 0, 0)
+ ( 485604.156, 4764106.500, 0, 0) Ring
+ ( 485577.021, 4764177.900, 0, 0)
+ ( 485791.220, 4764259.305, 0, 0)
+ ( 485818.355, 4764187.906, 0, 0)
+ ( 485604.156, 4764106.500, 0, 0)
+
+Shape:3 (Polygon) nVertices=5, nParts=1
+ Bounds:( 484861.500, 4762570.513, 0, 0)
+ to ( 485092.062, 4763026.856, 0, 0)
+ ( 485092.062, 4762597.000, 0, 0) Ring
+ ( 485020.420, 4762570.513, 0, 0)
+ ( 484861.500, 4763000.370, 0, 0)
+ ( 484933.143, 4763026.856, 0, 0)
+ ( 485092.062, 4762597.000, 0, 0)
+
+Shape:4 (Polygon) nVertices=5, nParts=1
+ Bounds:( 484452.624, 4763792.614, 0, 0)
+ to ( 484628.031, 4764105.947, 0, 0)
+ ( 484628.031, 4763818.500, 0, 0) Ring
+ ( 484556.169, 4763792.614, 0, 0)
+ ( 484452.624, 4764080.061, 0, 0)
+ ( 484524.486, 4764105.947, 0, 0)
+ ( 484628.031, 4763818.500, 0, 0)
+
+Shape:5 (Polygon) nVertices=5, nParts=1
+ Bounds:( 484355.352, 4764139.435, 0, 0)
+ to ( 484505.344, 4764380.892, 0, 0)
+ ( 484505.344, 4764165.500, 0, 0) Ring
+ ( 484433.546, 4764139.435, 0, 0)
+ ( 484355.352, 4764354.827, 0, 0)
+ ( 484427.150, 4764380.892, 0, 0)
+ ( 484505.344, 4764165.500, 0, 0)
+
+Shape:6 (Polygon) nVertices=9, nParts=1
+ Bounds:( 484548.866, 4763118.531, 0, 0)
+ to ( 484772.062, 4763742.258, 0, 0)
+ ( 484772.062, 4763152.000, 0, 0) Ring
+ ( 484703.404, 4763118.531, 0, 0)
+ ( 484605.763, 4763318.832, 0, 0)
+ ( 484548.866, 4763471.149, 0, 0)
+ ( 484603.088, 4763742.258, 0, 0)
+ ( 484677.987, 4763727.278, 0, 0)
+ ( 484628.031, 4763477.500, 0, 0)
+ ( 484676.031, 4763349.000, 0, 0)
+ ( 484772.062, 4763152.000, 0, 0)
+
+Shape:7 (Polygon) nVertices=5, nParts=1
+ Bounds:( 484671.739, 4763562.500, 0, 0)
+ to ( 484911.415, 4763682.338, 0, 0)
+ ( 484686.719, 4763562.500, 0, 0) Ring
+ ( 484671.739, 4763637.399, 0, 0)
+ ( 484896.435, 4763682.338, 0, 0)
+ ( 484911.415, 4763607.439, 0, 0)
+ ( 484686.719, 4763562.500, 0, 0)
+
+Shape:8 (Polygon) nVertices=5, nParts=1
+ Bounds:( 484930.172, 4763125.500, 0, 0)
+ to ( 485596.342, 4763453.269, 0, 0)
+ ( 484958.719, 4763125.500, 0, 0) Ring
+ ( 484930.172, 4763196.347, 0, 0)
+ ( 485567.795, 4763453.269, 0, 0)
+ ( 485596.342, 4763382.423, 0, 0)
+ ( 484958.719, 4763125.500, 0, 0)
+
+Shape:9 (Polygon) nVertices=5, nParts=1
+ Bounds:( 485102.757, 4763082.500, 0, 0)
+ to ( 485344.154, 4763234.029, 0, 0)
+ ( 485129.406, 4763082.500, 0, 0) Ring
+ ( 485102.757, 4763154.083, 0, 0)
+ ( 485317.505, 4763234.029, 0, 0)
+ ( 485344.154, 4763162.446, 0, 0)
+ ( 485129.406, 4763082.500, 0, 0)
+
+Shape:10 (Polygon) nVertices=5, nParts=1
+ Bounds:( 485368.786, 4762538.500, 0, 0)
+ to ( 485824.016, 4762774.029, 0, 0)
+ ( 485396.156, 4762538.500, 0, 0) Ring
+ ( 485368.786, 4762609.810, 0, 0)
+ ( 485796.646, 4762774.029, 0, 0)
+ ( 485824.016, 4762702.719, 0, 0)
+ ( 485396.156, 4762538.500, 0, 0)
+
+Shape:11 (Polygon) nVertices=5, nParts=1
+ Bounds:( 487002.484, 4763184.000, 0, 0)
+ to ( 487243.960, 4763333.368, 0, 0)
+ ( 487028.312, 4763184.000, 0, 0) Ring
+ ( 487002.484, 4763255.883, 0, 0)
+ ( 487218.132, 4763333.368, 0, 0)
+ ( 487243.960, 4763261.486, 0, 0)
+ ( 487028.312, 4763184.000, 0, 0)
+
+Shape:12 (Polygon) nVertices=5, nParts=1
+ Bounds:( 486733.537, 4762455.413, 0, 0)
+ to ( 487076.312, 4763275.483, 0, 0)
+ ( 487076.312, 4762480.000, 0, 0) Ring
+ ( 487003.996, 4762455.413, 0, 0)
+ ( 486733.537, 4763250.896, 0, 0)
+ ( 486805.854, 4763275.483, 0, 0)
+ ( 487076.312, 4762480.000, 0, 0)
+
+Shape:13 (Polygon) nVertices=5, nParts=1
+ Bounds:( 486440.735, 4762331.029, 0, 0)
+ to ( 486772.281, 4763075.311, 0, 0)
+ ( 486772.281, 4762357.000, 0, 0) Ring
+ ( 486700.450, 4762331.029, 0, 0)
+ ( 486440.735, 4763049.339, 0, 0)
+ ( 486512.566, 4763075.311, 0, 0)
+ ( 486772.281, 4762357.000, 0, 0)
+
+Shape:14 (Polygon) nVertices=5, nParts=1
+ Bounds:( 486383.882, 4762986.530, 0, 0)
+ to ( 486521.594, 4763227.908, 0, 0)
+ ( 486521.594, 4763008.000, 0, 0) Ring
+ ( 486448.291, 4762986.530, 0, 0)
+ ( 486383.882, 4763206.438, 0, 0)
+ ( 486457.184, 4763227.908, 0, 0)
+ ( 486521.594, 4763008.000, 0, 0)
+
+Shape:15 (Polygon) nVertices=9, nParts=1
+ Bounds:( 486360.416, 4762774.310, 0, 0)
+ to ( 486800.882, 4763656.208, 0, 0)
+ ( 486489.594, 4763600.000, 0, 0) Ring
+ ( 486541.313, 4763656.208, 0, 0)
+ ( 486762.057, 4763453.094, 0, 0)
+ ( 486800.882, 4763266.659, 0, 0)
+ ( 486420.883, 4762774.310, 0, 0)
+ ( 486360.416, 4762820.979, 0, 0)
+ ( 486718.938, 4763285.500, 0, 0)
+ ( 486692.281, 4763413.500, 0, 0)
+ ( 486489.594, 4763600.000, 0, 0)
+
+Shape:16 (Polygon) nVertices=5, nParts=1
+ Bounds:( 486682.872, 4762181.000, 0, 0)
+ to ( 487292.496, 4762415.463, 0, 0)
+ ( 486702.969, 4762181.000, 0, 0) Ring
+ ( 486682.872, 4762254.691, 0, 0)
+ ( 487272.400, 4762415.463, 0, 0)
+ ( 487292.496, 4762341.772, 0, 0)
+ ( 486702.969, 4762181.000, 0, 0)
+
+Shape:17 (Polygon) nVertices=5, nParts=1
+ Bounds:( 487480.713, 4762283.320, 0, 0)
+ to ( 487732.406, 4762812.552, 0, 0)
+ ( 487732.406, 4762309.000, 0, 0) Ring
+ ( 487660.470, 4762283.320, 0, 0)
+ ( 487480.713, 4762786.872, 0, 0)
+ ( 487552.649, 4762812.552, 0, 0)
+ ( 487732.406, 4762309.000, 0, 0)
+
+Shape:18 (Polygon) nVertices=5, nParts=1
+ Bounds:( 487069.757, 4763685.709, 0, 0)
+ to ( 487220.344, 4763927.145, 0, 0)
+ ( 487220.344, 4763712.000, 0, 0) Ring
+ ( 487148.629, 4763685.709, 0, 0)
+ ( 487069.757, 4763900.854, 0, 0)
+ ( 487141.471, 4763927.145, 0, 0)
+ ( 487220.344, 4763712.000, 0, 0)
+
+Shape:19 (Polygon) nVertices=9, nParts=1
+ Bounds:( 487854.719, 4758279.000, 0, 0)
+ to ( 488518.085, 4758475.003, 0, 0)
+ ( 487854.719, 4758404.000, 0, 0) Ring
+ ( 487882.875, 4758475.003, 0, 0)
+ ( 488183.362, 4758355.845, 0, 0)
+ ( 488341.273, 4758360.840, 0, 0)
+ ( 488515.420, 4758366.919, 0, 0)
+ ( 488518.085, 4758290.583, 0, 0)
+ ( 488343.812, 4758284.500, 0, 0)
+ ( 488169.938, 4758279.000, 0, 0)
+ ( 487854.719, 4758404.000, 0, 0)
+
+Shape:20 (Polygon) nVertices=5, nParts=1
+ Bounds:( 486300.557, 4758366.000, 0, 0)
+ to ( 486613.245, 4758546.262, 0, 0)
+ ( 486327.781, 4758366.000, 0, 0) Ring
+ ( 486300.557, 4758437.366, 0, 0)
+ ( 486586.021, 4758546.262, 0, 0)
+ ( 486613.245, 4758474.896, 0, 0)
+ ( 486327.781, 4758366.000, 0, 0)
+
+Shape:21 (Polygon) nVertices=5, nParts=1
+ Bounds:( 486709.618, 4758518.000, 0, 0)
+ to ( 486949.999, 4758681.145, 0, 0)
+ ( 486740.750, 4758518.000, 0, 0) Ring
+ ( 486709.618, 4758587.750, 0, 0)
+ ( 486918.867, 4758681.145, 0, 0)
+ ( 486949.999, 4758611.396, 0, 0)
+ ( 486740.750, 4758518.000, 0, 0)
+
+Shape:22 (Polygon) nVertices=5, nParts=1
+ Bounds:( 487325.398, 4757807.034, 0, 0)
+ to ( 487555.844, 4758263.402, 0, 0)
+ ( 487555.844, 4757833.500, 0, 0) Ring
+ ( 487484.193, 4757807.034, 0, 0)
+ ( 487325.398, 4758236.937, 0, 0)
+ ( 487397.049, 4758263.402, 0, 0)
+ ( 487555.844, 4757833.500, 0, 0)
+
+Shape:23 (Polygon) nVertices=5, nParts=1
+ Bounds:( 487255.256, 4758215.573, 0, 0)
+ to ( 487387.406, 4758456.611, 0, 0)
+ ( 487387.406, 4758235.000, 0, 0) Ring
+ ( 487313.536, 4758215.573, 0, 0)
+ ( 487255.256, 4758437.184, 0, 0)
+ ( 487329.126, 4758456.611, 0, 0)
+ ( 487387.406, 4758235.000, 0, 0)
+
+Shape:24 (Polygon) nVertices=5, nParts=1
+ Bounds:( 487248.714, 4758360.500, 0, 0)
+ to ( 487559.687, 4758550.761, 0, 0)
+ ( 487278.719, 4758360.500, 0, 0) Ring
+ ( 487248.714, 4758430.742, 0, 0)
+ ( 487529.682, 4758550.761, 0, 0)
+ ( 487559.687, 4758480.519, 0, 0)
+ ( 487278.719, 4758360.500, 0, 0)
+
+Shape:25 (Polygon) nVertices=5, nParts=1
+ Bounds:( 487573.994, 4758496.500, 0, 0)
+ to ( 487815.502, 4758644.603, 0, 0)
+ ( 487599.344, 4758496.500, 0, 0) Ring
+ ( 487573.994, 4758568.553, 0, 0)
+ ( 487790.152, 4758644.603, 0, 0)
+ ( 487815.502, 4758572.550, 0, 0)
+ ( 487599.344, 4758496.500, 0, 0)
+-------------------------------------------------------------------------
+Test 2: dump brklinz.shp
+-------------------------------------------------------------------------
+Shapefile Type: ArcZ # of Shapes: 122
+
+File Bounds: ( 6294338.260, 1978444.010,0,0)
+ to ( 6296321.860, 1979694.450,0,0)
+
+Shape:0 (ArcZ) nVertices=92, nParts=1
+ Bounds:( 6294700.210, 1978579.390, 818.64, 0)
+ to ( 6295395.930, 1979050.330, 917.86, 0)
+ ( 6295372.750, 1978755.830, 823.06, 0) Ring
+ ( 6295366.170, 1978739.190, 826.58, 0)
+ ( 6295360.400, 1978718.540, 829.2, 0)
+ ( 6295352.620, 1978697.000, 832.22, 0)
+ ( 6295345.960, 1978677.040, 834.64, 0)
+ ( 6295339.690, 1978656.810, 838.51, 0)
+ ( 6295335.040, 1978637.600, 840.94, 0)
+ ( 6295331.080, 1978621.450, 844.48, 0)
+ ( 6295324.350, 1978607.940, 847.04, 0)
+ ( 6295313.370, 1978598.450, 850.38, 0)
+ ( 6295296.780, 1978594.950, 853.27, 0)
+ ( 6295273.800, 1978594.990, 858.06, 0)
+ ( 6295251.750, 1978595.380, 861.53, 0)
+ ( 6295232.340, 1978598.400, 864.22, 0)
+ ( 6295206.740, 1978606.390, 866.38, 0)
+ ( 6295180.610, 1978616.970, 868.15, 0)
+ ( 6295156.350, 1978630.540, 870.65, 0)
+ ( 6295132.270, 1978645.210, 872.02, 0)
+ ( 6295111.070, 1978659.740, 875.17, 0)
+ ( 6295090.030, 1978674.920, 878.84, 0)
+ ( 6295071.060, 1978689.340, 882.06, 0)
+ ( 6295051.900, 1978705.080, 886.98, 0)
+ ( 6295036.460, 1978719.260, 889.66, 0)
+ ( 6295023.620, 1978732.910, 893.53, 0)
+ ( 6295010.450, 1978750.380, 895.24, 0)
+ ( 6294999.910, 1978767.850, 897.47, 0)
+ ( 6294989.810, 1978783.860, 900.29, 0)
+ ( 6294975.040, 1978795.570, 902.45, 0)
+ ( 6294956.300, 1978806.830, 906.32, 0)
+ ( 6294937.260, 1978814.620, 909.21, 0)
+ ( 6294919.240, 1978821.960, 912.88, 0)
+ ( 6294897.040, 1978832.210, 915.04, 0)
+ ( 6294878.070, 1978844.070, 916.49, 0)
+ ( 6294865.010, 1978855.820, 917.34, 0)
+ ( 6294859.560, 1978870.150, 916.81, 0)
+ ( 6294861.520, 1978882.920, 916.62, 0)
+ ( 6294874.640, 1978906.220, 917.86, 0)
+ ( 6294886.980, 1978926.880, 917.6, 0)
+ ( 6294889.630, 1978953.270, 917.54, 0)
+ ( 6294888.520, 1978978.280, 916.88, 0)
+ ( 6294880.350, 1978998.390, 915.96, 0)
+ ( 6294866.540, 1979018.920, 915.57, 0)
+ ( 6294843.270, 1979039.140, 915.57, 0)
+ ( 6294812.250, 1979049.040, 915.96, 0)
+ ( 6294777.640, 1979050.330, 916.75, 0)
+ ( 6294752.060, 1979040.520, 916.68, 0)
+ ( 6294730.990, 1979028.850, 916.62, 0)
+ ( 6294716.690, 1979008.420, 916.62, 0)
+ ( 6294706.050, 1978987.490, 916.95, 0)
+ ( 6294700.210, 1978965.390, 916.95, 0)
+ ( 6294700.520, 1978937.670, 917.01, 0)
+ ( 6294712.060, 1978911.340, 916.95, 0)
+ ( 6294724.820, 1978893.560, 916.62, 0)
+ ( 6294741.630, 1978878.010, 916.36, 0)
+ ( 6294759.360, 1978865.090, 916.36, 0)
+ ( 6294777.650, 1978855.370, 916.22, 0)
+ ( 6294807.570, 1978846.970, 916.36, 0)
+ ( 6294837.640, 1978836.590, 916.55, 0)
+ ( 6294858.650, 1978831.390, 916.29, 0)
+ ( 6294878.860, 1978825.840, 915.37, 0)
+ ( 6294897.630, 1978817.860, 913.67, 0)
+ ( 6294914.550, 1978809.520, 910.78, 0)
+ ( 6294932.380, 1978798.580, 907.17, 0)
+ ( 6294947.360, 1978788.370, 904.42, 0)
+ ( 6294960.500, 1978778.120, 901.86, 0)
+ ( 6294974.780, 1978761.900, 898.78, 0)
+ ( 6294988.510, 1978747.610, 895.7, 0)
+ ( 6295005.230, 1978730.220, 892.81, 0)
+ ( 6295023.560, 1978713.470, 889.34, 0)
+ ( 6295043.310, 1978696.320, 885.07, 0)
+ ( 6295061.830, 1978680.810, 881.47, 0)
+ ( 6295080.970, 1978664.550, 877.79, 0)
+ ( 6295104.570, 1978648.190, 874.58, 0)
+ ( 6295126.310, 1978633.890, 872.09, 0)
+ ( 6295149.840, 1978618.720, 869.6, 0)
+ ( 6295173.840, 1978605.030, 867.37, 0)
+ ( 6295198.110, 1978594.150, 866.12, 0)
+ ( 6295222.830, 1978586.990, 865.2, 0)
+ ( 6295243.030, 1978583.810, 863.5, 0)
+ ( 6295268.110, 1978581.290, 860.35, 0)
+ ( 6295291.530, 1978579.390, 856.48, 0)
+ ( 6295313.200, 1978582.040, 852.42, 0)
+ ( 6295329.170, 1978591.410, 848.81, 0)
+ ( 6295339.780, 1978603.880, 845.07, 0)
+ ( 6295345.640, 1978621.110, 842.12, 0)
+ ( 6295351.070, 1978642.970, 838.32, 0)
+ ( 6295357.250, 1978666.560, 834.77, 0)
+ ( 6295367.290, 1978691.000, 831.89, 0)
+ ( 6295376.030, 1978718.470, 828.09, 0)
+ ( 6295383.930, 1978744.860, 824.35, 0)
+ ( 6295389.990, 1978768.720, 821.33, 0)
+ ( 6295395.930, 1978790.090, 818.64, 0)
+
+Shape:1 (ArcZ) nVertices=9, nParts=1
+ Bounds:( 6295218.470, 1978444.010, 864.55, 0)
+ to ( 6295330.760, 1978581.880, 882.45, 0)
+ ( 6295330.760, 1978444.010, 882.45, 0) Ring
+ ( 6295306.050, 1978461.190, 880.94, 0)
+ ( 6295280.210, 1978482.710, 878.52, 0)
+ ( 6295258.180, 1978504.050, 875.89, 0)
+ ( 6295239.910, 1978524.670, 871.89, 0)
+ ( 6295225.650, 1978546.540, 869.53, 0)
+ ( 6295218.470, 1978565.550, 866.97, 0)
+ ( 6295223.960, 1978575.510, 865.27, 0)
+ ( 6295230.580, 1978581.880, 864.55, 0)
+
+Shape:2 (ArcZ) nVertices=10, nParts=1
+ Bounds:( 6295199.220, 1978444.010, 866.32, 0)
+ to ( 6295309.040, 1978588.800, 882.08, 0)
+ ( 6295200.070, 1978588.800, 866.32, 0) Ring
+ ( 6295199.220, 1978571.840, 867.24, 0)
+ ( 6295200.770, 1978555.740, 868.88, 0)
+ ( 6295207.890, 1978538.040, 869.86, 0)
+ ( 6295223.020, 1978520.530, 870.84, 0)
+ ( 6295239.450, 1978502.440, 874.06, 0)
+ ( 6295258.050, 1978483.440, 876.48, 0)
+ ( 6295268.990, 1978473.760, 879.17, 0)
+ ( 6295285.710, 1978461.560, 880.55, 0)
+ ( 6295309.040, 1978444.010, 882.08, 0)
+
+Shape:3 (ArcZ) nVertices=5, nParts=1
+ Bounds:( 6294340.890, 1979449.280, 1031.78, 0)
+ to ( 6294394.080, 1979522.030, 1039.78, 0)
+ ( 6294394.080, 1979449.280, 1039.78, 0) Ring
+ ( 6294378.800, 1979469.230, 1038.73, 0)
+ ( 6294364.980, 1979486.740, 1037.28, 0)
+ ( 6294350.800, 1979504.980, 1035.12, 0)
+ ( 6294340.890, 1979522.030, 1031.78, 0)
+
+Shape:4 (ArcZ) nVertices=6, nParts=1
+ Bounds:( 6294344.380, 1979583.450, 1008.04, 0)
+ to ( 6294354.670, 1979678.070, 1023.45, 0)
+ ( 6294344.380, 1979583.450, 1023.45, 0) Ring
+ ( 6294348.050, 1979601.580, 1019.18, 0)
+ ( 6294349.570, 1979621.200, 1016.5, 0)
+ ( 6294351.990, 1979637.890, 1012.95, 0)
+ ( 6294353.090, 1979657.140, 1011.51, 0)
+ ( 6294354.670, 1979678.070, 1008.04, 0)
+
+Shape:5 (ArcZ) nVertices=3, nParts=1
+ Bounds:( 6294338.260, 1979628.600, 1008.63, 0)
+ to ( 6294341.080, 1979674.100, 1015.71, 0)
+ ( 6294341.080, 1979674.100, 1008.63, 0) Ring
+ ( 6294339.460, 1979649.880, 1011.71, 0)
+ ( 6294338.260, 1979628.600, 1015.71, 0)
+
+Shape:6 (ArcZ) nVertices=3, nParts=1
+ Bounds:( 6294350.160, 1979437.980, 1038.6, 0)
+ to ( 6294379.980, 1979476.720, 1040.1, 0)
+ ( 6294350.160, 1979476.720, 1038.6, 0) Ring
+ ( 6294368.100, 1979454.860, 1040.1, 0)
+ ( 6294379.980, 1979437.980, 1039.32, 0)
+
+Shape:7 (ArcZ) nVertices=39, nParts=1
+ Bounds:( 6295371.530, 1978758.160, 754.11, 0)
+ to ( 6295534.560, 1979677.750, 823.3, 0)
+ ( 6295534.560, 1979677.750, 779.95, 0) Ring
+ ( 6295534.380, 1979648.150, 778.57, 0)
+ ( 6295534.480, 1979605.990, 775.16, 0)
+ ( 6295533.970, 1979577.580, 772.21, 0)
+ ( 6295532.310, 1979547.260, 768.41, 0)
+ ( 6295532.970, 1979521.290, 763.82, 0)
+ ( 6295532.390, 1979496.890, 759.1, 0)
+ ( 6295532.940, 1979474.010, 755.49, 0)
+ ( 6295533.680, 1979452.180, 754.11, 0)
+ ( 6295533.850, 1979434.640, 754.11, 0)
+ ( 6295532.170, 1979409.180, 755.75, 0)
+ ( 6295531.580, 1979384.450, 758.7, 0)
+ ( 6295531.590, 1979356.090, 760.28, 0)
+ ( 6295530.190, 1979325.690, 761.13, 0)
+ ( 6295530.020, 1979291.090, 761.66, 0)
+ ( 6295529.210, 1979259.420, 762.7, 0)
+ ( 6295526.250, 1979221.610, 762.77, 0)
+ ( 6295524.260, 1979187.500, 763.75, 0)
+ ( 6295522.640, 1979155.350, 764.61, 0)
+ ( 6295521.540, 1979123.230, 765.33, 0)
+ ( 6295518.460, 1979096.000, 765.92, 0)
+ ( 6295511.670, 1979081.110, 767.16, 0)
+ ( 6295500.700, 1979064.060, 768.41, 0)
+ ( 6295489.330, 1979049.600, 770.11, 0)
+ ( 6295475.500, 1979033.100, 773.07, 0)
+ ( 6295462.530, 1979018.190, 775.16, 0)
+ ( 6295447.760, 1979001.400, 779.49, 0)
+ ( 6295433.380, 1978984.530, 782.9, 0)
+ ( 6295419.040, 1978965.820, 785.92, 0)
+ ( 6295409.020, 1978946.820, 790.58, 0)
+ ( 6295399.860, 1978923.910, 795.1, 0)
+ ( 6295391.010, 1978894.410, 800.94, 0)
+ ( 6295387.440, 1978875.550, 805.53, 0)
+ ( 6295382.030, 1978849.030, 809.79, 0)
+ ( 6295382.190, 1978828.930, 813.33, 0)
+ ( 6295383.570, 1978809.290, 817.4, 0)
+ ( 6295380.880, 1978789.860, 819.69, 0)
+ ( 6295375.630, 1978771.810, 822.58, 0)
+ ( 6295371.530, 1978758.160, 823.3, 0)
+
+Shape:8 (ArcZ) nVertices=35, nParts=1
+ Bounds:( 6295396.480, 1978794.780, 753.98, 0)
+ to ( 6295549.010, 1979670.060, 818.58, 0)
+ ( 6295396.620, 1978794.780, 818.58, 0) Ring
+ ( 6295397.330, 1978816.670, 815.76, 0)
+ ( 6295396.480, 1978836.150, 812.22, 0)
+ ( 6295397.670, 1978857.110, 807.95, 0)
+ ( 6295401.180, 1978874.720, 804.61, 0)
+ ( 6295406.260, 1978897.320, 799.95, 0)
+ ( 6295413.580, 1978919.930, 794.77, 0)
+ ( 6295421.330, 1978938.190, 790.31, 0)
+ ( 6295431.450, 1978956.590, 786.51, 0)
+ ( 6295444.950, 1978974.360, 782.38, 0)
+ ( 6295461.420, 1978993.620, 777.66, 0)
+ ( 6295479.760, 1979013.510, 773.26, 0)
+ ( 6295494.630, 1979032.330, 771.1, 0)
+ ( 6295510.990, 1979052.120, 767.69, 0)
+ ( 6295524.170, 1979071.090, 766.84, 0)
+ ( 6295532.180, 1979091.890, 765.33, 0)
+ ( 6295536.530, 1979120.830, 764.8, 0)
+ ( 6295537.480, 1979150.200, 764.08, 0)
+ ( 6295539.470, 1979189.490, 763.43, 0)
+ ( 6295541.670, 1979230.490, 762.64, 0)
+ ( 6295541.760, 1979271.330, 761.79, 0)
+ ( 6295543.650, 1979306.300, 761.46, 0)
+ ( 6295544.470, 1979335.540, 760.47, 0)
+ ( 6295544.960, 1979363.490, 759.23, 0)
+ ( 6295545.620, 1979392.020, 757.13, 0)
+ ( 6295546.340, 1979419.430, 754.9, 0)
+ ( 6295547.120, 1979439.940, 753.98, 0)
+ ( 6295546.510, 1979459.150, 754.38, 0)
+ ( 6295545.460, 1979482.710, 757.66, 0)
+ ( 6295545.530, 1979507.330, 761.13, 0)
+ ( 6295545.610, 1979532.470, 765.59, 0)
+ ( 6295546.490, 1979565.520, 770.44, 0)
+ ( 6295547.960, 1979597.100, 775.03, 0)
+ ( 6295548.990, 1979628.040, 777.26, 0)
+ ( 6295549.010, 1979670.060, 780.15, 0)
+
+Shape:9 (ArcZ) nVertices=45, nParts=1
+ Bounds:( 6295694.040, 1978444.010, 696.95, 0)
+ to ( 6296208.790, 1979687.080, 787.43, 0)
+ ( 6295698.400, 1979687.080, 787.43, 0) Ring
+ ( 6295694.040, 1979670.950, 786.31, 0)
+ ( 6295696.410, 1979650.280, 785.13, 0)
+ ( 6295700.080, 1979634.530, 784.8, 0)
+ ( 6295704.080, 1979620.010, 784.15, 0)
+ ( 6295708.420, 1979601.930, 782.44, 0)
+ ( 6295711.230, 1979584.790, 781.99, 0)
+ ( 6295712.060, 1979564.780, 780.8, 0)
+ ( 6295710.550, 1979537.480, 779.69, 0)
+ ( 6295711.290, 1979508.020, 777.59, 0)
+ ( 6295710.010, 1979477.420, 776.08, 0)
+ ( 6295709.300, 1979442.530, 773.59, 0)
+ ( 6295709.160, 1979413.640, 772.21, 0)
+ ( 6295707.090, 1979372.570, 769.46, 0)
+ ( 6295708.140, 1979336.210, 767.49, 0)
+ ( 6295709.710, 1979297.130, 764.67, 0)
+ ( 6295710.960, 1979272.310, 763.29, 0)
+ ( 6295714.640, 1979241.200, 761.2, 0)
+ ( 6295719.050, 1979211.560, 759.82, 0)
+ ( 6295724.280, 1979179.840, 758.31, 0)
+ ( 6295729.460, 1979152.460, 756.74, 0)
+ ( 6295735.770, 1979126.530, 754.44, 0)
+ ( 6295744.970, 1979095.400, 752.87, 0)
+ ( 6295755.820, 1979063.140, 750.31, 0)
+ ( 6295767.590, 1979028.330, 747.62, 0)
+ ( 6295782.240, 1978993.450, 744.21, 0)
+ ( 6295801.580, 1978952.420, 741.26, 0)
+ ( 6295825.730, 1978905.370, 736.87, 0)
+ ( 6295842.330, 1978877.810, 734.7, 0)
+ ( 6295859.110, 1978851.150, 731.55, 0)
+ ( 6295875.620, 1978827.010, 729.52, 0)
+ ( 6295899.080, 1978794.830, 727.42, 0)
+ ( 6295923.640, 1978763.720, 724.34, 0)
+ ( 6295949.340, 1978734.180, 721.39, 0)
+ ( 6295975.020, 1978704.320, 718.57, 0)
+ ( 6296000.320, 1978677.440, 716.01, 0)
+ ( 6296026.940, 1978648.120, 713.45, 0)
+ ( 6296053.500, 1978617.500, 709.78, 0)
+ ( 6296078.620, 1978589.630, 706.9, 0)
+ ( 6296098.880, 1978566.880, 704.47, 0)
+ ( 6296126.050, 1978537.930, 702.37, 0)
+ ( 6296150.670, 1978507.990, 700.14, 0)
+ ( 6296179.280, 1978476.280, 698.7, 0)
+ ( 6296208.030, 1978444.880, 696.99, 0)
+ ( 6296208.790, 1978444.010, 696.95, 0)
+
+Shape:10 (ArcZ) nVertices=10, nParts=1
+ Bounds:( 6296270.060, 1979014.970, 712.54, 0)
+ to ( 6296315.990, 1979152.310, 725.13, 0)
+ ( 6296306.110, 1979152.310, 725.13, 0) Ring
+ ( 6296288.270, 1979139.690, 723.42, 0)
+ ( 6296276.630, 1979122.410, 721.98, 0)
+ ( 6296270.060, 1979101.470, 719.95, 0)
+ ( 6296270.390, 1979084.580, 719.36, 0)
+ ( 6296275.110, 1979068.970, 717.26, 0)
+ ( 6296284.280, 1979052.820, 716.41, 0)
+ ( 6296294.680, 1979040.410, 715.49, 0)
+ ( 6296305.720, 1979027.370, 713.59, 0)
+ ( 6296315.990, 1979014.970, 712.54, 0)
+
+Shape:11 (ArcZ) nVertices=18, nParts=1
+ Bounds:( 6296044.930, 1978451.120, 690.11, 0)
+ to ( 6296312.920, 1978679.190, 713.72, 0)
+ ( 6296312.920, 1978493.560, 690.11, 0) Ring
+ ( 6296301.160, 1978479.050, 690.9, 0)
+ ( 6296287.840, 1978464.950, 692.4, 0)
+ ( 6296276.430, 1978454.890, 693.58, 0)
+ ( 6296262.580, 1978451.120, 694.44, 0)
+ ( 6296249.650, 1978452.500, 694.9, 0)
+ ( 6296237.110, 1978461.670, 696.08, 0)
+ ( 6296223.600, 1978477.650, 697.78, 0)
+ ( 6296209.320, 1978493.930, 698.7, 0)
+ ( 6296193.640, 1978511.140, 699.16, 0)
+ ( 6296176.980, 1978529.710, 700.6, 0)
+ ( 6296157.700, 1978550.970, 701.98, 0)
+ ( 6296136.720, 1978574.950, 703.49, 0)
+ ( 6296121.400, 1978591.550, 705.39, 0)
+ ( 6296102.290, 1978613.590, 707.36, 0)
+ ( 6296084.440, 1978634.580, 709.13, 0)
+ ( 6296065.890, 1978654.760, 711.29, 0)
+ ( 6296044.930, 1978679.190, 713.72, 0)
+
+Shape:12 (ArcZ) nVertices=71, nParts=1
+ Bounds:( 6295741.070, 1978679.190, 713.72, 0)
+ to ( 6296321.860, 1979680.370, 813.79, 0)
+ ( 6296044.930, 1978679.190, 713.72, 0) Ring
+ ( 6296025.660, 1978700.780, 716.6, 0)
+ ( 6296006.480, 1978721.510, 718.37, 0)
+ ( 6295987.070, 1978742.720, 721, 0)
+ ( 6295970.410, 1978761.420, 722.44, 0)
+ ( 6295953.490, 1978780.070, 724.28, 0)
+ ( 6295932.470, 1978805.820, 726.44, 0)
+ ( 6295913.490, 1978830.550, 728.67, 0)
+ ( 6295896.490, 1978855.310, 731.16, 0)
+ ( 6295881.220, 1978878.070, 733.39, 0)
+ ( 6295867.710, 1978899.180, 734.7, 0)
+ ( 6295853.950, 1978923.310, 737, 0)
+ ( 6295839.810, 1978950.030, 739.56, 0)
+ ( 6295825.270, 1978979.390, 742.11, 0)
+ ( 6295809.100, 1979015.600, 745.46, 0)
+ ( 6295796.940, 1979045.170, 748.02, 0)
+ ( 6295785.770, 1979078.900, 750.97, 0)
+ ( 6295777.080, 1979104.550, 752.54, 0)
+ ( 6295768.950, 1979133.460, 754.84, 0)
+ ( 6295762.170, 1979163.090, 756.87, 0)
+ ( 6295755.640, 1979194.930, 758.9, 0)
+ ( 6295750.610, 1979225.390, 760.48, 0)
+ ( 6295746.300, 1979259.750, 762.64, 0)
+ ( 6295743.320, 1979291.750, 764.54, 0)
+ ( 6295741.650, 1979321.060, 766.64, 0)
+ ( 6295741.070, 1979353.790, 768.54, 0)
+ ( 6295741.170, 1979384.450, 770.71, 0)
+ ( 6295742.010, 1979419.210, 772.48, 0)
+ ( 6295743.010, 1979454.740, 774.44, 0)
+ ( 6295743.910, 1979493.310, 776.94, 0)
+ ( 6295744.990, 1979530.290, 778.97, 0)
+ ( 6295745.900, 1979569.120, 781.46, 0)
+ ( 6295745.940, 1979603.910, 783.3, 0)
+ ( 6295747.600, 1979636.660, 785.85, 0)
+ ( 6295751.850, 1979653.260, 787.49, 0)
+ ( 6295760.490, 1979665.820, 788.87, 0)
+ ( 6295773.510, 1979673.830, 790.18, 0)
+ ( 6295788.460, 1979676.100, 791.95, 0)
+ ( 6295823.990, 1979674.960, 793.46, 0)
+ ( 6295871.620, 1979674.070, 796.94, 0)
+ ( 6295918.980, 1979673.120, 798.97, 0)
+ ( 6295971.200, 1979672.130, 802.25, 0)
+ ( 6296019.370, 1979671.600, 803.95, 0)
+ ( 6296054.350, 1979670.030, 805.92, 0)
+ ( 6296074.580, 1979662.250, 806.58, 0)
+ ( 6296085.660, 1979647.700, 806.97, 0)
+ ( 6296089.370, 1979635.300, 807.69, 0)
+ ( 6296086.380, 1979620.160, 808.61, 0)
+ ( 6296080.060, 1979601.690, 810.32, 0)
+ ( 6296074.440, 1979583.990, 811.17, 0)
+ ( 6296070.250, 1979568.770, 812.22, 0)
+ ( 6296072.470, 1979552.830, 812.94, 0)
+ ( 6296083.220, 1979536.790, 813.46, 0)
+ ( 6296102.650, 1979531.410, 813.79, 0)
+ ( 6296121.290, 1979536.450, 813.73, 0)
+ ( 6296133.190, 1979548.520, 813.2, 0)
+ ( 6296138.010, 1979563.380, 812.61, 0)
+ ( 6296135.460, 1979580.580, 811.37, 0)
+ ( 6296129.950, 1979598.850, 810.18, 0)
+ ( 6296124.490, 1979618.170, 809.46, 0)
+ ( 6296122.100, 1979635.880, 808.35, 0)
+ ( 6296126.820, 1979651.410, 807.36, 0)
+ ( 6296136.390, 1979661.360, 806.51, 0)
+ ( 6296149.630, 1979666.080, 806.05, 0)
+ ( 6296163.380, 1979667.880, 805.73, 0)
+ ( 6296186.080, 1979667.460, 805.14, 0)
+ ( 6296215.190, 1979666.580, 805, 0)
+ ( 6296247.690, 1979667.830, 803.5, 0)
+ ( 6296273.580, 1979670.850, 802.32, 0)
+ ( 6296295.410, 1979674.090, 800.68, 0)
+ ( 6296321.860, 1979680.370, 799.23, 0)
+
+Shape:13 (ArcZ) nVertices=6, nParts=1
+ Bounds:( 6295372.650, 1979608.700, 773.19, 0)
+ to ( 6295470.330, 1979679.550, 780.15, 0)
+ ( 6295372.650, 1979679.550, 780.15, 0) Ring
+ ( 6295387.140, 1979664.770, 777.85, 0)
+ ( 6295406.650, 1979645.400, 776.21, 0)
+ ( 6295422.760, 1979631.580, 775.29, 0)
+ ( 6295442.800, 1979612.190, 773.65, 0)
+ ( 6295470.330, 1979608.700, 773.19, 0)
+
+Shape:14 (ArcZ) nVertices=7, nParts=1
+ Bounds:( 6295415.710, 1979491.540, 772.08, 0)
+ to ( 6295453.550, 1979590.190, 773.85, 0)
+ ( 6295453.550, 1979590.110, 772.09, 0) Ring
+ ( 6295453.110, 1979590.190, 772.08, 0)
+ ( 6295439.430, 1979579.260, 772.74, 0)
+ ( 6295430.870, 1979552.770, 772.93, 0)
+ ( 6295420.940, 1979527.860, 773.19, 0)
+ ( 6295415.710, 1979510.070, 773.79, 0)
+ ( 6295421.080, 1979491.540, 773.85, 0)
+
+Shape:15 (ArcZ) nVertices=9, nParts=1
+ Bounds:( 6295351.240, 1979521.410, 773, 0)
+ to ( 6295430.330, 1979692.520, 782.11, 0)
+ ( 6295395.270, 1979521.410, 774.51, 0) Ring
+ ( 6295415.880, 1979549.790, 773.85, 0)
+ ( 6295426.030, 1979579.220, 773, 0)
+ ( 6295430.330, 1979604.610, 773.06, 0)
+ ( 6295418.610, 1979622.140, 774.31, 0)
+ ( 6295398.970, 1979639.020, 776.34, 0)
+ ( 6295382.220, 1979655.690, 778.31, 0)
+ ( 6295365.040, 1979674.420, 780.15, 0)
+ ( 6295351.240, 1979692.520, 782.11, 0)
+
+Shape:16 (ArcZ) nVertices=28, nParts=1
+ Bounds:( 6294520.270, 1979256.990, 932.36, 0)
+ to ( 6294743.290, 1979675.030, 1016.69, 0)
+ ( 6294531.940, 1979675.030, 932.36, 0) Ring
+ ( 6294523.870, 1979650.550, 933.54, 0)
+ ( 6294520.270, 1979620.920, 936.75, 0)
+ ( 6294525.030, 1979592.840, 940.29, 0)
+ ( 6294533.880, 1979567.770, 942.98, 0)
+ ( 6294546.040, 1979543.320, 949.28, 0)
+ ( 6294564.140, 1979524.750, 951.64, 0)
+ ( 6294585.590, 1979515.130, 956.36, 0)
+ ( 6294611.810, 1979503.890, 959.38, 0)
+ ( 6294635.130, 1979494.900, 966.2, 0)
+ ( 6294662.590, 1979487.470, 969.41, 0)
+ ( 6294687.540, 1979482.070, 971.77, 0)
+ ( 6294710.180, 1979470.160, 976.75, 0)
+ ( 6294732.150, 1979450.140, 978.53, 0)
+ ( 6294743.290, 1979431.460, 981.94, 0)
+ ( 6294738.700, 1979402.930, 984.69, 0)
+ ( 6294731.290, 1979380.980, 986.79, 0)
+ ( 6294717.670, 1979358.290, 988.3, 0)
+ ( 6294706.340, 1979342.050, 991.38, 0)
+ ( 6294697.140, 1979315.920, 996.76, 0)
+ ( 6294696.360, 1979292.580, 1000.17, 0)
+ ( 6294691.930, 1979275.010, 1002.4, 0)
+ ( 6294681.970, 1979259.950, 1004.76, 0)
+ ( 6294665.150, 1979256.990, 1006.53, 0)
+ ( 6294638.580, 1979258.930, 1010.33, 0)
+ ( 6294617.350, 1979259.730, 1012.76, 0)
+ ( 6294592.000, 1979262.260, 1015.32, 0)
+ ( 6294572.550, 1979262.000, 1016.69, 0)
+
+Shape:17 (ArcZ) nVertices=43, nParts=1
+ Bounds:( 6294466.100, 1979253.610, 930.98, 0)
+ to ( 6294720.520, 1979678.410, 1018.46, 0)
+ ( 6294572.550, 1979262.000, 1016.69, 0) Ring
+ ( 6294549.640, 1979260.720, 1017.48, 0)
+ ( 6294522.440, 1979260.520, 1017.48, 0)
+ ( 6294472.060, 1979253.610, 1016.63, 0)
+ ( 6294469.530, 1979302.330, 1017.15, 0)
+ ( 6294466.100, 1979341.240, 1016.63, 0)
+ ( 6294469.480, 1979374.290, 1016.5, 0)
+ ( 6294506.640, 1979382.010, 1016.96, 0)
+ ( 6294538.320, 1979377.390, 1016.89, 0)
+ ( 6294581.400, 1979377.510, 1017.74, 0)
+ ( 6294603.050, 1979366.770, 1017.74, 0)
+ ( 6294597.820, 1979338.470, 1018, 0)
+ ( 6294587.060, 1979307.490, 1018.46, 0)
+ ( 6294579.280, 1979283.460, 1017.87, 0)
+ ( 6294593.320, 1979278.020, 1016.36, 0)
+ ( 6294613.160, 1979275.640, 1013.15, 0)
+ ( 6294634.390, 1979274.630, 1009.54, 0)
+ ( 6294650.590, 1979272.960, 1006.4, 0)
+ ( 6294666.970, 1979274.830, 1003.77, 0)
+ ( 6294675.710, 1979289.290, 1001.81, 0)
+ ( 6294681.310, 1979309.230, 998.13, 0)
+ ( 6294686.190, 1979327.900, 995.64, 0)
+ ( 6294692.280, 1979346.960, 991.64, 0)
+ ( 6294699.730, 1979367.200, 989.08, 0)
+ ( 6294709.530, 1979384.310, 985.74, 0)
+ ( 6294716.160, 1979401.370, 983.25, 0)
+ ( 6294720.520, 1979414.810, 980.1, 0)
+ ( 6294718.980, 1979441.480, 978, 0)
+-------------------------------------------------------------------------
+Test 3: dump polygon.shp
+-------------------------------------------------------------------------
+Shapefile Type: Polygon # of Shapes: 474
+
+File Bounds: ( 471127.188, 4751545.000,0,0)
+ to ( 489292.312, 4765610.500,0,0)
+
+Shape:0 (Polygon) nVertices=20, nParts=1
+ Bounds:( 479647.000, 4764856.500, 0, 0)
+ to ( 480389.688, 4765610.500, 0, 0)
+ ( 479819.844, 4765180.500, 0, 0) Ring
+ ( 479690.188, 4765259.500, 0, 0)
+ ( 479647.000, 4765369.500, 0, 0)
+ ( 479730.375, 4765400.500, 0, 0)
+ ( 480039.031, 4765539.500, 0, 0)
+ ( 480035.344, 4765558.500, 0, 0)
+ ( 480159.781, 4765610.500, 0, 0)
+ ( 480202.281, 4765482.000, 0, 0)
+ ( 480365.000, 4765015.500, 0, 0)
+ ( 480389.688, 4764950.000, 0, 0)
+ ( 480133.969, 4764856.500, 0, 0)
+ ( 480080.281, 4764979.500, 0, 0)
+ ( 480082.969, 4765049.500, 0, 0)
+ ( 480088.812, 4765139.500, 0, 0)
+ ( 480059.906, 4765239.500, 0, 0)
+ ( 480019.719, 4765319.500, 0, 0)
+ ( 479980.219, 4765409.500, 0, 0)
+ ( 479909.875, 4765370.000, 0, 0)
+ ( 479859.875, 4765270.000, 0, 0)
+ ( 479819.844, 4765180.500, 0, 0)
+
+Shape:1 (Polygon) nVertices=20, nParts=1
+ Bounds:( 479014.938, 4764879.000, 0, 0)
+ to ( 480039.031, 4765558.500, 0, 0)
+ ( 480035.344, 4765558.500, 0, 0) Ring
+ ( 480039.031, 4765539.500, 0, 0)
+ ( 479730.375, 4765400.500, 0, 0)
+ ( 479647.000, 4765369.500, 0, 0)
+ ( 479690.188, 4765259.500, 0, 0)
+ ( 479819.844, 4765180.500, 0, 0)
+ ( 479779.844, 4765109.500, 0, 0)
+ ( 479681.781, 4764940.000, 0, 0)
+ ( 479468.000, 4764942.500, 0, 0)
+ ( 479411.438, 4764940.500, 0, 0)
+ ( 479353.000, 4764939.500, 0, 0)
+ ( 479208.656, 4764882.500, 0, 0)
+ ( 479196.812, 4764879.000, 0, 0)
+ ( 479123.281, 4765015.000, 0, 0)
+ ( 479046.531, 4765117.000, 0, 0)
+ ( 479029.719, 4765110.500, 0, 0)
+ ( 479014.938, 4765147.500, 0, 0)
+ ( 479149.938, 4765200.500, 0, 0)
+ ( 479639.625, 4765399.500, 0, 0)
+ ( 480035.344, 4765558.500, 0, 0)
+
+Shape:2 (Polygon) nVertices=54, nParts=1
+ Bounds:( 480882.688, 4763472.500, 0, 0)
+ to ( 484519.969, 4765410.000, 0, 0)
+ ( 481575.000, 4764999.500, 0, 0) Ring
+ ( 481542.312, 4765097.500, 0, 0)
+ ( 481443.688, 4765387.500, 0, 0)
+ ( 481499.656, 4765410.000, 0, 0)
+ ( 481631.000, 4765031.000, 0, 0)
+ ( 481693.312, 4764853.000, 0, 0)
+ ( 481759.281, 4764889.500, 0, 0)
+ ( 481860.031, 4764920.000, 0, 0)
+ ( 482002.969, 4764910.000, 0, 0)
+ ( 482180.094, 4764909.500, 0, 0)
+ ( 482359.812, 4764960.000, 0, 0)
+ ( 482510.500, 4765065.000, 0, 0)
+ ( 482619.906, 4765080.500, 0, 0)
+ ( 482809.500, 4765090.000, 0, 0)
+ ( 483189.812, 4765084.500, 0, 0)
+ ( 483330.312, 4765105.500, 0, 0)
+ ( 483591.094, 4765260.000, 0, 0)
+ ( 483700.500, 4765280.000, 0, 0)
+ ( 483799.938, 4765270.000, 0, 0)
+ ( 484039.844, 4765280.500, 0, 0)
+ ( 484115.688, 4765300.000, 0, 0)
+ ( 484120.625, 4765280.000, 0, 0)
+ ( 484131.125, 4765260.000, 0, 0)
+ ( 484167.844, 4765271.000, 0, 0)
+ ( 484277.875, 4765015.500, 0, 0)
+ ( 484455.062, 4764500.000, 0, 0)
+ ( 484519.969, 4764345.000, 0, 0)
+ ( 484482.031, 4764332.000, 0, 0)
+ ( 483904.719, 4764113.500, 0, 0)
+ ( 483334.844, 4763905.000, 0, 0)
+ ( 482941.031, 4763760.500, 0, 0)
+ ( 482590.719, 4763624.500, 0, 0)
+ ( 482185.656, 4763472.500, 0, 0)
+ ( 482009.844, 4763980.500, 0, 0)
+ ( 481960.438, 4764099.500, 0, 0)
+ ( 481767.500, 4764014.500, 0, 0)
+ ( 480955.500, 4763700.000, 0, 0)
+ ( 480882.688, 4763670.000, 0, 0)
+ ( 481039.938, 4763889.500, 0, 0)
+ ( 481130.312, 4763979.500, 0, 0)
+ ( 481143.438, 4764010.500, 0, 0)
+ ( 481199.844, 4764180.000, 0, 0)
+ ( 481141.625, 4764480.500, 0, 0)
+ ( 481140.469, 4764510.500, 0, 0)
+ ( 481159.938, 4764580.000, 0, 0)
+ ( 481185.500, 4764607.000, 0, 0)
+ ( 481199.219, 4764623.500, 0, 0)
+ ( 481209.812, 4764633.500, 0, 0)
+ ( 481235.312, 4764650.000, 0, 0)
+ ( 481635.969, 4764795.500, 0, 0)
+ ( 481645.312, 4764797.500, 0, 0)
+ ( 481629.844, 4764829.500, 0, 0)
+ ( 481602.125, 4764915.500, 0, 0)
+ ( 481575.000, 4764999.500, 0, 0)
+
+Shape:3 (Polygon) nVertices=29, nParts=1
+ Bounds:( 479117.812, 4764505.000, 0, 0)
+ to ( 480088.812, 4765409.500, 0, 0)
+ ( 479819.844, 4765180.500, 0, 0) Ring
+ ( 479859.875, 4765270.000, 0, 0)
+ ( 479909.875, 4765370.000, 0, 0)
+ ( 479980.219, 4765409.500, 0, 0)
+ ( 480019.719, 4765319.500, 0, 0)
+ ( 480059.906, 4765239.500, 0, 0)
+ ( 480088.812, 4765139.500, 0, 0)
+ ( 480082.969, 4765049.500, 0, 0)
+ ( 480000.281, 4765043.000, 0, 0)
+ ( 479934.969, 4765020.000, 0, 0)
+ ( 479895.125, 4765000.000, 0, 0)
+ ( 479734.375, 4764865.000, 0, 0)
+ ( 479680.281, 4764852.000, 0, 0)
+ ( 479644.781, 4764827.500, 0, 0)
+ ( 479637.875, 4764803.000, 0, 0)
+ ( 479617.219, 4764760.000, 0, 0)
+ ( 479587.281, 4764718.000, 0, 0)
+ ( 479548.031, 4764693.500, 0, 0)
+ ( 479504.906, 4764609.500, 0, 0)
+ ( 479239.812, 4764505.000, 0, 0)
+ ( 479117.812, 4764847.000, 0, 0)
+ ( 479196.812, 4764879.000, 0, 0)
+ ( 479208.656, 4764882.500, 0, 0)
+ ( 479353.000, 4764939.500, 0, 0)
+ ( 479411.438, 4764940.500, 0, 0)
+ ( 479468.000, 4764942.500, 0, 0)
+ ( 479681.781, 4764940.000, 0, 0)
+ ( 479779.844, 4765109.500, 0, 0)
+ ( 479819.844, 4765180.500, 0, 0)
+
+Shape:4 (Polygon) nVertices=22, nParts=1
+ Bounds:( 480537.156, 4764738.000, 0, 0)
+ to ( 481575.000, 4765387.500, 0, 0)
+ ( 480537.156, 4765014.000, 0, 0) Ring
+ ( 481090.281, 4765242.000, 0, 0)
+ ( 481443.688, 4765387.500, 0, 0)
+ ( 481542.312, 4765097.500, 0, 0)
+ ( 481575.000, 4764999.500, 0, 0)
+ ( 481538.906, 4764982.500, 0, 0)
+ ( 481509.656, 4764967.000, 0, 0)
+ ( 481457.375, 4764937.000, 0, 0)
+ ( 481465.906, 4764872.500, 0, 0)
+ ( 481291.094, 4764810.000, 0, 0)
+ ( 481281.312, 4764876.500, 0, 0)
+ ( 481136.844, 4764994.500, 0, 0)
+ ( 481088.188, 4764936.000, 0, 0)
+ ( 480984.250, 4764875.000, 0, 0)
+ ( 480930.719, 4764852.000, 0, 0)
+ ( 480922.031, 4764850.500, 0, 0)
+ ( 480824.969, 4764820.000, 0, 0)
+ ( 480761.469, 4764778.000, 0, 0)
+ ( 480701.062, 4764738.000, 0, 0)
+ ( 480605.000, 4764835.000, 0, 0)
+ ( 480567.969, 4764918.000, 0, 0)
+ ( 480537.156, 4765014.000, 0, 0)
+
+Shape:5 (Polygon) nVertices=60, nParts=1
+ Bounds:( 484482.031, 4760649.500, 0, 0)
+ to ( 488408.281, 4765179.000, 0, 0)
+ ( 484482.031, 4764332.000, 0, 0) Ring
+ ( 484519.969, 4764345.000, 0, 0)
+ ( 484817.938, 4764465.500, 0, 0)
+ ( 485615.406, 4764770.000, 0, 0)
+ ( 486269.688, 4765010.000, 0, 0)
+ ( 486320.062, 4765024.000, 0, 0)
+ ( 486340.594, 4765040.000, 0, 0)
+ ( 486369.844, 4765050.000, 0, 0)
+ ( 486719.969, 4765170.000, 0, 0)
+ ( 486738.625, 4765179.000, 0, 0)
+ ( 486987.781, 4764497.500, 0, 0)
+ ( 487019.875, 4764384.500, 0, 0)
+ ( 487077.375, 4764226.500, 0, 0)
+ ( 487120.031, 4764100.000, 0, 0)
+ ( 487160.250, 4763998.000, 0, 0)
+ ( 487186.812, 4763922.500, 0, 0)
+ ( 487408.250, 4763315.500, 0, 0)
+ ( 487608.062, 4762780.000, 0, 0)
+ ( 487659.406, 4762650.000, 0, 0)
+ ( 487719.406, 4762480.000, 0, 0)
+ ( 487741.062, 4762419.500, 0, 0)
+ ( 487747.875, 4762395.500, 0, 0)
+ ( 487880.875, 4762032.000, 0, 0)
+ ( 487899.438, 4761975.500, 0, 0)
+ ( 488082.000, 4761480.000, 0, 0)
+ ( 488408.281, 4760649.500, 0, 0)
+ ( 488050.375, 4760824.500, 0, 0)
+ ( 487690.906, 4760802.000, 0, 0)
+ ( 487640.062, 4760879.500, 0, 0)
+ ( 487594.938, 4761023.000, 0, 0)
+ ( 487341.375, 4761776.500, 0, 0)
+ ( 487037.125, 4761672.500, 0, 0)
+ ( 487005.375, 4761662.500, 0, 0)
+ ( 486788.219, 4761579.500, 0, 0)
+ ( 486822.250, 4761492.000, 0, 0)
+ ( 486838.312, 4761437.500, 0, 0)
+ ( 486841.312, 4761381.000, 0, 0)
+ ( 486850.562, 4761340.000, 0, 0)
+ ( 486810.750, 4761335.500, 0, 0)
+ ( 486775.438, 4761400.000, 0, 0)
+ ( 486710.094, 4761368.000, 0, 0)
+ ( 486606.188, 4761330.000, 0, 0)
+ ( 486548.656, 4761488.000, 0, 0)
+ ( 486380.656, 4761428.500, 0, 0)
+ ( 486152.906, 4761348.000, 0, 0)
+ ( 485900.250, 4761250.500, 0, 0)
+ ( 485666.875, 4761156.500, 0, 0)
+ ( 485585.875, 4761374.500, 0, 0)
+ ( 485564.875, 4761444.500, 0, 0)
+ ( 485496.219, 4761614.500, 0, 0)
+ ( 485438.688, 4761760.500, 0, 0)
+ ( 485264.969, 4762222.500, 0, 0)
+ ( 485192.688, 4762439.000, 0, 0)
+ ( 485175.406, 4762493.500, 0, 0)
+ ( 484947.344, 4763100.500, 0, 0)
+ ( 484888.000, 4763260.500, 0, 0)
+ ( 484785.469, 4763560.500, 0, 0)
+ ( 484760.219, 4763659.500, 0, 0)
+ ( 484696.969, 4763734.000, 0, 0)
+ ( 484482.031, 4764332.000, 0, 0)
+
+Shape:6 (Polygon) nVertices=26, nParts=1
+ Bounds:( 478315.531, 4764174.000, 0, 0)
+ to ( 479305.875, 4765147.500, 0, 0)
+ ( 479014.938, 4765147.500, 0, 0) Ring
+ ( 479029.719, 4765110.500, 0, 0)
+ ( 479117.812, 4764847.000, 0, 0)
+ ( 479239.812, 4764505.000, 0, 0)
+ ( 479305.875, 4764361.000, 0, 0)
+ ( 479256.031, 4764314.500, 0, 0)
+ ( 479220.906, 4764212.500, 0, 0)
+ ( 479114.500, 4764174.000, 0, 0)
+ ( 479018.281, 4764418.500, 0, 0)
+ ( 478896.938, 4764371.000, 0, 0)
+ ( 478748.812, 4764308.500, 0, 0)
+ ( 478503.031, 4764218.000, 0, 0)
+ ( 478461.750, 4764337.500, 0, 0)
+ ( 478443.938, 4764400.500, 0, 0)
+ ( 478447.812, 4764454.000, 0, 0)
+ ( 478448.688, 4764531.500, 0, 0)
+ ( 478502.188, 4764541.500, 0, 0)
+ ( 478683.000, 4764730.500, 0, 0)
+ ( 478621.031, 4764788.500, 0, 0)
+ ( 478597.344, 4764766.500, 0, 0)
+ ( 478532.500, 4764695.500, 0, 0)
+ ( 478460.125, 4764615.000, 0, 0)
+ ( 478408.062, 4764654.000, 0, 0)
+ ( 478315.531, 4764876.000, 0, 0)
+ ( 478889.250, 4765100.000, 0, 0)
+ ( 479014.938, 4765147.500, 0, 0)
+
+Shape:7 (Polygon) nVertices=6, nParts=1
+ Bounds:( 479029.719, 4764847.000, 0, 0)
+ to ( 479196.812, 4765117.000, 0, 0)
+ ( 479029.719, 4765110.500, 0, 0) Ring
+ ( 479046.531, 4765117.000, 0, 0)
+ ( 479123.281, 4765015.000, 0, 0)
+ ( 479196.812, 4764879.000, 0, 0)
+ ( 479117.812, 4764847.000, 0, 0)
+ ( 479029.719, 4765110.500, 0, 0)
+
+Shape:8 (Polygon) nVertices=20, nParts=1
+ Bounds:( 479504.906, 4764609.500, 0, 0)
+ to ( 480133.969, 4765049.500, 0, 0)
+ ( 480082.969, 4765049.500, 0, 0) Ring
+ ( 480080.281, 4764979.500, 0, 0)
+ ( 480133.969, 4764856.500, 0, 0)
+ ( 479968.469, 4764788.000, 0, 0)
+ ( 479750.688, 4764702.000, 0, 0)
+ ( 479735.906, 4764752.000, 0, 0)
+ ( 479640.094, 4764721.000, 0, 0)
+ ( 479658.594, 4764670.000, 0, 0)
+ ( 479504.906, 4764609.500, 0, 0)
+ ( 479548.031, 4764693.500, 0, 0)
+ ( 479587.281, 4764718.000, 0, 0)
+ ( 479617.219, 4764760.000, 0, 0)
+ ( 479637.875, 4764803.000, 0, 0)
+ ( 479644.781, 4764827.500, 0, 0)
+ ( 479680.281, 4764852.000, 0, 0)
+ ( 479734.375, 4764865.000, 0, 0)
+ ( 479895.125, 4765000.000, 0, 0)
+ ( 479934.969, 4765020.000, 0, 0)
+ ( 480000.281, 4765043.000, 0, 0)
+ ( 480082.969, 4765049.500, 0, 0)
+
+Shape:9 (Polygon) nVertices=31, nParts=1
+ Bounds:( 479968.469, 4764183.000, 0, 0)
+ to ( 480731.656, 4765014.000, 0, 0)
+ ( 480389.688, 4764950.000, 0, 0) Ring
+ ( 480537.156, 4765014.000, 0, 0)
+ ( 480567.969, 4764918.000, 0, 0)
+ ( 480605.000, 4764835.000, 0, 0)
+ ( 480701.062, 4764738.000, 0, 0)
+ ( 480710.250, 4764690.500, 0, 0)
+ ( 480588.594, 4764740.500, 0, 0)
+ ( 480540.719, 4764741.000, 0, 0)
+ ( 480515.125, 4764695.000, 0, 0)
+ ( 480731.656, 4764561.500, 0, 0)
+ ( 480692.188, 4764453.500, 0, 0)
+ ( 480677.844, 4764439.000, 0, 0)
+ ( 480655.344, 4764397.500, 0, 0)
+ ( 480584.375, 4764353.000, 0, 0)
+ ( 480500.406, 4764326.500, 0, 0)
+ ( 480358.531, 4764277.000, 0, 0)
+ ( 480192.312, 4764183.000, 0, 0)
+ ( 480157.125, 4764266.500, 0, 0)
+ ( 480234.312, 4764304.000, 0, 0)
+ ( 480289.125, 4764348.500, 0, 0)
+ ( 480316.000, 4764395.000, 0, 0)
+ ( 480343.562, 4764477.000, 0, 0)
+ ( 480343.719, 4764532.500, 0, 0)
+ ( 480258.031, 4764767.000, 0, 0)
+ ( 480177.156, 4764742.000, 0, 0)
+ ( 480093.750, 4764703.000, 0, 0)
+ ( 480011.000, 4764674.500, 0, 0)
+ ( 479985.062, 4764732.000, 0, 0)
+ ( 479968.469, 4764788.000, 0, 0)
+ ( 480133.969, 4764856.500, 0, 0)
+ ( 480389.688, 4764950.000, 0, 0)
+
+Shape:10 (Polygon) nVertices=61, nParts=1
+ Bounds:( 479492.688, 4762880.500, 0, 0)
+ to ( 481645.312, 4764999.500, 0, 0)
+ ( 480701.062, 4764738.000, 0, 0) Ring
+ ( 480761.469, 4764778.000, 0, 0)
+ ( 480824.969, 4764820.000, 0, 0)
+ ( 480922.031, 4764850.500, 0, 0)
+ ( 480930.719, 4764852.000, 0, 0)
+ ( 480984.250, 4764875.000, 0, 0)
+ ( 481088.188, 4764936.000, 0, 0)
+ ( 481136.844, 4764994.500, 0, 0)
+ ( 481281.312, 4764876.500, 0, 0)
+ ( 481291.094, 4764810.000, 0, 0)
+ ( 481465.906, 4764872.500, 0, 0)
+ ( 481457.375, 4764937.000, 0, 0)
+ ( 481509.656, 4764967.000, 0, 0)
+ ( 481538.906, 4764982.500, 0, 0)
+ ( 481575.000, 4764999.500, 0, 0)
+ ( 481602.125, 4764915.500, 0, 0)
+ ( 481629.844, 4764829.500, 0, 0)
+ ( 481645.312, 4764797.500, 0, 0)
+ ( 481635.969, 4764795.500, 0, 0)
+ ( 481235.312, 4764650.000, 0, 0)
+ ( 481209.812, 4764633.500, 0, 0)
+ ( 481199.219, 4764623.500, 0, 0)
+ ( 481185.500, 4764607.000, 0, 0)
+ ( 481159.938, 4764580.000, 0, 0)
+ ( 481140.469, 4764510.500, 0, 0)
+ ( 481141.625, 4764480.500, 0, 0)
+ ( 481199.844, 4764180.000, 0, 0)
+ ( 481143.438, 4764010.500, 0, 0)
+ ( 481130.312, 4763979.500, 0, 0)
+ ( 481039.938, 4763889.500, 0, 0)
+ ( 480882.688, 4763670.000, 0, 0)
+ ( 480826.062, 4763650.500, 0, 0)
+ ( 480745.188, 4763628.500, 0, 0)
+ ( 480654.438, 4763627.500, 0, 0)
+ ( 480599.812, 4763660.000, 0, 0)
+ ( 480281.938, 4763576.500, 0, 0)
+ ( 480221.500, 4763533.500, 0, 0)
+ ( 480199.688, 4763509.000, 0, 0)
+ ( 480195.094, 4763430.000, 0, 0)
+ ( 480273.688, 4763305.500, 0, 0)
+ ( 480309.688, 4763063.500, 0, 0)
+ ( 480201.844, 4762962.500, 0, 0)
+ ( 479855.312, 4762880.500, 0, 0)
+ ( 479848.531, 4762897.000, 0, 0)
+ ( 479728.875, 4763217.500, 0, 0)
+ ( 479492.688, 4763850.000, 0, 0)
+ ( 479550.062, 4763919.500, 0, 0)
+ ( 480120.219, 4764188.500, 0, 0)
+ ( 480192.312, 4764183.000, 0, 0)
+ ( 480358.531, 4764277.000, 0, 0)
+ ( 480500.406, 4764326.500, 0, 0)
+ ( 480584.375, 4764353.000, 0, 0)
+ ( 480655.344, 4764397.500, 0, 0)
+ ( 480677.844, 4764439.000, 0, 0)
+ ( 480692.188, 4764453.500, 0, 0)
+ ( 480731.656, 4764561.500, 0, 0)
+ ( 480515.125, 4764695.000, 0, 0)
+ ( 480540.719, 4764741.000, 0, 0)
+ ( 480588.594, 4764740.500, 0, 0)
+ ( 480710.250, 4764690.500, 0, 0)
+ ( 480701.062, 4764738.000, 0, 0)
+
+Shape:11 (Polygon) nVertices=21, nParts=1
+ Bounds:( 476732.906, 4763624.500, 0, 0)
+ to ( 478408.062, 4764876.000, 0, 0)
+ ( 478315.531, 4764876.000, 0, 0) Ring
+ ( 478408.062, 4764654.000, 0, 0)
+ ( 478325.250, 4764606.500, 0, 0)
+ ( 478220.094, 4764574.500, 0, 0)
+ ( 478140.344, 4764511.000, 0, 0)
+ ( 478065.062, 4764487.500, 0, 0)
+ ( 478080.938, 4764401.500, 0, 0)
+ ( 478110.500, 4764308.500, 0, 0)
+ ( 478149.969, 4764212.500, 0, 0)
+ ( 478180.219, 4764150.000, 0, 0)
+ ( 478192.500, 4764099.500, 0, 0)
+ ( 477893.125, 4763984.500, 0, 0)
+ ( 477417.031, 4763800.500, 0, 0)
+ ( 477005.594, 4763640.000, 0, 0)
+ ( 476958.312, 4763624.500, 0, 0)
+ ( 476947.250, 4763664.500, 0, 0)
+ ( 476732.906, 4764243.000, 0, 0)
+ ( 477322.375, 4764502.000, 0, 0)
+ ( 477599.906, 4764600.000, 0, 0)
+ ( 477949.656, 4764745.000, 0, 0)
+ ( 478315.531, 4764876.000, 0, 0)
+
+Shape:12 (Polygon) nVertices=22, nParts=1
+ Bounds:( 478065.062, 4764099.500, 0, 0)
+ to ( 478683.000, 4764788.500, 0, 0)
+ ( 478408.062, 4764654.000, 0, 0) Ring
+ ( 478460.125, 4764615.000, 0, 0)
+ ( 478532.500, 4764695.500, 0, 0)
+ ( 478597.344, 4764766.500, 0, 0)
+ ( 478621.031, 4764788.500, 0, 0)
+ ( 478683.000, 4764730.500, 0, 0)
+ ( 478502.188, 4764541.500, 0, 0)
+ ( 478448.688, 4764531.500, 0, 0)
+ ( 478447.812, 4764454.000, 0, 0)
+ ( 478443.938, 4764400.500, 0, 0)
+ ( 478461.750, 4764337.500, 0, 0)
+ ( 478503.031, 4764218.000, 0, 0)
+ ( 478192.500, 4764099.500, 0, 0)
+ ( 478180.219, 4764150.000, 0, 0)
+ ( 478149.969, 4764212.500, 0, 0)
+ ( 478110.500, 4764308.500, 0, 0)
+ ( 478080.938, 4764401.500, 0, 0)
+ ( 478065.062, 4764487.500, 0, 0)
+ ( 478140.344, 4764511.000, 0, 0)
+ ( 478220.094, 4764574.500, 0, 0)
+ ( 478325.250, 4764606.500, 0, 0)
+ ( 478408.062, 4764654.000, 0, 0)
+
+Shape:13 (Polygon) nVertices=27, nParts=1
+ Bounds:( 479239.812, 4763850.000, 0, 0)
+ to ( 480343.719, 4764788.000, 0, 0)
+ ( 479750.688, 4764702.000, 0, 0) Ring
+ ( 479968.469, 4764788.000, 0, 0)
+ ( 479985.062, 4764732.000, 0, 0)
+ ( 480011.000, 4764674.500, 0, 0)
+ ( 480093.750, 4764703.000, 0, 0)
+ ( 480177.156, 4764742.000, 0, 0)
+ ( 480258.031, 4764767.000, 0, 0)
+ ( 480343.719, 4764532.500, 0, 0)
+ ( 480343.562, 4764477.000, 0, 0)
+ ( 480316.000, 4764395.000, 0, 0)
+ ( 480289.125, 4764348.500, 0, 0)
+ ( 480234.312, 4764304.000, 0, 0)
+ ( 480157.125, 4764266.500, 0, 0)
+ ( 480192.312, 4764183.000, 0, 0)
+ ( 480120.219, 4764188.500, 0, 0)
+ ( 479550.062, 4763919.500, 0, 0)
+ ( 479492.688, 4763850.000, 0, 0)
+ ( 479487.750, 4763864.500, 0, 0)
+ ( 479442.750, 4763990.000, 0, 0)
+ ( 479436.000, 4764023.000, 0, 0)
+ ( 479398.938, 4764100.000, 0, 0)
+ ( 479349.625, 4764230.000, 0, 0)
+ ( 479305.875, 4764361.000, 0, 0)
+ ( 479239.812, 4764505.000, 0, 0)
+ ( 479504.906, 4764609.500, 0, 0)
+ ( 479658.594, 4764670.000, 0, 0)
+ ( 479750.688, 4764702.000, 0, 0)
+
+Shape:14 (Polygon) nVertices=5, nParts=1
+ Bounds:( 479640.094, 4764670.000, 0, 0)
+ to ( 479750.688, 4764752.000, 0, 0)
+ ( 479750.688, 4764702.000, 0, 0) Ring
+ ( 479658.594, 4764670.000, 0, 0)
+ ( 479640.094, 4764721.000, 0, 0)
+ ( 479735.906, 4764752.000, 0, 0)
+ ( 479750.688, 4764702.000, 0, 0)
+
+Shape:15 (Polygon) nVertices=28, nParts=1
+ Bounds:( 478503.031, 4763357.500, 0, 0)
+ to ( 479349.625, 4764418.500, 0, 0)
+ ( 479305.875, 4764361.000, 0, 0) Ring
+ ( 479349.625, 4764230.000, 0, 0)
+ ( 479218.156, 4764126.000, 0, 0)
+ ( 479128.344, 4764030.500, 0, 0)
+ ( 479103.406, 4764000.000, 0, 0)
+ ( 479099.594, 4763977.500, 0, 0)
+ ( 479080.812, 4763930.000, 0, 0)
+ ( 478999.812, 4763864.500, 0, 0)
+-------------------------------------------------------------------------
+Test 4: dump pline.dbf - uses new F field type
+-------------------------------------------------------------------------
+Field 0: Type=Integer, Title=`FNODE_', Width=11, Decimals=0
+Field 1: Type=Integer, Title=`TNODE_', Width=11, Decimals=0
+Field 2: Type=Integer, Title=`LPOLY_', Width=11, Decimals=0
+Field 3: Type=Integer, Title=`RPOLY_', Width=11, Decimals=0
+Field 4: Type=Double, Title=`LENGTH', Width=13, Decimals=3
+Field 5: Type=Integer, Title=`PLINE_', Width=11, Decimals=0
+Field 6: Type=Integer, Title=`PLINE_ID', Width=11, Decimals=0
+Field 7: Type=Integer, Title=`UID', Width=11, Decimals=0
+Field 8: Type=Integer, Title=`GISO_TYPE_', Width=11, Decimals=0
+Field 9: Type=Integer, Title=`SYMBOL', Width=6, Decimals=0
+Field 10: Type=Integer, Title=`LOCK__ID', Width=11, Decimals=0
+Field 11: Type=Integer, Title=`PHASE__ID', Width=6, Decimals=0
+Field 12: Type=Integer, Title=`OBJECT__ID', Width=11, Decimals=0
+Field 13: Type=String, Title=`TYPE', Width=50, Decimals=0
+Field 14: Type=Integer, Title=`SYM_NBR', Width=6, Decimals=0
+Field 15: Type=String, Title=`PHASE', Width=4, Decimals=0
+Field 16: Type=String, Title=`CKT_NM', Width=30, Decimals=0
+Field 17: Type=String, Title=`VOLTAGE', Width=30, Decimals=0
+Field 18: Type=String, Title=`CMPN', Width=30, Decimals=0
+
+Record: 0
+FNODE_: 351
+TNODE_: 352
+LPOLY_: 0
+RPOLY_: 0
+LENGTH: 139.451
+PLINE_: 1
+PLINE_ID: 8588
+UID: 544484
+GISO_TYPE_: 13
+SYMBOL: 101
+LOCK__ID: 0
+PHASE__ID: 0
+OBJECT__ID: 131978
+TYPE: Overhead Primary
+SYM_NBR: 101
+PHASE: ABC
+CKT_NM: MED36
+VOLTAGE: (NULL)
+CMPN: (NULL)
+
+Record: 1
+FNODE_: 352
+TNODE_: 362
+LPOLY_: 0
+RPOLY_: 0
+LENGTH: 158.033
+PLINE_: 2
+PLINE_ID: 8695
+UID: 544591
+-------------------------------------------------------------------------
+Test 5: NULL Shapes.
+-------------------------------------------------------------------------
+Shapefile Type: Arc # of Shapes: 124
+
+File Bounds: ( 257104.880, 5176098.606,0,0)
+ to ( 335497.500, 5226768.100,0,0)
+
+Shape:0 (Arc) nVertices=21, nParts=1
+ Bounds:( 317138.450, 5176398.916, 0, 0)
+ to ( 317325.590, 5186063.780, 0, 0)
+ ( 317255.906, 5176398.916, 0, 0) Ring
+ ( 317188.010, 5176506.460, 0, 0)
+ ( 317176.920, 5176524.510, 0, 0)
+ ( 317165.340, 5176546.850, 0, 0)
+ ( 317157.950, 5176566.020, 0, 0)
+ ( 317150.020, 5176587.650, 0, 0)
+ ( 317140.130, 5176623.380, 0, 0)
+ ( 317138.700, 5176637.220, 0, 0)
+ ( 317138.450, 5176652.790, 0, 0)
+ ( 317194.710, 5177654.350, 0, 0)
+ ( 317208.900, 5178001.150, 0, 0)
+ ( 317257.240, 5178791.400, 0, 0)
+ ( 317233.330, 5179171.730, 0, 0)
+ ( 317178.860, 5179593.910, 0, 0)
+ ( 317177.430, 5180161.330, 0, 0)
+ ( 317179.910, 5181231.060, 0, 0)
+ ( 317191.120, 5182009.000, 0, 0)
+ ( 317217.150, 5182812.160, 0, 0)
+ ( 317251.760, 5184426.350, 0, 0)
+ ( 317285.550, 5185242.720, 0, 0)
+ ( 317325.590, 5186063.780, 0, 0)
+
+Shape:1 (Arc) nVertices=14, nParts=1
+ Bounds:( 327417.340, 5176119.960, 0, 0)
+ to ( 327575.150, 5179522.550, 0, 0)
+ ( 327417.340, 5176119.960, 0, 0) Ring
+ ( 327472.250, 5177756.610, 0, 0)
+ ( 327475.670, 5178507.280, 0, 0)
+ ( 327487.420, 5179001.910, 0, 0)
+ ( 327488.760, 5179080.090, 0, 0)
+ ( 327485.310, 5179309.310, 0, 0)
+ ( 327487.010, 5179328.210, 0, 0)
+ ( 327491.800, 5179348.860, 0, 0)
+ ( 327499.800, 5179374.940, 0, 0)
+ ( 327512.980, 5179413.100, 0, 0)
+ ( 327527.290, 5179446.960, 0, 0)
+ ( 327538.870, 5179469.890, 0, 0)
+ ( 327552.260, 5179491.550, 0, 0)
+ ( 327575.150, 5179522.550, 0, 0)
+
+Shape:2 (Arc) nVertices=40, nParts=1
+ Bounds:( 326935.880, 5180924.980, 0, 0)
+ to ( 327723.190, 5198803.660, 0, 0)
+ ( 327370.950, 5180924.980, 0, 0) Ring
+ ( 327410.070, 5181060.540, 0, 0)
+ ( 327512.850, 5181435.450, 0, 0)
+ ( 327518.640, 5181464.010, 0, 0)
+ ( 327523.700, 5181488.920, 0, 0)
+ ( 327524.500, 5181514.570, 0, 0)
+ ( 327468.010, 5182633.640, 0, 0)
+ ( 327500.040, 5183199.840, 0, 0)
+ ( 327499.600, 5183224.920, 0, 0)
+ ( 327484.700, 5183355.010, 0, 0)
+ ( 327483.690, 5183400.900, 0, 0)
+ ( 327483.840, 5183464.480, 0, 0)
+ ( 327486.010, 5183494.980, 0, 0)
+ ( 327571.280, 5184207.820, 0, 0)
+ ( 327617.210, 5184599.430, 0, 0)
+ ( 327620.420, 5184623.780, 0, 0)
+ ( 327625.530, 5184650.530, 0, 0)
+ ( 327698.430, 5184927.070, 0, 0)
+ ( 327702.100, 5184946.520, 0, 0)
+ ( 327717.940, 5185394.820, 0, 0)
+ ( 327723.190, 5185719.320, 0, 0)
+ ( 327719.460, 5185737.170, 0, 0)
+ ( 327712.090, 5185755.740, 0, 0)
+ ( 327699.840, 5185775.080, 0, 0)
+ ( 327683.830, 5185791.480, 0, 0)
+ ( 327665.380, 5185807.950, 0, 0)
+ ( 327641.970, 5185822.740, 0, 0)
+ ( 327622.280, 5185829.070, 0, 0)
+ ( 327604.950, 5185832.940, 0, 0)
+ ( 326937.500, 5185829.310, 0, 0)
+ ( 326935.880, 5187515.510, 0, 0)
+ ( 326983.050, 5189115.230, 0, 0)
+ ( 326998.860, 5189920.820, 0, 0)
+ ( 327060.240, 5190715.870, 0, 0)
+ ( 327123.230, 5192332.220, 0, 0)
+ ( 327179.920, 5193766.290, 0, 0)
+ ( 327185.490, 5193921.940, 0, 0)
+ ( 327204.120, 5195553.580, 0, 0)
+ ( 327218.270, 5197179.250, 0, 0)
+ ( 327251.330, 5198803.660, 0, 0)
+
+Shape:3 (NullShape) nVertices=0, nParts=0
+ Bounds:( 0.000, 0.000, 0, 0)
+ to ( 0.000, 0.000, 0, 0)
+
+Shape:4 (NullShape) nVertices=0, nParts=0
+ Bounds:( 0.000, 0.000, 0, 0)
+ to ( 0.000, 0.000, 0, 0)
+
+Shape:5 (NullShape) nVertices=0, nParts=0
+ Bounds:( 0.000, 0.000, 0, 0)
+ to ( 0.000, 0.000, 0, 0)
+
+Shape:6 (Arc) nVertices=2, nParts=1
+ Bounds:( 327123.230, 5192296.600, 0, 0)
+ to ( 328480.850, 5192332.220, 0, 0)
+ ( 327123.230, 5192332.220, 0, 0) Ring
+ ( 328480.850, 5192296.600, 0, 0)
+
+Shape:7 (Arc) nVertices=5, nParts=1
+ Bounds:( 329222.060, 5217943.490, 0, 0)
+ to ( 335290.680, 5218084.780, 0, 0)
+ ( 329222.060, 5218084.780, 0, 0) Ring
+ ( 330442.520, 5218057.650, 0, 0)
+ ( 332059.960, 5218033.810, 0, 0)
+ ( 333685.820, 5218004.860, 0, 0)
+ ( 335290.680, 5217943.490, 0, 0)
+
+Shape:8 (Arc) nVertices=65, nParts=1
+ Bounds:( 280048.100, 5177687.643, 0, 0)
+ to ( 280439.410, 5182567.120, 0, 0)
+ ( 280316.840, 5177687.643, 0, 0) Ring
+ ( 280325.310, 5177968.830, 0, 0)
+ ( 280324.630, 5178037.940, 0, 0)
+ ( 280324.150, 5178059.350, 0, 0)
+ ( 280320.130, 5178084.560, 0, 0)
+ ( 280299.860, 5178170.250, 0, 0)
+ ( 280288.710, 5178218.940, 0, 0)
+ ( 280274.280, 5178283.640, 0, 0)
+ ( 280268.000, 5178330.870, 0, 0)
+ ( 280267.910, 5178346.760, 0, 0)
+ ( 280270.510, 5178364.580, 0, 0)
+ ( 280274.820, 5178382.360, 0, 0)
+ ( 280278.440, 5178397.210, 0, 0)
+ ( 280351.400, 5178743.800, 0, 0)
+ ( 280369.860, 5178800.630, 0, 0)
+ ( 280378.670, 5178826.010, 0, 0)
+ ( 280400.350, 5178869.890, 0, 0)
+ ( 280414.870, 5178901.180, 0, 0)
+ ( 280427.030, 5178934.990, 0, 0)
+ ( 280436.250, 5178971.970, 0, 0)
+ ( 280439.410, 5178992.650, 0, 0)
+ ( 280439.170, 5179001.630, 0, 0)
+ ( 280437.010, 5179011.690, 0, 0)
+ ( 280434.930, 5179016.970, 0, 0)
+ ( 280431.870, 5179022.260, 0, 0)
+ ( 280413.610, 5179041.850, 0, 0)
+ ( 280410.040, 5179046.780, 0, 0)
+ ( 280406.640, 5179052.480, 0, 0)
diff --git a/src/shapelib/stream1.sh b/src/shapelib/stream1.sh
new file mode 100755
index 0000000..8a32887
--- /dev/null
+++ b/src/shapelib/stream1.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+EG_DATA=/u/www/projects/shapelib/eg_data
+
+echo -------------------------------------------------------------------------
+echo Test 1: dump anno.shp
+echo -------------------------------------------------------------------------
+./shpdump $EG_DATA/anno.shp | head -250
+
+echo -------------------------------------------------------------------------
+echo Test 2: dump brklinz.shp
+echo -------------------------------------------------------------------------
+./shpdump $EG_DATA/brklinz.shp | head -500
+
+echo -------------------------------------------------------------------------
+echo Test 3: dump polygon.shp
+echo -------------------------------------------------------------------------
+./shpdump $EG_DATA/polygon.shp | head -500
+
+echo -------------------------------------------------------------------------
+echo Test 4: dump pline.dbf - uses new F field type
+echo -------------------------------------------------------------------------
+./dbfdump -m -h $EG_DATA/pline.dbf | head -50
+
+echo -------------------------------------------------------------------------
+echo Test 5: NULL Shapes.
+echo -------------------------------------------------------------------------
+./shpdump $EG_DATA/csah.dbf | head -150
diff --git a/src/shapelib/stream2.out b/src/shapelib/stream2.out
new file mode 100644
index 0000000..424a9e6
--- /dev/null
+++ b/src/shapelib/stream2.out
@@ -0,0 +1,530 @@
+-----------------------------------------------------------------------
+Test 2/0
+-----------------------------------------------------------------------
+Shapefile Type: NullShape # of Shapes: 2
+
+File Bounds: ( 0.000, 0.000,0,0)
+ to ( 10.000, 20.000,0,0)
+
+Shape:0 (NullShape) nVertices=0, nParts=0
+ Bounds:( 0.000, 0.000, 0, 0)
+ to ( 0.000, 0.000, 0, 0)
+
+Shape:1 (NullShape) nVertices=0, nParts=0
+ Bounds:( 0.000, 0.000, 0, 0)
+ to ( 0.000, 0.000, 0, 0)
+-----------------------------------------------------------------------
+Test 2/1
+-----------------------------------------------------------------------
+Shapefile Type: Point # of Shapes: 2
+
+File Bounds: ( 1.000, 2.000,0,0)
+ to ( 10.000, 20.000,0,0)
+
+Shape:0 (Point) nVertices=1, nParts=0
+ Bounds:( 1.000, 2.000, 0, 0)
+ to ( 1.000, 2.000, 0, 0)
+ ( 1.000, 2.000, 0, 0)
+
+Shape:1 (Point) nVertices=1, nParts=0
+ Bounds:( 10.000, 20.000, 0, 0)
+ to ( 10.000, 20.000, 0, 0)
+ ( 10.000, 20.000, 0, 0)
+-----------------------------------------------------------------------
+Test 2/2
+-----------------------------------------------------------------------
+Shapefile Type: PointZ # of Shapes: 2
+
+File Bounds: ( 1.000, 2.000,3,4)
+ to ( 10.000, 20.000,30,40)
+
+Shape:0 (PointZ) nVertices=1, nParts=0
+ Bounds:( 1.000, 2.000, 3, 4)
+ to ( 1.000, 2.000, 3, 4)
+ ( 1.000, 2.000, 3, 4)
+
+Shape:1 (PointZ) nVertices=1, nParts=0
+ Bounds:( 10.000, 20.000, 30, 40)
+ to ( 10.000, 20.000, 30, 40)
+ ( 10.000, 20.000, 30, 40)
+-----------------------------------------------------------------------
+Test 2/3
+-----------------------------------------------------------------------
+Shapefile Type: PointM # of Shapes: 2
+
+File Bounds: ( 1.000, 2.000,0,4)
+ to ( 10.000, 20.000,0,40)
+
+Shape:0 (PointM) nVertices=1, nParts=0
+ Bounds:( 1.000, 2.000, 0, 4)
+ to ( 1.000, 2.000, 0, 4)
+ ( 1.000, 2.000, 0, 4)
+
+Shape:1 (PointM) nVertices=1, nParts=0
+ Bounds:( 10.000, 20.000, 0, 40)
+ to ( 10.000, 20.000, 0, 40)
+ ( 10.000, 20.000, 0, 40)
+-----------------------------------------------------------------------
+Test 2/4
+-----------------------------------------------------------------------
+Shapefile Type: MultiPoint # of Shapes: 3
+
+File Bounds: ( 1.150, 2.250,0,0)
+ to ( 24.150, 25.250,0,0)
+
+Shape:0 (MultiPoint) nVertices=4, nParts=0
+ Bounds:( 1.150, 2.250, 0, 0)
+ to ( 4.150, 5.250, 0, 0)
+ ( 1.150, 2.250, 0, 0)
+ ( 2.150, 3.250, 0, 0)
+ ( 3.150, 4.250, 0, 0)
+ ( 4.150, 5.250, 0, 0)
+
+Shape:1 (MultiPoint) nVertices=4, nParts=0
+ Bounds:( 11.150, 12.250, 0, 0)
+ to ( 14.150, 15.250, 0, 0)
+ ( 11.150, 12.250, 0, 0)
+ ( 12.150, 13.250, 0, 0)
+ ( 13.150, 14.250, 0, 0)
+ ( 14.150, 15.250, 0, 0)
+
+Shape:2 (MultiPoint) nVertices=4, nParts=0
+ Bounds:( 21.150, 22.250, 0, 0)
+ to ( 24.150, 25.250, 0, 0)
+ ( 21.150, 22.250, 0, 0)
+ ( 22.150, 23.250, 0, 0)
+ ( 23.150, 24.250, 0, 0)
+ ( 24.150, 25.250, 0, 0)
+-----------------------------------------------------------------------
+Test 2/5
+-----------------------------------------------------------------------
+Shapefile Type: MultiPointZ # of Shapes: 3
+
+File Bounds: ( 1.150, 2.250,3.35,4.45)
+ to ( 24.150, 25.250,26.35,27.45)
+
+Shape:0 (MultiPointZ) nVertices=4, nParts=0
+ Bounds:( 1.150, 2.250, 3.35, 4.45)
+ to ( 4.150, 5.250, 6.35, 7.45)
+ ( 1.150, 2.250, 3.35, 4.45)
+ ( 2.150, 3.250, 4.35, 5.45)
+ ( 3.150, 4.250, 5.35, 6.45)
+ ( 4.150, 5.250, 6.35, 7.45)
+
+Shape:1 (MultiPointZ) nVertices=4, nParts=0
+ Bounds:( 11.150, 12.250, 13.35, 14.45)
+ to ( 14.150, 15.250, 16.35, 17.45)
+ ( 11.150, 12.250, 13.35, 14.45)
+ ( 12.150, 13.250, 14.35, 15.45)
+ ( 13.150, 14.250, 15.35, 16.45)
+ ( 14.150, 15.250, 16.35, 17.45)
+
+Shape:2 (MultiPointZ) nVertices=4, nParts=0
+ Bounds:( 21.150, 22.250, 23.35, 24.45)
+ to ( 24.150, 25.250, 26.35, 27.45)
+ ( 21.150, 22.250, 23.35, 24.45)
+ ( 22.150, 23.250, 24.35, 25.45)
+ ( 23.150, 24.250, 25.35, 26.45)
+ ( 24.150, 25.250, 26.35, 27.45)
+-----------------------------------------------------------------------
+Test 2/6
+-----------------------------------------------------------------------
+Shapefile Type: MultiPointM # of Shapes: 3
+
+File Bounds: ( 1.150, 2.250,0,4.45)
+ to ( 24.150, 25.250,0,27.45)
+
+Shape:0 (MultiPointM) nVertices=4, nParts=0
+ Bounds:( 1.150, 2.250, 0, 4.45)
+ to ( 4.150, 5.250, 0, 7.45)
+ ( 1.150, 2.250, 0, 4.45)
+ ( 2.150, 3.250, 0, 5.45)
+ ( 3.150, 4.250, 0, 6.45)
+ ( 4.150, 5.250, 0, 7.45)
+
+Shape:1 (MultiPointM) nVertices=4, nParts=0
+ Bounds:( 11.150, 12.250, 0, 14.45)
+ to ( 14.150, 15.250, 0, 17.45)
+ ( 11.150, 12.250, 0, 14.45)
+ ( 12.150, 13.250, 0, 15.45)
+ ( 13.150, 14.250, 0, 16.45)
+ ( 14.150, 15.250, 0, 17.45)
+
+Shape:2 (MultiPointM) nVertices=4, nParts=0
+ Bounds:( 21.150, 22.250, 0, 24.45)
+ to ( 24.150, 25.250, 0, 27.45)
+ ( 21.150, 22.250, 0, 24.45)
+ ( 22.150, 23.250, 0, 25.45)
+ ( 23.150, 24.250, 0, 26.45)
+ ( 24.150, 25.250, 0, 27.45)
+-----------------------------------------------------------------------
+Test 2/7
+-----------------------------------------------------------------------
+Shapefile Type: Arc # of Shapes: 4
+
+File Bounds: ( 0.000, 0.000,0,0)
+ to ( 100.000, 100.000,0,0)
+
+Shape:0 (Arc) nVertices=5, nParts=1
+ Bounds:( 1.000, 1.000, 0, 0)
+ to ( 2.000, 2.000, 0, 0)
+ ( 1.000, 1.000, 0, 0) Ring
+ ( 2.000, 1.000, 0, 0)
+ ( 2.000, 2.000, 0, 0)
+ ( 1.000, 2.000, 0, 0)
+ ( 1.000, 1.000, 0, 0)
+
+Shape:1 (Arc) nVertices=5, nParts=1
+ Bounds:( 1.000, 4.000, 0, 0)
+ to ( 2.000, 5.000, 0, 0)
+ ( 1.000, 4.000, 0, 0) Ring
+ ( 2.000, 4.000, 0, 0)
+ ( 2.000, 5.000, 0, 0)
+ ( 1.000, 5.000, 0, 0)
+ ( 1.000, 4.000, 0, 0)
+
+Shape:2 (Arc) nVertices=5, nParts=1
+ Bounds:( 1.000, 7.000, 0, 0)
+ to ( 2.000, 8.000, 0, 0)
+ ( 1.000, 7.000, 0, 0) Ring
+ ( 2.000, 7.000, 0, 0)
+ ( 2.000, 8.000, 0, 0)
+ ( 1.000, 8.000, 0, 0)
+ ( 1.000, 7.000, 0, 0)
+
+Shape:3 (Arc) nVertices=15, nParts=3
+ Bounds:( 0.000, 0.000, 0, 0)
+ to ( 100.000, 100.000, 0, 0)
+ ( 0.000, 0.000, 0, 0) Ring
+ ( 0.000, 100.000, 0, 0)
+ ( 100.000, 100.000, 0, 0)
+ ( 100.000, 0.000, 0, 0)
+ ( 0.000, 0.000, 0, 0)
+ + ( 10.000, 20.000, 0, 0) Ring
+ ( 30.000, 20.000, 0, 0)
+ ( 30.000, 40.000, 0, 0)
+ ( 10.000, 40.000, 0, 0)
+ ( 10.000, 20.000, 0, 0)
+ + ( 60.000, 20.000, 0, 0) Ring
+ ( 90.000, 20.000, 0, 0)
+ ( 90.000, 40.000, 0, 0)
+ ( 60.000, 40.000, 0, 0)
+ ( 60.000, 20.000, 0, 0)
+-----------------------------------------------------------------------
+Test 2/8
+-----------------------------------------------------------------------
+Shapefile Type: ArcZ # of Shapes: 4
+
+File Bounds: ( 0.000, 0.000,0,0)
+ to ( 100.000, 100.000,27.35,28.45)
+
+Shape:0 (ArcZ) nVertices=5, nParts=1
+ Bounds:( 1.000, 1.000, 3.35, 4.45)
+ to ( 2.000, 2.000, 7.35, 8.45)
+ ( 1.000, 1.000, 3.35, 4.45) Ring
+ ( 2.000, 1.000, 4.35, 5.45)
+ ( 2.000, 2.000, 5.35, 6.45)
+ ( 1.000, 2.000, 6.35, 7.45)
+ ( 1.000, 1.000, 7.35, 8.45)
+
+Shape:1 (ArcZ) nVertices=5, nParts=1
+ Bounds:( 1.000, 4.000, 13.35, 14.45)
+ to ( 2.000, 5.000, 17.35, 18.45)
+ ( 1.000, 4.000, 13.35, 14.45) Ring
+ ( 2.000, 4.000, 14.35, 15.45)
+ ( 2.000, 5.000, 15.35, 16.45)
+ ( 1.000, 5.000, 16.35, 17.45)
+ ( 1.000, 4.000, 17.35, 18.45)
+
+Shape:2 (ArcZ) nVertices=5, nParts=1
+ Bounds:( 1.000, 7.000, 23.35, 24.45)
+ to ( 2.000, 8.000, 27.35, 28.45)
+ ( 1.000, 7.000, 23.35, 24.45) Ring
+ ( 2.000, 7.000, 24.35, 25.45)
+ ( 2.000, 8.000, 25.35, 26.45)
+ ( 1.000, 8.000, 26.35, 27.45)
+ ( 1.000, 7.000, 27.35, 28.45)
+
+Shape:3 (ArcZ) nVertices=15, nParts=3
+ Bounds:( 0.000, 0.000, 0, 0)
+ to ( 100.000, 100.000, 14, 28)
+ ( 0.000, 0.000, 0, 0) Ring
+ ( 0.000, 100.000, 1, 2)
+ ( 100.000, 100.000, 2, 4)
+ ( 100.000, 0.000, 3, 6)
+ ( 0.000, 0.000, 4, 8)
+ + ( 10.000, 20.000, 5, 10) Ring
+ ( 30.000, 20.000, 6, 12)
+ ( 30.000, 40.000, 7, 14)
+ ( 10.000, 40.000, 8, 16)
+ ( 10.000, 20.000, 9, 18)
+ + ( 60.000, 20.000, 10, 20) Ring
+ ( 90.000, 20.000, 11, 22)
+ ( 90.000, 40.000, 12, 24)
+ ( 60.000, 40.000, 13, 26)
+ ( 60.000, 20.000, 14, 28)
+-----------------------------------------------------------------------
+Test 2/9
+-----------------------------------------------------------------------
+Shapefile Type: ArcM # of Shapes: 4
+
+File Bounds: ( 0.000, 0.000,0,0)
+ to ( 100.000, 100.000,0,28.45)
+
+Shape:0 (ArcM) nVertices=5, nParts=1
+ Bounds:( 1.000, 1.000, 0, 4.45)
+ to ( 2.000, 2.000, 0, 8.45)
+ ( 1.000, 1.000, 0, 4.45) Ring
+ ( 2.000, 1.000, 0, 5.45)
+ ( 2.000, 2.000, 0, 6.45)
+ ( 1.000, 2.000, 0, 7.45)
+ ( 1.000, 1.000, 0, 8.45)
+
+Shape:1 (ArcM) nVertices=5, nParts=1
+ Bounds:( 1.000, 4.000, 0, 14.45)
+ to ( 2.000, 5.000, 0, 18.45)
+ ( 1.000, 4.000, 0, 14.45) Ring
+ ( 2.000, 4.000, 0, 15.45)
+ ( 2.000, 5.000, 0, 16.45)
+ ( 1.000, 5.000, 0, 17.45)
+ ( 1.000, 4.000, 0, 18.45)
+
+Shape:2 (ArcM) nVertices=5, nParts=1
+ Bounds:( 1.000, 7.000, 0, 24.45)
+ to ( 2.000, 8.000, 0, 28.45)
+ ( 1.000, 7.000, 0, 24.45) Ring
+ ( 2.000, 7.000, 0, 25.45)
+ ( 2.000, 8.000, 0, 26.45)
+ ( 1.000, 8.000, 0, 27.45)
+ ( 1.000, 7.000, 0, 28.45)
+
+Shape:3 (ArcM) nVertices=15, nParts=3
+ Bounds:( 0.000, 0.000, 0, 0)
+ to ( 100.000, 100.000, 0, 28)
+ ( 0.000, 0.000, 0, 0) Ring
+ ( 0.000, 100.000, 0, 2)
+ ( 100.000, 100.000, 0, 4)
+ ( 100.000, 0.000, 0, 6)
+ ( 0.000, 0.000, 0, 8)
+ + ( 10.000, 20.000, 0, 10) Ring
+ ( 30.000, 20.000, 0, 12)
+ ( 30.000, 40.000, 0, 14)
+ ( 10.000, 40.000, 0, 16)
+ ( 10.000, 20.000, 0, 18)
+ + ( 60.000, 20.000, 0, 20) Ring
+ ( 90.000, 20.000, 0, 22)
+ ( 90.000, 40.000, 0, 24)
+ ( 60.000, 40.000, 0, 26)
+ ( 60.000, 20.000, 0, 28)
+-----------------------------------------------------------------------
+Test 2/10
+-----------------------------------------------------------------------
+Shapefile Type: Polygon # of Shapes: 4
+
+File Bounds: ( 0.000, 0.000,0,0)
+ to ( 100.000, 100.000,0,0)
+
+Shape:0 (Polygon) nVertices=5, nParts=1
+ Bounds:( 1.000, 1.000, 0, 0)
+ to ( 2.000, 2.000, 0, 0)
+ ( 1.000, 1.000, 0, 0) Ring
+ ( 2.000, 1.000, 0, 0)
+ ( 2.000, 2.000, 0, 0)
+ ( 1.000, 2.000, 0, 0)
+ ( 1.000, 1.000, 0, 0)
+
+Shape:1 (Polygon) nVertices=5, nParts=1
+ Bounds:( 1.000, 4.000, 0, 0)
+ to ( 2.000, 5.000, 0, 0)
+ ( 1.000, 4.000, 0, 0) Ring
+ ( 2.000, 4.000, 0, 0)
+ ( 2.000, 5.000, 0, 0)
+ ( 1.000, 5.000, 0, 0)
+ ( 1.000, 4.000, 0, 0)
+
+Shape:2 (Polygon) nVertices=5, nParts=1
+ Bounds:( 1.000, 7.000, 0, 0)
+ to ( 2.000, 8.000, 0, 0)
+ ( 1.000, 7.000, 0, 0) Ring
+ ( 2.000, 7.000, 0, 0)
+ ( 2.000, 8.000, 0, 0)
+ ( 1.000, 8.000, 0, 0)
+ ( 1.000, 7.000, 0, 0)
+
+Shape:3 (Polygon) nVertices=15, nParts=3
+ Bounds:( 0.000, 0.000, 0, 0)
+ to ( 100.000, 100.000, 0, 0)
+ ( 0.000, 0.000, 0, 0) Ring
+ ( 0.000, 100.000, 0, 0)
+ ( 100.000, 100.000, 0, 0)
+ ( 100.000, 0.000, 0, 0)
+ ( 0.000, 0.000, 0, 0)
+ + ( 10.000, 20.000, 0, 0) Ring
+ ( 30.000, 20.000, 0, 0)
+ ( 30.000, 40.000, 0, 0)
+ ( 10.000, 40.000, 0, 0)
+ ( 10.000, 20.000, 0, 0)
+ + ( 60.000, 20.000, 0, 0) Ring
+ ( 90.000, 20.000, 0, 0)
+ ( 90.000, 40.000, 0, 0)
+ ( 60.000, 40.000, 0, 0)
+ ( 60.000, 20.000, 0, 0)
+-----------------------------------------------------------------------
+Test 2/11
+-----------------------------------------------------------------------
+Shapefile Type: PolygonZ # of Shapes: 4
+
+File Bounds: ( 0.000, 0.000,0,0)
+ to ( 100.000, 100.000,27.35,28.45)
+
+Shape:0 (PolygonZ) nVertices=5, nParts=1
+ Bounds:( 1.000, 1.000, 3.35, 4.45)
+ to ( 2.000, 2.000, 7.35, 8.45)
+ ( 1.000, 1.000, 3.35, 4.45) Ring
+ ( 2.000, 1.000, 4.35, 5.45)
+ ( 2.000, 2.000, 5.35, 6.45)
+ ( 1.000, 2.000, 6.35, 7.45)
+ ( 1.000, 1.000, 7.35, 8.45)
+
+Shape:1 (PolygonZ) nVertices=5, nParts=1
+ Bounds:( 1.000, 4.000, 13.35, 14.45)
+ to ( 2.000, 5.000, 17.35, 18.45)
+ ( 1.000, 4.000, 13.35, 14.45) Ring
+ ( 2.000, 4.000, 14.35, 15.45)
+ ( 2.000, 5.000, 15.35, 16.45)
+ ( 1.000, 5.000, 16.35, 17.45)
+ ( 1.000, 4.000, 17.35, 18.45)
+
+Shape:2 (PolygonZ) nVertices=5, nParts=1
+ Bounds:( 1.000, 7.000, 23.35, 24.45)
+ to ( 2.000, 8.000, 27.35, 28.45)
+ ( 1.000, 7.000, 23.35, 24.45) Ring
+ ( 2.000, 7.000, 24.35, 25.45)
+ ( 2.000, 8.000, 25.35, 26.45)
+ ( 1.000, 8.000, 26.35, 27.45)
+ ( 1.000, 7.000, 27.35, 28.45)
+
+Shape:3 (PolygonZ) nVertices=15, nParts=3
+ Bounds:( 0.000, 0.000, 0, 0)
+ to ( 100.000, 100.000, 14, 28)
+ ( 0.000, 0.000, 0, 0) Ring
+ ( 0.000, 100.000, 1, 2)
+ ( 100.000, 100.000, 2, 4)
+ ( 100.000, 0.000, 3, 6)
+ ( 0.000, 0.000, 4, 8)
+ + ( 10.000, 20.000, 5, 10) Ring
+ ( 30.000, 20.000, 6, 12)
+ ( 30.000, 40.000, 7, 14)
+ ( 10.000, 40.000, 8, 16)
+ ( 10.000, 20.000, 9, 18)
+ + ( 60.000, 20.000, 10, 20) Ring
+ ( 90.000, 20.000, 11, 22)
+ ( 90.000, 40.000, 12, 24)
+ ( 60.000, 40.000, 13, 26)
+ ( 60.000, 20.000, 14, 28)
+-----------------------------------------------------------------------
+Test 2/12
+-----------------------------------------------------------------------
+Shapefile Type: PolygonM # of Shapes: 4
+
+File Bounds: ( 0.000, 0.000,0,0)
+ to ( 100.000, 100.000,0,28.45)
+
+Shape:0 (PolygonM) nVertices=5, nParts=1
+ Bounds:( 1.000, 1.000, 0, 4.45)
+ to ( 2.000, 2.000, 0, 8.45)
+ ( 1.000, 1.000, 0, 4.45) Ring
+ ( 2.000, 1.000, 0, 5.45)
+ ( 2.000, 2.000, 0, 6.45)
+ ( 1.000, 2.000, 0, 7.45)
+ ( 1.000, 1.000, 0, 8.45)
+
+Shape:1 (PolygonM) nVertices=5, nParts=1
+ Bounds:( 1.000, 4.000, 0, 14.45)
+ to ( 2.000, 5.000, 0, 18.45)
+ ( 1.000, 4.000, 0, 14.45) Ring
+ ( 2.000, 4.000, 0, 15.45)
+ ( 2.000, 5.000, 0, 16.45)
+ ( 1.000, 5.000, 0, 17.45)
+ ( 1.000, 4.000, 0, 18.45)
+
+Shape:2 (PolygonM) nVertices=5, nParts=1
+ Bounds:( 1.000, 7.000, 0, 24.45)
+ to ( 2.000, 8.000, 0, 28.45)
+ ( 1.000, 7.000, 0, 24.45) Ring
+ ( 2.000, 7.000, 0, 25.45)
+ ( 2.000, 8.000, 0, 26.45)
+ ( 1.000, 8.000, 0, 27.45)
+ ( 1.000, 7.000, 0, 28.45)
+
+Shape:3 (PolygonM) nVertices=15, nParts=3
+ Bounds:( 0.000, 0.000, 0, 0)
+ to ( 100.000, 100.000, 0, 28)
+ ( 0.000, 0.000, 0, 0) Ring
+ ( 0.000, 100.000, 0, 2)
+ ( 100.000, 100.000, 0, 4)
+ ( 100.000, 0.000, 0, 6)
+ ( 0.000, 0.000, 0, 8)
+ + ( 10.000, 20.000, 0, 10) Ring
+ ( 30.000, 20.000, 0, 12)
+ ( 30.000, 40.000, 0, 14)
+ ( 10.000, 40.000, 0, 16)
+ ( 10.000, 20.000, 0, 18)
+ + ( 60.000, 20.000, 0, 20) Ring
+ ( 90.000, 20.000, 0, 22)
+ ( 90.000, 40.000, 0, 24)
+ ( 60.000, 40.000, 0, 26)
+ ( 60.000, 20.000, 0, 28)
+-----------------------------------------------------------------------
+Test 2/13
+-----------------------------------------------------------------------
+Shapefile Type: MultiPatch # of Shapes: 4
+
+File Bounds: ( 0.000, 0.000,0,0)
+ to ( 100.000, 100.000,27.35,28.45)
+
+Shape:0 (MultiPatch) nVertices=5, nParts=1
+ Bounds:( 1.000, 1.000, 3.35, 0)
+ to ( 2.000, 2.000, 7.35, 0)
+ ( 1.000, 1.000, 3.35, 0) Ring
+ ( 2.000, 1.000, 4.35, 0)
+ ( 2.000, 2.000, 5.35, 0)
+ ( 1.000, 2.000, 6.35, 0)
+ ( 1.000, 1.000, 7.35, 0)
+
+Shape:1 (MultiPatch) nVertices=5, nParts=1
+ Bounds:( 1.000, 4.000, 13.35, 0)
+ to ( 2.000, 5.000, 17.35, 0)
+ ( 1.000, 4.000, 13.35, 0) Ring
+ ( 2.000, 4.000, 14.35, 0)
+ ( 2.000, 5.000, 15.35, 0)
+ ( 1.000, 5.000, 16.35, 0)
+ ( 1.000, 4.000, 17.35, 0)
+
+Shape:2 (MultiPatch) nVertices=5, nParts=1
+ Bounds:( 1.000, 7.000, 23.35, 0)
+ to ( 2.000, 8.000, 27.35, 0)
+ ( 1.000, 7.000, 23.35, 0) Ring
+ ( 2.000, 7.000, 24.35, 0)
+ ( 2.000, 8.000, 25.35, 0)
+ ( 1.000, 8.000, 26.35, 0)
+ ( 1.000, 7.000, 27.35, 0)
+
+Shape:3 (MultiPatch) nVertices=15, nParts=3
+ Bounds:( 0.000, 0.000, 0, 0)
+ to ( 100.000, 100.000, 14, 0)
+ ( 0.000, 0.000, 0, 0) Ring
+ ( 0.000, 100.000, 1, 0)
+ ( 100.000, 100.000, 2, 0)
+ ( 100.000, 0.000, 3, 0)
+ ( 0.000, 0.000, 4, 0)
+ + ( 10.000, 20.000, 5, 0) InnerRing
+ ( 30.000, 20.000, 6, 0)
+ ( 30.000, 40.000, 7, 0)
+ ( 10.000, 40.000, 8, 0)
+ ( 10.000, 20.000, 9, 0)
+ + ( 60.000, 20.000, 10, 0) InnerRing
+ ( 90.000, 20.000, 11, 0)
+ ( 90.000, 40.000, 12, 0)
+ ( 60.000, 40.000, 13, 0)
+ ( 60.000, 20.000, 14, 0)
diff --git a/src/shapelib/stream2.sh b/src/shapelib/stream2.sh
new file mode 100755
index 0000000..bd0b111
--- /dev/null
+++ b/src/shapelib/stream2.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13; do
+ echo -----------------------------------------------------------------------
+ echo Test 2/$i
+ echo -----------------------------------------------------------------------
+
+ ./shptest $i
+ ./shpdump test${i}.shp
+done
+
diff --git a/src/shapelib/stream3.out b/src/shapelib/stream3.out
new file mode 100644
index 0000000..b668233
--- /dev/null
+++ b/src/shapelib/stream3.out
@@ -0,0 +1,37 @@
+Shapefile Type: Polygon # of Shapes: 3
+
+File Bounds: ( 0.000, 0.000,0,0)
+ to ( 180.000, 170.000,0,0)
+
+Shape:0 (Polygon) nVertices=9, nParts=2
+ Bounds:( 0.000, 0.000, 0, 0)
+ to ( 100.000, 100.000, 0, 0)
+ ( 0.000, 0.000, 0, 0) Ring
+ ( 100.000, 0.000, 0, 0)
+ ( 100.000, 100.000, 0, 0)
+ ( 0.000, 100.000, 0, 0)
+ ( 0.000, 0.000, 0, 0)
+ + ( 20.000, 20.000, 0, 0) Ring
+ ( 20.000, 30.000, 0, 0)
+ ( 30.000, 30.000, 0, 0)
+ ( 20.000, 20.000, 0, 0)
+
+Shape:1 (Polygon) nVertices=4, nParts=1
+ Bounds:( 150.000, 150.000, 0, 0)
+ to ( 180.000, 170.000, 0, 0)
+ ( 150.000, 150.000, 0, 0) Ring
+ ( 160.000, 150.000, 0, 0)
+ ( 180.000, 170.000, 0, 0)
+ ( 150.000, 150.000, 0, 0)
+
+Shape:2 (Polygon) nVertices=4, nParts=1
+ Bounds:( 150.000, 150.000, 0, 0)
+ to ( 180.000, 170.000, 0, 0)
+ ( 150.000, 150.000, 0, 0) Ring
+ ( 160.000, 150.000, 0, 0)
+ ( 180.000, 170.000, 0, 0)
+ ( 150.000, 150.000, 0, 0)
+Descriptio TestInt TestDouble
+Square with triangle missing 1 2.50000
+Smaller triangle 100 1000.25000
+(NULL) (NULL) (NULL)
diff --git a/src/shp_hash.c b/src/shp_hash.c
new file mode 100644
index 0000000..aa82a0d
--- /dev/null
+++ b/src/shp_hash.c
@@ -0,0 +1,390 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: shp_hash.c,v 1.29 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#ifdef USE_RTREE
+#ifdef HAVE_LIBSHP
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+#ifdef HAVE_SHAPEFIL_H
+#include <shapefil.h>
+#else
+#ifdef HAVE_LIBSHP_SHAPEFIL_H
+#include <libshp/shapefil.h>
+#else
+#error HAVE_LIBSHP defined but no corresponding include defined
+#endif // HAVE_LIBSHP_SHAPEFIL_H
+#endif // HAVE_SHAPEFIL_H
+
+
+#include <rtree/index.h>
+
+#include "xastir.h"
+#include "util.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+/// THIS ONLY FOR DEBUGGING!
+#include "hashtable_private.h"
+#include "shp_hash.h"
+#include "snprintf.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+#define PURGE_PERIOD 3600 // One hour, hard coded for now.
+ // This should be in a slider in the timing
+ // configuration instead.
+
+//#define PURGE_PERIOD 120 // debugging
+
+static struct hashtable *shp_hash=NULL;
+static time_t purge_time;
+
+#define SHP_HASH_SIZE 65535
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+
+
+
+
+unsigned int shape_hash_from_key(void *key) {
+ char *str=(char *)key;
+ unsigned int shphash=5381;
+ int c;
+ int i=0;
+ while (str[i]!='\0') {
+ c=str[i++];
+ shphash = ((shphash << 5) + shphash)^c;
+ }
+
+ return (shphash);
+}
+
+
+
+
+
+int shape_keys_equal(void *key1, void *key2) {
+
+ // fprintf(stderr,"Comparing %s to %s\n",(char *)key1,(char *)key2);
+ if (strncmp((char *)key1,(char *)key2,strlen((char *)key1))==0) {
+ // fprintf(stderr," match\n");
+ return(1);
+ } else {
+ // fprintf(stderr," no match\n");
+ return(0);
+ }
+}
+
+
+
+
+
+void init_shp_hash(int clobber) {
+ //fprintf(stderr," Initializing shape hash \n");
+ // make sure we don't leak
+ if (shp_hash) {
+ if (clobber) {
+ hashtable_destroy(shp_hash, 1);
+ shp_hash=create_hashtable(SHP_HASH_SIZE,
+ shape_hash_from_key,
+ shape_keys_equal);
+ }
+ } else {
+ shp_hash=create_hashtable(SHP_HASH_SIZE,
+ shape_hash_from_key,
+ shape_keys_equal);
+ }
+
+ // Now set the static timer value to the next time we need to run the purge
+ // routine
+ purge_time = sec_now() + PURGE_PERIOD;
+}
+
+
+
+
+
+// destructor for a single shapeinfo structure
+void destroy_shpinfo(shpinfo *si) {
+ if (si) {
+ empty_shpinfo(si);
+ // fprintf(stderr,
+ // " Freeing shpinfo %lx\n",
+ // (unsigned long int) si);
+ free(si);
+ }
+}
+
+
+
+
+
+// free the pointers in a shapinfo object
+void empty_shpinfo(shpinfo *si) {
+ if (si) {
+ if (si->root) {
+ // fprintf(stderr," Freeing root\n");
+ Xastir_RTreeDestroyNode(si->root);
+ si->root=NULL;
+ }
+
+ // This is a little annoying --- the hashtable functions free the
+ // key, which is in our case the filename. So since we're only going
+ // to empty the shpinfo when we're removing from the hashtable, we
+ // must not free the filename ourselves.
+ // if (si->filename) {
+ // fprintf(stderr," Freeing filename\n");
+ // free(si->filename);
+ // si->filename=NULL;
+ // }
+ }
+}
+
+
+
+
+
+void destroy_shp_hash(void) {
+ struct hashtable_itr *iterator=NULL;
+ shpinfo *si;
+ int ret;
+
+ if (shp_hash) {
+ // walk through the hashtable, free any pointers in the values
+ // that aren't null, or we'll leak like a sieve.
+
+ // the hashtable functions always attempt to dereference iterator,
+ // and don't check if you give it a null, but will return null if
+ // there's nothing in the table. Grrrr.
+ iterator=hashtable_iterator(shp_hash);
+ do {
+ ret=0;
+ if (iterator) {
+ si = hashtable_iterator_value(iterator);
+ if (si)
+ empty_shpinfo(si);
+ ret=hashtable_iterator_advance(iterator);
+ }
+ } while (ret);
+ hashtable_destroy(shp_hash, 1); // destroy the hashtable, freeing
+ // what's left of the entries
+ shp_hash=NULL;
+ if (iterator) free(iterator);
+ }
+}
+
+
+
+
+
+void add_shp_to_hash(char *filename, SHPHandle sHP) {
+
+ // This function does NOT check whether there already is something in
+ // the hashtable that matches.
+ // Check that before calling this routine.
+
+ shpinfo *temp;
+ int filenm_len;
+
+ filenm_len=strlen(filename);
+ if (!shp_hash) { // no table to add to
+ init_shp_hash(1); // so create one
+ }
+ temp = (shpinfo *)malloc(sizeof(shpinfo));
+ CHECKMALLOC(temp);
+ // leave room for terminator
+ temp->filename = (char *) malloc(sizeof(char)*(filenm_len+1));
+ CHECKMALLOC(temp->filename);
+
+ strncpy(temp->filename,filename,filenm_len+1);
+ temp->filename[filenm_len]='\0'; // just to be safe
+// xastir_snprintf(temp->filename,sizeof(shpinfo),"%s",filename);
+
+ temp->root = Xastir_RTreeNewIndex();
+ temp->creation = sec_now();
+ temp->last_access = temp->creation;
+
+ build_rtree(&(temp->root),sHP);
+
+ //fprintf(stderr, " adding %s...",temp->filename);
+ if (!hashtable_insert(shp_hash,temp->filename,temp)) {
+ fprintf(stderr,"Insert failed on shapefile hash --- fatal\n");
+ free(temp->filename);
+ free(temp);
+ exit(1);
+ }
+}
+
+
+
+
+
+shpinfo *get_shp_from_hash(char *filename) {
+ shpinfo *result;
+ if (!shp_hash) { // no table to search
+ init_shp_hash(1); // so create one
+ return NULL;
+ }
+
+ //fprintf(stderr," searching for %s...",filename);
+
+ result=hashtable_search(shp_hash,filename);
+
+ // if (result) {
+ // fprintf(stderr," found it\n");
+ // } else {
+ // fprintf(stderr," it is not there\n");
+ // }
+
+ // If there is one, we have now accessed it, so bump the last access time
+ if (result) {
+ result->last_access = sec_now();
+ }
+
+ return (result);
+
+}
+
+
+
+
+
+//CAREFUL: note how adding things to the tree can change the root
+// Must not ever use cache a value of the root pointer if there's any
+// chance that the tree needs to be expanded!
+void build_rtree (struct Node **root, SHPHandle sHP) {
+ int nEntities;
+ intptr_t i;
+ SHPObject *psCShape;
+ struct Rect bbox_shape;
+ SHPGetInfo(sHP, &nEntities, NULL, NULL, NULL);
+ for( i = 0; i < nEntities; i++ ) {
+ psCShape = SHPReadObject ( sHP, i );
+ if (psCShape != NULL) {
+ bbox_shape.boundary[0]=(RectReal) psCShape->dfXMin;
+ bbox_shape.boundary[1]=(RectReal) psCShape->dfYMin;
+ bbox_shape.boundary[2]=(RectReal) psCShape->dfXMax;
+ bbox_shape.boundary[3]=(RectReal) psCShape->dfYMax;
+ SHPDestroyObject ( psCShape );
+ // Only insert the rect if it will not fail the assertion in
+ // Xastir_RTreeInsertRect --- this will cause us to ignore any shapes that
+ // have invalid bboxes (or that return invalid bboxes from shapelib
+ // for whatever reason
+ if (bbox_shape.boundary[0] <= bbox_shape.boundary[2] &&
+ bbox_shape.boundary[1] <= bbox_shape.boundary[3]) {
+ Xastir_RTreeInsertRect(&bbox_shape, (void *)(i+1), root, 0);
+ }
+ }
+ }
+}
+
+
+
+
+
+void purge_shp_hash(time_t secs_now) {
+ struct hashtable_itr *iterator=NULL;
+ shpinfo *si;
+ int ret;
+
+
+ if (secs_now > purge_time) { // Time to purge
+ //time_now = localtime(&secs_now);
+ //(void)strftime(timestring,100,"%a %b %d %H:%M:%S %Z %Y",time_now);
+ //fprintf(stderr,"Purging...%s\n",timestring);
+
+ purge_time += PURGE_PERIOD;
+
+ if (shp_hash) {
+ // walk through the hash table and kill entries that are old
+
+ iterator=hashtable_iterator(shp_hash);
+ do {
+ ret=0;
+ if (iterator) { // must check this, because could be null
+ // if the iterator malloc failed
+ si=hashtable_iterator_value(iterator);
+
+ if (si) {
+ if (secs_now > si->last_access+PURGE_PERIOD) {
+ // this is stale, hasn't been accessed in a while
+ //fprintf(stderr,
+ // "found stale entry for %s, deleting it.\n",
+ // si->filename);
+ //fprintf(stderr," Destroying si=%lx\n",
+ // (unsigned long int) si);
+ ret=hashtable_iterator_remove(iterator);
+
+ // Important that we NOT do the
+ // destroy first, because we've used
+ // the filename pointer field of the
+ // structure as the key, and the
+ // remove function will free that. If
+ // we clobber the struct first, we
+ // invite segfaults
+ destroy_shpinfo(si);
+
+ //fprintf(stderr," removing from hashtable\n");
+ } else {
+ ret=hashtable_iterator_advance(iterator);
+ }
+ }
+ }
+ } while (ret);
+ // we're now done with the iterator. Free it to stop us from
+ // leaking!
+ if (iterator) free(iterator);
+ }
+ //fprintf(stderr," done Purging...\n");
+ }
+}
+
+#endif // HAVE_LIBSHP
+#endif // USE_RTREE
+
+
+// To get rid of "-pedantic" compiler warning:
+int NON_EMPTY_SOURCE_FILE;
+
+
diff --git a/src/shp_hash.h b/src/shp_hash.h
new file mode 100644
index 0000000..498e949
--- /dev/null
+++ b/src/shp_hash.h
@@ -0,0 +1,39 @@
+
+// $Id: shp_hash.h,v 1.11 2012/11/01 18:57:19 we7u Exp $
+// Copyright (C) 2004-2012 The Xastir Group
+
+
+#ifndef __XASTIR_SHP_HASH_H
+#define __XASTIR_SHP_HASH_H
+
+#ifdef USE_RTREE
+
+#ifdef HAVE_SHAPEFIL_H
+#include <shapefil.h>
+#else
+#ifdef HAVE_LIBSHP_SHAPEFIL_H
+#include <libshp/shapefil.h>
+#else
+#error HAVE_LIBSHP defined but no corresponding include defined
+#endif // HAVE_LIBSHP_SHAPEFIL_H
+#endif // HAVE_SHAPEFIL_H
+
+typedef struct _shpinfo{
+ char *filename;
+ struct Node* root;
+ time_t creation;
+ time_t last_access;
+ int num_accesses;
+}shpinfo;
+
+void init_shp_hash(int clobber);
+void add_shp_to_hash(char *filename,SHPHandle sHP);
+void build_rtree(struct Node **root, SHPHandle sHP);
+void destroy_shp_hash(void);
+void empty_shpinfo(shpinfo *si);
+void destroy_shpinfo(shpinfo *si);
+void purge_shp_hash(time_t secs_now);
+shpinfo *get_shp_from_hash(char *filename);
+
+#endif // USE_RTREE
+#endif // __XASTIR_SHP_HASH_H
diff --git a/src/snprintf.c b/src/snprintf.c
new file mode 100644
index 0000000..793b619
--- /dev/null
+++ b/src/snprintf.c
@@ -0,0 +1,747 @@
+/*
+ * snprintf.c - a portable implementation of snprintf and vsnprintf
+ *
+ * $Id: snprintf.c,v 1.14 2012/08/25 16:38:29 tvrusso Exp $
+ */
+/*
+ * Portions Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+
+/*
+ * Copyright Patrick Powell 1995
+ * This code is based on code written by Patrick Powell (papowell at astart.com)
+ * It may be used for any purpose as long as this notice remains intact
+ * on all source code distributions
+ */
+
+/**************************************************************
+ * Original:
+ * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
+ * A bombproof version of doprnt (dopr) included.
+ * Sigh. This sort of thing is always nasty do deal with. Note that
+ * the version here does not include floating point...
+ *
+ * snprintf() is used instead of sprintf() as it does limit checks
+ * for string length. This covers a nasty loophole.
+ *
+ * The other functions are there to prevent NULL pointers from
+ * causing nast effects.
+ *
+ * More Recently:
+ * Brandon Long <blong at fiction.net> 9/15/96 for mutt 0.43
+ * This was ugly. It is still ugly. I opted out of floating point
+ * numbers, but the formatter understands just about everything
+ * from the normal C string format, at least as far as I can tell from
+ * the Solaris 2.5 printf(3S) man page.
+ *
+ * Brandon Long <blong at fiction.net> 10/22/97 for mutt 0.87.1
+ * Ok, added some minimal floating point support, which means this
+ * probably requires libm on most operating systems. Don't yet
+ * support the exponent (e,E) and sigfig (g,G). Also, fmtint()
+ * was pretty badly broken, it just wasn't being exercised in ways
+ * which showed it, so that's been fixed. Also, formated the code
+ * to mutt conventions, and removed dead code left over from the
+ * original. Also, there is now a builtin-test, just compile with:
+ * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
+ * and run snprintf for results.
+ *
+ * Thomas Roessler <roessler at guug.de> 01/27/98 for mutt 0.89i
+ * The PGP code was using unsigned hexadecimal formats.
+ * Unfortunately, unsigned formats simply didn't work.
+ *
+ * Michael Elkins <me at cs.hmc.edu> 03/05/98 for mutt 0.90.8
+ * The original code assumed that both snprintf() and vsnprintf() were
+ * missing. Some systems only have snprintf() but not vsnprintf(), so
+ * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
+ *
+ * Andrew Tridgell (tridge at samba.org) Oct 1998
+ * fixed handling of %.0f
+ * added test for HAVE_LONG_DOUBLE
+ *
+ *
+ **************************************************************/
+
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#ifndef HAVE_VSNPRINTF
+
+/* varargs declarations: */
+
+#if defined(__STDC__)
+# ifdef HAVE_STDARG_H
+# include <stdarg.h>
+# else // HAVE_STDARG_H
+# ifdef HAVE_STD_ARGS_H
+# include <std_args.h>
+# endif // HAVE_STD_ARGS_H
+# endif // HAVE_STDARG_H
+# include <stdarg.h>
+# define HAVE_STDARGS /* let's hope that works everywhere (mj) */
+# define VA_LOCAL_DECL va_list ap
+# define VA_START(f) va_start(ap, f)
+# define VA_SHIFT(v,t); /* no-op for ANSI */
+# define VA_END va_end(ap)
+#else // __STDC__
+# include <varargs.h>
+# undef HAVE_STDARGS
+# define VA_LOCAL_DECL va_list ap
+# define VA_START(f) va_start(ap) /* f is ignored! */
+# define VA_SHIFT(v,t) v = va_arg(ap,t)
+# define VA_END va_end(ap)
+#endif // __STDC__
+
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+#ifdef HAVE_LONG_DOUBLE
+#define LDOUBLE long double
+#else // HAVE_LONG_DOUBLE
+#define LDOUBLE double
+#endif // HAVE_LONG_DOUBLE
+
+static void dopr(char *buffer, size_t maxlen, const char *format, va_list args);
+static void fmtstr(char *buffer, size_t * currlen, size_t maxlen, char *value,
+ int flags, int min, int max);
+static void fmtint(char *buffer, size_t * currlen, size_t maxlen, long value,
+ int base, int min, int max, int flags);
+static void fmtfp(char *buffer, size_t * currlen, size_t maxlen,
+ LDOUBLE fvalue, int min, int max, int flags);
+static void dopr_outch(char *buffer, size_t * currlen, size_t maxlen, char c);
+
+/*
+ * dopr(): poor man's version of doprintf
+ */
+
+/* format read states */
+#define DP_S_DEFAULT 0
+#define DP_S_FLAGS 1
+#define DP_S_MIN 2
+#define DP_S_DOT 3
+#define DP_S_MAX 4
+#define DP_S_MOD 5
+#define DP_S_CONV 6
+#define DP_S_DONE 7
+
+/* format flags - Bits */
+#define DP_F_MINUS (1 << 0)
+#define DP_F_PLUS (1 << 1)
+#define DP_F_SPACE (1 << 2)
+#define DP_F_NUM (1 << 3)
+#define DP_F_ZERO (1 << 4)
+#define DP_F_UP (1 << 5)
+#define DP_F_UNSIGNED (1 << 6)
+
+/* Conversion Flags */
+#define DP_C_SHORT 1
+#define DP_C_LONG 2
+#define DP_C_LDOUBLE 3
+
+#define char_to_int(p) (p - '0')
+#define MAX(p, q) ((p >= q) ? p : q)
+
+static void dopr(char *buffer, size_t maxlen, const char *format, va_list args) {
+ char ch;
+ long value;
+ LDOUBLE fvalue;
+ char *strvalue;
+ int min;
+ int max;
+ int state;
+ int flags;
+ int cflags;
+ size_t currlen;
+
+ state = DP_S_DEFAULT;
+ currlen = flags = cflags = min = 0;
+ max = -1;
+ ch = *format++;
+
+ while (state != DP_S_DONE) {
+ if ((ch == '\0') || (currlen >= maxlen))
+ state = DP_S_DONE;
+
+ switch (state) {
+ case DP_S_DEFAULT:
+ if (ch == '%')
+ state = DP_S_FLAGS;
+ else
+ dopr_outch(buffer, &currlen, maxlen, ch);
+
+ ch = *format++;
+ break;
+ case DP_S_FLAGS:
+ switch (ch) {
+ case '-':
+ flags |= DP_F_MINUS;
+ ch = *format++;
+ break;
+ case '+':
+ flags |= DP_F_PLUS;
+ ch = *format++;
+ break;
+ case ' ':
+ flags |= DP_F_SPACE;
+ ch = *format++;
+ break;
+ case '#':
+ flags |= DP_F_NUM;
+ ch = *format++;
+ break;
+ case '0':
+ flags |= DP_F_ZERO;
+ ch = *format++;
+ break;
+ default:
+ state = DP_S_MIN;
+ break;
+ }
+ break;
+ case DP_S_MIN:
+ if (isdigit(ch)) {
+ min = 10 * min + char_to_int(ch);
+ ch = *format++;
+ } else if (ch == '*') {
+ min = va_arg(args, int);
+ ch = *format++;
+ state = DP_S_DOT;
+ } else
+ state = DP_S_DOT;
+
+ break;
+ case DP_S_DOT:
+ if (ch == '.') {
+ state = DP_S_MAX;
+ ch = *format++;
+ } else
+ state = DP_S_MOD;
+
+ break;
+ case DP_S_MAX:
+ if (isdigit(ch)) {
+ if (max < 0)
+ max = 0;
+
+ max = 10 * max + char_to_int(ch);
+ ch = *format++;
+ } else if (ch == '*') {
+ max = va_arg(args, int);
+ ch = *format++;
+ state = DP_S_MOD;
+ } else
+ state = DP_S_MOD;
+
+ break;
+ case DP_S_MOD:
+ /* Currently, we don't support Long Long, bummer */
+ switch (ch) {
+ case 'h':
+ cflags = DP_C_SHORT;
+ ch = *format++;
+ break;
+ case 'l':
+ cflags = DP_C_LONG;
+ ch = *format++;
+ break;
+ case 'L':
+ cflags = DP_C_LDOUBLE;
+ ch = *format++;
+ break;
+ default:
+ break;
+ }
+ state = DP_S_CONV;
+ break;
+ case DP_S_CONV:
+ switch (ch) {
+ case 'd':
+ case 'i':
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, short int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, long int);
+ else
+ value = va_arg(args, int);
+
+ fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags);
+ break;
+ case 'o':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned short int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else
+ value = va_arg(args, unsigned int);
+
+ fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags);
+ break;
+ case 'u':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned short int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else
+ value = va_arg(args, unsigned int);
+
+ fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags);
+ break;
+ case 'X':
+ flags |= DP_F_UP;
+ case 'x':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned short int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else
+ value = va_arg(args, unsigned int);
+
+ fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags);
+ break;
+ case 'f':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+
+ /* um, floating point? */
+ fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags);
+ break;
+ case 'E':
+ flags |= DP_F_UP;
+ case 'e':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+ break;
+ case 'G':
+ flags |= DP_F_UP;
+ case 'g':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+
+ break;
+ case 'c':
+ dopr_outch(buffer, &currlen, maxlen, va_arg(args, int));
+ break;
+ case 's':
+ strvalue = va_arg(args, char *);
+ if (max < 0)
+ max = maxlen; /* ie, no max */
+
+ fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max);
+ break;
+ case 'p':
+ strvalue = va_arg(args, void *);
+ fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min,
+ max, flags);
+ break;
+ case 'n':
+ if (cflags == DP_C_SHORT) {
+ short int *num;
+ num = va_arg(args, short int *);
+ *num = currlen;
+ } else if (cflags == DP_C_LONG) {
+ long int *num;
+ num = va_arg(args, long int *);
+ *num = currlen;
+ } else {
+ int *num;
+ num = va_arg(args, int *);
+ *num = currlen;
+ }
+ break;
+ case '%':
+ dopr_outch(buffer, &currlen, maxlen, ch);
+ break;
+ case 'w':
+ /* not supported yet, treat as next char */
+ ch = *format++;
+ break;
+ default:
+ /* Unknown, skip */
+ break;
+ }
+ ch = *format++;
+ state = DP_S_DEFAULT;
+ flags = cflags = min = 0;
+ max = -1;
+ break;
+ case DP_S_DONE:
+ break;
+ default:
+ /* hmm? */
+ break; /* some picky compilers need this */
+ }
+ }
+ if (currlen < maxlen - 1)
+ buffer[currlen] = '\0';
+ else
+ buffer[maxlen - 1] = '\0';
+}
+
+static void fmtstr(char *buffer, size_t * currlen, size_t maxlen,
+ char *value, int flags, int min, int max)
+{
+ int padlen, strln; /* amount to pad */
+ int cnt = 0;
+
+ if (value == 0) {
+ value = "<NULL>";
+ }
+
+ for (strln = 0; value[strln]; ++strln); /* strlen */
+ padlen = min - strln;
+ if (padlen < 0)
+ padlen = 0;
+
+ if (flags & DP_F_MINUS)
+ padlen = -padlen; /* Left Justify */
+
+ while ((padlen > 0) && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --padlen;
+ ++cnt;
+ }
+
+ while (*value && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, *value++);
+ ++cnt;
+ }
+
+ while ((padlen < 0) && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ ++padlen;
+ ++cnt;
+ }
+}
+
+/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
+
+static void fmtint(char *buffer, size_t * currlen, size_t maxlen,
+ long value, int base, int min, int max, int flags)
+{
+ int signvalue = 0;
+ unsigned long uvalue;
+ char convert[20];
+ int place = 0;
+ int spadlen = 0; /* amount to space pad */
+ int zpadlen = 0; /* amount to zero pad */
+ int caps = 0;
+
+ if (max < 0)
+ max = 0;
+
+ uvalue = value;
+
+ if (!(flags & DP_F_UNSIGNED)) {
+ if (value < 0) {
+ signvalue = '-';
+ uvalue = -value;
+ } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
+ signvalue = '+';
+ else if (flags & DP_F_SPACE)
+ signvalue = ' ';
+ }
+
+ if (flags & DP_F_UP)
+ caps = 1; /* Should characters be upper case? */
+
+ do {
+ convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [uvalue % (unsigned) base];
+
+ uvalue = (uvalue / (unsigned) base);
+ }
+
+ while (uvalue && (place < 20));
+ if (place == 20)
+ place--;
+
+ convert[place] = 0;
+
+ zpadlen = max - place;
+ spadlen = min - MAX(max, place) - (signvalue ? 1 : 0);
+
+ if (zpadlen < 0)
+ zpadlen = 0;
+
+ if (spadlen < 0)
+ spadlen = 0;
+
+ if (flags & DP_F_ZERO) {
+ zpadlen = MAX(zpadlen, spadlen);
+ spadlen = 0;
+ }
+
+ if (flags & DP_F_MINUS)
+ spadlen = -spadlen; /* Left Justifty */
+
+#ifdef DEBUG_SNPRINTF
+ dprint(1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
+ zpadlen, spadlen, min, max, place));
+#endif // DEBUG_SNPRINTF
+
+ /* Spaces */
+ while (spadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --spadlen;
+ }
+
+ /* Sign */
+ if (signvalue)
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+
+ /* Zeros */
+ if (zpadlen > 0) {
+ while (zpadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --zpadlen;
+ }
+ }
+
+ /* Digits */
+ while (place > 0)
+ dopr_outch(buffer, currlen, maxlen, convert[--place]);
+
+ /* Left Justified spaces */
+ while (spadlen < 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ ++spadlen;
+ }
+}
+
+static LDOUBLE abs_val(LDOUBLE value) {
+ LDOUBLE result = value;
+
+ if (value < 0)
+ result = -value;
+
+ return result;
+}
+
+static LDOUBLE pow10(int exp) {
+ LDOUBLE result = 1;
+
+ while (exp) {
+ result *= 10;
+ exp--;
+ }
+
+ return result;
+}
+
+static long round(LDOUBLE value) {
+ long intpart;
+
+ intpart = value;
+ value = value - intpart;
+ if (value >= 0.5)
+ intpart++;
+
+ return intpart;
+}
+
+static void fmtfp(char *buffer, size_t * currlen, size_t maxlen,
+ LDOUBLE fvalue, int min, int max, int flags)
+{
+ int signvalue = 0;
+ LDOUBLE ufvalue;
+ char iconvert[20];
+ char fconvert[20];
+ int iplace = 0;
+ int fplace = 0;
+ int padlen = 0; /* amount to pad */
+ int zpadlen = 0;
+ int caps = 0;
+ long intpart;
+ long fracpart;
+
+ /*
+ * AIX manpage says the default is 0, but Solaris says the default
+ * is 6, and sprintf on AIX defaults to 6
+ */
+ if (max < 0)
+ max = 6;
+
+ ufvalue = abs_val(fvalue);
+
+ if (fvalue < 0)
+ signvalue = '-';
+ else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
+ signvalue = '+';
+ else if (flags & DP_F_SPACE)
+ signvalue = ' ';
+
+#if 0
+ if (flags & DP_F_UP)
+ caps = 1; /* Should characters be upper case? */
+#endif // 0
+
+ intpart = ufvalue;
+
+ /*
+ * Sorry, we only support 9 digits past the decimal because of our
+ * conversion method
+ */
+ if (max > 9)
+ max = 9;
+
+ /* We "cheat" by converting the fractional part to integer by
+ * multiplying by a factor of 10
+ */
+ fracpart = round((pow10(max)) * (ufvalue - intpart));
+
+ if (fracpart >= pow10(max)) {
+ intpart++;
+ fracpart -= pow10(max);
+ }
+
+ /* Convert integer part */
+ do {
+ iconvert[iplace++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")[intpart % 10];
+ intpart = (intpart / 10);
+ } while (intpart && (iplace < 20));
+
+ if (iplace == 20)
+ iplace--;
+
+ iconvert[iplace] = 0;
+
+ /* Convert fractional part */
+ do {
+ fconvert[fplace++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")[fracpart % 10];
+ fracpart = (fracpart / 10);
+ } while (fracpart && (fplace < 20));
+
+ if (fplace == 20)
+ fplace--;
+
+ fconvert[fplace] = 0;
+
+ /* -1 for decimal point, another -1 if we are printing a sign */
+ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
+ zpadlen = max - fplace;
+
+ if (zpadlen < 0)
+ zpadlen = 0;
+
+ if (padlen < 0)
+ padlen = 0;
+
+ if (flags & DP_F_MINUS)
+ padlen = -padlen; /* Left Justifty */
+
+ if ((flags & DP_F_ZERO) && (padlen > 0)) {
+ if (signvalue) {
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+ --padlen;
+ signvalue = 0;
+ }
+ while (padlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --padlen;
+ }
+ }
+
+ while (padlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --padlen;
+ }
+
+ if (signvalue)
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+
+ while (iplace > 0)
+ dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]);
+
+ /*
+ * Decimal point. This should probably use locale to find the correct
+ * char to print out.
+ */
+ if (max > 0) {
+ dopr_outch(buffer, currlen, maxlen, '.');
+
+ while (fplace > 0)
+ dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]);
+ }
+
+ while (zpadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --zpadlen;
+ }
+
+ while (padlen < 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ ++padlen;
+ }
+}
+
+static void dopr_outch(char *buffer, size_t * currlen, size_t maxlen, char c) {
+ if (*currlen < maxlen)
+ buffer[(*currlen)++] = c;
+}
+
+int xastir_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
+{
+ str[0] = 0;
+ dopr(str, count, fmt, args);
+ return (strlen(str));
+}
+#endif /* !HAVE_VSNPRINTF */
+
+#ifndef HAVE_SNPRINTF
+# ifdef HAVE_STDARGS
+int xastir_snprintf(char *str, size_t count, const char *fmt, ...)
+# else // HAVE_STDARGS
+int xastir_snprintf(va_alist) va_dcl
+# endif // HAVE_STDARGS
+{
+# ifndef HAVE_STDARGS
+ char *str;
+ size_t count;
+ char *fmt;
+# endif // HAVE_STDARGS
+ VA_LOCAL_DECL;
+
+ VA_START(fmt);
+ VA_SHIFT(str, char *);
+ VA_SHIFT(count, size_t);
+ VA_SHIFT(fmt, char *);
+ (void) xastir_vsnprintf(str, count, fmt, ap);
+ VA_END;
+ return (strlen(str));
+}
+#endif /* !HAVE_SNPRINTF */
+
+
diff --git a/src/snprintf.h b/src/snprintf.h
new file mode 100644
index 0000000..00b6457
--- /dev/null
+++ b/src/snprintf.h
@@ -0,0 +1,59 @@
+/*
+ * snprintf.h
+ * header file for snprintf.c
+ *
+ * $Id: snprintf.h,v 1.14 2012/11/01 18:57:19 we7u Exp $
+ */
+/*
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ */
+
+#ifndef _XASTIR_COMPAT_SNPRINTF_H_
+#define _XASTIR_COMPAT_SNPRINTF_H_
+
+#include <stdio.h>
+#include "config.h"
+
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif // HAVE_STDARG_H
+
+/* Use the system libraries version of vsnprintf() if available. Otherwise
+ * use our own.
+ */
+#ifndef HAVE_VSNPRINTF
+int xastir_vsnprintf(char *str, size_t count, const char *fmt, va_list ap);
+#else // HAVE_VSNPRINTF
+# define xastir_vsnprintf vsnprintf
+#endif // HAVE_VSNPRINTF
+
+/* Use the system libraries version of snprintf() if available. Otherwise
+ * use our own.
+ */
+#ifndef HAVE_SNPRINTF
+ #ifdef __STDC__
+ int xastir_snprintf(char *str, size_t count, const char *fmt, ...);
+ #else // __STDC__
+ int xastir_snprintf();
+ #endif // __STDC__
+#else // HAVE_SNPRINTF
+ #define xastir_snprintf snprintf
+#endif // HAVE_SNPRINTF
+
+#endif /* !XASTIR_COMPAT_SNPRINTF_H_ */
+
+
diff --git a/src/sound.c b/src/sound.c
new file mode 100644
index 0000000..693c0da
--- /dev/null
+++ b/src/sound.c
@@ -0,0 +1,124 @@
+/*
+ * $Id: sound.c,v 1.22 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+#include "xastir.h"
+#include "main.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+
+
+pid_t play_sound(char *sound_cmd, char *soundfile) {
+ pid_t sound_pid;
+ char command[600];
+
+ sound_pid=0;
+ if (strlen(sound_cmd)>3 && strlen(soundfile)>1) {
+ if (last_sound_pid==0) {
+
+ // Create a new process to run in
+ sound_pid = fork();
+ if (sound_pid!=-1) {
+ if(sound_pid==0) {
+// This is the child process
+
+
+ // Go back to default signal handler instead of
+ // calling restart() on SIGHUP
+ (void) signal(SIGHUP,SIG_DFL);
+
+
+ // Change the name of the new child process. So
+ // far this only works for "ps" listings, not
+ // for "top". This code only works on Linux.
+ // For BSD use setproctitle(3), NetBSD can use
+ // setprogname(2).
+#ifdef __linux__
+ init_set_proc_title(my_argc, my_argv, my_envp);
+ set_proc_title("%s", "festival process (xastir)");
+ //fprintf(stderr,"DEBUG: %s\n", Argv[0]);
+#endif // __linux__
+
+
+ xastir_snprintf(command,
+ sizeof(command),
+ "%s %s/%s",
+ sound_cmd,
+ SOUND_DIR,
+ soundfile);
+
+ (void)system(command); // Note we're not caring about whether it succeeded or not
+ exit(0); // Exits only this process, not Xastir itself
+ }
+ else {
+// This is the parent process
+ last_sound_pid=sound_pid;
+ }
+ } else
+ fprintf(stderr,"Error! trying to play sound\n");
+ } else {
+ sound_pid=last_sound_pid;
+ /*fprintf(stderr,"Sound already running\n");*/
+ }
+ }
+ return(sound_pid);
+}
+
+
+
+
+
+int sound_done(void) {
+ int done;
+ int *status;
+
+ status=NULL;
+ done=0;
+ if(last_sound_pid!=0) {
+ if(waitpid(last_sound_pid,status,WNOHANG)==last_sound_pid) {
+ done=1;
+ last_sound_pid=0;
+ }
+ }
+ return(done);
+}
+
+
diff --git a/src/symbols.h b/src/symbols.h
new file mode 100644
index 0000000..502b3de
--- /dev/null
+++ b/src/symbols.h
@@ -0,0 +1,33 @@
+/*
+ * $Id: symbols.h,v 1.10 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifndef XASTIR_SYMBOLS_H
+#define XASTIR_SYMBOLS_H
+
+/* define Symbol Active */
+
+
+
+#endif /* XASTIR_SYMBOLS_H */
+
diff --git a/src/testdbfawk.c b/src/testdbfawk.c
new file mode 100644
index 0000000..3b12307
--- /dev/null
+++ b/src/testdbfawk.c
@@ -0,0 +1,282 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: testdbfawk.c,v 1.6 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 2003-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#ifdef WITH_DBFAWK
+
+#ifdef HAVE_SHAPEFIL_H
+#include <shapefil.h>
+#else
+#ifdef HAVE_LIBSHP_SHAPEFIL_H
+#include <libshp/shapefil.h>
+#else
+#error HAVE_LIBSHP defined but no corresponding include defined
+#endif // HAVE_LIBSHP_SHAPEFIL_H
+#endif // HAVE_SHAPEFIL_H
+
+#include <ctype.h>
+#include <sys/types.h>
+#include "awk.h"
+#include "dbfawk.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+
+
+/*
+ * Sample test program
+ */
+
+void die(const char *s) {
+ fprintf(stderr,"%s\n",s);
+ exit(1);
+}
+
+
+
+
+
+/*
+ * print_symtbl: debugging
+ */
+void print_symtbl(awk_symtab *this) {
+ awk_symbol *s;
+ char buf[1024];
+ int len;
+ int i;
+
+// fprintf(stderr,"symtbl 0%0x dump:\n",(u_int)this);
+ fprintf(stderr,"symtbl 0x%0lx dump:\n",
+ (uintptr_t)this);
+ for (i = 0; i < AWK_SYMTAB_HASH_SIZE; i++) {
+ for (s = this->hash[i]; s; s = s->next_sym) {
+ *buf = '\0';
+ awk_get_sym(s,buf,sizeof(buf),&len);
+ fprintf(stderr,"%d %s = '%.*s'\n",i,s->name,len,buf);
+ }
+ }
+}
+
+
+
+
+
+awk_rule rules[] = {
+ { 0, BEGIN, NULL, NULL, 0, 0, "key=\"\"; lanes=1; color=8; name=\"\"; filled=0; pattern=1; display_level=8192; label_level=32",0 ,0 },
+ { 0, REGEXP, "^TLID=(.*)$", NULL, 0, 0, "key=\"$1\"",0,0 },
+ { 0, REGEXP, "^FENAME=United States Highway (.*)$", NULL, 0, 0, "name=\"US $1\"; next",0,0 },
+ { 0, REGEXP, "^FENAME=(.*)$", NULL, 0, 0, "name=\"$1\"; next",0,0 },
+ { 0, REGEXP, "^CFCC=A1", NULL, 0, 0, "lanes=4; color=4; next",0,0 },
+ { 0, REGEXP, "^CFCC=A3", NULL, 0, 0, "lanes=2; color=8",0,0 },
+ { 0, REGEXP, "^CFCC=A3[1-6]", NULL, 0, 0, "display_level=256; next",0,0 },
+};
+
+
+
+
+
+int nrules = sizeof(rules)/sizeof(rules[0]);
+
+void usage(void) {
+ fprintf(stderr,"Usage: testdbfawk [-f file.awk| -D dir] -d file.dbf\n");
+ fprintf(stderr," -D for dir containing *.dbfawk files.\n");
+ fprintf(stderr," or -f for file containing awk rules.\n");
+ fprintf(stderr," -d for dbf file to parse \n");
+}
+
+
+
+
+
+int debug = 0;
+
+
+
+
+
+int main(int argc, char *argv[]) {
+ awk_program *rs = NULL;
+ // int args;
+ awk_symtab *symtbl;
+ /* variables to bind to: */
+ int color;
+ int lanes;
+ int font_size;
+ char dbfinfo[1024]; /* list of DBF field names */
+ char dbffields[1024]; /* subset we want to read */
+ char name[128];
+ char key[128];
+ char symbol[4];
+ int filled = 5;
+ int pattern=0;
+ int display_level = 1234;
+ int label_level = 9;
+ int label_color = 8;
+ char *dir = NULL,*file = NULL,*dfile = NULL;
+ dbfawk_sig_info *si = NULL, *sigs = NULL;
+
+// Allocates new memory!
+ symtbl = awk_new_symtab();
+ if (argc >= 2 && (strcmp(argv[1],"--help") == 0 || strcmp(argv[1],"-?") == 0)) {
+ usage();
+ exit(1);
+ }
+ if (argc > 2 && strcmp(argv[1],"-D") == 0) {
+ dir = argv[2];
+ argv++; argv++;
+ argc -= 2;
+ sigs = dbfawk_load_sigs(dir,".dbfawk");
+ if (!sigs)
+ die("Couldn't find dbfawk sigs\n");
+ } else if (argc > 2 && strcmp(argv[1],"-f") == 0) {
+ file = argv[2];
+ argv++; argv++;
+ argc -= 2;
+ rs = awk_load_program_file(file); /* load up the program */
+ } else
+ rs = awk_load_program_array(rules,nrules); /* load up the program */
+ if (argc > 2 && strcmp(argv[1],"-d") == 0) {
+ dfile = argv[2];
+ argv++; argv++;
+ argc -= 2;
+ }
+
+ /* declare/bind these symbols */
+// Allocates new memory!
+ awk_declare_sym(symtbl,"dbfinfo",STRING,dbfinfo,sizeof(dbfinfo));
+ awk_declare_sym(symtbl,"dbffields",STRING,dbffields,sizeof(dbffields));
+ awk_declare_sym(symtbl,"color",INT,&color,sizeof(color));
+ awk_declare_sym(symtbl,"lanes",INT,&lanes,sizeof(lanes));
+ awk_declare_sym(symtbl,"name",STRING,name,sizeof(name));
+ awk_declare_sym(symtbl,"key",STRING,key,sizeof(key));
+ awk_declare_sym(symtbl,"symbol",STRING,symbol,sizeof(symbol));
+ awk_declare_sym(symtbl,"filled",INT,&filled,sizeof(filled));
+ awk_declare_sym(symtbl,"pattern",INT,&pattern,sizeof(pattern));
+ awk_declare_sym(symtbl,"display_level",INT,&display_level,sizeof(display_level));
+ awk_declare_sym(symtbl,"label_level",INT,&label_level,sizeof(label_level));
+ awk_declare_sym(symtbl,"label_color",INT,&label_color,sizeof(label_color));
+ awk_declare_sym(symtbl,"font_size",INT,&font_size,sizeof(font_size));
+
+ if (dfile) { /* parse dbf file */
+ DBFHandle dbf = DBFOpen(dfile,"rb");
+ int i;
+ char sig[sizeof(dbfinfo)]; /* write the signature here */
+ int nf;
+ dbfawk_field_info *fi;
+
+ if (!dbf)
+ die("DBFopen");
+
+ nf = dbfawk_sig(dbf,sig,sizeof(sig));
+ fprintf(stderr,"%d Columns, %d Records in file\n",nf,
+ DBFGetRecordCount(dbf));
+ fprintf(stderr,"sig: %s\n",sig);
+
+ /* If -D then search for matching sig; else use the supplied awk_prog */
+ if (sigs) {
+ si = dbfawk_find_sig(sigs,sig,dfile);
+ if (!si)
+ die("No matching dbfawk signature found");
+ rs = si->prog;
+ }
+ if (awk_compile_program(symtbl,rs) < 0) {
+ die("couldn't compile rules");
+ }
+
+ awk_exec_begin(rs); /* execute a BEGIN rule if any */
+ // print_symtbl(symtbl);
+
+ if (strcmp(sig,dbfinfo) == 0) {
+ fprintf(stderr,"DBF Signatures match!\n");
+ } else {
+ fprintf(stderr,"DBF Signatures DON'T match\n");
+ }
+ fi = dbfawk_field_list(dbf, dbffields);
+ /* now actually read the whole file */
+ for (i = 0; i < DBFGetRecordCount(dbf); i++ ) {
+ dbfawk_parse_record(rs,dbf,fi,i);
+ fprintf(stderr,"name=%s, ",name);
+ fprintf(stderr,"key=%s, ",key);
+ fprintf(stderr,"symbol=%s, ",symbol);
+ fprintf(stderr,"color=%d, ", color);
+ fprintf(stderr,"lanes=%d, ", lanes);
+ fprintf(stderr,"filled=%d, ",filled);
+ fprintf(stderr,"pattern=%d, ",pattern);
+ fprintf(stderr,"display_level=%d, ",display_level);
+ fprintf(stderr,"font_size=%d, ", font_size);
+ fprintf(stderr,"label_level=%d\n",label_level);
+ fprintf(stderr,"label_color=%d\n",label_color);
+ // print_symtbl(symtbl);
+ }
+ DBFClose(dbf);
+ } else { /* use cmdline args */
+ usage();
+ exit(1);
+ /*
+ * remove this capability because it leads to
+ * segfaults if user gives invalid command line arguments.
+ * better to just print usage string
+ awk_exec_begin_record(rs);
+ for (args = 1; args < argc; args++) {
+ fprintf(stderr,"==> %s\n",argv[args]);
+ awk_exec_program(rs,argv[args],strlen(argv[args]));
+ // print_symtbl(symtbl);
+ }
+ awk_exec_end_record(rs);
+ */
+ }
+ awk_exec_end(rs); /* execute an END rule if any */
+ // print_symtbl(symtbl);
+ if (si)
+ dbfawk_free_sigs(si);
+ else if (rs)
+ awk_free_program(rs);
+ awk_free_symtab(symtbl);
+ exit(0);
+}
+#else /* !WITH_DBFAWK */
+
+
+
+
+
+int main(int argc, char *argv[]) {
+ fprintf(stderr,"DBFAWK support not compiled.\n");
+ exit(1);
+}
+#endif /* !WITH_DBFAWK */
+
+
diff --git a/src/tile_mgmnt.c b/src/tile_mgmnt.c
new file mode 100644
index 0000000..b628a2b
--- /dev/null
+++ b/src/tile_mgmnt.c
@@ -0,0 +1,355 @@
+/*
+ * $Id: tile_mgmnt.c,v 1.5 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 2003-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <errno.h>
+
+#include "xastir.h"
+#include "fetch_remote.h"
+#include "util.h"
+#include "snprintf.h"
+#include "maps.h"
+
+#ifdef HAVE_LIBCURL
+#include <curl/curl.h>
+#endif // HAVE_LIBCURL
+
+#include "tile_mgmnt.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+// OSM Minimum cache time
+#define SECONDS_7_DAYS (7 * 24 * 3600)
+
+/*
+ * latLon2tileNum - calculate tile number
+ *
+ * The tile number is returned in in the structure pointed to by the
+ * tilenum argument.
+ */
+void latLon2tileNum (double lon_deg,
+ double lat_deg,
+ int zoom,
+ tileNum_t *tilenum) {
+ unsigned long ntiles;
+ double lat_rad;
+ ntiles = 1 << zoom;
+
+ if (lat_deg > MAX_LAT_OSM) {
+ lat_deg = MAX_LAT_OSM;
+ }
+ else if (lat_deg < (-1.0 * MAX_LAT_OSM)) {
+ lat_deg = -1.0 * MAX_LAT_OSM;
+ }
+
+ if (lon_deg > MAX_LON_OSM) {
+ lon_deg = MAX_LON_OSM;
+ }
+ else if (lon_deg < (-1.0 * MAX_LON_OSM)) {
+ lon_deg = -1.0 * MAX_LON_OSM;
+ }
+
+ lat_rad = (lat_deg * M_PI) / 180.0;
+
+ tilenum->x = ((lon_deg + 180.0) / 360.0) * ntiles;
+ tilenum->y = ((1 - (log(tan(lat_rad)
+ + (1.0 / cos(lat_rad))) / M_PI)) / 2.0) * ntiles;
+
+ if (tilenum->y >= ntiles) {
+ tilenum->y = (ntiles - 1);
+ }
+
+ if (tilenum->x >= ntiles) {
+ tilenum->x = (ntiles - 1);
+ }
+
+ return;
+
+} // latLon2tileNum()
+
+
+/*
+ * tile2coord - calculate lat/lon of NW corner of tile
+ *
+ * Use tilex+1 and tiley+1 to get the coordinates of the SE corner.
+ *
+ * Based on example code at
+ * http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
+ *
+ */
+void tile2coord (unsigned long tilex,
+ unsigned long tiley,
+ int zoom,
+ coord_t *NWcorner) {
+ unsigned long ntiles;
+ double lat_rad;
+
+ ntiles = 1 << zoom;
+ lat_rad = M_PI - ((2.0 * M_PI) * ((double)(tiley) / (double)ntiles));
+ NWcorner->lat = (180.0 / M_PI) * atan(0.5 * (exp((double)lat_rad) - exp(-1.0 * (double)lat_rad)));
+
+ NWcorner->lon = (((double)(tilex) / (double)ntiles) * 360.0) - 180.0;
+
+ return;
+
+} // tile2coord()
+
+/*
+ * calcTileArea - calculate the x and y range of tile numbers
+ *
+ * Returns the calculated values in the structure pointed to by the
+ * tiles argument.
+ */
+void calcTileArea (double lon_upper_left,
+ double lat_upper_left,
+ double lon_lower_right,
+ double lat_lower_right,
+ int zoom,
+ tileArea_t *tiles) {
+ tileNum_t tilenum;
+ latLon2tileNum(lon_upper_left, lat_upper_left, zoom, &tilenum);
+ tiles->startx = tilenum.x;
+ tiles->starty = tilenum.y;
+ latLon2tileNum(lon_lower_right, lat_lower_right, zoom, &tilenum);
+ tiles->endx = tilenum.x;
+ tiles->endy = tilenum.y;
+ return;
+
+} // calcTileArea()
+
+
+/*
+ * tilesMissing - return the count of tiles that are missing from the cache
+ */
+int tilesMissing (unsigned long startx,
+ unsigned long endx,
+ unsigned long starty,
+ unsigned long endy,
+ int zoom,
+ char *cacheDir,
+ char *tileExt) {
+ struct stat sb;
+ char local_filename[1100];
+ unsigned long x, y;
+ int numMissing = 0;
+
+ for (x = startx; x <= endx; x++) {
+ for (y = starty; y <= endy; y++) {
+
+ xastir_snprintf(local_filename, sizeof(local_filename),
+ "%s/%u/%lu/%lu.%s", cacheDir, zoom, x, y, tileExt);
+
+ if (stat(local_filename, &sb) == -1) {
+ numMissing++;
+ }
+ }
+ }
+ return(numMissing);
+
+} // end of tilesMissing()
+
+
+/*
+ * getOneTile - get one tile from the web
+ *
+ * The tile is fetched if it does not exist and 1 is returned.
+ *
+ * If the tile exists in the cache and it is older than 7 days, then it
+ * will be refreshed from the server.
+ *
+ * Returns 1 if a tile did not exist and download was attempted.
+ * Returns 0 if a tile exists in the cache (tile might be updated).
+ *
+ * Returns libcurl errors as a negative integer.
+ *
+ * WARNING: Download failures are not reported for wget.
+ *
+ */
+#ifdef HAVE_LIBCURL
+int getOneTile (CURL *session,
+ char *baseURL,
+ unsigned long x,
+ unsigned long y,
+ int zoom,
+ char *baseDir,
+ char *tileExt) {
+ CURLcode res;
+ time_t cacheTimeout;
+#else
+int getOneTile (char *baseURL,
+ unsigned long x,
+ unsigned long y,
+ int zoom,
+ char *baseDir,
+ char *tileExt) {
+#endif // HAVE_LIBCURL
+
+ struct stat sb;
+ char url[1100];
+ char local_filename[1100];
+ int result = 0;
+
+ xastir_snprintf(url, sizeof(url), "%s/%u/%lu/%lu.%s", baseURL, zoom,
+ x, y, tileExt);
+ xastir_snprintf(local_filename, sizeof(local_filename),
+ "%s/%u/%lu/%lu.%s", baseDir, zoom, x, y, tileExt);
+
+ if (stat(local_filename, &sb) == -1) {
+ if (debug_level & 512) {
+ fprintf(stderr, "Fetching %s\n", url);
+ }
+ result = 1; // only count files that do not exist
+
+#ifdef HAVE_LIBCURL
+ res = fetch_remote_tile(session, url, local_filename);
+
+ } else {
+
+ // Check for updated tiles after 7 days, per
+ // OSM Tile Usage Policy,
+ // http://wiki.openstreetmap.org/wiki/Tile_usage_policy,
+ // 2010/07/29
+ cacheTimeout = sb.st_mtime + SECONDS_7_DAYS;
+ if (cacheTimeout <= time(NULL)) {
+ // tile exists in the cache, but is older than 7 days, so
+ // check the server for a newer version.
+ if (debug_level & 512) {
+ fprintf(stderr, "Refreshing %s.\n", url);
+ }
+ res = fetch_remote_tile(session, url, local_filename);
+
+ } else {
+
+ if (debug_level & 512) {
+ fprintf(stderr, "Skipping- %s\n", url);
+ fprintf(stderr, " because cache time has not expired.\n");
+ fprintf(stderr, " cache expires %s",
+ ctime(&cacheTimeout));
+ }
+
+ res = CURLE_OK;
+ }
+ }
+
+ if (CURLE_OK != res) {
+ // return the curl error as a negative value to distinqusih it
+ // successful values
+ result = -1 * (int)res;
+ }
+
+#else // don't HAVE_LIBCURL
+ (void)fetch_remote_file(url, local_filename);
+ }
+#endif // HAVE_LIBCURL
+
+ return(result);
+
+} // getOneTile()
+
+
+/*
+ * mkpath() - attempt to make each directory in a path
+ */
+static void mkpath(const char *dir) {
+ char tmp[MAX_FILENAME];
+ char *p = NULL;
+ size_t len;
+
+ xastir_snprintf(tmp, sizeof(tmp),"%s", dir);
+ len = strlen(tmp);
+ if(tmp[len - 1] == '/') {
+ tmp[len - 1] = 0;
+ }
+
+ for (p = tmp + 1; *p; p++) {
+ if(*p == '/') {
+ *p = 0;
+ mkdir(tmp, S_IRWXU);
+ *p = '/';
+ }
+ }
+ mkdir(tmp, S_IRWXU);
+
+ return;
+} // end of mkpath()
+
+
+/*
+ * mkOSMmapDirs - try to create all the directories needed for the tiles
+ *
+ * This is simply a best-effort attempt because there are valid reasons
+ * for mkdir() to fail. For example, the tiles could be buffered in a RO
+ * structure.
+ */
+void mkOSMmapDirs (char *baseDir,
+ unsigned long startx,
+ unsigned long endx,
+ int zoom) {
+ char fullPath[MAX_FILENAME];
+ char errmsg[1024];
+ struct stat sb;
+ unsigned long dnum;
+
+
+ xastir_snprintf(fullPath, sizeof(fullPath), "%s/%u/", baseDir, zoom);
+ mkpath(fullPath);
+
+ for (dnum = startx; dnum <= endx; dnum++) {
+ xastir_snprintf(fullPath, sizeof(fullPath), "%s/%u/%lu/",
+ baseDir, zoom, dnum);
+ mkdir(fullPath, S_IRWXU);
+
+ if (debug_level & 512) {
+ if (stat(fullPath, &sb) == -1) {
+#ifdef HAVE_POSIX_STRERROR_R
+ strerror_r(errno, errmsg, sizeof(errmsg));
+ fprintf(stderr, "%s: %s\n", errmsg, fullPath);
+#else
+ fprintf(stderr, "%s: %s\n",
+ strerror_r(errno, errmsg, sizeof(errmsg)), fullPath);
+#endif
+ }
+ else if ((sb.st_mode & S_IWUSR) != S_IWUSR) {
+ fprintf(stderr, "warning: directory %s is not writable\n", fullPath);
+ }
+ else if (!S_ISDIR(sb.st_mode)) {
+ fprintf(stderr, "warning: %s is not a directory\n", fullPath);
+ }
+ }
+ }
+
+ return;
+} // mkOSMmapDirs()
+
+
diff --git a/src/tile_mgmnt.h b/src/tile_mgmnt.h
new file mode 100644
index 0000000..ea41985
--- /dev/null
+++ b/src/tile_mgmnt.h
@@ -0,0 +1,63 @@
+/*
+ * $Id: tile_mgmnt.h,v 1.4 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 2003-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+#ifndef __TILE_MGMNT_H
+#define __TILE_MGMNT_H
+
+#ifdef HAVE_LIBCURL
+#include <curl/curl.h>
+#endif // HAVE_LIBCURL
+
+typedef struct tileNum_s {
+ unsigned long x;
+ unsigned long y;
+} tileNum_t;
+
+typedef struct coord_s {
+ double lat;
+ double lon;
+} coord_t;
+
+typedef struct tileArea_s {
+ unsigned long startx;
+ unsigned long endx;
+ unsigned long starty;
+ unsigned long endy;
+} tileArea_t;
+
+#define MAX_LAT_OSM 85.0511
+#define MAX_LON_OSM 180.0
+
+void latLon2tileNum(double lon_deg, double lat_deg, int zoom, tileNum_t *tilenum);
+void tile2coord(unsigned long tilex, unsigned long tiley, int zoom, coord_t *NWcorner);
+void calcTileArea(double lon_upper_left,double lat_upper_left,double lon_lower_right,double lat_lower_right,int zoom,tileArea_t *tiles);
+
+#ifdef HAVE_LIBCURL
+int getOneTile(CURL *session, char *baseURL, unsigned long x, unsigned long y, int zoom, char *baseDir, char *tileExt);
+#else
+int getOneTile(char *baseURL, unsigned long x, unsigned long y, int zoom, char *baseDir, char *tileExt);
+#endif // HAVE_LIBCURL
+
+void mkOSMmapDirs(char *baseDir, unsigned long startx, unsigned long endx, int zoom);
+int tilesMissing (unsigned long startx, unsigned long endx, unsigned long starty, unsigned long endy, int zoom, char *baseDir, char *tileExt);
+
+#endif // __TILE_MGMNT_H
diff --git a/src/track_gui.c b/src/track_gui.c
new file mode 100644
index 0000000..abdc2cc
--- /dev/null
+++ b/src/track_gui.c
@@ -0,0 +1,1007 @@
+/*
+ * $Id: track_gui.c,v 1.77 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <Xm/XmAll.h>
+
+#include "xastir.h"
+#include "main.h"
+#include "lang.h"
+#include "objects.h"
+#include "popup.h"
+#include "fetch_remote.h"
+#include "util.h"
+#include "xa_config.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+extern XmFontList fontlist1; // Menu/System fontlist
+
+Widget track_station_dialog = (Widget)NULL;
+Widget track_station_data = (Widget)NULL;
+Widget download_findu_dialog = (Widget)NULL;
+
+static xastir_mutex track_station_dialog_lock;
+static xastir_mutex download_findu_dialog_lock;
+
+// track values
+Widget track_case_data, track_match_data;
+
+// Download findu values
+Widget download_trail_station_data;
+Widget posit_start_value;
+Widget posit_length_value;
+
+int fetching_findu_trail_now = 0;
+
+int track_station_on = 0; /* used for tracking stations */
+int track_me;
+int track_case; /* used for tracking stations */
+int track_match; /* used for tracking stations */
+char tracking_station_call[30]; /* Tracking station callsign */
+char download_trail_station_call[30]; /* Trail station callsign */
+//N0VH
+#define MAX_FINDU_DURATION 120
+#define MAX_FINDU_START_TIME 336
+// Make these two match, as that will be the most desired case: Snag
+// the track for as far back as possible up to the present in one
+// shot...
+int posit_start = MAX_FINDU_DURATION;
+int posit_length = MAX_FINDU_DURATION;
+
+
+
+
+
+void track_gui_init(void)
+{
+ init_critical_section( &track_station_dialog_lock );
+ init_critical_section( &download_findu_dialog_lock );
+
+ if (temp_tracking_station_call[0] != '\0') {
+ xastir_snprintf(tracking_station_call,
+ sizeof(tracking_station_call),
+ "%s",
+ temp_tracking_station_call);
+ track_station_on = 1;
+ }
+ else {
+ tracking_station_call[0] = '\0';
+ }
+}
+
+
+
+
+
+/**** Track STATION ******/
+
+
+void track_station_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+
+begin_critical_section(&track_station_dialog_lock, "track_gui.c:track_station_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ track_station_dialog = (Widget)NULL;
+
+end_critical_section(&track_station_dialog_lock, "track_gui.c:track_station_destroy_shell" );
+
+}
+
+
+
+
+
+void Track_station_clear(Widget w, XtPointer clientData, XtPointer callData) {
+
+ /* clear station */
+ track_station_on=0;
+ //track_station_data=NULL;
+ //tracking_station_call[0] = '\0';
+
+ // Clear the TrackMe button as well
+ XmToggleButtonSetState(trackme_button,FALSE,TRUE);
+
+ track_station_destroy_shell(w, clientData, callData);
+ display_zoom_status();
+}
+
+
+
+
+
+void Track_station_now(Widget w, XtPointer clientData, XtPointer callData) {
+ char temp[MAX_CALLSIGN+1];
+ char temp2[200];
+ int found = 0;
+ char *temp_ptr;
+
+
+ temp_ptr = XmTextFieldGetString(track_station_data);
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(temp);
+ (void)remove_trailing_dash_zero(temp);
+
+ xastir_snprintf(tracking_station_call,
+ sizeof(tracking_station_call),
+ "%s",
+ temp);
+ track_case = (int)XmToggleButtonGetState(track_case_data);
+ track_match = (int)XmToggleButtonGetState(track_match_data);
+ found = locate_station(da, temp, track_case, track_match, 0);
+
+ if ( valid_object(tracking_station_call) // Name of object is legal
+ || valid_call(tracking_station_call)
+ || valid_item(tracking_station_call ) ) {
+ track_station_on = 1; // Track it whether we've seen it yet or not
+ if (!found) {
+ xastir_snprintf(temp2, sizeof(temp2), langcode("POPEM00026"), temp);
+ popup_message_always(langcode("POPEM00025"),temp2);
+ }
+ // Check for exact match, includes SSID
+ if ( track_me & !is_my_call( tracking_station_call, 1) ) {
+ XmToggleButtonSetState( trackme_button, FALSE, FALSE );
+ track_me = 0;
+ }
+ } else {
+ tracking_station_call[0] = '\0'; // Empty it out again
+ track_station_on = 0;
+ xastir_snprintf(temp2, sizeof(temp2), langcode("POPEM00002"), temp);
+ popup_message_always(langcode("POPEM00003"),temp2);
+ }
+
+ track_station_destroy_shell(w, clientData, callData);
+ display_zoom_status();
+}
+
+
+
+
+
+void Track_station( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, my_form, button_ok, button_close, button_clear, call, sep;
+ Atom delw;
+
+ if (!track_station_dialog) {
+
+begin_critical_section(&track_station_dialog_lock, "track_gui.c:Track_station" );
+
+ track_station_dialog = XtVaCreatePopupShell(langcode("WPUPTSP001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Track_station pane",
+ xmPanedWindowWidgetClass,
+ track_station_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Track_station my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 3,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ call = XtVaCreateManagedWidget(langcode("WPUPTSP002"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ track_station_data = XtVaCreateManagedWidget("Track_station track locate data",
+ xmTextFieldWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNwidth, ((15*7)+2),
+ XmNmaxLength, 15,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, call,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ track_case_data = XtVaCreateManagedWidget(langcode("WPUPTSP003"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, call,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset ,10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ track_match_data = XtVaCreateManagedWidget(langcode("WPUPTSP004"),
+ xmToggleButtonWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, call,
+ XmNtopOffset, 20,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget,track_case_data,
+ XmNrightOffset ,20,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ sep = XtVaCreateManagedWidget("Track_station sep",
+ xmSeparatorGadgetClass,
+ my_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget,track_case_data,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("WPUPTSP005"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_clear = XtVaCreateManagedWidget(langcode("WPUPTSP006"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_close = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNrightOffset, 5,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Track_station_now, track_station_dialog);
+ XtAddCallback(button_close, XmNactivateCallback, track_station_destroy_shell, track_station_dialog);
+ XtAddCallback(button_clear, XmNactivateCallback, Track_station_clear, track_station_dialog);
+
+ XmToggleButtonSetState(track_case_data,FALSE,FALSE);
+ XmToggleButtonSetState(track_match_data,TRUE,FALSE);
+
+ pos_dialog(track_station_dialog);
+
+ delw = XmInternAtom(XtDisplay(track_station_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(track_station_dialog, delw, track_station_destroy_shell, (XtPointer)track_station_dialog);
+
+// if (track_station_on==1)
+ XmTextFieldSetString(track_station_data,tracking_station_call);
+
+ XtManageChild(my_form);
+ XtManageChild(pane);
+
+end_critical_section(&track_station_dialog_lock, "track_gui.c:Track_station" );
+
+ XtPopup(track_station_dialog,XtGrabNone);
+ fix_dialog_size(track_station_dialog);
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(track_station_dialog);
+ XmProcessTraversal(button_close, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(track_station_dialog), XtWindow(track_station_dialog));
+}
+
+
+
+
+
+/***** DOWNLOAD FINDU TRAILS *****/
+
+
+
+// Struct used for passing two parameters to findu_transfer_thread
+typedef struct {
+ char *download_client_ptrs[2];
+} track_ptrs_struct;
+track_ptrs_struct track_ptrs;
+
+
+
+// This is the separate execution thread that fetches the track from
+// findu. The thread is started up by the Download_trail_now()
+// function below.
+//
+static void* findu_transfer_thread(void *arg) {
+ char *fileimg;
+ char *log_filename;
+// char log_filename_tmp[210];
+ char **ptrs;
+ char sys_cmd[128];
+
+
+ // Get fileimg and log_filename from parameters
+ ptrs = arg;
+ log_filename = ptrs[0];
+ fileimg = ptrs[1];
+
+ // Set global "busy" variable
+ fetching_findu_trail_now = 1;
+
+ if (fetch_remote_file(fileimg, log_filename)) {
+
+ // Had trouble getting the file. Abort.
+
+// We may not be able to do any GUI stuff from multiple
+// threads/processes at the same time. If that is found to be the
+// case we can write to STDERR instead.
+
+ // Dump a message to STDERR
+// fprintf(stderr,
+// "%s %s\n",
+// langcode("POPEM00035"),
+// langcode("POPEM00044"));
+
+ // Fetch Findu Trail: Failed
+ popup_message_always(langcode("POPEM00035"),
+ langcode("POPEM00044"));
+
+ // Reset global "busy" variable
+ fetching_findu_trail_now = 0;
+
+ // End the thread
+ return(NULL);
+ }
+
+// We need to move this message up to the main thread if possible so
+// that we don't have multiple threads writing to the GUI. This
+// sort of operation can cause segfaults. In practice I haven't
+// seen any segfaults due to this particular popup though.
+
+ // Fetch Findu Trail: Complete
+ popup_message_always(langcode("POPEM00036"),
+ langcode("POPEM00045"));
+
+ // Set permissions on the file so that any user can overwrite it.
+ chmod(log_filename, 0666);
+
+#if defined(HAVE_SED)
+ // Add three spaces before each "<br>" and axe the "<br>". This
+ // is so that Base-91 compressed packets with no comment and no
+ // speed/course/altitude will get decoded ok. Otherwise the
+ // spaces that are critical to the Base-91 packets won't be
+ // there due to findu.com filtering them out.
+ //
+// "sed -i -e \"s/<br>/ <br>/\" %s",
+ sprintf(sys_cmd,
+ "%s -i -e \"s/<br>/ /\" %s",
+ SED_PATH,
+ log_filename);
+ system(sys_cmd);
+//fprintf(stderr,"%s\n", sys_cmd);
+
+// Greater-than symbol '>'
+ sprintf(sys_cmd,
+ "%s -i -e \"s/>/>/\" %s",
+ SED_PATH,
+ log_filename);
+ system(sys_cmd);
+
+// Less-than symbol '<'
+ sprintf(sys_cmd,
+ "%s -i -e \"s/</</\" %s",
+ SED_PATH,
+ log_filename);
+ system(sys_cmd);
+
+// Ampersand '&' (A difficult character to escape from the shell!)
+ sprintf(sys_cmd,
+ "%s -i -e \"s/&/\\&/\" %s",
+ SED_PATH,
+ log_filename);
+ system(sys_cmd);
+
+// Double-quote symbol '"'
+ sprintf(sys_cmd,
+ "%s -i -e \"s/"/""/\" %s",
+ SED_PATH,
+ log_filename);
+ system(sys_cmd);
+
+// Remove whitespace at the start of a line
+// sed 's/^[ \t]*//'
+ sprintf(sys_cmd,
+ "%s -i -e \"s/^[ \t]*//\" %s",
+ SED_PATH,
+ log_filename);
+ system(sys_cmd);
+
+// Remove any lines that start with '<'
+ sprintf(sys_cmd,
+ "%s -i -e \"s/^<.*$//\" %s",
+ SED_PATH,
+ log_filename);
+ system(sys_cmd);
+
+// Remove any lines that start with '"http'
+ sprintf(sys_cmd,
+ "%s -i -e \"/^\\\"http.*$/d\" %s",
+ SED_PATH,
+ log_filename);
+ system(sys_cmd);
+
+// Remove any blank lines from the file
+// sed '/^$/d'
+ sprintf(sys_cmd,
+ "%s -i -e \"/^$/d\" %s",
+ SED_PATH,
+ log_filename);
+ system(sys_cmd);
+#endif // HAVE_SED
+
+/*
+#ifdef HAVE_HTML2TEXT
+ // Create temp filename
+ snprintf(log_filename_tmp, sizeof(log_filename_tmp), "%s%s",
+ log_filename,
+ ".tmp");
+ // Create html2text command
+ sprintf(sys_cmd,
+ "%s -width 300 -o %s %s",
+ HTML2TEXT_PATH,
+ log_filename_tmp,
+ log_filename);
+ // Convert the newly-downloaded file from html to text format
+ system(sys_cmd);
+ // Rename the file so that we can keep the static char* name
+ // pointing to it, needed for the read_file_ptr code in the main
+ // thread.
+#if defined(HAVE_MV)
+ sprintf(sys_cmd,
+ "%s %s %s",
+ MV_PATH,
+ log_filename_tmp,
+ log_filename);
+ system(sys_cmd);
+#endif // HAVE_MV
+#endif // HAVE_HTML2TEXT
+*/
+
+ // Here we do the findu stuff, if the findu_flag is set. Else we do an imagemap.
+ // We have the log data we're interested in within the log_filename file.
+ // Cause that file to be read by the "File->Open Log File" routine. HTML
+ // tags will be ignored just fine.
+ read_file_ptr = fopen(log_filename, "r");
+
+ if (read_file_ptr != NULL) {
+ read_file = 1;
+ }
+ else {
+ fprintf(stderr,"Couldn't open file: %s\n", log_filename);
+ }
+
+ // Reset global "busy" variable
+ fetching_findu_trail_now = 0;
+
+ // End the thread
+ return(NULL);
+}
+
+
+
+
+
+void Download_trail_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+
+begin_critical_section(&download_findu_dialog_lock, "track_gui.c:Download_trail_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ download_findu_dialog = (Widget)NULL;
+
+end_critical_section(&download_findu_dialog_lock, "track_gui.c:Download_trail_destroy_shell" );
+}
+
+
+
+
+
+void Download_trail_now(Widget w, XtPointer clientData, XtPointer callData) {
+ char temp[MAX_CALLSIGN+1];
+ static char fileimg[400];
+ static char log_filename[200];
+ char *temp_ptr;
+ pthread_t download_trail_thread;
+ static XtPointer download_client_data = NULL;
+
+ char tmp_base_dir[MAX_VALUE];
+
+ get_user_base_dir("tmp",tmp_base_dir, sizeof(tmp_base_dir));
+
+ // If we're already fetching a trail, we shouldn't be calling
+ // this callback function. Get out.
+ if (fetching_findu_trail_now)
+ return;
+
+ // Pass two parameters to findu_transfer_thread via a struct
+ track_ptrs.download_client_ptrs[0] = log_filename;
+ track_ptrs.download_client_ptrs[1] = fileimg;
+ download_client_data = &track_ptrs;
+
+ // Check whether it's ok to do a download currently.
+ if (read_file) {
+ // No, we're already in the middle of reading in some file.
+ // Skip trying to download yet another file.
+
+ fprintf(stderr,"Processing another file. Wait a bit, then try again\n");
+
+ popup_message_always(langcode("POPEM00035"),
+ langcode("POPEM00041"));
+
+ return;
+ }
+
+// busy_cursor(appshell);
+
+ xastir_snprintf(log_filename,
+ sizeof(log_filename),
+ "%s/map.log",
+ tmp_base_dir);
+
+ // Erase any previously existing local file by the same name.
+ // This avoids the problem of having an old tracklog here and
+ // the code trying to display it when the download fails.
+ unlink( log_filename );
+
+
+ XmScaleGetValue(posit_start_value , &posit_start);
+ XmScaleGetValue(posit_length_value , &posit_length);
+
+ temp_ptr = XmTextFieldGetString(download_trail_station_data);
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ temp_ptr);
+ XtFree(temp_ptr);
+
+ (void)remove_trailing_spaces(temp);
+ (void)remove_trailing_dash_zero(temp);
+
+ xastir_snprintf(download_trail_station_call,
+ sizeof(download_trail_station_call),
+ "%s",
+ temp);
+ //Download_trail_destroy_shell(w, clientData, callData);
+
+
+// New URL's for findu. The second one looks very promising.
+//http://www.findu.com/cgi-bin/raw.cgi?call=k4hg-8&time=1
+//http://www.findu.com/cgi-bin/rawposit.cgi?call=k4hg-8&time=1
+//
+// The last adds this to the beginning of the line:
+//
+// "20030619235323,"
+//
+// which is a date/timestamp. We'll need to do some extra stuff
+// here in order to actually use that date/timestamp though.
+// Setting the read_file_ptr to the downloaded file won't do it.
+
+
+
+// "http://www.findu.com/cgi-bin/rawposit.cgi?call=%s&start=%d&length=%d&time=1", // New, with timestamp
+ xastir_snprintf(fileimg, sizeof(fileimg),
+ //
+ // Posits only:
+ // "http://www.findu.com/cgi-bin/rawposit.cgi?call=%s&start=%d&length=%d",
+ //
+ // Posits plus timestamps (we can't handle timestamps yet):
+ // "http://www.findu.com/cgi-bin/rawposit.cgi?call=%s&start=%d&length=%d&time=1", // New, with timestamp
+ //
+ // Download all packets, not just posits:
+ "http://www.findu.com/cgi-bin/raw.cgi?call=%s&start=%d&length=%d",
+ //
+ download_trail_station_call,posit_start,posit_length);
+
+ if (debug_level & 1024) {
+ fprintf(stderr, "%s\n", fileimg);
+ }
+
+
+//----- Start New Thread -----
+
+ if (pthread_create(&download_trail_thread,
+ NULL,
+ findu_transfer_thread,
+ download_client_data)) {
+
+ fprintf(stderr,"Error creating findu transfer thread\n");
+ }
+ else {
+ // We're off and running with the new thread!
+ }
+
+ display_zoom_status();
+
+ Download_trail_destroy_shell(w, clientData, callData);
+}
+
+
+
+
+
+void Reset_posit_length_max(Widget w, XtPointer clientData, XtPointer callData) {
+
+ XmScaleGetValue(posit_length_value, &posit_length);
+ XmScaleGetValue(posit_start_value, &posit_start);
+
+ // Check whether start hours is greater than max findu allows
+ // for duration
+ //
+ if (posit_start > MAX_FINDU_DURATION) { // Set the duration slider to
+ // findu's max duration hours
+
+ XtVaSetValues(posit_length_value,
+ XmNvalue, MAX_FINDU_DURATION,
+ NULL);
+ posit_length = MAX_FINDU_DURATION;
+ }
+ else { // Not near the max, so set the duration slider to match
+ // the start hours
+
+ XtVaSetValues(posit_length_value,
+ XmNvalue, posit_start,
+ NULL);
+ posit_length = posit_start;
+ }
+}
+
+
+
+
+
+void Download_findu_trail( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, my_form, button_ok, button_cancel, call, sep;
+ Atom delw;
+ XmString x_str;
+
+
+ if (!download_findu_dialog) {
+
+begin_critical_section(&download_findu_dialog_lock, "track_gui.c:Download_findu_trail" );
+
+ download_findu_dialog = XtVaCreatePopupShell(langcode("WPUPTSP007"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse,XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Download_findu_trail pane",
+ xmPanedWindowWidgetClass,
+ download_findu_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("Download_findu_trail my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 2,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ call = XtVaCreateManagedWidget(langcode("WPUPTSP008"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ download_trail_station_data = XtVaCreateManagedWidget("download_trail_station_data",
+ xmTextFieldWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 15,
+ XmNwidth, ((15*7)+2),
+ XmNmaxLength, 15,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, call,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ x_str = XmStringCreateLocalized(langcode("WPUPTSP009"));
+ posit_start_value = XtVaCreateManagedWidget("Start of Trail (hrs ago)",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, call,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ //XmNwidth, 190,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 1,
+ XmNmaximum, MAX_FINDU_START_TIME,
+ XmNshowValue, TRUE,
+ XmNvalue, posit_start,
+// Note: Some versions of OpenMotif (distributed with Fedora,
+// perhaps others) don't work properly with XtVaTypedArg() as used
+// here, instead showing blank labels for the Scale widgets.
+// XtVaTypedArg, XmNtitleString, XmRString, langcode("WPUPTSP009"), 22,
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+ x_str = XmStringCreateLocalized(langcode("WPUPTSP010"));
+ posit_length_value = XtVaCreateManagedWidget("Length of trail (hrs)",
+ xmScaleWidgetClass,
+ my_form,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, posit_start_value,
+ XmNtopOffset, 15,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ //XmNwidth, 190,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNsensitive, TRUE,
+ XmNorientation, XmHORIZONTAL,
+ XmNborderWidth, 1,
+ XmNminimum, 1,
+ XmNmaximum, MAX_FINDU_DURATION,
+ XmNshowValue, TRUE,
+ XmNvalue, posit_length,
+// Note: Some versions of OpenMotif (distributed with Fedora,
+// perhaps others) don't work properly with XtVaTypedArg() as used
+// here, instead showing blank labels for the Scale widgets.
+// XtVaTypedArg, XmNtitleString, XmRString, langcode("WPUPTSP010"), 19,
+ XmNtitleString, x_str,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ XmStringFree(x_str);
+
+ sep = XtVaCreateManagedWidget("Download_findu_trail sep",
+ xmSeparatorGadgetClass,
+ my_form,
+ XmNorientation, XmHORIZONTAL,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget,posit_length_value,
+ XmNtopOffset, 10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment,XmATTACH_FORM,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_ok = XtVaCreateManagedWidget(langcode("WPUPTSP007"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 0,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 1,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+ if (fetching_findu_trail_now)
+ XtSetSensitive(button_ok, FALSE);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00002"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, sep,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 5,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 1,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 2,
+ XmNrightOffset, 5,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNtraversalOn, TRUE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_ok, XmNactivateCallback, Download_trail_now, download_findu_dialog);
+ XtAddCallback(button_cancel, XmNactivateCallback, Download_trail_destroy_shell, download_findu_dialog);
+ XtAddCallback(posit_start_value, XmNvalueChangedCallback, Reset_posit_length_max, download_findu_dialog);
+
+ pos_dialog(download_findu_dialog);
+
+ delw = XmInternAtom(XtDisplay(download_findu_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(download_findu_dialog, delw, Download_trail_destroy_shell, (XtPointer)download_findu_dialog);
+
+ XmTextFieldSetString(download_trail_station_data,download_trail_station_call);
+
+ XtManageChild(my_form);
+ XtManageChild(pane);
+
+end_critical_section(&download_findu_dialog_lock, "track_gui.c:Download_trail" );
+
+ XtPopup(download_findu_dialog,XtGrabNone);
+ fix_dialog_size(download_findu_dialog);
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(download_findu_dialog);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+
+ } else
+ (void)XRaiseWindow(XtDisplay(download_findu_dialog), XtWindow(download_findu_dialog));
+}
+
+
diff --git a/src/track_gui.h b/src/track_gui.h
new file mode 100644
index 0000000..0c732d1
--- /dev/null
+++ b/src/track_gui.h
@@ -0,0 +1,42 @@
+/*
+ * $Id: track_gui.h,v 1.12 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ *
+ *
+ */
+
+#ifndef __TRACK_GUI_H
+#define __TRACK_GUI_H
+
+/* from track_gui.c */
+extern void track_gui_init(void);
+extern void Track_station(Widget w, XtPointer clientData, XtPointer callData);
+extern int track_station_on;
+extern int track_me;
+extern int track_case;
+extern int track_match;
+extern char tracking_station_call[30];
+extern void Download_findu_trail(Widget w, XtPointer clientData, XtPointer callData);
+
+#endif // __TRACK_GUI_H
+
+
diff --git a/src/util.c b/src/util.c
new file mode 100644
index 0000000..e08252f
--- /dev/null
+++ b/src/util.c
@@ -0,0 +1,5738 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: util.c,v 1.249 2012/09/23 16:19:22 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+
+// Needed for Solaris
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif // HAVE_STRINGS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <math.h>
+#include <errno.h>
+
+#include "xastir.h"
+#include "util.h"
+#include "main.h"
+#include "xa_config.h"
+#include "datum.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+#include "maps.h"
+
+
+#define CHECKMALLOC(m) if (!m) { fprintf(stderr, "***** Malloc Failed *****\n"); exit(0); }
+
+// For mutex debugging with Linux threads only
+#ifdef MUTEX_DEBUG
+#include <asm/errno.h>
+//
+// Newer pthread function
+# ifdef HAVE_PTHREAD_MUTEXATTR_SETTYPE
+extern int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);
+# endif // HAVE_PTHREAD_MUTEXATTR_SETTYPE
+//
+// Older, deprecated pthread function
+# ifdef HAVE_PTHREAD_MUTEXATTR_SETKIND_NP
+extern int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind);
+# endif // HAVE_PTHREAD_MUTEXATTR_SETKIND_NP
+//
+#endif // MUTEX_DEBUG
+
+
+#ifdef HAVE_LIBCURL
+#include <curl/curl.h>
+#endif // HAVE_LIBCURL
+
+// Needed for size_t
+#include <sys/types.h>
+
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+int position_amb_chars;
+char echo_digis[6][MAX_CALLSIGN+1];
+
+#define ACCEPT_0N_0E /* set this to see stations at 0N/0E on the map */
+
+struct timeval timer_start;
+struct timeval timer_stop;
+struct timezone tz;
+
+
+static struct hashtable *tactical_hash = NULL;
+#define TACTICAL_HASH_SIZE 1024
+
+#define MAX_LOGFILE_SIZE 2048000
+
+
+/////////////////////////////////////////////////////////////////////
+// convert_from_xastir_coordinates()
+//
+// Converts from Xastir coordinate system to lat/lon. First two
+// parameters are the output floating point lat/lon values. 2nd two
+// are the input Xastir X/Y values.
+//
+// 0 (90 deg. or 90N)
+//
+// 0 (-180 deg. or 180W) 129,600,000 (180 deg. or 180E)
+//
+// 64,800,000 (-90 deg. or 90S)
+//
+// Returns 0 if error, 1 if good values were converted.
+// Errors are due to the x and/or y values exceeding the above
+// limits. In such cases the float values are set to appropriate
+// minimum or maximum values.
+/////////////////////////////////////////////////////////////////////
+int convert_from_xastir_coordinates ( float *f_longitude,
+ float *f_latitude,
+ long x,
+ long y ) {
+
+//fprintf(stderr,"convert_from_xastir_coordinates\n");
+ int result = 1; // assume the input values are in range
+
+ if (x < 0l ) {
+ fprintf(stderr,
+ "convert_from_xastir_coordinates:X out-of-range (too low):%lu\n",
+ x);
+ x = 0;
+ result = 0;
+ }
+
+ if (x > 129600000l) {
+ fprintf(stderr,
+ "convert_from_xastir_coordinates:X out-of-range (too high):%lu\n",
+ x);
+ x = 129600000l;
+ result = 0;
+ }
+
+ if (y < 0l) {
+ fprintf(stderr,
+ "convert_from_xastir_coordinates:Y out-of-range (too low):%lu\n",
+ y);
+ y = 0;
+ result = 0;
+ }
+
+ if (y > 64800000l) {
+ fprintf(stderr,
+ "convert_from_xastir_coordinates:Y out-of-range (too high):%lu\n",
+ y);
+ y = 64800000l;
+ result = 0;
+ }
+
+ *f_latitude = (float)( -((y - 32400000l) / 360000.0) );
+ *f_longitude = (float)( (x - 64800000l) / 360000.0 );
+
+//fprintf(stderr,"input x: %lu\tinput y: %lu\n",
+// x,
+// y);
+//fprintf(stderr,"latitude: %f\tlongitude: %f\n",
+// *f_latitude,
+// *f_longitude);
+
+ return(result);
+}
+
+
+
+
+
+/////////////////////////////////////////////////////////////////////
+// convert_to_xastir_coordinates()
+//
+// Converts from lat/lon to Xastir coordinate system.
+// First two parameters are the output Xastir X/Y values,
+// 2nd two are the input floating point lat/lon values.
+//
+// 0 (90 deg. or 90N)
+//
+// 0 (-180 deg. or 180W) 129,600,000 (180 deg. or 180E)
+//
+// 64,800,000 (-90 deg. or 90S)
+//
+// Returns 0 if error, 1 if good values were converted.
+/////////////////////////////////////////////////////////////////////
+int convert_to_xastir_coordinates ( unsigned long* x,
+ unsigned long* y,
+ float f_longitude,
+ float f_latitude ) {
+
+ int ok = 1;
+
+ *y = (unsigned long)(32400000l + (360000.0 * (-f_latitude)));
+ *x = (unsigned long)(64800000l + (360000.0 * f_longitude));
+
+ if (f_longitude < -180.0) {
+ fprintf(stderr,
+ "convert_to_xastir_coordinates:Longitude out-of-range (too low):%f\n",
+ f_longitude);
+ *x = 0;
+ ok = 0;
+ }
+
+ if (f_longitude > 180.0) {
+ fprintf(stderr,
+ "convert_to_xastir_coordinates:Longitude out-of-range (too high):%f\n",
+ f_longitude);
+ *x = 129600000l;
+ ok = 0;
+ }
+
+ if (f_latitude < -90.0) {
+ fprintf(stderr,
+ "convert_to_xastir_coordinates:Latitude out-of-range (too low):%f\n",
+ f_latitude);
+ *y = 0;
+ ok = 0;
+ }
+
+ if (f_latitude > 90.0) {
+ fprintf(stderr,
+ "convert_to_xastir_coordinates:Latitude out-of-range (too high):%f\n",
+ f_latitude);
+ *y = 64800000l;
+ ok =0;
+ }
+
+ return(ok);
+}
+
+
+
+
+
+// Multiply all the characters in the callsign, truncated to
+// TACTICAL_HASH_SIZE
+//
+unsigned int tactical_hash_from_key(void *key) {
+ unsigned char *jj = key;
+ unsigned int tac_hash = 1;
+
+ while (*jj != '\0') {
+ tac_hash = tac_hash * (unsigned int)*jj++;
+ }
+
+ tac_hash = tac_hash % TACTICAL_HASH_SIZE;
+
+// fprintf(stderr,"hash = %d\n", tac_hash);
+ return (tac_hash);
+}
+
+
+
+
+
+int tactical_keys_equal(void *key1, void *key2) {
+
+//fprintf(stderr,"Comparing %s to %s\n",(char *)key1,(char *)key2);
+ if (strlen((char *)key1) == strlen((char *)key2)
+ && strncmp((char *)key1,(char *)key2,strlen((char *)key1))==0) {
+//fprintf(stderr," match\n");
+ return(1);
+ }
+ else {
+//fprintf(stderr," no match\n");
+ return(0);
+ }
+}
+
+
+
+
+
+void init_tactical_hash(int clobber) {
+// fprintf(stderr," Initializing tactical hash \n");
+ // make sure we don't leak
+//fprintf(stderr,"init_tactical_hash\n");
+ if (tactical_hash) {
+//fprintf(stderr,"Already have one!\n");
+ if (clobber) {
+//fprintf(stderr,"Clobbering hash table\n");
+ hashtable_destroy(tactical_hash, 1);
+ tactical_hash=create_hashtable(TACTICAL_HASH_SIZE,
+ tactical_hash_from_key,
+ tactical_keys_equal);
+ }
+ }
+ else {
+//fprintf(stderr,"Creating hash table from scratch\n");
+ tactical_hash=create_hashtable(TACTICAL_HASH_SIZE,
+ tactical_hash_from_key,
+ tactical_keys_equal);
+ }
+}
+
+
+
+
+
+char *get_tactical_from_hash(char *callsign) {
+ char *result;
+
+ if (callsign == NULL || *callsign == '\0') {
+ fprintf(stderr,"Empty callsign passed to get_tactical_from_hash()\n");
+ return(NULL);
+ }
+
+ if (!tactical_hash) { // no table to search
+//fprintf(stderr,"Creating hash table\n");
+ init_tactical_hash(1); // so create one
+ return NULL;
+ }
+
+// fprintf(stderr," searching for %s...",callsign);
+
+ result=hashtable_search(tactical_hash,callsign);
+
+ if (result) {
+// fprintf(stderr,"\t\tFound it, %s, len=%d, %s\n",
+// callsign,
+// strlen(callsign),
+// result);
+ } else {
+// fprintf(stderr,"\t\tNot found, %s, len=%d\n",
+// callsign,
+// strlen(callsign));
+ }
+
+ return (result);
+}
+
+
+
+
+
+// This function checks whether there already is something in the
+// hashtable that matches. If a match found, it overwrites the
+// tactical call for that entry, else it inserts a new record.
+//
+void add_tactical_to_hash(char *callsign, char *tactical_call) {
+ char *temp1; // tac-call
+ char *temp2; // callsign
+ char *ptr;
+
+
+ // Note that tactical_call can be '\0', which means we're
+ // getting rid of a previous tactical call.
+ //
+ if (callsign == NULL || *callsign == '\0'
+ || tactical_call == NULL) {
+ return;
+ }
+
+ if (!tactical_hash) { // no table to add to
+//fprintf(stderr,"init_tactical_hash\n");
+ init_tactical_hash(1); // so create one
+ }
+
+ // Remove any matching entry to avoid duplicates
+ ptr = hashtable_remove(tactical_hash, callsign);
+ if (ptr) { // If value found, free the storage space for it as
+ // the hashtable_remove function doesn't. It does
+ // however remove the key (callsign) ok.
+ free(ptr);
+ }
+
+ temp1 = (char *)malloc(MAX_TACTICAL_CALL+1);
+ CHECKMALLOC(temp1);
+
+ temp2 = (char *)malloc(MAX_CALLSIGN+1);
+ CHECKMALLOC(temp2);
+
+//fprintf(stderr, "\t\t\tAdding %s = %s...\n", callsign, tactical_call);
+
+ xastir_snprintf(temp2,
+ MAX_CALLSIGN+1,
+ "%s",
+ callsign);
+
+ xastir_snprintf(temp1,
+ MAX_TACTICAL_CALL+1,
+ "%s",
+ tactical_call);
+
+ // (key) (value)
+ // hash call tac-call
+ if (!hashtable_insert(tactical_hash, temp2, temp1)) {
+ fprintf(stderr,"Insert failed on tactical hash --- fatal\n");
+ free(temp1);
+ free(temp2);
+ exit(1);
+ }
+
+ // A check to see whether hash insert/update worked properly
+ ptr = get_tactical_from_hash(callsign);
+ if (!ptr) {
+ fprintf(stderr,"***Failed hash insert/update***\n");
+ }
+ else {
+//fprintf(stderr,"Current: %s -> %s\n",
+// callsign,
+// ptr);
+ }
+}
+
+
+
+
+
+void destroy_tactical_hash(void) {
+ struct hashtable_itr *iterator = NULL;
+ char *value;
+
+ if (tactical_hash && hashtable_count(tactical_hash) > 0) {
+
+ iterator = hashtable_iterator(tactical_hash);
+
+ do {
+ if (iterator) {
+ value = hashtable_iterator_value(iterator);
+ if (value) {
+ free(value);
+ }
+ }
+ } while (hashtable_iterator_remove(iterator));
+
+ // Destroy the hashtable, freeing what's left of the
+ // entries.
+ hashtable_destroy(tactical_hash, 1);
+
+ tactical_hash = NULL;
+
+ if (iterator) free(iterator);
+ }
+}
+
+
+
+
+
+// Prints string to STDERR only if "my_debug_level" bits are set in
+// the global "debug_level" variable. Used for getting extra debug
+// messages during various stages of debugging.
+//
+void xastir_debug(int my_debug_level, char *debug_string) {
+
+ if (debug_level & my_debug_level) {
+ fprintf(stderr, "%s", debug_string);
+ }
+}
+
+
+
+
+
+char *remove_all_spaces(char *data) {
+ char *ptr;
+ int length = strlen(data);
+
+ ptr = data;
+ while ( (ptr = strpbrk(data, " ")) ) {
+ memmove(ptr, ptr+1, strlen(ptr)+1);
+ length--;
+ }
+
+ // Terminate at the new string length
+ data[length] = '\0';
+
+ return(data);
+}
+
+
+
+
+
+char *remove_leading_spaces(char *data) {
+ int i,j;
+ int count;
+
+ if (data == NULL)
+ return NULL;
+
+ if (strlen(data) == 0)
+ return NULL;
+
+ count = 0;
+ // Count the leading space characters
+ for (i = 0; i < (int)strlen(data); i++) {
+ if (data[i] == ' ') {
+ count++;
+ }
+ else { // Found a non-space
+ break;
+ }
+ }
+
+ // Check whether entire string was spaces
+ if (count == (int)strlen(data)) {
+ // Empty the string
+ data[0] = '\0';
+ }
+ else if (count > 0) { // Found some spaces
+ i = 0;
+ for( j = count; j < (int)strlen(data); j++ ) {
+ data[i++] = data[j]; // Move string left
+ }
+ data[i] = '\0'; // Terminate the new string
+ }
+
+ return(data);
+}
+
+
+
+
+
+char *remove_trailing_spaces(char *data) {
+ int datalen;
+
+ if (data != NULL) {
+
+ datalen=strlen(data);
+ for(datalen--;datalen>=0;datalen--)
+ if(data[datalen] == ' ')
+ data[datalen] = '\0';
+ else
+ break;
+ }
+
+ // May end up with nothing left.
+ return(data);
+}
+
+
+
+
+
+char *remove_trailing_asterisk(char *data) {
+ int datalen;
+
+ if (data != NULL) {
+
+ datalen=strlen(data);
+ for(datalen--;datalen>0;datalen--) {
+ if(data[datalen] == '*')
+ data[datalen] = '\0';
+ else
+ break;
+ }
+ }
+ // May end up with nothing left.
+ return(data);
+}
+
+
+
+
+
+// Removes trailing "-0" from string.
+//
+// Modifies "data" variable.
+//
+char *remove_trailing_dash_zero(char *data) {
+ char *ptr;
+ char *ptr2;
+ int len = strlen(data);
+
+
+ // String too short?
+ if (len < 2)
+ return(data);
+
+ ptr2 = data + len - 1; // Point to last char
+ ptr = ptr2 - 1; // Point to next-to-last char
+
+ // Check for "-0" at end. Remove if found.
+ if (*ptr == '-' && *ptr2 == '0') {
+ *ptr = '\0'; // Terminate
+ }
+
+ return(data);
+}
+
+
+
+
+
+// Save the current time, used for timing code sections.
+void start_timer(void) {
+ gettimeofday(&timer_start,&tz);
+}
+
+
+
+
+
+// Save the current time, used for timing code sections.
+void stop_timer(void) {
+ gettimeofday(&timer_stop,&tz);
+}
+
+
+
+
+
+// Print the difference in the two times saved above.
+void print_timer_results(void) {
+fprintf(stderr,"Total: %f sec\n",
+ (float)(timer_stop.tv_sec - timer_start.tv_sec +
+ ((timer_stop.tv_usec - timer_start.tv_usec) / 1000000.0) ));
+}
+
+
+
+
+
+//
+// Inserts localtime date/time in "timestring". Timestring
+// Should be at least 101 characters long.
+//
+void get_timestamp(char *timestring) {
+ struct tm *time_now;
+ time_t secs_now;
+
+
+ secs_now=sec_now();
+ time_now = localtime(&secs_now);
+
+// %e is not implemented on all systems, but %d should be
+// (void)strftime(timestring,100,"%a %b %e %H:%M:%S %Z %Y",time_now);
+ (void)strftime(timestring,100,"%a %b %d %H:%M:%S %Z %Y",time_now);
+}
+
+
+
+
+
+/* function get_iso_datetime converts time in seconds to an ISO date
+ * time in the form yyyy-mm-dd hh:mm:ss utc_offset
+ * @param aTime time in seconds since the begining of the unix epoch
+ * @param timestring pointer to a char[101] into which the timestamp
+ * is written in the format yyyy-mm-dd hh:mm:ss followed by a utc
+ * offset for the timezone.
+ * @param nowIfNotSet when true, if aTime is not set (int)aTime==0,
+ * then return the current time rather than formatting aTime, when
+ * false, returns formatted aTime even if it was zero.
+ * @param nowIfInvalid when true, if aTime is invalid (int)aTime=-1,
+ * then returns the formatted current time rather than formatting
+ * aTime, otherwise returns formatted invalid time.
+ * @returns 0 on when (int)aTime==-1 where time provided invalid
+ * returns 1 otherwise. */
+int get_iso_datetime(time_t aTime, char *timestring,int nowIfNotSet, int nowIfInvalid) {
+ struct tm *time_now;
+ time_t secs_now;
+ int returnvalue = 1;
+ if (((int)aTime==0 && nowIfNotSet) || ((int)aTime==-1 && nowIfInvalid)) {
+ secs_now=sec_now();
+ time_now = localtime(&secs_now);
+ (void)strftime(timestring,100,"%F %H:%M:%S %z",time_now);
+ } else {
+ // will also end up here if time_t is -1
+ (void)strftime(timestring,100,"%F %H:%M:%S %z",localtime(&aTime));
+ }
+ if ((int)aTime==-1) {
+ returnvalue = 0;
+ }
+ return returnvalue;
+}
+
+
+
+
+
+
+/* function get_W3CDTF_datetime converts time in seconds to a W3CDTF date
+ * time in the form yyyy-mm-ddThh:mm:ss-utc_offsethh:mm
+ * See: http://www.w3.org/TR/NOTE-datetime
+ * This is effectively an ISO date, with a T between the date and the
+ * time, no space between the time and the utc offset, and a colon
+ * separating utc offset hours from utc offset seconds.
+ * Example: 2008-01-25T08:35:20-05:00
+ * @param aTime time in seconds since the begining of the unix epoch
+ * @param timestring pointer to a char[101] into which the timestamp
+ * is written in the format yyyy-mm-ddThh:mm:ss followed by a utc
+ * offset for the timezone, (e.g. -05:00).
+ * @param nowIfNotSet when true, if aTime is not set (int)aTime==0,
+ * then return the current time rather than formatting aTime, when
+ * false, returns formatted aTime even if it was zero.
+ * @param nowIfInvalid when true, if aTime is invalid (int)aTime=-1,
+ * then returns the formatted current time rather than formatting
+ * aTime, otherwise returns formatted invalid time.
+ * @returns 0 on when (int)aTime==-1 where time provided invalid
+ * returns 1 otherwise. */
+int get_w3cdtf_datetime(time_t aTime, char *timestring,int nowIfNotSet, int nowIfInvalid) {
+ struct tm *time_now;
+ time_t secs_now;
+ int returnvalue = 1;
+ if (((int)aTime==0 && nowIfNotSet) || ((int)aTime==-1 && nowIfInvalid)) {
+ secs_now=sec_now();
+ time_now = localtime(&secs_now);
+ (void)strftime(timestring,100,"%FT%H:%M:%S %z",time_now);
+ timestring[19] = timestring[20];
+ timestring[20] = timestring[21];
+ timestring[21] = timestring[22];
+ timestring[22] = ':';
+ } else {
+ // will also end up here if time_t is -1
+ (void)strftime(timestring,100,"%FT%H:%M:%S %z",localtime(&aTime));
+ timestring[19] = timestring[20];
+ timestring[20] = timestring[21];
+ timestring[21] = timestring[22];
+ timestring[22] = ':';
+ }
+ if ((int)aTime==-1) {
+ returnvalue = 0;
+ }
+ return returnvalue;
+}
+
+
+
+
+/***********************************************************/
+/* returns the hour (00..23), localtime */
+/***********************************************************/
+int get_hours(void) {
+ struct tm *time_now;
+ time_t secs_now;
+ char shour[5];
+
+ secs_now=sec_now();
+ time_now = localtime(&secs_now);
+ (void)strftime(shour,4,"%H",time_now);
+ return(atoi(shour));
+}
+
+
+
+
+
+/***********************************************************/
+/* returns the minute (00..59), localtime */
+/***********************************************************/
+int get_minutes(void) {
+ struct tm *time_now;
+ time_t secs_now;
+ char sminute[5];
+
+ secs_now=sec_now();
+ time_now = localtime(&secs_now);
+ (void)strftime(sminute,4,"%M",time_now);
+ return(atoi(sminute));
+}
+
+
+
+
+
+/***********************************************************/
+/* returns the second (00..61), localtime */
+/***********************************************************/
+int get_seconds(void) {
+ struct tm *time_now;
+ time_t secs_now;
+ char sminute[5];
+
+ secs_now=sec_now();
+ time_now = localtime(&secs_now);
+ (void)strftime(sminute,4,"%S",time_now);
+ return(atoi(sminute));
+}
+
+
+
+
+
+
+/*************************************************************************/
+/* output_lat - format position with position_amb_chars for transmission */
+/*************************************************************************/
+char *output_lat(char *in_lat, int comp_pos) {
+ int i,j;
+
+//fprintf(stderr,"in_lat:%s\n", in_lat);
+
+ if (!comp_pos) {
+ // Don't do this as it results in truncation!
+ //in_lat[7]=in_lat[8]; // Shift N/S down for transmission
+ }
+ else if (position_amb_chars>0) {
+ in_lat[7]='0';
+ }
+
+ j=0;
+ if (position_amb_chars>0 && position_amb_chars<5) {
+ for (i=6;i>(6-position_amb_chars-j);i--) {
+ if (i==4) {
+ i--;
+ j=1;
+ }
+ if (!comp_pos) {
+ in_lat[i]=' ';
+ } else
+ in_lat[i]='0';
+ }
+ }
+
+ if (!comp_pos) {
+ in_lat[8] = '\0';
+ }
+
+ return(in_lat);
+}
+
+
+
+
+
+/**************************************************************************/
+/* output_long - format position with position_amb_chars for transmission */
+/**************************************************************************/
+char *output_long(char *in_long, int comp_pos) {
+ int i,j;
+
+//fprintf(stderr,"in_long:%s\n", in_long);
+
+ if (!comp_pos) {
+ // Don't do this as it results in truncation!
+ //in_long[8]=in_long[9]; // Shift e/w down for transmission
+ }
+ else if (position_amb_chars>0) {
+ in_long[8]='0';
+ }
+
+ j=0;
+ if (position_amb_chars>0 && position_amb_chars<5) {
+ for (i=7;i>(7-position_amb_chars-j);i--) {
+ if (i==5) {
+ i--;
+ j=1;
+ }
+ if (!comp_pos) {
+ in_long[i]=' ';
+ } else
+ in_long[i]='0';
+ }
+ }
+
+ if (!comp_pos)
+ in_long[9] = '\0';
+
+ return(in_long);
+}
+
+
+
+
+
+/*********************************************************************/
+/* PHG range calculation */
+/* NOTE: Keep these calculations consistent with phg_decode! */
+/* Yes, there is a reason why they both exist. */
+/*********************************************************************/
+double phg_range(char p, char h, char g) {
+ double power, height, gain, range;
+
+ if ( (p < '0') || (p > '9') ) // Power is outside limits
+ power = 0.0;
+ else
+ power = (double)( (p-'0')*(p-'0') ); // lclint said: "Assignment of char to double" here
+
+ if (h < '0') // Height is outside limits (there is no upper limit according to the spec)
+ height = 10.0;
+ else
+ height = 10.0 * pow(2.0, (double)(h-'0'));
+
+ if ( (g < '0') || (g > '9') ) // Gain is outside limits
+ gain = 1.0;
+ else
+ gain = pow(10.0, (double)(g-'0') / 10.0);
+
+ range = sqrt(2.0 * height * sqrt((power / 10.0) * (gain / 2.0)));
+
+// if (range > 70.0)
+// fprintf(stderr,"PHG%c%c%c results in range of %f\n", p, h, g, range);
+
+ // Note: Bob Bruninga, WB4APR, decided to cut PHG circles by
+ // 1/2 in order to show more realistic mobile ranges.
+ range = range / 2.0;
+
+ return(range);
+}
+
+
+
+
+
+/*********************************************************************/
+/* shg range calculation (for DF'ing) */
+/* */
+/*********************************************************************/
+double shg_range(char s, char h, char g) {
+ double power, height, gain, range;
+
+ if ( (s < '0') || (s > '9') ) // Power is outside limits
+ s = '0';
+
+ if (s == '0') // No signal strength
+ power = 10.0 / 0.8; // Preventing divide by zero (same as DOSaprs does it)
+ else
+ power = 10 / (s - '0'); // Makes circle smaller with higher signal strengths
+
+ if (h < '0') // Height is outside limits (there is no upper limit according to the spec)
+ height = 10.0;
+ else
+ height = 10.0 * pow(2.0, (double)(h-'0'));
+
+ if ( (g < '0') || (g > '9') ) // Gain is outside limits
+ gain = 1.0;
+ else
+ gain = pow(10.0, (double)(g-'0') / 10.0);
+
+ range = sqrt(2.0 * height * sqrt((power / 10.0) * (gain / 2.0)));
+
+ range = (range * 40) / 51; // Present fudge factors used in DOSaprs
+
+ //fprintf(stderr,"SHG%c%c%c results in range of %f\n", s, h, g, range);
+
+ return(range);
+}
+
+
+
+
+
+/*********************************************************************/
+/* PHG decode */
+/* NOTE: Keep these calculations consistent with phg_range! */
+/* Yes, there is a reason why they both exist. */
+/*********************************************************************/
+void phg_decode(const char *langstr, const char *phg, char *phg_decoded, int phg_decoded_length) {
+ double power, height, gain, range;
+ char directivity[6], temp[64];
+ int gain_db;
+ int len;
+
+ len = strlen(phg_decoded);
+
+ if (strlen(phg) != 7) {
+ xastir_snprintf(phg_decoded,
+ phg_decoded_length,
+ "%s %s",
+ langstr,
+ langcode("WPUPSTI073") ); // "BAD PHG"
+ return;
+ }
+
+ if ( (phg[3] < '0') || (phg[3] > '9') ) // Power is outside limits
+ power = 0.0;
+ else
+ power = (double)( (phg[3]-'0')*(phg[3]-'0') );
+
+ if (phg[4] < '0') // Height is outside limits (there is no upper limit according to the spec)
+ height = 10.0;
+ else
+ height = 10.0 * pow(2.0, (double)(phg[4]-'0'));
+
+ if ( (phg[5] < '0') || (phg[5] > '9') ) { // Gain is outside limits
+ gain = 1.0;
+ gain_db = 0;
+ }
+ else {
+ gain = pow(10.0, (double)(phg[5]-'0') / 10.0);
+ gain_db = phg[5]-'0';
+ }
+
+ range = sqrt(2.0 * height * sqrt((power / 10.0) * (gain / 2.0)));
+ // Note: Bob Bruninga, WB4APR, decided to cut PHG circles by
+ // 1/2 in order to show more realistic mobile ranges.
+ range = range / 2.0;
+
+ switch (phg[6]) {
+ case '0':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ langcode("WPUPSTI071") ); // "omni"
+ break;
+ case '1':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " NE");
+ break;
+ case '2':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " E");
+ break;
+ case '3':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " SE");
+ break;
+ case '4':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " S");
+ break;
+ case '5':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " SW");
+ break;
+ case '6':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " W");
+ break;
+ case '7':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " NW");
+ break;
+ case '8':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " N");
+ break;
+ default:
+ directivity[0] = '\0'; break;
+ }
+
+ if (english_units)
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%.0fW @ %.0fft %s, %ddB%s, %s %.1fmi",
+ power,
+ height,
+ langcode("WPUPSTI070"), // HAAT
+ gain_db,
+ directivity,
+ langcode("WPUPSTI072"), // range
+ range);
+ else
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%.0fW @ %.1fm %s, %ddB%s, %s %.1fkm",
+ power,
+ height*0.3048,
+ langcode("WPUPSTI070"), // HAAT
+ gain_db,
+ directivity,
+ langcode("WPUPSTI072"), // range
+ range*1.609344);
+
+ xastir_snprintf(phg_decoded,
+ phg_decoded_length,
+ "%s %s",
+ langstr,
+ temp);
+}
+
+
+
+
+
+/*********************************************************************/
+/* SHG decode */
+/* */
+/*********************************************************************/
+void shg_decode(const char *langstr, const char *shg, char *shg_decoded, int shg_decoded_length) {
+ double power, height, gain, range;
+ char directivity[6], temp[80], signal[64];
+ int gain_db;
+ char s;
+ int len;
+
+ len = strlen(shg_decoded);
+ if (strlen(shg) != 7) {
+ xastir_snprintf(shg_decoded,
+ shg_decoded_length,
+ langstr,
+ langcode("WPUPSTI074") ); // "BAD SHG"
+ return;
+ }
+
+ s = shg[3];
+
+ if ( (s < '0') || (s > '9') ) // Signal is outside limits
+ s = '0'; // force to lowest legal value
+
+ switch (s) {
+ case '0':
+ xastir_snprintf(signal,
+ sizeof(signal),
+ "%s",
+ langcode("WPUPSTI076") );
+ // "No signal detected"
+ break;
+ case '1':
+ xastir_snprintf(signal,
+ sizeof(signal),
+ "%s",
+ langcode("WPUPSTI077") );
+ // "Detectible signal (Maybe)"
+ break;
+ case '2':
+ xastir_snprintf(signal,
+ sizeof(signal),
+ "%s",
+ langcode("WPUPSTI078") );
+ // "Detectible signal but not copyable)"
+ break;
+ case '3':
+ xastir_snprintf(signal,
+ sizeof(signal),
+ "%s",
+ langcode("WPUPSTI079") );
+ // "Weak signal, marginally readable"
+ break;
+ case '4':
+ xastir_snprintf(signal,
+ sizeof(signal),
+ "%s",
+ langcode("WPUPSTI080") );
+ // "Noisy but copyable signal"
+ break;
+ case '5':
+ xastir_snprintf(signal,
+ sizeof(signal),
+ "%s",
+ langcode("WPUPSTI081") );
+ // "Some noise, easy to copy signal"
+ break;
+ case '6':
+ xastir_snprintf(signal,
+ sizeof(signal),
+ "%s",
+ langcode("WPUPSTI082") );
+ // "Good signal w/detectible noise"
+ break;
+ case '7':
+ xastir_snprintf(signal,
+ sizeof(signal),
+ "%s",
+ langcode("WPUPSTI083") );
+ // "Near full-quieting signal"
+ break;
+ case '8':
+ xastir_snprintf(signal,
+ sizeof(signal),
+ "%s",
+ langcode("WPUPSTI084") );
+ // "Full-quieting signal"
+ break;
+ case '9':
+ xastir_snprintf(signal,
+ sizeof(signal),
+ "%s",
+ langcode("WPUPSTI085") );
+ // "Extremely strong & full-quieting signal"
+ break;
+ default:
+ signal[0] = '\0';
+ break;
+ }
+
+ if (s == '0')
+ power = (double)( 10 / 0.8 ); // Preventing divide by zero (same as DOSaprs does it)
+ else
+ power = (double)( 10 / (s - '0') );
+
+ if (shg[4] < '0') // Height is outside limits (there is no upper limit according to the spec)
+ height = 10.0;
+ else
+ height = 10.0 * pow(2.0, (double)(shg[4]-'0'));
+
+ if ( (shg[5] < '0') || (shg[5] > '9') ) { // Gain is outside limits
+ gain = 1.0;
+ gain_db = 0;
+ } else {
+ gain = pow(10.0, (double)(shg[5]-'0') / 10.0);
+ gain_db = shg[5]-'0';
+ }
+
+ range = sqrt(2.0 * height * sqrt((power / 10.0) * (gain / 2.0)));
+
+ range = range * 0.85; // Present fudge factor (used by DOSaprs)
+
+ switch (shg[6]) {
+ case '0':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s ",
+ langcode("WPUPSTI071") ); // "omni"
+ break;
+ case '1':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " NE");
+ break;
+ case '2':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " E");
+ break;
+ case '3':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " SE");
+ break;
+ case '4':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " S");
+ break;
+ case '5':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " SW");
+ break;
+ case '6':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " W");
+ break;
+ case '7':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " NW");
+ break;
+ case '8':
+ xastir_snprintf(directivity,
+ sizeof(directivity),
+ "%s",
+ " N");
+ break;
+ default:
+ directivity[0] = '\0'; break;
+ }
+
+ if (english_units)
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%.0fft %s, %ddB%s, %s: %.1fmi, %s",
+ height,
+ langcode("WPUPSTI070"), // "HAAT"
+ gain_db,
+ directivity,
+ langcode("WPUPSTI075"), // "DF Range"
+ range,
+ signal);
+ else
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%.1fm %s, %ddB%s, %s: %.1fkm, %s",
+ height*0.3048,
+ langcode("WPUPSTI070"), // "HAAT"
+ gain_db,
+ directivity,
+ langcode("WPUPSTI075"), // "DF Range"
+ range*1.609344,
+ signal);
+
+ xastir_snprintf(shg_decoded,
+ shg_decoded_length,
+ langstr,
+ temp);
+}
+
+
+
+
+
+/*********************************************************************/
+/* Bearing decode */
+/* */
+/*********************************************************************/
+void bearing_decode(const char *langstr, const char *bearing_str,
+ const char *NRQ, char *bearing_decoded, int bearing_decoded_length) {
+ int bearing, range, width;
+ char N,R,Q;
+ char temp[64];
+ int len;
+
+
+//fprintf(stderr,"bearing_decode incoming: bearing is %s, NRQ is %s\n", bearing_str, NRQ);
+
+ len = strlen(bearing_decoded);
+
+ if (strlen(bearing_str) != 3) {
+ xastir_snprintf(bearing_decoded,
+ bearing_decoded_length,
+ langstr,
+ langcode("WPUPSTI086") ); // "BAD BEARING"
+ return;
+ }
+
+ if (strlen(NRQ) != 3) {
+ xastir_snprintf(bearing_decoded,
+ bearing_decoded_length,
+ langstr,
+ langcode("WPUPSTI087") ); // "BAD NRQ"
+ return;
+ }
+
+ bearing = atoi(bearing_str);
+ N = NRQ[0];
+ R = NRQ[1];
+ Q = NRQ[2];
+
+ range = 0;
+ width = 0;
+
+ if (N != 0) {
+
+//fprintf(stderr,"N != 0\n");
+
+ range = (int)( pow(2.0,R - '0') );
+
+ switch (Q) {
+ case('1'):
+ width = 240; // Degrees of beam width. What's the point?
+ break;
+ case('2'):
+ width = 120; // Degrees of beam width. What's the point?
+ break;
+ case('3'):
+ width = 64; // Degrees of beam width. What's the point?
+ break;
+ case('4'):
+ width = 32; // Degrees of beam width. Starting to be usable.
+ break;
+ case('5'):
+ width = 16; // Degrees of beam width. Usable.
+ break;
+ case('6'):
+ width = 8; // Degrees of beam width. Usable.
+ break;
+ case('7'):
+ width = 4; // Degrees of beam width. Nice!
+ break;
+ case('8'):
+ width = 2; // Degrees of beam width. Nice!
+ break;
+ case('9'):
+ width = 1; // Degrees of beam width. Very Nice!
+ break;
+ default:
+ width = 8; // Degrees of beam width
+ break;
+ }
+
+//fprintf(stderr,"Width = %d\n",width);
+
+ if (english_units) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%i�, %s: %i�, %s: %i mi",
+ bearing,
+ langcode("WPUPSTI088"), // DF Beamwidth
+ width,
+ langcode("WPUPSTI089"), // DF Length
+ range);
+ } else {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%i�, %s: %i�, %s: %0.2f km",
+ bearing,
+ langcode("WPUPSTI088"), // DF Beamwidth
+ width,
+ langcode("WPUPSTI089"), // DF Length
+ range*1.609344);
+ }
+ } else {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ langcode("WPUPSTI090") ); // "Not Valid"
+
+//fprintf(stderr,"N was 0\n");
+ }
+ xastir_snprintf(bearing_decoded,
+ bearing_decoded_length,
+ langstr,
+ temp);
+
+//fprintf(stderr,"bearing_decoded:%s\n", bearing_decoded);
+//fprintf(stderr,"temp:%s\n", temp);
+}
+
+
+
+
+
+//********************************************************************/
+// get_line - read a line from a file */
+//
+// NOTE: This routine will not work for binary files. It works only
+// for ASCII-format files, and terminates each line at the first
+// control-character found (unless it's a tab). Converts tab
+// character to 1 space character.
+//
+//********************************************************************/
+/*
+char *get_line(FILE *f, char *linedata, int maxline) {
+ char temp_line[32768];
+ int i;
+
+ // Snag one string from the file. We'll end up with a
+ // terminating zero at temp_line[32767] in any case, because the
+ // max quantity we'll get here will be 32767 with a terminating
+ // zero added after whatever quantity is read.
+ (void)fgets(temp_line, 32768, f);
+
+ // A newline may have been added by the above fgets call.
+ // Change any newlines or other control characters to line-end
+ // characters.
+ for (i = 0; i < strlen(temp_line); i++) {
+ // Change any control characters to '\0';
+ if (temp_line[i] < 0x20) {
+ if (temp_line[i] == '\t') { // Found a tab char
+ temp_line[i] = ' '; // Convert to a space char
+ }
+ else { // Not a tab
+ if (temp_line[i] != '\n') { // LF
+ if ( (i != (strlen(temp_line) - 2) ) // CRLF
+ && (i != (strlen(temp_line) - 1) ) ) { // CR
+ fprintf(stderr,"get_line: found control chars in: %s\n",
+ temp_line);
+ }
+ }
+ temp_line[i] = '\0'; // Terminate the string
+ }
+ }
+ }
+
+ xastir_snprintf(linedata,
+ maxline,
+ "%s",
+ temp_line);
+
+ return(linedata);
+}
+*/
+char *get_line(FILE *f, char *linedata, int maxline) {
+ int length;
+
+ // Write terminating chars throughout variable
+ memset(linedata,0,maxline);
+
+ // Get the data
+ (void)fgets(linedata, maxline, f);
+
+ // Change CR/LF to '\0'
+ length = strlen(linedata);
+
+ // Check the last two characters
+ if (length > 0) {
+ if ( (linedata[length - 1] == '\n')
+ || (linedata[length - 1] == '\r') ) {
+ linedata[length - 1] = '\0';
+ }
+ }
+
+ if (length > 1) {
+ if ( (linedata[length - 2] == '\n')
+ || (linedata[length - 2] == '\r') ) {
+ linedata[length - 2] = '\0';
+ }
+ }
+
+ return(linedata);
+}
+
+
+
+
+
+// time_from_aprsstring()
+//
+// Called from alert.c:alert_build_list() only. Converts to
+// localtime if it's a zulu time string we're parsing.
+//
+time_t time_from_aprsstring(char *aprs_time) {
+ int day, hour, minute;
+ char tz[20];
+ struct tm *time_now, alert_time;
+ time_t timenw;
+ long zone;
+
+#ifndef HAVE_TM_GMTOFF
+ #ifdef __CYGWIN__
+ // Use "_timezone" instead of timezone in Cygwin
+ #define timezone _timezone
+ #else // __CYGWIN__
+ extern time_t timezone;
+ #endif // __CYGWIN__
+#endif // HAVE_TM_GMTOFF
+
+
+#ifdef __CYGWIN__
+ // Must call tzset before using the _timezone variable in
+ // Cygwin, else the timezone won't have been initialized.
+ tzset();
+#endif // __CYGWIN__
+
+ // Compute our current time and the offset from GMT. If
+ // daylight savings time is in effect, factor that in as well.
+ (void)time(&timenw);
+ time_now = localtime(&timenw);
+#ifdef HAVE_TM_GMTOFF
+ // tm_gmtoff is the GMT offset in seconds. Some Unix systems
+ // have this extra field in the tm struct, some don't.
+ // tm_gmtoff is seconds EAST of UTC.
+ zone = time_now->tm_gmtoff;
+ //fprintf(stderr,"gmtoff: %ld, tm_isdst: %d\n",
+ //time_now->tm_gmtoff,
+ //time_now->tm_isdst);
+#else // HAVE_TM_GMTOFF
+ // Note: timezone is seconds WEST of UTC. Need to negate
+ // timezone to have the offset occur in the correct direction.
+ zone = -((int)timezone - 3600 * (int)(time_now->tm_isdst > 0));
+ //fprintf(stderr,"timezone: %d, tm_isdst: %d\n",
+ //timezone,
+ //time_now->tm_isdst);
+#endif // HAVE_TM_GMTOFF
+ // zone should now be the number to subtract in order to get
+ // localtime, in seconds. For PST, I get -28800 which equals -8
+ // hours. Summertime I should get -25200, or -7 hours.
+ //fprintf(stderr,"Zone: %ld\n",zone);
+
+
+ // Split the input time string into its component parts.
+ tz[0] = tz[1] = '\0';
+ switch (sscanf(aprs_time, "%2d%2d%2d%19s", &day, &hour, &minute, tz)) {
+ case 0:
+ day = 0;
+
+ case 1:
+ hour = 0;
+
+ case 2:
+ minute = 0;
+
+ default:
+ break;
+ }
+ if (day > 31) {
+ day = 31; // Wierd, can't have too many days in the month!
+ hour = 23;
+ minute = 59;
+ }
+
+ // We set up our alert_time so that it points into the same
+ // struct as time_now. We do this both so that we can get
+ // automatically filled in pieces of the struct (year, etc), and
+ // so that we have a more global struct to return the time in.
+ // We'll have to adjust a few things like month/year if the time
+ // is too far distant from our current time and crosses some
+ // boundary.
+ alert_time = *time_now;
+ alert_time.tm_sec = 0;
+
+ //fprintf(stderr,"alert_time: %d %d %d\n",
+ // alert_time.tm_mday,
+ // alert_time.tm_hour,
+ // alert_time.tm_min);
+
+ // Check to see how many parameters we parsed, and do our
+ // computations accordingly.
+ if (day) { // If we parsed out the day
+ // Check whether our new day is more than ten days +/- from
+ // the current day of the month. If so, assume it was from
+ // the month previous or after.
+ if (day < (time_now->tm_mday - 10)) {
+ // Day of month went down drastically. Must be a date
+ // in the next month. Bump up by one month and check
+ // whether we overflowed into the next year. Note that
+ // month ranges from 0 to 11.
+ if (++alert_time.tm_mon > 11) {
+ alert_time.tm_mon = 0;
+ alert_time.tm_year++;
+ }
+ }
+ else if (day > (time_now->tm_mday + 10)) {
+ // Day of month went up drastically. Must be a date
+ // during last month. Decrement by one month and check
+ // whether we need to also decrement the year.
+ if (--alert_time.tm_mon < 0) {
+ alert_time.tm_mon = 11;
+ alert_time.tm_year--;
+ }
+ }
+
+ // Fill in the struct with our new values that we parsed.
+ alert_time.tm_mday = day;
+ alert_time.tm_min = minute;
+ alert_time.tm_hour = hour;
+
+ // Need to do conversions from zulu time?
+ if ((char)tolower((int)tz[0]) == 'z') {
+ // Yep, do the conversions. Note that the zone variable
+ // already has the sign set correctly to get the correct
+ // time by using addition (PDT zone = -28800).
+
+ // Initialize daylight savings time to 0 in this
+ // instance, 'cuz we're starting with Zulu time and we
+ // want the localtime conversion to change it correctly.
+ // Zulu time has no daylight savings time offset.
+ //
+// WE7U:
+// No, it gave us an offset of 6 hours from UTC when we set this to
+// zero, 7 hours (correct) when we set it to one, during the summer.
+// Hopefully it will give us an 8-hour offset during the wintertime
+// but that remains to be seen...
+//
+// FYI: We're in daylight savings time during the summer, when
+// we're at a 7-hour offset. Winter is actual time and a -8 hour
+// offset.
+//
+// One on-line resource suggested setting it to -1 for automatic
+// determination of DST. This works too, during the summer. Again,
+// check during the wintertime too when we're at normal time.
+ //
+ alert_time.tm_isdst = -1;
+
+
+ // Do the hour offset
+ alert_time.tm_hour += zone/3600;
+
+ // Now check whether we have any offsets left to do.
+ zone %= 3600;
+ if (zone)
+ alert_time.tm_min += zone/60;
+
+ // Now check whether we have any overflows. According
+ // to the "mktime()" man page, we probably don't need to
+ // do this for overflow (It normalizes the time itself),
+ // but I think we still need to for underflow.
+//WE7U: Check this stuff carefully!
+ if (alert_time.tm_min > 59) {
+ alert_time.tm_hour++;
+ alert_time.tm_min -= 60;
+ }
+ if (alert_time.tm_hour > 23) {
+ alert_time.tm_mday++;
+ alert_time.tm_hour -= 24;
+ if (mktime(&alert_time) == -1) {
+ alert_time.tm_mday = 1;
+ alert_time.tm_mon++;
+ if (mktime(&alert_time) == -1) {
+ alert_time.tm_mon = 0;
+ alert_time.tm_year++;
+ }
+ }
+ }
+ else if (alert_time.tm_hour < 0) {
+ alert_time.tm_hour += 24;
+ if (--alert_time.tm_mday <= 0) {
+ if (--alert_time.tm_mon < 0) {
+ alert_time.tm_year--;
+ alert_time.tm_mon = 11;
+ alert_time.tm_mday = 31;
+ }
+ else if (alert_time.tm_mon == 3 || alert_time.tm_mon == 5 ||
+ alert_time.tm_mon == 8 || alert_time.tm_mon == 10) {
+ alert_time.tm_mday = 30;
+ }
+ else if (alert_time.tm_mon == 1) {
+ alert_time.tm_mday = (alert_time.tm_year%4 == 0) ? 29: 28;
+ }
+ else {
+ alert_time.tm_mday = 31;
+ }
+ }
+ }
+ }
+ }
+ else { // We didn't parse out the day from the input string.
+
+ // What's this all about??? Different format of APRS
+ // time/date string?
+ alert_time.tm_year--;
+ }
+
+ if ( debug_level & 2 ) {
+ time_t a_time,now_time,diff;
+
+ fprintf(stderr,"\n Input: %s\n",aprs_time);
+
+ fprintf(stderr,"Output: %02d%02d%02d\n\n",
+ alert_time.tm_mday,
+ alert_time.tm_hour,
+ alert_time.tm_min);
+
+ a_time = mktime(&alert_time);
+ fprintf(stderr,"Alert: %ld\n", (long)a_time);
+
+ now_time = sec_now();
+ fprintf(stderr," Now: %ld\n", (long)now_time);
+
+ diff = now_time - a_time;
+
+ if (diff >= 0)
+ fprintf(stderr,"Expired by %ld minutes\n", (long)(diff/60) );
+ else
+ fprintf(stderr,"%ld minutes until expiration\n", (long)((-diff)/60) );
+
+ if (alert_time.tm_isdst > 0)
+ fprintf(stderr,"Daylight savings time is in effect\n");
+ }
+
+ return(mktime(&alert_time));
+}
+
+
+
+
+
+// Note: last_speed should be in knots.
+//
+// Input format for lat/long is DDMM.MM or DDMM.MMM format, like:
+// 4722.93N 12244.17W or
+// 4722.938N 12244.177W
+//
+char *compress_posit(const char *input_lat, const char group, const char *input_lon, const char symbol,
+ const unsigned int last_course, const unsigned int last_speed, const char *phg) {
+ static char pos[100];
+ char lat[5], lon[5];
+ char c, s, t, ext;
+ int temp, deg;
+ double minutes;
+ char temp_str[20];
+
+
+//fprintf(stderr,"lat:%s, long:%s, symbol:%c%c, course:%d, speed:%d, phg:%s\n",
+// input_lat,
+// input_lon,
+// group,
+// symbol,
+// last_course,
+// last_speed,
+// phg);
+
+ // Fetch degrees (first two chars)
+ temp_str[0] = input_lat[0];
+ temp_str[1] = input_lat[1];
+ temp_str[2] = '\0';
+ deg = atoi(temp_str);
+
+ // Fetch minutes (rest of numbers)
+ xastir_snprintf(temp_str,
+ sizeof(temp_str),
+ "%s",
+ input_lat);
+ temp_str[0] = ' '; // Blank out degrees
+ temp_str[1] = ' '; // Blank out degrees
+ minutes = atof(temp_str);
+
+ // Check for North latitude
+ if (strstr(input_lat, "N") || strstr(input_lat, "n"))
+ ext = 'N';
+ else
+ ext = 'S';
+
+//fprintf(stderr,"ext:%c\n", ext);
+
+ temp = 380926 * (90 - (deg + minutes / 60.0) * ( ext=='N' ? 1 : -1 ));
+
+//fprintf(stderr,"temp: %d\t",temp);
+
+ lat[3] = (char)(temp%91 + 33); temp /= 91;
+ lat[2] = (char)(temp%91 + 33); temp /= 91;
+ lat[1] = (char)(temp%91 + 33); temp /= 91;
+ lat[0] = (char)(temp + 33);
+ lat[4] = '\0';
+
+//fprintf(stderr,"%s\n",lat);
+
+ // Fetch degrees (first three chars)
+ temp_str[0] = input_lon[0];
+ temp_str[1] = input_lon[1];
+ temp_str[2] = input_lon[2];
+ temp_str[3] = '\0';
+ deg = atoi(temp_str);
+
+ // Fetch minutes (rest of numbers)
+ xastir_snprintf(temp_str,
+ sizeof(temp_str),
+ "%s",
+ input_lon);
+ temp_str[0] = ' '; // Blank out degrees
+ temp_str[1] = ' '; // Blank out degrees
+ temp_str[2] = ' '; // Blank out degrees
+ minutes = atof(temp_str);
+
+ // Check for West longitude
+ if (strstr(input_lon, "W") || strstr(input_lon, "w"))
+ ext = 'W';
+ else
+ ext = 'E';
+
+//fprintf(stderr,"ext:%c\n", ext);
+
+ temp = 190463 * (180 + (deg + minutes / 60.0) * ( ext=='W' ? -1 : 1 ));
+
+//fprintf(stderr,"temp: %d\t",temp);
+
+ lon[3] = (char)(temp%91 + 33); temp /= 91;
+ lon[2] = (char)(temp%91 + 33); temp /= 91;
+ lon[1] = (char)(temp%91 + 33); temp /= 91;
+ lon[0] = (char)(temp + 33);
+ lon[4] = '\0';
+
+//fprintf(stderr,"%s\n",lon);
+
+ // Set up csT bytes for course/speed if either are non-zero
+ c = s = t = ' ';
+ if (last_course > 0 || last_speed > 0) {
+
+ if (last_course >= 360)
+ c = '!'; // 360 would be past 'z'. Set it to zero.
+ else
+ c = (char)(last_course/4 + 33);
+
+ s = (char)(log(last_speed + 1.0) / log(1.08) + 33.5); // Poor man's rounding + ASCII
+ t = 'C';
+ }
+ // Else set up csT bytes for PHG if within parameters
+ else if (strlen(phg) >= 6) {
+ double power, height, gain, range, s_temp;
+
+
+ c = '{';
+
+ if ( (phg[3] < '0') || (phg[3] > '9') ) { // Power is out of limits
+ power = 0.0;
+ }
+ else {
+ power = (double)((int)(phg[3]-'0'));
+ power = power * power; // Lowest possible value is 0.0
+ }
+
+ if (phg[4] < '0') // Height is out of limits (no upper limit according to the spec)
+ height = 10.0;
+ else
+ height= 10.0 * pow(2.0,(double)phg[4] - (double)'0'); // Lowest possible value is 10.0
+
+ if ( (phg[5] < '0') || (phg[5] > '9') ) // Gain is out of limits
+ gain = 1.0;
+ else
+ gain = pow(10.0,((double)(phg[5]-'0') / 10.0)); // Lowest possible value is 1.0
+
+ range = sqrt(2.0 * height * sqrt((power / 10.0) * (gain / 2.0))); // Lowest possible value is 0.0
+
+ // Check for range of 0, and skip log10 if so
+ if (range != 0.0)
+ s_temp = log10(range/2) / log10(1.08) + 33.0;
+ else
+ s_temp = 0.0 + 33.0;
+
+ s = (char)(s_temp + 0.5); // Cheater's way of rounding, add 0.5 and truncate
+
+ t = 'C';
+ }
+ // Note that we can end up with three spaces at the end if no
+ // course/speed/phg were supplied. Do not knock this down, as
+ // the compressed posit has a fixed 13-character length
+ // according to the spec!
+ //
+ xastir_snprintf(pos,
+ sizeof(pos),
+ "%c%s%s%c%c%c%c",
+ group,
+ lat,
+ lon,
+ symbol,
+ c,
+ s,
+ t);
+
+//fprintf(stderr,"New compressed pos: (%s)\n",pos);
+ return pos;
+}
+
+
+
+
+
+/*
+ * See if position is defined
+ * 90�N 180�W (0,0 in internal coordinates) is our undefined position
+ * 0N/0E is excluded from trails, could be excluded from map (#define ACCEPT_0N_0E)
+ */
+
+int position_defined(long lat, long lon, int strict) {
+
+ if (lat == 0l && lon == 0l)
+ return(0); // undefined location
+#ifndef ACCEPT_0N_0E
+ if (strict)
+#endif // ACCEPT_0N_0E
+ if (lat == 90*60*60*100l && lon == 180*60*60*100l) // 0N/0E
+ return(0); // undefined location
+ return(1);
+}
+
+
+
+
+
+// Function to convert from screen (pixel) coordinates to the Xastir
+// coordinate system.
+//
+void convert_screen_to_xastir_coordinates(int x,
+ int y,
+ long *lat,
+ long *lon) {
+
+ *lon = (center_longitude - ((screen_width * scale_x)/2) + (x * scale_x));
+ *lat = (center_latitude - ((screen_height * scale_y)/2) + (y * scale_y));
+
+ if (*lon < 0)
+ *lon = 0l; // 180�W
+
+ if (*lon > 129600000l)
+ *lon = 129600000l; // 180�E
+
+ if (*lat < 0)
+ *lat = 0l; // 90�N
+
+ if (*lat > 64800000l)
+ *lat = 64800000l; // 90�S
+}
+
+
+
+
+
+// Convert Xastir lat/lon to UTM printable string
+void convert_xastir_to_UTM_str(char *str, int str_len, long x, long y) {
+ double utmNorthing;
+ double utmEasting;
+ char utmZone[10];
+
+ ll_to_utm_ups(E_WGS_84,
+ (double)(-((y - 32400000l )/360000.0)),
+ (double)((x - 64800000l )/360000.0),
+ &utmNorthing,
+ &utmEasting,
+ utmZone,
+ sizeof(utmZone) );
+ utmZone[9] = '\0';
+ //fprintf(stderr,"%s %07.0f %07.0f\n", utmZone, utmEasting,
+ //utmNorthing );
+ xastir_snprintf(str,
+ str_len,
+ "%s %07.0f %07.0f",
+ utmZone,
+ utmEasting,
+ utmNorthing);
+}
+
+
+
+
+// To produce MGRS coordinates, we'll call ll_to_utm_ups()
+// [?? Earlier text: "the above function" ??]
+// then convert the result to the 2-letter digraph format used
+// for MGRS. The ll_to_utm_ups() function switches to the special
+// irregular UTM zones for the areas near Svalbard and SW Norway
+// if the "coordinate_system" variable is set to "USE_MGRS",
+// so we'll be using the correct zone boundaries for MGRS if that
+// variable is set when we make the call.
+//
+// If "nice_format" == 1, we add leading spaces plus spaces between
+// the easting and northing in order to line up more nicely with the
+// UTM output format.
+//
+// convert_xastir_to_MGRS_str is a wrapper around the components
+// function below that returns the MGRS coordinate of x and y as a
+// single MGRS string.
+//
+/* convert_xastir_to_MGRS_str_components returns each of the components
+ of the MGRS string separately.
+ Example MGRS string: 18T VK 66790 55998
+ Parameters:
+ utmZone Returns the UTM zone: e.g. 18T
+ utmZone_len length of the utmZone char[]
+ EastingL Returns the first letter of the MGRS digraph: e.g. V
+ EastingL_len length of the EastingL char[]
+ NorthingL Returns the second letter of the MGRS digraph: e.g. K
+ NorthingL_len length of the NorthingL char[]
+ int_utmEasting returns the MGRS easting: e.g. 66790
+ int_utmNorthing returns the MGRS northing: e.g. 55998
+ x xastir x coordinate to obtain MGRS coordinate for.
+ y xastir x coordinate to obtain MGRS coordinate for.
+ nice_format 1 for populate space_string with three spaces
+ 0 to make space_string and empty string, see above.
+ space_string Returned string that can be used to make MGRS strings
+ allign more cleanly with UTM strings.
+ space_string_len length of the space_string char[]
+*/
+void convert_xastir_to_MGRS_str_components(char *utmZone, int utmZone_len,
+ char *EastingL, int EastingL_len,
+ char *NorthingL, int NorthingL_len,
+ unsigned int *int_utmEasting, unsigned int *int_utmNorthing,
+ long x, long y,
+ int nice_format, char *space_string, int space_string_len) {
+
+ double utmNorthing;
+ double utmEasting;
+ //char utmZone[10];
+ int start;
+ int my_east, my_north;
+ //unsigned int int_utmEasting, int_utmNorthing;
+ int UPS = 0;
+ int North_UPS = 0;
+ int coordinate_system_save = coordinate_system;
+ //char space_string[4] = " "; // Three spaces
+
+ // Set for correct zones
+ coordinate_system = USE_MGRS;
+
+ ll_to_utm_ups(E_WGS_84,
+ (double)(-((y - 32400000l )/360000.0)),
+ (double)((x - 64800000l )/360000.0),
+ &utmNorthing,
+ &utmEasting,
+ utmZone,
+ sizeof(utmZone) );
+ utmZone[9] = '\0';
+
+ // Restore it
+ coordinate_system = coordinate_system_save;
+
+
+ //fprintf(stderr,"%s %07.0f %07.0f\n", utmZone, utmEasting,
+ //utmNorthing );
+ //xastir_snprintf(str, str_len, "%s %07.0f %07.0f",
+ // utmZone, utmEasting, utmNorthing );
+
+
+ // Convert the northing and easting values to the digraph letter
+ // format. Letters 'I' and 'O' are skipped for both eastings
+ // and northings. Letters 'W' through 'Z' are skipped for
+ // northings.
+ //
+ // N/S letters alternate in a cycle of two. Begins at the
+ // equator with A and F in alternate zones. Odd-numbered zones
+ // use A-V, even-numbered zones use F-V, then A-V.
+ //
+ // E/W letters alternate in a cycle of three. Each E/W zone
+ // uses an 8-letter block. Starts at A-H, then J-R, then S-Z,
+ // then repeats every 18 degrees.
+ //
+ // N/S letters have a cycle of two, E/W letters have a cycle of
+ // three. The same lettering repeats after six zones (2,000,000
+ // meter intervals).
+ //
+ // AA is at equator and 180W.
+
+ // Easting: Each zone covers 6 degrees. Zone 1 = A-H, Zone 2 =
+ // J-R, Zone 3 = S-Z, then repeat. So, take zone number-1,
+ // modulus 3, multiple that number by 8. Modulus 24. That's
+ // our starting letter for the zone. Take the easting number,
+ // divide by 100,000, , add the starting number, compute modulus
+ // 24, then use that index into our E_W array.
+ //
+ // Northing: Figure out whether even/odd zone number. Divide
+ // by 100,000. If even, add 5 (starts at 'F' if even). Compute
+ // modulus 20, then use that index into our N_S array.
+
+
+ *int_utmEasting = (unsigned int)utmEasting;
+ *int_utmNorthing = (unsigned int)utmNorthing;
+ *int_utmEasting = *int_utmEasting % 100000;
+ *int_utmNorthing = *int_utmNorthing % 100000;
+
+
+ // Check for South Polar UPS area, set flags if found.
+ if ( utmZone[0] == 'A'
+ || utmZone[0] == 'B'
+ || utmZone[1] == 'A'
+ || utmZone[1] == 'B'
+ || utmZone[2] == 'A'
+ || utmZone[2] == 'B' ) {
+ // We're in the South Polar UPS area
+ UPS++;
+ }
+ // Check for North Polar UPS area, set flags if found.
+ else if ( utmZone[0] == 'Y'
+ || utmZone[0] == 'Z'
+ || utmZone[1] == 'Y'
+ || utmZone[1] == 'Z'
+ || utmZone[2] == 'Y'
+ || utmZone[2] == 'Z') {
+ // We're in the North Polar UPS area
+ UPS++;
+ North_UPS++;
+ }
+ else {
+ // We're in the UTM area. Set no flags.
+ }
+
+
+ if (UPS) { // Special processing for UPS area (A/B/Y/Z bands)
+
+ // Note: Zone number isn't used for UPS, but zone letter is.
+ if (nice_format) { // Add two leading spaces
+ utmZone[2] = utmZone[0];
+ utmZone[0] = ' ';
+ utmZone[1] = ' ';
+ utmZone[3] = '\0';
+ }
+ else {
+ space_string[0] = '\0';
+ }
+
+ if (North_UPS) { // North polar UPS zone
+ char UPS_N_Easting[15] = "RSTUXYZABCFGHJ";
+ char UPS_N_Northing[15] = "ABCDEFGHJKLMNP";
+
+ // Calculate the index into the 2-letter digraph arrays.
+ my_east = (int)(utmEasting / 100000.0);
+ my_east = my_east - 13;
+ my_north = (int)(utmNorthing / 100000.0);
+ my_north = my_north - 13;
+
+ /*xastir_snprintf(str,
+ str_len,
+ "%s %c%c %05d %s%05d",
+ utmZone,
+ UPS_N_Easting[my_east],
+ UPS_N_Northing[my_north],
+ int_utmEasting,
+ space_string,
+ int_utmNorthing ); */
+ xastir_snprintf(EastingL,EastingL_len,
+ "%c", UPS_N_Easting[my_east]);
+ xastir_snprintf(NorthingL,NorthingL_len,
+ "%c", UPS_N_Northing[my_north]);
+ }
+ else { // South polar UPS zone
+ char UPS_S_Easting[25] = "JKLPQRSTUXYZABCFGHJKLPQR";
+ char UPS_S_Northing[25] = "ABCDEFGHJKLMNPQRSTUVWXYZ";
+
+ // Calculate the index into the 2-letter digraph arrays.
+ my_east = (int)(utmEasting / 100000.0);
+ my_east = my_east - 8;
+ my_north = (int)(utmNorthing / 100000.0);
+ my_north = my_north - 8;
+
+ /* xastir_snprintf(str,
+ str_len,
+ "%s %c%c %05d %s%05d",
+ utmZone,
+ UPS_S_Easting[my_east],
+ UPS_S_Northing[my_north],
+ int_utmEasting,
+ space_string,
+ int_utmNorthing ); */
+ xastir_snprintf(EastingL,EastingL_len,
+ "%c", UPS_S_Easting[my_east]);
+ xastir_snprintf(NorthingL,NorthingL_len,
+ "%c", UPS_S_Northing[my_north]);
+ }
+ }
+ else { // UTM Area
+ char E_W[25] = "ABCDEFGHJKLMNPQRSTUVWXYZ";
+ char N_S[21] = "ABCDEFGHJKLMNPQRSTUV";
+
+
+ if (!nice_format) {
+ space_string[0] = '\0';
+ }
+
+
+ // Calculate the indexes into the 2-letter digraph arrays.
+ start = atoi(utmZone);
+ start--;
+ start = start % 3;
+ start = start * 8;
+ start = start % 24;
+ // "start" is now an index into the starting letter for the
+ // zone.
+
+
+ my_east = (int)(utmEasting / 100000.0) - 1;
+ my_east = my_east + start;
+ my_east = my_east % 24;
+// fprintf(stderr, "Start: %c East (guess): %c ",
+// E_W[start],
+// E_W[my_east]);
+
+
+ start = atoi(utmZone);
+ start = start % 2;
+ if (start) { // Odd-numbered zone
+ start = 0;
+ }
+ else { // Even-numbered zone
+ start = 5;
+ }
+ my_north = (int)(utmNorthing / 100000.0);
+ my_north = my_north + start;
+ my_north = my_north % 20;
+// fprintf(stderr, "Start: %c North (guess): %c\n",
+// N_S[start],
+// N_S[my_north]);
+
+ /* xastir_snprintf(str,
+ str_len,
+ "%s %c%c %05d %s%05d",
+ utmZone,
+ E_W[my_east],
+ N_S[my_north],
+ int_utmEasting,
+ space_string,
+ int_utmNorthing ); */
+ xastir_snprintf(EastingL, EastingL_len,
+ "%c", E_W[my_east]);
+ xastir_snprintf(NorthingL, NorthingL_len,
+ "%c", N_S[my_north]);
+ }
+}
+
+
+
+
+
+/* Wrapper around convert_xastir_to_MGRS_str_components
+ to return an MGRS coordinate as a single string.
+ Parameters:
+ str The character array to be populated with the MGRS string.
+ str_len Length of str.
+ x xastir x coordinate.
+ y xastir y coordinate.
+ If "nice_format" == 1, we add leading spaces plus spaces between
+ the easting and northing in order to line up more nicely with the
+ UTM output format.
+*/
+void convert_xastir_to_MGRS_str(char *str, int str_len, long x, long y, int nice_format) {
+ char space_string[4] = " "; // Three spaces
+ unsigned int intEasting = 0;
+ unsigned int intNorthing = 0;
+ char EastingL[3] = " ";
+ char NorthingL[3] = " ";
+ char utmZone[10];
+ convert_xastir_to_MGRS_str_components(utmZone, strlen(utmZone),
+ EastingL, sizeof(EastingL),
+ NorthingL, sizeof(NorthingL),
+ &intEasting, &intNorthing,
+ x, y,
+ nice_format, space_string, strlen(space_string)) ;
+ xastir_snprintf(str,
+ str_len,
+ "%s %c%c %05d %s%05d",
+ utmZone,
+ EastingL[0],
+ NorthingL[0],
+ intEasting,
+ space_string,
+ intNorthing );
+}
+
+
+
+
+
+// Convert Xastir lat/lon to UTM
+void convert_xastir_to_UTM(double *easting, double *northing, char *zone, int zone_len, long x, long y) {
+
+ ll_to_utm_ups(E_WGS_84,
+ (double)(-((y - 32400000l )/360000.0)),
+ (double)((x - 64800000l )/360000.0),
+ northing,
+ easting,
+ zone,
+ zone_len);
+ zone[zone_len-1] = '\0';
+}
+
+
+
+
+
+// Convert UTM to Xastir lat/lon
+void convert_UTM_to_xastir(double easting, double northing, char *zone, long *x, long *y) {
+ double lat, lon;
+
+ utm_ups_to_ll(E_WGS_84,
+ northing,
+ easting,
+ zone,
+ &lat,
+ &lon);
+
+ // Reverse latitude to fit our coordinate system then convert to
+ // Xastir units.
+ *y = (long)(lat * -360000.0) + 32400000l;
+
+ // Convert longitude to xastir units
+ *x = (long)(lon * 360000.0) + 64800000l;
+}
+
+
+
+
+// convert latitude from long to string
+// Input is in Xastir coordinate system
+//
+// CONVERT_LP_NOSP = DDMM.MMN
+// CONVERT_HP_NOSP = DDMM.MMMN
+// CONVERT_VHP_NOSP = DDMM.MMMMN
+// CONVERT_LP_NORMAL = DD MM.MMN
+// CONVERT_HP_NORMAL = DD MM.MMMN
+// CONVERT_UP_TRK = NDD MM.MMMM
+// CONVERT_DEC_DEG = DD.DDDDDN
+// CONVERT_DMS_NORMAL = DD MM SS.SN
+// CONVERT_DMS_NORMAL_FORMATED = DD'MM'SS.SN
+// CONVERT_HP_NORMAL_FORMATED = DD'MM.MMMMN
+//
+void convert_lat_l2s(long lat, char *str, int str_len, int type) {
+ char ns;
+ float deg, min, sec;
+ int ideg, imin;
+ long temp;
+
+
+ str[0] = '\0';
+ deg = (float)(lat - 32400000l) / 360000.0;
+
+ // Switch to integer arithmetic to avoid floating-point
+ // rounding errors.
+ temp = (long)(deg * 100000);
+
+ ns = 'S';
+ if (temp <= 0) {
+ ns = 'N';
+ temp = labs(temp);
+ }
+
+ ideg = (int)temp / 100000;
+ min = (temp % 100000) * 60.0 / 100000.0;
+
+ // Again switch to integer arithmetic to avoid floating-point
+ // rounding errors.
+ temp = (long)(min * 1000);
+ imin = (int)(temp / 1000);
+ sec = (temp % 1000) * 60.0 / 1000.0;
+
+ switch (type) {
+
+ case(CONVERT_LP_NOSP): /* do low P w/no space */
+ xastir_snprintf(str,
+ str_len,
+ "%02d%05.2f%c",
+ ideg,
+// min+0.001, // Correct possible unbiased rounding
+ min,
+ ns);
+ break;
+
+ case(CONVERT_LP_NORMAL): /* do low P normal */
+ xastir_snprintf(str,
+ str_len,
+ "%02d %05.2f%c",
+ ideg,
+// min+0.001, // Correct possible unbiased rounding
+ min,
+ ns);
+ break;
+
+ case(CONVERT_HP_NOSP): /* do HP w/no space */
+ xastir_snprintf(str,
+ str_len,
+ "%02d%06.3f%c",
+ ideg,
+// min+0.0001, // Correct possible unbiased rounding
+ min,
+ ns);
+ break;
+
+ case(CONVERT_VHP_NOSP): /* do Very HP w/no space */
+ xastir_snprintf(str,
+ str_len,
+ "%02d%07.4f%c",
+ ideg,
+// min+0.00001, // Correct possible unbiased rounding
+ min,
+ ns);
+ break;
+
+ case(CONVERT_UP_TRK): /* for tracklog files */
+ xastir_snprintf(str,
+ str_len,
+ "%c%02d %07.4f",
+ ns,
+ ideg,
+// min+0.00001); // Correct possible unbiased rounding
+ min);
+ break;
+
+ case(CONVERT_DEC_DEG):
+ xastir_snprintf(str,
+ str_len,
+ "%08.5f%c",
+// (ideg+min/60.0)+0.000001, // Correct possible unbiased rounding
+ ideg+min/60.0,
+ ns);
+ break;
+
+ case(CONVERT_DMS_NORMAL):
+ xastir_snprintf(str,
+ str_len,
+ "%02d %02d %04.1f%c",
+ ideg,
+ imin,
+// sec+0.01, // Correct possible unbiased rounding
+ sec,
+ ns);
+ break;
+
+ case(CONVERT_DMS_NORMAL_FORMATED):
+ xastir_snprintf(str,
+ str_len,
+ "%02d�%02d\'%04.1f%c",
+ ideg,
+ imin,
+// sec+0.01, // Correct possible unbiased rounding
+ sec,
+ ns);
+ break;
+
+ case(CONVERT_HP_NORMAL_FORMATED):
+ xastir_snprintf(str,
+ str_len,
+ "%02d�%06.3f%c",
+ ideg,
+// min+0.0001, // Correct possible unbiased roundin
+ min,
+ ns);
+ break;
+
+ case(CONVERT_HP_NORMAL):
+ default: /* do HP normal */
+ xastir_snprintf(str,
+ str_len,
+ "%02d %06.3f%c",
+ ideg,
+// min+0.0001, // Correct possible unbiased rounding
+ min,
+ ns);
+ break;
+ }
+}
+
+
+
+
+
+// convert longitude from long to string
+// Input is in Xastir coordinate system
+//
+// CONVERT_LP_NOSP = DDDMM.MME
+// CONVERT_HP_NOSP = DDDMM.MMME
+// CONVERT_VHP_NOSP = DDDMM.MMMME
+// CONVERT_LP_NORMAL = DDD MM.MME
+// CONVERT_HP_NORMAL = DDD MM.MMME
+// CONVERT_UP_TRK = EDDD MM.MMMM
+// CONVERT_DEC_DEG = DDD.DDDDDE
+// CONVERT_DMS_NORMAL = DDD MM SS.SN
+// CONVERT_DMS_NORMAL_FORMATED = DDD'MM'SS.SN
+//
+void convert_lon_l2s(long lon, char *str, int str_len, int type) {
+ char ew;
+ float deg, min, sec;
+ int ideg, imin;
+ long temp;
+
+ str[0] = '\0';
+ deg = (float)(lon - 64800000l) / 360000.0;
+
+ // Switch to integer arithmetic to avoid floating-point rounding
+ // errors.
+ temp = (long)(deg * 100000);
+
+ ew = 'E';
+ if (temp <= 0) {
+ ew = 'W';
+ temp = labs(temp);
+ }
+
+ ideg = (int)temp / 100000;
+ min = (temp % 100000) * 60.0 / 100000.0;
+
+ // Again switch to integer arithmetic to avoid floating-point
+ // rounding errors.
+ temp = (long)(min * 1000);
+ imin = (int)(temp / 1000);
+ sec = (temp % 1000) * 60.0 / 1000.0;
+
+ switch(type) {
+
+ case(CONVERT_LP_NOSP): /* do low P w/nospacel */
+ xastir_snprintf(str,
+ str_len,
+ "%03d%05.2f%c",
+ ideg,
+// min+0.001, // Correct possible unbiased rounding
+ min,
+ ew);
+ break;
+
+ case(CONVERT_LP_NORMAL): /* do low P normal */
+ xastir_snprintf(str,
+ str_len,
+ "%03d %05.2f%c",
+ ideg,
+// min+0.001, // Correct possible unbiased rounding
+ min,
+ ew);
+ break;
+
+ case(CONVERT_HP_NOSP): /* do HP w/nospace */
+ xastir_snprintf(str,
+ str_len,
+ "%03d%06.3f%c",
+ ideg,
+// min+0.0001, // Correct possible unbiased rounding
+ min,
+ ew);
+ break;
+
+ case(CONVERT_VHP_NOSP): /* do Very HP w/nospace */
+ xastir_snprintf(str,
+ str_len,
+ "%03d%07.4f%c",
+ ideg,
+// min+0.00001, // Correct possible unbiased rounding
+ min,
+ ew);
+ break;
+
+ case(CONVERT_UP_TRK): /* for tracklog files */
+ xastir_snprintf(str,
+ str_len,
+ "%c%03d %07.4f",
+ ew,
+ ideg,
+// min+0.00001); // Correct possible unbiased rounding
+ min);
+ break;
+
+ case(CONVERT_DEC_DEG):
+ xastir_snprintf(str,
+ str_len,
+ "%09.5f%c",
+// (ideg+min/60.0)+0.000001, // Correct possible unbiased rounding
+ ideg+min/60.0,
+ ew);
+ break;
+
+ case(CONVERT_DMS_NORMAL):
+ xastir_snprintf(str,
+ str_len,
+ "%03d %02d %04.1f%c",
+ ideg,
+ imin,
+// sec+0.01, // Correct possible unbiased rounding
+ sec,
+ ew);
+ break;
+
+ case(CONVERT_DMS_NORMAL_FORMATED):
+ xastir_snprintf(str,
+ str_len,
+ "%03d�%02d\'%04.1f%c",
+ ideg,
+ imin,
+// sec+0.01, // Correct possible unbiased rounding
+ sec,
+ ew);
+ break;
+
+ case(CONVERT_HP_NORMAL_FORMATED):
+ xastir_snprintf(str,
+ str_len,
+ "%03d�%06.3f%c",
+ ideg,
+// min+0.0001, // Correct possible unbiased rounding
+ min,
+ ew);
+ break;
+
+ case(CONVERT_HP_NORMAL):
+ default: /* do HP normal */
+ xastir_snprintf(str,
+ str_len,
+ "%03d %06.3f%c",
+ ideg,
+// min+0.0001, // Correct possible unbiased rounding
+ min,
+ ew);
+ break;
+ }
+}
+
+
+
+
+
+/* convert latitude from string to long with 1/100 sec resolution */
+//
+// Input is in [D]DMM.MM[MM]N format (degrees/decimal
+// minutes/direction)
+//
+long convert_lat_s2l(char *lat) { /* N=0�, Ctr=90�, S=180� */
+ long centi_sec;
+ char copy[15];
+ char n[15];
+ char *p;
+ char offset;
+
+
+ // Find the decimal point if present
+ p = strstr(lat, ".");
+
+ if (p == NULL) // No decimal point found
+ return(0l);
+
+ memset(copy, '\0', sizeof(copy));
+ offset = p - lat; // Arithmetic on pointers
+ switch (offset) {
+ case 0: // .MM[MM]N
+ return(0l); // Bad, no degrees or minutes
+ break;
+ case 1: // M.MM[MM]N
+ return(0l); // Bad, no degrees
+ break;
+ case 2: // MM.MM[MM]N
+ return(0l); // Bad, no degrees
+ break;
+ case 3: // DMM.MM[MM]N
+ xastir_snprintf(copy,
+ sizeof(copy),
+ "0%s", // Add a leading '0'
+ lat);
+ break;
+ case 4: // DDMM.MM[MM]N
+ xastir_snprintf(copy,
+ sizeof(copy),
+ "%s", // Copy verbatim
+ lat);
+ break;
+ default:
+ break;
+ }
+
+ copy[14] = '\0';
+ centi_sec=0l;
+ if (copy[4]=='.'
+ && ( (char)toupper((int)copy[ 5])=='N'
+ || (char)toupper((int)copy[ 6])=='N'
+ || (char)toupper((int)copy[ 7])=='N'
+ || (char)toupper((int)copy[ 8])=='N'
+ || (char)toupper((int)copy[ 9])=='N'
+ || (char)toupper((int)copy[10])=='N'
+ || (char)toupper((int)copy[11])=='N'
+ || (char)toupper((int)copy[ 5])=='S'
+ || (char)toupper((int)copy[ 6])=='S'
+ || (char)toupper((int)copy[ 7])=='S'
+ || (char)toupper((int)copy[ 8])=='S'
+ || (char)toupper((int)copy[ 9])=='S'
+ || (char)toupper((int)copy[10])=='S'
+ || (char)toupper((int)copy[11])=='S')) {
+
+ substr(n, copy, 2); // degrees
+ centi_sec=atoi(n)*60*60*100;
+
+ substr(n, copy+2, 2); // minutes
+ centi_sec += atoi(n)*60*100;
+
+ substr(n, copy+5, 4); // fractional minutes
+ // Keep the fourth digit if present, as it resolves to 0.6
+ // of a 1/100 sec resolution. Two counts make one count in
+ // the Xastir coordinate system.
+
+ // Extend the digits to full precision by adding zeroes on
+ // the end.
+ strncat(n, "0000", sizeof(n) - 1 - strlen(n));
+
+ // Get rid of the N/S character
+ if (!isdigit((int)n[2]))
+ n[2] = '0';
+ if (!isdigit((int)n[3]))
+ n[3] = '0';
+
+ // Terminate substring at the correct digit
+ n[4] = '\0';
+//fprintf(stderr,"Lat: %s\n", n);
+
+ // Add 0.5 (Poor man's rounding)
+ centi_sec += (long)((atoi(n) * 0.6) + 0.5);
+
+ if ( (char)toupper((int)copy[ 5])=='N'
+ || (char)toupper((int)copy[ 6])=='N'
+ || (char)toupper((int)copy[ 7])=='N'
+ || (char)toupper((int)copy[ 8])=='N'
+ || (char)toupper((int)copy[ 9])=='N'
+ || (char)toupper((int)copy[10])=='N'
+ || (char)toupper((int)copy[11])=='N') {
+ centi_sec = -centi_sec;
+ }
+
+ centi_sec += 90*60*60*100;
+ }
+ return(centi_sec);
+}
+
+
+
+
+
+/* convert longitude from string to long with 1/100 sec resolution */
+//
+// Input is in [DD]DMM.MM[MM]W format (degrees/decimal
+// minutes/direction).
+//
+long convert_lon_s2l(char *lon) { /* W=0�, Ctr=180�, E=360� */
+ long centi_sec;
+ char copy[16];
+ char n[16];
+ char *p;
+ char offset;
+
+
+ // Find the decimal point if present
+ p = strstr(lon, ".");
+
+ if (p == NULL) // No decimal point found
+ return(0l);
+
+ memset(copy, '\0', sizeof(copy));
+ offset = p - lon; // Arithmetic on pointers
+ switch (offset) {
+ case 0: // .MM[MM]N
+ return(0l); // Bad, no degrees or minutes
+ break;
+ case 1: // M.MM[MM]N
+ return(0l); // Bad, no degrees
+ break;
+ case 2: // MM.MM[MM]N
+ return(0l); // Bad, no degrees
+ break;
+ case 3: // DMM.MM[MM]N
+ xastir_snprintf(copy,
+ sizeof(copy),
+ "00%s", // Add two leading zeroes
+ lon);
+ break;
+ case 4: // DDMM.MM[MM]N
+ xastir_snprintf(copy,
+ sizeof(copy),
+ "0%s", // Add leading '0'
+ lon);
+ break;
+ case 5: // DDDMM.MM[MM]N
+ xastir_snprintf(copy,
+ sizeof(copy),
+ "%s", // Copy verbatim
+ lon);
+ break;
+ default:
+ break;
+ }
+
+ copy[15] = '\0';
+ centi_sec=0l;
+ if (copy[5]=='.'
+ && ( (char)toupper((int)copy[ 6])=='W'
+ || (char)toupper((int)copy[ 7])=='W'
+ || (char)toupper((int)copy[ 8])=='W'
+ || (char)toupper((int)copy[ 9])=='W'
+ || (char)toupper((int)copy[10])=='W'
+ || (char)toupper((int)copy[11])=='W'
+ || (char)toupper((int)copy[12])=='W'
+ || (char)toupper((int)copy[ 6])=='E'
+ || (char)toupper((int)copy[ 7])=='E'
+ || (char)toupper((int)copy[ 8])=='E'
+ || (char)toupper((int)copy[ 9])=='E'
+ || (char)toupper((int)copy[10])=='E'
+ || (char)toupper((int)copy[11])=='E'
+ || (char)toupper((int)copy[12])=='E')) {
+
+ substr(n,copy,3); // degrees 013
+ centi_sec=atoi(n)*60*60*100;
+
+ substr(n,copy+3,2); // minutes 26
+ centi_sec += atoi(n)*60*100;
+ // 01326.66E 01326.660E
+
+ substr(n,copy+6,4); // fractional minutes 66E 660E or 6601
+ // Keep the fourth digit if present, as it resolves to 0.6
+ // of a 1/100 sec resolution. Two counts make one count in
+ // the Xastir coordinate system.
+
+ // Extend the digits to full precision by adding zeroes on
+ // the end.
+ strncat(n, "0000", sizeof(n) - 1 - strlen(n));
+
+ // Get rid of the E/W character
+ if (!isdigit((int)n[2]))
+ n[2] = '0';
+ if (!isdigit((int)n[3]))
+ n[3] = '0';
+
+ n[4] = '\0'; // Make sure substring is terminated
+//fprintf(stderr,"Lon: %s\n", n);
+
+ // Add 0.5 (Poor man's rounding)
+ centi_sec += (long)((atoi(n) * 0.6) + 0.5);
+
+ if ( (char)toupper((int)copy[ 6])=='W'
+ || (char)toupper((int)copy[ 7])=='W'
+ || (char)toupper((int)copy[ 8])=='W'
+ || (char)toupper((int)copy[ 9])=='W'
+ || (char)toupper((int)copy[10])=='W'
+ || (char)toupper((int)copy[11])=='W'
+ || (char)toupper((int)copy[12])=='W') {
+ centi_sec = -centi_sec;
+ }
+
+ centi_sec +=180*60*60*100;;
+ }
+ return(centi_sec);
+}
+
+
+
+
+
+/*
+ * Convert latitude from Xastir format to radian
+ */
+double convert_lat_l2r(long lat) {
+ double ret;
+ double degrees;
+
+ degrees = (double)(lat / (100.0*60.0*60.0)) -90.0;
+ ret = (-1)*degrees*(M_PI/180.0);
+ return(ret);
+}
+
+
+
+
+
+/*
+ * Convert longitude from Xastir format to radian
+ */
+double convert_lon_l2r(long lon) {
+ double ret;
+ double degrees;
+
+ degrees = (double)(lon / (100.0*60.0*60.0)) -180.0;
+ ret = (-1)*degrees*(M_PI/180.0);
+ return(ret);
+}
+
+
+
+
+
+// Distance calculation (Great Circle) using the Haversine formula
+// (2-parameter arctan version), which gives better accuracy than
+// the "Law of Cosines" for short distances. It should be
+// equivalent to the "Law of Cosines for Spherical Trigonometry" for
+// longer distances. Haversine is a great-circle calculation.
+//
+//
+// Inputs: lat1/long1/lat2/long2 in radians (double)
+//
+// Outputs: Distance in meters between them (double)
+//
+double calc_distance_haversine_radian(double lat1, double lon1, double lat2, double lon2) {
+ double dlon, dlat;
+ double a, c, d;
+ double R = EARTH_RADIUS_METERS;
+ #define square(x) (x)*(x)
+
+
+ dlon = lon2 - lon1;
+ dlat = lat2 - lat1;
+ a = square((sin(dlat/2.0))) + cos(lat1) * cos(lat2) * square((sin(dlon/2.0)));
+ c = 2.0 * atan2(sqrt(a), sqrt(1.0-a));
+ d = R * c;
+
+ return(d);
+}
+
+
+
+
+
+// Distance calculation (Great Circle) using the Haversine formula
+// (2-parameter arctan version), which gives better accuracy than
+// the "Law of Cosines" for short distances. It should be
+// equivalent to the "Law of Cosines for Spherical Trigonometry" for
+// longer distances. Haversine is a great-circle calculation.
+//
+//
+// Inputs: lat1/long1/lat2/long2 in Xastir coordinate system (long)
+//
+// Outputs: Distance in meters between them (double)
+//
+double calc_distance_haversine(long lat1, long lon1, long lat2, long lon2) {
+ double r_lat1,r_lat2;
+ double r_lon1,r_lon2;
+
+ r_lat1 = convert_lat_l2r(lat1);
+ r_lon1 = convert_lon_l2r(lon1);
+ r_lat2 = convert_lat_l2r(lat2);
+ r_lon2 = convert_lon_l2r(lon2);
+
+ return(calc_distance_haversine_radian(r_lat1, r_lon1, r_lat2, r_lon2));
+}
+
+
+
+
+
+/*
+ * Calculate distance in meters between two locations
+ *
+ * What type of calculation is this, Rhumb Line distance or Great
+ * Circle distance?
+ * Answer: "Law of Cosines for Spherical Trigonometry", which is a
+ * great-circle calculation.
+ *
+ *
+ * Inputs: lat1/long1/lat2/long2 in Xastir coordinate system (long)
+ *
+ * Outputs: Distance in meters between them (double)
+ *
+ */
+double calc_distance_law_of_cosines(long lat1, long lon1, long lat2, long lon2) {
+ double r_lat1,r_lat2;
+ double r_lon1,r_lon2;
+ double r_d;
+
+
+ r_lat1 = convert_lat_l2r(lat1);
+ r_lon1 = convert_lon_l2r(lon1);
+ r_lat2 = convert_lat_l2r(lat2);
+ r_lon2 = convert_lon_l2r(lon2);
+ r_d = acos(sin(r_lat1) * sin(r_lat2) + cos(r_lat1) * cos(r_lat2) * cos(r_lon1-r_lon2));
+
+//fprintf(stderr,"Law of Cosines Distance: %f\n",
+// r_d*180*60/M_PI*1852);
+//fprintf(stderr," Haversine Distance: %f\n\n",
+// calc_distance_haversine(lat1, lon1, lat2, lon2));
+
+ return(r_d*180*60/M_PI*1852);
+}
+
+
+
+
+
+// Here's where we choose which of the above two functions get used.
+//
+double calc_distance(long lat1, long lon1, long lat2, long lon2) {
+// return(calc_distance_law_of_cosines(lat1, lon1, lat2, lon2));
+ return(calc_distance_haversine(lat1, lon1, lat2, lon2));
+}
+
+
+
+
+
+/*
+ * Calculate distance between two locations in nautical miles and course from loc2 to loc1
+ *
+ * What type of calculation is this, Rhumb Line distance or Great
+ * Circle distance?
+ * Answer: "Law of Cosines for Spherical Trigonometry", which is a
+ * great-circle calculation, or Haversine, also a great-circle
+ * calculation.
+ *
+ * NOTE: The angle returned is a separate calculation, but using
+ * the unit sphere distance in it's calculation. A great circle
+ * bearing is computed, not a Rhumb-line bearing.
+ *
+ *
+ * Inputs: lat1/long1/lat2/long2 in Xastir coordinate system (long)
+ * Length of course_deg string (int)
+ *
+ * Outputs: Distance in nautical miles between them (double).
+ * course_deg (string)
+ *
+ */
+double calc_distance_course(long lat1, long lon1, long lat2, long lon2, char *course_deg, int course_deg_length) {
+ double ret;
+ double r_lat1, r_lat2;
+ double r_lon1, r_lon2;
+ double r_d, r_c, r_m;
+
+ r_lat1 = convert_lat_l2r(lat1);
+ r_lon1 = convert_lon_l2r(lon1);
+ r_lat2 = convert_lat_l2r(lat2);
+ r_lon2 = convert_lon_l2r(lon2);
+
+
+ // Compute the distance. We have a choice between using Law of
+ // Cosines or Haversine Formula here.
+
+ // 1) Law of Cosines for Spherical Trigonometry. This is
+ // unreliable for small distances because the inverse cosine is
+ // ill-conditioned. A computer carrying seven significant
+ // digits can't distinguish the cosines of distances smaller
+ // than about one minute of arc.
+// r_d = acos(sin(r_lat1) * sin(r_lat2) + cos(r_lat1) * cos(r_lat2) * cos(r_lon1-r_lon2));
+
+
+ // 2) Haversine Formula. Returns answer in meters.
+ r_m = calc_distance_haversine_radian(r_lat1, r_lon1, r_lat2, r_lon2);
+ //
+ // Conversion from distance in meters back to unit sphere. This
+ // is needed for the course calculation below as well as the
+ // later scaling up to feet/meters or miles/km.
+ r_d = r_m / EARTH_RADIUS_METERS;
+
+
+ // Compute the great-circle bearing
+ if (cos(r_lat1) < 0.0000000001) {
+ if (r_lat1>0.0)
+ r_c=M_PI;
+ else
+ r_c=0.0;
+ } else {
+ if (sin((r_lon2-r_lon1))<0.0)
+ r_c = acos((sin(r_lat2)-sin(r_lat1)*cos(r_d))/(sin(r_d)*cos(r_lat1)));
+ else
+ r_c = (2*M_PI) - acos((sin(r_lat2)-sin(r_lat1)*cos(r_d))/(sin(r_d)*cos(r_lat1)));
+
+ }
+
+ // Return the course
+ xastir_snprintf(course_deg,
+ course_deg_length,
+ "%.1f",
+ (180.0/M_PI)*r_c);
+
+ // Return the distance (nautical miles?)
+ ret = r_d*180*60/M_PI;
+
+/*
+// Convert from nautical miles to feet
+fprintf(stderr,"Law of Cosines Distance: %fft\t%fmi\n",
+ ret*5280.0*1.15078, ret*1.15078);
+// Convert from meters to feet
+fprintf(stderr," Haversine Distance: %fft\t%fmi\n\n",
+ calc_distance_haversine(lat1, lon1, lat2, lon2)*3.28084,
+ calc_distance_haversine(lat1, lon1, lat2, lon2)/1000/1.609344);
+*/
+
+ return(ret);
+}
+
+
+
+
+
+//*****************************************************************
+// distance_from_my_station - compute distance from my station and
+// course with a given call
+//
+// return distance and course
+//
+// Returns 0.0 for distance if station not found in database or the
+// station hasn't sent out a posit yet.
+//*****************************************************************
+
+double distance_from_my_station(char *call_sign, char *course_deg) {
+ DataRow *p_station;
+ double distance;
+ float value;
+ long l_lat, l_lon;
+
+ distance = 0.0;
+ l_lat = convert_lat_s2l(my_lat);
+ l_lon = convert_lon_s2l(my_long);
+ p_station = NULL;
+ if (search_station_name(&p_station,call_sign,1)) {
+ // Check whether we have a posit yet for this station
+ if ( (p_station->coord_lat == 0l)
+ && (p_station->coord_lon == 0l) ) {
+ distance = 0.0;
+ }
+ else {
+ value = (float)calc_distance_course(l_lat,
+ l_lon,
+ p_station->coord_lat,
+ p_station->coord_lon,
+ course_deg,
+ sizeof(course_deg));
+
+ if (english_units)
+ distance = value * 1.15078; // nautical miles to miles
+ else
+ distance = value * 1.852; // nautical miles to km
+ }
+// fprintf(stderr,"DistFromMy: %s %s -> %f\n",temp_lat,temp_long,distance);
+ }
+ else { // Station not found
+ distance = 0.0;
+ }
+
+ //fprintf(stderr,"Distance for %s: %f\n", call_sign, distance);
+
+ return(distance);
+}
+
+
+
+
+
+/*********************************************************************/
+/* convert_bearing_to_name - converts a bearing in degrees to */
+/* name for the bearing. Expects the degrees as a text string */
+/* since that's what the preceding functions output. */
+/* Set the opposite flag true for the inverse bearing (from vs to) */
+/*********************************************************************/
+
+static struct {
+ double low,high;
+ char *dircode,*lang;
+} directions[] = {
+ {327.5,360,"N","SPCHDIRN00"},
+ {0,22.5,"N","SPCHDIRN00"},
+ {22.5,67.5,"NE","SPCHDIRNE0"},
+ {67.5,112.5,"E","SPCHDIRE00"},
+ {112.5,157.5,"SE","SPCHDIRSE0"},
+ {157.5,202.5,"S","SPCHDIRS00"},
+ {202.5,247.5,"SW","SPCHDIRSW0"},
+ {247.5,292.5,"W","SPCHDIRW00"},
+ {292.5,327.5,"NW","SPCHDIRNW0"},
+};
+
+
+
+char *convert_bearing_to_name(char *bearing, int opposite) {
+ double deg = atof(bearing);
+ int i;
+
+ if (opposite) {
+ if (deg > 180) deg -= 180.0;
+ else if (deg <= 180) deg += 180.0;
+ }
+ for (i = 0; i < (int)( sizeof(directions)/sizeof(directions[0]) ); i++) {
+ if (deg >= directions[i].low && deg < directions[i].high)
+ return langcode(directions[i].lang);
+ }
+ return "?";
+}
+
+
+
+
+
+// Calculate new position based on distance and angle.
+//
+// Input: lat/long in Xastir coordinate system (100ths of seconds)
+// distance in nautical miles
+// angle in � true
+//
+// Outputs: *x_long, *y_lat in Xastir coordinate system (100ths of
+// seconds)
+//
+//
+// From http://home.t-online.de/home/h.umland/Chapter12.pdf
+//
+// Dead-reckoning using distance in km, course C:
+// Lat_B� = Lat_A� + ( (360/40031.6) * distance * cos C )
+//
+// Dead-reckoning using distance in nm, course C:
+// Lat_B� = Lat_A� + ( (distance/60) * cos C )
+//
+// Average of two latitudes (required for next two equations)
+// Lat_M� = (Lat_A� + Lat_B�) / 2
+//
+// Dead-reckoning using distance in km, course C:
+// Lon_B� = Lon_A� + ( (360/40031.6) * distance * (sin C / cos
+// Lat_M) )
+//
+// Dead-reckoning using distance in nm, course C:
+// Lon_B� = Lon_A� + ( (distance/60) * (sin C / cos Lat_M) )
+//
+// If resulting longitude exceeds +/- 180�, subtract/add 360�.
+//
+void compute_DR_position(long x_long, // input
+ long y_lat, // input
+ double range, // input in nautical miles
+ double course, // input in � true
+ long *x_long2, // output
+ long *y_lat2) { // output
+ double bearing_radians, lat_M_radians;
+ float lat_A, lat_B, lon_A, lon_B, lat_M;
+ int ret;
+ unsigned long x_u_long, y_u_lat;
+
+
+//fprintf(stderr,"Distance:%fnm, Course:%f, Time:%d\n",
+// range,
+// course,
+// (int)(sec_now() - p_station->sec_heard));
+
+ // Bearing in radians
+ bearing_radians = (double)((course/360.0) * 2.0 * M_PI);
+
+ // Convert lat/long to floats
+ ret = convert_from_xastir_coordinates( &lon_A,
+ &lat_A,
+ x_long,
+ y_lat);
+
+ // Check if conversion ok
+ if (!ret) {
+ // Problem during conversion. Exit without changes.
+ *x_long2 = x_long;
+ *y_lat2 = y_lat;
+ return;
+ }
+
+ // Compute new latitude
+ lat_B = (float)((double)(lat_A) + (range/60.0) * cos(bearing_radians));
+
+ // Compute mid-range latitude
+ lat_M = (lat_A + lat_B) / 2.0;
+
+ // Convert lat_M to radians
+ lat_M_radians = (double)((lat_M/360.0) * 2.0 * M_PI);
+
+ // Compute new longitude
+ lon_B = (float)((double)(lon_A)
+ + (range/60.0) * ( sin(bearing_radians) / cos(lat_M_radians)) );
+
+ // Test for out-of-bounds longitude, correct if so.
+ if (lon_B < -360.0)
+ lon_B = lon_B + 360.0;
+ if (lon_B > 360.0)
+ lon_B = lon_B - 360.0;
+
+//fprintf(stderr,"Lat:%f, Lon:%f\n", lat_B, lon_B);
+
+ ret = convert_to_xastir_coordinates(&x_u_long,
+ &y_u_lat,
+ lon_B,
+ lat_B);
+
+ // Check if conversion ok
+ if (!ret) {
+ // Problem during conversion. Exit without changes.
+ *x_long2 = x_long;
+ *y_lat2 = y_lat;
+ return;
+ }
+
+ // Convert from unsigned long to long
+ *x_long2 = (long)x_u_long;
+ *y_lat2 = (long)y_u_lat;
+}
+
+
+
+
+
+// Calculate new position based on speed/course/modified-time.
+// We'll call it from Create_object_item_tx_string() and from the
+// modify object/item routines to calculate a new position and stuff
+// it into the record along with the modification time before we
+// start off in a new direction.
+//
+// Input: *p_station
+//
+// Outputs: *x_long, *y_lat in Xastir coordinate system (100ths of
+// seconds)
+//
+//
+// From http://home.t-online.de/home/h.umland/Chapter12.pdf
+//
+// Dead-reckoning using distance in km, course C:
+// Lat_B� = Lat_A� + ( (360/40031.6) * distance * cos C )
+//
+// Dead-reckoning using distance in nm, course C:
+// Lat_B� = Lat_A� + ( (distance/60) * cos C )
+//
+// Average of two latitudes (required for next two equations)
+// Lat_M� = (Lat_A� + Lat_B�) / 2
+//
+// Dead-reckoning using distance in km, course C:
+// Lon_B� = Lon_A� + ( (360/40031.6) * distance * (sin C / cos
+// Lat_M) )
+//
+// Dead-reckoning using distance in nm, course C:
+// Lon_B� = Lon_A� + ( (distance/60) * (sin C / cos Lat_M) )
+//
+// If resulting longitude exceeds +/- 180�, subtract/add 360�.
+//
+//
+// Possible Problems/Changes:
+// --------------------------
+// *) Change to using last_modified_time for DR. Also tweak the
+// code so that we don't do incremental DR and use our own
+// decoded objects to update everything. If we keep the
+// last_modified_time and the last_modified_position separate
+// DR'ed objects/items, we can always use those instead of the
+// other variables if we have a non-zero speed.
+//
+// *) Make sure not to corrupt our position of the object when we
+// receive the packet back via loopback/RF/internet. In
+// particular the position and the last_modified_time should stay
+// constant in this case so that dead-reckoning can continue to
+// move the object consistently, plus we won't compound errors as
+// we go.
+//
+// *) A server Xastir sees empty strings on it's server port when
+// these objects are transmitted to it. Investigate. It
+// sometimes does it when speed is 0, but it's not consistent.
+//
+// *) Get the last_modified_time embedded into the logfile so that
+// we don't "lose time" if we shut down for a bit. DR'ed objects
+// will be at the proper positions when we start back up.
+//
+void compute_current_DR_position(DataRow *p_station, long *x_long, long *y_lat) {
+ int my_course = 0; // In � true
+ double range = 0.0;
+ double bearing_radians, lat_M_radians;
+ float lat_A, lat_B, lon_A, lon_B, lat_M;
+ int ret;
+ unsigned long x_u_long, y_u_lat;
+ time_t secs_now;
+
+
+ secs_now=sec_now();
+
+
+ // Check whether we have course in the current data
+ //
+ if ( (strlen(p_station->course)>0) && (atof(p_station->course) > 0) ) {
+
+ my_course = atoi(p_station->course); // In � true
+ }
+ //
+ // Else check whether the previous position had a course. Note
+ // that newest_trackpoint if it exists should be the same as the
+ // current data, so we have to go back one further trackpoint.
+ // Make sure in this case that this trackpoint has occurred
+ // within the dead-reckoning timeout period though, else ignore
+ // it.
+ //
+ else if ( (p_station->newest_trackpoint != NULL)
+ && (p_station->newest_trackpoint->prev != NULL)
+ && (p_station->newest_trackpoint->prev->course != -1) // Undefined
+ && ( (secs_now-p_station->newest_trackpoint->prev->sec) < dead_reckoning_timeout) ) {
+
+ // In � true
+ my_course = p_station->newest_trackpoint->prev->course;
+ }
+
+
+ // Get distance in nautical miles from the current data
+ //
+ if ( (strlen(p_station->speed)>0) && (atof(p_station->speed) >= 0) ) {
+
+ // Speed is in knots (same as nautical miles/hour)
+ range = (double)( (sec_now() - p_station->sec_heard)
+ * ( atof(p_station->speed) / 3600.0 ) );
+ }
+ //
+ // Else check whether the previous position had speed. Note
+ // that newest_trackpoint if it exists should be the same as the
+ // current data, so we have to go back one further trackpoint.
+ //
+ else if ( (p_station->newest_trackpoint != NULL)
+ && (p_station->newest_trackpoint->prev != NULL)
+ && (p_station->newest_trackpoint->prev->speed != -1) // Undefined
+ && ( (secs_now-p_station->newest_trackpoint->prev->sec) < dead_reckoning_timeout) ) {
+
+ // Speed is in units of 0.1km/hour. Different than above!
+ range = (double)( (sec_now() - p_station->sec_heard)
+ * ( p_station->newest_trackpoint->prev->speed / 10 * 0.5399568 / 3600.0 ) );
+ }
+
+
+//fprintf(stderr,"Distance:%fnm, Course:%d, Time:%d\n",
+// range,
+// my_course,
+// (int)(sec_now() - p_station->sec_heard));
+
+ // Bearing in radians
+ bearing_radians = (double)((my_course/360.0) * 2.0 * M_PI);
+
+ // Convert lat/long to floats
+ ret = convert_from_xastir_coordinates( &lon_A,
+ &lat_A,
+ p_station->coord_lon,
+ p_station->coord_lat);
+
+ // Check if conversion ok
+ if (!ret) {
+ // Problem during conversion. Exit without changes.
+ *x_long = p_station->coord_lon;
+ *y_lat = p_station->coord_lat;
+ return;
+ }
+
+ // Compute new latitude
+ lat_B = (float)((double)(lat_A) + (range/60.0) * cos(bearing_radians));
+
+ // Compute mid-range latitude
+ lat_M = (lat_A + lat_B) / 2.0;
+
+ // Convert lat_M to radians
+ lat_M_radians = (double)((lat_M/360.0) * 2.0 * M_PI);
+
+ // Compute new longitude
+ lon_B = (float)((double)(lon_A)
+ + (range/60.0) * ( sin(bearing_radians) / cos(lat_M_radians)) );
+
+ // Test for out-of-bounds longitude, correct if so.
+ if (lon_B < -360.0)
+ lon_B = lon_B + 360.0;
+ if (lon_B > 360.0)
+ lon_B = lon_B - 360.0;
+
+//fprintf(stderr,"Lat:%f, Lon:%f\n", lat_B, lon_B);
+
+ ret = convert_to_xastir_coordinates(&x_u_long,
+ &y_u_lat,
+ lon_B,
+ lat_B);
+
+ // Check if conversion ok
+ if (!ret) {
+ // Problem during conversion. Exit without changes.
+ *x_long = p_station->coord_lon;
+ *y_lat = p_station->coord_lat;
+ return;
+ }
+
+ // Convert from unsigned long to long
+ *x_long = (long)x_u_long;
+ *y_lat = (long)y_u_lat;
+}
+
+
+
+
+
+int filethere(char *fn) {
+ FILE *f;
+ int ret;
+
+ ret =0;
+ f=fopen(fn,"r");
+ if (f != NULL) {
+ ret=1;
+ (void)fclose(f);
+ }
+ return(ret);
+}
+
+
+
+
+
+int filecreate(char *fn) {
+ FILE *f;
+ int ret;
+
+ if (! filethere(fn)) { // If no file
+
+ ret = 0;
+ fprintf(stderr,"Making user %s file\n", fn);
+ f=fopen(fn,"w+"); // Create it
+ if (f != NULL) {
+ ret=1; // We were successful
+ (void)fclose(f);
+ }
+ return(ret); // Couldn't create file for some reason
+ }
+ return(1); // File already exists
+}
+
+
+
+
+
+time_t file_time(char *fn) {
+ struct stat file_status;
+
+ if(stat(fn,&file_status)==0)
+ return((time_t)file_status.st_ctime);
+
+ return(-1);
+}
+
+
+
+
+
+// Function written by Adam Hahn, AI4QB. Contributed to the public
+// domain. We've modified it from his initial code so any bugs are
+// our fault.
+int copy_file(char *infilename, char *outfilename) {
+ FILE *infile, *outfile;
+ char *buffer;
+ size_t numread = 0;
+
+
+ if ((infile = fopen(infilename,"rb")) > (FILE *)0) {
+
+ if ((outfile = fopen(outfilename,"wb")) > (FILE *)0) {
+ buffer = (char *)malloc(1024);
+
+ while (!feof(infile)) {
+ numread = fread(buffer, 1, 1024, infile);
+ fwrite(buffer, 1, numread, outfile);
+ }
+ free(buffer);
+ fflush(outfile);
+ fclose(outfile);
+ }
+ else {
+ fprintf(stderr,"Error opening destination file %s for writing", outfilename);
+ fclose(infile);
+ return(1);
+ }
+ fclose(infile);
+ }
+ else {
+ fprintf(stderr,"Error opening source file %s for reading", infilename);
+ return(1);
+ }
+ return 0;
+}
+
+
+
+
+
+// used by log_data
+void rotate_file(char *file, int max_keep ){
+ int i;
+ char file_a[MAX_FILENAME];
+ char file_b[MAX_FILENAME];
+ struct stat file_status;
+
+ if (debug_level & 1) {
+ fprintf(stderr, "Rotating: %s. Will keep %d \n", file, max_keep);
+ }
+
+ for(i=max_keep;i>=1;i--){
+
+ if (debug_level & 1) {
+ fprintf(stderr, "rotate: %s : %s\n", file_b, file_a);
+ }
+
+ xastir_snprintf(file_a,sizeof(file_a),"%s.%d",file,i);
+ xastir_snprintf(file_b,sizeof(file_b),"%s.%d",file,i-1);
+
+ unlink (file_a);
+ if (stat(file_a, &file_status) == 0) {
+ // We got good status. That means it didn't get deleted!
+ fprintf(stderr,
+ "Couldn't delete file '%s': %s",
+ file_a,strerror(errno));
+ return;
+ }
+
+ // Rename previous to next
+ //
+ // Check whether file_b exists
+ if (stat(file_b, &file_status) == 0) {
+ if (!S_ISREG(file_status.st_mode)) {
+ fprintf(stderr,
+ "Couldn't stat %s\n",
+ file_b);
+ break;
+ }
+ if ( rename (file_b, file_a) ) {
+ fprintf(stderr,
+ "Couldn't rename %s to %s, cancelling log_rotate()\n",
+ file_b,
+ file_a);
+ return;
+ }
+ }
+
+ }
+
+ if (debug_level & 1) {
+ fprintf(stderr, "rotate: %s : %s\n", file, file_a);
+ }
+
+ if ( rename (file, file_a) ) {
+ fprintf(stderr,
+ "Couldn't rename %s to %s, cancelling log_rotate()\n",
+ file,
+ file_a);
+ }
+
+ return;
+}
+
+
+
+
+
+char *fetch_file_line(FILE *f, char *line) {
+ char cin;
+ int pos;
+
+
+ pos = 0;
+ line[0] = '\0';
+
+ while (!feof(f)) {
+
+ // Read one character at a time
+ if (fread(&cin,1,1,f) == 1) {
+
+ if (pos < MAX_LINE_SIZE) {
+ if (cin != (char)13) // CR
+ line[pos++] = cin;
+ }
+
+ if (cin == (char)10) { // Found LF as EOL char
+ line[pos++] = '\0'; // Always add a terminating zero after last char
+ pos = 0; // start next line
+ return(line);
+ }
+ }
+ }
+
+ // Must be end of file
+ line[pos] = '\0';
+ return(line);
+}
+
+
+
+
+
+// Restore weather alerts so that we have a clear picture of the
+// current state. Check timestamps on the file. If relatively
+// current, read the file in.
+//
+void load_wx_alerts_from_log_working_sub(time_t time_now, char *filename) {
+ time_t file_timestamp;
+ int file_age;
+ int expire_limit; // In seconds
+ char line[MAX_LINE_SIZE+1];
+ FILE *f;
+
+
+ expire_limit = 60 * 60 * 24 * 15; // 15 days
+// expire_limit = 60 * 60 * 24 * 1; // 1 day
+
+ file_timestamp = file_time(filename);
+
+ if (file_timestamp == -1) {
+// fprintf(stderr,"File %s doesn't exist\n", filename);
+ return;
+ }
+
+ file_age = time_now - file_timestamp;
+
+ if ( file_age > expire_limit) {
+// fprintf(stderr,"Old file: %s, skipping...\n", filename);
+ return;
+ }
+
+// fprintf(stderr,"File is current: %s\n", filename);
+
+ // Read the file in, as it exists and is relatively new.
+
+ // Check timestamps before each log line and skip those that are
+ // old. Lines in the file should look about like this:
+ //
+ // # 1157027319 Thu Aug 31 05:28:39 PDT 2006
+ // OUNSWO>APRS::SKYOUN :OUN Check For Activation VCEAB
+ // # 1157027319 Thu Aug 31 05:28:39 PDT 2006
+ // LZKFFS>APRS::NWS_ADVIS:311324z,FLOOD,ARC67-147 V1PAA
+ //
+ // We could try to use the regular read_file and read_file_ptr
+ // scheme for reading in the log file, but we'd have to modify
+ // it in two ways: We need to keep from bringing up the
+ // interfaces so we'd need to set a flag when done reading and
+ // then start them, plus we'd need to have it check the
+ // timestamps and skip old ones. Instead we'll do it all on our
+ // own here so that we can control everything ourselves.
+
+ f = fopen(filename, "r");
+ if (!f) {
+ fprintf(stderr,"Wx Alert log file could not be opened for reading\n");
+ return;
+ }
+
+ while (!feof(f)) { // Read until end of file
+
+ (void)fetch_file_line(f, line);
+
+restart_sync:
+
+ if (line[0] == '\0') {
+ // Empty line found, skip
+ }
+
+ else if (line[0] == '#') { // Timestamp line, check the date
+ time_t line_stamp;
+ int line_age;
+
+ if (strlen(line) < 3) { // Line is too short, skip
+ goto restart_sync;
+ }
+
+ line_stamp = atoi(&line[2]);
+ line_age = time_now - line_stamp;
+//fprintf(stderr, "Age: %d\t", line_age);
+
+ if ( line_age < expire_limit) {
+ // Age is good, read next line and process it
+
+ (void)fetch_file_line(f, line);
+
+ if (line[0] != '#') { // It's a packet, not a timestamp line
+//fprintf(stderr,"%s\n",line);
+ decode_ax25_line(line,'F',-1, 1); // Decode the packet
+ }
+ else {
+ goto restart_sync;
+ }
+ }
+ }
+ }
+ if (feof(f)) { // Close file if at the end
+ (void)fclose(f);
+ }
+}
+
+
+
+
+
+// Restore weather alerts so that we have a clear picture of the
+// current state. Do this before we start the interfaces. Only
+// reload if the log files datestamps are relatively current.
+//
+// Check timestamps on each file in turn. If relatively
+// current, read them in the correct order:
+// wx_alert.log.3
+// wx_alert.log.2
+// wx_alert.log.1
+// wx.alert.log
+//
+void load_wx_alerts_from_log(void) {
+ time_t time_now;
+ char filename[MAX_FILENAME];
+ char logfile_path[MAX_VALUE];
+
+ get_user_base_dir(LOGFILE_WX_ALERT,logfile_path, sizeof(logfile_path));
+
+ time_now = sec_now();
+
+ fprintf(stderr,"*** Reading WX Alert log files\n");
+
+ // wx_alert.log.3
+ xastir_snprintf(filename,
+ sizeof(filename),
+ "%s.3",
+ logfile_path );
+ load_wx_alerts_from_log_working_sub(time_now, filename);
+
+ // wx_alert.log.2
+ xastir_snprintf(filename,
+ sizeof(filename),
+ "%s.2",
+ logfile_path );
+ load_wx_alerts_from_log_working_sub(time_now, filename);
+
+ // wx_alert.log.1
+ xastir_snprintf(filename,
+ sizeof(filename),
+ "%s.1",
+ logfile_path );
+ load_wx_alerts_from_log_working_sub(time_now, filename);
+
+ // wx_alert.log
+ xastir_snprintf(filename,
+ sizeof(filename),
+ "%s",
+ logfile_path );
+ load_wx_alerts_from_log_working_sub(time_now, filename);
+
+ fill_in_new_alert_entries();
+
+ fprintf(stderr,"*** Done with WX Alert log files\n");
+}
+
+
+
+
+
+// Note that the length of "line" can be up to MAX_DEVICE_BUFFER,
+// which is currently set to 4096.
+//
+void log_data(char *file, char *line) {
+ FILE *f;
+ struct stat file_status;
+ int reset_setuid = 0 ;
+
+
+ // Check for "# Tickle" first, don't log it if found.
+ // It's an idle string designed to keep the socket active.
+ if ( (strncasecmp(line, "#Tickle", 7)==0)
+ || (strncasecmp(line, "# Tickle", 8) == 0) ) {
+ return;
+ }
+ else {
+ char temp[200];
+ char timestring[100+1];
+ struct tm *time_now;
+ time_t secs_now;
+
+ // Fetch the current date/time string
+// get_timestamp(timestring);
+ secs_now=sec_now();
+
+ time_now = localtime(&secs_now);
+
+ (void)strftime(timestring,100,"%a %b %d %H:%M:%S %Z %Y",time_now);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "# %ld %s",
+ (unsigned long)secs_now,
+ timestring);
+
+ // Change back to the base directory
+
+// This call corrupts the "file" variable. Commented it out as we
+// don't appear to need it anyway. The complete root-anchored
+// path/filename are passed to us in the "file" parameter.
+//
+// chdir(get_user_base_dir(""));
+
+ // check size and rotate if too big
+
+ if (stat(file, &file_status)==0){
+
+// if (debug_level & 1) {
+// fprintf(stderr, "log_data(): logfile size: %ld \n",(long) file_status.st_size);
+// }
+
+ if ((file_status.st_size + strlen(temp) + strlen(line) )> MAX_LOGFILE_SIZE){
+ if (debug_level & 1) {
+ fprintf(stderr, "log_data(): calling rotate_file()\n");
+ }
+
+ rotate_file(file,3);
+ }
+
+ }
+ else {
+ // ENOENT is ok -- we make the file below
+ if (errno != ENOENT ) {
+ fprintf(stderr,"Couldn't stat log file '%s': %s\n",
+ file,strerror(errno));
+ return;
+ }
+
+ }
+
+ if (getuid() != geteuid()){
+ reset_setuid=1;
+ DISABLE_SETUID_PRIVILEGE;
+ }
+
+ f=fopen(file,"a");
+ if (f!=NULL) {
+ fprintf(f,"%s\n", temp); // Write the timestamp line
+ fprintf(f,"%s\n",line); // Write the data line
+ (void)fclose(f);
+ }
+ else {
+ fprintf(stderr,"Couldn't open file for appending: %s\n", file);
+ }
+
+ if(reset_setuid){
+ ENABLE_SETUID_PRIVILEGE;
+ }
+ }
+}
+
+
+
+
+
+//
+// Tactical callsign logging
+//
+// Logging function called from the Assign Tactical Call right-click
+// menu option and also from db.c:fill_in_tactical_call. Each
+// tactical assignment is logged as one line.
+//
+// We need to check for identical callsigns in the file, deleting
+// lines that have the same name and adding new records to the end.
+// Actually BAD IDEA! We want to keep the history of the tactical
+// calls so that we can trace the changes later.
+//
+// Best method: Look for lines containing matching callsigns and
+// comment them out, adding the new tactical callsign at the end of
+// the file.
+//
+// Do we need to use a special marker to mean NO tactical callsign
+// is assigned? This is for when we had a tactical call but now
+// we're removing it. The reload_tactical_calls() routine below
+// would need to match. Since we're using comma-delimited files, we
+// can just check for an empty string instead.
+//
+void log_tactical_call(char *call_sign, char *tactical_call_sign) {
+ char file[MAX_VALUE];
+ FILE *f;
+
+
+ // Add it to our in-memory hash so that if stations expire and
+ // then appear again they get assigned the same tac-call.
+ add_tactical_to_hash(call_sign, tactical_call_sign);
+
+
+ get_user_base_dir("config/tactical_calls.log", file, sizeof(file));
+
+ f=fopen(file,"a");
+ if (f!=NULL) {
+
+ if (tactical_call_sign == NULL)
+ fprintf(f,"%s,\n",call_sign);
+ else
+ fprintf(f,"%s,%s\n",call_sign,tactical_call_sign);
+
+ (void)fclose(f);
+
+ if (debug_level & 1) {
+ fprintf(stderr,
+ "Saving tactical call to file: %s:%s",
+ call_sign,
+ tactical_call_sign);
+ }
+ }
+ else {
+ fprintf(stderr,"Couldn't open file for appending: %s\n", file);
+ }
+}
+
+
+
+
+
+//
+// Function to load saved tactical calls back into xastir. This
+// is called on startup. This implements persistent tactical calls
+// across xastir restarts.
+//
+// Here we create a hash lookup and store one record for each valid
+// line read from the tactical calls log file. The key for each
+// hash entry is the callsign-SSID. Here we simply read them in and
+// create the hash. When a new station is heard on the air, it is
+// checked against this hash and the tactical call field filled in
+// if there is a match.
+//
+// Note that the length of "line" can be up to max_device_buffer,
+// which is currently set to 4096.
+//
+void reload_tactical_calls(void) {
+ char file[MAX_VALUE];
+ FILE *f;
+ char line[300+1];
+
+
+ get_user_base_dir("config/tactical_calls.log", file, sizeof(file));
+
+ f=fopen(file,"r");
+ if (f!=NULL) {
+
+ while (fgets(line, 300, f) != NULL) {
+
+ if (debug_level & 1)
+ fprintf(stderr,"loading tactical calls from file: %s",line);
+
+ if (line[0] != '#') { // skip comment lines
+ char *ptr;
+
+ // we're dealing with comma-separated files, so
+ // break the two pieces at the comma.
+ ptr = index(line,',');
+
+ if (ptr != NULL) {
+ char *ptr2;
+
+
+ ptr[0] = '\0'; // terminate the callsign
+ ptr++; // point to the tactical callsign
+
+ // check for lf
+ ptr2 = index(ptr,'\n');
+ if (ptr2 != NULL)
+ ptr2[0] = '\0';
+
+ // check for cr
+ ptr2 = index(ptr,'\r');
+ if (ptr2 != NULL)
+ ptr2[0] = '\0';
+
+ if (debug_level & 1)
+ fprintf(stderr, "Call=%s,\tTactical=%s\n", line, ptr);
+
+ // call tac-call
+ add_tactical_to_hash(line, ptr);
+ }
+ }
+ }
+ (void)fclose(f);
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"couldn't open file for reading: %s\n", file);
+ }
+
+/*
+ if (tactical_hash) {
+ fprintf(stderr,"Stations w/tactical calls defined: %d\n",
+ hashtable_count(tactical_hash));
+ }
+*/
+
+}
+
+
+
+
+
+// Returns time in seconds since the Unix epoch.
+//
+time_t sec_now(void) {
+ time_t timenw;
+ time_t ret;
+
+ ret = time(&timenw);
+ return(ret);
+}
+
+
+
+
+
+char *get_time(char *time_here) {
+ struct tm *time_now;
+ time_t timenw;
+
+ (void)time(&timenw);
+ time_now = localtime(&timenw);
+ (void)strftime(time_here,MAX_TIME,"%m%d%Y%H%M%S",time_now);
+ return(time_here);
+}
+
+
+
+
+
+/////////////////////////////////// Utilities ////////////////////////////////////////////////////
+
+
+/*
+ * Check for valid path and change it to TAPR format
+ * Add missing asterisk for stations that we must have heard via a digi
+ * Extract port for KAM TNCs
+ * Handle igate injection ID formats: "callsign-ssid,I" & "callsign-0ssid"
+ *
+ * TAPR-2 Format:
+ * KC2ELS-1*>SX0PWT,RELAY,WIDE:`2`$l##>/>"4)}
+ *
+ * AEA Format:
+ * KC2ELS-1*>RELAY>WIDE>SX0PWT:`2`$l##>/>"4)}
+ */
+
+int valid_path(char *path) {
+ int i,len,hops,j;
+ int type,ast,allast,ins;
+ char ch;
+
+
+ len = (int)strlen(path);
+ type = 0; // 0: unknown, 1: AEA '>', 2: TAPR2 ',', 3: mixed
+ hops = 1;
+ ast = 0;
+ allast = 0;
+
+ // There are some multi-port TNCs that deliver the port at the end
+ // of the path. For now we discard this information. If there is
+ // multi-port TNC support some day, we should write the port into
+ // our database.
+ // KAM: /V /H
+ // KPC-9612: /0 /1 /2
+ if (len > 2 && path[len-2] == '/') {
+ ch = path[len-1];
+ if (ch == 'V' || ch == 'H' || ch == '0' || ch == '1' || ch == '2') {
+ path[len-2] = '\0';
+ len = (int)strlen(path);
+ }
+ }
+
+
+ // One way of adding igate injection ID is to add "callsign-ssid,I".
+ // We need to remove the ",I" portion so it doesn't count as another
+ // digi here. This should be at the end of the path.
+ if (len > 2 && path[len-2] == ',' && path[len-1] == 'I') { // Found ",I"
+ //fprintf(stderr,"%s\n",path);
+ //fprintf(stderr,"Found ',I'\n");
+ path[len-2] = '\0';
+ len = (int)strlen(path);
+ //fprintf(stderr,"%s\n\n",path);
+ }
+ // Now look for the same thing but with a '*' character at the end.
+ // This should be at the end of the path.
+ if (len > 3 && path[len-3] == ',' && path[len-2] == 'I' && path[len-1] == '*') { // Found ",I*"
+ //fprintf(stderr,"%s\n",path);
+ //fprintf(stderr,"Found ',I*'\n");
+ path[len-3] = '\0';
+ len = (int)strlen(path);
+ //fprintf(stderr,"%s\n\n",path);
+ }
+
+
+ // Another method of adding igate injection ID is to add a '0' in front of
+ // the SSID. For WE7U it would change to WE7U-00, for WE7U-15 it would
+ // change to WE7U-015. Take out this zero so the rest of the decoding will
+ // work. This should be at the end of the path.
+ // Also look for the same thing but with a '*' character at the end.
+ if (len > 6) {
+ for (i=len-1; i>len-6; i--) {
+ if (path[i] == '-' && path[i+1] == '0') {
+ //fprintf(stderr,"%s\n",path);
+ for (j=i+1; j<len; j++) {
+ path[j] = path[j+1]; // Shift everything left by one
+ }
+ len = (int)strlen(path);
+ //fprintf(stderr,"%s\n\n",path);
+ }
+ // Check whether we just chopped off the '0' from "-0".
+ // If so, chop off the dash as well.
+ if (path[i] == '-' && path[i+1] == '\0') {
+ //fprintf(stderr,"%s\tChopping off dash\n",path);
+ path[i] = '\0';
+ len = (int)strlen(path);
+ //fprintf(stderr,"%s\n",path);
+ }
+ // Check for "-*", change to '*' only
+ if (path[i] == '-' && path[i+1] == '*') {
+ //fprintf(stderr,"%s\tChopping off dash\n",path);
+ path[i] = '*';
+ path[i+1] = '\0';
+ len = (int)strlen(path);
+ //fprintf(stderr,"%s\n",path);
+ }
+ // Check for "-0" or "-0*". Change to "" or "*".
+ if ( path[i] == '-' && path[i+1] == '0' ) {
+ //fprintf(stderr,"%s\tShifting left by two\n",path);
+ for (j=i; j<len; j++) {
+ path[j] = path[j+2]; // Shift everything left by two
+ }
+ len = (int)strlen(path);
+ //fprintf(stderr,"%s\n",path);
+ }
+ }
+ }
+
+
+ for (i=0,j=0; i<len; i++) {
+ ch = path[i];
+
+ if (ch == '>' || ch == ',') { // found digi call separator
+ // We're at the start of a callsign entry in the path
+
+ if (ast > 1 || (ast == 1 && i-j > 10) || (ast == 0 && (i == j || i-j > 9))) {
+ if (debug_level & 1)
+ fprintf(stderr, "valid_path(): Bad Path: More than one * in call or wrong call size\n");
+ return(0); // more than one asterisk in call or wrong call size
+ }
+ ast = 0; // reset local asterisk counter
+
+ j = i+1; // set to start of next call
+ if (ch == ',')
+ type |= 0x02; // set TAPR2 flag
+ else
+ type |= 0x01; // set AEA flag (found '>')
+ hops++; // count hops
+ }
+
+ else { // digi call character or asterisk
+ // We're in the middle of a callsign entry
+
+ if (ch == '*') {
+ ast++; // count asterisks in call
+ allast++; // count asterisks in path
+ }
+ else if ((ch <'A' || ch > 'Z') // Not A-Z
+ && (ch <'a' || ch > 'z') // Not a-z
+ && (ch <'0' || ch > '9') // Not 0-9
+ && ch != '-') {
+ // Note that Q-construct and internet callsigns can
+ // have a-z in them, AX.25 callsigns cannot unless
+ // they are in a 3rd-party packet.
+
+ if (debug_level & 1)
+ fprintf(stderr, "valid_path: Bad Path: Anti-loop stuff from aprsd or lower-case chars found\n");
+ return(0); // wrong character in path
+ }
+ }
+ }
+ if (ast > 1 || (ast == 1 && i-j > 10) || (ast == 0 && (i == j || i-j > 9))) {
+ if (debug_level & 1)
+ fprintf(stderr, "valid_path: Bad Path: More than one * or wrong call size (2)\n");
+ return(0); // more than one asterisk or wrong call size
+ }
+
+ if (type == 0x03) {
+ if (debug_level & 1)
+ fprintf(stderr, "valid_path: Bad Path: Wrong format, both > and , in path\n");
+ return(0); // wrong format, both '>' and ',' in path
+ }
+
+ if (hops > 9) { // [APRS Reference chapter 3]
+ if (debug_level & 1)
+ fprintf(stderr, "valid_path: Bad Path: hops > 9\n");
+ return(0); // too much hops, destination + 0-8 digipeater addresses
+ }
+
+ if (type == 0x01) {
+ int delimiters[20];
+ int k = 0;
+ char dest[15];
+ char rest[100];
+
+ for (i=0; i<len; i++) {
+ if (path[i] == '>') {
+ path[i] = ','; // Exchange separator character
+ delimiters[k++] = i; // Save the delimiter indexes
+ }
+ }
+
+ // We also need to move the destination callsign to the end.
+ // AEA has them in a different order than TAPR-2 format.
+ // We'll move the destination address between delimiters[0]
+ // and [1] to the end of the string.
+
+ //fprintf(stderr,"Orig. Path:%s\n",path);
+ // Save the destination
+ xastir_snprintf(dest,sizeof(dest),"%s",&path[delimiters[--k]+1]);
+ dest[strlen(path) - delimiters[k] - 1] = '\0'; // Terminate it
+ dest[14] = '\0'; // Just to make sure
+ path[delimiters[k]] = '\0'; // Delete it from the original path
+ //fprintf(stderr,"Destination: %s\n",dest);
+
+ // TAPR-2 Format:
+ // KC2ELS-1*>SX0PWT,RELAY,WIDE:`2`$l##>/>"4)}
+ //
+ // AEA Format:
+ // KC2ELS-1*>RELAY>WIDE>SX0PWT:`2`$l##>/>"4)}
+ // 9 15 20
+
+ // We now need to insert the destination into the middle of
+ // the string. Save part of it in another variable first.
+ xastir_snprintf(rest,
+ sizeof(rest),
+ "%s",
+ path);
+ //fprintf(stderr,"Rest:%s\n",rest);
+ xastir_snprintf(path,len+1,"%s,%s",dest,rest);
+ //fprintf(stderr,"New Path:%s\n",path);
+ }
+
+ if (allast < 1) { // try to insert a missing asterisk
+ ins = 0;
+ hops = 0;
+
+ for (i=0; i<len; i++) {
+
+ for (j=i; j<len; j++) { // search for separator
+ if (path[j] == ',')
+ break;
+ }
+
+ if (hops > 0 && (j - i) == 5) { // WIDE3
+ if ( path[ i ] == 'W' && path[i+1] == 'I' && path[i+2] == 'D'
+ && path[i+3] == 'E' && path[i+4] >= '0' && path[i+4] <= '9') {
+ ins = j;
+ }
+ }
+
+/*
+Don't do this! It can mess up relay/wide1-1 digipeating by adding
+an asterisk later in the path than the first unused digi.
+ if (hops > 0 && (j - i) == 7) { // WIDE3-2
+ if ( path[ i ] == 'W' && path[i+1] == 'I' && path[i+2] == 'D'
+ && path[i+3] == 'E' && path[i+4] >= '0' && path[i+4] <= '9'
+ && path[i+5] == '-' && path[i+6] >= '0' && path[i+6] <= '9'
+ && (path[i+4] != path[i+6]) ) {
+ ins = j;
+ }
+ }
+*/
+
+ if (hops > 0 && (j - i) == 6) { // TRACE3
+ if ( path[ i ] == 'T' && path[i+1] == 'R' && path[i+2] == 'A'
+ && path[i+3] == 'C' && path[i+4] == 'E'
+ && path[i+5] >= '0' && path[i+5] <= '9') {
+ if (hops == 1)
+ ins = j;
+ else
+ ins = i-1;
+ }
+ }
+
+/*
+Don't do this! It can mess up relay/wide1-1 digipeating by adding
+an asterisk later in the path than the first unused digi.
+ if (hops > 0 && (j - i) == 8) { // TRACE3-2
+ if ( path[ i ] == 'T' && path[i+1] == 'R' && path[i+2] == 'A'
+ && path[i+3] == 'C' && path[i+4] == 'E' && path[i+5] >= '0'
+ && path[i+5] <= '9' && path[i+6] == '-' && path[i+7] >= '0'
+ && path[i+7] <= '9' && (path[i+5] != path[i+7]) ) {
+ if (hops == 1)
+ ins = j;
+ else
+ ins = i-1;
+ }
+ }
+*/
+
+ hops++;
+ i = j; // skip to start of next call
+ }
+ if (ins > 0) {
+ for (i=len;i>=ins;i--) {
+ path[i+1] = path[i]; // generate space for '*'
+ // we work on a separate path copy which is long enough to do it
+ }
+ path[ins] = '*'; // and insert it
+ }
+ }
+ return(1); // Path is good
+}
+
+
+
+
+
+/*
+ * Check for a valid AX.25 call
+ * Valid calls consist of up to 6 uppercase alphanumeric characters
+ * plus optional SSID (four-bit integer) [APRS Reference, AX.25 Reference]
+ */
+int valid_call(char *call) {
+ int len, ok;
+ int i, del, has_num, has_chr;
+ char c;
+
+ has_num = 0;
+ has_chr = 0;
+ ok = 1;
+ len = (int)strlen(call);
+
+ if (len == 0)
+ return(0); // wrong size
+
+ while (call[0]=='c' && call[1]=='m' && call[2]=='d' && call[3]==':') {
+ // Erase TNC prompts from beginning of callsign. This may
+ // not be the right place to do this, but it came in handy
+ // here, so that's where I put it. -- KB6MER
+
+ if (debug_level & 1) {
+ char filtered_data[MAX_LINE_SIZE+1];
+
+ xastir_snprintf(filtered_data,
+ sizeof(filtered_data),
+ "%s",
+ call);
+ makePrintable(filtered_data);
+ fprintf(stderr,"valid_call: Command Prompt removed from: %s",
+ filtered_data);
+ }
+
+ for(i=0; call[i+4]; i++)
+ call[i]=call[i+4];
+
+ call[i++]=0;
+ call[i++]=0;
+ call[i++]=0;
+ call[i++]=0;
+ len=strlen(call);
+
+ if (debug_level & 1) {
+ char filtered_data[MAX_LINE_SIZE+1];
+
+ xastir_snprintf(filtered_data,
+ sizeof(filtered_data),
+ "%s",
+ call);
+ makePrintable(filtered_data);
+ fprintf(stderr," result: %s", filtered_data);
+ }
+ }
+
+ if (len > 9)
+ return(0); // Too long for valid call (6-2 max e.g. KB6MER-12)
+
+ del = 0;
+ for (i=len-2;ok && i>0 && i>=len-3;i--) { // search for optional SSID
+ if (call[i] =='-')
+ del = i; // found the delimiter
+ }
+ if (del) { // we have a SSID, so check it
+ if (len-del == 2) { // 2 char SSID
+ if (call[del+1] < '1' || call[del+1] > '9') // -1 ... -9
+ del = 0;
+ }
+ else { // 3 char SSID
+ if (call[del+1] != '1' || call[del+2] < '0' || call[del+2] > '5') // -10 ... -15
+ del = 0;
+ }
+ }
+
+ if (del)
+ len = del; // length of base call
+
+ for (i=0;ok && i<len;i++) { // check for uppercase alphanumeric
+ c = call[i];
+
+ if (c >= 'A' && c <= 'Z')
+ has_chr = 1; // we need at least one char
+ else if (c >= '0' && c <= '9')
+ has_num = 1; // we need at least one number
+ else
+ ok = 0; // wrong character in call
+ }
+
+// if (!has_num || !has_chr) // with this we also discard NOCALL etc.
+ if (!has_chr)
+ ok = 0;
+
+ ok = (ok && strcmp(call,"NOCALL") != 0); // check for errors
+ ok = (ok && strcmp(call,"ERROR!") != 0);
+ ok = (ok && strcmp(call,"WIDE") != 0);
+ ok = (ok && strcmp(call,"RELAY") != 0);
+ ok = (ok && strcmp(call,"MAIL") != 0);
+
+ return(ok);
+}
+
+
+
+
+
+/*
+ * Check for a valid internet name.
+ * Accept darned-near anything here as long as it is the proper
+ * length and printable.
+ */
+int valid_inet_name(char *name, char *info, char *origin, int origin_size) {
+ int len, i, ok, oknws, okbom;
+ char *ptr;
+
+ len = (int)strlen(name);
+
+ if (len > 9 || len == 0) // max 9 printable ASCII characters
+ return(0); // wrong size
+
+ for (i=0;i<len;i++)
+ if (!isprint((int)name[i]))
+ return(0); // not printable
+
+ // Modifies "origin" if a match found
+ //
+ if (len >= 5 && strncmp(name,"aprsd",5) == 0) {
+ xastir_snprintf(origin, origin_size, "INET");
+ origin[4] = '\0'; // Terminate it
+ return(1); // aprsdXXXX is ok
+ }
+
+ // Modifies "origin" if a match found
+ if (len == 6) { // check for NWS or BOM
+ ok = 1;
+ oknws = 0;
+ okbom = 0;
+ for (i=0;i<6;i++)
+ if (name[i] <'A' || name[i] > 'Z') // 6 uppercase characters
+ ok = 0;
+ ok = ok && (info != NULL); // check if we can test info
+ if (ok) {
+ ptr = strstr(info,":NWS-"); // "NWS-" in info field (non-compressed alert)
+ oknws = (ptr != NULL);
+
+ if (!oknws) {
+ ptr = strstr(info,":NWS_"); // "NWS_" in info field (compressed alert)
+ oknws = (ptr != NULL);
+ }
+
+ // If we've got here, it's not an NWS message, let's see if its a BOM message
+ if (!oknws) {
+ ptr = strstr(info,":BOM-"); // "BOM-" in info field (compressed alert)
+ okbom = (ptr != NULL);
+ }
+
+ if (!okbom) {
+ ptr = strstr(info,":BOM_"); // "BOM_" in info field (compressed alert)
+ okbom = (ptr != NULL);
+ }
+ }
+
+ // Depending on whether we had an NWS or BOM message, se the origin appropriately
+ if (oknws) {
+ xastir_snprintf(origin, origin_size, "INET-NWS");
+ origin[8] = '\0';
+ return(1); // weather alerts
+ }
+ if (okbom) {
+ xastir_snprintf(origin, origin_size, "INET-BOM");
+ origin[8] = '\0';
+ return(1); // weather alerts
+ }
+ }
+
+ return(1); // Accept anything else if we get to this point in
+ // the code. After all, the message came from the
+ // internet, not from RF.
+}
+
+
+
+
+
+/*
+ * Keep track of last six digis that echo my transmission
+ */
+void upd_echo(char *path) {
+ int i,j,len;
+
+ if (echo_digis[5][0] != '\0') {
+ for (i=0;i<5;i++) {
+ xastir_snprintf(echo_digis[i],
+ MAX_CALLSIGN+1,
+ "%s",
+ echo_digis[i+1]);
+
+ }
+ echo_digis[5][0] = '\0';
+ }
+ for (i=0,j=0;i < (int)strlen(path);i++) {
+ if (path[i] == '*')
+ break;
+ if (path[i] == ',')
+ j=i;
+ }
+ if (j > 0)
+ j++; // first char of call
+ if (i > 0 && i-j <= 9) {
+ len = i-j;
+ for (i=0;i<5;i++) { // look for free entry
+ if (echo_digis[i][0] == '\0')
+ break;
+ }
+ substr(echo_digis[i],path+j,len);
+ }
+}
+
+
+
+
+
+// dl9sau:
+// I liked to have xastir to compute the locator along with the normal coordinates.
+// The algorithm derives from dk5sg's util/qth.c (wampes)
+//
+// This computes Maidenhead grid coordinates and is used for both
+// the status line ("text2" widget) and the Coordinate Calculator at
+// present.
+//
+char *sec_to_loc(long longitude, long latitude)
+{
+ static char buf[7];
+ char *loc = buf;
+
+ // database.h: long coord_lon; // Xastir coordinates 1/100 sec, 0 = 180�W
+ // database.h: long coord_lat; // Xastir coordinates 1/100 sec, 0 = 90�N
+
+ longitude /= 100L;
+ latitude = 2L * 90L * 3600L - 1L - (latitude / 100L);
+
+ *loc++ = (char) (longitude / 72000L + 'A'); longitude = longitude % 72000L;
+ *loc++ = (char) (latitude / 36000L + 'A'); latitude = latitude % 36000L;
+ *loc++ = (char) (longitude / 7200L + '0'); longitude = longitude % 7200L;
+ *loc++ = (char) (latitude / 3600L + '0'); latitude = latitude % 3600L;
+ *loc++ = (char) (longitude / 300L + 'a');
+ *loc++ = (char) (latitude / 150L + 'a');
+ *loc = 0; // Terminate the string
+ return buf;
+}
+
+
+
+
+
+/*
+ * Substring function WITH a terminating NULL char, needs a string of at least size+1
+ */
+void substr(char *dest, char *src, int size) {
+ xastir_snprintf(dest, size+1, "%s", src);
+}
+
+
+
+
+
+
+char *to_upper(char *data) {
+ int i;
+
+ for(i=strlen(data)-1;i>=0;i--)
+ if(islower((int)data[i]))
+ data[i]=toupper((int)data[i]);
+
+ return(data);
+}
+
+
+
+
+
+char *to_lower(char *data) {
+ int i;
+
+ for(i=strlen(data)-1;i>=0;i--)
+ if(isupper((int)data[i]))
+ data[i]=tolower((int)data[i]);
+
+ return(data);
+}
+
+
+
+
+
+int is_num_chr(char ch) {
+ return((int)isdigit(ch));
+}
+
+
+
+
+
+
+int is_num_or_sp(char ch) {
+ return((int)((ch >= '0' && ch <= '9') || ch == ' '));
+}
+
+
+
+
+
+
+int is_xnum_or_dash(char *data, int max){
+ int i;
+ int ok;
+
+ ok=1;
+ for(i=0; i<max;i++)
+ if(!(isxdigit((int)data[i]) || data[i]=='-')) {
+ ok=0;
+ break;
+ }
+
+ return(ok);
+}
+
+
+
+
+
+// not used
+int is_num_stuff(char *data, int max) {
+ int i;
+ int ok;
+
+ ok=1;
+ for(i=0; i<max;i++)
+ if(!(isdigit((int)data[i]) || data[i]=='-' || data[i]=='+' || data[i]=='.')) {
+ ok=0;
+ break;
+ }
+
+ return(ok);
+}
+
+
+
+
+
+// not used
+int is_num(char *data) {
+ int i;
+ int ok;
+
+ ok=1;
+ for(i=strlen(data)-1;i>=0;i--)
+ if(!isdigit((int)data[i])) {
+ ok=0;
+ break;
+ }
+
+ return(ok);
+}
+
+
+
+
+
+//--------------------------------------------------------------------
+//Removes all control codes ( < 1Ch ) from a string and set the 8th bit to zero
+void removeCtrlCodes(char *cp) {
+ int i,j;
+ int len = (int)strlen(cp);
+ unsigned char *ucp = (unsigned char *)cp;
+
+ for (i=0, j=0; i<=len; i++) {
+ ucp[i] &= 0x7f; // Clear 8th bit
+ if ( (ucp[i] >= (unsigned char)0x1c) // Check for printable plus the Mic-E codes
+ || ((char)ucp[i] == '\0') ) // or terminating 0
+ ucp[j++] = ucp[i] ; // Copy to temp if printable
+ }
+}
+
+
+
+
+
+//--------------------------------------------------------------------
+//Removes all control codes ( <0x20 or >0x7e ) from a string, including
+// CR's, LF's, tab's, etc.
+//
+void makePrintable(char *cp) {
+ int i,j;
+ int len = (int)strlen(cp);
+ unsigned char *ucp = (unsigned char *)cp;
+
+ for (i=0, j=0; i<=len; i++) {
+ ucp[i] &= 0x7f; // Clear 8th bit
+ if ( ((ucp[i] >= (unsigned char)0x20) && (ucp[i] <= (unsigned char)0x7e))
+ || ((char)ucp[i] == '\0') ) // Check for printable or terminating 0
+ ucp[j++] = ucp[i] ; // Copy to (possibly) new location if printable
+ }
+}
+
+
+
+
+
+
+//----------------------------------------------------------------------
+// Implements safer mutex locking. Posix-compatible mutex's will lock
+// up a thread if lock's/unlock's aren't in perfect pairs. They also
+// allow one thread to unlock a mutex that was locked by a different
+// thread.
+// Remember to keep this thread-safe. Need dynamic storage (no statics)
+// and thread-safe calls.
+//
+// In order to keep track of process ID's in a portable way, we probably
+// can't use the process ID stored inside the pthread_mutex_t struct.
+// There's no easy way to get at it. For that reason we'll create
+// another struct that contains both the process ID and a pointer to
+// the pthread_mutex_t, and pass pointers to those structs around in
+// our programs instead. The new struct is "xastir_mutex".
+//
+
+
+// Function to initialize the new xastir_mutex
+// objects before use.
+//
+void init_critical_section(xastir_mutex *lock) {
+#ifdef MUTEX_DEBUG
+ pthread_mutexattr_t attr;
+
+ // Note that this stuff is not POSIX, so is considered non-portable.
+ // Exists in Linux Threads implementation only?
+
+# ifdef __LSB__
+ // LSB VERSION (Linux Standard Base)
+ // Note that we _must_ use the newer pthread function in this
+ // case per LSB specs.
+ (void)pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
+# else // __LSB__
+ // NON_LSB VERSION
+ // Check first for newer pthread function
+# ifdef HAVE_PTHREAD_MUTEXATTR_SETTYPE
+ (void)pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
+# else
+ // Use older, deprecated pthread function
+ (void)pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
+# endif // HAVE_PTHREAD_MUTEXATTR_SETTYPE
+# endif // __LSB__
+
+ (void)pthread_mutexattr_init(&attr);
+ (void)pthread_mutex_init(&lock->lock, &attr);
+#else // MUTEX_DEBUG
+ (void)pthread_mutex_init(&lock->lock, NULL); // Set to default POSIX-compatible type
+#endif // MUTEX_DEBUG
+
+ lock->threadID = 0; // No thread has locked it yet
+}
+
+
+
+
+
+// Function which uses xastir_mutex objects to lock a
+// critical shared section of code or variables. Makes
+// sure that only one thread can access the critical section
+// at a time. If there are no problems, it returns zero.
+//
+int begin_critical_section(xastir_mutex *lock, char *text) {
+ pthread_t calling_thread;
+ int problems;
+#ifdef MUTEX_DEBUG
+ int ret;
+#endif // MUTEX_DEBUG
+
+ problems = 0;
+
+ // Note that /usr/include/bits/pthreadtypes.h has the
+ // definition for pthread_mutex_t, and it includes the
+ // owner thread number: _pthread_descr pthread_mutex_t.__m_owner
+ // It's probably not portable to use it though.
+
+ // Get thread number we're currently running under
+ calling_thread = pthread_self();
+
+ if (pthread_equal( lock->threadID, calling_thread ))
+ {
+ // We tried to lock something that we already have the lock on.
+ fprintf(stderr,"%s:Warning:This thread already has the lock on this resource\n", text);
+ problems++;
+ return(0); // Return the OK code. Skip trying the lock.
+ }
+
+ //if (lock->threadID != 0)
+ //{
+ // We tried to lock something that another thread has the lock on.
+ // This is normal operation. The pthread_mutex_lock call below
+ // will put our process to sleep until the mutex is unlocked.
+ //}
+
+ // Try to lock it.
+#ifdef MUTEX_DEBUG
+ // Instead of blocking the thread, we'll loop here until there's
+ // no deadlock, printing out status as we go.
+ do {
+ ret = pthread_mutex_lock(&lock->lock);
+ if (ret == EDEADLK) { // Normal operation. At least two threads want this lock.
+ fprintf(stderr,"%s:pthread_mutex_lock(&lock->lock) == EDEADLK\n", text);
+ sched_yield(); // Yield the cpu to another thread
+ }
+ else if (ret == EINVAL) {
+ fprintf(stderr,"%s:pthread_mutex_lock(&lock->lock) == EINVAL\n", text);
+ fprintf(stderr,"Forgot to initialize the mutex object...\n");
+ problems++;
+ sched_yield(); // Yield the cpu to another thread
+ }
+ } while (ret == EDEADLK);
+
+ if (problems)
+ fprintf(stderr,"Returning %d to calling thread\n", problems);
+#else // MUTEX_DEBUG
+ pthread_mutex_lock(&lock->lock);
+#endif // MUTEX_DEBUG
+
+ // Note: This can only be set AFTER we already have the mutex lock.
+ // Otherwise there may be contention with other threads for setting
+ // this variable.
+ //
+ lock->threadID = calling_thread; // Save the threadID that we used
+ // to lock this resource
+
+ return(problems);
+}
+
+
+
+
+
+// Function which ends the locking of a critical section
+// of code. If there are no problems, it returns zero.
+//
+int end_critical_section(xastir_mutex *lock, char *text) {
+ pthread_t calling_thread;
+ int problems;
+#ifdef MUTEX_DEBUG
+ int ret;
+#endif // MUTEX_DEBUG
+
+ problems = 0;
+
+ // Get thread number we're currently running under
+ calling_thread = pthread_self();
+
+ if (lock->threadID == 0)
+ {
+ // We have a problem. This resource hasn't been locked.
+ fprintf(stderr,"%s:Warning:Trying to unlock a resource that hasn't been locked:%ld\n",
+ text,
+ (long int)lock->threadID);
+ problems++;
+ }
+
+ if (! pthread_equal( lock->threadID, calling_thread ))
+ {
+ // We have a problem. We just tried to unlock a mutex which
+ // a different thread originally locked. Not good.
+ fprintf(stderr,"%s:Trying to unlock a resource that a different thread locked originally: %ld:%ld\n",
+ text,
+ (long int)lock->threadID,
+ (long int)calling_thread);
+ problems++;
+ }
+
+
+ // We need to clear this variable BEFORE we unlock the mutex, 'cuz
+ // other threads might be waiting to lock the mutex.
+ //
+ lock->threadID = 0; // We're done with this lock.
+
+
+ // Try to unlock it. Compare the thread identifier we used before to make
+ // sure we should.
+
+#ifdef MUTEX_DEBUG
+ // EPERM error: We're trying to unlock something that we don't have a lock on.
+ ret = pthread_mutex_unlock(&lock->lock);
+
+ if (ret == EPERM) {
+ fprintf(stderr,"%s:pthread_mutex_unlock(&lock->lock) == EPERM\n", text);
+ problems++;
+ }
+ else if (ret == EINVAL) {
+ fprintf(stderr,"%s:pthread_mutex_unlock(&lock->lock) == EINVAL\n", text);
+ fprintf(stderr,"Someone forgot to initialize the mutex object\n");
+ problems++;
+ }
+
+ if (problems)
+ fprintf(stderr,"Returning %d to calling thread\n", problems);
+#else // MUTEX_DEBUG
+ (void)pthread_mutex_unlock(&lock->lock);
+#endif // MUTEX_DEBUG
+
+ return(problems);
+}
+
+
+
+
+
+#ifdef TIMING_DEBUG
+void time_mark(int start)
+{
+ static struct timeval t_start;
+ struct timeval t_cur;
+ long sec, usec;
+
+ if (start) {
+ gettimeofday(&t_start, NULL);
+ fprintf(stderr,"\nstart: 0.000000s");
+ }
+ else {
+ gettimeofday(&t_cur, NULL);
+ sec = t_cur.tv_sec - t_start.tv_sec;
+ usec = t_cur.tv_usec - t_start.tv_usec;
+ if (usec < 0) {
+ sec--;
+ usec += 1000000;
+ }
+ fprintf(stderr,"time: %ld.%06lds\n", sec, usec);
+ }
+}
+#endif // TIMING_DEBUG
+
+
+
+
+
+// Function which adds commas to callsigns (and other abbreviations?)
+// in order to make the text sound better when run through a Text-to-
+// Speech system. We try to change only normal amateur callsigns.
+// If we find a number in the text before a dash is found, we
+// consider it to be a normal callsign. We don't add commas to the
+// SSID portion of a call.
+void spell_it_out(char *text, int max_length) {
+ char buffer[2000];
+ int i = 0;
+ int j = 0;
+ int number_found_before_dash = 0;
+ int dash_found = 0;
+
+ while (text[i] != '\0') {
+
+ if (text[i] == '-')
+ dash_found++;
+
+ if (is_num_chr(text[i]) && !dash_found)
+ number_found_before_dash++;
+
+ buffer[j++] = text[i];
+
+ if (!dash_found) // Don't add commas to SSID
+ buffer[j++] = ',';
+
+ i++;
+ }
+ buffer[j] = '\0';
+
+ // Only use the new string if it kind'a looks like a callsign
+ if (number_found_before_dash)
+ xastir_snprintf(text, max_length, "%s", buffer);
+}
+
+
+
+
+
+#define kKey 0x73e2 // This is the seed for the key
+
+
+
+
+
+static short doHash(char *theCall) {
+ char rootCall[10]; // need to copy call to remove ssid from parse
+ char *p1 = rootCall;
+ short hash;
+ short i,len;
+ char *ptr = rootCall;
+
+ while ((*theCall != '-') && (*theCall != '\0')) *p1++ = toupper((int)(*theCall++));
+ *p1 = '\0';
+
+ hash = kKey; // Initialize with the key value
+ i = 0;
+ len = (short)strlen(rootCall);
+
+ while (i<len) {// Loop through the string two bytes at a time
+ hash ^= (unsigned char)(*ptr++)<<8; // xor high byte with accumulated hash
+ hash ^= (*ptr++); // xor low byte with accumulated hash
+ i += 2;
+ }
+ return (short)(hash & 0x7fff); // mask off the high bit so number is always positive
+}
+
+
+
+
+
+short checkHash(char *theCall, short theHash) {
+ return (short)(doHash(theCall) == theHash);
+}
+
+
+
+
+
+// Breaks up a string into substrings using an arbitrary character
+// as the delimiter. Makes each entry in the array of char ptrs
+// point to one substring. Modifies incoming string and cptr[]
+// array. Send a character constant string to it and you'll get an
+// instant segfault (the function can't modify a char constant
+// string). Use this function instead of strtok().
+//
+void split_string( char *data, char *cptr[], int max, char search_char ) {
+ int ii;
+ char *temp;
+ char *current = data;
+
+
+ // NULL each char pointer
+ for (ii = 0; ii < max; ii++) {
+ cptr[ii] = NULL;
+ }
+
+ // Save the beginning substring address
+ cptr[0] = current;
+
+ for (ii = 1; ii < max; ii++) {
+ temp = strchr(current,search_char); // Find next search character
+
+ if(!temp) { // No search characters found
+ return; // All done with string
+ }
+
+ // Store pointer to next substring in array
+ cptr[ii] = &temp[1];
+ current = &temp[1];
+
+ // Overwrite search character with end-of-string char and bump
+ // pointer by one.
+ temp[0] = '\0';
+ }
+}
+
+
+
+
+
+// Function to check for proper relations between the n-N
+// numbers. Called from check_unproto_path() function below.
+//
+int check_n_N (int prev, int last) {
+ int bad_path = 0;
+
+
+ if (prev < last) {
+ // Whoa, n < N, not good
+ bad_path = 1;
+ }
+ else if (last > MAX_WIDES) {
+ // N is greater than MAX_WIDES
+ bad_path = 1;
+ }
+ else if (prev > MAX_WIDES) {
+ // n is greater than MAX_WIDES
+ bad_path = 1;
+ }
+ else if (last == 0) {
+ // N is 0, it's a used-up digipeater slot
+ bad_path = 1;
+ }
+ if (debug_level & 1 && bad_path)
+ fprintf(stderr,"n-N wrong\n");
+
+ return(bad_path);
+}
+
+
+
+
+
+// This function checks to make sure an unproto path falls within
+// the socially acceptable values, such as only one RELAY or
+// WIDE1-1 which may appear only as the first option, use of WIDE4-4
+// and higher should be questioned, etc.
+//
+// "MAX_WIDES" is defined in util.h
+//
+// Returns:
+// 1 = bad path
+// 0 = good path
+//
+int check_unproto_path ( char *data ) {
+ char *tmpdata;
+ char *tmp;
+ char *ViaCalls[10];
+ int bad_path, ii, have_relay, have_wide, have_widen;
+ int have_trace, have_tracen;
+ int lastp = 0;
+ int prevp = 0;
+ int last = 0;
+ int prev = 0;
+ int total_digi_length = 0;
+
+
+ if (debug_level & 1)
+ fprintf(stderr, "Input string: %s\n", data);
+
+ bad_path = ii = have_relay = have_wide = 0;
+ have_widen = have_trace = have_tracen = 0;
+
+ // Remember to free() tmpdata before we return
+#ifdef HAVE_STRNDUP
+ tmpdata = (char *)strndup(data, strlen(data));
+#else
+ tmpdata = (char *)strdup(data);
+#endif
+ (void)to_upper(tmpdata);
+ if ((tmp = strchr(tmpdata, '/'))) *tmp ='\0';// Only check VHF portion of path
+ split_string(tmpdata, ViaCalls, 10, ',');
+
+ for (ii = 0; ii < 10; ii++) {
+ lastp = 0;
+ prevp = 0;
+ last = 0;
+ prev = 0;
+
+
+ // Check for empty string in this slot
+ if (ViaCalls[ii] == NULL) {
+ // We're done. Exit the loop with whatever flags were
+ // set in previous iterations.
+ if (debug_level & 1) {
+ fprintf(stderr,"NULL string, slot %d\n", ii);
+ }
+ break;
+ }
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"%s string, slot %d\n", ViaCalls[ii], ii);
+ }
+
+ lastp = strlen(ViaCalls[ii]) - 1;
+ prevp = lastp - 2;
+ // Snag the N character, convert to integer
+ last = ViaCalls[ii][lastp] - 0x30;
+
+ if (prevp >= 0) {
+ // Snag the n character, convert to integer
+ prev = ViaCalls[ii][prevp] - 0x30;
+ }
+
+ // Check whether RELAY appears later in the path
+ if (!strncmp(ViaCalls[ii], "RELAY", 5)) {
+ have_relay++;
+ total_digi_length++;
+ if (ii != 0) {
+ // RELAY should not appear after the first item in a
+ // path!
+ bad_path = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"RELAY appears later in the path\n");
+ break;
+ }
+ }
+
+ // Check whether WIDE1-1 appears later in the path (the new
+ // "RELAY")
+ else if (!strncmp(ViaCalls[ii], "WIDE1-1", 7)) {
+ have_relay++;
+ total_digi_length++;
+ if (ii != 0) {
+ // WIDE1-1 should not appear after the first item in
+ // a path!
+ bad_path = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"WIDE1-1 appears later in the path\n");
+ break;
+ }
+ }
+
+ // Check whether WIDE2-1 appears first in the path. This is
+ // fine, but don't trigger an error later because of another
+ // WIDEn-N after an initial WIDE2-1. This is to allow paths
+ // like "WIDE2-1,WIDE-2-2" or "WIDE2-1,MD2-2"
+ else if ( (ii == 0) && (!strncmp(ViaCalls[ii], "WIDE2-1", 7)) ) {
+ total_digi_length++;
+ if (debug_level & 1)
+ fprintf(stderr,"Found initial WIDE2-1 (a good thing)\n");
+ }
+
+ // Check for WIDE/TRACE/WIDEn-N/TRACEn-N in the path
+ else if (strstr(ViaCalls[ii], "WIDE") || strstr(ViaCalls[ii], "TRACE")) {
+ // This is some variant of WIDE or TRACE, could be
+ // WIDE/WIDEn-N/TRACE/TRACEn-N
+ int is_wide = 0;
+
+
+ if (strstr(ViaCalls[ii], "WIDE")) {
+ is_wide++;
+ }
+
+ // Check for WIDEn-N or TRACEn-N
+ if (strstr(ViaCalls[ii], "-")) {
+ // This is a WIDEn-N or TRACEn-N callsign
+
+
+ // Here we are adding the unused portion of the
+ // WIDEn-N/TRACEn-N to the total_digi_length
+ // variable. We use the unused portion because that
+ // way we're not fooled if people start with a
+ // number for N that is higher/lower than n. The
+ // initial thought was to grab the higher of n or N,
+ // but those lines are commented out here.
+ //
+ //if (last > prev)
+ total_digi_length += last;
+ //else
+ // total_digi_length += prev;
+
+
+ // Check for previous WIDEn-N/TRACEn-N
+ if (have_widen || have_tracen) {
+ // Already have a large area via
+ bad_path = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"Previous WIDEn-N or TRACEn-N\n");
+ break;
+ }
+
+ // Perform WIDEn-N checks
+ if (is_wide) {
+ if (debug_level & 1)
+ fprintf(stderr,"Found wideN-n at slot %d\n", ii);
+
+ if (strcmp(ViaCalls[ii], "WIDE1-1") !=0) // Home station, RELAY replacement
+ have_widen++; // Note: We mark "have_relay" for
+ // "WIDE1-1" instead of "have_widen"
+
+ // We know its a WIDEn-N, time to find out what n is
+ if (strlen(ViaCalls[ii]) != 7) {
+ // This should be WIDEn-N and should be
+ // exactly 7 characters
+ bad_path = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"String length of widen-N is not 7 characters, slot %d\n", ii);
+ break;
+ }
+
+ // Check for proper relations between the n-N
+ // numbers.
+ if ( check_n_N(prev, last) ) {
+ bad_path = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"In WIDEn-N checks, slot %d\n", ii);
+ break;
+ }
+ }
+
+ // Perform similar checks for TRACEn-N
+ else {
+ if (debug_level & 1)
+ fprintf(stderr,"Found traceN-n, slot %d\n", ii);
+ have_tracen++;
+
+ // We know its a TRACEn-N time to find out what
+ // n is
+ if (strlen(ViaCalls[ii]) != 8) {
+ // This should be TRACEn-N and should be
+ // exactly 8 characters
+ bad_path = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"String length of tracen-N is not 8 characters, slot %d\n", ii);
+ break;
+ }
+
+ // Check for proper relations between the n-N
+ // numbers.
+ if ( check_n_N(prev, last) ) {
+ bad_path = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"In TRACEn-N checks, slot %d\n", ii);
+ break;
+ }
+ }
+
+ }
+
+ else {
+ // We know we have a WIDE or TRACE in this callsign slot
+ total_digi_length++;
+ if (is_wide) {
+ have_wide++;
+ }
+ else {
+ have_trace++;
+ }
+
+ if (have_relay && (ii > MAX_WIDES)) {
+ // RELAY and more than "MAX_WIDES" WIDE/TRACE calls
+// Here we could check have_wide/have_trace to see what the actual
+// count of WIDE/TRACE calls is at this point...
+ bad_path = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"Have relay and ii > MAX_WIDES\n");
+ break;
+ }
+ else if (!have_relay && ii > (MAX_WIDES - 1)) {
+ // More than WIDE,WIDE,WIDE or TRACE,TRACE,TRACE
+// Here we could check have_wide/have_trace to see what the actual
+// count of WIDE/TRACE calls is at this point...
+ bad_path = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"No relay, but ii > MAX_WIDES-1\n");
+ break;
+ }
+ else if (have_widen || have_tracen) {
+ // WIDE/TRACE after something other than RELAY
+ // or WIDE1-1
+ bad_path = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"WIDE or TRACE after something other than RELAY or WIDE1-1\n");
+ break;
+ }
+ }
+ }
+
+ // Not RELAY/WIDE/TRACE/WIDEn-N/TRACEn-N call
+ else {
+ // Might as well stub this out, could be anything at
+ // this point, a LINKn-N or LANn-N or a explicit
+ // callsign
+ if (!strstr(ViaCalls[ii], "-")) {
+/*
+ // We do not have an SSID, treat it as a RELAY
+ if (have_relay) {
+ bad_path = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"No SSID\n");
+ break;
+ }
+*/
+
+ have_relay++;
+ }
+
+ else {
+ // Could be a LAN or LINK or explicit call, check
+ // for a digit preceding the dash
+
+ if (prev > 0 && prev <= 9) { // Found a digit
+ // We've found an n-N */
+ if (have_widen || have_tracen) {
+ // Already have a previous wide path
+ bad_path = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"Found n-N and previous WIDEn-N or TRACEn-N\n");
+ break;
+ }
+
+ // Check for proper relations between the n-N
+ // numbers.
+ if ( check_n_N(prev, last) ) {
+ bad_path = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"In OTHER checks\n");
+ break;
+ }
+
+ if (debug_level & 1)
+ fprintf(stderr,"Found wideN-n, slot %d\n", ii);
+ have_widen++;
+ }
+ else {
+/*
+ // Must be an explicit callsign, treat as relay
+ if (have_relay) {
+ bad_path = 1;
+ if (debug_level & 1)
+ fprintf(stderr,"\n");
+ break;
+ }
+*/
+ have_relay++;
+ }
+ }
+ }
+ } // End of for loop
+
+ if (debug_level & 1)
+ fprintf(stderr,"Total digi length: %d\n", total_digi_length);
+
+ if (total_digi_length > MAX_WIDES + 1) {
+
+ if (debug_level & 1)
+ fprintf(stderr,"Total digi count is too high!\n");
+
+ bad_path = 1;
+ }
+
+ // Free the memory we allocated with strndup()
+ free(tmpdata);
+ return(bad_path);
+
+} // End of check_unproto_path
+
+
+
+
+
+// Set string printed out by segfault handler
+void set_dangerous( char *ptr ) {
+ xastir_snprintf(dangerous_operation,
+ sizeof(dangerous_operation),
+ "%s",
+ ptr);
+}
+
+
+
+
+
+// Clear string printed out by segfault handler
+void clear_dangerous(void) {
+ dangerous_operation[0] = '\0';
+}
+
+
+
+
+
+// Write out a WKT file
+void xastirWriteWKT(char *filename)
+{
+ // This "WKT" string describes the coordinate system we use in Xastir.
+ // We'll use this string to write out ".prj" files to associate with
+ // shapefiles we create from GPS or APRS tracks.
+ char Xastir_WKT[] = "GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.017453292519943295]]";
+
+ FILE *f;
+
+ f=fopen(filename,"w"); // open for write
+ if (f != NULL) {
+ fprintf(f,"%s\n",Xastir_WKT);
+ fclose(f);
+ } else {
+ fprintf(stderr,"Could not open file %s for writing\n",filename);
+ }
+}
+
+
+
+
+
+// makeMultiline
+// Create an APRS multiline string given an array of lat/lon pairs.
+//
+// Allocates memory that must be freed by the caller.
+//
+// lon and lat are arrays. lonObj, latObj are return values of object
+// location (point from which offsets are computed).
+//
+// lineType is 0 for a closed polygon, 1 for a polyline
+//
+// colorStyle is a character as defined in the wxsvr.net multiline protocol
+// web site at wxsvr.net.
+//
+// character | color | style
+// a red solid
+// b red dashed
+// c red double-dashed
+// d yellow solid
+// e yellow dashed
+// f yellow double-dashed
+// g blue solid
+// h blue dashed
+// i blue double-dashed
+// j green solid
+// k green dashed
+// l green double-dashed
+
+// Returns a null pointer if user requested too many vertices, or if scale
+// is out of range, or if we fail to malloc the string.
+//
+// One could pass only a list of lat/lons here and get back a point at which
+// to create an object (at the centroid) and a string representing the
+// multiline.
+#define minFun(a,b) ( ((a)<(b))?(a):(b))
+#define maxFun(a,b) ( ((a)>(b))?(a):(b))
+
+char * makeMultiline(int numPairs, double *lon, double *lat, char colorStyle,
+ int lineType, char* sqnc,
+ double *lonCentr, double *latCentr )
+{
+
+ char * returnString;
+
+ // the APRS spec requires a max of 43 chars in the comment section of
+ // objects, which leaves room for only so many vertices in a multiline
+ // number allowed= (43-(6-5))/2=16
+ // 43chars - 6 for the sequence number- 5 for the starting pattern leaves
+ // 32 characters for lat/lon pairs, or 16 pairs
+
+ if ( numPairs > 16) {
+ returnString = NULL;
+ } else {
+ double minLat, minLon;
+ double maxLat, maxLon;
+ int iPair;
+ double scale1,scale2,scale;
+
+ // find min/max of arrays
+ minLat=minLon=180;
+ maxLat=maxLon=-180;
+
+ for ( iPair=0; iPair < numPairs; iPair++) {
+ minLon = minFun(minLon,lon[iPair]);
+ minLat = minFun(minLat,lat[iPair]);
+ maxLon = maxFun(maxLon,lon[iPair]);
+ maxLat = maxFun(maxLat,lat[iPair]);
+ }
+
+ *lonCentr = (maxLon+minLon)/2;
+ *latCentr = (maxLat+minLat)/2;
+
+ // Compute scale:
+ // The scale is the value that makes the maximum or minimum offset
+ // map to +44 or -45. Pick the scale factor that keeps the
+ // offsets in that range:
+
+ if (maxLat > maxLon) {
+ scale1= (maxLat-*latCentr)/44.0;
+ } else {
+ scale1= (maxLon-*lonCentr)/44.0;
+ }
+
+ if (minLat < minLon) {
+ scale2 = (minLat-*latCentr)/(-45.0);
+ } else {
+ scale2 = (minLon-*lonCentr)/(-45.0);
+ }
+
+ scale = maxFun(scale1,scale2);
+
+ if (scale < .0001) {
+ scale=0.0001;
+ }
+
+ if (scale > 1) {
+ // Out of range, no shape returned
+ returnString = NULL;
+ } else {
+ // Not all systems have a log10(), but they all have log()
+ // So let's stick with natural logs
+ double ln10=log(10.0);
+ // KLUDGE: the multiline spec says we use
+ // 20*(int)(log10(scale/.0001)) to generate the scale char,
+ // but this means we'll often produce real scales that are smaller
+ // than the one we just calculated, which means we'd produce
+ // offsets outside the (-45,44) allowed range. So kludge and
+ // add 1 to the value
+ int lnscalefac=20*log(scale/.0001)/ln10+1;
+ int rsMaxLen=numPairs*2+6+4+1;
+ int stringOffset=0;
+
+ // Now recompute the scale to be the one we actually transmitted
+ // This pretty much means we'll never have the best precision
+ // we could possibly have, but it'll be close enough
+ scale=pow(10,(double)lnscalefac/20-4);
+
+ // We're ready to produce the multiline string. So get on with it
+
+ // multiline string is "}CTS" (literal "}" followed by
+ // line Color-style specifier, followed by open/closed
+ // Type specifier, followed by Scale character), followed
+ // by even number of character pairs, followed by "{seqnc"
+ // (sequence number).
+
+
+ returnString=malloc(sizeof(char)*rsMaxLen);
+
+ if (returnString != NULL) {
+ returnString[stringOffset++]=' ';
+ returnString[stringOffset++]='}';
+ returnString[stringOffset++]=colorStyle;
+ returnString[stringOffset++]= (lineType == 0)?'0':'1';
+
+ returnString[stringOffset++] = lnscalefac+33;
+
+ for ( iPair=0; iPair<numPairs; ++iPair) {
+ double latOffset=lat[iPair]-*latCentr;
+ // the wxsvr protocol is Western Hemisphere-Centric,
+ // and treats positive offsets in longitude as being
+ // west of the reference point. So have to reverse
+ // the sense of direction here.
+ // This will yield positive offsets if lonCenter is
+ // negative (west) and lon[iPair] is more negative
+ // (more west)
+ double lonOffset=*lonCentr-lon[iPair];
+
+ returnString[stringOffset++]=
+ (char)((int)(latOffset/scale)+78);
+ returnString[stringOffset++]=
+ (char)((int)(lonOffset/scale)+78);
+ }
+ returnString[stringOffset++]='{';
+ strncpy(&(returnString[stringOffset]),sqnc,6);
+ returnString[rsMaxLen-1] = '\0'; // Just to be safe
+ }
+ }
+ }
+ return (returnString);
+}
+
+
diff --git a/src/util.h b/src/util.h
new file mode 100644
index 0000000..774eee4
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,179 @@
+/*
+ * $Id: util.h,v 1.63 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifndef __XASTIR_UTIL_H
+#define __XASTIR_UTIL_H
+
+#include "database.h"
+#include <pthread.h>
+#include "hashtable.h"
+
+// Max number of WIDE digipeaters allowed
+#define MAX_WIDES 3
+
+static __inline__ short l16(long val) {
+ // This limits large integer values to the 16 bit range for X
+ // drawing
+ if (val < -32768) val = -32768;
+ if (val > 32767) val = 32767;
+ return (short)val;
+}
+
+static __inline__ unsigned short lu16(long val) {
+ // This limits large unsigned integer values to the 16 bit range
+ // for X drawing
+ if (val < 0) val = 0;
+ if (val > 65535) val = 65535;
+ return (unsigned short)val;
+}
+
+extern int convert_from_xastir_coordinates ( float *f_longitude,
+ float *f_latitude,
+ long x,
+ long y );
+extern int convert_to_xastir_coordinates (unsigned long* x,
+ unsigned long* y,
+ float f_longitude,
+ float f_latitude);
+extern char *get_tactical_from_hash(char *callsign);
+extern void destroy_tactical_hash(void);
+extern void xastir_debug(int my_debug_level, char *debug_string);
+extern char *remove_all_spaces(char *data);
+extern char *remove_leading_spaces(char *data);
+extern char *remove_trailing_spaces(char *data);
+extern char *remove_trailing_asterisk(char *data);
+extern char *remove_trailing_dash_zero(char *data);
+extern int position_amb_chars;
+extern void start_timer(void);
+extern void stop_timer(void);
+extern void print_timer_results(void);
+extern void get_timestamp(char *timestring);
+extern int get_iso_datetime(time_t aTime, char *timestring, int nowIfNotSet, int nowIfInvalid);
+extern int get_w3cdtf_datetime(time_t aTime, char *timestring,int nowIfNotSet, int nowIfInvalid);
+extern int get_hours(void);
+extern int get_minutes(void);
+extern int get_seconds(void);
+extern char *output_lat(char *in_lat, int comp_pos);
+extern char *output_long(char *in_long, int comp_pos);
+extern double phg_range(char p, char h, char g);
+extern double shg_range(char s, char h, char g);
+extern void phg_decode(const char *langstr, const char *phg, char *phg_decoded, int phg_decoded_length);
+extern void shg_decode(const char *langstr, const char *shg, char *shg_decoded, int shg_decoded_length);
+extern void bearing_decode(const char *langstr, const char *bearing_str, const char *NRQ, char *bearing_decoded, int bearing_decoded_length);
+extern char *get_line(FILE *f, char *linedata, int maxline);
+extern time_t time_from_aprsstring(char *timestamp);
+extern char *compress_posit(const char *lat, const char group, const char *lon, const char symbol,
+ const unsigned int course, const unsigned int speed, const char *phg);
+
+extern int position_defined(long lat, long lon, int strict);
+extern void convert_screen_to_xastir_coordinates(int x, int y, long *lat, long *lon);
+extern void convert_xastir_to_UTM_str(char *str, int str_len, long x, long y);
+extern void convert_xastir_to_MGRS_str_components(char *utmZone, int utmZone_len,
+ char *EastingL, int EastingL_len,
+ char *NorthingL, int NorthingL_len,
+ unsigned int *int_utmEasting, unsigned int *int_utmNorthing,
+ long x, long y,
+ int nice_format, char *space_string, int space_string_len);
+extern void convert_xastir_to_MGRS_str(char *str, int str_len, long x, long y, int nice_format);
+extern void convert_xastir_to_UTM(double *easting, double *northing, char *zone, int zone_len, long x, long y);
+extern void convert_UTM_to_xastir(double easting, double northing, char *zone, long *x, long *y);
+extern double convert_lat_l2r(long lat);
+extern double convert_lon_l2r(long lon);
+extern void convert_lat_l2s(long lat, char *str, int str_len, int type);
+extern void convert_lon_l2s(long lon, char *str, int str_len, int type);
+extern long convert_lat_s2l(char *lat);
+extern long convert_lon_s2l(char *lon);
+
+extern double calc_distance(long lat1, long lon1, long lat2, long lon2);
+extern double calc_distance_course(long lat1, long lon1, long lat2, long lon2, char *course_deg, int course_deg_length);
+extern double distance_from_my_station(char *call_sign, char *course_deg);
+
+extern char *convert_bearing_to_name(char *bearing, int opposite);
+
+extern void compute_DR_position(long x_long, long y_lat, double range, double course, long *x_long2, long *y_lat2);
+extern void compute_current_DR_position(DataRow *p_station, long *x_long, long *y_lat);
+
+extern int filethere(char *fn);
+extern int filecreate(char *fn);
+extern int copy_file(char *infilename, char *outfilename);
+extern time_t file_time(char *fn);
+extern void load_wx_alerts_from_log(void);
+extern void log_data(char *file, char *line);
+extern void log_tactical_call(char *call_sign, char *tactical_call_sign);
+extern void reload_tactical_calls(void);
+extern time_t sec_now(void);
+extern char *get_time(char *time_here);
+
+extern void substr(char *dest, char *src, int size);
+extern int valid_path(char *path);
+extern int valid_call(char *call);
+extern int valid_inet_name(char *name, char *info, char *origin, int origin_size);
+
+extern char echo_digis[6][9+1];
+extern void upd_echo(char *path);
+
+extern char *to_upper(char *data);
+extern char *to_lower(char *data);
+extern int is_num_chr(char ch);
+extern int is_num_or_sp(char ch);
+extern int is_xnum_or_dash(char *data, int max);
+extern void removeCtrlCodes(char *cp);
+extern void makePrintable(char *cp);
+extern void spell_it_out(char *text, int max_length);
+
+typedef struct
+{
+ pthread_mutex_t lock;
+ pthread_t threadID;
+} xastir_mutex;
+
+extern void init_critical_section(xastir_mutex *lock);
+extern int begin_critical_section(xastir_mutex *lock, char *text);
+extern int end_critical_section(xastir_mutex *lock, char *text);
+
+//#define TIMING_DEBUG
+#ifdef TIMING_DEBUG
+void time_mark(int start);
+#endif // TIMING_DEBUG
+
+// dl9sau
+extern char *sec_to_loc(long longitude, long latitude);
+
+extern short checkHash(char *theCall, short theHash);
+
+extern void split_string ( char *data, char *cptr[], int max, char search_char );
+extern int check_unproto_path( char *data );
+
+extern void set_dangerous( char *ptr );
+extern void clear_dangerous(void);
+
+void xastirWriteWKT(char *name);
+char * makeMultiline(int numPairs, double *lon, double *lat, char colorStyle,
+ int lineType, char* sqnc,
+ double *lonCentr, double *latCentr );
+
+#endif // __XASTIR_UTIL_H
+
+
diff --git a/src/view_message_gui.c b/src/view_message_gui.c
new file mode 100644
index 0000000..c6d96a2
--- /dev/null
+++ b/src/view_message_gui.c
@@ -0,0 +1,732 @@
+/*
+ * $Id: view_message_gui.c,v 1.43 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <Xm/XmAll.h>
+#include <X11/Xatom.h>
+#include <X11/Shell.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+#include <ctype.h>
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+#include "xastir.h"
+#include "main.h"
+#include "util.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+extern XmFontList fontlist1; // Menu/System fontlist
+
+Widget All_messages_dialog = NULL;
+Widget view_messages_text = NULL;
+Widget vm_dist_data = NULL;
+
+static xastir_mutex All_messages_dialog_lock;
+
+int vm_range;
+int view_message_limit = 10000;
+int Read_messages_packet_data_type = 0; // 1=tnc_only, 2=net_only, 0=tnc&net
+int Read_messages_mine_only = 0;
+
+
+
+
+
+void view_message_gui_init(void)
+{
+ init_critical_section( &All_messages_dialog_lock );
+}
+
+
+
+
+
+void view_message_print_record(Message *m_fill) {
+ int pos;
+ char *temp;
+ int i;
+ int my_size = 200;
+ char temp_my_course[10];
+ XmTextPosition drop_ptr;
+ int distance;
+
+
+ // Make sure it's within our distance range we have set
+ distance = (int)distance_from_my_station(m_fill->from_call_sign,temp_my_course);
+
+ if (Read_messages_mine_only
+ || (!Read_messages_mine_only
+ && ( (vm_range == 0) || (distance <= vm_range) ) ) ) {
+
+ // Check that it's coming from the correct type of interface
+ // Compare Read_messages_packet_data_type against the port
+ // type associated with data_port to determine whether or
+ // not to display it.
+ //
+ // I = Internet
+ // L = Local
+ // T = TNC
+ // F = File
+ //
+ switch (Read_messages_packet_data_type) {
+
+ case 2: // Display NET data only
+ // if not network_interface, return
+ if (m_fill->data_via != 'I')
+ return; // Don't display it
+ break;
+
+ case 1: // Display TNC data only
+ // if not local_tnc_interface, return
+ if (m_fill->data_via != 'T')
+ return; // Don't display it
+ break;
+
+ case 0: // Display both TNC and NET data
+ default:
+ break;
+ }
+
+ // Check for my stations only if set
+ if (Read_messages_mine_only) {
+ char short_call[MAX_CALLSIGN];
+ char *p;
+
+ xastir_snprintf(short_call,
+ sizeof(short_call),
+ "%s",
+ my_callsign);
+ if ( (p = index(short_call,'-')) ) {
+ *p = '\0'; // Terminate it
+ }
+
+ if (!strstr(m_fill->call_sign, short_call)
+ && !strstr(m_fill->from_call_sign, short_call)) {
+ return;
+ }
+ }
+
+ if ((temp = malloc((size_t)my_size)) == NULL)
+ return;
+
+ sprintf(temp,"%-9s>%-9s %s:%5s %s:%c :%s\n",
+ m_fill->from_call_sign,
+ m_fill->call_sign,
+ langcode("WPUPMSB013"),
+ m_fill->seq,
+ langcode("WPUPMSB014"),
+ m_fill->type,
+ m_fill->message_line);
+
+ pos = (int)XmTextGetLastPosition(view_messages_text);
+
+
+ XmTextInsert(view_messages_text, pos, temp);
+ pos += strlen(temp);
+ while (pos > view_message_limit) {
+ for (drop_ptr = i = 0; i < 3; i++) {
+ (void)XmTextFindString(view_messages_text, drop_ptr, "\n", XmTEXT_FORWARD, &drop_ptr);
+ drop_ptr++;
+ }
+ XmTextReplace(view_messages_text, 0, drop_ptr, "");
+ pos = (int)XmTextGetLastPosition(view_messages_text);
+ }
+ XtVaSetValues(view_messages_text, XmNcursorPosition, pos, NULL);
+
+ free(temp);
+ }
+}
+
+
+
+
+
+void view_message_display_file(char msg_type) {
+ int pos;
+
+ if ((All_messages_dialog != NULL)) {
+ mscan_file(msg_type, view_message_print_record);
+ }
+ pos = (int)XmTextGetLastPosition(view_messages_text);
+ XmTextShowPosition(view_messages_text, pos);
+}
+
+
+
+
+
+void all_messages(char from, char *call_sign, char *from_call, char *message) {
+ char temp_my_course[10];
+ char *temp;
+ char data1[97];
+ char data2[97];
+ int pos;
+ int i;
+ int my_size = 200;
+ XmTextPosition drop_ptr;
+
+
+ if (Read_messages_mine_only
+ || (!Read_messages_mine_only
+ && ((vm_range == 0)
+ || ((int)distance_from_my_station(call_sign,temp_my_course) <= vm_range)) ) ) {
+
+ // Check that it's coming from the correct type of interface
+ // Compare Read_messages_packet_data_type against the port
+ // type associated with data_port to determine whether or
+ // not to display it.
+ //
+ // I = Internet
+ // L = Local
+ // T = TNC
+ // F = File
+ //
+ switch (Read_messages_packet_data_type) {
+
+ case 2: // Display NET data only
+ // if not network_interface, return
+ if (from != 'I')
+ return; // Don't display it
+ break;
+
+ case 1: // Display TNC data only
+ // if not local_tnc_interface, return
+ if (from != 'T')
+ return; // Don't display it
+ break;
+
+ case 0: // Display both TNC and NET data
+ default:
+ break;
+ }
+
+ // Check for my stations only if set
+ if (Read_messages_mine_only) {
+ char short_call[MAX_CALLSIGN];
+ char *p;
+
+ xastir_snprintf(short_call,
+ sizeof(short_call),
+ "%s",
+ my_callsign);
+ if ( (p = index(short_call,'-')) ) {
+ *p = '\0'; // Terminate it
+ }
+
+ if (!strstr(call_sign, short_call)
+ && !strstr(from_call, short_call)) {
+ return;
+ }
+ }
+
+ if ((temp = malloc((size_t)my_size)) == NULL)
+ return;
+
+ if (strlen(message)>95) {
+ xastir_snprintf(data1,
+ sizeof(data1),
+ "%s",
+ message);
+ data1[95]='\0';
+ xastir_snprintf(data2,
+ sizeof(data2),
+ "\n\t%s",
+ message+95);
+ } else {
+ xastir_snprintf(data1,
+ sizeof(data1),
+ "%s",
+ message);
+ data2[0] = '\0';
+ }
+
+ if (strncmp(call_sign, "java",4) == 0) {
+ xastir_snprintf(call_sign,
+ MAX_CALLSIGN+1,
+ "%s", langcode("WPUPMSB015") ); // Broadcast
+ xastir_snprintf(temp,
+ my_size,
+ "%s %s\t%s%s\n",
+ from_call,
+ call_sign,
+ data1,
+ data2);
+ } else if (strncmp(call_sign, "USER", 4) == 0) {
+ xastir_snprintf(call_sign,
+ MAX_CALLSIGN+1,
+ "%s", langcode("WPUPMSB015") ); // Broadcast
+ xastir_snprintf(temp,
+ my_size,
+ "%s %s\t%s%s\n",
+ from_call,
+ call_sign,
+ data1,
+ data2);
+ } else
+ xastir_snprintf(temp,
+ my_size,
+ "%s to %s via:%c\t%s%s\n",
+ from_call,
+ call_sign,
+ from,
+ data1,
+ data2);
+
+ if ((All_messages_dialog != NULL)) {
+
+begin_critical_section(&All_messages_dialog_lock, "view_message_gui.c:all_messages" );
+
+ pos = (int)XmTextGetLastPosition(view_messages_text);
+ XmTextInsert(view_messages_text, pos, temp);
+ pos += strlen(temp);
+ while (pos > view_message_limit) {
+ for (drop_ptr = i = 0; i < 3; i++) {
+ (void)XmTextFindString(view_messages_text, drop_ptr, "\n", XmTEXT_FORWARD, &drop_ptr);
+ drop_ptr++;
+ }
+ XmTextReplace(view_messages_text, 0, drop_ptr, "");
+ pos = (int)XmTextGetLastPosition(view_messages_text);
+ }
+ XtVaSetValues(view_messages_text, XmNcursorPosition, pos, NULL);
+ XmTextShowPosition(view_messages_text, pos);
+
+end_critical_section(&All_messages_dialog_lock, "view_message_gui.c:all_messages" );
+
+ }
+ free(temp);
+ }
+}
+
+
+
+
+
+void All_messages_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ char *temp_ptr;
+
+
+ temp_ptr = XmTextFieldGetString(vm_dist_data);
+ vm_range = atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ XtPopdown(shell);
+
+begin_critical_section(&All_messages_dialog_lock, "view_message_gui.c:All_messages_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ All_messages_dialog = (Widget)NULL;
+
+end_critical_section(&All_messages_dialog_lock, "view_message_gui.c:All_messages_destroy_shell" );
+
+}
+
+
+
+
+
+void All_messages_change_range( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget shell = (Widget) clientData;
+ char *temp_ptr;
+
+
+ temp_ptr = XmTextFieldGetString(vm_dist_data);
+ vm_range = atoi(temp_ptr);
+ XtFree(temp_ptr);
+
+ XtPopdown(shell);
+
+ All_messages_destroy_shell(widget, clientData, callData);
+ view_all_messages(widget, clientData, callData);
+}
+
+
+
+
+
+void Read_messages_packet_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set)
+ Read_messages_packet_data_type = atoi(which);
+ else
+ Read_messages_packet_data_type = 0;
+}
+
+
+
+
+
+Widget button_range;
+
+
+
+
+
+void Read_messages_mine_only_toggle( /*@unused@*/ Widget widget, XtPointer clientData, XtPointer callData) {
+ char *which = (char *)clientData;
+ XmToggleButtonCallbackStruct *state = (XmToggleButtonCallbackStruct *)callData;
+
+ if(state->set) {
+ Read_messages_mine_only = atoi(which);
+ XtSetSensitive(vm_dist_data, FALSE);
+ }
+ else {
+ Read_messages_mine_only = 0;
+ XtSetSensitive(vm_dist_data, TRUE);
+ }
+}
+
+
+
+
+
+void view_all_messages( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ Widget pane, my_form, button_close, dist, dist_units;
+ Widget option_box, tnc_data, net_data, tnc_net_data,
+ read_mine_only_button;
+ unsigned int n;
+#define NCNT 50
+#define IncN(n) if (n< NCNT) n++; else fprintf(stderr, "Oops, too many arguments for array!\a")
+ Arg args[NCNT];
+ Atom delw;
+ char temp[10];
+
+ if (!All_messages_dialog) {
+
+begin_critical_section(&All_messages_dialog_lock, "view_message_gui.c:view_all_messages" );
+
+ All_messages_dialog = XtVaCreatePopupShell(langcode("AMTMW00001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("view_all_messages pane",
+ xmPanedWindowWidgetClass,
+ All_messages_dialog,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ my_form = XtVaCreateWidget("view_all_messages my_form",
+ xmFormWidgetClass,
+ pane,
+ XmNfractionBase, 5,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ NULL);
+
+ dist = XtVaCreateManagedWidget(langcode("AMTMW00002"),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtraversalOn, FALSE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ vm_dist_data = XtVaCreateManagedWidget("view_all_messages dist_data",
+ xmTextFieldWidgetClass,
+ my_form,
+ XmNeditable, TRUE,
+ XmNcursorPositionVisible, TRUE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 8,
+ XmNwidth, ((8*7)+2),
+ XmNmaxLength, 8,
+ XmNbackground, colors[0x0f],
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, dist,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ dist_units = XtVaCreateManagedWidget((english_units?langcode("UNIOP00004"):langcode("UNIOP00005")),
+ xmLabelWidgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, vm_dist_data,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtraversalOn, FALSE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ button_range = XtVaCreateManagedWidget(langcode("BULMW00003"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, dist_units,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_range, XmNactivateCallback, All_messages_change_range, All_messages_dialog);
+
+ button_close = XtVaCreateManagedWidget(langcode("UNIOP00003"),
+ xmPushButtonGadgetClass,
+ my_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, button_range,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNnavigationType, XmTAB_GROUP,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_close, XmNactivateCallback, All_messages_destroy_shell, All_messages_dialog);
+
+ n=0;
+ XtSetArg(args[n],XmNforeground, MY_FG_COLOR); n++;
+ XtSetArg(args[n],XmNbackground, MY_BG_COLOR); n++;
+ XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
+ XtSetArg(args[n], XmNtopWidget, dist); n++;
+ XtSetArg(args[n], XmNtopOffset, 5); n++;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_NONE); n++;
+ XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNleftOffset, 5); n++;
+ XtSetArg(args[n], XmNrightAttachment, XmATTACH_NONE); n++;
+ XtSetArg(args[n], XmNfontList, fontlist1); n++;
+
+ option_box = XmCreateRadioBox(my_form,
+ "Vew Messages option box",
+ args,
+ n);
+
+ XtVaSetValues(option_box,
+ XmNpacking, XmPACK_TIGHT,
+ XmNorientation, XmHORIZONTAL,
+ NULL);
+
+ tnc_data = XtVaCreateManagedWidget(langcode("WPUPDPD002"),
+ xmToggleButtonGadgetClass,
+ option_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(tnc_data,XmNvalueChangedCallback,Read_messages_packet_toggle,"1");
+
+ net_data = XtVaCreateManagedWidget(langcode("WPUPDPD003"),
+ xmToggleButtonGadgetClass,
+ option_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(net_data,XmNvalueChangedCallback,Read_messages_packet_toggle,"2");
+
+ tnc_net_data = XtVaCreateManagedWidget(langcode("WPUPDPD004"),
+ xmToggleButtonGadgetClass,
+ option_box,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(tnc_net_data,XmNvalueChangedCallback,Read_messages_packet_toggle,"0");
+
+ read_mine_only_button = XtVaCreateManagedWidget(langcode("WPUPDPD008"),
+ xmToggleButtonGadgetClass,
+ my_form,
+ XmNvisibleWhenOff, TRUE,
+ XmNindicatorSize, 12,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, dist,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, option_box,
+ XmNleftOffset, 20,
+ XmNrightAttachment, XmATTACH_NONE,
+ MY_FOREGROUND_COLOR,
+ MY_BACKGROUND_COLOR,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(read_mine_only_button,XmNvalueChangedCallback,Read_messages_mine_only_toggle,"1");
+
+ n=0;
+ XtSetArg(args[n], XmNrows, 15); IncN(n);
+ XtSetArg(args[n], XmNcolumns, 85); IncN(n);
+ XtSetArg(args[n], XmNeditable, FALSE); IncN(n);
+ XtSetArg(args[n], XmNtraversalOn, TRUE); IncN(n);
+ XtSetArg(args[n], XmNlistSizePolicy, XmVARIABLE); IncN(n);
+ XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); IncN(n);
+ XtSetArg(args[n], XmNwordWrap, TRUE); IncN(n);
+ XtSetArg(args[n], XmNscrollHorizontal, TRUE); IncN(n);
+ XtSetArg(args[n], XmNscrollVertical, TRUE); IncN(n);
+// XtSetArg(args[n], XmNscrollBarDisplayPolicy, XmSTATIC); IncN(n);
+ XtSetArg(args[n], XmNselectionPolicy, XmMULTIPLE_SELECT); IncN(n);
+ XtSetArg(args[n], XmNcursorPositionVisible, FALSE); IncN(n);
+ XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); IncN(n);
+ XtSetArg(args[n], XmNtopWidget, option_box); IncN(n);
+ XtSetArg(args[n], XmNtopOffset, 5); IncN(n);
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); IncN(n);
+ XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); IncN(n);
+ XtSetArg(args[n], XmNleftOffset, 5); IncN(n);
+ XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); IncN(n);
+ XtSetArg(args[n], XmNrightOffset, 5); IncN(n);
+ XtSetArg(args[n], XmNforeground, MY_FG_COLOR); IncN(n);
+ XtSetArg(args[n], XmNbackground, MY_BG_COLOR); IncN(n);
+ XtSetArg(args[n], XmNfontList, fontlist1); n++;
+
+ view_messages_text = XmCreateScrolledText(my_form,
+ "view_all_messages text",
+ args,
+ n);
+
+// It's hard to get tab groups working with ScrolledText widgets. Tab'ing in is
+// fine, but then I'm stuck in insert mode and it absorbs the tabs and beeps.
+
+ pos_dialog(All_messages_dialog);
+
+ delw = XmInternAtom(XtDisplay(All_messages_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(All_messages_dialog, delw, All_messages_destroy_shell, (XtPointer)All_messages_dialog);
+
+ sprintf(temp,"%d",vm_range);
+ XmTextFieldSetString(vm_dist_data,temp);
+
+ switch (Read_messages_packet_data_type) {
+ case(0):
+ XmToggleButtonSetState(tnc_net_data,TRUE,FALSE);
+ break;
+
+ case(1):
+ XmToggleButtonSetState(tnc_data,TRUE,FALSE);
+ break;
+
+ case(2):
+ XmToggleButtonSetState(net_data,TRUE,FALSE);
+ break;
+
+ default:
+ XmToggleButtonSetState(tnc_net_data,TRUE,FALSE);
+ break;
+ }
+
+ if (Read_messages_mine_only) {
+ XmToggleButtonSetState(read_mine_only_button,TRUE,FALSE);
+ XtSetSensitive(vm_dist_data, FALSE);
+ }
+ else {
+ XmToggleButtonSetState(read_mine_only_button,FALSE,FALSE);
+ XtSetSensitive(vm_dist_data, TRUE);
+ }
+
+ XtManageChild(option_box);
+ XtManageChild(view_messages_text);
+ XtVaSetValues(view_messages_text, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(my_form);
+ XtManageChild(pane);
+
+ redraw_on_new_packet_data=1;
+
+ // Dump all currently active messages to the new window
+ view_message_display_file('M');
+
+end_critical_section(&All_messages_dialog_lock, "view_message_gui.c:view_all_messages" );
+
+ XtPopup(All_messages_dialog,XtGrabNone);
+// fix_dialog_vsize(All_messages_dialog);
+
+ // Move focus to the Close button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(All_messages_dialog);
+ XmProcessTraversal(button_close, XmTRAVERSE_CURRENT);
+
+
+ }
+ else {
+ (void)XRaiseWindow(XtDisplay(All_messages_dialog), XtWindow(All_messages_dialog));
+ }
+}
+
+
diff --git a/src/wx.c b/src/wx.c
new file mode 100644
index 0000000..702b942
--- /dev/null
+++ b/src/wx.c
@@ -0,0 +1,3770 @@
+/*
+ * $Id: wx.c,v 1.80 2012/08/31 23:39:01 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+//
+// The code currently supports these types of locally-connected or
+// network-connected weather stations:
+//
+// Peet Brothers Ultimeter 2000 (Set to Data logging mode)
+// Peet Brothers Ultimeter 2000 (Set to Packet mode)
+// Peet Brothers Ultimeter 2000 (Set to Complete Record Mode)
+// Peet Brothers Ultimeter-II
+// Qualimetrics Q-Net?
+// Radio Shack WX-200/Huger WM-918/Oregon Scientific WM-918
+// Dallas One-Wire Weather Station (via OWW network daemon)
+// Davis Weather Monitor II/Wizard III/Vantage Pro (via meteo/db2APRS link)
+//
+
+
+// Need to modify code to use WX_rain_gauge_type. Peet brothers.
+// See http://www.peetbros.com, FAQ's and owner's manuals for
+// details:
+//
+// Peet Bros Ultimeter II: 0.1"/0.5mm or 0.01"/0.25mm
+// Divide by 10 or 100 from the serial output.
+//
+// Peet Bros Ultimeter 2000, 800, & 100: 0.01"/0.25mm or 0.1mm
+// If 0.01" gauge, divide by 100. If 0.1mm gauge, convert to
+// proper English units.
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+#include <string.h>
+
+#include <Xm/XmAll.h>
+
+#include "wx.h"
+#include "main.h"
+#include "xastir.h"
+#include "interface.h"
+#include "lang.h"
+#include "util.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+#define MAX_RAW_WX_STRING 800
+
+char wx_station_type[100];
+char raw_wx_string[MAX_RAW_WX_STRING+1];
+
+#define MAX_WX_STRING 300
+#define WX_TYPE 'X'
+
+/* rain totals */
+float rain_minute[60]; // Total rain for each min. of last hour, hundredths of an inch
+float rain_minute_total = 0.0; // Total for last hour, hundredths of an inch
+int rain_minute_last_write = -1; // Write pointer for rain_minute[] array, set to an invalid number
+float rain_00 = 0.0; // hundredths of an inch
+float rain_24 = 0.0; // hundredths of an inch
+float rain_base[24]; // hundredths of an inch
+int rain_check = 0; // Flag for re-checking rain_total each hour
+
+float wind_chill = 0; // holder for wind chill calc
+
+// Gust totals
+float gust[60]; // High wind gust for each min. of last hour
+int gust_write_ptr = 0;
+int gust_read_ptr = 0;
+int gust_last_write = 0;
+
+
+/* Other WX station data */
+char wx_dew_point[10];
+char wx_dew_point_on;
+char wx_high_wind[10];
+char wx_high_wind_on;
+char wx_wind_chill[10];
+char wx_wind_chill_on;
+char wx_three_hour_baro[10]; // hPa
+char wx_three_hour_baro_on;
+char wx_hi_temp[10];
+char wx_hi_temp_on;
+char wx_low_temp[10];
+char wx_low_temp_on;
+char wx_heat_index[10];
+char wx_heat_index_on;
+
+
+
+
+
+/***********************************************************/
+/* clear rain data */
+/***********************************************************/
+void clear_rain_data(void) {
+ int x;
+
+
+ // Clear rain_base queue (starting rain total for each hour)
+ for ( x = 0; x < 24; x++ ) {
+ rain_base[x] = 0.0;
+ }
+
+ rain_00 = 0.0;
+ rain_24 = 0.0;
+ rain_check = 0; // Set flag so we'll recheck rain_total
+ // a few times at start of each hour
+
+ // Clear hourly rain queue
+ for ( x = 0; x < 60; x++ )
+ rain_minute[x] = 0.0;
+
+ rain_minute_total = 0.0;
+ rain_minute_last_write = 70; // Invalid number so we'll know we're just starting.
+}
+
+
+
+
+
+/**************************************************************/
+/* compute_rain_hour - rolling average for the last 59.x */
+/* minutes of rain. I/O numbers are in hundredths of an inch.*/
+/* Output is in "rain_minute_total", a global variable. */
+/**************************************************************/
+void compute_rain_hour(float rain_total) {
+ int current, j;
+ float lowest;
+
+
+ // Deposit the _starting_ rain_total for each minute into a separate bucket.
+ // Subtract lowest rain_total in queue from current rain_total to get total
+ // for the last hour.
+
+
+ current = get_minutes(); // Fetch the current minute value. Use this as an index
+ // into our minute "buckets" where we store the data.
+
+
+ rain_minute[ (current + 1) % 60 ] = 0.0; // Zero out the next bucket (probably have data in
+ // there from the previous hour).
+
+
+ if (rain_minute[current] == 0.0) // If no rain_total stored yet in this minute's bucket
+ rain_minute[current] = rain_total; // Write into current bucket
+
+
+ // Find the lowest non-zero value for rain_total. The max value is "rain_total".
+ lowest = rain_total; // Set to maximum to get things going
+ for (j = 0; j < 60; j++) {
+ if ( (rain_minute[j] > 0.0) && (rain_minute[j] < lowest) ) { // Found a lower non-zero value?
+ lowest = rain_minute[j]; // Snag it
+ }
+ }
+ // Found it, subtract the two to get total for the last hour
+ rain_minute_total = rain_total - lowest;
+
+ if (debug_level & 2)
+ fprintf(stderr,"Rain_total:%0.2f Hourly:%0.2f (Low:%0.2f) ", rain_total, rain_minute_total, lowest);
+}
+
+
+
+
+
+/***********************************************************/
+/* compute_rain - compute rain totals from the total rain */
+/* so far. rain_total (in hundredths of an inch) keeps on */
+/* incrementing. */
+/***********************************************************/
+void compute_rain(float rain_total) {
+ int current, i;
+ float lower;
+
+
+ // Skip the routine if input is outlandish (Negative value, zero, or 512 inches!).
+ // We seem to get occasional 0.0 packets from wx200d. This makes them go away.
+ if ( (rain_total <= 0.0) || (rain_total > 51200.0) )
+ return;
+
+ compute_rain_hour(rain_total);
+
+ current = get_hours();
+
+ // Set rain_base: The first rain_total for each hour.
+ if (rain_base[current] == 0.0) { // If we don't have a start value yet for this hour,
+ rain_base[current] = rain_total; // save it away.
+ rain_check = 0; // Set up rain_check so we'll do the following
+ // "else" clause a few times at start of each hour.
+ }
+ else { // rain_base has been set, is it wrong? We recheck three times at start of hour.
+ if (rain_check < 3) {
+ rain_check++;
+ // Is rain less than base? It shouldn't be.
+ if (rain_total < rain_base[current])
+ rain_base[current] = rain_total;
+
+ // Difference greater than 10 inches since last reading? It shouldn't be.
+ if (fabs(rain_total - rain_base[current]) > 1000.0) // Remember: Hundredths of an inch
+ rain_base[current] = rain_total;
+ }
+ }
+ rain_base[ (current + 1) % 24 ] = 0.0; // Clear next hour's index.
+
+
+ // Compute total rain in last 24 hours: Really we'll compute the total rain
+ // in the last 23 hours plus the portion of an hour we've completed (Sum up
+ // all 24 of the hour totals). This isn't the perfect way to do it, but to
+ // really do it right we'd need finer increments of time (to get closer to
+ // the goal of 24 hours of rain).
+ lower = rain_total;
+ for ( i = 0; i < 24; i++ ) { // Find the lowest non-zero rain_base value in last 24 hours
+ if ( (rain_base[i] > 0.0) && (rain_base[i] < lower) ) {
+ lower = rain_base[i];
+ }
+ }
+ rain_24 = rain_total - lower; // Hundredths of an inch
+
+
+ // Compute rain since midnight. Note that this uses whatever local time was set
+ // on the machine. It might not be local midnight if your box is set to GMT.
+ lower = rain_total;
+ for ( i = 0; i <= current; i++ ) { // Find the lowest non-zero rain_base value since midnight
+ if ( (rain_base[i] > 0.0) && (rain_base[i] < lower) ) {
+ lower = rain_base[i];
+ }
+ }
+ rain_00 = rain_total - lower; // Hundredths of an inch
+
+ // It is the responsibility of the calling program to save
+ // the new totals in the data structure for our station.
+ // We don't return anything except in global variables.
+
+
+ if (debug_level & 2) {
+ fprintf(stderr,"24hrs:%0.2f ", rain_24);
+ fprintf(stderr,"rain_00:%0.2f\n", rain_00);
+ }
+}
+
+
+
+
+
+/**************************************************************/
+/* compute_gust - compute max wind gust during last 5 minutes */
+/* */
+/**************************************************************/
+float compute_gust(float wx_speed, float last_speed, time_t *last_speed_time) {
+ float computed_gust;
+ int current, j;
+
+
+ // Deposit max gust for each minute into a different bucket.
+ // Check all buckets for max gust within the last five minutes
+ // (Really 4 minutes plus whatever portion of a minute we've completed).
+
+ current = get_minutes(); // Fetch the current minute value. We use this as an index
+ // into our minute "buckets" where we store the data.
+
+ // If we haven't started collecting yet, set up to do so
+ if (gust_read_ptr == gust_write_ptr) { // We haven't started yet
+ gust_write_ptr = current; // Set to write into current bucket
+ gust_last_write = current;
+
+ gust_read_ptr = current - 1; // Set read pointer back one, modulus 60
+ if (gust_read_ptr < 0)
+ gust_read_ptr = 59;
+
+ gust[gust_write_ptr] = 0.0; // Zero the max gust
+ gust[gust_read_ptr] = 0.0; // for both buckets.
+
+//WE7U: Debug
+//gust[gust_write_ptr] = 45.9;
+ }
+
+ // Check whether we've advanced at least one minute yet
+ if (current != gust_write_ptr) { // We've advanced to a different minute
+ gust_write_ptr = current; // Start writing into a new bucket.
+ gust[gust_write_ptr] = 0.0; // Zero the new bucket
+
+ // Check how many bins of real data we have currently. Note that this '5' is
+ // correct, as we just advanced "current" to the next minute. We're just pulling
+ // along the read_ptr behind us if we have 5 bins worth of data by now.
+ if ( ((gust_read_ptr + 5) % 60) == gust_write_ptr) // We have 5 bins of real data
+ gust_read_ptr = (gust_read_ptr + 1) % 60; // So advance the read pointer,
+
+ // Check for really bad pointers, perhaps the weather station got
+ // unplugged for a while or it's just REALLY slow at sending us data?
+ // We're checking to see if gust_last_write happened in the previous
+ // minute. If not, we skipped a minute or more somewhere.
+ if ( ((gust_last_write + 1) % 60) != current ) {
+ // We lost some time somewhere: Reset the pointers, older gust data is
+ // lost. Start over collecting new gust data.
+
+ gust_read_ptr = current - 1; // Set read pointer back one, modulus 60
+ if (gust_read_ptr < 0)
+ gust_read_ptr = 59;
+
+ gust[gust_read_ptr] = 0.0;
+ }
+ gust_last_write = current;
+ }
+
+ // Is current wind speed higher than the current minute bucket?
+ if (wx_speed > gust[gust_write_ptr])
+ gust[gust_write_ptr] = wx_speed; // Save it in the bucket
+
+ // Read the last (up to) five buckets and find the max gust
+ computed_gust=gust[gust_write_ptr];
+ j = gust_read_ptr;
+ while (j != ((gust_write_ptr + 1) % 60) ) {
+ if ( computed_gust < gust[j] )
+ computed_gust = gust[j];
+ j = (j + 1) % 60;
+ }
+
+ if (debug_level & 2) {
+ j = gust_read_ptr;
+ while (j != ((gust_write_ptr + 1) % 60) ) {
+ fprintf(stderr,"%0.2f ", gust[j]);
+ j = (j + 1) % 60;
+ }
+ fprintf(stderr,"gust:%0.2f\n", computed_gust);
+ }
+
+ *last_speed_time = sec_now();
+ return(computed_gust);
+}
+
+
+
+
+
+//
+// cycle_weather - keep the weather queues moving even if data from
+// weather station is scarce. This is called from main.c:UpdateTime()
+// on a periodic basis. This routine also does the 30 second timestamp
+// for the log files.
+//
+void cycle_weather(void) {
+ DataRow *p_station;
+ WeatherRow *weather;
+ float last_speed, computed_gust;
+ time_t last_speed_time;
+
+
+ // Find my own local weather data
+ if (search_station_name(&p_station,my_callsign,1)) {
+ if (p_station->weather_data != NULL) { // If station has WX data
+ weather = p_station->weather_data;
+ // Cycle the rain queues, feed in the last rain total we had
+ (void)compute_rain((float)atof(weather->wx_rain_total));
+
+
+ // Note: Some weather stations provide the per-hour, 24-hour,
+ // and since-midnight rain rates already. Further, some stations
+ // don't even provide total rain (Davis APRS DataLogger and the
+ // db2APRS program), so anything we compute here is actually wrong.
+ // Do NOT clobber these if so. This flag is set in fill_wx_data
+ // when the station provides its data.
+
+ if (weather->wx_compute_rain_rates) {
+ // Hourly rain total
+ xastir_snprintf(weather->wx_rain,
+ sizeof(weather->wx_rain),
+ "%0.2f",
+ rain_minute_total);
+
+ // Last 24 hour rain
+ xastir_snprintf(weather->wx_prec_24,
+ sizeof(weather->wx_prec_24),
+ "%0.2f",
+ rain_24);
+
+ // Rain since midnight
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ rain_00);
+ }
+ else
+ {
+ // LaCrosse stations don't provide the since-midnight
+ // numbers and so this will be blank.
+ // So if we have blanks here, fill it in.
+ if ( weather->wx_prec_00[0] == '\0' &&
+ weather->wx_rain_total[0] != '\0') {
+
+ // Rain since midnight
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ rain_00);
+ }
+ }
+
+
+ /* get last gust speed */
+ if (strlen(weather->wx_gust) > 0) {
+ /* get last speed */
+ last_speed = (float)atof(weather->wx_gust);
+ last_speed_time = weather->wx_speed_sec_time;
+ } else
+ last_speed = 0.0;
+
+ /* wind speed */
+ computed_gust = compute_gust((float)atof(weather->wx_speed),
+ last_speed,
+ &last_speed_time);
+ weather->wx_speed_sec_time = sec_now();
+ if ( (computed_gust > 0.0) || (weather->wx_gust != 0) )
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%03d",
+ (int)(computed_gust + 0.5)); // Cheater's way of rounding
+ }
+ }
+}
+
+
+
+
+
+/***********************************************************/
+/* clear other wx data */
+/***********************************************************/
+void clear_local_wx_data(void) {
+ memset(wx_dew_point,0,sizeof(wx_dew_point));
+ wx_dew_point_on = 0;
+
+ memset(wx_high_wind,0,sizeof(wx_high_wind));
+ wx_high_wind_on = 0;
+
+ memset(wx_wind_chill,0,sizeof(wx_wind_chill));
+ wx_wind_chill_on = 0;
+
+ memset(wx_three_hour_baro,0,sizeof(wx_three_hour_baro));
+ wx_three_hour_baro_on = 0;
+
+ memset(wx_hi_temp,0,sizeof(wx_hi_temp));
+ wx_hi_temp_on = 0;
+
+ memset(wx_low_temp,0,sizeof(wx_low_temp));
+ wx_low_temp_on = 0;
+
+ memset(wx_heat_index,0,sizeof(wx_heat_index));
+ wx_heat_index_on = 0;
+}
+
+
+
+
+
+/***************************************************/
+/* Check last WX data received - clear data if old */
+/***************************************************/
+void wx_last_data_check(void) {
+ DataRow *p_station;
+
+ p_station = NULL;
+ if (search_station_name(&p_station,my_callsign,1)) {
+ if (p_station->weather_data != NULL)
+ if (p_station->weather_data->wx_speed_sec_time+360 < sec_now())
+ if (p_station->weather_data->wx_gust[0] != 0)
+ xastir_snprintf(p_station->weather_data->wx_gust,
+ sizeof(p_station->weather_data->wx_gust),
+ "%03d",
+ 0);
+ }
+}
+
+
+
+
+
+//*********************************************************************
+// Decode Peet Brothers Ultimeter 2000 weather data (Data logging mode)
+//
+// This function is called from db.c:data_add() only. Used for
+// decoding incoming packets, not for our own weather station data.
+//
+// The Ultimeter 2000 can be in any of three modes, Data Logging Mode,
+// Packet Mode, or Complete Record Mode. This routine handles only
+// the Data Logging Mode.
+//*********************************************************************
+void decode_U2000_L(int from, unsigned char *data, WeatherRow *weather) {
+ time_t last_speed_time;
+ float last_speed;
+ float computed_gust;
+ char temp_data1[10];
+ char *temp_conv;
+ char format;
+
+ last_speed = 0.0;
+ last_speed_time = 0;
+ computed_gust = 0.0;
+ format = 0;
+
+ if (debug_level & 1)
+ fprintf(stderr,"APRS WX3 Peet Bros U-2k (data logging mode): |%s|\n", data);
+
+ weather->wx_type = WX_TYPE;
+ xastir_snprintf(weather->wx_station,
+ sizeof(weather->wx_station),
+ "U2k");
+
+ /* get last gust speed */
+ if (strlen(weather->wx_gust) > 0 && !from) {
+ /* get last speed */
+ last_speed = (float)atof(weather->wx_gust);
+ last_speed_time = weather->wx_speed_sec_time;
+ }
+
+ // 006B 00 58
+ // 00A4 00 46 01FF 380E 2755 02C1 03E8 ---- 0052 04D7 0001 007BM
+ // ^ ^ ^ ^ ^ ^ ^
+ // 0 6 8 12 16 24 40
+ /* wind speed */
+ if (data[0] != '-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)data,4);
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ if (from) {
+ weather->wx_speed_sec_time = sec_now();
+ } else {
+ /* local station */
+ computed_gust = compute_gust((float)atof(weather->wx_speed),
+ last_speed,
+ &last_speed_time);
+ weather->wx_speed_sec_time = sec_now();
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%03d",
+ (int)(0.5 + computed_gust)); // Cheater's way of rounding
+ }
+ } else {
+ if (!from)
+ weather->wx_speed[0] = 0;
+ }
+
+ /* wind direction */
+ //
+ // Note that the first two digits here may be 00, or may be FF
+ // if a direction calibration has been entered. We should zero
+ // them.
+ //
+ if (data[4] != '-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+4),4);
+ temp_data1[0] = '0';
+ temp_data1[1] = '0';
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "%03d",
+ (int)(((float)strtol(temp_data1,&temp_conv,16)/256.0)*360.0));
+ } else {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "000");
+ if (!from)
+ weather->wx_course[0]=0;
+ }
+
+ /* outdoor temp */
+ if (data[8] != '-') { // '-' signifies invalid data
+ int temp4;
+
+ substr(temp_data1,(char *)(data+8),4);
+ temp4 = (int)strtol(temp_data1,&temp_conv,16);
+
+ if (temp_data1[0] > '7') { // Negative value, convert
+ temp4 = (temp4 & (temp4-0x7FFF)) - 0x8000;
+ }
+
+ xastir_snprintf(weather->wx_temp,
+ sizeof(weather->wx_temp),
+ "%03d",
+ (int)((float)((temp4<<16)/65536)/10.0));
+
+ }
+ else {
+ if (!from)
+ weather->wx_temp[0]=0;
+ }
+
+ /* rain total long term */
+ if (data[12] != '-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+12),4);
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)/100.0);
+ if (!from) {
+ /* local station */
+ compute_rain((float)atof(weather->wx_rain_total));
+ /*last hour rain */
+ xastir_snprintf(weather->wx_rain,
+ sizeof(weather->wx_rain),
+ "%0.2f",
+ rain_minute_total);
+ /*last 24 hour rain */
+ xastir_snprintf(weather->wx_prec_24,
+ sizeof(weather->wx_prec_24),
+ "%0.2f",
+ rain_24);
+ /* rain since midnight */
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ rain_00);
+ }
+ } else {
+ if (!from)
+ weather->wx_rain_total[0]=0;
+ }
+
+ /* baro */
+ if (data[16] != '-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+16),4);
+ xastir_snprintf(weather->wx_baro,
+ sizeof(weather->wx_baro),
+ "%0.1f",
+ (float)strtol(temp_data1,&temp_conv,16)/10.0);
+ } else {
+ if (!from)
+ weather->wx_baro[0]=0;
+ }
+
+
+ /* outdoor humidity */
+ if (data[24] != '-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+24),4);
+ xastir_snprintf(weather->wx_hum,
+ sizeof(weather->wx_hum),
+ "%03d",
+ (int)((float)strtol(temp_data1,&temp_conv,16)/10.0));
+ } else {
+ if (!from)
+ weather->wx_hum[0]=0;
+ }
+
+ /* todays rain total */
+ if (data[40] != '-') { // '-' signifies invalid data
+ if (from) {
+ substr(temp_data1,(char *)(data+40),4);
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)/100.0);
+ }
+ } else {
+ if (!from)
+ weather->wx_prec_00[0] = 0;
+ }
+}
+
+
+
+
+
+//********************************************************************
+// Decode Peet Brothers Ultimeter 2000 weather data (Packet mode)
+//
+// This function is called from db.c:data_add() only. Used for
+// decoding incoming packets, not for our own weather station data.
+//
+// The Ultimeter 2000 can be in any of three modes, Data Logging Mode,
+// Packet Mode, or Complete Record Mode. This routine handles only
+// the Packet Mode.
+//********************************************************************
+void decode_U2000_P(int from, unsigned char *data, WeatherRow *weather) {
+ time_t last_speed_time;
+ float last_speed;
+ float computed_gust;
+ char temp_data1[10];
+ char *temp_conv;
+ int len;
+
+ last_speed = 0.0;
+ last_speed_time = 0;
+ computed_gust = 0.0;
+ len = (int)strlen((char *)data);
+
+ if (debug_level & 1)
+ fprintf(stderr,"APRS WX5 Peet Bros U-2k Packet (Packet mode): |%s|\n",data);
+
+ weather->wx_type = WX_TYPE;
+ xastir_snprintf(weather->wx_station,
+ sizeof(weather->wx_station),
+ "U2k");
+
+ /* get last gust speed */
+ if (strlen(weather->wx_gust) > 0 && !from) {
+ /* get last speed */
+ last_speed = (float)atof(weather->wx_gust);
+ last_speed_time = weather->wx_speed_sec_time;
+ }
+
+ // $ULTW 0031 00 37 02CE 0069 ---- 0000 86A0 0001 ---- 011901CC 0000 0005
+ // ^ ^ ^ ^ ^ ^ ^ ^
+ // 0 6 8 12 16 32 44 48
+
+ /* wind speed peak over last 5 min */
+ if (data[0] != '-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)data,4);
+ if (from) {
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ /* this may be the only wind data */
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ } else {
+ /* local station and may be the only wind data */
+ if (len < 51) {
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ computed_gust = compute_gust((float)atof(weather->wx_speed),
+ last_speed,
+ &last_speed_time);
+ weather->wx_speed_sec_time = sec_now();
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%03d",
+ (int)(0.5 + computed_gust));
+ }
+ }
+ } else {
+ if (!from)
+ weather->wx_gust[0] = 0;
+ }
+
+ /* wind direction */
+ //
+ // Note that the first two digits here may be 00, or may be FF
+ // if a direction calibration has been entered. We should zero
+ // them.
+ //
+ if (data[4] != '-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+4),4);
+ temp_data1[0] = '0';
+ temp_data1[1] = '0';
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "%03d",
+ (int)(((float)strtol(temp_data1,&temp_conv,16)/256.0)*360.0));
+ } else {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "000");
+ if (!from)
+ weather->wx_course[0] = 0;
+ }
+
+ /* outdoor temp */
+ if (data[8] != '-') { // '-' signifies invalid data
+ int temp4;
+
+ substr(temp_data1,(char *)(data+8),4);
+ temp4 = (int)strtol(temp_data1,&temp_conv,16);
+
+ if (temp_data1[0] > '7') { // Negative value, convert
+ temp4 = (temp4 & (temp4-0x7FFF)) - 0x8000;
+ }
+
+ xastir_snprintf(weather->wx_temp,
+ sizeof(weather->wx_temp),
+ "%03d",
+ (int)((float)((temp4<<16)/65536)/10.0));
+ }
+ else {
+ if (!from)
+ weather->wx_temp[0] = 0;
+ }
+ /* todays rain total (on some units) */
+ if ((data[44]) != '-') { // '-' signifies invalid data
+ if (from) {
+ substr(temp_data1,(char *)(data+44),4);
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)/100.0);
+ }
+ } else {
+ if (!from)
+ weather->wx_prec_00[0] = 0;
+ }
+
+ /* rain total long term */
+ if (data[12] != '-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+12),4);
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)/100.0);
+ if (!from) {
+ /* local station */
+ compute_rain((float)atof(weather->wx_rain_total));
+ /*last hour rain */
+ xastir_snprintf(weather->wx_rain,
+ sizeof(weather->wx_rain),
+ "%0.2f",
+ rain_minute_total);
+ /*last 24 hour rain */
+ xastir_snprintf(weather->wx_prec_24,
+ sizeof(weather->wx_prec_24),
+ "%0.2f",
+ rain_24);
+ /* rain since midnight */
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ rain_00);
+ }
+ } else {
+ if (!from)
+ weather->wx_rain_total[0] = 0;
+ }
+
+ /* baro */
+ if (data[16] != '-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+16),4);
+ xastir_snprintf(weather->wx_baro,
+ sizeof(weather->wx_baro),
+ "%0.1f",
+ (float)strtol(temp_data1,&temp_conv,16)/10.0);
+ } else {
+ if (!from)
+ weather->wx_baro[0] = 0;
+ }
+
+ /* outdoor humidity */
+ if (data[32] != '-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+32),4);
+ xastir_snprintf(weather->wx_hum,
+ sizeof(weather->wx_hum),
+ "%03d",
+ (int)((float)strtol(temp_data1,&temp_conv,16)/10.0));
+ } else {
+ if (!from)
+ weather->wx_hum[0] = 0;
+ }
+
+ /* 1 min wind speed avg */
+ if (len > 48 && (data[48]) != '-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+48),4);
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ if (from) {
+ weather->wx_speed_sec_time = sec_now();
+ } else {
+ /* local station */
+ computed_gust = compute_gust((float)atof(weather->wx_speed),
+ last_speed,
+ &last_speed_time);
+ weather->wx_speed_sec_time = sec_now();
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%03d",
+ (int)(0.5 + computed_gust));
+ }
+ } else {
+ if (!from) {
+ if (len > 48)
+ weather->wx_speed[0] = 0;
+ }
+ }
+}
+
+
+
+
+
+//*****************************************************************
+// Decode Peet Brothers Ultimeter-II weather data
+//
+// This function is called from db.c:data_add() only. Used for
+// decoding incoming packets, not for our own weather station data.
+//*****************************************************************
+void decode_Peet_Bros(int from, unsigned char *data, WeatherRow *weather, int type) {
+ time_t last_speed_time;
+ float last_speed;
+ float computed_gust;
+ char temp_data1[10];
+ char *temp_conv;
+
+ last_speed = 0.0;
+ computed_gust = 0.0;
+ last_speed_time = 0;
+
+ if (debug_level & 1)
+ fprintf(stderr,"APRS WX4 Peet Bros U-II: |%s|\n",data);
+
+ weather->wx_type = WX_TYPE;
+ xastir_snprintf(weather->wx_station,
+ sizeof(weather->wx_station),
+ "UII");
+
+ // '*' = MPH
+ // '#' = km/h
+ //
+ // # 5 0B 75 0082 0082
+ // * 7 00 76 0000 0000
+ // ^ ^ ^ ^
+ // rain [1/100 inch ?]
+ // outdoor temp
+ // wind speed [mph / km/h]
+ // wind dir
+
+ /* wind direction */
+ //
+ // 0x00 is N
+ // 0x04 is E
+ // 0x08 is S
+ // 0x0C is W
+ //
+ substr(temp_data1,(char *)data,1);
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "%03d",
+ (int)(((float)strtol(temp_data1,&temp_conv,16)/16.0)*360.0));
+
+ /* get last gust speed */
+ if (strlen(weather->wx_gust) > 0 && !from) {
+ /* get last speed */
+ last_speed = (float)atof(weather->wx_gust);
+ last_speed_time = weather->wx_speed_sec_time;
+ }
+
+ /* wind speed */
+ substr(temp_data1,(char *)(data+1),2);
+ if (type == APRS_WX4) { // '#' speed in km/h, convert to mph
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + (float)(strtol(temp_data1,&temp_conv,16)*0.62137)));
+ } else { // type == APRS_WX6, '*' speed in mph
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + (float)strtol(temp_data1,&temp_conv,16)));
+ }
+
+ if (from) {
+ weather->wx_speed_sec_time = sec_now();
+ } else {
+ /* local station */
+ computed_gust = compute_gust((float)atof(weather->wx_speed),
+ last_speed,
+ &last_speed_time);
+ weather->wx_speed_sec_time = sec_now();
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%03d",
+ (int)(0.5 + computed_gust));
+ }
+
+ /* outdoor temp */
+ if (data[3] != '-') { // '-' signifies invalid data
+ int temp4;
+
+ substr(temp_data1,(char *)(data+3),2);
+ temp4 = (int)strtol(temp_data1,&temp_conv,16);
+
+ if (temp_data1[0] > '7') { // Negative value, convert
+ temp4 = (temp4 & (temp4-0x7FFF)) - 0x8000;
+ }
+
+ xastir_snprintf(weather->wx_temp,
+ sizeof(weather->wx_temp),
+ "%03d",
+ temp4-56);
+ } else {
+ if (!from)
+ weather->wx_temp[0] = 0;
+ }
+
+ // Rain divided by 100 for readings in hundredth of an inch
+ if (data[5] != '-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+5),4);
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)/100.0);
+ if (!from) {
+ /* local station */
+ compute_rain((float)atof(weather->wx_rain_total));
+ /*last hour rain */
+ xastir_snprintf(weather->wx_rain,
+ sizeof(weather->wx_rain),
+ "%0.2f",
+ rain_minute_total);
+ /*last 24 hour rain */
+ xastir_snprintf(weather->wx_prec_24,
+ sizeof(weather->wx_prec_24),
+ "%0.2f",
+ rain_24);
+ /* rain since midnight */
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ rain_00);
+ }
+ } else {
+ if (!from)
+ weather->wx_rain_total[0] = 0;
+ }
+}
+
+
+
+
+
+/**************************************************/
+/* RSW num convert. For Radio Shack WX-200, */
+/* converts two decimal nibbles into integer */
+/* number. */
+/**************************************************/
+int rswnc(unsigned char c) {
+ return( (int)( (c>>4) & 0x0f) * 10 + (int)(c&0x0f) );
+}
+
+
+
+
+
+//*********************************************************
+// wx fill data field
+// from: 0=local station, 1=regular decode (other stations)
+// type: type of WX packet
+// data: the packet of WX data
+// fill: the station data to fill
+//
+// This function is called only by wx.c:wx_decode()
+//
+// It is always called with a first parameter of 0, so we
+// use this only for our own serially-connected or network
+// connected weather station, not for decoding other
+// people's weather packets.
+//*********************************************************
+//
+// Note that the length of "data" can be up to MAX_DEVICE_BUFFER,
+// which is currently set to 4096.
+//
+void wx_fill_data(int from, int type, unsigned char *data, DataRow *fill) {
+ time_t last_speed_time;
+ float last_speed;
+ float computed_gust;
+ int temp1;
+ int temp2;
+ int temp3;
+ float temp_temp;
+ char temp[MAX_DEVICE_BUFFER+1];
+ char temp_data1[10];
+ char *temp_conv;
+ int len;
+ int t2;
+ int hidx_temp;
+ int rh2;
+ int hi_hum;
+ int heat_index;
+ char format;
+ WeatherRow *weather;
+ float tmp1,tmp2,tmp3,tmp4,tmp5,tmp6,tmp9,tmp10,tmp11,tmp12,tmp13,tmp14,tmp15,tmp16,tmp17,tmp18,tmp19;
+ int tmp7,tmp8;
+ int dallas_type = 19;
+
+
+ last_speed=0.0;
+ computed_gust=0.0;
+ last_speed_time=0;
+ format = 0;
+
+
+ len=(int)strlen((char*)data);
+
+ weather = fill->weather_data; // should always be defined
+
+ switch (type) {
+
+//WE7U
+ /////////////////////////////////////
+ // Dallas One-Wire Weather Station //
+ /////////////////////////////////////
+
+// KB1MTS - Added values for T13 thru T19 for humidity and barometer,
+// however only current values (not min or max) are used.
+
+
+ case (DALLAS_ONE_WIRE):
+
+ if (debug_level & 1)
+ fprintf(stderr,"APRS WX Dallas One-Wire %s:<%s>\n",fill->call_sign,data);
+
+ weather->wx_type=WX_TYPE;
+ xastir_snprintf(weather->wx_station,
+ sizeof(weather->wx_station),
+ "OWW");
+
+ if (19 == sscanf((const char *)data,
+ "%f %f %f %f %f %f %d %d %f %f %f %f %f %f %f %f %f %f %f",
+ &tmp1,
+ &tmp2,
+ &tmp3,
+ &tmp4,
+ &tmp5,
+ &tmp6,
+ &tmp7,
+ &tmp8,
+ &tmp9,
+ &tmp10,
+ &tmp11,
+ &tmp12,
+ &tmp13,
+ &tmp14,
+ &tmp15,
+ &tmp16,
+ &tmp17,
+ &tmp18,
+ &tmp19)) {
+ dallas_type = 19;
+ }
+ else if (12 == sscanf((const char *)data,
+ "%f %f %f %f %f %f %d %d %f %f %f %f",
+ &tmp1,
+ &tmp2,
+ &tmp3,
+ &tmp4,
+ &tmp5,
+ &tmp6,
+ &tmp7,
+ &tmp8,
+ &tmp9,
+ &tmp10,
+ &tmp11,
+ &tmp12)) {
+ dallas_type = 12;
+ }
+ else {
+ fprintf(stderr,"wx_fill_data:sscanf parsing error\n");
+ }
+
+
+ // The format of the data originates here:
+ // http://weather.henriksens.net/
+
+ // tmp1: primary temp (C)
+ // tmp2: temp max (C)
+ // tmp3: temp min (C)
+ // tmp4: anemometer (mps)
+ // tmp5: anemometer gust (peak speed MS)
+ // tmp6: anemometer speed max * 0.447040972 (max speed MS)
+ // tmp7: vane bearing - 1 (current wind direction)
+ // tmp8: vane mode (max dir)
+ // tmp9: rain rate
+ // tmp10: rain total today
+ // tmp11: rain total week
+ // tmp12: rain since month
+ // tmp13: Current Humidity
+ // tmp14: Max Humidity
+ // tmp15: Min Humidity
+ // tmp16: Current Barometer
+ // tmp17: Max Barometer
+ // tmp18: Min Barometer
+ // tmp19: Barometer Rate
+
+ // Temperature
+ xastir_snprintf(weather->wx_temp,
+ sizeof(weather->wx_temp),
+ "%03d",
+ (int)(tmp1 * 9.0 / 5.0 + 32.0 + 0.5));
+ //fprintf(stderr,"Read: %2.1f C, Storing: %s F\n",tmp1,weather->wx_temp);
+
+ // Wind direction. Each vane increment equals 22.5 degrees.
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "%03d",
+ (int)(tmp7 * 22.5 + 0.5));
+
+ // Check for course = 0. Change to 360.
+ if (strncmp(weather->wx_course,"000",3) == 0) {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "360");
+ }
+
+ // Wind speed. We get it in meters per second, store it
+ // in mph.
+ tmp4 = tmp4 * 3600.0 / 1000.0; // kph
+ tmp4 = tmp4 * 0.62137; // mph
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(tmp4 + 0.5));
+
+ if (dallas_type == 19) {
+ // Humidity. This is received by percentage.
+ xastir_snprintf(weather->wx_hum,
+ sizeof(weather->wx_hum),
+ "%2.1f", (double)(tmp13));
+
+ // Barometer. Sent in inHg
+ xastir_snprintf(weather->wx_baro,
+ sizeof(weather->wx_baro),
+ "%4.4f", (float)(tmp16 * 33.864));
+ }
+
+
+// Rain: I don't have a rain gauge, and I couldn't tell from the
+// "OWW" docs exactly which of the four rain fields did what. If
+// someone can help me with that I'll add rain gauge code for the
+// Dallas One-Wire.
+
+
+
+ break;
+
+ ////////////////////////////////
+ // Peet Brothers Ultimeter-II //
+ ////////////////////////////////
+ case (APRS_WX4): // '#', Wind speed in km/h
+ case (APRS_WX6): // '*', Wind speed in mph
+
+ // This one assumes 0.1" rain gauge. Must correct in software if
+ // any other type is used.
+
+ if (debug_level & 1)
+ fprintf(stderr,"APRS WX4 Peet Bros U-II %s:<%s>\n",fill->call_sign,data);
+
+ weather->wx_type=WX_TYPE;
+ xastir_snprintf(weather->wx_station,
+ sizeof(weather->wx_station),
+ "UII");
+
+ /* wind direction */
+ //
+ // 0x00 is N
+ // 0x04 is E
+ // 0x08 is S
+ // 0x0C is W
+ //
+ substr(temp_data1,(char *)(data+1),1);
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "%03d",
+ (int)(((float)strtol(temp_data1,&temp_conv,16)/16.0)*360.0));
+
+ // Check for course == 0. Change to 360.
+ if (strncmp(weather->wx_course,"000",3) == 0) {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "360");
+ }
+
+ /* get last gust speed */
+ if (strlen(weather->wx_gust) > 0 && !from) { // From local station
+ /* get last speed */
+ last_speed=(float)atof(weather->wx_gust);
+ last_speed_time=weather->wx_speed_sec_time;
+ }
+
+ /* wind speed */
+ substr(temp_data1,(char *)(data+2),2);
+ if (type == APRS_WX4) { // '#', Data is in km/h, convert to mph
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + (float)(strtol(temp_data1,&temp_conv,16)*0.62137)));
+ } else { // APRS_WX6 or '*', Data is in MPH
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + (float)strtol(temp_data1,&temp_conv,16)));
+ }
+
+ if (from) { // From remote station
+ weather->wx_speed_sec_time = sec_now();
+ } else {
+ /* local station */
+ computed_gust = compute_gust((float)atof(weather->wx_speed),
+ last_speed,
+ &last_speed_time);
+ weather->wx_speed_sec_time = sec_now();
+ if ( (computed_gust > 0.0) || (weather->wx_gust != 0) )
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%03d",
+ (int)(0.5 + computed_gust));
+ }
+
+ /* outdoor temp */
+ if (data[4]!='-') { // '-' signifies invalid data
+ int temp4;
+
+ substr(temp_data1,(char *)(data+4),2);
+ temp4 = (int)strtol(temp_data1,&temp_conv,16);
+
+ if (temp_data1[0] > '7') { // Negative value, convert
+ temp4 = (temp4 & (temp4-0x7FFF)) - 0x8000;
+ }
+
+ xastir_snprintf(weather->wx_temp,
+ sizeof(weather->wx_temp),
+ "%03d",
+ temp4-56);
+ } else {
+ if (!from) // From local station
+ weather->wx_temp[0]=0;
+ }
+
+ /* rain div by 100 for readings 0.1 inch */
+// What? Shouldn't this be /10?
+
+ if (data[6]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+6),4);
+ if (!from) { // From local station
+ switch (WX_rain_gauge_type) {
+ case 1: // 0.1" rain gauge
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)*10);
+ break;
+ case 3: // 0.1mm rain gauge
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)/2.54);
+ break;
+ case 2: // 0.01" rain gauge
+ case 0: // No conversion
+ default:
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16));
+ break;
+ }
+ /* local station */
+ compute_rain((float)atof(weather->wx_rain_total));
+ weather->wx_compute_rain_rates=1;
+ /*last hour rain */
+ xastir_snprintf(weather->wx_rain,
+ sizeof(weather->wx_rain),
+ "%0.2f",
+ rain_minute_total);
+ /*last 24 hour rain */
+ xastir_snprintf(weather->wx_prec_24,
+ sizeof(weather->wx_prec_24),
+ "%0.2f",
+ rain_24);
+ /* rain since midnight */
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ rain_00);
+ }
+ } else {
+ if (!from) // From local station
+ weather->wx_rain_total[0]=0;
+ }
+ break;
+
+
+
+ ///////////////////////////////////////////////////////
+ // Peet Brothers Ultimeter 2000 in data logging mode //
+ ///////////////////////////////////////////////////////
+ case (APRS_WX3):
+ if (debug_level & 1)
+ fprintf(stderr,"APRS WX3 Peet Bros U-2k (data logging mode) %s:<%s>\n",fill->call_sign,data+2);
+
+ weather->wx_type=WX_TYPE;
+ xastir_snprintf(weather->wx_station,
+ sizeof(weather->wx_station),
+ "U2k");
+
+ /* get last gust speed */
+ if (strlen(weather->wx_gust) > 0 && !from) { // From local station
+ /* get last speed */
+ last_speed=(float)atof(weather->wx_gust);
+ last_speed_time=weather->wx_speed_sec_time;
+ }
+
+ /* wind speed */
+ if (data[2]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+2),4);
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ if (from) { // From remote station
+ weather->wx_speed_sec_time = sec_now();
+ } else {
+ /* local station */
+ computed_gust = compute_gust((float)atof(weather->wx_speed),
+ last_speed,
+ &last_speed_time);
+ weather->wx_speed_sec_time = sec_now();
+ if ( (computed_gust > 0.0) || (weather->wx_gust != 0) )
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%03d",
+ (int)(0.5 + computed_gust));
+ }
+ } else {
+ if (!from) // From local station
+ weather->wx_speed[0]=0;
+ }
+
+ /* wind direction */
+ //
+ // Note that the first two digits here may be 00, or may
+ // be FF if a direction calibration has been entered.
+ // We should zero them.
+ //
+ if (data[6]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+6),4);
+ // Zero out the first two bytes
+ temp_data1[0] = '0';
+ temp_data1[1] = '0';
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "%03d",
+ (int)(((float)strtol(temp_data1,&temp_conv,16)/256.0)*360.0));
+
+ // Check for course = 0. Change to 360.
+ if (strncmp(weather->wx_course,"000",3) == 0) {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "360");
+ }
+
+ } else {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "000");
+ if (!from) // From local station
+ weather->wx_course[0]=0;
+ }
+
+ /* outdoor temp */
+ if (data[10]!='-') { // '-' signifies invalid data
+ int temp4;
+
+ substr(temp_data1,(char *)(data+10),4);
+ temp4 = (int)strtol(temp_data1,&temp_conv,16);
+
+ if (temp_data1[0] > '7') { // Negative value, convert
+ temp4 = (temp4 & (temp4-0x7FFF)) - 0x8000;
+ }
+
+ xastir_snprintf(weather->wx_temp,
+ sizeof(weather->wx_temp),
+ "%03d",
+ (int)((float)((temp4<<16)/65536)/10.0));
+ } else {
+ if (!from) // From local station
+ weather->wx_temp[0]=0;
+ }
+
+ /* rain total long term */
+ if (data[14]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+14),4);
+ if (!from) { // From local station
+ switch (WX_rain_gauge_type) {
+ case 1: // 0.1" rain gauge
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)*10);
+ break;
+ case 3: // 0.1mm rain gauge
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)/2.54);
+ break;
+ case 2: // 0.01" rain gauge
+ case 0: // No conversion
+ default:
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16));
+ break;
+ }
+ /* local station */
+ compute_rain((float)atof(weather->wx_rain_total));
+ weather->wx_compute_rain_rates=1;
+ /*last hour rain */
+ xastir_snprintf(weather->wx_rain,
+ sizeof(weather->wx_rain),
+ "%0.2f",
+ rain_minute_total);
+ /*last 24 hour rain */
+ xastir_snprintf(weather->wx_prec_24,
+ sizeof(weather->wx_prec_24),
+ "%0.2f",
+ rain_24);
+ /* rain since midnight */
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ rain_00);
+ }
+ } else {
+ if (!from) // From local station
+ weather->wx_rain_total[0]=0;
+ }
+
+ /* baro */
+ if (data[18]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+18),4);
+ xastir_snprintf(weather->wx_baro,
+ sizeof(weather->wx_baro),
+ "%0.1f",
+ (float)strtol(temp_data1,&temp_conv,16)/10.0);
+ }
+
+ /* outdoor humidity */
+ if (data[26]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+26),4);
+ xastir_snprintf(weather->wx_hum,
+ sizeof(weather->wx_hum),
+ "%03d",
+ (int)((float)strtol(temp_data1,&temp_conv,16)/10.0));
+ } else {
+ if (!from) // From local station
+ weather->wx_hum[0]=0;
+ }
+
+ // Isn't this replaced by the above switch-case?
+ // No, I don't think so. We can get these packets over
+ // RF as well.
+ /* todays rain total */
+ if (strlen((const char *)data) > 45) {
+ if (data[42]!='-') { // '-' signifies invalid data
+ if (from) { // From remote station
+ substr(temp_data1,(char *)(data+42),4);
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)/100.0);
+ }
+ } else {
+ if (!from) // From local station
+ weather->wx_prec_00[0]=0;
+ }
+ }
+ break;
+
+
+
+ /////////////////////////////////////////////////
+ // Peet Brothers Ultimeter 2000 in packet mode //
+ /////////////////////////////////////////////////
+ case(APRS_WX5):
+ if (debug_level & 1)
+ fprintf(stderr,"APRS WX5 Peet Bros U-2k Packet (Packet mode) %s:<%s>\n",fill->call_sign,data);
+
+ weather->wx_type=WX_TYPE;
+ xastir_snprintf(weather->wx_station,
+ sizeof(weather->wx_station),
+ "U2k");
+
+ /* get last gust speed */
+ if (strlen(weather->wx_gust) > 0 && !from) { // From local station
+ /* get last speed */
+ last_speed=(float)atof(weather->wx_gust);
+ last_speed_time=weather->wx_speed_sec_time;
+ }
+
+ /* wind speed peak over last 5 min */
+ if (data[5]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+5),4);
+ if (from) { // From remote station
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ /* this may be the only wind data */
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ } else {
+ /* local station and may be the only wind data */
+ if (len<56) {
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ computed_gust = compute_gust((float)atof(weather->wx_speed),
+ last_speed,
+ &last_speed_time);
+ weather->wx_speed_sec_time = sec_now();
+ if ( (computed_gust > 0.0) || (weather->wx_gust != 0) )
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%03d",
+ (int)(0.5 + computed_gust));
+ }
+ }
+ } else {
+ if (!from) // From local station
+ weather->wx_gust[0]=0;
+ }
+
+ /* wind direction */
+ //
+ // Note that the first two digits here may be 00, or may
+ // be FF if a direction calibration has been entered.
+ // We should zero them.
+ //
+ if (data[9]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+9),4);
+ temp_data1[0] = '0';
+ temp_data1[1] = '0';
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "%03d",
+ (int)(((float)strtol(temp_data1,&temp_conv,16)/256.0)*360.0));
+
+ // Check for course = 0. Change to 360.
+ if (strncmp(weather->wx_course,"000",3) == 0) {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "360");
+ }
+
+ } else {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "000");
+ if (!from) // From local station
+ weather->wx_course[0]=0;
+ }
+
+ /* outdoor temp */
+ if (data[13]!='-') { // '-' signifies invalid data
+ int temp4;
+
+ substr(temp_data1,(char *)(data+13),4);
+ temp4 = (int)strtol(temp_data1,&temp_conv,16);
+
+ if (temp_data1[0] > '7') { // Negative value, convert
+ temp4 = (temp4 & (temp4-0x7FFF)) - 0x8000;
+ }
+
+ xastir_snprintf(weather->wx_temp,
+ sizeof(weather->wx_temp),
+ "%03d",
+ (int)((float)((temp4<<16)/65536)/10.0));
+ } else {
+ if (!from) // From local station
+ weather->wx_temp[0]=0;
+ }
+ /* todays rain total (on some units) */
+ if (data[49]!='-') { // '-' signifies invalid data
+ if (from) { // From remote station
+ substr(temp_data1,(char *)(data+49),4);
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)/100.0);
+ }
+ } else {
+ if (!from) // From local station
+ weather->wx_prec_00[0]=0;
+ }
+
+ /* rain total long term */
+ if (data[17]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+17),4);
+ if (!from) { // From local station
+ switch (WX_rain_gauge_type) {
+ case 1: // 0.1" rain gauge
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)*10);
+ break;
+ case 3: // 0.1mm rain gauge
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)/2.54);
+ break;
+ case 2: // 0.01" rain gauge
+ case 0: // No conversion
+ default:
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16));
+ break;
+ }
+ /* local station */
+ compute_rain((float)atof(weather->wx_rain_total));
+ weather->wx_compute_rain_rates=1;
+ /*last hour rain */
+ xastir_snprintf(weather->wx_rain,
+ sizeof(weather->wx_rain),
+ "%0.2f",
+ rain_minute_total);
+ /*last 24 hour rain */
+ xastir_snprintf(weather->wx_prec_24,
+ sizeof(weather->wx_prec_24),
+ "%0.2f",
+ rain_24);
+ /* rain since midnight */
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ rain_00);
+ }
+ } else {
+ if (!from) // From local station
+ weather->wx_rain_total[0]=0;
+ }
+
+ /* baro */
+ if (data[21]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+21),4);
+ xastir_snprintf(weather->wx_baro,
+ sizeof(weather->wx_baro),
+ "%0.1f",
+ (float)strtol(temp_data1, &temp_conv, 16)/10.0);
+ } else {
+ if (!from) // From local station
+ weather->wx_baro[0]=0;
+ }
+
+ /* outdoor humidity */
+ if (data[37]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+37),4);
+ xastir_snprintf(weather->wx_hum,
+ sizeof(weather->wx_hum),
+ "%03d",
+ (int)((float)strtol(temp_data1,&temp_conv,16)/10.0));
+ } else {
+ if (!from) // From local station
+ weather->wx_hum[0]=0;
+ }
+
+ /* 1 min wind speed avg */
+ if (len>53 && (data[53]) != '-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+53),4);
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ if (from) { // From remote station
+ weather->wx_speed_sec_time = sec_now();
+ } else {
+ /* local station */
+ computed_gust = compute_gust((float)atof(weather->wx_speed),
+ last_speed,
+ &last_speed_time);
+ weather->wx_speed_sec_time = sec_now();
+ if ( (computed_gust > 0.0) || (weather->wx_gust != 0) )
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%03d",
+ (int)(0.5 + computed_gust));
+ }
+ } else {
+ if (!from) { // From local station
+ if (len>53)
+ weather->wx_speed[0]=0;
+ }
+ }
+ break;
+
+
+
+ //////////////////////////////////////////////////////////
+ // Peet Brothers Ultimeter 2000 in complete record mode //
+ //////////////////////////////////////////////////////////
+ //
+ // In this mode most fields are 4-bytes two's complement. A
+ // few fields are 2-bytes wide.
+ //
+ // <http://www.peetbros.com/HTML_Pages/faqs.htm>
+ //
+ case(PEET_COMPLETE):
+ if (debug_level & 1)
+ fprintf(stderr,"Peet Bros U-2k Packet (Complete Record Mode) %s:<%s>\n",fill->call_sign,data);
+
+ if (!from) { // From local station
+ int done_with_wx_speed = 0;
+
+
+ /* decode only for local station */
+ weather->wx_type=WX_TYPE;
+ xastir_snprintf(weather->wx_station,
+ sizeof(weather->wx_station),
+ "U2k");
+
+
+ if (data[12]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+12),4);
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ }
+ else
+ weather->wx_gust[0]=0;
+
+
+ // Check whether field 115 is available at bytes 452
+ // through 455. If so, that's the one-minute wind
+ // speed average in 0.1kph, which matches the APRS
+ // spec except for the units (which should be MPH).
+ if ( (len >= 456) && (data[452] != '-') ) { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+452),4);
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5
+ + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ done_with_wx_speed++;
+ }
+
+
+ // Some Peet units don't have that particular wind
+ // speed field, so snag what wind speed we can from
+ // the other wind speed fields, which don't quite
+ // match the APRS spec as they're instantaneous
+ // values, not one-minute sustained speeds.
+
+
+ // KG9AE
+ // Peet Bros CR mode wind values should be selected based on which are highest.
+ /* Wind Speed fields 1, 34, and 71. Wind direction fields 2, 35, 72. */
+ if (data[4] !='-') { // '-' signifies invalid data
+ substr(temp_data1, (char *)data+4, 4);
+ temp1 = (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137);
+ }
+ else {
+ temp1=0;
+ }
+ if (data[136] !='-') { // '-' signifies invalid data
+ substr(temp_data1, (char *)data+136, 4);
+ temp2 = (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137);
+ }
+ else {
+ temp2=0;
+ }
+ if (data[284] !='-') { // '-' signifies invalid data
+ substr(temp_data1, (char *)data+284, 4);
+ temp3 = (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137);
+ }
+ else {
+ temp3=0;
+ }
+
+ // fprintf(stderr,"WIND: wind1 %d, wind2 %d, wind3 %d\n", temp1, temp2, temp3);
+
+ // Select wind speed and direction based on which
+ // wind speed is the highest. Ugh, surely there's a
+ // way to make this pretty. A function might be
+ // better.
+ if ( temp1 >= temp2 && temp1 >= temp3 ){
+ // fprintf(stderr,"WIND: ***\n");
+
+ /* wind speed */
+ if (!done_with_wx_speed) {
+ substr(temp_data1,(char *)(data+4),4);
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ }
+
+ /* wind direction */
+ //
+ // Note that the first two digits here may be
+ // 00, or may be FF if a direction calibration
+ // has been entered. We should zero them.
+ //
+ if (data[8]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+8),4);
+ temp_data1[0] = '0';
+ temp_data1[1] = '0';
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "%03d",
+ (int)(((float)strtol(temp_data1,&temp_conv,16)/256.0)*360.0));
+
+ // Check for course = 0. Change to 360.
+ if (strncmp(weather->wx_course,"000",3) == 0) {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "360");
+ }
+
+ } else {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "000");
+ weather->wx_course[0]=0;
+ }
+ }
+ else if ( temp2 >= temp1 && temp2 >= temp3 ){
+ // fprintf(stderr,"WIND: ***\n");
+
+ if (!done_with_wx_speed) {
+ /* wind speed */
+ substr(temp_data1,(char *)(data+136),4);
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ }
+
+ /* wind direction */
+ //
+ // Note that the first two digits here may be
+ // 00, or may be FF if a direction calibration
+ // has been entered. We should zero them.
+ //
+ if (data[140]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+140),4);
+ temp_data1[0] = '0';
+ temp_data1[1] = '0';
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "%03d",
+ (int)(((float)strtol(temp_data1,&temp_conv,16)/256.0)*360.0));
+
+ // Check for course = 0. Change to 360.
+ if (strncmp(weather->wx_course,"000",3) == 0) {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "360");
+ }
+
+ } else {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "000");
+ weather->wx_course[0]=0;
+ }
+ }
+ else if ( temp3 >= temp2 && temp3 >= temp1 ){
+ // fprintf(stderr,"WIND: ***\n");
+
+ if (!done_with_wx_speed) {
+ /* wind speed */
+ substr(temp_data1,(char *)(data+284),4);
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ }
+
+ /* wind direction */
+ //
+ // Note that the first two digits here may be
+ // 00, or may be FF if a direction calibration
+ // has been entered. We should zero them.
+ //
+ if (data[288]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+288),4);
+ temp_data1[0] = '0';
+ temp_data1[1] = '0';
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "%03d",
+ (int)(((float)strtol(temp_data1,&temp_conv,16)/256.0)*360.0));
+
+ // Check for course = 0. Change to 360.
+ if (strncmp(weather->wx_course,"000",3) == 0) {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "360");
+ }
+
+ } else {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "000");
+ weather->wx_course[0]=0;
+ }
+ }
+ else { /* Or default to the first value */
+ // fprintf(stderr,"WIND: DEFAULTING!\n");
+
+ if (!done_with_wx_speed) {
+ /* wind speed */
+ substr(temp_data1,(char *)(data+4),4);
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ }
+
+ /* wind direction */
+ //
+ // Note that the first two digits here may be
+ // 00, or may be FF if a direction calibration
+ // has been entered. We should zero them.
+ //
+ if (data[8]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+8),4);
+ temp_data1[0] = '0';
+ temp_data1[1] = '0';
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "%03d",
+ (int)(((float)strtol(temp_data1,&temp_conv,16)/256.0)*360.0));
+
+ // Check for course = 0. Change to 360.
+ if (strncmp(weather->wx_course,"000",3) == 0) {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "360");
+ }
+
+ } else {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "000");
+ weather->wx_course[0]=0;
+ }
+ }
+
+
+ /* outdoor temp */
+ if (data[24]!='-') { // '-' signifies invalid data
+ int temp4;
+
+ substr(temp_data1,(char *)(data+24),4);
+ temp4 = (int)strtol(temp_data1,&temp_conv,16);
+
+ if (temp_data1[0] > '7') { // Negative value, convert
+ temp4 = (temp4 & (temp4-0x7FFF)) - 0x8000;
+ }
+
+ xastir_snprintf(weather->wx_temp,
+ sizeof(weather->wx_temp),
+ "%03d",
+ (int)((float)((temp4<<16)/65536)/10.0));
+ } else
+ weather->wx_temp[0]=0;
+
+// We don't want to parse this here because compute_rain()
+// calculates this for us from the accumulating long-term rain
+// total. If we were to do it here as well, we'll get conflicting
+// results. Since only some units put out today's rain total, we'll
+// just rely on our own calculations for it instead. It'll work
+// across more units.
+/*
+ // todays rain total (on some units)
+ if (data[28]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+28),4);
+ switch (WX_rain_gauge_type) {
+ case 1: // 0.1" rain gauge
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)/10.0);
+ break;
+ case 3: // 0.1mm rain gauge
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)/254.0);
+ break;
+ case 2: // 0.01" rain gauge
+ case 0: // No conversion
+ default:
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)/100.0);
+ break;
+ }
+ } else
+ weather->wx_prec_00[0]=0;
+*/
+
+ /* rain total long term */
+ if ((char)data[432]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+432),4);
+ switch (WX_rain_gauge_type) {
+ case 1: // 0.1" rain gauge
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)*10);
+ break;
+ case 3: // 0.1mm rain gauge
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16)/2.54);
+ break;
+ case 2: // 0.01" rain gauge
+ case 0: // No conversion
+ default:
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ (float)strtol(temp_data1,&temp_conv,16));
+ break;
+ }
+ /* Since local station only */
+ compute_rain((float)atof(weather->wx_rain_total));
+ weather->wx_compute_rain_rates=1;
+
+ /*last hour rain */
+ xastir_snprintf(weather->wx_rain,
+ sizeof(weather->wx_rain),
+ "%0.2f",
+ rain_minute_total);
+
+ /*last 24 hour rain */
+ xastir_snprintf(weather->wx_prec_24,
+ sizeof(weather->wx_prec_24),
+ "%0.2f",
+ rain_24);
+
+ /* rain since midnight */
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ rain_00);
+ } else
+ weather->wx_rain_total[0]=0;
+
+ /* baro */
+ if (data[32]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+32),4);
+ xastir_snprintf(weather->wx_baro,
+ sizeof(weather->wx_baro),
+ "%0.1f",
+ (float)strtol(temp_data1,&temp_conv,16)/10.0);
+ } else
+ weather->wx_baro[0]=0;
+
+ /* outdoor humidity */
+ if (data[52]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+52),4);
+ xastir_snprintf(weather->wx_hum,
+ sizeof(weather->wx_hum),
+ "%03d",
+ (int)((float)strtol(temp_data1,&temp_conv,16)/10.0));
+ } else
+ weather->wx_hum[0]=0;
+
+ /* dew point */
+ if (data[60]!='-') { // '-' signifies invalid data
+ int temp4;
+
+ substr(temp_data1,(char *)(data+60),4);
+ temp4 = (int)strtol(temp_data1,&temp_conv,16);
+
+ if (temp_data1[0] > '7') { // Negative value, convert
+ temp4 = (temp4 & (temp4-0x7FFF)) - 0x8000;
+ }
+
+ xastir_snprintf(wx_dew_point,
+ sizeof(wx_dew_point),
+ "%03d",
+ (int)((float)((temp4<<16)/65536)/10.0));
+ wx_dew_point_on = 1;
+ }
+
+ /*high winds for today*/
+ if (data[248]!='-') { // '-' signifies invalid data
+ substr(temp_data1,(char *)(data+248),4);
+ xastir_snprintf(wx_high_wind,
+ sizeof(wx_high_wind),
+ "%03d",
+ (int)(0.5 + ((float)strtol(temp_data1,&temp_conv,16)/10.0)*0.62137));
+ wx_high_wind_on = 1;
+ }
+
+ /*wind chill */
+ if (data[20]!='-') { // '-' signifies invalid data
+ int temp4;
+
+ substr(temp_data1,(char *)(data+20),4);
+ temp4 = (int)strtol(temp_data1,&temp_conv,16);
+
+ if (temp_data1[0] > '7') { // Negative value, convert
+ temp4 = (temp4 & (temp4-0x7FFF)) - 0x8000;
+ }
+
+ xastir_snprintf(wx_wind_chill,
+ sizeof(wx_wind_chill),
+ "%03d",
+ (int)((float)((temp4<<16)/65536)/10.0));
+ wx_wind_chill_on = 1;
+ }
+
+ /*3-Hr Barometric Change */
+ if (data[36]!='-') { // '-' signifies invalid data
+ int temp4;
+
+ substr(temp_data1,(char *)(data+36),4);
+ temp4 = (int)strtol(temp_data1,&temp_conv,16);
+
+ if (temp_data1[0] > '7') { // Negative value, convert
+ temp4 = (temp4 & (temp4-0x7FFF)) - 0x8000;
+ }
+
+ xastir_snprintf(wx_three_hour_baro,
+ sizeof(wx_three_hour_baro),
+ "%0.2f",
+// Old code
+// (float)((strtol(temp_data1,&temp_conv,16)<<16)/65536)/100.0/3.38639);
+// New code, fix by Matt Werner, kb0kqa:
+ (float)((temp4<<16)/65536)/10.0);
+
+ wx_three_hour_baro_on = 1;
+ }
+
+ /* High Temp for Today*/
+ if (data[276]!='-') { // '-' signifies invalid data
+ int temp4;
+
+ substr(temp_data1,(char *)(data+276),4);
+ temp4 = (int)strtol(temp_data1,&temp_conv,16);
+
+ if (temp_data1[0] > '7') { // Negative value, convert
+ temp4 = (temp4 & (temp4-0x7FFF)) - 0x8000;
+ }
+
+ xastir_snprintf(wx_hi_temp,
+ sizeof(wx_hi_temp),
+ "%03d",
+ (int)((float)((temp4<<16)/65536)/10.0));
+ wx_hi_temp_on = 1;
+ } else
+ wx_hi_temp_on = 0;
+
+ /* Low Temp for Today*/
+ if (data[100]!='-') { // '-' signifies invalid data
+ int temp4;
+
+ substr(temp_data1,(char *)(data+100),4);
+ temp4 = (int)strtol(temp_data1,&temp_conv,16);
+
+ if (temp_data1[0] > '7') { // Negative value, convert
+ temp4 = (temp4 & (temp4-0x7FFF)) - 0x8000;
+ }
+
+ xastir_snprintf(wx_low_temp,
+ sizeof(wx_low_temp),
+ "%03d",
+ (int)((float)((temp4<<16)/65536)/10.0));
+ wx_low_temp_on = 1;
+ } else
+ wx_low_temp_on = 0;
+
+ /* Heat Index Calculation*/
+ hi_hum=atoi(weather->wx_hum);
+ rh2= atoi(weather->wx_hum);
+ rh2=(rh2 * rh2);
+ hidx_temp=atoi(weather->wx_temp);
+ t2= atoi(weather->wx_temp);
+ t2=(t2 * t2);
+
+ if (hidx_temp >= 70) {
+ heat_index=-42.379+2.04901523 * hidx_temp+10.1433127 * hi_hum-0.22475541
+ * hidx_temp * hi_hum-0.00683783 * t2-0.05481717 * rh2+0.00122874
+ * t2 * hi_hum+0.00085282 * hidx_temp * rh2-0.00000199 * t2 * rh2;
+ xastir_snprintf (wx_heat_index,
+ sizeof(wx_heat_index),
+ "%03d",
+ heat_index);
+ wx_heat_index_on = 1;
+ } else
+ wx_heat_index_on = 0;
+ }
+ break;
+
+
+
+ ////////////////////////
+ // Qualimetrics Q-Net //
+ ////////////////////////
+ case(QM_WX):
+ if (debug_level & 1)
+ fprintf(stderr,"Qualimetrics Q-Net %s:<%s>\n",fill->call_sign,data);
+
+ weather->wx_type=WX_TYPE;
+ xastir_snprintf(weather->wx_station,
+ sizeof(weather->wx_station),
+ "Q-N");
+
+ // Can this sscanf overflow the "temp" buffer? I
+ // changed the length of temp to MAX_DEVICE_BUFFER to
+ // avoid this problem.
+ if (6 != sscanf((char *)data,"%19s %d %19s %d %19s %d",temp,&temp1,temp,&temp2,temp,&temp3)) {
+ fprintf(stderr,"wx_fill_data:sscanf parsing error\n");
+ }
+
+ /* outdoor temp */
+ xastir_snprintf(weather->wx_temp,
+ sizeof(weather->wx_temp),
+ "%03d",
+ (int)((temp2/10.0)));
+
+ /* baro */
+ xastir_snprintf(weather->wx_baro,
+ sizeof(weather->wx_baro),
+ "%0.1f",
+ ((float)temp3/100.0)*33.864);
+
+ /* outdoor humidity */
+ xastir_snprintf(weather->wx_hum,
+ sizeof(weather->wx_hum),
+ "%03d",
+ temp1);
+
+ if (!from) { // From local station
+ weather->wx_gust[0]=0;
+ weather->wx_course[0]=0;
+ weather->wx_rain[0]=0;
+ weather->wx_prec_00[0]=0;
+ weather->wx_prec_24[0]=0;
+ weather->wx_rain_total[0]=0;
+ weather->wx_gust[0]=0;
+ weather->wx_speed[0]=0;
+ }
+ break;
+
+
+
+ ///////////////////////////////////////////////////////////
+ // Radio Shack WX-200 or Huger/Oregon Scientific WM-918 //
+ ///////////////////////////////////////////////////////////
+ case(RSWX200):
+
+ // Notes: Many people run the wx200d daemon connected to the weather station,
+ // with Xastir then connected to wx200d. Note that wx200d changes the protocol
+ // slightly: It only sends frames that have changed to the clients. This means
+ // even if the weather station is sending regular packets, wx200d won't send
+ // them along to Xastir if all the bits are the same as the last packet of that
+ // type. To fix this I had to tie into the main.c:UpdateTime() function to do
+ // regular updates at a 30 second rate, to keep the rain and gust queues cycling
+ // on a regular basis.
+ //
+ // 2nd Note: Some WX-200 weather stations send bogus data. I had to add in a
+ // bunch of filtering to keep the global variables from getting corrupted by
+ // this data. More filtering may need to be done and/or the limits may need to
+ // be changed.
+
+ if (!from) { // From local station
+ if (debug_level & 1)
+ fprintf(stderr,"RSWX200 WX (binary)\n");
+
+ weather->wx_type=WX_TYPE;
+ xastir_snprintf(weather->wx_station,
+ sizeof(weather->wx_station),
+ "RSW");
+
+ switch (data[0]) {
+ case 0x8f: /* humidity */
+ if ( (rswnc(data[20]) <= 100) && (rswnc(data[2]) >= 0) )
+ xastir_snprintf(weather->wx_hum,
+ sizeof(weather->wx_hum),
+ "%03d",
+ rswnc(data[20]));
+ else
+ //sprintf(weather->wx_hum,"100");
+ fprintf(stderr,"Humidity out-of-range, ignoring: %03d\n",rswnc(data[20]) );
+ break;
+
+ case 0x9f: /* temp */
+ /* all data in C ?*/
+ xastir_snprintf(temp_data1,
+ sizeof(temp_data1),
+ "%c%d%0.1f",
+ ((data[17]&0x08) ? '-' : '+'),(data[17]&0x7),rswnc(data[16])/10.0);
+ /*fprintf(stderr,"temp data: <%s> %d %d %d\n", temp_data1,((data[17]&0x08)==0x08),(data[17]&0x7),rswnc(data[16]));*/
+ temp_temp = (float)((atof(temp_data1)*1.8)+32);
+ if ( (temp_temp >= -99.0) && (temp_temp < 200.0) ) {
+ xastir_snprintf(weather->wx_temp,
+ sizeof(weather->wx_temp),
+ "%03d",
+ (int)((atof(temp_data1)*1.8)+32));
+ /*fprintf(stderr,"Temp %s C %0.2f %03d\n",temp_data1,atof(temp_data1),(int)atof(temp_data1));
+ fprintf(stderr,"Temp F %0.2f %03d\n",(atof(temp_data1)*1.8)+32,(int)(atof(temp_data1)*1.8)+32);
+ */
+ } else { // We don't want to save this one
+ fprintf(stderr,"Temp out-of-range, ignoring: %0.2f\n", temp_temp);
+ }
+ xastir_snprintf(temp_data1,
+ sizeof(temp_data1),
+ "%c%d%d.%d",
+ ((data[18]&0x80) ? '-' : '+'),(data[18]&0x70)>>4,(data[18]&0x0f),(data[17] & 0xf0) >> 4);
+ xastir_snprintf(wx_hi_temp,
+ sizeof(wx_hi_temp),
+ "%03d",
+ (int)((atof(temp_data1)*1.8)+32));
+ wx_hi_temp_on=1;
+ xastir_snprintf(temp_data1,
+ sizeof(temp_data1),
+ "%c%d%d.%d",
+ ((data[23]&0x80) ? '-' : '+'),(data[23]&0x70)>>4,(data[23]&0x0f),(data[22] & 0xf0) >> 4);
+ xastir_snprintf(wx_low_temp,
+ sizeof(wx_low_temp),
+ "%03d",
+ (int)((atof(temp_data1)*1.8)+32));
+ wx_low_temp_on=1;
+ break;
+
+ case 0xaf: /* baro/dewpt */
+ // local baro pressure in mb?
+ // sprintf(weather->wx_baro,"%02d%02d",rswnc(data[2]),rswnc(data[1]));
+ // Sea Level Adjusted baro in mb
+ xastir_snprintf(weather->wx_baro,
+ sizeof(weather->wx_baro),
+ "%0d%02d%0.1f",
+ (data[5]&0x0f),
+ rswnc(data[4]),
+ ((float)rswnc(data[3])/10.0));
+
+ /* dew point in C */
+ temp_temp = (int)((rswnc(data[18])*1.8)+32);
+ if ( (temp_temp >= 32.0) && (temp_temp < 150.0) )
+ xastir_snprintf(wx_dew_point,
+ sizeof(wx_dew_point),
+ "%03d",
+ (int)((rswnc(data[18])*1.8)+32));
+ else
+ fprintf(stderr,"Dew point out-of-range, ignoring: %0.2f\n", temp_temp);
+ break;
+
+ case 0xbf: /* Rain */
+ // All data in mm. Convert to hundredths of an inch.
+ xastir_snprintf(temp_data1,
+ sizeof(temp_data1),
+ "%02d%02d",
+ rswnc(data[6]),
+ rswnc(data[5]));
+
+ temp_temp = (float)(atof(temp_data1) * 3.9370079);
+
+ if ( (temp_temp >= 0) && (temp_temp < 51200.0) ) { // Between 0 and 512 inches
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%0.2f",
+ atof(temp_data1) * 3.9370079);
+
+ /* Since local station only */
+ compute_rain((float)atof(weather->wx_rain_total));
+ weather->wx_compute_rain_rates=1;
+
+ /* Last hour rain */
+ xastir_snprintf(weather->wx_rain,
+ sizeof(weather->wx_rain),
+ "%0.2f",
+ rain_minute_total);
+
+ /* Last 24 hour rain */
+ xastir_snprintf(weather->wx_prec_24,
+ sizeof(weather->wx_prec_24),
+ "%0.2f",
+ rain_24);
+
+ /* Rain since midnight */
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ rain_00);
+ } else {
+ fprintf(stderr,"Total Rain out-of-range, ignoring: %0.2f\n", temp_temp);
+ }
+ break;
+
+ case 0xcf: /* Wind w/chill*/
+ /* get last gust speed */
+ if (strlen(weather->wx_gust) > 0) {
+ /* get last speed */
+ last_speed=(float)atof(weather->wx_gust);
+ last_speed_time=weather->wx_speed_sec_time;
+ }
+ /* all data in m/s */
+ /* average wind speed */
+ xastir_snprintf(temp_data1,
+ sizeof(temp_data1),
+ "%01d%0.1f",
+ (data[5]&0xf),
+ (float)( rswnc(data[4]) / 10 ));
+ // Convert to mph
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%03d",
+ (int)(0.5 + (atof(temp_data1)*2.2369)));
+
+ /* wind gust */
+ xastir_snprintf(temp_data1,
+ sizeof(temp_data1),
+ "%01d%0.1f",
+ (data[2]&0xf),
+ (float)( rswnc(data[1]) / 10 ));
+ /*sprintf(weather->wx_gust,"%03d",(int)(0.5 + (atof(temp_data1)*2.2369)));*/
+
+ /* do computed gust, convert to mph */
+ computed_gust = compute_gust((int)(0.5 + (atof(temp_data1)*2.2369)),
+ last_speed,
+ &last_speed_time);
+ weather->wx_speed_sec_time = sec_now();
+ if ( (computed_gust > 0.0) || (weather->wx_gust != 0) )
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%03d",
+ (int)(0.5 + computed_gust));
+
+ /* high wind gust */
+ xastir_snprintf(temp_data1,
+ sizeof(temp_data1),
+ "%01d%0.1f",
+ (data[8]&0xf),
+ (float)( rswnc(data[7]) / 10 ));
+ xastir_snprintf(wx_high_wind,
+ sizeof(wx_high_wind),
+ "%03d",
+ (int)(0.5 + (atof(temp_data1)*2.2369)));
+ wx_high_wind_on = 1;
+
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "%02d%01d",
+ rswnc(data[3]),
+ (data[2]&0xf0)>>4);
+
+ // Check for course = 0. Change to 360.
+ if (strncmp(weather->wx_course,"000",3) == 0) {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "360");
+ }
+
+ /* wind chill in C */
+ xastir_snprintf(temp_data1,
+ sizeof(temp_data1),
+ "%c%d",
+ ((data[21]&0x20) ? '-' : '+'),
+ rswnc(data[16]));
+
+ temp_temp = (float)((atof(temp_data1)*1.8)+32);
+ if ( (temp_temp > -200.0) && (temp_temp < 200.0) )
+ xastir_snprintf(wx_wind_chill,
+ sizeof(wx_wind_chill),
+ "%03d",
+ (int)((atof(temp_data1)*1.8)+32));
+ else
+ fprintf(stderr,"Wind_chill out-of-range, ignoring: %0.2f\n", temp_temp);
+
+ wx_wind_chill_on = 1;
+ break;
+ default:
+ break;
+ }
+
+ if (strlen(weather->wx_hum) > 0 && strlen(weather->wx_temp) > 0) {
+ /* Heat Index Calculation*/
+ hi_hum=atoi(weather->wx_hum);
+ rh2= atoi(weather->wx_hum);
+ rh2=(rh2 * rh2);
+ hidx_temp=atoi(weather->wx_temp);
+ t2= atoi(weather->wx_temp);
+ t2=(t2 * t2);
+
+ if (hidx_temp >= 70) {
+ heat_index=(-42.379+2.04901523 * hidx_temp+10.1433127 * hi_hum-0.22475541 * hidx_temp *
+ hi_hum-0.00683783 * t2-0.05481717 * rh2+0.00122874 * t2 * hi_hum+0.00085282 *
+ hidx_temp * rh2-0.00000199 * t2 * rh2);
+ xastir_snprintf(wx_heat_index,
+ sizeof(wx_heat_index),
+ "%03d",
+ heat_index);
+
+ wx_heat_index_on=1;
+ }
+ else {
+ wx_heat_index[0] = 0;
+ }
+ } // end of heat index calculation
+ } // end of if (!from)
+ break; // End of case for RSWX200 weather station
+
+
+ ///////////////////////////////////////////////////////////
+ // Davis WMII/WWIII/Vantage Pro via meteo & db2APRS //
+ ///////////////////////////////////////////////////////////
+
+ // Note: format is really APRS Spec 'positionless' WX string w/tag for X and Davis
+
+ case(DAVISMETEO) :
+
+
+ // todo - need to deal with lack of values, such as c...s...g...t045 string
+
+ memset(weather->wx_course,0,4); // Keep out fradulent data...
+ memset(weather->wx_speed,0,4);
+ memset(weather->wx_gust,0,4);
+ memset(weather->wx_temp,0,5);
+ memset(weather->wx_rain,0,10);
+ memset(weather->wx_prec_00,0,10);
+ memset(weather->wx_prec_24,0,10);
+ memset(weather->wx_rain_total,0,10);
+ memset(weather->wx_hum,0,5);
+ memset(weather->wx_baro,0,10);
+ memset(weather->wx_station,0,MAX_WXSTATION);
+
+ if ((temp_conv=strchr((char *)data,'c'))) { // Wind Direction in Degrees
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "%s",
+ temp_conv+1);
+ weather->wx_course[3] = '\0';
+ }
+
+ // Check for course = 0. Change to 360.
+ if (strncmp(weather->wx_course,"000",3) == 0) {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "360");
+ }
+
+ if ((temp_conv=strchr((char *)data,'s'))) { // Wind Speed in MPH - not snowfall
+ xastir_snprintf(weather->wx_speed,
+ sizeof(weather->wx_speed),
+ "%s",
+ temp_conv+1);
+ weather->wx_speed[3] = '\0';
+ }
+
+ if ((temp_conv=strchr((char *)data,'g'))) { // Wind Gust in MPH
+ xastir_snprintf(weather->wx_gust,
+ sizeof(weather->wx_gust),
+ "%s",
+ temp_conv+1);
+ weather->wx_gust[3] = '\0';
+
+ // compute high wind
+ if(wx_high_wind[0] == '\0' || // first time
+ (get_hours() == 0 && get_minutes() == 0) || // midnite
+ (atol(weather->wx_gust) > atol(wx_high_wind))) { // gust
+ xastir_snprintf(wx_high_wind,
+ sizeof(wx_high_wind),
+ "%s",
+ weather->wx_gust);
+ }
+ wx_high_wind_on=1;
+ }
+
+ if ((temp_conv=strchr((char *)data,'t'))) { // Temperature in Degrees F
+ xastir_snprintf(weather->wx_temp,
+ sizeof(weather->wx_temp),
+ "%s",
+ temp_conv+1);
+ weather->wx_temp[3] = '\0';
+
+ // compute hi temp, since APRS doesn't send that
+ if(wx_hi_temp[0] == '\0' || // first time
+ (get_hours() == 0 && get_minutes() == 0) || // midnite
+ (atol(weather->wx_temp) > atol(wx_hi_temp))) {
+ xastir_snprintf(wx_hi_temp,
+ sizeof(wx_hi_temp),
+ "%s",
+ weather->wx_temp);
+ }
+ wx_hi_temp_on=1;
+
+ // compute low temp, since APRS doesn't send that
+ if(wx_low_temp[0] == '\0' || // first time
+ (get_hours() == 0 && get_minutes() == 0) || // midnite
+ (atol(weather->wx_temp) < atol(wx_low_temp))) {
+ xastir_snprintf(wx_low_temp,
+ sizeof(wx_low_temp),
+ "%s",
+ weather->wx_temp);
+ }
+ wx_low_temp_on=1;
+ }
+
+ if ((temp_conv=strchr((char *)data,'r'))) { // Rain per hour
+ xastir_snprintf(weather->wx_rain,
+ sizeof(weather->wx_rain),
+ "%s",
+ temp_conv+1);
+ weather->wx_rain[3] = '\0';
+ }
+
+ if ((temp_conv=strchr((char *)data,'p'))) { // Rain per 24 hrs/total
+ xastir_snprintf(weather->wx_prec_24,
+ sizeof(weather->wx_prec_24),
+ "%s",
+ temp_conv+1);
+ weather->wx_prec_24[3] = '\0';
+ }
+
+ if ((temp_conv=strchr((char *)data,'P'))) { // Rain since midnight
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%s",
+ temp_conv+1);
+ weather->wx_prec_00[3] = '\0';
+ }
+
+ if ((temp_conv=strchr((char *)data,'T'))) { // Total Rain since
+ // wx station reset
+ xastir_snprintf(weather->wx_rain_total,
+ sizeof(weather->wx_rain_total),
+ "%s",
+ temp_conv+1);
+ weather->wx_rain_total[4] = '\0';
+ }
+
+ // Ok, here's the deal --- if we got total rain AND we didn't get
+ // rain-since-midnight, fix it up.
+ // This is a problem with LaCrosse --- no rain-since-midnight
+ // provided. Don't do anything at all if we didn't get total rain
+ // from the station. compute_rain *depends* on "total rain" being
+ // a strictly increasing number that is never reset to zero during
+ // Xastir's run.
+ if (strlen(weather->wx_rain_total) >0 ) {
+ compute_rain((float)atof(weather->wx_rain_total));
+ if (weather->wx_prec_00[0] == '\0') {
+ /* rain since midnight */
+ xastir_snprintf(weather->wx_prec_00,
+ sizeof(weather->wx_prec_00),
+ "%0.2f",
+ rain_00);
+ }
+ }
+
+ // we are should be getting total rain from the station, but
+ // we are also getting the rates.
+ // Davis gives 24-hour, since-midnight, and 1-hour rates.
+ // LaCrosse gives 24 and 1 hour.
+ // Don't recompute what the station already gave us.
+ weather->wx_compute_rain_rates=0;
+
+ if ((temp_conv=strchr((char *)data,'h'))) { // Humidity %
+
+ if (!strncmp(temp_conv+1,"00",2)) { // APRS says 00 is
+ xastir_snprintf(weather->wx_hum, // 100% humidity
+ sizeof(weather->wx_hum),
+ "%s",
+ "100");
+ weather->wx_hum[3] = '\0';
+ } else {
+ xastir_snprintf(weather->wx_hum, // humidity less than
+ sizeof(weather->wx_hum), // 100%
+ "%s",
+ temp_conv+1);
+ weather->wx_hum[2] = '\0';
+ }
+ }
+
+ if ((temp_conv=strchr((char *)data,'b'))) { // Air Pressure in 1/10 hPa
+ memset(temp_data1,0,sizeof(temp_data1));
+
+ xastir_snprintf(temp_data1,
+ sizeof(temp_data1),
+ "%s",
+ temp_conv+1);
+ temp_data1[5] = '\0';
+
+ temp_temp = (float)(atof(temp_data1))/10.0;
+ xastir_snprintf(temp_data1,
+ sizeof(temp_data1),
+ "%0.1f",
+ temp_temp);
+ xastir_snprintf(weather->wx_baro,
+ sizeof(weather->wx_baro),
+ "%s",
+ temp_data1);
+ }
+
+ if ((temp_conv=strchr((char *)data,'x'))) { // WX Station Identifier
+ xastir_snprintf(weather->wx_station,
+ sizeof(weather->wx_station),
+ "%s",
+ temp_conv+1);
+ weather->wx_station[MAX_WXSTATION-1] = '\0';
+ }
+
+ // now compute wind chill
+ wind_chill = 35.74 + .6215 * atof(weather->wx_temp) -
+ 35.75 * pow(atof(weather->wx_gust), .16) +
+ .4275 * atof(weather->wx_temp) *
+ pow(atof(weather->wx_gust), .16);
+
+ if((wind_chill < atof(weather->wx_temp)) &&
+ (atof(weather->wx_temp) < 50)) {
+
+ xastir_snprintf(wx_wind_chill,
+ sizeof(wx_wind_chill),
+ "%.0f",
+ wind_chill);
+ wx_wind_chill_on = 1;
+ }
+ else {
+ wx_wind_chill_on = 0;
+ wx_wind_chill[0] = '\0';
+ }
+
+ // The rest of the optional WX data is not used by
+ // xastir (Luminosity, etc), except for snow, which
+ // conflicts with wind speed (both are lower case 's')
+
+ if (debug_level & 1)
+ fprintf(stdout,"Davis Decode: wd-%s,ws-%s,wg-%s,t-%s,rh-%s,r00-%s,r24-%s,rt-%s,h-%s,ap-%s,station-%s\n",
+
+ weather->wx_course,weather->wx_speed,weather->wx_gust,
+ weather->wx_temp,weather->wx_rain,weather->wx_prec_00,
+ weather->wx_prec_24,weather->wx_rain_total,
+ weather->wx_hum,weather->wx_baro,weather->wx_station);
+ break;
+ // This is the output of the Davis APRS Data Logger. The format
+ // is in fact exactly the same as a regular APRS weather packet,
+ // complete with position information. Ignore that.
+ // @xxxxxxzDDMM.mmN/DDDMM.mmW_CSE/SPDgGGGtTTTrRRRpRRRPRRRhXXbXXXXX.DsVP
+ case (DAVISAPRSDL):
+
+ memset(weather->wx_course,0,4); // Keep out fradulent data...
+ memset(weather->wx_speed,0,4);
+ memset(weather->wx_gust,0,4);
+ memset(weather->wx_temp,0,5);
+ memset(weather->wx_rain,0,10);
+ memset(weather->wx_prec_00,0,10);
+ memset(weather->wx_prec_24,0,10);
+ memset(weather->wx_rain_total,0,10);
+ memset(weather->wx_hum,0,5);
+ memset(weather->wx_baro,0,10);
+ memset(weather->wx_station,0,MAX_WXSTATION);
+
+ if (sscanf((char *)data,
+ "%*27s%3s/%3sg%3st%3sr%3sp%3sP%3sh%2sb%5s.DsVP",
+ weather->wx_course,
+ weather->wx_speed,
+ weather->wx_gust,
+ weather->wx_temp,
+ weather->wx_rain,
+ weather->wx_prec_24,
+ weather->wx_prec_00,
+ weather->wx_hum,
+ weather->wx_baro) == 9){
+ // then we got all the data out of the packet... now process
+ // First null-terminate all the strings:
+ weather->wx_course[3]='\0';
+ weather->wx_speed[3]='\0';
+ weather->wx_gust[3]='\0';
+ weather->wx_temp[3]='\0';
+ weather->wx_rain[3]='\0';
+ weather->wx_prec_24[3]='\0';
+ weather->wx_prec_00[3]='\0';
+ weather->wx_hum[2]='\0';
+ weather->wx_baro[6]='\0';
+
+
+ // NOTE: Davis APRS Data Logger does NOT provide total rain,
+ // and so data from compute_rain (which needs total rain) will
+ // be wrong. Set this flag to stop that from clobbering our
+ // good rain rate data.
+ weather->wx_compute_rain_rates=0;
+
+ // Check for course = 0. Change to 360.
+ if (strncmp(weather->wx_course,"000",3) == 0) {
+ xastir_snprintf(weather->wx_course,
+ sizeof(weather->wx_course),
+ "360");
+ }
+
+ // compute high wind
+ if(wx_high_wind[0] == '\0' || // first time
+ (get_hours() == 0 && get_minutes() == 0) || // midnite
+ (atol(weather->wx_gust) > atol(wx_high_wind))) { // gust
+ xastir_snprintf(wx_high_wind,
+ sizeof(wx_high_wind),
+ "%s",
+ weather->wx_gust);
+ }
+ wx_high_wind_on=1;
+
+ // compute hi temp, since APRS doesn't send that
+ if(wx_hi_temp[0] == '\0' || // first time
+ (get_hours() == 0 && get_minutes() == 0) || // midnite
+ (atol(weather->wx_temp) > atol(wx_hi_temp))) {
+ xastir_snprintf(wx_hi_temp,
+ sizeof(wx_hi_temp),
+ "%s",
+ weather->wx_temp);
+ }
+ wx_hi_temp_on=1;
+
+ // compute low temp, since APRS doesn't send that
+ if(wx_low_temp[0] == '\0' || // first time
+ (get_hours() == 0 && get_minutes() == 0) || // midnite
+ (atol(weather->wx_temp) < atol(wx_low_temp))) {
+ xastir_snprintf(wx_low_temp,
+ sizeof(wx_low_temp),
+ "%s",
+ weather->wx_temp);
+ }
+ wx_low_temp_on=1;
+
+
+ // fix up humidity --- 00 in APRS means 100%:
+ if (strncmp(weather->wx_hum,"00",2)==0) {
+ weather->wx_hum[0]='1';
+ weather->wx_hum[1]=weather->wx_hum[2]='0';
+ weather->wx_hum[3]='\0';
+ }
+
+ // fix up barometer. APRS sends in 10ths of millibars:
+ temp_temp=(float)(atof(weather->wx_baro))/10.0;
+ weather->wx_baro[0]='\0'; // zero out so snprintf doesn't append
+ xastir_snprintf(weather->wx_baro,
+ sizeof(weather->wx_baro),
+ "%0.1f",
+ temp_temp); // this should terminate Just Fine.
+
+ // now compute wind chill
+ wind_chill = 35.74 + .6215 * atof(weather->wx_temp) -
+ 35.75 * pow(atof(weather->wx_gust), .16) +
+ .4275 * atof(weather->wx_temp) *
+ pow(atof(weather->wx_gust), .16);
+
+ if((wind_chill < atof(weather->wx_temp)) &&
+ (atof(weather->wx_temp) < 50)) {
+
+ xastir_snprintf(wx_wind_chill,
+ sizeof(wx_wind_chill),
+ "%.0f",
+ wind_chill);
+ wx_wind_chill_on = 1;
+ }
+ else {
+ wx_wind_chill_on = 0;
+ wx_wind_chill[0] = '\0';
+ }
+ xastir_snprintf(weather->wx_station,
+ sizeof(weather->wx_station),
+ "%s",
+ (char *) &(data[63]));
+
+ /* Heat Index Calculation*/
+ hi_hum=atoi(weather->wx_hum);
+ rh2= atoi(weather->wx_hum);
+ rh2=(rh2 * rh2);
+ hidx_temp=atoi(weather->wx_temp);
+ t2= atoi(weather->wx_temp);
+ t2=(t2 * t2);
+
+ if (hidx_temp >= 70) {
+ heat_index=-42.379+2.04901523 * hidx_temp+10.1433127 * hi_hum-0.22475541
+ * hidx_temp * hi_hum-0.00683783 * t2-0.05481717 * rh2+0.00122874
+ * t2 * hi_hum+0.00085282 * hidx_temp * rh2-0.00000199 * t2 * rh2;
+ xastir_snprintf (wx_heat_index,
+ sizeof(wx_heat_index),
+ "%03d",
+ heat_index);
+ wx_heat_index_on = 1;
+ } else
+ wx_heat_index_on = 0;
+
+
+ if (debug_level & 1)
+ fprintf(stdout,"Davis APRS DataLogger Decode $Revision: 1.80 $: wd-%s,ws-%s,wg-%s,t-%s,rh-%s,r24-%s,r00-%s,h-%s,ap-%s,station-%s\n",
+
+ weather->wx_course,weather->wx_speed,weather->wx_gust,
+ weather->wx_temp, weather->wx_rain,
+ weather->wx_prec_24, weather->wx_prec_00,weather->wx_hum,weather->wx_baro,
+ weather->wx_station);
+ }
+ break;
+
+ }
+ // End of big switch
+} // End of wx_fill_data()
+
+
+
+
+
+//**********************************************************
+// Decode WX data line
+// wx_line: raw wx data to decode
+//
+// This is called from main.c:UpdateTime() only. It
+// decodes data for serially-connected and network-connected
+// WX interfaces only. It calls wx_fill_data() to do the
+// real work once it figures out what type of data it has.
+//**********************************************************
+//
+// Note that the length of "wx_line" can be up to MAX_DEVICE_BUFFER,
+// which is currently set to 4096.
+//
+void wx_decode(unsigned char *wx_line, int data_length, int port) {
+ DataRow *p_station;
+ int decoded;
+ int find;
+ int i;
+ int len;
+ char time_data[MAX_TIME];
+ unsigned int check_sum;
+ int max;
+ WeatherRow *weather;
+ float t1,t2,t3,t4,t5,t6,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19;
+ int t7,t8;
+
+
+ //fprintf(stderr,"wx_decode: %s\n",wx_line);
+ //fprintf(stderr,"\nwx_decode: %d bytes\n", data_length);
+
+ find=0;
+
+ len = data_length;
+ if (len == 0) {
+ len=strlen((char *)wx_line);
+ }
+
+ if (len>10 || ((int)wx_line[0]!=0 && port_data[port].data_type==1)) {
+ if (search_station_name(&p_station,my_callsign,1)) {
+ if (get_weather_record(p_station)) { // DK7IN: only add record if we found something...
+ weather = p_station->weather_data;
+
+ decoded=0;
+ /* Ok decode wx data */
+ if (wx_line[0]=='!'
+ && wx_line[1]=='!'
+ && is_xnum_or_dash((char *)(wx_line+2),40)
+ && port_data[port].data_type==0) {
+
+ /* Found Peet Bros U-2k */
+ if (debug_level & 1)
+ fprintf(stderr,"Found Peet Bros U-2k WX:%s\n",wx_line+2);
+
+ xastir_snprintf(wx_station_type,
+ sizeof(wx_station_type),
+ "%s",
+ langcode("WXPUPSI011"));
+
+ xastir_snprintf(raw_wx_string,
+ sizeof(raw_wx_string),
+ "%s",
+ wx_line);
+
+ raw_wx_string[MAX_RAW_WX_STRING] = '\0'; // Terminate it
+
+ xastir_snprintf(weather->wx_time,
+ sizeof(weather->wx_time),
+ "%s",
+ get_time(time_data));
+
+ weather->wx_sec_time=sec_now();
+ //weather->wx_data=1;
+ wx_fill_data(0,APRS_WX3,wx_line,p_station);
+ decoded=1;
+ }
+ else if (((wx_line[0]=='#') || (wx_line[0]=='*'))
+ && is_xnum_or_dash((char *)(wx_line+1),13)
+ && port_data[port].data_type==0) {
+
+ /* Found Peet Bros raw U2 data */
+ xastir_snprintf(wx_station_type,
+ sizeof(wx_station_type),
+ "%s",
+ langcode("WXPUPSI012"));
+
+ if (debug_level & 1)
+ fprintf(stderr,"Found Peet Bros raw U2 data WX#:%s\n",wx_line+1);
+
+ xastir_snprintf(raw_wx_string,
+ sizeof(raw_wx_string),
+ "%s",
+ wx_line);
+
+ raw_wx_string[MAX_RAW_WX_STRING] = '\0'; // Terminate it
+
+ xastir_snprintf(weather->wx_time,
+ sizeof(weather->wx_time),
+ "%s",
+ get_time(time_data));
+ weather->wx_sec_time=sec_now();
+ //weather->wx_data=1;
+
+ if (wx_line[0]=='#') // Wind speed in km/h
+ wx_fill_data(0,APRS_WX4,wx_line,p_station);
+ else // '*', Wind speed in mph
+ wx_fill_data(0,APRS_WX6,wx_line,p_station);
+
+ decoded=1;
+ }
+ else if (strncmp("$ULTW",(char *)wx_line,5)==0
+ && is_xnum_or_dash((char *)(wx_line+5),44)
+ && port_data[port].data_type==0) {
+
+ /* Found Peet Bros raw U2 data */
+
+ xastir_snprintf(wx_station_type,
+ sizeof(wx_station_type),
+ "%s",
+ langcode("WXPUPSI013"));
+
+ if (debug_level & 1)
+ fprintf(stderr,"Found Peet Bros Ultimeter Packet data WX#:%s\n",wx_line+5);
+
+ xastir_snprintf(raw_wx_string,
+ sizeof(raw_wx_string),
+ "%s",
+ wx_line);
+ raw_wx_string[MAX_RAW_WX_STRING] = '\0'; // Terminate it
+
+ weather->wx_sec_time=sec_now();
+ //weather->wx_data=1;
+ wx_fill_data(0,APRS_WX5,wx_line,p_station);
+ decoded=1;
+ }
+ else if (wx_line[2]==' ' && wx_line[5]==' ' && wx_line[8]=='/' && wx_line[11]=='/'
+ && wx_line[14]==' ' && wx_line[17]==':' && wx_line[20]==':'
+ && strncmp(" #0:",(char *)wx_line+23,4)==0 && port_data[port].data_type==0) {
+ find=0;
+ for (i=len;i>23 && !find;i--) {
+ if ((int)wx_line[i]==0x03) {
+ find=1;
+ wx_line[i] = 0;
+ }
+ }
+ if (find) {
+
+ /* found Qualimetrics Q-Net station */
+
+ xastir_snprintf(wx_station_type,
+ sizeof(wx_station_type),
+ "%s",
+ langcode("WXPUPSI016"));
+
+ if (debug_level & 1)
+ fprintf(stderr,"Found Qualimetrics Q-Net station data WX#:%s\n",wx_line+23);
+
+ xastir_snprintf(weather->wx_time,
+ sizeof(weather->wx_time),
+ "%s",
+ get_time(time_data));
+ weather->wx_sec_time=sec_now();
+ //weather->wx_data=1;
+ wx_fill_data(0,QM_WX,wx_line+24,p_station);
+ decoded=1;
+ }
+ }
+
+//WE7U
+ // else look for ten ASCII decimal point chars in the input, or do an
+ // sscanf looking for the correct number and types of fields for the
+ // OWW server in ARNE mode. 6 %f's, 2 %d's, 11 %f's.
+ else if (sscanf((const char *)wx_line,"%f %f %f %f %f %f %d %d %f %f %f %f %f %f %f %f %f %f %f", &t1,&t2,&t3,&t4,&t5,&t6,&t7,&t8,&t9,&t10,&t11,&t12,&t13,&t14,&t15,&t16,&t17,&t18,&t19) == 19) {
+
+ // Found Dallas One-Wire Weather Station
+ if (debug_level & 1)
+ fprintf(stderr,"Found OWW ARNE-mode(19) one-wire weather station data\n");
+
+ weather->wx_sec_time=sec_now();
+ wx_fill_data(0,DALLAS_ONE_WIRE,wx_line,p_station);
+ decoded=1;
+ }
+
+ else if (sscanf((const char *)wx_line,"%f %f %f %f %f %f %d %d %f %f %f %f", &t1,&t2,&t3,&t4,&t5,&t6,&t7,&t8,&t9,&t10,&t11,&t12) == 12) {
+
+ // Found Dallas One-Wire Weather Station
+ if (debug_level & 1)
+ fprintf(stderr,"Found OWW ARNE-mode(12) one-wire weather station data\n");
+
+ weather->wx_sec_time=sec_now();
+ wx_fill_data(0,DALLAS_ONE_WIRE,wx_line,p_station);
+ decoded=1;
+ }
+
+ else if (strncmp("&CR&",(char *)wx_line,4)==0
+ && is_xnum_or_dash((char *)(wx_line+5),44)
+ && port_data[port].data_type==0) {
+
+ if (debug_level & 1)
+ fprintf(stderr,"Found Peet Complete station data\n");
+
+ xastir_snprintf(wx_station_type,
+ sizeof(wx_station_type),
+ "%s",
+ langcode("WXPUPSI017"));
+
+ xastir_snprintf(raw_wx_string,
+ sizeof(raw_wx_string),
+ "%s",
+ wx_line);
+
+ raw_wx_string[MAX_RAW_WX_STRING] = '\0'; // Terminate it
+
+ weather->wx_sec_time=sec_now();
+ //weather->wx_data=1;
+ wx_fill_data(0,PEET_COMPLETE,wx_line,p_station);
+ decoded=1;
+ }
+
+ else if (port_data[port].data_type==1) {
+// int jj;
+
+ /* binary data type */
+ if (debug_level & 1)
+ fprintf(stderr,"Found binary data: %d bytes\n", len);
+
+ /* clear raw string */
+ memset(raw_wx_string,0,sizeof(raw_wx_string));
+ max=0;
+ switch (wx_line[0]) {
+ case 0x8f:
+ max=34;
+ break;
+
+ case 0x9f:
+ max=33;
+ break;
+
+ case 0xaf:
+ max=30;
+ break;
+
+ case 0xbf:
+ max=13;
+ break;
+
+ case 0xcf:
+ max=26;
+ break;
+
+ default:
+ break;
+ }
+
+// fprintf(stderr, "wx_decode binary: ");
+// for (jj = 0; jj < len+1; jj++) {
+// fprintf(stderr, "%02x ", wx_line[jj]);
+// }
+// fprintf(stderr, "\n");
+// fprintf(stderr, "Integers: ");
+// for (jj = 0; jj < max+1; jj++) {
+// fprintf(stderr, "%0d ", wx_line[jj]);
+// }
+// fprintf(stderr, "\n");
+
+
+ if (len < (max+1)) {
+ fprintf(stderr, " Short NET_WX packet, %d bytes\n", len);
+ }
+
+ if (max > 0 && len >= (max+1) ) {
+
+ // Compute the checksum from the data
+ check_sum = 0;
+
+ for (i = 0; i < max; i++) {
+ check_sum += wx_line[i];
+ }
+// fprintf(stderr," Checksum: 0x%02x ", 0x0ff & check_sum);
+
+ if ( wx_line[max] == (0xff & check_sum) ) {
+
+ /* good RS WX-200 data */
+ //fprintf(stderr,"GOOD RS WX-200 %0X data\n",wx_line[0]);
+ /* found RS WX-200 */
+ xastir_snprintf(wx_station_type,
+ sizeof(wx_station_type),
+ "%s",
+ langcode("WXPUPSI025"));
+ xastir_snprintf(weather->wx_time,
+ sizeof(weather->wx_time),
+ "%s",
+ get_time(time_data));
+ weather->wx_sec_time=sec_now();
+ //weather->wx_data=1;
+ wx_fill_data(0,RSWX200,wx_line,p_station);
+ decoded=1;
+ }
+ else {
+// fprintf(stderr, "bad");
+ }
+ }
+ }
+ else if (wx_line[0]=='@' && strncmp((char *)&(wx_line[63]),".DsVP",5)==0) {
+ // this is a Davis Vantage Pro with APRS Data Logger
+ if (debug_level & 1)
+ fprintf(stdout,"Davis VP APRS Data Logger data found ... %s\n", wx_line);
+ xastir_snprintf(wx_station_type,
+ sizeof(wx_station_type),
+ "%s",
+ langcode("WXPUPSI028"));
+
+ xastir_snprintf(weather->wx_time,
+ sizeof(weather->wx_time),
+ "%s",
+ get_time(time_data));
+ weather->wx_sec_time=sec_now();
+ wx_fill_data(0,DAVISAPRSDL,wx_line,p_station);
+ decoded=1;
+ }
+ else { // ASCII data of undetermined type
+
+ // Davis Weather via meteo -> db2APRS -> TCP port
+
+ if (strstr((const char *)wx_line, "xDvs")) { // APRS 'postionless' WX data w/ Davis & X tag
+
+ if (debug_level & 1)
+ fprintf(stdout,"Davis Data found... %s\n",wx_line);
+
+ xastir_snprintf(wx_station_type,
+ sizeof(wx_station_type),
+ "%s",
+ langcode("WXPUPSI026"));
+ xastir_snprintf(weather->wx_time,
+ sizeof(weather->wx_time),
+ "%s",
+ get_time(time_data));
+ weather->wx_sec_time=sec_now();
+ wx_fill_data(0,DAVISMETEO,wx_line,p_station);
+ decoded=1;
+ }
+
+ else if (debug_level & 1) {
+ fprintf(stderr,"Unknown WX DATA:%s\n",wx_line);
+ }
+ }
+
+ if (decoded) {
+ /* save data back */
+
+if (begin_critical_section(&port_data_lock, "wx.c:wx_decode(1)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ port_data[port].decode_errors=0;
+
+if (end_critical_section(&port_data_lock, "wx.c:wx_decode(2)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ statusline(langcode("BBARSTA032"),1); // Decoded WX Data
+ /* redraw now */
+ //redraw_on_new_data=2;
+ redraw_on_new_data=1;
+ fill_wx_data();
+ }
+ else {
+ /* Undecoded packet */
+ memset(raw_wx_string,0,sizeof(raw_wx_string));
+
+if (begin_critical_section(&port_data_lock, "wx.c:wx_decode(3)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ port_data[port].decode_errors++; // We have errors in decoding
+ if (port_data[port].decode_errors>10) {
+ /* wrong data type? */
+ port_data[port].data_type++; // Try another data type. 0=ascii, 1=wx binary
+ port_data[port].data_type&=0x01;
+ /*if (debug_level & 1)*/
+ fprintf(stderr,"Data type %d\n",port_data[port].data_type);
+ port_data[port].decode_errors=0;
+ }
+
+if (end_critical_section(&port_data_lock, "wx.c:wx_decode(4)" ) > 0)
+ fprintf(stderr,"port_data_lock, Port = %d\n", port);
+
+ }
+ }
+ }
+ }
+}
+
+
+
+
+
+/***********************************************************/
+/* fill string with WX data for transmit */
+/* */
+/***********************************************************/
+
+time_t wx_tx_data1(char *st, int st_size) {
+ DataRow *p_station;
+ time_t wx_time;
+ char temp[100];
+ WeatherRow *weather;
+
+ st[0] = '\0';
+ wx_time = 0;
+ if (search_station_name(&p_station,my_callsign,1)) {
+ if (get_weather_record(p_station)) { // station has wx data
+ weather = p_station->weather_data;
+
+
+//WE7U: For debugging purposes only
+//weather->wx_sec_time=sec_now();
+//sprintf(weather->wx_course,"359"); // degrees
+//sprintf(weather->wx_speed,"001"); // mph
+//sprintf(weather->wx_gust,"010"); // mph
+//sprintf(weather->wx_temp,"069"); // Farenheit
+
+//if ( strlen(weather->wx_rain_total) == 0)
+// sprintf(weather->wx_rain_total,"1900.40");
+
+//sprintf(weather->wx_rain_total,"1987.6"); // hundredths of an inch
+//compute_rain(atof(weather->wx_rain_total));
+//sprintf(weather->wx_rain_total,"1988.6");
+//compute_rain(atof(weather->wx_rain_total));
+//sprintf(weather->wx_rain_total,"1990.6");
+
+//compute_rain(atof(weather->wx_rain_total));
+//sprintf(weather->wx_rain,"%0.2f",rain_minute_total);
+//sprintf(weather->wx_prec_24,"%0.2f",rain_24);
+//sprintf(weather->wx_prec_00,"%0.2f",rain_00);
+
+//sprintf(weather->wx_rain,"0"); // hundredths of an inch
+//sprintf(weather->wx_prec_00,"0"); // hundredths of an inch
+//sprintf(weather->wx_prec_24,"0"); // hundredths of an inch
+
+//sprintf(weather->wx_hum,"92"); // %
+//sprintf(weather->wx_baro,"1013.0"); // hPa
+//weather->wx_type = WX_TYPE;
+//xastir_snprintf(weather->wx_station,sizeof(weather->wx_station),"RSW");
+// 359/000g000t065r010P020p030h92b01000
+
+
+ if (strlen(weather->wx_course) > 0 && strlen(weather->wx_speed) > 0) {
+ // We have enough wx_data
+ wx_time=weather->wx_sec_time;
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ weather->wx_course);
+ if (strlen(temp) > 3) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_course too long: %s\n", temp);
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "...");
+ }
+ if ( (atoi(weather->wx_course) > 360) || (atoi(weather->wx_course) < 0) ) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_course out-of-range: %s\n", weather->wx_course);
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "...");
+ }
+ //sprintf(st,"%s/%s",weather->wx_course,weather->wx_speed);
+ strncat(st, temp, st_size - 1 - strlen(st));
+ strncat(st, "/", st_size - 1 - strlen(st));
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s",
+ weather->wx_speed);
+ if (strlen(temp) > 3) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_speed too long: %s\n", temp);
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "...");
+ }
+ if ( (atoi(weather->wx_speed) < 0) || (atoi(weather->wx_speed) > 999) ) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_speed out-of-range: %s\n", weather->wx_speed);
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "...");
+ }
+ strncat(st, temp, st_size - 1 - strlen(st));
+ } else {
+ // We don't have enough wx_data, may be from a Qualimetrics Q-Net?
+ wx_time=weather->wx_sec_time;
+ xastir_snprintf(st,
+ st_size,
+ ".../...");
+
+
+ if (debug_level & 1) {
+ fprintf(stderr,"\n\nAt least one field was empty: Course: %s\tSpeed: %s\n", weather->wx_course, weather->wx_speed);
+ fprintf(stderr,"Will be sending '.../...' instead of real values.\n\n\n");
+ }
+
+
+ }
+ if (strlen(weather->wx_gust) > 0) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "g%s",
+ weather->wx_gust);
+ if (strlen(temp) > 4) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_gust too long: %s\n", temp);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "g...");
+ }
+ if (atoi(weather->wx_gust) < 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_gust out-of-range: %s\n", weather->wx_gust);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "g...");
+ }
+ strncat(st, temp, st_size - 1 - strlen(st));
+ } else
+ strncat(st, "g...", st_size - 1 - strlen(st));
+
+ if (strlen(weather->wx_temp) > 0) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "t%s",
+ weather->wx_temp);
+ if (strlen(temp) > 4) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_temp too long: %s\n", temp);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "t...");
+ }
+ if ( (atoi(weather->wx_temp) > 999) || (atoi(weather->wx_temp) < -99) ) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_temp out-of-bounds: %s\n", weather->wx_temp);
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "t...");
+ }
+ strncat(st, temp, st_size - 1 - strlen(st));
+ } else
+ strncat(st, "t...", st_size - 1 - strlen(st));
+
+ if (strlen(weather->wx_rain) > 0) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "r%03d",
+ (int)(atof(weather->wx_rain) + 0.5) ); // Cheater's way of rounding
+ if (strlen(temp)>4) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_rain too long: %s\n", temp);
+
+ // Don't transmit this field if it's not valid
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "r ");
+ }
+ if ((int)(atof(weather->wx_rain)) < 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_rain out-of-bounds: %s\n", weather->wx_rain);
+
+ // Don't transmit this field if it's not valid
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "r...");
+ }
+ strncat(st, temp, st_size - 1 - strlen(st));
+ } else {
+ // Don't transmit this field if it's not valid
+ //strncat(st, "r...", st_size - 1 - strlen(st));
+ }
+
+ if (strlen(weather->wx_prec_00) > 0) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "P%03d",
+ (int)(atof(weather->wx_prec_00) + 0.5) ); // Cheater's way of rounding
+ if (strlen(temp)>4) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_prec_00 too long: %s\n", temp);
+
+ // Don't transmit this field if it's not valid
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "P ");
+ }
+ if ((int)(atof(weather->wx_prec_00)) < 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_prec_00 out-of-bounds: %s\n", weather->wx_prec_00);
+
+ // Don't transmit this field if it's not valid
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "P...");
+ }
+ strncat(st, temp, st_size - 1 - strlen(st));
+ } else {
+ // Don't transmit this field if it's not valid
+ //strncat(st, "P...", st_size - 1 - strlen(st));
+ }
+
+ if (strlen(weather->wx_prec_24) > 0) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "p%03d",
+ (int)(atof(weather->wx_prec_24) + 0.5) ); // Cheater's way of rounding
+ if (strlen(temp)>4) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_prec_24 too long: %s\n", temp);
+
+ // Don't transmit this field if it's not valid
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "p ");
+ }
+ if ((int)(atof(weather->wx_prec_24)) < 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_prec_24 out-of-bounds: %s\n", weather->wx_prec_24);
+
+ // Don't transmit this field if it's not valid
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "p...");
+ }
+ strncat(st, temp, st_size - 1 - strlen(st));
+ } else {
+ // Don't transmit this field if it's not valid
+ //strncat(st, "p...", st_size - 1 - strlen(st));
+ }
+
+ if (strlen(weather->wx_hum) > 0) {
+ if (atoi(weather->wx_hum)>99) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "h00");
+ } else
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "h%02d",
+ atoi(weather->wx_hum));
+
+ if (strlen(temp) > 4) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_hum too long: %s\n", temp);
+
+ // Don't transmit this field if it's not valid
+ //xastir_snprintf(temp,sizeof(temp),"h..");
+ }
+ if (atoi(weather->wx_hum) < 0) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_hum out-of-bounds: %s\n", weather->wx_hum);
+ // Don't transmit this field if it's not valid
+ //xastir_snprintf(temp,sizeof(temp),"h..");
+ }
+ strncat(st, temp, st_size - 1 - strlen(st));
+ } else {
+ // Don't transmit this field if it's not valid
+ //strncat(st, "h..", st_size - 1 - strlen(st));
+ }
+
+ if (strlen(weather->wx_baro) > 0) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "b%05d",
+ (int)((atof(weather->wx_baro) * 10.0)) );
+ if (strlen(temp)>6) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_baro too long: %s\n", temp);
+ // Don't transmit this field if it's not valid
+ //xastir_snprintf(temp,sizeof(temp),"b.....");
+ }
+ if ((int)((atof(weather->wx_baro) * 10.0) < 0)) {
+ if (debug_level & 1)
+ fprintf(stderr,"wx_baro out-of-bounds: %s\n", weather->wx_baro);
+ // Don't transmit this field if it's not valid
+ //xastir_snprintf(temp,sizeof(temp),"b.....");
+ }
+ strncat(st, temp, st_size - 1 - strlen(st));
+ } else {
+ // Don't transmit this field if it's not valid
+ //strncat(st, "b.....", st_size - 1 - strlen(st));
+ }
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%c%s",
+ weather->wx_type,
+ weather->wx_station);
+ strncat(st, temp, st_size - 1 - strlen(st));
+ }
+ }
+
+
+ if (debug_level & 1)
+ fprintf(stderr,"Weather String: %s\n", st);
+
+
+ return(wx_time);
+}
+
+
+
+
+
+/***********************************************************/
+/* transmit raw wx data */
+/* */
+/***********************************************************/
+void tx_raw_wx_data(void) {
+
+ if (strlen(raw_wx_string)>10) {
+ output_my_data(raw_wx_string,-1,0,0,0,NULL);
+ if (debug_level & 1)
+ fprintf(stderr,"Sending Raw WX data <%s>\n",raw_wx_string);
+ }
+}
+
+
diff --git a/src/wx.h b/src/wx.h
new file mode 100644
index 0000000..0123783
--- /dev/null
+++ b/src/wx.h
@@ -0,0 +1,79 @@
+/*
+ * $Id: wx.h,v 1.16 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#ifndef __XASTIR_WX_H
+#define __XASTIR_WX_H
+
+#include "database.h"
+
+extern void fill_wx_data(void);
+
+extern Widget GetTopShell(Widget w);
+extern void pos_dialog(Widget w);
+extern char wx_station_type[];
+
+/* from wx.c */
+extern char wx_dew_point[10];
+extern char wx_dew_point_on;
+extern char wx_high_wind[10];
+extern char wx_high_wind_on;
+extern char wx_wind_chill[10];
+extern char wx_wind_chill_on;
+extern char wx_three_hour_baro[10]; // hPa
+extern char wx_three_hour_baro_on; // hPa
+extern char wx_hi_temp[10];
+extern char wx_hi_temp_on;
+extern char wx_low_temp[10];
+extern char wx_low_temp_on;
+extern char wx_heat_index[10];
+extern char wx_heat_index_on;
+extern char wx_station_type[];
+
+
+/* from wx.c */
+extern time_t wx_tx_data1(char *st, int st_size);
+extern void wx_decode(unsigned char *wx_line, int data_length, int port);
+extern void fill_wx_data(void);
+extern void clear_rain_data(void);
+extern void tx_raw_wx_data(void);
+extern void clear_local_wx_data(void);
+extern void wx_last_data_check(void);
+extern void wx_fill_data(int from, int type, unsigned char *data, DataRow *fill);
+extern void decode_U2000_L(int from, unsigned char *data, WeatherRow *weather);
+extern void decode_U2000_P(int from, unsigned char *data, WeatherRow *weather);
+extern void decode_Peet_Bros(int from, unsigned char *data, WeatherRow *weather, int type);
+extern void cycle_weather(void);
+
+
+/* wx_gui.c */
+extern void wx_alert_update_list(void);
+
+extern void WX_station(Widget w, XtPointer clientData, XtPointer callData);
+
+extern void wx_alert_finger_output( Widget widget, char *handle);
+
+#endif // __XASTIR_WX_H
+
+
diff --git a/src/wx_gui.c b/src/wx_gui.c
new file mode 100644
index 0000000..fc79441
--- /dev/null
+++ b/src/wx_gui.c
@@ -0,0 +1,2116 @@
+/*
+ * $Id: wx_gui.c,v 1.60 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "snprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif // HAVE_LOCALE_H
+
+#ifdef HAVE_LIBINTL_H
+#include <libintl.h>
+#define _(x) gettext(x)
+#else // HAVE_LIBINTL_H
+#define _(x) (x)
+#endif // HAVE_LIBINTL_H
+
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif // HAVE_MATH_H
+
+#include "xastir.h"
+#include "wx.h"
+#include "main.h"
+#include "alert.h"
+#include "lang.h"
+
+#include <Xm/XmAll.h>
+#ifdef HAVE_XBAE_MATRIX_H
+#include <Xbae/Matrix.h>
+#endif // HAVE_XBAE_MATRIX_H
+#include <X11/cursorfont.h>
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+extern XmFontList fontlist1; // Menu/System fontlist
+
+/************ Weather Alerts ****************/
+Widget wx_alert_shell = (Widget)NULL;
+Widget wx_detailed_alert_shell = (Widget)NULL;
+static Widget wx_alert_list;
+
+static xastir_mutex wx_alert_shell_lock;
+static xastir_mutex wx_detailed_alert_shell_lock;
+static xastir_mutex wx_station_dialog_lock;
+
+
+
+
+
+void wx_gui_init(void)
+{
+ init_critical_section( &wx_alert_shell_lock );
+ init_critical_section( &wx_detailed_alert_shell_lock );
+ init_critical_section( &wx_station_dialog_lock );
+}
+
+
+
+
+
+void wx_detailed_alert_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+
+begin_critical_section(&wx_detailed_alert_shell_lock, "wx_gui.c:wx_detailed_alert_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ wx_detailed_alert_shell = (Widget)NULL;
+
+end_critical_section(&wx_detailed_alert_shell_lock, "wx_gui.c:wx_detailed_alert_destroy_shell" );
+
+}
+
+
+
+
+
+// This gets/displays the "finger" output from the WXSVR. Called
+// from both the Station Info "NWS" button and by double-clicking on
+// the view weather alerts window.
+//
+void wx_alert_finger_output( Widget widget, char *handle) {
+ static Widget pane, my_form, mess, button_cancel,wx_detailed_alert_list;
+ Atom delw;
+ Arg al[50]; // Arg List
+ register unsigned int ac = 0; // Arg Count
+ char temp[1024];
+ XmString item;
+ FILE *fd;
+ int ret;
+ int server_fd;
+ struct sockaddr_in serv_addr;
+ struct hostent *serverhost;
+
+
+ if (debug_level & 1)
+ fprintf(stderr,"Handle: %s\n",handle);
+
+ if(!wx_detailed_alert_shell) {
+
+begin_critical_section(&wx_detailed_alert_shell_lock, "wx_gui.c:wx_alert_double_click_action" );
+
+ wx_detailed_alert_shell = XtVaCreatePopupShell(langcode("WPUPWXA001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNminWidth, 600,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("wx_alert_double_click_action pane",xmPanedWindowWidgetClass, wx_detailed_alert_shell,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ my_form = XtVaCreateWidget("wx_alert_double_click_action my_form", xmFormWidgetClass, pane,
+ XmNtraversalOn, TRUE,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNwidth, 600,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ mess = XtVaCreateManagedWidget(langcode("WPUPWXA002"), xmLabelWidgetClass, my_form,
+ XmNtraversalOn, FALSE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ /* set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNbackground, colors[0xff]); ac++;
+ XtSetArg(al[ac], XmNvisibleItemCount, 13); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNshadowThickness, 3); ac++;
+ XtSetArg(al[ac], XmNselectionPolicy, XmSINGLE_SELECT); ac++;
+
+ XtSetArg(al[ac], XmNvisualPolicy, XmCONSTANT); ac++;
+ XtSetArg(al[ac], XmNscrollingPolicy,XmAUTOMATIC); ac++;
+ XtSetArg(al[ac], XmNscrollBarPlacement, XmBOTTOM_RIGHT); ac++;
+ XtSetArg(al[ac], XmNscrollBarDisplayPolicy,XmAS_NEEDED); ac++;
+ XtSetArg(al[ac], XmNlistSizePolicy, XmCONSTANT); ac++;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopWidget, mess); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 5); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 45); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 5); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 5); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ wx_detailed_alert_list = XmCreateScrolledList(my_form, "wx_alert_double_click_action wx_detailed_alert_list", al, ac);
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),xmPushButtonGadgetClass, my_form,
+ XmNtopAttachment, XmATTACH_NONE,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,10,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_cancel, XmNactivateCallback, wx_detailed_alert_destroy_shell, wx_detailed_alert_shell);
+
+end_critical_section(&wx_detailed_alert_shell_lock, "wx_gui.c:wx_alert_double_click_action" );
+
+ pos_dialog(wx_detailed_alert_shell);
+
+ delw = XmInternAtom(XtDisplay(wx_detailed_alert_shell), "WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(wx_detailed_alert_shell, delw, wx_detailed_alert_destroy_shell, (XtPointer)wx_detailed_alert_shell);
+
+ XtManageChild(my_form);
+ XtManageChild(wx_detailed_alert_list);
+ XtVaSetValues(wx_detailed_alert_list, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(pane);
+
+ XtPopup(wx_detailed_alert_shell, XtGrabNone);
+// fix_dialog_vsize(wx_detailed_alert_shell);
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(wx_detailed_alert_shell);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+ } else {
+ (void)XRaiseWindow(XtDisplay(wx_detailed_alert_shell), XtWindow(wx_detailed_alert_shell));
+ }
+
+ // Erase the entire list before we start writing to it in
+ // case it was left up from a previous query.
+ XmListDeleteAllItems(wx_detailed_alert_list);
+
+ // Perform a "finger" command, which is really just a telnet
+ // with a single line command sent to the remote host, then a
+ // bunch of text sent back. We implement it here via our own
+ // TCP code, as it's really very simple.
+
+ // Allocate a socket for our use
+ if ((server_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+// fprintf(stderr,"wx_alert_finger_output: can't get socket\n");
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "wx_alert_finger_output: can't get socket");
+ item = XmStringGenerate(temp, XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, NULL);
+ XmListAddItemUnselected(wx_detailed_alert_list, item, 0);
+ XmStringFree(item);
+ return;
+ }
+
+ memset(&serv_addr, 0, sizeof(serv_addr));
+
+
+ // Changing Finger host because WXSVR.net has been down for a
+ // month or more and Pete, AE5PL, has a replacement online that
+ // performs this function.
+ //serverhost = gethostbyname("wxsvr.net");
+ serverhost = gethostbyname("wx.aprs-is.net");
+
+
+ if (serverhost == (struct hostent *)0) {
+// fprintf(stderr,"wx_alert_finger_output: gethostbyname failed\n");
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "wx_alert_finger_output: gethostbyname failed");
+ item = XmStringGenerate(temp, XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, NULL);
+ XmListAddItemUnselected(wx_detailed_alert_list, item, 0);
+ XmStringFree(item);
+ (void)close(server_fd); // Close the socket
+ return;
+ }
+ memmove(&serv_addr.sin_addr,serverhost->h_addr, (size_t)serverhost->h_length);
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_port = htons(79); // Finger protocol uses port 79
+
+ if (connect(server_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
+// fprintf(stderr,"wx_alert_finger_output: connect to server failed\n");
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "wx_alert_finger_output: connect to server failed");
+ item = XmStringGenerate(temp, XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, NULL);
+ XmListAddItemUnselected(wx_detailed_alert_list, item, 0);
+ XmStringFree(item);
+ (void)close(server_fd); // Close the socket
+ return;
+ }
+
+ // Create a file descriptor for the socket
+ fd = fdopen(dup(server_fd),"wb");
+ if (fd == NULL) {
+// fprintf(stderr,"Couldn't create duplicate write socket\n");
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "Couldn't create duplicate write socket");
+ item = XmStringGenerate(temp, XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, NULL);
+ XmListAddItemUnselected(wx_detailed_alert_list, item, 0);
+ XmStringFree(item);
+ (void)close(server_fd); // Close the socket
+ return;
+ }
+
+ // Set up the text we're going to send to the remote finger
+ // server.
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%s\r\n",
+ handle);
+
+ // Send the request text out the socket
+ ret = fprintf(fd, "%s", temp);
+
+ if (ret == 0 || ret == -1) {
+// fprintf(stderr,"Couldn't send finger command to wxsvr\n");
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "Couldn't send finger command to wxsvr");
+ item = XmStringGenerate(temp, XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, NULL);
+ XmListAddItemUnselected(wx_detailed_alert_list, item, 0);
+ XmStringFree(item);
+ (void)fclose(fd);
+ (void)close(server_fd); // Close the socket
+ return;
+ }
+
+ // Close the duplicate port we used for writing
+ (void)fclose(fd);
+
+//
+// Read back the results from the socket
+//
+
+ // Create a file descriptor for the socket
+ fd = fdopen(dup(server_fd),"rb");
+ if (fd == NULL) {
+// fprintf(stderr,"Couldn't create duplicate read socket\n");
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "Couldn't create duplicate read socket");
+ item = XmStringGenerate(temp, XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, NULL);
+ XmListAddItemUnselected(wx_detailed_alert_list, item, 0);
+ XmStringFree(item);
+ (void)close(server_fd); // Close the socket
+ return;
+ }
+
+ // Process the data we received from the remote finger server
+ //
+ while (fgets (temp, sizeof (temp), fd)) { // While we have data to process
+ char *ptr;
+
+ // Remove any linefeeds or carriage returns from each
+ // string.
+ ptr = temp;
+ while ( (ptr = strpbrk(temp, "\n\r")) )
+ memmove(ptr, ptr+1, strlen(ptr)+1);
+
+ if (debug_level & 1)
+ fprintf(stderr,"%s\n",temp);
+
+ // Create an XmString for each line and add it to the
+ // end of the list.
+ item = XmStringGenerate(temp, XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, NULL);
+ XmListAddItemUnselected(wx_detailed_alert_list, item, 0);
+ XmStringFree(item);
+ }
+
+ // All done!
+ fclose(fd);
+ (void)close(server_fd); // Close the socket
+}
+
+
+
+
+
+void wx_alert_double_click_action( Widget widget, XtPointer clientData, XtPointer callData) {
+ char *choice;
+ XmListCallbackStruct *selection = callData;
+ char handle[14];
+ char *ptr;
+
+
+ XmStringGetLtoR(selection->item, XmFONTLIST_DEFAULT_TAG, &choice);
+ //fprintf(stderr,"Selected item %d (%s)\n", selection->item_position, choice);
+
+ // Grab the first 13 characters. Remove spaces. This is our handle
+ // into the weather server for the full weather alert text.
+
+ xastir_snprintf(handle,
+ sizeof(handle),
+ "%s",
+ choice);
+
+ XtFree(choice); // Release as soon as we're done!
+
+ handle[13] = '\0'; // Terminate the string
+ // Remove spaces
+ ptr = handle;
+ while ( (ptr = strpbrk(handle, " ")) )
+ memmove(ptr, ptr+1, strlen(ptr)+1);
+ handle[9] = '\0'; // Terminate after first 9 chars
+
+ if (debug_level & 1)
+ fprintf(stderr,"Handle: %s\n",handle);
+
+ wx_alert_finger_output( widget, handle);
+}
+
+
+
+
+
+void wx_alert_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+
+begin_critical_section(&wx_alert_shell_lock, "wx_gui.c:wx_alert_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ wx_alert_shell = (Widget)NULL;
+
+end_critical_section(&wx_alert_shell_lock, "wx_gui.c:wx_alert_destroy_shell" );
+
+}
+
+
+static int alert_comp(const void *a, const void *b) {
+ alert_entry *a_entry = *(alert_entry **)a;
+ alert_entry *b_entry = *(alert_entry **)b;
+ int a_active, b_active;
+
+ if (a_entry->title[on_screen] && !b_entry->title[on_screen])
+ return (-1);
+
+ if (!a_entry->title[0] && b_entry->title[0])
+ return (1);
+
+ if (a_entry->flags[on_screen] == 'Y' && b_entry->flags[on_screen] != 'Y')
+ return (-1);
+
+ if (a_entry->flags[on_screen] != 'Y' && b_entry->flags[on_screen] == 'Y')
+ return (1);
+
+ if (a_entry->flags[on_screen] == '?' && b_entry->flags[on_screen] == 'N')
+ return (-1);
+
+ if (a_entry->flags[on_screen] == 'N' && b_entry->flags[on_screen] == '?')
+ return (1);
+
+ a_active = alert_active(a_entry, ALERT_ALL);
+ b_active = alert_active(b_entry, ALERT_ALL);
+ if (a_active && b_active) {
+ if (a_active - b_active) {
+ return (a_active - b_active);
+ }
+ } else if (a_active) {
+ return (-1);
+ }
+ else if (b_active) {
+ return (1);
+ }
+
+ return (strcmp(a_entry->title, b_entry->title));
+}
+
+
+void wx_alert_update_list(void) {
+ int nn; // index into alert table. Starts at 0
+ int ii; // index into dialog lines. Starts at 1
+ int max_item_count; // max dialog lines
+ char temp[600];
+ XmString item;
+ static alert_entry **alert_list;
+ static int alert_list_limit;
+
+ if (wx_alert_shell) {
+ struct hashtable_itr *iterator;
+ alert_entry *alert;
+
+begin_critical_section(&wx_alert_shell_lock, "wx_gui.c:wx_alert_update_list" );
+
+ // Get the previous alert count from the alert list window
+ XtVaGetValues(wx_alert_list, XmNitemCount, &max_item_count, NULL);
+
+ if ((nn = alert_list_count()) > alert_list_limit) {
+ alert_entry **tmp = realloc(alert_list, nn * sizeof(alert_entry *));
+ if (tmp) {
+ alert_list = tmp;
+ alert_list_limit = nn;
+ } else {
+ fprintf(stderr, "wx_gui: Alert list allocation error\n");
+ exit(1);
+ }
+
+ }
+ // Iterate through the alert hash. Create a string for each
+ // non-expired/non-blank entry.
+ iterator = create_wx_alert_iterator();
+ for (nn = 0, alert = get_next_wx_alert(iterator); iterator != NULL && alert; alert = get_next_wx_alert(iterator)) {
+
+ // Check whether alert record is empty/filled. This
+ // code is from the earlier array implementation. If
+ // we're expiring records from our hash properly we
+ // probably don't need this anymore.
+ //
+// if (alert->title[0] == '\0') { // It's empty
+// fprintf(stderr, "wx_gui:alert->title NULL\n");
+// break;
+// }
+ alert_list[nn++] = alert;
+ }
+ qsort(alert_list, nn, sizeof(alert_entry *), alert_comp);
+ for (ii = 0; ii < nn;
+) {
+ alert = alert_list[ii];
+ // AFGNPW NWS-WARN Until: 191500z AK_Z213 WIND P7IAA
+ // TSATOR NWS-ADVIS Until: 190315z OK_C127 TORNDO H2VAA
+ //xastir_snprintf(temp, sizeof(temp), "%-9s %-9s Until: %-7s %-7s %-20s %s",
+
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%-9s %-5s %-9s %c%c @%c%c%c%cz ==> %c%c @%c%c%c%cz %c%c %-7s %s %s%s%s%s",
+ alert->from,
+ alert->seq,
+ alert->to,
+ alert->issue_date_time[0],
+ alert->issue_date_time[1],
+ alert->issue_date_time[2],
+ alert->issue_date_time[3],
+ alert->issue_date_time[4],
+ alert->issue_date_time[5],
+ alert->activity[0],
+ alert->activity[1],
+ alert->activity[2],
+ alert->activity[3],
+ alert->activity[4],
+ alert->activity[5],
+ alert->flags[on_screen],
+ alert->flags[source],
+ alert->title,
+ alert->alert_tag,
+ alert->desc0,
+ alert->desc1,
+ alert->desc2,
+ alert->desc3);
+
+ item = XmStringGenerate(temp, XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, NULL);
+
+ ii++;
+
+ // It looks like if we are higher than 'max_item_count',
+ // it must be a new entry that we haven't written to the
+ // window yet. Add it.
+ if (max_item_count < ii) {
+ XmListAddItemUnselected(wx_alert_list, item, 0);
+ } else {
+ // Replace it in the window. Note: This might re-order the list each time.
+ XmListReplaceItemsPos(wx_alert_list, &item, 1, ii);
+ }
+
+ XmStringFree(item);
+
+ } // End of for loop
+#ifndef USING_LIBGC
+//fprintf(stderr,"free iterator 9\n");
+ if (iterator) free(iterator);
+#endif // USING_LIBGC
+
+ // If we have fewer alerts now, delete the extras from the window
+ if (ii < max_item_count) {
+ XmListDeleteItemsPos(wx_alert_list, max_item_count - ii, ii+1);
+ }
+
+end_critical_section(&wx_alert_shell_lock, "wx_gui.c:wx_alert_update_list" );
+
+ }
+}
+
+
+
+
+
+void Display_Wx_Alert( /*@unused@*/ Widget wdgt, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, my_form, mess, button_cancel;
+ Atom delw;
+ Arg al[50]; /* Arg List */
+ register unsigned int ac = 0; /* Arg Count */
+
+ if(!wx_alert_shell) {
+
+begin_critical_section(&wx_alert_shell_lock, "wx_gui.c:Display_Wx_Alert" );
+
+ wx_alert_shell = XtVaCreatePopupShell(langcode("WPUPWXA001"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNminWidth, 600,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("Display_Wx_Alert pane",xmPanedWindowWidgetClass, wx_alert_shell,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ my_form = XtVaCreateWidget("Display_Wx_Alert my_form", xmFormWidgetClass, pane,
+ XmNtraversalOn, TRUE,
+ XmNfractionBase, 5,
+ XmNbackground, colors[0xff],
+ XmNwidth, 600,
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ mess = XtVaCreateManagedWidget(langcode("WPUPWXA002"), xmLabelWidgetClass, my_form,
+ XmNtraversalOn, FALSE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 5,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 5,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ /* set args for color */
+ ac=0;
+ XtSetArg(al[ac], XmNbackground, colors[0xff]); ac++;
+ XtSetArg(al[ac], XmNvisibleItemCount, 13); ac++;
+ XtSetArg(al[ac], XmNtraversalOn, TRUE); ac++;
+ XtSetArg(al[ac], XmNshadowThickness, 3); ac++;
+// XtSetArg(al[ac], XmNselectionPolicy, XmMULTIPLE_SELECT); ac++;
+ XtSetArg(al[ac], XmNselectionPolicy, XmSINGLE_SELECT); ac++;
+
+ XtSetArg(al[ac], XmNvisualPolicy, XmCONSTANT); ac++;
+ XtSetArg(al[ac], XmNscrollingPolicy,XmAUTOMATIC); ac++;
+ XtSetArg(al[ac], XmNscrollBarPlacement, XmBOTTOM_RIGHT); ac++;
+ XtSetArg(al[ac], XmNscrollBarDisplayPolicy,XmAS_NEEDED); ac++;
+// XtSetArg(al[ac], XmNscrollBarDisplayPolicy, XmSTATIC); ac++;
+ XtSetArg(al[ac], XmNlistSizePolicy, XmCONSTANT); ac++;
+// XtSetArg(al[ac], XmNlistSizePolicy, XmVARIABLE); ac++;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopWidget, mess); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 5); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 45); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 5); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 5); ac++;
+ XtSetArg(al[ac], XmNfontList, fontlist1); ac++;
+
+ wx_alert_list = XmCreateScrolledList(my_form, "Display_Wx_Alert wx_alert_list", al, ac);
+
+end_critical_section(&wx_alert_shell_lock, "wx_gui.c:Display_Wx_Alert" );
+
+ wx_alert_update_list();
+
+ button_cancel = XtVaCreateManagedWidget(langcode("UNIOP00003"),xmPushButtonGadgetClass, my_form,
+ XmNtopAttachment, XmATTACH_NONE,
+// XmNtopOffset, 265,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,10,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 3,
+ XmNbackground, colors[0xff],
+ XmNnavigationType, XmTAB_GROUP,
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_cancel, XmNactivateCallback, wx_alert_destroy_shell, wx_alert_shell);
+ XtAddCallback(wx_alert_list, XmNdefaultActionCallback, wx_alert_double_click_action, NULL);
+
+ pos_dialog(wx_alert_shell);
+
+ delw = XmInternAtom(XtDisplay(wx_alert_shell), "WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(wx_alert_shell, delw, wx_alert_destroy_shell, (XtPointer)wx_alert_shell);
+
+ XtManageChild(my_form);
+ XtManageChild(wx_alert_list);
+ XtVaSetValues(wx_alert_list, XmNbackground, colors[0x0f], NULL);
+ XtManageChild(pane);
+
+ XtPopup(wx_alert_shell, XtGrabNone);
+// fix_dialog_vsize(wx_alert_shell);
+
+ // Move focus to the Cancel button. This appears to highlight the
+ // button fine, but we're not able to hit the <Enter> key to
+ // have that default function happen. Note: We _can_ hit the
+ // <SPACE> key, and that activates the option.
+// XmUpdateDisplay(wx_alert_shell);
+ XmProcessTraversal(button_cancel, XmTRAVERSE_CURRENT);
+ } else {
+ (void)XRaiseWindow(XtDisplay(wx_alert_shell), XtWindow(wx_alert_shell));
+ }
+} /* Display_Wx_Alert */
+
+
+
+
+
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+
+
+
+
+
+/**** WX Station *******/
+Widget wx_station_dialog=(Widget)NULL;
+Widget WX_type_data;
+Widget WX_temp_data;
+Widget WX_wind_cse_data;
+Widget WX_wind_spd_data;
+Widget WX_wind_gst_data;
+Widget WX_rain_data;
+Widget WX_to_rain_data;
+Widget WX_rain_h_data;
+Widget WX_rain_24_data;
+Widget WX_humidity_data;
+Widget WX_speed_label;
+Widget WX_gust_label;
+Widget WX_temp_label;
+Widget WX_rain_label;
+Widget WX_to_rain_label;
+Widget WX_rain_h_label;
+Widget WX_rain_24_label;
+Widget WX_dew_point_data;
+Widget WX_high_wind_data;
+Widget WX_wind_chill_data;
+Widget WX_heat_index_data;
+Widget WX_baro_data;
+Widget WX_baro_label;
+Widget WX_three_hour_baro_data;
+Widget WX_three_hour_baro_label;
+Widget WX_hi_temp_data;
+Widget WX_low_temp_data;
+Widget WX_dew_point_label;
+Widget WX_wind_chill_label;
+Widget WX_heat_index_label;
+Widget WX_hi_temp_label;
+Widget WX_low_temp_label;
+Widget WX_high_wind_label;
+
+
+
+
+
+void WX_station_destroy_shell( /*@unused@*/ Widget widget, XtPointer clientData, /*@unused@*/ XtPointer callData) {
+
+ Widget shell = (Widget) clientData;
+ XtPopdown(shell);
+
+begin_critical_section(&wx_station_dialog_lock, "wx_gui.c:WX_station_destroy_shell" );
+
+ XtDestroyWidget(shell);
+ wx_station_dialog = (Widget)NULL;
+
+end_critical_section(&wx_station_dialog_lock, "wx_gui.c:WX_station_destroy_shell" );
+
+}
+
+
+
+
+
+void WX_station_change_data(Widget widget, XtPointer clientData, XtPointer callData) {
+
+ WX_station_destroy_shell(widget,clientData,callData);
+}
+
+
+
+
+
+// This is the "Own Weather Station" Dialog
+//
+void WX_station( /*@unused@*/ Widget w, /*@unused@*/ XtPointer clientData, /*@unused@*/ XtPointer callData) {
+ static Widget pane, my_form, form1, button_close, frame,
+ WX_type, temp, wind_cse, wind_deg, wind_spd, wind_gst,
+ my_rain, to_rain, rain_h, my_rain_24, baro,
+ humidity, humidity_n,
+ dew_point,
+ high_wind, wind_chill,
+ heat_index, three_hour_baro,
+ hi_temp, low_temp,
+ sts;
+
+ Atom delw;
+
+ if(!wx_station_dialog) {
+
+begin_critical_section(&wx_station_dialog_lock, "wx_gui.c:WX_station" );
+
+ wx_station_dialog = XtVaCreatePopupShell(langcode("WXPUPSI000"),
+ xmDialogShellWidgetClass, appshell,
+ XmNdeleteResponse, XmDESTROY,
+ XmNdefaultPosition, FALSE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ pane = XtVaCreateWidget("WX_station pane",xmPanedWindowWidgetClass, wx_station_dialog,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ my_form = XtVaCreateWidget("WX_station my_form",xmFormWidgetClass, pane,
+ XmNfractionBase,7,
+ XmNbackground, colors[0xff],
+ XmNautoUnmanage, FALSE,
+ XmNshadowThickness, 1,
+ NULL);
+
+ WX_type = XtVaCreateManagedWidget(langcode("WXPUPSI001"),xmLabelWidgetClass, my_form,
+XmNtraversalOn, FALSE,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ WX_type_data = XtVaCreateManagedWidget("WX_station type data", xmTextFieldWidgetClass, my_form,
+XmNtraversalOn, FALSE,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 70,
+ XmNtopOffset, 6,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment,XmATTACH_WIDGET,
+ XmNleftWidget, WX_type,
+ XmNleftOffset, 5,
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 30,
+ XmNfontList, fontlist1,
+ NULL);
+
+ frame = XtVaCreateManagedWidget("WX_station frame", xmFrameWidgetClass, my_form,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, WX_type_data,
+ XmNtopOffset,10,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 10,
+ XmNrightAttachment,XmATTACH_FORM,
+ XmNrightOffset, 10,
+ XmNbackground, colors[0xff],
+ NULL);
+
+ sts = XtVaCreateManagedWidget(langcode("WXPUPSI002"),xmLabelWidgetClass,frame,
+XmNtraversalOn, FALSE,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ form1 = XtVaCreateWidget("WX_station form1",xmFormWidgetClass, frame,
+XmNtraversalOn, FALSE,
+ XmNfractionBase, 7,
+ XmNbackground, colors[0xff],
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ wind_cse = XtVaCreateManagedWidget(langcode("WXPUPSI003"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ WX_wind_cse_data = XtVaCreateManagedWidget("WX_station wc data", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNmaxLength, 3,
+ XmNtopOffset, 6,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_FORM,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ wind_deg = XtVaCreateManagedWidget(langcode("UNIOP00024"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_wind_cse_data,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ wind_spd = XtVaCreateManagedWidget(langcode("WXPUPSI004"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, wind_cse,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ WX_wind_spd_data = XtVaCreateManagedWidget("WX_station ws data", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNmaxLength, 3,
+ XmNtopOffset, 7,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, wind_cse,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_speed_label= XtVaCreateManagedWidget("WX_station speed label",xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns,5,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, wind_cse,
+ XmNtopOffset, 9,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_wind_spd_data,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ wind_gst = XtVaCreateManagedWidget(langcode("WXPUPSI005"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, wind_spd,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ WX_wind_gst_data = XtVaCreateManagedWidget("WX_station wg data", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNmaxLength, 3,
+ XmNtopOffset, 7,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, wind_spd,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_gust_label= XtVaCreateManagedWidget("WX_station gust label",xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns,5,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, wind_spd,
+ XmNtopOffset, 9,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_wind_gst_data,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ temp = XtVaCreateManagedWidget(langcode("WXPUPSI006"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, wind_gst,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ WX_temp_data = XtVaCreateManagedWidget("WX_station temp data", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNmaxLength, 8,
+ XmNtopOffset, 7,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, wind_gst,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_temp_label= XtVaCreateManagedWidget("WX_station temp label",xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns,5,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, wind_gst,
+ XmNtopOffset, 9,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_temp_data,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ my_rain = XtVaCreateManagedWidget(langcode("WXPUPSI007"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, temp,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ WX_rain_data = XtVaCreateManagedWidget("WX_station rain data", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNmaxLength, 10,
+ XmNtopOffset, 7,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, temp,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_rain_label= XtVaCreateManagedWidget("WX_station rain label",xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns,5,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, temp,
+ XmNtopOffset, 9,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_rain_data,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ to_rain = XtVaCreateManagedWidget(langcode("WXPUPSI008"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, my_rain,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ WX_to_rain_data = XtVaCreateManagedWidget("WX_station today rain data", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNmaxLength, 10,
+ XmNtopOffset, 7,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, my_rain,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ WX_to_rain_label= XtVaCreateManagedWidget("WX_station to label",xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns,10,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, my_rain,
+ XmNtopOffset, 9,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_to_rain_data,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ rain_h = XtVaCreateManagedWidget(langcode("WXPUPSI014"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, to_rain,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ WX_rain_h_data = XtVaCreateManagedWidget("WX_station hour rain data", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNmaxLength, 10,
+ XmNtopOffset, 7,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, to_rain,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ WX_rain_h_label= XtVaCreateManagedWidget("WX_station hour label",xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns,10,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, to_rain,
+ XmNtopOffset, 9,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_rain_h_data,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ my_rain_24 = XtVaCreateManagedWidget(langcode("WXPUPSI015"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, rain_h,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ WX_rain_24_data = XtVaCreateManagedWidget("WX_station 24h rain data", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNmaxLength, 10,
+ XmNtopOffset, 7,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, rain_h,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ WX_rain_24_label= XtVaCreateManagedWidget("WX_station 24h label",xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness, 0,
+ XmNcolumns,10,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, rain_h,
+ XmNtopOffset, 9,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_rain_24_data,
+ XmNleftOffset, 0,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ humidity = XtVaCreateManagedWidget(langcode("WXPUPSI010"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, my_rain_24,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ WX_humidity_data = XtVaCreateManagedWidget("WX_station Humidity data", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, TRUE,
+ XmNshadowThickness, 1,
+ XmNcolumns, 6,
+ XmNmaxLength, 8,
+ XmNtopOffset, 7,
+ XmNbackground, colors[0x0f],
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 2,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, my_rain_24,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNfontList, fontlist1,
+ NULL);
+
+ humidity_n = XtVaCreateManagedWidget(langcode("UNIOP00026"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, my_rain_24,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_humidity_data,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ dew_point = XtVaCreateManagedWidget(langcode("WXPUPSI018"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 4,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_dew_point_data = XtVaCreateManagedWidget("WX_station dew point", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness,1,
+ XmNcolumns, 6,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_dew_point_label = XtVaCreateManagedWidget("WX_station dew label" ,xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness,0,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_dew_point_data,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ high_wind = XtVaCreateManagedWidget(langcode("WXPUPSI019"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, dew_point,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 4,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_high_wind_data = XtVaCreateManagedWidget("WX_station High Wind", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNcolumns, 6,
+ XmNsensitive, TRUE,
+ XmNshadowThickness,1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, dew_point,
+ XmNtopOffset, 7,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_high_wind_label = XtVaCreateManagedWidget("WX_station high wind label",xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness,0,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget,dew_point,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_high_wind_data,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ wind_chill = XtVaCreateManagedWidget(langcode("WXPUPSI020"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, high_wind,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 4,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_wind_chill_data = XtVaCreateManagedWidget("WX_station Wind Chill", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNcolumns, 6,
+ XmNsensitive,TRUE,
+ XmNshadowThickness,1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, high_wind,
+ XmNtopOffset, 7,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_wind_chill_label = XtVaCreateManagedWidget("WX_station wind label",xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness,0,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget,high_wind,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_wind_chill_data,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ heat_index = XtVaCreateManagedWidget(langcode("WXPUPSI021"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, wind_chill,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 4,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_heat_index_data = XtVaCreateManagedWidget("WX_station Heat Index", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNcolumns, 6,
+ XmNsensitive,TRUE,
+ XmNshadowThickness,1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, wind_chill,
+ XmNtopOffset, 7,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_heat_index_label = XtVaCreateManagedWidget("WX_station heat label",xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness,0,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget,wind_chill,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_heat_index_data,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ baro = XtVaCreateManagedWidget(langcode("WXPUPSI009"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, heat_index,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 4,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_baro_data = XtVaCreateManagedWidget("WX_station Baro", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNcolumns, 6,
+ XmNsensitive,TRUE,
+ XmNshadowThickness,1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, heat_index,
+ XmNtopOffset, 7,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_baro_label = XtVaCreateManagedWidget("WX_Station baro unit label",xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness,0,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget,heat_index,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_baro_data,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ three_hour_baro = XtVaCreateManagedWidget(langcode("WXPUPSI022"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, baro,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 4,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_three_hour_baro_data = XtVaCreateManagedWidget("WX_station 3-Hr Baro", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNcolumns, 6,
+ XmNsensitive,TRUE,
+ XmNshadowThickness,1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, baro,
+ XmNtopOffset, 7,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_three_hour_baro_label = XtVaCreateManagedWidget("WX_station 3hr baro unit label",xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness,0,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, baro,
+ XmNtopOffset, 12,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_three_hour_baro_data,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ hi_temp = XtVaCreateManagedWidget(langcode("WXPUPSI023"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, three_hour_baro,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 4,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_hi_temp_data = XtVaCreateManagedWidget("WX_station Today's High Temp", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNcolumns, 6,
+ XmNsensitive,TRUE,
+ XmNshadowThickness,1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, three_hour_baro,
+ XmNtopOffset, 7,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_hi_temp_label = XtVaCreateManagedWidget("WX_station high temp label",xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness,0,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, three_hour_baro,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_hi_temp_data,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ low_temp = XtVaCreateManagedWidget(langcode("WXPUPSI024"),xmLabelWidgetClass, form1,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, hi_temp,
+ XmNtopOffset, 11,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 4,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_low_temp_data = XtVaCreateManagedWidget("WX_station Today's Low Temp", xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNcolumns, 6,
+ XmNsensitive,TRUE,
+ XmNshadowThickness,1,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNtopAttachment,XmATTACH_WIDGET,
+ XmNtopWidget, hi_temp,
+ XmNtopOffset, 7,
+ XmNbottomAttachment,XmATTACH_NONE,
+ XmNbackground, colors[0x0f],
+ XmNfontList, fontlist1,
+ NULL);
+
+ WX_low_temp_label = XtVaCreateManagedWidget("WX_station low temp label",xmTextFieldWidgetClass, form1,
+ XmNeditable, FALSE,
+ XmNcursorPositionVisible, FALSE,
+ XmNsensitive, STIPPLE,
+ XmNshadowThickness,0,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, hi_temp,
+ XmNtopOffset, 8,
+ XmNbottomAttachment, XmATTACH_NONE,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, WX_low_temp_data,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_NONE,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+
+ button_close = XtVaCreateManagedWidget(langcode("UNIOP00003"),xmPushButtonGadgetClass, my_form,
+XmNtraversalOn, TRUE,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frame,
+ XmNtopOffset, 10,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset,10,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 3,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 4,
+ XmNbackground, colors[0xff],
+ XmNfontList, fontlist1,
+ NULL);
+
+ XtAddCallback(button_close, XmNactivateCallback, WX_station_destroy_shell, wx_station_dialog);
+
+ pos_dialog(wx_station_dialog);
+
+ delw = XmInternAtom(XtDisplay(wx_station_dialog),"WM_DELETE_WINDOW", FALSE);
+ XmAddWMProtocolCallback(wx_station_dialog, delw, WX_station_destroy_shell, (XtPointer)wx_station_dialog);
+
+ XtManageChild(my_form);
+ XtManageChild(form1);
+ XtManageChild(pane);
+
+end_critical_section(&wx_station_dialog_lock, "wx_gui.c:WX_station" );
+
+ XtPopup(wx_station_dialog,XtGrabNone);
+ fix_dialog_size(wx_station_dialog);
+ fill_wx_data();
+ } else {
+ (void)XRaiseWindow(XtDisplay(wx_station_dialog), XtWindow(wx_station_dialog));
+ }
+}
+
+
+
+
+
+void fill_wx_data(void) {
+ DataRow *p_station;
+ char temp[20];
+ WeatherRow *weather;
+
+ if (wx_station_dialog != NULL) {
+
+begin_critical_section(&wx_station_dialog_lock, "wx_gui.c:fill_wx_data" );
+
+ if (search_station_name(&p_station,my_callsign,1)) {
+ if (get_weather_record(p_station)) { // DK7IN: only add record if we found something...
+ weather = p_station->weather_data;
+
+ if (strlen(wx_station_type) > 1)
+ XmTextFieldSetString(WX_type_data,wx_station_type);
+ else
+ XmTextFieldSetString(WX_type_data,"");
+ XtManageChild(WX_type_data);
+
+ if (weather != 0) { // we have weather data
+ if (strlen(weather->wx_temp) > 0) {
+ if (!english_units) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%03d",
+ (int)(((atof(weather->wx_temp)-32)*5.0)/9.0));
+
+ XmTextFieldSetString(WX_temp_data,temp);
+ } else XmTextFieldSetString(WX_temp_data,weather->wx_temp);
+ } else
+ XmTextFieldSetString(WX_temp_data,"");
+ XtManageChild(WX_temp_data);
+
+ if (strlen(weather->wx_course) > 0)
+ XmTextFieldSetString(WX_wind_cse_data,weather->wx_course);
+ else
+ XmTextFieldSetString(WX_wind_cse_data,"");
+
+ XtManageChild(WX_wind_cse_data);
+
+ if (strlen(weather->wx_speed) > 0) {
+ if (!english_units) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%03d",
+ (int)(atof(weather->wx_speed)*1.6094));
+
+ XmTextFieldSetString(WX_wind_spd_data,temp);
+ } else
+ XmTextFieldSetString(WX_wind_spd_data,weather->wx_speed);
+ } else
+ XmTextFieldSetString(WX_wind_spd_data,"");
+
+ XtManageChild(WX_wind_spd_data);
+
+ if (strlen(weather->wx_gust) > 0) {
+ if (!english_units) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%03d",
+ (int)(atof(weather->wx_gust)*1.6094));
+
+ XmTextFieldSetString(WX_wind_gst_data,temp);
+ } else
+ XmTextFieldSetString(WX_wind_gst_data,weather->wx_gust);
+ } else
+ XmTextFieldSetString(WX_wind_gst_data,"");
+
+ XtManageChild(WX_wind_gst_data);
+
+ if (strlen(weather->wx_rain_total) > 0) {
+ if (!english_units)
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%0.2f",
+ atof(weather->wx_rain_total)*.254);
+ else
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%0.2f",
+ atof(weather->wx_rain_total)/100.0);
+
+ XmTextFieldSetString(WX_rain_data,temp);
+ } else
+ XmTextFieldSetString(WX_rain_data,"");
+
+ XtManageChild(WX_rain_data);
+
+ if (strlen(weather->wx_rain) > 0) {
+ if (!english_units)
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%0.2f",
+ atof(weather->wx_rain)*.254);
+ else
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%0.2f",
+ atof(weather->wx_rain)/100.0);
+
+ XmTextFieldSetString(WX_rain_h_data,temp);
+ } else
+ XmTextFieldSetString(WX_rain_h_data,"");
+
+ XtManageChild(WX_rain_h_data);
+
+ if (strlen(weather->wx_prec_24) > 0) {
+ if (!english_units)
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%0.2f",
+ atof(weather->wx_prec_24)*.254);
+ else
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%0.2f",
+ atof(weather->wx_prec_24)/100.0);
+
+ XmTextFieldSetString(WX_rain_24_data,temp);
+ } else
+ XmTextFieldSetString(WX_rain_24_data,"");
+
+ XtManageChild(WX_rain_24_data);
+
+ if (strlen(weather->wx_prec_00) > 0) {
+ if (!english_units)
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%0.2f",
+ atof(weather->wx_prec_00)*.254);
+ else
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%0.2f",
+ atof(weather->wx_prec_00)/100.0);
+
+ XmTextFieldSetString(WX_to_rain_data,temp);
+ } else
+ XmTextFieldSetString(WX_to_rain_data,"");
+
+ XtManageChild(WX_rain_data);
+
+ if (strlen(weather->wx_hum) > 0)
+ XmTextFieldSetString(WX_humidity_data,weather->wx_hum);
+ else
+ XmTextFieldSetString(WX_humidity_data,"");
+
+ XtManageChild(WX_humidity_data);
+
+ if (strlen(wx_dew_point) > 0) {
+ if (!english_units) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%03d",
+ (int)(((atof(wx_dew_point)-32)*5.0)/9.0));
+ XmTextFieldSetString(WX_dew_point_data,temp);
+ } else
+ XmTextFieldSetString(WX_dew_point_data,wx_dew_point);
+ } else
+ XmTextFieldSetString(WX_dew_point_data,"");
+
+ XtManageChild(WX_dew_point_data);
+
+ if (strlen(wx_high_wind) > 0) {
+ if (!english_units) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%03d",
+ (int)(atof(wx_high_wind)*1.6094));
+ XmTextFieldSetString(WX_high_wind_data,temp);
+ } else
+ XmTextFieldSetString(WX_high_wind_data,wx_high_wind);
+ } else
+ XmTextFieldSetString(WX_high_wind_data,"");
+
+ XtManageChild(WX_high_wind_data);
+
+ if (strlen(wx_wind_chill) > 0) {
+ if (!english_units) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%03d",
+ (int)(((atof(wx_wind_chill)-32)*5.0)/9.0));
+ XmTextFieldSetString(WX_wind_chill_data,temp);
+ } else
+ XmTextFieldSetString(WX_wind_chill_data,wx_wind_chill);
+ } else
+ XmTextFieldSetString(WX_wind_chill_data,"");
+
+ XtManageChild(WX_wind_chill_data);
+
+ if (strlen(weather->wx_baro) > 0) {
+ if (!english_units) {
+ //xastir_snprintf(temp, sizeof(temp), "%0.0f",
+ // atof(wx_baro_inHg)*25.4); // inch Hg -> mm Hg
+ //XmTextFieldSetString(WX_baro_data,temp);
+ XmTextFieldSetString(WX_baro_data,weather->wx_baro); // hPa
+ }
+ else { // inches mercury
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%0.2f",
+ (atof(weather->wx_baro)*0.02953));
+ XmTextFieldSetString(WX_baro_data,temp);
+ }
+ } else
+ XmTextFieldSetString(WX_baro_data,"");
+
+ XtManageChild(WX_baro_data);
+
+ if (wx_three_hour_baro_on) {
+ if (!english_units) { // hPa
+ //xastir_snprintf(temp, sizeof(temp), "%0.0f",
+ // atof(wx_three_hour_baro)*25.4); // inch Hg -> mm Hg
+ XmTextFieldSetString(WX_three_hour_baro_data,wx_three_hour_baro);
+ } else { // inches mercury
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%0.2f",
+ (atof(wx_three_hour_baro)*0.02953));
+ XmTextFieldSetString(WX_three_hour_baro_data,temp);
+ }
+ } else
+ XmTextFieldSetString(WX_three_hour_baro_data,"");
+
+ XtManageChild(WX_three_hour_baro_data);
+
+ if (wx_hi_temp_on) {
+ if (!english_units) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%03d",
+ (int)(((atof(wx_hi_temp)-32)*5.0)/9.0));
+ XmTextFieldSetString(WX_hi_temp_data,temp);
+ } else
+ XmTextFieldSetString(WX_hi_temp_data,wx_hi_temp);
+ } else
+ XmTextFieldSetString(WX_hi_temp_data,"");
+
+ XtManageChild(WX_hi_temp_data);
+
+ if (wx_low_temp_on) {
+ if (!english_units) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%03d",
+ (int)(((atof(wx_low_temp)-32)*5.0)/9.0));
+ XmTextFieldSetString(WX_low_temp_data,temp);
+ } else
+ XmTextFieldSetString(WX_low_temp_data,wx_low_temp);
+ } else
+ XmTextFieldSetString(WX_low_temp_data,"");
+
+ XtManageChild(WX_low_temp_data);
+
+ if (wx_heat_index_on) {
+ if (!english_units) {
+ xastir_snprintf(temp,
+ sizeof(temp),
+ "%03d",
+ (int)(((atof(wx_heat_index)-32)*5.0)/9.0));
+ XmTextFieldSetString(WX_heat_index_data,temp);
+ } else
+ XmTextFieldSetString(WX_heat_index_data,wx_heat_index);
+ } else
+ XmTextFieldSetString(WX_heat_index_data,"");
+
+ XtManageChild(WX_heat_index_data);
+ }
+ }
+ }
+
+ /* labels */
+ if (!english_units)
+ XmTextFieldSetString(WX_speed_label,langcode("UNIOP00012"));
+ else
+ XmTextFieldSetString(WX_speed_label,langcode("UNIOP00013"));
+
+ XtManageChild(WX_speed_label);
+
+ if (!english_units)
+ XmTextFieldSetString(WX_gust_label,langcode("UNIOP00012"));
+ else
+ XmTextFieldSetString(WX_gust_label,langcode("UNIOP00013"));
+
+ XtManageChild(WX_gust_label);
+
+ if (!english_units)
+ XmTextFieldSetString(WX_temp_label,langcode("UNIOP00014"));
+ else
+ XmTextFieldSetString(WX_temp_label,langcode("UNIOP00015"));
+
+ XtManageChild(WX_temp_label);
+
+ if (!english_units)
+ XmTextFieldSetString(WX_rain_label,langcode("UNIOP00016"));
+ else
+ XmTextFieldSetString(WX_rain_label,langcode("UNIOP00017"));
+
+ XtManageChild(WX_rain_label);
+
+ if (!english_units)
+ XmTextFieldSetString(WX_to_rain_label,langcode("UNIOP00022"));
+ else
+ XmTextFieldSetString(WX_to_rain_label,langcode("UNIOP00023"));
+
+ XtManageChild(WX_to_rain_label);
+
+ if (!english_units)
+ XmTextFieldSetString(WX_rain_h_label,langcode("UNIOP00020"));
+ else
+ XmTextFieldSetString(WX_rain_h_label,langcode("UNIOP00021"));
+
+ XtManageChild(WX_rain_h_label);
+
+ if (!english_units)
+ XmTextFieldSetString(WX_rain_24_label,langcode("UNIOP00018"));
+ else
+ XmTextFieldSetString(WX_rain_24_label,langcode("UNIOP00019"));
+
+ XtManageChild(WX_rain_24_label);
+
+ if (!english_units)
+ XmTextFieldSetString(WX_dew_point_label,langcode("UNIOP00014"));
+ else
+ XmTextFieldSetString(WX_dew_point_label,langcode("UNIOP00015"));
+
+ XtManageChild(WX_dew_point_label);
+
+ if (!english_units)
+ XmTextFieldSetString(WX_wind_chill_label,langcode("UNIOP00014"));
+ else
+ XmTextFieldSetString(WX_wind_chill_label,langcode("UNIOP00015"));
+
+ XtManageChild(WX_wind_chill_label);
+
+ if (!english_units)
+ XmTextFieldSetString(WX_heat_index_label,langcode("UNIOP00014"));
+ else
+ XmTextFieldSetString(WX_heat_index_label,langcode("UNIOP00015"));
+
+ XtManageChild(WX_heat_index_label);
+
+ if (!english_units)
+ XmTextFieldSetString(WX_hi_temp_label,langcode("UNIOP00014"));
+ else
+ XmTextFieldSetString(WX_hi_temp_label,langcode("UNIOP00015"));
+
+ XtManageChild(WX_hi_temp_label);
+
+ if (!english_units)
+ XmTextFieldSetString(WX_low_temp_label,langcode("UNIOP00014"));
+ else
+ XmTextFieldSetString(WX_low_temp_label,langcode("UNIOP00015"));
+
+ XtManageChild(WX_low_temp_label);
+
+ if (!english_units)
+ XmTextFieldSetString(WX_high_wind_label,langcode("UNIOP00012"));
+ else
+ XmTextFieldSetString(WX_high_wind_label,langcode("UNIOP00013"));
+
+ XtManageChild(WX_high_wind_label);
+
+ if (!english_units)
+ XmTextFieldSetString(WX_baro_label,langcode("UNIOP00025"));
+ else
+ XmTextFieldSetString(WX_baro_label,langcode("UNIOP00027"));
+
+ XtManageChild(WX_baro_label);
+
+ if (!english_units)
+ XmTextFieldSetString(WX_three_hour_baro_label,langcode("UNIOP00025"));
+ else
+ XmTextFieldSetString(WX_three_hour_baro_label,langcode("UNIOP00027"));
+
+ XtManageChild(WX_three_hour_baro_label);
+
+end_critical_section(&wx_station_dialog_lock, "wx_gui.c:fill_wx_data" );
+
+ }
+}
+
+
diff --git a/src/x_spider.c b/src/x_spider.c
new file mode 100644
index 0000000..b19a354
--- /dev/null
+++ b/src/x_spider.c
@@ -0,0 +1,1725 @@
+/*
+ * $Id: x_spider.c,v 1.67 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 2003-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+
+//
+// The idea here: Have Xastir spawn off a separate server (via a
+// system() call?) which can provide listening sockets for other
+// APRS clients to connect to. This allows other clients to share
+// Xastir's TNC ports. Forking Xastir directly and running the
+// server code doesn't work out well: The new process ends up with
+// the large Xastir memory image. We need a separate app with a
+// small memory image for the server. It might spawn off quite a
+// few processes, and we need it to be small and fast.
+//
+// The initial goal here is to take one box that is RF-rich (running
+// one or more TNC's), and have the ability to let other APRS
+// clients (Xastir or otherwise) to share the RF and/or internet
+// connections of the "master" Xastir session. This could be useful
+// in an EOC (Emergency Operations Center), a large SAR mission with
+// multiple computers, or simply to allow one to connect to their
+// home Xastir session from work and gain the use of the RF ports.
+// My use: On a SAR mission, using wireless networking and laptops
+// to let everyone see the same picture, multiplexing to one Xastir
+// session running a TNC. As usual, I'm sure other users will
+// figure out new and inventive uses for it.
+//
+// Yes, this does pose some security risks to the license of the
+// operator. I wouldn't recommend having an open port on the
+// internet to allow people to use your RF ports. Of course with
+// the authentication stuff that'll be in here, it's as secure as
+// the igating stuff that we currently have for APRS.
+//
+// I thought about using IPC Messaging or FIFO's (named pipes) in
+// order to make the connection from this server back to the
+// "master" Xastir session. I looked at the lack of support for
+// them in Cygwin and decided to use sockets instead. We'll set up
+// a special registration for Xastir so that this server code knows
+// which port is the "master" port (controlling port).
+//
+// Xastir will end up with a togglebutton to enable the server:
+// Starts up x_spider.
+// Connects to x_spider with a socket.
+// Sends a special string so x_spider knows which one is the
+// controlling (master) socket.
+// All packets received/transmitted by Xastir on any port also get
+// sent to x_spider.
+//
+// x_spider:
+// Accepts client socket connections.
+// Spawns a new process for each one.
+// Each new process talks to the main x_spider via two pipes.
+// Authenticate each connecting client in the normal manner.
+// Accept data from any socket, echo data out _all_ sockets.
+// If the "master" Xastir sends a shutdown packet, all connections
+// are dropped and x_spider and all it's children will exit.
+// x_spider uses select() calls to multiplex all pipes and the
+// listening socket. It shouldn't use up much CPU as it'll be
+// in the blocking select call until it has data to process.
+// x_spider's children should also wait in blocking calls until
+// there is data to process.
+//
+// This makes the design of the server rather simple: It needs to
+// authenticate clients and it needs to parse the shutdown message
+// from the "master" socket. Other than that it just needs to
+// re-transmit anything heard on one socket to all of the other
+// connected sockets.
+//
+// Xastir itself will have to change a bit in order to add the
+// togglebutton, to send anything transmit/received to the special
+// socket, and to send the registration and shutdown strings to the
+// server at the appropriate times. Not earth-shaking changes, but
+// changes nonetheless.
+//
+// Most of this code is adapted directly from W. Richard Steven's
+// book: "Unix Network Programming". Highly recommended book, as
+// are the other books by him that I own. I was sorry to hear of
+// his passing.
+//
+// Name for this? Spider, centipede, millipede, octopus,
+// multiplexer, repeater.
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "x_spider.h"
+#include "snprintf.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <signal.h>
+#include <termios.h>
+#include <pwd.h>
+
+#include <termios.h>
+#include <setjmp.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <netinet/in.h> // Moved ahead of inet.h as reports of some *BSD's not
+ // including this as they should.
+#include <arpa/inet.h>
+#include <netinet/tcp.h> // Needed for TCP_NODELAY setsockopt() (disabling Nagle algorithm)
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif // HAVE_NETDB_H
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // TIME_WITH_SYS_TIME
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+#include <errno.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif // HAVE_LOCALE_H
+
+#ifdef HAVE_LIBINTL_H
+#include <libintl.h>
+#define _(x) gettext(x)
+#else // HAVE_LIBINTL_H
+#define _(x) (x)
+#endif // HAVE_LIBINTL_H
+
+
+#ifndef SIGRET
+#define SIGRET void
+#endif // SIGRET
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+// Define this if you wish to use this as a standalone program
+// instead of as a function in another program.
+//
+//#define STANDALONE_PROGRAM
+
+
+
+// These are from util.h/util.c. We can't include util.h here
+// because it causes other problems.
+extern short checkHash(char *theCall, short theHash);
+extern void get_timestamp(char *timestring);
+extern void split_string( char *data, char *cptr[], int max, char search_char );
+
+
+// From database.h
+extern char my_callsign[];
+
+
+typedef struct _pipe_object {
+ int to_child[2];
+ int to_parent[2];
+ char callsign[20];
+ int authenticated;
+ int active; // Mark for deletion after every task is finished
+ struct _pipe_object *next;
+} pipe_object;
+
+
+pipe_object *pipe_head = NULL;
+//int master_fd = -1; // Start with an invalid value
+
+pipe_object *xastir_tcp_pipe = NULL;
+pipe_object *xastir_udp_pipe = NULL;
+
+// TCP server pipes to/from Xastir proper
+int pipe_xastir_to_tcp_server = -1;
+int pipe_tcp_server_to_xastir = -1;
+
+// UDP server pipes to/from Xastir proper
+int pipe_xastir_to_udp_server = -1; // (not currently used)
+int pipe_udp_server_to_xastir = -1;
+
+
+
+
+
+/*
+// Read "n" bytes from a descriptor. Use in place of read() when fd
+// is a stream socket. This routine is from "Unix Network
+// Programming".
+//
+// This routine is not used currently.
+//
+int readn(register int fd, register char *ptr, register int nbytes) {
+ int nleft, nread;
+
+ nleft = nbytes;
+ while (nleft > 0) {
+ nread = read(fd, ptr, nleft);
+ if (nread < 0) {
+ return(nread); // Error, return < 0
+ }
+ else if (nread == 0) {
+ break; // EOF
+ }
+
+ nleft -= nread;
+ ptr += nread;
+ }
+ return(nbytes - nleft); // Return >= 0
+}
+*/
+
+
+
+
+
+// Write "n" bytes to a descriptor. Use in place of write() when fd
+// is a stream socket. This routine is from "Unix Network
+// Programming".
+//
+int writen(register int fd, register char *ptr, register int nbytes) {
+ int nleft, nwritten;
+
+ nleft = nbytes;
+ while (nleft > 0) {
+ nwritten = write(fd, ptr, nleft);
+ if (nwritten <= 0) {
+ return(nwritten); // Error
+ }
+
+ nleft -= nwritten;
+ ptr += nwritten;
+ }
+
+// fprintf(stderr,
+// "writen: %d bytes written, %d bytes left to write\n",
+// nleft,
+// nbytes - nleft);
+
+ return(nbytes - nleft);
+}
+
+
+
+
+
+// Read a line from a descriptor. Read the line one byte at a time,
+// looking for the newline. We store the newline in the buffer,
+// then follow it with a null (the same as fgets(3)). We return the
+// number of characters up to, but not including, the null (the same
+// as strlen(3)); This routine is from "Unix Network Programming".
+//
+int readline(register int fd, register char *ptr, register int maxlen) {
+ int n, rc;
+ char c;
+
+ for (n = 1; n < maxlen; n++) {
+ if ( (rc = read(fd, &c, 1)) == 1) {
+ *ptr++ = c;
+ if (c == '\n') {
+ break;
+ }
+ }
+ else if (rc == 0) {
+ if (n == 1) {
+ return(0); // EOF, no data read
+ }
+ else {
+ break; // EOF, some data was read
+ }
+ }
+ else {
+ return(-1); // Error
+ }
+ }
+ *ptr = 0;
+ return(n);
+}
+
+
+
+
+
+#define MAXLINE 512
+
+
+// Read a stream socket one line at a time, and write each line back
+// to the sender. Return when the connection is terminated. This
+// routine is from "Unix Network Programming".
+//
+/*
+void str_echo(int sockfd) {
+ int n;
+ char line[MAXLINE];
+
+ for ( ; ; ) {
+ n = readline(sockfd, line, MAXLINE);
+ if (n == 0) {
+ return; // Connection terminated
+ }
+ if (n < 0) {
+ fprintf(stderr,"str_echo: No data to read\n");
+ }
+
+ if (writen(sockfd, line, n) != n) {
+ fprintf(stderr,"str_echo: Writen error\n");
+ }
+ }
+}
+*/
+
+
+
+
+
+// Read a stream socket one line at a time, and write each line back
+// to the sender. Return when the connection is terminated. This
+// routine is from "Unix Network Programming".
+//
+void str_echo2(int sockfd, int pipe_from_parent, int pipe_to_parent) {
+ int n;
+ char line[MAXLINE];
+
+
+ // Set socket to be non-blocking.
+ //
+ if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) {
+ fprintf(stderr,"str_echo2: Couldn't set socket non-blocking\n");
+ }
+
+ // Set read-end of pipe to be non-blocking.
+ //
+ if (fcntl(pipe_from_parent, F_SETFL, O_NONBLOCK) < 0) {
+ fprintf(stderr,"str_echo2: Couldn't set read-end of pipe_from_parent non-blocking\n");
+ }
+
+
+ //Send our callsign to spider clients as "#callsign" much like APRS-IS sends "# javaAPRS"
+ // # xastir 1.5.1 callsign:<mycall>
+ sprintf(line,"# Welcome to Xastir's server port, callsign: %s\r\n",my_callsign);
+ writen(sockfd,line,strlen(line));
+
+ // Infinite loop
+ for ( ; ; ) {
+
+ //
+ // Read data from socket, write to pipe (parent)
+ //
+ if (!sockfd) // Socket is closed
+ return; // Connection terminated
+
+ n = readline(sockfd, line, MAXLINE);
+ if (n == 0) {
+ return; // Connection terminated
+ }
+ if (n < 0) {
+ //fprintf(stderr,"str_echo2: Readline error: %d\n",errno);
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ // This is normal if we have no data to read
+ //fprintf(stderr,"EAGAIN or EWOULDBLOCK\n");
+ }
+ else { // Non-normal error. Report it.
+ fprintf(stderr,"str_echo2: Readline error socket: %d\n",errno);
+//close(sockfd);
+return;
+ }
+ }
+ else { // We received some data. Send it down the pipe.
+// fprintf(stderr,"str_echo2: %s\n",line);
+ if (writen(pipe_to_parent, line, n) != n) {
+ fprintf(stderr,"str_echo2: Writen error socket: %d\n",errno);
+//close(sockfd);
+return;
+ }
+ }
+
+
+ //
+ // Read data from pipe (parent), write to socket
+ //
+ if (!pipe_from_parent)
+ exit(0);
+
+ n = readline(pipe_from_parent, line, MAXLINE);
+ if (n == 0) {
+ exit(0); // Connection terminated
+ }
+ if (n < 0) {
+ //fprintf(stderr,"str_echo2: Readline error: %d\n",errno);
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ // This is normal if we have no data to read
+ //fprintf(stderr,"EAGAIN or EWOULDBLOCK\n");
+ }
+ else { // Non-normal error. Report it.
+ fprintf(stderr,"str_echo2: Readline error pipe: %d\n",errno);
+//close(pipe_from_parent);
+return;
+ }
+ }
+ else { // We received some data. Send it down the socket.
+// fprintf(stderr,"str_echo2: %s\n",line);
+
+ if (writen(sockfd, line, n) != n) {
+ fprintf(stderr,"str_echo2: Writen error pipe: %d\n",errno);
+//close(pipe_from_parent);
+return;
+ }
+ }
+
+ // Slow the loop down to prevent excessive CPU.
+
+// NOTE: We must be faster at processing packets than the
+// main.c:UpdateTime() can send them to us through the pipe! If
+// we're not, we lose or corrupt packets.
+
+ usleep(1000); // 1ms
+ }
+}
+
+
+
+
+
+// Function which checks the incoming pipes to see if there's any
+// data. If there is, checks to see if it is a control packet or a
+// registration packet from the master. If not, echoes the data out
+// all outgoing pipes.
+//
+// If we get a shutdown from the verified master, send a "1" as the
+// return value, which will shut down the server. Otherwise send a
+// "0" return value.
+//
+// Incoming registration data: Record only the master socket. All
+// others should be handled by the child processes, and they should
+// not pass the registration info down to us. Same for control
+// packets. Actually, the child process handling the master socket
+// could skip notifying us as well, and just pass down the control
+// packets if the master sent any (like the shutdown packet). If we
+// lost the connection between Xastir and x_spider, we might not
+// have a clean way of shutting down the server in that case though.
+// Might be better to record it down here, and if the pipes ever
+// closed, we shut down x_spider and all the child processes.
+//
+int pipe_check(char *client_address) {
+ pipe_object *p = pipe_head;
+ int n;
+ char line[MAXLINE];
+
+
+ // Need a select here with a timeout? Also need a method of
+ // revising the read bits we send to select. Should we revise
+ // them every time through the loop, or set a variable in the
+ // main() routine whenever a new connect comes in. What about
+ // connects that go away? We need a way to free up the pipes
+ // and sockets in that case, and revise the select bits again.
+
+// select();
+
+//fprintf(stderr,"pipe_check()\n");
+
+ // All of the read ends of the pipes have been set non-blocking
+ // by this point.
+
+ // Check all the pipes in the linked list looking for something
+ // to read.
+ while (p != NULL) {
+// fprintf(stderr,"Running through pipes\n");
+
+ //
+ // Read data from pipe, write to all pipes except the one
+ // who sent it.
+ //
+ n = p->active ? readline(p->to_parent[0], line, MAXLINE): 0;
+ if (n == 0 && p->active) {
+ char timestring[101];
+
+ get_timestamp(timestring);
+
+ if (p->authenticated) {
+ fprintf(stderr,
+ "%s X_spider session terminated, callsign: %s, address: %s\n",
+ timestring,
+ p->callsign,
+ client_address);
+ }
+ else {
+ fprintf(stderr,
+ "%s X_spider session terminated, unauthenticated user, address %s\n",
+ timestring,
+ client_address);
+ }
+
+ // Close the pipe
+ close(p->to_child[1]);
+ close(p->to_parent[0]);
+
+ p->active = 0; // This task is ready to let go.
+
+ wait(NULL); // Reap the status of the dead process
+ }
+ else if (n < 0) {
+ //fprintf(stderr,"pipe_check: Readline error: %d\n",errno);
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ // This is normal if we have no data to read
+ //fprintf(stderr,"EAGAIN or EWOULDBLOCK\n");
+ }
+ else { // Non-normal error. Report it.
+ fprintf(stderr,"pipe_check: Readline error: %d\n",errno);
+ }
+ }
+ else if (p->active) { // We received some data. Send it down all of the
+ // pipes except the one that sent it.
+
+ pipe_object *q;
+
+
+// Check for an authentication string. If the pipe has not been
+// authenticated, we don't allow it to send anything to the upstream
+// server. It's probably ok to send it to downstream connections
+// though.
+
+ // Check for "user" "pass" string.
+ // "user WE7U-13 pass XXXX vers XASTIR 1.3.3"
+ if (strstr(line,"user") && strstr(line,"pass")) {
+ char line2[MAXLINE];
+ char *callsign;
+ char *passcode_str;
+ short passcode;
+ char *space;
+
+ // We have a string with user/pass in it, but they
+ // can be anywhere along the line. We'll have to
+ // search for each piece.
+
+//fprintf(stderr,"x_spider:Found an authentication string\n");
+
+ // Copy the line
+ xastir_snprintf(line2, sizeof(line2), "%s", line);
+
+ // Add white space to the end.
+ strncat(line2,
+ " ",
+ sizeof(line2) - 1 - strlen(line2));
+
+ // Find the "user" string position
+ callsign = strstr(line2,"user");
+
+ if (callsign == NULL)
+ continue;
+
+ // Fast-forward past the "user" word.
+ callsign += 4;
+
+ // Skip past any additional spaces that might be
+ // present between "user" and callsign.
+ while (callsign[0] == ' ' && callsign[0] != '\0') {
+ callsign += 1;
+ }
+
+ if (callsign[0] == '\0')
+ continue;
+
+ // We should now be pointing at the beginning of the
+ // callsign.
+
+ // Find the space after the callsign
+ space = strstr(callsign," ");
+
+ if (space == NULL)
+ continue;
+
+ // Terminate the callsign string
+ space[0] = '\0';
+
+ // Snag the passcode string
+
+ // Find the "pass" string
+ passcode_str = strstr(&space[1],"pass");
+
+ if (passcode_str == NULL)
+ continue;
+
+ // Fast-forward past the "pass" word.
+ passcode_str = passcode_str + 4;
+
+ // Skip past any additional spaces that might be
+ // present between "pass" and the passcode.
+ while (passcode_str[0] == ' ' && passcode_str[0] != '\0') {
+ passcode_str += 1;
+ }
+
+ if (passcode_str[0] == '\0')
+ continue;
+
+ // Find the space after the passcode
+ space = strstr(&passcode_str[0]," ");
+
+ if (space == NULL)
+ continue;
+
+ // Terminate the passcode string
+ space[0] = '\0';
+
+ passcode = atoi(passcode_str);
+
+//fprintf(stderr,"x_spider: user:.%s., pass:%d\n", callsign, passcode);
+
+ if (checkHash(callsign, passcode)) {
+ // Authenticate the pipe. It is now allowed to send
+ // to the upstream server.
+ //fprintf(stderr,
+ // "x_spider: Authenticated user %s\n",
+ // callsign);
+ p->authenticated = 1;
+ xastir_snprintf(p->callsign,
+ sizeof(p->callsign),
+ "%s",
+ callsign);
+ p->callsign[19] = '\0';
+ }
+ else {
+ fprintf(stderr,
+ "X_spider: Bad authentication, user %s, pass %d\n",
+ callsign,
+ passcode);
+ fprintf(stderr,
+ "Line: %s\n",
+ line);
+ }
+ }
+
+ q = pipe_head;
+
+ while (q != NULL) {
+// fprintf(stderr,"pipe_check: %s\n",line);
+
+ // Only send to active pipes
+ if (q != p && q->active) {
+ if (writen(q->to_child[1], line, n) != n) {
+ fprintf(stderr,"pipe_check: Writen error1: %d\n",errno);
+ }
+ }
+ q = q->next;
+ }
+
+ // Here we send it to Xastir itself. We use a couple of
+ // global variables just like channel_data() does, but
+ // we don't have to protect them in the same manner as
+ // we only have one process on each end.
+ //
+
+// Send it down the pipe to Xastir's main thread. Knock off any
+// carriage return that might be present. We only want a linefeed
+// on the end.
+ if (n > 0 && (line[n-1] == '\r' || line[n-1] == '\n')) {
+ line[n-1] = '\0';
+ n--;
+ }
+ if (n > 0 && (line[n-1] == '\r' || line[n-1] == '\n')) {
+ line[n-1] = '\0';
+ n--;
+ }
+ // Add the linefeed on the end
+ strncat(line,"\n",1);
+ n++;
+
+// Only send to upstream server if this client has authenticated.
+ if (p->authenticated) {
+
+//fprintf(stderr,"Data available, sending to server\n");
+//fprintf(stderr,"\t%s\n",line);
+
+ if (writen(pipe_tcp_server_to_xastir, line, n) != n) {
+ fprintf(stderr, "pipe_check: Writen error2: %d\n", errno);
+ }
+ }
+ }
+
+ if (p) p = p->next;
+ }
+
+
+ // Check the pipe from Xastir's main thread to see if it is
+ // sending us any data
+ n = readline(pipe_xastir_to_tcp_server, line, MAXLINE);
+
+ if (n == 0) {
+ exit(0); // Connection terminated
+ }
+
+ if (n < 0) {
+ //fprintf(stderr,"pipe_check: Readline error: %d\n",errno);
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ // This is normal if we have no data to read
+ //fprintf(stderr,"EAGAIN or EWOULDBLOCK\n");
+ }
+ else { // Non-normal error. Report it.
+ fprintf(stderr,"pipe_check: Readline error: %d\n",errno);
+ }
+ }
+
+ else { // We received some data. Send it down all of the
+ // pipes.
+// Also send it down the socket.
+
+ // Check for disconnected clients and delete their records
+ // from the chain.
+ pipe_object *q = pipe_head;
+ pipe_object *r = pipe_head;
+ for (q = pipe_head; q != NULL; ) {
+
+ if (!q->active) { // Marked for deletion.
+
+ // Check for head of list, handle it in a special
+ // manner. We don't have to fix up the "next"
+ // pointer on the previous object (it doesn't exist)
+ // but must fix up "pipe_head" pointer.
+ if (q == pipe_head) {
+ pipe_head = q->next; // New head of list
+ p = q; // Assign temporary pointer
+ q = q->next; // Keep pointer to next object
+ r = q; // Keep 'r' and 'q' the same for now,
+ // later 'r' will lag 'q' by one object
+ free(p); // Free struct at temporary pointer
+ }
+ else { // Not the head object
+ r->next = q->next; // Bridge soon-to-be-made gap
+ p = q; // Assign temporary pointer
+ q = q->next; // Keep pointer to next connection.
+ free(p); // Free struct at temp pointer
+ }
+ }
+ else {
+ r = q; // Pointer to last object (so we can get to
+ // the "next" pointer)
+ q = q->next; // Pointer to next object
+ }
+ }
+ q = pipe_head; // Reset pointer to beginning of list
+
+ //fprintf(stderr,"n:%d\n",n);
+ // Terminate it
+ line[n] = '\0';
+ //fprintf(stderr,"sp %s\n", line);
+
+ // The internet protocol for sending lines is "\r\n". Knock
+ // off any line-end characters that might be present, then
+ // add a "\r\n" combo on the end.
+ //
+ if (n >= 1 && (line[n-1] == '\r' || line[n-1] == '\n')) {
+ line[n-1] = '\0';
+ n--;
+ }
+ if (n >= 1 && (line[n-1] == '\r' || line[n-1] == '\n')) {
+ line[n-1] = '\0';
+ n--;
+ }
+ // Add carriage-return/linefeed onto the end
+ strncat(line, "\r\n", 2);
+ n += 2;
+
+ while (q != NULL && q->active) {
+// fprintf(stderr,"pipe_check: %s\n",line);
+
+ if (writen(q->to_child[1], line, n) != n) {
+ fprintf(stderr,"pipe_check: Writen error1: %d\n",errno);
+ }
+ q = q->next;
+ }
+ }
+
+ return(0);
+}
+
+
+
+
+
+// The below three functions init_set_proc_title() and
+// set_proc_title() are from:
+// http://lightconsulting.com/~thalakan/process-title-notes.html
+// They seems to work fine on Linux, but they only change the "ps"
+// listings, not the top listings. I don't know why yet.
+
+// Here's another good web page for Linux:
+// http://www.uwsg.iu.edu/hypermail/linux/kernel/0006.1/0610.html
+
+// clear_proc_title is to clean up internal pointers for environment.
+
+/* Globals */
+static char **Argv = ((void *)0);
+#ifdef __linux__
+#ifndef __LSB__
+extern char *__progname, *__progname_full;
+#endif // __LSB__
+#endif // __linux__
+static char *LastArgv = ((void *)0);
+static char **local_environ;
+static char *old_progname, *old_progname_full;
+
+
+
+void clear_proc_title(void)
+{
+ int i;
+ for(i = 0; local_environ && local_environ[i] != NULL; i++) {
+ free(local_environ[i]);
+ }
+ if (local_environ) {
+ free(local_environ);
+ local_environ = NULL;
+ }
+#ifdef __linux__
+#ifndef __LSB__
+ free(__progname);
+ free(__progname_full);
+ __progname = old_progname;
+ __progname_full = old_progname_full;
+#endif // __LSB__
+#endif // __linux__
+}
+
+void init_set_proc_title(int argc, char *argv[], char *envp[]) {
+ int i, envpsize;
+ char **p;
+
+ for(i = envpsize = 0; envp[i] != NULL; i++)
+ envpsize += strlen(envp[i]) + 1;
+
+ if((p = (char **) malloc((i + 1) * sizeof(char *))) != NULL ) {
+ local_environ = p;
+
+ for(i = 0; envp[i] != NULL; i++) {
+ if((local_environ[i] = malloc(strlen(envp[i]) + 1)) != NULL)
+ xastir_snprintf(local_environ[i],
+ strlen(envp[i])+1,
+ "%s",
+ envp[i]);
+ }
+ }
+ local_environ[i] = NULL;
+
+ Argv = argv;
+
+ for(i = 0; argv[i] != NULL; i++) {
+ if((LastArgv + 1) == argv[i]) // Not sure if this conditional is needed
+ LastArgv = envp[i] + strlen(envp[i]);
+ }
+#ifdef __linux__
+#ifndef __LSB__
+ // Pretty sure you don't need this either
+ old_progname = __progname;
+ old_progname_full = __progname_full;
+ __progname = strdup("xastir");
+ __progname_full = strdup(argv[0]);
+#endif // __LSB__
+#endif // __linux__
+ atexit(clear_proc_title);
+}
+
+
+void set_proc_title(char *fmt,...) {
+ va_list msg;
+ static char statbuf[8192];
+ char *p;
+ int i,maxlen = (LastArgv - Argv[0]) - 2;
+
+ //fprintf(stderr,"DEBUG: maxlen: %i\n", maxlen);
+
+ va_start(msg,fmt);
+
+ memset(statbuf, 0, sizeof(statbuf));
+ xastir_vsnprintf(statbuf, sizeof(statbuf), fmt, msg);
+
+ va_end(msg);
+
+ i = strlen(statbuf);
+
+ xastir_snprintf(Argv[0], maxlen, "%s", statbuf);
+ p = &Argv[0][i];
+
+ while(p < LastArgv)
+ *p++ = '\0';
+ Argv[1] = ((void *)0) ;
+}
+
+
+
+
+
+// This TCP server provides a listening socket. When a client
+// connects, the server forks off a separate process to handle it
+// and goes back to listening for new connects. The initial code
+// framework here is from the book: "Unix Network Programming".
+//
+// Create two pipes between this server and each child process.
+// Identify and record which socket is the master socket connection
+// (back to the Xastir session that started up x_spider). Set this
+// variable once, don't change it if another client connects and
+// claims to be the master. If we get control commands from the
+// master, service them.
+//
+// If anything that comes in from a client that's not a registration
+// or a control packet, repeat it to all of the other connected
+// clients, including sending it to the controlling Xastir socket
+// (which is also a data channel).
+//
+// We need to make the "accept" call non-blocking so that we can
+// keep servicing all of the pipes from the children. If any pipe
+// has data, check whether it's a registration from the master or a
+// control packet. If not, send the data out each client
+// connection. Each child will take care of normal APRS
+// authentication. If the client doesn't authenticate, close the
+// socket and exit from the child process. Notify the main process
+// as well?
+//
+#ifdef STANDALONE_PROGRAM
+int main(int argc, char *argv[]) {
+#else // !STANDALONE_PROGRAM
+void TCP_Server(int argc, char *argv[], char *envp[]) {
+#endif // STANDALONE_PROGRAM
+
+ int sockfd, newsockfd, childpid;
+ socklen_t clilen;
+ struct sockaddr_in cli_addr, serv_addr;
+ pipe_object *p;
+ int sendbuff;
+ int pipe_to_parent; /* symbolic names to reduce confusion */
+ int pipe_from_parent;
+ char timestring[101];
+
+
+ // Open a TCP listening socket
+ //
+ if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ fprintf(stderr,"x_spider: Can't open socket for listening\n");
+ fprintf(stderr,"Could some processes still be running from a previous run of Xastir?\n");
+ exit(1);
+ }
+
+ // Set the new socket to be non-blocking.
+ //
+ if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) {
+ fprintf(stderr,"x_spider: Couldn't set socket non-blocking\n");
+ fprintf(stderr,"Could some processes still be running from a previous run of Xastir?\n");
+ }
+
+ // Set up to reuse the port number (good for debug so we can
+ // restart the server quickly against the same port).
+ //
+ sendbuff = 1;
+ if (setsockopt(sockfd,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ (char *)&sendbuff,
+ sizeof(sendbuff)) < 0) {
+ fprintf(stderr,"x_spider: Couldn't set socket REUSEADDR\n");
+ fprintf(stderr,"Could some processes still be running from a previous run of Xastir?\n");
+ }
+
+ // Bind our local address so that the client can send to us.
+ //
+ memset((char *)&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ serv_addr.sin_port = htons(SERV_TCP_PORT);
+
+ if (bind(sockfd,
+ (struct sockaddr *)&serv_addr,
+ sizeof(serv_addr)) < 0) {
+ fprintf(stderr,"x_spider: Can't bind local address\n");
+ fprintf(stderr,"Could some processes still be running from a previous run of Xastir?\n");
+ exit(1);
+ }
+
+ // Set up to listen. We allow up to five backlog connections
+ // (unserviced connects that get put on a queue until we can
+ // service them).
+ //
+ listen(sockfd, 5);
+ memset((char *)&cli_addr, 0, sizeof(cli_addr));
+
+ // Infinite loop
+ //
+ for ( ; ; ) {
+ int flag;
+
+
+ // Look for a connection from a client process. This is a
+ // concurrent server (allows multiple concurrent
+ // connections).
+
+ clilen = (socklen_t)sizeof(cli_addr);
+
+ // "accept" is the call where we wait for a connection. We
+ // made the socket non-blocking above so that we pop out of
+ // it with an EAGAIN if we don't have an incoming socket
+ // connection. This lets us check all of our pipe
+ // connections for incoming data periodically.
+ //
+ newsockfd = accept(sockfd,
+ (struct sockaddr *)&cli_addr,
+ &clilen);
+
+ if (newsockfd == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+
+ // We returned from the non-blocking accept but with
+ // no incoming socket connection. Check the pipe
+ // queues for incoming data.
+ //
+ if (pipe_check(inet_ntoa(cli_addr.sin_addr)) == -1) {
+
+ // We received a shutdown command from the
+ // master socket connection.
+ exit(0);
+ }
+ goto finis;
+ }
+ else if (newsockfd < 0) {
+
+ // Some error happened in accept(). Skip the rest
+ // of the loop.
+ //
+ fprintf(stderr,"x_spider: Accept error: %d\n", errno);
+ fprintf(stderr,"Could some processes still be running from a previous run of Xastir?\n");
+ goto finis;
+ }
+ }
+
+ // Else we returned from the accept with an incoming
+ // connection. Service it.
+ //
+ // Allocate a new pipe before we fork.
+ //
+ p = (pipe_object *)malloc(sizeof(pipe_object));
+ if (p == NULL) {
+ fprintf(stderr,"x_spider: Couldn't malloc pipe_object\n");
+ close(newsockfd);
+ goto finis;
+ }
+
+ // We haven't authenticated this user client yet.
+ p->authenticated = 0;
+ p->callsign[0] = '\0';
+
+ get_timestamp(timestring);
+
+ fprintf(stderr,"%s X_spider client connected from address %s\n",
+ timestring,
+ inet_ntoa(cli_addr.sin_addr));
+
+ if (pipe(p->to_child) < 0 || pipe(p->to_parent) < 0) {
+ fprintf(stderr,"x_spider: Can't create pipes\n");
+ if (p->to_child[1]) close(p->to_child[1]);
+ if (p->to_child[0]) close(p->to_child[0]);
+ free(p); // Free the malloc'd memory.
+ p = NULL;
+ close(newsockfd);
+ goto finis;
+ }
+
+ // Indicate active connection!
+ p->active = 1;
+
+ // Link it into the head of the chain.
+ //
+ p->next = pipe_head;
+ pipe_head = p;
+
+ flag = 1;
+
+ // Turn on the socket keepalive option
+ (void)setsockopt(newsockfd, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int));
+
+ // Disable the Nagle algorithm (speeds things up)
+ (void)setsockopt(newsockfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
+
+ if ( (childpid = fork()) < 0) {
+ //
+ // Problem forking. Clean up and continue loop.
+ //
+
+ fprintf(stderr,"x_spider: Fork error\n");
+ // Close pipes
+ close(p->to_child[0]);
+ close(p->to_child[1]);
+ close(p->to_parent[0]);
+ close(p->to_parent[1]);
+ pipe_head = p->next;
+ free(p); // Free the malloc'd memory.
+ p = NULL;
+ close(newsockfd);
+ goto finis;
+ }
+ else if (childpid == 0) {
+ //
+ // child process
+ //
+
+
+ // Go back to default signal handler instead of calling
+ // restart() on SIGHUP
+ (void) signal(SIGHUP,SIG_DFL);
+
+
+/*
+ fprintf(stderr,
+ "Client address: %s\n",
+ inet_ntoa(cli_addr.sin_addr));
+*/
+
+ // Change the name of the new child process. So far
+ // this only works for "ps" listings, not for "top".
+ // This code only works on Linux. For BSD use
+ // setproctitle(3), NetBSD can use setprogname(2).
+#ifdef __linux__
+ init_set_proc_title(argc, argv, envp);
+ set_proc_title("%s%s %s",
+ "x-spider client @",
+ inet_ntoa(cli_addr.sin_addr),
+ "(xastir)");
+ //fprintf(stderr,"DEBUG: %s\n", Argv[0]);
+ (void) signal(SIGHUP, exit);
+#endif // __linux__
+
+// It'd be very cool here to include the IP address of the remote
+// client on the "ps" line, and include the callsign of the
+// connecting client once the client authenticates. Both of these
+// are do-able.
+
+
+ // New naming system so that we don't have to remember
+ // the longer name:
+ //
+ pipe_to_parent = p->to_parent[1];
+ pipe_from_parent = p->to_child[0];
+
+ close(sockfd); // Close original socket. Child
+ // doesn't need the listening
+ // socket.
+ close(p->to_child[1]); // Close write end of pipe
+ close(p->to_parent[0]); // Close read end of pipe
+
+// str_echo(newsockfd); // Process the request
+ str_echo2(newsockfd,
+ pipe_from_parent,
+ pipe_to_parent);
+
+
+ // Clean up and exit
+ //
+ close(pipe_to_parent);
+ close(pipe_from_parent);
+ exit(0);
+
+ }
+ //
+ // Parent process
+ //
+
+ close(newsockfd);
+ close(p->to_parent[1]); // Close write end of pipe
+ close(p->to_child[0]); // Close read end of pipe
+
+ // Set read-end of pipe to be non-blocking.
+ //
+ if (fcntl(p->to_parent[0], F_SETFL, O_NONBLOCK) < 0) {
+ fprintf(stderr,"x_spider: Couldn't set read-end of pipe_to_parent non-blocking\n");
+ fprintf(stderr,"Could some processes still be running from a previous run of Xastir?\n");
+ }
+
+finis:
+ // Need a delay so that we don't use too much CPU, at least
+ // for debug. Put the delay into the select() call in the
+ // pipe_check() function once we get to that stage of
+ // coding.
+ //
+
+// NOTE: We must be faster at processing packets than the
+// main.c:UpdateTime() can send them to us through the pipe! If
+// we're not, we lose or corrupt packets.
+
+ usleep(1000); // 1ms
+ }
+}
+
+
+
+
+
+// Send a nack back to the xastir_udp_client program
+void send_udp_nack(int sock, struct sockaddr_in from, int fromlen) {
+ int n;
+
+ n = sendto(sock,
+ "NACK", // Negative Acknowledgment
+ 5,
+ 0,
+ (struct sockaddr *)&from,
+ fromlen);
+ if (n < 0) {
+ fprintf(stderr, "Error: sendto");
+ }
+}
+
+
+
+
+
+// Create a UDP listening port. This allows scripts and other
+// programs to inject packets into Xastir via UDP protocol.
+//
+void UDP_Server(int argc, char *argv[], char *envp[]) {
+ int sock, length, n1, n2;
+ socklen_t fromlen;
+ struct sockaddr_in server;
+ struct sockaddr_in from;
+ char buf[1024];
+ char buf2[512];
+ char *callsign;
+ short passcode;
+ char *cptr[10];
+ char *message = NULL;
+ char message2[1024];
+ int send_to_inet;
+ int send_to_rf;
+
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+ if (sock < 0) {
+ fprintf(stderr, "Error: Opening socket");
+ fprintf(stderr,"Could some processes still be running from a previous run of Xastir?\n");
+ return;
+ }
+
+ length = sizeof(server);
+ memset(&server, 0, length);
+
+ server.sin_family = AF_INET;
+ server.sin_addr.s_addr = INADDR_ANY;
+ server.sin_port = htons(SERV_UDP_PORT);
+
+ if (bind(sock, (struct sockaddr *)&server, length) < 0) {
+ fprintf(stderr, "Error: Binding");
+ fprintf(stderr,"Could some processes still be running from a previous run of Xastir?\n");
+ return;
+ }
+
+ fromlen = sizeof(struct sockaddr_in);
+
+ while (1) {
+ n1 = recvfrom(sock,
+ buf,
+ 1024,
+ 0,
+ (struct sockaddr *)&from,
+ &fromlen);
+ if (n1 < 0) {
+ fprintf(stderr, "Error: recvfrom");
+ }
+ else if (n1 == 0) {
+ continue;
+ }
+ else {
+ buf[n1] = '\0'; // Terminate the buffer
+ }
+
+fprintf(stderr, "Received datagram: %s", buf);
+
+
+ send_to_inet = 0;
+ send_to_rf = 0;
+
+
+ //
+ // Authenticate the packet. First line should contain:
+ //
+ // callsign,passcode,[TO_RF],[TO_INET]
+ //
+ // The second line should contain the APRS packet
+ //
+
+ // Copy the entire buffer so that we can modify it
+ xastir_snprintf(buf2, sizeof(buf2), "%s", buf);
+ split_string(buf2, cptr, 10, ',');
+
+ if (cptr[0] == NULL || cptr[0][0] == '\0') { // callsign
+ send_udp_nack(sock, from, fromlen);
+ continue;
+ }
+
+ callsign = cptr[0];
+
+ if (cptr[1] == NULL || cptr[1][0] == '\0') { // passcode
+ send_udp_nack(sock, from, fromlen);
+ continue;
+ }
+
+ passcode = atoi(cptr[1]);
+
+fprintf(stderr,"x_spider udp: user:%s pass:%d\n", callsign, passcode);
+
+ if (checkHash(callsign, passcode)) {
+ // Authenticate the pipe. It is now allowed to send
+ // to the upstream server.
+ //fprintf(stderr,
+ // "x_spider: Authenticated user %s\n",
+ // callsign);
+ }
+ else {
+ fprintf(stderr,
+ "X_spider: Bad authentication, user %s, pass %d\n",
+ callsign,
+ passcode);
+ fprintf(stderr,
+ "UDP Packet: %s\n",
+ buf);
+ send_udp_nack(sock, from, fromlen);
+ continue;
+ }
+
+
+ // Here's where we would look for the optional flags in the
+ // first line. Here we implement these flags:
+ // -identify
+ // -to_rf
+ // -to_inet
+
+
+ // Look for the "-identify" flag in the UDP packet
+ //
+ if (strstr(buf, "-identify")) {
+
+ // Send the callsign back to the xastir_udp_client
+ // program
+ n1 = sendto(sock,
+ my_callsign,
+ strlen(my_callsign)+1,
+ 0,
+ (struct sockaddr *)&from,
+ fromlen);
+ if (n1 < 0) {
+ fprintf(stderr, "Error: sendto");
+ }
+ continue;
+ }
+
+
+ // Look for the "-to_inet" flag in the UDP packet
+ //
+ if (strstr(buf, "-to_inet")) {
+//fprintf(stderr,"Sending to INET\n");
+ send_to_inet++;
+ }
+
+
+ // Look for the "-to_rf" flag in the UDP packet
+ //
+ if (strstr(buf, "-to_rf")) {
+//fprintf(stderr,"Sending to local RF\n");
+ send_to_rf++;
+ }
+
+
+ // Now snag the text message from the second line using the
+ // original buffer. Look for the first '\n' character which
+ // is just before the text message itself.
+ message = strchr(buf, '\n');
+ message++; // Point to the first char after the '\n'
+
+ if (message == NULL || message[0] == '\0') {
+//fprintf(stderr,"Empty message field\n");
+ send_udp_nack(sock, from, fromlen);
+ continue;
+ }
+
+//fprintf(stderr,"Message: %s", message);
+
+ xastir_snprintf(message2,
+ sizeof(message2),
+ "%s%s%s",
+ (send_to_inet) ? "TO_INET," : "",
+ (send_to_rf) ? "TO_RF," : "",
+ message);
+
+//fprintf(stderr,"Message2: %s", message2);
+
+
+
+//
+//
+// NOTE:
+// Should we refuse to send the message on if "callsign" and the
+// FROM callsign in the packet don't match?
+//
+// Should we change to third-party format if "my_callsign" and the
+// FROM callsign in the packet don't match?
+//
+// Require all three callsigns to match?
+//
+//
+
+
+
+ n1 = strlen(message);
+ n2 = strlen(message2);
+
+
+ // Send to Xastir udp pipe
+ //
+//fprintf(stderr,"Sending to Xastir itself\n");
+ if (writen(pipe_udp_server_to_xastir, message2, n2) != n2) {
+ fprintf(stderr,"UDP_Server: Writen error1: %d\n", errno);
+ }
+
+ // Send to the x_spider TCP server, so it can go to all
+ // connected TCP clients
+//fprintf(stderr,"Sending to TCP clients\n");
+ if (writen(pipe_xastir_to_tcp_server, message, n1) != n1) {
+ fprintf(stderr, "UDP_Server: Writen error2: %d\n", errno);
+ }
+
+ // Send an ACK back to the xastir_udp_client program
+ n1 = sendto(sock,
+ "ACK", // Acknowledgment. Good UDP packet.
+ 4,
+ 0,
+ (struct sockaddr *)&from,
+ fromlen);
+ if (n1 < 0) {
+ fprintf(stderr, "Error: sendto");
+ }
+ }
+}
+
+
+
+
+
+// Function used to start a separate process for the server. This
+// way the server can be running concurrently with the main part of
+// Xastir.
+//
+// Turns out that with a "fork", the memory image of the server was
+// too large. Might try it with a thread instead before abandoning
+// that method altogether. It would be nice to have this be more
+// integrated with Xastir, instead of having to have a socket to
+// communicate between Xastir and the server.
+//
+#ifndef STANDALONE_PROGRAM
+int Fork_TCP_server(int argc, char *argv[], char *envp[]) {
+ int childpid;
+
+
+ // Allocate a pipe before we fork.
+ //
+ xastir_tcp_pipe = (pipe_object *)malloc(sizeof(pipe_object));
+ if (xastir_tcp_pipe == NULL) {
+ fprintf(stderr,"x_spider: Couldn't malloc pipe_object\n");
+ return(0);
+ }
+
+ if (pipe(xastir_tcp_pipe->to_child) < 0 || pipe(xastir_tcp_pipe->to_parent) < 0) {
+ fprintf(stderr,"x_spider: Can't create pipes\n");
+ free(xastir_tcp_pipe); // Free the malloc'd memory.
+ xastir_tcp_pipe = NULL;
+ return(0);
+ }
+
+ xastir_tcp_pipe->authenticated = 1;
+ xastir_tcp_pipe->callsign[0] = '\0';
+
+ if ( (childpid = fork()) < 0) {
+ fprintf(stderr,"Fork_TCP_server: Fork error\n");
+
+ // Close pipes
+ close(xastir_tcp_pipe->to_child[0]);
+ close(xastir_tcp_pipe->to_child[1]);
+ close(xastir_tcp_pipe->to_parent[0]);
+ close(xastir_tcp_pipe->to_parent[1]);
+ free(xastir_tcp_pipe); // Free the malloc'd memory.
+ xastir_tcp_pipe = NULL;
+ return(0);
+ }
+ else if (childpid == 0) {
+ //
+ // Child process
+ //
+
+
+ // Go back to default signal handler instead of calling
+ // restart() on SIGHUP
+ (void) signal(SIGHUP,SIG_DFL);
+
+
+ // Change the name of the new child process. So far this
+ // only works for "ps" listings, not for "top". This code
+ // only works on Linux. For BSD use setproctitle(3), NetBSD
+ // can use setprogname(2).
+#ifdef __linux__
+ init_set_proc_title(argc, argv, envp);
+ set_proc_title("%s", "x-spider TCP daemon (xastir)");
+ //fprintf(stderr,"DEBUG: %s\n", Argv[0]);
+ (void) signal(SIGHUP, exit);
+#endif // __linux__
+
+
+ close(xastir_tcp_pipe->to_child[1]); // Close write end of pipe
+ close(xastir_tcp_pipe->to_parent[0]); // Close read end of pipe
+
+ // Assign the global variables
+ pipe_tcp_server_to_xastir = xastir_tcp_pipe->to_parent[1];
+ pipe_xastir_to_tcp_server = xastir_tcp_pipe->to_child[0];
+
+ // Set read-end of pipe to be non-blocking.
+ //
+ if (fcntl(pipe_xastir_to_tcp_server, F_SETFL, O_NONBLOCK) < 0) {
+ fprintf(stderr,"x_spider: Couldn't set read-end of pipe_xastir_to_tcp_server non-blocking\n");
+ fprintf(stderr,"Could some processes still be running from a previous run of Xastir?\n");
+ }
+
+ // Go into an infinite loop here which restarts the
+ // listening process whenever it dies.
+ //
+// while (1) {
+// fprintf(stderr,"Starting TCP_Server...\n");
+
+ TCP_Server(argc, argv, envp);
+
+// fprintf(stderr,"TCP_Server process died.\n");
+// }
+ }
+ //
+ // Parent process
+ //
+
+ close(xastir_tcp_pipe->to_parent[1]); // Close write end of pipe
+ close(xastir_tcp_pipe->to_child[0]); // Close read end of pipe
+
+ // Assign the global variables so that Xastir itself will know
+ // how to talk to the pipes
+ pipe_tcp_server_to_xastir = xastir_tcp_pipe->to_parent[0];
+ pipe_xastir_to_tcp_server = xastir_tcp_pipe->to_child[1];
+
+ // Set read-end of pipe to be non-blocking.
+ //
+ if (fcntl(pipe_tcp_server_to_xastir, F_SETFL, O_NONBLOCK) < 0) {
+ fprintf(stderr,"x_spider: Couldn't set read-end of pipe_tcp_server_to_xastir non-blocking\n");
+ fprintf(stderr,"Could some processes still be running from a previous run of Xastir?\n");
+ }
+
+// // Set write-end of pipe to be non-blocking.
+// //
+// if (fcntl(pipe_xastir_to_tcp_server, F_SETFL, O_NONBLOCK) < 0) {
+// fprintf(stderr,"x_spider: Couldn't set read-end of pipe_xastir_to_tcp_server non-blocking\n");
+// }
+
+ // We don't need to do anything here except return back to the
+ // calling routine with the PID of the new server process, so
+ // that it can request the server and all it's children to quit
+ // when Xastir quits or segfaults.
+ return(childpid); // Really the parent PID in this case
+}
+#endif // STANDALONE_PROGRAM
+
+
+
+
+
+int Fork_UDP_server(int argc, char *argv[], char *envp[]) {
+ int childpid;
+
+
+ // Allocate a pipe before we fork.
+ //
+ xastir_udp_pipe = (pipe_object *)malloc(sizeof(pipe_object));
+ if (xastir_udp_pipe == NULL) {
+ fprintf(stderr,"x_spider: Couldn't malloc pipe_object\n");
+ return(0);
+ }
+
+ if (pipe(xastir_udp_pipe->to_child) < 0 || pipe(xastir_udp_pipe->to_parent) < 0) {
+ fprintf(stderr,"x_spider: Can't create pipes\n");
+ free(xastir_udp_pipe); // Free the malloc'd memory.
+ xastir_udp_pipe = NULL;
+ return(0);
+ }
+
+ xastir_udp_pipe->authenticated = 1;
+ xastir_udp_pipe->callsign[0] = '\0';
+
+ if ( (childpid = fork()) < 0) {
+ fprintf(stderr,"Fork_UDP_server: Fork error\n");
+
+ // Close pipes
+ close(xastir_udp_pipe->to_child[0]);
+ close(xastir_udp_pipe->to_child[1]);
+ close(xastir_udp_pipe->to_parent[0]);
+ close(xastir_udp_pipe->to_parent[1]);
+ free(xastir_udp_pipe); // Free the malloc'd memory.
+ xastir_udp_pipe = NULL;
+ return(0);
+ }
+ else if (childpid == 0) {
+ //
+ // Child process
+ //
+
+
+ // Go back to default signal handler instead of calling
+ // restart() on SIGHUP
+ (void) signal(SIGHUP,SIG_DFL);
+
+
+ // Change the name of the new child process. So far this
+ // only works for "ps" listings, not for "top". This code
+ // only works on Linux. For BSD use setproctitle(3), NetBSD
+ // can use setprogname(2).
+#ifdef __linux__
+ init_set_proc_title(argc, argv, envp);
+ set_proc_title("%s", "x-spider UDP daemon (xastir)");
+ //fprintf(stderr,"DEBUG: %s\n", Argv[0]);
+ (void) signal(SIGHUP, exit);
+#endif // __linux__
+
+
+ close(xastir_udp_pipe->to_child[1]); // Close write end of pipe
+ close(xastir_udp_pipe->to_parent[0]); // Close read end of pipe
+
+ // Assign the global variables
+ pipe_udp_server_to_xastir = xastir_udp_pipe->to_parent[1];
+ pipe_xastir_to_udp_server = xastir_udp_pipe->to_child[0];
+
+ // Set read-end of pipe to be non-blocking.
+ //
+// if (fcntl(pipe_xastir_to_udp_server, F_SETFL, O_NONBLOCK) < 0) {
+// fprintf(stderr,
+// "x_spider: Couldn't set read-end of pipe_xastir_to_udp_server non-blocking\n");
+// }
+
+ // Go into an infinite loop here which restarts the
+ // listening process whenever it dies.
+ //
+// while (1) {
+// fprintf(stderr,"Starting UDP_Server...\n");
+
+ UDP_Server(argc, argv, envp);
+
+ fprintf(stderr,"UDP_Server process died.\n");
+// }
+ }
+ //
+ // Parent process
+ //
+
+ close(xastir_udp_pipe->to_parent[1]); // Close write end of pipe
+ close(xastir_udp_pipe->to_child[0]); // Close read end of pipe
+
+ // Assign the global variables so that Xastir itself will know
+ // how to talk to the pipes
+ pipe_udp_server_to_xastir = xastir_udp_pipe->to_parent[0];
+ pipe_xastir_to_udp_server = xastir_udp_pipe->to_child[1];
+
+
+ // Set read-end of pipe to be non-blocking.
+ //
+ if (fcntl(pipe_udp_server_to_xastir, F_SETFL, O_NONBLOCK) < 0) {
+ fprintf(stderr,"x_spider: Couldn't set read-end of pipe_udp_server_to_xastir non-blocking\n");
+ fprintf(stderr,"Could some processes still be running from a previous run of Xastir?\n");
+ }
+
+// // Set write-end of pipe to be non-blocking.
+// //
+// if (fcntl(pipe_xastir_to_udp_server, F_SETFL, O_NONBLOCK) < 0) {
+// fprintf(stderr,"x_spider: Couldn't set read-end of pipe_xastir_to_udp_server non-blocking\n");
+// }
+
+
+ // We don't need to do anything here except return back to the
+ // calling routine with the PID of the new server process, so
+ // that it can request the server and all it's children to quit
+ // when Xastir quits or segfaults.
+ return(childpid); // Really the parent PID in this case
+}
+
+
diff --git a/src/x_spider.h b/src/x_spider.h
new file mode 100644
index 0000000..beb9b18
--- /dev/null
+++ b/src/x_spider.h
@@ -0,0 +1,48 @@
+/*
+ * $Id: x_spider.h,v 1.16 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 2003-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifndef __XASTIR_SERVER_H
+#define __XASTIR_SERVER_H
+
+//#include "xastir.h"
+
+
+#define NET_CONNECT_TIMEOUT 20
+#define SERV_TCP_PORT 2023
+#define SERV_UDP_PORT 2023
+
+
+char *pname;
+extern int pipe_xastir_to_tcp_server;
+extern int pipe_tcp_server_to_xastir;
+extern int pipe_xastir_to_udp_server;
+extern int pipe_udp_server_to_xastir;
+
+extern int writen(register int fd, register char *ptr, register int nbytes);
+extern int readline(register int fd, register char *ptr, register int maxlen);
+extern int Fork_TCP_server(int argc, char *argv[], char *envp[]);
+extern int Fork_UDP_server(int argc, char *argv[], char *envp[]);
+
+
+#endif /* XASTIR_SERVER_H */
+
diff --git a/src/xa_config.c b/src/xa_config.c
new file mode 100644
index 0000000..8341d6f
--- /dev/null
+++ b/src/xa_config.c
@@ -0,0 +1,2489 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: xa_config.c,v 1.193 2012/10/22 23:59:55 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <locale.h>
+
+#include <Xm/XmAll.h>
+
+#include "xa_config.h"
+#include "interface.h"
+#include "xastir.h"
+#include "main.h"
+#include "util.h"
+#include "bulletin_gui.h"
+#include "list_gui.h"
+#include "messages.h"
+#include "draw_symbols.h"
+#include "maps.h"
+#include "track_gui.h"
+#include "geo.h"
+#include "snprintf.h"
+#include "objects.h"
+#include "db_gis.h"
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+#define CONFIG_FILE "config/xastir.cnf"
+#define CONFIG_FILE_BAK1 "config/xastir.cnf.1"
+#define CONFIG_FILE_BAK2 "config/xastir.cnf.2"
+#define CONFIG_FILE_BAK3 "config/xastir.cnf.3"
+#define CONFIG_FILE_BAK4 "config/xastir.cnf.4"
+#define CONFIG_FILE_TMP "config/xastir.cnf.tmp"
+
+#define MAX_VALUE 300
+
+//extern char xa_config_dir[];
+
+
+
+void store_string(FILE * fout, char *option, char *value) {
+
+// if (debug_level & 1)
+// fprintf(stderr,"Store String Start\n");
+
+// TODO: Replace with function which doesn't depend on locale.
+// We'd also need to replace any xastir_snprintf() functions
+// throughout.
+ fprintf (fout, "%s:%s\n", option, value);
+
+// if (debug_level & 1)
+// fprintf(stderr,"Store String Stop\n");
+
+}
+
+
+
+
+
+void store_char(FILE * fout, char *option, char value) {
+ char value_o[2];
+
+ value_o[0] = value;
+ value_o[1] = '\0';
+ store_string (fout, option, value_o);
+}
+
+
+
+
+
+void store_int(FILE * fout, char *option, int value) {
+ char value_o[MAX_VALUE];
+
+ xastir_snprintf (value_o, sizeof(value_o), "%d", value);
+ store_string (fout, option, value_o);
+}
+
+
+
+
+
+void store_long (FILE * fout, char *option, long value) {
+ char value_o[MAX_VALUE];
+
+ xastir_snprintf(value_o, sizeof(value_o), "%ld", value);
+ store_string (fout, option, value_o);
+}
+
+
+
+
+
+void store_float (FILE * fout, char *option, float value) {
+ char value_o[MAX_VALUE];
+
+ xastir_snprintf(value_o, sizeof(value_o), "%f", value);
+ store_string (fout, option, value_o);
+}
+
+
+
+
+
+FILE * fin;
+
+void input_close(void)
+{
+ if(fin != NULL)
+ (void)fclose(fin);
+ fin = NULL;
+}
+
+
+
+
+
+/*
+ This function will read the configuration file (xastir.cnf) until it finds
+ the requested option. When the requested option is found it will return
+ the value of that option.
+ The return value of the function will be 1 if the option is found and 0
+ if the option is not found.
+ May return empty string in "value".
+*/
+int get_string(char *option, char *value, int value_size) {
+ char config_file[MAX_VALUE];
+ char config_line[256];
+ short option_found;
+ char *value_array[2];
+
+ option_found = 0;
+
+ if (fin == NULL) {
+
+ get_user_base_dir(CONFIG_FILE, config_file, sizeof(config_file));
+
+ // filecreate() refuses to create a new file if it already
+ // exists.
+ (void)filecreate(config_file);
+ fin = fopen (config_file, "r");
+ }
+
+ if (fin != NULL) {
+ int loop_counter = 0;
+
+ while (!option_found && loop_counter < 2) {
+ // Search to the end of file and then repeat from the
+ // beginning (once) if not found the first time. As
+ // long as we keep the order of saves/restores to/from
+ // the file the same, this will mean exactly one fgets()
+ // per variable sought.
+ if (loop_counter == 1) {
+ // We didn't find it the first time through, try
+ // once more from the start of file.
+ (void)fseek(fin, 0, SEEK_SET);
+ }
+
+ // Read the file line-by-line. fgets() also reads in
+ // the line-end characters so we'll have to remove
+ // those.
+ while (!option_found && (fgets (&config_line[0], 256, fin) != NULL)) {
+
+ // Find the line containing "option"
+ // Here we assume no leading/trailing white space
+ // for value_array[0].
+ split_string(config_line, value_array, 2, ':');
+
+ if (strcmp (value_array[0], option) == 0) {
+ int len;
+
+ // Found the correct line
+ option_found = 1;
+
+ remove_leading_spaces(value_array[1]);
+
+ // Eliminate line-end chars. Do this twice 'cuz
+ // some operating systems add two characters
+ // (\r\n)
+ len = strlen(value_array[1]);
+ if (len > 0) {
+ if ( (value_array[1][len-1] == '\n')
+ || (value_array[1][len-1] == '\r') ) {
+ value_array[1][len-1] = '\0';
+ }
+ }
+ len = strlen(value_array[1]);
+ if (len > 0) {
+ if ( (value_array[1][len-1] == '\n')
+ || (value_array[1][len-1] == '\r') ) {
+ value_array[1][len-1] = '\0';
+ }
+ }
+
+ remove_trailing_spaces(value_array[1]);
+
+ if (value_array[1] == NULL)
+ value = "";
+ else
+ xastir_snprintf(value,
+ value_size,
+ "%s",
+ value_array[1]);
+
+ //fprintf(stderr,"%s = %s\n", value_array[0], value);
+ }
+ } // End of while (fgets)
+ loop_counter++;
+ } // End of while (!option_found)
+ } // End of if
+ else
+ fprintf(stderr,"Couldn't open file: %s\n", config_file);
+
+ return (option_found);
+}
+
+
+
+
+
+int get_char(char *option, char *value) {
+ char value_o[MAX_VALUE];
+ int ret;
+
+ ret = get_string (option, value_o, sizeof(value_o));
+ if (ret)
+ *value = value_o[0];
+
+ return (ret);
+}
+
+
+
+
+
+// Snags an int and checks whether it is within the correct range.
+// If not, it assigns a default value. Returns the value.
+int get_int(char *option, int low, int high, int def) {
+ char value_o[MAX_VALUE];
+ int ret;
+
+ ret = get_string (option, value_o, sizeof(value_o));
+ if (ret && (atoi(value_o) >= low) && (atoi(value_o) <= high) ) {
+ return(atoi (value_o));
+ }
+
+ if (!ret) {
+// fprintf(stderr,"xastir.cnf: %s not found, inserting default: %d\n",
+// option,
+// def);
+ return(def);
+ }
+
+ fprintf(stderr,"xastir.cnf: %s out-of-range: %d, changing to default: %d\n",
+ option,
+ atoi(value_o),
+ def);
+ return(def);
+}
+
+
+
+
+
+// Snags a long and checks whether it is within the correct range.
+// If not, it assigns a default value. Returns the value.
+long get_long(char *option, long low, long high, long def) {
+ char value_o[MAX_VALUE];
+ int ret;
+
+ ret = get_string (option, value_o, sizeof(value_o));
+ if (ret && (atol(value_o) >= low) && (atol(value_o) <= high) ) {
+ return(atol(value_o));
+ }
+
+ if (!ret) {
+// fprintf(stderr,"xastir.cnf: %s not found, inserting default: %ld\n",
+// option,
+// def);
+ return(def);
+ }
+
+ fprintf(stderr,
+ "xastir.cnf: %s out-of-range: %ld, changing to default: %ld\n",
+ option,
+ atol(value_o),
+ def);
+ return(def);
+}
+
+
+
+
+
+// Snags a float value and checks whether it is within the correct
+// range. If not, it assigns a default value. Returns the value.
+float get_float(char *option, float low, float high, float def) {
+ char value_o[MAX_VALUE];
+ int ret;
+
+ ret = get_string (option, value_o, sizeof(value_o));
+ if (ret && (strtof(value_o, NULL) >= low) && (strtof(value_o, NULL) <= high ) ) {
+ return(strtof(value_o, NULL));
+ }
+
+ if (!ret) {
+// fprintf(stderr,"xastir.cnf: %s not found, inserting default: %f\n",
+// option,
+// def);
+ return(def);
+ }
+
+ fprintf(stderr,
+ "xastir.cnf: %s out-of-range: %f, changing to default: %f\n",
+ option,
+ strtof(value_o, NULL),
+ def);
+ return(def);
+}
+
+
+
+
+// Note on get_user_base_dir
+//
+// The original implementation of this function used a static char array
+// to do all the path construction, and returned a pointer to that array.
+//
+// This function was changed in Sept 2012 to remove its original use
+// of a single static char array. That version was highly unsafe in a
+// threaded environment, and was used routinely in multiple threads.
+// Even inserting mutexes to prevent simultaneous writes by multiple threads
+// wasn't good enough, because once the mutex was released there was no
+// guarantee that one thread would not write into the static array while
+// another thread was reading it. The result was that it was sometimes
+// possible for paths to get corrupted, especially if multiple logging
+// options and png snapshots were simultaneously selected.
+//
+// Prior to the change, one called this as:
+// ptr = get_user_base_dir("pathfragment");
+// and ptr was always a pointer to the static char array. Now
+// the caller is responsible for passing in the array into which we'll
+// write. This way, threads should never be clobbering each other's paths
+// returned from this routine.
+//
+char *get_user_base_dir(char *dir, char * base, size_t base_size) {
+ char *env_ptr;
+
+ // fprintf(stderr,"base: %s \nxa_config_dir: %s\n", base, xa_config_dir);
+
+ switch (xa_config_dir[0]) {
+ case '/':
+ //have some path
+ xastir_snprintf(base, base_size, "%s",xa_config_dir);
+ break;
+
+ case '\0' :
+ // build from scratch
+ xastir_snprintf(base,
+ base_size,
+ "%s",
+ ((env_ptr = getenv ("XASTIR_USER_BASE")) != NULL) ? env_ptr : user_dir);
+
+ if (base[strlen (base) - 1] != '/')
+ strncat (base, "/", base_size - 1 - strlen(base));
+
+ strncat (base, ".xastir/", base_size - 1 - strlen(base));
+ break ;
+
+ default:
+ // Unqualified path
+ xastir_snprintf(base, base_size, "%s",
+ ((env_ptr = getenv ("PWD")) != NULL) ? env_ptr : user_dir);
+
+ if (base[strlen (base) - 1] != '/')
+ strncat (base, "/", base_size - 1 - strlen(base));
+
+ strncat (base, xa_config_dir, base_size - 1 - strlen(base));
+ }
+
+ if (base[strlen (base) - 1] != '/')
+ strncat (base, "/", base_size - 1 - strlen(base));
+
+ // Save base so we monkey around less later.
+
+ xastir_snprintf(xa_config_dir,sizeof(xa_config_dir),"%s", base);
+
+ // Append dir and return
+
+ return strncat(base, dir, base_size - 1 - strlen(base));
+
+}
+
+
+
+
+
+char *get_data_base_dir(char *dir) {
+ static char base[MAX_VALUE];
+ char *env_ptr;
+
+ // Snag this variable from the environment if it exists there,
+ // else grab it from the define from the compile command-line
+ // that should look like one of these:
+ //
+ // -DXASTIR_DATA_BASE=\"/opt/Xastir/share/xastir\"
+ // -DXASTIR_DATA_BASE=\"/usr/local/share/xastir\"
+ //
+ xastir_snprintf(base,
+ sizeof(base),
+ "%s",
+ ((env_ptr = getenv ("XASTIR_DATA_BASE")) != NULL) ? env_ptr : XASTIR_DATA_BASE);
+
+ if (base[strlen (base) - 1] != '/')
+ strncat(base, "/", sizeof(base) - 1 - strlen(base));
+
+ strncat(base, dir, sizeof(base) - 1 - strlen(base));
+ return base;
+}
+
+
+
+
+
+// Care should be taken here to make sure that no out-of-range data
+// is saved, as it will mess up Xastir startup from that point on.
+// Also: Config file should be owned by the user, and not by root.
+// If chmod 4755 is done on the executable, then the config file ends
+// up being owned by root from then on.
+//
+// Yea, I could have made this nicer by algorithmically figuring out
+// the backup filenames and rotating among .1 through .9. Perhaps
+// next go-around! Just having multiples is a big win, in case some
+// of them get blown away.
+//
+// Another step that needs to be made is to restore config settings
+// for the cases where Xastir comes up with a nonexistent or empty
+// xastir.cnf file. If the backups exist, we should copy them
+// across.
+//
+void save_data(void) {
+ int i;
+ char name_temp[20];
+ char name[50];
+ FILE * fout;
+ char config_file_tmp[MAX_VALUE];
+ char config_file[MAX_VALUE];
+ char config_file_bak1[MAX_VALUE];
+ char config_file_bak2[MAX_VALUE];
+ char config_file_bak3[MAX_VALUE];
+ char config_file_bak4[MAX_VALUE];
+ struct stat file_status;
+
+
+ // Force the locale to a default so that we don't have
+ // conversion problems due to LANG/LC_ALL/LC_CTYPE/LC_NUMERIC
+ // environment variables.
+ (void)setlocale(LC_NUMERIC, "C");
+ (void)setlocale(LC_CTYPE, "C");
+
+// if (debug_level & 1)
+// fprintf(stderr,"Store String Start\n");
+
+ // The new file we'll create
+ get_user_base_dir(CONFIG_FILE_TMP, config_file_tmp,
+ sizeof(config_file_tmp));
+
+ // Save to the new config file
+ fout = fopen (config_file_tmp, "a");
+ if (fout != NULL) {
+// Position x_return;
+// Position y_return;
+
+
+ if (debug_level & 1)
+ fprintf(stderr,"Save Data Start\n");
+
+ /* language */
+ store_string (fout, "LANGUAGE", lang_to_use);
+
+ /* my data */
+ store_string (fout, "STATION_CALLSIGN", my_callsign);
+
+ store_string (fout, "STATION_LAT", my_lat);
+ store_string (fout, "STATION_LONG", my_long);
+ store_char (fout, "STATION_GROUP", my_group);
+ store_char (fout, "STATION_SYMBOL", my_symbol);
+ store_char (fout, "STATION_MESSAGE_TYPE", aprs_station_message_type);
+ store_string (fout, "STATION_POWER", my_phg);
+ store_string (fout, "STATION_COMMENTS", my_comment);
+ store_int (fout, "MY_TRAIL_DIFF_COLOR", my_trail_diff_color);
+ if (debug_level & 1)
+ fprintf(stderr,"Save Data 1\n");
+
+ /* default values */
+ store_long (fout, "SCREEN_WIDTH", screen_width);
+ store_long (fout, "SCREEN_HEIGHT", screen_height);
+
+
+/*
+ // Get the X/Y offsets for the main window
+ XtVaGetValues(appshell,
+ XmNx, &x_return,
+ XmNy, &y_return,
+ NULL);
+
+fprintf(stderr,"X:%d y:%d\n", (int)x_return, (int)y_return);
+ store_int (fout, "SCREEN_X_OFFSET", (int)x_return);
+ store_int (fout, "SCREEN_Y_OFFSET", (int)y_return);
+*/
+
+
+ store_long (fout, "SCREEN_LAT", center_latitude);
+ store_long (fout, "SCREEN_LONG", center_longitude);
+
+ store_string(fout, "RELAY_DIGIPEAT_CALLS", relay_digipeater_calls);
+
+ store_int (fout, "COORDINATE_SYSTEM", coordinate_system);
+
+ store_int (fout, "STATION_TRANSMIT_AMB", position_amb_chars);
+
+ if (scale_y > 0)
+ store_long (fout, "SCREEN_ZOOM", scale_y);
+ else
+ store_long (fout, "SCREEN_ZOOM", 1);
+
+ store_int (fout, "MAP_BGCOLOR", map_background_color);
+
+ store_int (fout, "MAP_DRAW_FILLED_COLORS", map_color_fill);
+
+#if !defined(NO_GRAPHICS)
+#if defined(HAVE_MAGICK)
+ store_float (fout, "IMAGEMAGICK_GAMMA_ADJUST", imagemagick_gamma_adjust);
+#endif // HAVE_MAGICK
+ store_float(fout, "RASTER_MAP_INTENSITY", raster_map_intensity);
+#endif // NO_GRAPHICS
+
+ store_string(fout, "PRINT_PROGRAM", printer_program);
+ store_string(fout, "PREVIEWER_PROGRAM", previewer_program);
+
+ store_int (fout, "MAP_LETTERSTYLE", letter_style);
+ store_int (fout, "MAP_ICONOUTLINESTYLE", icon_outline_style);
+ store_int (fout, "MAP_WX_ALERT_STYLE", wx_alert_style);
+ store_string(fout, "ALTNET_CALL", altnet_call);
+ store_int(fout, "ALTNET", altnet);
+ store_int(fout, "SKIP_DUPE_CHECK", skip_dupe_checking);
+ store_string (fout, "AUTO_MAP_DIR", AUTO_MAP_DIR);
+ store_string (fout, "ALERT_MAP_DIR", ALERT_MAP_DIR);
+ store_string (fout, "SELECTED_MAP_DIR", SELECTED_MAP_DIR);
+ store_string (fout, "SELECTED_MAP_DATA", SELECTED_MAP_DATA);
+ store_string (fout, "MAP_INDEX_DATA", MAP_INDEX_DATA);
+ store_string (fout, "SYMBOLS_DIR", SYMBOLS_DIR);
+ store_string (fout, "SOUND_DIR", SOUND_DIR);
+ store_string (fout, "GROUP_DATA_FILE", group_data_file);
+ store_string (fout, "GNIS_FILE", locate_gnis_filename);
+ store_string (fout, "GEOCODE_FILE", geocoder_map_filename);
+ store_int (fout, "SHOW_FIND_TARGET", show_destination_mark);
+
+ /* maps */
+ store_int (fout, "MAPS_LONG_LAT_GRID", long_lat_grid);
+ store_int (fout, "MAPS_LABELED_GRID_BORDER", draw_labeled_grid_border);
+ store_int (fout, "MAPS_LEVELS", map_color_levels);
+ store_int (fout, "MAPS_LABELS", map_labels);
+ store_int (fout, "MAP_LOCK_PAN_ZOOM", map_lock_pan_zoom);
+ store_int (fout, "MAPS_AUTO_MAPS", map_auto_maps);
+ store_int (fout, "MAPS_AUTO_MAPS_SKIP_RASTER", auto_maps_skip_raster);
+ store_int (fout, "MAPS_INDEX_ON_STARTUP", index_maps_on_startup);
+
+ store_string (fout, "MAPS_LABEL_FONT_TINY", rotated_label_fontname[FONT_TINY]);
+ store_string (fout, "MAPS_LABEL_FONT_SMALL", rotated_label_fontname[FONT_SMALL]);
+ store_string (fout, "MAPS_LABEL_FONT_MEDIUM", rotated_label_fontname[FONT_MEDIUM]);
+ // NOTE: FONT_DEFAULT points to FONT_MEDIUM.
+ store_string (fout, "MAPS_LABEL_FONT_LARGE", rotated_label_fontname[FONT_LARGE]);
+ store_string (fout, "MAPS_LABEL_FONT_HUGE", rotated_label_fontname[FONT_HUGE]);
+ store_string (fout, "MAPS_LABEL_FONT_BORDER", rotated_label_fontname[FONT_BORDER]);
+ store_string (fout, "SYSTEM_FIXED_FONT", rotated_label_fontname[FONT_SYSTEM]);
+ store_string (fout, "STATION_FONT", rotated_label_fontname[FONT_STATION]);
+ store_string (fout, "ATV_ID_FONT", rotated_label_fontname[FONT_ATV_ID]);
+
+
+//N0VH
+#if defined(HAVE_MAGICK)
+ store_int (fout, "NET_MAP_TIMEOUT", net_map_timeout);
+ store_int (fout, "TIGERMAP_SHOW_GRID", tiger_show_grid);
+ store_int (fout, "TIGERMAP_SHOW_COUNTIES", tiger_show_counties);
+ store_int (fout, "TIGERMAP_SHOW_CITIES", tiger_show_cities);
+ store_int (fout, "TIGERMAP_SHOW_PLACES", tiger_show_places);
+ store_int (fout, "TIGERMAP_SHOW_MAJROADS", tiger_show_majroads);
+ store_int (fout, "TIGERMAP_SHOW_STREETS", tiger_show_streets);
+ store_int (fout, "TIGERMAP_SHOW_RAILROAD", tiger_show_railroad);
+ store_int (fout, "TIGERMAP_SHOW_STATES", tiger_show_states);
+ store_int (fout, "TIGERMAP_SHOW_INTERSTATE", tiger_show_interstate);
+ store_int (fout, "TIGERMAP_SHOW_USHWY", tiger_show_ushwy);
+ store_int (fout, "TIGERMAP_SHOW_STATEHWY", tiger_show_statehwy);
+ store_int (fout, "TIGERMAP_SHOW_WATER", tiger_show_water);
+ store_int (fout, "TIGERMAP_SHOW_LAKES", tiger_show_lakes);
+ store_int (fout, "TIGERMAP_SHOW_MISC", tiger_show_misc);
+#endif //HAVE_MAGICK
+
+#ifdef HAVE_LIBGEOTIFF
+ store_int (fout, "DRG_XOR_COLORS", DRG_XOR_colors);
+ store_int (fout, "DRG_SHOW_COLORS_0", DRG_show_colors[0]);
+ store_int (fout, "DRG_SHOW_COLORS_1", DRG_show_colors[1]);
+ store_int (fout, "DRG_SHOW_COLORS_2", DRG_show_colors[2]);
+ store_int (fout, "DRG_SHOW_COLORS_3", DRG_show_colors[3]);
+ store_int (fout, "DRG_SHOW_COLORS_4", DRG_show_colors[4]);
+ store_int (fout, "DRG_SHOW_COLORS_5", DRG_show_colors[5]);
+ store_int (fout, "DRG_SHOW_COLORS_6", DRG_show_colors[6]);
+ store_int (fout, "DRG_SHOW_COLORS_7", DRG_show_colors[7]);
+ store_int (fout, "DRG_SHOW_COLORS_8", DRG_show_colors[8]);
+ store_int (fout, "DRG_SHOW_COLORS_9", DRG_show_colors[9]);
+ store_int (fout, "DRG_SHOW_COLORS_10", DRG_show_colors[10]);
+ store_int (fout, "DRG_SHOW_COLORS_11", DRG_show_colors[11]);
+ store_int (fout, "DRG_SHOW_COLORS_12", DRG_show_colors[12]);
+#endif // HAVE_LIBGEOTIFF
+
+ // filter values
+ // NOT SAVED: Select_.none
+ store_int (fout, "DISPLAY_MY_STATION", Select_.mine);
+ store_int (fout, "DISPLAY_TNC_STATIONS", Select_.tnc);
+ store_int (fout, "DISPLAY_TNC_DIRECT_STATIONS", Select_.direct);
+ store_int (fout, "DISPLAY_TNC_VIADIGI_STATIONS", Select_.via_digi);
+ store_int (fout, "DISPLAY_NET_STATIONS", Select_.net);
+ store_int (fout, "DISPLAY_TACTICAL_STATIONS", Select_.tactical);
+ store_int (fout, "DISPLAY_OLD_STATION_DATA", Select_.old_data);
+ store_int (fout, "DISPLAY_STATIONS", Select_.stations);
+ store_int (fout, "DISPLAY_FIXED_STATIONS", Select_.fixed_stations);
+ store_int (fout, "DISPLAY_MOVING_STATIONS", Select_.moving_stations);
+ store_int (fout, "DISPLAY_WEATHER_STATIONS", Select_.weather_stations);
+ store_int (fout, "DISPLAY_CWOP_WX_STATIONS", Select_.CWOP_wx_stations);
+ store_int (fout, "DISPLAY_OBJECTS", Select_.objects);
+ store_int (fout, "DISPLAY_STATION_WX_OBJ", Select_.weather_objects);
+ store_int (fout, "DISPLAY_WATER_GAGE_OBJ", Select_.gauge_objects);
+ store_int (fout, "DISPLAY_OTHER_OBJECTS", Select_.other_objects);
+
+ // display values
+ store_int (fout, "DISPLAY_CALLSIGN", Display_.callsign);
+ store_int (fout, "DISPLAY_LABEL_ALL_TRACKPOINTS", Display_.label_all_trackpoints);
+ store_int (fout, "DISPLAY_SYMBOL", Display_.symbol);
+ store_int (fout, "DISPLAY_SYMBOL_ROTATE", Display_.symbol_rotate);
+ store_int (fout, "DISPLAY_STATION_PHG", Display_.phg);
+ store_int (fout, "DISPLAY_DEFAULT_PHG", Display_.default_phg);
+ store_int (fout, "DISPLAY_MOBILES_PHG", Display_.phg_of_moving);
+ store_int (fout, "DISPLAY_ALTITUDE", Display_.altitude);
+ store_int (fout, "DISPLAY_COURSE", Display_.course);
+ store_int (fout, "DISPLAY_SPEED", Display_.speed);
+ store_int (fout, "DISPLAY_SPEED_SHORT", Display_.speed_short);
+ store_int (fout, "DISPLAY_DIST_COURSE", Display_.dist_bearing);
+ store_int (fout, "DISPLAY_WEATHER", Display_.weather);
+ store_int (fout, "DISPLAY_STATION_WX", Display_.weather_text);
+ store_int (fout, "DISPLAY_TEMP_ONLY", Display_.temperature_only);
+ store_int (fout, "DISPLAY_WIND_BARB", Display_.wind_barb);
+ store_int (fout, "DISPLAY_STATION_TRAILS", Display_.trail);
+ store_int (fout, "DISPLAY_LAST_HEARD", Display_.last_heard);
+ store_int (fout, "DISPLAY_POSITION_AMB", Display_.ambiguity);
+ store_int (fout, "DISPLAY_DF_INFO", Display_.df_data);
+ store_int (fout, "DISPLAY_DF_BEAMWIDTH_INFO", Display_.df_beamwidth_data);
+ store_int (fout, "DISPLAY_DF_BEARING_INFO", Display_.df_bearing_data);
+ store_int (fout, "DISPLAY_DEAD_RECKONING_INFO", Display_.dr_data);
+ store_int (fout, "DISPLAY_DEAD_RECKONING_ARC", Display_.dr_arc);
+ store_int (fout, "DISPLAY_DEAD_RECKONING_COURSE", Display_.dr_course);
+ store_int (fout, "DISPLAY_DEAD_RECKONING_SYMBOL", Display_.dr_symbol);
+
+
+ store_int (fout, "DISPLAY_UNITS_ENGLISH", english_units);
+ store_int (fout, "DISPLAY_DIST_BEAR_STATUS", do_dbstatus);
+
+
+ // CAD Objects
+ store_int (fout, "DISPLAY_CAD_OBJECT_LABEL", CAD_show_label);
+ store_int (fout, "DISPLAY_CAD_OBJECT_PROBABILITY", CAD_show_raw_probability);
+ store_int (fout, "DISPLAY_CAD_OBJECT_COMMENT", CAD_show_comment);
+ store_int (fout, "DISPLAY_CAD_OBJECT_AREA", CAD_show_area);
+
+
+ // Interface values
+ store_int (fout, "DISABLE_TRANSMIT", transmit_disable);
+ store_int (fout, "DISABLE_POSIT_TX", posit_tx_disable);
+ store_int (fout, "DISABLE_OBJECT_TX", object_tx_disable);
+ store_int (fout, "ENABLE_SERVER_PORT", enable_server_port);
+
+
+ for (i = 0; i < MAX_IFACE_DEVICES; i++) {
+ xastir_snprintf (name_temp, sizeof(name_temp), "DEVICE%0d_", i);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TYPE", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].device_type);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "NAME", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].device_name);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "RADIO_PORT", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].radio_port);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "CONVERSE_CMD", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].device_converse_string);
+
+
+#ifdef HAVE_DB
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "DATABASE_TYPE", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].database_type);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "DATABASE_SCHEMA_TYPE", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].database_schema_type);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "DATABASE_USERNAME", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].database_username);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "DATABASE_SCHEMA", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].database_schema);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "DATABASE_UNIX_SOCKET", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].database_unix_socket);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "QUERY_ON_STARTUP", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].query_on_startup);
+
+#endif /* HAVE_DB */
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "INTERFACE_COMMENT", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].comment);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "HOST", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].device_host_name);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "PASSWD", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].device_host_pswd);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "FILTER_PARAMS", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].device_host_filter_string);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "UNPROTO1", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].unproto1);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "UNPROTO2", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].unproto2);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "UNPROTO3", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].unproto3);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "UNPROTO_IGATE", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].unproto_igate);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_UP_FILE", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].tnc_up_file);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_DOWN_FILE", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].tnc_down_file);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_TXDELAY", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].txdelay);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_PERSISTENCE", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].persistence);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_SLOTTIME", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].slottime);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_TXTAIL", sizeof(name) - 1 - strlen(name));
+ store_string (fout, name, devices[i].txtail);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_FULLDUPLEX", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].fullduplex);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_INIT_KISSMODE", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].init_kiss);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "SPEED", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].sp);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "STYLE", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].style);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "IGATE_OPTION", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].igate_options);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TXMT", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].transmit_data);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "RELAY_DIGIPEAT", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].relay_digipeat);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "RECONN", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].reconnect);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "ONSTARTUP", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].connect_on_startup);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat(name, "GPSRETR", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].gps_retrieve);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "SETTIME", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].set_time);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNCEXTRADELAY", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, devices[i].tnc_extra_delay);
+
+ }
+ /* TNC */
+ store_int (fout, "TNC_LOG_DATA", log_tnc_data);
+ store_string (fout, "LOGFILE_TNC", LOGFILE_TNC);
+
+ /* NET */
+ store_int (fout, "NET_LOG_DATA", log_net_data);
+
+ store_int (fout, "NET_RUN_AS_IGATE", operate_as_an_igate);
+ store_int (fout, "NETWORK_WAITTIME", NETWORK_WAITTIME);
+
+ // LOGGING
+ store_int (fout, "LOG_IGATE", log_igate);
+ store_int (fout, "LOG_WX", log_wx);
+ store_int (fout, "LOG_MESSAGE", log_message_data);
+ store_int (fout, "LOG_WX_ALERT", log_wx_alert_data);
+ store_string (fout, "LOGFILE_IGATE", LOGFILE_IGATE);
+ store_string (fout, "LOGFILE_NET", LOGFILE_NET);
+ store_string (fout, "LOGFILE_WX", LOGFILE_WX);
+ store_string (fout, "LOGFILE_MESSAGE", LOGFILE_MESSAGE);
+ store_string (fout, "LOGFILE_WX_ALERT", LOGFILE_WX_ALERT);
+
+ // SNAPSHOTS
+ store_int (fout, "SNAPSHOTS_ENABLED", snapshots_enabled);
+
+ // KML SNAPSHOTS
+ store_int (fout, "KMLSNAPSHOTS_ENABLED", kmlsnapshots_enabled);
+
+ /* WX ALERTS */
+ store_long (fout, "WX_ALERTS_REFRESH_TIME", (long)WX_ALERTS_REFRESH_TIME);
+
+ /* GPS */
+ store_long (fout, "GPS_TIME", (long)gps_time); /* still needed */
+
+ /* POSIT RATE */
+ store_long (fout, "POSIT_RATE", (long)POSIT_rate);
+
+ /* OBJECT RATE */
+ store_long (fout, "OBJECT_RATE", (long)OBJECT_rate);
+
+ /* UPDATE DR RATE */
+ store_long (fout, "UPDATE_DR_RATE", (long)update_DR_rate);
+
+ /* station broadcast type */
+ store_int (fout, "BST_TYPE", output_station_type);
+
+#ifdef TRANSMIT_RAW_WX
+ store_int (fout, "BST_WX_RAW", transmit_raw_wx);
+#endif // TRANSMIT_RAW_WX
+
+ store_int (fout, "BST_COMPRESSED_POSIT", transmit_compressed_posit);
+
+ store_int (fout, "COMPRESSED_OBJECTS_ITEMS", transmit_compressed_objects_items);
+
+ store_int (fout, "SMART_BEACONING", smart_beaconing);
+ store_int (fout, "SB_TURN_MIN", sb_turn_min);
+ store_int (fout, "SB_TURN_SLOPE", sb_turn_slope);
+ store_int (fout, "SB_TURN_TIME", sb_turn_time);
+ store_int (fout, "SB_POSIT_FAST", sb_posit_fast);
+ store_int (fout, "SB_POSIT_SLOW", sb_posit_slow);
+ store_int (fout, "SB_LOW_SPEED_LIMIT", sb_low_speed_limit);
+ store_int (fout, "SB_HIGH_SPEED_LIMIT", sb_high_speed_limit);
+
+ store_int (fout, "POP_UP_NEW_BULLETINS", pop_up_new_bulletins);
+ store_int (fout, "VIEW_ZERO_DISTANCE_BULLETINS", view_zero_distance_bulletins);
+
+ store_int (fout, "WARN_ABOUT_MOUSE_MODIFIERS", warn_about_mouse_modifiers);
+
+ /* -dk7in- variable beacon interval */
+ /* mobile: max 2 min */
+ /* fixed: max 15 min */
+ if ((output_station_type >= 1) && (output_station_type <= 3))
+ max_transmit_time = (time_t)120l; /* 2 min @ mobile */
+ else
+ max_transmit_time = (time_t)900l; /* 15 min @ fixed */
+
+ /* Audio Alarms */
+ store_string (fout, "SOUND_COMMAND", sound_command);
+
+ store_int (fout, "SOUND_PLAY_ONS", sound_play_new_station);
+ store_string (fout, "SOUND_ONS_FILE", sound_new_station);
+ store_int (fout, "SOUND_PLAY_ONM", sound_play_new_message);
+ store_string (fout, "SOUND_ONM_FILE", sound_new_message);
+
+ store_int (fout, "SOUND_PLAY_PROX", sound_play_prox_message);
+ store_string (fout, "SOUND_PROX_FILE", sound_prox_message);
+ store_string (fout, "PROX_MIN", prox_min);
+ store_string (fout, "PROX_MAX", prox_max);
+ store_int (fout, "SOUND_PLAY_BAND", sound_play_band_open_message);
+ store_string (fout, "SOUND_BAND_FILE", sound_band_open_message);
+ store_string (fout, "BANDO_MIN", bando_min);
+ store_string (fout, "BANDO_MAX", bando_max);
+ store_int (fout, "SOUND_PLAY_WX_ALERT", sound_play_wx_alert_message);
+ store_string (fout, "SOUND_WX_ALERT_FILE", sound_wx_alert_message);
+
+#ifdef HAVE_FESTIVAL
+ /* Festival speech settings */
+ store_int (fout, "SPEAK_NEW_STATION",festival_speak_new_station);
+ store_int (fout, "SPEAK_PROXIMITY_ALERT",festival_speak_proximity_alert);
+ store_int (fout, "SPEAK_TRACKED_ALERT",festival_speak_tracked_proximity_alert);
+ store_int (fout, "SPEAK_BAND_OPENING",festival_speak_band_opening);
+ store_int (fout, "SPEAK_MESSAGE_ALERT",festival_speak_new_message_alert);
+ store_int (fout, "SPEAK_MESSAGE_BODY",festival_speak_new_message_body);
+ store_int (fout, "SPEAK_WEATHER_ALERT",festival_speak_new_weather_alert);
+ store_int (fout, "SPEAK_ID",festival_speak_ID);
+#endif // HAVE_FESTIVAL
+ store_int (fout, "ATV_SCREEN_ID", ATV_screen_ID);
+
+ /* defaults */
+ store_long (fout, "DEFAULT_STATION_OLD", (long)sec_old);
+
+ store_long (fout, "DEFAULT_STATION_CLEAR", (long)sec_clear);
+ store_long(fout, "DEFAULT_STATION_REMOVE", (long)sec_remove);
+ store_string (fout, "HELP_DATA", HELP_FILE);
+
+ store_string (fout, "MESSAGE_COUNTER", message_counter);
+
+ store_string (fout, "AUTO_MSG_REPLY", auto_reply_message);
+ store_int (fout, "DISPLAY_PACKET_TYPE", Display_packet_data_type);
+
+ store_int (fout, "BULLETIN_RANGE", bulletin_range);
+ store_int(fout,"VIEW_MESSAGE_RANGE",vm_range);
+ store_int(fout,"VIEW_MESSAGE_LIMIT",view_message_limit);
+ store_int(fout,"PREDEF_MENU_LOAD",predefined_menu_from_file);
+ store_string(fout,"PREDEF_MENU_FILE",predefined_object_definition_filename);
+
+ store_int(fout, "READ_MESSAGES_PACKET_DATA_TYPE", Read_messages_packet_data_type);
+ store_int(fout, "READ_MESSAGES_MINE_ONLY", Read_messages_mine_only);
+
+ /* printer variables */
+ store_int (fout, "PRINT_ROTATED", print_rotated);
+ store_int (fout, "PRINT_AUTO_ROTATION", print_auto_rotation);
+ store_int (fout, "PRINT_AUTO_SCALE", print_auto_scale);
+ store_int (fout, "PRINT_IN_MONOCHROME", print_in_monochrome);
+ store_int (fout, "PRINT_INVERT_COLORS", print_invert);
+
+ /* Rain Gauge Type, set in the Serial Weather interface
+ properties dialog, but really a global default */
+ store_int (fout, "RAIN_GAUGE_TYPE", WX_rain_gauge_type);
+
+
+ /* list attributes */
+ for (i = 0; i < LST_NUM; i++) {
+ xastir_snprintf (name_temp, sizeof(name_temp), "LIST%0d_", i);
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "H", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, list_size_h[i]);
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "W", sizeof(name) - 1 - strlen(name));
+ store_int (fout, name, list_size_w[i]);
+ }
+
+ store_int (fout, "TRACK_ME", track_me);
+ store_string (fout, "TRACKING_STATION_CALLSIGN", tracking_station_call);
+ store_int (fout, "MAP_CHOOSER_EXPAND_DIRS", map_chooser_expand_dirs);
+ store_int (fout, "ST_DIRECT_TIMEOUT", st_direct_timeout);
+ store_int (fout, "DEAD_RECKONING_TIMEOUT", dead_reckoning_timeout);
+ store_int (fout, "SERIAL_CHAR_PACING", serial_char_pacing);
+ store_int (fout, "TRAIL_SEGMENT_TIME", trail_segment_time);
+ store_int (fout, "TRAIL_SEGMENT_DISTANCE", trail_segment_distance);
+ store_int (fout, "RINO_DOWNLOAD_INTERVAL", RINO_download_interval);
+ store_int (fout, "SNAPSHOT_INTERVAL", snapshot_interval);
+
+
+ if (debug_level & 1)
+ fprintf(stderr,"Save Data Stop\n");
+
+ // Close the config_file_tmp file, we're done writing it.
+ (void)fclose (fout);
+
+
+ get_user_base_dir(CONFIG_FILE, config_file, sizeof(config_file));
+
+ get_user_base_dir(CONFIG_FILE_BAK1, config_file_bak1,
+ sizeof(config_file_bak1));
+
+ get_user_base_dir(CONFIG_FILE_BAK2, config_file_bak2,
+ sizeof(config_file_bak2));
+
+ get_user_base_dir(CONFIG_FILE_BAK3, config_file_bak3,
+ sizeof(config_file_bak3));
+
+ get_user_base_dir(CONFIG_FILE_BAK4,config_file_bak4,
+ sizeof(config_file_bak4));
+
+
+ //
+ // Rename the old config files so that we have a few
+ // backups in case of corruption:
+ //
+ // xastir.cnf.3 -> xastir.cnf.4
+ // xastir.cnf.2 -> xastir.cnf.3
+ // xastir.cnf.1 -> xastir.cnf.2
+ // xastir.cnf -> xastir.cnf.1
+ // xastir.cnf.tmp -> xastir.cnf
+ //
+
+ // Rename bak3 to bak4
+ // NOTE: bak3 won't exist until a few saves have happened.
+ //
+ // Check whether bak3 exists
+ if (stat(config_file_bak3, &file_status) == 0) {
+ if (!S_ISREG(file_status.st_mode)) {
+ fprintf(stderr,
+ "Couldn't stat %s, cancelling save_data()\n",
+ config_file_bak3);
+ return;
+ }
+ if ( rename (config_file_bak3, config_file_bak4) ) {
+ fprintf(stderr,
+ "Couldn't rename %s to %s, cancelling save_data()\n",
+ config_file_bak3,
+ config_file_bak4);
+
+ // Attempt to restore to previous state
+ // Nothing to do here!
+ return;
+ }
+ }
+
+ // Rename bak2 to bak3
+ // NOTE: bak2 won't exist until a few saves have happened.
+ //
+ // Check whether bak2 exists
+ if (stat(config_file_bak2, &file_status) == 0) {
+ if (!S_ISREG(file_status.st_mode)) {
+ fprintf(stderr,
+ "Couldn't stat %s, cancelling save_data()\n",
+ config_file_bak2);
+ return;
+ }
+ if ( rename (config_file_bak2, config_file_bak3) ) {
+ fprintf(stderr,
+ "Couldn't rename %s to %s, cancelling save_data()\n",
+ config_file_bak2,
+ config_file_bak3);
+
+ // Attempt to restore to previous state
+ rename (config_file_bak4, config_file_bak3);
+ // Nothing to do here!
+ return;
+ }
+ }
+
+ // Rename bak1 to bak2
+ // NOTE: bak1 won't exist until a couple of saves have happened.
+ //
+ // Check whether bak1 exists
+ if (stat(config_file_bak1, &file_status) == 0) {
+ if (!S_ISREG(file_status.st_mode)) {
+ fprintf(stderr,
+ "Couldn't stat %s, cancelling save_data()\n",
+ config_file_bak1);
+ return;
+ }
+ if ( rename (config_file_bak1, config_file_bak2) ) {
+ fprintf(stderr,
+ "Couldn't rename %s to %s, cancelling save_data()\n",
+ config_file_bak1,
+ config_file_bak2);
+
+ // Attempt to restore to previous state
+ rename (config_file_bak3, config_file_bak2);
+ rename (config_file_bak4, config_file_bak3);
+ return;
+ }
+ }
+
+// NOTE: To minimize the possibility that we'll end up with a
+// missing or corrupt config file, we actually should COPY
+// config_file to config_file_bak1 here so that there's always a
+// config file in place no matter what. In the next block we can do
+// the rename of config_file_tmp to config_file and not miss a beat.
+// See "man 2 rename".
+
+ // Rename config to bak1
+ // NOTE: config won't exist until the first save happens.
+ //
+ // Check whether config exists
+ if (stat(config_file, &file_status) == 0) {
+ if (!S_ISREG(file_status.st_mode)) {
+ fprintf(stderr,
+ "Couldn't stat %s, cancelling save_data()\n",
+ config_file);
+ return;
+ }
+ //
+ // Note "copy_file()" instead of "rename()". This
+ // assures that we always have a config file in place no
+ // matter what errors might occur.
+ //
+ if ( copy_file(config_file, config_file_bak1) ) {
+ fprintf(stderr,
+ "Couldn't copy %s to %s, cancelling save_data()\n",
+ config_file,
+ config_file_bak1);
+
+ // Attempt to restore to previous state
+ rename (config_file_bak2, config_file_bak1);
+ rename (config_file_bak3, config_file_bak2);
+ rename (config_file_bak4, config_file_bak3);
+ return;
+ }
+ }
+
+ // Rename config.tmp to xastir.cnf
+ // NOTE: config won't exist until the first save happens.
+ //
+ // Check whether config.tmp exists
+ if (stat(config_file_tmp, &file_status) == 0) {
+ if (!S_ISREG(file_status.st_mode)) {
+ fprintf(stderr,
+ "Couldn't stat %s, cancelling save_data()\n",
+ config_file_tmp);
+ return;
+ }
+ if ( rename (config_file_tmp, config_file) ) {
+ fprintf(stderr,
+ "Couldn't rename %s to %s, cancelling save_data()\n",
+ config_file_tmp,
+ config_file);
+
+ // Attempt to restore to previous state
+ rename (config_file_bak1, config_file);
+ rename (config_file_bak2, config_file_bak1);
+ rename (config_file_bak3, config_file_bak2);
+ rename (config_file_bak4, config_file_bak3);
+ return;
+ }
+ }
+ } else {
+ // Couldn't create new config (out of filespace?).
+ fprintf(stderr,"Couldn't open config file for appending: %s\n", config_file);
+
+ // Back out the changes done to the config and backup files.
+ //
+ // Continue using original config file.
+ if ( rename (config_file_bak1, config_file) ) {
+ // Problem here, couldn't rename bak1 file to xastir.cnf
+ fprintf(stderr,
+ "Couldn't recover %s from %s file\n",
+ config_file,
+ config_file_bak1);
+ return;
+ }
+ }
+}
+
+
+
+
+
+void load_data_or_default(void) {
+ int i;
+ char name_temp[20];
+ char name[50];
+ long temp;
+ char user_base_dir[MAX_VALUE];
+
+ // Force the locale to a default so that we don't have
+ // conversion problems due to LANG/LC_ALL/LC_CTYPE/LC_NUMERIC
+ // environment variables.
+ (void)setlocale(LC_NUMERIC, "C");
+ (void)setlocale(LC_CTYPE, "C");
+
+ /* language */
+ if (!get_string ("LANGUAGE", lang_to_use, sizeof(lang_to_use))
+ || lang_to_use[0] == '\0') {
+ xastir_snprintf(lang_to_use,
+ sizeof(lang_to_use),
+ "English");
+ }
+
+ /* my data */
+ if (!get_string ("STATION_CALLSIGN", my_callsign, sizeof(my_callsign))
+ || my_callsign[0] == '\0') {
+ xastir_snprintf(my_callsign,
+ sizeof(my_callsign),
+ "NOCALL");
+ }
+
+ if (!get_string ("STATION_LAT", my_lat, sizeof(my_lat))
+ || my_lat[0] == '\0') {
+ xastir_snprintf(my_lat,
+ sizeof(my_lat),
+ "0000.000N");
+ }
+ if ( (my_lat[4] != '.')
+ || (my_lat[8] != 'N' && my_lat[8] != 'S') ) {
+ xastir_snprintf(my_lat,
+ sizeof(my_lat),
+ "0000.000N");
+ fprintf(stderr,"Invalid Latitude, changing it to 0000.000N\n");
+ }
+ // convert old data to high prec
+ temp = convert_lat_s2l (my_lat);
+ convert_lat_l2s (temp, my_lat, sizeof(my_lat), CONVERT_HP_NOSP);
+
+
+ if (!get_string ("STATION_LONG", my_long, sizeof(my_long))
+ || my_long[0] == '\0') {
+ xastir_snprintf(my_long,
+ sizeof(my_long),
+ "00000.000W");
+ }
+ if ( (my_long[5] != '.')
+ || (my_long[9] != 'W' && my_long[9] != 'E') ) {
+ xastir_snprintf(my_long,
+ sizeof(my_long),
+ "00000.000W");
+ fprintf(stderr,"Invalid Longitude, changing it to 00000.000W\n");
+ }
+ // convert old data to high prec
+ temp = convert_lon_s2l (my_long);
+ convert_lon_l2s (temp, my_long, sizeof(my_long), CONVERT_HP_NOSP);
+
+
+ position_amb_chars = get_int ("STATION_TRANSMIT_AMB", 0, 4, 0);
+
+ if (!get_char ("STATION_GROUP", &my_group))
+ my_group = '/';
+
+ if (!get_char ("STATION_SYMBOL", &my_symbol))
+ my_symbol = 'x';
+
+ if (!get_char ("STATION_MESSAGE_TYPE", &aprs_station_message_type))
+ aprs_station_message_type = '=';
+
+ // Empty string is ok here.
+ if (!get_string ("STATION_POWER", my_phg, sizeof(my_phg)))
+ my_phg[0] = '\0';
+
+ if (!get_string ("STATION_COMMENTS", my_comment, sizeof(my_comment))
+ || my_comment[0] == '\0') {
+ xastir_snprintf (my_comment, sizeof(my_comment), "XASTIR-%s", XASTIR_SYSTEM);
+ }
+ /* replacing defined MY_TRAIL_DIFF_COLOR from db.c, default 0 matches
+ default value of MY_TRAIL_DIFF_COLOR to show all mycall-ssids in
+ the same color. */
+ my_trail_diff_color = get_int ("MY_TRAIL_DIFF_COLOR", 0, 1, 0);
+
+ /* default values */
+ screen_width = get_long ("SCREEN_WIDTH", 61l, 10000l, 590l);
+ screen_height = get_long ("SCREEN_HEIGHT", 1l, 10000l, 420l);
+
+// screen_x_offset = (Position)get_int ("SCREEN_X_OFFSET", 0, 10000, 0);
+// screen_y_offset = (Position)get_int ("SCREEN_Y_OFFSET", 0, 10000, 0);
+
+
+ center_latitude = get_long ("SCREEN_LAT", 0l, 64800000l, 32400000l);
+ center_longitude = get_long ("SCREEN_LONG", 0l, 129600000l, 64800000l);
+
+ // Empty string is ok here
+ if (!get_string("RELAY_DIGIPEAT_CALLS", relay_digipeater_calls, sizeof(relay_digipeater_calls)))
+ xastir_snprintf (relay_digipeater_calls, sizeof(relay_digipeater_calls), "WIDE1-1");
+ // Make them all upper-case.
+ (void)to_upper(relay_digipeater_calls);
+ // And take out all spaces
+ (void)remove_all_spaces(relay_digipeater_calls);
+
+ coordinate_system = get_int ("COORDINATE_SYSTEM", 0, 5, USE_DDMMMM);
+
+ scale_y = get_long ("SCREEN_ZOOM", 1l, 500000l, 327680l);
+
+ scale_x = get_x_scale(center_longitude,center_latitude,scale_y);
+
+ map_background_color = get_int ("MAP_BGCOLOR", 0, 11, 0);
+
+ map_color_fill = get_int ( "MAP_DRAW_FILLED_COLORS", 0, 1, 1);
+
+#if !defined(NO_GRAPHICS)
+#if defined(HAVE_MAGICK)
+ imagemagick_gamma_adjust = get_float("IMAGEMAGICK_GAMMA_ADJUST", 0.0, 1.0, 0.0);
+#endif // HAVE_MAGICK
+ raster_map_intensity = get_float("RASTER_MAP_INTENSITY", 0.0, 1.0, 1.0);
+#endif // NO_GRAPHICS
+
+ if (!get_string ("PRINT_PROGRAM", printer_program, sizeof(printer_program))
+ || printer_program[0] == '\0') {
+ xastir_snprintf(printer_program,
+ sizeof(printer_program),
+ "%s",
+#ifdef LPR_PATH
+ // Path to LPR if defined
+ LPR_PATH
+#else // LPR_PATH
+ // Empty path
+ ""
+#endif // LPR_PATH
+ );
+ }
+ if (!get_string ("PREVIEWER_PROGRAM", previewer_program, sizeof(previewer_program))
+ || previewer_program[0] == '\0') {
+ xastir_snprintf(previewer_program,
+ sizeof(previewer_program),
+ "%s",
+#ifdef GV_PATH
+ // Path to GV if defined
+ GV_PATH
+#else // GV_PATH
+ // Empty path
+ ""
+#endif // GV_PATH
+ );
+ }
+
+ letter_style = get_int ("MAP_LETTERSTYLE", 0, 2, 1);
+
+ icon_outline_style = get_int ("MAP_ICONOUTLINESTYLE", 0, 3, 0);
+
+ wx_alert_style = get_int ("MAP_WX_ALERT_STYLE", 0, 1, 0);
+
+ // Empty string is ok here
+ if (!get_string("ALTNET_CALL", altnet_call, sizeof(altnet_call)))
+ xastir_snprintf(altnet_call,
+ sizeof(altnet_call),
+ "XASTIR");
+
+ altnet = get_int("ALTNET", 0, 1, 0);
+
+ skip_dupe_checking = get_int("SKIP_DUPE_CHECK", 0, 1, 0);
+
+ if (!get_string ("AUTO_MAP_DIR", AUTO_MAP_DIR, sizeof(AUTO_MAP_DIR))
+ || AUTO_MAP_DIR[0] == '\0') {
+ xastir_snprintf(AUTO_MAP_DIR,
+ sizeof(AUTO_MAP_DIR),
+ "%s",
+ get_data_base_dir ("maps"));
+ }
+
+ if (!get_string ("ALERT_MAP_DIR", ALERT_MAP_DIR, sizeof(ALERT_MAP_DIR))
+ || ALERT_MAP_DIR[0] == '\0') {
+ xastir_snprintf(ALERT_MAP_DIR,
+ sizeof(ALERT_MAP_DIR),
+ "%s",
+ get_data_base_dir ("Counties"));
+ }
+
+ if (!get_string ("SELECTED_MAP_DIR", SELECTED_MAP_DIR, sizeof(SELECTED_MAP_DIR))
+ || SELECTED_MAP_DIR[0] == '\0') {
+ xastir_snprintf(SELECTED_MAP_DIR,
+ sizeof(SELECTED_MAP_DIR),
+ "%s",
+ get_data_base_dir ("maps"));
+ }
+
+ if (!get_string ("SELECTED_MAP_DATA", SELECTED_MAP_DATA, sizeof(SELECTED_MAP_DATA))
+ || SELECTED_MAP_DATA[0] == '\0') {
+ xastir_snprintf(SELECTED_MAP_DATA,
+ sizeof(SELECTED_MAP_DATA),
+ "%s",
+ "config/selected_maps.sys");
+ }
+
+ // get the base path for the user base directory, so we can use it over
+ // and over without having to call get_user_base_dir a godzillion times.
+ get_user_base_dir("",user_base_dir, sizeof(user_base_dir));
+
+ // Check for old complete path, change to new short path if a
+ // match
+ if (strncmp( user_base_dir, SELECTED_MAP_DATA, strlen(user_base_dir)) == 0)
+ xastir_snprintf(SELECTED_MAP_DATA,
+ sizeof(SELECTED_MAP_DATA),
+ "%s",
+ "config/selected_maps.sys");
+
+ if (!get_string ("MAP_INDEX_DATA", MAP_INDEX_DATA, sizeof(MAP_INDEX_DATA))
+ || MAP_INDEX_DATA[0] == '\0') {
+ xastir_snprintf(MAP_INDEX_DATA,
+ sizeof(MAP_INDEX_DATA),
+ "%s",
+ "config/map_index.sys");
+ }
+ // Check for old complete path, change to new short path if a
+ // match
+ if (strncmp( user_base_dir, MAP_INDEX_DATA, strlen(user_base_dir)) == 0)
+ xastir_snprintf(MAP_INDEX_DATA,
+ sizeof(MAP_INDEX_DATA),
+ "%s",
+ "config/map_index.sys");
+
+ if (!get_string ("SYMBOLS_DIR", SYMBOLS_DIR, sizeof(SYMBOLS_DIR))
+ || SYMBOLS_DIR[0] == '\0') {
+ xastir_snprintf(SYMBOLS_DIR,
+ sizeof(SYMBOLS_DIR),
+ "%s",
+ get_data_base_dir ("symbols"));
+ }
+
+ if (!get_string ("SOUND_DIR", SOUND_DIR, sizeof(SOUND_DIR))
+ || SOUND_DIR[0] == '\0') {
+ xastir_snprintf(SOUND_DIR,
+ sizeof(SOUND_DIR),
+ "%s",
+ get_data_base_dir ("sounds"));
+ }
+
+ if (!get_string ("GROUP_DATA_FILE", group_data_file, sizeof(group_data_file))
+ || group_data_file[0] == '\0') {
+ xastir_snprintf(group_data_file,
+ sizeof(group_data_file),
+ "%s",
+ "config/groups");
+ }
+ // Check for old complete path, change to new short path if a
+ // match
+ if (strncmp( user_base_dir, group_data_file, strlen(user_base_dir)) == 0)
+ xastir_snprintf(group_data_file,
+ sizeof(group_data_file),
+ "%s",
+ "config/groups");
+
+ if (!get_string ("GNIS_FILE", locate_gnis_filename, sizeof(locate_gnis_filename))
+ || locate_gnis_filename[0] == '\0') {
+ xastir_snprintf(locate_gnis_filename,
+ sizeof(locate_gnis_filename),
+ "%s",
+ get_data_base_dir ("GNIS/WA.gnis"));
+ }
+
+ if (!get_string ("GEOCODE_FILE", geocoder_map_filename, sizeof(geocoder_map_filename))
+ || geocoder_map_filename[0] == '\0') {
+ xastir_snprintf(geocoder_map_filename,
+ sizeof(geocoder_map_filename),
+ "%s",
+ get_data_base_dir ("GNIS/geocode"));
+ }
+
+ show_destination_mark = get_int ("SHOW_FIND_TARGET", 0, 1, 1);
+
+ /* maps */
+ long_lat_grid = get_int ("MAPS_LONG_LAT_GRID", 0, 1, 1);
+
+ draw_labeled_grid_border = get_int ("MAPS_LABELED_GRID_BORDER", 0, 1, 0);
+
+ map_color_levels = get_int ("MAPS_LEVELS", 0, 1, 1);
+
+ map_labels = get_int ("MAPS_LABELS", 0, 1, 1);
+
+ map_lock_pan_zoom = get_int ("MAP_LOCK_PAN_ZOOM", 0, 1, 0);
+
+ map_auto_maps = get_int ("MAPS_AUTO_MAPS", 0, 1, 0);
+
+ auto_maps_skip_raster = get_int ("MAPS_AUTO_MAPS_SKIP_RASTER", 0, 1, 0);
+
+ index_maps_on_startup = get_int ("MAPS_INDEX_ON_STARTUP", 0, 1, 1);
+
+ if (!get_string ("MAPS_LABEL_FONT_TINY", rotated_label_fontname[FONT_TINY], sizeof(rotated_label_fontname[FONT_TINY]))
+ || rotated_label_fontname[FONT_TINY][0] == '\0') {
+ xastir_snprintf(rotated_label_fontname[FONT_TINY],
+ sizeof(rotated_label_fontname[FONT_TINY]),
+ "-adobe-helvetica-medium-r-normal--8-*-*-*-*-*-iso8859-1");
+ }
+
+ if (!get_string ("MAPS_LABEL_FONT_SMALL", rotated_label_fontname[FONT_SMALL], sizeof(rotated_label_fontname[FONT_SMALL]))
+ || rotated_label_fontname[FONT_SMALL][0] == '\0') {
+ xastir_snprintf(rotated_label_fontname[FONT_SMALL],
+ sizeof(rotated_label_fontname[FONT_SMALL]),
+ "-adobe-helvetica-medium-r-normal--10-*-*-*-*-*-iso8859-1");
+ }
+
+ if (!get_string ("MAPS_LABEL_FONT_MEDIUM", rotated_label_fontname[FONT_MEDIUM], sizeof(rotated_label_fontname[FONT_MEDIUM]))
+ || rotated_label_fontname[FONT_MEDIUM][0] == '\0') {
+ xastir_snprintf(rotated_label_fontname[FONT_MEDIUM],
+ sizeof(rotated_label_fontname[FONT_MEDIUM]),
+ "-adobe-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1");
+ }
+ // NOTE: FONT_DEFAULT points to FONT_MEDIUM
+
+ if (!get_string ("MAPS_LABEL_FONT_LARGE", rotated_label_fontname[FONT_LARGE], sizeof(rotated_label_fontname[FONT_LARGE]))
+ || rotated_label_fontname[FONT_LARGE][0] == '\0') {
+ xastir_snprintf(rotated_label_fontname[FONT_LARGE],
+ sizeof(rotated_label_fontname[FONT_LARGE]),
+ "-adobe-helvetica-medium-r-normal--14-*-*-*-*-*-iso8859-1");
+ }
+
+ if (!get_string ("MAPS_LABEL_FONT_HUGE", rotated_label_fontname[FONT_HUGE], sizeof(rotated_label_fontname[FONT_HUGE]))
+ || rotated_label_fontname[FONT_HUGE][0] == '\0') {
+ xastir_snprintf(rotated_label_fontname[FONT_HUGE],
+ sizeof(rotated_label_fontname[FONT_HUGE]),
+ "-adobe-helvetica-medium-r-normal--24-*-*-*-*-*-iso8859-1");
+ }
+
+ if (!get_string ("MAPS_LABEL_FONT_BORDER", rotated_label_fontname[FONT_BORDER], sizeof(rotated_label_fontname[FONT_BORDER]))
+ || rotated_label_fontname[FONT_BORDER][0] == '\0') {
+ xastir_snprintf(rotated_label_fontname[FONT_BORDER],
+ sizeof(rotated_label_fontname[FONT_BORDER]),
+ "-adobe-helvetica-medium-r-normal--14-*-*-*-*-*-iso8859-1");
+ }
+
+ if (!get_string ("SYSTEM_FIXED_FONT", rotated_label_fontname[FONT_SYSTEM], sizeof(rotated_label_fontname[FONT_SYSTEM]))
+ || rotated_label_fontname[FONT_SYSTEM][0] == '\0') {
+ xastir_snprintf(rotated_label_fontname[FONT_SYSTEM],
+ sizeof(rotated_label_fontname[FONT_SYSTEM]),
+ "fixed");
+ // NOTE: This same default font is hard-coded into
+ // main.c, to be used for the case when the user enters
+ // an invalid font (so the program won't crash).
+ }
+
+ if (!get_string ("STATION_FONT", rotated_label_fontname[FONT_STATION], sizeof(rotated_label_fontname[FONT_STATION]))
+ || rotated_label_fontname[FONT_STATION][0] == '\0') {
+ xastir_snprintf(rotated_label_fontname[FONT_STATION],
+ sizeof(rotated_label_fontname[FONT_STATION]),
+ "fixed");
+ // NOTE: This same default font is hard-coded into
+ // main.c, to be used for the case when the user enters
+ // an invalid font (so the program won't crash).
+ }
+
+ if (!get_string ("ATV_ID_FONT", rotated_label_fontname[FONT_ATV_ID], sizeof(rotated_label_fontname[FONT_ATV_ID]))
+ || rotated_label_fontname[FONT_ATV_ID][0] == '\0') {
+ xastir_snprintf(rotated_label_fontname[FONT_ATV_ID],
+ sizeof(rotated_label_fontname[FONT_ATV_ID]),
+ "-*-helvetica-*-*-*-*-*-240-*-*-*-*-*-*");
+ }
+
+
+//N0VH
+#if defined(HAVE_MAGICK)
+ net_map_timeout = get_int ("NET_MAP_TIMEOUT", 10, 300, 120);
+
+ tiger_show_grid = get_int ("TIGERMAP_SHOW_GRID", 0, 1, 0);
+ tiger_show_counties = get_int ("TIGERMAP_SHOW_COUNTIES", 0, 1, 1);
+ tiger_show_cities = get_int ("TIGERMAP_SHOW_CITIES", 0, 1, 1);
+ tiger_show_places = get_int ("TIGERMAP_SHOW_PLACES", 0, 1, 1);
+ tiger_show_majroads = get_int ("TIGERMAP_SHOW_MAJROADS", 0, 1, 1);
+ tiger_show_streets = get_int ("TIGERMAP_SHOW_STREETS", 0, 1, 0);
+ tiger_show_railroad = get_int ("TIGERMAP_SHOW_RAILROAD", 0, 1, 1);
+ tiger_show_states = get_int ("TIGERMAP_SHOW_STATES", 0, 1, 0);
+ tiger_show_interstate = get_int ("TIGERMAP_SHOW_INTERSTATE", 0, 1, 1);
+ tiger_show_ushwy = get_int ("TIGERMAP_SHOW_USHWY", 0, 1, 1);
+ tiger_show_statehwy = get_int ("TIGERMAP_SHOW_STATEHWY", 0, 1, 1);
+ tiger_show_water = get_int ("TIGERMAP_SHOW_WATER", 0, 1, 1);
+ tiger_show_lakes = get_int ("TIGERMAP_SHOW_LAKES", 0, 1, 1);
+ tiger_show_misc = get_int ("TIGERMAP_SHOW_MISC", 0, 1, 1);
+#endif //HAVE_MAGICK
+
+#ifdef HAVE_LIBGEOTIFF
+ DRG_XOR_colors = get_int ("DRG_XOR_COLORS", 0, 1, 0);
+ DRG_show_colors[0] = get_int ("DRG_SHOW_COLORS_0", 0, 1, 1);
+ DRG_show_colors[1] = get_int ("DRG_SHOW_COLORS_1", 0, 1, 1);
+ DRG_show_colors[2] = get_int ("DRG_SHOW_COLORS_2", 0, 1, 1);
+ DRG_show_colors[3] = get_int ("DRG_SHOW_COLORS_3", 0, 1, 1);
+ DRG_show_colors[4] = get_int ("DRG_SHOW_COLORS_4", 0, 1, 1);
+ DRG_show_colors[5] = get_int ("DRG_SHOW_COLORS_5", 0, 1, 1);
+ DRG_show_colors[6] = get_int ("DRG_SHOW_COLORS_6", 0, 1, 1);
+ DRG_show_colors[7] = get_int ("DRG_SHOW_COLORS_7", 0, 1, 1);
+ DRG_show_colors[8] = get_int ("DRG_SHOW_COLORS_8", 0, 1, 1);
+ DRG_show_colors[9] = get_int ("DRG_SHOW_COLORS_9", 0, 1, 1);
+ DRG_show_colors[10] = get_int ("DRG_SHOW_COLORS_10", 0, 1, 1);
+ DRG_show_colors[11] = get_int ("DRG_SHOW_COLORS_11", 0, 1, 1);
+ DRG_show_colors[12] = get_int ("DRG_SHOW_COLORS_12", 0, 1, 1);
+#endif // HAVE_LIBGEOTIFF
+
+ // filter values
+ // NOT SAVED: Select_.none
+ Select_.mine = get_int ("DISPLAY_MY_STATION", 0, 1, 1);
+ Select_.tnc = get_int ("DISPLAY_TNC_STATIONS", 0, 1, 1);
+ Select_.direct = get_int ("DISPLAY_TNC_DIRECT_STATIONS", 0, 1, 1);
+ Select_.via_digi = get_int ("DISPLAY_TNC_VIADIGI_STATIONS", 0, 1, 1);
+ Select_.net = get_int ("DISPLAY_NET_STATIONS", 0, 1, 1);
+ Select_.tactical = get_int ("DISPLAY_TACTICAL_STATIONS", 0, 1, 0);
+ Select_.old_data = get_int ("DISPLAY_OLD_STATION_DATA", 0, 1, 0);
+ Select_.stations = get_int ("DISPLAY_STATIONS", 0, 1, 1);
+ Select_.fixed_stations = get_int ("DISPLAY_FIXED_STATIONS", 0, 1, 1);
+ Select_.moving_stations = get_int ("DISPLAY_MOVING_STATIONS", 0, 1, 1);
+ Select_.weather_stations = get_int ("DISPLAY_WEATHER_STATIONS", 0, 1, 1);
+ Select_.CWOP_wx_stations = get_int ("DISPLAY_CWOP_WX_STATIONS", 0, 1, 1);
+ Select_.objects = get_int ("DISPLAY_OBJECTS", 0, 1, 1);
+ Select_.weather_objects = get_int ("DISPLAY_STATION_WX_OBJ", 0, 1, 1);
+ Select_.gauge_objects = get_int ("DISPLAY_WATER_GAGE_OBJ", 0, 1, 1);
+ Select_.other_objects = get_int ("DISPLAY_OTHER_OBJECTS", 0, 1, 1);
+
+ // display values
+ Display_.callsign = get_int ("DISPLAY_CALLSIGN", 0, 1, 1);
+ Display_.label_all_trackpoints = get_int ("DISPLAY_LABEL_ALL_TRACKPOINTS", 0, 1, 0);
+ Display_.symbol = get_int ("DISPLAY_SYMBOL", 0, 1, 1);
+ Display_.symbol_rotate = get_int ("DISPLAY_SYMBOL_ROTATE", 0, 1, 1);
+ Display_.phg = get_int ("DISPLAY_STATION_PHG", 0, 1, 0);
+ Display_.default_phg = get_int ("DISPLAY_DEFAULT_PHG", 0, 1, 0);
+ Display_.phg_of_moving = get_int ("DISPLAY_MOBILES_PHG", 0, 1, 0);
+ Display_.altitude = get_int ("DISPLAY_ALTITUDE", 0, 1, 0);
+ Display_.course = get_int ("DISPLAY_COURSE", 0, 1, 0);
+ Display_.speed = get_int ("DISPLAY_SPEED", 0, 1, 1);
+ Display_.speed_short = get_int ("DISPLAY_SPEED_SHORT", 0, 1, 0);
+ Display_.dist_bearing = get_int ("DISPLAY_DIST_COURSE", 0, 1, 0);
+ Display_.weather = get_int ("DISPLAY_WEATHER", 0, 1, 1);
+ Display_.weather_text = get_int ("DISPLAY_STATION_WX", 0, 1, 1);
+ Display_.temperature_only = get_int ("DISPLAY_TEMP_ONLY", 0, 1, 0);
+ Display_.wind_barb = get_int ("DISPLAY_WIND_BARB", 0, 1, 1);
+ Display_.trail = get_int ("DISPLAY_STATION_TRAILS", 0, 1, 1);
+ Display_.last_heard = get_int ("DISPLAY_LAST_HEARD", 0, 1, 0);
+ Display_.ambiguity = get_int ("DISPLAY_POSITION_AMB", 0, 1, 1);
+ Display_.df_data = get_int ("DISPLAY_DF_INFO", 0, 1, 1);
+ Display_.df_beamwidth_data = get_int ("DISPLAY_DF_BEAMWIDTH_INFO", 0, 1, 1);
+ Display_.df_bearing_data = get_int ("DISPLAY_DF_BEARING_INFO", 0, 1, 0);
+ Display_.dr_data = get_int ("DISPLAY_DEAD_RECKONING_INFO", 0, 1, 1);
+ Display_.dr_arc = get_int ("DISPLAY_DEAD_RECKONING_ARC", 0, 1, 1);
+ Display_.dr_course = get_int ("DISPLAY_DEAD_RECKONING_COURSE", 0, 1, 1);
+ Display_.dr_symbol = get_int ("DISPLAY_DEAD_RECKONING_SYMBOL", 0, 1, 1);
+
+
+
+ english_units = get_int ("DISPLAY_UNITS_ENGLISH", 0, 1, 0);
+ do_dbstatus = get_int ("DISPLAY_DIST_BEAR_STATUS", 0, 1, 0);
+
+
+ CAD_show_label = get_int ("DISPLAY_CAD_OBJECT_LABEL", 0, 1, 1);
+ CAD_show_raw_probability = get_int ("DISPLAY_CAD_OBJECT_PROBABILITY", 0, 1, 1 );
+ CAD_show_comment = get_int ("DISPLAY_CAD_OBJECT_COMMENT", 0, 1, 1 );
+ CAD_show_area = get_int ("DISPLAY_CAD_OBJECT_AREA", 0, 1, 1 );
+
+
+ transmit_disable = get_int ("DISABLE_TRANSMIT", 0, 1, 0);
+ posit_tx_disable = get_int ("DISABLE_POSIT_TX", 0, 1, 0);
+ object_tx_disable = get_int ("DISABLE_OBJECT_TX", 0, 1, 0);
+ enable_server_port = get_int ("ENABLE_SERVER_PORT", 0, 1, 0);
+
+
+ for (i = 0; i < MAX_IFACE_DEVICES; i++) {
+ xastir_snprintf (name_temp, sizeof(name_temp), "DEVICE%0d_", i);
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TYPE", sizeof(name) - 1 - strlen(name));
+ devices[i].device_type = get_int (name, 0,MAX_IFACE_DEVICE_TYPES,DEVICE_NONE);
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "NAME", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].device_name, sizeof(devices[i].device_name)))
+ devices[i].device_name[0] = '\0';
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "RADIO_PORT", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].radio_port, sizeof(devices[i].radio_port)))
+ xastir_snprintf(devices[i].radio_port,
+ sizeof(devices[i].radio_port),
+ "0");
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "CONVERSE_CMD", sizeof(name) - 1 - strlen(name));
+ if (!get_string (name, devices[i].device_converse_string, sizeof(devices[i].device_converse_string))
+ || (strlen(devices[i].device_converse_string) == 0))
+ xastir_snprintf(devices[i].device_converse_string,
+ sizeof(devices[i].device_converse_string),
+ "k");
+
+
+#ifdef HAVE_DB
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "DATABASE_TYPE", sizeof(name) - 1 - strlen(name));
+
+ devices[i].database_type = get_int (name, 0,MAX_DB_TYPE,MAX_DB_TYPE);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "DATABASE_SCHEMA_TYPE", sizeof(name) - 1 - strlen(name));
+ devices[i].database_schema_type = get_int (name, 0,MAX_XASTIR_SCHEMA,XASTIR_SCHEMA_SIMPLE);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "DATABASE_USERNAME", sizeof(name) - 1 - strlen(name));
+ // default to xastir
+ if (!get_string (name, devices[i].database_username, sizeof(devices[i].database_username)))
+ xastir_snprintf(devices[i].database_username,
+ sizeof(devices[i].database_username),
+ "xastir");
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "DATABASE_SCHEMA", sizeof(name) - 1 - strlen(name));
+ // default to xastir
+ if (!get_string (name, devices[i].database_schema, sizeof(devices[i].database_schema)))
+ xastir_snprintf(devices[i].database_schema,
+ sizeof(devices[i].database_schema),
+ "xastir");
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "DATABASE_UNIX_SOCKET", sizeof(name) - 1 - strlen(name));
+ // empty string is ok here
+ if (!get_string (name, devices[i].database_unix_socket, sizeof(devices[i].database_unix_socket)))
+ xastir_snprintf(devices[i].database_unix_socket,
+ sizeof(devices[i].database_unix_socket),
+ "0");
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "QUERY_ON_STARTUP", sizeof(name) - 1 - strlen(name));
+ devices[i].query_on_startup = get_int (name, 0,1,0);
+
+#endif /* HAVE_DB */
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "INTERFACE_COMMENT", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].comment, sizeof(devices[i].comment)))
+ devices[i].comment[0] = '\0';
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "HOST", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].device_host_name, sizeof(devices[i].device_host_name)))
+ devices[i].device_host_name[0] = '\0';
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "PASSWD", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].device_host_pswd, sizeof(devices[i].device_host_pswd)))
+ devices[i].device_host_pswd[0] = '\0';
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "FILTER_PARAMS", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].device_host_filter_string, sizeof(devices[i].device_host_filter_string)))
+ devices[i].device_host_filter_string[0] = '\0';
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "UNPROTO1", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].unproto1, sizeof(devices[i].unproto1)))
+ devices[i].unproto1[0] = '\0';
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "UNPROTO2", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].unproto2, sizeof(devices[i].unproto2)))
+ devices[i].unproto2[0] = '\0';
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "UNPROTO3", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].unproto3, sizeof(devices[i].unproto3)))
+ devices[i].unproto3[0] = '\0';
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "UNPROTO_IGATE", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].unproto_igate, sizeof(devices[i].unproto_igate))
+ || devices[i].unproto_igate[0] == '\0') {
+ xastir_snprintf(devices[i].unproto_igate, sizeof(devices[i].unproto_igate), "WIDE2-1");
+ }
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_UP_FILE", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].tnc_up_file, sizeof(devices[i].tnc_up_file)))
+ devices[i].tnc_up_file[0] = '\0';
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_DOWN_FILE", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].tnc_down_file, sizeof(devices[i].tnc_down_file)))
+ devices[i].tnc_down_file[0] = '\0';
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_TXDELAY", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].txdelay, sizeof(devices[i].txdelay)))
+ xastir_snprintf(devices[i].txdelay,
+ sizeof(devices[i].txdelay),
+ "40");
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_PERSISTENCE", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].persistence, sizeof(devices[i].persistence)))
+ xastir_snprintf(devices[i].persistence,
+ sizeof(devices[i].persistence),
+ "63");
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_SLOTTIME", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].slottime, sizeof(devices[i].slottime)))
+ xastir_snprintf(devices[i].slottime,
+ sizeof(devices[i].slottime),
+ "10");
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_TXTAIL", sizeof(name) - 1 - strlen(name));
+ // Empty string is ok here.
+ if (!get_string (name, devices[i].txtail, sizeof(devices[i].txtail)))
+ xastir_snprintf(devices[i].txtail,
+ sizeof(devices[i].txtail),
+ "30");
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_FULLDUPLEX", sizeof(name) - 1 - strlen(name));
+ devices[i].fullduplex = get_int (name, 0, 1, 0);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNC_INIT_KISSMODE", sizeof(name) - 1 - strlen(name));
+ devices[i].init_kiss = get_int (name, 0, 1, 0);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "SPEED", sizeof(name) - 1 - strlen(name));
+ devices[i].sp = get_int (name, 0,230400,0);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "STYLE", sizeof(name) - 1 - strlen(name));
+ devices[i].style = get_int (name, 0,2,0);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "IGATE_OPTION", sizeof(name) - 1 - strlen(name));
+ devices[i].igate_options = get_int (name, 0,2,0);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TXMT", sizeof(name) - 1 - strlen(name));
+ devices[i].transmit_data = get_int (name, 0,1,0);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "RELAY_DIGIPEAT", sizeof(name) - 1 - strlen(name));
+ devices[i].relay_digipeat = get_int (name, 0,1,1);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "RECONN", sizeof(name) - 1 - strlen(name));
+ devices[i].reconnect = get_int (name, 0,1,0);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "ONSTARTUP", sizeof(name) - 1 - strlen(name));
+ devices[i].connect_on_startup = get_int (name, 0,1,0);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "GPSRETR", sizeof(name) - 1 - strlen(name));
+ devices[i].gps_retrieve = get_int (name, 0,255,DEFAULT_GPS_RETR);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "SETTIME", sizeof(name) - 1 - strlen(name));
+ devices[i].set_time = get_int (name, 0,1,0);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "TNCEXTRADELAY", sizeof(name) - 1 - strlen(name));
+ devices[i].tnc_extra_delay = get_int (name, 0,9999999,0);
+ }
+
+ /* TNC */
+ log_tnc_data = get_int ("TNC_LOG_DATA", 0,1,0);
+
+ if (!get_string ("LOGFILE_TNC", LOGFILE_TNC, sizeof(LOGFILE_TNC))
+ || LOGFILE_TNC[0] == '\0') {
+ xastir_snprintf(LOGFILE_TNC,
+ sizeof(LOGFILE_TNC),
+ "%s",
+ "logs/tnc.log");
+ }
+ // Check for old complete path, change to new short path if a
+ // match
+ if (strncmp( user_base_dir, LOGFILE_TNC, strlen(user_base_dir)) == 0)
+ xastir_snprintf(LOGFILE_TNC,
+ sizeof(LOGFILE_TNC),
+ "%s",
+ "logs/tnc.log");
+
+ /* NET */
+ log_net_data = get_int ("NET_LOG_DATA", 0,1,0);
+
+ operate_as_an_igate = get_int ("NET_RUN_AS_IGATE", 0,2,0);
+
+ log_igate = get_int ("LOG_IGATE", 0,1,0);
+
+ NETWORK_WAITTIME = get_int ("NETWORK_WAITTIME", 10,120,10);
+
+ // LOGGING
+ log_wx = get_int ("LOG_WX", 0,1,0);
+ log_message_data = get_int ("LOG_MESSAGE", 0, 1, 0);
+ log_wx_alert_data = get_int ("LOG_WX_ALERT", 0, 1, 0);
+
+ if (!get_string ("LOGFILE_IGATE", LOGFILE_IGATE, sizeof(LOGFILE_IGATE))
+ || LOGFILE_IGATE[0] == '\0') {
+ xastir_snprintf(LOGFILE_IGATE,
+ sizeof(LOGFILE_IGATE),
+ "%s",
+ "logs/igate.log");
+ }
+ // Check for old complete path, change to new short path if a
+ // match
+ if (strncmp( user_base_dir, LOGFILE_IGATE, strlen(user_base_dir)) == 0)
+ xastir_snprintf(LOGFILE_IGATE,
+ sizeof(LOGFILE_IGATE),
+ "%s",
+ "logs/igate.log");
+
+ if (!get_string ("LOGFILE_NET", LOGFILE_NET, sizeof(LOGFILE_NET))
+ || LOGFILE_NET[0] == '\0') {
+ xastir_snprintf(LOGFILE_NET,
+ sizeof(LOGFILE_NET),
+ "%s",
+ "logs/net.log");
+ }
+ // Check for old complete path, change to new short path if a
+ // match
+ if (strncmp( user_base_dir, LOGFILE_NET, strlen(user_base_dir)) == 0)
+ xastir_snprintf(LOGFILE_NET,
+ sizeof(LOGFILE_NET),
+ "%s",
+ "logs/net.log");
+
+ if (!get_string ("LOGFILE_WX", LOGFILE_WX, sizeof(LOGFILE_WX))
+ || LOGFILE_WX[0] == '\0') {
+ xastir_snprintf(LOGFILE_WX,
+ sizeof(LOGFILE_WX),
+ "%s",
+ "logs/wx.log");
+ }
+ // Check for old complete path, change to new short path if a
+ // match
+ if (strncmp( user_base_dir, LOGFILE_WX, strlen(user_base_dir)) == 0)
+ xastir_snprintf(LOGFILE_WX,
+ sizeof(LOGFILE_WX),
+ "%s",
+ "logs/wx.log");
+
+ if (!get_string ("LOGFILE_MESSAGE", LOGFILE_MESSAGE, sizeof(LOGFILE_MESSAGE))
+ || LOGFILE_MESSAGE[0] == '\0') {
+ xastir_snprintf(LOGFILE_MESSAGE,
+ sizeof(LOGFILE_MESSAGE),
+ "%s",
+ "logs/message.log");
+ }
+ // Check for old complete path, change to new short path if a
+ // match
+ if (strncmp( user_base_dir, LOGFILE_MESSAGE, strlen(user_base_dir)) == 0)
+ xastir_snprintf(LOGFILE_MESSAGE,
+ sizeof(LOGFILE_MESSAGE),
+ "%s",
+ "logs/message.log");
+
+ if (!get_string ("LOGFILE_WX_ALERT", LOGFILE_WX_ALERT, sizeof(LOGFILE_WX_ALERT))
+ || LOGFILE_WX_ALERT[0] == '\0') {
+ xastir_snprintf(LOGFILE_WX_ALERT,
+ sizeof(LOGFILE_WX_ALERT),
+ "%s",
+ "logs/wx_alert.log");
+ }
+ // Check for old complete path, change to new short path if a
+ // match
+ if (strncmp( user_base_dir, LOGFILE_WX_ALERT, strlen(user_base_dir)) == 0)
+ xastir_snprintf(LOGFILE_WX_ALERT,
+ sizeof(LOGFILE_WX_ALERT),
+ "%s",
+ "logs/wx_alert.log");
+
+ // SNAPSHOTS
+ snapshots_enabled = get_int ("SNAPSHOTS_ENABLED", 0,1,0);
+
+ // KML SNAPSHOTS
+ kmlsnapshots_enabled = get_int ("KMLSNAPSHOTS_ENABLED", 0,1,0);
+
+ /* WX ALERTS */
+ WX_ALERTS_REFRESH_TIME = (time_t) get_long ("WX_ALERTS_REFRESH_TIME", 10l, 86400l, 60l);
+
+ /* gps */
+ gps_time = (time_t) get_long ("GPS_TIME", 1l, 86400l, 60l);
+
+ /* POSIT RATE */
+ POSIT_rate = (time_t) get_long ("POSIT_RATE", 0l, 86400l, 30*60l);
+
+ /* OBJECT RATE */
+ OBJECT_rate = (time_t) get_long ("OBJECT_RATE", 1l, 86400l, 30*60l);
+
+ /* UPDATE DR RATE */
+ update_DR_rate = (time_t) get_long ("UPDATE_DR_RATE", 1l, 86400l, 30l);
+
+ /* station broadcast type */
+ output_station_type = get_int ("BST_TYPE", 0,5,0);
+
+#ifdef TRANSMIT_RAW_WX
+ /* raw wx transmit */
+ transmit_raw_wx = get_int ("BST_WX_RAW", 0,1,0);
+#endif // TRANSMIT_RAW_WX
+
+ /* compressed posit transmit */
+ transmit_compressed_posit = get_int ("BST_COMPRESSED_POSIT", 0,1,0);
+
+ /* compressed objects/items transmit */
+ transmit_compressed_objects_items = get_int ("COMPRESSED_OBJECTS_ITEMS", 0,1,0);
+
+ smart_beaconing = get_int ("SMART_BEACONING", 0,1,1);
+ sb_turn_min = get_int ("SB_TURN_MIN", 1,360,20);
+ sb_turn_slope = get_int ("SB_TURN_SLOPE", 0,360,25);
+ sb_turn_time = get_int ("SB_TURN_TIME", 0,3600,5);
+ sb_posit_fast = get_int ("SB_POSIT_FAST", 1,1440,60);
+ sb_posit_slow = get_int ("SB_POSIT_SLOW", 1,1440,30);
+ sb_low_speed_limit = get_int ("SB_LOW_SPEED_LIMIT", 0,999,2);
+ sb_high_speed_limit = get_int ("SB_HIGH_SPEED_LIMIT", 0,999,60);
+
+ pop_up_new_bulletins = get_int ("POP_UP_NEW_BULLETINS", 0,1,1);
+ view_zero_distance_bulletins = get_int ("VIEW_ZERO_DISTANCE_BULLETINS", 0,1,1);
+
+ warn_about_mouse_modifiers = get_int ("WARN_ABOUT_MOUSE_MODIFIERS", 0,1,1);
+
+
+ /* Audio Alarms*/
+ // Empty string is ok here.
+ if (!get_string ("SOUND_COMMAND", sound_command, sizeof(sound_command)))
+ xastir_snprintf(sound_command,
+ sizeof(sound_command),
+ "play");
+
+ sound_play_new_station = get_int ("SOUND_PLAY_ONS", 0,1,0);
+
+ if (!get_string ("SOUND_ONS_FILE", sound_new_station, sizeof(sound_new_station))
+ || sound_new_station[0] == '\0') {
+ xastir_snprintf(sound_new_station,
+ sizeof(sound_new_station),
+ "newstation.wav");
+ }
+
+ sound_play_new_message = get_int ("SOUND_PLAY_ONM", 0,1,0);
+
+ if (!get_string ("SOUND_ONM_FILE", sound_new_message, sizeof(sound_new_message))
+ || sound_new_message[0] == '\0') {
+ xastir_snprintf(sound_new_message,
+ sizeof(sound_new_message),
+ "newmessage.wav");
+ }
+
+ sound_play_prox_message = get_int ("SOUND_PLAY_PROX", 0,1,0);
+
+ if (!get_string ("SOUND_PROX_FILE", sound_prox_message, sizeof(sound_prox_message))
+ || sound_prox_message[0] == '\0') {
+ xastir_snprintf(sound_prox_message,
+ sizeof(sound_prox_message),
+ "proxwarn.wav");
+ }
+
+ if (!get_string ("PROX_MIN", prox_min, sizeof(prox_min))
+ || prox_min[0] == '\0') {
+ xastir_snprintf(prox_min,
+ sizeof(prox_min),
+ "0.01");
+ }
+
+ if (!get_string ("PROX_MAX", prox_max, sizeof(prox_max))
+ || prox_max[0] == '\0') {
+ xastir_snprintf(prox_max,
+ sizeof(prox_max),
+ "10");
+ }
+
+ sound_play_band_open_message = get_int ("SOUND_PLAY_BAND", 0,1,0);
+
+ if (!get_string ("SOUND_BAND_FILE", sound_band_open_message, sizeof(sound_band_open_message))
+ || sound_band_open_message[0] == '\0') {
+ xastir_snprintf(sound_band_open_message,
+ sizeof(sound_band_open_message),
+ "bandopen.wav");
+ }
+
+ if (!get_string ("BANDO_MIN", bando_min, sizeof(bando_min))
+ || bando_min[0] == '\0') {
+ xastir_snprintf(bando_min,
+ sizeof(bando_min),
+ "200");
+ }
+
+ if (!get_string ("BANDO_MAX", bando_max, sizeof(bando_max))
+ || bando_max[0] == '\0') {
+ xastir_snprintf(bando_max,
+ sizeof(bando_max),
+ "2000");
+ }
+
+ sound_play_wx_alert_message = get_int ("SOUND_PLAY_WX_ALERT", 0,1,0);
+
+ if (!get_string ("SOUND_WX_ALERT_FILE", sound_wx_alert_message, sizeof(sound_wx_alert_message))
+ || sound_wx_alert_message[0] == '\0') {
+ xastir_snprintf(sound_wx_alert_message,
+ sizeof(sound_wx_alert_message),
+ "thunder.wav");
+ }
+
+#ifdef HAVE_FESTIVAL
+ /* Festival Speech defaults */
+ festival_speak_new_station = get_int ("SPEAK_NEW_STATION",0,1,0);
+ festival_speak_proximity_alert = get_int ("SPEAK_PROXIMITY_ALERT",0,1,0);
+ festival_speak_tracked_proximity_alert = get_int ("SPEAK_TRACKED_ALERT",0,1,0);
+ festival_speak_band_opening = get_int ("SPEAK_BAND_OPENING",0,1,0);
+ festival_speak_new_message_alert = get_int ("SPEAK_MESSAGE_ALERT",0,1,0);
+ festival_speak_new_message_body = get_int ("SPEAK_MESSAGE_BODY",0,1,0);
+ festival_speak_new_weather_alert = get_int ("SPEAK_WEATHER_ALERT",0,1,0);
+ festival_speak_new_station = get_int ("SPEAK_ID",0,1,0);
+#endif // HAVE_FESTIVAL
+
+ ATV_screen_ID = get_int ("ATV_SCREEN_ID",0,1,0);
+
+ /* defaults */
+ sec_old = (time_t) get_long ("DEFAULT_STATION_OLD", 1l, 604800l, 4800l);
+
+ sec_clear = (time_t) get_long ("DEFAULT_STATION_CLEAR", 1l, 604800l, 43200l);
+
+ sec_remove = get_long("DEFAULT_STATION_REMOVE", 1l, 604800*2, sec_clear*2);
+
+ if (!get_string ("MESSAGE_COUNTER", message_counter, sizeof(message_counter))
+ || message_counter[0] == '\0') {
+ xastir_snprintf(message_counter,
+ sizeof(message_counter),
+ "00");
+ }
+
+ message_counter[2] = '\0'; // Terminate at 2 chars
+ // Check that chars are within the correct ranges
+ if ( (message_counter[0] < '0')
+ || (message_counter[1] < '0')
+ || ( (message_counter[0] > '9') && (message_counter[0] < 'A') )
+ || ( (message_counter[1] > '9') && (message_counter[1] < 'A') )
+ || ( (message_counter[0] > 'Z') && (message_counter[0] < 'a') )
+ || ( (message_counter[1] > 'Z') && (message_counter[1] < 'a') )
+ || (message_counter[0] > 'z')
+ || (message_counter[1] > 'z') ) {
+ message_counter[0] = '0';
+ message_counter[1] = '0';
+ }
+
+ if (!get_string ("AUTO_MSG_REPLY", auto_reply_message, sizeof(auto_reply_message))
+ || auto_reply_message[0] == '\0') {
+ xastir_snprintf(auto_reply_message,
+ sizeof(auto_reply_message),
+ "Autoreply- No one is at the keyboard");
+ }
+
+ Display_packet_data_type = get_int ("DISPLAY_PACKET_TYPE", 0,2,0);
+
+ bulletin_range = get_int ("BULLETIN_RANGE", 0,99999,0);
+
+ vm_range = get_int("VIEW_MESSAGE_RANGE", 0,99999,0);
+
+ view_message_limit = get_int("VIEW_MESSAGE_LIMIT", 10000,99999,10000);
+ predefined_menu_from_file = get_int("PREDEF_MENU_LOAD",0,1,0);
+ if (!get_string ("PREDEF_MENU_FILE", predefined_object_definition_filename, sizeof(predefined_object_definition_filename))
+ || predefined_object_definition_filename[0] == '\0') {
+ xastir_snprintf(predefined_object_definition_filename,
+ sizeof(predefined_object_definition_filename),
+ "predefined_SAR.sys");
+ }
+
+ Read_messages_packet_data_type = get_int ("READ_MESSAGES_PACKET_DATA_TYPE", 0,2,0);
+ Read_messages_mine_only = get_int ("READ_MESSAGES_MINE_ONLY", 0,1,0);
+
+ /* printer variables */
+ print_rotated = get_int ("PRINT_ROTATED", 0,1,0);
+ print_auto_rotation = get_int ("PRINT_AUTO_ROTATION", 0,1,1);
+ print_auto_scale = get_int ("PRINT_AUTO_SCALE", 0,1,1);
+ print_in_monochrome = get_int ("PRINT_IN_MONOCHROME", 0,1,0);
+ print_invert = get_int ("PRINT_INVERT_COLORS", 0,1,0);
+
+ // 0 = no correction
+ WX_rain_gauge_type = get_int ("RAIN_GAUGE_TYPE", 0,3,0);
+
+
+ /* list attributes */
+ for (i = 0; i < LST_NUM; i++) {
+ xastir_snprintf (name_temp, sizeof(name_temp), "LIST%0d_", i);
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "H", sizeof(name) - 1 - strlen(name));
+ list_size_h[i] = get_int (name, -1,8192,-1);
+
+ xastir_snprintf(name,
+ sizeof(name),
+ "%s",
+ name_temp);
+ strncat (name, "W", sizeof(name) - 1 - strlen(name));
+ list_size_w[i] = get_int (name, -1,8192,-1);
+ }
+
+ // 0 = no tracking
+ track_me = get_int ("TRACK_ME", 0,1,0);
+
+// store_string (fout, "TRACKING_STATION_CALLSIGN", tracking_station_call);
+ if (!get_string ("TRACKING_STATION_CALLSIGN", tracking_station_call, sizeof(tracking_station_call))) {
+ tracking_station_call[0] = '\0';
+ }
+
+
+ map_chooser_expand_dirs = get_int ("MAP_CHOOSER_EXPAND_DIRS", 0,1,1);
+
+ // One hour default
+ st_direct_timeout = get_int ("ST_DIRECT_TIMEOUT", 1,60*60*24*30,60*60);
+
+ // Ten minute default
+ dead_reckoning_timeout = get_int ("DEAD_RECKONING_TIMEOUT", 1,60*60*24*30,60*10);
+
+ // 1ms default
+ serial_char_pacing = get_int ("SERIAL_CHAR_PACING", 0,50,1);
+
+ // 45 minutes default, 12 hours max
+ trail_segment_time = get_int ("TRAIL_SEGMENT_TIME", 0,12*60,45);
+
+ // 1 degree default
+ trail_segment_distance = get_int ("TRAIL_SEGMENT_DISTANCE", 0,45,1);
+
+ // 0 minutes default (function disabled)
+ RINO_download_interval = get_int ("RINO_DOWNLOAD_INTERVAL", 0,30,0);
+
+ // 5 minutes default
+ snapshot_interval = get_int ("SNAPSHOT_INTERVAL", 1,30,5);
+
+ input_close();
+}
+
+
diff --git a/src/xa_config.h b/src/xa_config.h
new file mode 100644
index 0000000..ad4388b
--- /dev/null
+++ b/src/xa_config.h
@@ -0,0 +1,35 @@
+/*
+ * $Id: xa_config.h,v 1.14 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+#define MAX_VALUE 300
+
+extern time_t next_time;
+
+char *get_user_base_dir(char *dir, char *dest, size_t dest_size);
+char *get_data_base_dir(char *dir);
+void save_data(void);
+void load_data_or_default(void);
+
+char xa_config_dir[1000]; /* cmdline option user config dir */
diff --git a/src/xastir.h b/src/xastir.h
new file mode 100644
index 0000000..c1506f7
--- /dev/null
+++ b/src/xastir.h
@@ -0,0 +1,270 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
+ * $Id: xastir.h,v 1.65 2012/11/01 18:57:19 we7u Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 1999,2000 Frank Giannandrea
+ * Copyright (C) 2000-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+/* All of the misc entry points to be included for all packages */
+
+#ifndef _XASTIR_H
+#define _XASTIR_H
+
+
+
+// Macros that help us avoid warnings on 64-bit CPU's.
+// Borrowed from the freeciv project (also a GPL project).
+#define INT_TO_XTPOINTER(m_i) ((XtPointer)((long)(m_i)))
+#define XTPOINTER_TO_INT(m_p) ((int)((long)(m_p)))
+
+
+#define SERIAL_KISS_RELAY_DIGI
+
+
+#include <X11/Intrinsic.h>
+
+//#include "database.h"
+#include "util.h"
+#include "messages.h"
+#include "fcc_data.h"
+#include "rac_data.h"
+
+
+#define MAX_CALLSIGN 9 // Objects are up to 9 chars
+
+
+// black
+#define MY_FG_COLOR colors[0x08]
+#define MY_FOREGROUND_COLOR XmNforeground,colors[0x08]
+// gray73
+#define MY_BG_COLOR colors[0xff]
+#define MY_BACKGROUND_COLOR XmNbackground,colors[0xff]
+
+// Latitude and longitude string formats.
+#define CONVERT_HP_NORMAL 0
+#define CONVERT_HP_NOSP 1
+#define CONVERT_LP_NORMAL 2
+#define CONVERT_LP_NOSP 3
+#define CONVERT_DEC_DEG 4
+#define CONVERT_UP_TRK 5
+#define CONVERT_DMS_NORMAL 6
+#define CONVERT_VHP_NOSP 7
+#define CONVERT_DMS_NORMAL_FORMATED 8
+#define CONVERT_HP_NORMAL_FORMATED 9
+
+#ifndef M_PI /* if not defined in math.h */
+#define M_PI 3.14159265358979323846
+#endif // M_PI
+
+#define SPEECH_TEST_STRING "Greeteengz frum eggzaster"
+
+/* GLOBAL DEFINES */
+extern char dangerous_operation[200];
+extern GC gc;
+extern Pixmap pixmap;
+extern Pixmap pixmap_final;
+extern Pixmap pixmap_alerts;
+extern Pixmap pixmap_50pct_stipple;
+extern Pixmap pixmap_25pct_stipple;
+extern Pixmap pixmap_13pct_stipple;
+extern Pixmap pixmap_wx_stipple;
+
+extern Widget appshell;
+
+
+extern int wait_to_redraw;
+/*extern char my_callsign[MAX_CALLSIGN+1];*/
+
+extern void pad_callsign(char *callsignout, char *callsignin);
+
+
+
+extern char *to_upper(char *data);
+
+extern void Send_message(Widget w, XtPointer clientData, XtPointer callData);
+
+extern void create_gc(Widget w);
+
+extern void Station_info(Widget w, XtPointer clientData, XtPointer calldata);
+
+extern void fix_dialog_size(Widget w);
+extern void fix_dialog_vsize(Widget w);
+
+extern int debug_level;
+extern GC gc;
+extern Pixel colors[];
+
+
+extern float f_center_longitude; // Floating point map center longitude
+extern float f_center_latitude; // Floating point map center latitude
+extern float f_NW_corner_longitude;// longitude of NW corner
+extern float f_NW_corner_latitude; // latitude of NW corner
+extern float f_SE_corner_longitude;// longitude of SE corner
+extern float f_SE_corner_latitude; // latitude of SE corner
+
+extern long center_longitude; // Longitude at center of map
+extern long center_latitude; // Latitude at center of map
+extern long NW_corner_longitude; // longitude of NW corner
+extern long NW_corner_latitude; // latitude of NW corner
+extern long SE_corner_longitude; // longitude of SE corner
+extern long SE_corner_latitude; // latitude of SE corner
+
+extern long scale_x; // x scaling in 1/100 sec per pixel
+extern long scale_y; // y scaling in 1/100 sec per pixel
+
+
+extern long screen_width;
+extern long screen_height;
+extern Position screen_x_offset;
+extern Position screen_y_offset;
+extern int long_lat_grid;
+//extern Pixmap pixmap;
+//extern Pixmap pixmap_final;
+//extern Pixmap pixmap_alerts;
+extern int map_color_levels;
+extern int map_labels;
+extern int map_lock_pan_zoom;
+extern int map_auto_maps;
+extern int auto_maps_skip_raster;
+extern time_t sec_remove;
+extern Widget da;
+extern Widget text;
+extern XtAppContext app_context;
+extern int redraw_on_new_data;
+//extern Widget hidden_shell;
+extern int tiger_flag;
+extern int index_maps_on_startup;
+#define MAX_LABEL_FONTNAME 256
+#define FONT_SYSTEM 0
+#define FONT_STATION 1
+#define FONT_TINY 2
+#define FONT_SMALL 3
+#define FONT_MEDIUM 4
+#define FONT_LARGE 5
+#define FONT_HUGE 6
+#define FONT_BORDER 7
+#define FONT_ATV_ID 8
+#define FONT_MAX 9
+#define FONT_DEFAULT FONT_MEDIUM
+#define MAX_FONTNAME 256
+extern char rotated_label_fontname[FONT_MAX][MAX_LABEL_FONTNAME];
+
+#ifdef HAVE_MAGICK //N0VH
+extern int tiger_show_grid;
+extern int tiger_show_counties;
+extern int tiger_show_cities;
+extern int tiger_show_places;
+extern int tiger_show_majroads;
+extern int tiger_show_streets;
+extern int tiger_show_railroad;
+extern int tiger_show_states;
+extern int tiger_show_interstate;
+extern int tiger_show_ushwy;
+extern int tiger_show_statehwy;
+extern int tiger_show_water;
+extern int tiger_show_lakes;
+extern int tiger_show_misc;
+#endif // HAVE_MAGICK
+
+#ifdef HAVE_LIBGEOTIFF
+extern int DRG_XOR_colors;
+extern int DRG_show_colors[13];
+#endif // HAVE_LIBGEOTIFF
+
+
+extern int net_map_timeout;
+
+extern void sort_list(char *filename,int size, Widget list, int *item);
+extern void redraw_symbols(Widget w);
+
+extern Colormap cmap;
+
+
+
+/* from messages.c */
+extern char message_counter[5+1];
+extern int auto_reply;
+extern char auto_reply_message[100];
+extern int satellite_ack_mode;
+extern void clear_outgoing_messages(void);
+extern void reset_outgoing_messages(void);
+extern void output_message(char *from, char *to, char *message, char *path);
+extern void check_and_transmit_messages(time_t time);
+extern Message_Window mw[MAX_MESSAGE_WINDOWS+1];
+extern void clear_message_windows(void);
+
+/* from sound.c */
+extern pid_t play_sound(char *sound_cmd, char *soundfile);
+extern int sound_done(void);
+
+/* from fcc_data.c */
+
+
+
+/* from rac_data.c */
+
+/* from lang.c */
+extern int load_language_file(char *filename);
+extern char *langcode(char *code);
+extern char langcode_hotkey(char *code);
+
+/* from sound.c */
+extern pid_t play_sound(char *sound_cmd, char *soundfile);
+
+/* from location.c */
+extern void set_last_position(void);
+extern void map_pos_last_position(void);
+
+/* from location_gui.c */
+extern char locate_station_call[30];
+extern void Last_location(Widget w, XtPointer clientData, XtPointer callData);
+extern void Jump_location(Widget w, XtPointer clientData, XtPointer callData);
+extern void map_pos(long mid_y, long mid_x, long sz);
+extern char locate_gnis_filename[200];
+
+// This needs to be quite long for some of the weather station
+// serial data to get through ok (Peet Bros U2k Complete Record Mode
+// for one).
+#define MAX_LINE_SIZE 512
+
+// from main.c
+extern char gprmc_save_string[MAX_LINE_SIZE+1];
+extern char gpgga_save_string[MAX_LINE_SIZE+1];
+extern int gps_port_save;
+
+// from map.c
+extern double calc_dscale_x(long x, long y);
+
+/* from popup_gui.c */
+extern void popup_message_always(char *banner, char *message);
+extern void popup_message(char *banner, char *message);
+extern void popup_ID_message(char *banner, char *message);
+
+
+/* from view_messages.c */
+extern void all_messages(char from, char *call_sign, char *from_call, char *message);
+extern void view_all_messages(Widget w, XtPointer clientData, XtPointer callData);
+
+/* from db.c */
+extern void setup_in_view(void);
+
+#endif /* XASTIR_H */
+
+
diff --git a/src/xastir_udp_client.c b/src/xastir_udp_client.c
new file mode 100644
index 0000000..295e6af
--- /dev/null
+++ b/src/xastir_udp_client.c
@@ -0,0 +1,212 @@
+/*
+ * $Id: xastir_udp_client.c,v 1.16 2012/08/25 16:38:29 tvrusso Exp $
+ *
+ * XASTIR, Amateur Station Tracking and Information Reporting
+ * Copyright (C) 2003-2012 The Xastir Group
+ *
+ * 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.
+ *
+ * Look at the README for more information on the program.
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <sys/socket.h>
+#include <string.h>
+
+#include <netinet/in.h> // Moved ahead of inet.h as reports of some *BSD's not
+ // including this as they should.
+#include <arpa/inet.h>
+//#include <netinet/tcp.h> // Needed for TCP_NODELAY setsockopt() (disabling Nagle algorithm)
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif // HAVE_NETDB_H
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+
+// Must be last include file
+#include "leak_detection.h"
+
+
+
+
+
+// Send a UDP packet to a UDP listening port. This allows scripts
+// and other programs to inject packets into Xastir via UDP
+// protocol.
+// Inputs:
+// hostname (argv[1])
+// port (argv[2])
+// callsign (argv[3])
+// passcode (argv[4])
+// optional flags: -identify
+// -to_rf
+// -to_inet
+// APRS Packet (argv[5])
+// Returns:
+// 0: Message sent, ack received
+// 1: Error condition
+//
+//
+//
+int main(int argc, char *argv[]) {
+ int sockfd, n;
+ socklen_t length;
+ struct sockaddr_in server, from;
+ struct hostent *hostinfo;
+ char buffer[512];
+ char callsign[10];
+ char extra[100];
+ int passcode;
+ char message[256];
+ int ii;
+
+
+ if (argc < 6) {
+ fprintf(stderr,
+ "\nUsage: xastir_udp_client server port call passcode -identify\n");
+ fprintf(stderr,
+ " xastir_udp_client server port call passcode [-to_rf] [-to_inet] \"APRS Packet\"\n");
+
+ fprintf(stderr,
+ "\nExample: xastir_udp_client localhost 2023 ab7cd 1234 \"APRS packet goes here\"\n");
+ return(1);
+ }
+
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0) {
+ fprintf(stderr, "socket\n");
+ return(1);
+ }
+
+ memset(&server, 0, sizeof(struct sockaddr_in));
+
+ server.sin_family = AF_INET;
+
+ hostinfo = gethostbyname(argv[1]);
+ if (hostinfo == NULL) {
+ fprintf(stderr, "Unknown host\n");
+ return(1);
+ }
+
+// server.sin_addr.s_addr = inet_addr("127.0.0.1");
+ memcpy(&server.sin_addr, hostinfo->h_addr, hostinfo->h_length);
+
+ server.sin_port = htons(atoi(argv[2]));
+
+ length = (socklen_t)sizeof(struct sockaddr_in);
+
+ // Fetch the callsign
+ snprintf(callsign, sizeof(callsign), "%s", argv[3]);
+ callsign[sizeof(callsign)-1] = '\0'; // Terminate it
+
+ // Fetch the passcode
+ passcode = atoi(argv[4]);
+
+ // Check for optional flags here:
+ // -identify
+ // -to_rf
+ // -to_inet
+ //
+ extra[0] = '\0';
+ for (ii = 5; ii < argc; ii++) {
+ if (strstr(argv[ii], "-identify")) {
+//fprintf(stderr,"Found -identify\n");
+ strncat(extra, ",-identify", 10);
+ }
+ else if (strstr(argv[ii], "-to_rf")) {
+//fprintf(stderr,"Found -to_rf\n");
+ strncat(extra, ",-to_rf", 7);
+ }
+ else if (strstr(argv[ii], "-to_inet")) {
+//fprintf(stderr,"Found -to_inet\n");
+ strncat(extra, ",-to_inet", 9);
+ }
+ }
+
+
+// fprintf(stdout, "Please enter the message: ");
+
+ // Fetch message portion from the end of the command-line
+ snprintf(message, sizeof(message), "%s", argv[argc-1]);
+ message[sizeof(message)-1] = '\0'; // Terminate it
+
+ if (message[0] == '\0') // Empty message
+ return(1);
+
+ memset(buffer, 0, 256);
+// fgets(buffer, 255, stdin);
+
+ snprintf(buffer,
+ sizeof(buffer),
+ "%s,%d%s\n%s\n",
+ callsign,
+ passcode,
+ extra,
+ message);
+
+//fprintf(stderr, "%s", buffer);
+
+ n = sendto(sockfd,
+ buffer,
+ (size_t)strlen(buffer),
+ 0,
+ (struct sockaddr *)&server,
+ length);
+ if (n < 0) {
+ fprintf(stderr, "Sendto\n");
+ return(1);
+ }
+
+ n = recvfrom(sockfd,
+ buffer,
+ 256,
+ 0,
+ (struct sockaddr *)&from,
+ &length);
+ if (n < 0) {
+ fprintf(stderr, "recvfrom\n");
+ return(1);
+ }
+
+ fprintf(stdout,"Received: %s\n", buffer);
+
+ if (strncmp(buffer, "NACK", 4) == 0) {
+//fprintf(stderr,"returning 1\n");
+ return(1); // Received a NACK
+ }
+ else if (strncmp(buffer, "ACK", 3) == 0) {
+//fprintf(stderr,"returning 0\n");
+ return(0); // Received an ACK
+ }
+ else {
+//fprintf(stderr,"returning 1\n");
+ return(1); // Received something other than ACK or NACK
+ }
+}
+
+
diff --git a/symbols/13pct.xbm b/symbols/13pct.xbm
new file mode 100644
index 0000000..e51a2ec
--- /dev/null
+++ b/symbols/13pct.xbm
@@ -0,0 +1,5 @@
+/* Created with The GIMP */
+#define 13pct_width 4
+#define 13pct_height 4
+static unsigned char 13pct_bits[] = {
+ 0x01, 0x00, 0x04, 0x00 };
diff --git a/symbols/25pct.xbm b/symbols/25pct.xbm
new file mode 100644
index 0000000..0359058
--- /dev/null
+++ b/symbols/25pct.xbm
@@ -0,0 +1,5 @@
+/* Created with The GIMP */
+#define 25pct_width 4
+#define 25pct_height 4
+static unsigned char 25pct_bits[] = {
+ 0x01, 0x04, 0x01, 0x04 };
diff --git a/symbols/2x2.xbm b/symbols/2x2.xbm
new file mode 100644
index 0000000..c0d8165
--- /dev/null
+++ b/symbols/2x2.xbm
@@ -0,0 +1,5 @@
+/* Created with The GIMP */
+#define 2x2_width 2
+#define 2x2_height 2
+static unsigned char 2x2_bits[] = {
+ 0x01, 0x02 };
diff --git a/symbols/Makefile.am b/symbols/Makefile.am
new file mode 100644
index 0000000..d3d244c
--- /dev/null
+++ b/symbols/Makefile.am
@@ -0,0 +1,8 @@
+# $Id: Makefile.am,v 1.17 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+
+symbolsdir=${pkgdatadir}/symbols
+EXTRA_DIST=symbols.dat 2x2.xbm 25pct.xbm 13pct.xbm alert.xbm flood.xbm red_flag.xbm snow.xbm torndo.xbm wind.xbm winter_storm.xbm winter_weather.xbm icon.png
+symbols_DATA= symbols.dat 2x2.xbm 25pct.xbm 13pct.xbm alert.xbm flood.xbm red_flag.xbm snow.xbm torndo.xbm wind.xbm winter_storm.xbm winter_weather.xbm icon.png
diff --git a/symbols/Makefile.in b/symbols/Makefile.in
new file mode 100644
index 0000000..b0a9ce3
--- /dev/null
+++ b/symbols/Makefile.in
@@ -0,0 +1,414 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+# $Id: Makefile.am,v 1.17 2012/11/01 18:57:19 we7u Exp $
+#
+# Copyright (C) 2000-2012 The Xastir Group
+#
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = symbols
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(symbolsdir)"
+DATA = $(symbols_DATA)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTSHP = @CONTSHP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GMAGIC_BIN = @GMAGIC_BIN@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBCOMPAT = @LIBCOMPAT@
+LIBOBJS = @LIBOBJS@
+LIBRTREE = @LIBRTREE@
+LIBS = @LIBS@
+LIBSHP = @LIBSHP@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LWPOSTGIS = @LWPOSTGIS@
+MAGIC_BIN = @MAGIC_BIN@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PG_CONFIG = @PG_CONFIG@
+POW_LIB = @POW_LIB@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SUBRTREE = @SUBRTREE@
+SUBSHP = @SUBSHP@
+VERSION = @VERSION@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+convert = @convert@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+festival = @festival@
+found_gdal_config = @found_gdal_config@
+gm = @gm@
+gpsman = @gpsman@
+gv = @gv@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lpr = @lpr@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+mv = @mv@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sed = @sed@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+wget = @wget@
+xfontsel = @xfontsel@
+symbolsdir = ${pkgdatadir}/symbols
+EXTRA_DIST = symbols.dat 2x2.xbm 25pct.xbm 13pct.xbm alert.xbm flood.xbm red_flag.xbm snow.xbm torndo.xbm wind.xbm winter_storm.xbm winter_weather.xbm icon.png
+symbols_DATA = symbols.dat 2x2.xbm 25pct.xbm 13pct.xbm alert.xbm flood.xbm red_flag.xbm snow.xbm torndo.xbm wind.xbm winter_storm.xbm winter_weather.xbm icon.png
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu symbols/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu symbols/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-symbolsDATA: $(symbols_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(symbolsdir)" || $(MKDIR_P) "$(DESTDIR)$(symbolsdir)"
+ @list='$(symbols_DATA)'; test -n "$(symbolsdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(symbolsdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(symbolsdir)" || exit $$?; \
+ done
+
+uninstall-symbolsDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(symbols_DATA)'; test -n "$(symbolsdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(symbolsdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(symbolsdir)" && rm -f $$files
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(symbolsdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-symbolsDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-symbolsDATA
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic distclean \
+ distclean-generic distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip install-symbolsDATA installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \
+ uninstall-am uninstall-symbolsDATA
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/symbols/alert.xbm b/symbols/alert.xbm
new file mode 100644
index 0000000..25a6210
--- /dev/null
+++ b/symbols/alert.xbm
@@ -0,0 +1,41 @@
+#define alert_width 109
+#define alert_height 32
+static unsigned char alert_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x82,
+ 0xef, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x21, 0x82, 0x20, 0x22, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x15, 0x50, 0x82, 0x20, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x50, 0x82, 0xe7, 0x21, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0x20, 0x22, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0x20, 0x22,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xbe,
+ 0x2f, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
diff --git a/symbols/flood.xbm b/symbols/flood.xbm
new file mode 100644
index 0000000..c48ce62
--- /dev/null
+++ b/symbols/flood.xbm
@@ -0,0 +1,41 @@
+#define flood_width 110
+#define flood_height 32
+static unsigned char flood_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc0, 0x17, 0x38, 0xce, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x44, 0x51, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x44, 0x51, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x13, 0x44, 0x51,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10,
+ 0x44, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x10, 0x44, 0x51, 0x54, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0xf0, 0x39, 0xce, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
diff --git a/symbols/icon.png b/symbols/icon.png
new file mode 100644
index 0000000..38851b4
Binary files /dev/null and b/symbols/icon.png differ
diff --git a/symbols/red_flag.xbm b/symbols/red_flag.xbm
new file mode 100644
index 0000000..382e2df
--- /dev/null
+++ b/symbols/red_flag.xbm
@@ -0,0 +1,41 @@
+#define red_flag_width 110
+#define red_flag_height 32
+static unsigned char red_flag_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xcf, 0xf7, 0x00, 0x5f, 0x40, 0x38, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x10, 0x01, 0x41, 0x40, 0x44,
+ 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x51, 0x10, 0x01, 0x41,
+ 0xa0, 0x04, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x13,
+ 0x01, 0x4f, 0xa0, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x51, 0x10, 0x01, 0x41, 0xf0, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x51, 0x10, 0x01, 0x41, 0x10, 0x45, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf7, 0x00, 0xc1, 0x17, 0x79, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x2a };
diff --git a/symbols/snow.xbm b/symbols/snow.xbm
new file mode 100644
index 0000000..d2fcd6a
--- /dev/null
+++ b/symbols/snow.xbm
@@ -0,0 +1,41 @@
+#define snow_width 110
+#define snow_height 32
+static unsigned char snow_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x22,
+ 0x27, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x88, 0xa6, 0x28, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0xaa, 0x28, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x70, 0xb2, 0x28, 0x09, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0xa2, 0x28, 0xa9, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x88, 0xa2, 0x28, 0x09,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x22,
+ 0xe7, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
diff --git a/symbols/symbols.dat b/symbols/symbols.dat
new file mode 100644
index 0000000..9c7b50d
--- /dev/null
+++ b/symbols/symbols.dat
@@ -0,0 +1,4758 @@
+# XASTIR, Amateur Station Tracking and Information Reporting
+# Copyright (C) 1999,2000 Frank Giannandrea
+# Copyright (C) 2001-2012 The Xastir Group
+#
+# $Id: symbols.dat,v 1.35 2012/11/01 18:57:19 we7u Exp $
+#
+# Symbol definitions for XASTIR
+#
+# If the 20th char in the APRS symbol line is a "l" (small letter L),
+# all four orientations of that symbol will be generated, in this
+# case the symbol graphic should be oriented to the left.
+#
+# The text behind the APRS symbol line is the definition text
+# according to the APRS Reference, optionally followed by the
+# current use of that symbol in [] braces.
+#
+# Symbol graphics are defined similar to XPM but with a fixed
+# palette.
+#
+# If an entry doesn't exist, it will display as the first entry
+# defined here (currently says "NO SYM YET").
+#
+# Symbol colors are defined in:
+# draw_symbols.c:read_symbol_from_file()
+#
+#
+# -------------------------------
+#
+TABLE ! description from APRS101.pdf [used here as]
+APRS #
+....................
+....q...q...qqq.....
+....qq..q..q...q....
+....q.q.q..q...q....
+....q..qq..q...q....
+....q...q...qqq.....
+....................
+..qqq..q...q..q...q.
+.q......q.q...qq.qq.
+..qq.....q....q.q.q.
+....q....q....q...q.
+.qqq.....q....q...q.
+....................
+.q...q..qqqq..qqqqq.
+..q.q...q.......q...
+...q....qqq.....q...
+...q....q.......q...
+...q....qqqq....q...
+....................
+....................
+#
+#
+# -----------------------------------
+# Primary table section starts here
+#
+TABLE /
+#
+APRS ! Police, Sheriff
+....................
+.........pp.........
+.........pp.........
+........p##p........
+........p##p........
+.......p####p.......
+.......p#####p......
+ppppppp#######pppppp
+.p################p.
+...p############p...
+...p############p...
+.....p########p.....
+.....p########p.....
+....p##########p....
+....................
+pp....pppppp.pp...p.
+pp....pp...p.pp.p.p.
+pp....pppppp.pp.p.p.
+pp....pp...p.pppppp.
+ppppp.pp...p.pppppp.
+#APRS " Reserved
+#
+APRS # Digi (green star with white center)
+....................
+....................
+.........kk.........
+.........kk.........
+........kkkk........
+.......kkkkkk.......
+..kkkkkkkkkkkkkkkk..
+...kkkkkmmmmkkkkk...
+....kkkmmmmmmkkk....
+.....kkmmmmmmkk.....
+.....kkmmmmmmkk.....
+....kkkmmmmmmkkk....
+...kkkkkmmmmkkkkk...
+..kkkkkkkkkkkkkkkk..
+.......kkkkkk.......
+........kkkk........
+.........kk.........
+.........kk.........
+....................
+....................
+#
+APRS $ Phone
+....................
+....................
+..llllllllllllllll..
+..llllllllllmmmmll..
+..lllllllllmllllml..
+..lllllllllmllllml..
+..lllllllllmllllml..
+..llllllllllmlllml..
+..llllllllllmlllml..
+..lllllllllmlllmll..
+..llllllllmlllmlll..
+..llmmmllmlllmllll..
+..lmlllmmlllmlllll..
+..lmlllllllmllllll..
+..lmllllllmlllllll..
+..lmlllllmllllllll..
+..llmmmmmlllllllll..
+..llllllllllllllll..
+....................
+....................
+#
+APRS % DX Cluster
+....................
+....................
+.mmmmmm..mmmm..mmmm.
+.mqqqqqm.mqqm..mqqm.
+.mqqqqqqmmqqm..mqqm.
+.mqqmmqqqmmqqmmqqm..
+.mqqm.mqqmmqqmmqqm..
+.mqqm.mqqm.mqqqqm...
+.mqqm.mqqm.mqqqqm...
+.mqqm.mqqm..mqqm....
+.mqqm.mqqm..mqqm....
+.mqqm.mqqm.mqqqqm...
+.mqqm.mqqm.mqqqqm...
+.mqqm.mqqmmqqmmqqm..
+.mqqmmqqqmmqqmmqqm..
+.mqqqqqqmmqqm..mqqm.
+.mqqqqqm.mqqm..mqqm.
+.mmmmmm..mmmm..mmmm.
+....................
+....................
+#
+APRS & HF Gateway
+....................
+....................
+.........qq.........
+........qqqq........
+.......qqqqqq.......
+......qqqqqqqq......
+.....qqq####qqq.....
+....qqq######qqq....
+...qqq##qqqq##qqq...
+..qqqq##qqqqqqqqqq..
+..qqqq##qqq###qqqq..
+...qqq##qqqq##qqq...
+....qqq######qqq....
+.....qqq####qqq.....
+......qqqqqqqq......
+.......qqqqqq.......
+........qqqq........
+.........qq.........
+....................
+....................
+#
+APRS ' l Small Aircraft (SSID -7)
+....................
+....................
+........ooo.........
+.......oooo.........
+.......oooo.........
+.......oooo...oo....
+.......oooo...oo....
+.......oooo...oo....
+.....ooooooooooo....
+.....ooooooooooo....
+.....ooooooooooo....
+.....ooooooooooo....
+.......oooo...oo....
+.......oooo...oo....
+.......oooo...oo....
+.......oooo.........
+.......oooo.........
+........ooo.........
+....................
+....................
+#
+APRS ( Mobile Satellite Groundstation
+.................p..
+.................p..
+................ppp.
+................ppp.
+....................
+..............p.....
+....................
+............p.......
+....................
+..........p.........
+p...................
+p.......p...........
+p...................
+p...................
+p...................
+p...................
+pp.p................
+ppp.................
+pppp................
+pppppppppp..........
+#
+APRS ) Wheelchair (handicapped)
+....................
+..llllllllllllllll..
+.llllllmmmlllllllll.
+.llllllmmmlllllllll.
+.llllllmmllllllllll.
+.llllllmmllllllllll.
+.lllllllmmlllllllll.
+.llllmmlmmmmmmmllll.
+.llmmmllmmlllllllll.
+.llmmllllmmmmmmmlll.
+.lmmllllllmmmmmmlll.
+.lmmlllllllmmlmmlll.
+.lmmlllllllmmlmmlll.
+.lmmlllllllmmlmmlll.
+.llmmlllllmmllmmlll.
+.llmmmllllmmllmmmml.
+.lllmmmmmmmllllllll.
+.llllmmmmmlllllllll.
+..llllllllllllllll..
+....................
+#
+APRS * l Snowmobile
+....................
+....................
+....................
+....................
+...........qq.......
+..........qq........
+.........qq.........
+........qq..........
+......q###q.........
+.....q#####q.......q
+....q######qqqqqqqqq
+....q######qqqqqqqqq
+q....q######qqqqqqqq
+qqq..qqqqqqqqqqqqqqq
+.qqqqqqqqqqqqqqqqqqq
+....................
+....................
+....................
+....................
+....................
+#
+APRS + Red Cross
+....................
+....................
+........jjjj........
+........jjjj........
+........jjjj........
+........jjjj........
+........jjjj........
+........jjjj........
+..jjjjjjjjjjjjjjjj..
+..jjjjjjjjjjjjjjjj..
+..jjjjjjjjjjjjjjjj..
+..jjjjjjjjjjjjjjjj..
+........jjjj........
+........jjjj........
+........jjjj........
+........jjjj........
+........jjjj........
+........jjjj........
+....................
+....................
+#
+APRS , Boy Scouts
+.........n..........
+........nbn.........
+.......nbbbn........
+.......nbbbn........
+....n.nbbbbbn.n.....
+...nbnnbbbbbnnbn....
+..nbbbbnbbbnbbbbn...
+..nbbbbbnbnbbbbbn...
+..nbbnnbnbnbnnbbn...
+...nn..qqqqq..nn....
+.......qqqqq........
+......nbbnbbn.......
+.....nbbnbnbbn......
+.....nnnbbbnnn......
+.......nbbbn........
+.ppp....nnn......p..
+p................p..
+.pp..pp.ppp.p.p.ppp.
+...p.p..p.p.p.p..p..
+ppp..pp.ppp.ppp..p..
+#
+APRS - House QTH (VHF)
+....................
+......q.............
+......q.............
+......q...q.........
+......q..qqq........
+......q.qqqqq.......
+......qqqqqqqq......
+......qqqqqqqqq.....
+.....qqqqqqqqqqq....
+....qqqqqqqqqqqqq...
+......q#######q.....
+......q#q###q#q.....
+......q###q###q.....
+......q###q###q.....
+......qqqqqqqqq.....
+....................
+....................
+....................
+....................
+....................
+#
+APRS . X
+....................
+....................
+....................
+....................
+....................
+....................
+......j......j......
+.......j....j.......
+........j..j........
+.........jj.........
+.........jj.........
+........j..j........
+.......j....j.......
+......j......j......
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS / Dot
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+........jjjj........
+.......jjjjjj.......
+.......jjjjjj.......
+.......jjjjjj.......
+.......jjjjjj.......
+........jjjj........
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS 0 Numerical Circle 0 (obsolete, use overlay)
+....................
+....................
+..qqqqqqqqqqqqqqqq..
+..qqqqqqqqqqqqqqqq..
+..qqqqqqmmmmqqqqqq..
+..qqqqqmmmmmmqqqqq..
+..qqqqmmmqqmmmqqqq..
+..qqqqmmqqqqmmqqqq..
+..qqqmmmqqqqmmmqqq..
+..qqqmmmqqqqmmmqqq..
+..qqqmmmqqqqmmmqqq..
+..qqqmmmqqqqmmmqqq..
+..qqqqmmqqqqmmqqqq..
+..qqqqmmmqqmmmqqqq..
+..qqqqqmmmmmmqqqqq..
+..qqqqqqmmmmqqqqqq..
+..qqqqqqqqqqqqqqqq..
+..qqqqqqqqqqqqqqqq..
+....................
+....................
+#
+APRS 1 Numerical Circle 1 (obsolete, use overlay)
+....................
+....................
+..ffffffffffffffff..
+..ffffffffffffffff..
+..ffffffffmmffffff..
+..fffffffmmmffffff..
+..ffffffmmmmffffff..
+..fffffmmmmmffffff..
+..fffffffmmmffffff..
+..fffffffmmmffffff..
+..fffffffmmmffffff..
+..fffffffmmmffffff..
+..fffffffmmmffffff..
+..fffffmmmmmmmffff..
+..fffffmmmmmmmffff..
+..ffffffffffffffff..
+..ffffffffffffffff..
+..ffffffffffffffff..
+....................
+....................
+#
+APRS 2 Numerical Circle 2 (obsolete, use overlay)
+....................
+....................
+..jjjjjjjjjjjjjjjj..
+..jjjjjjjjjjjjjjjj..
+..jjjjjjjjjjjjjjjj..
+..jjjjmmmmmmmmjjjj..
+..jjjmmmmmmmmmmjjj..
+..jjjmmmjjjjmmmjjj..
+..jjjjjjjjjjmmmjjj..
+..jjjjjjjjjmmmjjjj..
+..jjjjjjjmmmjjjjjj..
+..jjjjjmmmjjjjjjjj..
+..jjjjmmmjjjjjjjjj..
+..jjjmmmmmmmmmmjjj..
+..jjjmmmmmmmmmmjjj..
+..jjjjjjjjjjjjjjjj..
+..jjjjjjjjjjjjjjjj..
+..jjjjjjjjjjjjjjjj..
+....................
+....................
+#
+APRS 3 Numerical Circle 3 (obsolete, use overlay)
+....................
+....................
+..aaaaaaaaaaaaaaaa..
+..aaaaaaaaaaaaaaaa..
+..aaaaaaaaaaaaaaaa..
+..aaaammmmmmmaaaaa..
+..aaaammmmmmmmaaaa..
+..aaaaaaaaaammaaaa..
+..aaaaaaaaaammaaaa..
+..aaaaaammmmmaaaaa..
+..aaaaaammmmmaaaaa..
+..aaaaaaaaaammaaaa..
+..aaaaaaaaaammaaaa..
+..aaaammmmmmmmaaaa..
+..aaaammmmmmmaaaaa..
+..aaaaaaaaaaaaaaaa..
+..aaaaaaaaaaaaaaaa..
+..aaaaaaaaaaaaaaaa..
+....................
+....................
+#
+APRS 4 Numerical Circle 4 (obsolete, use overlay)
+....................
+....................
+..################..
+..################..
+..################..
+..#####ooo#ooo####..
+..#####ooo#ooo####..
+..####ooo##ooo####..
+..####ooo##ooo####..
+..###oooooooooo###..
+..###oooooooooo###..
+..#########ooo####..
+..#########ooo####..
+..#########ooo####..
+..#########ooo####..
+..################..
+..################..
+..################..
+....................
+....................
+#
+APRS 5 Numerical Circle 5 (obsolete, use overlay)
+....................
+....................
+..kkkkkkkkkkkkkkkk..
+..kkkkkkkkkkkkkkkk..
+..kkkkkkkkkkkkkkkk..
+..kkkkmmmmmmmmkkkk..
+..kkkkmmmmmmmmkkkk..
+..kkkkmmkkkkkkkkkk..
+..kkkkmmkkkkkkkkkk..
+..kkkkmmmmmmmkkkkk..
+..kkkkmmmmmmmmkkkk..
+..kkkkkkkkkkmmkkkk..
+..kkkkkkkkkkmmkkkk..
+..kkkkmmmmmmmmkkkk..
+..kkkkmmmmmmmkkkkk..
+..kkkkkkkkkkkkkkkk..
+..kkkkkkkkkkkkkkkk..
+..kkkkkkkkkkkkkkkk..
+....................
+....................
+#
+APRS 6 Numerical Circle 6 (obsolete, use overlay)
+....................
+....................
+..llllllllllllllll..
+..llllllllllllllll..
+..llllllllllllllll..
+..lllllmmmmmmmllll..
+..llllmmmmmmmmllll..
+..llllmmllllllllll..
+..llllmmllllllllll..
+..llllmmmmmmmlllll..
+..llllmmmmmmmmllll..
+..llllmmllllmmllll..
+..llllmmllllmmllll..
+..llllmmmmmmmmllll..
+..lllllmmmmmmlllll..
+..llllllllllllllll..
+..llllllllllllllll..
+..llllllllllllllll..
+....................
+....................
+#
+APRS 7 Numerical Circle 7 (obsolete, use overlay)
+....................
+....................
+..bbbbbbbbbbbbbbbb..
+..bbbbbbbbbbbbbbbb..
+..bbbbbbbbbbbbbbbb..
+..bbbbmmmmmmmbbbbb..
+..bbbbmmmmmmmbbbbb..
+..bbbbbbbbbmmbbbbb..
+..bbbbbbbbbmmbbbbb..
+..bbbbbbbbbmmbbbbb..
+..bbbbbbbbmmbbbbbb..
+..bbbbbbbbmmbbbbbb..
+..bbbbbbbbmmbbbbbb..
+..bbbbbbbmmbbbbbbb..
+..bbbbbbbmmbbbbbbb..
+..bbbbbbbmmbbbbbbb..
+..bbbbbbbbbbbbbbbb..
+..bbbbbbbbbbbbbbbb..
+....................
+....................
+#
+APRS 8 Numerical Circle 8 (obsolete, use overlay)
+....................
+....................
+..cccccccccccccccc..
+..cccccccccccccccc..
+..cccccccccccccccc..
+..cccccmmmmmmccccc..
+..ccccmmmmmmmmcccc..
+..ccccmmccccmmcccc..
+..ccccmmccccmmcccc..
+..cccccmmmmmmccccc..
+..cccccmmmmmmccccc..
+..ccccmmccccmmcccc..
+..ccccmmccccmmcccc..
+..ccccmmmmmmmmcccc..
+..cccccmmmmmmccccc..
+..cccccccccccccccc..
+..cccccccccccccccc..
+..cccccccccccccccc..
+....................
+....................
+#
+APRS 9 Numerical Circle 9 (obsolete, use overlay)
+....................
+....................
+..qqqqqqqqqqqqqqqq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmqqqqqqmmmmq..
+..qmmmqqqqqqqqmmmq..
+..qmmmqqmmmmqqmmmq..
+..qmmmqqmmmmqqmmmq..
+..qmmmqqqqqqqqmmmq..
+..qmmmmqqqqqqqmmmq..
+..qmmmmmmmmmqqmmmq..
+..qmmmmmmmmmqqmmmq..
+..qmmmqqqqqqqqmmmq..
+..qmmmqqqqqqqmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qqqqqqqqqqqqqqqq..
+....................
+....................
+#
+APRS : Fire
+....................
+....................
+....q...............
+...q#q...........q..
+...qjq..........q#q.
+...q#q.........q##q.
+...qqq..qq.qq.q#qq..
+..q#q#qq#q.q#qq#q...
+...qq#q##qq#jqqq#q..
+...q#q#jfj##j#f#qq..
+..q#j#jj#j#jj#jjq...
+..qjjjfjjj#j#j#q....
+...qjjfjj#jjjjfq....
+....qjjffjjfjfjjq...
+...qjjffjfjjfjjfqq..
+...qjfffjjfjfjfjjq..
+..qjffjjfffjjffjq...
+..qjffjjfjffjjffjq..
+..qffffffffffffffq..
+....................
+#
+APRS ; Campground (Portable Ops!)
+....................
+....................
+..........e.........
+..........e.........
+..........e.........
+..........e.........
+.........iei........
+.........iei........
+........ikeki.......
+.......ikkekki......
+......ikkceckki.....
+.....ikkkoeokkki....
+....ikkkcieickkki...
+...ikkkkoieiokkkki..
+....kkkciieiickkk...
+....kkkoiieiiokkk...
+....kkciiieiiickk...
+..eeeeeeeeeeeeeeee..
+....................
+....................
+#
+APRS < l Motorcycle (SSID -10)
+....................
+....................
+....................
+.......ppp..........
+.......p............
+.......ppppp........
+......pp.........p..
+.....pppppp....pp...
+.pppppp####pppppppp.
+p.pmppp####pppppmp.p
+.pmppp.ppppppqpmmmp.
+pmmpmmppppppppppppmp
+pmpmmmppppppppmmmmmp
+.pmmmp..ppppp.pmmmp.
+..pmp..........pmp..
+...p............p...
+....................
+....................
+....................
+....................
+#
+APRS = l Railroad Engine
+....................
+....................
+.....cmccmcccc......
+....ccccmc..........
+....pp..............
+..qqqqqq...qqqqqqq..
+...qqqq....qqqqqqq..
+....qq.....qq...qq..
+....qq.....qq...qq..
+....qq.....qq...qq..
+..qqqqqqqqqqqqqqqq..
+..qqqqqqqqqqqqqqqq..
+..qqqqqqqqqqqqqqqq..
+..qqqqqqqqqqqqqqqq..
+..qqqqqqqqqqqqqqqq..
+...q..q..qmmq.qmmq..
+..qmqqmq.qmmq.qmmq..
+...q..q...qq...qq...
+....................
+....................
+#
+APRS > l Car (SSID -9)
+....................
+....................
+....................
+....................
+.........ppppp......
+........pcccncp.....
+.......pccccnccp....
+......pcccccncccp...
+...pppdqdddddddddp..
+..pjjjjdjjjjdjjjjjp.
+.pjjjjjdjjjjdjjjjjdp
+p#jjoojdjjjjdjjoojjp
+pjjonnodjjjjdjonnojp
+.ppqnnqpppppppqnnqp.
+....qq.........qq...
+....................
+....................
+....................
+....................
+....................
+#
+APRS ? File Server
+....................
+....................
+pppp..p..p.....pppp.
+p.....p..p.....p....
+p.....p..p.....p....
+pppp..p..p.....pppp.
+p.....p..p.....p....
+p.....p..p.....p....
+p.....p..pppp..pppp.
+....................
+....................
+....................
+.ppp.pp.ppp..p.p.ppp
+p....p..p..p.p.p.p..
+p....p..p..p.p.p.p..
+.pp..pp.ppp..p.p.ppp
+...p.p..p.p..p.p.p..
+...p.p..p.p..p.p.p..
+ppp..pp.p..p..p..ppp
+....................
+#
+APRS @ Hurricane Future Prediction (dot)
+ppp..ppp...ppp..ppp.
+p..p.p..p..p....p..p
+ppp..ppp...ppp..p..p
+p....p.p...p....p..p
+p....p..p..ppp..ppp.
+....................
+....ll.....ll.......
+...ll....ll..ll.....
+...ll...llll...ll...
+....ll.lllllll......
+......lllllll.ll....
+...ll...llll...ll...
+.....ll..ll...ll....
+.......ll....ll.....
+....................
+ppp...ppp...ppppp...
+.p...p...p....p.....
+.p...p........p.....
+.p...p...p....p.....
+ppp...ppp.....p.....
+#
+APRS A Aid Station
+....................
+....................
+..hhhhhhhhhhhhhhhh..
+..hhhhhhhhhhhhhhhh..
+..hhhhhhhmmhhhhhhh..
+..hhhhhhhmmhhhhhhh..
+..hhhhhhhmmhhhhhhh..
+..hhhhhhhmmhhhhhhh..
+..hhhhhhhmmhhhhhhh..
+..hhmmmmmmmmmmmmhh..
+..hhmmmmmmmmmmmmhh..
+..hhhhhhhmmhhhhhhh..
+..hhhhhhhmmhhhhhhh..
+..hhhhhhhmmhhhhhhh..
+..hhhhhhhmmhhhhhhh..
+..hhhhhhhmmhhhhhhh..
+..hhhhhhhhhhhhhhhh..
+..hhhhhhhhhhhhhhhh..
+....................
+....................
+#
+APRS B BBS or PBBS
+....................
+....................
+....................
+....................
+....................
+...ggg..ggg...gg....
+...g..g.g..g.g..g...
+...g..g.g..g.g......
+...ggg..ggg...g.....
+...g..g.g..g..g.....
+...g..g.g..g...g....
+...g..g.g..g....g...
+...g..g.g..g.g..g...
+...gggg.ggg...gg....
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS C l Canoe
+....................
+....................
+....................
+....................
+....................
+.............p......
+pppp........p...pppp
+peeppppppppppppppeep
+peeeeeeeeepeeeeeeeep
+.peeeeeeepeeeeeeeep.
+..peeeeepeeeeeeeep..
+...pppppppppppppp...
+......p.............
+.....p..............
+...ppp..............
+..ppp...............
+.ppp................
+....................
+....................
+....................
+#
+#APRS D
+#
+APRS E Eyeball (eye catcher)
+....................
+....................
+........pppp........
+......pmmmmmmp......
+....pmmmmmmmmmmp....
+..pmmmmmhhhhmmmmmp..
+.pmmmmhhhhhhhhmmmmp.
+.pmmmmhhhhhhhhmmmmp.
+pmmmhhhhhpphhhhhmmmp
+pmmmhhhhpppphhhhmmmp
+pmmmhhhhpppphhhhmmmp
+pmmmhhhhhpphhhhhmmmp
+.pmmmmhhhhhhhhmmmmp.
+.pmmmmhhhhhhhhmmmmp.
+..pmmmmmhhhhmmmmmp..
+....pmmmmmmmmmmp....
+......pmmmmmmp......
+........pppp........
+....................
+....................
+#
+APRS F l Farm Equipment
+....................
+....................
+....................
+....................
+....................
+............qqqqqqq.
+............qkkkkkq.
+...qq.......qkmmmkq.
+...qq.......qkmmmkq.
+...qq.......qkmmmkq.
+..qqqqqqqqqqkkkkkkq.
+.qkkkkkkkkkkkqqqqqq.
+.qkkkkkkkkkkqqqqqqq.
+..qqqkkkkkkqqqkkkqq.
+.qqqqqqqqqqqqqkkkqq.
+.qqqqq......qqkkkqq.
+.qqqqq......qqqqqqq.
+.qqqq........qqqqq..
+....................
+....................
+#
+APRS G Grid Square (6-character)
+....................
+..q.q.q......q.q.q..
+..q.q.q.qjjq.q.q.q..
+..qqqqqqqqqqqqqqqq..
+..q.q.q.qjjq.q.q.q..
+..q.q.q.qjjq.q.q.q..
+........qjjq........
+........qjjq........
+........qjjq........
+........qjjq........
+.......qqjjqq.......
+.......qjqqjq.......
+...qq..qqjjqq..qq...
+..q..q.qqjjqq.q..q..
+..q....qjqqjq..q....
+..q.qq.qjqqjq...q...
+..q..q.qqjjqq.q..q..
+...qq..qqqqqq..qq...
+....................
+....................
+#
+APRS H Hotel (blue bed icon)
+....................
+....................
+..hhhhhhhhhhhhhhhh..
+..hhhhhhhhhhhhhhhh..
+..hhhhhhhhhhhhhhhh..
+..hhhhhhhhhhhhhhhh..
+..hhhhhhhhhhhhhhhh..
+..hmhhhhhhhhhhhhhh..
+..hmhhhhhhhhhhhhhh..
+..hmhhhhhhhhhhhhhh..
+..hmhmmhhmmmmmmhmh..
+..hmhmmmmmmmmmmhmh..
+..hmhmmhhmmmmmmhmh..
+..hmhhhhhhhhhhhhmh..
+..hmmmmmmmmmmmmmmh..
+..hmhhhhhhhhhhhhmh..
+..hmhhhhhhhhhhhhmh..
+..hhhhhhhhhhhhhhhh..
+....................
+....................
+#
+APRS I TCP/IP on air network station
+....................
+....................
+....................
+.#################..
+.##iiiii#iii#iii##..
+..###i###i#i#i#i#...
+..###i###i###iii#...
+..###i###i#i#i###...
+...##i###iii#i##....
+...#############....
+...#############....
+...###iii#iii###....
+....###i##i#i##.....
+....###i##iii##.....
+....###i##i####.....
+.....#iii#i###......
+.....#########......
+.....#########......
+....................
+....................
+#
+#APRS J
+#
+APRS K School
+.........pp.........
+........p##p........
+.......p####p.......
+......p######p......
+.....p########p.....
+....p##########p....
+...p############p...
+..pppppppppppppppp..
+..p##############p..
+..p##pp##ppp##pp#p..
+..p##pp##ppp##pp#p..
+..p######ppp#####p..
+..pppppppppppppppp..
+....................
+....................
+.pp....p...........p
+p......p...........p
+.p..pp.ppp.ppp.ppp.p
+..p.p..p.p.p.p.p.p.p
+pp..pp.p.p.ppp.ppp.p
+#
+APRS L Logged-on Internet User (Desktop Computer)
+qqqqq.qqqqqqqqqqqqqq
+qmqmq.qqqqqqqqqqqqqq
+qqmqq.qqmmmmmmmmmmqq
+qmqmq.qqmmmqmmmqmmqq
+qqmqq.qqmmmmqmqmmmqq
+qmqmq.qqmmmmmqmmmmqq
+qqmqq.qqmmmmqmqmmmqq
+qmqmq.qqmmmqmmmqmmqq
+qqmqq.qqmmmmmmmmmmqq
+qmqmq.qqqqqqqqqqqqqq
+qqmqq.qqqqqqqqqqqqqq
+qmqmq.q............q
+qqqqq.qqqqqqqqqqqqqq
+....................
+....................
+....qqqqqqqqqqqqqqqq
+...qmqmqmqmqmqmqmqq.
+..qqmqmqmqmqmqmqmq..
+.qmmqmqmqmqmqmqmq...
+qqqqqqqqqqqqqqqq....
+#
+APRS M MacAPRS
+....................
+....................
+...........kk.......
+..........kkk.......
+.........kkk........
+.........kkk........
+.....kkkkkkkkkk.....
+....kkkkkkkkkkkk....
+...############.....
+...###########......
+...aaaaaaaaaaa......
+...aaaaaaaaaaa......
+...jjjjjjjjjjjj.....
+...jjjjjjjjjjjj.....
+....bbbbbbbbbbbb....
+....bbbbbbbbbbbb....
+.....llllllllll.....
+......llllllll......
+....................
+....................
+#
+APRS N NTS Station
+....................
+.......gggggg.......
+......gggggggg......
+.....ggmmgggmgg.....
+.....ggmgmggmgg.....
+....gggmggmgmggg....
+....gggmgggmmggg....
+...gggggggggggggg...
+...ggggmmmmmmgggg...
+..gggggggmmggggggg..
+..gggggggmmggggggg..
+...gggggggggggggg...
+...gggggmmmmmgggg...
+....gggmgggggggg....
+....ggggmmmmgggg....
+.....gggggggmgg.....
+.....ggmmmmmggg.....
+......gggggggg......
+.......gggggg.......
+....................
+#
+APRS O Balloon (SSID -11)
+....................
+....................
+......hffjffh.......
+.....h##kjk##h......
+....h###jjj###h.....
+...h####jjj####h....
+...###jj###jj###....
+...jjjjj###jjjjj....
+...jjjjj###jjjjj....
+...jjjblllllbjjj....
+....lllllllllll.....
+.....lllllllll......
+......lllllll.......
+.......h.a.h........
+........pcp.........
+.......fefef........
+.......fefef........
+.......oqqqo........
+....................
+....................
+#
+APRS P l Police
+....................
+....................
+..........ll........
+..........ll........
+.........ppppp......
+........pcccncp.....
+.......pccccnccp....
+......pcccccncccp...
+...pppnqnnnnnnnnnp..
+..pmmmmkkkkkkmmmmmp.
+.pmmmmmkccckkmmmmmep
+p#mmoomkkkkkkmmoommp
+pmmonnokkkkkkmonnomp
+.ppqnnqpppppppqnnqp.
+....qq.........qq...
+....................
+....................
+....................
+....................
+....................
+#
+#APRS Q
+#
+APRS R l Recreational Vehicle (SSID -13) (motor-home)
+....................
+....................
+....................
+....................
+....................
+........pppppppppp..
+..pqqqqqqqqqqqqqqqqq
+.pmmmmmmmmmmmmmmmmmq
+ppppmmmmmpppmmpppmmq
+qpppmmmmmpppmmpppmmq
+qmmmmmmmmmmmmmmmmmmq
+qmmmmmmmqmmmqmmmqmmq
+qmmmmmmmmmmmmmmmmmmq
+qqqqqqqqqqqqqqqqqqqq
+.qqqq.......qqqq....
+..qq.........qq.....
+....................
+....................
+....................
+....................
+#
+APRS S l Space Shuttle
+................qqq.
+...............qmcq.
+..............qmmcq.
+.............qnmecq.
+............qnmmhcq.
+..........qqnmmmmcq.
+........pqnmmmmmcnqq
+...oqqqonnnnnnnncmmq
+.qqomcmmmmmmmmmcmmmq
+qqmqcnmmmmmmmmmcqqqn
+.qqomcmmmmmmmmmcmmmq
+...oqqqonnnnnnnncmmq
+........pqnmmmmmcnqq
+..........qqnmmmmcq.
+............qnmmecq.
+.............qnhlcq.
+..............qmmcq.
+...............qmcq.
+................qqq.
+....................
+#
+APRS T SSTV
+..pppp.......pppp...
+.p....p.....p....p..
+p......p...p......p.
+p....... ..p........
+.pppppp.....pppppp..
+.......p..........p.
+p......p...p......p.
+.p....p.....p....p..
+..pppp.......pppp...
+....................
+....................
+ppppppp....p.......p
+...p.......p.......p
+...p.......p.......p
+...p........p.....p.
+...p........p.....p.
+...p.........p...p..
+...p.........p...p..
+...p..........p.p...
+...p...........p....
+#
+APRS U l Bus (SSID -2)
+....................
+....................
+....................
+....................
+....................
+.....aaaaaaaaaaaaaa.
+....a##############a
+...ac#cc#cc#cc#cc#ca
+..acc#cc#cc#cc#cc#ca
+aa#################a
+a##################a
+a##################a
+aannaaaaaaaaaaaannaa
+.qooq..........qooq.
+..qq............qq..
+....................
+....................
+....................
+....................
+....................
+#
+APRS V ATV
+.........pp.........
+........p..p........
+.......p....p.......
+......p. ....p......
+.....p........p.....
+....pppppppppppp....
+...p............p...
+..p..............p..
+.p................p.
+....................
+....................
+ppppppp....p.......p
+...p.......p.......p
+...p.......p.......p
+...p........p.....p.
+...p........p.....p.
+...p.........p...p..
+...p.........p...p..
+...p..........p.p...
+...p...........p....
+#
+APRS W National Weather Service Site
+....................
+....................
+.......gggggg.......
+.....gghhhhhhgg.....
+....ghhhhhhhhhhg....
+...ghhhhhhhhhhhhg...
+...ghhhhhhhhhhhhg...
+..gmmhhhmmhmmhhmmg..
+..gmmhhhmmhmmmmmmg..
+..gmmhhhmmhhmmmmhg..
+..gmmhmhmmhhmmmmhg..
+..gmmmmmmmhmmmmmmg..
+..gmmmhmmmhmmhhmmg..
+...ghhhhhhhhhhhhg...
+...ghhhhhhhhhhhhg...
+....ghhhhhhhhhhg....
+.....gghhhhhhgg.....
+.......gggggg.......
+....................
+....................
+#
+APRS X l Helicopter (SSID -6)
+....................
+....................
+....................
+..mqqmqqmqqmqqm.....
+qmqmqmqmqmqmqmqmq...
+..qmqqmqqmqqmqq.....
+.......mq...........
+...qqqqqq...........
+..qqqqjjq.......mmm.
+.qmmmqjjjq.....mqqqm
+qmmmmqjjjjqjqjqmqmqm
+qqqqqqjjjjjqjqjmqqqm
+.qjjjjjjjq......mmm.
+..qjqqjqq...........
+...jq.jq............
+j..jq.jq............
+qjjjjjjjjjjj........
+.qqqqqqqqqqq........
+....................
+....................
+#
+APRS Y l Yacht (sail boat) (SSID -5)
+....................
+....................
+...........q........
+..........qqq.......
+.........qcqcq......
+........qccqcq......
+.......qcccqcq......
+......qccccqccq.....
+.....qcccccqccq.....
+....qccccccqcccq....
+...qcccccccqcccq....
+..qqqqqqqqqqqqqqqq..
+...qkkkkkkkkkkkkq...
+....qkkkkkkkkkkq....
+.....qqqqqqqqqq.....
+....................
+....................
+....................
+....................
+....................
+#
+APRS Z WinAPRS
+....................
+....................
+....................
+.........qqqqqq.....
+........qjjjqkkqq...
+.qq...qqjjjjqkkkkq..
+...qqq.qjjjjqkkkkq..
+.qq...qqjjjjqkkkkq..
+...qqq.qjjjjqkkkkq..
+.qq...qqjjqqqqkkkq..
+...qqq.qqqllq#qqkq..
+.qq...qqllllq###qq..
+...qqq.qllllq####q..
+.qq...qqllllq####q..
+...qqq.qllllq####q..
+.qq...qqllllq####q..
+...qqq.qlqqqqq###q..
+.qq...qqq.....qq#q..
+...qqq..........qq..
+....................
+#
+APRS [ l Jogger
+....................
+....................
+....................
+....................
+.......qq...........
+.......qq...........
+.......qqllpp.......
+...p...lelleep......
+...pe...lll..ep.....
+....pe..lll..ep.....
+.....ppqqll..ep.....
+......qqqqqq........
+.....qqqqqqq........
+.....qqq..qqqqq.....
+......llq..qllq.....
+.....qqq......q.....
+....................
+....................
+....................
+....................
+#
+APRS \ Triangle (DF station)
+....................
+....................
+.........qq.........
+........q##q........
+........q##q........
+.......q####q.......
+.......q####q.......
+......q######q......
+......q######q......
+.....q########q.....
+.....q########q.....
+....q#qqq##qqq#q....
+....q#q##q#q###q....
+...q##q##q#qq###q...
+...q##q##q#q####q...
+..q###qqq##q#####q..
+..q##############q..
+..qqqqqqqqqqqqqqqq..
+....................
+....................
+#
+APRS ] Mail/Post Office
+....................
+....................
+.....llllllllll.....
+...llllllllllllll...
+..llllmhmhmhmhllll..
+..lllmhmhmhmhmhlll..
+..llllllllllllllll..
+..llllllllllllllll..
+..llmlmllmllmlmlll..
+..llmmmlmlmlmlmlll..
+..llmhmlmmmlmlmlll..
+..llmlmlmlmlmlmlll..
+..llmlmlmlmlmlmmll..
+..llllllllllllllll..
+..llllllllllllllll..
+..llll........llll..
+..lll..........lll..
+..lll..........lll..
+....................
+....................
+#
+APRS ^ l Large Aircraft
+....................
+....................
+.........oo.........
+.........oo.........
+........ooo.........
+........ooo.........
+........ooo......o..
+.......oooo.....oo..
+.......oooo....ooo..
+..oooooooooooooooo..
+..oooooooooooooooo..
+.......oooo....ooo..
+.......oooo.....oo..
+........ooo......o..
+........ooo.........
+........ooo.........
+.........oo.........
+.........oo.........
+....................
+....................
+#
+APRS _ Weather Station (blue)
+....................
+....................
+.......hhhhhh.......
+.....hhhhhhhhhh.....
+....hhhhhhhhhhhh....
+...hhhhhhhhhhhhhh...
+...hhhhhhhhhhhhhh...
+..hmmhhhmmhmmhhmmh..
+..hmmhhhmmhmmmmmmh..
+..hmmhhhmmhhmmmmhh..
+..hmmhmhmmhhmmmmhh..
+..hmmmmmmmhmmmmmmh..
+..hmmmhmmmhmmhhmmh..
+...hhhhhhhhhhhhhh...
+...hhhhhhhhhhhhhh...
+....hhhhhhhhhhhh....
+.....hhhhhhhhhh.....
+.......hhhhhh.......
+....................
+....................
+#
+APRS ` Dish Antenna
+....................
+....................
+..q.................
+..qq................
+..qoq...............
+..qooq..............
+...qooqqqqqqqq......
+...qoooq....qq......
+...qooooq..q.q......
+...pqooooqq..q......
+....qoooooq..q......
+.....qoooooq.q......
+....qpqoooooqq......
+...qqqpqoooooq......
+..qqqqqpqoooooq.....
+..qqqqqq.qqooooq....
+..qqqqqqp..pqqooq...
+..qqqqqqqp....qqqq..
+....................
+....................
+#
+APRS a l Ambulance (SSID -1)
+....................
+....................
+....................
+....................
+....................
+.......qqqqqqqqqqq..
+......qqmmjjmmmmmq..
+.....qoqmmjjmmmmmq..
+..qqqqqqjjjjjjmmmq..
+..qmmmmmjjjjjjmmmq..
+..qmmmmmmmjjmmmmmq..
+..qmqqqqmmjjqqqqmq..
+..qqqqqqqmmqqqqqqq..
+..qqqoqqqqqqqqoqqq..
+....qqoq....qoqq....
+.....qq......qq.....
+....................
+....................
+....................
+....................
+#
+APRS b l Bicycle (SSID -4)
+....................
+....................
+.........q..........
+.........qqq........
+.........q..........
+........q...........
+.......qq...qqq.....
+....qqqmqq..q.......
+...qq..m.qqqq.......
+..qq......qqqq......
+..q....m...q.qq.....
+..q...m....q..qq....
+..q....m...q...qq...
+..q.....m..q...qq...
+..qq......qq..q..q..
+...qq....qq...q..q..
+....qqqqqq.....qq...
+....................
+....................
+....................
+#
+APRS c Incident Command Post
+qqqqqqqqqqqqqqqqqqqq
+qmmmmmmmmmmmmmmmmmlq
+qmmmmmmmmmmmmmmmmllq
+qmmmmmmmmmmmmmmmlllq
+qmmmmmmmmmmmmmmllllq
+qmmmmmmmmmmmmmlllllq
+qmmmmmmmmmmmmllllllq
+qmmmmmmmmmmmlllllllq
+qmmmmmmmmmmllllllllq
+qmmmmmmmmmlllllllllq
+qmmmmmmmmllllllllllq
+qmmmmmmmlllllllllllq
+qmmmmmmllllllllllllq
+qmmmmmlllllllllllllq
+qmmmmllllllllllllllq
+qmmmlllllllllllllllq
+qmmllllllllllllllllq
+qmlllllllllllllllllq
+qllllllllllllllllllq
+qqqqqqqqqqqqqqqqqqqq
+#
+APRS d Dual Garage (Fire Department)
+....................
+.........qq.........
+........qjjq........
+.......qjjjjq.......
+......qjjjjjjq......
+.....qjjjjjjjjq.....
+....qjjjjjjjjjjq....
+...qjjjjjjjjjjjjq...
+..qqqqqqqqqqqqqqqq..
+..qjjjjjjjjjjjjjjq..
+..qjmmmjmjmmmjmmjq..
+..qjmjjjmjmjmjmjjq..
+..qjmmjjmjmmmjmmjq..
+..qjmjjjmjmjmjmjjq..
+..qjmjjjmjmjmjmmjq..
+..qjjjjjjjjjjjjjjq..
+..qqqqqqqqqqqqqqqq..
+....................
+....................
+....................
+#
+APRS e l Horse (equestrian)
+....................
+....................
+....................
+..........qq........
+.........qqqq.......
+..........qq........
+.........qqq........
+...qq...q.qq........
+..qqqq....qq........
+.qqqqqqqqqqqqqqqq...
+.qq..qqqqqqqqqqq.q..
+......qqqqqqqqqq..q.
+.......qqq....q.q...
+......q.q....q...q..
+.....q...q....q..q..
+.....q....q....q..q.
+....................
+....................
+....................
+....................
+#
+APRS f l Fire Truck (SSID -3)
+....................
+....................
+....................
+....................
+....................
+....................
+...jjjjmmmmmmmmmmmm.
+..jcccjjmjjmjjmjjmj.
+.jccccjjmjjmjjmjjmj.
+.jjjjjjmmmmmmmmmmmm.
+.jjjjjjjjjjjjjjjjoo.
+.oojqjjjjjjqjjjqjoo.
+...qqq....qqq.qqq...
+....q......q...q....
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS g Glider
+....................
+....................
+....................
+....................
+..jjjj..............
+..jaaajjjj..........
+..jaaaaaaajjjj......
+..j###########jjjj..
+..jjjjjjjjjjjjjjjj..
+....p..........p....
+.....p........p.....
+......p......p......
+.......pccccp.......
+.....gggggggggg.....
+.....ggggggg.gg.....
+....................
+....................
+....................
+....................
+....................
+#
+APRS h Hospital
+....................
+.........qq.........
+........qmmq........
+.......qmmmmq.......
+......qmmmmmmq......
+.....qmmmmmmmmq.....
+....qmmmmmmmmmmq....
+...qmmmmmmmmmmmmq...
+..qqqqqqqqqqqqqqqq..
+...qmmmmmjjmmmmmq...
+...qmmmmmjjmmmmmq...
+...qmmmjjjjjjmmmq...
+...qmmmjjjjjjmmmq...
+...qmmmjjjjjjmmmq...
+...qmmmmmjjmmmmmq...
+...qmmmmmjjmmmmmq...
+...qqqqqqqqqqqqqq...
+....................
+....................
+....................
+#
+APRS i IOTA (island on the air)
+....................
+......k..k..........
+....kkkkkkkkkk......
+....kkkiiiik#kkk....
+..kk##kkii#kk#k.kk..
+..k#kkk#ffk#k.#k....
+.k.k.k#.ffk....k....
+k..k..k.ff..........
+........ff..........
+........ff..........
+........ff..........
+....aeaeffaeaea.....
+..eaeaeaeaeaeaeaea..
+.haeaeaeaeaeaeaeaeh.
+.hhaeaeaeaeaeaeaehh.
+..hhhhhhhhhhhhhhhh..
+...hhhhhhhhhhhhh....
+....................
+....................
+....................
+#
+APRS j l Jeep (SSID -12)
+....................
+....................
+....................
+....................
+..........koooooo...
+.........k...o...o..
+........k...co...co.
+.......kkp..no...po.
+.kkkkkkkkc..nkkkkkkq
+k#kkkkkkk..okkkkkkkq
+nkqqqkkkkpppkkqqqkkq
+nqqcqqkkkkkkkqqcqqnn
+.qcmcqoonnnnnqcmcqq.
+.oqcqo.......oqcqo..
+..oqo.........oqo...
+....................
+....................
+....................
+....................
+....................
+#
+APRS k l Truck (SSID -14)
+....................
+....................
+....................
+....................
+........jjj.........
+.......jjmj.........
+......jjmmj.........
+.....jjmmmj.........
+..jjjjpjjqpjjjjjjj..
+..jjjjpjjjpjjjjjjj..
+..jjjjjpjjpjjjjjjj..
+..qpppjppppjjpppjq..
+..qpcpjjjjjjjpcpjq..
+...ppp.......ppp....
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS l Logged-on Laptop
+....................
+....................
+....qqqqqqqqqqqqqqqq
+....qmmmmmmmmmmmmmmq
+....qmmmmmmmmmmmmmmq
+....qmmmmmmmmmmmmmmq
+....qmmmmmqmmqmmmmmq
+....qmmmmmmqqmmmmmmq
+....qmmmmmmqqmmmmmmq
+....qmmmmmqmmqmmmmmq
+....qmmmmmmmmmmmmmmq
+....qmmmmmmmmmmmmmmq
+....qmmmmmmmmmmmmmmq
+....qqqqqqqqqqqqqqqq
+...qmqmqmqmqmqmqmqq.
+..qqmqmqmqmqmqmqmq..
+.qmmqmqmqmqmqmqmq...
+qqqqqqqqqqqqqqqq....
+....................
+....................
+#
+APRS m Mic-Repeater
+....................
+.......g....g.......
+.......gg..gg.......
+.......g.gg.g.......
+.......g....g.......
+.......g....g.......
+....................
+........gggg........
+.........gg.........
+.........gg.........
+........gggg........
+....................
+........gggg........
+.......g....g.......
+.......g............
+.......g....g.......
+........gggg........
+..ggggg......ggggg..
+....................
+....................
+#
+APRS n Node
+....................
+....................
+....................
+....................
+....................
+....................
+......qqq..qq.......
+......qqq..qq.......
+......qqqq.qq.......
+......qqqq.qq.......
+......qq.qqqq.......
+......qq.qqqq.......
+......qq..qqq.......
+......qq..qqq.......
+......qq...qq.......
+....................
+....................
+....................
+....................
+....................
+#
+APRS o Emergency Operations Center
+....................
+.........pp.........
+........pjjp........
+.......pjjjjp.......
+......pjjjjjjp......
+.....pjjjjjjjjp.....
+....pjjjjjjjjjjp....
+...pjjjjjjjjjjjjp...
+..pjjjjjjjjjjjjjjp..
+...pjmmjjmjjjmjjp...
+...pjmjjmjmjmjmjp...
+...pjmjjmjmjmjjjp...
+...pjmmjmjmjmjjjp...
+...pjmjjmjmjmjjjp...
+...pjmjjmjmjmjmjp...
+...pjmmjjmjjjmjjp...
+...pjjjjjjjjjjjjp...
+....................
+....................
+....................
+#
+APRS p l Rover (puppy dog)
+....................
+....................
+....................
+....................
+....qqqq............
+....qqqq.........q..
+...qmqmq........qq..
+..qqmmmqq......qmq..
+..qqqqmmmqqqqqqmmq..
+.....qmmmmqqqqmmqq..
+......qqmmmmmmmmq...
+......qqmmmmmmmmq...
+......qmqqqqqmmmq...
+......qmq....qmmq...
+......qmq.....qmq...
+.....qqqq....qqmq...
+.....qqq.....qqq....
+....................
+....................
+....................
+#
+APRS q Grid Square Above 128m
+....................
+..q.q.q......q.q.q..
+..q.q.q.ikki.q.q.q..
+..qqqqqqqqqqqqqqqq..
+..q.q.q.ikki.q.q.q..
+..q.q.q.ikki.q.q.q..
+........ikki........
+........ikki........
+........ikki........
+........ikki........
+.......iikkii.......
+.......ikiiki.......
+...qq..iikkii..qq...
+..q..q.iikkii.q..q..
+..q....ikiiki..q....
+..q.qq.ikiiki...q...
+..q..q.iikkii.q..q..
+...qq..iiiiii..qq...
+....................
+....................
+#
+APRS r Antenna, like radio station
+....................
+..q.q.q......q.q.q..
+..q.q.q.lhhl.q.q.q..
+..qqqqqqqqqqqqqqqq..
+..q.q.q.lhhl.q.q.q..
+..q.q.q.lhhl.q.q.q..
+........lhhl........
+........lhhl........
+........lhhl........
+........lhhl........
+.......llhhll.......
+.......lhllhl.......
+.......llhhll.......
+.......llhhll.......
+.......lhllhl.......
+.......lhllhl.......
+.......llhhll.......
+.......llllll.......
+....................
+....................
+#
+APRS s l Ship (power boat) (SSID -8)
+....................
+....................
+....................
+....................
+....................
+....................
+........qqqq.....q..
+.......qqccq....q...
+......qqqqqq...q....
+..iiiiiiiiiiiiiiii..
+..iiiiiiiiiiiiiiii..
+...iiiiiiiiiiiiiii..
+....iiiiiiiiiiiiii..
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS t Truck Stop
+....................
+....................
+..gggggggggggggggg..
+..gggggggggggggggg..
+..gmmmmmmmmggggggg..
+..gmmmmmmmmggggggg..
+..ggggmmggggmmmmgg..
+..ggggmmgggmmmmmmg..
+..ggggmmgggmmggmmg..
+..ggggmmgggmmggggg..
+..ggggmmggggmmgggg..
+..ggggmmgggggmmggg..
+..ggggmmggggggmmgg..
+..ggggmmgggggggmmg..
+..gggggggggmmggmmg..
+..gggggggggmmmmmmg..
+..ggggggggggmmmmgg..
+..gggggggggggggggg..
+....................
+....................
+#
+APRS u l Truck (18-wheeler)
+....................
+....................
+....................
+....................
+....................
+....................
+.llll.llllllllllllll
+.lcll.llllllllllllll
+.lcll.llgggllgglggll
+lllll.llllllllllllll
+lllll.llllllllllllll
+lnlnlqnnnllllllnnnll
+oqoqooqoqo....oqoqo.
+.o....o.o......o.o..
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS v l Van (SSID -15)
+....................
+....................
+....................
+....................
+....................
+.......hhhhhhhhhhh..
+......hccchccchccch.
+.....hcccchccchccch.
+....hccccchccchccch.
+..hhhphhhhhhhhhhhhh.
+.hhhhhhhhhhhhhhhhhj.
+.hhhhhhhhhhhhhhhhhh.
+.ohqqhhhhhhhhhhqqho.
+.hqccqhhhhhhhhqccqh.
+..qccq........qccq..
+...qq..........qq...
+....................
+....................
+....................
+....................
+#
+APRS w Water Station
+....................
+....................
+..gggggggggggggggg..
+..gggggggggggggggg..
+..gmggmgggggggmmgg..
+..gmggmggggggmggmg..
+..gmggmggggggmggmg..
+..gmggmggggggmggmg..
+..gmmmmggmmggmggmg..
+..gmggmgmggmgmggmg..
+..gmggmggggmgmggmg..
+..gmggmggggmgmggmg..
+..gmggmgggmggmggmg..
+..gmggmggmggggmmgg..
+..ggggggmggggggggg..
+..ggggggmmmmgggggg..
+..gggggggggggggggg..
+..gggggggggggggggg..
+....................
+....................
+#
+APRS x X-APRS (Unix)
+....................
+....................
+....................
+.qqqq............qq.
+..qqqq..........qq..
+...qqqq........qq...
+....qqqq......qq....
+.....qqqq....qq.....
+......qqqq..qq......
+.......qqq.qq.......
+.......qq.qqq.......
+......qq..qqqq......
+.....qq....qqqq.....
+....qq......qqqq....
+...qq........qqqq...
+..qq..........qqqq..
+.qq............qqqq.
+....................
+....................
+....................
+#
+APRS y Yagi at QTH
+....................
+..q.q.q.q.q.........
+..qqqqqqqqq.........
+..q.q.q.q.q.........
+......q.............
+......q..qqq........
+......q.qqqqq.......
+......qqqqqqqq......
+......qqqqqqqqq.....
+.....qqqqqqqqqqq....
+....qqqqqqqqqqqqq...
+......q#######q.....
+......q#q###q#q.....
+......q###q###q.....
+......q###q###q.....
+......qqqqqqqqq.....
+....................
+....................
+....................
+....................
+#
+#APRS z
+#
+#APRS {
+#
+#APRS | Reserved - TNC Stream Switch
+#
+#APRS }
+#
+#APRS ~ Reserved - TNC Stream Switch
+#
+#
+#
+# -----------------------------------
+# -----------------------------------
+#
+# Secondary table section starts here
+# -----------------------------------
+# -----------------------------------
+#
+#
+#
+TABLE \
+#
+APRS ! Emergency
+....................
+.........jj.........
+........jjjj........
+........jjjj........
+.......jjmmjj.......
+.......jjmmjj.......
+......jjmqqmjj......
+......jjmqqmjj......
+.....jjmmqqmmjj.....
+.....jjmmqqmmjj.....
+....jjmmmqqmmmjj....
+....jjmmmqqmmmjj....
+...jjmmmmmmmmmmjj...
+...jjmmmmqqmmmmjj...
+..jjmmmmmqqmmmmmjj..
+..jjmmmmmmmmmmmmjj..
+.jjjjjjjjjjjjjjjjjj.
+..jjjjjjjjjjjjjjjj..
+....................
+....................
+#
+#APRS " Reserved
+#
+APRS # Digi (green star) (w overlay)
+....................
+....................
+.........kk.........
+.........kk.........
+........kmmk........
+........kmmk........
+..kkkkkkkmmkkkkkkk..
+...kmmmmmmmmmmmmk...
+....kmmmmmmmmmmk....
+.....kmmmmmmmmk.....
+.....kmmmmmmmmk.....
+....kmmmmmmmmmmk....
+...kmmmmmmmmmmmmk...
+..kkkkkkkmmkkkkkkk..
+........kmmk........
+........kmmk........
+.........kk.........
+.........kk.........
+....................
+....................
+#
+APRS $ Bank or ATM (green box)
+....................
+....................
+....kkkkkkkkkkk.....
+...kkkkkmkmkkkkk....
+..kkkkkmmmmmkkkkk...
+..kkkkmkmkmkmkkkk...
+..kkkkmkmkmkkkkkk...
+..kkkkmkmkmkkkkkk...
+..kkkkkmmkmkkkkkk...
+..kkkkkkmkmkkkkkk...
+..kkkkkkmmmkkkkkk...
+..kkkkkkmkmmkkkkk...
+..kkkkkkmkmkmkkkk...
+..kkkkkkmkmkmkkkk...
+..kkkkmkmkmkmkkkk...
+..kkkkkmmmmmkkkkk...
+...kkkkkmkmkkkkk....
+....kkkkkkkkkkk.....
+....................
+....................
+#
+APRS % Power Plant (w overlay)
+nnoooooooooonn......
+..nnnooooooooon.....
+.....nnnooooooonn...
+........nnnoooooon..
+...........nnnoooon.
+..............nnnoon
+................qqqq
+................qqqq
+..........q...q.qqqq
+.........qq..qq.qqqq
+........qqq.qqq.qqqq
+......qqqqqqqqqqqqqq
+......qqqqqqqq#qqqqq
+......qqqqqqq#qqqqqq
+......qqqqqq#qqqqqqq
+......qqqqqqq#qqqqqq
+......qqqqqqqq#qqqqq
+......qqqqqqq#qqqqqq
+......qqqqqq#qqqqqqq
+......qqqqqqqqqqqqqq
+#
+APRS & Any Gateway (diamond) (w overlay)
+....................
+....................
+.........qq.........
+........qqqq........
+.......qqqqqq.......
+......qqmmmmqq......
+.....qqmmmmmmqq.....
+....qqmmmmmmmmqq....
+...qqmmmmmmmmmmqq...
+..qqqmmmmmmmmmmqqq..
+..qqqmmmmmmmmmmqqq..
+...qqmmmmmmmmmmqq...
+....qqmmmmmmmmqq....
+.....qqmmmmmmqq.....
+......qqmmmmqq......
+.......qqqqqq.......
+........qqqq........
+.........qq.........
+....................
+....................
+#
+APRS ' Crash Site
+..ppppppppp.........
+....pppppppp........
+.......ppppp........
+.......ppppp........
+.......pppp.........
+......pppp..........
+.....ppp........j...
+.....ppp.......jmj..
+......ppp.....jmmj..
+.......ppp....jmaj..
+..jjj....pp...jamj..
+..jmmj...pp..jammj..
+..jmmmj.p...jmmmj...
+...jmmmjj..jmmmj....
+....jmmmj.jmmmj.....
+.....jmmjjjjjj......
+..kkkkjjjjjjjkkkkk..
+..ffffffffffffffff..
+j.....j.j...........
+..jj..j..j..........
+#
+APRS ( Cloudy
+....................
+....................
+..ccccccccc.........
+...ccccccccccc......
+.....ccnccccccc.....
+........ncccccccc...
+...cccccccccccccc...
+..ccccccccnccccccc..
+..cccccccccncccccc..
+..cccccccccncccccc..
+..ccccccccnccccccc..
+..nnnccnnnccccccnn..
+...nnpppnnnppppnn...
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS ) MEO (MODIS EARTH OBSERVATION)
+....................
+....................
+....................
+....................
+....................
+....jjjjjqqjjjjj....
+....jqqjjqqjjqqj....
+....jjjqjqqjqjjj....
+....jjjjqqqqjjjj....
+....jqqqqqqqqqqj....
+....jqqqqqqqqqqj....
+....jjjjqqqqjjjj....
+....jjjqjqqjqjjj....
+....jqqjjqqjjqqj....
+....jjjjjqqjjjjj....
+....................
+....................
+....................
+....................
+....................
+#
+APRS * Snow
+....................
+....................
+............h.......
+...........hh.......
+....hh....hhh.......
+....hhhh..hhh.......
+.....hhhh.hhh.......
+......hhhhhh..hhhh..
+......hhhhhhhhhhh...
+.......hhhhhhhhh....
+....hhhhhhhhh.......
+...hhhhhhhhhhh......
+..hhhh..hhhhhh......
+........hh.hhhh.....
+.......hhh..hhhh....
+.......hhh....hh....
+.......hh...........
+.......h............
+....................
+....................
+#
+APRS + Church
+....................
+....................
+.........qq.........
+.........qq.........
+.........qq.........
+...qqqqqqqqqqqqqq...
+...qqqqqqqqqqqqqq...
+.........qq.........
+.........qq.........
+.........qq.........
+.........qq.........
+.........qq.........
+.........qq.........
+.........qq.........
+.........qq.........
+.........qq.........
+.........qq.........
+.........qq.........
+....................
+....................
+#
+APRS , Girl Scouts
+....................
+....................
+......jjjjjjj.......
+......j.....j.......
+.......j...j........
+..jj...j...j...jjj..
+..j.jjjj...jjjj..j..
+..j..............j..
+..j..............j..
+..j..............j..
+..j..............j..
+..jjjj.......jjjjj..
+......j.....j.......
+.......j...j........
+........j.j.........
+.ppp.....j.......p..
+p................p..
+.pp..pp.ppp.p.p.ppp.
+...p.p..p.p.p.p..p..
+ppp..pp.ppp.ppp..p..
+#
+APRS - House (HF)
+....................
+.........qqq........
+..q..q....q...qqqq..
+..q..q....q...q.....
+..qqqq....q...qqq...
+..q..q....q...q.....
+..q..q...qqq..q.....
+........qqqqq.......
+.......qqqqqqq......
+......qqqqqqqqq.....
+.....qqqqqqqqqqq....
+....qqqqqqqqqqqqq...
+......q#######q.....
+......q#q###q#q.....
+......q###q###q.....
+......q###q###q.....
+......qqqqqqqqq.....
+....................
+....................
+....................
+#
+APRS . Ambiguous Plot (Big Question Mark)
+.....jjjjjjjjjj.....
+....jjjjjjjjjjjj....
+..jjjj........jjjj..
+.jjj............jjj.
+jjj..............jjj
+jjj..............jjj
+.................jjj
+................jjj.
+...............jjj..
+..............jjj...
+...........jjjjj....
+........jjjjjj......
+........jjjj........
+........jjjj........
+........jjjj........
+....................
+....................
+........jjjj........
+........jjjj........
+........jjjj........
+#
+APRS / Waypoint (destination)
+..q.......q.qqqqqq..
+..q.......q.q....q..
+..q.......q.q....q..
+...q..q..q..qqqqqq..
+...qq.q.qq..q.......
+....qq.qq...q.......
+....................
+........jjjj........
+.......jjjjjj.......
+.......jjjjjj.......
+.......jjjjjj.......
+.......jjjjjj.......
+........jjjj........
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS 0 Circle (w overlay)
+........qqqq........
+......qmmmmmmq......
+.....qmmmmmmmmq.....
+...qmmmmmmmmmmmmq...
+..qmmmmmmmmmmmmmmq..
+.qmmmmmmmmmmmmmmmmq.
+.qmmmmmmmmmmmmmmmmq.
+qmmmmmmmmmmmmmmmmmmq
+qmmmmmmmmmmmmmmmmmmq
+qmmmmmmmmmmmmmmmmmmq
+qmmmmmmmmmmmmmmmmmmq
+qmmmmmmmmmmmmmmmmmmq
+qmmmmmmmmmmmmmmmmmmq
+.qmmmmmmmmmmmmmmmmq.
+.qmmmmmmmmmmmmmmmmq.
+..qmmmmmmmmmmmmmmq..
+...qmmmmmmmmmmmmq...
+.....qmmmmmmmmq.....
+......qmmmmmmq......
+........qqqq........
+#
+#APRS 1
+#
+#APRS 2
+#
+#APRS 3
+#
+#APRS 4
+#
+#APRS 5
+#
+#APRS 6
+#
+#APRS 7
+#
+#APRS 8
+#
+APRS 9 Gas Station (blue pump)
+....................
+....................
+......llll..........
+.....llllll.........
+....llmmmmlll.......
+....lllllllll.......
+....llmmmmll.l......
+....llllllll.l......
+....llllllll..l.....
+....llllllll..l.....
+....llllllll..l.....
+....llllllll..l.....
+....lllllllll.l.....
+....llllllll.l......
+....llllllll........
+....llllllll........
+....llllllll........
+....llllllll........
+....................
+....................
+#
+APRS : Hail
+....................
+....................
+.........qq.........
+........qmmq........
+.......qmmmmq.......
+......qmmmmmmq......
+.....qmmmmmmmmq.....
+....qmmmmmmmmmmq....
+...qqqqqqqqqqqqqq...
+....................
+....................
+...qqqqqqqqqqqqqq...
+....qmmmmmmmmmmq....
+.....qmmmmmmmmq.....
+......qmmmmmmq......
+.......qmmmmq.......
+........qmmq........
+.........qq.........
+....................
+....................
+#
+APRS ; Park/Picnic Area
+....................
+....................
+....hhhhhhhhhhhh....
+...hhhhhhhhhhhhhh...
+...hhhhhhhhhhhhhh...
+...hhhhhhhhhhhhhh...
+...hhhhmmmmmmhhhh...
+...hhhhhmhhmhhhhh...
+...hhhhhhmmhhhhhh...
+...hhhhhhmmhhhhhh...
+...hhhhhmhhmhhhhh...
+...hmmmmmmmmmmmmh...
+...hhhmhhhhhhmhhh...
+...hhmhhhhhhhhmhh...
+...hmhhhhhhhhhhmh...
+...hhhhhhhhhhhhhh...
+...hhhhhhhhhhhhhh...
+....hhhhhhhhhhhh....
+....................
+....................
+#
+APRS < NWS Advisory (gale flag)
+....................
+....................
+........qq..........
+........qjqq........
+........qjjjqq......
+........qjjjjjq.....
+........qjjjqq......
+........qjqq........
+........qq..........
+........q...........
+........q...........
+........q...........
+........q...........
+........q...........
+........q...........
+........q...........
+........q...........
+........q...........
+....................
+....................
+#
+#APRS =
+#
+APRS > l Car (w overlay)
+....................
+....................
+....................
+....................
+.........ppppp......
+........pcccncp.....
+.......pccccnccp....
+......pcccccncccp...
+...pppnqnnnnnnnnnp..
+..pmmmmmmmmmmmmmmmp.
+.pmmmmmmmmmmmmmmmmep
+p#mmoommmmmmmmmoommp
+pmmonnommmmmmmonnomp
+.ppqnnqpppppppqnnqp.
+....qq.........qq...
+....................
+....................
+....................
+....................
+....................
+#
+APRS ? Information Kiosk (blue box with ?)
+....................
+....................
+..hhhhhhhhhhhhhhhh..
+..hhhhhhmmmhhhhhhh..
+..hhhhhmmmmmhhhhhh..
+..hhhhmmhhhmmhhhhh..
+..hhhmmhhhhhmmhhhh..
+..hhhmmhhhhhmmhhhh..
+..hhhhhhhhhhmmhhhh..
+..hhhhhhhhhmmhhhhh..
+..hhhhhhhhmmhhhhhh..
+..hhhhhhhmmhhhhhhh..
+..hhhhhhhmmhhhhhhh..
+..hhhhhhhmmhhhhhhh..
+..hhhhhhhhhhhhhhhh..
+..hhhhhhhmmhhhhhhh..
+..hhhhhhhmmhhhhhhh..
+..hhhhhhhhhhhhhhhh..
+....................
+....................
+#
+APRS @ Hurricane/Tropical Storm
+....................
+....................
+.....l...lggggl.....
+....g..lgllllllgl...
+...lg..glllgggllg...
+...g..llllglllglll..
+..ll..gllglllllglg..
+..gl..lllglllllllg..
+..ll..llgllgll.lll..
+..ll..lll..lll..ll..
+..ll..lll..lll..ll..
+..gll.llgllgll..lg..
+..glllllllglll..lg..
+..glglllllgllg..ll..
+..lllglllgllll..g...
+...lllggglllg..gl...
+...lgglllllgl..g....
+.....lggggl...l.....
+....................
+....................
+#
+APRS A Box (w overlay)
+....................
+....................
+..qqqqqqqqqqqqqqqq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qqqqqqqqqqqqqqqq..
+....................
+....................
+#
+APRS B Blowing Snow
+....................
+....................
+....................
+..qq..q...q..q...q..
+..q.q.q..q.q.q...q..
+..qq..q..q.q.q.q.q..
+..q.q.q..q.q.qq.qq..
+..qq..qq..q..q...q..
+....................
+..qq.q.q..q..q...q..
+..q..qqq.q.q.q...q..
+...q.qqq.q.q.q.q.q..
+...q.qqq.q.q.qq.qq..
+..qq.q.q..q..q...q..
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS C Coast Guard
+....................
+....................
+....................
+....................
+....................
+...qqqq.....qqqqq...
+..q....q...q........
+..q........q........
+..q........q........
+..q........q..qqqq..
+..q........q.....q..
+..q....q...q.....q..
+...qqqq.....qqqqqq..
+....................
+..g.g.g.g.g.g.g.g...
+...g.g.g.g.g.g.g.g..
+....................
+....................
+....................
+....................
+#
+APRS D Drizzle
+....................
+....................
+....................
+..qq..qqq..q.qqqqq..
+..q.q.q..q.q....q...
+..q.q.qqq..q...q....
+..q.q.q.q..q..q.....
+..qq..q..q.q.qqqqq..
+....................
+..qqq....q...q.q.q..
+..q..q..q.q..q.qqq..
+..qqq..qqqqq.q.qqq..
+..q.q..q...q.q.qqq..
+..q..q.q...q.q.q.q..
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS E Smoke
+....................
+....................
+...mqqqqqqqqqqqm....
+.mqqqqqqqqqqqqqqm...
+...mqqqqqqqqqqqm....
+......mqqqqqqqqqqm..
+........mqqqqm......
+..........mqppqm....
+........mqqqqm......
+.......mqppqm.......
+........mqjjqm......
+........mqjpqm......
+......mqqjjqqqm.....
+....mqqqjjqqqqqm....
+...mqqqjjjqqqppqm...
+..mqqqqqjjppqqqqqm..
+.mqqqqqqqjjqqqqqqqm.
+.mqqqqqqppjjjjrqqqm.
+.mmmmmmmmmmmmmmmmmm.
+....................
+#
+APRS F Freezing Rain
+....................
+....................
+....................
+..qqqqq.qqq..qqqqq..
+..q.....q..q....q...
+..qqqq..qqq....q....
+..q.....q.q...q.....
+..q.....q..q.qqqqq..
+....................
+..qqq....q...q.q.q..
+..q..q..q.q..q.qqq..
+..qqq..qqqqq.q.qqq..
+..q.q..q...q.q.qqq..
+..q..q.q...q.q.q.q..
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS G Snow Shower
+....................
+....................
+.......q....q.......
+........qq.q........
+.........qqqqq......
+......qqqqq.........
+........q.qq........
+.......q....q.......
+....................
+..qqqqqqqqqqqqqqqq..
+..qmmmmmmmmmmmmmmq..
+...qmmmmmmmmmmmmq...
+....qmmmmmmmmmmq....
+.....qmmmmmmmmq.....
+......qmmmmmmq......
+.......qmmmmq.......
+........qmmq........
+.........qq.........
+....................
+....................
+#
+APRS H Haze
+q..q................
+q..q................
+qqqq................
+q..q................
+q..q................
+......q.............
+.....q.q............
+....q...q...........
+....qqqqq...........
+....q...q...........
+..........qqqqq.....
+.............q......
+............q.......
+...........q........
+..........qqqqq.....
+................qqqq
+................q...
+................qqqq
+................q...
+................qqqq
+#
+APRS I Rain Shower
+....................
+....................
+........qqqq........
+.......qqqqqq.......
+......qqqqqqqq......
+......qqqqqqqq......
+......qqqqqqqq......
+.......qqqqqq.......
+........qqqq........
+..qqqqqqqqqqqqqqqq..
+..qmmmmmmmmmmmmmmq..
+...qmmmmmmmmmmmmq...
+....qmmmmmmmmmmq....
+.....qmmmmmmmmq.....
+......qmmmmmmq......
+.......qmmmmq.......
+........qmmq........
+.........qq.........
+....................
+....................
+#
+APRS J Lightning
+....................
+....................
+..............qqqq..
+.............qq##q..
+.............q###q..
+............qq##qq..
+.......q....q###q...
+......qqq...q##qq...
+......q#qq.q##qq....
+.....qq##qqq##q.....
+.....q####q##qq.....
+....qq#qq###qq......
+....q#qqqq#qq.......
+...qq#q..qqq........
+...q#q....q.........
+..qq#q..............
+..q#q...............
+..qq................
+..q.................
+....................
+#
+APRS K Kenwood
+....................
+....................
+....................
+.......jjjjjjj......
+....qqq.jjjjj.qqq...
+....qqq..jjj..qqq...
+....qqq..jjj..qqq...
+....qqqq.cqc.qqq....
+.....qqqqcqcqqqq....
+......qqqqqqqqq.....
+......qqqqcqqqq.....
+.......qqq.qqq......
+.......qqq.qqq......
+........qq.qq.......
+........q...q.......
+....................
+....................
+....................
+....................
+....................
+#
+APRS L Lighthouse
+....................
+....................
+....q..........q....
+.....q..qqqq..q.....
+......q.qmmq.q......
+......qqqmmqqq......
+.....q.qqqqqq.q.....
+....q..qqqqqq..q....
+.......qqqqqq.......
+.......qqqqqq.......
+.......qqqqqq.......
+.......qqqqqq.......
+......qqqqqqqq......
+......qqqqqqqq......
+......qqqqqqqq......
+......qqqqqqqq......
+......qqqqqqqq......
+......qqqqqqqq......
+....................
+....................
+#
+#APRS M
+#
+APRS N Navigation Buoy
+....................
+....................
+........qqqqq.......
+........q...q.......
+........q...q.......
+........qqqqq.......
+........qmmmq.......
+........qmmmq.......
+........qmmmq.......
+........qmmmq.......
+........qmmmq.......
+........qmmmq.......
+........qmmmq.......
+...qqqqqqqqqqqqqqq..
+hh.....hhh.....hhh..
+..h...h...h...h...h.
+...hhh.....hhh.....h
+....h.......h......h
+....................
+....................
+#
+APRS O Rocket
+..........q.........
+..........q.........
+..........q.........
+..........q.........
+.........qmq........
+........qmmmq.......
+........qmmmq.......
+........qmmmq.......
+........qmmmq.......
+........qmmmq.......
+........qmmmq.......
+........qmmmq.......
+........qmmmq.......
+........qmqmq.......
+........qmqmq.......
+.......qqmqmqq......
+......qqqmqmqqq.....
+.....qqqqmqmqqqq....
+....qqqqqmqmqqqqq...
+....qqqqqqqqqqqqq...
+#
+APRS P Parking
+....................
+....................
+....hhhhhhhhhhh.....
+...hhhhhhhhhhhhh....
+...hhmmmmmmmmhhh....
+...hhmmmmmmmmmhh....
+...hhmmhhhhhmmhh....
+...hhmmhhhhhmmhh....
+...hhmmhhhhhmmhh....
+...hhmmmmmmmmmhh....
+...hhmmmmmmmmhhh....
+...hhmmhhhhhhhhh....
+...hhmmhhhhhhhhh....
+...hhmmhhhhhhhhh....
+...hhmmhhhhhhhhh....
+...hhmmhhhhhhhhh....
+...hhhhhhhhhhhhh....
+....hhhhhhhhhhh.....
+....................
+....................
+#
+APRS Q Earthquake
+....................
+....................
+.......qqqqqq.......
+.....qqmmmmmmqq.....
+....qmmmmmmmmmmq....
+...qmmmmqqqqmmmmq...
+...qmmqqmmmmqqmmq...
+..qmmmqmmmmmmqmmmq..
+..qmmqmmmmmmmmqmmq..
+..qmmqmmmqqmmmqmmq..
+..qmmqmmmqqmmmqmmq..
+..qmmqmmmmmmmmqmmq..
+..qmmmqmmmmmmqmmmq..
+...qmmqqmmmmqqmmq...
+...qmmmmqqqqmmmmq...
+....qmmmmmmmmmmq....
+.....qqmmmmmmqq.....
+.......qqqqqq.......
+....................
+....................
+#
+APRS R Restaurant
+....................
+....................
+..hhhhhhhhhhhhhhhh..
+..hhhhhhhhmhhhhhhh..
+..hmhhhmhhmhhhmhhh..
+..hmhmhmhhmhhmhmhh..
+..hmhmhmhhmhmhhhmh..
+..hmhmhmhhmhmhhhmh..
+..hmhmhmhhmhmhhhmh..
+..hhmmmhhhmhhmhmhh..
+..hhhmhhhhmhhhmhhh..
+..hhhmhhhhmhhhmhhh..
+..hhhmhhhhmhhhmhhh..
+..hhhmhhhhmhhhmhhh..
+..hhhmhhhhmhhhmhhh..
+..hhhmhhhhmhhhmhhh..
+..hhhhhhhhmhhhhhhh..
+..hhhhhhhhhhhhhhhh..
+....................
+....................
+#
+APRS S Satellite/Pacsat
+....................
+..........q.........
+..........q.........
+..........q.........
+..........q.........
+....n...qqqqqqqq....
+....cn.q..q...qq....
+....cnqqqqqqqq.q....
+....cnqqqqqqqq.q....
+....cnqqqqqqqq.q....
+....n.qqqqqqqq.q....
+......qqqqqqqq.q....
+......qqqqqqqqq.....
+......qqqqqqqq......
+.....q........q.....
+....q..........q....
+...q............q...
+..q..............q..
+....................
+....................
+#
+APRS T Thunderstorm
+....................
+....................
+.....qqqqqqqqqqq....
+...qqqmmqqqcmmmmq...
+...qmmmmmqqcmmmmq...
+..qmmmmmmqqqcmpppq..
+..qmmmccqqqqcppppq..
+..pqqqqccqqqcppppq..
+..pppqpcpppppppppp..
+..pppppppppppppppp..
+..ppppppppppppppp...
+...pppppppppppp.....
+.........q#q........
+........q#q.........
+.......q###q........
+........q#q.........
+.......q#q..........
+.......qq...........
+....................
+....................
+#
+APRS U Sunny
+....................
+....................
+....................
+......a..a..a.......
+.......a.a.a........
+....a.........a.....
+.....a.#####.a......
+..a...#######...a...
+...a.#########.a....
+.....#########......
+..aa.#########.aa...
+.....#########......
+...a.#########.a....
+..a...#######...a...
+.....a.#####.a......
+....a.........a.....
+.......a.a.a........
+......a..a..a.......
+....................
+....................
+#
+APRS V VORTAC Nav Aid
+....................
+....................
+....................
+....................
+...qq..........qq...
+..qqqqqqqqqqqqqqqq..
+.qqqqq........qqqqq.
+qqqqq..........qqqqq
+qqqq.....qq.....qqqq
+.qq.....qqqq.....qq.
+..q.....qqqq.....q..
+...q.....qq.....q...
+....q..........q....
+.....q........q.....
+......qqqqqqqq......
+......qqqqqqqq......
+......qqqqqqqq......
+......qqqqqqqq......
+....................
+....................
+#
+APRS W NWS Site (w overlay)
+....................
+....................
+.......hhhhhh.......
+.....hhmmmmmmhh.....
+....hmmmmmmmmmmh....
+...hmmmmmmmmmmmmh...
+...hmmmmmmmmmmmmh...
+..hppmmmppmppmmpph..
+..hppmmmppmpppppph..
+..hppmmmppmmppppmh..
+..hppmpmppmmppppmh..
+..hpppppppmpppppph..
+..hpppmpppmppmmpph..
+...hmmmmmmmmmmmmh...
+...hmmmmmmmmmmmmh...
+....hmmmmmmmmmmh....
+.....hhmmmmmmhh.....
+.......hhhhhh.......
+....................
+....................
+#
+APRS X Pharmacy Rx
+....................
+....................
+..pppppppp..........
+..ppppppppp.........
+..pp.....pp.........
+..pp.....pp.........
+..pp....pp..........
+..ppppppp...........
+..pppppp............
+..pp..pp............
+..pp...pp...........
+..pp....pp.....pp...
+..pp.....pp...pp....
+..pp......pp.pp.....
+...........ppp......
+...........pp.......
+..........pp.pp.....
+.........pp...pp....
+........pp.....pp...
+....................
+#
+#APRS Y
+#
+#APRS Z
+#
+APRS [ Wall Cloud
+....................
+....................
+................ll..
+..............llcl..
+............llcccl..
+..........llccllcl..
+........llccclllcl..
+......llccccllcccl..
+....llcccllcllcccl..
+..llcccccllcllcccl..
+..lccccccllcllcccl..
+..lcllcccllcllcccl..
+..lcllclcllcllcccl..
+..lclllllllcllcccl..
+..lclllclllcllllcl..
+..lcllcccllcclllcl..
+..lccccccccccccccl..
+..llllllllllllllll..
+....................
+....................
+#
+#APRS \
+#
+#APRS ]
+#
+APRS ^ l Aircraft (w overlay)
+....................
+....................
+.........nn.........
+.........nn.........
+........n.n.........
+........n.n.........
+........n.n......n..
+.......n..n.....nn..
+.......n..n....n.n..
+..n.n.n.n.n.n.n..n..
+..n.n.n.n.n.n.n..n..
+.......n..n....n.n..
+.......n..n.....nn..
+........n.n......n..
+........n.n.........
+........n.n.........
+.........nn.........
+.........nn.........
+....................
+....................
+#
+APRS _ WX Stn with digi (green) (w overlay)
+....................
+....................
+.......kkkkkk.......
+.....kkkkkkkkkk.....
+....kkkkkkkkkkkk....
+...kkkkkkkkkkkkkk...
+...kkkkkkkkkkkkkk...
+..kmmkkkmmkmmkkmmk..
+..kmmkkkmmkmmmmmmk..
+..kmmkkkmmkkmmmmkk..
+..kmmkmkmmkkmmmmkk..
+..kmmmmmmmkmmmmmmk..
+..kmmmkmmmkmmkkmmk..
+...kkkkkkkkkkkkkk...
+...kkkkkkkkkkkkkk...
+....kkkkkkkkkkkk....
+.....kkkkkkkkkk.....
+.......kkkkkk.......
+....................
+....................
+#
+APRS ` Rain
+....................
+....................
+pppppppppppppppppppp
+pppppppppppppppppppp
+pppppppppppppppppppp
+pppppppppppppppppppp
+...pp...pp...pp...pp
+....................
+....................
+..p..p..p..p..p..p..
+....................
+....................
+.p..p..p..p..p..p...
+....................
+....................
+...p..p..p..p..p..p.
+....................
+....................
+.p..p...p...p...p...
+....................
+#
+APRS a A=ARES R=RACES W=Winlink etc. (w overlay)
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+...q..qq..qq..q.....
+..q.q.q.q.q.q.q.....
+..qqq.qq..qq..q.....
+..q.q.qq..qq..q.....
+..q.q.q.q.q.q.qqq...
+....................
+....................
+#
+APRS b Blowing Dust/Sand
+....................
+....................
+.....qqq............
+...qqqmmq.......q...
+...qmmmmmq....qq..q.
+..qmmmmmmq..qq..qq..
+..qmmmmqqqqqqqqq....
+..qnmnmccqqqqq......
+..qmnmncqqqq..qqqq..
+..qnmnmnmnq.qqq.....
+..qmnmnmnmq....qqq..
+...qqqqqqq.......q..
+....................
+..qq..q...q..q...q..
+..q.q.q..q.q.q...q..
+..qq..q..q.q.q.q.q..
+..q.q.q..q.q.qq.qq..
+..qq..qq..q..q...q..
+....................
+....................
+#
+APRS c Civil Defense (R=RACES, C=CERTS) (w overlay)
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+...qqqq...qqqq......
+..q.......q...q.....
+..q.......q...q.....
+..q.......q...q.....
+...qqqq...qqqq......
+....................
+....................
+#
+APRS d DX spot (by callsign prefix)
+....................
+..q.q.q......q.q.q..
+..q.q.q.lhhl.q.q.q..
+..qqqqqqqqqqqqqqqq..
+..q.q.q.lhhl.q.q.q..
+..q.q.q.lhhl.q.q.q..
+........lhhl........
+........lhhl........
+........lhhl........
+........lhhl........
+.......llhhll.......
+.......lhllhl.......
+.......llhhll.......
+..qqq..llhhll.q..q..
+..q..q.lhllhl.q..q..
+..q..q.lhllhl..qq...
+..q..q.llhhll.q..q..
+..qqq..llllll.q..q..
+....................
+....................
+#
+APRS e Sleet
+....................
+....................
+.....qqqqqqqqqqq....
+...qqqmmqqqqmmmmq...
+..qmmmmmmqqqmmmmmq..
+.qmmmmmmmqqqcmppppq.
+.qmmmmqqqqqqcpppppq.
+.ppqqqqccqqqcpppppq.
+.pppqpccppppppppppp.
+.pppppppppppppppppp.
+..pppppppppppppppp..
+...ppppppppppppp....
+....................
+...qq.q..qq.qq.qqq..
+..q...q..q..q...q...
+...q..q..qq.qq..q...
+....q.q..q..q...q...
+..qq..qq.qq.qq..q...
+....................
+....................
+#
+APRS f Funnel Cloud
+....................
+....................
+..qqqq....cnnnnnc...
+..q......cnnppppnc..
+..qqq....nnppppppn..
+..q......cnpppppnc..
+..q.......cnpppnc...
+..q........cpppn....
+............npppc...
+............cpppc...
+...qq......cnppn....
+..q..q.....pppc.....
+..q.......npp.......
+..q.......pppc......
+..q.......pppc..c...
+..q..q....npncc.c...
+...qq......cppcc....
+.............pq.....
+....................
+....................
+#
+APRS g Gale Flags
+....................
+....................
+........qq..........
+........qjqq........
+........qjjjqq......
+........qjjjjjq.....
+........qjjqqq......
+........qjq.........
+........qq..........
+........qjqq........
+........qjjjqq......
+........qjjjjjq.....
+........qjjjqq......
+........qjqq........
+........qq..........
+........q...........
+........q...........
+........q...........
+....................
+....................
+#
+APRS h Ham Store
+....................
+.........pp.........
+........p##p........
+.......p####p.......
+......p######p......
+.....p########p.....
+....p##########p....
+...p############p...
+..p##############p..
+.pp##############pp.
+..p##############p..
+..p#p##p##p##p#p#p..
+..p#p##p#p#p#ppp#p..
+..p#pppp#ppp#p#p#p..
+..p#p##p#p#p#p#p#p..
+..p#p##p#p#p#p#p#p..
+..p##############p..
+..pppppppppppppppp..
+....................
+....................
+....................
+#
+APRS i Indoor Short Range Digi (w overlay)
+....................
+....................
+..ppp...............
+..p..p..............
+..p..p..............
+..p..p..............
+..ppp...p...........
+........p...........
+........p...........
+........p...........
+........p...ppp.....
+...........p........
+...........p.pp.....
+...........p..p.....
+............ppp..p..
+.................p..
+.................p..
+.................p..
+.................p..
+....................
+#
+APRS j l Work Zone (steam shovel)
+....................
+....................
+....................
+....................
+........pp..........
+.......pppp.........
+......pp..pp........
+.....pp....pp.......
+p...pp......pppppp..
+.ppppp......p#pp#p..
+.p###p......p#pp#p..
+.ppppp....pp#####p..
+..........p######p..
+..........ppppppppp.
+.........pmmmp.pmmmp
+.........ppppp.ppppp
+....................
+....................
+....................
+....................
+#
+APRS k l SUV
+....................
+....................
+....................
+....................
+..........ddddddddd.
+.........d...d....d.
+........d....d....d.
+.......ddp...d....d.
+.ddddddddddddddddddq
+d#dddddddddddddddddq
+ndqqqddddpppddqqqddq
+nqqcqqdddddddqqcqqnn
+.qcmcqoonnnnnqcmcqq.
+.oqcqo.......oqcqo..
+..oqo.........oqo...
+....................
+....................
+....................
+....................
+....................
+#
+APRS l Area Symbols (box, circle, etc)
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+.........jj.........
+.........jj.........
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS m Value Signpost (3-char display)
+....................
+....................
+.........qq.........
+...qqqqqqqqqqqqqq...
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+..qmmmmmmmmmmmmmmq..
+...qqqqqqqqqqqqqq...
+.........qq.........
+.........qq.........
+.........qq.........
+.........qq.........
+.........qq.........
+.........qq.........
+....................
+....................
+#
+APRS n Triangle (w overlay)
+....................
+....................
+....................
+....................
+....................
+....................
+.........jj.........
+.........jj.........
+........jjjj........
+........jjjj........
+.......jjjjjj.......
+.......jjjjjj.......
+......jjjjjjjj......
+......jjjjjjjj......
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS o Small Circle
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+.........jj.........
+.......j....j.......
+......j......j......
+......j......j......
+......j......j......
+.......j....j.......
+.........jj.........
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS p Partly Cloudy
+............q.......
+........i.i.k.i.k...
+.........k......i...
+...........q#q...i..
+......iqqq#####k.k..
+.....qooooq#####i.ik
+....ioooooo#####q...
+...iioonnooqqq###.ki
+..qooqqncoqqonq##...
+.qoonooonooooooqk.ik
+.qnncnonnnonnooq....
+.qoonnnccnnccnoq.i..
+..qqoonnnnnnoqi.k...
+....qqqqqqqqq.i.i...
+....hlhlh.lhq.k.....
+....h.h.l.hh........
+....l.lh.l.l........
+....h.hh.h.h........
+...l.l.l.lh.........
+....................
+#
+#APRS q
+#
+APRS r Restrooms
+hhhhhhhhhhhhhhhhhhhh
+hhhhhhhhhmhhhhhhhhhh
+hhhhhhhhhmhhhhhhhhhh
+hhhhmhhhhmhhhhhmhhhh
+hhhmmmhhhmhhhhmmmhhh
+hhhhmhhhhmhhhhhmhhhh
+hhhhmhhhhmhhhhhmhhhh
+hmmmmmmmhmhhmmmmmmmh
+hhhhmhhhhmhhhhhmhhhh
+hhhhmhhhhmhhhhhmhhhh
+hhhhmhhhhmhhhhmmmhhh
+hhhhmhhhhmhhhhmmmhhh
+hhhmhmhhhmhhhmmmmmhh
+hhmhhhmhhmhhhmmmmmhh
+hmhhhhhmhmhhmmmmmmmh
+hhhhhhhhhmhhhhhhhhhh
+hhhhhhhhhmhhhhhhhhhh
+hhhhhhhhhmhhhhhhhhhh
+hhhhhhhhhmhhhhhhhhhh
+hhhhhhhhhhhhhhhhhhhh
+#
+APRS s l Ship/Boat (top view) (w overlay)
+....................
+....................
+....................
+....................
+....................
+....................
+........qqqq.....q..
+.......q...q....q...
+......q....q...q....
+..iiii.....iiiiiii..
+..i..............i..
+...i.............i..
+....iiiiiiiiiiiiii..
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS t Tornado
+.......mmmmmmmm.....
+......mmqqqqqqmm....
+....mmqjnnnnnnnqjmm
+...mmqjnnnppppnnjqmm
+...mmqjnnppppppppjqm
+....mmqjnpppppnjqmm.
+.....mmqjnpppnjqmm..
+......mmqjpppnqmm...
+.......mmqnpppqqmm..
+.......mmqjpppqqmm..
+......mmqjnppnqmm...
+......mmqpppqqmm....
+.....mmqnppqmm......
+.....mmqpppbmmqmm...
+.....mmqpppbmmbqmm..
+.....mmqnpnbbmbqmm..
+......mmqcppmbqmm...
+........mmqpqqmm....
+.........mmqmm......
+..........mmm.......
+#
+APRS u l Truck (w overlay)
+....................
+....................
+....................
+....................
+........jjj.........
+.......j..j.........
+......j...j.........
+.....j....j.........
+..jjj......jjjjjjj..
+..j..............j..
+..j..............j..
+..qpppj.....jpppjq..
+..qpcpjjjjjjjpcpjq..
+...ppp.......ppp....
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS v l Van (w overlay)
+....................
+....................
+....................
+....................
+....................
+.......hhhhhhhhhhh..
+......h...........h.
+.....h............h.
+....h.............h.
+..h...............h.
+.h................j.
+.h................h.
+.ohqqh........hqqho.
+.hqccqhhhhhhhhqccqh.
+..qccq........qccq..
+...qq..........qq...
+....................
+....................
+....................
+....................
+#
+APRS w Flooding
+....................
+....................
+....................
+....................
+....................
+...c.....c.....c....
+....h.....h.....h...
+...lll...lll...lll..
+..llllllllllllllll..
+..llllllllllllllll..
+..llllllllllllllll..
+..llllllllllllllll..
+..llllllllllllllll..
+..cchclhchlhchlcch..
+..cllclclclclclclc..
+..cclclclclclclclc..
+..cllcchchlhchlcch..
+..llllllllllllllll..
+....................
+....................
+#
+#APRS x
+#
+APRS y Skywarn
+qqqqqqqqqmmqqqqqqqqq
+qqqqqqqmqqqqmqqqqqqq
+qqqqqmqqqqqqqqmqqqqq
+qqqqmqqqqqqqqqqmqqqq
+qqqmmqqqqqqqqqqmmqqq
+qqmmqqaqqqqqqaqqmmqq
+qmmmqqaaqqqqaaqqmmmq
+qmmqqaaaqqqqaaaqqmmq
+mmmqqaaaqqqqaaaqqmmm
+mmmqqaaaqqqaaaaqqmmm
+mmmqqaaaqqqaaaaqqmmm
+mmmqqaaaaqqaaaaqqmmm
+qmmqqaaaaaqqaaaqqmmq
+qmmmqqaaaaqqaaqqmmmq
+qqmmqqaaaaqqaaqqmmqq
+qqqmmqqaaqqaaqqmmqqq
+qqqqmqqaaqaaaqqmqqqq
+qqqqqmqqqqqqqqmqqqqq
+qqqqqqqmqqqqmqqqqqqq
+qqqqqqqqqmmqqqqqqqqq
+#
+APRS z Shelter (Evacuation) w overlay
+....................
+.........pp.........
+........pjjp........
+.......pjjjjp.......
+......pjjjjjjp......
+.....pjjjjjjjjp.....
+....pjjjjjjjjjjp....
+...pjjjjjjjjjjjjp...
+..pjjjjjjjjjjjjjjp..
+...pjjjjjjjjjjjjp...
+...pjjjjjjjjjjjjp...
+...pjjjjjjjjjjjjp...
+...pjjjjjjjjjjjjp...
+...pjjjjjjjjjjjjp...
+...pjjjjjjjjjjjjp...
+...pjjjjjjjjjjjjp...
+...pjjjjjjjjjjjjp...
+....................
+....................
+....................
+#
+APRS { Fog
+....................
+....................
+....................
+....................
+....................
+..qqqq..qqq...qqq...
+..q....q...q.q...q..
+..q....q...q.q...q..
+..qqq..q...q.q......
+..q....q...q.q......
+..q....q...q.q..qq..
+..q....q...q.q...q..
+..q....q...q.q...q..
+..q.....qqq...qqq...
+....................
+....................
+....................
+....................
+....................
+....................
+#
+#APRS | Reserved - TNC Stream Switch
+#
+#APRS }
+#
+#APRS ~ Reserved - TNC Stream Switch
+#
+#
+# -------------------------
+#
+TABLE #
+#
+APRS 0 Overlay Characters, etc
+....................
+....................
+....................
+....................
+.........cc.........
+........cqqc........
+.......cqccqc.......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+.......cqccqc.......
+........cqqc........
+.........cc.........
+....................
+....................
+....................
+....................
+....................
+#
+APRS 1
+....................
+....................
+....................
+....................
+.........ccc........
+........ccqc........
+........cqqc........
+........ccqc........
+.........cqc........
+.........cqc........
+.........cqc........
+.........cqc........
+.........cqc........
+.........cqc........
+.........ccc........
+....................
+....................
+....................
+....................
+....................
+#
+APRS 2
+....................
+....................
+....................
+....................
+........ccccc.......
+.......ccqqqqc......
+......ccqcccqc......
+......cqcc.cqc......
+......ccc.ccqc......
+.........ccqcc......
+........ccqcc.......
+.......ccqcc........
+......ccqccccc......
+......cqqqqqqc......
+......cccccccc......
+....................
+....................
+....................
+....................
+....................
+#
+APRS 3
+....................
+....................
+....................
+....................
+......cccccccc......
+......cqqqqqqc......
+......cccccqcc......
+........ccqcc.......
+.........qqcc.......
+........cccqcc......
+..........ccqc......
+......ccc.ccqc......
+......cqcccqcc......
+......ccqqqcc.......
+.......ccccc........
+....................
+....................
+....................
+....................
+....................
+#
+APRS 4
+....................
+....................
+....................
+....................
+...........ccc......
+..........ccqc......
+.........ccqqc......
+........ccqcqc......
+.......ccqccqc......
+......ccqc.cqc......
+......cqccccqcc.....
+......cqqqqqqqc.....
+......ccccccqcc.....
+...........cqc......
+...........ccc......
+....................
+....................
+....................
+....................
+....................
+#
+APRS 5
+....................
+....................
+....................
+....................
+......cccccccc......
+......cqqqqqqc......
+......cqcccccc......
+......cqcccc........
+......cqqqqqc.......
+.......cccccqc......
+...........cqc......
+......ccc..cqc......
+......cqccccqc......
+......ccqqqqc.......
+.......cccccc.......
+....................
+....................
+....................
+....................
+....................
+#
+APRS 6
+....................
+....................
+....................
+....................
+.........ccc........
+........cqqqc.......
+.......cqccc........
+......cqcccc........
+......cqqqqqc.......
+......cqccccqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqccccqc......
+.......cqqqqc.......
+........cccc........
+....................
+....................
+....................
+....................
+....................
+#
+APRS 7
+....................
+....................
+....................
+....................
+......cccccccc......
+......cqqqqqqc......
+......ccccccqc......
+..........cqcc......
+.........ccqc.......
+.........cqcc.......
+........ccqc........
+........cqcc........
+........cqc.........
+........cqc.........
+........ccc.........
+....................
+....................
+....................
+....................
+....................
+#
+APRS 8
+....................
+....................
+....................
+....................
+........cccc........
+.......cqqqqc.......
+......cqccccqc......
+......cqccccqc......
+......ccqqqqcc......
+......cqccccqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqccccqc......
+.......cqqqqc.......
+........cccc........
+....................
+....................
+....................
+....................
+....................
+#
+APRS 9
+....................
+....................
+....................
+....................
+........cccc........
+.......cqqqqc.......
+......cqccccqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqccccqc......
+.......cqqqqqc......
+........ccccqc......
+........cccqcc......
+.......cqqqcc.......
+........cccc........
+....................
+....................
+....................
+....................
+....................
+#
+APRS A
+....................
+....................
+....................
+....................
+.........ccc........
+.........cqc........
+........ccqcc.......
+........cqcqc.......
+.......ccqcqcc......
+.......cqc.cqc......
+......ccqc.cqcc.....
+......cqqqqqqqc.....
+......cqcccccqc.....
+......cqc...cqc.....
+......ccc...ccc.....
+....................
+....................
+....................
+....................
+....................
+#
+APRS B
+....................
+....................
+....................
+....................
+......cccccc........
+......cqqqqqc.......
+......cqccccqc......
+......cqccccqc......
+......cqqqqqcc......
+......cqccccqc......
+......cqc...qc......
+......cqc..cqc......
+......cqccccqc......
+......cqqqqqc.......
+......cccccc........
+....................
+....................
+....................
+....................
+....................
+#
+APRS C
+....................
+....................
+....................
+....................
+.......cccccc.......
+......ccqqqqcc......
+......cqccccqc......
+......cqc..ccc......
+......cqc...........
+......cqc...........
+......cqc...........
+......cqc..ccc......
+......cqccccqc......
+......ccqqqqcc......
+.......cccccc.......
+....................
+....................
+....................
+....................
+....................
+#
+APRS D
+....................
+....................
+....................
+....................
+......cccccc........
+......cqqqqcc.......
+......cqcccqcc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqcccqcc......
+......cqqqqcc.......
+......cccccc........
+....................
+....................
+....................
+....................
+....................
+#
+APRS E
+....................
+....................
+....................
+....................
+......ccccccc.......
+......cqqqqqc.......
+......cqccccc.......
+......cqc...........
+......cqcccc........
+......cqqqqc........
+......cqcccc........
+......cqc...........
+......cqccccc.......
+......cqqqqqc.......
+......ccccccc.......
+....................
+....................
+....................
+....................
+....................
+#
+APRS F
+....................
+....................
+....................
+....................
+......ccccccc.......
+......cqqqqqc.......
+......cqccccc.......
+......cqc...........
+......cqcccc........
+......cqqqqc........
+......cqcccc........
+......cqc...........
+......cqc...........
+......cqc...........
+......ccc...........
+....................
+....................
+....................
+....................
+....................
+#
+APRS G
+....................
+....................
+....................
+....................
+.......cccccc.......
+......ccqqqqcc......
+......cqccccqc......
+......cqc...c.......
+......cqc.cccc......
+......cqccqqqc......
+......cqc.ccqc......
+......cqc...qc......
+......cqccccqc......
+......ccqqqqcc......
+.......cccccc.......
+....................
+....................
+....................
+....................
+....................
+#
+APRS H
+....................
+....................
+....................
+....................
+......ccc..ccc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqccccqc......
+......cqqqqqqc......
+......cqccccqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......ccc..ccc......
+....................
+....................
+....................
+....................
+....................
+#
+APRS I
+....................
+....................
+....................
+....................
+........ccc.........
+........cqc.........
+........cqc.........
+........cqc.........
+........cqc.........
+........cqc.........
+........cqc.........
+........cqc.........
+........cqc.........
+........cqc.........
+........ccc.........
+....................
+....................
+....................
+....................
+....................
+#
+APRS J
+....................
+....................
+....................
+....................
+..........ccc.......
+..........cqc.......
+..........cqc.......
+..........cqc.......
+..........cqc.......
+..........cqc.......
+.....ccc..cqc.......
+.....cqc..cqc.......
+.....cqccccqc.......
+.....ccqqqqcc.......
+......cccccc........
+....................
+....................
+....................
+....................
+....................
+#
+APRS K
+....................
+....................
+....................
+....................
+......ccc..ccc......
+......cqc..cqc......
+......cqc.cqcc......
+......cqccqcc.......
+......cqcqcc........
+......cqqcc.........
+......cqcqcc........
+......cqccqcc.......
+......cqc.cqcc......
+......cqc..cqc......
+......ccc..ccc......
+....................
+....................
+....................
+....................
+....................
+#
+APRS L
+....................
+....................
+....................
+....................
+......ccc...........
+......cqc...........
+......cqc...........
+......cqc...........
+......cqc...........
+......cqc...........
+......cqc...........
+......cqc...........
+......cqccccc.......
+......cqqqqqc.......
+......ccccccc.......
+....................
+....................
+....................
+....................
+....................
+#
+APRS M
+....................
+....................
+....................
+....................
+......ccc...ccc.....
+......cqcc.ccqc.....
+......cqqc.cqqc.....
+......cqcqcqcqc.....
+......cqccqccqc.....
+......cqcccccqc.....
+......cqc...cqc.....
+......cqc...cqc.....
+......cqc...cqc.....
+......cqc...cqc.....
+......ccc...ccc.....
+....................
+....................
+....................
+....................
+....................
+#
+APRS N
+....................
+....................
+....................
+....................
+......cccc.ccc......
+......cqqc.cqc......
+......cqqc.cqc......
+......cqcqccqc......
+......cqcqccqc......
+......cqccqcqc......
+......cqccqcqc......
+......cqc.cqqc......
+......cqc.cqqc......
+......cqc..cqc......
+......ccc..ccc......
+....................
+....................
+....................
+....................
+....................
+#
+APRS O
+....................
+....................
+....................
+....................
+........cccc........
+.......cqqqqc.......
+......cqccccqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqccccqc......
+.......cqqqqc.......
+........cccc........
+....................
+....................
+....................
+....................
+....................
+#
+APRS P
+....................
+....................
+....................
+....................
+......ccccccc.......
+......cqqqqqcc......
+......cqccccqc......
+......cqc..cqc......
+......cqccccqc......
+......cqqqqqcc......
+......cqccccc.......
+......cqc...........
+......cqc...........
+......cqc...........
+......ccc...........
+....................
+....................
+....................
+....................
+....................
+#
+APRS Q
+....................
+....................
+....................
+....................
+........cccc........
+.......cqqqqc.......
+......cqccccqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqccccqc......
+......cqccqcqc......
+.......cqqqqc.......
+........ccccqc......
+............cc......
+....................
+....................
+....................
+....................
+#
+APRS R
+....................
+....................
+....................
+....................
+......ccccccc.......
+......cqqqqqcc......
+......cqccccqc......
+......cqc..cqc......
+......cqccccqc......
+......cqqqqqcc......
+......cqcqccc.......
+......cqccqcc.......
+......cqc.cqcc......
+......cqc..cqc......
+......ccc..ccc......
+....................
+....................
+....................
+....................
+....................
+#
+APRS S
+....................
+....................
+....................
+....................
+........cccc........
+.......cqqqqc.......
+......cqccccqc......
+......cqc...c.......
+......cqcccc........
+.......cqqqqc.......
+........ccccqc......
+......ccc..cqc......
+......cqccccqc......
+.......cqqqqc.......
+........cccc........
+....................
+....................
+....................
+....................
+....................
+#
+APRS T
+....................
+....................
+....................
+....................
+......ccccccccc.....
+......cqqqqqqqc.....
+......ccccqcccc.....
+.........cqc........
+.........cqc........
+.........cqc........
+.........cqc........
+.........cqc........
+.........cqc........
+.........cqc........
+.........ccc........
+....................
+....................
+....................
+....................
+....................
+#
+APRS U
+....................
+....................
+....................
+....................
+......ccc..ccc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqc..cqc......
+......cqccccqc......
+......ccqqqqcc......
+.......cccccc.......
+....................
+....................
+....................
+....................
+....................
+#
+APRS V
+....................
+....................
+....................
+....................
+......ccc...ccc.....
+......cqc...cqc.....
+......cqc...cqc.....
+......cqcc.ccqc.....
+......ccqc.cqcc.....
+.......cqc.cqc......
+.......ccqcqcc......
+........cqcqc.......
+........ccqcc.......
+.........cqc........
+.........ccc........
+....................
+....................
+....................
+....................
+....................
+#
+APRS W
+....................
+....................
+....................
+....................
+.....ccc.....ccc....
+.....cqc.....cqc....
+.....cqc..c..cqc....
+.....cqc.cqc.cqc....
+.....ccqccqccqcc....
+......cqcqcqcqc.....
+......cqcqcqcqc.....
+......ccqc.cqcc.....
+.......cqc.cqc......
+.......cqc.cqc......
+.......ccc.ccc......
+....................
+....................
+....................
+....................
+....................
+#
+APRS X
+....................
+....................
+....................
+....................
+.......ccc.ccc......
+.......cqc.cqc......
+.......cqc.cqc......
+.......ccqcqcc......
+........cqcqc.......
+.........cqc........
+........cqcqc.......
+.......ccqcqcc......
+.......cqc.cqc......
+.......cqc.cqc......
+.......ccc.ccc......
+....................
+....................
+....................
+....................
+....................
+#
+APRS Y
+....................
+....................
+....................
+....................
+......ccc.ccc.......
+......cqc.cqc.......
+......cqc.cqc.......
+......cqc.cqc.......
+......ccqcqcc.......
+.......cqcqc........
+.......ccqcc........
+........cqc.........
+........cqc.........
+........cqc.........
+........ccc.........
+....................
+....................
+....................
+....................
+....................
+#
+APRS Z
+....................
+....................
+....................
+....................
+......cccccccc......
+......cqqqqqqq......
+......ccccccqc......
+..........ccqc......
+.........ccqcc......
+........ccqcc.......
+.......ccqcc........
+......ccqcc.........
+......cqcccccc......
+......cqqqqqqc......
+......cccccccc......
+....................
+....................
+....................
+....................
+....................
+#
+APRS >
+....................
+....................
+....................
+....................
+.....d..............
+.....dd.............
+.ddddddd............
+ndddddddd...........
+nddddddd............
+nnnnndd.............
+....nd..............
+....................
+....................
+..kkkkkkk...........
+.nkkkkkkk...........
+.nkkkkkkk...........
+.nkkkkkkk...........
+.nkkkkkkk...........
+.nnnnnnn............
+....................
+#
+APRS <
+....................
+....................
+....................
+....................
+...d................
+..dd................
+.dddddddd...........
+ddddddddd...........
+ndddddddd...........
+.nddnnnn............
+..nd................
+....................
+....................
+..kkkkkkk...........
+.nkkkkkkk...........
+.nkkkkkkk...........
+.nkkkkkkk...........
+.nkkkkkkk...........
+.nnnnnnn............
+....................
+#
+APRS *
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+..ddddddd...........
+.nddddddd...........
+.nddddddd...........
+.nddddddd...........
+.nddddddd...........
+.nnnnnnn............
+....................
+#
+APRS ^
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+..kkkkkkk...........
+.nkkkkkkk...........
+.nkkkkkkk...........
+.nkkkkkkk...........
+.nkkkkkkk...........
+.nnnnnnn............
+....................
+#
+#
+# -------------------------
+#
+TABLE ~
+#
+APRS 0
+..gggggg............
+.gggggggg...........
+gggggggggg..........
+nnnnnnnnn...........
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS 1
+..hhhhhh............
+.hhhhhhhh...........
+hhhhhhhhhh..........
+nnnnnnnnn...........
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS 2
+..iiiiii............
+.iiiiiiii...........
+iiiiiiiiii..........
+nnnnnnnnn...........
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS 3
+..aaaaaa............
+.aaaaaaaa...........
+aaaaaaaaaa..........
+nnnnnnnnn...........
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS 4
+..######............
+.########...........
+##########..........
+nnnnnnnnn...........
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS 5
+..llllll............
+.llllllll...........
+llllllllll..........
+nnnnnnnnn...........
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS 6
+..kkkkkk............
+.kkkkkkkk...........
+kkkkkkkkkk..........
+nnnnnnnnn...........
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS 7
+..jjjjjj............
+.jjjjjjjj...........
+jjjjjjjjjj..........
+nnnnnnnnn...........
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS 8
+npllllllpn..........
+lnllllllnl..........
+lhhhhhhhhl..........
+npllllllpn..........
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+....................
+#
+APRS #
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+~~~~~~~~~~..........
+#
+APRS $
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~
+DONE
diff --git a/symbols/torndo.xbm b/symbols/torndo.xbm
new file mode 100644
index 0000000..d8362d1
--- /dev/null
+++ b/symbols/torndo.xbm
@@ -0,0 +1,41 @@
+#define tornado_width 110
+#define tornado_height 32
+static unsigned char tornado_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0xf8, 0x9c,
+ 0x27, 0x22, 0x1e, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0xa2, 0x68, 0x22, 0xa2, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0xa2, 0xa8, 0x52, 0xa2, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0xa2, 0x27, 0x53, 0xa2, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xa2, 0x28, 0xfa, 0xa2, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xa2, 0x28, 0x8a,
+ 0xa2, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x9c,
+ 0x28, 0x8a, 0x1e, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
diff --git a/symbols/wind.xbm b/symbols/wind.xbm
new file mode 100644
index 0000000..64436dc
--- /dev/null
+++ b/symbols/wind.xbm
@@ -0,0 +1,41 @@
+#define wind_width 109
+#define wind_height 32
+static unsigned char wind_bits[] = {
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0x12, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x49, 0x32, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x49, 0x52, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x45, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x12, 0x45, 0x00, 0x00,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x49, 0x12, 0x45,
+ 0x54, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+ 0x12, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
diff --git a/symbols/winter_storm.xbm b/symbols/winter_storm.xbm
new file mode 100644
index 0000000..9bcd780
--- /dev/null
+++ b/symbols/winter_storm.xbm
@@ -0,0 +1,41 @@
+#define wntr_strm_width 110
+#define wntr_strm_height 32
+static unsigned char wntr_strm_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x24, 0x49, 0xf4, 0x7d, 0x0f, 0xe0, 0x7c, 0xce, 0x13, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xc9, 0x44, 0x04, 0x11, 0x10, 0x11, 0x51,
+ 0x34, 0x06, 0x00, 0x00, 0x00, 0x00, 0x24, 0x49, 0x45, 0x04, 0x11, 0x10,
+ 0x10, 0x51, 0x54, 0x05, 0x00, 0x00, 0x00, 0x00, 0x24, 0x49, 0x46, 0x3c,
+ 0x0f, 0xe0, 0x10, 0xd1, 0x93, 0x04, 0x00, 0x00, 0x00, 0x00, 0x24, 0x49,
+ 0x44, 0x04, 0x11, 0x00, 0x11, 0x51, 0x14, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x24, 0x49, 0x44, 0x04, 0x11, 0x10, 0x11, 0x51, 0x14, 0x04, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xfc, 0x48, 0x44, 0x7c, 0x11, 0xe0, 0x10, 0x4e, 0x14, 0x24,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
diff --git a/symbols/winter_weather.xbm b/symbols/winter_weather.xbm
new file mode 100644
index 0000000..c2b6521
--- /dev/null
+++ b/symbols/winter_weather.xbm
@@ -0,0 +1,41 @@
+#define winter_wx_width 109
+#define winter_wx_height 32
+static unsigned char winter_wx_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x92, 0x44, 0xdf,
+ 0xf7, 0x00, 0x49, 0x11, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x4a, 0x92,
+ 0x4c, 0x44, 0x10, 0x01, 0x49, 0x8a, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x92, 0x54, 0x44, 0x10, 0x01, 0x49, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x92, 0x64, 0xc4, 0xf3, 0x00, 0x49, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x92, 0x44, 0x44, 0x10, 0x01, 0x49, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x92, 0x44, 0x44, 0x10, 0x01,
+ 0x49, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x8f, 0x44, 0xc4,
+ 0x17, 0x01, 0x3f, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
diff --git a/terraserver-reflectivity.geo b/terraserver-reflectivity.geo
new file mode 100644
index 0000000..a96a8ad
--- /dev/null
+++ b/terraserver-reflectivity.geo
@@ -0,0 +1,2 @@
+TERRASERVER-REFLECTIVITY
+
diff --git a/terraserver-topo.geo b/terraserver-topo.geo
new file mode 100644
index 0000000..043744d
--- /dev/null
+++ b/terraserver-topo.geo
@@ -0,0 +1,2 @@
+TERRASERVER-TOPO
+
diff --git a/terraserver-urban.geo b/terraserver-urban.geo
new file mode 100644
index 0000000..7e5dbaf
--- /dev/null
+++ b/terraserver-urban.geo
@@ -0,0 +1,2 @@
+TERRASERVER-URBAN
+
diff --git a/terraserver.geo b/terraserver.geo
new file mode 100644
index 0000000..6159ce4
--- /dev/null
+++ b/terraserver.geo
@@ -0,0 +1,2 @@
+TERRASERVER-SATELLITE
+
diff --git a/testdbfawk.1 b/testdbfawk.1
new file mode 100644
index 0000000..24ec346
--- /dev/null
+++ b/testdbfawk.1
@@ -0,0 +1,48 @@
+.TH testdbfawk 1 2009-12-22 "The Xastir Group"
+
+.SH NAME
+testdbfawk \- scan dbfawk files for matching dbf file for map rendering in xastir
+
+.SH SYNOPSIS
+.B testdbfawk
+.I [-f file.awk| -D dir] -d file.dbf
+
+.SH DESCRIPTION
+Scan dbfawk files for matching dbf file for map rendering in xastir
+.br
+.PP
+.B --help
+prints command line usage
+.br
+.B -D
+for dir containing *.dbfawk files.
+.br
+.B -f
+for file containing awk rules.
+.br
+.B -d
+for dbf file to parse
+.SH EXAMPLES
+testdbfawk \-D . \-d tgr36119lkA.dbf 2>&1|less
+
+testdbfawk scans the current directory for dbfawk files with signatures that match tgr36119lkA.dbf's
+signature. testdbfawk dumps its output to standard error, so in the example standard error is
+redirected to standard out and piped into "less" for paging.
+
+.SH NOTES
+Dbfawk hints and kinks: You have to think like an awk programmer and
+realize that the order that rules are listed matters, that it's important
+to use "next" as soon as it makes sense so other rules aren't looked at
+unnecessarily and, to use "skip" when you want to fix bad dbf data.
+
+.SH SEE ALSO
+README.MAPS in xastir documentation
+.br
+.PP
+.B APRS[tm]
+is a Trademark of Bob Bruninga, his home page is at "http://www.aprs.org/aprs.html"
+
+.SH COPYING
+Copyright (C) 1999,2000 Frank Giannandrea KC2GJS
+.br
+Copyright (C) 2000-2012 The Xastir Group
diff --git a/worldhi.map b/worldhi.map
new file mode 100644
index 0000000..d88de89
Binary files /dev/null and b/worldhi.map differ
diff --git a/xastir-lsb.spec.in b/xastir-lsb.spec.in
new file mode 100644
index 0000000..c11258f
--- /dev/null
+++ b/xastir-lsb.spec.in
@@ -0,0 +1,108 @@
+# NOTE:
+# “Free Standards Group, FSG, Linux Standard Base, LSB, Free
+# Standards Certified, LSB Certified and the Free Standards
+# Certified logo are trademarks, service marks and certification
+# marks, as appropriate, of Free Standards Group in the United
+# States and in other countries.”
+#
+# We are in no way representing that Xastir has been certified by
+# the FSG. To do so costs real money. We do intend some Xastir
+# binaries to install and run properly on LSB-3.0 compliant x86
+# Linux systems though...
+#
+Summary : Amateur Station Tracking and Reporting system for Amateur Radio APRS
+Name : xastir
+Version : @VERSION@
+Release : 1
+Copyright : GPL
+Group : Applications/Networking
+Packager : Curt Mills, WE7U <archer at eskimo.com>
+# Icon : src/xastir.xpm
+Source : http://prdownloads.sourceforge.net/xastir/xastir-@VERSION@.tar.gz
+URL : http://www.xastir.org
+#BuildRoot : %{_tmppath}/%{name}-buildroot
+BuildRoot : RPM
+#Requires :
+#AutoReqProv : no
+PreReq : lsb >= 3.0
+#
+#
+# Stuff gleaned from the LSB appbat RPM build files:
+#
+# Force a 486 target
+#buildarchtranslate: i686 i486
+#buildarchtranslate: i586 i486
+#buildarchtranslate: pentium3 i486
+#buildarchtranslate: pentium4 i486
+#buildarchtranslate: athlon i486
+#buildarchtranslate: k6 i486a
+#
+# Overrides for LSB packaging
+# We want a non-root build. Just put everything in the same directory.
+# Only _rpmdir and _builddir are actually used in these builds but we
+# define all five of the directories for completeness.
+#%_topdir /home/archer/xastir
+#%_rpmdir %{_topdir}/rpm
+#%_specdir %{_topdir}/rpm
+#%_builddir %{_topdir}/rpm
+#%_sourcedir %{_topdir}/rpm
+#%_srcrpmdir %{_topdir}/rpm
+#%pkgroot %{_topdir}/rpm
+#
+#%_messagelevel 0
+#
+# Replace the "buildpolicy" defined in the distro's brp-(distro) file.
+# Forces uncompressed manpages so the specfiles don't vary.
+#%__os_install_post \
+# /usr/lib/rpm/brp-strip \
+# /usr/lib/rpm/brp-strip-comment-note
+#
+# Unpackaged files in a build root don't terminate a build
+#%_unpackaged_files_terminate_build 0
+#
+# Missing %doc files in the build directory don't terminate a build
+#%_missing_doc_files_terminate_build 0
+#
+# Force gzip payload
+#%_binary_payload w9.gzdio
+
+
+%description
+Xastir is a graphical application that interfaces HAM radio
+and internet access to real-time mapping software.
+
+Install XASTIR if you are interested in APRS(tm) and HAM radio
+software.
+
+%prep
+%setup -q
+#%patch
+%build
+%install
+%clean
+
+%files
+%defattr(-,root,root)
+
+# Documents: Go into special doc area at /opt/Xastir/share/doc/xastir/
+%doc AUTHORS ChangeLog COPYING DEBUG_LEVELS FAQ INSTALL LICENSE
+%doc README README.Contributing README.CVS README.Getting-Started
+%doc README.MAPS README.win32 UPGRADE COPYING.LIB.LESSTIF
+
+/opt/Xastir/bin
+/opt/Xastir/share/xastir/help
+/opt/Xastir/share/xastir/config
+/opt/Xastir/share/xastir/symbols
+/opt/Xastir/share/man
+/opt/Xastir/lib/xastir
+
+# protect user-installed map and other files from being clobbered
+%config /opt/Xastir/share/xastir/maps
+%dir %attr(666,root,root) /opt/Xastir/share/xastir/maps/GPS
+%config /opt/Xastir/share/xastir/Counties
+%config /opt/Xastir/share/xastir/fcc
+%config /opt/Xastir/share/xastir/GNIS
+%config /opt/Xastir/share/xastir/sounds
+
+%changelog
+
diff --git a/xastir-min.spec b/xastir-min.spec
new file mode 100644
index 0000000..a3dc74e
--- /dev/null
+++ b/xastir-min.spec
@@ -0,0 +1,77 @@
+Summary : Amateur Station Tracking and Reporting system for amateur radio
+Name : xastir
+Version : 2.0.4
+Release : 1
+#Epoch : 1
+License : GPL
+Group : Applications/Networking
+Packager : n2ygk at weca.org
+# Icon : src/xastir.xpm
+Source : http://prdownloads.sourceforge.net/xastir/xastir-2.0.4.tar.gz
+URL : http://www.xastir.org
+BuildRoot : %{_tmppath}/%{name}-buildroot
+#Requires :
+
+%description
+Xastir is a graphical application that interfaces HAM radio
+and internet access to realtime mapping software.
+
+Install XASTIR if you are interested in APRS(tm) and HAM radio
+software.
+
+%prep
+%setup -q
+#%patch
+
+%build
+./bootstrap.sh
+%configure --without-ax25 --without-festival --without-gpsman --without-graphicsmagick --with-imagemagick --with-internal-shapelib --without-libproj --without-geotiff --without-gdal --without-pcre --without-dbfawk --without-map-cache
+make
+
+%install
+rm -rf ${RPM_BUILD_ROOT}
+%makeinstall
+# Docs go into package docs area instead of the Makefile install
+# locations listed here:
+rm -rf ${RPM_BUILD_ROOT}/usr/share/doc
+
+%clean
+rm -rf ${RPM_BUILD_ROOT}
+
+%files
+%defattr(-,root,root)
+
+# Documents: Go into special doc area at /usr/share/doc/xastir/ or
+# /usr/share/doc/packages/xastir/
+%doc AUTHORS ChangeLog COPYING DEBUG_LEVELS FAQ INSTALL LICENSE
+%doc README README.Contributing README.CVS README.Getting-Started
+%doc README.MAPS README.win32 UPGRADE
+
+
+%{_prefix}/bin
+%{_prefix}/share/xastir/help
+%{_prefix}/share/xastir/config
+%{_prefix}/share/xastir/symbols
+%{_prefix}/share/man
+%{_prefix}/lib/xastir
+
+# protect user-installed map and other files from being clobbered
+
+%config %{_prefix}/share/xastir/maps
+%dir %attr(666,root,root) %{_prefix}/share/xastir/maps/GPS
+%config %{_prefix}/share/xastir/Counties
+%config %{_prefix}/share/xastir/fcc
+%config %{_prefix}/share/xastir/GNIS
+%config %{_prefix}/share/xastir/sounds
+
+%changelog
+* Thu Jul 03 2003 Alan Crosswell <n2ygk at weca.org>
+- 1.2.1 my patches now integrated into the main trunk.
+* Sat Jun 21 2003 Alan Crosswell <n2ygk at weca.org>
+- added xastir-maps.patch
+* Mon Jun 16 2003 Alan Crosswell <n2ygk at weca.org>
+- 1.2.0
+* Fri Jun 06 2003 Alan Crosswell <n2ygk at weca.org>
+- June 5 snapshot
+* Thu May 15 2003 Alan Crosswell <n2ygk at weca.org>
+- start with chuck's spec file for 1.1.4
diff --git a/xastir-min.spec.in b/xastir-min.spec.in
new file mode 100644
index 0000000..15f522f
--- /dev/null
+++ b/xastir-min.spec.in
@@ -0,0 +1,77 @@
+Summary : Amateur Station Tracking and Reporting system for amateur radio
+Name : @PACKAGE@
+Version : @VERSION@
+Release : 1
+#Epoch : 1
+License : GPL
+Group : Applications/Networking
+Packager : n2ygk at weca.org
+# Icon : src/@PACKAGE at .xpm
+Source : http://prdownloads.sourceforge.net/@PACKAGE@/@PACKAGE@-@VERSION@.tar.gz
+URL : http://www.xastir.org
+BuildRoot : %{_tmppath}/%{name}-buildroot
+#Requires :
+
+%description
+Xastir is a graphical application that interfaces HAM radio
+and internet access to realtime mapping software.
+
+Install XASTIR if you are interested in APRS(tm) and HAM radio
+software.
+
+%prep
+%setup -q
+#%patch
+
+%build
+./bootstrap.sh
+%configure --without-ax25 --without-festival --without-gpsman --without-graphicsmagick --with-imagemagick --with-internal-shapelib --without-libproj --without-geotiff --without-gdal --without-pcre --without-dbfawk --without-map-cache
+make
+
+%install
+rm -rf ${RPM_BUILD_ROOT}
+%makeinstall
+# Docs go into package docs area instead of the Makefile install
+# locations listed here:
+rm -rf ${RPM_BUILD_ROOT}/usr/share/doc
+
+%clean
+rm -rf ${RPM_BUILD_ROOT}
+
+%files
+%defattr(-,root,root)
+
+# Documents: Go into special doc area at /usr/share/doc/xastir/ or
+# /usr/share/doc/packages/xastir/
+%doc AUTHORS ChangeLog COPYING DEBUG_LEVELS FAQ INSTALL LICENSE
+%doc README README.Contributing README.CVS README.Getting-Started
+%doc README.MAPS README.win32 UPGRADE
+
+
+%{_prefix}/bin
+%{_prefix}/share/xastir/help
+%{_prefix}/share/xastir/config
+%{_prefix}/share/xastir/symbols
+%{_prefix}/share/man
+%{_prefix}/lib/xastir
+
+# protect user-installed map and other files from being clobbered
+
+%config %{_prefix}/share/xastir/maps
+%dir %attr(666,root,root) %{_prefix}/share/xastir/maps/GPS
+%config %{_prefix}/share/xastir/Counties
+%config %{_prefix}/share/xastir/fcc
+%config %{_prefix}/share/xastir/GNIS
+%config %{_prefix}/share/xastir/sounds
+
+%changelog
+* Thu Jul 03 2003 Alan Crosswell <n2ygk at weca.org>
+- 1.2.1 my patches now integrated into the main trunk.
+* Sat Jun 21 2003 Alan Crosswell <n2ygk at weca.org>
+- added xastir-maps.patch
+* Mon Jun 16 2003 Alan Crosswell <n2ygk at weca.org>
+- 1.2.0
+* Fri Jun 06 2003 Alan Crosswell <n2ygk at weca.org>
+- June 5 snapshot
+* Thu May 15 2003 Alan Crosswell <n2ygk at weca.org>
+- start with chuck's spec file for 1.1.4
diff --git a/xastir.1 b/xastir.1
new file mode 100644
index 0000000..fd6e76a
--- /dev/null
+++ b/xastir.1
@@ -0,0 +1,108 @@
+.TH XASTIR 1 "HI8GN on Apr 09 2002" "By Jose R. Marte A." "Xastir APRS(tm) Client APPLICATION"
+.SH NAME
+Xastir \- graphical application that interfaces HAM radio
+and APRS(tm) internet access to real-time mapping software.
+.SH "DESCRIPTION"
+This manual page briefly documents the
+.BR Xastir
+commands.
+.SH SYNOPSIS
+.B xastir
+.I "[options] Language ..."
+.SH OPTIONS
+The program follows the usual GNU command line syntax, with long
+options starting with one dash (`-').
+A summary of options is included below.
+.TP
+.br
+.B \-c /path/dir
+Specify an optional config directory. Defaults to ~/.xastir
+.TP
+.br
+.B \-f callsign
+Track callsign
+.TP
+.br
+.B \-i
+Use a private colormap
+.TP
+.br
+.B \-geometry WxH+x+y
+Set Window Geometry/Position
+.TP
+.br
+.B \-l Language
+Xastir remembers the language once you set it the first time.
+.TP
+.br
+.B \-m
+Deselect Maps
+.TP
+.br
+.B \-p
+Disable popups
+.TP
+.br
+.B \-t
+Internal SIGSEGV handler enabled
+.TP
+.br
+.B \-v Level
+Set the debug level
+.TP
+.br
+.B \-?
+Show summary of options available.
+.br
+.SH AVAILABLE LANGUAGES
+Current choices are:
+.br
+.B Dutch English French German Italian Portuguese Spanish.
+.SH Usage is:
+.br
+.B xastir -i -v 2047 -l Dutch &
+.br
+.SH SIGNALS
+.B SIGINT, SIQQUIT, SIGTERM
+Cause Xastir to exit.
+.br
+.B SIGHUP
+Causes a restart.
+.br
+.B SIGUSR1
+Causes a snapshot to occur.
+.br
+.SH NETWORK PORTS
+Enable these ports on this menu: "Interface->Enable Server Ports"
+.br
+.PP
+.B TCP:2023
+Bidirectional TCP port for clients to connect to. Requires login if
+client will be transmitting.
+.br
+.B UDP:2023
+Unidirectional UDP input port for clients to inject packets. See
+the documentation for the format.
+.br
+.SH "SEE ALSO"
+The program is documented fully by
+.IR "help-English.dat" ,
+available via the HELP menu option in Xastir, plus the various
+README and INSTALL text files that come with the program. Also see
+<http://www.xastir.org> and the Documentation Wiki there.
+.br
+.PP
+.B Xastir
+is a program for APRS(tm)...
+.br
+.PP
+.B APRS[tm]
+is a Trademark of Bob Bruninga, his home page is at
+"http://www.aprs.org/aprs.html"
+.SH COPYING
+Copyright (C) 1999,2000 Frank Giannandrea KC2GJS
+.br
+Copyright (C) 2000-2012 The Xastir Group
+.SH AUTHOR
+This manual page was written by Jose <hi8gn at amsat.org>,
+for the Debian GNU/Linux system (but may be used by others).
diff --git a/xastir.spec b/xastir.spec
new file mode 100644
index 0000000..65f22ae
--- /dev/null
+++ b/xastir.spec
@@ -0,0 +1,77 @@
+Summary : Amateur Station Tracking and Reporting system for amateur radio
+Name : xastir
+Version : 2.0.4
+Release : 1
+#Epoch : 1
+License : GPL
+Group : Applications/Networking
+Packager : n2ygk at weca.org
+# Icon : src/xastir.xpm
+Source : http://prdownloads.sourceforge.net/xastir/xastir-2.0.4.tar.gz
+URL : http://www.xastir.org
+BuildRoot : %{_tmppath}/%{name}-buildroot
+#Requires :
+
+%description
+Xastir is a graphical application that interfaces HAM radio
+and internet access to realtime mapping software.
+
+Install XASTIR if you are interested in APRS(tm) and HAM radio
+software.
+
+%prep
+%setup -q
+#%patch
+
+%build
+./bootstrap.sh
+%configure --without-graphicsmagick --with-rtree
+make
+
+%install
+rm -rf ${RPM_BUILD_ROOT}
+%makeinstall
+# Docs go into package docs area instead of the Makefile install
+# locations listed here:
+rm -rf ${RPM_BUILD_ROOT}/usr/share/doc
+
+%clean
+rm -rf ${RPM_BUILD_ROOT}
+
+%files
+%defattr(-,root,root)
+
+# Documents: Go into special doc area at /usr/share/doc/xastir/ or
+# /usr/share/doc/packages/xastir/
+%doc AUTHORS ChangeLog COPYING DEBUG_LEVELS FAQ INSTALL LICENSE
+%doc README README.Contributing README.CVS README.Getting-Started
+%doc README.MAPS README.win32 UPGRADE
+
+
+%{_prefix}/bin
+%{_prefix}/share/xastir/help
+%{_prefix}/share/xastir/config
+%{_prefix}/share/xastir/symbols
+%{_prefix}/share/man
+%{_prefix}/%{lib}/xastir
+
+# protect user-installed map and other files from being clobbered
+
+%config %{_prefix}/share/xastir/maps
+%dir %attr(666,root,root) %{_prefix}/share/xastir/maps/GPS
+%config %{_prefix}/share/xastir/Counties
+%config %{_prefix}/share/xastir/fcc
+%config %{_prefix}/share/xastir/GNIS
+%config %{_prefix}/share/xastir/sounds
+
+%changelog
+* Thu Jul 03 2003 Alan Crosswell <n2ygk at weca.org>
+- 1.2.1 my patches now integrated into the main trunk.
+* Sat Jun 21 2003 Alan Crosswell <n2ygk at weca.org>
+- added xastir-maps.patch
+* Mon Jun 16 2003 Alan Crosswell <n2ygk at weca.org>
+- 1.2.0
+* Fri Jun 06 2003 Alan Crosswell <n2ygk at weca.org>
+- June 5 snapshot
+* Thu May 15 2003 Alan Crosswell <n2ygk at weca.org>
+- start with chuck's spec file for 1.1.4
diff --git a/xastir.spec.in b/xastir.spec.in
new file mode 100644
index 0000000..706511a
--- /dev/null
+++ b/xastir.spec.in
@@ -0,0 +1,77 @@
+Summary : Amateur Station Tracking and Reporting system for amateur radio
+Name : @PACKAGE@
+Version : @VERSION@
+Release : 1
+#Epoch : 1
+License : GPL
+Group : Applications/Networking
+Packager : n2ygk at weca.org
+# Icon : src/@PACKAGE at .xpm
+Source : http://prdownloads.sourceforge.net/@PACKAGE@/@PACKAGE@-@VERSION@.tar.gz
+URL : http://www.xastir.org
+BuildRoot : %{_tmppath}/%{name}-buildroot
+#Requires :
+
+%description
+Xastir is a graphical application that interfaces HAM radio
+and internet access to realtime mapping software.
+
+Install XASTIR if you are interested in APRS(tm) and HAM radio
+software.
+
+%prep
+%setup -q
+#%patch
+
+%build
+./bootstrap.sh
+%configure --without-graphicsmagick --with-rtree
+make
+
+%install
+rm -rf ${RPM_BUILD_ROOT}
+%makeinstall
+# Docs go into package docs area instead of the Makefile install
+# locations listed here:
+rm -rf ${RPM_BUILD_ROOT}/usr/share/doc
+
+%clean
+rm -rf ${RPM_BUILD_ROOT}
+
+%files
+%defattr(-,root,root)
+
+# Documents: Go into special doc area at /usr/share/doc/xastir/ or
+# /usr/share/doc/packages/xastir/
+%doc AUTHORS ChangeLog COPYING DEBUG_LEVELS FAQ INSTALL LICENSE
+%doc README README.Contributing README.CVS README.Getting-Started
+%doc README.MAPS README.win32 UPGRADE
+
+
+%{_prefix}/bin
+%{_prefix}/share/xastir/help
+%{_prefix}/share/xastir/config
+%{_prefix}/share/xastir/symbols
+%{_prefix}/share/man
+%{_prefix}/%{lib}/xastir
+
+# protect user-installed map and other files from being clobbered
+
+%config %{_prefix}/share/xastir/maps
+%dir %attr(666,root,root) %{_prefix}/share/xastir/maps/GPS
+%config %{_prefix}/share/xastir/Counties
+%config %{_prefix}/share/xastir/fcc
+%config %{_prefix}/share/xastir/GNIS
+%config %{_prefix}/share/xastir/sounds
+
+%changelog
+* Thu Jul 03 2003 Alan Crosswell <n2ygk at weca.org>
+- 1.2.1 my patches now integrated into the main trunk.
+* Sat Jun 21 2003 Alan Crosswell <n2ygk at weca.org>
+- added xastir-maps.patch
+* Mon Jun 16 2003 Alan Crosswell <n2ygk at weca.org>
+- 1.2.0
+* Fri Jun 06 2003 Alan Crosswell <n2ygk at weca.org>
+- June 5 snapshot
+* Thu May 15 2003 Alan Crosswell <n2ygk at weca.org>
+- start with chuck's spec file for 1.1.4
diff --git a/xastir_udp_client.1 b/xastir_udp_client.1
new file mode 100644
index 0000000..cce85c2
--- /dev/null
+++ b/xastir_udp_client.1
@@ -0,0 +1,43 @@
+.TH xastir_udp_client 1 2009-12-22 "The Xastir Group"
+
+.SH NAME
+xastir_udp_client \- send simple messages to xastir for APRS(tm) network.
+
+.SH SYNOPSIS
+.B xastir_udp_client
+.I <hostname> <port> <callsign> <passcode> {-identify | [-to_rf] <message>}
+
+.SH DESCRIPTION
+
+xastir_udp_client sends packets into the UDP listening port of an enabled xastir instance.
+
+.SH EXAMPLES
+
+ xastir_udp_client localhost 2023 <callsign> <passcode> "APRS Packet Goes Here"
+
+Currently that will inject the packet into Xastir's decoding routines and send
+it to any TCP-connected clients. It will also igate it to the INET if you have
+igating enabled. It will send the packet out the RF ports as third-party
+packets only if you add the "\-to_rf" flag after the passcode like this:
+
+ xastir_udp_client localhost 2023 <callsign> <passcode> \-to_rf "APRS Packet"
+
+The UDP client is useful for generating and injecting APRS packets from
+external scripts. It can also be used to fetch the callsign of the remote
+xastir server by using the \-identify flag:
+
+ xastir_udp_client localhost 2023 <callsign> <passcode> \-identify
+
+.SH NOTES
+This is a very simple utility that provides no validation of message content.
+
+.SH SEE ALSO
+xastir help file
+.br
+.PP
+.B APRS[tm]
+is a Trademark of Bob Bruninga, his home page is at "http://www.aprs.org/aprs.html"
+.SH COPYING
+Copyright (C) 1999,2000 Frank Giannandrea KC2GJS
+.br
+Copyright (C) 2000-2012 The Xastir Group
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hamradio/xastir.git
More information about the pkg-hamradio-commits
mailing list